From 2be2a06575bca5b49ae66d19b78bf9d3c99fcaaa Mon Sep 17 00:00:00 2001 From: nabarun Date: Wed, 16 Mar 2022 21:45:31 +0530 Subject: [PATCH] Add integration tests for service to fill indexing gap --- .github/workflows/on-pr.yaml | 31 ++ Makefile | 1 + scripts/run_integration_test.sh | 1 + .../run_integration_test_forward_eth_calls.sh | 1 + ...gration_test_watched_address_gap_filler.sh | 28 ++ test/direct_proxy_integration_test.go | 35 +- test/helper.go | 18 + test/integration_test.go | 35 +- ...ss_gap_filling_service_integration_test.go | 318 ++++++++++++++++++ 9 files changed, 414 insertions(+), 54 deletions(-) create mode 100644 scripts/run_integration_test_watched_address_gap_filler.sh create mode 100644 test/watched_address_gap_filling_service_integration_test.go diff --git a/.github/workflows/on-pr.yaml b/.github/workflows/on-pr.yaml index c139e829..9b6235fb 100644 --- a/.github/workflows/on-pr.yaml +++ b/.github/workflows/on-pr.yaml @@ -114,3 +114,34 @@ jobs: while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8081)" != "200" ]; do echo "waiting for ipld-eth-server..." && sleep 5; done && \ while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8545)" != "200" ]; do echo "waiting for geth-statediff..." && sleep 5; done && \ make integrationtest + + integrationtest_watchedaddress_gapfillingservice: + name: Run integration tests for watched addresses with gap filling service enabled + env: + GOPATH: /tmp/go + DB_WRITE: true + ETH_FORWARD_ETH_CALLS: false + ETH_PROXY_ON_ERROR: false + ETH_HTTP_PATH: "" + WATCHED_ADDRESS_GAP_FILLER_ENABLED: true + WATCHED_ADDRESS_GAP_FILLER_INTERVAL: 2 + strategy: + matrix: + go-version: [1.16.x] + os: [ubuntu-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Create GOPATH + run: mkdir -p /tmp/go + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - uses: actions/checkout@v2 + - name: Run database + run: docker-compose -f docker-compose.test.yml -f docker-compose.yml up -d ipld-eth-db dapptools contract eth-server + - name: Test + run: | + while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8081)" != "200" ]; do echo "waiting for ipld-eth-server..." && sleep 5; done && \ + while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8545)" != "200" ]; do echo "waiting for geth-statediff..." && sleep 5; done && \ + make integrationtest diff --git a/Makefile b/Makefile index 6cecdaa5..c452ad51 100644 --- a/Makefile +++ b/Makefile @@ -77,6 +77,7 @@ integrationtest_local: | $(GINKGO) $(GOOSE) go fmt ./... ./scripts/run_integration_test.sh ./scripts/run_integration_test_forward_eth_calls.sh + ./scripts/run_integration_test_watched_address_gap_filler.sh build: go fmt ./... diff --git a/scripts/run_integration_test.sh b/scripts/run_integration_test.sh index 09bffcef..7e834f89 100755 --- a/scripts/run_integration_test.sh +++ b/scripts/run_integration_test.sh @@ -5,6 +5,7 @@ export ETH_FORWARD_ETH_CALLS=false export DB_WRITE=true export ETH_HTTP_PATH="" export ETH_PROXY_ON_ERROR=false +export WATCHED_ADDRESS_GAP_FILLER_ENABLED=false # Clear up existing docker images and volume. docker-compose down --remove-orphans --volumes diff --git a/scripts/run_integration_test_forward_eth_calls.sh b/scripts/run_integration_test_forward_eth_calls.sh index 0b7ab672..97985ceb 100644 --- a/scripts/run_integration_test_forward_eth_calls.sh +++ b/scripts/run_integration_test_forward_eth_calls.sh @@ -5,6 +5,7 @@ export ETH_FORWARD_ETH_CALLS=true export DB_WRITE=false export ETH_HTTP_PATH="dapptools:8545" export ETH_PROXY_ON_ERROR=false +export WATCHED_ADDRESS_GAP_FILLER_ENABLED=false # Clear up existing docker images and volume. docker-compose down --remove-orphans --volumes diff --git a/scripts/run_integration_test_watched_address_gap_filler.sh b/scripts/run_integration_test_watched_address_gap_filler.sh new file mode 100644 index 00000000..1201782e --- /dev/null +++ b/scripts/run_integration_test_watched_address_gap_filler.sh @@ -0,0 +1,28 @@ +set -e +set -o xtrace + +export ETH_FORWARD_ETH_CALLS=false +export DB_WRITE=true +export ETH_HTTP_PATH="" +export ETH_PROXY_ON_ERROR=false +export WATCHED_ADDRESS_GAP_FILLER_ENABLED=true +export WATCHED_ADDRESS_GAP_FILLER_INTERVAL=5 + +# Clear up existing docker images and volume. +docker-compose down --remove-orphans --volumes + +# Build and start the containers. +# Note: Build only if `ipld-eth-server` or other container code is modified. Otherwise comment this line. +docker-compose -f docker-compose.test.yml -f docker-compose.yml build eth-server +docker-compose -f docker-compose.test.yml -f docker-compose.yml up -d ipld-eth-db dapptools contract eth-server + +export PGPASSWORD=password +export DATABASE_USER=vdbm +export DATABASE_PORT=8077 +export DATABASE_PASSWORD=password +export DATABASE_HOSTNAME=127.0.0.1 + +# Wait for containers to be up and execute the integration test. +while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8081)" != "200" ]; do echo "waiting for ipld-eth-server..." && sleep 5; done && \ + while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8545)" != "200" ]; do echo "waiting for geth-statediff..." && sleep 5; done && \ + make integrationtest diff --git a/test/direct_proxy_integration_test.go b/test/direct_proxy_integration_test.go index 4256c18d..68255213 100644 --- a/test/direct_proxy_integration_test.go +++ b/test/direct_proxy_integration_test.go @@ -20,6 +20,8 @@ import ( var _ = Describe("Integration test", func() { directProxyEthCalls, err := strconv.ParseBool(os.Getenv("ETH_FORWARD_ETH_CALLS")) Expect(err).To(BeNil()) + watchedAddressServiceEnabled, err := strconv.ParseBool(os.Getenv("WATCHED_ADDRESS_GAP_FILLER_ENABLED")) + Expect(err).To(BeNil()) gethHttpPath := "http://127.0.0.1:8545" gethClient, err := ethclient.Dial(gethHttpPath) Expect(err).ToNot(HaveOccurred()) @@ -38,11 +40,14 @@ var _ = Describe("Integration test", func() { var txErr error sleepInterval := 2 * time.Second + BeforeEach(func() { + if !directProxyEthCalls || watchedAddressServiceEnabled { + Skip("skipping direct-proxy-forwarding integration tests") + } + }) + Describe("get Block", func() { BeforeEach(func() { - if !directProxyEthCalls { - Skip("skipping direct-proxy-forwarding integration tests") - } contract, contractErr = integration.DeployContract() time.Sleep(sleepInterval) }) @@ -94,9 +99,6 @@ var _ = Describe("Integration test", func() { Describe("Transaction", func() { BeforeEach(func() { - if !directProxyEthCalls { - Skip("skipping direct-proxy-forwarding integration tests") - } contract, contractErr = integration.DeployContract() time.Sleep(sleepInterval) }) @@ -122,9 +124,6 @@ var _ = Describe("Integration test", func() { Describe("Receipt", func() { BeforeEach(func() { - if !directProxyEthCalls { - Skip("skipping direct-proxy-forwarding integration tests") - } contract, contractErr = integration.DeployContract() time.Sleep(sleepInterval) }) @@ -142,9 +141,6 @@ var _ = Describe("Integration test", func() { Describe("FilterLogs", func() { BeforeEach(func() { - if !directProxyEthCalls { - Skip("skipping direct-proxy-forwarding integration tests") - } contract, contractErr = integration.DeployContract() time.Sleep(sleepInterval) }) @@ -174,9 +170,6 @@ var _ = Describe("Integration test", func() { Describe("CodeAt", func() { BeforeEach(func() { - if !directProxyEthCalls { - Skip("skipping direct-proxy-forwarding integration tests") - } contract, contractErr = integration.DeployContract() time.Sleep(sleepInterval) }) @@ -224,9 +217,6 @@ var _ = Describe("Integration test", func() { Describe("Get balance", func() { address := "0x1111111111111111111111111111111111111112" BeforeEach(func() { - if !directProxyEthCalls { - Skip("skipping direct-proxy-forwarding integration tests") - } tx, txErr = integration.SendEth(address, "0.01") time.Sleep(sleepInterval) }) @@ -286,9 +276,6 @@ var _ = Describe("Integration test", func() { Describe("Get Storage", func() { BeforeEach(func() { - if !directProxyEthCalls { - Skip("skipping direct-proxy-forwarding integration tests") - } contract, contractErr = integration.DeployContract() erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10) @@ -392,9 +379,6 @@ var _ = Describe("Integration test", func() { Describe("eth call", func() { BeforeEach(func() { - if !directProxyEthCalls { - Skip("skipping direct-proxy-forwarding integration tests") - } contract, contractErr = integration.DeployContract() erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10) @@ -445,9 +429,6 @@ var _ = Describe("Integration test", func() { Describe("Chain ID", func() { It("Check chain id", func() { - if !directProxyEthCalls { - Skip("skipping direct-proxy-forwarding integration tests") - } _, err := gethClient.ChainID(ctx) Expect(err).ToNot(HaveOccurred()) diff --git a/test/helper.go b/test/helper.go index 41167622..59b4db71 100644 --- a/test/helper.go +++ b/test/helper.go @@ -167,3 +167,21 @@ func ClearWatchedAddresses(gethRPCClient *rpc.Client) error { return nil } + +func Create2Contract(contractName string, salt string) (*ContractDeployed, error) { + res, err := http.Get(fmt.Sprintf("%s/v1/create2Contract?contract=%s&salt=%s", srvUrl, contractName, salt)) + if err != nil { + return nil, err + } + defer res.Body.Close() + + var contract ContractDeployed + + decoder := json.NewDecoder(res.Body) + err = decoder.Decode(&contract) + if err != nil { + return nil, err + } + + return &contract, nil +} diff --git a/test/integration_test.go b/test/integration_test.go index 9abaaaff..d38474ac 100644 --- a/test/integration_test.go +++ b/test/integration_test.go @@ -31,6 +31,8 @@ var ( var _ = Describe("Integration test", func() { directProxyEthCalls, err := strconv.ParseBool(os.Getenv("ETH_FORWARD_ETH_CALLS")) Expect(err).To(BeNil()) + watchedAddressServiceEnabled, err := strconv.ParseBool(os.Getenv("WATCHED_ADDRESS_GAP_FILLER_ENABLED")) + Expect(err).To(BeNil()) gethHttpPath := "http://127.0.0.1:8545" gethClient, err := ethclient.Dial(gethHttpPath) Expect(err).ToNot(HaveOccurred()) @@ -49,11 +51,14 @@ var _ = Describe("Integration test", func() { var txErr error sleepInterval := 2 * time.Second + BeforeEach(func() { + if directProxyEthCalls || watchedAddressServiceEnabled { + Skip("skipping no-direct-proxy-forwarding integration tests") + } + }) + Describe("get Block", func() { BeforeEach(func() { - if directProxyEthCalls { - Skip("skipping no-direct-proxy-forwarding integration tests") - } contract, contractErr = integration.DeployContract() time.Sleep(sleepInterval) }) @@ -123,9 +128,6 @@ var _ = Describe("Integration test", func() { Describe("Transaction", func() { BeforeEach(func() { - if directProxyEthCalls { - Skip("skipping no-direct-proxy-forwarding integration tests") - } contract, contractErr = integration.DeployContract() time.Sleep(sleepInterval) }) @@ -157,9 +159,6 @@ var _ = Describe("Integration test", func() { Describe("Receipt", func() { BeforeEach(func() { - if directProxyEthCalls { - Skip("skipping no-direct-proxy-forwarding integration tests") - } contract, contractErr = integration.DeployContract() time.Sleep(sleepInterval) }) @@ -187,9 +186,6 @@ var _ = Describe("Integration test", func() { Describe("FilterLogs", func() { BeforeEach(func() { - if directProxyEthCalls { - Skip("skipping no-direct-proxy-forwarding integration tests") - } contract, contractErr = integration.DeployContract() time.Sleep(sleepInterval) }) @@ -220,9 +216,6 @@ var _ = Describe("Integration test", func() { Describe("CodeAt", func() { BeforeEach(func() { - if directProxyEthCalls { - Skip("skipping no-direct-proxy-forwarding integration tests") - } contract, contractErr = integration.DeployContract() time.Sleep(sleepInterval) }) @@ -270,9 +263,6 @@ var _ = Describe("Integration test", func() { Describe("Get balance", func() { address := "0x1111111111111111111111111111111111111112" BeforeEach(func() { - if directProxyEthCalls { - Skip("skipping no-direct-proxy-forwarding integration tests") - } tx, txErr = integration.SendEth(address, "0.01") time.Sleep(sleepInterval) }) @@ -336,9 +326,6 @@ var _ = Describe("Integration test", func() { Describe("Get Storage", func() { BeforeEach(func() { - if directProxyEthCalls { - Skip("skipping no-direct-proxy-forwarding integration tests") - } contract, contractErr = integration.DeployContract() erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10) @@ -452,9 +439,6 @@ var _ = Describe("Integration test", func() { Describe("eth call", func() { BeforeEach(func() { - if directProxyEthCalls { - Skip("skipping no-direct-proxy-forwarding integration tests") - } contract, contractErr = integration.DeployContract() erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10) @@ -505,9 +489,6 @@ var _ = Describe("Integration test", func() { Describe("Chain ID", func() { It("Check chain id", func() { - if directProxyEthCalls { - Skip("skipping no-direct-proxy-forwarding integration tests") - } gethChainId, err := gethClient.ChainID(ctx) Expect(err).ToNot(HaveOccurred()) diff --git a/test/watched_address_gap_filling_service_integration_test.go b/test/watched_address_gap_filling_service_integration_test.go new file mode 100644 index 00000000..8e33446f --- /dev/null +++ b/test/watched_address_gap_filling_service_integration_test.go @@ -0,0 +1,318 @@ +package integration_test + +import ( + "context" + "math/big" + "os" + "strconv" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/statediff/types" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + integration "github.com/vulcanize/ipld-eth-server/test" +) + +var _ = Describe("Watched address gap filling service integration test", func() { + dbWrite, err := strconv.ParseBool(os.Getenv("DB_WRITE")) + Expect(err).To(BeNil()) + + watchedAddressServiceEnabled, err := strconv.ParseBool(os.Getenv("WATCHED_ADDRESS_GAP_FILLER_ENABLED")) + Expect(err).To(BeNil()) + + serviceInterval, err := strconv.ParseInt(os.Getenv("WATCHED_ADDRESS_GAP_FILLER_INTERVAL"), 10, 0) + Expect(err).To(BeNil()) + + gethHttpPath := "http://127.0.0.1:8545" + gethRPCClient, err := rpc.Dial(gethHttpPath) + Expect(err).ToNot(HaveOccurred()) + + ipldEthHttpPath := "http://127.0.0.1:8081" + ipldClient, err := ethclient.Dial(ipldEthHttpPath) + Expect(err).ToNot(HaveOccurred()) + ipldRPCClient, err := rpc.Dial(ipldEthHttpPath) + Expect(err).ToNot(HaveOccurred()) + + var ( + ctx = context.Background() + + contractErr error + txErr error + + GLD1 *integration.ContractDeployed + SLV1 *integration.ContractDeployed + SLV2 *integration.ContractDeployed + + countAIndex string + countBIndex string + + oldCountA1 = big.NewInt(0) + oldCountA2 = big.NewInt(0) + oldCountB2 = big.NewInt(0) + + updatedCountA1 = big.NewInt(1) + updatedCountA2 = big.NewInt(1) + updatedCountB2 = big.NewInt(1) + + SLV2CountBIncrementedAt *integration.CountIncremented + + contract1Salt = "contract1SLV" + ) + + BeforeEach(func() { + if !dbWrite || !watchedAddressServiceEnabled { + Skip("skipping watched address gap filling service integration tests") + } + }) + + It("test init", func() { + // Clear out watched addresses + err := integration.ClearWatchedAddresses(gethRPCClient) + Expect(err).ToNot(HaveOccurred()) + + // Deploy a GLD contract + GLD1, contractErr = integration.DeployContract() + Expect(contractErr).ToNot(HaveOccurred()) + + // Watch GLD1 contract + operation := types.Add + args := []types.WatchAddressArg{ + { + Address: GLD1.Address, + CreatedAt: uint64(GLD1.BlockNumber), + }, + } + ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args) + Expect(ipldErr).ToNot(HaveOccurred()) + + // Deploy two SLV contracts and update storage slots + SLV1, contractErr = integration.Create2Contract("SLVToken", contract1Salt) + Expect(contractErr).ToNot(HaveOccurred()) + + _, txErr = integration.IncrementCount(SLV1.Address, "A") + Expect(txErr).ToNot(HaveOccurred()) + + SLV2, contractErr = integration.DeploySLVContract() + Expect(contractErr).ToNot(HaveOccurred()) + + _, txErr = integration.IncrementCount(SLV2.Address, "A") + Expect(txErr).ToNot(HaveOccurred()) + SLV2CountBIncrementedAt, txErr = integration.IncrementCount(SLV2.Address, "B") + Expect(txErr).ToNot(HaveOccurred()) + + // Get storage slot keys + storageSlotAKey, err := integration.GetStorageSlotKey("SLVToken", "countA") + Expect(err).ToNot(HaveOccurred()) + countAIndex = storageSlotAKey.Key + + storageSlotBKey, err := integration.GetStorageSlotKey("SLVToken", "countB") + Expect(err).ToNot(HaveOccurred()) + countBIndex = storageSlotBKey.Key + }) + + defer It("test cleanup", func() { + // Destroy create2 contract + _, err := integration.DestroySLVContract(SLV1.Address) + Expect(err).ToNot(HaveOccurred()) + + // Clear out watched addresses + err = integration.ClearWatchedAddresses(gethRPCClient) + Expect(err).ToNot(HaveOccurred()) + }) + + Context("previously unwatched contract watched", func() { + It("indexes state only for watched contract", func() { + // WatchedAddresses = [GLD1] + // SLV1, countA + countA1Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV1.Address), common.HexToHash(countAIndex), nil) + Expect(err).ToNot(HaveOccurred()) + countA1 := new(big.Int).SetBytes(countA1Storage) + Expect(countA1.String()).To(Equal(oldCountA1.String())) + + // SLV2, countA + countA2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countAIndex), nil) + Expect(err).ToNot(HaveOccurred()) + countA2 := new(big.Int).SetBytes(countA2Storage) + Expect(countA2.String()).To(Equal(oldCountA2.String())) + + // SLV2, countB + countB2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countBIndex), nil) + Expect(err).ToNot(HaveOccurred()) + countB2 := new(big.Int).SetBytes(countB2Storage) + Expect(countB2.String()).To(Equal(oldCountB2.String())) + }) + + It("indexes past state on watching a contract", func() { + // Watch SLV1 contract + args := []types.WatchAddressArg{ + { + Address: SLV1.Address, + CreatedAt: uint64(SLV1.BlockNumber), + }, + } + ipldErr := ipldRPCClient.Call(nil, ipldMethod, types.Add, args) + Expect(ipldErr).ToNot(HaveOccurred()) + + // Sleep for service interval + few extra seconds + time.Sleep(time.Duration(serviceInterval+2) * time.Second) + + // WatchedAddresses = [GLD1, SLV1] + // SLV1, countA + countA1Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV1.Address), common.HexToHash(countAIndex), nil) + Expect(err).ToNot(HaveOccurred()) + countA1 := new(big.Int).SetBytes(countA1Storage) + Expect(countA1.String()).To(Equal(updatedCountA1.String())) + + // SLV2, countA + countA2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countAIndex), nil) + Expect(err).ToNot(HaveOccurred()) + countA2 := new(big.Int).SetBytes(countA2Storage) + Expect(countA2.String()).To(Equal(oldCountA2.String())) + + // SLV2, countB + countB2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countBIndex), nil) + Expect(err).ToNot(HaveOccurred()) + countB2 := new(big.Int).SetBytes(countB2Storage) + Expect(countB2.String()).To(Equal(oldCountB2.String())) + }) + }) + + Context("previously unwatched contract watched (different 'created_at')", func() { + It("indexes past state from 'created_at' onwards on watching a contract", func() { + // Watch SLV2 (created_at -> countB incremented) contract + args := []types.WatchAddressArg{ + { + Address: SLV2.Address, + CreatedAt: uint64(SLV2CountBIncrementedAt.BlockNumber), + }, + } + ipldErr := ipldRPCClient.Call(nil, ipldMethod, types.Add, args) + Expect(ipldErr).ToNot(HaveOccurred()) + + // Sleep for service interval + few extra seconds + time.Sleep(time.Duration(serviceInterval+2) * time.Second) + + // WatchedAddresses = [GLD1, SLV1, SLV2] + // SLV2, countA + countA2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countAIndex), nil) + Expect(err).ToNot(HaveOccurred()) + countA2 := new(big.Int).SetBytes(countA2Storage) + Expect(countA2.String()).To(Equal(oldCountA2.String())) + + // SLV2, countB + countB2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countBIndex), nil) + Expect(err).ToNot(HaveOccurred()) + countB2 := new(big.Int).SetBytes(countB2Storage) + Expect(countB2.String()).To(Equal(updatedCountB2.String())) + }) + + It("indexes missing past state on watching a contract from an earlier 'created_at'", func() { + // Remove SLV2 (created_at -> countB incremented) watched contract + args := []types.WatchAddressArg{ + { + Address: SLV2.Address, + CreatedAt: uint64(SLV2CountBIncrementedAt.BlockNumber), + }, + } + ipldErr := ipldRPCClient.Call(nil, ipldMethod, types.Remove, args) + Expect(ipldErr).ToNot(HaveOccurred()) + + // Watch SLV2 (created_at -> deployment) contract + args = []types.WatchAddressArg{ + { + Address: SLV2.Address, + CreatedAt: uint64(SLV2.BlockNumber), + }, + } + ipldErr = ipldRPCClient.Call(nil, ipldMethod, types.Add, args) + Expect(ipldErr).ToNot(HaveOccurred()) + + // Sleep for service interval + few extra seconds + time.Sleep(time.Duration(serviceInterval+2) * time.Second) + + // WatchedAddresses = [GLD1, SLV1, SLV2] + // SLV2, countA + countA2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countAIndex), nil) + Expect(err).ToNot(HaveOccurred()) + countA2 := new(big.Int).SetBytes(countA2Storage) + Expect(countA2.String()).To(Equal(updatedCountA2.String())) + + // SLV2, countB + countB2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countBIndex), nil) + Expect(err).ToNot(HaveOccurred()) + countB2 := new(big.Int).SetBytes(countB2Storage) + Expect(countB2.String()).To(Equal(updatedCountB2.String())) + }) + }) + + Context("destroyed contract redeployed and watched", func() { + It("returns zero value for destroyed contract", func() { + _, err := integration.DestroySLVContract(SLV1.Address) + Expect(err).ToNot(HaveOccurred()) + + updatedCountA1 = big.NewInt(0) + + operation := types.Remove + args := []types.WatchAddressArg{ + { + Address: SLV1.Address, + CreatedAt: uint64(SLV1.BlockNumber), + }, + } + ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args) + Expect(ipldErr).ToNot(HaveOccurred()) + + // WatchedAddresses = [GLD1, SLV2] + // SLV1, countA + countA1Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV1.Address), common.HexToHash(countAIndex), nil) + Expect(err).ToNot(HaveOccurred()) + countA1 := new(big.Int).SetBytes(countA1Storage) + Expect(countA1.String()).To(Equal(updatedCountA1.String())) + oldCountA1.Set(updatedCountA1) + }) + + It("indexes state for redeployed contract", func() { + // Redeploy contract + SLV1, contractErr = integration.Create2Contract("SLVToken", contract1Salt) + Expect(contractErr).ToNot(HaveOccurred()) + + // Add to watched address + operation := types.Add + args := []types.WatchAddressArg{ + { + Address: SLV1.Address, + CreatedAt: uint64(SLV1.BlockNumber), + }, + } + ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args) + Expect(ipldErr).ToNot(HaveOccurred()) + + // Sleep for service interval + few extra seconds + time.Sleep(time.Duration(serviceInterval+2) * time.Second) + + // WatchedAddresses = [GLD1, SLV2, SLV1] + // SLV1, countA + countA1Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV1.Address), common.HexToHash(countAIndex), nil) + Expect(err).ToNot(HaveOccurred()) + countA1 := new(big.Int).SetBytes(countA1Storage) + Expect(countA1.String()).To(Equal(updatedCountA1.String())) + oldCountA1.Set(updatedCountA1) + + // Update storage slots + _, txErr = integration.IncrementCount(SLV1.Address, "A") + time.Sleep(sleepInterval) + Expect(txErr).ToNot(HaveOccurred()) + updatedCountA1.Add(updatedCountA1, big.NewInt(1)) + + countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV1.Address), common.HexToHash(countAIndex), nil) + Expect(err).ToNot(HaveOccurred()) + countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage) + Expect(countA1AfterIncrement.String()).To(Equal(updatedCountA1.String())) + oldCountA1.Set(updatedCountA1) + }) + }) +})