Skip to content

Latest commit

 

History

History
238 lines (198 loc) · 12.3 KB

eip-0005.md

File metadata and controls

238 lines (198 loc) · 12.3 KB

EIP-0005: Contract Template

  • Author: aslesarenko
  • Status: Proposed
  • Created: 06-Apr-2020
  • License: CC0
  • Forking: not needed

Contents

Description

This EIP defines a standard serialization formats and contract metadata for cross-platform reusable contract templates.

Background And Motivation

Ergo supports flexible language ErgoTree of guarding propositions which protect UTXO boxes. The propositions are stored in the blockchain according to ErgoTree serialization format, which is designed for compact storage and fast script execution and transaction validation.

However, ErgoTree binary format intentionally doesn't include metadata, which may be necessary for various Ergo applications.

This standard defines extended serialization format of contract templates, which may be reused across different protocol implementations, applications and tools on many execution environments.

Example Use Cases

  • ErgoTree compilers can generate contract templates with the necessary metadata
  • The template generated by ErgoScala compiler can be used in the environments where Java jar library generated by Scala2.12 is not supported (Android, native, web, etc.)
  • Once generated the contract template becomes self-contained and can be stored, transfered, parsed, executed etc across platforms, tools and applications.
  • The contract template format supports partial ErgoTree implementations.

Contract Template Serialization Format

Each contract template can be represented using an array of bytes. The content of the array is the following sequence of data fields. Note, the Field Name is not saved and used here only for description of the corresponding content. Thus, the format is schema-less. Binary serialization format is suitable for compact storage and wire transfers. All the fields are required (mandatory).

