123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- package trie
- import (
- "bytes"
- "math/big"
- "testing"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/ethdb/memorydb"
- )
- func TestSizeBug(t *testing.T) {
- st := NewStackTrie(nil)
- nt, _ := New(common.Hash{}, NewDatabase(memorydb.New()))
- leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
- value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3")
- nt.TryUpdate(leaf, value)
- st.TryUpdate(leaf, value)
- if nt.Hash() != st.Hash() {
- t.Fatalf("error %x != %x", st.Hash(), nt.Hash())
- }
- }
- func TestEmptyBug(t *testing.T) {
- st := NewStackTrie(nil)
- nt, _ := New(common.Hash{}, NewDatabase(memorydb.New()))
- //leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
- //value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3")
- kvs := []struct {
- K string
- V string
- }{
- {K: "405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace", V: "9496f4ec2bf9dab484cac6be589e8417d84781be08"},
- {K: "40edb63a35fcf86c08022722aa3287cdd36440d671b4918131b2514795fefa9c", V: "01"},
- {K: "b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6", V: "947a30f7736e48d6599356464ba4c150d8da0302ff"},
- {K: "c2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", V: "02"},
- }
- for _, kv := range kvs {
- nt.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V))
- st.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V))
- }
- if nt.Hash() != st.Hash() {
- t.Fatalf("error %x != %x", st.Hash(), nt.Hash())
- }
- }
- func TestValLength56(t *testing.T) {
- st := NewStackTrie(nil)
- nt, _ := New(common.Hash{}, NewDatabase(memorydb.New()))
- //leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
- //value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3")
- kvs := []struct {
- K string
- V string
- }{
- {K: "405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace", V: "1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"},
- }
- for _, kv := range kvs {
- nt.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V))
- st.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V))
- }
- if nt.Hash() != st.Hash() {
- t.Fatalf("error %x != %x", st.Hash(), nt.Hash())
- }
- }
- // TestUpdateSmallNodes tests a case where the leaves are small (both key and value),
- // which causes a lot of node-within-node. This case was found via fuzzing.
- func TestUpdateSmallNodes(t *testing.T) {
- st := NewStackTrie(nil)
- nt, _ := New(common.Hash{}, NewDatabase(memorydb.New()))
- kvs := []struct {
- K string
- V string
- }{
- {"63303030", "3041"}, // stacktrie.Update
- {"65", "3000"}, // stacktrie.Update
- }
- for _, kv := range kvs {
- nt.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V))
- st.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V))
- }
- if nt.Hash() != st.Hash() {
- t.Fatalf("error %x != %x", st.Hash(), nt.Hash())
- }
- }
- // TestUpdateVariableKeys contains a case which stacktrie fails: when keys of different
- // sizes are used, and the second one has the same prefix as the first, then the
- // stacktrie fails, since it's unable to 'expand' on an already added leaf.
- // For all practical purposes, this is fine, since keys are fixed-size length
- // in account and storage tries.
- //
- // The test is marked as 'skipped', and exists just to have the behaviour documented.
- // This case was found via fuzzing.
- func TestUpdateVariableKeys(t *testing.T) {
- t.SkipNow()
- st := NewStackTrie(nil)
- nt, _ := New(common.Hash{}, NewDatabase(memorydb.New()))
- kvs := []struct {
- K string
- V string
- }{
- {"0x33303534636532393561313031676174", "303030"},
- {"0x3330353463653239356131303167617430", "313131"},
- }
- for _, kv := range kvs {
- nt.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V))
- st.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V))
- }
- if nt.Hash() != st.Hash() {
- t.Fatalf("error %x != %x", st.Hash(), nt.Hash())
- }
- }
- // TestStacktrieNotModifyValues checks that inserting blobs of data into the
- // stacktrie does not mutate the blobs
- func TestStacktrieNotModifyValues(t *testing.T) {
- st := NewStackTrie(nil)
- { // Test a very small trie
- // Give it the value as a slice with large backing alloc,
- // so if the stacktrie tries to append, it won't have to realloc
- value := make([]byte, 1, 100)
- value[0] = 0x2
- want := common.CopyBytes(value)
- st.TryUpdate([]byte{0x01}, value)
- st.Hash()
- if have := value; !bytes.Equal(have, want) {
- t.Fatalf("tiny trie: have %#x want %#x", have, want)
- }
- st = NewStackTrie(nil)
- }
- // Test with a larger trie
- keyB := big.NewInt(1)
- keyDelta := big.NewInt(1)
- var vals [][]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 < 1000; i++ {
- key := common.BigToHash(keyB)
- value := getValue(i)
- st.TryUpdate(key.Bytes(), value)
- vals = append(vals, value)
- keyB = keyB.Add(keyB, keyDelta)
- keyDelta.Add(keyDelta, common.Big1)
- }
- st.Hash()
- for i := 0; i < 1000; i++ {
- want := getValue(i)
- have := vals[i]
- if !bytes.Equal(have, want) {
- t.Fatalf("item %d, have %#x want %#x", i, have, want)
- }
- }
- }
- // TestStacktrieSerialization tests that the stacktrie works well if we
- // serialize/unserialize it a lot
- func TestStacktrieSerialization(t *testing.T) {
- var (
- st = NewStackTrie(nil)
- nt, _ = New(common.Hash{}, NewDatabase(memorydb.New()))
- 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.TryUpdate(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.TryUpdate(k, common.CopyBytes(vals[i]))
- }
- if have, want := st.Hash(), nt.Hash(); have != want {
- t.Fatalf("have %#x want %#x", have, want)
- }
- }
|