mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-22 19:50:36 +00:00
dca36e8b29
* Trace first block * Fixes for CalcTrieRoots * Timings of the CalcTrieRoot * Fix lint * Add memory profiling * Reduce allocations in StreamHash * Fix * Fix * Fix * Optimise allocations * Reuse streams * Fixes * Fix * Unit test fix * Fix lint * Reuse hashbuilder * No loop * Reuse resolver * Fixed tests * Fix test * Fix test * Fix test * Fix witness threshold * Optimise allocations in RLP transform * Optimise allocations in RLP transform * Optimise branchHash * 100 times again * Replace ToStream with Iterator * StreamMergeIterator * No streams * Amplification * Minimise the use of hashOnly * 100 times * Reduce stack operations * Reduce appends * More optimisations * More optimisations * More optimisations * local hex * Small fix * Remove test * Fix lint * Fix lint * Fix lint * Add test for empty * Fix lint * More tests * Fix lint * Add measurement of stateless exec
107 lines
2.4 KiB
Go
107 lines
2.4 KiB
Go
package trie
|
|
|
|
import (
|
|
"fmt"
|
|
"math/big"
|
|
|
|
"github.com/ledgerwatch/turbo-geth/common"
|
|
"github.com/ledgerwatch/turbo-geth/trie/rlphacks"
|
|
)
|
|
|
|
func BuildTrieFromWitness(witness *Witness, isBinary bool, trace bool) (*Trie, CodeMap, error) {
|
|
codeMap := make(map[common.Hash][]byte)
|
|
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, nil, err
|
|
}
|
|
case *OperatorExtension:
|
|
if trace {
|
|
fmt.Printf("EXTENSION ")
|
|
}
|
|
if err := hb.extension(op.Key); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
case *OperatorBranch:
|
|
if trace {
|
|
fmt.Printf("BRANCH ")
|
|
}
|
|
if err := hb.branch(uint16(op.Mask)); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
case *OperatorHash:
|
|
if trace {
|
|
fmt.Printf("HASH ")
|
|
}
|
|
if err := hb.hash(op.Hash[:]); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
case *OperatorCode:
|
|
if trace {
|
|
fmt.Printf("CODE ")
|
|
}
|
|
|
|
if codeHash, err := hb.code(op.Code); err == nil {
|
|
codeMap[codeHash] = op.Code
|
|
} else {
|
|
return nil, 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, nil, err
|
|
}
|
|
case *OperatorEmptyRoot:
|
|
if trace {
|
|
fmt.Printf("EMPTYROOT ")
|
|
}
|
|
hb.emptyRoot()
|
|
default:
|
|
return nil, nil, fmt.Errorf("unknown operand type: %T", operator)
|
|
}
|
|
}
|
|
if trace {
|
|
fmt.Printf("\n")
|
|
}
|
|
if !hb.hasRoot() {
|
|
if isBinary {
|
|
return NewBinary(EmptyRoot), nil, nil
|
|
}
|
|
return New(EmptyRoot), nil, nil
|
|
}
|
|
r := hb.root()
|
|
var tr *Trie
|
|
if isBinary {
|
|
tr = NewBinary(hb.rootHash())
|
|
} else {
|
|
tr = New(hb.rootHash())
|
|
}
|
|
tr.root = r
|
|
return tr, codeMap, nil
|
|
}
|