Field Name Format Example Description
TreeVersion Opt[UByte] 1 Optional version of ErgoTree which should be used
NameLength VLQ(UInt) 18 Length of Name bytes (> 0)
Name Bytes "rewardOutputScript" User readable name (non-empty string bytes in UTF-8 encoding)
DescLength VLQ(UInt) 20 Length of Description bytes (>= 0)
Description Bytes "holds mining rewards" User readable contract description (string bytes in UTF-8 encoding)
ConstNum VLQ(UInt) 2 Number of items in ConstTypes and ConstValues (>= 0)
ConstTypes Type* (*) ConstNum of constant types serialized (see Type Serialization section of ErgoTree Spec
ConstValues Opt[Opt[Data]*] (**) Optional. Either None or ConstNum number of again optional default constant values serialized (see Data Serialization section of ErgoTree Spec)
ParamNum VLQ(UInt) 1 Number of named template parameters (>= 0)
Parameters Parameter* minerPk: SigmaProp Typed template parameters (see Parameter Serialization Format section below)
TemplateSize VLQ(UInt) 28 Size in bytes of the serialized ExpressionTree field (> 0)
ExpressionTree Expr (***) Contract Template expression bytes with ConstantPlaceholders (see Expression Serialization section of ErgoTree Spec

Notes:

  • In general, some constants are required which depends on the contract semantics. The format doesn't impose any restrictions on that. Some constant values like 720 take small number of bytes, but others, like SigmaProp in the example, are even larger than the template bytes itself (compare (**) and (***) hex). Constants that are not required can be omitted.

  • The format is optimized for the size of the serialized bytes. For this purpose ConstValues field is separated from the ConstTypes field and each constant value is serialized as Data format prefixed by 0 - if the value is None, and 1 - if the value is Some(v). The v bytes follow immediately after the Some prefix. Thus, large constants can be omitted.

  • Some contracts may have ExpressionTree field where all semantically significant constants are not segregated. In most cases this is more compact and can be done by the compilers (e.g. ErgoScala compiler) where constant <-> parameter mapping is explicit. For such contracts the whole ConstValues field may be serialized as None.

  • TemplateSize field can be used to skip parsing ExpressionTree when the contract template is embedded into some other format. Thus, templates can be quickly scanned and the ExpressionTree bytes can be obtained for hashing or template-based requests to the blockchain.

  • each ContractTemplate can be converted to ErgoTree of the corresponding version (using t.TreeVersion)0

(*) IR:

Seq(
  SInt, 
  SSigmaProp
)

Hex: "0x0408"

(**) IR:

Seq(
  720, 
  SigmaProp(ProveDlog(ECPoint(79be66, 483ada,...)))
)

Hex: "0x0101a00b01cd0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"

(***) IR:

SigmaAnd(Seq(
    BoolToSigmaProp(GE(Height,Plus(SelectField(ExtractCreationInfo(Self),1), ConstantPlaceholder(0,SInt)))),
    ConstantPlaceholder(1,SSigmaProp)))
)

Hex: "0xea02d192a39a8cc7a70173007301"

Parameter Serialization Format

Parameters specify additional meta information for the contract template. The number of parameters can be less then or equal to the number of segregated constants (see ConstNum field). This is because some constant values may not be changed without breaking contract logic and hence they cannot be used as template parameters. This depends on the contract, the format supports all the necessary combinations.

Field Name Format Example Description
NameLength VLQ(UInt) 7 Length of Name bytes
Name Bytes "minerPk" User readable parameter name (string bytes in UTF-8 encoding)
DescLength VLQ(UInt) 18 Length of Description bytes
Description Bytes "miner's public key" User readable parameter description (string bytes in UTF-8 encoding)
Placeholder VLQ(UInt) 1 Placeholder index in ErgoTree.constants array

Note, the Placeholder field maps the parameters to the constants in the ExpressionTree expression tree. More specifically, given a contract template t: ContractTemplate and a parameter p: Parameter inside t then p.Placeholder is an index in t.ConstTypes and t.ConstValues, such that c = t.ConstValues(p.Placeholder) is a value of the constant in t.ExpressionTree which has the index p.Placeholder. This also means that there is a placeholder in t.ExpressionTree which also refers to c as if it were in constants array of ErgoTree (i.e. we have p.Placeholder == ph.index for some ph in t.ExpressionTree). Note, that each value in t.ConstValues is optional, which means that for some parameters the default value is not defined, however the type can always be looked up as t = t.ConstTypes(p.Placeholder).

JSON Format

In addition to the binary format, the contract templates can be represented using JSON. It may serve better for some applications. Below we define the standard JSON representation of contract templates.

{
  "name": "rewardOutputScript",
  "description": "holds mining rewards",
  "constTypes": ["0x04", "0x08"],
  "constValues": ["0xa00b", "0xcd0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"],
  "parameters": [
     { 
       "name": "minerPk",
       "description": "miner's public key",
       "placeholder": 1
     }
  ],
  "templateTree": "ea02d192a39a8cc7a70173007301"
}

Notes:

  • The constTypes property is required and the length of the array should be equal to ConstNum. Each element of constTypes is Base16 encoded bytes of the corresponding serialized type (see Type format in ErgoTree spec).
  • If ConstValues is None, then it can be omitted in JSON or equal to null. In non null, then the length of constValues array should be equal to the length of constTypes. Missing constants should be represented as null values in the array. Every non-null value in the array should be Base16 encoded string of constant value serialized as Data format (see ErgoTree spec).

Conversion to ErgoTree

Contract template t can be used to compose ErgoTree bytes as shown in the following table, where t.name means taking the corresponding field from the template t.

Field Name Format Data Value
Header UByte t.TreeVersion plus additional bits
ConstLength VLQ(UInt) t.ConstNum
Constants Const+ Constants(i) = Constant(t.ConstTypes(i), t.ConstValues(i))
Template Expr t.ExpressionTree

The template parameters (see t.Parameters) can be used to substitute new values in the Constants thus redefining the default values of the template, or providing missing constant values.

Note, ErgoTree composition from a template doesn't require an implementation of all the ErgoTree serializers. Only Type Serializer and DataSerializer (see ErgoTree Specification) have to be implemented to parse and serialize ConstTypes and ConstValues bytes, replace the necessary constants (using Placeholder field of the parameter) and then serialize the updated array of the constants back to the new bytes array.

This relaxed requirement, will significantly simplify composition of valid ErgoTrees from templates on the platforms, where full serializer is not available. In particular, a template can be composed in one environment with full ErgoTree support and then transfered to another environment and used there for actual ErgoTree composition.

Notes on Supporting this EIP in ErgoTree Compilers

Compilers producing ErgoTree (such as ErgoScript, ErgoScala or others) can support this EIP directly buy generating a template packaged as either JSON or bytes.

For example, in the case of ErgoScala, the compiler is Scala macros. The programmer can specify the contract template metadata as annotations (on both contract method and its parameters) and the macros can access them and use for embedding into the template bytes.

The ErgoScala compiler macros maps the parameters of the Scala method to the segregated constants, however those constants are mixed with other constants in the contract body (which are not mapped to template parameters).

By using annotations the ErgoScala macros can map parameters to constant positions (in ErgoTree.constants array) and use this mapping both in compilation of ErgoTree and generation of the template bytes. In particular, when creating ErgoTree bytes, the ErgoScala macros can do partial constant segregation, i.e. segregate only those constants from the expression tree which are mapped to the parameters leaving others in the tree. Thus created contract template will also satisfy an additional requirement, i.e. the number of constants will be the same as the number of parameters.

Similar algorithm can be used in the other ErgoTree compiler implementations.