diff --git a/core/state/state_test.go b/core/state/state_test.go index 689e7dbc423671b8371a5934e05bcde3955f855c..53e0fa1fb38a6a1edb9859028a37814e4390e909 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -19,7 +19,6 @@ package state import ( "bytes" "math/big" - "os" "testing" "context" @@ -326,11 +325,6 @@ func TestDump(t *testing.T) { t.Fatal(err) } - f, _ := os.Create("/Users/boris/go/src/github.com/ledgerwatch/turbo-geth/debug/trie_wrong.txt") - tds.tMu.Lock() - tds.t.Print(f) - tds.tMu.Unlock() - // check that dump contains the state objects that are in trie got := string(tds.DefaultDump()) want := `{ diff --git a/trie/debug.go b/trie/debug.go index d3ae43e2d4509305ec6cd12f9c0ac1e63c374a9c..7ede19426be15addc00adae108a35f6d0b4d542b 100644 --- a/trie/debug.go +++ b/trie/debug.go @@ -19,171 +19,44 @@ package trie import ( - "bufio" "bytes" - "encoding/hex" "fmt" "io" - "strconv" "github.com/ledgerwatch/turbo-geth/common" "github.com/ledgerwatch/turbo-geth/common/pool" ) func (t *Trie) Print(w io.Writer) { - if t.root != nil { - t.root.print(w) - } - fmt.Fprintf(w, "\n") -} - -func (t *Trie) PrintTrie() { - if t.root == nil { - fmt.Printf("nil Trie\n") - } else { - fmt.Printf("%s\n", t.root.fstring("")) - } -} - -func loadNode(br *bufio.Reader) (node, error) { - nodeType, err := br.ReadString('(') - if err != nil { - return nil, err - } - switch nodeType[len(nodeType)-2:] { - case "f(": - return loadFull(br) - case "d(": - return loadDuo(br) - case "s(": - return loadShort(br) - case "h(": - return loadHash(br) - case "v(": - return loadValue(br) - } - return nil, fmt.Errorf("unknown node type: %s", nodeType) -} - -func loadFull(br *bufio.Reader) (*fullNode, error) { - n := fullNode{} - for { - next, err := br.Peek(1) - if err != nil { - return nil, err - } - if next[0] == ')' { - break - } - idxStr, err := br.ReadBytes(':') - if err != nil { - return nil, err - } - idxStr = idxStr[:len(idxStr)-1] // chop off ":" - idx, err := strconv.ParseInt(string(idxStr), 10, 64) - if err != nil { - return nil, err - } - n.Children[idx], err = loadNode(br) - if err != nil { - return nil, err - } - } - if _, err := br.Discard(1); err != nil { // Discard ")" - return nil, err - } - return &n, nil -} - -func loadDuo(br *bufio.Reader) (*duoNode, error) { - n := duoNode{} - idxStr1, err := br.ReadBytes(':') - if err != nil { - return nil, err - } - idxStr1 = idxStr1[:len(idxStr1)-1] // chop off ":" - idx1, err := strconv.ParseInt(string(idxStr1), 10, 64) - if err != nil { - return nil, err - } - n.child1, err = loadNode(br) - if err != nil { - return nil, err - } - idxStr2, err := br.ReadBytes(':') + witness, err := t.ExtractWitness(1, false, nil) if err != nil { - return nil, err + panic(err) } - idxStr2 = idxStr2[:len(idxStr2)-1] // chop off ":" - idx2, err := strconv.ParseInt(string(idxStr2), 10, 64) + _, err = witness.WriteTo(w) if err != nil { - return nil, err - } - n.child2, err = loadNode(br) - if err != nil { - return nil, err + panic(err) } - n.mask = (uint32(1) << uint(idx1)) | (uint32(1) << uint(idx2)) - if _, err := br.Discard(1); err != nil { // Discard ")" - return nil, err - } - return &n, nil } -func loadShort(br *bufio.Reader) (*shortNode, error) { - n := shortNode{} - keyHexHex, err := br.ReadBytes(':') - if err != nil { - return nil, err - } - keyHexHex = keyHexHex[:len(keyHexHex)-1] - keyHex, err := hex.DecodeString(string(keyHexHex)) - if err != nil { - return nil, err - } - n.Key = keyHex - n.Val, err = loadNode(br) - if err != nil { - return nil, err - } - if _, err := br.Discard(1); err != nil { // Discard ")" - return nil, err - } - return &n, nil +type HexStdOutWriter struct{} + +func (*HexStdOutWriter) Write(p []byte) (n int, err error) { + fmt.Printf("%x", p) + return len(p), nil } -func loadHash(br *bufio.Reader) (hashNode, error) { - hashHex, err := br.ReadBytes(')') - if err != nil { - return nil, err - } - hashHex = hashHex[:len(hashHex)-1] - hash, err := hex.DecodeString(string(hashHex)) - if err != nil { - return nil, err - } - return hashNode(hash), nil +func (t *Trie) PrintTrie() { + fmt.Printf("trie:0x") + t.Print(&HexStdOutWriter{}) + fmt.Println("") } -func loadValue(br *bufio.Reader) (valueNode, error) { - valHex, err := br.ReadBytes(')') - if err != nil { - return nil, err - } - valHex = valHex[:len(valHex)-1] - val, err := hex.DecodeString(string(valHex)) +func Load(r io.Reader) (*Trie, error) { + witness, err := NewWitnessFromReader(r, false) if err != nil { return nil, err } - return valueNode(val), nil -} - -func Load(r io.Reader) (*Trie, error) { - br := bufio.NewReader(r) - t := NewTestRLPTrie(common.Hash{}) - var err error - t.root, err = loadNode(br) - return t, err + return BuildTrieFromWitness(witness, false, false) } func (t *Trie) PrintDiff(t2 *Trie, w io.Writer) { diff --git a/trie/debug_test.go b/trie/debug_test.go index 90e9234f394f99eb36b225b9d435d16770b07a7c..cb932158e7026978c0add6a5253e4717a7f6fead 100644 --- a/trie/debug_test.go +++ b/trie/debug_test.go @@ -73,7 +73,7 @@ func TestPrintLoad(t *testing.T) { tr.Print(&b) if trace { fmt.Printf("Trie: %s\n", tr.root.fstring("")) - fmt.Printf("Buffer: %s\n", b.Bytes()) + fmt.Printf("Buffer: 0x%x\n", b.Bytes()) } trLoaded, err := Load(&b) if err != nil { diff --git a/trie/trie_witness.go b/trie/trie_witness.go index 127d869e3df02131be589daedcad96b48997e621..7fd880374a7100e525c9d875042c9c62db95c64c 100644 --- a/trie/trie_witness.go +++ b/trie/trie_witness.go @@ -3,7 +3,11 @@ package trie import "errors" func (t *Trie) ExtractWitness(blockNr uint64, trace bool, rs *ResolveSet) (*Witness, error) { - return extractWitnessFromRootNode(t.root, blockNr, trace, rs) + var h HashOnly + if rs != nil { + h = rs + } + return extractWitnessFromRootNode(t.root, blockNr, trace, h) } func (t *Trie) ExtractWitnessForPrefix(prefix []byte, blockNr uint64, trace bool, rs *ResolveSet) (*Witness, error) { @@ -19,12 +23,11 @@ func (t *Trie) ExtractWitnessForPrefix(prefix []byte, blockNr uint64, trace bool // if hashOnly param is set to a ResolveSet instance, it will make a witness for only the accounts/storages that were actually touched; other paths will be hashed. func extractWitnessFromRootNode(root node, blockNr uint64, trace bool, hashOnly HashOnly) (*Witness, error) { builder := NewWitnessBuilder(root, blockNr, trace) - var limiter *MerklePathLimiter + var limiter *MerklePathLimiter = nil if hashOnly != nil { hr := newHasher(false) defer returnHasherToPool(hr) limiter = &MerklePathLimiter{hashOnly, hr.hash} } - return builder.Build(limiter) } diff --git a/trie/witness.go b/trie/witness.go index e2f1fb2fca8eacafa6f4e400b1b120fe4ae31d99..f43897227d77bbeba764951d15c8eaab802e8b70 100644 --- a/trie/witness.go +++ b/trie/witness.go @@ -147,12 +147,25 @@ func (w *Witness) WriteDiff(w2 *Witness, output io.Writer) { fmt.Fprintf(output, "w1 operands: %d; w2 operands: %d\n", len(w.Operators), len(w2.Operators)) } - for i := 0; i < len(w.Operators); i++ { - switch o1 := w.Operators[i].(type) { + length := len(w.Operators) + if len(w2.Operators) > length { + length = len(w2.Operators) + } + + for i := 0; i < length; i++ { + var op WitnessOperator + if i < len(w.Operators) { + op = w.Operators[i] + } + if i >= len(w2.Operators) { + fmt.Fprintf(output, "unexpected o1[%d] = %T %v; o2[%d] = nil\n", i, op, op, i) + continue + } + switch o1 := op.(type) { case *OperatorBranch: o2, ok := w2.Operators[i].(*OperatorBranch) if !ok { - fmt.Fprintf(output, "o1[%d] = %T; o2[%d] = %T\n", i, o1, i, o2) + fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2) } if o1.Mask != o2.Mask { fmt.Fprintf(output, "o1[%d].Mask = %v; o2[%d].Mask = %v", i, o1.Mask, i, o2.Mask) @@ -160,7 +173,7 @@ func (w *Witness) WriteDiff(w2 *Witness, output io.Writer) { case *OperatorHash: o2, ok := w2.Operators[i].(*OperatorHash) if !ok { - fmt.Fprintf(output, "o1[%d] = %T; o2[%d] = %T\n", i, o1, i, o2) + fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2) } if !bytes.Equal(o1.Hash.Bytes(), o2.Hash.Bytes()) { fmt.Fprintf(output, "o1[%d].Hash = %s; o2[%d].Hash = %s\n", i, o1.Hash.Hex(), i, o2.Hash.Hex()) @@ -168,7 +181,7 @@ func (w *Witness) WriteDiff(w2 *Witness, output io.Writer) { case *OperatorCode: o2, ok := w2.Operators[i].(*OperatorCode) if !ok { - fmt.Fprintf(output, "o1[%d] = %T; o2[%d] = %T\n", i, o1, i, o2) + fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2) } if !bytes.Equal(o1.Code, o2.Code) { fmt.Fprintf(output, "o1[%d].Code = %x; o2[%d].Code = %x\n", i, o1.Code, i, o2.Code) @@ -176,12 +189,12 @@ func (w *Witness) WriteDiff(w2 *Witness, output io.Writer) { case *OperatorEmptyRoot: o2, ok := w2.Operators[i].(*OperatorEmptyRoot) if !ok { - fmt.Fprintf(output, "o1[%d] = %T; o2[%d] = %T\n", i, o1, i, o2) + fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2) } case *OperatorExtension: o2, ok := w2.Operators[i].(*OperatorExtension) if !ok { - fmt.Fprintf(output, "o1[%d] = %T; o2[%d] = %T\n", i, o1, i, o2) + fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2) } if !bytes.Equal(o1.Key, o2.Key) { fmt.Fprintf(output, "extension o1[%d].Key = %x; o2[%d].Key = %x\n", i, o1.Key, i, o2.Key) @@ -189,7 +202,7 @@ func (w *Witness) WriteDiff(w2 *Witness, output io.Writer) { case *OperatorLeafAccount: o2, ok := w2.Operators[i].(*OperatorLeafAccount) if !ok { - fmt.Fprintf(output, "o1[%d] = %T; o2[%d] = %T\n", i, o1, i, o2) + fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2) } if !bytes.Equal(o1.Key, o2.Key) { fmt.Fprintf(output, "leafAcc o1[%d].Key = %x; o2[%d].Key = %x\n", i, o1.Key, i, o2.Key) @@ -209,7 +222,7 @@ func (w *Witness) WriteDiff(w2 *Witness, output io.Writer) { case *OperatorLeafValue: o2, ok := w2.Operators[i].(*OperatorLeafValue) if !ok { - fmt.Fprintf(output, "o1[%d] = %T; o2[%d] = %T\n", i, o1, i, o2) + fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2) } if !bytes.Equal(o1.Key, o2.Key) { fmt.Fprintf(output, "leafVal o1[%d].Key = %x; o2[%d].Key = %x\n", i, o1.Key, i, o2.Key) @@ -219,7 +232,7 @@ func (w *Witness) WriteDiff(w2 *Witness, output io.Writer) { } default: o2 := w2.Operators[i] - fmt.Fprintf(output, "unexpected o1[%d] = %T; o2[%d] = %T\n", i, o1, i, o2) + fmt.Fprintf(output, "unexpected o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2) } } } diff --git a/trie/witness_builder.go b/trie/witness_builder.go index 57060767336b643b19291ce46974789705fcf465..81a64b941595305e10a4c2f6e0a095cb9e5ec875 100644 --- a/trie/witness_builder.go +++ b/trie/witness_builder.go @@ -160,7 +160,7 @@ func (b *WitnessBuilder) processAccountCode(n *accountNode, hashOnly HashOnly) e return nil } - if n.code == nil || !hashOnly.IsCodeTouched(n.CodeHash) { + if n.code == nil || (hashOnly != nil && !hashOnly.IsCodeTouched(n.CodeHash)) { return b.addHashOp(hashNode(n.CodeHash[:])) } @@ -184,7 +184,11 @@ func (b *WitnessBuilder) makeBlockWitness( nd node, hex []byte, limiter *MerklePathLimiter, force bool) error { processAccountNode := func(key []byte, storageKey []byte, n *accountNode) error { - if err := b.processAccountCode(n, limiter.HashOnly); err != nil { + var hashOnly HashOnly + if limiter != nil { + hashOnly = limiter.HashOnly + } + if err := b.processAccountCode(n, hashOnly); err != nil { return err } if err := b.processAccountStorage(n, storageKey, limiter); err != nil {