Upgrade to v5 schema

Now uses:
* ipld direct_by_leaf StateDB for basic queries
* trie_by_cid StateDB for trie slice and proof queries

Also:
* vulcanize => cerc refactor
* Backend method to close dbs
* state tests are in multiple packages, to allow separate ginkgo suites
* removes gap-filler module
* integration tests and github workflows
* run stack-orchestrator for testnet
* fix various issues with tests, hardhat server, dockerfile
* fix cmd flags / env vars
* fix flaky tests and clean up code
* remove unused code, scripts
* remove outdated docs
* update version
This commit is contained in:
Roy Crihfield 2023-04-14 14:26:46 +08:00
parent ec6707c6ab
commit 6d7487152c
84 changed files with 5124 additions and 17650 deletions

View File

@ -10,7 +10,8 @@ jobs:
runs-on: ubuntu-latest
# Map a step output to a job output
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
# should_skip: ${{ steps.skip_check.outputs.should_skip }}
should_skip: false # XXX dev
steps:
- id: skip_check
uses: fkirc/skip-duplicate-actions@v4
@ -23,10 +24,6 @@ jobs:
uses: ./.github/workflows/tests.yaml
if: ${{ needs.pre_job.outputs.should_skip != 'true' }}
needs: pre_job
with:
STACK_ORCHESTRATOR_REF: "e62830c982d4dfc5f3c1c2b12c1754a7e9b538f1"
GO_ETHEREUM_REF: "c339429ff6550d8012d65977fc79f73bba2616e3"
IPLD_ETH_DB_REF: "6c00c38cc4e1db6f7c4cecbb62fdfd540fba50d6"
build:
name: Run docker build
runs-on: ubuntu-latest
@ -36,21 +33,20 @@ jobs:
(needs.run-tests.result == 'success' || needs.run-tests.result == 'skipped') &&
github.event_name == 'release'
steps:
- uses: actions/checkout@v2
- name: Get the version
id: vars
- uses: actions/checkout@v3
- id: vars
name: Output SHA and version tag
run: |
echo ::set-output name=sha::$(echo ${GITHUB_SHA:0:7})
echo ::set-output name=tag::$(echo ${GITHUB_REF#refs/tags/})
- name: Run docker build
run: make docker-build
- name: Tag docker image SHA
run: docker tag cerc-io/ipld-eth-server git.vdb.to/cerc-io/ipld-eth-server/ipld-eth-server:${{steps.vars.outputs.sha}}
- name: Tag docker image TAG
run: docker tag git.vdb.to/cerc-io/ipld-eth-server/ipld-eth-server:${{steps.vars.outputs.sha}} git.vdb.to/cerc-io/ipld-eth-server/ipld-eth-server:${{steps.vars.outputs.tag}}
- name: Docker Login
run: echo ${{ secrets.GITEA_TOKEN }} | docker login https://git.vdb.to -u cerccicd --password-stdin
- name: Docker Push SHA
run: docker push git.vdb.to/cerc-io/ipld-eth-server/ipld-eth-server:${{steps.vars.outputs.sha}}
- name: Docker Push TAG
run: docker push git.vdb.to/cerc-io/ipld-eth-server/ipld-eth-server:${{steps.vars.outputs.tag}}
echo sha=$(echo ${GITHUB_SHA:0:7}) >> "$GITHUB_OUTPUT"
echo tag=$(echo ${GITHUB_REF#refs/tags/}) >> "$GITHUB_OUTPUT""
- name: Build and tag Docker image
run: |
docker build . \
-t cerc-io/ipld-eth-server \
-t git.vdb.to/cerc-io/ipld-eth-server/ipld-eth-server:${{steps.vars.outputs.sha}} \
-t git.vdb.to/cerc-io/ipld-eth-server/ipld-eth-server:${{steps.vars.outputs.tag}}
- name: Push Docker tags
run: |
echo ${{ secrets.GITEA_TOKEN }} | docker login https://git.vdb.to -u cerccicd --password-stdin
docker push git.vdb.to/cerc-io/ipld-eth-server/ipld-eth-server:${{steps.vars.outputs.sha}}
docker push git.vdb.to/cerc-io/ipld-eth-server/ipld-eth-server:${{steps.vars.outputs.tag}}

View File

@ -1,186 +1,94 @@
name: Test the stack.
on:
workflow_call:
inputs:
STACK_ORCHESTRATOR_REF:
required: true
type: string
GO_ETHEREUM_REF:
required: true
type: string
IPLD_ETH_DB_REF:
required: true
type: string
jobs:
build:
name: Run docker build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run docker build
run: make docker-build
test:
name: Run unit tests
env:
GOPATH: /tmp/go
name: "Run unit tests"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v4
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: 1.19.7
- name: Bring up docker timescaledb container
run: docker compose up -d ipld-eth-db
- name: Run db migrations
go-version-file: 'go.mod'
check-latest: true
- name: "Run DB container"
run: docker compose -f test/compose-db.yml up --wait
- name: "Build and run tests"
run: |
sleep 30;
docker compose up -d migrations
go install github.com/onsi/ginkgo/v2/ginkgo
ginkgo -v -r --skipPackage=./test
- name: Run test
run: |
sleep 30;
PGPASSWORD=password DATABASE_USER=vdbm DATABASE_PORT=8077 DATABASE_PASSWORD=password DATABASE_HOSTNAME=127.0.0.1 DATABASE_NAME=vulcanize_testing make test
integrationtest:
name: Run integration tests
env:
GOPATH: /tmp/go
DB_WRITE: true
ETH_FORWARD_ETH_CALLS: false
ETH_PROXY_ON_ERROR: false
ETH_HTTP_PATH: "go-ethereum:8545"
integration-test:
name: "Run integration tests"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v4
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: 1.19.7
- name: Create GOPATH
run: mkdir -p /tmp/go
- uses: actions/checkout@v2
go-version-file: 'go.mod'
check-latest: true
- name: "Install stack-orchestrator"
# FIXME: using my dev branch for v5 migration changes until a release has them
# run: |
# curl -L -O https://github.com/cerc-io/stack-orchestrator/releases/latest/download/laconic-so
uses: actions/checkout@v3
with:
path: "./ipld-eth-server"
- uses: actions/checkout@v2
with:
ref: ${{ inputs.STACK_ORCHESTRATOR_REF }}
path: "./stack-orchestrator/"
repository: cerc-io/mshaw_stack_hack
- uses: actions/checkout@v2
with:
ref: ${{ inputs.GO_ETHEREUM_REF }}
repository: cerc-io/go-ethereum
path: "./go-ethereum/"
- uses: actions/checkout@v2
with:
ref: ${{ inputs.IPLD_ETH_DB_REF }}
repository: cerc-io/ipld-eth-db
path: "./ipld-eth-db/"
- name: Create config file
repository: cerc-io/stack-orchestrator
ref: roy/for-ci
path: ./stack-orchestrator
- run: pip install ./stack-orchestrator
- name: "Run testnet stack"
env:
LACONIC_SO: laconic-so
run: ./scripts/integration-setup.sh
- name: "Build and run server"
env:
ETH_FORWARD_ETH_CALLS: false
ETH_CHAIN_ID: "${{ env.ETH_CHAIN_ID }}"
ETH_CHAIN_CONFIG: "${{ env.ETH_CHAIN_CONFIG }}"
DEPLOYER_PRIVATE_KEY: "${{ env.DEPLOYER_PRIVATE_KEY }}"
run: docker compose -f test/compose-server.yml up --wait
- name: "Run tests"
env:
ETH_CHAIN_ID: "${{ env.ETH_CHAIN_ID }}"
ETH_HTTP_PATH: "${{ env.ETH_HTTP_PATH }}"
run: |
echo vulcanize_go_ethereum=$GITHUB_WORKSPACE/go-ethereum/ > ./config.sh
echo vulcanize_ipld_eth_db=$GITHUB_WORKSPACE/ipld-eth-db/ >> ./config.sh
echo vulcanize_ipld_eth_server=$GITHUB_WORKSPACE/ipld-eth-server/ >> ./config.sh
echo vulcanize_test_contract=$GITHUB_WORKSPACE/ipld-eth-server/test/contract >> ./config.sh
echo genesis_file_path=start-up-files/go-ethereum/genesis.json >> ./config.sh
echo db_write=$DB_WRITE >> ./config.sh
echo eth_forward_eth_calls=$ETH_FORWARD_ETH_CALLS >> ./config.sh
echo eth_proxy_on_error=$ETH_PROXY_ON_ERROR >> ./config.sh
echo eth_http_path=$ETH_HTTP_PATH >> ./config.sh
cat ./config.sh
- name: Build geth
run: |
cd $GITHUB_WORKSPACE/stack-orchestrator/helper-scripts
./compile-geth.sh \
-p "$GITHUB_WORKSPACE/config.sh" \
-e docker
- name: Run docker compose
run: |
docker-compose \
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/local/docker-compose-db-sharding.yml" \
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/local/docker-compose-go-ethereum.yml" \
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/local/docker-compose-ipld-eth-server.yml" \
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/local/docker-compose-contract.yml" \
--env-file "$GITHUB_WORKSPACE/config.sh" \
up -d --build
- name: Test
run: |
cd $GITHUB_WORKSPACE/ipld-eth-server
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
go install github.com/onsi/ginkgo/v2/ginkgo
ginkgo -v --label-filter '!proxy' -r ./test
integrationtest_forwardethcalls:
name: Run integration tests for direct proxy fall-through of eth_calls
env:
GOPATH: /tmp/go
DB_WRITE: false
ETH_FORWARD_ETH_CALLS: true
ETH_PROXY_ON_ERROR: false
ETH_HTTP_PATH: "go-ethereum:8545"
integration-test-eth-proxy:
name: "Run direct-proxy integration tests"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v4
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: 1.19.7
- name: Create GOPATH
run: mkdir -p /tmp/go
- uses: actions/checkout@v2
go-version-file: 'go.mod'
check-latest: true
- name: "Install stack-orchestrator"
uses: actions/checkout@v3
with:
path: "./ipld-eth-server"
- uses: actions/checkout@v2
with:
ref: ${{ inputs.STACK_ORCHESTRATOR_REF }}
path: "./stack-orchestrator/"
repository: cerc-io/mshaw_stack_hack
- uses: actions/checkout@v2
with:
ref: ${{ inputs.GO_ETHEREUM_REF }}
repository: cerc-io/go-ethereum
path: "./go-ethereum/"
- uses: actions/checkout@v2
with:
ref: ${{ inputs.IPLD_ETH_DB_REF }}
repository: cerc-io/ipld-eth-db
path: "./ipld-eth-db/"
- name: Create config file
repository: cerc-io/stack-orchestrator
ref: roy/for-ci
path: ./stack-orchestrator
- run: pip install ./stack-orchestrator
- name: "Run testnet stack"
env:
LACONIC_SO: laconic-so
CERC_RUN_STATEDIFF: false
run: ./scripts/integration-setup.sh
- name: "Build and run server"
env:
ETH_FORWARD_ETH_CALLS: true
ETH_CHAIN_ID: "${{ env.ETH_CHAIN_ID }}"
ETH_CHAIN_CONFIG: "${{ env.ETH_CHAIN_CONFIG }}"
DEPLOYER_PRIVATE_KEY: "${{ env.DEPLOYER_PRIVATE_KEY }}"
run: docker compose -f test/compose-server.yml up --wait
- name: "Run tests"
env:
ETH_CHAIN_ID: "${{ env.ETH_CHAIN_ID }}"
ETH_HTTP_PATH: "${{ env.ETH_HTTP_PATH }}"
run: |
echo vulcanize_go_ethereum=$GITHUB_WORKSPACE/go-ethereum/ > ./config.sh
echo vulcanize_ipld_eth_db=$GITHUB_WORKSPACE/ipld-eth-db/ >> ./config.sh
echo vulcanize_ipld_eth_server=$GITHUB_WORKSPACE/ipld-eth-server/ >> ./config.sh
echo vulcanize_test_contract=$GITHUB_WORKSPACE/ipld-eth-server/test/contract >>./config.sh
echo genesis_file_path=start-up-files/go-ethereum/genesis.json >> ./config.sh
echo db_write=$DB_WRITE >> ./config.sh
echo eth_forward_eth_calls=$ETH_FORWARD_ETH_CALLS >> ./config.sh
echo eth_proxy_on_error=$ETH_PROXY_ON_ERROR >> ./config.sh
echo eth_http_path=$ETH_HTTP_PATH >> ./config.sh
cat ./config.sh
- name: Build geth
run: |
cd $GITHUB_WORKSPACE/stack-orchestrator/helper-scripts
./compile-geth.sh \
-p "$GITHUB_WORKSPACE/config.sh" \
-e docker
- name: Run docker compose
run: |
docker-compose \
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/local/docker-compose-db-sharding.yml" \
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/local/docker-compose-go-ethereum.yml" \
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/local/docker-compose-ipld-eth-server.yml" \
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/local/docker-compose-contract.yml" \
--env-file "$GITHUB_WORKSPACE/config.sh" \
up -d --build
- name: Test
run: |
cd $GITHUB_WORKSPACE/ipld-eth-server
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
go install github.com/onsi/ginkgo/v2/ginkgo
ginkgo -v --label-filter 'proxy' -r ./test

View File

@ -1,6 +1,6 @@
FROM golang:1.19-alpine as builder
RUN apk --update --no-cache add make git g++ linux-headers
RUN apk --update --no-cache add gcc musl-dev
# DEBUG
RUN apk add busybox-extras
@ -19,12 +19,12 @@ 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 .
RUN GOOS=linux go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o ipld-eth-server .
# Copy migration tool
# Get migration tool
WORKDIR /
ARG GOOSE_VER="v2.6.0"
ADD https://github.com/pressly/goose/releases/download/${GOOSE_VER}/goose-linux64 ./goose
ARG GOOSE_VER="v3.6.1"
ADD https://github.com/pressly/goose/releases/download/${GOOSE_VER}/goose_linux_x86_64 ./goose
RUN chmod +x ./goose
# app container

View File

@ -33,9 +33,9 @@ External dependency
## Install
Start by downloading ipld-eth-server and moving into the repo:
`GO111MODULE=off go get -d github.com/cerc-io/ipld-eth-server/v4`
`GO111MODULE=off go get -d github.com/cerc-io/ipld-eth-server/v5`
`cd $GOPATH/src/github.com/cerc-io/ipld-eth-server/v4@v4.x.x`
`cd $GOPATH/src/github.com/cerc-io/ipld-eth-server/v5@v5.x.x`
Then, build the binary:
@ -67,11 +67,10 @@ The corresponding CLI flags can be found with the `./ipld-eth-server serve --hel
wsPath = "127.0.0.1:8081" # $SERVER_WS_PATH
httpPath = "127.0.0.1:8082" # $SERVER_HTTP_PATH
graphql = true # $SERVER_GRAPHQL
graphqlEndpoint = "" # $SERVER_GRAPHQL_ENDPOINT
graphqlPath = "" # $SERVER_GRAPHQL_PATH
[ethereum]
chainID = "1" # $ETH_CHAIN_ID
defaultSender = "" # $ETH_DEFAULT_SENDER_ADDR
rpcGasCap = "1000000000000" # $ETH_RPC_GAS_CAP
httpPath = "127.0.0.1:8545" # $ETH_HTTP_PATH
nodeID = "arch1" # $ETH_NODE_ID
@ -80,9 +79,9 @@ The corresponding CLI flags can be found with the `./ipld-eth-server serve --hel
networkID = "1" # $ETH_NETWORK_ID
```
The `database` fields are for connecting to a Postgres database that has been/is being populated by [ipld-eth-indexer](https://github.com/vulcanize/ipld-eth-indexer)
The `server` fields set the paths for exposing the ipld-eth-server endpoints
The `ethereum` fields set the chainID and default sender address to use for EVM simulation, and can optionally be used to configure a remote eth node to forward cache misses to
The `database` fields are for connecting to a Postgres database that has been/is being populated by [ipld-eth-indexer](https://github.com/vulcanize/ipld-eth-indexer)
The `server` fields set the paths for exposing the ipld-eth-server endpoints
The `ethereum` fields set the chainID and default sender address to use for EVM simulation, and can optionally be used to configure a remote eth node to forward cache misses to
### Endpoints
@ -92,61 +91,35 @@ TODO: Port the IPLD RPC subscription endpoints after the decoupling
#### Ethereum JSON-RPC
ipld-eth-server currently recapitulates portions of the Ethereum JSON-RPC api standard.
The currently supported standard endpoints are:
`eth_call`
`eth_getBalance`
`eth_getStorageAt`
`eth_getCode`
`eth_getProof`
`eth_blockNumber`
`eth_getHeaderByNumber`
`eth_getHeaderByHash`
`eth_getBlockByNumber`
`eth_getBlockByHash`
`eth_getTransactionCount`
`eth_getBlockTransactionCountByHash`
`eth_getBlockTransactionCountByNumber`
`eth_getTransactionByHash`
`eth_getRawTransactionByHash`
`eth_getTransactionByBlockHashAndIndex`
`eth_getTransactionByBlockNumberAndIndex`
`eth_getRawTransactionByBlockHashAndIndex`
`eth_getRawTransactionByBlockNumberAndIndex`
`eth_getTransactionReceipt`
`eth_getLogs`
`eth_getUncleCountByBlockHash`
`eth_getUncleCountByBlockNumber`
`eth_getUncleByBlockHashAndIndex`
`eth_getUncleByBlockNumberAndIndex`
The currently supported standard endpoints are:
`eth_call`
`eth_getBalance`
`eth_getStorageAt`
`eth_getCode`
`eth_getProof`
`eth_blockNumber`
`eth_getHeaderByNumber`
`eth_getHeaderByHash`
`eth_getBlockByNumber`
`eth_getBlockByHash`
`eth_getTransactionCount`
`eth_getBlockTransactionCountByHash`
`eth_getBlockTransactionCountByNumber`
`eth_getTransactionByHash`
`eth_getRawTransactionByHash`
`eth_getTransactionByBlockHashAndIndex`
`eth_getTransactionByBlockNumberAndIndex`
`eth_getRawTransactionByBlockHashAndIndex`
`eth_getRawTransactionByBlockNumberAndIndex`
`eth_getTransactionReceipt`
`eth_getLogs`
`eth_getUncleCountByBlockHash`
`eth_getUncleCountByBlockNumber`
`eth_getUncleByBlockHashAndIndex`
`eth_getUncleByBlockNumberAndIndex`
TODO: Add the rest of the standard endpoints and unique endpoints (e.g. getSlice)
### CLI Options and Environment variables
| CLI Option | Environment Variable | Default Value | Comment |
| ----------------------------- | ----------------------------- | ---------------- | ----------------------------------- |
| `database-hostname` | `DATABASE_HOSTNAME` | localhost | IPLD database host |
| `database-port` | `DATABASE_PORT` | 5432 | IPLD database port |
| `database-name` | `DATABASE_NAME` | vulcanize_public | IPLD database name |
| `database-user` | `DATABASE_USER` | | IPLD database user |
| `database-password` | `DATABASE_PASSWORD` | | IPLD database password |
| `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-http` | `ETH_SERVER_HTTP` | true | If `true` enable Eth HTTP JSON-RPC Server |
| `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-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-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-path` | `IPLD_SERVER_GRAPHQLPATH` | | If `ipld-server-graphql` set to true, endpoint url for graphql server (host:port) |
| `ipld-postgraphile-path` | `IPLD_POSTGRAPHILEPATH` | | If `ipld-server-graphql` set to true, http url for postgraphile server on top of IPLD db |
| `tracing-http-path` | `TRACING_HTTPPATH` | | If `ipld-server-graphql` set to true, http url for tracing server |
| `tracing-postgraphile-path` | `TRACING.POSTGRAPHILEPATH` | | If `ipld-server-graphql` set to true, http url for postgraphile server on top of tracing db |
### Testing
Follow steps in [test/README.md](./test/README.md)

View File

@ -1,16 +0,0 @@
{
"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
}
}

View File

@ -25,8 +25,8 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
"github.com/cerc-io/ipld-eth-server/v4/pkg/prom"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
"github.com/cerc-io/ipld-eth-server/v5/pkg/prom"
)
var (

View File

@ -25,17 +25,16 @@ import (
"sync"
"time"
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
"github.com/ethereum/go-ethereum/rpc"
"github.com/mailgun/groupcache/v2"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/vulcanize/gap-filler/pkg/mux"
"github.com/cerc-io/ipld-eth-server/v4/pkg/graphql"
srpc "github.com/cerc-io/ipld-eth-server/v4/pkg/rpc"
s "github.com/cerc-io/ipld-eth-server/v4/pkg/serve"
v "github.com/cerc-io/ipld-eth-server/v4/version"
"github.com/cerc-io/ipld-eth-server/v5/pkg/graphql"
srpc "github.com/cerc-io/ipld-eth-server/v5/pkg/rpc"
s "github.com/cerc-io/ipld-eth-server/v5/pkg/serve"
v "github.com/cerc-io/ipld-eth-server/v5/version"
)
var ErrNoRpcEndpoints = errors.New("no rpc endpoints is available")
@ -44,9 +43,7 @@ var ErrNoRpcEndpoints = errors.New("no rpc endpoints is available")
var serveCmd = &cobra.Command{
Use: "serve",
Short: "serve chain data from PG-IPFS",
Long: `This command configures a VulcanizeDB ipld-eth-server.
`,
Long: `This command configures a VulcanizeDB ipld-eth-server.`,
Run: func(cmd *cobra.Command, args []string) {
subCommand = cmd.CalledAs()
logWithCommand = *log.WithField("SubCommand", subCommand)
@ -55,22 +52,28 @@ var serveCmd = &cobra.Command{
}
func serve() {
logWithCommand.Infof("running ipld-eth-server version: %s", v.VersionWithMeta)
logWithCommand.Infof("ipld-eth-server version: %s", v.VersionWithMeta)
wg := new(sync.WaitGroup)
logWithCommand.Debug("loading server configuration variables")
serverConfig, err := s.NewConfig()
if err != nil {
logWithCommand.Fatal(err)
}
logWithCommand.Infof("server config: %+v", serverConfig)
logWithCommand.Debug("initializing new server service")
logWithCommand.Debug("server config: %+v", serverConfig)
server, err := s.NewServer(serverConfig)
if err != nil {
logWithCommand.Fatal(err)
}
if serverConfig.ForwardEthCalls {
logWithCommand.Info("Fowarding eth_call")
}
if serverConfig.ForwardGetStorageAt {
logWithCommand.Info("Fowarding eth_getStorageAt")
}
if serverConfig.ProxyOnError {
logWithCommand.Info("Proxy on error is enabled")
}
logWithCommand.Info("starting up server servers")
server.Serve(wg)
if err := startServers(server, serverConfig); err != nil {
logWithCommand.Fatal(err)
@ -80,11 +83,6 @@ func serve() {
logWithCommand.Fatal(err)
}
err = startIpldGraphQL(serverConfig)
if err != nil {
logWithCommand.Fatal(err)
}
err = startGroupCacheService(serverConfig)
if err != nil {
logWithCommand.Fatal(err)
@ -94,7 +92,7 @@ func serve() {
go startStateTrieValidator(serverConfig, server)
logWithCommand.Info("state validator enabled")
} else {
logWithCommand.Info("state validator disabled")
logWithCommand.Debug("state validator disabled")
}
shutdown := make(chan os.Signal, 1)
@ -109,33 +107,33 @@ func serve() {
func startServers(server s.Server, settings *s.Config) error {
if settings.IPCEnabled {
logWithCommand.Info("starting up IPC server")
logWithCommand.Debug("starting up IPC server")
_, _, err := srpc.StartIPCEndpoint(settings.IPCEndpoint, server.APIs())
if err != nil {
return err
}
} else {
logWithCommand.Info("IPC server is disabled")
logWithCommand.Debug("IPC server is disabled")
}
if settings.WSEnabled {
logWithCommand.Info("starting up WS server")
logWithCommand.Debug("starting up WS server")
_, _, err := srpc.StartWSEndpoint(settings.WSEndpoint, server.APIs(), []string{"vdb", "net"}, nil)
if err != nil {
return err
}
} else {
logWithCommand.Info("WS server is disabled")
logWithCommand.Debug("WS server is disabled")
}
if settings.HTTPEnabled {
logWithCommand.Info("starting up HTTP server")
logWithCommand.Debug("starting up HTTP server")
_, err := srpc.StartHTTPEndpoint(settings.HTTPEndpoint, server.APIs(), []string{"vdb", "eth", "debug", "net"}, nil, []string{"*"}, rpc.HTTPTimeouts{})
if err != nil {
return err
}
} else {
logWithCommand.Info("HTTP server is disabled")
logWithCommand.Debug("HTTP server is disabled")
}
return nil
@ -143,7 +141,7 @@ func startServers(server s.Server, settings *s.Config) error {
func startEthGraphQL(server s.Server, settings *s.Config) (graphQLServer *graphql.Service, err error) {
if settings.EthGraphqlEnabled {
logWithCommand.Info("starting up ETH GraphQL server")
logWithCommand.Debug("starting up ETH GraphQL server")
endPoint := settings.EthGraphqlEndpoint
if endPoint != "" {
graphQLServer, err = graphql.New(server.Backend(), endPoint, nil, []string{"*"}, rpc.HTTPTimeouts{})
@ -153,69 +151,17 @@ func startEthGraphQL(server s.Server, settings *s.Config) (graphQLServer *graphq
err = graphQLServer.Start(nil)
}
} else {
logWithCommand.Info("ETH GraphQL server is disabled")
logWithCommand.Debug("ETH GraphQL server is disabled")
}
return
}
func startIpldGraphQL(settings *s.Config) error {
if settings.IpldGraphqlEnabled {
logWithCommand.Info("starting up IPLD GraphQL server")
gqlIpldAddr, err := url.Parse(settings.IpldPostgraphileEndpoint)
if err != nil {
return err
}
gqlTracingAPIAddr, err := url.Parse(settings.TracingPostgraphileEndpoint)
if err != nil {
return err
}
ethClients, err := parseRpcAddresses(settings.EthHttpEndpoint)
if err != nil {
return err
}
var tracingClients []*rpc.Client
tracingEndpoint := viper.GetString("tracing.httpPath")
if tracingEndpoint != "" {
tracingClients, err = parseRpcAddresses(tracingEndpoint)
if err != nil {
return err
}
}
router, err := mux.NewServeMux(&mux.Options{
BasePath: "/",
EnableGraphiQL: true,
Postgraphile: mux.PostgraphileOptions{
Default: gqlIpldAddr,
TracingAPI: gqlTracingAPIAddr,
},
RPC: mux.RPCOptions{
DefaultClients: ethClients,
TracingClients: tracingClients,
},
})
if err != nil {
return err
}
go http.ListenAndServe(settings.IpldGraphqlEndpoint, router)
} else {
logWithCommand.Info("IPLD GraphQL server is disabled")
}
return nil
}
func startGroupCacheService(settings *s.Config) error {
gcc := settings.GroupCache
if gcc.Pool.Enabled {
logWithCommand.Info("starting up groupcache pool HTTTP server")
logWithCommand.Debug("starting up groupcache pool HTTTP server")
pool := groupcache.NewHTTPPoolOpts(gcc.Pool.HttpEndpoint, &groupcache.HTTPPoolOptions{})
pool.Set(gcc.Pool.PeerHttpEndpoints...)
@ -233,9 +179,9 @@ func startGroupCacheService(settings *s.Config) error {
// Start a HTTP server to listen for peer requests from the groupcache
go server.ListenAndServe()
logWithCommand.Infof("groupcache pool endpoint opened for url %s", httpURL)
logWithCommand.Infof("groupcache pool endpoint opened at %s", httpURL)
} else {
logWithCommand.Info("Groupcache pool is disabled")
logWithCommand.Debug("Groupcache pool is disabled")
}
return nil
@ -316,21 +262,14 @@ func init() {
// flags for all config variables
// eth graphql and json-rpc parameters
serveCmd.PersistentFlags().Bool("eth-server-graphql", false, "turn on the eth graphql server")
serveCmd.PersistentFlags().String("eth-server-graphql-path", "", "endpoint url for eth graphql server (host:port)")
serveCmd.PersistentFlags().Bool("eth-server-http", true, "turn on the eth http json-rpc server")
serveCmd.PersistentFlags().String("eth-server-http-path", "", "endpoint url for eth http json-rpc server (host:port)")
serveCmd.PersistentFlags().Bool("eth-server-ws", false, "turn on the eth websocket json-rpc server")
serveCmd.PersistentFlags().String("eth-server-ws-path", "", "endpoint url for eth websocket json-rpc server (host:port)")
serveCmd.PersistentFlags().Bool("eth-server-ipc", false, "turn on the eth ipc json-rpc server")
serveCmd.PersistentFlags().String("eth-server-ipc-path", "", "path for eth ipc json-rpc server")
// ipld and tracing graphql parameters
serveCmd.PersistentFlags().Bool("ipld-server-graphql", false, "turn on the ipld graphql server")
serveCmd.PersistentFlags().String("ipld-server-graphql-path", "", "endpoint url for ipld graphql server (host:port)")
serveCmd.PersistentFlags().String("ipld-postgraphile-path", "", "http url to postgraphile on top of ipld database")
serveCmd.PersistentFlags().String("tracing-http-path", "", "http url to tracing service")
serveCmd.PersistentFlags().String("tracing-postgraphile-path", "", "http url to postgraphile on top of tracing db")
serveCmd.PersistentFlags().Bool("server-graphql", false, "turn on the eth graphql server")
serveCmd.PersistentFlags().String("server-graphql-path", "", "endpoint url for eth graphql server (host:port)")
serveCmd.PersistentFlags().Bool("server-http", true, "turn on the eth http json-rpc server")
serveCmd.PersistentFlags().String("server-http-path", "", "endpoint url for eth http json-rpc server (host:port)")
serveCmd.PersistentFlags().Bool("server-ws", false, "turn on the eth websocket json-rpc server")
serveCmd.PersistentFlags().String("server-ws-path", "", "endpoint url for eth websocket json-rpc server (host:port)")
serveCmd.PersistentFlags().Bool("server-ipc", false, "turn on the eth ipc json-rpc server")
serveCmd.PersistentFlags().String("server-ipc-path", "", "path for eth ipc json-rpc server")
serveCmd.PersistentFlags().String("eth-http-path", "", "http url for ethereum node")
serveCmd.PersistentFlags().String("eth-node-id", "", "eth node id")
@ -359,27 +298,20 @@ func init() {
// and their bindings
// eth graphql server
viper.BindPFlag("eth.server.graphql", serveCmd.PersistentFlags().Lookup("eth-server-graphql"))
viper.BindPFlag("eth.server.graphqlPath", serveCmd.PersistentFlags().Lookup("eth-server-graphql-path"))
viper.BindPFlag("server.graphql", serveCmd.PersistentFlags().Lookup("server-graphql"))
viper.BindPFlag("server.graphqlPath", serveCmd.PersistentFlags().Lookup("server-graphql-path"))
// eth http json-rpc server
viper.BindPFlag("eth.server.http", serveCmd.PersistentFlags().Lookup("eth-server-http"))
viper.BindPFlag("eth.server.httpPath", serveCmd.PersistentFlags().Lookup("eth-server-http-path"))
viper.BindPFlag("server.http", serveCmd.PersistentFlags().Lookup("server-http"))
viper.BindPFlag("server.httpPath", serveCmd.PersistentFlags().Lookup("server-http-path"))
// eth websocket json-rpc server
viper.BindPFlag("eth.server.ws", serveCmd.PersistentFlags().Lookup("eth-server-ws"))
viper.BindPFlag("eth.server.wsPath", serveCmd.PersistentFlags().Lookup("eth-server-ws-path"))
viper.BindPFlag("server.ws", serveCmd.PersistentFlags().Lookup("server-ws"))
viper.BindPFlag("server.wsPath", serveCmd.PersistentFlags().Lookup("server-ws-path"))
// eth ipc json-rpc server
viper.BindPFlag("eth.server.ipc", serveCmd.PersistentFlags().Lookup("eth-server-ipc"))
viper.BindPFlag("eth.server.ipcPath", serveCmd.PersistentFlags().Lookup("eth-server-ipc-path"))
// ipld and tracing graphql parameters
viper.BindPFlag("ipld.server.graphql", serveCmd.PersistentFlags().Lookup("ipld-server-graphql"))
viper.BindPFlag("ipld.server.graphqlPath", serveCmd.PersistentFlags().Lookup("ipld-server-graphql-path"))
viper.BindPFlag("ipld.postgraphilePath", serveCmd.PersistentFlags().Lookup("ipld-postgraphile-path"))
viper.BindPFlag("tracing.httpPath", serveCmd.PersistentFlags().Lookup("tracing-http-path"))
viper.BindPFlag("tracing.postgraphilePath", serveCmd.PersistentFlags().Lookup("tracing-postgraphile-path"))
viper.BindPFlag("server.ipc", serveCmd.PersistentFlags().Lookup("server-ipc"))
viper.BindPFlag("server.ipcPath", serveCmd.PersistentFlags().Lookup("server-ipc-path"))
viper.BindPFlag("ethereum.httpPath", serveCmd.PersistentFlags().Lookup("eth-http-path"))
viper.BindPFlag("ethereum.nodeID", serveCmd.PersistentFlags().Lookup("eth-node-id"))
@ -387,7 +319,6 @@ func init() {
viper.BindPFlag("ethereum.genesisBlock", serveCmd.PersistentFlags().Lookup("eth-genesis-block"))
viper.BindPFlag("ethereum.networkID", serveCmd.PersistentFlags().Lookup("eth-network-id"))
viper.BindPFlag("ethereum.chainID", serveCmd.PersistentFlags().Lookup("eth-chain-id"))
viper.BindPFlag("ethereum.defaultSender", serveCmd.PersistentFlags().Lookup("eth-default-sender"))
viper.BindPFlag("ethereum.rpcGasCap", serveCmd.PersistentFlags().Lookup("eth-rpc-gas-cap"))
viper.BindPFlag("ethereum.chainConfig", serveCmd.PersistentFlags().Lookup("eth-chain-config"))
viper.BindPFlag("ethereum.supportsStateDiff", serveCmd.PersistentFlags().Lookup("eth-supports-state-diff"))

View File

@ -18,14 +18,14 @@ package cmd
import (
"time"
validator "github.com/cerc-io/eth-ipfs-state-validator/v4/pkg"
ipfsethdb "github.com/cerc-io/ipfs-ethdb/v4/postgres"
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
validator "github.com/cerc-io/eth-ipfs-state-validator/v5/pkg"
ipfsethdb "github.com/cerc-io/ipfs-ethdb/v5/postgres/v0"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
"github.com/ethereum/go-ethereum/common"
"github.com/spf13/cobra"
"github.com/spf13/viper"
s "github.com/cerc-io/ipld-eth-server/v4/pkg/serve"
s "github.com/cerc-io/ipld-eth-server/v5/pkg/serve"
)
const GroupName = "statedb-validate"
@ -34,7 +34,7 @@ const CacheSizeInMB = 16 // 16 MB
var validateCmd = &cobra.Command{
Use: "validate",
Short: "valdiate state",
Short: "validate state",
Long: `This command validates the trie for the given state root`,
Run: func(cmd *cobra.Command, args []string) {
subCommand = cmd.CalledAs()

View File

@ -16,19 +16,17 @@
package cmd
import (
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
"github.com/spf13/cobra"
v "github.com/cerc-io/ipld-eth-server/v4/version"
v "github.com/cerc-io/ipld-eth-server/v5/version"
)
// versionCmd represents the version command
var versionCmd = &cobra.Command{
Use: "version",
Short: "Prints the version of ipld-eth-server",
Long: `Use this command to fetch the version of ipld-eth-server
Usage: ./ipld-eth-server version`,
Long: `Use this command to fetch the version of ipld-eth-server`,
Run: func(cmd *cobra.Command, args []string) {
subCommand = cmd.CalledAs()
logWithCommand = *log.WithField("SubCommand", subCommand)

View File

@ -1,12 +0,0 @@
version: '3.2'
services:
contract:
build:
context: ./test/contract
args:
ETH_ADDR: "http://go-ethereum:8545"
environment:
ETH_ADDR: "http://go-ethereum:8545"
ports:
- "127.0.0.1:3000:3000"

View File

@ -1,59 +0,0 @@
version: '3.2'
services:
migrations:
restart: on-failure
depends_on:
- ipld-eth-db
image: git.vdb.to/cerc-io/ipld-eth-db/ipld-eth-db:v5.0.0-alpha
environment:
DATABASE_USER: "vdbm"
DATABASE_NAME: "vulcanize_testing"
DATABASE_PASSWORD: "password"
DATABASE_HOSTNAME: "ipld-eth-db"
DATABASE_PORT: 5432
ipld-eth-db:
image: timescale/timescaledb:latest-pg14
restart: always
command: ["postgres", "-c", "log_statement=all"]
environment:
POSTGRES_USER: "vdbm"
POSTGRES_DB: "vulcanize_testing"
POSTGRES_PASSWORD: "password"
ports:
- "127.0.0.1:8077:5432"
eth-server:
restart: unless-stopped
depends_on:
- ipld-eth-db
build:
context: ./
cache_from:
- alpine:latest
- golang:1.13-alpine
environment:
IPLD_SERVER_GRAPHQL: "true"
IPLD_POSTGRAPHILEPATH: http://graphql:5000
ETH_SERVER_HTTPPATH: 0.0.0.0:8081
VDB_COMMAND: "serve"
ETH_CHAIN_CONFIG: "/tmp/chain.json"
DATABASE_NAME: "vulcanize_testing"
DATABASE_HOSTNAME: "ipld-eth-db"
DATABASE_PORT: 5432
DATABASE_USER: "vdbm"
DATABASE_PASSWORD: "password"
ETH_CHAIN_ID: 4
ETH_FORWARD_ETH_CALLS: $ETH_FORWARD_ETH_CALLS
ETH_PROXY_ON_ERROR: $ETH_PROXY_ON_ERROR
ETH_HTTP_PATH: $ETH_HTTP_PATH
volumes:
- type: bind
source: ./chain.json
target: /tmp/chain.json
ports:
- "127.0.0.1:8081:8081"
volumes:
vdb_db_eth_server:

View File

@ -40,9 +40,9 @@ An example of how to subscribe to a real-time Ethereum data feed from ipld-eth-s
"github.com/ethereum/go-ethereum/rpc"
"github.com/spf13/viper"
"github.com/cerc-io/ipld-eth-server/v4/pkg/client"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v4/pkg/watch"
"github.com/cerc-io/ipld-eth-server/v5/pkg/client"
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v5/pkg/watch"
)
config, _ := eth.NewEthSubscriptionConfig()
@ -160,9 +160,9 @@ An example of how to subscribe to a real-time Bitcoin data feed from ipld-eth-se
"github.com/ethereum/go-ethereum/rpc"
"github.com/spf13/viper"
"github.com/vulcanize/ipld-eth-server/v4/pkg/btc"
"github.com/vulcanize/ipld-eth-server/v4/pkg/client"
"github.com/vulcanize/ipld-eth-server/v4/pkg/watch"
"github.com/vulcanize/ipld-eth-server/v5/pkg/btc"
"github.com/vulcanize/ipld-eth-server/v5/pkg/client"
"github.com/vulcanize/ipld-eth-server/v5/pkg/watch"
)
config, _ := btc.NewBtcSubscriptionConfig()

View File

@ -1,5 +1,5 @@
[database]
name = "vulcanize_public" # $DATABASE_NAME
name = "cerc_testing" # $DATABASE_NAME
hostname = "localhost" # $DATABASE_HOSTNAME
port = 5432 # $DATABASE_PORT
user = "postgres" # $DATABASE_USER
@ -9,16 +9,18 @@
level = "info" # $LOGRUS_LEVEL
[server]
ipc = false
ipcPath = "~/.vulcanize/vulcanize.ipc" # $SERVER_IPC_PATH
wsPath = "127.0.0.1:8081" # $SERVER_WS_PATH
httpPath = "127.0.0.1:8082" # $SERVER_HTTP_PATH
ws = true
wsPath = "127.0.0.1:8080" # $SERVER_WS_PATH
http = true
httpPath = "127.0.0.1:8081" # $SERVER_HTTP_PATH
graphql = true # $SERVER_GRAPHQL
graphqlEndpoint = "127.0.0.1:8083" # $SERVER_GRAPHQL_ENDPOINT
graphqlPath = "127.0.0.1:8082" # $SERVER_GRAPHQL_PATH
[ethereum]
chainConfig = "./chain.json" # ETH_CHAIN_CONFIG
chainID = "1" # $ETH_CHAIN_ID
defaultSender = "" # $ETH_DEFAULT_SENDER_ADDR
rpcGasCap = "1000000000000" # $ETH_RPC_GAS_CAP
httpPath = "127.0.0.1:8545" # $ETH_HTTP_PATH
supportsStateDiff = true # $ETH_SUPPORTS_STATEDIFF

65
go.mod
View File

@ -1,30 +1,28 @@
module github.com/cerc-io/ipld-eth-server/v4
module github.com/cerc-io/ipld-eth-server/v5
go 1.19
require (
github.com/cerc-io/eth-ipfs-state-validator/v4 v4.0.15-alpha
github.com/cerc-io/ipfs-ethdb/v4 v4.0.13-alpha
github.com/cerc-io/eth-ipfs-state-validator/v5 v5.0.0-alpha
github.com/cerc-io/ipfs-ethdb/v5 v5.0.0-alpha
github.com/cerc-io/ipld-eth-statedb v0.0.5-alpha
github.com/ethereum/go-ethereum v1.11.5
github.com/google/uuid v1.3.0
github.com/graph-gophers/graphql-go v1.3.0
github.com/ipfs/go-block-format v0.0.3
github.com/ipfs/go-cid v0.3.2
github.com/ipfs/go-ipfs-blockstore v1.2.0
github.com/ipfs/go-ipfs-ds-help v1.1.0
github.com/ipfs/go-ipld-format v0.4.0
github.com/jmoiron/sqlx v1.3.5
github.com/joho/godotenv v1.4.0
github.com/lib/pq v1.10.7
github.com/machinebox/graphql v0.2.2
github.com/mailgun/groupcache/v2 v2.3.0
github.com/multiformats/go-multihash v0.2.1
github.com/onsi/ginkgo v1.16.5
github.com/onsi/gomega v1.24.0
github.com/onsi/ginkgo/v2 v2.9.2
github.com/onsi/gomega v1.27.4
github.com/prometheus/client_golang v1.14.0
github.com/sirupsen/logrus v1.9.0
github.com/spf13/cobra v1.4.0
github.com/spf13/viper v1.11.0
github.com/vulcanize/gap-filler v0.4.2
gorm.io/driver/postgres v1.3.7
gorm.io/gorm v1.23.5
)
@ -38,6 +36,7 @@ require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
@ -64,30 +63,28 @@ require (
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect
github.com/flynn/noise v1.0.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/friendsofgo/graphiql v0.2.2 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
github.com/georgysavva/scany v1.2.1 // indirect
github.com/getsentry/sentry-go v0.17.0 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/getsentry/sentry-go v0.18.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.3.0 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/pprof v0.0.0-20221203041831-ce31453925ec // indirect
github.com/google/pprof v0.0.0-20230406165453-00490a63f317 // indirect
github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/graphql-go/graphql v0.7.9 // indirect
github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-bexpr v0.1.10 // indirect
@ -104,6 +101,7 @@ require (
github.com/ipfs/bbloom v0.0.4 // indirect
github.com/ipfs/go-bitfield v1.0.0 // indirect
github.com/ipfs/go-bitswap v0.11.0 // indirect
github.com/ipfs/go-block-format v0.0.3 // indirect
github.com/ipfs/go-blockservice v0.5.0 // indirect
github.com/ipfs/go-cidutil v0.1.0 // indirect
github.com/ipfs/go-datastore v0.6.0 // indirect
@ -113,8 +111,10 @@ require (
github.com/ipfs/go-filestore v1.2.0 // indirect
github.com/ipfs/go-fs-lock v0.0.7 // indirect
github.com/ipfs/go-graphsync v0.14.1 // indirect
github.com/ipfs/go-ipfs-blockstore v1.2.0 // indirect
github.com/ipfs/go-ipfs-chunker v0.0.5 // indirect
github.com/ipfs/go-ipfs-delay v0.0.1 // indirect
github.com/ipfs/go-ipfs-ds-help v1.1.0 // indirect
github.com/ipfs/go-ipfs-exchange-interface v0.2.0 // indirect
github.com/ipfs/go-ipfs-exchange-offline v0.3.0 // indirect
github.com/ipfs/go-ipfs-keystore v0.1.0 // indirect
@ -125,7 +125,6 @@ require (
github.com/ipfs/go-ipfs-routing v0.3.0 // indirect
github.com/ipfs/go-ipfs-util v0.0.2 // indirect
github.com/ipfs/go-ipld-cbor v0.0.6 // indirect
github.com/ipfs/go-ipld-format v0.4.0 // indirect
github.com/ipfs/go-ipld-legacy v0.1.1 // indirect
github.com/ipfs/go-ipns v0.3.0 // indirect
github.com/ipfs/go-libipfs v0.2.0 // indirect
@ -146,18 +145,17 @@ require (
github.com/ipld/go-codec-dagpb v1.5.0 // indirect
github.com/ipld/go-ipld-prime v0.19.0 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.12.1 // indirect
github.com/jackc/pgconn v1.14.0 // indirect
github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.3.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
github.com/jackc/pgtype v1.11.0 // indirect
github.com/jackc/pgx/v4 v4.16.1 // indirect
github.com/jackc/puddle v1.2.1 // indirect
github.com/jackc/pgproto3/v2 v2.3.2 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgtype v1.14.0 // indirect
github.com/jackc/pgx/v4 v4.18.1 // indirect
github.com/jackc/puddle v1.3.0 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect
github.com/jinzhu/copier v0.2.4 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.4 // indirect
github.com/klauspost/compress v1.15.15 // indirect
@ -217,9 +215,7 @@ require (
github.com/multiformats/go-multicodec v0.7.0 // indirect
github.com/multiformats/go-multistream v0.3.3 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/onsi/ginkgo/v2 v2.5.1 // indirect
github.com/opencontainers/runtime-spec v1.0.2 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
@ -230,7 +226,7 @@ require (
github.com/pkg/errors v0.9.1 // indirect
github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.37.1 // indirect
github.com/prometheus/common v0.39.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
@ -239,6 +235,7 @@ require (
github.com/samber/lo v1.36.0 // indirect
github.com/segmentio/fasthash v1.0.3 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/smartystreets/assertions v1.0.1 // indirect
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
@ -254,7 +251,6 @@ require (
github.com/tklauser/numcpus v0.6.0 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect
github.com/valyala/fastjson v1.6.3 // indirect
github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect
github.com/whyrusleeping/cbor-gen v0.0.0-20221220214510-0333c149dec0 // indirect
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect
@ -273,21 +269,20 @@ require (
go4.org v0.0.0-20200411211856-f5505b9728dd // indirect
golang.org/x/crypto v0.6.0 // indirect
golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect
golang.org/x/mod v0.7.0 // indirect
golang.org/x/net v0.6.0 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/net v0.9.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
golang.org/x/tools v0.3.0 // indirect
golang.org/x/tools v0.8.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.1.7 // indirect
)
replace github.com/ethereum/go-ethereum v1.11.5 => github.com/cerc-io/go-ethereum v1.11.5-statediff-4.3.9-alpha
replace github.com/ethereum/go-ethereum v1.11.5 => github.com/cerc-io/go-ethereum v1.11.5-statediff-5.0.5-alpha

116
go.sum
View File

@ -120,10 +120,10 @@ github.com/btcsuite/btcd v0.0.0-20190605094302-a0d1e3e36d50/go.mod h1:3J08xEfcug
github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94=
github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo=
github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k=
github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
@ -144,17 +144,18 @@ github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8
github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/ceramicnetwork/go-dag-jose v0.1.0 h1:yJ/HVlfKpnD3LdYP03AHyTvbm3BpPiz2oZiOeReJRdU=
github.com/cerc-io/eth-ipfs-state-validator/v4 v4.0.15-alpha h1:8jW+gtgbezgl0KxouCUXLNGPgsLLFYLqZVkXUNOw/1I=
github.com/cerc-io/eth-ipfs-state-validator/v4 v4.0.15-alpha/go.mod h1:iscV/XtO2CqnxNSj6mazN5Cxq0RNvupO4+gCKnZTV4U=
github.com/cerc-io/go-ethereum v1.11.5-statediff-4.3.9-alpha h1:nzy/bUmzq8ImRIxchClNoO7Bytom8ETDuOFHzuHFBXs=
github.com/cerc-io/go-ethereum v1.11.5-statediff-4.3.9-alpha/go.mod h1:Q4LXiMcJCctVW1uoIuF59VRCW1W+zrc5GkewoARwAmk=
github.com/cerc-io/ipfs-ethdb/v4 v4.0.13-alpha h1:9UBH+8rOmXTgO9w4qxqc8dHxBi5/z1wjz9tOxzrMDyY=
github.com/cerc-io/ipfs-ethdb/v4 v4.0.13-alpha/go.mod h1:HKzAT0Rvayc7XxKdTHubT40toKsCrqRyF9+F4fECcTc=
github.com/cerc-io/eth-ipfs-state-validator/v5 v5.0.0-alpha h1:TGCr/v0CrDsz1Mjr4000omuEGw7RNdn+OYqIivlF3+Q=
github.com/cerc-io/eth-ipfs-state-validator/v5 v5.0.0-alpha/go.mod h1:t+1UYws60dkLRecMN2NXl4LlKxQBLjhDh34swi6Jcvc=
github.com/cerc-io/go-ethereum v1.11.5-statediff-5.0.5-alpha h1:Rj/5+dDbYWa5k58g7h1jNytbWa0NY8IEKExFWaI8bcA=
github.com/cerc-io/go-ethereum v1.11.5-statediff-5.0.5-alpha/go.mod h1:DIk2wFexjyzvyjuzSOtBEIAPRNZTnLXNbIHEyq1Igek=
github.com/cerc-io/ipfs-ethdb/v5 v5.0.0-alpha h1:I1iXTaIjbTH8ehzNXmT2waXcYBifi1yjK6FK3W3a0Pg=
github.com/cerc-io/ipfs-ethdb/v5 v5.0.0-alpha/go.mod h1:EGAdV/YewEADFDDVF1k9GNwy8vNWR29Xb87sRHgMIng=
github.com/cerc-io/ipld-eth-statedb v0.0.5-alpha h1:olsE5OCvfTrQGLE5T2Z4VYOfx8n5ONgciKdEW5I0x3I=
github.com/cerc-io/ipld-eth-statedb v0.0.5-alpha/go.mod h1:6XprlGrhm65KkHesgcLwgIHWD0TvbkQ3T9ZsfBXKvsk=
github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
@ -287,8 +288,6 @@ github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVB
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/friendsofgo/graphiql v0.2.2 h1:ccnuxpjgIkB+Lr9YB2ZouiZm7wvciSfqwpa9ugWzmn0=
github.com/friendsofgo/graphiql v0.2.2/go.mod h1:8Y2kZ36AoTGWs78+VRpvATyt3LJBx0SZXmay80ZTRWo=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
@ -302,8 +301,8 @@ github.com/georgysavva/scany v1.2.1/go.mod h1:vGBpL5XRLOocMFFa55pj0P04DrL3I7qKVR
github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c=
github.com/getsentry/sentry-go v0.17.0 h1:UustVWnOoDFHBS7IJUB2QK/nB5pap748ZEp0swnQJak=
github.com/getsentry/sentry-go v0.17.0/go.mod h1:B82dxtBvxG0KaPD8/hfSV+VcHD+Lg/xUS4JuQn1P4cM=
github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0=
github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
@ -321,14 +320,13 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
@ -339,13 +337,14 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
@ -408,8 +407,9 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
@ -453,8 +453,8 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20221203041831-ce31453925ec h1:fR20TYVVwhK4O7r7y+McjRYyaTH6/vjwJOajE+XhlzM=
github.com/google/pprof v0.0.0-20221203041831-ce31453925ec/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
github.com/google/pprof v0.0.0-20230406165453-00490a63f317 h1:hFhpt7CTmR3DX+b4R19ydQFtofxT0Sv3QsKNMVQYTMQ=
github.com/google/pprof v0.0.0-20230406165453-00490a63f317/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@ -484,8 +484,6 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0=
github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
github.com/graphql-go/graphql v0.7.9 h1:5Va/Rt4l5g3YjwDnid3vFfn43faaQBq7rMcIZ0VnV34=
github.com/graphql-go/graphql v0.7.9/go.mod h1:k6yrAYQaSP59DC5UVxbgxESlmVyojThKdORUqGDGmrI=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
@ -771,8 +769,9 @@ github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpT
github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o=
github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY=
github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
github.com/jackc/pgconn v1.12.1 h1:rsDFzIpRk7xT4B8FufgpCCeyjdNpKyghZeSefViE5W8=
github.com/jackc/pgconn v1.12.1/go.mod h1:ZkhRC59Llhrq3oSfrikvwQ5NaxYExr6twkdkMLaKono=
github.com/jackc/pgconn v1.14.0 h1:vrbA9Ud87g6JdFWkHTJXppVce58qPIdP7N8y0Ml/A7Q=
github.com/jackc/pgconn v1.14.0/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E=
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
@ -789,11 +788,13 @@ github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:
github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgproto3/v2 v2.3.0 h1:brH0pCGBDkBW07HWlN/oSBXrmo3WB0UvZd1pIuDcL8Y=
github.com/jackc/pgproto3/v2 v2.3.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgproto3/v2 v2.3.2 h1:7eY55bdBeCz1F2fTzSz69QC+pG46jYq9/jtSPiJ5nn0=
github.com/jackc/pgproto3/v2 v2.3.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
@ -802,8 +803,9 @@ github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkAL
github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ=
github.com/jackc/pgtype v1.6.2/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig=
github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM=
github.com/jackc/pgtype v1.11.0 h1:u4uiGPz/1hryuXzyaBhSk6dnIyyG2683olG2OV+UUgs=
github.com/jackc/pgtype v1.11.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
github.com/jackc/pgtype v1.14.0 h1:y+xUdabmyMkJLyApYuPj38mW+aAIqCe5uuBB51rH3Vw=
github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
@ -812,15 +814,17 @@ github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6
github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg=
github.com/jackc/pgx/v4 v4.10.1/go.mod h1:QlrWebbs3kqEZPHCTGyxecvzG6tvIsYu+A5b1raylkA=
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
github.com/jackc/pgx/v4 v4.16.1 h1:JzTglcal01DrghUqt+PmzWsZx/Yh7SC/CTQmSBMTd0Y=
github.com/jackc/pgx/v4 v4.16.1/go.mod h1:SIhx0D5hoADaiXZVyv+3gSm3LCIIINTVO0PficsvWGQ=
github.com/jackc/pgx/v4 v4.18.1 h1:YP7G1KABtKpB5IHrO9vYwSrCOhs7p3uqhvhhQBptya0=
github.com/jackc/pgx/v4 v4.18.1/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE=
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.2.1 h1:gI8os0wpRXFd4FiAY2dWiqRK037tjj3t7rKFeO4X5iw=
github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.3.0 h1:eHK/5clGOatcjX3oWGBO/MpxpbHzSwud5EWTSCI+MX0=
github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA=
github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
@ -839,8 +843,6 @@ github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZl
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jinzhu/copier v0.2.4 h1:dT3tI+8GzU8DjJFCj9mLYtjfRtUmK7edauduQdcZCpI=
github.com/jinzhu/copier v0.2.4/go.mod h1:24xnZezI2Yqac9J61UC6/dG/k76ttpq0DdJI3QmUvro=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
@ -860,8 +862,6 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o=
@ -1256,7 +1256,6 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
@ -1358,8 +1357,8 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/ginkgo/v2 v2.5.1 h1:auzK7OI497k6x4OvWq+TKAcpcSAlod0doAH72oIN0Jw=
github.com/onsi/ginkgo/v2 v2.5.1/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc=
github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU=
github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts=
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
@ -1368,8 +1367,8 @@ github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoT
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
github.com/onsi/gomega v1.24.0 h1:+0glovB9Jd6z3VR+ScSwQqXVTIfJcGA9UBM8yzQxhqg=
github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
github.com/onsi/gomega v1.27.4 h1:Z2AnStgsdSayCMDiCU42qIz+HLqEPcgiOCXjAU/w+8E=
github.com/onsi/gomega v1.27.4/go.mod h1:riYq/GJKh8hhoM01HN6Vmuy93AarCXCBGpvFDK3q3fQ=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0=
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
@ -1432,8 +1431,6 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
@ -1451,10 +1448,8 @@ github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.37.1 h1:pYY6b5sGXqEB0WwcRGAoVGKbxVthy9qF17R4gbHZVe0=
github.com/prometheus/common v0.37.1/go.mod h1:jEuMeTn4pKGSAxwr7rXtOD70GeY0ERpt0d9FkKf9sK4=
github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI=
github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
@ -1462,7 +1457,6 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk=
@ -1627,15 +1621,11 @@ github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
github.com/valyala/fastjson v1.6.3 h1:tAKFnnwmeMGPbwJ7IwxcTPCNr3uIzoIj3/Fh90ra4xc=
github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
github.com/vulcanize/gap-filler v0.4.2 h1:agi++vcjvyPN53Ah17UWq7qpi2uKW/9asXqPiimDxKY=
github.com/vulcanize/gap-filler v0.4.2/go.mod h1:V5Qad/ihLQT4mI2EgWKNrXqGG5QqOKLHMQRnfFtbu68=
github.com/wangjia184/sortedset v0.0.0-20160527075905-f5d03557ba30/go.mod h1:YkocrP2K2tcw938x9gCOmT5G5eCD6jsTz0SZuyAqwIE=
github.com/warpfork/go-testmark v0.10.0 h1:E86YlUMYfwIacEsQGlnTvjk1IgYkyTGjPhF0RnwTCmw=
github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
@ -1829,8 +1819,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -1888,16 +1878,14 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -1909,8 +1897,6 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -2012,14 +1998,12 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -2029,13 +2013,13 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -2045,9 +2029,9 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -2129,8 +2113,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM=
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -16,7 +16,7 @@
package main
import (
"github.com/cerc-io/ipld-eth-server/v4/cmd"
"github.com/cerc-io/ipld-eth-server/v5/cmd"
)
func main() {

BIN
pkg/.DS_Store vendored

Binary file not shown.

View File

@ -25,9 +25,8 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/rpc"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth"
)
var _ tracers.Backend = &Backend{}
@ -43,9 +42,7 @@ type Backend struct {
// StateAtBlock retrieves the state database associated with a certain block
func (b *Backend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive, preferDisk bool) (*state.StateDB, tracers.StateReleaseFunc, error) {
rpcBlockNumber := rpc.BlockNumber(block.NumberU64())
statedb, _, err := b.StateAndHeaderByNumberOrHash(ctx, rpc.BlockNumberOrHashWithNumber(rpcBlockNumber))
return statedb, func() {}, err
return nil, func() {}, errMethodNotSupported
}
// StateAtTransaction returns the execution environment of a certain transaction

View File

@ -27,9 +27,6 @@ import (
"strconv"
"time"
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
ipld_eth_statedb "github.com/cerc-io/ipld-eth-statedb"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
@ -43,7 +40,9 @@ import (
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/statediff"
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
"github.com/cerc-io/ipld-eth-server/v5/pkg/shared"
ipld_direct_state "github.com/cerc-io/ipld-eth-statedb/direct_by_leaf"
)
const (
@ -165,10 +164,10 @@ func (pea *PublicEthAPI) BlockNumber() hexutil.Uint64 {
}
// GetBlockByNumber returns the requested canonical block.
// * When blockNr is -1 the chain head is returned.
// * We cannot support pending block calls since we do not have an active miner
// * When fullTx is true all transactions in the block are returned, otherwise
// only the transaction hash is returned.
// - When blockNr is -1 the chain head is returned.
// - We cannot support pending block calls since we do not have an active miner
// - When fullTx is true all transactions in the block are returned, otherwise
// only the transaction hash is returned.
func (pea *PublicEthAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
block, err := pea.B.BlockByNumber(ctx, number)
if block != nil && err == nil {
@ -612,6 +611,7 @@ func (pea *PublicEthAPI) localGetTransactionReceipt(ctx context.Context, hash co
from, _ := types.Sender(signer, tx)
fields := map[string]interface{}{
"type": hexutil.Uint64(receipt.Type),
"blockHash": blockHash,
"blockNumber": hexutil.Uint64(blockNumber),
"transactionHash": hash,
@ -780,7 +780,9 @@ State and Storage
// block numbers are also allowed.
func (pea *PublicEthAPI) GetBalance(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Big, error) {
bal, err := pea.localGetBalance(ctx, address, blockNrOrHash)
if bal != nil && err == nil {
if err != nil && err != sql.ErrNoRows {
return nil, err
} else if bal != nil {
return bal, nil
}
if pea.config.ProxyOnError {
@ -878,7 +880,7 @@ func (pea *PublicEthAPI) GetProof(ctx context.Context, address common.Address, s
// this continues to use ipfs-ethdb based geth StateDB as it requires trie access
func (pea *PublicEthAPI) localGetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (*AccountResult, error) {
state, _, err := pea.B.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
state, _, err := pea.B.IPLDTrieStateDBAndHeaderByNumberOrHash(ctx, blockNrOrHash)
if state == nil || err != nil {
return nil, err
}
@ -982,7 +984,7 @@ type OverrideAccount struct {
type StateOverride map[common.Address]OverrideAccount
// Apply overrides the fields of specified accounts into the given state.
func (diff *StateOverride) Apply(state *ipld_eth_statedb.StateDB) error {
func (diff *StateOverride) Apply(state *ipld_direct_state.StateDB) error {
if diff == nil {
return nil
}
@ -1059,7 +1061,7 @@ func DoCall(ctx context.Context, b *Backend, args CallArgs, blockNrOrHash rpc.Bl
log.Debugxf(ctx, "Executing EVM call finished %s runtime %s", time.Now().String(), time.Since(start).String())
}(time.Now())
state, header, err := b.IPLDStateDBAndHeaderByNumberOrHash(ctx, blockNrOrHash)
state, header, err := b.IPLDDirectStateDBAndHeaderByNumberOrHash(ctx, blockNrOrHash)
if state == nil || err != nil {
return nil, err
}
@ -1110,7 +1112,7 @@ func DoCall(ctx context.Context, b *Backend, args CallArgs, blockNrOrHash rpc.Bl
return nil, fmt.Errorf("execution aborted (timeout = %v)", timeout)
}
if err != nil {
return result, fmt.Errorf("err: %w (supplied gas %d)", err, args.Gas)
return result, fmt.Errorf("err: %w (supplied gas %d)", err, msg.GasLimit)
}
return result, nil
}
@ -1149,12 +1151,10 @@ func (pea *PublicEthAPI) writeStateDiffAt(height int64) {
defer cancel()
var data json.RawMessage
params := statediff.Params{
IntermediateStateNodes: true,
IntermediateStorageNodes: true,
IncludeBlock: true,
IncludeReceipts: true,
IncludeTD: true,
IncludeCode: true,
IncludeBlock: true,
IncludeReceipts: true,
IncludeTD: true,
IncludeCode: true,
}
log.Debugf("Calling statediff_writeStateDiffAt(%d)", height)
if err := pea.rpc.CallContext(ctx, &data, "statediff_writeStateDiffAt", uint64(height), params); err != nil {
@ -1172,12 +1172,10 @@ func (pea *PublicEthAPI) writeStateDiffFor(blockHash common.Hash) {
defer cancel()
var data json.RawMessage
params := statediff.Params{
IntermediateStateNodes: true,
IntermediateStorageNodes: true,
IncludeBlock: true,
IncludeReceipts: true,
IncludeTD: true,
IncludeCode: true,
IncludeBlock: true,
IncludeReceipts: true,
IncludeTD: true,
IncludeCode: true,
}
log.Debugf("Calling statediff_writeStateDiffFor(%s)", blockHash.Hex())
if err := pea.rpc.CallContext(ctx, &data, "statediff_writeStateDiffFor", blockHash, params); err != nil {

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package eth_test
package eth_api_test
import (
"context"
@ -31,14 +31,15 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/statediff/indexer/interfaces"
"github.com/ethereum/go-ethereum/statediff/indexer/ipld"
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
"github.com/jmoiron/sqlx"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth/test_helpers"
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth/test_helpers"
"github.com/cerc-io/ipld-eth-server/v5/pkg/shared"
)
var (
@ -50,7 +51,8 @@ var (
blockHash = test_helpers.MockBlock.Header().Hash()
baseFee = test_helpers.MockLondonBlock.BaseFee()
ctx = context.Background()
expectedBlock = map[string]interface{}{
expectedBlock = map[string]interface{}{
"number": (*hexutil.Big)(test_helpers.MockBlock.Number()),
"hash": test_helpers.MockBlock.Hash(),
"parentHash": test_helpers.MockBlock.ParentHash(),
@ -151,6 +153,7 @@ var (
"logsBloom": test_helpers.MockReceipts[0].Bloom,
"status": hexutil.Uint(test_helpers.MockReceipts[0].Status),
"effectiveGasPrice": (*hexutil.Big)(big.NewInt(100)),
"type": hexutil.Uint64(types.LegacyTxType),
}
expectedReceipt2 = map[string]interface{}{
"blockHash": blockHash,
@ -166,6 +169,7 @@ var (
"logsBloom": test_helpers.MockReceipts[1].Bloom,
"root": hexutil.Bytes(test_helpers.MockReceipts[1].PostState),
"effectiveGasPrice": (*hexutil.Big)(big.NewInt(200)),
"type": hexutil.Uint64(types.LegacyTxType),
}
expectedReceipt3 = map[string]interface{}{
"blockHash": blockHash,
@ -181,80 +185,78 @@ var (
"logsBloom": test_helpers.MockReceipts[2].Bloom,
"root": hexutil.Bytes(test_helpers.MockReceipts[2].PostState),
"effectiveGasPrice": (*hexutil.Big)(big.NewInt(150)),
"type": hexutil.Uint64(types.LegacyTxType),
}
)
var (
db *sqlx.DB
api *eth.PublicEthAPI
chainConfig = params.TestChainConfig
)
var _ = BeforeSuite(func() {
var (
err error
tx interfaces.Batch
)
db = shared.SetupDB()
indexAndPublisher := shared.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash())
backend, err := eth.NewEthBackend(db, &eth.Config{
ChainConfig: chainConfig,
VMConfig: vm.Config{},
RPCGasCap: big.NewInt(10000000000), // Max gas capacity for a rpc call.
GroupCacheConfig: &shared.GroupCacheConfig{
StateDB: shared.GroupConfig{
Name: "api_test",
CacheSizeInMB: 8,
CacheExpiryInMins: 60,
LogStatsIntervalInSecs: 0,
},
},
})
Expect(err).ToNot(HaveOccurred())
api, _ = eth.NewPublicEthAPI(backend, nil, eth.APIConfig{StateDiffTimeout: shared.DefaultStateDiffTimeout})
tx, err = indexAndPublisher.PushBlock(test_helpers.MockBlock, test_helpers.MockReceipts, test_helpers.MockBlock.Difficulty())
Expect(err).ToNot(HaveOccurred())
ipld := sdtypes.IPLD{
CID: ipld.Keccak256ToCid(ipld.RawBinary, test_helpers.CodeHash.Bytes()).String(),
Content: test_helpers.ContractCode,
}
err = indexAndPublisher.PushIPLD(tx, ipld)
Expect(err).ToNot(HaveOccurred())
for _, node := range test_helpers.MockStateNodes {
err = indexAndPublisher.PushStateNode(tx, node, test_helpers.MockBlock.Hash().String())
Expect(err).ToNot(HaveOccurred())
}
err = tx.Submit(err)
Expect(err).ToNot(HaveOccurred())
uncles := test_helpers.MockBlock.Uncles()
uncleHashes := make([]common.Hash, len(uncles))
for i, uncle := range uncles {
uncleHashes[i] = uncle.Hash()
}
expectedBlock["uncles"] = uncleHashes
// setting chain config to for london block
chainConfig.LondonBlock = big.NewInt(2)
indexAndPublisher = shared.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash())
tx, err = indexAndPublisher.PushBlock(test_helpers.MockLondonBlock, test_helpers.MockLondonReceipts, test_helpers.MockLondonBlock.Difficulty())
Expect(err).ToNot(HaveOccurred())
err = tx.Submit(err)
Expect(err).ToNot(HaveOccurred())
})
var _ = AfterSuite(func() { shared.TearDownDB(db) })
var _ = Describe("API", func() {
var (
db *sqlx.DB
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
// Note: if you focus one of the tests be sure to focus this and the defered It()
It("test init", func() {
var (
err error
tx interfaces.Batch
)
db = shared.SetupDB()
indexAndPublisher := shared.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash())
backend, err := eth.NewEthBackend(db, &eth.Config{
ChainConfig: chainConfig,
VMConfig: vm.Config{},
RPCGasCap: big.NewInt(10000000000), // Max gas capacity for a rpc call.
GroupCacheConfig: &shared.GroupCacheConfig{
StateDB: shared.GroupConfig{
Name: "api_test",
CacheSizeInMB: 8,
CacheExpiryInMins: 60,
LogStatsIntervalInSecs: 0,
},
},
})
Expect(err).ToNot(HaveOccurred())
api, _ = eth.NewPublicEthAPI(backend, nil, eth.APIConfig{false, false, false, false, shared.DefaultStateDiffTimeout})
tx, err = indexAndPublisher.PushBlock(test_helpers.MockBlock, test_helpers.MockReceipts, test_helpers.MockBlock.Difficulty())
Expect(err).ToNot(HaveOccurred())
ccHash := sdtypes.CodeAndCodeHash{
Hash: test_helpers.ContractCodeHash,
Code: test_helpers.ContractCode,
}
err = indexAndPublisher.PushCodeAndCodeHash(tx, ccHash)
Expect(err).ToNot(HaveOccurred())
for _, node := range test_helpers.MockStateNodes {
err = indexAndPublisher.PushStateNode(tx, node, test_helpers.MockBlock.Hash().String())
Expect(err).ToNot(HaveOccurred())
}
err = tx.Submit(err)
Expect(err).ToNot(HaveOccurred())
uncles := test_helpers.MockBlock.Uncles()
uncleHashes := make([]common.Hash, len(uncles))
for i, uncle := range uncles {
uncleHashes[i] = uncle.Hash()
}
expectedBlock["uncles"] = uncleHashes
// setting chain config to for london block
chainConfig.LondonBlock = big.NewInt(2)
indexAndPublisher = shared.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash())
tx, err = indexAndPublisher.PushBlock(test_helpers.MockLondonBlock, test_helpers.MockLondonReceipts, test_helpers.MockLondonBlock.Difficulty())
Expect(err).ToNot(HaveOccurred())
err = tx.Submit(err)
Expect(err).ToNot(HaveOccurred())
})
// Single test db tear down at end of all tests
defer It("test teardown", func() { shared.TearDownDB(db) })
/*
Headers and blocks
@ -329,12 +331,12 @@ var _ = Describe("API", func() {
It("Fetch BaseFee from london block by block number, returns `nil` for legacy block", func() {
block, err := api.GetBlockByNumber(ctx, number, false)
Expect(err).ToNot(HaveOccurred())
_, ok := block["baseFee"]
_, ok := block["baseFeePerGas"]
Expect(ok).To(Equal(false))
block, err = api.GetBlockByNumber(ctx, londonBlockNum, false)
Expect(err).ToNot(HaveOccurred())
Expect(block["baseFee"].(*big.Int)).To(Equal(baseFee))
Expect(block["baseFeePerGas"]).To(Equal((*hexutil.Big)(baseFee)))
})
It("Retrieves a block by number with uncles in correct order", func() {
block, err := api.GetBlockByNumber(ctx, londonBlockNum, false)
@ -383,11 +385,11 @@ var _ = Describe("API", func() {
It("Fetch BaseFee from london block by block hash, returns `nil` for legacy block", func() {
block, err := api.GetBlockByHash(ctx, test_helpers.MockBlock.Hash(), true)
Expect(err).ToNot(HaveOccurred())
_, ok := block["baseFee"]
_, ok := block["baseFeePerGas"]
Expect(ok).To(Equal(false))
block, err = api.GetBlockByHash(ctx, test_helpers.MockLondonBlock.Hash(), false)
Expect(err).ToNot(HaveOccurred())
Expect(block["baseFee"].(*big.Int)).To(Equal(baseFee))
Expect(block["baseFeePerGas"]).To(Equal((*hexutil.Big)(baseFee)))
})
It("Retrieves a block by hash with uncles in correct order", func() {
block, err := api.GetBlockByHash(ctx, test_helpers.MockLondonBlock.Hash(), false)

View File

@ -0,0 +1,29 @@
// VulcanizeDB
// Copyright © 2019 Vulcanize
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package eth_api_test
import (
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestETHSuite(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "ipld-eth-server/pkg/eth/api_test")
}

View File

@ -25,18 +25,12 @@ import (
"math/big"
"time"
validator "github.com/cerc-io/eth-ipfs-state-validator/v4/pkg"
ipfsethdb "github.com/cerc-io/ipfs-ethdb/v4/postgres"
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
ipld_eth_statedb "github.com/cerc-io/ipld-eth-statedb"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
@ -45,9 +39,17 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
ethServerShared "github.com/ethereum/go-ethereum/statediff/indexer/shared"
"github.com/ethereum/go-ethereum/statediff/indexer/ipld"
"github.com/ethereum/go-ethereum/trie"
"github.com/jmoiron/sqlx"
validator "github.com/cerc-io/eth-ipfs-state-validator/v5/pkg"
ipfsethdb "github.com/cerc-io/ipfs-ethdb/v5/postgres/v0"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
"github.com/cerc-io/ipld-eth-server/v5/pkg/shared"
ipld_direct_state "github.com/cerc-io/ipld-eth-statedb/direct_by_leaf"
ipld_sql "github.com/cerc-io/ipld-eth-statedb/sql"
ipld_trie_state "github.com/cerc-io/ipld-eth-statedb/trie_by_cid/state"
)
var (
@ -64,6 +66,9 @@ const (
StateDBGroupCacheName = "statedb"
)
// Backend handles all interactions with IPLD/SQL-backed Ethereum state.
// Note that this does not contain a geth state.StateDatabase, as it is not compatible with the
// IPFS v0 blockstore nor the leaf-key indexed SQL schema.
type Backend struct {
// underlying postgres db
DB *sqlx.DB
@ -72,10 +77,11 @@ type Backend struct {
Retriever *Retriever
// ethereum interfaces
EthDB ethdb.Database
StateDatabase state.Database
// We'll use this state.Database for eth_call and any place we don't need trie access
IpldStateDatabase ipld_eth_statedb.StateDatabase
EthDB ethdb.Database
// We use this state.Database for eth_call and any place we don't need trie access
IpldDirectStateDatabase ipld_direct_state.StateDatabase
// We use this where state must be accessed by trie
IpldTrieStateDatabase ipld_trie_state.Database
Config *Config
}
@ -83,7 +89,6 @@ type Backend struct {
type Config struct {
ChainConfig *params.ChainConfig
VMConfig vm.Config
DefaultSender *common.Address
RPCGasCap *big.Int
GroupCacheConfig *shared.GroupCacheConfig
}
@ -104,17 +109,14 @@ func NewEthBackend(db *sqlx.DB, c *Config) (*Backend, error) {
})
logStateDBStatsOnTimer(ethDB.(*ipfsethdb.Database), gcc)
ipldStateDB, err := ipld_eth_statedb.NewStateDatabaseWithSqlxPool(db)
if err != nil {
return nil, err
}
driver := ipld_sql.NewSQLXDriverFromPool(context.Background(), db)
return &Backend{
DB: db,
Retriever: r,
EthDB: ethDB,
StateDatabase: state.NewDatabase(ethDB),
IpldStateDatabase: ipldStateDB,
Config: c,
DB: db,
Retriever: r,
EthDB: ethDB,
IpldDirectStateDatabase: ipld_direct_state.NewStateDatabase(driver),
IpldTrieStateDatabase: ipld_trie_state.NewDatabase(ethDB),
Config: c,
}, nil
}
@ -123,27 +125,35 @@ func (b *Backend) ChainDb() ethdb.Database {
return b.EthDB
}
// HeaderByNumber gets the canonical header for the provided block number
func (b *Backend) HeaderByNumber(ctx context.Context, blockNumber rpc.BlockNumber) (*types.Header, error) {
func (b *Backend) normalizeBlockNumber(blockNumber rpc.BlockNumber) (int64, error) {
var err error
number := blockNumber.Int64()
if blockNumber == rpc.LatestBlockNumber {
number, err = b.Retriever.RetrieveLastBlockNumber()
if err != nil {
return nil, err
return 0, err
}
}
if blockNumber == rpc.EarliestBlockNumber {
number, err = b.Retriever.RetrieveFirstBlockNumber()
if err != nil {
return nil, err
return 0, err
}
}
if blockNumber == rpc.PendingBlockNumber {
return nil, errPendingBlockNumber
return 0, errPendingBlockNumber
}
if number < 0 {
return nil, errNegativeBlockNumber
return 0, errNegativeBlockNumber
}
return number, nil
}
// HeaderByNumber gets the canonical header for the provided block number
func (b *Backend) HeaderByNumber(ctx context.Context, blockNumber rpc.BlockNumber) (*types.Header, error) {
number, err := b.normalizeBlockNumber(blockNumber)
if err != nil {
return nil, err
}
_, canonicalHeaderRLP, err := b.GetCanonicalHeader(uint64(number))
if err != nil {
@ -156,23 +166,7 @@ func (b *Backend) HeaderByNumber(ctx context.Context, blockNumber rpc.BlockNumbe
// HeaderByHash gets the header for the provided block hash
func (b *Backend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
// Begin tx
tx, err := b.DB.Beginx()
if err != nil {
return nil, err
}
defer func() {
if p := recover(); p != nil {
shared.Rollback(tx)
panic(p)
} else if err != nil {
shared.Rollback(tx)
} else {
err = tx.Commit()
}
}()
_, headerRLP, err := b.Retriever.RetrieveHeaderByHash(tx, hash)
_, headerRLP, err := b.Retriever.RetrieveHeaderByHash(hash)
if err != nil {
return nil, err
}
@ -191,14 +185,16 @@ func (b *Backend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.Bl
return nil, err
}
if header == nil {
return nil, errors.New("header for hash not found")
return nil, errHeaderHashNotFound
}
canonicalHash, err := b.GetCanonicalHash(header.Number.Uint64())
if err != nil {
return nil, err
}
if blockNrOrHash.RequireCanonical && canonicalHash != hash {
return nil, errors.New("hash is not currently canonical")
if blockNrOrHash.RequireCanonical {
canonicalHash, err := b.GetCanonicalHash(header.Number.Uint64())
if err != nil {
return nil, err
}
if canonicalHash != hash {
return nil, errors.New("hash is not currently canonical")
}
}
return header, nil
}
@ -245,14 +241,16 @@ func (b *Backend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.Blo
return nil, err
}
if header == nil {
return nil, errors.New("header for hash not found")
return nil, errHeaderHashNotFound
}
canonicalHash, err := b.GetCanonicalHash(header.Number.Uint64())
if err != nil {
return nil, err
}
if blockNrOrHash.RequireCanonical && canonicalHash != hash {
return nil, errors.New("hash is not currently canonical")
if blockNrOrHash.RequireCanonical {
canonicalHash, err := b.GetCanonicalHash(header.Number.Uint64())
if err != nil {
return nil, err
}
if canonicalHash != hash {
return nil, errors.New("hash is not currently canonical")
}
}
block, err := b.BlockByHash(ctx, hash)
if err != nil {
@ -268,28 +266,10 @@ func (b *Backend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.Blo
// BlockByNumber returns the requested canonical block
func (b *Backend) BlockByNumber(ctx context.Context, blockNumber rpc.BlockNumber) (*types.Block, error) {
var err error
number := blockNumber.Int64()
if blockNumber == rpc.LatestBlockNumber {
number, err = b.Retriever.RetrieveLastBlockNumber()
if err != nil {
return nil, err
}
number, err := b.normalizeBlockNumber(blockNumber)
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
}
if number < 0 {
return nil, errNegativeBlockNumber
}
// Get the canonical hash
canonicalHash, err := b.GetCanonicalHash(uint64(number))
if err != nil {
if err == sql.ErrNoRows {
@ -360,12 +340,12 @@ func (b *Backend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Blo
}
// Compose everything together into a complete block
return types.NewBlock(header, transactions, uncles, receipts, new(trie.Trie)), err
return types.NewBlock(header, transactions, uncles, receipts, trie.NewEmpty(nil)), err
}
// GetHeaderByBlockHash retrieves header for a provided block hash
func (b *Backend) GetHeaderByBlockHash(tx *sqlx.Tx, hash common.Hash) (*types.Header, error) {
_, headerRLP, err := b.Retriever.RetrieveHeaderByHash(tx, hash)
_, headerRLP, err := b.Retriever.RetrieveHeaderByHash2(tx, hash)
if err != nil {
return nil, err
}
@ -376,11 +356,11 @@ func (b *Backend) GetHeaderByBlockHash(tx *sqlx.Tx, hash common.Hash) (*types.He
// CurrentHeader returns the current block's header
func (b *Backend) CurrentHeader() *types.Header {
block, err := b.BlockByNumber(context.Background(), rpc.LatestBlockNumber)
header, err := b.HeaderByNumber(context.Background(), rpc.LatestBlockNumber)
if err != nil {
return nil
}
return block.Header()
return header
}
// GetBody returns the the body for the provided block hash and number
@ -388,8 +368,11 @@ func (b *Backend) GetBody(ctx context.Context, hash common.Hash, number rpc.Bloc
if number < 0 || hash == (common.Hash{}) {
return nil, errors.New("invalid arguments; expect hash and no special block numbers")
}
block, bErr := b.BlockByHash(ctx, hash)
if block != nil && bErr == nil {
block, err := b.BlockByHash(ctx, hash)
if err != nil {
return nil, err
}
if block != nil {
return block.Body(), nil
}
return nil, errors.New("block body not found")
@ -403,7 +386,7 @@ func (b *Backend) GetUnclesByBlockHash(tx *sqlx.Tx, hash common.Hash) ([]*types.
}
uncles := make([]*types.Header, 0)
if err := rlp.DecodeBytes(uncleBytes, uncles); err != nil {
if err := rlp.DecodeBytes(uncleBytes, &uncles); err != nil {
return nil, err
}
@ -418,7 +401,7 @@ func (b *Backend) GetUnclesByBlockHashAndNumber(tx *sqlx.Tx, hash common.Hash, n
}
uncles := make([]*types.Header, 0)
if err := rlp.DecodeBytes(uncleBytes, uncles); err != nil {
if err := rlp.DecodeBytes(uncleBytes, &uncles); err != nil {
return nil, err
}
@ -594,10 +577,24 @@ func (b *Backend) GetLogs(ctx context.Context, hash common.Hash, number uint64)
return logs, nil
}
// StateAndHeaderByNumberOrHash returns the statedb and header for the provided block number or hash
func (b *Backend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) {
if blockNr, ok := blockNrOrHash.Number(); ok {
return b.StateAndHeaderByNumber(ctx, blockNr)
// IPLDStateDBAndHeaderByNumberOrHash returns the statedb and header for the provided block number or hash
func (b *Backend) IPLDDirectStateDBAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*ipld_direct_state.StateDB, *types.Header, error) {
if number, ok := blockNrOrHash.Number(); ok {
// Pending state is only known by the miner
if number == rpc.PendingBlockNumber {
return nil, nil, errPendingBlockNumber
}
// Otherwise resolve the block number and return its state
header, err := b.HeaderByNumber(ctx, number)
if err != nil {
return nil, nil, err
}
if header == nil {
return nil, nil, errHeaderNotFound
}
// TODO use GetCanonicalHeaderAndHash to avoid rehashing
statedb, err := ipld_direct_state.New(header.Hash(), b.IpldDirectStateDatabase)
return statedb, header, err
}
if hash, ok := blockNrOrHash.Hash(); ok {
header, err := b.HeaderByHash(ctx, hash)
@ -605,81 +602,66 @@ func (b *Backend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHas
return nil, nil, err
}
if header == nil {
return nil, nil, errors.New("header for hash not found")
return nil, nil, errHeaderHashNotFound
}
canonicalHash, err := b.GetCanonicalHash(header.Number.Uint64())
if err != nil {
return nil, nil, err
if blockNrOrHash.RequireCanonical {
canonicalHash, err := b.GetCanonicalHash(header.Number.Uint64())
if err != nil {
return nil, nil, err
}
if canonicalHash != hash {
return nil, nil, errors.New("hash is not currently canonical")
}
}
if blockNrOrHash.RequireCanonical && canonicalHash != hash {
return nil, nil, errors.New("hash is not currently canonical")
}
stateDb, err := state.New(header.Root, b.StateDatabase, nil)
return stateDb, header, err
statedb, err := ipld_direct_state.New(header.Hash(), b.IpldDirectStateDatabase)
return statedb, header, err
}
return nil, nil, errors.New("invalid arguments; neither block nor hash specified")
}
// IPLDStateDBAndHeaderByNumberOrHash returns the statedb and header for the provided block number or hash
func (b *Backend) IPLDStateDBAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*ipld_eth_statedb.StateDB, *types.Header, error) {
if blockNr, ok := blockNrOrHash.Number(); ok {
return b.IPLDStateDBAndHeaderByNumber(ctx, blockNr)
}
if hash, ok := blockNrOrHash.Hash(); ok {
header, err := b.HeaderByHash(ctx, hash)
func (b *Backend) IPLDTrieStateDBAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*ipld_trie_state.StateDB, *types.Header, error) {
var header *types.Header
if number, ok := blockNrOrHash.Number(); ok {
// Pending state is only known by the miner
if number == rpc.PendingBlockNumber {
return nil, nil, errPendingBlockNumber
}
// Otherwise resolve the block number and return its state
blockHash, err := b.GetCanonicalHash(uint64(number))
if err != nil {
return nil, nil, err
}
header, err = b.HeaderByHash(ctx, blockHash)
if err != nil {
return nil, nil, err
}
if header == nil {
return nil, nil, errors.New("header for hash not found")
return nil, nil, errHeaderNotFound
}
canonicalHash, err := b.GetCanonicalHash(header.Number.Uint64())
} else if hash, ok := blockNrOrHash.Hash(); ok {
var err error
header, err = b.HeaderByHash(ctx, hash)
if err != nil {
return nil, nil, err
}
if blockNrOrHash.RequireCanonical && canonicalHash != hash {
return nil, nil, errors.New("hash is not currently canonical")
if header == nil {
return nil, nil, errHeaderHashNotFound
}
stateDB, err := ipld_eth_statedb.New(header.Root, b.IpldStateDatabase)
return stateDB, header, err
if blockNrOrHash.RequireCanonical {
canonicalHash, err := b.GetCanonicalHash(header.Number.Uint64())
if err != nil {
return nil, nil, err
}
if canonicalHash != hash {
return nil, nil, errors.New("hash is not currently canonical")
}
}
} else {
return nil, nil, errors.New("invalid arguments; neither block nor hash specified")
}
return nil, nil, errors.New("invalid arguments; neither block nor hash specified")
}
// StateAndHeaderByNumber returns the statedb and header for a provided block number
func (b *Backend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
// Pending state is only known by the miner
if number == rpc.PendingBlockNumber {
return nil, nil, errPendingBlockNumber
}
// Otherwise resolve the block number and return its state
header, err := b.HeaderByNumber(ctx, number)
if err != nil {
return nil, nil, err
}
if header == nil {
return nil, nil, errors.New("header not found")
}
stateDb, err := state.New(header.Root, b.StateDatabase, nil)
return stateDb, header, err
}
// IPLDStateDBAndHeaderByNumber returns the statedb and header for a provided block number
func (b *Backend) IPLDStateDBAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*ipld_eth_statedb.StateDB, *types.Header, error) {
// Pending state is only known by the miner
if number == rpc.PendingBlockNumber {
return nil, nil, errPendingBlockNumber
}
// Otherwise resolve the block number and return its state
header, err := b.HeaderByNumber(ctx, number)
if err != nil {
return nil, nil, err
}
if header == nil {
return nil, nil, errors.New("header not found")
}
stateDb, err := ipld_eth_statedb.New(header.Root, b.IpldStateDatabase)
return stateDb, header, err
statedb, err := ipld_trie_state.New(header.Root, b.IpldTrieStateDatabase, nil)
return statedb, header, err
}
// GetCanonicalHash gets the canonical hash for the provided number, if there is one
@ -691,19 +673,30 @@ func (b *Backend) GetCanonicalHash(number uint64) (common.Hash, error) {
return common.HexToHash(hashResult), nil
}
type rowResult struct {
CID string
Data []byte
}
// GetCanonicalHeader gets the canonical header for the provided number, if there is one
func (b *Backend) GetCanonicalHeader(number uint64) (string, []byte, error) {
type rowResult struct {
CID string
Data []byte
}
headerResult := new(rowResult)
return headerResult.CID, headerResult.Data, b.DB.QueryRowx(RetrieveCanonicalHeaderByNumber, number).StructScan(headerResult)
return headerResult.CID, headerResult.Data,
b.DB.QueryRowx(RetrieveCanonicalHeaderByNumber, number).StructScan(headerResult)
}
// GetCanonicalHeader gets the canonical hash and header for the provided number, if they exist
func (b *Backend) GetCanonicalHeaderAndHash(number uint64) (string, []byte, error) {
type rowResult struct {
Data []byte
BlockHash string
}
headerResult := new(rowResult)
return headerResult.BlockHash, headerResult.Data,
b.DB.QueryRowx(RetrieveCanonicalHeaderAndHashByNumber, number).StructScan(headerResult)
}
// GetEVM constructs and returns a vm.EVM
func (b *Backend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header) (*vm.EVM, func() error, error) {
func (b *Backend) GetEVM(ctx context.Context, msg *core.Message, state vm.StateDB, header *types.Header) (*vm.EVM, func() error, error) {
vmError := func() error { return nil }
txContext := core.NewEVMTxContext(msg)
evmCtx := core.NewEVMBlockContext(header, b, nil)
@ -759,13 +752,21 @@ func (b *Backend) GetAccountByHash(ctx context.Context, address common.Address,
return nil, err
}
_, accountRlp, err := b.Retriever.RetrieveAccountByAddressAndBlockHash(address, hash)
acctRecord, err := b.Retriever.RetrieveAccountByAddressAndBlockHash(address, hash)
if err != nil {
return nil, err
}
acct := new(types.StateAccount)
return acct, rlp.DecodeBytes(accountRlp, acct)
balance, ok := new(big.Int).SetString(acctRecord.Balance, 10)
if !ok {
return nil, fmt.Errorf("failed to parse balance %s", acctRecord.Balance)
}
return &types.StateAccount{
Nonce: acctRecord.Nonce,
Balance: balance,
Root: common.HexToHash(acctRecord.Root),
CodeHash: acctRecord.CodeHash,
}, nil
}
// GetCodeByNumberOrHash returns the byte code for the contract deployed at the provided address at the block with the provided hash or block number
@ -803,14 +804,13 @@ func (b *Backend) GetCodeByNumber(ctx context.Context, address common.Address, b
return nil, err
}
if hash == (common.Hash{}) {
return nil, fmt.Errorf("no canoncial block hash found for provided height (%d)", number)
return nil, fmt.Errorf("no canonical block hash found for provided height (%d)", number)
}
return b.GetCodeByHash(ctx, address, hash)
}
// GetCodeByHash returns the byte code for the contract deployed at the provided address at the block with the provided hash
func (b *Backend) GetCodeByHash(ctx context.Context, address common.Address, hash common.Hash) ([]byte, error) {
codeHash := make([]byte, 0)
leafKey := crypto.Keccak256Hash(address.Bytes())
// Begin tx
tx, err := b.DB.Beginx()
@ -827,17 +827,14 @@ func (b *Backend) GetCodeByHash(ctx context.Context, address common.Address, has
err = tx.Commit()
}
}()
var codeHash string
err = tx.Get(&codeHash, RetrieveCodeHashByLeafKeyAndBlockHash, leafKey.Hex(), hash.Hex())
if err != nil {
return nil, err
}
var mhKey string
mhKey, err = ethServerShared.MultihashKeyFromKeccak256(common.BytesToHash(codeHash))
if err != nil {
return nil, err
}
code := make([]byte, 0)
err = tx.Get(&code, RetrieveCodeByMhKey, mhKey)
cid := ipld.Keccak256ToCid(ipld.RawBinary, common.HexToHash(codeHash).Bytes())
var code []byte
err = tx.Get(&code, RetrieveCodeByKey, cid.String())
return code, err
}
@ -890,8 +887,7 @@ func (b *Backend) GetStorageByHash(ctx context.Context, address common.Address,
return nil, err
}
_, _, storageRlp, err := b.Retriever.RetrieveStorageAtByAddressAndStorageSlotAndBlockHash(address, key, hash)
return storageRlp, err
return b.Retriever.RetrieveStorageAtByAddressAndStorageSlotAndBlockHash(address, key, hash)
}
func (b *Backend) GetSlice(path string, depth int, root common.Hash, storage bool) (*GetSliceResponse, error) {
@ -902,14 +898,23 @@ func (b *Backend) GetSlice(path string, depth int, root common.Hash, storage boo
metaData := metaDataFields{}
startTime := makeTimestamp()
t, _ := b.StateDatabase.OpenTrie(root)
var t ipld_trie_state.Trie
var err error
if storage {
t, err = b.IpldTrieStateDatabase.OpenStorageTrie(common.Hash{}, common.Hash{}, root)
} else {
t, err = b.IpldTrieStateDatabase.OpenTrie(root)
}
if err != nil {
return nil, err
}
metaData.trieLoadingTime = makeTimestamp() - startTime
// Convert the head hex path to a decoded byte path
headPath := common.FromHex(path)
// Get Stem nodes
err := b.getSliceStem(headPath, t, response, &metaData, storage)
err = b.getSliceStem(headPath, t, response, &metaData, storage)
if err != nil {
return nil, err
}
@ -933,16 +938,16 @@ func (b *Backend) GetSlice(path string, depth int, root common.Hash, storage boo
return response, nil
}
func (b *Backend) getSliceStem(headPath []byte, t state.Trie, response *GetSliceResponse, metaData *metaDataFields, storage bool) error {
func (b *Backend) getSliceStem(headPath []byte, t ipld_trie_state.Trie, response *GetSliceResponse, metaData *metaDataFields, storage bool) error {
leavesFetchTime := int64(0)
totalStemStartTime := makeTimestamp()
for i := 0; i < len(headPath); i++ {
// Create path for each node along the stem
nodePath := make([]byte, len(headPath[:i]))
copy(nodePath, headPath[:i])
// nodePath := make([]byte, len(headPath[:i]))
nodePath := headPath[:i]
rawNode, _, err := t.(*trie.StateTrie).TryGetNode(trie.HexToCompact(nodePath))
rawNode, _, err := t.TryGetNode(trie.HexToCompact(nodePath))
if err != nil {
return err
}
@ -952,12 +957,12 @@ func (b *Backend) getSliceStem(headPath []byte, t state.Trie, response *GetSlice
continue
}
node, nodeElements, err := ResolveNode(nodePath, rawNode, b.StateDatabase.TrieDB())
node, nodeElements, err := ResolveNode(nodePath, rawNode, b.IpldTrieStateDatabase.TrieDB())
if err != nil {
return err
}
leafFetchTime, err := fillSliceNodeData(b.EthDB, response.TrieNodes.Stem, response.Leaves, node, nodeElements, storage)
leafFetchTime, err := fillSliceNodeData(b.IpldTrieStateDatabase, response.TrieNodes.Stem, response.Leaves, node, nodeElements, storage)
if err != nil {
return err
}
@ -981,10 +986,10 @@ func (b *Backend) getSliceStem(headPath []byte, t state.Trie, response *GetSlice
return nil
}
func (b *Backend) getSliceHead(headPath []byte, t state.Trie, response *GetSliceResponse, metaData *metaDataFields, storage bool) error {
func (b *Backend) getSliceHead(headPath []byte, t ipld_trie_state.Trie, response *GetSliceResponse, metaData *metaDataFields, storage bool) error {
totalHeadStartTime := makeTimestamp()
rawNode, _, err := t.(*trie.StateTrie).TryGetNode(trie.HexToCompact(headPath))
rawNode, _, err := t.TryGetNode(trie.HexToCompact(headPath))
if err != nil {
return err
}
@ -994,12 +999,12 @@ func (b *Backend) getSliceHead(headPath []byte, t state.Trie, response *GetSlice
return nil
}
node, nodeElements, err := ResolveNode(headPath, rawNode, b.StateDatabase.TrieDB())
node, nodeElements, err := ResolveNode(headPath, rawNode, b.IpldTrieStateDatabase.TrieDB())
if err != nil {
return err
}
leafFetchTime, err := fillSliceNodeData(b.EthDB, response.TrieNodes.Head, response.Leaves, node, nodeElements, storage)
leafFetchTime, err := fillSliceNodeData(b.IpldTrieStateDatabase, response.TrieNodes.Head, response.Leaves, node, nodeElements, storage)
if err != nil {
return err
}
@ -1021,7 +1026,7 @@ func (b *Backend) getSliceHead(headPath []byte, t state.Trie, response *GetSlice
return nil
}
func (b *Backend) getSliceTrie(headPath []byte, t state.Trie, response *GetSliceResponse, metaData *metaDataFields, depth int, storage bool) error {
func (b *Backend) getSliceTrie(headPath []byte, t ipld_trie_state.Trie, response *GetSliceResponse, metaData *metaDataFields, depth int, storage bool) error {
it, timeTaken := getIteratorAtPath(t, headPath)
metaData.trieLoadingTime += timeTaken
@ -1051,12 +1056,16 @@ func (b *Backend) getSliceTrie(headPath []byte, t state.Trie, response *GetSlice
continue
}
node, nodeElements, err := ResolveNodeIt(it, b.StateDatabase.TrieDB())
blob, err := it.NodeBlob(), it.Error()
if err != nil {
return err
}
node, nodeElements, err := ResolveNode(it.Path(), blob, b.IpldTrieStateDatabase.TrieDB())
if err != nil {
return err
}
leafFetchTime, err := fillSliceNodeData(b.EthDB, response.TrieNodes.Slice, response.Leaves, node, nodeElements, storage)
leafFetchTime, err := fillSliceNodeData(b.IpldTrieStateDatabase, response.TrieNodes.Slice, response.Leaves, node, nodeElements, storage)
if err != nil {
return err
}
@ -1133,6 +1142,15 @@ func (b *Backend) ServiceFilter(ctx context.Context, session *bloombits.MatcherS
panic("implement me")
}
// Close closes the backing DB and EthDB instances
func (b *Backend) Close() error {
err := b.EthDB.Close()
if err != nil {
log.Errorf("error closing EthDB: %s", err)
}
return b.DB.Close()
}
func logStateDBStatsOnTimer(ethDB *ipfsethdb.Database, gcc *shared.GroupCacheConfig) {
// No stats logging if interval isn't a positive integer.
if gcc.StateDB.LogStatsIntervalInSecs <= 0 {
@ -1143,7 +1161,7 @@ func logStateDBStatsOnTimer(ethDB *ipfsethdb.Database, gcc *shared.GroupCacheCon
go func() {
for range ticker.C {
log.Infof("%s groupcache stats: %+v", StateDBGroupCacheName, ethDB.GetCacheStats())
log.Debugf("%s groupcache stats: %+v", StateDBGroupCacheName, ethDB.GetCacheStats())
}
}()
}

View File

@ -27,15 +27,14 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/trie"
nodeiter "github.com/ethereum/go-ethereum/trie/concurrent_iterator"
"github.com/cerc-io/ipld-eth-statedb/trie_by_cid/state"
)
var nullHashBytes = common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000")
@ -65,7 +64,7 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} {
}
if head.BaseFee != nil {
headerMap["baseFee"] = head.BaseFee
headerMap["baseFeePerGas"] = (*hexutil.Big)(head.BaseFee)
}
return headerMap
}
@ -329,7 +328,7 @@ func getIteratorAtPath(t state.Trie, startKey []byte) (trie.NodeIterator, int64)
}
func fillSliceNodeData(
ethDB ethdb.KeyValueReader,
sdb state.Database,
nodesMap map[string]string,
leavesMap map[string]GetSliceResponseAccount,
node StateNode,
@ -343,7 +342,7 @@ func fillSliceNodeData(
// Extract account data if it's a Leaf node
leafStartTime := makeTimestamp()
if node.NodeType == Leaf && !storage {
stateLeafKey, storageRoot, code, err := extractContractAccountInfo(ethDB, node, nodeElements)
stateLeafKey, storageRoot, code, err := extractContractAccountInfo(sdb, node, nodeElements)
if err != nil {
return 0, fmt.Errorf("GetSlice account lookup error: %s", err.Error())
}
@ -360,7 +359,7 @@ func fillSliceNodeData(
return makeTimestamp() - leafStartTime, nil
}
func extractContractAccountInfo(ethDB ethdb.KeyValueReader, node StateNode, nodeElements []interface{}) (string, string, []byte, error) {
func extractContractAccountInfo(sdb state.Database, node StateNode, nodeElements []interface{}) (string, string, []byte, error) {
var account types.StateAccount
if err := rlp.DecodeBytes(nodeElements[1].([]byte), &account); err != nil {
return "", "", nil, fmt.Errorf("error decoding account for leaf node at path %x nerror: %v", node.Path, err)
@ -381,7 +380,32 @@ func extractContractAccountInfo(ethDB ethdb.KeyValueReader, node StateNode, node
// Extract codeHash and get code
codeHash := common.BytesToHash(account.CodeHash)
codeBytes := rawdb.ReadCode(ethDB, codeHash)
codeBytes, err := sdb.ContractCode(codeHash)
if err != nil {
return "", "", nil, err
}
return stateLeafKeyString, storageRootString, codeBytes, nil
}
// IsLeaf checks if the node we are at is a leaf
func IsLeaf(elements []interface{}) (bool, error) {
if len(elements) > 2 {
return false, nil
}
if len(elements) < 2 {
return false, fmt.Errorf("node cannot be less than two elements in length")
}
switch elements[0].([]byte)[0] / 16 {
case '\x00':
return false, nil
case '\x01':
return false, nil
case '\x02':
return true, nil
case '\x03':
return true, nil
default:
return false, fmt.Errorf("unknown hex prefix")
}
}

View File

@ -17,19 +17,13 @@
package eth_test
import (
"io/ioutil"
"testing"
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestETHSuite(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "eth ipld server eth suite test")
RunSpecs(t, "ipld-eth-server/pkg/eth")
}
var _ = BeforeSuite(func() {
log.SetOutput(ioutil.Discard)
})

View File

@ -4,7 +4,8 @@ import (
"fmt"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/cerc-io/ipld-eth-statedb/trie_by_cid/trie"
)
// NodeType for explicitly setting type of node
@ -73,18 +74,17 @@ type StorageNode struct {
}
func ResolveNode(path []byte, node []byte, trieDB *trie.Database) (StateNode, []interface{}, error) {
nodePath := make([]byte, len(path))
copy(nodePath, path)
var nodeElements []interface{}
if err := rlp.DecodeBytes(node, &nodeElements); err != nil {
return StateNode{}, nil, err
}
ty, err := CheckKeyType(nodeElements)
if err != nil {
return StateNode{}, nil, err
}
nodePath := make([]byte, len(path))
copy(nodePath, path)
return StateNode{
NodeType: ty,
Path: nodePath,
@ -94,23 +94,9 @@ func ResolveNode(path []byte, node []byte, trieDB *trie.Database) (StateNode, []
// ResolveNodeIt return the state diff node pointed by the iterator.
func ResolveNodeIt(it trie.NodeIterator, trieDB *trie.Database) (StateNode, []interface{}, error) {
nodePath := make([]byte, len(it.Path()))
copy(nodePath, it.Path())
node, err := trieDB.Node(it.Hash())
node, err := it.NodeBlob(), it.Error()
if err != nil {
return StateNode{}, nil, err
}
var nodeElements []interface{}
if err = rlp.DecodeBytes(node, &nodeElements); err != nil {
return StateNode{}, nil, err
}
ty, err := CheckKeyType(nodeElements)
if err != nil {
return StateNode{}, nil, err
}
return StateNode{
NodeType: ty,
Path: nodePath,
NodeValue: node,
}, nodeElements, nil
return ResolveNode(it.Path(), node, trieDB)
}

View File

@ -17,22 +17,21 @@
package eth
import (
"bytes"
"fmt"
"math/big"
"strconv"
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/statediff/indexer/models"
"github.com/ethereum/go-ethereum/statediff/trie_helpers"
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
"github.com/jmoiron/sqlx"
"github.com/lib/pq"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
)
// Retriever is used for fetching
@ -60,14 +59,13 @@ type HeaderCIDRecord struct {
TotalDifficulty string `gorm:"column:td"`
TxRoot string
RctRoot string `gorm:"column:receipt_root"`
UncleRoot string
UnclesHash string
Bloom []byte
MhKey string
// gorm doesn't check if foreign key exists in database.
// It is required to eager load relations using preload.
TransactionCIDs []TransactionCIDRecord `gorm:"foreignKey:HeaderID,BlockNumber;references:BlockHash,BlockNumber"`
IPLD IPLDModelRecord `gorm:"foreignKey:MhKey,BlockNumber;references:Key,BlockNumber"`
IPLD IPLDModelRecord `gorm:"foreignKey:CID,BlockNumber;references:Key,BlockNumber"`
}
// TableName overrides the table name used by HeaderCIDRecord
@ -83,8 +81,15 @@ type TransactionCIDRecord struct {
Index int64
Src string
Dst string
MhKey string
IPLD IPLDModelRecord `gorm:"foreignKey:MhKey,BlockNumber;references:Key,BlockNumber"`
IPLD IPLDModelRecord `gorm:"foreignKey:CID,BlockNumber;references:Key,BlockNumber"`
}
type StateAccountRecord struct {
Nonce uint64 `db:"nonce"`
Balance string `db:"balance"`
Root string `db:"storage_root"`
CodeHash []byte `db:"code_hash"`
Removed bool `db:"removed"`
}
// TableName overrides the table name used by TransactionCIDRecord
@ -220,13 +225,13 @@ func (r *Retriever) RetrieveFilteredGQLLogs(tx *sqlx.Tx, rctFilter ReceiptFilter
pgStr, args = logFilterCondition(&id, pgStr, args, rctFilter)
pgStr += ` ORDER BY log_cids.index`
logCIDs := make([]LogResult, 0)
err := tx.Select(&logCIDs, pgStr, args...)
logs := make([]LogResult, 0)
err := tx.Select(&logs, pgStr, args...)
if err != nil {
return nil, err
}
return logCIDs, nil
return logs, nil
}
// RetrieveFilteredLogs retrieves and returns all the log CIDs provided blockHeight or blockHash that conform to the provided
@ -250,13 +255,22 @@ func (r *Retriever) RetrieveFilteredLogs(tx *sqlx.Tx, rctFilter ReceiptFilter, b
pgStr, args = logFilterCondition(&id, pgStr, args, rctFilter)
pgStr += ` ORDER BY log_cids.index`
logCIDs := make([]LogResult, 0)
err := tx.Select(&logCIDs, pgStr, args...)
logs := make([]LogResult, 0)
err := tx.Select(&logs, pgStr, args...)
if err != nil {
return nil, err
}
// decode logs and extract original contract Data
for i, log := range logs {
var buf []interface{}
r := bytes.NewReader(log.LogLeafData)
if err := rlp.Decode(r, &buf); err != nil {
return nil, err
}
logs[i].Data = buf[2].([]byte)
}
return logCIDs, nil
return logs, nil
}
func hasTopics(topics [][]string) bool {
@ -360,7 +374,14 @@ func (r *Retriever) RetrieveTxCIDByHash(txHash string, blockNumber *big.Int) (Tr
var EmptyNodeValue = make([]byte, common.HashLength)
// RetrieveHeaderByHash returns the cid and rlp bytes for the header corresponding to the provided block hash
func (r *Retriever) RetrieveHeaderByHash(tx *sqlx.Tx, hash common.Hash) (string, []byte, error) {
func (r *Retriever) RetrieveHeaderByHash(hash common.Hash) (string, []byte, error) {
headerResult := new(ipldResult)
return headerResult.CID, headerResult.Data, r.db.Get(headerResult, RetrieveHeaderByHashPgStr, hash.Hex())
}
// RetrieveHeaderByHash2 returns the cid and rlp bytes for the header corresponding to the provided block hash
// using a sqlx.Tx
func (r *Retriever) RetrieveHeaderByHash2(tx *sqlx.Tx, hash common.Hash) (string, []byte, error) {
headerResult := new(ipldResult)
return headerResult.CID, headerResult.Data, tx.Get(headerResult, RetrieveHeaderByHashPgStr, hash.Hex())
}
@ -368,7 +389,7 @@ func (r *Retriever) RetrieveHeaderByHash(tx *sqlx.Tx, hash common.Hash) (string,
// RetrieveUncles returns the cid and rlp bytes for the uncle list corresponding to the provided block hash, number (of non-omner root block)
func (r *Retriever) RetrieveUncles(tx *sqlx.Tx, hash common.Hash, number uint64) (string, []byte, error) {
uncleResult := new(ipldResult)
if err := tx.Select(uncleResult, RetrieveUnclesPgStr, hash.Hex(), number); err != nil {
if err := tx.Get(uncleResult, RetrieveUnclesPgStr, hash.Hex(), number); err != nil {
return "", nil, err
}
return uncleResult.CID, uncleResult.Data, nil
@ -377,7 +398,7 @@ func (r *Retriever) RetrieveUncles(tx *sqlx.Tx, hash common.Hash, number uint64)
// RetrieveUnclesByBlockHash returns the cid and rlp bytes for the uncle list corresponding to the provided block hash (of non-omner root block)
func (r *Retriever) RetrieveUnclesByBlockHash(tx *sqlx.Tx, hash common.Hash) (string, []byte, error) {
uncleResult := new(ipldResult)
if err := tx.Select(uncleResult, RetrieveUnclesByBlockHashPgStr, hash.Hex()); err != nil {
if err := tx.Get(uncleResult, RetrieveUnclesByBlockHashPgStr, hash.Hex()); err != nil {
return "", nil, err
}
return uncleResult.CID, uncleResult.Data, nil
@ -419,13 +440,12 @@ func DecodeLeafNode(node []byte) ([]byte, error) {
if err := rlp.DecodeBytes(node, &nodeElements); err != nil {
return nil, err
}
ty, err := trie_helpers.CheckKeyType(nodeElements)
ok, err := IsLeaf(nodeElements)
if err != nil {
return nil, err
}
if ty != sdtypes.Leaf {
return nil, fmt.Errorf("expected leaf node but found %s", ty)
if !ok {
return nil, fmt.Errorf("expected leaf node but found %v", nodeElements)
}
return nodeElements[1].([]byte), nil
}
@ -443,11 +463,7 @@ func (r *Retriever) RetrieveReceipts(tx *sqlx.Tx, hash common.Hash, number uint6
for i, res := range rctResults {
cids[i] = res.CID
nodeVal, err := DecodeLeafNode(res.Data)
if err != nil {
return nil, nil, nil, err
}
rcts[i] = nodeVal
rcts[i] = res.Data
txs[i] = common.HexToHash(res.TxHash)
}
@ -480,64 +496,48 @@ func (r *Retriever) RetrieveReceiptsByBlockHash(tx *sqlx.Tx, hash common.Hash) (
// RetrieveAccountByAddressAndBlockHash returns the cid and rlp bytes for the account corresponding to the provided address and block hash
// TODO: ensure this handles deleted accounts appropriately
func (r *Retriever) RetrieveAccountByAddressAndBlockHash(address common.Address, hash common.Hash) (string, []byte, error) {
accountResult := new(nodeInfo)
func (r *Retriever) RetrieveAccountByAddressAndBlockHash(address common.Address, hash common.Hash) (StateAccountRecord, error) {
var accountResult StateAccountRecord
leafKey := crypto.Keccak256Hash(address.Bytes())
if err := r.db.Get(accountResult, RetrieveAccountByLeafKeyAndBlockHashPgStr, leafKey.Hex(), hash.Hex()); err != nil {
return "", nil, err
if err := r.db.Get(&accountResult, RetrieveAccountByLeafKeyAndBlockHashPgStr, leafKey.Hex(), hash.Hex()); err != nil {
return StateAccountRecord{}, err
}
if accountResult.Removed {
return "", EmptyNodeValue, nil
return StateAccountRecord{}, nil
}
blockNumber, err := strconv.ParseUint(accountResult.BlockNumber, 10, 64)
if err != nil {
return "", nil, err
}
accountResult.Data, err = shared.FetchIPLD(r.db, accountResult.CID, blockNumber)
if err != nil {
return "", nil, err
}
var i []interface{}
if err := rlp.DecodeBytes(accountResult.Data, &i); err != nil {
return "", nil, fmt.Errorf("error decoding state leaf node rlp: %s", err.Error())
}
if len(i) != 2 {
return "", nil, fmt.Errorf("eth Retriever expected state leaf node rlp to decode into two elements")
}
return accountResult.CID, i[1].([]byte), nil
return accountResult, nil
}
// RetrieveStorageAtByAddressAndStorageSlotAndBlockHash returns the cid and rlp bytes for the storage value corresponding to the provided address, storage slot, and block hash
func (r *Retriever) RetrieveStorageAtByAddressAndStorageSlotAndBlockHash(address common.Address, key, hash common.Hash) (string, []byte, []byte, error) {
storageResult := new(nodeInfo)
func (r *Retriever) RetrieveStorageAtByAddressAndStorageSlotAndBlockHash(address common.Address, key, hash common.Hash) ([]byte, error) {
var storageResult nodeInfo
stateLeafKey := crypto.Keccak256Hash(address.Bytes())
storageHash := crypto.Keccak256Hash(key.Bytes())
if err := r.db.Get(storageResult, RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr, stateLeafKey.Hex(), storageHash.Hex(), hash.Hex()); err != nil {
return "", nil, nil, err
if err := r.db.Get(&storageResult,
RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr,
stateLeafKey.Hex(), storageHash.Hex(), hash.Hex()); err != nil {
return nil, err
}
if storageResult.StateLeafRemoved || storageResult.Removed {
return "", EmptyNodeValue, EmptyNodeValue, nil
return EmptyNodeValue, nil
}
blockNumber, err := strconv.ParseUint(storageResult.BlockNumber, 10, 64)
if err != nil {
return "", nil, nil, err
}
storageResult.Data, err = shared.FetchIPLD(r.db, storageResult.CID, blockNumber)
if err != nil {
return "", nil, nil, err
}
var i []interface{}
if err := rlp.DecodeBytes(storageResult.Data, &i); err != nil {
err = fmt.Errorf("error decoding storage leaf node rlp: %s", err.Error())
return "", nil, nil, err
}
if len(i) != 2 {
return "", nil, nil, fmt.Errorf("eth Retriever expected storage leaf node rlp to decode into two elements")
}
return storageResult.CID, storageResult.Data, i[1].([]byte), nil
return storageResult.Value, nil
}
// RetrieveStorageAndRLP returns the cid and rlp bytes for the storage value corresponding to the
// provided address, storage slot, and block hash
func (r *Retriever) RetrieveStorageAndRLP(address common.Address, key, hash common.Hash) (string, []byte, error) {
var storageResult nodeInfo
stateLeafKey := crypto.Keccak256Hash(address.Bytes())
storageHash := crypto.Keccak256Hash(key.Bytes())
if err := r.db.Get(&storageResult,
RetrieveStorageAndRLPByAddressHashAndLeafKeyAndBlockHashPgStr,
stateLeafKey.Hex(), storageHash.Hex(), hash.Hex()); err != nil {
return "", nil, err
}
if storageResult.StateLeafRemoved || storageResult.Removed {
return "", EmptyNodeValue, nil
}
return storageResult.CID, storageResult.Data, nil
}

View File

@ -17,16 +17,19 @@
package eth_test
import (
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth/test_helpers"
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
"context"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/statediff/indexer/interfaces"
"github.com/ethereum/go-ethereum/trie"
"github.com/jmoiron/sqlx"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth/test_helpers"
"github.com/cerc-io/ipld-eth-server/v5/pkg/shared"
)
var _ = Describe("Retriever", func() {
@ -34,6 +37,7 @@ var _ = Describe("Retriever", func() {
db *sqlx.DB
diffIndexer interfaces.StateDiffIndexer
retriever *eth.Retriever
ctx = context.Background()
)
BeforeEach(func() {
db = shared.SetupDB()
@ -43,20 +47,19 @@ var _ = Describe("Retriever", func() {
})
AfterEach(func() {
shared.TearDownDB(db)
db.Close()
})
Describe("Retrieve", func() {
BeforeEach(func() {
tx, err := diffIndexer.PushBlock(test_helpers.MockBlock, test_helpers.MockReceipts, test_helpers.MockBlock.Difficulty())
It("Retrieve", func() {
tx, err := diffIndexer.PushBlock(test_helpers.MockBlock, test_helpers.MockReceipts, test_helpers.MockBlock.Difficulty())
Expect(err).ToNot(HaveOccurred())
for _, node := range test_helpers.MockStateNodes {
err = diffIndexer.PushStateNode(tx, node, test_helpers.MockBlock.Hash().String())
Expect(err).ToNot(HaveOccurred())
for _, node := range test_helpers.MockStateNodes {
err = diffIndexer.PushStateNode(tx, node, test_helpers.MockBlock.Hash().String())
Expect(err).ToNot(HaveOccurred())
}
}
err = tx.Submit(err)
Expect(err).ToNot(HaveOccurred())
})
err = tx.Submit(err)
Expect(err).ToNot(HaveOccurred())
})
Describe("RetrieveFirstBlockNumber", func() {
@ -166,5 +169,5 @@ var _ = Describe("Retriever", func() {
func newMockBlock(blockNumber uint64) *types.Block {
header := test_helpers.MockHeader
header.Number.SetUint64(blockNumber)
return types.NewBlock(&test_helpers.MockHeader, test_helpers.MockTransactions, nil, test_helpers.MockReceipts, new(trie.Trie))
return types.NewBlock(&test_helpers.MockHeader, test_helpers.MockTransactions, nil, test_helpers.MockReceipts, trie.NewEmpty(nil))
}

View File

@ -95,24 +95,23 @@ const (
)
WHERE block_hash = $1
ORDER BY eth.transaction_cids.index ASC`
// TODO: join on ipld.blocks and return IPLD object in this query instead of round tripping back to ipld.blocks
RetrieveAccountByLeafKeyAndBlockHashPgStr = `SELECT state_cids.cid, state_cids.block_number, state_cids.removed
FROM eth.state_cids
INNER JOIN eth.header_cids ON (
state_cids.header_id = header_cids.block_hash
AND state_cids.block_number = header_cids.block_number
)
WHERE state_leaf_key = $1
AND header_cids.block_number <= (SELECT block_number
FROM eth.header_cids
WHERE block_hash = $2)
AND header_cids.block_hash = (SELECT canonical_header_hash(header_cids.block_number))
ORDER BY header_cids.block_number DESC
LIMIT 1`
RetrieveAccountByLeafKeyAndBlockHashPgStr = `SELECT state_cids.nonce, state_cids.balance, state_cids.storage_root, state_cids.code_hash, state_cids.removed
FROM eth.state_cids
INNER JOIN eth.header_cids ON (
state_cids.header_id = header_cids.block_hash
AND state_cids.block_number = header_cids.block_number
)
WHERE state_leaf_key = $1
AND header_cids.block_number <= (SELECT block_number
FROM eth.header_cids
WHERE block_hash = $2)
AND header_cids.block_hash = (SELECT canonical_header_hash(header_cids.block_number))
ORDER BY header_cids.block_number DESC
LIMIT 1`
RetrieveFilteredGQLLogs = `SELECT CAST(eth.log_cids.block_number as TEXT), eth.log_cids.header_id as block_hash,
eth.log_cids.cid, eth.log_cids.index, eth.log_cids.rct_id, eth.log_cids.address,
eth.log_cids.topic0, eth.log_cids.topic1, eth.log_cids.topic2, eth.log_cids.topic3, eth.log_cids.log_data,
data, eth.receipt_cids.cid, eth.receipt_cids.post_status, eth.receipt_cids.tx_id AS tx_hash
eth.log_cids.topic0, eth.log_cids.topic1, eth.log_cids.topic2, eth.log_cids.topic3,
data, eth.receipt_cids.cid AS rct_cid, eth.receipt_cids.post_status, eth.receipt_cids.tx_id AS tx_hash
FROM eth.log_cids, eth.receipt_cids, ipld.blocks
WHERE eth.log_cids.rct_id = receipt_cids.tx_id
AND eth.log_cids.header_id = receipt_cids.header_id
@ -122,19 +121,28 @@ const (
AND receipt_cids.header_id = $1`
RetrieveFilteredLogs = `SELECT CAST(eth.log_cids.block_number as TEXT), eth.log_cids.cid, eth.log_cids.index, eth.log_cids.rct_id,
eth.log_cids.address, eth.log_cids.topic0, eth.log_cids.topic1, eth.log_cids.topic2, eth.log_cids.topic3,
eth.log_cids.log_data, eth.transaction_cids.tx_hash, eth.transaction_cids.index as txn_index,
eth.receipt_cids.cid as cid, eth.receipt_cids.post_status, header_cids.block_hash
FROM eth.log_cids, eth.receipt_cids, eth.transaction_cids, eth.header_cids
eth.transaction_cids.tx_hash, eth.transaction_cids.index as txn_index,
blocks.data, eth.receipt_cids.cid AS rct_cid, eth.receipt_cids.post_status, header_cids.block_hash
FROM eth.log_cids, eth.receipt_cids, eth.transaction_cids, eth.header_cids, ipld.blocks
WHERE eth.log_cids.rct_id = receipt_cids.tx_id
AND eth.log_cids.header_id = eth.receipt_cids.header_id
AND eth.log_cids.block_number = eth.receipt_cids.block_number
AND log_cids.cid = blocks.key
AND log_cids.block_number = blocks.block_number
AND receipt_cids.tx_id = transaction_cids.tx_hash
AND receipt_cids.header_id = transaction_cids.header_id
AND receipt_cids.block_number = transaction_cids.block_number
AND transaction_cids.header_id = header_cids.block_hash
AND transaction_cids.block_number = header_cids.block_number`
RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr = `SELECT cid, val, block_number, removed, state_leaf_removed FROM get_storage_at_by_hash($1, $2, $3)`
RetrieveCanonicalBlockHashByNumber = `SELECT block_hash
RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr = `SELECT cid, val, block_number, removed, state_leaf_removed FROM get_storage_at_by_hash($1, $2, $3)`
RetrieveStorageAndRLPByAddressHashAndLeafKeyAndBlockHashPgStr = `
SELECT cid, val, storage.block_number, removed, state_leaf_removed, data
FROM get_storage_at_by_hash($1, $2, $3) AS storage
INNER JOIN ipld.blocks ON (
storage.cid = blocks.key
AND storage.block_number = blocks.block_number
)`
RetrieveCanonicalBlockHashByNumber = `SELECT block_hash
FROM canonical_header_hash($1) AS block_hash
WHERE block_hash IS NOT NULL`
RetrieveCanonicalHeaderByNumber = `SELECT cid, data FROM eth.header_cids
@ -143,6 +151,12 @@ const (
AND header_cids.block_number = blocks.block_number
)
WHERE block_hash = (SELECT canonical_header_hash($1))`
RetrieveCanonicalHeaderAndHashByNumber = `SELECT data, block_hash FROM eth.header_cids
INNER JOIN ipld.blocks ON (
header_cids.cid = blocks.key
AND header_cids.block_number = blocks.block_number
)
WHERE block_hash = (SELECT canonical_header_hash($1))`
RetrieveTD = `SELECT CAST(td as TEXT) FROM eth.header_cids
WHERE header_cids.block_hash = $1`
RetrieveRPCTransaction = `SELECT blocks.data, header_id, transaction_cids.block_number, index
@ -151,11 +165,8 @@ const (
AND blocks.block_number = transaction_cids.block_number
AND transaction_cids.tx_hash = $1
AND transaction_cids.header_id = (SELECT canonical_header_hash(transaction_cids.block_number))`
RetrieveCodeHashByLeafKeyAndBlockHash = `SELECT code_hash FROM eth.state_accounts, eth.state_cids, eth.header_cids
WHERE state_accounts.header_id = state_cids.header_id
AND state_accounts.state_path = state_cids.state_path
AND state_accounts.block_number = state_cids.block_number
AND state_cids.header_id = header_cids.block_hash
RetrieveCodeHashByLeafKeyAndBlockHash = `SELECT code_hash FROM eth.state_cids, eth.header_cids
WHERE state_cids.header_id = header_cids.block_hash
AND state_cids.block_number = header_cids.block_number
AND state_leaf_key = $1
AND header_cids.block_number <= (SELECT block_number
@ -164,7 +175,7 @@ const (
AND header_cids.block_hash = (SELECT canonical_header_hash(header_cids.block_number))
ORDER BY header_cids.block_number DESC
LIMIT 1`
RetrieveCodeByMhKey = `SELECT data FROM ipld.blocks WHERE key = $1`
RetrieveCodeByKey = `SELECT data FROM ipld.blocks WHERE key = $1`
)
type ipldResult struct {

View File

@ -0,0 +1,29 @@
// VulcanizeDB
// Copyright © 2019 Vulcanize
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package eth_state_test
import (
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestETHSuite(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "ipld-eth-server/pkg/eth/state_test")
}

View File

@ -0,0 +1,13 @@
package eth_state_test
import (
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth"
. "github.com/onsi/gomega"
)
func CheckGetSliceResponse(sliceResponse eth.GetSliceResponse, expectedResponse eth.GetSliceResponse) {
Expect(sliceResponse.SliceID).To(Equal(expectedResponse.SliceID))
Expect(sliceResponse.TrieNodes).To(Equal(expectedResponse.TrieNodes))
Expect(sliceResponse.Leaves).To(Equal(expectedResponse.Leaves))
Expect(sliceResponse.MetaData.NodeStats).To(Equal(expectedResponse.MetaData.NodeStats))
}

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package eth_test
package eth_state_test
import (
"bytes"
@ -22,7 +22,6 @@ import (
"fmt"
"io/ioutil"
"math/big"
"time"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
@ -30,21 +29,26 @@ import (
"github.com/ethereum/go-ethereum/core"
"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/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/statediff"
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
"github.com/jmoiron/sqlx"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth/test_helpers"
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
"github.com/ethereum/go-ethereum/statediff"
// "github.com/ethereum/go-ethereum/statediff/test_helpers"
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth/test_helpers"
"github.com/cerc-io/ipld-eth-server/v5/pkg/shared"
)
var (
parsedABI abi.ABI
parsedABI abi.ABI
randomAddress = common.HexToAddress("0x9F4203bd7a11aCB94882050E6f1C3ab14BBaD3D9")
randomHash = crypto.Keccak256Hash(randomAddress.Bytes())
number = rpc.BlockNumber(test_helpers.BlockNumber.Int64())
block1StateRoot = common.HexToHash("0xa1f614839ebdd58677df2c9d66a3e0acc9462acc49fad6006d0b6e5d2b98ed21")
rootDataHashBlock1 = "a1f614839ebdd58677df2c9d66a3e0acc9462acc49fad6006d0b6e5d2b98ed21"
@ -83,7 +87,7 @@ var (
func init() {
// load abi
abiBytes, err := ioutil.ReadFile("./test_helpers/abi.json")
abiBytes, err := ioutil.ReadFile("../test_helpers/abi.json")
if err != nil {
panic(err)
}
@ -93,132 +97,133 @@ func init() {
}
}
var _ = Describe("eth state reading tests", func() {
const chainLength = 5
var (
blocks []*types.Block
receipts []types.Receipts
chain *core.BlockChain
db *sqlx.DB
api *eth.PublicEthAPI
backend *eth.Backend
chainConfig = params.TestChainConfig
mockTD = big.NewInt(1337)
expectedCanonicalHeader map[string]interface{}
)
It("test init", func() {
// db and type initializations
var err error
db = shared.SetupDB()
transformer := shared.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash())
const chainLength = 5
backend, err = eth.NewEthBackend(db, &eth.Config{
ChainConfig: chainConfig,
VMConfig: vm.Config{},
RPCGasCap: big.NewInt(10000000000), // Max gas capacity for a rpc call.
GroupCacheConfig: &shared.GroupCacheConfig{
StateDB: shared.GroupConfig{
Name: "eth_state_test",
CacheSizeInMB: 8,
CacheExpiryInMins: 60,
LogStatsIntervalInSecs: 0,
},
var (
blocks []*types.Block
receipts []types.Receipts
chain *core.BlockChain
db *sqlx.DB
api *eth.PublicEthAPI
backend *eth.Backend
chainConfig = &*params.TestChainConfig
mockTD = big.NewInt(1337)
expectedCanonicalHeader map[string]interface{}
ctx = context.Background()
)
var _ = BeforeSuite(func() {
chainConfig.LondonBlock = big.NewInt(100)
// db and type initializations
var err error
db = shared.SetupDB()
backend, err = eth.NewEthBackend(db, &eth.Config{
ChainConfig: chainConfig,
VMConfig: vm.Config{},
RPCGasCap: big.NewInt(10000000000), // Max gas capacity for a rpc call.
GroupCacheConfig: &shared.GroupCacheConfig{
StateDB: shared.GroupConfig{
Name: "eth_state_test",
CacheSizeInMB: 8,
CacheExpiryInMins: 60,
LogStatsIntervalInSecs: 0,
},
})
Expect(err).ToNot(HaveOccurred())
api, _ = eth.NewPublicEthAPI(backend, nil, eth.APIConfig{false, false, false, false, shared.DefaultStateDiffTimeout})
},
})
Expect(err).ToNot(HaveOccurred())
api, _ = eth.NewPublicEthAPI(backend, nil, eth.APIConfig{StateDiffTimeout: shared.DefaultStateDiffTimeout})
// make the test blockchain (and state)
blocks, receipts, chain = test_helpers.MakeChain(chainLength, test_helpers.Genesis, test_helpers.TestChainGen)
params := statediff.Params{
IntermediateStateNodes: true,
IntermediateStorageNodes: true,
}
canonicalHeader := blocks[1].Header()
expectedCanonicalHeader = map[string]interface{}{
"number": (*hexutil.Big)(canonicalHeader.Number),
"hash": canonicalHeader.Hash(),
"parentHash": canonicalHeader.ParentHash,
"nonce": canonicalHeader.Nonce,
"mixHash": canonicalHeader.MixDigest,
"sha3Uncles": canonicalHeader.UncleHash,
"logsBloom": canonicalHeader.Bloom,
"stateRoot": canonicalHeader.Root,
"miner": canonicalHeader.Coinbase,
"difficulty": (*hexutil.Big)(canonicalHeader.Difficulty),
"extraData": hexutil.Bytes([]byte{}),
"size": hexutil.Uint64(canonicalHeader.Size()),
"gasLimit": hexutil.Uint64(canonicalHeader.GasLimit),
"gasUsed": hexutil.Uint64(canonicalHeader.GasUsed),
"timestamp": hexutil.Uint64(canonicalHeader.Time),
"transactionsRoot": canonicalHeader.TxHash,
"receiptsRoot": canonicalHeader.ReceiptHash,
"totalDifficulty": (*hexutil.Big)(mockTD),
}
// iterate over the blocks, generating statediff payloads, and transforming the data into Postgres
builder := statediff.NewBuilder(chain.StateCache())
for i, block := range blocks {
var args statediff.Args
var rcts types.Receipts
if i == 0 {
args = statediff.Args{
OldStateRoot: common.Hash{},
NewStateRoot: block.Root(),
BlockNumber: block.Number(),
BlockHash: block.Hash(),
}
} else {
args = statediff.Args{
OldStateRoot: blocks[i-1].Root(),
NewStateRoot: block.Root(),
BlockNumber: block.Number(),
BlockHash: block.Hash(),
}
rcts = receipts[i-1]
// make the test blockchain (and state)
blocks, receipts, chain = test_helpers.MakeChain(chainLength, test_helpers.Genesis, test_helpers.TestChainGen, chainConfig)
transformer := shared.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash())
params := statediff.Params{}
canonicalHeader := blocks[1].Header()
expectedCanonicalHeader = map[string]interface{}{
"number": (*hexutil.Big)(canonicalHeader.Number),
"hash": canonicalHeader.Hash(),
"parentHash": canonicalHeader.ParentHash,
"nonce": canonicalHeader.Nonce,
"mixHash": canonicalHeader.MixDigest,
"sha3Uncles": canonicalHeader.UncleHash,
"logsBloom": canonicalHeader.Bloom,
"stateRoot": canonicalHeader.Root,
"miner": canonicalHeader.Coinbase,
"difficulty": (*hexutil.Big)(canonicalHeader.Difficulty),
"extraData": hexutil.Bytes([]byte{}),
"size": hexutil.Uint64(canonicalHeader.Size()),
"gasLimit": hexutil.Uint64(canonicalHeader.GasLimit),
"gasUsed": hexutil.Uint64(canonicalHeader.GasUsed),
"timestamp": hexutil.Uint64(canonicalHeader.Time),
"transactionsRoot": canonicalHeader.TxHash,
"receiptsRoot": canonicalHeader.ReceiptHash,
"totalDifficulty": (*hexutil.Big)(mockTD),
}
// iterate over the blocks, generating statediff payloads, and transforming the data into Postgres
builder := statediff.NewBuilder(chain.StateCache())
for i, block := range blocks {
var args statediff.Args
var rcts types.Receipts
if i == 0 {
args = statediff.Args{
OldStateRoot: common.Hash{},
NewStateRoot: block.Root(),
BlockNumber: block.Number(),
BlockHash: block.Hash(),
}
diff, err := builder.BuildStateDiffObject(args, params)
Expect(err).ToNot(HaveOccurred())
tx, err := transformer.PushBlock(block, rcts, mockTD)
Expect(err).ToNot(HaveOccurred())
for _, node := range diff.Nodes {
err = transformer.PushStateNode(tx, node, block.Hash().String())
Expect(err).ToNot(HaveOccurred())
} else {
args = statediff.Args{
OldStateRoot: blocks[i-1].Root(),
NewStateRoot: block.Root(),
BlockNumber: block.Number(),
BlockHash: block.Hash(),
}
err = tx.Submit(err)
rcts = receipts[i-1]
}
diff, err := builder.BuildStateDiffObject(args, params)
Expect(err).ToNot(HaveOccurred())
tx, err := transformer.PushBlock(block, rcts, mockTD)
Expect(err).ToNot(HaveOccurred())
for _, node := range diff.Nodes {
err = transformer.PushStateNode(tx, node, block.Hash().String())
Expect(err).ToNot(HaveOccurred())
}
// Insert some non-canonical data into the database so that we test our ability to discern canonicity
indexAndPublisher := shared.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash())
tx, err := indexAndPublisher.PushBlock(test_helpers.MockBlock, test_helpers.MockReceipts, test_helpers.MockBlock.Difficulty())
Expect(err).ToNot(HaveOccurred())
for _, ipld := range diff.IPLDs {
err = transformer.PushIPLD(tx, ipld)
Expect(err).ToNot(HaveOccurred())
}
err = tx.Submit(err)
Expect(err).ToNot(HaveOccurred())
}
// The non-canonical header has a child
tx, err = indexAndPublisher.PushBlock(test_helpers.MockChild, test_helpers.MockReceipts, test_helpers.MockChild.Difficulty())
Expect(err).ToNot(HaveOccurred())
// Insert some non-canonical data into the database so that we test our ability to discern canonicity
indexAndPublisher := shared.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash())
hash := sdtypes.CodeAndCodeHash{
Hash: test_helpers.CodeHash,
Code: test_helpers.ContractCode,
}
tx, err := indexAndPublisher.PushBlock(test_helpers.MockBlock, test_helpers.MockReceipts, test_helpers.MockBlock.Difficulty())
Expect(err).ToNot(HaveOccurred())
err = indexAndPublisher.PushCodeAndCodeHash(tx, hash)
Expect(err).ToNot(HaveOccurred())
err = tx.Submit(err)
Expect(err).ToNot(HaveOccurred())
// wait for tx batch process to complete.
time.Sleep(10000 * time.Millisecond)
err = tx.Submit(err)
Expect(err).ToNot(HaveOccurred())
})
defer It("test teardown", func() {
shared.TearDownDB(db)
chain.Stop()
})
// The non-canonical header has a child
tx, err = indexAndPublisher.PushBlock(test_helpers.MockChild, test_helpers.MockReceipts, test_helpers.MockChild.Difficulty())
Expect(err).ToNot(HaveOccurred())
err = tx.Submit(err)
Expect(err).ToNot(HaveOccurred())
})
var _ = AfterSuite(func() {
shared.TearDownDB(db)
chain.Stop()
})
var _ = Describe("eth state reading tests", func() {
Describe("eth_call", func() {
It("Applies call args (tx data) on top of state, returning the result (e.g. a Getter method call)", func() {
@ -229,6 +234,7 @@ var _ = Describe("eth state reading tests", func() {
To: &test_helpers.ContractAddr,
Data: &bdata,
}
// Before contract deployment, returns nil
res, err := api.Call(context.Background(), callArgs, rpc.BlockNumberOrHashWithNumber(0), nil)
Expect(err).ToNot(HaveOccurred())
@ -261,25 +267,25 @@ var _ = Describe("eth state reading tests", func() {
})
})
var (
expectedContractBalance = (*hexutil.Big)(common.Big0)
expectedBankBalanceBlock0 = (*hexutil.Big)(test_helpers.TestBankFunds)
expectedAcct1BalanceBlock1 = (*hexutil.Big)(big.NewInt(10000))
expectedBankBalanceBlock1 = (*hexutil.Big)(new(big.Int).Sub(test_helpers.TestBankFunds, big.NewInt(10000)))
expectedAcct2BalanceBlock2 = (*hexutil.Big)(big.NewInt(1000))
expectedBankBalanceBlock2 = (*hexutil.Big)(new(big.Int).Sub(expectedBankBalanceBlock1.ToInt(), big.NewInt(1000)))
expectedAcct2BalanceBlock3 = (*hexutil.Big)(new(big.Int).Add(expectedAcct2BalanceBlock2.ToInt(), test_helpers.MiningReward))
expectedAcct2BalanceBlock4 = (*hexutil.Big)(new(big.Int).Add(expectedAcct2BalanceBlock3.ToInt(), test_helpers.MiningReward))
expectedAcct1BalanceBlock5 = (*hexutil.Big)(new(big.Int).Add(expectedAcct1BalanceBlock1.ToInt(), test_helpers.MiningReward))
)
Describe("eth_getBalance", func() {
It("Retrieves the eth balance for the provided account address at the block with the provided number", func() {
var (
expectedContractBalance = (*hexutil.Big)(common.Big0)
expectedBankBalanceBlock0 = (*hexutil.Big)(test_helpers.TestBankFunds)
expectedAcct1BalanceBlock1 = (*hexutil.Big)(big.NewInt(10000))
expectedBankBalanceBlock1 = (*hexutil.Big)(new(big.Int).Sub(test_helpers.TestBankFunds, big.NewInt(10000)))
expectedAcct2BalanceBlock2 = (*hexutil.Big)(big.NewInt(1000))
expectedBankBalanceBlock2 = (*hexutil.Big)(new(big.Int).Sub(expectedBankBalanceBlock1.ToInt(), big.NewInt(1000)))
expectedAcct2BalanceBlock3 = (*hexutil.Big)(new(big.Int).Add(expectedAcct2BalanceBlock2.ToInt(), test_helpers.MiningReward))
expectedAcct2BalanceBlock4 = (*hexutil.Big)(new(big.Int).Add(expectedAcct2BalanceBlock3.ToInt(), test_helpers.MiningReward))
expectedAcct1BalanceBlock5 = (*hexutil.Big)(new(big.Int).Add(expectedAcct1BalanceBlock1.ToInt(), test_helpers.MiningReward))
)
It("Retrieves account balance by block number", func() {
bal, err := api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(0))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedBankBalanceBlock0))
@ -364,7 +370,7 @@ var _ = Describe("eth state reading tests", func() {
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedBankBalanceBlock2))
})
It("Retrieves the eth balance for the provided account address at the block with the provided hash", func() {
It("Retrieves account balance by block hash", func() {
bal, err := api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedBankBalanceBlock0))
@ -449,7 +455,7 @@ var _ = Describe("eth state reading tests", func() {
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedBankBalanceBlock2))
})
It("Returns `0` for an account it cannot find the balance for an account at the provided block number", func() {
It("Returns 0 if account balance not found by block number", func() {
bal, err := api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(0))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
@ -462,7 +468,7 @@ var _ = Describe("eth state reading tests", func() {
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
})
It("Returns `0` for an error for an account it cannot find the balance for an account at the provided block hash", func() {
It("Returns 0 if account balance not found by block hash", func() {
bal, err := api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
@ -474,7 +480,6 @@ var _ = Describe("eth state reading tests", func() {
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)))
})
})
@ -498,7 +503,7 @@ var _ = Describe("eth state reading tests", func() {
Expect(code).To(Equal((hexutil.Bytes)(test_helpers.ContractCode)))
})
It("Returns `nil` for an account it cannot find the code for", func() {
code, err := api.GetCode(ctx, randomAddr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
code, err := api.GetCode(ctx, randomAddress, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(code).To(BeEmpty())
})
@ -604,7 +609,7 @@ var _ = Describe("eth state reading tests", func() {
},
}
eth.CheckGetSliceResponse(*sliceResponse, expectedResponse)
CheckGetSliceResponse(*sliceResponse, expectedResponse)
})
It("Retrieves the state slice for root path with 0 depth", func() {
path := "0x"
@ -633,7 +638,7 @@ var _ = Describe("eth state reading tests", func() {
Leaves: map[string]eth.GetSliceResponseAccount{},
}
eth.CheckGetSliceResponse(*sliceResponse, expectedResponse)
CheckGetSliceResponse(*sliceResponse, expectedResponse)
})
It("Retrieves the state slice for a path to an account", func() {
path := "0x06"
@ -669,7 +674,7 @@ var _ = Describe("eth state reading tests", func() {
},
}
eth.CheckGetSliceResponse(*sliceResponse, expectedResponse)
CheckGetSliceResponse(*sliceResponse, expectedResponse)
})
It("Retrieves the state slice for a path to a non-existing account", func() {
path := "0x06"
@ -698,7 +703,7 @@ var _ = Describe("eth state reading tests", func() {
Leaves: map[string]eth.GetSliceResponseAccount{},
}
eth.CheckGetSliceResponse(*sliceResponse, expectedResponse)
CheckGetSliceResponse(*sliceResponse, expectedResponse)
})
It("Retrieves the storage slice for root path", func() {
@ -731,7 +736,7 @@ var _ = Describe("eth state reading tests", func() {
Leaves: map[string]eth.GetSliceResponseAccount{},
}
eth.CheckGetSliceResponse(*sliceResponse, expectedResponse)
CheckGetSliceResponse(*sliceResponse, expectedResponse)
})
It("Retrieves the storage slice for root path with 0 depth", func() {
path := "0x"
@ -760,7 +765,7 @@ var _ = Describe("eth state reading tests", func() {
Leaves: map[string]eth.GetSliceResponseAccount{},
}
eth.CheckGetSliceResponse(*sliceResponse, expectedResponse)
CheckGetSliceResponse(*sliceResponse, expectedResponse)
})
It("Retrieves the storage slice for root path with deleted nodes", func() {
path := "0x"
@ -789,7 +794,7 @@ var _ = Describe("eth state reading tests", func() {
Leaves: map[string]eth.GetSliceResponseAccount{},
}
eth.CheckGetSliceResponse(*sliceResponse, expectedResponse)
CheckGetSliceResponse(*sliceResponse, expectedResponse)
})
It("Retrieves the storage slice for a path to a storage node", func() {
path := "0x0b"
@ -820,7 +825,7 @@ var _ = Describe("eth state reading tests", func() {
Leaves: map[string]eth.GetSliceResponseAccount{},
}
eth.CheckGetSliceResponse(*sliceResponse, expectedResponse)
CheckGetSliceResponse(*sliceResponse, expectedResponse)
})
})
})

View File

@ -1,49 +0,0 @@
// VulcanizeDB
// Copyright © 2019 Vulcanize
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package eth
import (
"github.com/ethereum/go-ethereum/statediff/indexer/models"
. "github.com/onsi/gomega"
)
// TxModelsContainsCID used to check if a list of TxModels contains a specific cid string
func TxModelsContainsCID(txs []models.TxModel, cid string) bool {
for _, tx := range txs {
if tx.CID == cid {
return true
}
}
return false
}
// ReceiptModelsContainsCID used to check if a list of ReceiptModel contains a specific cid string
func ReceiptModelsContainsCID(rcts []models.ReceiptModel, cid string) bool {
for _, rct := range rcts {
if rct.LeafCID == cid {
return true
}
}
return false
}
func CheckGetSliceResponse(sliceResponse GetSliceResponse, expectedResponse GetSliceResponse) {
Expect(sliceResponse.SliceID).To(Equal(expectedResponse.SliceID))
Expect(sliceResponse.MetaData.NodeStats).To(Equal(expectedResponse.MetaData.NodeStats))
Expect(sliceResponse.TrieNodes).To(Equal(expectedResponse.TrieNodes))
Expect(sliceResponse.Leaves).To(Equal(expectedResponse.Leaves))
}

View File

@ -0,0 +1,82 @@
package test_helpers
import (
"context"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/statediff"
"github.com/cerc-io/ipld-eth-server/v5/pkg/shared"
)
type IndexChainParams struct {
Blocks []*types.Block
Receipts []types.Receipts
StateCache state.Database
ChainConfig *params.ChainConfig
StateDiffParams statediff.Params
TotalDifficulty *big.Int
// Whether to skip indexing state nodes (state_cids, storage_cids)
SkipStateNodes bool
// Whether to skip indexing IPLD blocks
SkipIPLDs bool
}
func IndexChain(params IndexChainParams) error {
indexer := shared.SetupTestStateDiffIndexer(context.Background(), params.ChainConfig, Genesis.Hash())
builder := statediff.NewBuilder(params.StateCache)
// iterate over the blocks, generating statediff payloads, and transforming the data into Postgres
for i, block := range params.Blocks {
var args statediff.Args
var rcts types.Receipts
if i == 0 {
args = statediff.Args{
OldStateRoot: common.Hash{},
NewStateRoot: block.Root(),
BlockNumber: block.Number(),
BlockHash: block.Hash(),
}
} else {
args = statediff.Args{
OldStateRoot: params.Blocks[i-1].Root(),
NewStateRoot: block.Root(),
BlockNumber: block.Number(),
BlockHash: block.Hash(),
}
rcts = params.Receipts[i-1]
}
diff, err := builder.BuildStateDiffObject(args, params.StateDiffParams)
if err != nil {
return err
}
tx, err := indexer.PushBlock(block, rcts, params.TotalDifficulty)
if err != nil {
return err
}
if !params.SkipStateNodes {
for _, node := range diff.Nodes {
if err = indexer.PushStateNode(tx, node, block.Hash().String()); err != nil {
return err
}
}
}
if !params.SkipIPLDs {
for _, ipld := range diff.IPLDs {
if err := indexer.PushIPLD(tx, ipld); err != nil {
return err
}
}
}
if err = tx.Submit(err); err != nil {
return err
}
}
return nil
}

View File

@ -17,7 +17,6 @@
package test_helpers
import (
"bytes"
"math/big"
"github.com/ethereum/go-ethereum/common"
@ -28,10 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/statediff/indexer/ipld"
"github.com/ethereum/go-ethereum/statediff/test_helpers"
"github.com/ipfs/go-cid"
)
// Test variables
@ -40,7 +36,8 @@ var (
TestBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
TestBankAddress = crypto.PubkeyToAddress(TestBankKey.PublicKey) //0x71562b71999873DB5b286dF957af199Ec94617F7
TestBankFunds = big.NewInt(100000000)
Genesis = test_helpers.GenesisBlockForTesting(Testdb, TestBankAddress, TestBankFunds)
Genesis = test_helpers.GenesisBlockForTesting(Testdb, TestBankAddress, TestBankFunds, big.NewInt(params.InitialBaseFee), params.MaxGasLimit)
Account1Key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
Account2Key, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
@ -65,11 +62,12 @@ data function sig: 73d4a13a
// MakeChain creates a chain of n blocks starting at and including parent.
// the returned hash chain is ordered head->parent.
func MakeChain(n int, parent *types.Block, chainGen func(int, *core.BlockGen)) ([]*types.Block, []types.Receipts, *core.BlockChain) {
config := params.TestChainConfig
config.LondonBlock = big.NewInt(100)
func MakeChain(n int, parent *types.Block, chainGen func(int, *core.BlockGen), config *params.ChainConfig) ([]*types.Block, []types.Receipts, *core.BlockChain) {
blocks, receipts := core.GenerateChain(config, parent, ethash.NewFaker(), Testdb, n, chainGen)
chain, _ := core.NewBlockChain(Testdb, nil, nil, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
chain, err := core.NewBlockChain(Testdb, nil, nil, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
if err != nil {
panic(err)
}
return append([]*types.Block{parent}, blocks...), receipts, chain
}
@ -110,40 +108,3 @@ func TestChainGen(i int, block *core.BlockGen) {
block.AddTx(tx)
}
}
// GetRctLeafNodeData converts the receipts to receipt trie and returns the receipt leaf node IPLD data and
// corresponding CIDs
func GetRctLeafNodeData(rcts types.Receipts) ([]cid.Cid, [][]byte, error) {
receiptTrie := ipld.NewRctTrie()
for idx, rct := range rcts {
ethRct, err := ipld.NewReceipt(rct)
if err != nil {
return nil, nil, err
}
if err = receiptTrie.Add(idx, ethRct.RawData()); err != nil {
return nil, nil, err
}
}
rctLeafNodes, keys, err := receiptTrie.GetLeafNodes()
if err != nil {
return nil, nil, err
}
ethRctleafNodeCids := make([]cid.Cid, len(rctLeafNodes))
ethRctleafNodeData := make([][]byte, len(rctLeafNodes))
for i, rln := range rctLeafNodes {
var idx uint
r := bytes.NewReader(keys[i].TrieKey)
err = rlp.Decode(r, &idx)
if err != nil {
return nil, nil, err
}
ethRctleafNodeCids[idx] = rln.Cid()
ethRctleafNodeData[idx] = rln.RawData()
}
return ethRctleafNodeCids, ethRctleafNodeData, nil
}

View File

@ -22,17 +22,19 @@ import (
"crypto/rand"
"math/big"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/statediff/indexer/ipld"
"github.com/ethereum/go-ethereum/statediff/indexer/models"
testhelpers "github.com/ethereum/go-ethereum/statediff/test_helpers"
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
"github.com/ethereum/go-ethereum/trie"
"github.com/ipfs/go-cid"
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
)
// Test variables
@ -58,6 +60,7 @@ var (
ReceiptHash: common.HexToHash("0x1"),
Difficulty: big.NewInt(500001),
Extra: []byte{},
ParentHash: Genesis.Hash(),
},
{
Time: 2,
@ -67,9 +70,10 @@ var (
ReceiptHash: common.HexToHash("0x2"),
Difficulty: big.NewInt(500002),
Extra: []byte{},
ParentHash: Genesis.Hash(),
},
}
MockBlock = createNewBlock(&MockHeader, MockTransactions, MockUncles, MockReceipts, new(trie.Trie))
MockBlock = createNewBlock(&MockHeader, MockTransactions, MockUncles, MockReceipts, trie.NewEmpty(nil))
MockChildHeader = types.Header{
Time: 0,
Number: new(big.Int).Add(BlockNumber, common.Big1),
@ -80,25 +84,23 @@ var (
Extra: []byte{},
ParentHash: MockBlock.Header().Hash(),
}
MockChild = types.NewBlock(&MockChildHeader, MockTransactions, MockUncles, MockReceipts, new(trie.Trie))
Address = common.HexToAddress("0xaE9BEa628c4Ce503DcFD7E305CaB4e29E7476592")
AnotherAddress = common.HexToAddress("0xaE9BEa628c4Ce503DcFD7E305CaB4e29E7476593")
AnotherAddress1 = common.HexToAddress("0xaE9BEa628c4Ce503DcFD7E305CaB4e29E7476594")
AnotherAddress2 = common.HexToAddress("0xaE9BEa628c4Ce503DcFD7E305CaB4e29E7476596")
ContractAddress = crypto.CreateAddress(SenderAddr, MockTransactions[2].Nonce())
ContractHash = crypto.Keccak256Hash(ContractAddress.Bytes()).String()
MockContractByteCode = []byte{0, 1, 2, 3, 4, 5}
mockTopic11 = common.HexToHash("0x04")
mockTopic12 = common.HexToHash("0x06")
mockTopic21 = common.HexToHash("0x05")
mockTopic22 = common.HexToHash("0x07")
mockTopic31 = common.HexToHash("0x08")
mockTopic41 = common.HexToHash("0x09")
mockTopic42 = common.HexToHash("0x0a")
mockTopic43 = common.HexToHash("0x0b")
mockTopic51 = common.HexToHash("0x0c")
mockTopic61 = common.HexToHash("0x0d")
MockLog1 = &types.Log{
MockChild = types.NewBlock(&MockChildHeader, MockTransactions, MockUncles, MockReceipts, trie.NewEmpty(nil))
Address = common.HexToAddress("0xaE9BEa628c4Ce503DcFD7E305CaB4e29E7476592")
AnotherAddress = common.HexToAddress("0xaE9BEa628c4Ce503DcFD7E305CaB4e29E7476593")
AnotherAddress1 = common.HexToAddress("0xaE9BEa628c4Ce503DcFD7E305CaB4e29E7476594")
AnotherAddress2 = common.HexToAddress("0xaE9BEa628c4Ce503DcFD7E305CaB4e29E7476596")
ContractAddress = crypto.CreateAddress(SenderAddr, MockTransactions[2].Nonce())
mockTopic11 = common.HexToHash("0x04")
mockTopic12 = common.HexToHash("0x06")
mockTopic21 = common.HexToHash("0x05")
mockTopic22 = common.HexToHash("0x07")
mockTopic31 = common.HexToHash("0x08")
mockTopic41 = common.HexToHash("0x09")
mockTopic42 = common.HexToHash("0x0a")
mockTopic43 = common.HexToHash("0x0b")
mockTopic51 = common.HexToHash("0x0c")
mockTopic61 = common.HexToHash("0x0d")
MockLog1 = &types.Log{
Address: Address,
Topics: []common.Hash{mockTopic11, mockTopic12},
Data: []byte{},
@ -148,71 +150,55 @@ var (
Index: 5,
}
rctCIDs, _, _ = GetRctLeafNodeData(MockReceipts)
Rct1CID = rctCIDs[0]
Rct4CID = rctCIDs[3]
MockTrxMeta = []models.TxModel{
rctCIDs, _ = getReceiptCIDs(MockReceipts)
Rct1CID = rctCIDs[0]
Rct4CID = rctCIDs[3]
MockTrxMeta = []models.TxModel{
{
CID: "", // This is empty until we go to publish to ipfs
MhKey: "",
Src: SenderAddr.Hex(),
Dst: Address.String(),
Index: 0,
TxHash: MockTransactions[0].Hash().String(),
Data: []byte{},
},
{
CID: "",
MhKey: "",
Src: SenderAddr.Hex(),
Dst: AnotherAddress.String(),
Index: 1,
TxHash: MockTransactions[1].Hash().String(),
Data: []byte{},
},
{
CID: "",
MhKey: "",
Src: SenderAddr.Hex(),
Dst: "",
Index: 2,
TxHash: MockTransactions[2].Hash().String(),
Data: MockContractByteCode,
},
{
CID: "",
MhKey: "",
Src: SenderAddr.Hex(),
Dst: "",
Index: 3,
TxHash: MockTransactions[3].Hash().String(),
Data: []byte{},
},
}
MockRctMeta = []models.ReceiptModel{
{
LeafCID: "",
LeafMhKey: "",
Contract: "",
ContractHash: "",
CID: "",
Contract: "",
},
{
LeafCID: "",
LeafMhKey: "",
Contract: "",
ContractHash: "",
CID: "",
Contract: "",
},
{
LeafCID: "",
LeafMhKey: "",
Contract: ContractAddress.String(),
ContractHash: ContractHash,
CID: "",
Contract: ContractAddress.String(),
},
{
LeafCID: "",
LeafMhKey: "",
Contract: "",
ContractHash: "",
CID: "",
Contract: "",
},
}
@ -226,21 +212,20 @@ var (
StorageValue,
})
nonce1 = uint64(1)
ContractRoot = "0x821e2556a290c86405f8160a2d662042a431ba456b9db265c79bb837c04be5f0"
ContractCodeHash = crypto.Keccak256Hash(MockContractByteCode)
contractPath = common.Bytes2Hex([]byte{'\x06'})
ContractLeafKey = testhelpers.AddressToLeafKey(ContractAddress)
ContractAccount, _ = rlp.EncodeToBytes(&types.StateAccount{
Nonce: nonce1,
ContractRoot = "0x821e2556a290c86405f8160a2d662042a431ba456b9db265c79bb837c04be5f0"
contractPath = common.Bytes2Hex([]byte{'\x06'})
ContractLeafKey = crypto.Keccak256(ContractAddress[:])
ContractAccount = types.StateAccount{
Nonce: uint64(1),
Balance: big.NewInt(0),
CodeHash: ContractCodeHash.Bytes(),
CodeHash: CodeHash.Bytes(),
Root: common.HexToHash(ContractRoot),
})
ContractPartialPath = common.Hex2Bytes("3114658a74d9cc9f7acf2c5cd696c3494d7c344d78bfec3add0d91ec4e8d1c45")
ContractLeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
}
ContractAccountRLP, _ = rlp.EncodeToBytes(&ContractAccount)
ContractPartialPath = common.Hex2Bytes("3114658a74d9cc9f7acf2c5cd696c3494d7c344d78bfec3add0d91ec4e8d1c45")
ContractLeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
ContractPartialPath,
ContractAccount,
ContractAccountRLP,
})
nonce0 = uint64(0)
@ -248,49 +233,49 @@ var (
AccountRoot = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
AccountCodeHash = common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
AccountAddresss = common.HexToAddress("0x0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e")
AccountLeafKey = testhelpers.Account2LeafKey
Account, _ = rlp.EncodeToBytes(&types.StateAccount{
AccountLeafKey = crypto.Keccak256(AccountAddresss[:])
Account = types.StateAccount{
Nonce: nonce0,
Balance: AccountBalance,
CodeHash: AccountCodeHash.Bytes(),
Root: common.HexToHash(AccountRoot),
})
}
AccountRLP, _ = rlp.EncodeToBytes(&Account)
AccountPartialPath = common.Hex2Bytes("3957f3e2f04a0764c3a0491b175f69926da61efbcc8f61fa1455fd2d2b4cdd45")
AccountLeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
AccountPartialPath,
Account,
AccountRLP,
})
MockStateNodes = []sdtypes.StateNode{
MockStateNodes = []sdtypes.StateLeafNode{
{
LeafKey: ContractLeafKey,
Path: []byte{'\x06'},
NodeValue: ContractLeafNode,
NodeType: sdtypes.Leaf,
StorageNodes: []sdtypes.StorageNode{
AccountWrapper: sdtypes.AccountWrapper{
Account: &ContractAccount,
LeafKey: ContractLeafKey,
CID: ipld.Keccak256ToCid(ipld.MEthStateTrie, crypto.Keccak256(ContractLeafNode)).String(),
},
StorageDiff: []sdtypes.StorageLeafNode{
{
Path: []byte{},
NodeType: sdtypes.Leaf,
LeafKey: StorageLeafKey,
NodeValue: StorageLeafNode,
LeafKey: StorageLeafKey,
Value: StorageValue,
CID: ipld.Keccak256ToCid(ipld.MEthStorageTrie, crypto.Keccak256(StorageLeafNode)).String(),
},
},
},
{
LeafKey: AccountLeafKey,
Path: []byte{'\x0c'},
NodeValue: AccountLeafNode,
NodeType: sdtypes.Leaf,
StorageNodes: []sdtypes.StorageNode{},
AccountWrapper: sdtypes.AccountWrapper{
Account: &Account,
LeafKey: AccountLeafKey,
CID: ipld.Keccak256ToCid(ipld.MEthStateTrie, crypto.Keccak256(AccountLeafNode)).String(),
},
},
}
MockStorageNodes = map[string][]sdtypes.StorageNode{
MockStorageNodes = map[string][]sdtypes.StorageLeafNode{
contractPath: {
{
LeafKey: StorageLeafKey,
NodeValue: StorageLeafNode,
NodeType: sdtypes.Leaf,
Path: []byte{},
LeafKey: StorageLeafKey,
Value: StorageValue,
CID: ipld.Keccak256ToCid(ipld.MEthStorageTrie, crypto.Keccak256(StorageLeafNode)).String(),
},
},
}
@ -338,7 +323,7 @@ var (
Extra: []byte{},
},
}
MockLondonBlock = createNewBlock(&MockLondonHeader, MockLondonTransactions, MockLondonUncles, MockLondonReceipts, new(trie.Trie))
MockLondonBlock = createNewBlock(&MockLondonHeader, MockLondonTransactions, MockLondonUncles, MockLondonReceipts, trie.NewEmpty(nil))
)
func createNewBlock(header *types.Header, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, hasher types.TrieHasher) *types.Block {
@ -355,7 +340,7 @@ func createNewBlock(header *types.Header, txs []*types.Transaction, uncles []*ty
// createDynamicTransactionsAndReceipts is a helper function to generate signed mock transactions and mock receipts with mock logs
func createDynamicTransactionsAndReceipts(blockNumber *big.Int) (types.Transactions, types.Receipts, common.Address) {
// make transactions
config := params.TestChainConfig
config := *params.TestChainConfig
config.LondonBlock = blockNumber
trx1 := types.NewTx(&types.DynamicFeeTx{
ChainID: config.ChainID,
@ -368,7 +353,7 @@ func createDynamicTransactionsAndReceipts(blockNumber *big.Int) (types.Transacti
Data: []byte{},
})
transactionSigner := types.MakeSigner(config, blockNumber)
transactionSigner := types.MakeSigner(&config, blockNumber)
mockCurve := elliptic.P256()
mockPrvKey, err := ecdsa.GenerateKey(mockCurve, rand.Reader)
if err != nil {
@ -404,7 +389,7 @@ func createLegacyTransactionsAndReceipts() (types.Transactions, types.Receipts,
// make transactions
trx1 := types.NewTransaction(0, Address, big.NewInt(1000), 50, big.NewInt(100), []byte{})
trx2 := types.NewTransaction(1, AnotherAddress, big.NewInt(2000), 100, big.NewInt(200), []byte{})
trx3 := types.NewContractCreation(2, big.NewInt(1500), 75, big.NewInt(150), MockContractByteCode)
trx3 := types.NewContractCreation(2, big.NewInt(1500), 75, big.NewInt(150), ContractCode)
trx4 := types.NewTransaction(3, AnotherAddress1, big.NewInt(2000), 100, big.NewInt(200), []byte{})
transactionSigner := types.MakeSigner(params.MainnetChainConfig, new(big.Int).Set(BlockNumber))
mockCurve := elliptic.P256()
@ -463,3 +448,15 @@ func createLegacyTransactionsAndReceipts() (types.Transactions, types.Receipts,
return types.Transactions{signedTrx1, signedTrx2, signedTrx3, signedTrx4}, types.Receipts{mockReceipt1, mockReceipt2, mockReceipt3, mockReceipt4}, SenderAddr
}
func getReceiptCIDs(rcts []*types.Receipt) ([]cid.Cid, error) {
cids := make([]cid.Cid, len(rcts))
for i, rct := range rcts {
ethRct, err := ipld.NewReceipt(rct)
if err != nil {
return nil, err
}
cids[i] = ethRct.Cid()
}
return cids, nil
}

View File

@ -22,12 +22,11 @@ import (
"math/big"
"strconv"
"github.com/ethereum/go-ethereum/core"
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/statediff/indexer/models"
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
@ -194,9 +193,9 @@ func (arg *CallArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (*core.Mes
msg := &core.Message{
Nonce: 0,
GasLimit: gas,
GasPrice: new(big.Int).Set(gasPrice),
GasFeeCap: new(big.Int).Set(gasFeeCap),
GasTipCap: new(big.Int).Set(gasTipCap),
GasPrice: gasPrice,
GasFeeCap: gasFeeCap,
GasTipCap: gasTipCap,
To: arg.To,
Value: value,
Data: data,
@ -216,8 +215,8 @@ type ConvertedPayload struct {
TxMetaData []models.TxModel
Receipts types.Receipts
ReceiptMetaData []models.ReceiptModel
StateNodes []sdtypes.StateNode
StorageNodes map[string][]sdtypes.StorageNode
StateNodes []sdtypes.StateLeafNode
StorageNodes map[string][]sdtypes.StorageLeafNode
}
// LogResult represent a log.
@ -232,7 +231,7 @@ type LogResult struct {
Topic2 string `db:"topic2"`
Topic3 string `db:"topic3"`
LogLeafData []byte `db:"data"`
RctCID string `db:"cid"`
RctCID string `db:"rct_cid"`
RctStatus uint64 `db:"post_status"`
BlockNumber string `db:"block_number"`
BlockHash string `db:"block_hash"`

View File

@ -43,12 +43,12 @@ type IPFSBlockResponse struct {
}
type EthTransactionCIDResponse struct {
CID string `json:"cid"`
TxHash string `json:"txHash"`
Index int32 `json:"index"`
Src string `json:"src"`
Dst string `json:"dst"`
BlockByMhKey IPFSBlockResponse `json:"blockByMhKey"`
CID string `json:"cid"`
TxHash string `json:"txHash"`
Index int32 `json:"index"`
Src string `json:"src"`
Dst string `json:"dst"`
BlockByCid IPFSBlockResponse `json:"blockByCid"`
}
type EthTransactionCIDByTxHash struct {
@ -72,7 +72,7 @@ type EthHeaderCIDResponse struct {
UncleRoot string `json:"uncleRoot"`
Bloom string `json:"bloom"`
EthTransactionCIDsByHeaderId EthTransactionCIDsByHeaderIdResponse `json:"ethTransactionCidsByHeaderId"`
BlockByMhKey IPFSBlockResponse `json:"blockByMhKey"`
BlockByCid IPFSBlockResponse `json:"blockByCid"`
}
type AllEthHeaderCIDsResponse struct {
@ -195,7 +195,7 @@ func (c *Client) AllEthHeaderCIDs(ctx context.Context, condition EthHeaderCIDCon
receiptRoot
uncleRoot
bloom
blockByMhKey {
blockByCid {
key
data
}
@ -244,7 +244,7 @@ func (c *Client) EthTransactionCIDByTxHash(ctx context.Context, txHash string) (
index
src
dst
blockByMhKey {
blockByCid {
data
}
}

View File

@ -34,9 +34,9 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
ipld_eth_statedb "github.com/cerc-io/ipld-eth-statedb"
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v5/pkg/shared"
"github.com/cerc-io/ipld-eth-statedb/direct_by_leaf"
)
var (
@ -51,8 +51,8 @@ type Account struct {
}
// getState fetches the StateDB object for an account.
func (a *Account) getState(ctx context.Context) (*ipld_eth_statedb.StateDB, error) {
state, _, err := a.backend.IPLDStateDBAndHeaderByNumberOrHash(ctx, a.blockNrOrHash)
func (a *Account) getState(ctx context.Context) (*state.StateDB, error) {
state, _, err := a.backend.IPLDDirectStateDBAndHeaderByNumberOrHash(ctx, a.blockNrOrHash)
return state, err
}
@ -1009,30 +1009,27 @@ func (r *Resolver) GetStorageAt(ctx context.Context, args struct {
Contract common.Address
Slot common.Hash
}) (*StorageResult, error) {
cid, ipldBlock, rlpValue, err := r.backend.Retriever.RetrieveStorageAtByAddressAndStorageSlotAndBlockHash(args.Contract, args.Slot, args.BlockHash)
cid, nodeRLP, err := r.backend.Retriever.RetrieveStorageAndRLP(args.Contract, args.Slot, args.BlockHash)
if err != nil {
if err == sql.ErrNoRows {
ret := StorageResult{value: []byte{}, cid: "", ipldBlock: []byte{}}
return &ret, nil
return &StorageResult{value: []byte{}, cid: "", ipldBlock: []byte{}}, nil
}
return nil, err
}
if bytes.Equal(rlpValue, eth.EmptyNodeValue) {
return &StorageResult{value: eth.EmptyNodeValue, cid: cid, ipldBlock: ipldBlock}, nil
valueRLP, err := eth.DecodeLeafNode(nodeRLP)
if err != nil {
return nil, err
}
if bytes.Equal(valueRLP, eth.EmptyNodeValue) {
return &StorageResult{value: eth.EmptyNodeValue, cid: cid, ipldBlock: nodeRLP}, nil
}
var value interface{}
err = rlp.DecodeBytes(rlpValue, &value)
err = rlp.DecodeBytes(valueRLP, &value)
if err != nil {
return nil, err
}
ret := StorageResult{value: value.([]byte), cid: cid, ipldBlock: ipldBlock}
return &ret, nil
return &StorageResult{value: value.([]byte), cid: cid, ipldBlock: nodeRLP}, nil
}
func (r *Resolver) GetLogs(ctx context.Context, args struct {
@ -1160,7 +1157,7 @@ func (t EthTransactionCID) Dst(ctx context.Context) string {
return t.dst
}
func (t EthTransactionCID) BlockByMhKey(ctx context.Context) IPFSBlock {
func (t EthTransactionCID) BlockByCid(ctx context.Context) IPFSBlock {
return t.ipfsBlock
}
@ -1249,7 +1246,7 @@ func (h EthHeaderCID) EthTransactionCidsByHeaderId(ctx context.Context) EthTrans
return EthTransactionCIDsConnection{nodes: h.transactions}
}
func (h EthHeaderCID) BlockByMhKey(ctx context.Context) IPFSBlock {
func (h EthHeaderCID) BlockByCid(ctx context.Context) IPFSBlock {
return h.ipfsBlock
}
@ -1326,7 +1323,7 @@ func (r *Resolver) AllEthHeaderCids(ctx context.Context, args struct {
td: td,
txRoot: headerCID.TxRoot,
receiptRoot: headerCID.RctRoot,
uncleRoot: headerCID.UncleRoot,
uncleRoot: headerCID.UnclesHash,
bloom: Bytes(headerCID.Bloom).String(),
ipfsBlock: IPFSBlock{
key: headerCID.IPLD.Key,

View File

@ -17,11 +17,9 @@
package graphql_test
import (
"io/ioutil"
"testing"
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
@ -29,7 +27,3 @@ func TestGraphQL(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "graphql test suite")
}
var _ = BeforeSuite(func() {
log.SetOutput(ioutil.Discard)
})

View File

@ -30,151 +30,113 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/statediff"
"github.com/ethereum/go-ethereum/statediff/indexer/ipld"
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
"github.com/jmoiron/sqlx"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth/test_helpers"
"github.com/cerc-io/ipld-eth-server/v4/pkg/graphql"
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
ethServerShared "github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth/test_helpers"
"github.com/cerc-io/ipld-eth-server/v5/pkg/graphql"
"github.com/cerc-io/ipld-eth-server/v5/pkg/shared"
)
var _ = Describe("GraphQL", func() {
const (
gqlEndPoint = "127.0.0.1:8083"
)
var (
randomAddr = common.HexToAddress("0x1C3ab14BBaD3D99F4203bd7a11aCB94882050E6f")
randomHash = crypto.Keccak256Hash(randomAddr.Bytes())
blocks []*types.Block
receipts []types.Receipts
chain *core.BlockChain
db *sqlx.DB
blockHashes []common.Hash
backend *eth.Backend
graphQLServer *graphql.Service
chainConfig = params.TestChainConfig
mockTD = big.NewInt(1337)
client = graphql.NewClient(fmt.Sprintf("http://%s/graphql", gqlEndPoint))
ctx = context.Background()
blockHash common.Hash
contractAddress common.Address
)
const (
gqlEndPoint = "127.0.0.1:8083"
)
It("test init", func() {
var err error
db = shared.SetupDB()
transformer := shared.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash())
var (
randomAddr = common.HexToAddress("0x1C3ab14BBaD3D99F4203bd7a11aCB94882050E6f")
randomHash = crypto.Keccak256Hash(randomAddr.Bytes())
blocks []*types.Block
receipts []types.Receipts
chain *core.BlockChain
db *sqlx.DB
backend *eth.Backend
graphQLServer *graphql.Service
chainConfig = &*params.TestChainConfig
client = graphql.NewClient(fmt.Sprintf("http://%s/graphql", gqlEndPoint))
mockTD = big.NewInt(1337)
ctx = context.Background()
nonCanonBlockHash common.Hash
nonCanonContractAddress common.Address
)
backend, err = eth.NewEthBackend(db, &eth.Config{
ChainConfig: chainConfig,
VMConfig: vm.Config{},
RPCGasCap: big.NewInt(10000000000),
GroupCacheConfig: &ethServerShared.GroupCacheConfig{
StateDB: ethServerShared.GroupConfig{
Name: "graphql_test",
CacheSizeInMB: 8,
CacheExpiryInMins: 60,
LogStatsIntervalInSecs: 0,
},
var _ = BeforeSuite(func() {
var err error
db = shared.SetupDB()
backend, err = eth.NewEthBackend(db, &eth.Config{
ChainConfig: chainConfig,
VMConfig: vm.Config{},
RPCGasCap: big.NewInt(10000000000),
GroupCacheConfig: &shared.GroupCacheConfig{
StateDB: shared.GroupConfig{
Name: "graphql_test",
CacheSizeInMB: 8,
CacheExpiryInMins: 60,
LogStatsIntervalInSecs: 0,
},
})
Expect(err).ToNot(HaveOccurred())
},
})
Expect(err).ToNot(HaveOccurred())
// make the test blockchain (and state)
blocks, receipts, chain = test_helpers.MakeChain(5, test_helpers.Genesis, test_helpers.TestChainGen)
params := statediff.Params{
IntermediateStateNodes: true,
IntermediateStorageNodes: true,
}
// iterate over the blocks, generating statediff payloads, and transforming the data into Postgres
builder := statediff.NewBuilder(chain.StateCache())
for i, block := range blocks {
blockHashes = append(blockHashes, block.Hash())
var args statediff.Args
var rcts types.Receipts
if i == 0 {
args = statediff.Args{
OldStateRoot: common.Hash{},
NewStateRoot: block.Root(),
BlockNumber: block.Number(),
BlockHash: block.Hash(),
}
} else {
args = statediff.Args{
OldStateRoot: blocks[i-1].Root(),
NewStateRoot: block.Root(),
BlockNumber: block.Number(),
BlockHash: block.Hash(),
}
rcts = receipts[i-1]
}
var diff sdtypes.StateObject
diff, err = builder.BuildStateDiffObject(args, params)
Expect(err).ToNot(HaveOccurred())
tx, err := transformer.PushBlock(block, rcts, mockTD)
Expect(err).ToNot(HaveOccurred())
for _, node := range diff.Nodes {
err = transformer.PushStateNode(tx, node, block.Hash().String())
Expect(err).ToNot(HaveOccurred())
}
err = tx.Submit(err)
Expect(err).ToNot(HaveOccurred())
}
// Insert some non-canonical data into the database so that we test our ability to discern canonicity
indexAndPublisher := shared.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash())
blockHash = test_helpers.MockBlock.Hash()
contractAddress = test_helpers.ContractAddr
tx, err := indexAndPublisher.PushBlock(test_helpers.MockBlock, test_helpers.MockReceipts, test_helpers.MockBlock.Difficulty())
Expect(err).ToNot(HaveOccurred())
err = tx.Submit(err)
Expect(err).ToNot(HaveOccurred())
// The non-canonical header has a child
tx, err = indexAndPublisher.PushBlock(test_helpers.MockChild, test_helpers.MockReceipts, test_helpers.MockChild.Difficulty())
Expect(err).ToNot(HaveOccurred())
ccHash := sdtypes.CodeAndCodeHash{
Hash: test_helpers.CodeHash,
Code: test_helpers.ContractCode,
}
err = indexAndPublisher.PushCodeAndCodeHash(tx, ccHash)
Expect(err).ToNot(HaveOccurred())
err = tx.Submit(err)
Expect(err).ToNot(HaveOccurred())
graphQLServer, err = graphql.New(backend, gqlEndPoint, nil, []string{"*"}, rpc.HTTPTimeouts{})
Expect(err).ToNot(HaveOccurred())
err = graphQLServer.Start(nil)
Expect(err).ToNot(HaveOccurred())
// make the test blockchain (and state)
chainConfig.LondonBlock = big.NewInt(100)
blocks, receipts, chain = test_helpers.MakeChain(5, test_helpers.Genesis, test_helpers.TestChainGen, chainConfig)
test_helpers.IndexChain(test_helpers.IndexChainParams{
StateCache: chain.StateCache(),
ChainConfig: chainConfig,
Blocks: blocks,
Receipts: receipts,
TotalDifficulty: mockTD,
})
defer It("test teardown", func() {
err := graphQLServer.Stop()
Expect(err).ToNot(HaveOccurred())
shared.TearDownDB(db)
chain.Stop()
})
// Insert some non-canonical data into the database so that we test our ability to discern canonicity
indexAndPublisher := shared.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash())
nonCanonBlockHash = test_helpers.MockBlock.Hash()
nonCanonContractAddress = test_helpers.ContractAddr
tx, err := indexAndPublisher.PushBlock(test_helpers.MockBlock, test_helpers.MockReceipts, test_helpers.MockBlock.Difficulty())
Expect(err).ToNot(HaveOccurred())
err = tx.Submit(err)
Expect(err).ToNot(HaveOccurred())
// The non-canonical header has a child
tx, err = indexAndPublisher.PushBlock(test_helpers.MockChild, test_helpers.MockReceipts, test_helpers.MockChild.Difficulty())
Expect(err).ToNot(HaveOccurred())
ipld := sdtypes.IPLD{
CID: ipld.Keccak256ToCid(ipld.RawBinary, test_helpers.CodeHash.Bytes()).String(),
Content: test_helpers.ContractCode,
}
err = indexAndPublisher.PushIPLD(tx, ipld)
Expect(err).ToNot(HaveOccurred())
err = tx.Submit(err)
Expect(err).ToNot(HaveOccurred())
graphQLServer, err = graphql.New(backend, gqlEndPoint, nil, []string{"*"}, rpc.HTTPTimeouts{})
Expect(err).ToNot(HaveOccurred())
err = graphQLServer.Start(nil)
Expect(err).ToNot(HaveOccurred())
})
var _ = AfterSuite(func() {
err := graphQLServer.Stop()
Expect(err).ToNot(HaveOccurred())
shared.TearDownDB(db)
chain.Stop()
})
var _ = Describe("GraphQL", func() {
Describe("eth_getLogs", func() {
It("Retrieves logs that matches the provided blockHash and contract address", func() {
logs, err := client.GetLogs(ctx, blockHash, []common.Address{contractAddress})
logs, err := client.GetLogs(ctx, nonCanonBlockHash, []common.Address{nonCanonContractAddress})
Expect(err).ToNot(HaveOccurred())
expectedLogs := []graphql.LogResponse{
@ -191,7 +153,7 @@ var _ = Describe("GraphQL", func() {
})
It("Retrieves logs for the failed receipt status that matches the provided blockHash and another contract address", func() {
logs, err := client.GetLogs(ctx, blockHash, []common.Address{test_helpers.AnotherAddress2})
logs, err := client.GetLogs(ctx, nonCanonBlockHash, []common.Address{test_helpers.AnotherAddress2})
Expect(err).ToNot(HaveOccurred())
expectedLogs := []graphql.LogResponse{
@ -208,7 +170,7 @@ var _ = Describe("GraphQL", func() {
})
It("Retrieves logs that matches the provided blockHash and multiple contract addresses", func() {
logs, err := client.GetLogs(ctx, blockHash, []common.Address{contractAddress, test_helpers.AnotherAddress2})
logs, err := client.GetLogs(ctx, nonCanonBlockHash, []common.Address{nonCanonContractAddress, test_helpers.AnotherAddress2})
Expect(err).ToNot(HaveOccurred())
expectedLogs := []graphql.LogResponse{
@ -232,13 +194,13 @@ var _ = Describe("GraphQL", func() {
})
It("Retrieves all the logs for the receipt that matches the provided blockHash and nil contract address", func() {
logs, err := client.GetLogs(ctx, blockHash, nil)
logs, err := client.GetLogs(ctx, nonCanonBlockHash, nil)
Expect(err).ToNot(HaveOccurred())
Expect(len(logs)).To(Equal(6))
})
It("Retrieves logs with random hash", func() {
logs, err := client.GetLogs(ctx, randomHash, []common.Address{contractAddress})
logs, err := client.GetLogs(ctx, randomHash, []common.Address{nonCanonContractAddress})
Expect(err).ToNot(HaveOccurred())
Expect(len(logs)).To(Equal(0))
})
@ -246,31 +208,31 @@ var _ = Describe("GraphQL", func() {
Describe("eth_getStorageAt", func() {
It("Retrieves the storage value at the provided contract address and storage leaf key at the block with the provided hash", func() {
storageRes, err := client.GetStorageAt(ctx, blockHashes[2], contractAddress, test_helpers.IndexOne)
storageRes, err := client.GetStorageAt(ctx, blocks[2].Hash(), nonCanonContractAddress, test_helpers.IndexOne)
Expect(err).ToNot(HaveOccurred())
Expect(storageRes.Value).To(Equal(common.HexToHash("01")))
storageRes, err = client.GetStorageAt(ctx, blockHashes[3], contractAddress, test_helpers.IndexOne)
storageRes, err = client.GetStorageAt(ctx, blocks[3].Hash(), nonCanonContractAddress, test_helpers.IndexOne)
Expect(err).ToNot(HaveOccurred())
Expect(storageRes.Value).To(Equal(common.HexToHash("03")))
storageRes, err = client.GetStorageAt(ctx, blockHashes[4], contractAddress, test_helpers.IndexOne)
storageRes, err = client.GetStorageAt(ctx, blocks[4].Hash(), nonCanonContractAddress, test_helpers.IndexOne)
Expect(err).ToNot(HaveOccurred())
Expect(storageRes.Value).To(Equal(common.HexToHash("09")))
})
It("Retrieves empty data if it tries to access a contract at a blockHash which does not exist", func() {
storageRes, err := client.GetStorageAt(ctx, blockHashes[0], contractAddress, test_helpers.IndexOne)
storageRes, err := client.GetStorageAt(ctx, blocks[0].Hash(), nonCanonContractAddress, test_helpers.IndexOne)
Expect(err).ToNot(HaveOccurred())
Expect(storageRes.Value).To(Equal(common.Hash{}))
storageRes, err = client.GetStorageAt(ctx, blockHashes[1], contractAddress, test_helpers.IndexOne)
storageRes, err = client.GetStorageAt(ctx, blocks[1].Hash(), nonCanonContractAddress, test_helpers.IndexOne)
Expect(err).ToNot(HaveOccurred())
Expect(storageRes.Value).To(Equal(common.Hash{}))
})
It("Retrieves empty data if it tries to access a contract slot which does not exist", func() {
storageRes, err := client.GetStorageAt(ctx, blockHashes[3], contractAddress, randomHash.Hex())
storageRes, err := client.GetStorageAt(ctx, blocks[3].Hash(), nonCanonContractAddress, randomHash.Hex())
Expect(err).ToNot(HaveOccurred())
Expect(storageRes.Value).To(Equal(common.Hash{}))
})
@ -316,7 +278,7 @@ var _ = Describe("GraphQL", func() {
compareEthTxCID(*ethTransactionCIDResp, txCID)
Expect(ethTransactionCIDResp.BlockByMhKey.Data).To(Equal(graphql.Bytes(txCID.IPLD.Data).String()))
Expect(ethTransactionCIDResp.BlockByCid.Data).To(Equal(graphql.Bytes(txCID.IPLD.Data).String()))
})
})
})
@ -337,7 +299,7 @@ func compareEthHeaderCID(ethHeaderCID graphql.EthHeaderCIDResponse, headerCID et
Expect(ethHeaderCID.Td).To(Equal(*new(graphql.BigInt).SetUint64(uint64(td))))
Expect(ethHeaderCID.TxRoot).To(Equal(headerCID.TxRoot))
Expect(ethHeaderCID.ReceiptRoot).To(Equal(headerCID.RctRoot))
Expect(ethHeaderCID.UncleRoot).To(Equal(headerCID.UncleRoot))
Expect(ethHeaderCID.UncleRoot).To(Equal(headerCID.UnclesHash))
Expect(ethHeaderCID.Bloom).To(Equal(graphql.Bytes(headerCID.Bloom).String()))
for tIdx, txCID := range headerCID.TransactionCIDs {
@ -345,8 +307,8 @@ func compareEthHeaderCID(ethHeaderCID graphql.EthHeaderCIDResponse, headerCID et
compareEthTxCID(ethTxCID, txCID)
}
Expect(ethHeaderCID.BlockByMhKey.Data).To(Equal(graphql.Bytes(headerCID.IPLD.Data).String()))
Expect(ethHeaderCID.BlockByMhKey.Key).To(Equal(headerCID.IPLD.Key))
Expect(ethHeaderCID.BlockByCid.Data).To(Equal(graphql.Bytes(headerCID.IPLD.Data).String()))
Expect(ethHeaderCID.BlockByCid.Key).To(Equal(headerCID.IPLD.Key))
}
func compareEthTxCID(ethTxCID graphql.EthTransactionCIDResponse, txCID eth.TransactionCIDRecord) {

View File

@ -292,7 +292,7 @@ const schema string = `
index: Int!
src: String!
dst: String!
blockByMhKey: IPFSBlock!
blockByCid: IPFSBlock!
}
type EthTransactionCidsConnection {
@ -317,7 +317,7 @@ const schema string = `
uncleRoot: String!
bloom: String!
ethTransactionCidsByHeaderId: EthTransactionCidsConnection!
blockByMhKey: IPFSBlock!
blockByCid: IPFSBlock!
}
type EthHeaderCidsConnection {

View File

@ -28,8 +28,8 @@ import (
"github.com/graph-gophers/graphql-go"
"github.com/graph-gophers/graphql-go/relay"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
)
// Service encapsulates a GraphQL service.
@ -76,8 +76,8 @@ func (s *Service) Start(server *p2p.Server) error {
if err != nil {
utils.Fatalf("Could not start RPC api: %v", err)
}
extapiURL := fmt.Sprintf("http://%v/", addr)
log.Infof("graphQL endpoint opened for url %s", extapiURL)
extapiURL := fmt.Sprintf("http://%v", addr)
log.Infof("GraphQL endpoint opened at %s", extapiURL)
return nil
}

View File

@ -188,8 +188,7 @@ func WithField(field string, value interface{}) *Entry {
func Init() error {
// Set the output.
viper.BindEnv("logrus.file", "LOGRUS_FILE")
logFile := viper.GetString("logrus.file")
logFile := viper.GetString("log.file")
if logFile != "" {
file, err := os.OpenFile(logFile,
os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0640)
@ -205,8 +204,7 @@ func Init() error {
}
// Set the level.
viper.BindEnv("logrus.level", "LOGRUS_LEVEL")
lvl, err := logrus.ParseLevel(viper.GetString("logrus.level"))
lvl, err := logrus.ParseLevel(viper.GetString("log.level"))
if err != nil {
return err
}
@ -230,7 +228,7 @@ func Init() error {
for next, again := frames.Next(); again; next, again = frames.Next() {
if !strings.Contains(next.File, "sirupsen/logrus.us") &&
!strings.HasPrefix(next.Function, "runtime.") &&
!strings.Contains(next.File, "ipld-eth-server/pkg/logrus") {
!strings.Contains(next.File, "ipld-eth-server/pkg/log") {
return next.Function, fmt.Sprintf("%s:%d", next.File, next.Line)
}
}

View File

@ -17,10 +17,10 @@
package net_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/cerc-io/ipld-eth-server/v4/pkg/net"
"github.com/cerc-io/ipld-eth-server/v5/pkg/net"
)
var _ = Describe("API", func() {

View File

@ -20,8 +20,8 @@ import (
"io/ioutil"
"testing"
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
. "github.com/onsi/ginkgo"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

View File

@ -25,7 +25,7 @@ import (
"net/http"
"time"
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
"github.com/google/uuid"
"github.com/ethereum/go-ethereum/rpc"

View File

@ -20,7 +20,7 @@ import (
"errors"
"net/http"
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
"github.com/prometheus/client_golang/prometheus/promhttp"
)

View File

@ -19,12 +19,12 @@ package rpc
import (
"fmt"
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/rpc"
"github.com/cerc-io/ipld-eth-server/v4/pkg/prom"
"github.com/cerc-io/ipld-eth-server/v5/pkg/prom"
)
// StartHTTPEndpoint starts the HTTP RPC endpoint, configured with cors/vhosts/modules.
@ -42,8 +42,8 @@ func StartHTTPEndpoint(endpoint string, apis []rpc.API, modules []string, cors [
if err != nil {
utils.Fatalf("Could not start RPC api: %v", err)
}
extapiURL := fmt.Sprintf("http://%v/", addr)
log.Infof("HTTP endpoint opened %s", extapiURL)
extapiURL := fmt.Sprintf("http://%s", addr)
log.Infof("HTTP endpoint opened at %s", extapiURL)
return srv, err
}

View File

@ -22,11 +22,11 @@ import (
"os"
"path/filepath"
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
"github.com/ethereum/go-ethereum/p2p/netutil"
"github.com/ethereum/go-ethereum/rpc"
"github.com/cerc-io/ipld-eth-server/v4/pkg/prom"
"github.com/cerc-io/ipld-eth-server/v5/pkg/prom"
)
var (

View File

@ -24,7 +24,8 @@ import (
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/rpc"
"github.com/cerc-io/ipld-eth-server/v4/pkg/prom"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
"github.com/cerc-io/ipld-eth-server/v5/pkg/prom"
)
// StartWSEndpoint starts a websocket endpoint.
@ -49,6 +50,7 @@ func StartWSEndpoint(endpoint string, apis []rpc.API, modules []string, wsOrigin
wsServer := NewWSServer(wsOrigins, handler)
wsServer.Handler = prom.WSMiddleware(wsServer.Handler)
go wsServer.Serve(listener)
log.Infof("WS endpoint opened at ws://%s", endpoint)
return listener, handler, err

View File

@ -29,18 +29,20 @@ import (
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/statediff"
"github.com/ethereum/go-ethereum/statediff/indexer/database/sql/postgres"
"github.com/ethereum/go-ethereum/statediff/indexer/node"
"github.com/jmoiron/sqlx"
"github.com/spf13/viper"
"github.com/cerc-io/ipld-eth-server/v4/pkg/prom"
ethServerShared "github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
"github.com/cerc-io/ipld-eth-server/v5/pkg/prom"
ethServerShared "github.com/cerc-io/ipld-eth-server/v5/pkg/shared"
)
// Env variables
const (
SERVER_WS_PATH = "SERVER_WS_PATH"
SERVER_IPC_PATH = "SERVER_IPC_PATH"
SERVER_HTTP_PATH = "SERVER_HTTP_PATH"
SERVER_WS_PATH = "SERVER_WS_PATH"
SERVER_IPC_PATH = "SERVER_IPC_PATH"
SERVER_HTTP_PATH = "SERVER_HTTP_PATH"
SERVER_GRAPHQL_PATH = "SERVER_GRAPHQL_PATH"
SERVER_MAX_IDLE_CONNECTIONS = "SERVER_MAX_IDLE_CONNECTIONS"
SERVER_MAX_OPEN_CONNECTIONS = "SERVER_MAX_OPEN_CONNECTIONS"
@ -57,6 +59,25 @@ const (
VALIDATOR_ENABLED = "VALIDATOR_ENABLED"
VALIDATOR_EVERY_NTH_BLOCK = "VALIDATOR_EVERY_NTH_BLOCK"
HTTP_TIMEOUT = "HTTP_TIMEOUT"
ETH_WS_PATH = "ETH_WS_PATH"
ETH_HTTP_PATH = "ETH_HTTP_PATH"
ETH_NODE_ID = "ETH_NODE_ID"
ETH_CLIENT_NAME = "ETH_CLIENT_NAME"
ETH_GENESIS_BLOCK = "ETH_GENESIS_BLOCK"
ETH_NETWORK_ID = "ETH_NETWORK_ID"
ETH_CHAIN_ID = "ETH_CHAIN_ID"
DATABASE_NAME = "DATABASE_NAME"
DATABASE_HOSTNAME = "DATABASE_HOSTNAME"
DATABASE_PORT = "DATABASE_PORT"
DATABASE_USER = "DATABASE_USER"
DATABASE_PASSWORD = "DATABASE_PASSWORD"
DATABASE_MAX_IDLE_CONNECTIONS = "DATABASE_MAX_IDLE_CONNECTIONS"
DATABASE_MAX_OPEN_CONNECTIONS = "DATABASE_MAX_OPEN_CONNECTIONS"
DATABASE_MAX_CONN_LIFETIME = "DATABASE_MAX_CONN_LIFETIME"
)
// Config struct
@ -76,12 +97,6 @@ type Config struct {
EthGraphqlEnabled bool
EthGraphqlEndpoint string
IpldGraphqlEnabled bool
IpldGraphqlEndpoint string
IpldPostgraphileEndpoint string
TracingHttpEndpoint string
TracingPostgraphileEndpoint string
ChainConfig *params.ChainConfig
DefaultSender *common.Address
RPCGasCap *big.Int
@ -106,8 +121,12 @@ type Config struct {
func NewConfig() (*Config, error) {
c := new(Config)
viper.BindEnv("server.httpPath", SERVER_HTTP_PATH)
viper.BindEnv("server.wsPath", SERVER_WS_PATH)
viper.BindEnv("server.ipcPath", SERVER_IPC_PATH)
viper.BindEnv("server.graphqlPath", SERVER_GRAPHQL_PATH)
viper.BindEnv("ethereum.httpPath", ETH_HTTP_PATH)
viper.BindEnv("ethereum.defaultSender", ETH_DEFAULT_SENDER_ADDR)
viper.BindEnv("ethereum.rpcGasCap", ETH_RPC_GAS_CAP)
viper.BindEnv("ethereum.chainConfig", ETH_CHAIN_CONFIG)
viper.BindEnv("ethereum.supportsStateDiff", ETH_SUPPORTS_STATEDIFF)
@ -115,6 +134,8 @@ func NewConfig() (*Config, error) {
viper.BindEnv("ethereum.forwardEthCalls", ETH_FORWARD_ETH_CALLS)
viper.BindEnv("ethereum.forwardGetStorageAt", ETH_FORWARD_GET_STORAGE_AT)
viper.BindEnv("ethereum.proxyOnError", ETH_PROXY_ON_ERROR)
viper.BindEnv("log.file", "LOG_FILE")
viper.BindEnv("log.level", "LOG_LEVEL")
c.dbInit()
ethHTTP := viper.GetString("ethereum.httpPath")
@ -132,9 +153,9 @@ func NewConfig() (*Config, error) {
c.EthHttpEndpoint = ethHTTPEndpoint
// websocket server
wsEnabled := viper.GetBool("eth.server.ws")
wsEnabled := viper.GetBool("server.ws")
if wsEnabled {
wsPath := viper.GetString("eth.server.wsPath")
wsPath := viper.GetString("server.wsPath")
if wsPath == "" {
wsPath = "127.0.0.1:8080"
}
@ -143,9 +164,9 @@ func NewConfig() (*Config, error) {
c.WSEnabled = wsEnabled
// ipc server
ipcEnabled := viper.GetBool("eth.server.ipc")
ipcEnabled := viper.GetBool("server.ipc")
if ipcEnabled {
ipcPath := viper.GetString("eth.server.ipcPath")
ipcPath := viper.GetString("server.ipcPath")
if ipcPath == "" {
home, err := os.UserHomeDir()
if err != nil {
@ -158,9 +179,9 @@ func NewConfig() (*Config, error) {
c.IPCEnabled = ipcEnabled
// http server
httpEnabled := viper.GetBool("eth.server.http")
httpEnabled := viper.GetBool("server.http")
if httpEnabled {
httpPath := viper.GetString("eth.server.httpPath")
httpPath := viper.GetString("server.httpPath")
if httpPath == "" {
httpPath = "127.0.0.1:8081"
}
@ -169,9 +190,9 @@ func NewConfig() (*Config, error) {
c.HTTPEnabled = httpEnabled
// eth graphql endpoint
ethGraphqlEnabled := viper.GetBool("eth.server.graphql")
ethGraphqlEnabled := viper.GetBool("server.graphql")
if ethGraphqlEnabled {
ethGraphqlPath := viper.GetString("eth.server.graphqlPath")
ethGraphqlPath := viper.GetString("server.graphqlPath")
if ethGraphqlPath == "" {
ethGraphqlPath = "127.0.0.1:8082"
}
@ -179,34 +200,6 @@ func NewConfig() (*Config, error) {
}
c.EthGraphqlEnabled = ethGraphqlEnabled
// ipld graphql endpoint
ipldGraphqlEnabled := viper.GetBool("ipld.server.graphql")
if ipldGraphqlEnabled {
ipldGraphqlPath := viper.GetString("ipld.server.graphqlPath")
if ipldGraphqlPath == "" {
ipldGraphqlPath = "127.0.0.1:8083"
}
c.IpldGraphqlEndpoint = ipldGraphqlPath
ipldPostgraphilePath := viper.GetString("ipld.postgraphilePath")
if ipldPostgraphilePath == "" {
return nil, errors.New("ipld-postgraphile-path parameter is empty")
}
c.IpldPostgraphileEndpoint = ipldPostgraphilePath
tracingHttpEndpoint := viper.GetString("tracing.httpPath")
tracingPostgraphilePath := viper.GetString("tracing.postgraphilePath")
// these two parameters either can be both empty or both set
if (tracingHttpEndpoint == "" && tracingPostgraphilePath != "") || (tracingHttpEndpoint != "" && tracingPostgraphilePath == "") {
return nil, errors.New("tracing.httpPath and tracing.postgraphilePath parameters either can be both empty or both set")
}
c.TracingHttpEndpoint = tracingHttpEndpoint
c.TracingPostgraphileEndpoint = tracingPostgraphilePath
}
c.IpldGraphqlEnabled = ipldGraphqlEnabled
overrideDBConnConfig(&c.DBConfig)
serveDB, err := ethServerShared.NewDB(c.DBConfig.DbConnectionString(), c.DBConfig)
if err != nil {
@ -216,11 +209,6 @@ func NewConfig() (*Config, error) {
prom.RegisterDBCollector(c.DBConfig.DatabaseName, serveDB)
c.DB = serveDB
defaultSenderStr := viper.GetString("ethereum.defaultSender")
if defaultSenderStr != "" {
sender := common.HexToAddress(defaultSenderStr)
c.DefaultSender = &sender
}
rpcGasCapStr := viper.GetString("ethereum.rpcGasCap")
if rpcGasCapStr != "" {
if rpcGasCap, ok := new(big.Int).SetString(rpcGasCapStr, 10); ok {
@ -313,3 +301,24 @@ func (c *Config) loadValidatorConfig() {
c.StateValidationEnabled = viper.GetBool("validator.enabled")
c.StateValidationEveryNthBlock = viper.GetUint64("validator.everyNthBlock")
}
// GetEthNodeAndClient returns eth node info and client from path url
func getEthNodeAndClient(path string) (node.Info, *rpc.Client, error) {
viper.BindEnv("ethereum.nodeID", ETH_NODE_ID)
viper.BindEnv("ethereum.clientName", ETH_CLIENT_NAME)
viper.BindEnv("ethereum.genesisBlock", ETH_GENESIS_BLOCK)
viper.BindEnv("ethereum.networkID", ETH_NETWORK_ID)
viper.BindEnv("ethereum.chainID", ETH_CHAIN_ID)
rpcClient, err := rpc.Dial(path)
if err != nil {
return node.Info{}, nil, err
}
return node.Info{
ID: viper.GetString("ethereum.nodeID"),
ClientName: viper.GetString("ethereum.clientName"),
GenesisBlock: viper.GetString("ethereum.genesisBlock"),
NetworkID: viper.GetString("ethereum.networkID"),
ChainID: viper.GetUint64("ethereum.chainID"),
}, rpcClient, nil
}

View File

@ -1,50 +0,0 @@
package serve
import (
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/statediff/indexer/node"
"github.com/spf13/viper"
)
// Env variables
const (
HTTP_TIMEOUT = "HTTP_TIMEOUT"
ETH_WS_PATH = "ETH_WS_PATH"
ETH_HTTP_PATH = "ETH_HTTP_PATH"
ETH_NODE_ID = "ETH_NODE_ID"
ETH_CLIENT_NAME = "ETH_CLIENT_NAME"
ETH_GENESIS_BLOCK = "ETH_GENESIS_BLOCK"
ETH_NETWORK_ID = "ETH_NETWORK_ID"
ETH_CHAIN_ID = "ETH_CHAIN_ID"
DATABASE_NAME = "DATABASE_NAME"
DATABASE_HOSTNAME = "DATABASE_HOSTNAME"
DATABASE_PORT = "DATABASE_PORT"
DATABASE_USER = "DATABASE_USER"
DATABASE_PASSWORD = "DATABASE_PASSWORD"
DATABASE_MAX_IDLE_CONNECTIONS = "DATABASE_MAX_IDLE_CONNECTIONS"
DATABASE_MAX_OPEN_CONNECTIONS = "DATABASE_MAX_OPEN_CONNECTIONS"
DATABASE_MAX_CONN_LIFETIME = "DATABASE_MAX_CONN_LIFETIME"
)
// GetEthNodeAndClient returns eth node info and client from path url
func getEthNodeAndClient(path string) (node.Info, *rpc.Client, error) {
viper.BindEnv("ethereum.nodeID", ETH_NODE_ID)
viper.BindEnv("ethereum.clientName", ETH_CLIENT_NAME)
viper.BindEnv("ethereum.genesisBlock", ETH_GENESIS_BLOCK)
viper.BindEnv("ethereum.networkID", ETH_NETWORK_ID)
viper.BindEnv("ethereum.chainID", ETH_CHAIN_ID)
rpcClient, err := rpc.Dial(path)
if err != nil {
return node.Info{}, nil, err
}
return node.Info{
ID: viper.GetString("ethereum.nodeID"),
ClientName: viper.GetString("ethereum.clientName"),
GenesisBlock: viper.GetString("ethereum.genesisBlock"),
NetworkID: viper.GetString("ethereum.networkID"),
ChainID: viper.GetUint64("ethereum.chainID"),
}, rpcClient, nil
}

View File

@ -21,7 +21,7 @@ import (
"sync"
"time"
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers"
ethnode "github.com/ethereum/go-ethereum/node"
@ -29,9 +29,9 @@ import (
"github.com/ethereum/go-ethereum/rpc"
"github.com/jmoiron/sqlx"
"github.com/cerc-io/ipld-eth-server/v4/pkg/debug"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v4/pkg/net"
"github.com/cerc-io/ipld-eth-server/v5/pkg/debug"
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v5/pkg/net"
)
const (
@ -94,7 +94,6 @@ func NewServer(settings *Config) (Server, error) {
sap.backend, err = eth.NewEthBackend(sap.db, &eth.Config{
ChainConfig: settings.ChainConfig,
VMConfig: vm.Config{NoBaseFee: true},
DefaultSender: settings.DefaultSender,
RPCGasCap: settings.RPCGasCap,
GroupCacheConfig: settings.GroupCache,
})
@ -159,7 +158,7 @@ func (sap *Service) Serve(wg *sync.WaitGroup) {
<-sap.QuitChan
log.Info("quiting eth ipld server process")
}()
log.Info("eth ipld server process successfully spun up")
log.Debug("eth ipld server process successfully spun up")
}
// Start is used to begin the service
@ -174,7 +173,7 @@ func (sap *Service) Start() error {
// Stop is used to close down the service
// This is mostly just to satisfy the node.Service interface
func (sap *Service) Stop() error {
log.Infof("stopping eth ipld server")
log.Info("stopping eth ipld server")
sap.Lock()
close(sap.QuitChan)
sap.Unlock()

View File

@ -17,11 +17,8 @@
package shared
import (
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
"github.com/ethereum/go-ethereum/common"
"github.com/ipfs/go-cid"
blockstore "github.com/ipfs/go-ipfs-blockstore"
dshelp "github.com/ipfs/go-ipfs-ds-help"
"github.com/jmoiron/sqlx"
)
@ -47,33 +44,3 @@ func Rollback(tx *sqlx.Tx) {
log.Error(err)
}
}
// FetchIPLDByMhKeyAndBlockNumber is used to retrieve an ipld from Postgres blockstore with the provided tx, mhkey string and blockNumber
func FetchIPLDByMhKeyAndBlockNumber(tx *sqlx.Tx, mhKey string, blockNumber uint64) ([]byte, error) {
pgStr := `SELECT data FROM ipld.blocks WHERE key = $1 AND block_number = $2`
var block []byte
return block, tx.Get(&block, pgStr, mhKey, blockNumber)
}
// FetchIPLD is used to retrieve an IPLD from Postgres mhkey and blockNumber
func FetchIPLD(db *sqlx.DB, mhKey string, blockNumber uint64) ([]byte, error) {
pgStr := `SELECT data FROM ipld.blocks WHERE key = $1 AND block_number = $2`
var block []byte
return block, db.Get(&block, pgStr, mhKey, blockNumber)
}
// MultihashKeyFromCID converts a cid into a blockstore-prefixed multihash db key string
func MultihashKeyFromCID(c cid.Cid) string {
dbKey := dshelp.MultihashToDsKey(c.Hash())
return blockstore.BlockPrefix.String() + dbKey.String()
}
// MultihashKeyFromCIDString converts a cid string into a blockstore-prefixed multihash db key string
func MultihashKeyFromCIDString(c string) (string, error) {
dc, err := cid.Decode(c)
if err != nil {
return "", err
}
dbKey := dshelp.MultihashToDsKey(dc.Hash())
return blockstore.BlockPrefix.String() + dbKey.String(), nil
}

View File

@ -19,8 +19,6 @@ package shared
import (
"bytes"
"context"
"os"
"strconv"
. "github.com/onsi/gomega"
@ -46,7 +44,8 @@ func IPLDsContainBytes(iplds []models.IPLDModel, b []byte) bool {
// SetupDB is use to setup a db for watcher tests
func SetupDB() *sqlx.DB {
config := getTestDBConfig()
config, err := postgres.TestConfig.WithEnv()
Expect(err).NotTo(HaveOccurred())
db, err := NewDB(config.DbConnectionString(), config)
Expect(err).NotTo(HaveOccurred())
@ -60,6 +59,8 @@ func TearDownDB(db *sqlx.DB) {
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM nodes`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM ipld.blocks`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.header_cids`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.uncle_cids`)
@ -72,12 +73,6 @@ func TearDownDB(db *sqlx.DB) {
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.storage_cids`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.state_accounts`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.access_list_elements`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM blocks`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.log_cids`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth_meta.watched_addresses`)
@ -96,20 +91,10 @@ func SetupTestStateDiffIndexer(ctx context.Context, chainConfig *params.ChainCon
ChainID: params.TestChainConfig.ChainID.Uint64(),
}
_, stateDiffIndexer, err := indexer.NewStateDiffIndexer(ctx, chainConfig, testInfo, getTestDBConfig())
dbconfig, err := postgres.TestConfig.WithEnv()
Expect(err).NotTo(HaveOccurred())
_, stateDiffIndexer, err := indexer.NewStateDiffIndexer(ctx, chainConfig, testInfo, dbconfig)
Expect(err).NotTo(HaveOccurred())
return stateDiffIndexer
}
func getTestDBConfig() postgres.Config {
port, _ := strconv.Atoi(os.Getenv("DATABASE_PORT"))
return postgres.Config{
Hostname: os.Getenv("DATABASE_HOSTNAME"),
DatabaseName: os.Getenv("DATABASE_NAME"),
Username: os.Getenv("DATABASE_USER"),
Password: os.Getenv("DATABASE_PASSWORD"),
Port: port,
Driver: postgres.SQLX,
}
}

View File

@ -1,137 +0,0 @@
import os
import sys
import subprocess
import errno
from typing import List, Dict
"""
Resolves dependency conflicts between a plugin repository's and the core repository's go.mods
Usage: python3 gomoderator.py {path_to_core_repository} {path_to_plugin_repository}
"""
ERROR_INVALID_NAME = 123
def is_pathname_valid(pathname: str) -> bool:
"""
`True` if the passed pathname is a valid pathname for the current OS;
`False` otherwise.
"""
try:
if not isinstance(pathname, str) or not pathname:
return False
_, pathname = os.path.splitdrive(pathname)
root_dirname = os.environ.get('HOMEDRIVE', 'C:') \
if sys.platform == 'win32' else os.path.sep
assert os.path.isdir(root_dirname) # ...Murphy and her ironclad Law
root_dirname = root_dirname.rstrip(os.path.sep) + os.path.sep
for pathname_part in pathname.split(os.path.sep):
try:
os.lstat(root_dirname + pathname_part)
except OSError as exc:
if hasattr(exc, 'winerror'):
if exc.winerror == ERROR_INVALID_NAME:
return False
elif exc.errno in {errno.ENAMETOOLONG, errno.ERANGE}:
return False
except TypeError as exc:
return False
else:
return True
def map_deps_to_version(deps_arr: List[str]) -> Dict[str, str]:
mapping = {}
for d in deps_arr:
if d.find(' => ') != -1:
ds = d.split(' => ')
d = ds[1]
d = d.replace(" v", "[>v") # might be able to just split on the empty space not _v and skip this :: insertion
d_and_v = d.split("[>")
mapping[d_and_v[0]] = d_and_v[1]
return mapping
# argument checks
assert len(sys.argv) == 3, "need core repository and plugin repository path arguments"
core_repository_path = sys.argv[1]
plugin_repository_path = sys.argv[2]
assert is_pathname_valid(core_repository_path), "core repository path argument is not valid"
assert is_pathname_valid(plugin_repository_path), "plugin repository path argument is not valid"
# collect `go list -m all` output from both repositories; remain in the plugin repository
os.chdir(core_repository_path)
core_deps_b = subprocess.check_output(["go", "list", "-m", "all"])
os.chdir(plugin_repository_path)
plugin_deps_b = subprocess.check_output(["go", "list", "-m", "all"])
core_deps = core_deps_b.decode("utf-8")
core_deps_arr = core_deps.splitlines()
del core_deps_arr[0] # first line is the project repo itself
plugin_deps = plugin_deps_b.decode("utf-8")
plugin_deps_arr = plugin_deps.splitlines()
del plugin_deps_arr[0]
core_deps_mapping = map_deps_to_version(core_deps_arr)
plugin_deps_mapping = map_deps_to_version(plugin_deps_arr)
# iterate over dependency maps for both repos and find version conflicts
# attempt to resolve conflicts by adding adding a `require` for the core version to the plugin's go.mod file
none = True
for dep, core_version in core_deps_mapping.items():
if dep in plugin_deps_mapping.keys():
plugin_version = plugin_deps_mapping[dep]
if core_version != plugin_version:
print(f'{dep} has a conflict: core is using version {core_version} '
f'but the plugin is using version {plugin_version}')
fixed_dep = f'{dep}@{core_version}'
print(f'attempting fix by `go mod edit -require={fixed_dep}')
subprocess.check_call(["go", "mod", "edit", f'-require={fixed_dep}'])
none = False
if none:
print("no conflicts to resolve")
quit()
# the above process does not work for all dep conflicts e.g. golang.org/x/text v0.3.0 will not stick this way
# so we will try the `go get {dep}` route for any remaining conflicts
updated_plugin_deps_b = subprocess.check_output(["go", "list", "-m", "all"])
updated_plugin_deps = updated_plugin_deps_b.decode("utf-8")
updated_plugin_deps_arr = updated_plugin_deps.splitlines()
del updated_plugin_deps_arr[0]
updated_plugin_deps_mapping = map_deps_to_version(updated_plugin_deps_arr)
none = True
for dep, core_version in core_deps_mapping.items():
if dep in updated_plugin_deps_mapping.keys():
updated_plugin_version = updated_plugin_deps_mapping[dep]
if core_version != updated_plugin_version:
print(f'{dep} still has a conflict: core is using version {core_version} '
f'but the plugin is using version {updated_plugin_version}')
fixed_dep = f'{dep}@{core_version}'
print(f'attempting fix by `go get {fixed_dep}')
subprocess.check_call(["go", "get", fixed_dep])
none = False
if none:
print("all conflicts have been resolved")
quit()
# iterate over plugins `go list -m all` output one more time and inform whether or not the above has worked
final_plugin_deps_b = subprocess.check_output(["go", "list", "-m", "all"])
final_plugin_deps = final_plugin_deps_b.decode("utf-8")
final_plugin_deps_arr = final_plugin_deps.splitlines()
del final_plugin_deps_arr[0]
final_plugin_deps_mapping = map_deps_to_version(final_plugin_deps_arr)
none = True
for dep, core_version in core_deps_mapping.items():
if dep in final_plugin_deps_mapping.keys():
final_plugin_version = final_plugin_deps_mapping[dep]
if core_version != final_plugin_version:
print(f'{dep} STILL has a conflict: core is using version {core_version} '
f'but the plugin is using version {final_plugin_version}')
none = False
if none:
print("all conflicts have been resolved")
quit()
print("failed to resolve all conflicts")

View File

@ -1,15 +0,0 @@
#!/usr/bin/env bash
set -ex
echo "Installing Postgres 11"
sudo service postgresql stop
sudo apt-get remove -q 'postgresql-*'
sudo apt-get update -q
sudo apt-get install -q postgresql-11 postgresql-client-11
sudo cp /etc/postgresql/{9.6,11}/main/pg_hba.conf
echo "Restarting Postgres 11"
sudo service postgresql restart
sudo psql -c 'CREATE ROLE travis SUPERUSER LOGIN CREATEDB;' -U postgres

58
scripts/integration-setup.sh Executable file
View File

@ -0,0 +1,58 @@
#!/bin/bash
set -e
# Prevent conflicting tty output
export BUILDKIT_PROGRESS=plain
# By default assume we are running in the project root
export CERC_REPO_BASE_DIR="${CERC_REPO_BASE_DIR:-..}"
CONFIG_DIR=$(readlink -f "${CONFIG_DIR:-$(mktemp -d)}")
# Pass this in so we can run eth_call forwarding tests, which expect no IPLD DB
echo "CERC_RUN_STATEDIFF=${CERC_RUN_STATEDIFF:-true}" >> $CONFIG_DIR/stack.env
laconic_so="${LACONIC_SO:-laconic-so} --verbose --stack fixturenet-eth-loaded"
set -x
# # Build and deploy a cluster with only what we need from the stack
# $laconic_so setup-repositories \
# --exclude cerc-io/ipld-eth-server,cerc-io/tx-spammer \
# --branches-file ./test/stack-refs.yml
# $laconic_so build-containers \
# --exclude cerc/ipld-eth-server,cerc/keycloak,cerc/tx-spammer
IMAGE_IPLD_ETH_DB=git.vdb.to/cerc-io/ipld-eth-db/ipld-eth-db:v5.0.2-alpha
IMAGE_GETH=git.vdb.to/cerc-io/go-ethereum/go-ethereum:v1.11.5-statediff-5.0.5-alpha
docker pull $IMAGE_IPLD_ETH_DB
docker pull $IMAGE_GETH
docker tag $IMAGE_IPLD_ETH_DB cerc/ipld-eth-db:local
docker tag $IMAGE_GETH cerc/go-ethereum:local
$laconic_so build-containers \
--exclude cerc/ipld-eth-server,cerc/keycloak,cerc/tx-spammer,cerc/go-ethereum,cerc/ipld-eth-db
$laconic_so deploy \
--include fixturenet-eth,ipld-eth-db \
--env-file $CONFIG_DIR/stack.env \
--cluster test up
# set +x
# Get IPv4 endpoint of geth file server
bootnode_endpoint=$(docker port test-fixturenet-eth-bootnode-geth-1 9898 | head -1)
# Extract the chain config and ID from genesis file
curl -s $bootnode_endpoint/geth.json | jq '.config' > $CONFIG_DIR/chain.json
# Output vars if we are running on Github
if [[ -n "$GITHUB_ENV" ]]; then
echo ETH_CHAIN_ID="$(jq '.chainId' $CONFIG_DIR/chain.json)" >> "$GITHUB_ENV"
echo ETH_CHAIN_CONFIG="$CONFIG_DIR/chain.json" >> "$GITHUB_ENV"
echo ETH_HTTP_PATH="$(docker port test-fixturenet-eth-geth-1-1 8545 | head -1)" >> "$GITHUB_ENV"
# Read a private key so we can send from a funded account
echo DEPLOYER_PRIVATE_KEY="$(curl -s $bootnode_endpoint/accounts.csv | head -1 | cut -d',' -f3)" >> "$GITHUB_ENV"
fi

View File

@ -1,27 +0,0 @@
#!/usr/bin/env bash
# Provide me with a postgres database name, and I will:
# - Drop the database
# - Recreate the database
# - Run the vulcanizedb migration
if [ "$1" = "" ]; then
echo "Provide a database name to reset"
exit 1
fi
db=$1
dir=$(basename "$(pwd)")
if [ $dir != "ipld-eth-server" ]
then
echo "Run me from the ipld-eth-server root dir"
exit 1
fi
user=$(whoami)
psql -c "DROP DATABASE $db" postgres
if [ $? -eq 0 ]; then
psql -c "CREATE DATABASE $db WITH OWNER $user" postgres
make migrate HOST_NAME=localhost NAME=$db PORT=5432
else
echo "Couldnt drop the database. Are you connected? Does it exist?"
fi

View File

@ -1,17 +0,0 @@
set -e
set -o xtrace
export ETH_FORWARD_ETH_CALLS=false
export DB_WRITE=true
export ETH_PROXY_ON_ERROR=false
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

View File

@ -1,17 +0,0 @@
set -e
set -o xtrace
export ETH_FORWARD_ETH_CALLS=true
export DB_WRITE=false
export ETH_PROXY_ON_ERROR=false
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

View File

@ -1,119 +0,0 @@
# Test Insructions
## Setup
- Clone [stack-orchestrator](https://github.com/vulcanize/stack-orchestrator), [ipld-eth-db](https://github.com/vulcanize/ipld-eth-db) [go-ethereum](https://github.com/vulcanize/go-ethereum) repositories.
- Checkout [v4 release](https://github.com/vulcanize/ipld-eth-db/releases/tag/v4.2.1-alpha) in ipld-eth-db repo.
```bash
# In ipld-eth-db repo.
git checkout v4.2.1-alpha
```
- Checkout [v4 release](https://github.com/vulcanize/go-ethereum/releases/tag/v1.10.23-statediff-4.2.0-alpha) in go-ethereum repo.
```bash
# In go-ethereum repo.
git checkout v1.10.23-statediff-4.2.0-alpha
```
- Checkout working commit in stack-orchestrator repo.
```bash
# In stack-orchestrator repo.
git checkout f2fd766f5400fcb9eb47b50675d2e3b1f2753702
```
## Run
- Run unit tests:
```bash
# In ipld-eth-server root directory.
./scripts/run_unit_test.sh
```
- Run integration tests:
- In stack-orchestrator repo, create config file:
```bash
cd helper-scripts
./create-config.sh
```
A `config.sh` will be created in the root directory.
- Update/Edit the generated config file with:
```bash
#!/bin/bash
# Path to ipld-eth-server repo.
vulcanize_ipld_eth_db=~/ipld-eth-db/
# Path to go-ethereum repo.
vulcanize_go_ethereum=~/go-ethereum/
# Path to ipld-eth-server repo.
vulcanize_ipld_eth_server=~/ipld-eth-server/
# Path to test contract.
vulcanize_test_contract=~/ipld-eth-server/test/contract
genesis_file_path='start-up-files/go-ethereum/genesis.json'
db_write=true
eth_forward_eth_calls=false
eth_proxy_on_error=false
eth_http_path="go-ethereum:8545"
```
- Run stack-orchestrator:
```bash
# In stack-orchestrator root directory.
cd helper-scripts
./wrapper.sh \
-e docker \
-d ../docker/local/docker-compose-db-sharding.yml \
-d ../docker/local/docker-compose-go-ethereum.yml \
-d ../docker/local/docker-compose-ipld-eth-server.yml \
-d ../docker/local/docker-compose-contract.yml \
-v remove \
-p ../config.sh
```
- Run test:
```bash
# In ipld-eth-server root directory.
./scripts/run_integration_test.sh
```
- Update stack-orchestrator `config.sh` file:
```bash
#!/bin/bash
# Path to go-ethereum repo.
vulcanize_go_ethereum=~/go-ethereum/
# Path to ipld-eth-server repo.
vulcanize_ipld_eth_server=~/ipld-eth-server/
# Path to test contract.
vulcanize_test_contract=~/ipld-eth-server/test/contract
genesis_file_path='start-up-files/go-ethereum/genesis.json'
db_write=false
eth_forward_eth_calls=true
eth_proxy_on_error=false
eth_http_path="go-ethereum:8545"
```
- Stop the stack-orchestrator and start again using the same command
- Run integration tests for direct proxy fall-through of eth_calls:
```bash
./scripts/run_integration_test_forward_eth_calls.sh
```

26
test/compose-db.yml Normal file
View File

@ -0,0 +1,26 @@
# Containers to run a DB instance for tests
services:
migrations:
restart: on-failure
depends_on:
- ipld-eth-db
image: git.vdb.to/cerc-io/ipld-eth-db/ipld-eth-db:v5.0.2-alpha
environment:
DATABASE_USER: "vdbm"
DATABASE_NAME: "cerc_testing"
DATABASE_PASSWORD: "password"
DATABASE_HOSTNAME: "ipld-eth-db"
DATABASE_PORT: 5432
ipld-eth-db:
container_name: test-ipld-eth-db
image: timescale/timescaledb:latest-pg14
restart: always
command: ["postgres", "-c", "log_statement=all"]
environment:
POSTGRES_USER: "vdbm"
POSTGRES_DB: "cerc_testing"
POSTGRES_PASSWORD: "password"
ports:
- 127.0.0.1:8077:5432

44
test/compose-server.yml Normal file
View File

@ -0,0 +1,44 @@
# Container to run the IPLD server as part of integration tests
services:
ipld-eth-server:
restart: unless-stopped
image: cerc/ipld-eth-server
build: ..
networks:
- test_default
environment:
DATABASE_NAME: "cerc_testing"
DATABASE_HOSTNAME: "ipld-eth-db"
DATABASE_PORT: 5432
DATABASE_USER: "vdbm"
DATABASE_PASSWORD: "password"
ETH_HTTP_PATH: fixturenet-eth-geth-1:8545
ETH_CHAIN_CONFIG: "/tmp/chain.json"
ETH_PROXY_ON_ERROR: false
ETH_FORWARD_ETH_CALLS: $ETH_FORWARD_ETH_CALLS
SERVER_HTTP_PATH: 0.0.0.0:8081
VDB_COMMAND: serve
volumes:
- type: bind
source: "${ETH_CHAIN_CONFIG:-./test/chain.json}"
target: /tmp/chain.json
ports:
- 127.0.0.1:8081:8081
contract-deployer:
restart: on-failure
image: cerc/contract-deployer
build: ./contract
networks:
- test_default
environment:
ETH_ADDR: "http://fixturenet-eth-geth-1:8545"
ETH_CHAIN_ID: $ETH_CHAIN_ID
DEPLOYER_PRIVATE_KEY: $DEPLOYER_PRIVATE_KEY
ports:
- 127.0.0.1:3000:3000
networks:
test_default:
external: true

View File

@ -1,4 +1,5 @@
FROM node:14
# Downgrade from 18.16, see https://github.com/NomicFoundation/hardhat/issues/3877
FROM node:18.15-slim
ARG ETH_ADDR
ENV ETH_ADDR $ETH_ADDR
@ -11,4 +12,4 @@ RUN npm run compile && ls -lah
EXPOSE 3000
ENTRYPOINT ["npm", "start"]
ENTRYPOINT ["node", "src/index.js"]

View File

@ -1,5 +1,6 @@
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract GLDToken is ERC20 {
constructor() ERC20("Gold", "GLD") {
_mint(msg.sender, 1000000000000000000000);

View File

@ -16,6 +16,16 @@ task("accounts", "Prints the list of accounts", async () => {
/**
* @type import('hardhat/config').HardhatUserConfig
*/
const localNetwork = {
url: process.env.ETH_ADDR || "http://127.0.0.1:8545",
chainId: Number(process.env.ETH_CHAIN_ID) || 99,
};
if (process.env.DEPLOYER_PRIVATE_KEY) {
localNetwork["accounts"] = [process.env.DEPLOYER_PRIVATE_KEY];
}
module.exports = {
solidity: {
version: "0.8.0",
@ -30,14 +40,7 @@ module.exports = {
}
},
networks: {
local: {
url: 'http://127.0.0.1:8545',
chainId: 99
},
docker: {
url: process.env.ETH_ADDR,
chainId: 99
}
}
local: localNetwork
},
defaultNetwork: "local"
};

File diff suppressed because it is too large Load Diff

View File

@ -4,23 +4,21 @@
"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"
"start": "node src/index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"description": "Solidity contract deployment server for integration testing",
"dependencies": {
"@openzeppelin/contracts": "^4.0.0",
"fastify": "^3.14.2",
"hardhat": "^2.2.0",
"fastify": "^4.0.0",
"hardhat": "^2.14.0",
"solidity-create2-deployer": "^0.4.0"
},
"devDependencies": {
"@nomiclabs/hardhat-ethers": "^2.0.2",
"@nomiclabs/hardhat-waffle": "^2.0.1",
"@nomiclabs/hardhat-ethers": "^2.2.3",
"@nomiclabs/hardhat-waffle": "^2.0.4",
"chai": "^4.3.4",
"ethereum-waffle": "^3.3.0",
"ethers": "^5.1.0"

View File

@ -1,18 +0,0 @@
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);
});

View File

@ -1,36 +0,0 @@
// 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);
});

View File

@ -2,8 +2,8 @@ const fastify = require('fastify')({ logger: true });
const hre = require("hardhat");
const {
deployContract,
isDeployed
deployContract,
isDeployed
} = require("solidity-create2-deployer");
const { getStorageSlotKey, deployCreate2Factory } = require('./utils');
@ -12,175 +12,147 @@ const CREATE2_FACTORY_ADDRESS = '0x4a27c059FD7E383854Ea7DE6Be9c390a795f6eE3'
// readiness check
fastify.get('/v1/healthz', async (req, reply) => {
reply
.code(200)
.header('Content-Type', 'application/json; charset=utf-8')
.send({ success: true })
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/destroyContract', async (req, reply) => {
const addr = req.query.addr;
const Token = await hre.ethers.getContractFactory("GLDToken");
const token = await Token.attach(addr);
await token.destroy();
const blockNum = await hre.ethers.provider.getBlockNumber()
return {
blockNumber: blockNum,
}
})
fastify.get('/v1/sendEth', async (req, reply) => {
const to = req.query.to;
const value = req.query.value;
const to = req.query.to;
const value = hre.ethers.utils.parseEther(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)
const owner = await hre.ethers.getSigner();
const tx = await owner.sendTransaction({to, value}).then(tx => tx.wait());
// 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,
}
return {
from: tx.from,
to: tx.to,
txHash: tx.hash,
blockNumber: tx.blockNumber,
blockHash: tx.blockHash,
}
});
fastify.get('/v1/deploySLVContract', async (req, reply) => {
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
const token = await SLVToken.deploy();
const receipt = await token.deployTransaction.wait();
function contractCreator(name) {
return async (req, reply) => {
const contract = await hre.ethers.getContractFactory(name);
const instance = await contract.deploy();
const rct = await instance.deployTransaction.wait();
return {
address: token.address,
txHash: token.deployTransaction.hash,
blockNumber: receipt.blockNumber,
blockHash: receipt.blockHash,
address: instance.address,
txHash: rct.transactionHash,
blockNumber: rct.blockNumber,
blockHash: rct.blockHash,
}
});
}
}
fastify.get('/v1/destroySLVContract', async (req, reply) => {
function contractDestroyer(name) {
return async (req, reply) => {
const addr = req.query.addr;
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
const token = SLVToken.attach(addr);
const tx = await token.destroy();
const receipt = await tx.wait();
const contract = await hre.ethers.getContractFactory(name);
const instance = contract.attach(addr);
const rct = await instance.destroy().then(tx => tx.wait());
return {
blockNumber: receipt.blockNumber,
blockNumber: rct.blockNumber,
}
})
}
}
fastify.get('/v1/deployContract', contractCreator("GLDToken"));
fastify.get('/v1/destroyContract', contractDestroyer("GLDToken"));
fastify.get('/v1/deploySLVContract', contractCreator("SLVToken"));
fastify.get('/v1/destroySLVContract', contractDestroyer("SLVToken"));
fastify.get('/v1/incrementCountA', async (req, reply) => {
const addr = req.query.addr;
const addr = req.query.addr;
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
const token = await SLVToken.attach(addr);
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
const token = await SLVToken.attach(addr);
const tx = await token.incrementCountA();
const receipt = await tx.wait();
const tx = await token.incrementCountA();
const receipt = await tx.wait();
return {
blockNumber: receipt.blockNumber,
}
return {
blockNumber: receipt.blockNumber,
}
});
fastify.get('/v1/incrementCountB', async (req, reply) => {
const addr = req.query.addr;
const addr = req.query.addr;
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
const token = await SLVToken.attach(addr);
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
const token = await SLVToken.attach(addr);
const tx = await token.incrementCountB();
const receipt = await tx.wait();
const tx = await token.incrementCountB();
const receipt = await tx.wait();
return {
blockNumber: receipt.blockNumber,
}
return {
blockNumber: receipt.blockNumber,
}
});
fastify.get('/v1/getStorageKey', async (req, reply) => {
const contract = req.query.contract;
const label = req.query.label;
const contract = req.query.contract;
const label = req.query.label;
const key = await getStorageSlotKey(contract, label)
const key = await getStorageSlotKey(contract, label)
return {
key
}
return {
key
}
});
fastify.get('/v1/create2Contract', async (req, reply) => {
const contract = req.query.contract;
const salt = req.query.salt;
const contract = req.query.contract;
const salt = req.query.salt;
const provider = hre.ethers.provider;
const signer = await hre.ethers.getSigner();
const isFactoryDeployed = await isDeployed(CREATE2_FACTORY_ADDRESS, provider);
const provider = hre.ethers.provider;
const signer = await hre.ethers.getSigner();
const isFactoryDeployed = await isDeployed(CREATE2_FACTORY_ADDRESS, provider);
if (!isFactoryDeployed) {
await deployCreate2Factory(provider, signer)
}
const contractFactory = await hre.ethers.getContractFactory(contract);
const bytecode = contractFactory.bytecode;
const constructorTypes = [];
const constructorArgs = [];
const { txHash, address, receipt } = await deployContract({
salt,
contractBytecode: bytecode,
constructorTypes: constructorTypes,
constructorArgs: constructorArgs,
signer
});
const success = await isDeployed(address, provider);
if (success) {
return {
address,
txHash,
blockNumber: receipt.blockNumber,
blockHash: receipt.blockHash,
}
if (!isFactoryDeployed) {
await deployCreate2Factory(provider, signer);
}
const contractFactory = await hre.ethers.getContractFactory(contract);
const bytecode = contractFactory.bytecode;
const constructorTypes = [];
const constructorArgs = [];
const createArgs = {
salt,
contractBytecode: bytecode,
constructorTypes: constructorTypes,
constructorArgs: constructorArgs,
signer
};
const { txHash, address, receipt } = await deployContract(createArgs);
const success = await isDeployed(address, provider);
if (success) {
return {
address,
txHash,
blockNumber: receipt.blockNumber,
blockHash: receipt.blockHash,
}
}
});
async function main() {
try {
await fastify.listen(3000, '0.0.0.0');
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
try {
await fastify.listen({ port: 3000, host: '0.0.0.0' });
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
}
process.on('SIGINT', () => fastify.close().then(() => process.exit(1)));
main();

View File

@ -1,7 +1,8 @@
const { artifacts } = require("hardhat")
const { utils, BigNumber } = require("ethers")
const { deployFactory } = require("solidity-create2-deployer");
const { deployFactory, isDeployed } = require("solidity-create2-deployer");
// Hardcoded account which solidity-create2-deployer uses to deploy its factory
const CREATE2_FACTORY_ACCOUNT = '0x2287Fa6efdEc6d8c3E0f4612ce551dEcf89A357A';
async function getStorageLayout(contractName) {
@ -38,17 +39,17 @@ async function getStorageSlotKey(contractName, variableName) {
};
async function deployCreate2Factory(provider, signer) {
// Send eth to account as required to deploy create2 factory contract.
// Fund hardcoded account before deploying factory
let tx = {
to: CREATE2_FACTORY_ACCOUNT,
value: utils.parseEther('0.01')
}
await signer.sendTransaction(tx).then(tx => tx.wait());
const txResponse = await signer.sendTransaction(tx);
await txResponse.wait()
// Deploy create2 factory contract.
await deployFactory(provider)
const address = await deployFactory(provider);
// solidity-create2-deployer doesn't await the deploy tx
while (!await isDeployed(address, provider));
return address;
}
module.exports = { getStorageSlotKey, deployCreate2Factory }

View File

@ -1,14 +0,0 @@
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!");
});
});

82
test/deploy_helpers.go Normal file
View File

@ -0,0 +1,82 @@
package integration
import (
"encoding/json"
"fmt"
"math/big"
"net/http"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/statediff/types"
)
type ContractDeployed struct {
Address common.Address `json:"address"`
TransactionHash common.Hash `json:"txHash"`
BlockNumber int64 `json:"blockNumber"`
BlockHash common.Hash `json:"blockHash"`
}
type ContractDestroyed struct {
BlockNumber int64 `json:"blockNumber"`
}
type Tx struct {
From string `json:"from"`
To string `json:"to"`
Value *big.Int `json:"value"`
TransactionHash string `json:"txHash"`
BlockNumber int64 `json:"blockNumber"`
BlockHash string `json:"blockHash"`
}
type StorageKey struct {
Key string `json:"key"`
}
type CountIncremented struct {
BlockNumber *big.Int `json:"blockNumber"`
}
const ContractServerUrl = "http://localhost:3000"
// Factory which creates endpoint functions
func MakeGetAndDecodeFunc[R any](format string) func(...interface{}) (*R, error) {
return func(params ...interface{}) (*R, error) {
params = append([]interface{}{ContractServerUrl}, params...)
url := fmt.Sprintf(format, params...)
res, err := http.Get(url)
if err != nil {
return nil, err
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
return nil, fmt.Errorf("%s: %s", url, res.Status)
}
var data R
decoder := json.NewDecoder(res.Body)
return &data, decoder.Decode(&data)
}
}
var (
DeployContract = MakeGetAndDecodeFunc[ContractDeployed]("%s/v1/deployContract")
DestroyContract = MakeGetAndDecodeFunc[ContractDestroyed]("%s/v1/destroyContract?addr=%s")
DeploySLVContract = MakeGetAndDecodeFunc[ContractDeployed]("%s/v1/deploySLVContract")
DestroySLVContract = MakeGetAndDecodeFunc[ContractDestroyed]("%s/v1/destroySLVContract?addr=%s")
SendEth = MakeGetAndDecodeFunc[Tx]("%s/v1/sendEth?to=%s&value=%s")
GetStorageSlotKey = MakeGetAndDecodeFunc[StorageKey]("%s/v1/getStorageKey?contract=%s&label=%s")
IncrementCount = MakeGetAndDecodeFunc[CountIncremented]("%s/v1/incrementCount%s?addr=%s")
Create2Contract = MakeGetAndDecodeFunc[ContractDeployed]("%s/v1/create2Contract?contract=%s&salt=%s")
)
func ClearWatchedAddresses(gethRPCClient *rpc.Client) error {
gethMethod := "statediff_watchAddress"
args := []types.WatchAddressArg{}
// Clear watched addresses
return gethRPCClient.Call(nil, gethMethod, types.Clear, args)
}

View File

@ -3,94 +3,68 @@ package integration_test
import (
"context"
"math/big"
"os"
"strconv"
"time"
"math/rand"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
integration "github.com/cerc-io/ipld-eth-server/v4/test"
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth"
integration "github.com/cerc-io/ipld-eth-server/v5/test"
)
var _ = Describe("Integration test", func() {
directProxyEthCalls, err := strconv.ParseBool(os.Getenv("ETH_FORWARD_ETH_CALLS"))
Expect(err).To(BeNil())
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())
var _ = Describe("Direct proxy integration test", Label("proxy"), func() {
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
BeforeEach(func() {
if !directProxyEthCalls {
Skip("skipping direct-proxy-forwarding integration tests")
}
})
Describe("get Block", func() {
BeforeEach(func() {
contract, contractErr = integration.DeployContract()
time.Sleep(sleepInterval)
Expect(contractErr).ToNot(HaveOccurred())
})
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)))
gethBlock, err := gethClient.BlockByNumber(ctx, big.NewInt(blockNum))
Expect(err).To(MatchError(ethereum.NotFound))
Expect(gethBlock).To(BeZero())
ipldBlock, err := ipldClient.BlockByNumber(ctx, big.NewInt(int64(blockNum)))
ipldBlock, err := ipldClient.BlockByNumber(ctx, big.NewInt(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))
gethBlock, err := gethClient.BlockByHash(ctx, nonExistingBlockHash)
Expect(err).To(MatchError(ethereum.NotFound))
Expect(gethBlock).To(BeZero())
ipldBlock, err := ipldClient.BlockByHash(ctx, common.HexToHash(nonExistingBlockHash))
ipldBlock, err := ipldClient.BlockByHash(ctx, nonExistingBlockHash)
Expect(err).To(MatchError(ethereum.NotFound))
Expect(ipldBlock).To(BeZero())
})
It("get block by number", func() {
Expect(contractErr).ToNot(HaveOccurred())
blockNum := contract.BlockNumber
_, err := gethClient.BlockByNumber(ctx, big.NewInt(int64(blockNum)))
_, err := gethClient.BlockByNumber(ctx, big.NewInt(blockNum))
Expect(err).ToNot(HaveOccurred())
_, err = ipldClient.BlockByNumber(ctx, big.NewInt(int64(blockNum)))
_, err = ipldClient.BlockByNumber(ctx, big.NewInt(blockNum))
Expect(err).To(HaveOccurred())
})
It("get block by hash", func() {
_, err := gethClient.BlockByHash(ctx, common.HexToHash(contract.BlockHash))
_, err := gethClient.BlockByHash(ctx, contract.BlockHash)
Expect(err).ToNot(HaveOccurred())
_, err = ipldClient.BlockByHash(ctx, common.HexToHash(contract.BlockHash))
_, err = ipldClient.BlockByHash(ctx, contract.BlockHash)
Expect(err).To(HaveOccurred())
})
})
@ -98,55 +72,52 @@ var _ = Describe("Integration test", func() {
Describe("Transaction", func() {
BeforeEach(func() {
contract, contractErr = integration.DeployContract()
time.Sleep(sleepInterval)
Expect(contractErr).ToNot(HaveOccurred())
})
It("Get tx by hash", func() {
Expect(contractErr).ToNot(HaveOccurred())
_, _, err := gethClient.TransactionByHash(ctx, common.HexToHash(contract.TransactionHash))
_, _, err := gethClient.TransactionByHash(ctx, contract.TransactionHash)
Expect(err).ToNot(HaveOccurred())
_, _, err = ipldClient.TransactionByHash(ctx, common.HexToHash(contract.TransactionHash))
_, _, err = ipldClient.TransactionByHash(ctx, contract.TransactionHash)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("not found"))
})
It("Get tx by block hash and index", func() {
_, err := gethClient.TransactionInBlock(ctx, common.HexToHash(contract.BlockHash), 0)
_, err := gethClient.TransactionInBlock(ctx, contract.BlockHash, 0)
Expect(err).ToNot(HaveOccurred())
_, err = ipldClient.TransactionInBlock(ctx, common.HexToHash(contract.BlockHash), 0)
_, err = ipldClient.TransactionInBlock(ctx, contract.BlockHash, 0)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("not found"))
})
})
Describe("Receipt", func() {
BeforeEach(func() {
contract, contractErr = integration.DeployContract()
time.Sleep(sleepInterval)
Expect(contractErr).ToNot(HaveOccurred())
})
It("Get tx receipt", func() {
Expect(contractErr).ToNot(HaveOccurred())
_, err := gethClient.TransactionReceipt(ctx, common.HexToHash(contract.TransactionHash))
_, err := gethClient.TransactionReceipt(ctx, contract.TransactionHash)
Expect(err).ToNot(HaveOccurred())
_, err = ipldClient.TransactionReceipt(ctx, common.HexToHash(contract.TransactionHash))
_, err = ipldClient.TransactionReceipt(ctx, contract.TransactionHash)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("not found"))
})
})
Describe("FilterLogs", func() {
BeforeEach(func() {
contract, contractErr = integration.DeployContract()
time.Sleep(sleepInterval)
Expect(contractErr).ToNot(HaveOccurred())
})
It("with blockhash", func() {
Expect(contractErr).ToNot(HaveOccurred())
blockHash := common.HexToHash(contract.BlockHash)
blockHash := contract.BlockHash
filterQuery := ethereum.FilterQuery{
//Addresses: addresses,
BlockHash: &blockHash,
@ -169,103 +140,95 @@ var _ = Describe("Integration test", func() {
Describe("CodeAt", func() {
BeforeEach(func() {
contract, contractErr = integration.DeployContract()
time.Sleep(sleepInterval)
Expect(contractErr).ToNot(HaveOccurred())
})
It("gets code of deployed contract with block number", func() {
_, err := gethClient.CodeAt(ctx, contract.Address, big.NewInt(contract.BlockNumber))
Expect(err).ToNot(HaveOccurred())
ipldCode, err := ipldClient.CodeAt(ctx, contract.Address, big.NewInt(contract.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(ipldCode).To(BeEmpty())
})
It("gets code of contract that doesn't exist at this height", func() {
gethCode, err := gethClient.CodeAt(ctx, contract.Address, big.NewInt(contract.BlockNumber-1))
Expect(err).ToNot(HaveOccurred())
ipldCode, err := ipldClient.CodeAt(ctx, contract.Address, big.NewInt(contract.BlockNumber-1))
Expect(err).ToNot(HaveOccurred())
Expect(gethCode).To(BeEmpty())
Expect(gethCode).To(Equal(ipldCode))
})
It("gets code at non-existing address without block number", func() {
Expect(contractErr).ToNot(HaveOccurred())
gethCode, err := gethClient.CodeAt(ctx, common.HexToAddress(nonExistingAddress), nil)
gethCode, err := gethClient.CodeAt(ctx, nonExistingAddress, nil)
Expect(err).ToNot(HaveOccurred())
ipldCode, err := ipldClient.CodeAt(ctx, common.HexToAddress(nonExistingAddress), nil)
ipldCode, err := ipldClient.CodeAt(ctx, 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() {
_, err := gethClient.CodeAt(ctx, common.HexToAddress(contract.Address), nil)
_, err := gethClient.CodeAt(ctx, contract.Address, nil)
Expect(err).ToNot(HaveOccurred())
ipldCode, err := ipldClient.CodeAt(ctx, common.HexToAddress(contract.Address), nil)
ipldCode, err := ipldClient.CodeAt(ctx, contract.Address, nil)
Expect(err).ToNot(HaveOccurred())
Expect(ipldCode).To(BeEmpty())
})
It("gets code of deployed contract with block number", func() {
_, 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(ipldCode).To(BeEmpty())
})
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"
var newAddress common.Address
rand.Read(newAddress[:])
BeforeEach(func() {
tx, txErr = integration.SendEth(address, "0.01")
time.Sleep(sleepInterval)
tx, txErr = integration.SendEth(newAddress, "0.01")
Expect(txErr).ToNot(HaveOccurred())
})
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)
gethBalance, err := gethClient.BalanceAt(ctx, newAddress, nil)
Expect(err).ToNot(HaveOccurred())
Expect(gethBalance.String()).To(Equal(big.NewInt(10000000000000000).String()))
Expect(gethBalance.String()).To(Equal("10000000000000000"))
ipldBalance, err := ipldClient.BalanceAt(ctx, common.HexToAddress(address), nil)
ipldBalance, err := ipldClient.BalanceAt(ctx, newAddress, nil)
Expect(err).ToNot(HaveOccurred())
Expect(ipldBalance.String()).To(Equal(big.NewInt(0).String()))
Expect(ipldBalance.String()).To(Equal("0"))
})
It("gets balance for an account with eth with block number", func() {
Expect(txErr).ToNot(HaveOccurred())
_, err := gethClient.BalanceAt(ctx, common.HexToAddress(address), big.NewInt(int64(tx.BlockNumber)))
_, err := gethClient.BalanceAt(ctx, newAddress, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
_, err = ipldClient.BalanceAt(ctx, common.HexToAddress(address), big.NewInt(int64(tx.BlockNumber)))
Expect(err).To(HaveOccurred())
_, err = ipldClient.BalanceAt(ctx, newAddress, big.NewInt(tx.BlockNumber))
Expect(err).To(MatchError("header not found"))
})
It("gets historical balance for an account with eth with block number", func() {
Expect(txErr).ToNot(HaveOccurred())
_, err := gethClient.BalanceAt(ctx, common.HexToAddress(address), big.NewInt(int64(tx.BlockNumber-1)))
_, err := gethClient.BalanceAt(ctx, newAddress, big.NewInt(tx.BlockNumber-1))
Expect(err).ToNot(HaveOccurred())
_, err = ipldClient.BalanceAt(ctx, common.HexToAddress(address), big.NewInt(int64(tx.BlockNumber-1)))
Expect(err).To(HaveOccurred())
_, err = ipldClient.BalanceAt(ctx, newAddress, big.NewInt(tx.BlockNumber-1))
Expect(err).To(MatchError("header not found"))
})
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)
It("gets balance for a non-existing account without block number", func() {
gethBalance, err := gethClient.BalanceAt(ctx, nonExistingAddress, nil)
Expect(err).ToNot(HaveOccurred())
ipldBalance, err := ipldClient.BalanceAt(ctx, common.HexToAddress(nonExistingAddress), nil)
ipldBalance, err := ipldClient.BalanceAt(ctx, 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)))
gethBalance, err := gethClient.BalanceAt(ctx, newAddress, big.NewInt(tx.BlockNumber+3))
Expect(err).To(MatchError("header not found"))
ipldBalance, err := ipldClient.BalanceAt(ctx, common.HexToAddress(nonExistingAddress), big.NewInt(int64(tx.BlockNumber+3)))
ipldBalance, err := ipldClient.BalanceAt(ctx, nonExistingAddress, big.NewInt(tx.BlockNumber+3))
Expect(err).To(MatchError("header not found"))
Expect(gethBalance).To(Equal(ipldBalance))
@ -275,100 +238,88 @@ var _ = Describe("Integration test", func() {
Describe("Get Storage", func() {
BeforeEach(func() {
contract, contractErr = integration.DeployContract()
erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10)
time.Sleep(sleepInterval)
Expect(contractErr).ToNot(HaveOccurred())
})
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)
gethStorage, err := gethClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, 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)
ipldStorage, err := ipldClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, nil)
Expect(err).ToNot(HaveOccurred())
Expect(ipldStorage).To(Equal(make([]byte, 32)))
})
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)))
gethStorage, err := gethClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, big.NewInt(contract.BlockNumber))
Expect(err).ToNot(HaveOccurred())
gethTotalSupply := new(big.Int).SetBytes(gethStorage)
Expect(gethTotalSupply).To(Equal(erc20TotalSupply))
_, err = ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(int64(contract.BlockNumber)))
Expect(err).To(HaveOccurred())
_, err = ipldClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, big.NewInt(contract.BlockNumber))
Expect(err).To(MatchError("header not found"))
})
It("gets storage for non-existing account", func() {
totalSupplyIndex := "0x2"
_, err := gethClient.StorageAt(ctx, common.HexToAddress(nonExistingAddress), common.HexToHash(totalSupplyIndex), big.NewInt(int64(contract.BlockNumber)))
_, err := gethClient.StorageAt(ctx, nonExistingAddress, ercTotalSupplyIndex, big.NewInt(contract.BlockNumber))
Expect(err).ToNot(HaveOccurred())
_, err = ipldClient.StorageAt(ctx, common.HexToAddress(nonExistingAddress), common.HexToHash(totalSupplyIndex), big.NewInt(int64(contract.BlockNumber)))
_, err = ipldClient.StorageAt(ctx, nonExistingAddress, ercTotalSupplyIndex, big.NewInt(contract.BlockNumber))
Expect(err).To(MatchError("header not found"))
})
It("gets storage for non-existing contract slot", func() {
_, err := gethClient.StorageAt(ctx, common.HexToAddress(contract.Address), randomHash, big.NewInt(int64(contract.BlockNumber)))
_, err := gethClient.StorageAt(ctx, contract.Address, randomHash, big.NewInt(contract.BlockNumber))
Expect(err).ToNot(HaveOccurred())
_, err = ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), randomHash, big.NewInt(int64(contract.BlockNumber)))
_, err = ipldClient.StorageAt(ctx, contract.Address, randomHash, big.NewInt(contract.BlockNumber))
Expect(err).To(MatchError("header not found"))
})
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))
gethStorage, err := gethClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, big.NewInt(0))
Expect(err).ToNot(HaveOccurred())
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(0))
ipldStorage, err := ipldClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, 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)))
gethStorage, err := gethClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, big.NewInt(blockNum))
Expect(err).To(MatchError("header not found"))
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(int64(blockNum)))
ipldStorage, err := ipldClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, big.NewInt(blockNum))
Expect(err).To(MatchError("header not found"))
Expect(gethStorage).To(Equal(ipldStorage))
})
It("get storage after self destruct", func() {
totalSupplyIndex := "0x2"
tx, err := integration.DestroyContract(contract.Address)
Expect(err).ToNot(HaveOccurred())
time.Sleep(sleepInterval)
gethStorage1, err := gethClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(tx.BlockNumber-1))
gethStorage1, err := gethClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, big.NewInt(tx.BlockNumber-1))
Expect(err).ToNot(HaveOccurred())
gethStorage2, err := gethClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(tx.BlockNumber))
gethStorage2, err := gethClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(gethStorage1).NotTo(Equal(gethStorage2))
Expect(gethStorage2).To(Equal(eth.EmptyNodeValue))
_, err = ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(tx.BlockNumber-1))
Expect(err).To(HaveOccurred())
_, err = ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(tx.BlockNumber))
_, err = ipldClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, big.NewInt(tx.BlockNumber-1))
Expect(err).To(MatchError("header not found"))
_, err = ipldClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, big.NewInt(tx.BlockNumber))
Expect(err).To(MatchError("header not found"))
// Query the current block
ipldStorage3, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), nil)
ipldStorage3, err := ipldClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, nil)
Expect(err).ToNot(HaveOccurred())
Expect(eth.EmptyNodeValue).To(Equal(ipldStorage3))
@ -376,23 +327,19 @@ var _ = Describe("Integration test", func() {
})
Describe("eth call", func() {
var msg ethereum.CallMsg
BeforeEach(func() {
contract, contractErr = integration.DeployContract()
erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10)
Expect(contractErr).ToNot(HaveOccurred())
time.Sleep(sleepInterval)
msg = ethereum.CallMsg{
To: &contract.Address,
Data: common.Hex2Bytes("18160ddd"), // totalSupply()
}
})
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())
@ -406,19 +353,13 @@ var _ = Describe("Integration test", func() {
})
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)))
gethResult, err := gethClient.CallContract(ctx, msg, big.NewInt(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)))
ipldResult, err := ipldClient.CallContract(ctx, msg, big.NewInt(contract.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(gethResult).To(Equal(ipldResult))

View File

@ -1,187 +0,0 @@
package integration
import (
"encoding/json"
"fmt"
"math/big"
"net/http"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/statediff/types"
)
type ContractDeployed struct {
Address string `json:"address"`
TransactionHash string `json:"txHash"`
BlockNumber int `json:"blockNumber"`
BlockHash string `json:"blockHash"`
}
type ContractDestroyed struct {
BlockNumber int64 `json:"blockNumber"`
}
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"`
}
type StorageKey struct {
Key string `json:"key"`
}
type CountIncremented struct {
BlockNumber int64 `json:"blockNumber"`
}
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 DestroyContract(addr string) (*ContractDestroyed, error) {
res, err := http.Get(fmt.Sprintf("%s/v1/destroyContract?addr=%s", srvUrl, addr))
if err != nil {
return nil, err
}
defer res.Body.Close()
var data ContractDestroyed
decoder := json.NewDecoder(res.Body)
return &data, decoder.Decode(&data)
}
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
}
func DeploySLVContract() (*ContractDeployed, error) {
res, err := http.Get(fmt.Sprintf("%s/v1/deploySLVContract", 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 DestroySLVContract(addr string) (*ContractDestroyed, error) {
res, err := http.Get(fmt.Sprintf("%s/v1/destroySLVContract?addr=%s", srvUrl, addr))
if err != nil {
return nil, err
}
defer res.Body.Close()
var data ContractDestroyed
decoder := json.NewDecoder(res.Body)
return &data, decoder.Decode(&data)
}
func IncrementCount(addr string, count string) (*CountIncremented, error) {
res, err := http.Get(fmt.Sprintf("%s/v1/incrementCount%s?addr=%s", srvUrl, count, addr))
if err != nil {
return nil, err
}
var blockNumber CountIncremented
decoder := json.NewDecoder(res.Body)
err = decoder.Decode(&blockNumber)
if err != nil {
return nil, err
}
return &blockNumber, nil
}
func GetStorageSlotKey(contract string, label string) (*StorageKey, error) {
res, err := http.Get(fmt.Sprintf("%s/v1/getStorageKey?contract=%s&label=%s", srvUrl, contract, label))
if err != nil {
return nil, err
}
defer res.Body.Close()
var key StorageKey
decoder := json.NewDecoder(res.Body)
err = decoder.Decode(&key)
if err != nil {
return nil, err
}
return &key, nil
}
func ClearWatchedAddresses(gethRPCClient *rpc.Client) error {
gethMethod := "statediff_watchAddress"
args := []types.WatchAddressArg{}
// Clear watched addresses
gethErr := gethRPCClient.Call(nil, gethMethod, types.Clear, args)
if gethErr != nil {
return gethErr
}
return nil
}
func Create2Contract(contractName string, salt string) (*ContractDeployed, error) {
res, err := http.Get(fmt.Sprintf("%s/v1/create2Contract?contract=%s&salt=%s", srvUrl, contractName, salt))
if err != nil {
return nil, err
}
defer res.Body.Close()
var contract ContractDeployed
decoder := json.NewDecoder(res.Body)
err = decoder.Decode(&contract)
if err != nil {
return nil, err
}
return &contract, nil
}

View File

@ -1,11 +1,13 @@
package integration_test
import (
"io/ioutil"
"os"
"strconv"
"testing"
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
. "github.com/onsi/ginkgo"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
@ -14,6 +16,38 @@ func TestIntegration(t *testing.T) {
RunSpecs(t, "integration test suite")
}
var (
gethHttpPath = "http://127.0.0.1:8545"
ipldEthHttpPath = "http://127.0.0.1:8081"
gethClient *ethclient.Client
ipldClient *ethclient.Client
gethRPCClient *rpc.Client
ipldRPCClient *rpc.Client
testChainId int64 = 99
)
var _ = BeforeSuite(func() {
log.SetOutput(ioutil.Discard)
var err error
envChainID := os.Getenv("ETH_CHAIN_ID")
if len(envChainID) == 0 {
panic("ETH_CHAIN_ID must be set")
}
testChainId, err = strconv.ParseInt(envChainID, 10, 64)
Expect(err).ToNot(HaveOccurred())
if path := os.Getenv("ETH_HTTP_PATH"); len(path) != 0 {
gethHttpPath = "http://" + path
}
if path := os.Getenv("SERVER_HTTP_PATH"); len(path) != 0 {
ipldEthHttpPath = "http://" + path
}
gethClient, err = ethclient.Dial(gethHttpPath)
Expect(err).ToNot(HaveOccurred())
ipldClient, err = ethclient.Dial(ipldEthHttpPath)
Expect(err).ToNot(HaveOccurred())
})

View File

@ -3,97 +3,78 @@ package integration_test
import (
"context"
"math/big"
"os"
"strconv"
"math/rand"
"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/ethclient"
"github.com/ethereum/go-ethereum/rlp"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
integration "github.com/cerc-io/ipld-eth-server/v4/test"
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth"
integration "github.com/cerc-io/ipld-eth-server/v5/test"
)
const nonExistingBlockHash = "0x111111111111111111111111111111111111111111111111111111111111111"
const nonExistingAddress = "0x1111111111111111111111111111111111111111"
var (
randomAddr = common.HexToAddress("0x1C3ab14BBaD3D99F4203bd7a11aCB94882050E6f")
randomHash = crypto.Keccak256Hash(randomAddr.Bytes())
nonExistingBlockHash = common.HexToHash("0x111111111111111111111111111111111111111111111111111111111111111")
nonExistingAddress = common.HexToAddress("0x1111111111111111111111111111111111111111")
randomAddr = common.HexToAddress("0x1C3ab14BBaD3D99F4203bd7a11aCB94882050E6f")
randomHash = crypto.Keccak256Hash(randomAddr.Bytes())
erc20TotalSupply, _ = new(big.Int).SetString("1000000000000000000000", 10)
ercTotalSupplyIndex = common.HexToHash("0x2")
delayInterval = time.Second * 1
)
var _ = Describe("Integration test", func() {
directProxyEthCalls, err := strconv.ParseBool(os.Getenv("ETH_FORWARD_ETH_CALLS"))
Expect(err).To(BeNil())
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())
var _ = Describe("Basic integration test", func() {
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
BeforeEach(func() {
if directProxyEthCalls {
Skip("skipping no-direct-proxy-forwarding integration tests")
}
})
Describe("get Block", func() {
BeforeEach(func() {
contract, contractErr = integration.DeployContract()
time.Sleep(sleepInterval)
Expect(contractErr).ToNot(HaveOccurred())
time.Sleep(delayInterval)
})
It("get not existing block by number", func() {
Expect(contractErr).ToNot(HaveOccurred())
blockNum := big.NewInt(contract.BlockNumber + 100)
blockNum := contract.BlockNumber + 100
gethBlock, err := gethClient.BlockByNumber(ctx, big.NewInt(int64(blockNum)))
gethBlock, err := gethClient.BlockByNumber(ctx, blockNum)
Expect(err).To(MatchError(ethereum.NotFound))
Expect(gethBlock).To(BeZero())
ipldBlock, err := ipldClient.BlockByNumber(ctx, big.NewInt(int64(blockNum)))
ipldBlock, err := ipldClient.BlockByNumber(ctx, 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))
gethBlock, err := gethClient.BlockByHash(ctx, nonExistingBlockHash)
Expect(err).To(MatchError(ethereum.NotFound))
Expect(gethBlock).To(BeZero())
ipldBlock, err := ipldClient.BlockByHash(ctx, common.HexToHash(nonExistingBlockHash))
ipldBlock, err := ipldClient.BlockByHash(ctx, nonExistingBlockHash)
Expect(err).To(MatchError(ethereum.NotFound))
Expect(ipldBlock).To(BeZero())
})
It("get block by number", func() {
Expect(contractErr).ToNot(HaveOccurred())
blockNum := big.NewInt(contract.BlockNumber)
blockNum := contract.BlockNumber
gethBlock, err := gethClient.BlockByNumber(ctx, big.NewInt(int64(blockNum)))
gethBlock, err := gethClient.BlockByNumber(ctx, blockNum)
Expect(err).ToNot(HaveOccurred())
ipldBlock, err := ipldClient.BlockByNumber(ctx, big.NewInt(int64(blockNum)))
ipldBlock, err := ipldClient.BlockByNumber(ctx, blockNum)
Expect(err).ToNot(HaveOccurred())
// check headers are equals
@ -107,10 +88,10 @@ var _ = Describe("Integration test", func() {
})
It("get block by hash", func() {
gethBlock, err := gethClient.BlockByHash(ctx, common.HexToHash(contract.BlockHash))
gethBlock, err := gethClient.BlockByHash(ctx, contract.BlockHash)
Expect(err).ToNot(HaveOccurred())
ipldBlock, err := ipldClient.BlockByHash(ctx, common.HexToHash(contract.BlockHash))
ipldBlock, err := ipldClient.BlockByHash(ctx, contract.BlockHash)
Expect(err).ToNot(HaveOccurred())
// check headers are equals
@ -127,16 +108,14 @@ var _ = Describe("Integration test", func() {
Describe("Transaction", func() {
BeforeEach(func() {
contract, contractErr = integration.DeployContract()
time.Sleep(sleepInterval)
Expect(contractErr).ToNot(HaveOccurred())
})
It("Get tx by hash", func() {
Expect(contractErr).ToNot(HaveOccurred())
gethTx, _, err := gethClient.TransactionByHash(ctx, common.HexToHash(contract.TransactionHash))
gethTx, _, err := gethClient.TransactionByHash(ctx, contract.TransactionHash)
Expect(err).ToNot(HaveOccurred())
ipldTx, _, err := ipldClient.TransactionByHash(ctx, common.HexToHash(contract.TransactionHash))
ipldTx, _, err := ipldClient.TransactionByHash(ctx, contract.TransactionHash)
Expect(err).ToNot(HaveOccurred())
compareTxs(gethTx, ipldTx)
@ -145,10 +124,10 @@ var _ = Describe("Integration test", func() {
})
It("Get tx by block hash and index", func() {
gethTx, err := gethClient.TransactionInBlock(ctx, common.HexToHash(contract.BlockHash), 0)
gethTx, err := gethClient.TransactionInBlock(ctx, contract.BlockHash, 0)
Expect(err).ToNot(HaveOccurred())
ipldTx, err := ipldClient.TransactionInBlock(ctx, common.HexToHash(contract.BlockHash), 0)
ipldTx, err := ipldClient.TransactionInBlock(ctx, contract.BlockHash, 0)
Expect(err).ToNot(HaveOccurred())
compareTxs(gethTx, ipldTx)
@ -158,16 +137,14 @@ var _ = Describe("Integration test", func() {
Describe("Receipt", func() {
BeforeEach(func() {
contract, contractErr = integration.DeployContract()
time.Sleep(sleepInterval)
Expect(contractErr).ToNot(HaveOccurred())
})
It("Get tx receipt", func() {
Expect(contractErr).ToNot(HaveOccurred())
gethReceipt, err := gethClient.TransactionReceipt(ctx, common.HexToHash(contract.TransactionHash))
gethReceipt, err := gethClient.TransactionReceipt(ctx, contract.TransactionHash)
Expect(err).ToNot(HaveOccurred())
ipldReceipt, err := ipldClient.TransactionReceipt(ctx, common.HexToHash(contract.TransactionHash))
ipldReceipt, err := ipldClient.TransactionReceipt(ctx, contract.TransactionHash)
Expect(err).ToNot(HaveOccurred())
Expect(gethReceipt).To(Equal(ipldReceipt))
@ -185,13 +162,11 @@ var _ = Describe("Integration test", func() {
Describe("FilterLogs", func() {
BeforeEach(func() {
contract, contractErr = integration.DeployContract()
time.Sleep(sleepInterval)
Expect(contractErr).ToNot(HaveOccurred())
})
It("with blockhash", func() {
Expect(contractErr).ToNot(HaveOccurred())
blockHash := common.HexToHash(contract.BlockHash)
blockHash := contract.BlockHash
filterQuery := ethereum.FilterQuery{
//Addresses: addresses,
BlockHash: &blockHash,
@ -215,42 +190,40 @@ var _ = Describe("Integration test", func() {
Describe("CodeAt", func() {
BeforeEach(func() {
contract, contractErr = integration.DeployContract()
time.Sleep(sleepInterval)
Expect(contractErr).ToNot(HaveOccurred())
})
It("gets code at non-existing address without block number", func() {
Expect(contractErr).ToNot(HaveOccurred())
gethCode, err := gethClient.CodeAt(ctx, common.HexToAddress(nonExistingAddress), nil)
gethCode, err := gethClient.CodeAt(ctx, nonExistingAddress, nil)
Expect(err).ToNot(HaveOccurred())
ipldCode, err := ipldClient.CodeAt(ctx, common.HexToAddress(nonExistingAddress), nil)
ipldCode, err := ipldClient.CodeAt(ctx, 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)
gethCode, err := gethClient.CodeAt(ctx, contract.Address, nil)
Expect(err).ToNot(HaveOccurred())
ipldCode, err := ipldClient.CodeAt(ctx, common.HexToAddress(contract.Address), nil)
ipldCode, err := ipldClient.CodeAt(ctx, 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)))
gethCode, err := gethClient.CodeAt(ctx, contract.Address, big.NewInt(contract.BlockNumber))
Expect(err).ToNot(HaveOccurred())
ipldCode, err := ipldClient.CodeAt(ctx, common.HexToAddress(contract.Address), big.NewInt(int64(contract.BlockNumber)))
ipldCode, err := ipldClient.CodeAt(ctx, contract.Address, big.NewInt(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)))
gethCode, err := gethClient.CodeAt(ctx, contract.Address, big.NewInt(contract.BlockNumber-1))
Expect(err).ToNot(HaveOccurred())
ipldCode, err := ipldClient.CodeAt(ctx, common.HexToAddress(contract.Address), big.NewInt(int64(contract.BlockNumber-1)))
ipldCode, err := ipldClient.CodeAt(ctx, contract.Address, big.NewInt(contract.BlockNumber-1))
Expect(err).ToNot(HaveOccurred())
Expect(gethCode).To(BeEmpty())
@ -259,63 +232,56 @@ var _ = Describe("Integration test", func() {
})
Describe("Get balance", func() {
address := "0x1111111111111111111111111111111111111112"
var newAddress common.Address
rand.Read(newAddress[:])
BeforeEach(func() {
tx, txErr = integration.SendEth(address, "0.01")
time.Sleep(sleepInterval)
})
It("gets balance for an account with eth without block number", func() {
tx, txErr = integration.SendEth(newAddress, "0.01")
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)))
gethBalance, err := gethClient.BalanceAt(ctx, newAddress, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
ipldBalance, err := ipldClient.BalanceAt(ctx, common.HexToAddress(address), big.NewInt(int64(tx.BlockNumber)))
ipldBalance, err := ipldClient.BalanceAt(ctx, newAddress, big.NewInt(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)))
It("gets balance for an account with eth without block number", func() {
gethBalance, err := gethClient.BalanceAt(ctx, newAddress, nil)
Expect(err).ToNot(HaveOccurred())
ipldBalance, err := ipldClient.BalanceAt(ctx, common.HexToAddress(address), big.NewInt(int64(tx.BlockNumber-1)))
ipldBalance, err := ipldClient.BalanceAt(ctx, newAddress, nil)
Expect(err).ToNot(HaveOccurred())
Expect(gethBalance).To(Equal(ipldBalance))
})
It("gets historical balance for an account with eth with block number", func() {
gethBalance, err := gethClient.BalanceAt(ctx, newAddress, big.NewInt(tx.BlockNumber-1))
Expect(err).ToNot(HaveOccurred())
ipldBalance, err := ipldClient.BalanceAt(ctx, newAddress, big.NewInt(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)
gethBalance, err := gethClient.BalanceAt(ctx, nonExistingAddress, nil)
Expect(err).ToNot(HaveOccurred())
ipldBalance, err := ipldClient.BalanceAt(ctx, common.HexToAddress(nonExistingAddress), nil)
ipldBalance, err := ipldClient.BalanceAt(ctx, 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)))
gethBalance, err := gethClient.BalanceAt(ctx, newAddress, big.NewInt(tx.BlockNumber+3))
Expect(err).To(MatchError("header not found"))
ipldBalance, err := ipldClient.BalanceAt(ctx, common.HexToAddress(nonExistingAddress), big.NewInt(int64(tx.BlockNumber+3)))
ipldBalance, err := ipldClient.BalanceAt(ctx, newAddress, big.NewInt(tx.BlockNumber+3))
Expect(err).To(MatchError("header not found"))
Expect(gethBalance).To(Equal(ipldBalance))
@ -323,126 +289,111 @@ var _ = Describe("Integration test", func() {
})
Describe("Get Storage", func() {
var slvContract *integration.ContractDeployed
var slvCountA *big.Int
contractSalt := "SLVContractSalt"
var contractSalt string
countAIndex := common.HexToHash("0x5")
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))
Expect(contract.BlockNumber).ToNot(BeZero())
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))
contractSalt = common.Bytes2Hex(contract.BlockHash[:10])
})
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)))
gethStorage, err := gethClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, big.NewInt(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)))
ipldStorage, err := ipldClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, big.NewInt(contract.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(gethStorage).To(Equal(ipldStorage))
})
It("gets ERC20 total supply (without block number)", func() {
gethStorage, err := gethClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, nil)
Expect(err).ToNot(HaveOccurred())
gethTotalSupply := new(big.Int).SetBytes(gethStorage)
Expect(gethTotalSupply).To(Equal(erc20TotalSupply))
ipldStorage, err := ipldClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, nil)
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)))
gethStorage, err := gethClient.StorageAt(ctx, nonExistingAddress, ercTotalSupplyIndex, big.NewInt(contract.BlockNumber))
Expect(err).ToNot(HaveOccurred())
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(nonExistingAddress), common.HexToHash(totalSupplyIndex), big.NewInt(int64(contract.BlockNumber)))
ipldStorage, err := ipldClient.StorageAt(ctx, nonExistingAddress, ercTotalSupplyIndex, big.NewInt(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)))
gethStorage, err := gethClient.StorageAt(ctx, contract.Address, randomHash, big.NewInt(contract.BlockNumber))
Expect(err).ToNot(HaveOccurred())
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), randomHash, big.NewInt(int64(contract.BlockNumber)))
ipldStorage, err := ipldClient.StorageAt(ctx, contract.Address, randomHash, big.NewInt(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))
gethStorage, err := gethClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, big.NewInt(0))
Expect(err).ToNot(HaveOccurred())
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(0))
ipldStorage, err := ipldClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, 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)))
gethStorage, err := gethClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, big.NewInt(blockNum))
Expect(err).To(MatchError("header not found"))
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(int64(blockNum)))
ipldStorage, err := ipldClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, big.NewInt(blockNum))
Expect(err).To(MatchError("header not found"))
Expect(gethStorage).To(Equal(ipldStorage))
})
It("get storage for SLV countA after tx", func() {
slvContract, contractErr = integration.Create2Contract("SLVToken", contractSalt)
It("gets storage for SLV countA after tx", func() {
slvContract, contractErr := integration.Create2Contract("SLVToken", contractSalt)
Expect(contractErr).ToNot(HaveOccurred())
countAIndex := "0x5"
time.Sleep(sleepInterval)
gethStorage, err := gethClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), nil)
gethStorage, err := gethClient.StorageAt(ctx, slvContract.Address, countAIndex, big.NewInt(slvContract.BlockNumber))
Expect(err).ToNot(HaveOccurred())
gethCountA := new(big.Int).SetBytes(gethStorage)
slvCountA = gethCountA
slvCountA := new(big.Int).SetBytes(gethStorage)
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), nil)
err = waitForBlock(ctx, ipldClient, slvContract.BlockNumber)
Expect(err).ToNot(HaveOccurred())
ipldStorage, err := ipldClient.StorageAt(ctx, slvContract.Address, countAIndex, big.NewInt(slvContract.BlockNumber))
Expect(err).ToNot(HaveOccurred())
ipldCountA := new(big.Int).SetBytes(ipldStorage)
Expect(ipldCountA.String()).To(Equal(slvCountA.String()))
Expect(ipldCountA).To(Equal(slvCountA))
_, txErr = integration.IncrementCount(slvContract.Address, "A")
Expect(txErr).ToNot(HaveOccurred())
inc, err := integration.IncrementCount("A", slvContract.Address)
Expect(err).ToNot(HaveOccurred())
slvCountA.Add(slvCountA, big.NewInt(1))
time.Sleep(sleepInterval)
ipldStorage, err = ipldClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), nil)
ipldStorage, err = ipldClient.StorageAt(ctx, slvContract.Address, countAIndex, inc.BlockNumber)
Expect(err).ToNot(HaveOccurred())
ipldCountA = new(big.Int).SetBytes(ipldStorage)
Expect(ipldCountA.String()).To(Equal(slvCountA.String()))
Expect(ipldCountA).To(Equal(slvCountA))
})
It("get storage after self destruct", func() {
totalSupplyIndex := "0x2"
countAIndex := "0x5"
It("gets storage after destruction and redeploy", func() {
slvContract, contractErr := integration.Create2Contract("SLVToken", contractSalt)
Expect(contractErr).ToNot(HaveOccurred())
tx, err := integration.DestroyContract(contract.Address)
Expect(err).ToNot(HaveOccurred())
@ -450,83 +401,68 @@ var _ = Describe("Integration test", func() {
slvTx, err := integration.DestroyContract(slvContract.Address)
Expect(err).ToNot(HaveOccurred())
time.Sleep(sleepInterval)
gethStorage1, err := gethClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(tx.BlockNumber-1))
gethStorage1, err := gethClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, big.NewInt(tx.BlockNumber-1))
Expect(err).ToNot(HaveOccurred())
gethStorage2, err := gethClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(tx.BlockNumber))
gethStorage2, err := gethClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(gethStorage1).NotTo(Equal(gethStorage2))
Expect(gethStorage2).To(Equal(eth.EmptyNodeValue))
ipldStorage1, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(tx.BlockNumber-1))
ipldStorage1, err := ipldClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, big.NewInt(tx.BlockNumber-1))
Expect(err).ToNot(HaveOccurred())
ipldStorage2, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(tx.BlockNumber))
ipldStorage2, err := ipldClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(ipldStorage1).To(Equal(gethStorage1))
Expect(ipldStorage2).To(Equal(gethStorage2))
// Query the current block
ipldStorage3, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), nil)
ipldStorage3, err := ipldClient.StorageAt(ctx, contract.Address, ercTotalSupplyIndex, nil)
Expect(err).ToNot(HaveOccurred())
Expect(ipldStorage2).To(Equal(ipldStorage3))
// Check for SLV contract
gethStorage, err := gethClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), big.NewInt(slvTx.BlockNumber))
gethStorage, err := gethClient.StorageAt(ctx, slvContract.Address, countAIndex, big.NewInt(slvTx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(gethStorage).To(Equal(eth.EmptyNodeValue))
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), big.NewInt(slvTx.BlockNumber))
ipldStorage, err := ipldClient.StorageAt(ctx, slvContract.Address, countAIndex, big.NewInt(slvTx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(ipldStorage).To(Equal(gethStorage))
slvCountA.Set(big.NewInt(0))
})
It("get storage after redeploying", func() {
// Redeploy to same address
slvContract, contractErr = integration.Create2Contract("SLVToken", contractSalt)
Expect(contractErr).ToNot(HaveOccurred())
time.Sleep(sleepInterval)
countAIndex := "0x5"
gethStorage, err := gethClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), nil)
gethStorage, err = gethClient.StorageAt(ctx, slvContract.Address, countAIndex, big.NewInt(slvContract.BlockNumber))
Expect(err).ToNot(HaveOccurred())
gethCountA := new(big.Int).SetBytes(gethStorage)
Expect(gethCountA.String()).To(Equal(slvCountA.String()))
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), nil)
ipldStorage, err = ipldClient.StorageAt(ctx, slvContract.Address, countAIndex, big.NewInt(slvContract.BlockNumber))
Expect(err).ToNot(HaveOccurred())
ipldCountA := new(big.Int).SetBytes(ipldStorage)
Expect(ipldCountA.String()).To(Equal(slvCountA.String()))
Expect(gethStorage).To(Equal(ipldStorage))
ipldCountA := new(big.Int).SetBytes(ipldStorage)
Expect(ipldCountA.String()).To(Equal("0"))
})
})
Describe("eth call", func() {
var msg ethereum.CallMsg
BeforeEach(func() {
contract, contractErr = integration.DeployContract()
erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10)
Expect(contractErr).ToNot(HaveOccurred())
time.Sleep(sleepInterval)
msg = ethereum.CallMsg{
To: &contract.Address,
Data: common.Hex2Bytes("18160ddd"), // totalSupply()
}
})
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())
@ -540,19 +476,26 @@ var _ = Describe("Integration test", func() {
})
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)))
gethResult, err := gethClient.CallContract(ctx, msg, big.NewInt(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)))
ipldResult, err := ipldClient.CallContract(ctx, msg, big.NewInt(contract.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(gethResult).To(Equal(ipldResult))
})
It("calls totalSupply() with block hash", func() {
gethResult, err := gethClient.CallContractAtHash(ctx, msg, contract.BlockHash)
Expect(err).ToNot(HaveOccurred())
gethTotalSupply := new(big.Int).SetBytes(gethResult)
Expect(gethTotalSupply).To(Equal(erc20TotalSupply))
ipldResult, err := ipldClient.CallContractAtHash(ctx, msg, contract.BlockHash)
Expect(err).ToNot(HaveOccurred())
Expect(gethResult).To(Equal(ipldResult))
@ -573,6 +516,7 @@ var _ = Describe("Integration test", func() {
})
func compareBlocks(block1 *types.Block, block2 *types.Block) {
GinkgoHelper()
Expect(block1.Header()).To(Equal(block2.Header()))
Expect(block1.Uncles()).To(Equal(block2.Uncles()))
@ -586,11 +530,12 @@ func compareBlocks(block1 *types.Block, block2 *types.Block) {
}
func compareTxs(tx1 *types.Transaction, tx2 *types.Transaction) {
GinkgoHelper()
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(99))
signer := types.NewLondonSigner(big.NewInt(testChainId))
gethSender, err := types.Sender(signer, tx1)
Expect(err).ToNot(HaveOccurred())

3
test/stack-refs.yml Normal file
View File

@ -0,0 +1,3 @@
repos:
- github.com/cerc-io/go-ethereum v1.11.5-statediff-5.0.5-alpha
- github.com/cerc-io/ipld-eth-db v5.0.2-alpha

28
test/util_test.go Normal file
View File

@ -0,0 +1,28 @@
package integration_test
import (
"context"
"errors"
"time"
"github.com/ethereum/go-ethereum/ethclient"
)
func waitForBlock(ctx context.Context, client *ethclient.Client, target int64) error {
timeout := 10 * time.Second
for {
select {
case <-time.After(timeout):
return errors.New("timed out")
default:
latest, err := client.BlockNumber(ctx)
if err != nil {
return err
}
if uint64(target) <= latest {
return nil
}
}
}
}

View File

@ -3,41 +3,22 @@ package integration_test
import (
"context"
"math/big"
"os"
"strconv"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
integration "github.com/cerc-io/ipld-eth-server/v4/test"
integration "github.com/cerc-io/ipld-eth-server/v5/test"
)
var (
gethMethod = "statediff_watchAddress"
ipldMethod = "vdb_watchAddress"
sleepInterval = 2 * time.Second
)
var _ = Describe("WatchAddress integration test", func() {
dbWrite, err := strconv.ParseBool(os.Getenv("DB_WRITE"))
Expect(err).To(BeNil())
gethHttpPath := "http://127.0.0.1:8545"
gethRPCClient, err := rpc.Dial(gethHttpPath)
Expect(err).ToNot(HaveOccurred())
ipldEthHttpPath := "http://127.0.0.1:8081"
ipldClient, err := ethclient.Dial(ipldEthHttpPath)
Expect(err).ToNot(HaveOccurred())
ipldRPCClient, err := rpc.Dial(ipldEthHttpPath)
Expect(err).ToNot(HaveOccurred())
var (
ctx = context.Background()
@ -45,11 +26,14 @@ var _ = Describe("WatchAddress integration test", func() {
contractErr error
incErr error
tx *integration.Tx
inc *integration.CountIncremented
contract1 *integration.ContractDeployed
contract2 *integration.ContractDeployed
contract3 *integration.ContractDeployed
countAIndex string
countAIndex common.Hash
prevBalance1 *big.Int
prevBalance2 *big.Int
@ -69,9 +53,13 @@ var _ = Describe("WatchAddress integration test", func() {
)
BeforeEach(func() {
if !dbWrite {
Skip("skipping WatchAddress API integration tests")
}
var err error
gethRPCClient, err = rpc.Dial(gethHttpPath)
Expect(err).ToNot(HaveOccurred())
ipldRPCClient, err = rpc.Dial(ipldEthHttpPath)
Expect(err).ToNot(HaveOccurred())
})
It("test init", func() {
@ -88,7 +76,7 @@ var _ = Describe("WatchAddress integration test", func() {
// Get the storage slot key
storageSlotAKey, err := integration.GetStorageSlotKey("SLVToken", "countA")
Expect(err).ToNot(HaveOccurred())
countAIndex = storageSlotAKey.Key
countAIndex = common.HexToHash(storageSlotAKey.Key)
// Clear out watched addresses
err = integration.ClearWatchedAddresses(gethRPCClient)
@ -97,21 +85,21 @@ var _ = Describe("WatchAddress integration test", func() {
// Get initial balances for all the contracts
// Contract 1
actualBalance1 = big.NewInt(0)
initBalance1, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
initBalance1, err := ipldClient.BalanceAt(ctx, contract1.Address, big.NewInt(contract1.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(initBalance1.String()).To(Equal(actualBalance1.String()))
prevBalance1 = big.NewInt(0)
// Contract 2
actualBalance2 = big.NewInt(0)
initBalance2, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
initBalance2, err := ipldClient.BalanceAt(ctx, contract2.Address, big.NewInt(contract2.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(initBalance2.String()).To(Equal(actualBalance2.String()))
prevBalance2 = big.NewInt(0)
// Contract 3
actualBalance3 = big.NewInt(0)
initBalance3, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
initBalance3, err := ipldClient.BalanceAt(ctx, contract3.Address, big.NewInt(contract3.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(initBalance3.String()).To(Equal(actualBalance3.String()))
prevBalance3 = big.NewInt(0)
@ -119,7 +107,7 @@ var _ = Describe("WatchAddress integration test", func() {
// Get initial storage values for the contracts
// Contract 1, countA
actualCountA1 = big.NewInt(0)
ipldCountA1Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
ipldCountA1Storage, err := ipldClient.StorageAt(ctx, contract1.Address, countAIndex, big.NewInt(contract1.BlockNumber))
Expect(err).ToNot(HaveOccurred())
ipldCountA1 := new(big.Int).SetBytes(ipldCountA1Storage)
Expect(ipldCountA1.String()).To(Equal(actualCountA1.String()))
@ -127,18 +115,18 @@ var _ = Describe("WatchAddress integration test", func() {
// Contract 2, countA
actualCountA2 = big.NewInt(0)
ipldCountA2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
ipldCountA2Storage, err := ipldClient.StorageAt(ctx, contract2.Address, countAIndex, big.NewInt(contract2.BlockNumber))
Expect(err).ToNot(HaveOccurred())
ipldCountA2 := new(big.Int).SetBytes(ipldCountA2Storage)
Expect(ipldCountA2.String()).To(Equal(actualCountA2.String()))
Expect(ipldCountA2.String()).To(Equal("0"))
prevCountA2 = big.NewInt(0)
// Contract 3, countA
actualCountA3 = big.NewInt(0)
ipldCountA3Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
ipldCountA3Storage, err := ipldClient.StorageAt(ctx, contract3.Address, countAIndex, big.NewInt(contract3.BlockNumber))
Expect(err).ToNot(HaveOccurred())
ipldCountA3 := new(big.Int).SetBytes(ipldCountA3Storage)
Expect(ipldCountA3.String()).To(Equal(actualCountA2.String()))
Expect(ipldCountA3.String()).To(Equal("0"))
prevCountA3 = big.NewInt(0)
})
@ -153,70 +141,64 @@ var _ = Describe("WatchAddress integration test", func() {
// WatchedAddresses = []
// Send eth to all three contract accounts
// Contract 1
_, txErr = integration.SendEth(contract1.Address, "0.01")
time.Sleep(sleepInterval)
tx, txErr = integration.SendEth(contract1.Address, "0.01")
Expect(txErr).ToNot(HaveOccurred())
actualBalance1.Add(actualBalance1, big.NewInt(10000000000000000))
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, contract1.Address, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(balance1AfterTransfer.String()).To(Equal(actualBalance1.String()))
prevBalance1.Set(actualBalance1)
// Contract 2
_, txErr = integration.SendEth(contract2.Address, "0.01")
time.Sleep(sleepInterval)
tx, txErr = integration.SendEth(contract2.Address, "0.01")
Expect(txErr).ToNot(HaveOccurred())
actualBalance2.Add(actualBalance2, big.NewInt(10000000000000000))
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, contract2.Address, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(balance2AfterTransfer.String()).To(Equal(actualBalance2.String()))
prevBalance2.Set(actualBalance2)
// Contract 3
_, txErr = integration.SendEth(contract3.Address, "0.01")
time.Sleep(sleepInterval)
tx, txErr = integration.SendEth(contract3.Address, "0.01")
Expect(txErr).ToNot(HaveOccurred())
actualBalance3.Add(actualBalance3, big.NewInt(10000000000000000))
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, contract3.Address, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(balance3AfterTransfer.String()).To(Equal(actualBalance3.String()))
prevBalance3.Set(actualBalance3)
// Increment counts
// Contract 1, countA
_, incErr = integration.IncrementCount(contract1.Address, "A")
time.Sleep(sleepInterval)
inc, incErr = integration.IncrementCount("A", contract1.Address)
Expect(incErr).ToNot(HaveOccurred())
actualCountA1.Add(actualCountA1, big.NewInt(1))
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, contract1.Address, countAIndex, inc.BlockNumber)
Expect(err).ToNot(HaveOccurred())
countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage)
Expect(countA1AfterIncrement.String()).To(Equal(actualCountA1.String()))
prevCountA1.Set(actualCountA1)
// Contract 2, countA
_, incErr = integration.IncrementCount(contract2.Address, "A")
time.Sleep(sleepInterval)
inc, incErr = integration.IncrementCount("A", contract2.Address)
Expect(incErr).ToNot(HaveOccurred())
actualCountA2.Add(actualCountA2, big.NewInt(1))
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, contract2.Address, countAIndex, inc.BlockNumber)
Expect(err).ToNot(HaveOccurred())
countA2AfterIncrement := new(big.Int).SetBytes(countA2AfterIncrementStorage)
Expect(countA2AfterIncrement.String()).To(Equal(actualCountA2.String()))
prevCountA2.Set(actualCountA2)
// Contract 3, countA
_, incErr = integration.IncrementCount(contract3.Address, "A")
time.Sleep(sleepInterval)
inc, incErr = integration.IncrementCount("A", contract3.Address)
Expect(incErr).ToNot(HaveOccurred())
actualCountA3.Add(actualCountA3, big.NewInt(1))
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, contract3.Address, countAIndex, inc.BlockNumber)
Expect(err).ToNot(HaveOccurred())
countA3AfterIncrement := new(big.Int).SetBytes(countA3AfterIncrementStorage)
Expect(countA3AfterIncrement.String()).To(Equal(actualCountA3.String()))
@ -229,7 +211,7 @@ var _ = Describe("WatchAddress integration test", func() {
operation := sdtypes.Add
args := []sdtypes.WatchAddressArg{
{
Address: contract1.Address,
Address: contract1.Address.String(),
CreatedAt: uint64(contract1.BlockNumber),
},
}
@ -239,67 +221,61 @@ var _ = Describe("WatchAddress integration test", func() {
// WatchedAddresses = [Contract1]
// Send eth to all three contract accounts
// Contract 1
_, txErr = integration.SendEth(contract1.Address, "0.01")
time.Sleep(sleepInterval)
tx, txErr = integration.SendEth(contract1.Address, "0.01")
Expect(txErr).ToNot(HaveOccurred())
actualBalance1.Add(actualBalance1, big.NewInt(10000000000000000))
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, contract1.Address, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(balance1AfterTransfer.String()).To(Equal(actualBalance1.String()))
prevBalance1.Set(actualBalance1)
// Contract 2
_, txErr = integration.SendEth(contract2.Address, "0.01")
time.Sleep(sleepInterval)
tx, txErr = integration.SendEth(contract2.Address, "0.01")
Expect(txErr).ToNot(HaveOccurred())
actualBalance2.Add(actualBalance2, big.NewInt(10000000000000000))
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, contract2.Address, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(balance2AfterTransfer.String()).To(Equal(prevBalance2.String()))
// Contract 3
_, txErr = integration.SendEth(contract3.Address, "0.01")
time.Sleep(sleepInterval)
tx, txErr = integration.SendEth(contract3.Address, "0.01")
Expect(txErr).ToNot(HaveOccurred())
actualBalance3.Add(actualBalance3, big.NewInt(10000000000000000))
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, contract3.Address, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(balance3AfterTransfer.String()).To(Equal(prevBalance3.String()))
// Increment counts
// Contract 1, countA
_, incErr = integration.IncrementCount(contract1.Address, "A")
time.Sleep(sleepInterval)
inc, incErr = integration.IncrementCount("A", contract1.Address)
Expect(incErr).ToNot(HaveOccurred())
actualCountA1.Add(actualCountA1, big.NewInt(1))
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, contract1.Address, countAIndex, inc.BlockNumber)
Expect(err).ToNot(HaveOccurred())
countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage)
Expect(countA1AfterIncrement.String()).To(Equal(actualCountA1.String()))
prevCountA1.Set(actualCountA1)
// Contract 2, countA
_, incErr = integration.IncrementCount(contract2.Address, "A")
time.Sleep(sleepInterval)
inc, incErr = integration.IncrementCount("A", contract2.Address)
Expect(incErr).ToNot(HaveOccurred())
actualCountA2.Add(actualCountA2, big.NewInt(1))
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, contract2.Address, countAIndex, inc.BlockNumber)
Expect(err).ToNot(HaveOccurred())
countA2AfterIncrement := new(big.Int).SetBytes(countA2AfterIncrementStorage)
Expect(countA2AfterIncrement.String()).To(Equal(prevCountA2.String()))
// Contract 3, countA
_, incErr = integration.IncrementCount(contract3.Address, "A")
time.Sleep(sleepInterval)
inc, incErr = integration.IncrementCount("A", contract3.Address)
Expect(incErr).ToNot(HaveOccurred())
actualCountA3.Add(actualCountA3, big.NewInt(1))
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, contract3.Address, countAIndex, inc.BlockNumber)
Expect(err).ToNot(HaveOccurred())
countA3AfterIncrement := new(big.Int).SetBytes(countA3AfterIncrementStorage)
Expect(countA3AfterIncrement.String()).To(Equal(prevCountA3.String()))
@ -311,7 +287,7 @@ var _ = Describe("WatchAddress integration test", func() {
operation := sdtypes.Add
args := []sdtypes.WatchAddressArg{
{
Address: contract2.Address,
Address: contract2.Address.String(),
CreatedAt: uint64(contract2.BlockNumber),
},
}
@ -321,69 +297,63 @@ var _ = Describe("WatchAddress integration test", func() {
// WatchedAddresses = [Contract1, Contract2]
// Send eth to all three contract accounts
// Contract 1
_, txErr = integration.SendEth(contract1.Address, "0.01")
time.Sleep(sleepInterval)
tx, txErr = integration.SendEth(contract1.Address, "0.01")
Expect(txErr).ToNot(HaveOccurred())
actualBalance1.Add(actualBalance1, big.NewInt(10000000000000000))
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, contract1.Address, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(balance1AfterTransfer.String()).To(Equal(actualBalance1.String()))
prevBalance1.Set(actualBalance1)
// Contract 2
_, txErr = integration.SendEth(contract2.Address, "0.01")
time.Sleep(sleepInterval)
tx, txErr = integration.SendEth(contract2.Address, "0.01")
Expect(txErr).ToNot(HaveOccurred())
actualBalance2.Add(actualBalance2, big.NewInt(10000000000000000))
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, contract2.Address, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(balance2AfterTransfer.String()).To(Equal(actualBalance2.String()))
prevBalance2.Set(actualBalance2)
// Contract 3
_, txErr = integration.SendEth(contract3.Address, "0.01")
time.Sleep(sleepInterval)
tx, txErr = integration.SendEth(contract3.Address, "0.01")
Expect(txErr).ToNot(HaveOccurred())
actualBalance3.Add(actualBalance3, big.NewInt(10000000000000000))
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, contract3.Address, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(balance3AfterTransfer.String()).To(Equal(prevBalance3.String()))
// Increment counts
// Contract 1, countA
_, incErr = integration.IncrementCount(contract1.Address, "A")
time.Sleep(sleepInterval)
inc, incErr = integration.IncrementCount("A", contract1.Address)
Expect(incErr).ToNot(HaveOccurred())
actualCountA1.Add(actualCountA1, big.NewInt(1))
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, contract1.Address, countAIndex, inc.BlockNumber)
Expect(err).ToNot(HaveOccurred())
countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage)
Expect(countA1AfterIncrement.String()).To(Equal(actualCountA1.String()))
prevCountA1.Set(actualCountA1)
// Contract 2, countA
_, incErr = integration.IncrementCount(contract2.Address, "A")
time.Sleep(sleepInterval)
inc, incErr = integration.IncrementCount("A", contract2.Address)
Expect(incErr).ToNot(HaveOccurred())
actualCountA2.Add(actualCountA2, big.NewInt(1))
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, contract2.Address, countAIndex, inc.BlockNumber)
Expect(err).ToNot(HaveOccurred())
countA2AfterIncrement := new(big.Int).SetBytes(countA2AfterIncrementStorage)
Expect(countA2AfterIncrement.String()).To(Equal(actualCountA2.String()))
prevCountA2.Set(actualCountA2)
// Contract 3, countA
_, incErr = integration.IncrementCount(contract3.Address, "A")
time.Sleep(sleepInterval)
inc, incErr = integration.IncrementCount("A", contract3.Address)
Expect(incErr).ToNot(HaveOccurred())
actualCountA3.Add(actualCountA3, big.NewInt(1))
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, contract3.Address, countAIndex, inc.BlockNumber)
Expect(err).ToNot(HaveOccurred())
countA3AfterIncrement := new(big.Int).SetBytes(countA3AfterIncrementStorage)
Expect(countA3AfterIncrement.String()).To(Equal(prevCountA3.String()))
@ -395,7 +365,7 @@ var _ = Describe("WatchAddress integration test", func() {
operation := sdtypes.Remove
args := []sdtypes.WatchAddressArg{
{
Address: contract1.Address,
Address: contract1.Address.String(),
CreatedAt: uint64(contract1.BlockNumber),
},
}
@ -405,67 +375,61 @@ var _ = Describe("WatchAddress integration test", func() {
// WatchedAddresses = [Contract2]
// Send eth to all three contract accounts
// Contract 1
_, txErr = integration.SendEth(contract1.Address, "0.01")
time.Sleep(sleepInterval)
tx, txErr = integration.SendEth(contract1.Address, "0.01")
Expect(txErr).ToNot(HaveOccurred())
actualBalance1.Add(actualBalance1, big.NewInt(10000000000000000))
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, contract1.Address, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(balance1AfterTransfer.String()).To(Equal(prevBalance1.String()))
// Contract 2
_, txErr = integration.SendEth(contract2.Address, "0.01")
time.Sleep(sleepInterval)
tx, txErr = integration.SendEth(contract2.Address, "0.01")
Expect(txErr).ToNot(HaveOccurred())
actualBalance2.Add(actualBalance2, big.NewInt(10000000000000000))
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, contract2.Address, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(balance2AfterTransfer.String()).To(Equal(actualBalance2.String()))
prevBalance2.Set(actualBalance2)
// Contract 3
_, txErr = integration.SendEth(contract3.Address, "0.01")
time.Sleep(sleepInterval)
tx, txErr = integration.SendEth(contract3.Address, "0.01")
Expect(txErr).ToNot(HaveOccurred())
actualBalance3.Add(actualBalance3, big.NewInt(10000000000000000))
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, contract3.Address, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(balance3AfterTransfer.String()).To(Equal(prevBalance3.String()))
// Increment counts
// Contract 1, countA
_, incErr = integration.IncrementCount(contract1.Address, "A")
time.Sleep(sleepInterval)
inc, incErr = integration.IncrementCount("A", contract1.Address)
Expect(incErr).ToNot(HaveOccurred())
actualCountA1.Add(actualCountA1, big.NewInt(1))
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, contract1.Address, countAIndex, inc.BlockNumber)
Expect(err).ToNot(HaveOccurred())
countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage)
Expect(countA1AfterIncrement.String()).To(Equal(prevCountA1.String()))
// Contract 2, countA
_, incErr = integration.IncrementCount(contract2.Address, "A")
time.Sleep(sleepInterval)
inc, incErr = integration.IncrementCount("A", contract2.Address)
Expect(incErr).ToNot(HaveOccurred())
actualCountA2.Add(actualCountA2, big.NewInt(1))
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, contract2.Address, countAIndex, inc.BlockNumber)
Expect(err).ToNot(HaveOccurred())
countA2AfterIncrement := new(big.Int).SetBytes(countA2AfterIncrementStorage)
Expect(countA2AfterIncrement.String()).To(Equal(actualCountA2.String()))
prevCountA2.Set(actualCountA2)
// Contract 3, countA
_, incErr = integration.IncrementCount(contract3.Address, "A")
time.Sleep(sleepInterval)
inc, incErr = integration.IncrementCount("A", contract3.Address)
Expect(incErr).ToNot(HaveOccurred())
actualCountA3.Add(actualCountA3, big.NewInt(1))
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, contract3.Address, countAIndex, inc.BlockNumber)
Expect(err).ToNot(HaveOccurred())
countA3AfterIncrement := new(big.Int).SetBytes(countA3AfterIncrementStorage)
Expect(countA3AfterIncrement.String()).To(Equal(prevCountA3.String()))
@ -477,11 +441,11 @@ var _ = Describe("WatchAddress integration test", func() {
operation := sdtypes.Set
args := []sdtypes.WatchAddressArg{
{
Address: contract1.Address,
Address: contract1.Address.String(),
CreatedAt: uint64(contract1.BlockNumber),
},
{
Address: contract3.Address,
Address: contract3.Address.String(),
CreatedAt: uint64(contract3.BlockNumber),
},
}
@ -491,68 +455,62 @@ var _ = Describe("WatchAddress integration test", func() {
// WatchedAddresses = [Contract1, Contract3]
// Send eth to all three contract accounts
// Contract 1
_, txErr = integration.SendEth(contract1.Address, "0.01")
time.Sleep(sleepInterval)
tx, txErr = integration.SendEth(contract1.Address, "0.01")
Expect(txErr).ToNot(HaveOccurred())
actualBalance1.Add(actualBalance1, big.NewInt(10000000000000000))
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, contract1.Address, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(balance1AfterTransfer.String()).To(Equal(actualBalance1.String()))
prevBalance1.Set(actualBalance1)
// Contract 2
_, txErr = integration.SendEth(contract2.Address, "0.01")
time.Sleep(sleepInterval)
tx, txErr = integration.SendEth(contract2.Address, "0.01")
Expect(txErr).ToNot(HaveOccurred())
actualBalance2.Add(actualBalance2, big.NewInt(10000000000000000))
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, contract2.Address, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(balance2AfterTransfer.String()).To(Equal(prevBalance2.String()))
// Contract 3
_, txErr = integration.SendEth(contract3.Address, "0.01")
time.Sleep(sleepInterval)
tx, txErr = integration.SendEth(contract3.Address, "0.01")
Expect(txErr).ToNot(HaveOccurred())
actualBalance3.Add(actualBalance3, big.NewInt(10000000000000000))
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, contract3.Address, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(balance3AfterTransfer.String()).To(Equal(actualBalance3.String()))
prevBalance3.Set(actualBalance3)
// Increment counts
// Contract 1, countA
_, incErr = integration.IncrementCount(contract1.Address, "A")
time.Sleep(sleepInterval)
inc, incErr = integration.IncrementCount("A", contract1.Address)
Expect(incErr).ToNot(HaveOccurred())
actualCountA1.Add(actualCountA1, big.NewInt(1))
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, contract1.Address, countAIndex, inc.BlockNumber)
Expect(err).ToNot(HaveOccurred())
countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage)
Expect(countA1AfterIncrement.String()).To(Equal(actualCountA1.String()))
prevCountA1.Set(actualCountA1)
// Contract 2, countA
_, incErr = integration.IncrementCount(contract2.Address, "A")
time.Sleep(sleepInterval)
inc, incErr = integration.IncrementCount("A", contract2.Address)
Expect(incErr).ToNot(HaveOccurred())
actualCountA2.Add(actualCountA2, big.NewInt(1))
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, contract2.Address, countAIndex, inc.BlockNumber)
Expect(err).ToNot(HaveOccurred())
countA2AfterIncrement := new(big.Int).SetBytes(countA2AfterIncrementStorage)
Expect(countA2AfterIncrement.String()).To(Equal(prevCountA2.String()))
// Contract 3, countA
_, incErr = integration.IncrementCount(contract3.Address, "A")
time.Sleep(sleepInterval)
inc, incErr = integration.IncrementCount("A", contract3.Address)
Expect(incErr).ToNot(HaveOccurred())
actualCountA3.Add(actualCountA3, big.NewInt(1))
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, contract3.Address, countAIndex, inc.BlockNumber)
Expect(err).ToNot(HaveOccurred())
countA3AfterIncrement := new(big.Int).SetBytes(countA3AfterIncrementStorage)
Expect(countA3AfterIncrement.String()).To(Equal(actualCountA3.String()))
@ -570,70 +528,64 @@ var _ = Describe("WatchAddress integration test", func() {
// WatchedAddresses = []
// Send eth to all three contract accounts
// Contract 1
_, txErr = integration.SendEth(contract1.Address, "0.01")
time.Sleep(sleepInterval)
tx, txErr = integration.SendEth(contract1.Address, "0.01")
Expect(txErr).ToNot(HaveOccurred())
actualBalance1.Add(actualBalance1, big.NewInt(10000000000000000))
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, contract1.Address, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(balance1AfterTransfer.String()).To(Equal(actualBalance1.String()))
prevBalance1.Set(actualBalance1)
// Contract 2
_, txErr = integration.SendEth(contract2.Address, "0.01")
time.Sleep(sleepInterval)
tx, txErr = integration.SendEth(contract2.Address, "0.01")
Expect(txErr).ToNot(HaveOccurred())
actualBalance2.Add(actualBalance2, big.NewInt(10000000000000000))
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, contract2.Address, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(balance2AfterTransfer.String()).To(Equal(actualBalance2.String()))
prevBalance2.Set(actualBalance2)
// Contract 3
_, txErr = integration.SendEth(contract3.Address, "0.01")
time.Sleep(sleepInterval)
tx, txErr = integration.SendEth(contract3.Address, "0.01")
Expect(txErr).ToNot(HaveOccurred())
actualBalance3.Add(actualBalance3, big.NewInt(10000000000000000))
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, contract3.Address, big.NewInt(tx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(balance3AfterTransfer.String()).To(Equal(actualBalance3.String()))
prevBalance3.Set(actualBalance3)
// Increment counts
// Contract 1, countA
_, incErr = integration.IncrementCount(contract1.Address, "A")
time.Sleep(sleepInterval)
inc, incErr = integration.IncrementCount("A", contract1.Address)
Expect(incErr).ToNot(HaveOccurred())
actualCountA1.Add(actualCountA1, big.NewInt(1))
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, contract1.Address, countAIndex, inc.BlockNumber)
Expect(err).ToNot(HaveOccurred())
countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage)
Expect(countA1AfterIncrement.String()).To(Equal(actualCountA1.String()))
prevCountA1.Set(actualCountA1)
// Contract 2, countA
_, incErr = integration.IncrementCount(contract2.Address, "A")
time.Sleep(sleepInterval)
inc, incErr = integration.IncrementCount("A", contract2.Address)
Expect(incErr).ToNot(HaveOccurred())
actualCountA2.Add(actualCountA2, big.NewInt(1))
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, contract2.Address, countAIndex, inc.BlockNumber)
Expect(err).ToNot(HaveOccurred())
countA2AfterIncrement := new(big.Int).SetBytes(countA2AfterIncrementStorage)
Expect(countA2AfterIncrement.String()).To(Equal(actualCountA2.String()))
prevCountA2.Set(actualCountA2)
// Contract 3, countA
_, incErr = integration.IncrementCount(contract3.Address, "A")
time.Sleep(sleepInterval)
inc, incErr = integration.IncrementCount("A", contract3.Address)
Expect(incErr).ToNot(HaveOccurred())
actualCountA3.Add(actualCountA3, big.NewInt(1))
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, contract3.Address, countAIndex, inc.BlockNumber)
Expect(err).ToNot(HaveOccurred())
countA3AfterIncrement := new(big.Int).SetBytes(countA3AfterIncrementStorage)
Expect(countA3AfterIncrement.String()).To(Equal(actualCountA3.String()))
@ -648,9 +600,11 @@ var _ = Describe("WatchAddress integration test", func() {
gethErr := gethRPCClient.Call(nil, gethMethod, operation, args)
Expect(gethErr).To(HaveOccurred())
Expect(gethErr.Error()).To(ContainSubstring("unexpected operation"))
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
Expect(ipldErr).To(HaveOccurred())
Expect(ipldErr.Error()).To(ContainSubstring("unexpected operation"))
Expect(ipldErr).To(Equal(gethErr))
})
@ -661,9 +615,11 @@ var _ = Describe("WatchAddress integration test", func() {
gethErr := gethRPCClient.Call(nil, gethMethod, operation, args)
Expect(gethErr).To(HaveOccurred())
Expect(gethErr.Error()).To(ContainSubstring("WatchAddressArg"))
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
Expect(ipldErr).To(HaveOccurred())
Expect(ipldErr.Error()).To(ContainSubstring("WatchAddressArg"))
Expect(ipldErr).To(Equal(gethErr))
})

View File

@ -1,60 +0,0 @@
// VulcanizeDB
// Copyright © 2019 Vulcanize
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package test_config
import (
"errors"
"github.com/cerc-io/ipld-eth-server/v4/pkg/log"
"github.com/ethereum/go-ethereum/statediff/indexer/database/sql/postgres"
"github.com/spf13/viper"
)
var DBConfig postgres.Config
func init() {
setTestConfig()
}
func setTestConfig() {
vip := viper.New()
vip.SetConfigName("testing")
vip.AddConfigPath("$GOPATH/src/github.com/cerc-io/ipld-eth-server/environments/")
if err := vip.ReadInConfig(); err != nil {
log.Fatal(err)
}
ipc := vip.GetString("client.ipcPath")
// If we don't have an ipc path in the config file, check the env variable
if ipc == "" {
vip.BindEnv("url", "INFURA_URL")
ipc = vip.GetString("url")
}
if ipc == "" {
log.Fatal(errors.New("testing.toml IPC path or $INFURA_URL env variable need to be set"))
}
hn := vip.GetString("database.hostname")
port := vip.GetInt("database.port")
name := vip.GetString("database.name")
DBConfig = postgres.Config{
Hostname: hn,
DatabaseName: name,
Port: port,
}
}

View File

@ -19,9 +19,9 @@ package version
import "fmt"
const (
Major = 4 // Major version component of the current release
Minor = 2 // Minor version component of the current release
Patch = 0 // Patch version component of the current release
Major = 5 // Major version component of the current release
Minor = 0 // Minor version component of the current release
Patch = 1 // Patch version component of the current release
Meta = "alpha" // Version metadata to append to the version string
)