Icon SunFilledIcon MoonStars
Icon SunFilledIcon MoonStars

Icon LinkCryptographic Primitives

Icon LinkHashing

All hashing is done with SHA-2-256 (also known as SHA-256), defined in FIPS 180-4 Icon Link.

Icon LinkMerkle Trees

Three Merkle tree structures are used: a Binary Merkle Tree (to commit to bytecode), a Binary Merkle Sum Tree (to commit to transactions and collected fees) and a Sparse Merkle Tree (to commit to contract storage, i.e. state).

Icon LinkBinary Merkle Tree

A specification for the Binary Merkle Tree is here Icon Link.

Icon LinkBinary Merkle Sum Tree

The Binary Merkle Sum Tree is an extension of the tree defined in RFC-6962 Icon Link.

The root pair (fee, digest) of an empty tree is:

(0x0000000000000000, hash()) = (0x0000000000000000, 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855)

The root pair of a tree with one leaf:

(leaf.fee, hash(0x00 ++ leaf.fee ++ serialize(leaf)))

The root pair of a tree with two or more leaves is defined recursively:

(left.fee + right.fee, hash(0x01 ++ left.fee ++ left.digest ++ right.fee ++ right.digest))

In other words, the root pair is 40 bytes (8 for fee sum, 32 for hash digest).

Icon LinkSparse Merkle Tree

A specification for the Sparse Merkle Tree is here Icon Link.

A specification describing a suite of test vectors and outputs of a Sparse Merkle Tree is here.

Before insertion of the key-value pair, each key of the Sparse Merkle Tree should be hashed with sha256 to prevent tree structure manipulations. During the proof verification, the original leaf key should be hashed similarly. Otherwise, the root will not match.

Icon LinkPublic-Key Cryptography

Consensus-critical data is authenticated using ECDSA Icon Link, with the curve secp256k1 Icon Link. A highly-optimized library is available in C (https://github.com/bitcoin-core/secp256k1 Icon Link), with wrappers in Go (https://pkg.go.dev/github.com/ethereum/go-ethereum/crypto/secp256k1 Icon Link) and Rust (https://docs.rs/crate/secp256k1 Icon Link).

Public keys are encoded in uncompressed form, as the concatenation of the x and y values. No prefix is needed to distinguish between encoding schemes as this is the only encoding supported.

Deterministic signatures (RFC-6979 Icon Link) should be used when signing, but this is not enforced at the protocol level as it cannot be.

Signatures are represented as the r and s (each 32 bytes), and v (1-bit) values of the signature. r and s take on their usual meaning (see: SEC 1, 4.1.3 Signing Operation Icon Link), while v is used for recovering the public key from a signature more quickly (see: SEC 1, 4.1.6 Public Key Recovery Operation Icon Link). Only low-s values in signatures are valid (i.e. s <= secp256k1.n//2); s can be replaced with -s mod secp256k1.n during the signing process if it is high. Given this, the first bit of s will always be 0, and can be used to store the 1-bit v value.

v represents the parity of the Y component of the point, 0 for even and 1 for odd. The X component of the point is assumed to always be low, since the possibility of it being high is negligible Icon Link.

Putting it all together, the encoding for signatures is:

|    32 bytes   ||           32 bytes           |
[256-bit r value][1-bit v value][255-bit s value]

This encoding scheme is derived from EIP 2098: Compact Signature Representation Icon Link.