diff --git a/libraries/shared/factories/storage/transformer.go b/libraries/shared/factories/storage/transformer.go index fce04465..58282e85 100644 --- a/libraries/shared/factories/storage/transformer.go +++ b/libraries/shared/factories/storage/transformer.go @@ -47,9 +47,11 @@ func (transformer Transformer) Execute(row utils.StorageDiffRow) error { if lookupErr != nil { return lookupErr } + //packed storage slots return a slice of decoded values value, decodeErr := utils.Decode(row, metadata) if decodeErr != nil { return decodeErr } + return transformer.Repository.Create(row.BlockHeight, row.BlockHash.Hex(), metadata, value) } diff --git a/libraries/shared/factories/storage/transformer_test.go b/libraries/shared/factories/storage/transformer_test.go index 354c106b..09b91d80 100644 --- a/libraries/shared/factories/storage/transformer_test.go +++ b/libraries/shared/factories/storage/transformer_test.go @@ -100,4 +100,54 @@ var _ = Describe("Storage transformer", func() { Expect(err).To(HaveOccurred()) Expect(err).To(MatchError(fakes.FakeError)) }) + + Describe("when a storage row contains more than one item packed in storage", func() { + var ( + rawValue = common.HexToAddress("000000000000000000000000000000000000000000000002a300000000002a30") + fakeBlockNumber = 123 + fakeBlockHash = "0x67890" + packedTypes = make(map[int]utils.ValueType) + ) + packedTypes[0] = utils.Uint48 + packedTypes[1] = utils.Uint48 + + var fakeMetadata = utils.StorageValueMetadata{ + Name: "", + Keys: nil, + Type: utils.PackedSlot, + PackedTypes: packedTypes, + } + + It("passes the decoded data items to the repository", func() { + mappings.Metadata = fakeMetadata + fakeRow := utils.StorageDiffRow{ + Contract: common.Address{}, + BlockHash: common.HexToHash(fakeBlockHash), + BlockHeight: fakeBlockNumber, + StorageKey: common.Hash{}, + StorageValue: rawValue.Hash(), + } + + err := t.Execute(fakeRow) + + Expect(err).NotTo(HaveOccurred()) + Expect(repository.PassedBlockNumber).To(Equal(fakeBlockNumber)) + Expect(repository.PassedBlockHash).To(Equal(common.HexToHash(fakeBlockHash).Hex())) + Expect(repository.PassedMetadata).To(Equal(fakeMetadata)) + expectedPassedValue := make(map[int]string) + expectedPassedValue[0]= "10800" + expectedPassedValue[1]= "172800" + Expect(repository.PassedValue.(map[int]string)).To(Equal(expectedPassedValue)) + }) + + It("returns error if creating a row fails", func() { + mappings.Metadata = fakeMetadata + repository.CreateErr = fakes.FakeError + + err := t.Execute(utils.StorageDiffRow{StorageValue: rawValue.Hash()}) + + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(fakes.FakeError)) + }) + }) }) diff --git a/libraries/shared/mocks/storage_repository.go b/libraries/shared/mocks/storage_repository.go index c4e351be..9a22a307 100644 --- a/libraries/shared/mocks/storage_repository.go +++ b/libraries/shared/mocks/storage_repository.go @@ -33,6 +33,7 @@ func (repository *MockStorageRepository) Create(blockNumber int, blockHash strin repository.PassedBlockNumber = blockNumber repository.PassedBlockHash = blockHash repository.PassedMetadata = metadata + repository.PassedValue = value return repository.CreateErr } diff --git a/libraries/shared/storage/utils/decoder.go b/libraries/shared/storage/utils/decoder.go index 149e41ad..c672cd31 100644 --- a/libraries/shared/storage/utils/decoder.go +++ b/libraries/shared/storage/utils/decoder.go @@ -18,9 +18,8 @@ package utils import ( "fmt" - "math/big" - "github.com/ethereum/go-ethereum/common" + "math/big" ) func Decode(row StorageDiffRow, metadata StorageValueMetadata) (interface{}, error) { @@ -61,17 +60,20 @@ func decodeAddress(raw []byte) string { return common.BytesToAddress(raw).Hex() } -func decodePackedSlot(raw []byte, packedTypes map[int]ValueType) []string{ +func decodePackedSlot(raw []byte, packedTypes map[int]ValueType) map[int]string{ storageSlot := raw - var results []string + var results = map[int]string{} + //the reason we're using a map and not a slice is that golang doesn't guarantee the order of a slice - for _, valueType := range packedTypes { + numberOfTypes := len(packedTypes) + for position := 0; position < numberOfTypes; position++ { + valueType := packedTypes[position] lengthOfStorageSlot := len(storageSlot) lengthOfItem := getNumberOfBytes(valueType) itemStartingIndex := lengthOfStorageSlot - lengthOfItem value := storageSlot[itemStartingIndex:] decodedValue := decodeIndividualItems(value, valueType) - results = append(results, decodedValue) + results[position] = decodedValue //pop last item off slot before moving on storageSlot = storageSlot[0:itemStartingIndex] diff --git a/libraries/shared/storage/utils/decoder_test.go b/libraries/shared/storage/utils/decoder_test.go index edb02ee0..67df8d52 100644 --- a/libraries/shared/storage/utils/decoder_test.go +++ b/libraries/shared/storage/utils/decoder_test.go @@ -85,12 +85,11 @@ var _ = Describe("Storage decoder", func() { } result, err := utils.Decode(row, metadata) - decodedValues := result.([]string) + decodedValues := result.(map[int]string) Expect(err).NotTo(HaveOccurred()) - expectedResult1 := big.NewInt(0).SetBytes(common.HexToHash("2a30").Bytes()).String() - expectedResult2 := big.NewInt(0).SetBytes(common.HexToHash("2a300").Bytes()).String() - Expect(decodedValues).To(ConsistOf(expectedResult1, expectedResult2)) + Expect(decodedValues[0]).To(Equal(big.NewInt(0).SetBytes(common.HexToHash("2a30").Bytes()).String())) + Expect(decodedValues[1]).To(Equal(big.NewInt(0).SetBytes(common.HexToHash("2a300").Bytes()).String())) }) It("decodes 5 uint48 items", func() { @@ -113,15 +112,14 @@ var _ = Describe("Storage decoder", func() { } result, err := utils.Decode(row, metadata) - decodedValues := result.([]string) + decodedValues := result.(map[int]string) Expect(err).NotTo(HaveOccurred()) - expectedResult1 := big.NewInt(0).SetBytes(common.HexToHash("A5D1A").Bytes()).String() - expectedResult2 := big.NewInt(0).SetBytes(common.HexToHash("FFFFFFFFFFFE").Bytes()).String() - expectedResult3 := big.NewInt(0).SetBytes(common.HexToHash("9F3C6").Bytes()).String() - expectedResult4 := big.NewInt(0).SetBytes(common.HexToHash("2a300").Bytes()).String() - expectedResult5 := big.NewInt(0).SetBytes(common.HexToHash("2a30").Bytes()).String() - Expect(decodedValues).To(ConsistOf(expectedResult1, expectedResult2, expectedResult3, expectedResult4, expectedResult5)) + Expect(decodedValues[0]).To(Equal(big.NewInt(0).SetBytes(common.HexToHash("2a30").Bytes()).String())) + Expect(decodedValues[1]).To(Equal(big.NewInt(0).SetBytes(common.HexToHash("2a300").Bytes()).String())) + Expect(decodedValues[2]).To(Equal(big.NewInt(0).SetBytes(common.HexToHash("9F3C6").Bytes()).String())) + Expect(decodedValues[3]).To(Equal(big.NewInt(0).SetBytes(common.HexToHash("FFFFFFFFFFFE").Bytes()).String())) + Expect(decodedValues[4]).To(Equal(big.NewInt(0).SetBytes(common.HexToHash("A5D1A").Bytes()).String())) }) It("decodes 2 uint128 items", func() { @@ -141,12 +139,11 @@ var _ = Describe("Storage decoder", func() { } result, err := utils.Decode(row, metadata) - decodedValues := result.([]string) + decodedValues := result.(map[int]string) Expect(err).NotTo(HaveOccurred()) - expectedResult1 := big.NewInt(0).SetBytes(common.HexToHash("000000038D7EA4C67FF8E502B6730000").Bytes()).String() - expectedResult2 := big.NewInt(0).SetBytes(common.HexToHash("AB54A98CEB1F0AD2").Bytes()).String() - Expect(decodedValues).To(ConsistOf(expectedResult1, expectedResult2)) + Expect(decodedValues[0]).To(Equal(big.NewInt(0).SetBytes(common.HexToHash("AB54A98CEB1F0AD2").Bytes()).String())) + Expect(decodedValues[1]).To(Equal(big.NewInt(0).SetBytes(common.HexToHash("38D7EA4C67FF8E502B6730000").Bytes()).String())) }) }) }) diff --git a/libraries/shared/storage/utils/value.go b/libraries/shared/storage/utils/value.go index c64a8d55..865bf9ae 100644 --- a/libraries/shared/storage/utils/value.go +++ b/libraries/shared/storage/utils/value.go @@ -34,6 +34,7 @@ type StorageValueMetadata struct { Keys map[Key]string Type ValueType PackedTypes map[int]ValueType //type of each item packed and their order + PackedNames map[int]string //name of each item packed and their order } func GetStorageValueMetadata(name string, keys map[Key]string, t ValueType) StorageValueMetadata {