mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-22 11:41:19 +00:00
267 lines
5.6 KiB
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
|
|
}
|