From 0ca71a5a1a111ce71a109cbe36079bbd64b2c570 Mon Sep 17 00:00:00 2001 From: asyukii Date: Thu, 12 Oct 2023 18:23:43 +0800 Subject: [PATCH] core/state: fix snapshot recovery a --- core/state/snapshot/generate.go | 26 ++++++++++++-- core/state/snapshot/generate_test.go | 45 ++++++++++++++++--------- ethclient/gethclient/gethclient.go | 4 +-- ethclient/gethclient/gethclient_test.go | 8 ++--- trie/trie_test.go | 2 +- 5 files changed, 59 insertions(+), 26 deletions(-) diff --git a/core/state/snapshot/generate.go b/core/state/snapshot/generate.go index 28f2abd289..7b5be0f2e7 100644 --- a/core/state/snapshot/generate.go +++ b/core/state/snapshot/generate.go @@ -194,7 +194,11 @@ func (dl *diskLayer) proveRange(ctx *generatorContext, trieId *trie.ID, prefix [ keys = append(keys, common.CopyBytes(key[len(prefix):])) if valueConvertFn == nil { - vals = append(vals, common.CopyBytes(iter.Value())) + rlpVal, err := convertSnapValToRLPVal(iter.Value()) + if err != nil { + return nil, err + } + vals = append(vals, rlpVal) } else { val, err := valueConvertFn(iter.Value()) if err != nil { @@ -204,10 +208,18 @@ func (dl *diskLayer) proveRange(ctx *generatorContext, trieId *trie.ID, prefix [ // // Here append the original value to ensure that the number of key and // value are aligned. - vals = append(vals, common.CopyBytes(iter.Value())) + rlpVal, err := convertSnapValToRLPVal(val) + if err != nil { + return nil, err + } + vals = append(vals, rlpVal) log.Error("Failed to convert account state data", "err", err) } else { - vals = append(vals, val) + rlpVal, err := convertSnapValToRLPVal(val) + if err != nil { + return nil, err + } + vals = append(vals, rlpVal) } } } @@ -735,6 +747,14 @@ func increaseKey(key []byte) []byte { return nil } +func convertSnapValToRLPVal(val []byte) ([]byte, error) { + snapVal, err := DecodeValueFromRLPBytes(val) + if err != nil { + return nil, err + } + return rlp.EncodeToBytes(snapVal.GetVal()) +} + // abortErr wraps an interruption signal received to represent the // generation is aborted by external processes. type abortErr struct { diff --git a/core/state/snapshot/generate_test.go b/core/state/snapshot/generate_test.go index 07016b675c..dc86636488 100644 --- a/core/state/snapshot/generate_test.go +++ b/core/state/snapshot/generate_test.go @@ -66,7 +66,7 @@ func testGeneration(t *testing.T, scheme string) { helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) root, snap := helper.CommitAndGenerate() - if have, want := root, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"); have != want { + if have, want := root, common.HexToHash("0x1b4b0ae3b50e6ce40184d08fc5857c5b6909e2b1d8017d9e3f69170e323b1f6c"); have != want { t.Fatalf("have %#x want %#x", have, want) } select { @@ -196,7 +196,8 @@ func (t *testHelper) addAccount(acckey string, acc *types.StateAccount) { func (t *testHelper) addSnapStorage(accKey string, keys []string, vals []string) { accHash := hashData([]byte(accKey)) for i, key := range keys { - rawdb.WriteStorageSnapshot(t.diskdb, accHash, hashData([]byte(key)), []byte(vals[i])) + val, _ := rlp.EncodeToBytes(vals[i]) + rawdb.WriteStorageSnapshot(t.diskdb, accHash, hashData([]byte(key)), val) } } @@ -204,7 +205,8 @@ func (t *testHelper) makeStorageTrie(owner common.Hash, keys []string, vals []st id := trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash) stTrie, _ := trie.NewStateTrie(id, t.triedb) for i, k := range keys { - stTrie.MustUpdate([]byte(k), []byte(vals[i])) + rlpVal, _ := rlp.EncodeToBytes(vals[i]) + stTrie.MustUpdate([]byte(k), rlpVal) // [133,118,97,108,45,49] } if !commit { return stTrie.Hash() @@ -512,7 +514,7 @@ func testGenerateCorruptStorageTrie(t *testing.T, scheme string) { // Delete a node in the storage trie. targetPath := []byte{0x4} - targetHash := common.HexToHash("0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371") + targetHash := common.HexToHash("0x1b4b0ae3b50e6ce40184d08fc5857c5b6909e2b1d8017d9e3f69170e323b1f6c") rawdb.DeleteTrieNode(helper.diskdb, hashData([]byte("acc-1")), targetPath, targetHash, scheme) rawdb.DeleteTrieNode(helper.diskdb, hashData([]byte("acc-3")), targetPath, targetHash, scheme) @@ -552,12 +554,16 @@ func testGenerateWithExtraAccounts(t *testing.T, scheme string) { // Identical in the snap key := hashData([]byte("acc-1")) - rawdb.WriteAccountSnapshot(helper.diskdb, key, val) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-1")), []byte("val-1")) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-2")), []byte("val-2")) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-3")), []byte("val-3")) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-4")), []byte("val-4")) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-5")), []byte("val-5")) + val, _ = rlp.EncodeToBytes([]byte("val-1")) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-1")), val) + val, _ = rlp.EncodeToBytes([]byte("val-2")) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-2")), val) + val, _ = rlp.EncodeToBytes([]byte("val-3")) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-3")), val) + val, _ = rlp.EncodeToBytes([]byte("val-4")) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-4")), val) + val, _ = rlp.EncodeToBytes([]byte("val-5")) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-5")), val) } { // Account two exists only in the snapshot @@ -570,9 +576,13 @@ func testGenerateWithExtraAccounts(t *testing.T, scheme string) { val, _ := rlp.EncodeToBytes(acc) key := hashData([]byte("acc-2")) rawdb.WriteAccountSnapshot(helper.diskdb, key, val) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("b-key-1")), []byte("b-val-1")) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("b-key-2")), []byte("b-val-2")) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("b-key-3")), []byte("b-val-3")) + val, _ = rlp.EncodeToBytes([]byte("b-val-1")) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("b-key-1")), val) + val, _ = rlp.EncodeToBytes([]byte("b-val-2")) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("b-key-2")), val) + val, _ = rlp.EncodeToBytes([]byte("b-val-3")) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("b-key-3")), val) + } root := helper.Commit() @@ -629,9 +639,12 @@ func testGenerateWithManyExtraAccounts(t *testing.T, scheme string) { // Identical in the snap key := hashData([]byte("acc-1")) rawdb.WriteAccountSnapshot(helper.diskdb, key, val) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-1")), []byte("val-1")) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-2")), []byte("val-2")) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-3")), []byte("val-3")) + val, _ = rlp.EncodeToBytes([]byte("val-1")) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-1")), val) + val, _ = rlp.EncodeToBytes([]byte("val-2")) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-2")), val) + val, _ = rlp.EncodeToBytes([]byte("val-3")) + rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-3")), val) } { // 100 accounts exist only in snapshot diff --git a/ethclient/gethclient/gethclient.go b/ethclient/gethclient/gethclient.go index fd29676de0..7b9c8587fd 100644 --- a/ethclient/gethclient/gethclient.go +++ b/ethclient/gethclient/gethclient.go @@ -127,7 +127,7 @@ func (ec *Client) GetProof(ctx context.Context, account common.Address, keys []s // GetStorageReviveProof returns the proof for the given keys. Prefix keys can be specified to obtain partial proof for a given key. // Both keys and prefix keys should have the same length. If user wish to obtain full proof for a given key, the corresponding prefix key should be empty string. -func (ec *Client) GetStorageReviveProof(ctx context.Context, account common.Address, keys []string, prefixKeys []string, hash common.Hash) (*types.ReviveResult, error) { +func (ec *Client) GetStorageReviveProof(ctx context.Context, stateRoot common.Hash, account common.Address, root common.Hash, keys []string, prefixKeys []string) (*types.ReviveResult, error) { type reviveResult struct { StorageProof []types.ReviveStorageProof `json:"storageProof"` BlockNum hexutil.Uint64 `json:"blockNum"` @@ -136,7 +136,7 @@ func (ec *Client) GetStorageReviveProof(ctx context.Context, account common.Addr var err error var res reviveResult - err = ec.c.CallContext(ctx, &res, "eth_getStorageReviveProof", account, keys, prefixKeys, hash) + err = ec.c.CallContext(ctx, &res, "eth_getStorageReviveProof", stateRoot, account, root, keys, prefixKeys) return &types.ReviveResult{ StorageProof: res.StorageProof, diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go index 3e24fcfa37..29b4b95f5f 100644 --- a/ethclient/gethclient/gethclient_test.go +++ b/ethclient/gethclient/gethclient_test.go @@ -93,7 +93,7 @@ func generateTestChain() (*core.Genesis, []*types.Block) { } func TestGethClient(t *testing.T) { - backend, _ := newTestBackend(t) + backend, blocks := newTestBackend(t) client := backend.Attach() defer backend.Close() defer client.Close() @@ -107,7 +107,7 @@ func TestGethClient(t *testing.T) { func(t *testing.T) { testGetProof(t, client) }, }, { "TestGetStorageReviveProof", - func(t *testing.T) { testGetStorageReviveProof(t, client) }, + func(t *testing.T) { testGetStorageReviveProof(t, client, blocks[0]) }, }, { "TestGetProofCanonicalizeKeys", func(t *testing.T) { testGetProofCanonicalizeKeys(t, client) }, @@ -239,9 +239,9 @@ func testGetProof(t *testing.T, client *rpc.Client) { } } -func testGetStorageReviveProof(t *testing.T, client *rpc.Client) { +func testGetStorageReviveProof(t *testing.T, client *rpc.Client, block *types.Block) { ec := New(client) - result, err := ec.GetStorageReviveProof(context.Background(), testAddr, []string{testSlot.String()}, []string{""}, common.Hash{}) + result, err := ec.GetStorageReviveProof(context.Background(), block.Header().Root, testAddr, block.Header().Root, []string{testSlot.String()}, []string{""}) proofs := result.StorageProof if err != nil { diff --git a/trie/trie_test.go b/trie/trie_test.go index dfff72b857..aa704f8166 100644 --- a/trie/trie_test.go +++ b/trie/trie_test.go @@ -1118,7 +1118,7 @@ func TestReviveBadProof(t *testing.T) { // Verify value does exists after revive val, err := trieA.Get([]byte("abcd")) - assert.NoError(t, err, "Get failed, key %x, val %x", []byte("abcd"), val) + assert.Error(t, err, "Get failed, key %x, val %x", []byte("abcd"), val) assert.NotEqual(t, []byte("A"), val) }