Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit 6869330

Browse files
Decode storage value RLP after fetching from statediffs
1 parent 2931edc commit 6869330

File tree

5 files changed

+138
-38
lines changed

5 files changed

+138
-38
lines changed

libraries/shared/fetcher/geth_rpc_storage_fetcher.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,12 @@ func (fetcher GethRpcStorageFetcher) FetchStorageDiffs(out chan<- utils.StorageD
6060
logrus.Trace(fmt.Sprintf("iterating through %d Storage values on account", len(account.Storage)))
6161
for _, storage := range account.Storage {
6262
logrus.Trace("adding storage diff to out channel")
63-
out <- utils.FromGethStateDiff(account, stateDiff, storage)
63+
diff, formatErr := utils.FromGethStateDiff(account, stateDiff, storage)
64+
if formatErr != nil {
65+
errs <- formatErr
66+
}
67+
68+
out <- diff
6469
}
6570
}
6671
}

libraries/shared/fetcher/geth_rpc_storage_fetcher_test.go

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package fetcher_test
1616

1717
import (
1818
"github.com/ethereum/go-ethereum/common"
19+
"github.com/ethereum/go-ethereum/rlp"
1920
"github.com/ethereum/go-ethereum/rpc"
2021
"github.com/ethereum/go-ethereum/statediff"
2122
. "github.com/onsi/ginkgo"
@@ -93,40 +94,87 @@ var _ = Describe("Geth RPC Storage Fetcher", func() {
9394
close(done)
9495
})
9596

97+
It("adds errors to error channel if decoding the state diff RLP fails", func(done Done) {
98+
badStatediffPayload := statediff.Payload{}
99+
streamer.SetPayloads([]statediff.Payload{badStatediffPayload})
100+
101+
go statediffFetcher.FetchStorageDiffs(storagediffChan, errorChan)
102+
103+
Expect(<-errorChan).To(MatchError("EOF"))
104+
105+
close(done)
106+
})
107+
96108
It("adds parsed statediff payloads to the rows channel", func(done Done) {
97109
streamer.SetPayloads([]statediff.Payload{test_data.MockStatediffPayload})
98110

99111
go statediffFetcher.FetchStorageDiffs(storagediffChan, errorChan)
100112

101113
height := test_data.BlockNumber
102114
intHeight := int(height.Int64())
103-
expectedStorageDiff := utils.StorageDiff{
115+
createdExpectedStorageDiff := utils.StorageDiff{
104116
KeccakOfContractAddress: common.BytesToHash(test_data.ContractLeafKey[:]),
105117
BlockHash: common.HexToHash("0xfa40fbe2d98d98b3363a778d52f2bcd29d6790b9b3f3cab2b167fd12d3550f73"),
106118
BlockHeight: intHeight,
107119
StorageKey: common.BytesToHash(test_data.StorageKey),
108-
StorageValue: common.BytesToHash(test_data.StorageValue),
120+
StorageValue: common.BytesToHash(test_data.SmallStorageValue),
109121
}
110-
anotherExpectedStorageDiff := utils.StorageDiff{
122+
updatedExpectedStorageDiff := utils.StorageDiff{
111123
KeccakOfContractAddress: common.BytesToHash(test_data.AnotherContractLeafKey[:]),
112124
BlockHash: common.HexToHash("0xfa40fbe2d98d98b3363a778d52f2bcd29d6790b9b3f3cab2b167fd12d3550f73"),
113125
BlockHeight: intHeight,
114126
StorageKey: common.BytesToHash(test_data.StorageKey),
115-
StorageValue: common.BytesToHash(test_data.StorageValue),
127+
StorageValue: common.BytesToHash(test_data.LargeStorageValue),
128+
}
129+
deletedExpectedStorageDiff := utils.StorageDiff{
130+
KeccakOfContractAddress: common.BytesToHash(test_data.AnotherContractLeafKey[:]),
131+
BlockHash: common.HexToHash("0xfa40fbe2d98d98b3363a778d52f2bcd29d6790b9b3f3cab2b167fd12d3550f73"),
132+
BlockHeight: intHeight,
133+
StorageKey: common.BytesToHash(test_data.StorageKey),
134+
StorageValue: common.BytesToHash(test_data.SmallStorageValue),
116135
}
117-
Expect(<-storagediffChan).To(Equal(expectedStorageDiff))
118-
Expect(<-storagediffChan).To(Equal(anotherExpectedStorageDiff))
136+
137+
createdStateDiff := <-storagediffChan
138+
updatedStateDiff := <-storagediffChan
139+
deletedStateDiff := <-storagediffChan
140+
141+
Expect(createdStateDiff).To(Equal(createdExpectedStorageDiff))
142+
Expect(updatedStateDiff).To(Equal(updatedExpectedStorageDiff))
143+
Expect(deletedStateDiff).To(Equal(deletedExpectedStorageDiff))
119144

120145
close(done)
121146
})
122147

123-
It("adds errors to error channel if parsing the diff fails", func(done Done) {
124-
badStatediffPayload := statediff.Payload{}
148+
It("adds errors to error channel if formatting the diff as a StateDiff object fails", func(done Done) {
149+
badStorageDiffs := []statediff.StorageDiff{{
150+
Key: test_data.StorageKey,
151+
Value: []byte{1, 2, 3},
152+
// this storage value will fail to be decoded as an RLP with the following error message:
153+
// "input contains more than one value"
154+
Path: test_data.StoragePath,
155+
Proof: [][]byte{},
156+
}}
157+
158+
accountDiffs := test_data.CreatedAccountDiffs
159+
accountDiffs[0].Storage = badStorageDiffs
160+
161+
stateDiff := statediff.StateDiff{
162+
BlockNumber: test_data.BlockNumber,
163+
BlockHash: common.HexToHash(test_data.BlockHash),
164+
CreatedAccounts: accountDiffs,
165+
}
166+
167+
stateDiffRlp, err := rlp.EncodeToBytes(stateDiff)
168+
Expect(err).NotTo(HaveOccurred())
169+
170+
badStatediffPayload := statediff.Payload{
171+
StateDiffRlp: stateDiffRlp,
172+
}
125173
streamer.SetPayloads([]statediff.Payload{badStatediffPayload})
126174

127175
go statediffFetcher.FetchStorageDiffs(storagediffChan, errorChan)
128176

129-
Expect(<-errorChan).To(MatchError("EOF"))
177+
Expect(<-errorChan).To(MatchError("rlp: input contains more than one value"))
130178

131179
close(done)
132180
})

libraries/shared/storage/utils/diff.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package utils
1919
import (
2020
"github.com/ethereum/go-ethereum/common"
2121
"github.com/ethereum/go-ethereum/crypto"
22+
"github.com/ethereum/go-ethereum/rlp"
2223
"github.com/ethereum/go-ethereum/statediff"
2324
"strconv"
2425
)
@@ -51,14 +52,20 @@ func FromParityCsvRow(csvRow []string) (StorageDiff, error) {
5152
}, nil
5253
}
5354

54-
func FromGethStateDiff(account statediff.AccountDiff, stateDiff *statediff.StateDiff, storage statediff.StorageDiff) StorageDiff {
55+
func FromGethStateDiff(account statediff.AccountDiff, stateDiff *statediff.StateDiff, storage statediff.StorageDiff) (StorageDiff, error) {
56+
var decodedValue []byte
57+
err := rlp.DecodeBytes(storage.Value, &decodedValue)
58+
if err != nil {
59+
return StorageDiff{}, err
60+
}
61+
5562
return StorageDiff{
5663
KeccakOfContractAddress: common.BytesToHash(account.Key),
5764
BlockHash: stateDiff.BlockHash,
5865
BlockHeight: int(stateDiff.BlockNumber.Int64()),
5966
StorageKey: common.BytesToHash(storage.Key),
60-
StorageValue: common.BytesToHash(storage.Value),
61-
}
67+
StorageValue: common.BytesToHash(decodedValue),
68+
}, nil
6269
}
6370

6471
func HexToKeccak256Hash(hex string) common.Hash {

libraries/shared/storage/utils/diff_test.go

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ package utils_test
1818

1919
import (
2020
"github.com/ethereum/go-ethereum/common"
21+
"github.com/ethereum/go-ethereum/rlp"
2122
"github.com/ethereum/go-ethereum/statediff"
2223
. "github.com/onsi/ginkgo"
2324
. "github.com/onsi/gomega"
2425
"github.com/vulcanize/vulcanizedb/libraries/shared/storage/utils"
26+
"github.com/vulcanize/vulcanizedb/libraries/shared/test_data"
2527
"github.com/vulcanize/vulcanizedb/pkg/fakes"
2628
"math/big"
2729
"math/rand"
@@ -63,18 +65,26 @@ var _ = Describe("Storage row parsing", func() {
6365
})
6466

6567
Describe("FromGethStateDiff", func() {
66-
It("adds relevant fields to diff", func() {
67-
accountDiff := statediff.AccountDiff{Key: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}}
68-
stateDiff := &statediff.StateDiff{
68+
var (
69+
accountDiff = statediff.AccountDiff{Key: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}}
70+
stateDiff = &statediff.StateDiff{
6971
BlockNumber: big.NewInt(rand.Int63()),
7072
BlockHash: fakes.FakeHash,
7173
}
74+
)
75+
76+
It("adds relevant fields to diff", func() {
77+
storageValueBytes := []byte{3}
78+
storageValueRlp, encodeErr := rlp.EncodeToBytes(storageValueBytes)
79+
Expect(encodeErr).NotTo(HaveOccurred())
80+
7281
storageDiff := statediff.StorageDiff{
7382
Key: []byte{0, 9, 8, 7, 6, 5, 4, 3, 2, 1},
74-
Value: []byte{1, 2, 3, 4, 5, 0, 9, 8, 7, 6},
83+
Value: storageValueRlp,
7584
}
7685

77-
result := utils.FromGethStateDiff(accountDiff, stateDiff, storageDiff)
86+
result, err := utils.FromGethStateDiff(accountDiff, stateDiff, storageDiff)
87+
Expect(err).NotTo(HaveOccurred())
7888

7989
expectedAddress := common.BytesToHash(accountDiff.Key)
8090
Expect(result.KeccakOfContractAddress).To(Equal(expectedAddress))
@@ -83,8 +93,34 @@ var _ = Describe("Storage row parsing", func() {
8393
Expect(result.BlockHeight).To(Equal(expectedBlockHeight))
8494
expectedStorageKey := common.BytesToHash(storageDiff.Key)
8595
Expect(result.StorageKey).To(Equal(expectedStorageKey))
86-
expectedStorageValue := common.BytesToHash(storageDiff.Value)
96+
expectedStorageValue := common.BytesToHash(storageValueBytes)
8797
Expect(result.StorageValue).To(Equal(expectedStorageValue))
8898
})
99+
100+
It("handles decoding large storage values from their RLP", func() {
101+
storageValueBytes := []byte{1, 2, 3, 4, 5, 0, 9, 8, 7, 6}
102+
storageValueRlp, encodeErr := rlp.EncodeToBytes(storageValueBytes)
103+
Expect(encodeErr).NotTo(HaveOccurred())
104+
105+
storageDiff := statediff.StorageDiff{
106+
Key: []byte{0, 9, 8, 7, 6, 5, 4, 3, 2, 1},
107+
Value: storageValueRlp,
108+
}
109+
110+
result, err := utils.FromGethStateDiff(accountDiff, stateDiff, storageDiff)
111+
Expect(err).NotTo(HaveOccurred())
112+
Expect(result.StorageValue).To(Equal(common.BytesToHash(storageValueBytes)))
113+
})
114+
115+
It("returns an err if decoding the storage value Rlp fails", func() {
116+
storageDiff := statediff.StorageDiff{
117+
Key: []byte{0, 9, 8, 7, 6, 5, 4, 3, 2, 1},
118+
Value: test_data.StorageKey,
119+
}
120+
121+
_, err := utils.FromGethStateDiff(accountDiff, stateDiff, storageDiff)
122+
Expect(err).To(HaveOccurred())
123+
Expect(err).To(MatchError("rlp: input contains more than one value"))
124+
})
89125
})
90126
})

libraries/shared/test_data/statediff.go

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,29 @@ import (
2929
var (
3030
BlockNumber = big.NewInt(rand.Int63())
3131
BlockHash = "0xfa40fbe2d98d98b3363a778d52f2bcd29d6790b9b3f3cab2b167fd12d3550f73"
32-
CodeHash = common.Hex2Bytes("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
33-
NewNonceValue = rand.Uint64()
34-
NewBalanceValue = rand.Int63()
35-
ContractRoot = common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
36-
StoragePath = common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").Bytes()
37-
StorageKey = common.HexToHash("0000000000000000000000000000000000000000000000000000000000000001").Bytes()
38-
StorageValue = common.Hex2Bytes("0x03")
39-
storage = []statediff.StorageDiff{{
32+
CodeHash = common.Hex2Bytes("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
33+
NewNonceValue = rand.Uint64()
34+
NewBalanceValue = rand.Int63()
35+
ContractRoot = common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
36+
StoragePath = common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").Bytes()
37+
StorageKey = common.HexToHash("0000000000000000000000000000000000000000000000000000000000000001").Bytes()
38+
SmallStorageValue = common.Hex2Bytes("03")
39+
SmallStorageValueRlp, _ = rlp.EncodeToBytes(SmallStorageValue)
40+
storageWithSmallValue = []statediff.StorageDiff{{
4041
Key: StorageKey,
41-
Value: StorageValue,
42+
Value: SmallStorageValueRlp,
4243
Path: StoragePath,
4344
Proof: [][]byte{},
4445
}}
45-
emptyStorage = make([]statediff.StorageDiff, 0)
46+
LargeStorageValue = common.Hex2Bytes("00191b53778c567b14b50ba0000")
47+
LargeStorageValueRlp, rlpErr = rlp.EncodeToBytes(LargeStorageValue)
48+
storageWithLargeValue = []statediff.StorageDiff{{
49+
Key: StorageKey,
50+
Value: LargeStorageValueRlp,
51+
Path: StoragePath,
52+
Proof: [][]byte{},
53+
}}
54+
EmptyStorage = make([]statediff.StorageDiff, 0)
4655
contractAddress = common.HexToAddress("0xaE9BEa628c4Ce503DcFD7E305CaB4e29E7476592")
4756
ContractLeafKey = crypto.Keccak256Hash(contractAddress[:])
4857
anotherContractAddress = common.HexToAddress("0xaE9BEa628c4Ce503DcFD7E305CaB4e29E7476593")
@@ -59,25 +68,20 @@ var (
5968
{
6069
Key: ContractLeafKey.Bytes(),
6170
Value: valueBytes,
62-
Storage: storage,
63-
},
64-
{
65-
Key: AnotherContractLeafKey.Bytes(),
66-
Value: valueBytes,
67-
Storage: emptyStorage,
71+
Storage: storageWithSmallValue,
6872
},
6973
}
7074

7175
UpdatedAccountDiffs = []statediff.AccountDiff{{
7276
Key: AnotherContractLeafKey.Bytes(),
7377
Value: valueBytes,
74-
Storage: storage,
78+
Storage: storageWithLargeValue,
7579
}}
7680

7781
DeletedAccountDiffs = []statediff.AccountDiff{{
78-
Key: ContractLeafKey.Bytes(),
82+
Key: AnotherContractLeafKey.Bytes(),
7983
Value: valueBytes,
80-
Storage: storage,
84+
Storage: storageWithSmallValue,
8185
}}
8286

8387
MockStateDiff = statediff.StateDiff{

0 commit comments

Comments
 (0)