Merge pull request #53 from vulcanize/integration_tests
integration test
This commit is contained in:
commit
f7fe3c2fc1
27
.github/workflows/on-pr.yaml
vendored
27
.github/workflows/on-pr.yaml
vendored
@ -11,7 +11,7 @@ jobs:
|
|||||||
- name: Run docker build
|
- name: Run docker build
|
||||||
run: make docker-build
|
run: make docker-build
|
||||||
test:
|
test:
|
||||||
name: Run integration tests
|
name: Run unit tests
|
||||||
env:
|
env:
|
||||||
GOPATH: /tmp/go
|
GOPATH: /tmp/go
|
||||||
strategy:
|
strategy:
|
||||||
@ -33,3 +33,28 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sleep 10
|
sleep 10
|
||||||
PGPASSWORD=password DATABASE_USER=vdbm DATABASE_PORT=8077 DATABASE_PASSWORD=password DATABASE_HOSTNAME=127.0.0.1 make test
|
PGPASSWORD=password DATABASE_USER=vdbm DATABASE_PORT=8077 DATABASE_PASSWORD=password DATABASE_HOSTNAME=127.0.0.1 make test
|
||||||
|
|
||||||
|
integrationtest:
|
||||||
|
name: Run integration tests
|
||||||
|
env:
|
||||||
|
GOPATH: /tmp/go
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
go-version: [1.15.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 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
|
||||||
|
13
Dockerfile
13
Dockerfile
@ -6,8 +6,17 @@ RUN apk add busybox-extras
|
|||||||
|
|
||||||
# Build ipld-eth-server
|
# Build ipld-eth-server
|
||||||
WORKDIR /go/src/github.com/vulcanize/ipld-eth-server
|
WORKDIR /go/src/github.com/vulcanize/ipld-eth-server
|
||||||
ADD . .
|
|
||||||
RUN GO111MODULE=on GCO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o ipld-eth-server .
|
# Cache the modules
|
||||||
|
ENV GO111MODULE=on
|
||||||
|
COPY go.mod .
|
||||||
|
COPY go.sum .
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Build the binary
|
||||||
|
RUN GCO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o ipld-eth-server .
|
||||||
|
|
||||||
# Copy migration tool
|
# Copy migration tool
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
22
Makefile
22
Makefile
@ -61,39 +61,25 @@ test: | $(GINKGO) $(GOOSE)
|
|||||||
dropdb -h $(DATABASE_HOSTNAME) -p $(DATABASE_PORT) -U $(DATABASE_USER) --if-exists $(TEST_DB)
|
dropdb -h $(DATABASE_HOSTNAME) -p $(DATABASE_PORT) -U $(DATABASE_USER) --if-exists $(TEST_DB)
|
||||||
createdb -h $(DATABASE_HOSTNAME) -p $(DATABASE_PORT) -U $(DATABASE_USER) $(TEST_DB)
|
createdb -h $(DATABASE_HOSTNAME) -p $(DATABASE_PORT) -U $(DATABASE_USER) $(TEST_DB)
|
||||||
$(GOOSE) -dir db/migrations postgres "$(TEST_CONNECT_STRING)" up
|
$(GOOSE) -dir db/migrations postgres "$(TEST_CONNECT_STRING)" up
|
||||||
$(GINKGO) -r --skipPackage=integration_tests,integration
|
$(GINKGO) -r --skipPackage=test
|
||||||
|
|
||||||
.PHONY: integrationtest
|
.PHONY: integrationtest
|
||||||
integrationtest: | $(GINKGO) $(GOOSE)
|
integrationtest: | $(GINKGO) $(GOOSE)
|
||||||
go vet ./...
|
go vet ./...
|
||||||
go fmt ./...
|
go fmt ./...
|
||||||
export PGPASSWORD=$(DATABASE_PASSWORD)
|
$(GINKGO) -r test/ -v
|
||||||
dropdb -h $(DATABASE_HOSTNAME) -p $(DATABASE_PORT) -U $(DATABASE_USER) --if-exists $(TEST_DB)
|
|
||||||
createdb -h $(DATABASE_HOSTNAME) -p $(DATABASE_PORT) -U $(DATABASE_USER) $(TEST_DB)
|
|
||||||
$(GOOSE) -dir db/migrations postgres "$(TEST_CONNECT_STRING)" up
|
|
||||||
$(GINKGO) -r integration_test/
|
|
||||||
|
|
||||||
.PHONY: test_local
|
.PHONY: test_local
|
||||||
test_local: | $(GINKGO) $(GOOSE)
|
test_local: | $(GINKGO) $(GOOSE)
|
||||||
go vet ./...
|
go vet ./...
|
||||||
go fmt ./...
|
go fmt ./...
|
||||||
dropdb -h $(HOST_NAME) -p $(PORT) -U $(USER) --if-exists $(TEST_DB)
|
./scripts/run_unit_test.sh
|
||||||
createdb -h $(HOST_NAME) -p $(PORT) -U $(USER) $(TEST_DB)
|
|
||||||
$(GOOSE) -dir db/migrations postgres "$(TEST_CONNECT_STRING_LOCAL)" up
|
|
||||||
$(GOOSE) -dir db/migrations postgres "$(TEST_CONNECT_STRING_LOCAL)" reset
|
|
||||||
make migrate NAME=$(TEST_DB)
|
|
||||||
$(GINKGO) -r --skipPackage=integration_tests,integration
|
|
||||||
|
|
||||||
.PHONY: integrationtest_local
|
.PHONY: integrationtest_local
|
||||||
integrationtest_local: | $(GINKGO) $(GOOSE)
|
integrationtest_local: | $(GINKGO) $(GOOSE)
|
||||||
go vet ./...
|
go vet ./...
|
||||||
go fmt ./...
|
go fmt ./...
|
||||||
dropdb -h $(HOST_NAME) -p $(PORT) -U $(USER) --if-exists $(TEST_DB)
|
./scripts/run_intregration_test.sh
|
||||||
createdb -h $(HOST_NAME) -p $(PORT) -U $(USER) $(TEST_DB)
|
|
||||||
$(GOOSE) -dir db/migrations postgres "$(TEST_CONNECT_STRING_LOCAL)" up
|
|
||||||
$(GOOSE) -dir db/migrations postgres "$(TEST_CONNECT_STRING_LOCAL)" reset
|
|
||||||
make migrate NAME=$(TEST_DB)
|
|
||||||
$(GINKGO) -r integration_test/
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
go fmt ./...
|
go fmt ./...
|
||||||
|
@ -135,9 +135,9 @@ TODO: Add the rest of the standard endpoints and unique endpoints (e.g. getSlice
|
|||||||
| `eth-server-graphql` | `ETH_SERVER_GRAPHQL` | false | If `true` enable Eth GraphQL Server |
|
| `eth-server-graphql` | `ETH_SERVER_GRAPHQL` | false | If `true` enable Eth GraphQL Server |
|
||||||
| `eth-server-graphql-path` | `ETH_SERVER_GRAPHQLPATH` | | If `eth-server-graphql` set to true, endpoint url for graphql server (host:port) |
|
| `eth-server-graphql-path` | `ETH_SERVER_GRAPHQLPATH` | | If `eth-server-graphql` set to true, endpoint url for graphql server (host:port) |
|
||||||
| `eth-server-http` | `ETH_SERVER_HTTP` | true | If `true` enable Eth HTTP JSON-RPC Server |
|
| `eth-server-http` | `ETH_SERVER_HTTP` | true | If `true` enable Eth HTTP JSON-RPC Server |
|
||||||
| `eth-server-http-path` | `ETH_SERVER_HTTP_PATH` | | If `eth-server-http` set to `true`, endpoint url for Eth HTTP JSON-RPC server (host:port) |
|
| `eth-server-http-path` | `ETH_SERVER_HTTPPATH` | | If `eth-server-http` set to `true`, endpoint url for Eth HTTP JSON-RPC server (host:port) |
|
||||||
| `eth-server-ws` | `ETH_SERVER_WS` | false | If `true` enable Eth WS JSON-RPC Server |
|
| `eth-server-ws` | `ETH_SERVER_WS` | false | If `true` enable Eth WS JSON-RPC Server |
|
||||||
| `eth-server-ws-path` | `ETH_SERVER_WS_PATH` | | If `eth-server-ws` set to `true`, endpoint url for Eth WS JSON-RPC server (host:port) |
|
| `eth-server-ws-path` | `ETH_SERVER_WSPATH` | | If `eth-server-ws` set to `true`, endpoint url for Eth WS JSON-RPC server (host:port) |
|
||||||
| `eth-server-ipc` | `ETH_SERVER_IPC` | false | If `true` enable Eth IPC JSON-RPC Server |
|
| `eth-server-ipc` | `ETH_SERVER_IPC` | false | If `true` enable Eth IPC JSON-RPC Server |
|
||||||
| `eth-server-ipc-path` | `ETH_SERVER_IPC_PATH` | | If `eth-server-ws` set to `true`, path for Eth IPC JSON-RPC server |
|
| `eth-server-ipc-path` | `ETH_SERVER_IPC_PATH` | | If `eth-server-ws` set to `true`, path for Eth IPC JSON-RPC server |
|
||||||
| `ipld-server-graphql` | `IPLD_SERVER_GRAPHQL` | false | If `true` enable IPLD GraphQL Server |
|
| `ipld-server-graphql` | `IPLD_SERVER_GRAPHQL` | false | If `true` enable IPLD GraphQL Server |
|
||||||
|
16
chain.json
Normal file
16
chain.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"chainId": 4,
|
||||||
|
"homesteadBlock": 1,
|
||||||
|
"eip150Block": 2,
|
||||||
|
"eip150Hash": "0x9b095b36c15eaf13044373aef8ee0bd3a382a5abb92e402afa44b8249c3a90e9",
|
||||||
|
"eip155Block": 3,
|
||||||
|
"eip158Block": 3,
|
||||||
|
"byzantiumBlock": 3,
|
||||||
|
"constantinopleBlock": 3,
|
||||||
|
"petersburgBlock": 3,
|
||||||
|
"istanbulBlock": 3,
|
||||||
|
"clique": {
|
||||||
|
"period": 15,
|
||||||
|
"epoch": 30000
|
||||||
|
}
|
||||||
|
}
|
14
docker-compose.test.yml
Normal file
14
docker-compose.test.yml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
version: '3.2'
|
||||||
|
|
||||||
|
services:
|
||||||
|
contract:
|
||||||
|
depends_on:
|
||||||
|
- dapptools
|
||||||
|
build:
|
||||||
|
context: ./test/contract
|
||||||
|
args:
|
||||||
|
ETH_ADDR: "http://dapptools:8545"
|
||||||
|
environment:
|
||||||
|
ETH_ADDR: "http://dapptools:8545"
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:3000:3000"
|
@ -20,7 +20,7 @@ services:
|
|||||||
restart: on-failure
|
restart: on-failure
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
image: vulcanize/statediff-migrations:v0.3.0
|
image: vulcanize/statediff-migrations:v0.4.0
|
||||||
environment:
|
environment:
|
||||||
DATABASE_USER: vdbm
|
DATABASE_USER: vdbm
|
||||||
DATABASE_NAME: vulcanize_public
|
DATABASE_NAME: vulcanize_public
|
||||||
@ -41,6 +41,7 @@ services:
|
|||||||
- "127.0.0.1:8077:5432"
|
- "127.0.0.1:8077:5432"
|
||||||
|
|
||||||
eth-server:
|
eth-server:
|
||||||
|
restart: unless-stopped
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
build:
|
build:
|
||||||
@ -49,16 +50,22 @@ services:
|
|||||||
- alpine:latest
|
- alpine:latest
|
||||||
- golang:1.13-alpine
|
- golang:1.13-alpine
|
||||||
environment:
|
environment:
|
||||||
|
IPLD_SERVER_GRAPHQL: "true"
|
||||||
|
IPLD_POSTGRAPHILEPATH: http://graphql:5000
|
||||||
|
ETH_SERVER_HTTPPATH: 0.0.0.0:8081
|
||||||
VDB_COMMAND: "serve"
|
VDB_COMMAND: "serve"
|
||||||
|
ETH_CHAIN_CONFIG: "/tmp/chain.json"
|
||||||
DATABASE_NAME: "vulcanize_public"
|
DATABASE_NAME: "vulcanize_public"
|
||||||
DATABASE_HOSTNAME: "db"
|
DATABASE_HOSTNAME: "db"
|
||||||
DATABASE_PORT: 5432
|
DATABASE_PORT: 5432
|
||||||
DATABASE_USER: "vdbm"
|
DATABASE_USER: "vdbm"
|
||||||
DATABASE_PASSWORD: "password"
|
DATABASE_PASSWORD: "password"
|
||||||
SERVER_WS_PATH: "0.0.0.0:8081"
|
ETH_CHAIN_ID: 4
|
||||||
SERVER_HTTP_PATH: "0.0.0.0:8082"
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ./chain.json
|
||||||
|
target: /tmp/chain.json
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:8080:8080"
|
|
||||||
- "127.0.0.1:8081:8081"
|
- "127.0.0.1:8081:8081"
|
||||||
|
|
||||||
graphql:
|
graphql:
|
||||||
|
@ -18,9 +18,11 @@ package eth
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
"time"
|
"time"
|
||||||
@ -38,7 +40,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/statediff"
|
"github.com/ethereum/go-ethereum/statediff"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-indexer/pkg/eth"
|
|
||||||
"github.com/vulcanize/ipld-eth-server/pkg/shared"
|
"github.com/vulcanize/ipld-eth-server/pkg/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -167,6 +168,21 @@ func (pea *PublicEthAPI) GetBlockByHash(ctx context.Context, hash common.Hash, f
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChainId is the EIP-155 replay-protection chain id for the current ethereum chain config.
|
||||||
|
func (pea *PublicEthAPI) ChainId() hexutil.Uint64 {
|
||||||
|
chainID := new(big.Int)
|
||||||
|
block, err := pea.B.CurrentBlock()
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf("ChainId failed with err %s", err.Error())
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if config := pea.B.Config.ChainConfig; config.IsEIP155(block.Number()) {
|
||||||
|
chainID = config.ChainID
|
||||||
|
}
|
||||||
|
return (hexutil.Uint64)(chainID.Uint64())
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Uncles
|
Uncles
|
||||||
@ -440,6 +456,14 @@ func (pea *PublicEthAPI) localGetTransactionReceipt(ctx context.Context, hash co
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
block, err := pea.B.BlockByHash(ctx, blockHash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = receipts.DeriveFields(pea.B.Config.ChainConfig, blockHash, blockNumber, block.Transactions())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if len(receipts) <= int(index) {
|
if len(receipts) <= int(index) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@ -525,9 +549,11 @@ func (pea *PublicEthAPI) localGetLogs(crit filters.FilterCriteria) ([]*types.Log
|
|||||||
for i, addr := range crit.Addresses {
|
for i, addr := range crit.Addresses {
|
||||||
addrStrs[i] = addr.String()
|
addrStrs[i] = addr.String()
|
||||||
}
|
}
|
||||||
topicStrSets := make([][]string, 4)
|
|
||||||
|
topicStrSets := make([][]string, len(crit.Topics))
|
||||||
for i, topicSet := range crit.Topics {
|
for i, topicSet := range crit.Topics {
|
||||||
if i > 3 {
|
if i > 3 {
|
||||||
|
topicStrSets = topicStrSets[:4]
|
||||||
// don't allow more than 4 topics
|
// don't allow more than 4 topics
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -569,8 +595,13 @@ func (pea *PublicEthAPI) localGetLogs(crit filters.FilterCriteria) ([]*types.Log
|
|||||||
if err := tx.Commit(); err != nil {
|
if err := tx.Commit(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return extractLogsOfInterest(rctIPLDs, filter.Topics)
|
block, err := pea.B.BlockByHash(context.Background(), *crit.BlockHash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return extractLogsOfInterest(pea.B.Config.ChainConfig, *crit.BlockHash, block.NumberU64(), block.Transactions(), rctIPLDs, filter)
|
||||||
|
}
|
||||||
|
|
||||||
// Otherwise, create block range from criteria
|
// Otherwise, create block range from criteria
|
||||||
// nil values are filled in; to request a single block have both ToBlock and FromBlock equal that number
|
// nil values are filled in; to request a single block have both ToBlock and FromBlock equal that number
|
||||||
startingBlock := crit.FromBlock
|
startingBlock := crit.FromBlock
|
||||||
@ -578,6 +609,7 @@ func (pea *PublicEthAPI) localGetLogs(crit filters.FilterCriteria) ([]*types.Log
|
|||||||
if startingBlock == nil {
|
if startingBlock == nil {
|
||||||
startingBlock = common.Big0
|
startingBlock = common.Big0
|
||||||
}
|
}
|
||||||
|
|
||||||
if endingBlock == nil {
|
if endingBlock == nil {
|
||||||
endingBlockInt, err := pea.B.Retriever.RetrieveLastBlockNumber()
|
endingBlockInt, err := pea.B.Retriever.RetrieveLastBlockNumber()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -585,24 +617,38 @@ func (pea *PublicEthAPI) localGetLogs(crit filters.FilterCriteria) ([]*types.Log
|
|||||||
}
|
}
|
||||||
endingBlock = big.NewInt(endingBlockInt)
|
endingBlock = big.NewInt(endingBlockInt)
|
||||||
}
|
}
|
||||||
|
|
||||||
start := startingBlock.Int64()
|
start := startingBlock.Int64()
|
||||||
end := endingBlock.Int64()
|
end := endingBlock.Int64()
|
||||||
allRctCIDs := make([]eth.ReceiptModel, 0)
|
var logs []*types.Log
|
||||||
for i := start; i <= end; i++ {
|
for i := start; i <= end; i++ {
|
||||||
rctCIDs, err := pea.B.Retriever.RetrieveRctCIDs(tx, filter, i, nil, nil)
|
rctCIDs, err := pea.B.Retriever.RetrieveRctCIDs(tx, filter, i, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
allRctCIDs = append(allRctCIDs, rctCIDs...)
|
|
||||||
}
|
block, err := pea.B.BlockByNumber(context.Background(), rpc.BlockNumber(i))
|
||||||
rctIPLDs, err := pea.B.Fetcher.FetchRcts(tx, allRctCIDs)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rctIPLDs, err := pea.B.Fetcher.FetchRcts(tx, rctCIDs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log, err := extractLogsOfInterest(pea.B.Config.ChainConfig, block.Hash(), uint64(i), block.Transactions(), rctIPLDs, filter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
logs = append(logs, log...)
|
||||||
|
}
|
||||||
|
|
||||||
if err := tx.Commit(); err != nil {
|
if err := tx.Commit(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
logs, err := extractLogsOfInterest(rctIPLDs, filter.Topics)
|
|
||||||
return logs, err // need to return err variable so that we return the err = tx.Commit() assignment in the defer
|
return logs, err // need to return err variable so that we return the err = tx.Commit() assignment in the defer
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -627,6 +673,10 @@ func (pea *PublicEthAPI) GetBalance(ctx context.Context, address common.Address,
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return (*hexutil.Big)(big.NewInt(0)), nil
|
||||||
|
}
|
||||||
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -644,7 +694,17 @@ func (pea *PublicEthAPI) localGetBalance(ctx context.Context, address common.Add
|
|||||||
func (pea *PublicEthAPI) GetStorageAt(ctx context.Context, address common.Address, key string, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
|
func (pea *PublicEthAPI) GetStorageAt(ctx context.Context, address common.Address, key string, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
|
||||||
storageVal, err := pea.B.GetStorageByNumberOrHash(ctx, address, common.HexToHash(key), blockNrOrHash)
|
storageVal, err := pea.B.GetStorageByNumberOrHash(ctx, address, common.HexToHash(key), blockNrOrHash)
|
||||||
if storageVal != nil && err == nil {
|
if storageVal != nil && err == nil {
|
||||||
return storageVal, nil
|
var value common.Hash
|
||||||
|
_, content, _, err := rlp.Split(storageVal)
|
||||||
|
if err == io.ErrUnexpectedEOF {
|
||||||
|
return hexutil.Bytes{}, nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
value.SetBytes(content)
|
||||||
|
|
||||||
|
return value[:], nil
|
||||||
}
|
}
|
||||||
if pea.rpc != nil {
|
if pea.rpc != nil {
|
||||||
var res hexutil.Bytes
|
var res hexutil.Bytes
|
||||||
@ -653,6 +713,9 @@ func (pea *PublicEthAPI) GetStorageAt(ctx context.Context, address common.Addres
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return make([]byte, 32), nil
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -669,6 +732,10 @@ func (pea *PublicEthAPI) GetCode(ctx context.Context, address common.Address, bl
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return code, nil
|
||||||
|
}
|
||||||
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,13 +18,16 @@ package eth_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"math/big"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth/filters"
|
"github.com/ethereum/go-ethereum/eth/filters"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
@ -168,7 +171,7 @@ var (
|
|||||||
"to": expectedTransaction3.To,
|
"to": expectedTransaction3.To,
|
||||||
"gasUsed": hexutil.Uint64(test_helpers.MockReceipts[2].GasUsed),
|
"gasUsed": hexutil.Uint64(test_helpers.MockReceipts[2].GasUsed),
|
||||||
"cumulativeGasUsed": hexutil.Uint64(test_helpers.MockReceipts[2].CumulativeGasUsed),
|
"cumulativeGasUsed": hexutil.Uint64(test_helpers.MockReceipts[2].CumulativeGasUsed),
|
||||||
"contractAddress": nil,
|
"contractAddress": test_helpers.ContractAddress,
|
||||||
"logs": test_helpers.MockReceipts[2].Logs,
|
"logs": test_helpers.MockReceipts[2].Logs,
|
||||||
"logsBloom": test_helpers.MockReceipts[2].Bloom,
|
"logsBloom": test_helpers.MockReceipts[2].Bloom,
|
||||||
"root": hexutil.Bytes(test_helpers.MockReceipts[2].PostState),
|
"root": hexutil.Bytes(test_helpers.MockReceipts[2].PostState),
|
||||||
@ -179,6 +182,7 @@ var _ = Describe("API", func() {
|
|||||||
var (
|
var (
|
||||||
db *postgres.DB
|
db *postgres.DB
|
||||||
api *eth.PublicEthAPI
|
api *eth.PublicEthAPI
|
||||||
|
chainConfig = params.TestChainConfig
|
||||||
)
|
)
|
||||||
// Test db setup, rather than using BeforeEach we only need to setup once since the tests do not mutate the database
|
// Test db setup, rather than using BeforeEach we only need to setup once since the tests do not mutate the database
|
||||||
// Note: if you focus one of the tests be sure to focus this and the defered It()
|
// Note: if you focus one of the tests be sure to focus this and the defered It()
|
||||||
@ -187,7 +191,11 @@ var _ = Describe("API", func() {
|
|||||||
db, err = shared.SetupDB()
|
db, err = shared.SetupDB()
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
indexAndPublisher := eth2.NewIPLDPublisher(db)
|
indexAndPublisher := eth2.NewIPLDPublisher(db)
|
||||||
backend, err := eth.NewEthBackend(db, ð.Config{})
|
backend, err := eth.NewEthBackend(db, ð.Config{
|
||||||
|
ChainConfig: chainConfig,
|
||||||
|
VmConfig: vm.Config{},
|
||||||
|
RPCGasCap: big.NewInt(10000000000), // Max gas capacity for a rpc call.
|
||||||
|
})
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
api = eth.NewPublicEthAPI(backend, nil, false)
|
api = eth.NewPublicEthAPI(backend, nil, false)
|
||||||
err = indexAndPublisher.Publish(test_helpers.MockConvertedPayload)
|
err = indexAndPublisher.Publish(test_helpers.MockConvertedPayload)
|
||||||
@ -271,10 +279,10 @@ var _ = Describe("API", func() {
|
|||||||
Expect(val).To(Equal(block[key]))
|
Expect(val).To(Equal(block[key]))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
It("Throws an error if a block cannot be found", func() {
|
It("Returns `nil` if a block cannot be found", func() {
|
||||||
_, err := api.GetBlockByNumber(ctx, wrongNumber, false)
|
block, err := api.GetBlockByNumber(ctx, wrongNumber, false)
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(err.Error()).To(ContainSubstring("sql: no rows in result set"))
|
Expect(block).To(BeNil())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -303,10 +311,10 @@ var _ = Describe("API", func() {
|
|||||||
Expect(val).To(Equal(block[key]))
|
Expect(val).To(Equal(block[key]))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
It("Throws an error if a block cannot be found", func() {
|
It("Returns `nil` if a block cannot be found", func() {
|
||||||
_, err := api.GetBlockByHash(ctx, randomHash, false)
|
block, err := api.GetBlockByHash(ctx, randomHash, false)
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(err.Error()).To(ContainSubstring("sql: no rows in result set"))
|
Expect(block).To(BeZero())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -325,10 +333,10 @@ var _ = Describe("API", func() {
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(uncle2).To(Equal(expectedUncle2))
|
Expect(uncle2).To(Equal(expectedUncle2))
|
||||||
})
|
})
|
||||||
It("Throws an error if an block for blocknumber cannot be found", func() {
|
It("Returns `nil` if an block for block number cannot be found", func() {
|
||||||
_, err := api.GetUncleByBlockNumberAndIndex(ctx, wrongNumber, 0)
|
block, err := api.GetUncleByBlockNumberAndIndex(ctx, wrongNumber, 0)
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(err.Error()).To(ContainSubstring("sql: no rows in result set"))
|
Expect(block).To(BeNil())
|
||||||
})
|
})
|
||||||
It("Returns `nil` if an uncle at the provided index does not exist for the block found for the provided block number", func() {
|
It("Returns `nil` if an uncle at the provided index does not exist for the block found for the provided block number", func() {
|
||||||
uncle, err := api.GetUncleByBlockNumberAndIndex(ctx, number, 2)
|
uncle, err := api.GetUncleByBlockNumberAndIndex(ctx, number, 2)
|
||||||
@ -346,10 +354,10 @@ var _ = Describe("API", func() {
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(uncle2).To(Equal(expectedUncle2))
|
Expect(uncle2).To(Equal(expectedUncle2))
|
||||||
})
|
})
|
||||||
It("Throws an error if an block for blockhash cannot be found", func() {
|
It("Returns `nil` if a block for blockhash cannot be found", func() {
|
||||||
_, err := api.GetUncleByBlockHashAndIndex(ctx, randomHash, 0)
|
block, err := api.GetUncleByBlockHashAndIndex(ctx, randomHash, 0)
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(err.Error()).To(ContainSubstring("sql: no rows in result set"))
|
Expect(block).To(BeNil())
|
||||||
})
|
})
|
||||||
It("Returns `nil` if an uncle at the provided index does not exist for the block with the provided hash", func() {
|
It("Returns `nil` if an uncle at the provided index does not exist for the block with the provided hash", func() {
|
||||||
uncle, err := api.GetUncleByBlockHashAndIndex(ctx, blockHash, 2)
|
uncle, err := api.GetUncleByBlockHashAndIndex(ctx, blockHash, 2)
|
||||||
@ -361,6 +369,7 @@ var _ = Describe("API", func() {
|
|||||||
Describe("eth_getUncleCountByBlockNumber", func() {
|
Describe("eth_getUncleCountByBlockNumber", func() {
|
||||||
It("Retrieves the number of uncles for the canonical block with the provided number", func() {
|
It("Retrieves the number of uncles for the canonical block with the provided number", func() {
|
||||||
count := api.GetUncleCountByBlockNumber(ctx, number)
|
count := api.GetUncleCountByBlockNumber(ctx, number)
|
||||||
|
Expect(*count).NotTo(Equal(nil))
|
||||||
Expect(uint64(*count)).To(Equal(uint64(2)))
|
Expect(uint64(*count)).To(Equal(uint64(2)))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -368,6 +377,7 @@ var _ = Describe("API", func() {
|
|||||||
Describe("eth_getUncleCountByBlockHash", func() {
|
Describe("eth_getUncleCountByBlockHash", func() {
|
||||||
It("Retrieves the number of uncles for the block with the provided hash", func() {
|
It("Retrieves the number of uncles for the block with the provided hash", func() {
|
||||||
count := api.GetUncleCountByBlockHash(ctx, blockHash)
|
count := api.GetUncleCountByBlockHash(ctx, blockHash)
|
||||||
|
Expect(*count).NotTo(Equal(nil))
|
||||||
Expect(uint64(*count)).To(Equal(uint64(2)))
|
Expect(uint64(*count)).To(Equal(uint64(2)))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -948,8 +958,17 @@ var _ = Describe("API", func() {
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
||||||
})
|
})
|
||||||
It("Throws an error for an account it cannot find the balance for", func() {
|
It("Retrieves the eth balance for the non-existing account address at the block with the provided hash", func() {
|
||||||
_, err := api.GetBalance(ctx, randomAddr, rpc.BlockNumberOrHashWithHash(blockHash, true))
|
bal, err := api.GetBalance(ctx, randomAddr, rpc.BlockNumberOrHashWithHash(blockHash, true))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
||||||
|
})
|
||||||
|
It("Throws an error for an account of a non-existing block hash", func() {
|
||||||
|
_, err := api.GetBalance(ctx, test_helpers.AccountAddresss, rpc.BlockNumberOrHashWithHash(randomHash, true))
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("Throws an error for an account of a non-existing block number", func() {
|
||||||
|
_, err := api.GetBalance(ctx, test_helpers.AccountAddresss, rpc.BlockNumberOrHashWithNumber(wrongNumber))
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).To(HaveOccurred())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -965,9 +984,10 @@ var _ = Describe("API", func() {
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(code).To(Equal((hexutil.Bytes)(test_helpers.ContractCode)))
|
Expect(code).To(Equal((hexutil.Bytes)(test_helpers.ContractCode)))
|
||||||
})
|
})
|
||||||
It("Throws an error for an account it cannot find the code for", func() {
|
It("Returns `nil` for an account it cannot find the code for", func() {
|
||||||
_, err := api.GetCode(ctx, randomAddr, rpc.BlockNumberOrHashWithHash(blockHash, true))
|
code, err := api.GetCode(ctx, randomAddr, rpc.BlockNumberOrHashWithHash(blockHash, true))
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(code).To(BeEmpty())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -18,6 +18,7 @@ package eth
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
@ -50,6 +51,8 @@ import (
|
|||||||
var (
|
var (
|
||||||
errPendingBlockNumber = errors.New("pending block number not supported")
|
errPendingBlockNumber = errors.New("pending block number not supported")
|
||||||
errNegativeBlockNumber = errors.New("negative block number not supported")
|
errNegativeBlockNumber = errors.New("negative block number not supported")
|
||||||
|
errHeaderHashNotFound = errors.New("header for hash not found")
|
||||||
|
errHeaderNotFound = errors.New("header not found")
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -201,9 +204,9 @@ func (b *Backend) GetTd(blockHash common.Hash) (*big.Int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CurrentBlock returns the current block
|
// CurrentBlock returns the current block
|
||||||
func (b *Backend) CurrentBlock() *types.Block {
|
func (b *Backend) CurrentBlock() (*types.Block, error) {
|
||||||
block, _ := b.BlockByNumber(context.Background(), rpc.LatestBlockNumber)
|
block, err := b.BlockByNumber(context.Background(), rpc.LatestBlockNumber)
|
||||||
return block
|
return block, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockByNumberOrHash returns block by number or hash
|
// BlockByNumberOrHash returns block by number or hash
|
||||||
@ -263,12 +266,18 @@ func (b *Backend) BlockByNumber(ctx context.Context, blockNumber rpc.BlockNumber
|
|||||||
// Get the canonical hash
|
// Get the canonical hash
|
||||||
canonicalHash, err := b.GetCanonicalHash(uint64(number))
|
canonicalHash, err := b.GetCanonicalHash(uint64(number))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Retrieve all the CIDs for the block
|
// Retrieve all the CIDs for the block
|
||||||
// TODO: optimize this by retrieving iplds directly rather than the cids first (this is remanent from when we fetched iplds through ipfs blockservice interface)
|
// TODO: optimize this by retrieving iplds directly rather than the cids first (this is remanent from when we fetched iplds through ipfs blockservice interface)
|
||||||
headerCID, uncleCIDs, txCIDs, rctCIDs, err := b.Retriever.RetrieveBlockByHash(canonicalHash)
|
headerCID, uncleCIDs, txCIDs, rctCIDs, err := b.Retriever.RetrieveBlockByHash(canonicalHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,6 +300,9 @@ func (b *Backend) BlockByNumber(ctx context.Context, blockNumber rpc.BlockNumber
|
|||||||
// Fetch and decode the header IPLD
|
// Fetch and decode the header IPLD
|
||||||
headerIPLD, err := b.Fetcher.FetchHeader(tx, headerCID)
|
headerIPLD, err := b.Fetcher.FetchHeader(tx, headerCID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var header types.Header
|
var header types.Header
|
||||||
@ -346,6 +358,9 @@ func (b *Backend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Blo
|
|||||||
// Retrieve all the CIDs for the block
|
// Retrieve all the CIDs for the block
|
||||||
headerCID, uncleCIDs, txCIDs, rctCIDs, err := b.Retriever.RetrieveBlockByHash(hash)
|
headerCID, uncleCIDs, txCIDs, rctCIDs, err := b.Retriever.RetrieveBlockByHash(hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,6 +383,9 @@ func (b *Backend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Blo
|
|||||||
// Fetch and decode the header IPLD
|
// Fetch and decode the header IPLD
|
||||||
headerIPLD, err := b.Fetcher.FetchHeader(tx, headerCID)
|
headerIPLD, err := b.Fetcher.FetchHeader(tx, headerCID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var header types.Header
|
var header types.Header
|
||||||
@ -377,6 +395,9 @@ func (b *Backend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Blo
|
|||||||
// Fetch and decode the uncle IPLDs
|
// Fetch and decode the uncle IPLDs
|
||||||
uncleIPLDs, err := b.Fetcher.FetchUncles(tx, uncleCIDs)
|
uncleIPLDs, err := b.Fetcher.FetchUncles(tx, uncleCIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var uncles []*types.Header
|
var uncles []*types.Header
|
||||||
@ -390,6 +411,9 @@ func (b *Backend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Blo
|
|||||||
// Fetch and decode the transaction IPLDs
|
// Fetch and decode the transaction IPLDs
|
||||||
txIPLDs, err := b.Fetcher.FetchTrxs(tx, txCIDs)
|
txIPLDs, err := b.Fetcher.FetchTrxs(tx, txCIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var transactions []*types.Transaction
|
var transactions []*types.Transaction
|
||||||
@ -403,6 +427,9 @@ func (b *Backend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Blo
|
|||||||
// Fetch and decode the receipt IPLDs
|
// Fetch and decode the receipt IPLDs
|
||||||
rctIPLDs, err := b.Fetcher.FetchRcts(tx, rctCIDs)
|
rctIPLDs, err := b.Fetcher.FetchRcts(tx, rctCIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var receipts []*types.Receipt
|
var receipts []*types.Receipt
|
||||||
@ -545,7 +572,7 @@ func (b *Backend) GetEVM(ctx context.Context, msg core.Message, state *state.Sta
|
|||||||
// GetAccountByNumberOrHash returns the account object for the provided address at the block corresponding to the provided number or hash
|
// GetAccountByNumberOrHash returns the account object for the provided address at the block corresponding to the provided number or hash
|
||||||
func (b *Backend) GetAccountByNumberOrHash(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*state.Account, error) {
|
func (b *Backend) GetAccountByNumberOrHash(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*state.Account, error) {
|
||||||
if blockNr, ok := blockNrOrHash.Number(); ok {
|
if blockNr, ok := blockNrOrHash.Number(); ok {
|
||||||
return b.GetAccountByNumber(ctx, address, uint64(blockNr.Int64()))
|
return b.GetAccountByNumber(ctx, address, blockNr)
|
||||||
}
|
}
|
||||||
if hash, ok := blockNrOrHash.Hash(); ok {
|
if hash, ok := blockNrOrHash.Hash(); ok {
|
||||||
return b.GetAccountByHash(ctx, address, hash)
|
return b.GetAccountByHash(ctx, address, hash)
|
||||||
@ -554,23 +581,48 @@ func (b *Backend) GetAccountByNumberOrHash(ctx context.Context, address common.A
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetAccountByNumber returns the account object for the provided address at the canonical block at the provided height
|
// GetAccountByNumber returns the account object for the provided address at the canonical block at the provided height
|
||||||
func (b *Backend) GetAccountByNumber(ctx context.Context, address common.Address, number uint64) (*state.Account, error) {
|
func (b *Backend) GetAccountByNumber(ctx context.Context, address common.Address, blockNumber rpc.BlockNumber) (*state.Account, error) {
|
||||||
hash, err := b.GetCanonicalHash(number)
|
var err error
|
||||||
|
number := blockNumber.Int64()
|
||||||
|
if blockNumber == rpc.LatestBlockNumber {
|
||||||
|
number, err = b.Retriever.RetrieveLastBlockNumber()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if hash == (common.Hash{}) {
|
|
||||||
return nil, fmt.Errorf("no canoncial block hash found for provided height (%d)", number)
|
|
||||||
}
|
}
|
||||||
|
if blockNumber == rpc.EarliestBlockNumber {
|
||||||
|
number, err = b.Retriever.RetrieveFirstBlockNumber()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if blockNumber == rpc.PendingBlockNumber {
|
||||||
|
return nil, errPendingBlockNumber
|
||||||
|
}
|
||||||
|
hash, err := b.GetCanonicalHash(uint64(number))
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, errHeaderNotFound
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return b.GetAccountByHash(ctx, address, hash)
|
return b.GetAccountByHash(ctx, address, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAccountByHash returns the account object for the provided address at the block with the provided hash
|
// GetAccountByHash returns the account object for the provided address at the block with the provided hash
|
||||||
func (b *Backend) GetAccountByHash(ctx context.Context, address common.Address, hash common.Hash) (*state.Account, error) {
|
func (b *Backend) GetAccountByHash(ctx context.Context, address common.Address, hash common.Hash) (*state.Account, error) {
|
||||||
|
_, err := b.HeaderByHash(context.Background(), hash)
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, errHeaderHashNotFound
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
_, accountRlp, err := b.IPLDRetriever.RetrieveAccountByAddressAndBlockHash(address, hash)
|
_, accountRlp, err := b.IPLDRetriever.RetrieveAccountByAddressAndBlockHash(address, hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
acct := new(state.Account)
|
acct := new(state.Account)
|
||||||
return acct, rlp.DecodeBytes(accountRlp, acct)
|
return acct, rlp.DecodeBytes(accountRlp, acct)
|
||||||
}
|
}
|
||||||
@ -578,7 +630,7 @@ func (b *Backend) GetAccountByHash(ctx context.Context, address common.Address,
|
|||||||
// GetCodeByNumberOrHash returns the byte code for the contract deployed at the provided address at the block with the provided hash or block number
|
// GetCodeByNumberOrHash returns the byte code for the contract deployed at the provided address at the block with the provided hash or block number
|
||||||
func (b *Backend) GetCodeByNumberOrHash(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) ([]byte, error) {
|
func (b *Backend) GetCodeByNumberOrHash(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) ([]byte, error) {
|
||||||
if blockNr, ok := blockNrOrHash.Number(); ok {
|
if blockNr, ok := blockNrOrHash.Number(); ok {
|
||||||
return b.GetCodeByNumber(ctx, address, uint64(blockNr.Int64()))
|
return b.GetCodeByNumber(ctx, address, blockNr)
|
||||||
}
|
}
|
||||||
if hash, ok := blockNrOrHash.Hash(); ok {
|
if hash, ok := blockNrOrHash.Hash(); ok {
|
||||||
return b.GetCodeByHash(ctx, address, hash)
|
return b.GetCodeByHash(ctx, address, hash)
|
||||||
@ -587,8 +639,25 @@ func (b *Backend) GetCodeByNumberOrHash(ctx context.Context, address common.Addr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetCodeByNumber returns the byte code for the contract deployed at the provided address at the canonical block with the provided block number
|
// GetCodeByNumber returns the byte code for the contract deployed at the provided address at the canonical block with the provided block number
|
||||||
func (b *Backend) GetCodeByNumber(ctx context.Context, address common.Address, number uint64) ([]byte, error) {
|
func (b *Backend) GetCodeByNumber(ctx context.Context, address common.Address, blockNumber rpc.BlockNumber) ([]byte, error) {
|
||||||
hash, err := b.GetCanonicalHash(number)
|
var err error
|
||||||
|
number := blockNumber.Int64()
|
||||||
|
if blockNumber == rpc.LatestBlockNumber {
|
||||||
|
number, err = b.Retriever.RetrieveLastBlockNumber()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if blockNumber == rpc.EarliestBlockNumber {
|
||||||
|
number, err = b.Retriever.RetrieveFirstBlockNumber()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if blockNumber == rpc.PendingBlockNumber {
|
||||||
|
return nil, errPendingBlockNumber
|
||||||
|
}
|
||||||
|
hash, err := b.GetCanonicalHash(uint64(number))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -630,31 +699,55 @@ func (b *Backend) GetCodeByHash(ctx context.Context, address common.Address, has
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetStorageByNumberOrHash returns the storage value for the provided contract address an storage key at the block corresponding to the provided number or hash
|
// GetStorageByNumberOrHash returns the storage value for the provided contract address an storage key at the block corresponding to the provided number or hash
|
||||||
func (b *Backend) GetStorageByNumberOrHash(ctx context.Context, address common.Address, storageLeafKey common.Hash, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
|
func (b *Backend) GetStorageByNumberOrHash(ctx context.Context, address common.Address, key common.Hash, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
|
||||||
if blockNr, ok := blockNrOrHash.Number(); ok {
|
if blockNr, ok := blockNrOrHash.Number(); ok {
|
||||||
return b.GetStorageByNumber(ctx, address, storageLeafKey, uint64(blockNr.Int64()))
|
return b.GetStorageByNumber(ctx, address, key, blockNr)
|
||||||
}
|
}
|
||||||
if hash, ok := blockNrOrHash.Hash(); ok {
|
if hash, ok := blockNrOrHash.Hash(); ok {
|
||||||
return b.GetStorageByHash(ctx, address, storageLeafKey, hash)
|
return b.GetStorageByHash(ctx, address, key, hash)
|
||||||
}
|
}
|
||||||
return nil, errors.New("invalid arguments; neither block nor hash specified")
|
return nil, errors.New("invalid arguments; neither block nor hash specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStorageByNumber returns the storage value for the provided contract address an storage key at the block corresponding to the provided number
|
// GetStorageByNumber returns the storage value for the provided contract address an storage key at the block corresponding to the provided number
|
||||||
func (b *Backend) GetStorageByNumber(ctx context.Context, address common.Address, storageLeafKey common.Hash, number uint64) (hexutil.Bytes, error) {
|
func (b *Backend) GetStorageByNumber(ctx context.Context, address common.Address, key common.Hash, blockNumber rpc.BlockNumber) (hexutil.Bytes, error) {
|
||||||
hash, err := b.GetCanonicalHash(number)
|
var err error
|
||||||
|
number := blockNumber.Int64()
|
||||||
|
if blockNumber == rpc.LatestBlockNumber {
|
||||||
|
number, err = b.Retriever.RetrieveLastBlockNumber()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if hash == (common.Hash{}) {
|
|
||||||
return nil, fmt.Errorf("no canoncial block hash found for provided height (%d)", number)
|
|
||||||
}
|
}
|
||||||
return b.GetStorageByHash(ctx, address, storageLeafKey, hash)
|
if blockNumber == rpc.EarliestBlockNumber {
|
||||||
|
number, err = b.Retriever.RetrieveFirstBlockNumber()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if blockNumber == rpc.PendingBlockNumber {
|
||||||
|
return nil, errPendingBlockNumber
|
||||||
|
}
|
||||||
|
hash, err := b.GetCanonicalHash(uint64(number))
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, errHeaderNotFound
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.GetStorageByHash(ctx, address, key, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStorageByHash returns the storage value for the provided contract address an storage key at the block corresponding to the provided hash
|
// GetStorageByHash returns the storage value for the provided contract address an storage key at the block corresponding to the provided hash
|
||||||
func (b *Backend) GetStorageByHash(ctx context.Context, address common.Address, storageLeafKey, hash common.Hash) (hexutil.Bytes, error) {
|
func (b *Backend) GetStorageByHash(ctx context.Context, address common.Address, key, hash common.Hash) (hexutil.Bytes, error) {
|
||||||
_, storageRlp, err := b.IPLDRetriever.RetrieveStorageAtByAddressAndStorageKeyAndBlockHash(address, storageLeafKey, hash)
|
_, err := b.HeaderByHash(context.Background(), hash)
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, errHeaderHashNotFound
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, storageRlp, err := b.IPLDRetriever.RetrieveStorageAtByAddressAndStorageSlotAndBlockHash(address, key, hash)
|
||||||
return storageRlp, err
|
return storageRlp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,12 +23,12 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum"
|
"github.com/ethereum/go-ethereum"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-indexer/pkg/ipfs"
|
"github.com/vulcanize/ipld-eth-indexer/pkg/ipfs"
|
||||||
)
|
)
|
||||||
@ -244,23 +244,91 @@ func newRPCTransactionFromBlockIndex(b *types.Block, index uint64) *RPCTransacti
|
|||||||
}
|
}
|
||||||
|
|
||||||
// extractLogsOfInterest returns logs from the receipt IPLD
|
// extractLogsOfInterest returns logs from the receipt IPLD
|
||||||
func extractLogsOfInterest(rctIPLDs []ipfs.BlockModel, wantedTopics [][]string) ([]*types.Log, error) {
|
func extractLogsOfInterest(config *params.ChainConfig, blockHash common.Hash, blockNumber uint64,
|
||||||
var logs []*types.Log
|
txs types.Transactions, rctIPLDs []ipfs.BlockModel, filter ReceiptFilter) ([]*types.Log, error) {
|
||||||
for _, rctIPLD := range rctIPLDs {
|
receipts := make(types.Receipts, len(rctIPLDs))
|
||||||
rctRLP := rctIPLD
|
|
||||||
var rct types.Receipt
|
for i, rctBytes := range rctIPLDs {
|
||||||
if err := rlp.DecodeBytes(rctRLP.Data, &rct); err != nil {
|
rct := new(types.Receipt)
|
||||||
|
if err := rlp.DecodeBytes(rctBytes.Data, rct); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, log := range rct.Logs {
|
receipts[i] = rct
|
||||||
if wanted := wantedLog(wantedTopics, log.Topics); wanted == true {
|
}
|
||||||
logs = append(logs, log)
|
|
||||||
}
|
err := receipts.DeriveFields(config, blockHash, blockNumber, txs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var unfilteredLogs []*types.Log
|
||||||
|
for _, receipt := range receipts {
|
||||||
|
unfilteredLogs = append(unfilteredLogs, receipt.Logs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
adders := make([]common.Address, len(filter.LogAddresses))
|
||||||
|
for i, addr := range filter.LogAddresses {
|
||||||
|
adders[i] = common.HexToAddress(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
topics := make([][]common.Hash, len(filter.Topics))
|
||||||
|
for i, v := range filter.Topics {
|
||||||
|
topics[i] = make([]common.Hash, len(v))
|
||||||
|
for j, topic := range v {
|
||||||
|
topics[i][j] = common.HexToHash(topic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logs := filterLogs(unfilteredLogs, nil, nil, adders, topics)
|
||||||
return logs, nil
|
return logs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func includes(addresses []common.Address, a common.Address) bool {
|
||||||
|
for _, addr := range addresses {
|
||||||
|
if addr == a {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// filterLogs creates a slice of logs matching the given criteria.
|
||||||
|
func filterLogs(logs []*types.Log, fromBlock, toBlock *big.Int, addresses []common.Address, topics [][]common.Hash) []*types.Log {
|
||||||
|
var ret []*types.Log
|
||||||
|
Logs:
|
||||||
|
for _, log := range logs {
|
||||||
|
if fromBlock != nil && fromBlock.Int64() >= 0 && fromBlock.Uint64() > log.BlockNumber {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if toBlock != nil && toBlock.Int64() >= 0 && toBlock.Uint64() < log.BlockNumber {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(addresses) > 0 && !includes(addresses, log.Address) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// If the to filtered topics is greater than the amount of topics in logs, skip.
|
||||||
|
if len(topics) > len(log.Topics) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for i, sub := range topics {
|
||||||
|
match := len(sub) == 0 // empty rule set == wildcard
|
||||||
|
for _, topic := range sub {
|
||||||
|
if log.Topics[i] == topic {
|
||||||
|
match = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !match {
|
||||||
|
continue Logs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = append(ret, log)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
// returns true if the log matches on the filter
|
// returns true if the log matches on the filter
|
||||||
func wantedLog(wantedTopics [][]string, actualTopics []common.Hash) bool {
|
func wantedLog(wantedTopics [][]string, actualTopics []common.Hash) bool {
|
||||||
// actualTopics will always have length <= 4
|
// actualTopics will always have length <= 4
|
||||||
|
@ -310,6 +310,14 @@ func (ecr *CIDRetriever) RetrieveRctCIDs(tx *sqlx.Tx, rctFilter ReceiptFilter, b
|
|||||||
args = append(args, blockHash.String())
|
args = append(args, blockHash.String())
|
||||||
id++
|
id++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add the below filters when we have log index in DB.
|
||||||
|
if true {
|
||||||
|
pgStr += ` ORDER BY transaction_cids.index`
|
||||||
|
receiptCids := make([]eth.ReceiptModel, 0)
|
||||||
|
return receiptCids, tx.Select(&receiptCids, pgStr, args...)
|
||||||
|
}
|
||||||
|
|
||||||
if len(rctFilter.LogAddresses) > 0 {
|
if len(rctFilter.LogAddresses) > 0 {
|
||||||
// Filter on log contract addresses if there are any
|
// Filter on log contract addresses if there are any
|
||||||
pgStr += fmt.Sprintf(` AND ((receipt_cids.log_contracts && $%d::VARCHAR(66)[]`, id)
|
pgStr += fmt.Sprintf(` AND ((receipt_cids.log_contracts && $%d::VARCHAR(66)[]`, id)
|
||||||
@ -371,6 +379,7 @@ func (ecr *CIDRetriever) RetrieveRctCIDs(tx *sqlx.Tx, rctFilter ReceiptFilter, b
|
|||||||
args = append(args, pq.Array(trxIds))
|
args = append(args, pq.Array(trxIds))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pgStr += ` ORDER BY transaction_cids.index`
|
pgStr += ` ORDER BY transaction_cids.index`
|
||||||
receiptCids := make([]eth.ReceiptModel, 0)
|
receiptCids := make([]eth.ReceiptModel, 0)
|
||||||
return receiptCids, tx.Select(&receiptCids, pgStr, args...)
|
return receiptCids, tx.Select(&receiptCids, pgStr, args...)
|
||||||
|
@ -237,6 +237,7 @@ var _ = Describe("Retriever", func() {
|
|||||||
Expect(empty).ToNot(BeTrue())
|
Expect(empty).ToNot(BeTrue())
|
||||||
Expect(len(cids)).To(Equal(1))
|
Expect(len(cids)).To(Equal(1))
|
||||||
Expect(cids[0].BlockNumber).To(Equal(test_helpers.MockCIDWrapper.BlockNumber))
|
Expect(cids[0].BlockNumber).To(Equal(test_helpers.MockCIDWrapper.BlockNumber))
|
||||||
|
|
||||||
expectedHeaderCID := test_helpers.MockCIDWrapper.Header
|
expectedHeaderCID := test_helpers.MockCIDWrapper.Header
|
||||||
expectedHeaderCID.ID = cids[0].Header.ID
|
expectedHeaderCID.ID = cids[0].Header.ID
|
||||||
expectedHeaderCID.NodeID = cids[0].Header.NodeID
|
expectedHeaderCID.NodeID = cids[0].Header.NodeID
|
||||||
@ -250,6 +251,7 @@ var _ = Describe("Retriever", func() {
|
|||||||
Expect(eth.ReceiptModelsContainsCID(cids[0].Receipts, test_helpers.MockCIDWrapper.Receipts[1].CID)).To(BeTrue())
|
Expect(eth.ReceiptModelsContainsCID(cids[0].Receipts, test_helpers.MockCIDWrapper.Receipts[1].CID)).To(BeTrue())
|
||||||
Expect(eth.ReceiptModelsContainsCID(cids[0].Receipts, test_helpers.MockCIDWrapper.Receipts[2].CID)).To(BeTrue())
|
Expect(eth.ReceiptModelsContainsCID(cids[0].Receipts, test_helpers.MockCIDWrapper.Receipts[2].CID)).To(BeTrue())
|
||||||
Expect(len(cids[0].StateNodes)).To(Equal(2))
|
Expect(len(cids[0].StateNodes)).To(Equal(2))
|
||||||
|
|
||||||
for _, stateNode := range cids[0].StateNodes {
|
for _, stateNode := range cids[0].StateNodes {
|
||||||
if stateNode.CID == test_helpers.State1CID.String() {
|
if stateNode.CID == test_helpers.State1CID.String() {
|
||||||
Expect(stateNode.StateKey).To(Equal(common.BytesToHash(test_helpers.ContractLeafKey).Hex()))
|
Expect(stateNode.StateKey).To(Equal(common.BytesToHash(test_helpers.ContractLeafKey).Hex()))
|
||||||
|
@ -38,7 +38,6 @@ import (
|
|||||||
eth2 "github.com/vulcanize/ipld-eth-indexer/pkg/eth"
|
eth2 "github.com/vulcanize/ipld-eth-indexer/pkg/eth"
|
||||||
"github.com/vulcanize/ipld-eth-indexer/pkg/postgres"
|
"github.com/vulcanize/ipld-eth-indexer/pkg/postgres"
|
||||||
"github.com/vulcanize/ipld-eth-indexer/pkg/shared"
|
"github.com/vulcanize/ipld-eth-indexer/pkg/shared"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
||||||
"github.com/vulcanize/ipld-eth-server/pkg/eth/test_helpers"
|
"github.com/vulcanize/ipld-eth-server/pkg/eth/test_helpers"
|
||||||
)
|
)
|
||||||
@ -60,6 +59,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var _ = Describe("eth state reading tests", func() {
|
var _ = Describe("eth state reading tests", func() {
|
||||||
|
const chainLength = 5
|
||||||
var (
|
var (
|
||||||
blocks []*types.Block
|
blocks []*types.Block
|
||||||
receipts []types.Receipts
|
receipts []types.Receipts
|
||||||
@ -80,13 +80,13 @@ var _ = Describe("eth state reading tests", func() {
|
|||||||
backend, err = eth.NewEthBackend(db, ð.Config{
|
backend, err = eth.NewEthBackend(db, ð.Config{
|
||||||
ChainConfig: chainConfig,
|
ChainConfig: chainConfig,
|
||||||
VmConfig: vm.Config{},
|
VmConfig: vm.Config{},
|
||||||
RPCGasCap: big.NewInt(10000000000),
|
RPCGasCap: big.NewInt(10000000000), // Max gas capacity for a rpc call.
|
||||||
})
|
})
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
api = eth.NewPublicEthAPI(backend, nil, false)
|
api = eth.NewPublicEthAPI(backend, nil, false)
|
||||||
|
|
||||||
// make the test blockchain (and state)
|
// make the test blockchain (and state)
|
||||||
blocks, receipts, chain = test_helpers.MakeChain(5, test_helpers.Genesis, test_helpers.TestChainGen)
|
blocks, receipts, chain = test_helpers.MakeChain(chainLength, test_helpers.Genesis, test_helpers.TestChainGen)
|
||||||
params := statediff.Params{
|
params := statediff.Params{
|
||||||
IntermediateStateNodes: true,
|
IntermediateStateNodes: true,
|
||||||
IntermediateStorageNodes: true,
|
IntermediateStorageNodes: true,
|
||||||
@ -234,12 +234,15 @@ var _ = Describe("eth state reading tests", func() {
|
|||||||
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(1))
|
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(1))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
||||||
_, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(1))
|
|
||||||
Expect(err).To(HaveOccurred())
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(1))
|
||||||
Expect(err.Error()).To(ContainSubstring("sql: no rows in result set"))
|
Expect(err).ToNot(HaveOccurred())
|
||||||
_, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(1))
|
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
||||||
Expect(err).To(HaveOccurred())
|
|
||||||
Expect(err.Error()).To(ContainSubstring("sql: no rows in result set"))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(1))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(1))
|
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(1))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock1))
|
Expect(bal).To(Equal(expectedBankBalanceBlock1))
|
||||||
@ -247,12 +250,15 @@ var _ = Describe("eth state reading tests", func() {
|
|||||||
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(2))
|
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(2))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(2))
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(2))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct2BalanceBlock2))
|
Expect(bal).To(Equal(expectedAcct2BalanceBlock2))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(2))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(2))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedContractBalance))
|
Expect(bal).To(Equal(expectedContractBalance))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(2))
|
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(2))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
||||||
@ -260,12 +266,15 @@ var _ = Describe("eth state reading tests", func() {
|
|||||||
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(3))
|
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(3))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(3))
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(3))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct2BalanceBlock3))
|
Expect(bal).To(Equal(expectedAcct2BalanceBlock3))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(3))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(3))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedContractBalance))
|
Expect(bal).To(Equal(expectedContractBalance))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(3))
|
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(3))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
||||||
@ -273,12 +282,15 @@ var _ = Describe("eth state reading tests", func() {
|
|||||||
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(4))
|
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(4))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(4))
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(4))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct2BalanceBlock4))
|
Expect(bal).To(Equal(expectedAcct2BalanceBlock4))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(4))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(4))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedContractBalance))
|
Expect(bal).To(Equal(expectedContractBalance))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(4))
|
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(4))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
||||||
@ -286,12 +298,15 @@ var _ = Describe("eth state reading tests", func() {
|
|||||||
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(5))
|
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(5))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct1BalanceBlock5))
|
Expect(bal).To(Equal(expectedAcct1BalanceBlock5))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(5))
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(5))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct2BalanceBlock4))
|
Expect(bal).To(Equal(expectedAcct2BalanceBlock4))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(5))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(5))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedContractBalance))
|
Expect(bal).To(Equal(expectedContractBalance))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(5))
|
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(5))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
||||||
@ -304,12 +319,15 @@ var _ = Describe("eth state reading tests", func() {
|
|||||||
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
||||||
_, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
|
|
||||||
Expect(err).To(HaveOccurred())
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
|
||||||
Expect(err.Error()).To(ContainSubstring("sql: no rows in result set"))
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
||||||
|
|
||||||
_, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
|
_, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(err.Error()).To(ContainSubstring("sql: no rows in result set"))
|
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock1))
|
Expect(bal).To(Equal(expectedBankBalanceBlock1))
|
||||||
@ -317,12 +335,15 @@ var _ = Describe("eth state reading tests", func() {
|
|||||||
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
Expect(bal).To(Equal(expectedAcct2BalanceBlock2))
|
Expect(bal).To(Equal(expectedAcct2BalanceBlock2))
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedContractBalance))
|
Expect(bal).To(Equal(expectedContractBalance))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
||||||
@ -330,12 +351,15 @@ var _ = Describe("eth state reading tests", func() {
|
|||||||
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct2BalanceBlock3))
|
Expect(bal).To(Equal(expectedAcct2BalanceBlock3))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedContractBalance))
|
Expect(bal).To(Equal(expectedContractBalance))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
||||||
@ -343,12 +367,15 @@ var _ = Describe("eth state reading tests", func() {
|
|||||||
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct2BalanceBlock4))
|
Expect(bal).To(Equal(expectedAcct2BalanceBlock4))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedContractBalance))
|
Expect(bal).To(Equal(expectedContractBalance))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
||||||
@ -356,37 +383,45 @@ var _ = Describe("eth state reading tests", func() {
|
|||||||
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct1BalanceBlock5))
|
Expect(bal).To(Equal(expectedAcct1BalanceBlock5))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct2BalanceBlock4))
|
Expect(bal).To(Equal(expectedAcct2BalanceBlock4))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedContractBalance))
|
Expect(bal).To(Equal(expectedContractBalance))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
||||||
})
|
})
|
||||||
It("Throws an error for an account it cannot find the balance for an account at the provided block number", func() {
|
It("Returns `0` for an account it cannot find the balance for an account at the provided block number", func() {
|
||||||
_, err := api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(0))
|
bal, err := api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(0))
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(err.Error()).To(ContainSubstring("sql: no rows in result set"))
|
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
||||||
_, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(0))
|
|
||||||
Expect(err).To(HaveOccurred())
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(0))
|
||||||
Expect(err.Error()).To(ContainSubstring("sql: no rows in result set"))
|
Expect(err).ToNot(HaveOccurred())
|
||||||
_, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(0))
|
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
||||||
Expect(err).To(HaveOccurred())
|
|
||||||
Expect(err.Error()).To(ContainSubstring("sql: no rows in result set"))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(0))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
||||||
})
|
})
|
||||||
It("Throws an error for an account it cannot find the balance for an account at the provided block hash", func() {
|
It("Returns `0` for an error for an account it cannot find the balance for an account at the provided block hash", func() {
|
||||||
_, err := api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
|
bal, err := api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(err.Error()).To(ContainSubstring("sql: no rows in result set"))
|
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
||||||
_, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
|
|
||||||
Expect(err).To(HaveOccurred())
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
|
||||||
Expect(err.Error()).To(ContainSubstring("sql: no rows in result set"))
|
Expect(err).ToNot(HaveOccurred())
|
||||||
_, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
|
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
||||||
Expect(err).To(HaveOccurred())
|
|
||||||
Expect(err.Error()).To(ContainSubstring("sql: no rows in result set"))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
||||||
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -409,52 +444,64 @@ var _ = Describe("eth state reading tests", func() {
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(code).To(Equal((hexutil.Bytes)(test_helpers.ContractCode)))
|
Expect(code).To(Equal((hexutil.Bytes)(test_helpers.ContractCode)))
|
||||||
})
|
})
|
||||||
It("Throws an error for an account it cannot find the code for", func() {
|
It("Returns `nil` for an account it cannot find the code for", func() {
|
||||||
_, err := api.GetCode(ctx, randomAddr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
|
code, err := api.GetCode(ctx, randomAddr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(code).To(BeEmpty())
|
||||||
})
|
})
|
||||||
It("Throws an error for a contract that doesn't exist at this hieght", func() {
|
It("Returns `nil` for a contract that doesn't exist at this height", func() {
|
||||||
_, err := api.GetCode(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(0))
|
code, err := api.GetCode(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(0))
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(code).To(BeEmpty())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("eth_getStorageAt", func() {
|
Describe("eth_getStorageAt", func() {
|
||||||
It("Throws an error if it tries to access a contract which does not exist", func() {
|
It("Returns empty slice if it tries to access a contract which does not exist", func() {
|
||||||
_, err := api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.ContractSlotKeyHash.Hex(), rpc.BlockNumberOrHashWithNumber(0))
|
storage, err := api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.ContractSlotKeyHash.Hex(), rpc.BlockNumberOrHashWithNumber(0))
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(err.Error()).To(ContainSubstring("sql: no rows in result set"))
|
Expect(storage).To(Equal(hexutil.Bytes(make([]byte, 32))))
|
||||||
|
|
||||||
_, err = api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.ContractSlotKeyHash.Hex(), rpc.BlockNumberOrHashWithNumber(1))
|
storage, err = api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.ContractSlotKeyHash.Hex(), rpc.BlockNumberOrHashWithNumber(1))
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(err.Error()).To(ContainSubstring("sql: no rows in result set"))
|
Expect(storage).To(Equal(hexutil.Bytes(make([]byte, 32))))
|
||||||
})
|
})
|
||||||
It("Throws an error if it tries to access a contract slot which does not exist", func() {
|
It("Returns empty slice if it tries to access a contract slot which does not exist", func() {
|
||||||
_, err := api.GetStorageAt(ctx, test_helpers.ContractAddr, randomHash.Hex(), rpc.BlockNumberOrHashWithNumber(2))
|
storage, err := api.GetStorageAt(ctx, test_helpers.ContractAddr, randomHash.Hex(), rpc.BlockNumberOrHashWithNumber(2))
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(err.Error()).To(ContainSubstring("sql: no rows in result set"))
|
Expect(storage).To(Equal(hexutil.Bytes(make([]byte, 32))))
|
||||||
})
|
})
|
||||||
It("Retrieves the storage value at the provided contract address and storage leaf key at the block with the provided hash or number", func() {
|
It("Retrieves the storage value at the provided contract address and storage leaf key at the block with the provided hash or number", func() {
|
||||||
// After deployment
|
// After deployment
|
||||||
val, err := api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.ContractSlotKeyHash.Hex(), rpc.BlockNumberOrHashWithNumber(2))
|
val, err := api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.IndexOne, rpc.BlockNumberOrHashWithNumber(2))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
expectedRes := hexutil.Bytes(common.Hex2Bytes("01"))
|
expectedRes := hexutil.Bytes(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001"))
|
||||||
Expect(val).To(Equal(expectedRes))
|
Expect(val).To(Equal(expectedRes))
|
||||||
|
|
||||||
val, err = api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.ContractSlotKeyHash.Hex(), rpc.BlockNumberOrHashWithNumber(3))
|
val, err = api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.IndexOne, rpc.BlockNumberOrHashWithNumber(3))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
expectedRes = hexutil.Bytes(common.Hex2Bytes("03"))
|
expectedRes = hexutil.Bytes(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000003"))
|
||||||
Expect(val).To(Equal(expectedRes))
|
Expect(val).To(Equal(expectedRes))
|
||||||
|
|
||||||
val, err = api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.ContractSlotKeyHash.Hex(), rpc.BlockNumberOrHashWithNumber(4))
|
val, err = api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.IndexOne, rpc.BlockNumberOrHashWithNumber(4))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
expectedRes = hexutil.Bytes(common.Hex2Bytes("09"))
|
expectedRes = hexutil.Bytes(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000009"))
|
||||||
Expect(val).To(Equal(expectedRes))
|
Expect(val).To(Equal(expectedRes))
|
||||||
|
|
||||||
val, err = api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.ContractSlotKeyHash.Hex(), rpc.BlockNumberOrHashWithNumber(5))
|
val, err = api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.IndexOne, rpc.BlockNumberOrHashWithNumber(5))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(val).To(Equal(hexutil.Bytes{}))
|
Expect(val).To(Equal(hexutil.Bytes{}))
|
||||||
})
|
})
|
||||||
|
It("Throws an error for a non-existing block hash", func() {
|
||||||
|
_, err := api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.IndexOne, rpc.BlockNumberOrHashWithHash(randomHash, true))
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
Expect(err).To(MatchError("header for hash not found"))
|
||||||
|
})
|
||||||
|
It("Throws an error for a non-existing block number", func() {
|
||||||
|
_, err := api.GetStorageAt(ctx, test_helpers.ContractAddr, test_helpers.IndexOne, rpc.BlockNumberOrHashWithNumber(chainLength+1))
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
Expect(err).To(MatchError("header not found"))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("eth_getHeaderByNumber", func() {
|
Describe("eth_getHeaderByNumber", func() {
|
||||||
|
@ -428,11 +428,12 @@ func (r *IPLDRetriever) RetrieveAccountByAddressAndBlockNumber(address common.Ad
|
|||||||
return accountResult.CID, i[1].([]byte), nil
|
return accountResult.CID, i[1].([]byte), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RetrieveStorageAtByAddressAndStorageKeyAndBlockHash returns the cid and rlp bytes for the storage value corresponding to the provided address, storage key, and block hash
|
// RetrieveStorageAtByAddressAndStorageSlotAndBlockHash returns the cid and rlp bytes for the storage value corresponding to the provided address, storage slot, and block hash
|
||||||
func (r *IPLDRetriever) RetrieveStorageAtByAddressAndStorageKeyAndBlockHash(address common.Address, storageLeafKey, hash common.Hash) (string, []byte, error) {
|
func (r *IPLDRetriever) RetrieveStorageAtByAddressAndStorageSlotAndBlockHash(address common.Address, key, hash common.Hash) (string, []byte, error) {
|
||||||
storageResult := new(nodeInfo)
|
storageResult := new(nodeInfo)
|
||||||
stateLeafKey := crypto.Keccak256Hash(address.Bytes())
|
stateLeafKey := crypto.Keccak256Hash(address.Bytes())
|
||||||
if err := r.db.Get(storageResult, RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr, stateLeafKey.Hex(), storageLeafKey.Hex(), hash.Hex()); err != nil {
|
storageHash := crypto.Keccak256Hash(key.Bytes())
|
||||||
|
if err := r.db.Get(storageResult, RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr, stateLeafKey.Hex(), storageHash.Hex(), hash.Hex()); err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
if storageResult.Removed {
|
if storageResult.Removed {
|
||||||
|
@ -34,7 +34,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/statediff/testhelpers"
|
"github.com/ethereum/go-ethereum/statediff/testhelpers"
|
||||||
"github.com/ipfs/go-block-format"
|
blocks "github.com/ipfs/go-block-format"
|
||||||
"github.com/multiformats/go-multihash"
|
"github.com/multiformats/go-multihash"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
ReceiptsRlp, _ = rlp.EncodeToBytes(MockReceipts)
|
ReceiptsRlp, _ = rlp.EncodeToBytes(MockReceipts)
|
||||||
MockBlock = types.NewBlock(&MockHeader, MockTransactions, MockUncles, MockReceipts, new(trie.Trie))
|
MockBlock = createNewBlock(&MockHeader, MockTransactions, MockUncles, MockReceipts, new(trie.Trie))
|
||||||
MockHeaderRlp, _ = rlp.EncodeToBytes(MockBlock.Header())
|
MockHeaderRlp, _ = rlp.EncodeToBytes(MockBlock.Header())
|
||||||
MockChildHeader = types.Header{
|
MockChildHeader = types.Header{
|
||||||
Time: 0,
|
Time: 0,
|
||||||
@ -107,12 +107,19 @@ var (
|
|||||||
Address: Address,
|
Address: Address,
|
||||||
Topics: []common.Hash{mockTopic11, mockTopic12},
|
Topics: []common.Hash{mockTopic11, mockTopic12},
|
||||||
Data: []byte{},
|
Data: []byte{},
|
||||||
|
BlockNumber: BlockNumber.Uint64(),
|
||||||
|
TxIndex: 0,
|
||||||
|
Index: 0,
|
||||||
}
|
}
|
||||||
MockLog2 = &types.Log{
|
MockLog2 = &types.Log{
|
||||||
Address: AnotherAddress,
|
Address: AnotherAddress,
|
||||||
Topics: []common.Hash{mockTopic21, mockTopic22},
|
Topics: []common.Hash{mockTopic21, mockTopic22},
|
||||||
Data: []byte{},
|
Data: []byte{},
|
||||||
|
BlockNumber: BlockNumber.Uint64(),
|
||||||
|
TxIndex: 1,
|
||||||
|
Index: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
HeaderCID, _ = ipld.RawdataToCid(ipld.MEthHeader, MockHeaderRlp, multihash.KECCAK_256)
|
HeaderCID, _ = ipld.RawdataToCid(ipld.MEthHeader, MockHeaderRlp, multihash.KECCAK_256)
|
||||||
HeaderMhKey = shared.MultihashKeyFromCID(HeaderCID)
|
HeaderMhKey = shared.MultihashKeyFromCID(HeaderCID)
|
||||||
Trx1CID, _ = ipld.RawdataToCid(ipld.MEthTx, MockTransactions.GetRlp(0), multihash.KECCAK_256)
|
Trx1CID, _ = ipld.RawdataToCid(ipld.MEthTx, MockTransactions.GetRlp(0), multihash.KECCAK_256)
|
||||||
@ -375,6 +382,8 @@ var (
|
|||||||
StateNodes: MockStateNodes,
|
StateNodes: MockStateNodes,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reward = eth.CalcEthBlockReward(MockBlock.Header(), MockBlock.Uncles(), MockBlock.Transactions(), MockReceipts)
|
||||||
|
|
||||||
MockCIDWrapper = ð2.CIDWrapper{
|
MockCIDWrapper = ð2.CIDWrapper{
|
||||||
BlockNumber: new(big.Int).Set(BlockNumber),
|
BlockNumber: new(big.Int).Set(BlockNumber),
|
||||||
Header: eth.HeaderModel{
|
Header: eth.HeaderModel{
|
||||||
@ -384,7 +393,7 @@ var (
|
|||||||
CID: HeaderCID.String(),
|
CID: HeaderCID.String(),
|
||||||
MhKey: HeaderMhKey,
|
MhKey: HeaderMhKey,
|
||||||
TotalDifficulty: MockBlock.Difficulty().String(),
|
TotalDifficulty: MockBlock.Difficulty().String(),
|
||||||
Reward: "5312500000000000000",
|
Reward: Reward.String(),
|
||||||
StateRoot: MockBlock.Root().String(),
|
StateRoot: MockBlock.Root().String(),
|
||||||
RctRoot: MockBlock.ReceiptHash().String(),
|
RctRoot: MockBlock.ReceiptHash().String(),
|
||||||
TxRoot: MockBlock.TxHash().String(),
|
TxRoot: MockBlock.TxHash().String(),
|
||||||
@ -489,6 +498,17 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func createNewBlock(header *types.Header, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, hasher types.Hasher) *types.Block {
|
||||||
|
block := types.NewBlock(header, txs, uncles, receipts, hasher)
|
||||||
|
bHash := block.Hash()
|
||||||
|
for _, r := range receipts {
|
||||||
|
for _, l := range r.Logs {
|
||||||
|
l.BlockHash = bHash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return block
|
||||||
|
}
|
||||||
|
|
||||||
// createTransactionsAndReceipts is a helper function to generate signed mock transactions and mock receipts with mock logs
|
// createTransactionsAndReceipts is a helper function to generate signed mock transactions and mock receipts with mock logs
|
||||||
func createTransactionsAndReceipts() (types.Transactions, types.Receipts, common.Address) {
|
func createTransactionsAndReceipts() (types.Transactions, types.Receipts, common.Address) {
|
||||||
// make transactions
|
// make transactions
|
||||||
@ -519,13 +539,26 @@ func createTransactionsAndReceipts() (types.Transactions, types.Receipts, common
|
|||||||
}
|
}
|
||||||
// make receipts
|
// make receipts
|
||||||
mockReceipt1 := types.NewReceipt(common.HexToHash("0x0").Bytes(), false, 50)
|
mockReceipt1 := types.NewReceipt(common.HexToHash("0x0").Bytes(), false, 50)
|
||||||
|
|
||||||
|
hash1 := signedTrx1.Hash()
|
||||||
|
MockLog1.TxHash = hash1
|
||||||
|
|
||||||
mockReceipt1.Logs = []*types.Log{MockLog1}
|
mockReceipt1.Logs = []*types.Log{MockLog1}
|
||||||
mockReceipt1.TxHash = signedTrx1.Hash()
|
mockReceipt1.TxHash = hash1
|
||||||
|
mockReceipt1.GasUsed = mockReceipt1.CumulativeGasUsed
|
||||||
|
|
||||||
mockReceipt2 := types.NewReceipt(common.HexToHash("0x1").Bytes(), false, 100)
|
mockReceipt2 := types.NewReceipt(common.HexToHash("0x1").Bytes(), false, 100)
|
||||||
|
hash2 := signedTrx2.Hash()
|
||||||
|
MockLog2.TxHash = hash2
|
||||||
|
|
||||||
mockReceipt2.Logs = []*types.Log{MockLog2}
|
mockReceipt2.Logs = []*types.Log{MockLog2}
|
||||||
mockReceipt2.TxHash = signedTrx2.Hash()
|
mockReceipt2.TxHash = hash2
|
||||||
mockReceipt3 := types.NewReceipt(common.HexToHash("0x2").Bytes(), false, 75)
|
mockReceipt2.GasUsed = mockReceipt2.CumulativeGasUsed - mockReceipt1.CumulativeGasUsed
|
||||||
|
|
||||||
|
mockReceipt3 := types.NewReceipt(common.HexToHash("0x2").Bytes(), false, 175)
|
||||||
mockReceipt3.Logs = []*types.Log{}
|
mockReceipt3.Logs = []*types.Log{}
|
||||||
mockReceipt3.TxHash = signedTrx3.Hash()
|
mockReceipt3.TxHash = signedTrx3.Hash()
|
||||||
|
mockReceipt3.GasUsed = mockReceipt3.CumulativeGasUsed - mockReceipt2.CumulativeGasUsed
|
||||||
|
|
||||||
return types.Transactions{signedTrx1, signedTrx2, signedTrx3}, types.Receipts{mockReceipt1, mockReceipt2, mockReceipt3}, SenderAddr
|
return types.Transactions{signedTrx1, signedTrx2, signedTrx3}, types.Receipts{mockReceipt1, mockReceipt2, mockReceipt3}, SenderAddr
|
||||||
}
|
}
|
||||||
|
@ -867,7 +867,11 @@ func (r *Resolver) Blocks(ctx context.Context, args struct {
|
|||||||
if args.To != nil {
|
if args.To != nil {
|
||||||
to = rpc.BlockNumber(*args.To)
|
to = rpc.BlockNumber(*args.To)
|
||||||
} else {
|
} else {
|
||||||
to = rpc.BlockNumber(r.backend.CurrentBlock().Number().Int64())
|
block, err := r.backend.CurrentBlock()
|
||||||
|
if err != nil {
|
||||||
|
return []*Block{}, nil
|
||||||
|
}
|
||||||
|
to = rpc.BlockNumber(block.Number().Int64())
|
||||||
}
|
}
|
||||||
if to < from {
|
if to < from {
|
||||||
return []*Block{}, nil
|
return []*Block{}, nil
|
||||||
|
21
scripts/run_intregration_test.sh
Executable file
21
scripts/run_intregration_test.sh
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
set -e
|
||||||
|
set -o xtrace
|
||||||
|
|
||||||
|
# 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` code is modified. Otherwise comment this line.
|
||||||
|
docker build -t ipld-eth-server_eth-server:latest .
|
||||||
|
docker-compose -f docker-compose.test.yml -f docker-compose.yml up -d 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
|
2
scripts/run_unit_test.sh
Executable file
2
scripts/run_unit_test.sh
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
docker-compose -f docker-compose.test.yml -f docker-compose.yml up -d db
|
||||||
|
PGPASSWORD=password DATABASE_USER=vdbm DATABASE_PORT=8077 DATABASE_PASSWORD=password DATABASE_HOSTNAME=127.0.0.1 make test
|
15
test/README.md
Normal file
15
test/README.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
Spin up services:
|
||||||
|
```
|
||||||
|
docker-compose -f docker-compose.test.yml -f docker-compose.yml up -d db dapptools contract eth-server
|
||||||
|
```
|
||||||
|
|
||||||
|
Running unit tests:
|
||||||
|
```bash
|
||||||
|
make test_local
|
||||||
|
```
|
||||||
|
|
||||||
|
Running integration test:
|
||||||
|
```bash
|
||||||
|
make integrationtest_local
|
||||||
|
```
|
3
test/contract/.dockerignore
Normal file
3
test/contract/.dockerignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
node_modules
|
||||||
|
artifacts
|
||||||
|
cache
|
5
test/contract/.gitignore
vendored
Normal file
5
test/contract/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
node_modules
|
||||||
|
|
||||||
|
#Hardhat files
|
||||||
|
cache
|
||||||
|
artifacts
|
14
test/contract/Dockerfile
Normal file
14
test/contract/Dockerfile
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
FROM node:14
|
||||||
|
|
||||||
|
ARG ETH_ADDR
|
||||||
|
ENV ETH_ADDR $ETH_ADDR
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci
|
||||||
|
COPY . .
|
||||||
|
RUN npm run compile && ls -lah
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
ENTRYPOINT ["npm", "start"]
|
7
test/contract/contracts/GLDToken.sol
Normal file
7
test/contract/contracts/GLDToken.sol
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
pragma solidity ^0.8.0;
|
||||||
|
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
||||||
|
contract GLDToken is ERC20 {
|
||||||
|
constructor() ERC20("Gold", "GLD") {
|
||||||
|
_mint(msg.sender, 1000000000000000000000);
|
||||||
|
}
|
||||||
|
}
|
32
test/contract/hardhat.config.js
Normal file
32
test/contract/hardhat.config.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
require("@nomiclabs/hardhat-waffle");
|
||||||
|
|
||||||
|
// This is a sample Hardhat task. To learn how to create your own go to
|
||||||
|
// https://hardhat.org/guides/create-task.html
|
||||||
|
task("accounts", "Prints the list of accounts", async () => {
|
||||||
|
const accounts = await ethers.getSigners();
|
||||||
|
|
||||||
|
for (const account of accounts) {
|
||||||
|
console.log(account.address);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// You need to export an object to set up your config
|
||||||
|
// Go to https://hardhat.org/config/ to learn more
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type import('hardhat/config').HardhatUserConfig
|
||||||
|
*/
|
||||||
|
module.exports = {
|
||||||
|
solidity: "0.8.0",
|
||||||
|
networks: {
|
||||||
|
local: {
|
||||||
|
url: 'http://127.0.0.1:8545',
|
||||||
|
chainId: 4
|
||||||
|
},
|
||||||
|
docker: {
|
||||||
|
url: process.env.ETH_ADDR,
|
||||||
|
chainId: 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
27700
test/contract/package-lock.json
generated
Normal file
27700
test/contract/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
27
test/contract/package.json
Normal file
27
test/contract/package.json
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"name": "contract",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"compile": "npx hardhat compile",
|
||||||
|
"start": "HARDHAT_NETWORK=docker node src/index.js",
|
||||||
|
"start:local": "ETH_ADDR=http://127.0.0.1:8545 npm run start",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"description": "",
|
||||||
|
"dependencies": {
|
||||||
|
"@openzeppelin/contracts": "^4.0.0",
|
||||||
|
"fastify": "^3.14.2",
|
||||||
|
"hardhat": "^2.2.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@nomiclabs/hardhat-ethers": "^2.0.2",
|
||||||
|
"@nomiclabs/hardhat-waffle": "^2.0.1",
|
||||||
|
"chai": "^4.3.4",
|
||||||
|
"ethereum-waffle": "^3.3.0",
|
||||||
|
"ethers": "^5.1.0"
|
||||||
|
}
|
||||||
|
}
|
18
test/contract/scripts/deploy.js
Normal file
18
test/contract/scripts/deploy.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
const hre = require("hardhat");
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
// await hre.run('compile');
|
||||||
|
// We get the contract to deploy
|
||||||
|
const GLDToken = await hre.ethers.getContractFactory("GLDToken");
|
||||||
|
const token = await GLDToken.deploy();
|
||||||
|
await token.deployed();
|
||||||
|
console.log("GLDToken deployed to:", token.address, token.deployTransaction.hash);
|
||||||
|
}
|
||||||
|
// We recommend this pattern to be able to use async/await everywhere
|
||||||
|
// and properly handle errors.
|
||||||
|
main()
|
||||||
|
.then(() => process.exit(0))
|
||||||
|
.catch(error => {
|
||||||
|
console.error(error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
36
test/contract/scripts/sample-script.js
Normal file
36
test/contract/scripts/sample-script.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// We require the Hardhat Runtime Environment explicitly here. This is optional
|
||||||
|
// but useful for running the script in a standalone fashion through `node <script>`.
|
||||||
|
//
|
||||||
|
// When running the script with `hardhat run <script>` you'll find the Hardhat
|
||||||
|
// Runtime Environment's members available in the global scope.
|
||||||
|
const hre = require("hardhat");
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
// Hardhat always runs the compile task when running scripts with its command
|
||||||
|
// line interface.
|
||||||
|
//
|
||||||
|
// If this script is run directly using `node` you may want to call compile
|
||||||
|
// manually to make sure everything is compiled
|
||||||
|
// await hre.run('compile');
|
||||||
|
|
||||||
|
// We get the contract to deploy
|
||||||
|
const Greeter = await hre.ethers.getContractFactory("Greeter");
|
||||||
|
const greeter = await Greeter.deploy("Hello, Hardhat!");
|
||||||
|
|
||||||
|
await greeter.deployed();
|
||||||
|
|
||||||
|
console.log("Greeter deployed to:", greeter.address, "; tx hash: ", greeter.deployTransaction.hash);
|
||||||
|
|
||||||
|
const result = await greeter.setGreeting("Hello 123!");
|
||||||
|
|
||||||
|
console.log("Greeter updated", "; tx hash: ", result.hash, "; block hash: ", result.blockHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We recommend this pattern to be able to use async/await everywhere
|
||||||
|
// and properly handle errors.
|
||||||
|
main()
|
||||||
|
.then(() => process.exit(0))
|
||||||
|
.catch(error => {
|
||||||
|
console.error(error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
60
test/contract/src/index.js
Normal file
60
test/contract/src/index.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
const fastify = require('fastify')({ logger: true });
|
||||||
|
const hre = require("hardhat");
|
||||||
|
|
||||||
|
// readiness check
|
||||||
|
fastify.get('/v1/healthz', async (req, reply) => {
|
||||||
|
reply
|
||||||
|
.code(200)
|
||||||
|
.header('Content-Type', 'application/json; charset=utf-8')
|
||||||
|
.send({ success: true })
|
||||||
|
});
|
||||||
|
|
||||||
|
fastify.get('/v1/deployContract', async (req, reply) => {
|
||||||
|
const GLDToken = await hre.ethers.getContractFactory("GLDToken");
|
||||||
|
const token = await GLDToken.deploy();
|
||||||
|
await token.deployed();
|
||||||
|
|
||||||
|
return {
|
||||||
|
address: token.address,
|
||||||
|
txHash: token.deployTransaction.hash,
|
||||||
|
blockNumber: token.deployTransaction.blockNumber,
|
||||||
|
blockHash: token.deployTransaction.blockHash,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
fastify.get('/v1/sendEth', async (req, reply) => {
|
||||||
|
const to = req.query.to;
|
||||||
|
const value = req.query.value;
|
||||||
|
|
||||||
|
const [owner] = await hre.ethers.getSigners();
|
||||||
|
const tx = await owner.sendTransaction({
|
||||||
|
to,
|
||||||
|
value: hre.ethers.utils.parseEther(value)
|
||||||
|
});
|
||||||
|
await tx.wait(1)
|
||||||
|
|
||||||
|
// console.log(tx);
|
||||||
|
// const coinbaseBalance = await hre.ethers.provider.getBalance(owner.address);
|
||||||
|
// const receiverBalance = await hre.ethers.provider.getBalance(to);
|
||||||
|
// console.log(coinbaseBalance.toString(), receiverBalance.toString());
|
||||||
|
|
||||||
|
return {
|
||||||
|
from: tx.from,
|
||||||
|
to: tx.to,
|
||||||
|
//value: tx.value.toString(),
|
||||||
|
txHash: tx.hash,
|
||||||
|
blockNumber: tx.blockNumber,
|
||||||
|
blockHash: tx.blockHash,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
try {
|
||||||
|
await fastify.listen(3000, '0.0.0.0');
|
||||||
|
} catch (err) {
|
||||||
|
fastify.log.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
14
test/contract/test/sample-test.js
Normal file
14
test/contract/test/sample-test.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
const { expect } = require("chai");
|
||||||
|
|
||||||
|
describe("Greeter", function() {
|
||||||
|
it("Should return the new greeting once it's changed", async function() {
|
||||||
|
const Greeter = await ethers.getContractFactory("Greeter");
|
||||||
|
const greeter = await Greeter.deploy("Hello, world!");
|
||||||
|
|
||||||
|
await greeter.deployed();
|
||||||
|
expect(await greeter.greet()).to.equal("Hello, world!");
|
||||||
|
|
||||||
|
await greeter.setGreeting("Hola, mundo!");
|
||||||
|
expect(await greeter.greet()).to.equal("Hola, mundo!");
|
||||||
|
});
|
||||||
|
});
|
62
test/helper.go
Normal file
62
test/helper.go
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package integration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ContractDeployed struct {
|
||||||
|
Address string `json:"address"`
|
||||||
|
TransactionHash string `json:"txHash"`
|
||||||
|
BlockNumber int `json:"blockNumber"`
|
||||||
|
BlockHash string `json:"blockHash"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Tx struct {
|
||||||
|
From string `json:"from"`
|
||||||
|
To string `json:"to"`
|
||||||
|
Value *big.Int `json:"value"`
|
||||||
|
TransactionHash string `json:"txHash"`
|
||||||
|
BlockNumber int `json:"blockNumber"`
|
||||||
|
BlockHash string `json:"blockHash"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const srvUrl = "http://localhost:3000"
|
||||||
|
|
||||||
|
func DeployContract() (*ContractDeployed, error) {
|
||||||
|
res, err := http.Get(fmt.Sprintf("%s/v1/deployContract", srvUrl))
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendEth(to string, value string) (*Tx, error) {
|
||||||
|
res, err := http.Get(fmt.Sprintf("%s/v1/sendEth?to=%s&value=%s", srvUrl, to, value))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
var tx Tx
|
||||||
|
|
||||||
|
decoder := json.NewDecoder(res.Body)
|
||||||
|
err = decoder.Decode(&tx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &tx, nil
|
||||||
|
}
|
19
test/integration_suite_test.go
Normal file
19
test/integration_suite_test.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package integration_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"io/ioutil"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIntegration(t *testing.T) {
|
||||||
|
RegisterFailHandler(Fail)
|
||||||
|
RunSpecs(t, "integration test suite")
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = BeforeSuite(func() {
|
||||||
|
logrus.SetOutput(ioutil.Discard)
|
||||||
|
})
|
486
test/integration_test.go
Normal file
486
test/integration_test.go
Normal file
@ -0,0 +1,486 @@
|
|||||||
|
package integration_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"math/big"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
integration "github.com/vulcanize/ipld-eth-server/test"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
|
)
|
||||||
|
|
||||||
|
const nonExistingBlockHash = "0x111111111111111111111111111111111111111111111111111111111111111"
|
||||||
|
const nonExistingAddress = "0x1111111111111111111111111111111111111111"
|
||||||
|
|
||||||
|
var (
|
||||||
|
randomAddr = common.HexToAddress("0x1C3ab14BBaD3D99F4203bd7a11aCB94882050E6f")
|
||||||
|
randomHash = crypto.Keccak256Hash(randomAddr.Bytes())
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Integration test", func() {
|
||||||
|
gethHttpPath := "http://127.0.0.1:8545"
|
||||||
|
gethClient, err := ethclient.Dial(gethHttpPath)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldEthHttpPath := "http://127.0.0.1:8081"
|
||||||
|
ipldClient, err := ethclient.Dial(ipldEthHttpPath)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
var contract *integration.ContractDeployed
|
||||||
|
var erc20TotalSupply *big.Int
|
||||||
|
var tx *integration.Tx
|
||||||
|
var bigIntResult bool
|
||||||
|
var contractErr error
|
||||||
|
var txErr error
|
||||||
|
sleepInterval := 2 * time.Second
|
||||||
|
|
||||||
|
Describe("get Block", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
contract, contractErr = integration.DeployContract()
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("get not existing block by number", func() {
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
blockNum := contract.BlockNumber + 100
|
||||||
|
|
||||||
|
gethBlock, err := gethClient.BlockByNumber(ctx, big.NewInt(int64(blockNum)))
|
||||||
|
Expect(err).To(MatchError(ethereum.NotFound))
|
||||||
|
Expect(gethBlock).To(BeZero())
|
||||||
|
|
||||||
|
ipldBlock, err := ipldClient.BlockByNumber(ctx, big.NewInt(int64(blockNum)))
|
||||||
|
Expect(err).To(MatchError(ethereum.NotFound))
|
||||||
|
Expect(ipldBlock).To(BeZero())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("get not existing block by hash", func() {
|
||||||
|
gethBlock, err := gethClient.BlockByHash(ctx, common.HexToHash(nonExistingBlockHash))
|
||||||
|
Expect(err).To(MatchError(ethereum.NotFound))
|
||||||
|
Expect(gethBlock).To(BeZero())
|
||||||
|
|
||||||
|
ipldBlock, err := ipldClient.BlockByHash(ctx, common.HexToHash(nonExistingBlockHash))
|
||||||
|
Expect(err).To(MatchError(ethereum.NotFound))
|
||||||
|
Expect(ipldBlock).To(BeZero())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("get block by number", func() {
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
blockNum := contract.BlockNumber
|
||||||
|
|
||||||
|
gethBlock, err := gethClient.BlockByNumber(ctx, big.NewInt(int64(blockNum)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldBlock, err := ipldClient.BlockByNumber(ctx, big.NewInt(int64(blockNum)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// check headers are equals
|
||||||
|
Expect(gethBlock.Header()).To(Equal(ipldBlock.Header()))
|
||||||
|
|
||||||
|
gethTxs := gethBlock.Transactions()
|
||||||
|
ipldTxs := ipldBlock.Transactions()
|
||||||
|
|
||||||
|
Expect(gethTxs.Len()).To(Equal(ipldTxs.Len()))
|
||||||
|
Expect(types.TxDifference(gethTxs, ipldTxs).Len()).To(Equal(0))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("get block by hash", func() {
|
||||||
|
gethBlock, err := gethClient.BlockByHash(ctx, common.HexToHash(contract.BlockHash))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldBlock, err := ipldClient.BlockByHash(ctx, common.HexToHash(contract.BlockHash))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// check headers are equals
|
||||||
|
compareBlocks(gethBlock, ipldBlock)
|
||||||
|
|
||||||
|
gethTxs := gethBlock.Transactions()
|
||||||
|
ipldTxs := ipldBlock.Transactions()
|
||||||
|
|
||||||
|
Expect(gethTxs.Len()).To(Equal(ipldTxs.Len()))
|
||||||
|
Expect(types.TxDifference(gethTxs, ipldTxs).Len()).To(Equal(0))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("Transaction", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
contract, contractErr = integration.DeployContract()
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("Get tx by hash", func() {
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
gethTx, _, err := gethClient.TransactionByHash(ctx, common.HexToHash(contract.TransactionHash))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldTx, _, err := ipldClient.TransactionByHash(ctx, common.HexToHash(contract.TransactionHash))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
compareTxs(gethTx, ipldTx)
|
||||||
|
|
||||||
|
Expect(gethTx.Hash()).To(Equal(ipldTx.Hash()))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("Get tx by block hash and index", func() {
|
||||||
|
gethTx, err := gethClient.TransactionInBlock(ctx, common.HexToHash(contract.BlockHash), 0)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldTx, err := ipldClient.TransactionInBlock(ctx, common.HexToHash(contract.BlockHash), 0)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
compareTxs(gethTx, ipldTx)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("Receipt", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
contract, contractErr = integration.DeployContract()
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("Get tx receipt", func() {
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
gethReceipt, err := gethClient.TransactionReceipt(ctx, common.HexToHash(contract.TransactionHash))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldReceipt, err := ipldClient.TransactionReceipt(ctx, common.HexToHash(contract.TransactionHash))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(gethReceipt).To(Equal(ipldReceipt))
|
||||||
|
|
||||||
|
rlpGeth, err := rlp.EncodeToBytes(gethReceipt)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
rlpIpld, err := rlp.EncodeToBytes(ipldReceipt)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(rlpGeth).To(Equal(rlpIpld))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("FilterLogs", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
contract, contractErr = integration.DeployContract()
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("with blockhash", func() {
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
blockHash := common.HexToHash(contract.BlockHash)
|
||||||
|
filterQuery := ethereum.FilterQuery{
|
||||||
|
//Addresses: addresses,
|
||||||
|
BlockHash: &blockHash,
|
||||||
|
Topics: [][]common.Hash{},
|
||||||
|
}
|
||||||
|
|
||||||
|
gethLogs, err := gethClient.FilterLogs(ctx, filterQuery)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldLogs, err := ipldClient.FilterLogs(ctx, filterQuery)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// not empty list
|
||||||
|
Expect(gethLogs).ToNot(BeEmpty())
|
||||||
|
|
||||||
|
Expect(len(gethLogs)).To(Equal(len(ipldLogs)))
|
||||||
|
Expect(gethLogs).To(Equal(ipldLogs))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("CodeAt", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
contract, contractErr = integration.DeployContract()
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("gets code at non-existing address without block number", func() {
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
gethCode, err := gethClient.CodeAt(ctx, common.HexToAddress(nonExistingAddress), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldCode, err := ipldClient.CodeAt(ctx, common.HexToAddress(nonExistingAddress), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(gethCode).To(BeEmpty())
|
||||||
|
Expect(gethCode).To(Equal(ipldCode))
|
||||||
|
})
|
||||||
|
It("gets code of deployed contract without block number", func() {
|
||||||
|
gethCode, err := gethClient.CodeAt(ctx, common.HexToAddress(contract.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldCode, err := ipldClient.CodeAt(ctx, common.HexToAddress(contract.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(gethCode).To(Equal(ipldCode))
|
||||||
|
})
|
||||||
|
It("gets code of deployed contract with block number", func() {
|
||||||
|
gethCode, err := gethClient.CodeAt(ctx, common.HexToAddress(contract.Address), big.NewInt(int64(contract.BlockNumber)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldCode, err := ipldClient.CodeAt(ctx, common.HexToAddress(contract.Address), big.NewInt(int64(contract.BlockNumber)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(gethCode).To(Equal(ipldCode))
|
||||||
|
})
|
||||||
|
It("gets code of contract that doesn't exist at this height", func() {
|
||||||
|
gethCode, err := gethClient.CodeAt(ctx, common.HexToAddress(contract.Address), big.NewInt(int64(contract.BlockNumber-1)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldCode, err := ipldClient.CodeAt(ctx, common.HexToAddress(contract.Address), big.NewInt(int64(contract.BlockNumber-1)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(gethCode).To(BeEmpty())
|
||||||
|
Expect(gethCode).To(Equal(ipldCode))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("Get balance", func() {
|
||||||
|
address := "0x1111111111111111111111111111111111111112"
|
||||||
|
BeforeEach(func() {
|
||||||
|
tx, txErr = integration.SendEth(address, "0.01")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("gets balance for an account with eth without block number", func() {
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
gethBalance, err := gethClient.BalanceAt(ctx, common.HexToAddress(address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldBalance, err := ipldClient.BalanceAt(ctx, common.HexToAddress(address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(gethBalance).To(Equal(ipldBalance))
|
||||||
|
})
|
||||||
|
It("gets balance for an account with eth with block number", func() {
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
gethBalance, err := gethClient.BalanceAt(ctx, common.HexToAddress(address), big.NewInt(int64(tx.BlockNumber)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldBalance, err := ipldClient.BalanceAt(ctx, common.HexToAddress(address), big.NewInt(int64(tx.BlockNumber)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(gethBalance).To(Equal(ipldBalance))
|
||||||
|
})
|
||||||
|
It("gets historical balance for an account with eth with block number", func() {
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
gethBalance, err := gethClient.BalanceAt(ctx, common.HexToAddress(address), big.NewInt(int64(tx.BlockNumber-1)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldBalance, err := ipldClient.BalanceAt(ctx, common.HexToAddress(address), big.NewInt(int64(tx.BlockNumber-1)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(gethBalance).To(Equal(ipldBalance))
|
||||||
|
})
|
||||||
|
It("gets balance for a non-existing account without block number", func() {
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
gethBalance, err := gethClient.BalanceAt(ctx, common.HexToAddress(nonExistingAddress), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldBalance, err := ipldClient.BalanceAt(ctx, common.HexToAddress(nonExistingAddress), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(gethBalance).To(Equal(ipldBalance))
|
||||||
|
})
|
||||||
|
It("gets balance for an non-existing block number", func() {
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
gethBalance, err := gethClient.BalanceAt(ctx, common.HexToAddress(address), big.NewInt(int64(tx.BlockNumber+3)))
|
||||||
|
Expect(err).To(MatchError("header not found"))
|
||||||
|
|
||||||
|
ipldBalance, err := ipldClient.BalanceAt(ctx, common.HexToAddress(nonExistingAddress), big.NewInt(int64(tx.BlockNumber+3)))
|
||||||
|
Expect(err).To(MatchError("header not found"))
|
||||||
|
|
||||||
|
Expect(gethBalance).To(Equal(ipldBalance))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("Get Storage", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
contract, contractErr = integration.DeployContract()
|
||||||
|
erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10)
|
||||||
|
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("gets ERC20 total supply (without block number)", func() {
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
Expect(bigIntResult).To(Equal(true))
|
||||||
|
|
||||||
|
totalSupplyIndex := "0x2"
|
||||||
|
|
||||||
|
gethStorage, err := gethClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
gethTotalSupply := new(big.Int).SetBytes(gethStorage)
|
||||||
|
Expect(gethTotalSupply).To(Equal(erc20TotalSupply))
|
||||||
|
|
||||||
|
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldTotalSupply := new(big.Int).SetBytes(ipldStorage)
|
||||||
|
Expect(ipldTotalSupply).To(Equal(erc20TotalSupply))
|
||||||
|
|
||||||
|
Expect(gethStorage).To(Equal(ipldStorage))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("gets ERC20 total supply (with block number)", func() {
|
||||||
|
totalSupplyIndex := "0x2"
|
||||||
|
|
||||||
|
gethStorage, err := gethClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(int64(contract.BlockNumber)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
gethTotalSupply := new(big.Int).SetBytes(gethStorage)
|
||||||
|
Expect(gethTotalSupply).To(Equal(erc20TotalSupply))
|
||||||
|
|
||||||
|
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(int64(contract.BlockNumber)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(gethStorage).To(Equal(ipldStorage))
|
||||||
|
})
|
||||||
|
It("gets storage for non-existing account", func() {
|
||||||
|
totalSupplyIndex := "0x2"
|
||||||
|
|
||||||
|
gethStorage, err := gethClient.StorageAt(ctx, common.HexToAddress(nonExistingAddress), common.HexToHash(totalSupplyIndex), big.NewInt(int64(contract.BlockNumber)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(nonExistingAddress), common.HexToHash(totalSupplyIndex), big.NewInt(int64(contract.BlockNumber)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(gethStorage).To(Equal(ipldStorage))
|
||||||
|
})
|
||||||
|
It("gets storage for non-existing contract slot", func() {
|
||||||
|
gethStorage, err := gethClient.StorageAt(ctx, common.HexToAddress(contract.Address), randomHash, big.NewInt(int64(contract.BlockNumber)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), randomHash, big.NewInt(int64(contract.BlockNumber)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(gethStorage).To(Equal(ipldStorage))
|
||||||
|
})
|
||||||
|
It("gets storage for non-existing contract", func() {
|
||||||
|
totalSupplyIndex := "0x2"
|
||||||
|
gethStorage, err := gethClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(0))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(0))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(gethStorage).To(Equal(ipldStorage))
|
||||||
|
})
|
||||||
|
It("gets storage for non-existing block number", func() {
|
||||||
|
blockNum := contract.BlockNumber + 100
|
||||||
|
totalSupplyIndex := "0x2"
|
||||||
|
|
||||||
|
gethStorage, err := gethClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(int64(blockNum)))
|
||||||
|
Expect(err).To(MatchError("header not found"))
|
||||||
|
|
||||||
|
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(int64(blockNum)))
|
||||||
|
Expect(err).To(MatchError("header not found"))
|
||||||
|
Expect(gethStorage).To(Equal(ipldStorage))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("eth call", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
contract, contractErr = integration.DeployContract()
|
||||||
|
erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10)
|
||||||
|
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("calls totalSupply() without block number", func() {
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
Expect(bigIntResult).To(Equal(true))
|
||||||
|
|
||||||
|
contractAddress := common.HexToAddress(contract.Address)
|
||||||
|
|
||||||
|
msg := ethereum.CallMsg{
|
||||||
|
To: &contractAddress,
|
||||||
|
Data: common.Hex2Bytes("18160ddd"), // totalSupply()
|
||||||
|
}
|
||||||
|
gethResult, err := gethClient.CallContract(ctx, msg, nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
gethTotalSupply := new(big.Int).SetBytes(gethResult)
|
||||||
|
Expect(gethTotalSupply).To(Equal(erc20TotalSupply))
|
||||||
|
|
||||||
|
ipldResult, err := ipldClient.CallContract(ctx, msg, nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(gethResult).To(Equal(ipldResult))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("calls totalSupply() with block number", func() {
|
||||||
|
contractAddress := common.HexToAddress(contract.Address)
|
||||||
|
|
||||||
|
msg := ethereum.CallMsg{
|
||||||
|
To: &contractAddress,
|
||||||
|
Data: common.Hex2Bytes("18160ddd"), // totalSupply()
|
||||||
|
}
|
||||||
|
gethResult, err := gethClient.CallContract(ctx, msg, big.NewInt(int64(contract.BlockNumber)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
gethTotalSupply := new(big.Int).SetBytes(gethResult)
|
||||||
|
Expect(gethTotalSupply).To(Equal(erc20TotalSupply))
|
||||||
|
|
||||||
|
ipldResult, err := ipldClient.CallContract(ctx, msg, big.NewInt(int64(contract.BlockNumber)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(gethResult).To(Equal(ipldResult))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("Chain ID", func() {
|
||||||
|
It("Check chain id", func() {
|
||||||
|
gethChainId, err := gethClient.ChainID(ctx)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldChainId, err := ipldClient.ChainID(ctx)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(gethChainId).To(Equal(ipldChainId))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
func compareBlocks(block1 *types.Block, block2 *types.Block) {
|
||||||
|
Expect(block1.Header()).To(Equal(block2.Header()))
|
||||||
|
Expect(block1.Uncles()).To(Equal(block2.Uncles()))
|
||||||
|
|
||||||
|
txs1 := block1.Transactions()
|
||||||
|
txs2 := block2.Transactions()
|
||||||
|
|
||||||
|
Expect(len(txs1)).To(Equal(len(txs2)))
|
||||||
|
for i, tx := range txs1 {
|
||||||
|
compareTxs(tx, txs2[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func compareTxs(tx1 *types.Transaction, tx2 *types.Transaction) {
|
||||||
|
Expect(tx1.Data()).To(Equal(tx2.Data()))
|
||||||
|
Expect(tx1.Hash()).To(Equal(tx2.Hash()))
|
||||||
|
Expect(tx1.Size()).To(Equal(tx2.Size()))
|
||||||
|
|
||||||
|
signer := types.NewEIP155Signer(big.NewInt(4))
|
||||||
|
|
||||||
|
gethSender, err := types.Sender(signer, tx1)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldSender, err := types.Sender(signer, tx2)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(gethSender).To(Equal(ipldSender))
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user