|
|
@ -25,6 +25,7 @@ import ( |
|
|
|
"io" |
|
|
|
"io" |
|
|
|
"math/rand" |
|
|
|
"math/rand" |
|
|
|
"reflect" |
|
|
|
"reflect" |
|
|
|
|
|
|
|
"sort" |
|
|
|
"testing" |
|
|
|
"testing" |
|
|
|
"testing/quick" |
|
|
|
"testing/quick" |
|
|
|
|
|
|
|
|
|
|
@ -46,7 +47,7 @@ func init() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func TestEmptyTrie(t *testing.T) { |
|
|
|
func TestEmptyTrie(t *testing.T) { |
|
|
|
trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) |
|
|
|
trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) |
|
|
|
res := trie.Hash() |
|
|
|
res := trie.Hash() |
|
|
|
exp := types.EmptyRootHash |
|
|
|
exp := types.EmptyRootHash |
|
|
|
if res != exp { |
|
|
|
if res != exp { |
|
|
@ -55,7 +56,7 @@ func TestEmptyTrie(t *testing.T) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func TestNull(t *testing.T) { |
|
|
|
func TestNull(t *testing.T) { |
|
|
|
trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) |
|
|
|
trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) |
|
|
|
key := make([]byte, 32) |
|
|
|
key := make([]byte, 32) |
|
|
|
value := []byte("test") |
|
|
|
value := []byte("test") |
|
|
|
trie.MustUpdate(key, value) |
|
|
|
trie.MustUpdate(key, value) |
|
|
@ -95,10 +96,10 @@ func testMissingNode(t *testing.T, memonly bool, scheme string) { |
|
|
|
updateString(trie, "120000", "qwerqwerqwerqwerqwerqwerqwerqwer") |
|
|
|
updateString(trie, "120000", "qwerqwerqwerqwerqwerqwerqwerqwer") |
|
|
|
updateString(trie, "123456", "asdfasdfasdfasdfasdfasdfasdfasdf") |
|
|
|
updateString(trie, "123456", "asdfasdfasdfasdfasdfasdfasdfasdf") |
|
|
|
root, nodes, _ := trie.Commit(false) |
|
|
|
root, nodes, _ := trie.Commit(false) |
|
|
|
triedb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil) |
|
|
|
triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) |
|
|
|
|
|
|
|
|
|
|
|
if !memonly { |
|
|
|
if !memonly { |
|
|
|
triedb.Commit(root, false) |
|
|
|
triedb.Commit(root) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
trie, _ = New(TrieID(root), triedb) |
|
|
|
trie, _ = New(TrieID(root), triedb) |
|
|
@ -167,7 +168,7 @@ func testMissingNode(t *testing.T, memonly bool, scheme string) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func TestInsert(t *testing.T) { |
|
|
|
func TestInsert(t *testing.T) { |
|
|
|
trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) |
|
|
|
trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) |
|
|
|
|
|
|
|
|
|
|
|
updateString(trie, "doe", "reindeer") |
|
|
|
updateString(trie, "doe", "reindeer") |
|
|
|
updateString(trie, "dog", "puppy") |
|
|
|
updateString(trie, "dog", "puppy") |
|
|
@ -179,7 +180,7 @@ func TestInsert(t *testing.T) { |
|
|
|
t.Errorf("case 1: exp %x got %x", exp, root) |
|
|
|
t.Errorf("case 1: exp %x got %x", exp, root) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
trie = NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) |
|
|
|
trie = NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) |
|
|
|
updateString(trie, "A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") |
|
|
|
updateString(trie, "A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") |
|
|
|
|
|
|
|
|
|
|
|
exp = common.HexToHash("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab") |
|
|
|
exp = common.HexToHash("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab") |
|
|
@ -190,7 +191,7 @@ func TestInsert(t *testing.T) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func TestGet(t *testing.T) { |
|
|
|
func TestGet(t *testing.T) { |
|
|
|
db := NewDatabase(rawdb.NewMemoryDatabase(), nil) |
|
|
|
db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme) |
|
|
|
trie := NewEmpty(db) |
|
|
|
trie := NewEmpty(db) |
|
|
|
updateString(trie, "doe", "reindeer") |
|
|
|
updateString(trie, "doe", "reindeer") |
|
|
|
updateString(trie, "dog", "puppy") |
|
|
|
updateString(trie, "dog", "puppy") |
|
|
@ -209,13 +210,14 @@ func TestGet(t *testing.T) { |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
root, nodes, _ := trie.Commit(false) |
|
|
|
root, nodes, _ := trie.Commit(false) |
|
|
|
db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil) |
|
|
|
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) |
|
|
|
trie, _ = New(TrieID(root), db) |
|
|
|
trie, _ = New(TrieID(root), db) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func TestDelete(t *testing.T) { |
|
|
|
func TestDelete(t *testing.T) { |
|
|
|
trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) |
|
|
|
db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme) |
|
|
|
|
|
|
|
trie := NewEmpty(db) |
|
|
|
vals := []struct{ k, v string }{ |
|
|
|
vals := []struct{ k, v string }{ |
|
|
|
{"do", "verb"}, |
|
|
|
{"do", "verb"}, |
|
|
|
{"ether", "wookiedoo"}, |
|
|
|
{"ether", "wookiedoo"}, |
|
|
@ -242,7 +244,7 @@ func TestDelete(t *testing.T) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func TestEmptyValues(t *testing.T) { |
|
|
|
func TestEmptyValues(t *testing.T) { |
|
|
|
trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) |
|
|
|
trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) |
|
|
|
|
|
|
|
|
|
|
|
vals := []struct{ k, v string }{ |
|
|
|
vals := []struct{ k, v string }{ |
|
|
|
{"do", "verb"}, |
|
|
|
{"do", "verb"}, |
|
|
@ -266,7 +268,7 @@ func TestEmptyValues(t *testing.T) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func TestReplication(t *testing.T) { |
|
|
|
func TestReplication(t *testing.T) { |
|
|
|
db := NewDatabase(rawdb.NewMemoryDatabase(), nil) |
|
|
|
db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme) |
|
|
|
trie := NewEmpty(db) |
|
|
|
trie := NewEmpty(db) |
|
|
|
vals := []struct{ k, v string }{ |
|
|
|
vals := []struct{ k, v string }{ |
|
|
|
{"do", "verb"}, |
|
|
|
{"do", "verb"}, |
|
|
@ -281,7 +283,7 @@ func TestReplication(t *testing.T) { |
|
|
|
updateString(trie, val.k, val.v) |
|
|
|
updateString(trie, val.k, val.v) |
|
|
|
} |
|
|
|
} |
|
|
|
root, nodes, _ := trie.Commit(false) |
|
|
|
root, nodes, _ := trie.Commit(false) |
|
|
|
db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil) |
|
|
|
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) |
|
|
|
|
|
|
|
|
|
|
|
// create a new trie on top of the database and check that lookups work.
|
|
|
|
// create a new trie on top of the database and check that lookups work.
|
|
|
|
trie2, err := New(TrieID(root), db) |
|
|
|
trie2, err := New(TrieID(root), db) |
|
|
@ -300,7 +302,7 @@ func TestReplication(t *testing.T) { |
|
|
|
|
|
|
|
|
|
|
|
// recreate the trie after commit
|
|
|
|
// recreate the trie after commit
|
|
|
|
if nodes != nil { |
|
|
|
if nodes != nil { |
|
|
|
db.Update(hash, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil) |
|
|
|
db.Update(hash, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) |
|
|
|
} |
|
|
|
} |
|
|
|
trie2, err = New(TrieID(hash), db) |
|
|
|
trie2, err = New(TrieID(hash), db) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
@ -327,7 +329,7 @@ func TestReplication(t *testing.T) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func TestLargeValue(t *testing.T) { |
|
|
|
func TestLargeValue(t *testing.T) { |
|
|
|
trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) |
|
|
|
trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) |
|
|
|
trie.MustUpdate([]byte("key1"), []byte{99, 99, 99, 99}) |
|
|
|
trie.MustUpdate([]byte("key1"), []byte{99, 99, 99, 99}) |
|
|
|
trie.MustUpdate([]byte("key2"), bytes.Repeat([]byte{1}, 32)) |
|
|
|
trie.MustUpdate([]byte("key2"), bytes.Repeat([]byte{1}, 32)) |
|
|
|
trie.Hash() |
|
|
|
trie.Hash() |
|
|
@ -531,7 +533,7 @@ func runRandTest(rt randTest) error { |
|
|
|
case opCommit: |
|
|
|
case opCommit: |
|
|
|
root, nodes, _ := tr.Commit(true) |
|
|
|
root, nodes, _ := tr.Commit(true) |
|
|
|
if nodes != nil { |
|
|
|
if nodes != nil { |
|
|
|
triedb.Update(root, origin, 0, trienode.NewWithNodeSet(nodes), nil) |
|
|
|
triedb.Update(root, origin, trienode.NewWithNodeSet(nodes)) |
|
|
|
} |
|
|
|
} |
|
|
|
newtr, err := New(TrieID(root), triedb) |
|
|
|
newtr, err := New(TrieID(root), triedb) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
@ -632,7 +634,7 @@ func BenchmarkUpdateLE(b *testing.B) { benchUpdate(b, binary.LittleEndian) } |
|
|
|
const benchElemCount = 20000 |
|
|
|
const benchElemCount = 20000 |
|
|
|
|
|
|
|
|
|
|
|
func benchGet(b *testing.B) { |
|
|
|
func benchGet(b *testing.B) { |
|
|
|
triedb := NewDatabase(rawdb.NewMemoryDatabase(), nil) |
|
|
|
triedb := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme) |
|
|
|
trie := NewEmpty(triedb) |
|
|
|
trie := NewEmpty(triedb) |
|
|
|
k := make([]byte, 32) |
|
|
|
k := make([]byte, 32) |
|
|
|
for i := 0; i < benchElemCount; i++ { |
|
|
|
for i := 0; i < benchElemCount; i++ { |
|
|
@ -651,7 +653,7 @@ func benchGet(b *testing.B) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func benchUpdate(b *testing.B, e binary.ByteOrder) *Trie { |
|
|
|
func benchUpdate(b *testing.B, e binary.ByteOrder) *Trie { |
|
|
|
trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) |
|
|
|
trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) |
|
|
|
k := make([]byte, 32) |
|
|
|
k := make([]byte, 32) |
|
|
|
b.ReportAllocs() |
|
|
|
b.ReportAllocs() |
|
|
|
for i := 0; i < b.N; i++ { |
|
|
|
for i := 0; i < b.N; i++ { |
|
|
@ -683,7 +685,7 @@ func BenchmarkHash(b *testing.B) { |
|
|
|
// entries, then adding N more.
|
|
|
|
// entries, then adding N more.
|
|
|
|
addresses, accounts := makeAccounts(2 * b.N) |
|
|
|
addresses, accounts := makeAccounts(2 * b.N) |
|
|
|
// Insert the accounts into the trie and hash it
|
|
|
|
// Insert the accounts into the trie and hash it
|
|
|
|
trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) |
|
|
|
trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) |
|
|
|
i := 0 |
|
|
|
i := 0 |
|
|
|
for ; i < len(addresses)/2; i++ { |
|
|
|
for ; i < len(addresses)/2; i++ { |
|
|
|
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) |
|
|
|
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) |
|
|
@ -714,7 +716,7 @@ func BenchmarkCommitAfterHash(b *testing.B) { |
|
|
|
func benchmarkCommitAfterHash(b *testing.B, collectLeaf bool) { |
|
|
|
func benchmarkCommitAfterHash(b *testing.B, collectLeaf bool) { |
|
|
|
// Make the random benchmark deterministic
|
|
|
|
// Make the random benchmark deterministic
|
|
|
|
addresses, accounts := makeAccounts(b.N) |
|
|
|
addresses, accounts := makeAccounts(b.N) |
|
|
|
trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) |
|
|
|
trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) |
|
|
|
for i := 0; i < len(addresses); i++ { |
|
|
|
for i := 0; i < len(addresses); i++ { |
|
|
|
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) |
|
|
|
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) |
|
|
|
} |
|
|
|
} |
|
|
@ -728,7 +730,7 @@ func benchmarkCommitAfterHash(b *testing.B, collectLeaf bool) { |
|
|
|
func TestTinyTrie(t *testing.T) { |
|
|
|
func TestTinyTrie(t *testing.T) { |
|
|
|
// Create a realistic account trie to hash
|
|
|
|
// Create a realistic account trie to hash
|
|
|
|
_, accounts := makeAccounts(5) |
|
|
|
_, accounts := makeAccounts(5) |
|
|
|
trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) |
|
|
|
trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) |
|
|
|
trie.MustUpdate(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001337"), accounts[3]) |
|
|
|
trie.MustUpdate(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001337"), accounts[3]) |
|
|
|
if exp, root := common.HexToHash("8c6a85a4d9fda98feff88450299e574e5378e32391f75a055d470ac0653f1005"), trie.Hash(); exp != root { |
|
|
|
if exp, root := common.HexToHash("8c6a85a4d9fda98feff88450299e574e5378e32391f75a055d470ac0653f1005"), trie.Hash(); exp != root { |
|
|
|
t.Errorf("1: got %x, exp %x", root, exp) |
|
|
|
t.Errorf("1: got %x, exp %x", root, exp) |
|
|
@ -741,7 +743,7 @@ func TestTinyTrie(t *testing.T) { |
|
|
|
if exp, root := common.HexToHash("0608c1d1dc3905fa22204c7a0e43644831c3b6d3def0f274be623a948197e64a"), trie.Hash(); exp != root { |
|
|
|
if exp, root := common.HexToHash("0608c1d1dc3905fa22204c7a0e43644831c3b6d3def0f274be623a948197e64a"), trie.Hash(); exp != root { |
|
|
|
t.Errorf("3: got %x, exp %x", root, exp) |
|
|
|
t.Errorf("3: got %x, exp %x", root, exp) |
|
|
|
} |
|
|
|
} |
|
|
|
checktr := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) |
|
|
|
checktr := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) |
|
|
|
it := NewIterator(trie.MustNodeIterator(nil)) |
|
|
|
it := NewIterator(trie.MustNodeIterator(nil)) |
|
|
|
for it.Next() { |
|
|
|
for it.Next() { |
|
|
|
checktr.MustUpdate(it.Key, it.Value) |
|
|
|
checktr.MustUpdate(it.Key, it.Value) |
|
|
@ -754,7 +756,7 @@ func TestTinyTrie(t *testing.T) { |
|
|
|
func TestCommitAfterHash(t *testing.T) { |
|
|
|
func TestCommitAfterHash(t *testing.T) { |
|
|
|
// Create a realistic account trie to hash
|
|
|
|
// Create a realistic account trie to hash
|
|
|
|
addresses, accounts := makeAccounts(1000) |
|
|
|
addresses, accounts := makeAccounts(1000) |
|
|
|
trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) |
|
|
|
trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) |
|
|
|
for i := 0; i < len(addresses); i++ { |
|
|
|
for i := 0; i < len(addresses); i++ { |
|
|
|
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) |
|
|
|
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) |
|
|
|
} |
|
|
|
} |
|
|
@ -808,6 +810,8 @@ type spongeDb struct { |
|
|
|
sponge hash.Hash |
|
|
|
sponge hash.Hash |
|
|
|
id string |
|
|
|
id string |
|
|
|
journal []string |
|
|
|
journal []string |
|
|
|
|
|
|
|
keys []string |
|
|
|
|
|
|
|
values map[string]string |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (s *spongeDb) Has(key []byte) (bool, error) { panic("implement me") } |
|
|
|
func (s *spongeDb) Has(key []byte) (bool, error) { panic("implement me") } |
|
|
@ -831,12 +835,27 @@ func (s *spongeDb) Put(key []byte, value []byte) error { |
|
|
|
valbrief = valbrief[:8] |
|
|
|
valbrief = valbrief[:8] |
|
|
|
} |
|
|
|
} |
|
|
|
s.journal = append(s.journal, fmt.Sprintf("%v: PUT([%x...], [%d bytes] %x...)\n", s.id, keybrief, len(value), valbrief)) |
|
|
|
s.journal = append(s.journal, fmt.Sprintf("%v: PUT([%x...], [%d bytes] %x...)\n", s.id, keybrief, len(value), valbrief)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if s.values == nil { |
|
|
|
s.sponge.Write(key) |
|
|
|
s.sponge.Write(key) |
|
|
|
s.sponge.Write(value) |
|
|
|
s.sponge.Write(value) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
s.keys = append(s.keys, string(key)) |
|
|
|
|
|
|
|
s.values[string(key)] = string(value) |
|
|
|
|
|
|
|
} |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
func (s *spongeDb) NewIterator(prefix []byte, start []byte) ethdb.Iterator { panic("implement me") } |
|
|
|
func (s *spongeDb) NewIterator(prefix []byte, start []byte) ethdb.Iterator { panic("implement me") } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (s *spongeDb) Flush() { |
|
|
|
|
|
|
|
// Bottom-up, the longest path first
|
|
|
|
|
|
|
|
sort.Sort(sort.Reverse(sort.StringSlice(s.keys))) |
|
|
|
|
|
|
|
for _, key := range s.keys { |
|
|
|
|
|
|
|
s.sponge.Write([]byte(key)) |
|
|
|
|
|
|
|
s.sponge.Write([]byte(s.values[key])) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// spongeBatch is a dummy batch which immediately writes to the underlying spongedb
|
|
|
|
// spongeBatch is a dummy batch which immediately writes to the underlying spongedb
|
|
|
|
type spongeBatch struct { |
|
|
|
type spongeBatch struct { |
|
|
|
db *spongeDb |
|
|
|
db *spongeDb |
|
|
@ -861,14 +880,14 @@ func TestCommitSequence(t *testing.T) { |
|
|
|
count int |
|
|
|
count int |
|
|
|
expWriteSeqHash []byte |
|
|
|
expWriteSeqHash []byte |
|
|
|
}{ |
|
|
|
}{ |
|
|
|
{20, common.FromHex("873c78df73d60e59d4a2bcf3716e8bfe14554549fea2fc147cb54129382a8066")}, |
|
|
|
{20, common.FromHex("330b0afae2853d96b9f015791fbe0fb7f239bf65f335f16dfc04b76c7536276d")}, |
|
|
|
{200, common.FromHex("ba03d891bb15408c940eea5ee3d54d419595102648d02774a0268d892add9c8e")}, |
|
|
|
{200, common.FromHex("5162b3735c06b5d606b043a3ee8adbdbbb408543f4966bca9dcc63da82684eeb")}, |
|
|
|
{2000, common.FromHex("f7a184f20df01c94f09537401d11e68d97ad0c00115233107f51b9c287ce60c7")}, |
|
|
|
{2000, common.FromHex("4574cd8e6b17f3fe8ad89140d1d0bf4f1bd7a87a8ac3fb623b33550544c77635")}, |
|
|
|
} { |
|
|
|
} { |
|
|
|
addresses, accounts := makeAccounts(tc.count) |
|
|
|
addresses, accounts := makeAccounts(tc.count) |
|
|
|
// This spongeDb is used to check the sequence of disk-db-writes
|
|
|
|
// This spongeDb is used to check the sequence of disk-db-writes
|
|
|
|
s := &spongeDb{sponge: sha3.NewLegacyKeccak256()} |
|
|
|
s := &spongeDb{sponge: sha3.NewLegacyKeccak256()} |
|
|
|
db := NewDatabase(rawdb.NewDatabase(s), nil) |
|
|
|
db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme) |
|
|
|
trie := NewEmpty(db) |
|
|
|
trie := NewEmpty(db) |
|
|
|
// Fill the trie with elements
|
|
|
|
// Fill the trie with elements
|
|
|
|
for i := 0; i < tc.count; i++ { |
|
|
|
for i := 0; i < tc.count; i++ { |
|
|
@ -876,9 +895,9 @@ func TestCommitSequence(t *testing.T) { |
|
|
|
} |
|
|
|
} |
|
|
|
// Flush trie -> database
|
|
|
|
// Flush trie -> database
|
|
|
|
root, nodes, _ := trie.Commit(false) |
|
|
|
root, nodes, _ := trie.Commit(false) |
|
|
|
db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil) |
|
|
|
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) |
|
|
|
// Flush memdb -> disk (sponge)
|
|
|
|
// Flush memdb -> disk (sponge)
|
|
|
|
db.Commit(root, false) |
|
|
|
db.Commit(root) |
|
|
|
if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) { |
|
|
|
if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) { |
|
|
|
t.Errorf("test %d, disk write sequence wrong:\ngot %x exp %x\n", i, got, exp) |
|
|
|
t.Errorf("test %d, disk write sequence wrong:\ngot %x exp %x\n", i, got, exp) |
|
|
|
} |
|
|
|
} |
|
|
@ -892,14 +911,14 @@ func TestCommitSequenceRandomBlobs(t *testing.T) { |
|
|
|
count int |
|
|
|
count int |
|
|
|
expWriteSeqHash []byte |
|
|
|
expWriteSeqHash []byte |
|
|
|
}{ |
|
|
|
}{ |
|
|
|
{20, common.FromHex("8e4a01548551d139fa9e833ebc4e66fc1ba40a4b9b7259d80db32cff7b64ebbc")}, |
|
|
|
{20, common.FromHex("8016650c7a50cf88485fd06cde52d634a89711051107f00d21fae98234f2f13d")}, |
|
|
|
{200, common.FromHex("6869b4e7b95f3097a19ddb30ff735f922b915314047e041614df06958fc50554")}, |
|
|
|
{200, common.FromHex("dde92ca9812e068e6982d04b40846dc65a61a9fd4996fc0f55f2fde172a8e13c")}, |
|
|
|
{2000, common.FromHex("444200e6f4e2df49f77752f629a96ccf7445d4698c164f962bbd85a0526ef424")}, |
|
|
|
{2000, common.FromHex("ab553a7f9aff82e3929c382908e30ef7dd17a332933e92ba3fe873fc661ef382")}, |
|
|
|
} { |
|
|
|
} { |
|
|
|
prng := rand.New(rand.NewSource(int64(i))) |
|
|
|
prng := rand.New(rand.NewSource(int64(i))) |
|
|
|
// This spongeDb is used to check the sequence of disk-db-writes
|
|
|
|
// This spongeDb is used to check the sequence of disk-db-writes
|
|
|
|
s := &spongeDb{sponge: sha3.NewLegacyKeccak256()} |
|
|
|
s := &spongeDb{sponge: sha3.NewLegacyKeccak256()} |
|
|
|
db := NewDatabase(rawdb.NewDatabase(s), nil) |
|
|
|
db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme) |
|
|
|
trie := NewEmpty(db) |
|
|
|
trie := NewEmpty(db) |
|
|
|
// Fill the trie with elements
|
|
|
|
// Fill the trie with elements
|
|
|
|
for i := 0; i < tc.count; i++ { |
|
|
|
for i := 0; i < tc.count; i++ { |
|
|
@ -917,9 +936,9 @@ func TestCommitSequenceRandomBlobs(t *testing.T) { |
|
|
|
} |
|
|
|
} |
|
|
|
// Flush trie -> database
|
|
|
|
// Flush trie -> database
|
|
|
|
root, nodes, _ := trie.Commit(false) |
|
|
|
root, nodes, _ := trie.Commit(false) |
|
|
|
db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil) |
|
|
|
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) |
|
|
|
// Flush memdb -> disk (sponge)
|
|
|
|
// Flush memdb -> disk (sponge)
|
|
|
|
db.Commit(root, false) |
|
|
|
db.Commit(root) |
|
|
|
if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) { |
|
|
|
if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) { |
|
|
|
t.Fatalf("test %d, disk write sequence wrong:\ngot %x exp %x\n", i, got, exp) |
|
|
|
t.Fatalf("test %d, disk write sequence wrong:\ngot %x exp %x\n", i, got, exp) |
|
|
|
} |
|
|
|
} |
|
|
@ -930,17 +949,26 @@ func TestCommitSequenceStackTrie(t *testing.T) { |
|
|
|
for count := 1; count < 200; count++ { |
|
|
|
for count := 1; count < 200; count++ { |
|
|
|
prng := rand.New(rand.NewSource(int64(count))) |
|
|
|
prng := rand.New(rand.NewSource(int64(count))) |
|
|
|
// This spongeDb is used to check the sequence of disk-db-writes
|
|
|
|
// This spongeDb is used to check the sequence of disk-db-writes
|
|
|
|
s := &spongeDb{sponge: sha3.NewLegacyKeccak256(), id: "a"} |
|
|
|
s := &spongeDb{ |
|
|
|
db := NewDatabase(rawdb.NewDatabase(s), nil) |
|
|
|
sponge: sha3.NewLegacyKeccak256(), |
|
|
|
|
|
|
|
id: "a", |
|
|
|
|
|
|
|
values: make(map[string]string), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme) |
|
|
|
trie := NewEmpty(db) |
|
|
|
trie := NewEmpty(db) |
|
|
|
// Another sponge is used for the stacktrie commits
|
|
|
|
|
|
|
|
stackTrieSponge := &spongeDb{sponge: sha3.NewLegacyKeccak256(), id: "b"} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Another sponge is used for the stacktrie commits
|
|
|
|
|
|
|
|
stackTrieSponge := &spongeDb{ |
|
|
|
|
|
|
|
sponge: sha3.NewLegacyKeccak256(), |
|
|
|
|
|
|
|
id: "b", |
|
|
|
|
|
|
|
values: make(map[string]string), |
|
|
|
|
|
|
|
} |
|
|
|
options := NewStackTrieOptions() |
|
|
|
options := NewStackTrieOptions() |
|
|
|
options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) { |
|
|
|
options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) { |
|
|
|
rawdb.WriteTrieNode(stackTrieSponge, common.Hash{}, path, hash, blob, db.Scheme()) |
|
|
|
rawdb.WriteTrieNode(stackTrieSponge, common.Hash{}, path, hash, blob, db.Scheme()) |
|
|
|
}) |
|
|
|
}) |
|
|
|
stTrie := NewStackTrie(options) |
|
|
|
stTrie := NewStackTrie(options) |
|
|
|
|
|
|
|
|
|
|
|
// Fill the trie with elements
|
|
|
|
// Fill the trie with elements
|
|
|
|
for i := 0; i < count; i++ { |
|
|
|
for i := 0; i < count; i++ { |
|
|
|
// For the stack trie, we need to do inserts in proper order
|
|
|
|
// For the stack trie, we need to do inserts in proper order
|
|
|
@ -960,13 +988,16 @@ func TestCommitSequenceStackTrie(t *testing.T) { |
|
|
|
// Flush trie -> database
|
|
|
|
// Flush trie -> database
|
|
|
|
root, nodes, _ := trie.Commit(false) |
|
|
|
root, nodes, _ := trie.Commit(false) |
|
|
|
// Flush memdb -> disk (sponge)
|
|
|
|
// Flush memdb -> disk (sponge)
|
|
|
|
db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil) |
|
|
|
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) |
|
|
|
db.Commit(root, false) |
|
|
|
db.Commit(root) |
|
|
|
|
|
|
|
s.Flush() |
|
|
|
|
|
|
|
|
|
|
|
// And flush stacktrie -> disk
|
|
|
|
// And flush stacktrie -> disk
|
|
|
|
stRoot := stTrie.Commit() |
|
|
|
stRoot := stTrie.Commit() |
|
|
|
if stRoot != root { |
|
|
|
if stRoot != root { |
|
|
|
t.Fatalf("root wrong, got %x exp %x", stRoot, root) |
|
|
|
t.Fatalf("root wrong, got %x exp %x", stRoot, root) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
stackTrieSponge.Flush() |
|
|
|
if got, exp := stackTrieSponge.sponge.Sum(nil), s.sponge.Sum(nil); !bytes.Equal(got, exp) { |
|
|
|
if got, exp := stackTrieSponge.sponge.Sum(nil), s.sponge.Sum(nil); !bytes.Equal(got, exp) { |
|
|
|
// Show the journal
|
|
|
|
// Show the journal
|
|
|
|
t.Logf("Expected:") |
|
|
|
t.Logf("Expected:") |
|
|
@ -989,34 +1020,47 @@ func TestCommitSequenceStackTrie(t *testing.T) { |
|
|
|
// that even a small trie which contains a leaf will have an extension making it
|
|
|
|
// that even a small trie which contains a leaf will have an extension making it
|
|
|
|
// not fit into 32 bytes, rlp-encoded. However, it's still the correct thing to do.
|
|
|
|
// not fit into 32 bytes, rlp-encoded. However, it's still the correct thing to do.
|
|
|
|
func TestCommitSequenceSmallRoot(t *testing.T) { |
|
|
|
func TestCommitSequenceSmallRoot(t *testing.T) { |
|
|
|
s := &spongeDb{sponge: sha3.NewLegacyKeccak256(), id: "a"} |
|
|
|
s := &spongeDb{ |
|
|
|
db := NewDatabase(rawdb.NewDatabase(s), nil) |
|
|
|
sponge: sha3.NewLegacyKeccak256(), |
|
|
|
|
|
|
|
id: "a", |
|
|
|
|
|
|
|
values: make(map[string]string), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme) |
|
|
|
trie := NewEmpty(db) |
|
|
|
trie := NewEmpty(db) |
|
|
|
// Another sponge is used for the stacktrie commits
|
|
|
|
|
|
|
|
stackTrieSponge := &spongeDb{sponge: sha3.NewLegacyKeccak256(), id: "b"} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Another sponge is used for the stacktrie commits
|
|
|
|
|
|
|
|
stackTrieSponge := &spongeDb{ |
|
|
|
|
|
|
|
sponge: sha3.NewLegacyKeccak256(), |
|
|
|
|
|
|
|
id: "b", |
|
|
|
|
|
|
|
values: make(map[string]string), |
|
|
|
|
|
|
|
} |
|
|
|
options := NewStackTrieOptions() |
|
|
|
options := NewStackTrieOptions() |
|
|
|
options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) { |
|
|
|
options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) { |
|
|
|
rawdb.WriteTrieNode(stackTrieSponge, common.Hash{}, path, hash, blob, db.Scheme()) |
|
|
|
rawdb.WriteTrieNode(stackTrieSponge, common.Hash{}, path, hash, blob, db.Scheme()) |
|
|
|
}) |
|
|
|
}) |
|
|
|
stTrie := NewStackTrie(options) |
|
|
|
stTrie := NewStackTrie(options) |
|
|
|
|
|
|
|
|
|
|
|
// Add a single small-element to the trie(s)
|
|
|
|
// Add a single small-element to the trie(s)
|
|
|
|
key := make([]byte, 5) |
|
|
|
key := make([]byte, 5) |
|
|
|
key[0] = 1 |
|
|
|
key[0] = 1 |
|
|
|
trie.Update(key, []byte{0x1}) |
|
|
|
trie.Update(key, []byte{0x1}) |
|
|
|
stTrie.Update(key, []byte{0x1}) |
|
|
|
stTrie.Update(key, []byte{0x1}) |
|
|
|
|
|
|
|
|
|
|
|
// Flush trie -> database
|
|
|
|
// Flush trie -> database
|
|
|
|
root, nodes, _ := trie.Commit(false) |
|
|
|
root, nodes, _ := trie.Commit(false) |
|
|
|
// Flush memdb -> disk (sponge)
|
|
|
|
// Flush memdb -> disk (sponge)
|
|
|
|
db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil) |
|
|
|
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) |
|
|
|
db.Commit(root, false) |
|
|
|
db.Commit(root) |
|
|
|
|
|
|
|
|
|
|
|
// And flush stacktrie -> disk
|
|
|
|
// And flush stacktrie -> disk
|
|
|
|
stRoot := stTrie.Commit() |
|
|
|
stRoot := stTrie.Commit() |
|
|
|
if stRoot != root { |
|
|
|
if stRoot != root { |
|
|
|
t.Fatalf("root wrong, got %x exp %x", stRoot, root) |
|
|
|
t.Fatalf("root wrong, got %x exp %x", stRoot, root) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
t.Logf("root: %x\n", stRoot) |
|
|
|
t.Logf("root: %x\n", stRoot) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s.Flush() |
|
|
|
|
|
|
|
stackTrieSponge.Flush() |
|
|
|
if got, exp := stackTrieSponge.sponge.Sum(nil), s.sponge.Sum(nil); !bytes.Equal(got, exp) { |
|
|
|
if got, exp := stackTrieSponge.sponge.Sum(nil), s.sponge.Sum(nil); !bytes.Equal(got, exp) { |
|
|
|
t.Fatalf("test, disk write sequence wrong:\ngot %x exp %x\n", got, exp) |
|
|
|
t.Fatalf("test, disk write sequence wrong:\ngot %x exp %x\n", got, exp) |
|
|
|
} |
|
|
|
} |
|
|
@ -1067,7 +1111,7 @@ func BenchmarkHashFixedSize(b *testing.B) { |
|
|
|
|
|
|
|
|
|
|
|
func benchmarkHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { |
|
|
|
func benchmarkHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { |
|
|
|
b.ReportAllocs() |
|
|
|
b.ReportAllocs() |
|
|
|
trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) |
|
|
|
trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) |
|
|
|
for i := 0; i < len(addresses); i++ { |
|
|
|
for i := 0; i < len(addresses); i++ { |
|
|
|
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) |
|
|
|
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) |
|
|
|
} |
|
|
|
} |
|
|
@ -1118,7 +1162,7 @@ func BenchmarkCommitAfterHashFixedSize(b *testing.B) { |
|
|
|
|
|
|
|
|
|
|
|
func benchmarkCommitAfterHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { |
|
|
|
func benchmarkCommitAfterHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { |
|
|
|
b.ReportAllocs() |
|
|
|
b.ReportAllocs() |
|
|
|
trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) |
|
|
|
trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) |
|
|
|
for i := 0; i < len(addresses); i++ { |
|
|
|
for i := 0; i < len(addresses); i++ { |
|
|
|
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) |
|
|
|
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) |
|
|
|
} |
|
|
|
} |
|
|
@ -1129,60 +1173,6 @@ func benchmarkCommitAfterHashFixedSize(b *testing.B, addresses [][20]byte, accou |
|
|
|
b.StopTimer() |
|
|
|
b.StopTimer() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func BenchmarkDerefRootFixedSize(b *testing.B) { |
|
|
|
|
|
|
|
b.Run("10", func(b *testing.B) { |
|
|
|
|
|
|
|
b.StopTimer() |
|
|
|
|
|
|
|
acc, add := makeAccounts(20) |
|
|
|
|
|
|
|
for i := 0; i < b.N; i++ { |
|
|
|
|
|
|
|
benchmarkDerefRootFixedSize(b, acc, add) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
b.Run("100", func(b *testing.B) { |
|
|
|
|
|
|
|
b.StopTimer() |
|
|
|
|
|
|
|
acc, add := makeAccounts(100) |
|
|
|
|
|
|
|
for i := 0; i < b.N; i++ { |
|
|
|
|
|
|
|
benchmarkDerefRootFixedSize(b, acc, add) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
b.Run("1K", func(b *testing.B) { |
|
|
|
|
|
|
|
b.StopTimer() |
|
|
|
|
|
|
|
acc, add := makeAccounts(1000) |
|
|
|
|
|
|
|
for i := 0; i < b.N; i++ { |
|
|
|
|
|
|
|
benchmarkDerefRootFixedSize(b, acc, add) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
b.Run("10K", func(b *testing.B) { |
|
|
|
|
|
|
|
b.StopTimer() |
|
|
|
|
|
|
|
acc, add := makeAccounts(10000) |
|
|
|
|
|
|
|
for i := 0; i < b.N; i++ { |
|
|
|
|
|
|
|
benchmarkDerefRootFixedSize(b, acc, add) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
b.Run("100K", func(b *testing.B) { |
|
|
|
|
|
|
|
b.StopTimer() |
|
|
|
|
|
|
|
acc, add := makeAccounts(100000) |
|
|
|
|
|
|
|
for i := 0; i < b.N; i++ { |
|
|
|
|
|
|
|
benchmarkDerefRootFixedSize(b, acc, add) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func benchmarkDerefRootFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { |
|
|
|
|
|
|
|
b.ReportAllocs() |
|
|
|
|
|
|
|
triedb := NewDatabase(rawdb.NewMemoryDatabase(), nil) |
|
|
|
|
|
|
|
trie := NewEmpty(triedb) |
|
|
|
|
|
|
|
for i := 0; i < len(addresses); i++ { |
|
|
|
|
|
|
|
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
h := trie.Hash() |
|
|
|
|
|
|
|
root, nodes, _ := trie.Commit(false) |
|
|
|
|
|
|
|
triedb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil) |
|
|
|
|
|
|
|
b.StartTimer() |
|
|
|
|
|
|
|
triedb.Dereference(h) |
|
|
|
|
|
|
|
b.StopTimer() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func getString(trie *Trie, k string) []byte { |
|
|
|
func getString(trie *Trie, k string) []byte { |
|
|
|
return trie.MustGet([]byte(k)) |
|
|
|
return trie.MustGet([]byte(k)) |
|
|
|
} |
|
|
|
} |
|
|
|