diff --git a/eth/stagedsync/stage_interhashes_test.go b/eth/stagedsync/stage_interhashes_test.go index 367fde478ca167e276913bc8623582c815e3e340..ee2f4b375afc5c0fe5ee9aa7df1366586f33af1d 100644 --- a/eth/stagedsync/stage_interhashes_test.go +++ b/eth/stagedsync/stage_interhashes_test.go @@ -57,8 +57,8 @@ func TestAccountAndStorageTrie(t *testing.T) { assert.Nil(t, tx.Put(kv.HashedStorage, dbutils.GenerateCompositeStorageKey(hash3, incarnation, loc3), val3)) assert.Nil(t, tx.Put(kv.HashedStorage, dbutils.GenerateCompositeStorageKey(hash3, incarnation, loc4), val4)) - hash4 := common.HexToHash("0xB100000000000000000000000000000000000000000000000000000000000000") - assert.Nil(t, addTestAccount(tx, hash4, 4*params.Ether, 0)) + hash4a := common.HexToHash("0xB1A0000000000000000000000000000000000000000000000000000000000000") + assert.Nil(t, addTestAccount(tx, hash4a, 4*params.Ether, 0)) hash5 := common.HexToHash("0xB310000000000000000000000000000000000000000000000000000000000000") assert.Nil(t, addTestAccount(tx, hash5, 8*params.Ether, 0)) @@ -66,36 +66,49 @@ func TestAccountAndStorageTrie(t *testing.T) { hash6 := common.HexToHash("0xB340000000000000000000000000000000000000000000000000000000000000") assert.Nil(t, addTestAccount(tx, hash6, 1*params.Ether, 0)) + // ---------------------------------------------------------------- + // Populate account & storage trie DB tables + // ---------------------------------------------------------------- + blockReader := snapshotsync.NewBlockReader() - _, err := RegenerateIntermediateHashes("IH", tx, StageTrieCfg(nil, false, true, t.TempDir(), blockReader), common.Hash{} /* expectedRootHash */, nil /* quit */) + cfg := StageTrieCfg(nil, false, true, t.TempDir(), blockReader) + _, err := RegenerateIntermediateHashes("IH", tx, cfg, common.Hash{} /* expectedRootHash */, nil /* quit */) assert.Nil(t, err) - accountTrie := make(map[string][]byte) + // ---------------------------------------------------------------- + // Check account trie + // ---------------------------------------------------------------- + + accountTrieA := make(map[string][]byte) err = tx.ForEach(kv.TrieOfAccounts, nil, func(k, v []byte) error { - accountTrie[string(k)] = v + accountTrieA[string(k)] = common.CopyBytes(v) return nil }) assert.Nil(t, err) - assert.Equal(t, 2, len(accountTrie)) + assert.Equal(t, 2, len(accountTrieA)) - hasState1, hasTree1, hasHash1, hashes1, rootHash1 := trie.UnmarshalTrieNode(accountTrie[string(common.FromHex("0B"))]) - assert.Equal(t, uint16(0b1011), hasState1) - assert.Equal(t, uint16(0b0001), hasTree1) - assert.Equal(t, uint16(0b1001), hasHash1) - assert.Equal(t, 2*length.Hash, len(hashes1)) - assert.Equal(t, 0, len(rootHash1)) + hasState1a, hasTree1a, hasHash1a, hashes1a, rootHash1a := trie.UnmarshalTrieNode(accountTrieA[string(common.FromHex("0B"))]) + assert.Equal(t, uint16(0b1011), hasState1a) + assert.Equal(t, uint16(0b0001), hasTree1a) + assert.Equal(t, uint16(0b1001), hasHash1a) + assert.Equal(t, 2*length.Hash, len(hashes1a)) + assert.Equal(t, 0, len(rootHash1a)) - hasState2, hasTree2, hasHash2, hashes2, rootHash2 := trie.UnmarshalTrieNode(accountTrie[string(common.FromHex("0B00"))]) - assert.Equal(t, uint16(0b10001), hasState2) - assert.Equal(t, uint16(0b00000), hasTree2) - assert.Equal(t, uint16(0b10000), hasHash2) - assert.Equal(t, 1*length.Hash, len(hashes2)) - assert.Equal(t, 0, len(rootHash2)) + hasState2a, hasTree2a, hasHash2a, hashes2a, rootHash2a := trie.UnmarshalTrieNode(accountTrieA[string(common.FromHex("0B00"))]) + assert.Equal(t, uint16(0b10001), hasState2a) + assert.Equal(t, uint16(0b00000), hasTree2a) + assert.Equal(t, uint16(0b10000), hasHash2a) + assert.Equal(t, 1*length.Hash, len(hashes2a)) + assert.Equal(t, 0, len(rootHash2a)) + + // ---------------------------------------------------------------- + // Check storage trie + // ---------------------------------------------------------------- storageTrie := make(map[string][]byte) err = tx.ForEach(kv.TrieOfStorage, nil, func(k, v []byte) error { - storageTrie[string(k)] = v + storageTrie[string(k)] = common.CopyBytes(v) return nil }) assert.Nil(t, err) @@ -112,6 +125,43 @@ func TestAccountAndStorageTrie(t *testing.T) { assert.Equal(t, uint16(0b0010), hasHash3) assert.Equal(t, 1*length.Hash, len(hashes3)) assert.Equal(t, length.Hash, len(rootHash3)) + + // ---------------------------------------------------------------- + // Incremental trie + // ---------------------------------------------------------------- + + newAddress := common.HexToAddress("0x4f61f2d5ebd991b85aa1677db97307caf5215c91") + hash4b, err := common.HashData(newAddress[:]) + assert.Nil(t, err) + assert.Equal(t, hash4a[0], hash4b[0]) + + assert.Nil(t, addTestAccount(tx, hash4b, 5*params.Ether, 0)) + + err = tx.Put(kv.AccountChangeSet, dbutils.EncodeBlockNumber(1), newAddress[:]) + assert.Nil(t, err) + + var s StageState + s.BlockNumber = 0 + _, err = incrementIntermediateHashes("IH", &s, tx, 1 /* to */, cfg, common.Hash{} /* expectedRootHash */, nil /* quit */) + assert.Nil(t, err) + + accountTrieB := make(map[string][]byte) + err = tx.ForEach(kv.TrieOfAccounts, nil, func(k, v []byte) error { + accountTrieB[string(k)] = common.CopyBytes(v) + return nil + }) + assert.Nil(t, err) + + assert.Equal(t, 2, len(accountTrieB)) + + hasState1b, hasTree1b, hasHash1b, hashes1b, rootHash1b := trie.UnmarshalTrieNode(accountTrieB[string(common.FromHex("0B"))]) + assert.Equal(t, hasState1a, hasState1b) + assert.Equal(t, hasTree1a, hasTree1b) + assert.Equal(t, uint16(0b1011), hasHash1b) + assert.Equal(t, 3*length.Hash, len(hashes1b)) + assert.Equal(t, rootHash1a, rootHash1b) + + assert.Equal(t, accountTrieA[string(common.FromHex("0B00"))], accountTrieB[string(common.FromHex("0B00"))]) } func TestAccountTrieAroundExtensionNode(t *testing.T) { @@ -167,3 +217,87 @@ func TestAccountTrieAroundExtensionNode(t *testing.T) { assert.Equal(t, length.Hash, len(hashes2)) assert.Equal(t, 0, len(rootHash2)) } + +func TestStorageDeletion(t *testing.T) { + _, tx := memdb.NewTestTx(t) + + address := common.HexToAddress("0x1000000000000000000000000000000000000000") + hashedAddress, err := common.HashData(address[:]) + assert.Nil(t, err) + incarnation := uint64(1) + assert.Nil(t, addTestAccount(tx, hashedAddress, params.Ether, incarnation)) + + plainLocation1 := common.HexToHash("0x1000000000000000000000000000000000000000000000000000000000000000") + hashedLocation1, err := common.HashData(plainLocation1[:]) + assert.Nil(t, err) + + plainLocation2 := common.HexToHash("0x1A00000000000000000000000000000000000000000000000000000000000000") + hashedLocation2, err := common.HashData(plainLocation2[:]) + assert.Nil(t, err) + + plainLocation3 := common.HexToHash("0x1E00000000000000000000000000000000000000000000000000000000000000") + hashedLocation3, err := common.HashData(plainLocation3[:]) + assert.Nil(t, err) + + value1 := common.FromHex("0xABCD") + assert.Nil(t, tx.Put(kv.HashedStorage, dbutils.GenerateCompositeStorageKey(hashedAddress, incarnation, hashedLocation1), value1)) + + value2 := common.FromHex("0x4321") + assert.Nil(t, tx.Put(kv.HashedStorage, dbutils.GenerateCompositeStorageKey(hashedAddress, incarnation, hashedLocation2), value2)) + + value3 := common.FromHex("0x4444") + assert.Nil(t, tx.Put(kv.HashedStorage, dbutils.GenerateCompositeStorageKey(hashedAddress, incarnation, hashedLocation3), value3)) + + // ---------------------------------------------------------------- + // Populate account & storage trie DB tables + // ---------------------------------------------------------------- + + blockReader := snapshotsync.NewBlockReader() + cfg := StageTrieCfg(nil, false, true, t.TempDir(), blockReader) + _, err = RegenerateIntermediateHashes("IH", tx, cfg, common.Hash{} /* expectedRootHash */, nil /* quit */) + assert.Nil(t, err) + + // ---------------------------------------------------------------- + // Check storage trie + // ---------------------------------------------------------------- + + storageTrieA := make(map[string][]byte) + err = tx.ForEach(kv.TrieOfStorage, nil, func(k, v []byte) error { + storageTrieA[string(k)] = common.CopyBytes(v) + return nil + }) + assert.Nil(t, err) + + assert.Equal(t, 1, len(storageTrieA)) + + // ---------------------------------------------------------------- + // Delete storage and increment the trie + // ---------------------------------------------------------------- + + assert.Nil(t, tx.Delete(kv.HashedStorage, dbutils.GenerateCompositeStorageKey(hashedAddress, incarnation, hashedLocation1), value1)) + assert.Nil(t, tx.Delete(kv.HashedStorage, dbutils.GenerateCompositeStorageKey(hashedAddress, incarnation, hashedLocation2), value2)) + assert.Nil(t, tx.Delete(kv.HashedStorage, dbutils.GenerateCompositeStorageKey(hashedAddress, incarnation, hashedLocation3), value3)) + + err = tx.Put(kv.StorageChangeSet, append(dbutils.EncodeBlockNumber(1), dbutils.PlainGenerateStoragePrefix(address[:], incarnation)...), plainLocation1[:]) + assert.Nil(t, err) + + err = tx.Put(kv.StorageChangeSet, append(dbutils.EncodeBlockNumber(1), dbutils.PlainGenerateStoragePrefix(address[:], incarnation)...), plainLocation2[:]) + assert.Nil(t, err) + + err = tx.Put(kv.StorageChangeSet, append(dbutils.EncodeBlockNumber(1), dbutils.PlainGenerateStoragePrefix(address[:], incarnation)...), plainLocation3[:]) + assert.Nil(t, err) + + var s StageState + s.BlockNumber = 0 + _, err = incrementIntermediateHashes("IH", &s, tx, 1 /* to */, cfg, common.Hash{} /* expectedRootHash */, nil /* quit */) + assert.Nil(t, err) + + storageTrieB := make(map[string][]byte) + err = tx.ForEach(kv.TrieOfStorage, nil, func(k, v []byte) error { + storageTrieB[string(k)] = common.CopyBytes(v) + return nil + }) + assert.Nil(t, err) + + assert.Equal(t, 0, len(storageTrieB)) +}