mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-22 11:41:19 +00:00
4f4b395aa4
* introduce code node * replace codeMap with code touches * fix a comment * fixups to tests * fix compile error * fix getnodedata tests * add tests and test stubs * add more test stubs * add test method bodies * add and fix more tests on trie for new codenode * add test change code between blocks * fix crash in stateless * remove unneded files * remove comment * fix deleted account code * fix resolve set builder for code nodes
103 lines
2.2 KiB
Go
103 lines
2.2 KiB
Go
package trie
|
|
|
|
import (
|
|
"fmt"
|
|
"math/big"
|
|
|
|
"github.com/ledgerwatch/turbo-geth/trie/rlphacks"
|
|
)
|
|
|
|
func BuildTrieFromWitness(witness *Witness, isBinary bool, trace bool) (*Trie, error) {
|
|
hb := NewHashBuilder(false)
|
|
for _, operator := range witness.Operators {
|
|
switch op := operator.(type) {
|
|
case *OperatorLeafValue:
|
|
if trace {
|
|
fmt.Printf("LEAF ")
|
|
}
|
|
keyHex := op.Key
|
|
val := op.Value
|
|
if err := hb.leaf(len(op.Key), keyHex, rlphacks.RlpSerializableBytes(val)); err != nil {
|
|
return nil, err
|
|
}
|
|
case *OperatorExtension:
|
|
if trace {
|
|
fmt.Printf("EXTENSION ")
|
|
}
|
|
if err := hb.extension(op.Key); err != nil {
|
|
return nil, err
|
|
}
|
|
case *OperatorBranch:
|
|
if trace {
|
|
fmt.Printf("BRANCH ")
|
|
}
|
|
if err := hb.branch(uint16(op.Mask)); err != nil {
|
|
return nil, err
|
|
}
|
|
case *OperatorHash:
|
|
if trace {
|
|
fmt.Printf("HASH ")
|
|
}
|
|
if err := hb.hash(op.Hash[:]); err != nil {
|
|
return nil, err
|
|
}
|
|
case *OperatorCode:
|
|
if trace {
|
|
fmt.Printf("CODE ")
|
|
}
|
|
|
|
if err := hb.code(op.Code); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
case *OperatorLeafAccount:
|
|
if trace {
|
|
fmt.Printf("ACCOUNTLEAF(code=%v storage=%v) ", op.HasCode, op.HasStorage)
|
|
}
|
|
balance := big.NewInt(0)
|
|
balance.SetBytes(op.Balance.Bytes())
|
|
nonce := op.Nonce
|
|
|
|
// FIXME: probably not needed, fix hb.accountLeaf
|
|
fieldSet := uint32(3)
|
|
if op.HasCode && op.HasStorage {
|
|
fieldSet = 15
|
|
}
|
|
|
|
// Incarnation is always needed for a hashbuilder.
|
|
// but it is just our implementation detail needed for contract self-descruction suport with our
|
|
// db structure. Stateless clients don't access the DB so we can just pass 0 here.
|
|
incarnaton := uint64(0)
|
|
|
|
if err := hb.accountLeaf(len(op.Key), op.Key, 0, balance, nonce, incarnaton, fieldSet); err != nil {
|
|
return nil, err
|
|
}
|
|
case *OperatorEmptyRoot:
|
|
if trace {
|
|
fmt.Printf("EMPTYROOT ")
|
|
}
|
|
hb.emptyRoot()
|
|
default:
|
|
return nil, fmt.Errorf("unknown operand type: %T", operator)
|
|
}
|
|
}
|
|
if trace {
|
|
fmt.Printf("\n")
|
|
}
|
|
if !hb.hasRoot() {
|
|
if isBinary {
|
|
return NewBinary(EmptyRoot), nil
|
|
}
|
|
return New(EmptyRoot), nil
|
|
}
|
|
r := hb.root()
|
|
var tr *Trie
|
|
if isBinary {
|
|
tr = NewBinary(hb.rootHash())
|
|
} else {
|
|
tr = New(hb.rootHash())
|
|
}
|
|
tr.root = r
|
|
return tr, nil
|
|
}
|