mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
trie: re-add stacktrie binary marshalling (OBS! format change)
This commit is contained in:
parent
171a932c44
commit
d2267d767f
3 changed files with 159 additions and 127 deletions
|
|
@ -420,88 +420,3 @@ func (stack *StackTrie) Commit() (h common.Hash, err error) {
|
|||
stack.writeFn(stack.owner, nil, h, st.val)
|
||||
return h, nil
|
||||
}
|
||||
|
||||
//// NewFromBinary initialises a serialized stacktrie with the given db.
|
||||
//func NewFromBinary(data []byte, writeFn NodeWriteFunc) (*StackTrie, error) {
|
||||
// var st StackTrie
|
||||
// if err := st.UnmarshalBinary(data); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// // If a database is used, we need to recursively add it to every child
|
||||
// if writeFn != nil {
|
||||
// st.setWriter(writeFn)
|
||||
// }
|
||||
// return &st, nil
|
||||
//}
|
||||
//
|
||||
//// MarshalBinary implements encoding.BinaryMarshaler
|
||||
//func (st *StackTrie) MarshalBinary() (data []byte, err error) {
|
||||
// var (
|
||||
// b bytes.Buffer
|
||||
// w = bufio.NewWriter(&b)
|
||||
// )
|
||||
// if err := gob.NewEncoder(w).Encode(struct {
|
||||
// Owner common.Hash
|
||||
// NodeType uint8
|
||||
// Val []byte
|
||||
// Key []byte
|
||||
// }{
|
||||
// st.owner,
|
||||
// st.nodeType,
|
||||
// st.val,
|
||||
// st.key,
|
||||
// }); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// for _, child := range st.children {
|
||||
// if child == nil {
|
||||
// w.WriteByte(0)
|
||||
// continue
|
||||
// }
|
||||
// w.WriteByte(1)
|
||||
// if childData, err := child.MarshalBinary(); err != nil {
|
||||
// return nil, err
|
||||
// } else {
|
||||
// w.Write(childData)
|
||||
// }
|
||||
// }
|
||||
// w.Flush()
|
||||
// return b.Bytes(), nil
|
||||
//}
|
||||
//
|
||||
//// UnmarshalBinary implements encoding.BinaryUnmarshaler
|
||||
//func (st *StackTrie) UnmarshalBinary(data []byte) error {
|
||||
// r := bytes.NewReader(data)
|
||||
// return st.unmarshalBinary(r)
|
||||
//}
|
||||
//
|
||||
//func (st *StackTrie) unmarshalBinary(r io.Reader) error {
|
||||
// var dec struct {
|
||||
// Owner common.Hash
|
||||
// NodeType uint8
|
||||
// Val []byte
|
||||
// Key []byte
|
||||
// }
|
||||
// if err := gob.NewDecoder(r).Decode(&dec); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// st.owner = dec.Owner
|
||||
// st.nodeType = dec.NodeType
|
||||
// st.val = dec.Val
|
||||
// st.key = dec.Key
|
||||
//
|
||||
// var hasChild = make([]byte, 1)
|
||||
// for i := range st.children {
|
||||
// if _, err := r.Read(hasChild); err != nil {
|
||||
// return err
|
||||
// } else if hasChild[0] == 0 {
|
||||
// continue
|
||||
// }
|
||||
// var child StackTrie
|
||||
// if err := child.unmarshalBinary(r); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// st.children[i] = &child
|
||||
// }
|
||||
// return nil
|
||||
//}
|
||||
|
|
|
|||
114
trie/stacktrie_marshalling.go
Normal file
114
trie/stacktrie_marshalling.go
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
// Copyright 2023 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package trie
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding"
|
||||
"encoding/gob"
|
||||
)
|
||||
|
||||
var ( //Compile-time interface checks
|
||||
_ = encoding.BinaryMarshaler((*StackTrie)(nil))
|
||||
_ = encoding.BinaryUnmarshaler((*StackTrie)(nil))
|
||||
)
|
||||
|
||||
// NewFromBinaryV2 initialises a serialized stacktrie with the given db.
|
||||
// OBS! Format was changed along with the name of this constructor.
|
||||
func NewFromBinaryV2(data []byte, writeFn NodeWriteFunc) (*StackTrie, error) {
|
||||
stack := NewStackTrie(writeFn)
|
||||
if err := stack.UnmarshalBinary(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return stack, nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements encoding.BinaryMarshaler
|
||||
func (st *StackTrie) MarshalBinary() (data []byte, err error) {
|
||||
var (
|
||||
b bytes.Buffer
|
||||
w = bufio.NewWriter(&b)
|
||||
)
|
||||
if err := gob.NewEncoder(w).Encode(st.owner); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := st.root.marshalInto(w); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
w.Flush()
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements encoding.BinaryUnmarshaler
|
||||
func (stack *StackTrie) UnmarshalBinary(data []byte) error {
|
||||
r := bytes.NewReader(data)
|
||||
if err := gob.NewDecoder(r).Decode(&stack.owner); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := stack.root.unmarshalFrom(r); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type encodedNode struct {
|
||||
NodeType uint8
|
||||
Val []byte
|
||||
Key []byte
|
||||
}
|
||||
|
||||
func (st *stNode) marshalInto(w *bufio.Writer) (err error) {
|
||||
if err := gob.NewEncoder(w).Encode(encodedNode{st.nodeType, st.val, st.key}); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, child := range st.children {
|
||||
if child == nil {
|
||||
w.WriteByte(0)
|
||||
continue
|
||||
}
|
||||
w.WriteByte(1)
|
||||
if err := child.marshalInto(w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (st *stNode) unmarshalFrom(r *bytes.Reader) error {
|
||||
var dec encodedNode
|
||||
if err := gob.NewDecoder(r).Decode(&dec); err != nil {
|
||||
return err
|
||||
}
|
||||
st.nodeType = dec.NodeType
|
||||
st.val = dec.Val
|
||||
st.key = dec.Key
|
||||
|
||||
for i := range st.children {
|
||||
if b, err := r.ReadByte(); err != nil {
|
||||
return err
|
||||
} else if b == 0 {
|
||||
continue
|
||||
}
|
||||
var child stNode
|
||||
if err := child.unmarshalFrom(r); err != nil {
|
||||
return err
|
||||
}
|
||||
st.children[i] = &child
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -379,45 +379,48 @@ func TestStacktrieNotModifyValues(t *testing.T) {
|
|||
|
||||
// TestStacktrieSerialization tests that the stacktrie works well if we
|
||||
// serialize/unserialize it a lot
|
||||
//func TestStacktrieSerialization(t *testing.T) {
|
||||
// var (
|
||||
// st = NewStackTrie(nil)
|
||||
// nt = NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
|
||||
// keyB = big.NewInt(1)
|
||||
// keyDelta = big.NewInt(1)
|
||||
// vals [][]byte
|
||||
// keys [][]byte
|
||||
// )
|
||||
// getValue := func(i int) []byte {
|
||||
// if i%2 == 0 { // large
|
||||
// return crypto.Keccak256(big.NewInt(int64(i)).Bytes())
|
||||
// } else { //small
|
||||
// return big.NewInt(int64(i)).Bytes()
|
||||
// }
|
||||
// }
|
||||
// for i := 0; i < 10; i++ {
|
||||
// vals = append(vals, getValue(i))
|
||||
// keys = append(keys, common.BigToHash(keyB).Bytes())
|
||||
// keyB = keyB.Add(keyB, keyDelta)
|
||||
// keyDelta.Add(keyDelta, common.Big1)
|
||||
// }
|
||||
// for i, k := range keys {
|
||||
// nt.Update(k, common.CopyBytes(vals[i]))
|
||||
// }
|
||||
//
|
||||
// for i, k := range keys {
|
||||
// blob, err := st.MarshalBinary()
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// newSt, err := NewFromBinary(blob, nil)
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// st = newSt
|
||||
// st.Update(k, common.CopyBytes(vals[i]))
|
||||
// }
|
||||
// if have, want := st.Hash(), nt.Hash(); have != want {
|
||||
// t.Fatalf("have %#x want %#x", have, want)
|
||||
// }
|
||||
//}
|
||||
func TestStacktrieSerialization(t *testing.T) {
|
||||
var (
|
||||
st = NewStackTrieWithOwner(nil, common.Hash{0x12})
|
||||
nt = NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
|
||||
keyB = big.NewInt(1)
|
||||
keyDelta = big.NewInt(1)
|
||||
vals [][]byte
|
||||
keys [][]byte
|
||||
)
|
||||
getValue := func(i int) []byte {
|
||||
if i%2 == 0 { // large
|
||||
return crypto.Keccak256(big.NewInt(int64(i)).Bytes())
|
||||
} else { //small
|
||||
return big.NewInt(int64(i)).Bytes()
|
||||
}
|
||||
}
|
||||
for i := 0; i < 10; i++ {
|
||||
vals = append(vals, getValue(i))
|
||||
keys = append(keys, common.BigToHash(keyB).Bytes())
|
||||
keyB = keyB.Add(keyB, keyDelta)
|
||||
keyDelta.Add(keyDelta, common.Big1)
|
||||
}
|
||||
for i, k := range keys {
|
||||
nt.Update(k, common.CopyBytes(vals[i]))
|
||||
}
|
||||
|
||||
for i, k := range keys {
|
||||
blob, err := st.MarshalBinary()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
newSt, err := NewFromBinaryV2(blob, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st = newSt
|
||||
st.Update(k, common.CopyBytes(vals[i]))
|
||||
}
|
||||
if have, want := st.Hash(), nt.Hash(); have != want {
|
||||
t.Fatalf("have %#x want %#x", have, want)
|
||||
}
|
||||
if have, want := st.owner, (common.Hash{0x12}); have != want {
|
||||
t.Fatalf("have %#x want %#x", have, want)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue