zktrie

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 27, 2022 License: Apache-2.0 Imports: 4 Imported by: 12

README

Type for zktrie

Data Format in stateDb

All data node being stored via stateDb are encoded by following syntax:

    node             =  magic string | node data ;

    magic string     =  "THIS IS SOME MAGIC BYTES FOR SMT m1rRXgP2xpDI" ;

    node data        =  middle node | leaf node | empty node ;

    empty node       = '0x2' ;

    middle node      = '0x0', left hash, right hash ;

    field            = 32 * hex char ;

    left hash        = field ;

    right hash       = field ;

    leaf node        = node key , value len , compress flag , <value len> * value field, key preimage ;

    node key         = field ;

    compress flag    = 3 * byte ;

    value len        = byte ;

    value field      = field | compressed field, compressed field ;

    compressed field = 16 * hex char ;

    key preimage     = '0x0' | preimage bytes ;

    preimage bytes   = len, <len> * byte ;

    len              = byte ;

A field is an element in prime field of BN256 represented by big endian integer and contained in fixed length (32) bytes;

A compressed field is a field represented by big endian integer which could be contained in 16 bytes;

For the total value len items of value field (maximum 255), the first 24 value fields can be recorded as field or 2x compressed field (i.e. a byte32). The corresonpdoing bit in compress flag is set to 1 if it was recorded as byte32, or 0 for a field.

Key scheme

The key of data node is obtained from one or more poseidon hash calculation: poseidon := (field, field) => field.

For middle node:

key = poseidon(<left hash>, <right hash>)

For leaf node:

key = poseidon(<pre key>, <value hash>)

pre key = poseidon(field(1), <node key>)

value hash = poseidon(<leaf element>, <leaf element>) | poseidon(<value hash>, <value hash>)

leaf element = <value field as field> | poseidon(<compressed field as field>, <compressed field as field>) | field(0)

That is, to calculate the key of a leaf node:

  1. In the sequence of value fields, take which is recorded as 'compressed' and calculate the 2x compressed field for its poseidon hash, replace the corresponding value field ad-hoc in the sequence;

  2. Consider the sequence from 1 as the leafs of a binary merkle tree (append a 0 field for odd leafs) and calculate its root by poseidon hash;

For empty node:

key = field(0)

Account data

Each account data is saved in one leaf node of account zktrie as 4 value fields:

  1. Nonce as field
  2. Balance as field
  3. CodeHash as compressed field (byte32)
  4. Storage root as field

The key for an account data is calculated from the 20-bit account address as following:


32-byte-zero-end-padding-addr := address, 16 * bytes (0)

key = poseidon(<first 16 byte of 32-byte-zero-end-padding-addr as field>, <last 16 byte of 32-byte-zero-end-padding-addr as field>)

Data examples

A leaf node in account trie:

0x017f9d3bbc51d12566ecc6049ca6bf76e32828c22b197405f63a833b566fe7da0a040400000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000029b74e075daad9f17eb39cd893c2dd32f52ecd99084d63964842defd00ebcbe208a2f471d50e56ac5000ab9e82f871e36b5a636b19bd02f70aa666a3bd03142f00

Can be decompose to:

  • 0x01: node type prefix for leaf node
  • 7f9d3bbc51d12566ecc6049ca6bf76e32828c22b197405f63a833b566fe7da0a: node key as field
  • 04: value len (4 value fields)
  • 040000: compress flag, a 24 bit array, indicating the third field is compressed
  • 0000000000000000000000000000000000000000000000000000000000000001: value field 0 (nonce)
  • 0000000000000000000000000000000000000000000000000000000000000000: value field 1 (balance)
  • 29b74e075daad9f17eb39cd893c2dd32f52ecd99084d63964842defd00ebcbe2: value field 2 (codeHash, as byte32)
  • 08a2f471d50e56ac5000ab9e82f871e36b5a636b19bd02f70aa666a3bd03142f: value field 3 (storage root)
  • 00: key preimage is not avaliable

The key calculation for this node is:


arr = [<value field 0>, <value field 1>, <value field 2>, <value field 3>]

hash_pre = poseidon(<first 16 byte for value field 2>, <last 16 byte for value field 2>)

arr[2] = hash_pre

layer1 = [poseidon(arr[0], arr[1]), poseidon(arr[2], arr[3])]

key = poseidon(layer1[0], layer1[1])

Notice all field and compressed field are represented as big endian integer.

A middle node in account trie:

0x00000000000000000000000000000000000000000000000000000000000000000004470b58d80eeb26da85b2c2db5c254900656fb459c07729f556ff02534ab32a

Notice the left child of this node is an empty node (so its key is field(0))

