|
|
|
@ -27,8 +27,8 @@ import ( |
|
|
|
|
"github.com/ethereum/go-ethereum/core/rawdb" |
|
|
|
|
"github.com/ethereum/go-ethereum/core/types" |
|
|
|
|
"github.com/ethereum/go-ethereum/crypto" |
|
|
|
|
"github.com/ethereum/go-ethereum/internal/testrand" |
|
|
|
|
"github.com/ethereum/go-ethereum/rlp" |
|
|
|
|
"github.com/ethereum/go-ethereum/trie/testutil" |
|
|
|
|
"github.com/ethereum/go-ethereum/trie/trienode" |
|
|
|
|
"github.com/ethereum/go-ethereum/trie/triestate" |
|
|
|
|
"github.com/holiman/uint256" |
|
|
|
@ -46,7 +46,10 @@ func updateTrie(addrHash common.Hash, root common.Hash, dirties, cleans map[comm |
|
|
|
|
h.Update(key.Bytes(), val) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
root, nodes, _ := h.Commit(false) |
|
|
|
|
root, nodes, err := h.Commit(false) |
|
|
|
|
if err != nil { |
|
|
|
|
panic(fmt.Errorf("failed to commit hasher, err: %w", err)) |
|
|
|
|
} |
|
|
|
|
return root, nodes |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -54,7 +57,7 @@ func generateAccount(storageRoot common.Hash) types.StateAccount { |
|
|
|
|
return types.StateAccount{ |
|
|
|
|
Nonce: uint64(rand.Intn(100)), |
|
|
|
|
Balance: uint256.NewInt(rand.Uint64()), |
|
|
|
|
CodeHash: testutil.RandBytes(32), |
|
|
|
|
CodeHash: testrand.Bytes(32), |
|
|
|
|
Root: storageRoot, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -101,8 +104,8 @@ func newTester(t *testing.T, historyLimit uint64) *tester { |
|
|
|
|
disk, _ = rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false) |
|
|
|
|
db = New(disk, &Config{ |
|
|
|
|
StateHistory: historyLimit, |
|
|
|
|
CleanCacheSize: 256 * 1024, |
|
|
|
|
DirtyCacheSize: 256 * 1024, |
|
|
|
|
CleanCacheSize: 16 * 1024, |
|
|
|
|
DirtyCacheSize: 16 * 1024, |
|
|
|
|
}) |
|
|
|
|
obj = &tester{ |
|
|
|
|
db: db, |
|
|
|
@ -113,7 +116,7 @@ func newTester(t *testing.T, historyLimit uint64) *tester { |
|
|
|
|
snapStorages: make(map[common.Hash]map[common.Hash]map[common.Hash][]byte), |
|
|
|
|
} |
|
|
|
|
) |
|
|
|
|
for i := 0; i < 2*128; i++ { |
|
|
|
|
for i := 0; i < 8; i++ { |
|
|
|
|
var parent = types.EmptyRootHash |
|
|
|
|
if len(obj.roots) != 0 { |
|
|
|
|
parent = obj.roots[len(obj.roots)-1] |
|
|
|
@ -146,8 +149,8 @@ func (t *tester) generateStorage(ctx *genctx, addr common.Address) common.Hash { |
|
|
|
|
origin = make(map[common.Hash][]byte) |
|
|
|
|
) |
|
|
|
|
for i := 0; i < 10; i++ { |
|
|
|
|
v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(testutil.RandBytes(32))) |
|
|
|
|
hash := testutil.RandomHash() |
|
|
|
|
v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(testrand.Bytes(32))) |
|
|
|
|
hash := testrand.Hash() |
|
|
|
|
|
|
|
|
|
storage[hash] = v |
|
|
|
|
origin[hash] = nil |
|
|
|
@ -175,8 +178,8 @@ func (t *tester) mutateStorage(ctx *genctx, addr common.Address, root common.Has |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
for i := 0; i < 3; i++ { |
|
|
|
|
v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(testutil.RandBytes(32))) |
|
|
|
|
hash := testutil.RandomHash() |
|
|
|
|
v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(testrand.Bytes(32))) |
|
|
|
|
hash := testrand.Hash() |
|
|
|
|
|
|
|
|
|
storage[hash] = v |
|
|
|
|
origin[hash] = nil |
|
|
|
@ -218,7 +221,7 @@ func (t *tester) generate(parent common.Hash) (common.Hash, *trienode.MergedNode |
|
|
|
|
switch rand.Intn(opLen) { |
|
|
|
|
case createAccountOp: |
|
|
|
|
// account creation
|
|
|
|
|
addr := testutil.RandomAddress() |
|
|
|
|
addr := testrand.Address() |
|
|
|
|
addrHash := crypto.Keccak256Hash(addr.Bytes()) |
|
|
|
|
if _, ok := t.accounts[addrHash]; ok { |
|
|
|
|
continue |
|
|
|
@ -320,14 +323,16 @@ func (t *tester) verifyState(root common.Hash) error { |
|
|
|
|
return errors.New("root node is not available") |
|
|
|
|
} |
|
|
|
|
for addrHash, account := range t.snapAccounts[root] { |
|
|
|
|
blob, err := reader.Node(common.Hash{}, addrHash.Bytes(), crypto.Keccak256Hash(account)) |
|
|
|
|
path := crypto.Keccak256(addrHash.Bytes()) |
|
|
|
|
blob, err := reader.Node(common.Hash{}, path, crypto.Keccak256Hash(account)) |
|
|
|
|
if err != nil || !bytes.Equal(blob, account) { |
|
|
|
|
return fmt.Errorf("account is mismatched: %w", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
for addrHash, slots := range t.snapStorages[root] { |
|
|
|
|
for hash, slot := range slots { |
|
|
|
|
blob, err := reader.Node(addrHash, hash.Bytes(), crypto.Keccak256Hash(slot)) |
|
|
|
|
path := crypto.Keccak256(hash.Bytes()) |
|
|
|
|
blob, err := reader.Node(addrHash, path, crypto.Keccak256Hash(slot)) |
|
|
|
|
if err != nil || !bytes.Equal(blob, slot) { |
|
|
|
|
return fmt.Errorf("slot is mismatched: %w", err) |
|
|
|
|
} |
|
|
|
@ -379,6 +384,12 @@ func (t *tester) bottomIndex() int { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestDatabaseRollback(t *testing.T) { |
|
|
|
|
// Redefine the diff layer depth allowance for faster testing.
|
|
|
|
|
maxDiffLayers = 4 |
|
|
|
|
defer func() { |
|
|
|
|
maxDiffLayers = 128 |
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
// Verify state histories
|
|
|
|
|
tester := newTester(t, 0) |
|
|
|
|
defer tester.release() |
|
|
|
@ -409,6 +420,12 @@ func TestDatabaseRollback(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestDatabaseRecoverable(t *testing.T) { |
|
|
|
|
// Redefine the diff layer depth allowance for faster testing.
|
|
|
|
|
maxDiffLayers = 4 |
|
|
|
|
defer func() { |
|
|
|
|
maxDiffLayers = 128 |
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
|
tester = newTester(t, 0) |
|
|
|
|
index = tester.bottomIndex() |
|
|
|
@ -448,6 +465,12 @@ func TestDatabaseRecoverable(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestDisable(t *testing.T) { |
|
|
|
|
// Redefine the diff layer depth allowance for faster testing.
|
|
|
|
|
maxDiffLayers = 4 |
|
|
|
|
defer func() { |
|
|
|
|
maxDiffLayers = 128 |
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
tester := newTester(t, 0) |
|
|
|
|
defer tester.release() |
|
|
|
|
|
|
|
|
@ -484,6 +507,12 @@ func TestDisable(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestCommit(t *testing.T) { |
|
|
|
|
// Redefine the diff layer depth allowance for faster testing.
|
|
|
|
|
maxDiffLayers = 4 |
|
|
|
|
defer func() { |
|
|
|
|
maxDiffLayers = 128 |
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
tester := newTester(t, 0) |
|
|
|
|
defer tester.release() |
|
|
|
|
|
|
|
|
@ -508,6 +537,12 @@ func TestCommit(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestJournal(t *testing.T) { |
|
|
|
|
// Redefine the diff layer depth allowance for faster testing.
|
|
|
|
|
maxDiffLayers = 4 |
|
|
|
|
defer func() { |
|
|
|
|
maxDiffLayers = 128 |
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
tester := newTester(t, 0) |
|
|
|
|
defer tester.release() |
|
|
|
|
|
|
|
|
@ -532,6 +567,12 @@ func TestJournal(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestCorruptedJournal(t *testing.T) { |
|
|
|
|
// Redefine the diff layer depth allowance for faster testing.
|
|
|
|
|
maxDiffLayers = 4 |
|
|
|
|
defer func() { |
|
|
|
|
maxDiffLayers = 128 |
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
tester := newTester(t, 0) |
|
|
|
|
defer tester.release() |
|
|
|
|
|
|
|
|
@ -574,6 +615,12 @@ func TestCorruptedJournal(t *testing.T) { |
|
|
|
|
// truncating the tail histories. This ensures that the ID of the persistent state
|
|
|
|
|
// always falls within the range of [oldest-history-id, latest-history-id].
|
|
|
|
|
func TestTailTruncateHistory(t *testing.T) { |
|
|
|
|
// Redefine the diff layer depth allowance for faster testing.
|
|
|
|
|
maxDiffLayers = 4 |
|
|
|
|
defer func() { |
|
|
|
|
maxDiffLayers = 128 |
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
tester := newTester(t, 10) |
|
|
|
|
defer tester.release() |
|
|
|
|
|
|
|
|
|