core, eth, les, trie: add a prefix to contract code (#21080)

This commit is contained in:
gary rong
2020-08-21 20:10:40 +08:00
committed by GitHub
parent b68929caee
commit 87c0ba9213
42 changed files with 580 additions and 287 deletions

View File

@ -133,13 +133,17 @@ func TestEmptyStateSync(t *testing.T) {
// Tests that given a root hash, a state can sync iteratively on a single thread,
// requesting retrieval tasks and returning all of them in one go.
func TestIterativeStateSyncIndividual(t *testing.T) { testIterativeStateSync(t, 1) }
func TestIterativeStateSyncBatched(t *testing.T) { testIterativeStateSync(t, 100) }
func TestIterativeStateSyncIndividual(t *testing.T) { testIterativeStateSync(t, 1, false) }
func TestIterativeStateSyncBatched(t *testing.T) { testIterativeStateSync(t, 100, false) }
func TestIterativeStateSyncIndividualFromDisk(t *testing.T) { testIterativeStateSync(t, 1, true) }
func TestIterativeStateSyncBatchedFromDisk(t *testing.T) { testIterativeStateSync(t, 100, true) }
func testIterativeStateSync(t *testing.T, count int) {
func testIterativeStateSync(t *testing.T, count int, commit bool) {
// Create a random state to copy
srcDb, srcRoot, srcAccounts := makeTestState()
if commit {
srcDb.TrieDB().Commit(srcRoot, false, nil)
}
// Create a destination state and sync with the scheduler
dstDb := rawdb.NewMemoryDatabase()
sched := NewStateSync(srcRoot, dstDb, trie.NewSyncBloom(1, dstDb))
@ -149,13 +153,18 @@ func testIterativeStateSync(t *testing.T, count int) {
results := make([]trie.SyncResult, len(queue))
for i, hash := range queue {
data, err := srcDb.TrieDB().Node(hash)
if err != nil {
data, err = srcDb.ContractCode(common.Hash{}, hash)
}
if err != nil {
t.Fatalf("failed to retrieve node data for %x", hash)
}
results[i] = trie.SyncResult{Hash: hash, Data: data}
}
if _, index, err := sched.Process(results); err != nil {
t.Fatalf("failed to process result #%d: %v", index, err)
for _, result := range results {
if err := sched.Process(result); err != nil {
t.Fatalf("failed to process result %v", err)
}
}
batch := dstDb.NewBatch()
if err := sched.Commit(batch); err != nil {
@ -184,13 +193,18 @@ func TestIterativeDelayedStateSync(t *testing.T) {
results := make([]trie.SyncResult, len(queue)/2+1)
for i, hash := range queue[:len(results)] {
data, err := srcDb.TrieDB().Node(hash)
if err != nil {
data, err = srcDb.ContractCode(common.Hash{}, hash)
}
if err != nil {
t.Fatalf("failed to retrieve node data for %x", hash)
}
results[i] = trie.SyncResult{Hash: hash, Data: data}
}
if _, index, err := sched.Process(results); err != nil {
t.Fatalf("failed to process result #%d: %v", index, err)
for _, result := range results {
if err := sched.Process(result); err != nil {
t.Fatalf("failed to process result %v", err)
}
}
batch := dstDb.NewBatch()
if err := sched.Commit(batch); err != nil {
@ -226,14 +240,19 @@ func testIterativeRandomStateSync(t *testing.T, count int) {
results := make([]trie.SyncResult, 0, len(queue))
for hash := range queue {
data, err := srcDb.TrieDB().Node(hash)
if err != nil {
data, err = srcDb.ContractCode(common.Hash{}, hash)
}
if err != nil {
t.Fatalf("failed to retrieve node data for %x", hash)
}
results = append(results, trie.SyncResult{Hash: hash, Data: data})
}
// Feed the retrieved results back and queue new tasks
if _, index, err := sched.Process(results); err != nil {
t.Fatalf("failed to process result #%d: %v", index, err)
for _, result := range results {
if err := sched.Process(result); err != nil {
t.Fatalf("failed to process result %v", err)
}
}
batch := dstDb.NewBatch()
if err := sched.Commit(batch); err != nil {
@ -270,6 +289,9 @@ func TestIterativeRandomDelayedStateSync(t *testing.T) {
delete(queue, hash)
data, err := srcDb.TrieDB().Node(hash)
if err != nil {
data, err = srcDb.ContractCode(common.Hash{}, hash)
}
if err != nil {
t.Fatalf("failed to retrieve node data for %x", hash)
}
@ -280,8 +302,10 @@ func TestIterativeRandomDelayedStateSync(t *testing.T) {
}
}
// Feed the retrieved results back and queue new tasks
if _, index, err := sched.Process(results); err != nil {
t.Fatalf("failed to process result #%d: %v", index, err)
for _, result := range results {
if err := sched.Process(result); err != nil {
t.Fatalf("failed to process result %v", err)
}
}
batch := dstDb.NewBatch()
if err := sched.Commit(batch); err != nil {
@ -302,6 +326,15 @@ func TestIncompleteStateSync(t *testing.T) {
// Create a random state to copy
srcDb, srcRoot, srcAccounts := makeTestState()
// isCode reports whether the hash is contract code hash.
isCode := func(hash common.Hash) bool {
for _, acc := range srcAccounts {
if hash == crypto.Keccak256Hash(acc.code) {
return true
}
}
return false
}
checkTrieConsistency(srcDb.TrieDB().DiskDB().(ethdb.Database), srcRoot)
// Create a destination state and sync with the scheduler
@ -315,14 +348,19 @@ func TestIncompleteStateSync(t *testing.T) {
results := make([]trie.SyncResult, len(queue))
for i, hash := range queue {
data, err := srcDb.TrieDB().Node(hash)
if err != nil {
data, err = srcDb.ContractCode(common.Hash{}, hash)
}
if err != nil {
t.Fatalf("failed to retrieve node data for %x", hash)
}
results[i] = trie.SyncResult{Hash: hash, Data: data}
}
// Process each of the state nodes
if _, index, err := sched.Process(results); err != nil {
t.Fatalf("failed to process result #%d: %v", index, err)
for _, result := range results {
if err := sched.Process(result); err != nil {
t.Fatalf("failed to process result %v", err)
}
}
batch := dstDb.NewBatch()
if err := sched.Commit(batch); err != nil {
@ -333,12 +371,9 @@ func TestIncompleteStateSync(t *testing.T) {
added = append(added, result.Hash)
}
// Check that all known sub-tries added so far are complete or missing entirely.
checkSubtries:
for _, hash := range added {
for _, acc := range srcAccounts {
if hash == crypto.Keccak256Hash(acc.code) {
continue checkSubtries // skip trie check of code nodes.
}
if isCode(hash) {
continue
}
// Can't use checkStateConsistency here because subtrie keys may have odd
// length and crash in LeafKey.
@ -351,13 +386,25 @@ func TestIncompleteStateSync(t *testing.T) {
}
// Sanity check that removing any node from the database is detected
for _, node := range added[1:] {
key := node.Bytes()
value, _ := dstDb.Get(key)
dstDb.Delete(key)
var (
key = node.Bytes()
code = isCode(node)
val []byte
)
if code {
val = rawdb.ReadCode(dstDb, node)
rawdb.DeleteCode(dstDb, node)
} else {
val = rawdb.ReadTrieNode(dstDb, node)
rawdb.DeleteTrieNode(dstDb, node)
}
if err := checkStateConsistency(dstDb, added[0]); err == nil {
t.Fatalf("trie inconsistency not caught, missing: %x", key)
}
dstDb.Put(key, value)
if code {
rawdb.WriteCode(dstDb, node, val)
} else {
rawdb.WriteTrieNode(dstDb, node, val)
}
}
}