Documentation

Index

Constants

View Source
const ElemBytesLen = 32

ElemBytesLen is the length of the Hash byte array

Variables

View Source
var BigOne = big.NewInt(1)
View Source
var BigZero = big.NewInt(0)
View Source
var HashZero = Hash{}

Functions

func BigEndianBitsToBigInt

func BigEndianBitsToBigInt(bits []bool) *big.Int

func CheckBigIntInField

func CheckBigIntInField(a *big.Int) bool

CheckBigIntInField checks if given *big.Int fits in a Field Q element

func InitHashScheme

func InitHashScheme(f func([]*big.Int) (*big.Int, error))

func NewBigIntFromHashBytes

func NewBigIntFromHashBytes(b []byte) (*big.Int, error)

NewBigIntFromHashBytes returns a *big.Int from a byte array, swapping the endianness in the process. This is the intended method to get a *big.Int from a byte array that previously has ben generated by the Hash.Bytes() method.

func ReverseByteOrder

func ReverseByteOrder(b []byte) []byte

ReverseByteOrder swaps the order of the bytes in the slice.

func SetBitBigEndian

func SetBitBigEndian(bitmap []byte, n uint)

SetBitBigEndian sets the bit n in the bitmap to 1, in Big Endian.

func TestBit

func TestBit(bitmap []byte, n uint) bool

TestBit tests whether the bit n in bitmap is 1.

func TestBitBigEndian

func TestBitBigEndian(bitmap []byte, n uint) bool

TestBitBigEndian tests whether the bit n in bitmap is 1, in Big Endian.

func ToSecureKey added in v0.2.0

func ToSecureKey(key []byte) (*big.Int, error)

ToSecureKey turn the byte key into the integer represent of "secured" key

Types

type Byte32

type Byte32 [32]byte

func NewByte32FromBytes

func NewByte32FromBytes(b []byte) *Byte32

same action as common.Hash (truncate bytes longer than 32 bytes FROM beginning, and padding 0 at the beginning for shorter bytes)

func NewByte32FromBytesPaddingZero

func NewByte32FromBytesPaddingZero(b []byte) *Byte32

create bytes32 with zeropadding to shorter bytes, or truncate it

func ToSecureKeyBytes added in v0.2.0

func ToSecureKeyBytes(key []byte) (*Byte32, error)

ToSecureKeyBytes turn the byte key into a 32-byte "secured" key, which represented a big-endian integer

func (*Byte32) Bytes

func (b *Byte32) Bytes() []byte

func (*Byte32) Hash

func (b *Byte32) Hash() (*big.Int, error)

type Hash

type Hash [32]byte

Hash is the generic type stored in the MerkleTree

func HashElems

func HashElems(fst, snd *big.Int, elems ...*big.Int) (*Hash, error)

HashElems performs a recursive poseidon hash over the array of ElemBytes, each hash reduce 2 fieds into one

func NewHashFromBigInt

func NewHashFromBigInt(b *big.Int) *Hash

NewHashFromBigInt returns a *Hash representation of the given *big.Int

func NewHashFromBytes

func NewHashFromBytes(b []byte) *Hash

NewHashFromBytes returns a *Hash from a byte array considered to be a represent of big-endian integer, it swapping the endianness in the process.

func NewHashFromCheckedBytes added in v0.2.0

func NewHashFromCheckedBytes(b []byte) (*Hash, error)

NewHashFromCheckedBytes is the intended method to get a *Hash from a byte array that previously has ben generated by the Hash.Bytes() method. so it check the size of bytes to be expected length

func NewHashFromString

func NewHashFromString(s string) (*Hash, error)

NewHashFromString returns a *Hash representation of the given decimal string

func PreHandlingElems

func PreHandlingElems(flagArray uint32, elems []Byte32) (*Hash, error)

PreHandlingElems turn persisted byte32 elements into field arrays for our hashElem it also has the compressed byte32

func (*Hash) BigInt

func (h *Hash) BigInt() *big.Int

BigInt returns the *big.Int representation of the *Hash

func (*Hash) Bytes

func (h *Hash) Bytes() []byte

Bytes returns the little endian []byte representation of the *Hash, which always is 32 bytes length.

func (Hash) Hex

func (h Hash) Hex() string

Hex returns the hexadecimal representation of the Hash

func (Hash) MarshalText

func (h Hash) MarshalText() ([]byte, error)

MarshalText implements the marshaler for the Hash type

func (Hash) String

func (h Hash) String() string

String returns decimal representation in string format of the Hash

func (*Hash) UnmarshalText

func (h *Hash) UnmarshalText(b []byte) error

UnmarshalText implements the unmarshaler for the Hash type

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL