erigon-pulse/trie/witness_operators.go

267 lines
5.6 KiB
Go

package trie
import (
"math/big"
"github.com/ledgerwatch/turbo-geth/common"
"github.com/ugorji/go/codec"
)
const (
flagCode = 1 << iota
flagStorage
flagNonce
flagBalance
)
// OperatorKindCode is "enum" type for defining the opcodes of the stack machine that reconstructs the structure of tries from Structure tape
type OperatorKindCode uint8
const (
// OpLeaf creates leaf node and pushes it onto the node stack, its hash onto the hash stack
OpLeaf OperatorKindCode = iota
// OpExtension pops a node from the node stack, constructs extension node from it and its operand's key, and pushes this extension node onto
// the node stack, its hash onto the hash stack
OpExtension
// OpBranch has operand, which is a bitset representing digits in the branch node. Pops the children nodes from the node stack (the number of
// children is equal to the number of bits in the bitset), constructs branch node and pushes it onto the node stack, its hash onto the hash stack
OpBranch
// OpHash and pushes the hash them onto the stack.
OpHash
// OpCode constructs code node and pushes it onto the node stack, its hash onto the hash stack.
OpCode
// OpAccountLeaf constructs an account node (without any storage and code) and pushes it onto the node stack, its hash onto the hash stack.
OpAccountLeaf
// OpEmptyRoot places nil onto the node stack, and empty root hash onto the hash stack.
OpEmptyRoot
// OpNewTrie stops the processing, because another trie is encoded into the witness.
OpNewTrie = OperatorKindCode(0xBB)
)
// WitnessOperator is a single operand in the block witness. It knows how to serialize/deserialize itself.
type WitnessOperator interface {
WriteTo(*OperatorMarshaller) error
// LoadFrom always assumes that the opcode value was already read
LoadFrom(*OperatorUnmarshaller) error
}
type OperatorHash struct {
Hash common.Hash
}
func (o *OperatorHash) WriteTo(output *OperatorMarshaller) error {
if err := output.WriteOpCode(OpHash); err != nil {
return nil
}
return output.WriteHash(o.Hash)
}
func (o *OperatorHash) LoadFrom(loader *OperatorUnmarshaller) error {
hash, err := loader.ReadHash()
if err != nil {
return err
}
o.Hash = hash
return nil
}
type OperatorLeafValue struct {
Key []byte
Value []byte
}
func (o *OperatorLeafValue) WriteTo(output *OperatorMarshaller) error {
if err := output.WriteOpCode(OpLeaf); err != nil {
return err
}
if err := output.WriteKey(o.Key); err != nil {
return err
}
return output.WriteByteArrayValue(o.Value)
}
func (o *OperatorLeafValue) LoadFrom(loader *OperatorUnmarshaller) error {
key, err := loader.ReadKey()
if err != nil {
return err
}
o.Key = key
value, err := loader.ReadByteArray()
if err != nil {
return err
}
o.Value = value
return nil
}
type OperatorLeafAccount struct {
Key []byte
Nonce uint64
Balance *big.Int
HasCode bool
HasStorage bool
}
func (o *OperatorLeafAccount) WriteTo(output *OperatorMarshaller) error {
if err := output.WriteOpCode(OpAccountLeaf); err != nil {
return err
}
if err := output.WriteKey(o.Key); err != nil {
return err
}
flags := byte(0)
if o.HasCode {
flags |= flagCode
}
if o.HasStorage {
flags |= flagStorage
}
if o.Nonce > 0 {
flags |= flagNonce
}
if o.Balance.Sign() != 0 {
flags |= flagBalance
}
if err := output.WriteByteValue(flags); err != nil {
return err
}
if o.Nonce > 0 {
if err := output.WriteUint64Value(o.Nonce); err != nil {
return err
}
}
if o.Balance.Sign() != 0 {
return output.WriteByteArrayValue(o.Balance.Bytes())
}
return nil
}
func (o *OperatorLeafAccount) LoadFrom(loader *OperatorUnmarshaller) error {
key, err := loader.ReadKey()
if err != nil {
return err
}
o.Key = key
flags, err := loader.ReadByte()
if err != nil {
return err
}
o.HasCode = flags&flagCode != 0
o.HasStorage = flags&flagStorage != 0
if flags&flagNonce != 0 {
o.Nonce, err = loader.ReadUInt64()
if err != nil {
return err
}
}
balance := big.NewInt(0)
if flags&flagBalance != 0 {
var balanceBytes []byte
balanceBytes, err = loader.ReadByteArray()
if err != nil {
return err
}
balance.SetBytes(balanceBytes)
}
o.Balance = balance
return nil
}
type OperatorCode struct {
Code []byte
}
func (o *OperatorCode) WriteTo(output *OperatorMarshaller) error {
if err := output.WriteOpCode(OpCode); err != nil {
return err
}
return output.WriteCode(o.Code)
}
func (o *OperatorCode) LoadFrom(loader *OperatorUnmarshaller) error {
code, err := loader.ReadByteArray()
if err != nil {
return err
}
o.Code = code
return nil
}
type OperatorBranch struct {
Mask uint32
}
func (o *OperatorBranch) WriteTo(output *OperatorMarshaller) error {
if err := output.WriteOpCode(OpBranch); err != nil {
return err
}
encoder := codec.NewEncoder(output.WithColumn(ColumnStructure), &cbor)
return encoder.Encode(o.Mask)
}
func (o *OperatorBranch) LoadFrom(loader *OperatorUnmarshaller) error {
mask, err := loader.ReadUint32()
if err != nil {
return err
}
o.Mask = mask
return nil
}
type OperatorEmptyRoot struct{}
func (o *OperatorEmptyRoot) WriteTo(output *OperatorMarshaller) error {
return output.WriteOpCode(OpEmptyRoot)
}
func (o *OperatorEmptyRoot) LoadFrom(loader *OperatorUnmarshaller) error {
// no-op
return nil
}
type OperatorExtension struct {
Key []byte
}
func (o *OperatorExtension) WriteTo(output *OperatorMarshaller) error {
if err := output.WriteOpCode(OpExtension); err != nil {
return err
}
return output.WriteKey(o.Key)
}
func (o *OperatorExtension) LoadFrom(loader *OperatorUnmarshaller) error {
key, err := loader.ReadKey()
if err != nil {
return err
}
o.Key = key
return nil
}