forked from cerc-io/ipld-eth-server
Compare commits
13
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ea4d1e40d | ||
|
|
ace12fbc35 | ||
|
|
8b8f644b2a | ||
|
|
8bfcce95ca | ||
|
|
0b12c3c329 | ||
|
|
037131528c | ||
|
|
04096fab0c | ||
|
|
dc14656bbc | ||
|
|
9676690a2d | ||
|
|
36e590c092 | ||
|
|
384d939dc2 | ||
|
|
24a45a3f00 | ||
|
|
867323a1ab |
@@ -60,13 +60,15 @@ jobs:
|
|||||||
integrationtest:
|
integrationtest:
|
||||||
name: Run integration tests
|
name: Run integration tests
|
||||||
env:
|
env:
|
||||||
STACK_ORCHESTRATOR_REF: fcbc74451c5494664fe21f765e89c9c6565c07cb
|
STACK_ORCHESTRATOR_REF: 35c677433aee5fafdf74eb3c251a453691b818d0
|
||||||
GO_ETHEREUM_REF: 498101102c891c4f8c3cab5649158c642ee1fd6b
|
GO_ETHEREUM_REF: ef8c9f2580dd577a7c5eca538fb0ed64d53dc4a4
|
||||||
GOPATH: /tmp/go
|
GOPATH: /tmp/go
|
||||||
DB_WRITE: true
|
DB_WRITE: true
|
||||||
ETH_FORWARD_ETH_CALLS: false
|
ETH_FORWARD_ETH_CALLS: false
|
||||||
ETH_PROXY_ON_ERROR: false
|
ETH_PROXY_ON_ERROR: false
|
||||||
ETH_HTTP_PATH: "go-ethereum:8545"
|
ETH_HTTP_PATH: "go-ethereum:8545"
|
||||||
|
WATCHED_ADDRESS_GAP_FILLER_ENABLED: false
|
||||||
|
WATCHED_ADDRESS_GAP_FILLER_INTERVAL: 2
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
go-version: [1.16.x]
|
go-version: [1.16.x]
|
||||||
@@ -96,6 +98,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
echo vulcanize_go_ethereum=$GITHUB_WORKSPACE/go-ethereum/ > ./config.sh
|
echo vulcanize_go_ethereum=$GITHUB_WORKSPACE/go-ethereum/ > ./config.sh
|
||||||
echo vulcanize_ipld_eth_server=$GITHUB_WORKSPACE/ipld-eth-server/ >> ./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 db_write=$DB_WRITE >> ./config.sh
|
echo db_write=$DB_WRITE >> ./config.sh
|
||||||
echo eth_forward_eth_calls=$ETH_FORWARD_ETH_CALLS >> ./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_proxy_on_error=$ETH_PROXY_ON_ERROR >> ./config.sh
|
||||||
@@ -113,6 +116,7 @@ jobs:
|
|||||||
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/latest/docker-compose-db.yml" \
|
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/latest/docker-compose-db.yml" \
|
||||||
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/local/docker-compose-go-ethereum.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-ipld-eth-server.yml" \
|
||||||
|
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/local/docker-compose-contract.yml" \
|
||||||
--env-file "$GITHUB_WORKSPACE/config.sh" \
|
--env-file "$GITHUB_WORKSPACE/config.sh" \
|
||||||
up -d --build
|
up -d --build
|
||||||
- name: Test
|
- name: Test
|
||||||
@@ -125,13 +129,15 @@ jobs:
|
|||||||
integrationtest_forwardethcalls:
|
integrationtest_forwardethcalls:
|
||||||
name: Run integration tests for direct proxy fall-through of eth_calls
|
name: Run integration tests for direct proxy fall-through of eth_calls
|
||||||
env:
|
env:
|
||||||
STACK_ORCHESTRATOR_REF: fcbc74451c5494664fe21f765e89c9c6565c07cb
|
STACK_ORCHESTRATOR_REF: 35c677433aee5fafdf74eb3c251a453691b818d0
|
||||||
GO_ETHEREUM_REF: 498101102c891c4f8c3cab5649158c642ee1fd6b
|
GO_ETHEREUM_REF: ef8c9f2580dd577a7c5eca538fb0ed64d53dc4a4
|
||||||
GOPATH: /tmp/go
|
GOPATH: /tmp/go
|
||||||
DB_WRITE: false
|
DB_WRITE: false
|
||||||
ETH_FORWARD_ETH_CALLS: true
|
ETH_FORWARD_ETH_CALLS: true
|
||||||
ETH_PROXY_ON_ERROR: false
|
ETH_PROXY_ON_ERROR: false
|
||||||
ETH_HTTP_PATH: "go-ethereum:8545"
|
ETH_HTTP_PATH: "go-ethereum:8545"
|
||||||
|
WATCHED_ADDRESS_GAP_FILLER_ENABLED: false
|
||||||
|
WATCHED_ADDRESS_GAP_FILLER_INTERVAL: 2
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
go-version: [1.16.x]
|
go-version: [1.16.x]
|
||||||
@@ -161,6 +167,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
echo vulcanize_go_ethereum=$GITHUB_WORKSPACE/go-ethereum/ > ./config.sh
|
echo vulcanize_go_ethereum=$GITHUB_WORKSPACE/go-ethereum/ > ./config.sh
|
||||||
echo vulcanize_ipld_eth_server=$GITHUB_WORKSPACE/ipld-eth-server/ >> ./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 db_write=$DB_WRITE >> ./config.sh
|
echo db_write=$DB_WRITE >> ./config.sh
|
||||||
echo eth_forward_eth_calls=$ETH_FORWARD_ETH_CALLS >> ./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_proxy_on_error=$ETH_PROXY_ON_ERROR >> ./config.sh
|
||||||
@@ -178,6 +185,78 @@ jobs:
|
|||||||
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/latest/docker-compose-db.yml" \
|
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/latest/docker-compose-db.yml" \
|
||||||
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/local/docker-compose-go-ethereum.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-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
|
||||||
|
|
||||||
|
integrationtest_watchedaddress_gapfillingservice:
|
||||||
|
name: Run integration tests for watched addresses with gap filling service enabled
|
||||||
|
env:
|
||||||
|
STACK_ORCHESTRATOR_REF: 35c677433aee5fafdf74eb3c251a453691b818d0
|
||||||
|
GO_ETHEREUM_REF: ef8c9f2580dd577a7c5eca538fb0ed64d53dc4a4
|
||||||
|
GOPATH: /tmp/go
|
||||||
|
DB_WRITE: true
|
||||||
|
ETH_FORWARD_ETH_CALLS: false
|
||||||
|
ETH_PROXY_ON_ERROR: false
|
||||||
|
ETH_HTTP_PATH: "go-ethereum:8545"
|
||||||
|
WATCHED_ADDRESS_GAP_FILLER_ENABLED: true
|
||||||
|
WATCHED_ADDRESS_GAP_FILLER_INTERVAL: 2
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
go-version: [1.16.x]
|
||||||
|
os: [ubuntu-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- name: Create GOPATH
|
||||||
|
run: mkdir -p /tmp/go
|
||||||
|
- name: Install Go
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: ${{ matrix.go-version }}
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
path: "./ipld-eth-server"
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
ref: ${{ env.STACK_ORCHESTRATOR_REF }}
|
||||||
|
path: "./stack-orchestrator/"
|
||||||
|
repository: vulcanize/stack-orchestrator
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
ref: ${{ env.GO_ETHEREUM_REF }}
|
||||||
|
repository: vulcanize/go-ethereum
|
||||||
|
path: "./go-ethereum/"
|
||||||
|
- name: Create config file
|
||||||
|
run: |
|
||||||
|
echo vulcanize_go_ethereum=$GITHUB_WORKSPACE/go-ethereum/ > ./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 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
|
||||||
|
echo watched_addres_gap_filler_enabled=$WATCHED_ADDRESS_GAP_FILLER_ENABLED >> ./config.sh
|
||||||
|
echo watched_addres_gap_filler_interval=$WATCHED_ADDRESS_GAP_FILLER_INTERVAL >> ./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/latest/docker-compose-db.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" \
|
--env-file "$GITHUB_WORKSPACE/config.sh" \
|
||||||
up -d --build
|
up -d --build
|
||||||
- name: Test
|
- name: Test
|
||||||
|
|||||||
@@ -8,22 +8,30 @@ temp_dir=$(mktemp -d)
|
|||||||
cd $temp_dir
|
cd $temp_dir
|
||||||
git clone -b $(cat /tmp/git_head_ref) "https://github.com/$(cat /tmp/git_repository).git"
|
git clone -b $(cat /tmp/git_head_ref) "https://github.com/$(cat /tmp/git_repository).git"
|
||||||
cd ipld-eth-server
|
cd ipld-eth-server
|
||||||
|
mkdir -p out
|
||||||
|
|
||||||
## Remove the branch and github related info. This way future runs wont be confused.
|
## Remove the branch and github related info. This way future runs wont be confused.
|
||||||
rm -f /tmp/git_head_ref /tmp/git_repository
|
rm -f /tmp/git_head_ref /tmp/git_repository
|
||||||
|
|
||||||
# Spin up DB
|
# Remove existing docker-tsdb directory
|
||||||
docker-compose up -d ipld-eth-db
|
rm -rf out/docker-tsdb/
|
||||||
trap "docker-compose down --remove-orphans; cd $start_dir ; rm -r $temp_dir" SIGINT SIGTERM ERR
|
|
||||||
sleep 10
|
# Copy over files to setup TimescaleDB
|
||||||
|
ID=$(docker create vulcanize/ipld-eth-db:v4.1.1-alpha)
|
||||||
|
docker cp $ID:/app/docker-tsdb out/docker-tsdb/
|
||||||
|
docker rm -v $ID
|
||||||
|
|
||||||
|
# Spin up TimescaleDB
|
||||||
|
docker-compose -f out/docker-tsdb/docker-compose.test.yml -f docker-compose.yml up ipld-eth-db
|
||||||
|
trap "docker-compose -f out/docker-tsdb/docker-compose.test.yml -f docker-compose.yml down --remove-orphans --volumes; cd $start_dir ; rm -r $temp_dir" SIGINT SIGTERM ERR
|
||||||
|
sleep 45
|
||||||
|
|
||||||
# Remove old logs so there's no confusion, then run test
|
# Remove old logs so there's no confusion, then run test
|
||||||
rm -f /tmp/test.log /tmp/return_test.txt
|
rm -f /tmp/test.log /tmp/return_test.txt
|
||||||
PGPASSWORD=password DATABASE_USER=vdbm DATABASE_PORT=8077 DATABASE_PASSWORD=password DATABASE_HOSTNAME=127.0.0.1 DATABASE_NAME=vulcanize_testing make test > /tmp/test.log
|
PGPASSWORD=password DATABASE_USER=vdbm DATABASE_PORT=8066 DATABASE_PASSWORD=password DATABASE_HOSTNAME=127.0.0.1 DATABASE_NAME=vulcanize_testing_v4 make test > /tmp/test.log
|
||||||
echo $? > /tmp/return_test.txt
|
echo $? > /tmp/return_test.txt
|
||||||
|
|
||||||
# Clean up
|
# Clean up
|
||||||
docker-compose down -v --remove-orphans
|
docker-compose -f out/docker-tsdb/docker-compose.test.yml -f docker-compose.yml down --remove-orphans --volumes
|
||||||
cd $start_dir
|
cd $start_dir
|
||||||
rm -fr $temp_dir
|
rm -fr $temp_dir
|
||||||
|
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ External dependency
|
|||||||
## Install
|
## Install
|
||||||
Start by downloading ipld-eth-server and moving into the repo:
|
Start by downloading ipld-eth-server and moving into the repo:
|
||||||
|
|
||||||
`GO111MODULE=off go get -d github.com/vulcanize/ipld-eth-server/v3`
|
`GO111MODULE=off go get -d github.com/vulcanize/ipld-eth-server/v4`
|
||||||
|
|
||||||
`cd $GOPATH/src/github.com/vulcanize/ipld-eth-server/v3@v3.x.x`
|
`cd $GOPATH/src/github.com/vulcanize/ipld-eth-server/v4@v4.x.x`
|
||||||
|
|
||||||
Then, build the binary:
|
Then, build the binary:
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/prom"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/prom"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
+27
-5
@@ -32,11 +32,12 @@ import (
|
|||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"github.com/vulcanize/gap-filler/pkg/mux"
|
"github.com/vulcanize/gap-filler/pkg/mux"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/graphql"
|
fill "github.com/vulcanize/ipld-eth-server/v4/pkg/fill"
|
||||||
srpc "github.com/vulcanize/ipld-eth-server/v3/pkg/rpc"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/graphql"
|
||||||
s "github.com/vulcanize/ipld-eth-server/v3/pkg/serve"
|
srpc "github.com/vulcanize/ipld-eth-server/v4/pkg/rpc"
|
||||||
v "github.com/vulcanize/ipld-eth-server/v3/version"
|
s "github.com/vulcanize/ipld-eth-server/v4/pkg/serve"
|
||||||
|
v "github.com/vulcanize/ipld-eth-server/v4/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNoRpcEndpoints = errors.New("no rpc endpoints is available")
|
var ErrNoRpcEndpoints = errors.New("no rpc endpoints is available")
|
||||||
@@ -100,12 +101,25 @@ func serve() {
|
|||||||
logWithCommand.Info("state validator disabled")
|
logWithCommand.Info("state validator disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var watchedAddressFillService *fill.Service
|
||||||
|
if serverConfig.WatchedAddressGapFillerEnabled {
|
||||||
|
watchedAddressFillService = fill.New(serverConfig)
|
||||||
|
wg.Add(1)
|
||||||
|
go watchedAddressFillService.Start(wg)
|
||||||
|
logWithCommand.Info("watched address gap filler enabled")
|
||||||
|
} else {
|
||||||
|
logWithCommand.Info("watched address gap filler disabled")
|
||||||
|
}
|
||||||
|
|
||||||
shutdown := make(chan os.Signal, 1)
|
shutdown := make(chan os.Signal, 1)
|
||||||
signal.Notify(shutdown, os.Interrupt)
|
signal.Notify(shutdown, os.Interrupt)
|
||||||
<-shutdown
|
<-shutdown
|
||||||
if graphQL != nil {
|
if graphQL != nil {
|
||||||
graphQL.Stop()
|
graphQL.Stop()
|
||||||
}
|
}
|
||||||
|
if watchedAddressFillService != nil {
|
||||||
|
watchedAddressFillService.Stop()
|
||||||
|
}
|
||||||
server.Stop()
|
server.Stop()
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
@@ -360,6 +374,10 @@ func init() {
|
|||||||
serveCmd.PersistentFlags().Bool("validator-enabled", false, "turn on the state validator")
|
serveCmd.PersistentFlags().Bool("validator-enabled", false, "turn on the state validator")
|
||||||
serveCmd.PersistentFlags().Uint("validator-every-nth-block", 1500, "only validate every Nth block")
|
serveCmd.PersistentFlags().Uint("validator-every-nth-block", 1500, "only validate every Nth block")
|
||||||
|
|
||||||
|
// watched address gap filler flags
|
||||||
|
serveCmd.PersistentFlags().Bool("watched-address-gap-filler-enabled", false, "turn on the watched address gap filler")
|
||||||
|
serveCmd.PersistentFlags().Int("watched-address-gap-filler-interval", 60, "watched address gap fill interval in secs")
|
||||||
|
|
||||||
// and their bindings
|
// and their bindings
|
||||||
// eth graphql server
|
// eth graphql server
|
||||||
viper.BindPFlag("eth.server.graphql", serveCmd.PersistentFlags().Lookup("eth-server-graphql"))
|
viper.BindPFlag("eth.server.graphql", serveCmd.PersistentFlags().Lookup("eth-server-graphql"))
|
||||||
@@ -408,4 +426,8 @@ func init() {
|
|||||||
// state validator flags
|
// state validator flags
|
||||||
viper.BindPFlag("validator.enabled", serveCmd.PersistentFlags().Lookup("validator-enabled"))
|
viper.BindPFlag("validator.enabled", serveCmd.PersistentFlags().Lookup("validator-enabled"))
|
||||||
viper.BindPFlag("validator.everyNthBlock", serveCmd.PersistentFlags().Lookup("validator-every-nth-block"))
|
viper.BindPFlag("validator.everyNthBlock", serveCmd.PersistentFlags().Lookup("validator-every-nth-block"))
|
||||||
|
|
||||||
|
// watched address gap filler flags
|
||||||
|
viper.BindPFlag("watch.fill.enabled", serveCmd.PersistentFlags().Lookup("watched-address-gap-filler-enabled"))
|
||||||
|
viper.BindPFlag("watch.fill.interval", serveCmd.PersistentFlags().Lookup("watched-address-gap-filler-interval"))
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -27,9 +27,9 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/client"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/client"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth"
|
||||||
w "github.com/vulcanize/ipld-eth-server/v3/pkg/serve"
|
w "github.com/vulcanize/ipld-eth-server/v4/pkg/serve"
|
||||||
)
|
)
|
||||||
|
|
||||||
// subscribeCmd represents the subscribe command
|
// subscribeCmd represents the subscribe command
|
||||||
|
|||||||
+3
-3
@@ -22,10 +22,10 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
validator "github.com/vulcanize/eth-ipfs-state-validator/v3/pkg"
|
validator "github.com/vulcanize/eth-ipfs-state-validator/v4/pkg"
|
||||||
ipfsethdb "github.com/vulcanize/ipfs-ethdb/v3/postgres"
|
ipfsethdb "github.com/vulcanize/ipfs-ethdb/v4/postgres"
|
||||||
|
|
||||||
s "github.com/vulcanize/ipld-eth-server/v3/pkg/serve"
|
s "github.com/vulcanize/ipld-eth-server/v4/pkg/serve"
|
||||||
)
|
)
|
||||||
|
|
||||||
const GroupName = "statedb-validate"
|
const GroupName = "statedb-validate"
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
v "github.com/vulcanize/ipld-eth-server/v3/version"
|
v "github.com/vulcanize/ipld-eth-server/v4/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
// versionCmd represents the version command
|
// versionCmd represents the version command
|
||||||
|
|||||||
+11
-10
@@ -2,17 +2,16 @@ version: '3.2'
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
ipld-eth-db:
|
ipld-eth-db:
|
||||||
restart: always
|
restart: on-failure
|
||||||
image: vulcanize/ipld-eth-db:v3.2.0
|
depends_on:
|
||||||
|
- access-node
|
||||||
|
image: vulcanize/ipld-eth-db:v4.1.1-alpha
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_USER: "vdbm"
|
DATABASE_USER: "vdbm"
|
||||||
POSTGRES_DB: "vulcanize_testing"
|
DATABASE_NAME: "vulcanize_testing_v4"
|
||||||
POSTGRES_PASSWORD: "password"
|
DATABASE_PASSWORD: "password"
|
||||||
volumes:
|
DATABASE_HOSTNAME: "access-node"
|
||||||
- vdb_db_eth_server:/var/lib/postgresql/data
|
DATABASE_PORT: 5432
|
||||||
ports:
|
|
||||||
- "127.0.0.1:8077:5432"
|
|
||||||
command: ["postgres", "-c", "log_statement=all"]
|
|
||||||
|
|
||||||
eth-server:
|
eth-server:
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -38,6 +37,8 @@ services:
|
|||||||
ETH_FORWARD_ETH_CALLS: $ETH_FORWARD_ETH_CALLS
|
ETH_FORWARD_ETH_CALLS: $ETH_FORWARD_ETH_CALLS
|
||||||
ETH_PROXY_ON_ERROR: $ETH_PROXY_ON_ERROR
|
ETH_PROXY_ON_ERROR: $ETH_PROXY_ON_ERROR
|
||||||
ETH_HTTP_PATH: $ETH_HTTP_PATH
|
ETH_HTTP_PATH: $ETH_HTTP_PATH
|
||||||
|
WATCHED_ADDRESS_GAP_FILLER_ENABLED: $WATCHED_ADDRESS_GAP_FILLER_ENABLED
|
||||||
|
WATCHED_ADDRESS_GAP_FILLER_INTERVAL: $WATCHED_ADDRESS_GAP_FILLER_INTERVAL
|
||||||
volumes:
|
volumes:
|
||||||
- type: bind
|
- type: bind
|
||||||
source: ./chain.json
|
source: ./chain.json
|
||||||
|
|||||||
@@ -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/ethereum/go-ethereum/rpc"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/client"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/client"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/watch"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/watch"
|
||||||
)
|
)
|
||||||
|
|
||||||
config, _ := eth.NewEthSubscriptionConfig()
|
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/ethereum/go-ethereum/rpc"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/btc"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/btc"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/client"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/client"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/watch"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/watch"
|
||||||
)
|
)
|
||||||
|
|
||||||
config, _ := btc.NewBtcSubscriptionConfig()
|
config, _ := btc.NewBtcSubscriptionConfig()
|
||||||
|
|||||||
@@ -28,3 +28,8 @@
|
|||||||
clientName = "Geth" # $ETH_CLIENT_NAME
|
clientName = "Geth" # $ETH_CLIENT_NAME
|
||||||
genesisBlock = "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" # $ETH_GENESIS_BLOCK
|
genesisBlock = "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" # $ETH_GENESIS_BLOCK
|
||||||
networkID = "1" # $ETH_NETWORK_ID
|
networkID = "1" # $ETH_NETWORK_ID
|
||||||
|
|
||||||
|
[watch]
|
||||||
|
[watch.fill]
|
||||||
|
enabled = false
|
||||||
|
interval = 30
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
module github.com/vulcanize/ipld-eth-server/v3
|
module github.com/vulcanize/ipld-eth-server/v4
|
||||||
|
|
||||||
go 1.15
|
go 1.15
|
||||||
|
|
||||||
@@ -9,7 +9,6 @@ require (
|
|||||||
github.com/ipfs/go-cid v0.0.7
|
github.com/ipfs/go-cid v0.0.7
|
||||||
github.com/ipfs/go-ipfs-blockstore v1.0.1
|
github.com/ipfs/go-ipfs-blockstore v1.0.1
|
||||||
github.com/ipfs/go-ipfs-ds-help v1.0.0
|
github.com/ipfs/go-ipfs-ds-help v1.0.0
|
||||||
github.com/ipfs/go-ipld-format v0.2.0
|
|
||||||
github.com/jmoiron/sqlx v1.3.5
|
github.com/jmoiron/sqlx v1.3.5
|
||||||
github.com/joho/godotenv v1.4.0
|
github.com/joho/godotenv v1.4.0
|
||||||
github.com/lib/pq v1.10.5
|
github.com/lib/pq v1.10.5
|
||||||
@@ -23,9 +22,9 @@ require (
|
|||||||
github.com/sirupsen/logrus v1.8.1
|
github.com/sirupsen/logrus v1.8.1
|
||||||
github.com/spf13/cobra v1.4.0
|
github.com/spf13/cobra v1.4.0
|
||||||
github.com/spf13/viper v1.11.0
|
github.com/spf13/viper v1.11.0
|
||||||
github.com/vulcanize/eth-ipfs-state-validator/v3 v3.0.0
|
github.com/vulcanize/eth-ipfs-state-validator/v4 v4.0.0-alpha
|
||||||
github.com/vulcanize/gap-filler v0.3.1
|
github.com/vulcanize/gap-filler v0.3.1
|
||||||
github.com/vulcanize/ipfs-ethdb/v3 v3.0.1
|
github.com/vulcanize/ipfs-ethdb/v4 v4.0.0-alpha
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/ethereum/go-ethereum v1.10.17 => github.com/vulcanize/go-ethereum v1.10.17-statediff-3.2.1
|
replace github.com/ethereum/go-ethereum v1.10.17 => github.com/vulcanize/go-ethereum v1.10.17-statediff-4.0.1-alpha
|
||||||
|
|||||||
@@ -1834,14 +1834,14 @@ github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPU
|
|||||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
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/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
||||||
github.com/vulcanize/eth-ipfs-state-validator/v3 v3.0.0 h1:hQcbewsJX5Xpd3xdE9n3JpGyuzUqMhwhpQCpbN+9Uiw=
|
github.com/vulcanize/eth-ipfs-state-validator/v4 v4.0.0-alpha h1:9TtxGBNl/hVQ8wegrZx//UnAMivImbcNcYTQxHfhjlQ=
|
||||||
github.com/vulcanize/eth-ipfs-state-validator/v3 v3.0.0/go.mod h1:CuuygZPciwwLV5vNY1LcIi0PZxXZbOmicw1/IkrPpPI=
|
github.com/vulcanize/eth-ipfs-state-validator/v4 v4.0.0-alpha/go.mod h1:cY+XmYdOtBc84s02GdDTFoybJF+mR7WDcr3Z7l4Fb1g=
|
||||||
github.com/vulcanize/gap-filler v0.3.1 h1:N5d+jCJo/VTWFvBSbTD7biRhK/OqDZzi1tgA85SIBKs=
|
github.com/vulcanize/gap-filler v0.3.1 h1:N5d+jCJo/VTWFvBSbTD7biRhK/OqDZzi1tgA85SIBKs=
|
||||||
github.com/vulcanize/gap-filler v0.3.1/go.mod h1:qowG1cgshVpBqMokiWro/1xhh0uypw7oAu8FQ42JMy4=
|
github.com/vulcanize/gap-filler v0.3.1/go.mod h1:qowG1cgshVpBqMokiWro/1xhh0uypw7oAu8FQ42JMy4=
|
||||||
github.com/vulcanize/go-ethereum v1.10.17-statediff-3.2.1 h1:BUIaiqqsWM61KfzIowqrGJ8TM2SWwmral4iJ/nhTSe0=
|
github.com/vulcanize/go-ethereum v1.10.17-statediff-4.0.1-alpha h1:ANyTG2JJkOaQD3IqkLLl2OjtTC+PKlrdmy6HIddpqZw=
|
||||||
github.com/vulcanize/go-ethereum v1.10.17-statediff-3.2.1/go.mod h1:mDwZX+QoWdqzQo6SDG3YVqCYACutcSG6uzpziMvTu28=
|
github.com/vulcanize/go-ethereum v1.10.17-statediff-4.0.1-alpha/go.mod h1:mDwZX+QoWdqzQo6SDG3YVqCYACutcSG6uzpziMvTu28=
|
||||||
github.com/vulcanize/ipfs-ethdb/v3 v3.0.1 h1:gm+6SgxcNOCz6mgwvhsxORLXsr9yIFvbJDuoAK85ONs=
|
github.com/vulcanize/ipfs-ethdb/v4 v4.0.0-alpha h1:XaltpDMGFqcEe+tsYTmqICeFhR+jTHHzc85YTVigEdE=
|
||||||
github.com/vulcanize/ipfs-ethdb/v3 v3.0.1/go.mod h1:SPBTTl5CqRexYfkI66pbzE5nQziYpoQ+7hH0XveA9IU=
|
github.com/vulcanize/ipfs-ethdb/v4 v4.0.0-alpha/go.mod h1:sSTqwalaV7CiXq83YkMJpZetoSxgcdzr0AG0NnuaGMM=
|
||||||
github.com/wangjia184/sortedset v0.0.0-20160527075905-f5d03557ba30/go.mod h1:YkocrP2K2tcw938x9gCOmT5G5eCD6jsTz0SZuyAqwIE=
|
github.com/wangjia184/sortedset v0.0.0-20160527075905-f5d03557ba30/go.mod h1:YkocrP2K2tcw938x9gCOmT5G5eCD6jsTz0SZuyAqwIE=
|
||||||
github.com/warpfork/go-testmark v0.3.0 h1:Q81c4u7hT+BR5kNfNQhEF0VT2pmL7+Kk0wD+ORYl7iA=
|
github.com/warpfork/go-testmark v0.3.0 h1:Q81c4u7hT+BR5kNfNQhEF0VT2pmL7+Kk0wD+ORYl7iA=
|
||||||
github.com/warpfork/go-testmark v0.3.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0=
|
github.com/warpfork/go-testmark v0.3.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0=
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/cmd"
|
"github.com/vulcanize/ipld-eth-server/v4/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ import (
|
|||||||
|
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/serve"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/serve"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client is used to subscribe to the ipld-eth-server ipld data stream
|
// Client is used to subscribe to the ipld-eth-server ipld data stream
|
||||||
|
|||||||
+1
-1
@@ -42,7 +42,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/statediff"
|
"github.com/ethereum/go-ethereum/statediff"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/shared"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
// APIName is the namespace for the watcher's eth api
|
// APIName is the namespace for the watcher's eth api
|
||||||
|
|||||||
+4
-4
@@ -36,10 +36,10 @@ import (
|
|||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth/test_helpers"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth/test_helpers"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/shared"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/shared"
|
||||||
ethServerShared "github.com/vulcanize/ipld-eth-server/v3/pkg/shared"
|
ethServerShared "github.com/vulcanize/ipld-eth-server/v4/pkg/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
+22
-11
@@ -43,12 +43,12 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
validator "github.com/vulcanize/eth-ipfs-state-validator/v3/pkg"
|
validator "github.com/vulcanize/eth-ipfs-state-validator/v4/pkg"
|
||||||
ipfsethdb "github.com/vulcanize/ipfs-ethdb/v3/postgres"
|
ipfsethdb "github.com/vulcanize/ipfs-ethdb/v4/postgres"
|
||||||
|
|
||||||
ethServerShared "github.com/ethereum/go-ethereum/statediff/indexer/shared"
|
ethServerShared "github.com/ethereum/go-ethereum/statediff/indexer/shared"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/shared"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -59,31 +59,42 @@ var (
|
|||||||
|
|
||||||
// errMissingSignature is returned if a block's extra-data section doesn't seem
|
// errMissingSignature is returned if a block's extra-data section doesn't seem
|
||||||
// to contain a 65 byte secp256k1 signature.
|
// to contain a 65 byte secp256k1 signature.
|
||||||
errMissingSignature = errors.New("extra-data 65 byte signature suffix missing")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RetrieveCanonicalBlockHashByNumber = `SELECT block_hash FROM eth.header_cids
|
RetrieveCanonicalBlockHashByNumber = `SELECT block_hash FROM eth.header_cids
|
||||||
INNER JOIN public.blocks ON (header_cids.mh_key = blocks.key)
|
INNER JOIN public.blocks ON (
|
||||||
|
header_cids.mh_key = blocks.key
|
||||||
|
AND header_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
WHERE block_hash = (SELECT canonical_header_hash($1))`
|
WHERE block_hash = (SELECT canonical_header_hash($1))`
|
||||||
RetrieveCanonicalHeaderByNumber = `SELECT cid, data FROM eth.header_cids
|
RetrieveCanonicalHeaderByNumber = `SELECT cid, data FROM eth.header_cids
|
||||||
INNER JOIN public.blocks ON (header_cids.mh_key = blocks.key)
|
INNER JOIN public.blocks ON (
|
||||||
|
header_cids.mh_key = blocks.key
|
||||||
|
AND header_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
WHERE block_hash = (SELECT canonical_header_hash($1))`
|
WHERE block_hash = (SELECT canonical_header_hash($1))`
|
||||||
RetrieveTD = `SELECT CAST(td as Text) FROM eth.header_cids
|
RetrieveTD = `SELECT CAST(td as Text) FROM eth.header_cids
|
||||||
WHERE header_cids.block_hash = $1`
|
WHERE header_cids.block_hash = $1`
|
||||||
RetrieveRPCTransaction = `SELECT blocks.data, block_hash, block_number, index FROM public.blocks, eth.transaction_cids, eth.header_cids
|
RetrieveRPCTransaction = `SELECT blocks.data, block_hash, transaction_cids.block_number, index
|
||||||
|
FROM public.blocks, eth.transaction_cids, eth.header_cids
|
||||||
WHERE blocks.key = transaction_cids.mh_key
|
WHERE blocks.key = transaction_cids.mh_key
|
||||||
|
AND blocks.block_number = transaction_cids.block_number
|
||||||
AND transaction_cids.header_id = header_cids.block_hash
|
AND transaction_cids.header_id = header_cids.block_hash
|
||||||
|
AND transaction_cids.block_number = header_cids.block_number
|
||||||
AND transaction_cids.tx_hash = $1`
|
AND transaction_cids.tx_hash = $1`
|
||||||
RetrieveCodeHashByLeafKeyAndBlockHash = `SELECT code_hash FROM eth.state_accounts, eth.state_cids, eth.header_cids
|
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
|
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
|
AND state_cids.header_id = header_cids.block_hash
|
||||||
|
AND state_cids.block_number = header_cids.block_number
|
||||||
AND state_leaf_key = $1
|
AND state_leaf_key = $1
|
||||||
AND block_number <= (SELECT block_number
|
AND header_cids.block_number <= (SELECT block_number
|
||||||
FROM eth.header_cids
|
FROM eth.header_cids
|
||||||
WHERE block_hash = $2)
|
WHERE block_hash = $2)
|
||||||
AND header_cids.block_hash = (SELECT canonical_header_hash(block_number))
|
AND header_cids.block_hash = (SELECT canonical_header_hash(header_cids.block_number))
|
||||||
ORDER BY block_number DESC
|
ORDER BY header_cids.block_number DESC
|
||||||
LIMIT 1`
|
LIMIT 1`
|
||||||
RetrieveCodeByMhKey = `SELECT data FROM public.blocks WHERE key = $1`
|
RetrieveCodeByMhKey = `SELECT data FROM public.blocks WHERE key = $1`
|
||||||
)
|
)
|
||||||
|
|||||||
+68
-33
@@ -19,6 +19,7 @@ package eth
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
@@ -27,7 +28,7 @@ import (
|
|||||||
"github.com/lib/pq"
|
"github.com/lib/pq"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/shared"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Retriever interface for substituting mocks in tests
|
// Retriever interface for substituting mocks in tests
|
||||||
@@ -59,7 +60,7 @@ func (ecr *CIDRetriever) RetrieveFirstBlockNumber() (int64, error) {
|
|||||||
// RetrieveLastBlockNumber is used to retrieve the latest block number in the db
|
// RetrieveLastBlockNumber is used to retrieve the latest block number in the db
|
||||||
func (ecr *CIDRetriever) RetrieveLastBlockNumber() (int64, error) {
|
func (ecr *CIDRetriever) RetrieveLastBlockNumber() (int64, error) {
|
||||||
var blockNumber int64
|
var blockNumber int64
|
||||||
err := ecr.db.Get(&blockNumber, "SELECT block_number FROM eth.header_cids ORDER BY block_number DESC LIMIT 1 ")
|
err := ecr.db.Get(&blockNumber, "SELECT block_number FROM eth.header_cids ORDER BY block_number DESC LIMIT 1")
|
||||||
return blockNumber, err
|
return blockNumber, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,9 +168,9 @@ func (ecr *CIDRetriever) Retrieve(filter SubscriptionSettings, blockNumber int64
|
|||||||
func (ecr *CIDRetriever) RetrieveHeaderCIDs(tx *sqlx.Tx, blockNumber int64) ([]models.HeaderModel, error) {
|
func (ecr *CIDRetriever) RetrieveHeaderCIDs(tx *sqlx.Tx, blockNumber int64) ([]models.HeaderModel, error) {
|
||||||
log.Debug("retrieving header cids for block ", blockNumber)
|
log.Debug("retrieving header cids for block ", blockNumber)
|
||||||
headers := make([]models.HeaderModel, 0)
|
headers := make([]models.HeaderModel, 0)
|
||||||
pgStr := `SELECT CAST(block_number as Text), block_hash,parent_hash,cid,mh_key,CAST(td as Text),node_id,
|
pgStr := `SELECT CAST(block_number as Text), block_hash, parent_hash, cid, mh_key, CAST(td as Text), node_id,
|
||||||
CAST(reward as Text), state_root,uncle_root,tx_root,receipt_root,bloom,timestamp,times_validated,
|
CAST(reward as Text), state_root, uncle_root,tx_root, receipt_root,bloom, timestamp, times_validated, coinbase
|
||||||
coinbase FROM eth.header_cids
|
FROM eth.header_cids
|
||||||
WHERE block_number = $1`
|
WHERE block_number = $1`
|
||||||
return headers, tx.Select(&headers, pgStr, blockNumber)
|
return headers, tx.Select(&headers, pgStr, blockNumber)
|
||||||
}
|
}
|
||||||
@@ -178,7 +179,8 @@ func (ecr *CIDRetriever) RetrieveHeaderCIDs(tx *sqlx.Tx, blockNumber int64) ([]m
|
|||||||
func (ecr *CIDRetriever) RetrieveUncleCIDsByHeaderID(tx *sqlx.Tx, headerID string) ([]models.UncleModel, error) {
|
func (ecr *CIDRetriever) RetrieveUncleCIDsByHeaderID(tx *sqlx.Tx, headerID string) ([]models.UncleModel, error) {
|
||||||
log.Debug("retrieving uncle cids for block id ", headerID)
|
log.Debug("retrieving uncle cids for block id ", headerID)
|
||||||
headers := make([]models.UncleModel, 0)
|
headers := make([]models.UncleModel, 0)
|
||||||
pgStr := `SELECT header_id,block_hash,parent_hash,cid,mh_key, CAST(reward as text) FROM eth.uncle_cids
|
pgStr := `SELECT CAST(block_number as Text), header_id, block_hash, parent_hash, cid, mh_key, CAST(reward as text)
|
||||||
|
FROM eth.uncle_cids
|
||||||
WHERE header_id = $1`
|
WHERE header_id = $1`
|
||||||
return headers, tx.Select(&headers, pgStr, headerID)
|
return headers, tx.Select(&headers, pgStr, headerID)
|
||||||
}
|
}
|
||||||
@@ -190,10 +192,15 @@ func (ecr *CIDRetriever) RetrieveTxCIDs(tx *sqlx.Tx, txFilter TxFilter, headerID
|
|||||||
args := make([]interface{}, 0, 3)
|
args := make([]interface{}, 0, 3)
|
||||||
results := make([]models.TxModel, 0)
|
results := make([]models.TxModel, 0)
|
||||||
id := 1
|
id := 1
|
||||||
pgStr := fmt.Sprintf(`SELECT transaction_cids.tx_hash, transaction_cids.header_id,transaction_cids.cid, transaction_cids.mh_key,
|
pgStr := fmt.Sprintf(`SELECT CAST(transaction_cids.block_number as Text), transaction_cids.tx_hash,
|
||||||
transaction_cids.dst, transaction_cids.src, transaction_cids.index, transaction_cids.tx_data
|
transaction_cids.header_id,transaction_cids.cid, transaction_cids.mh_key, transaction_cids.dst,
|
||||||
FROM eth.transaction_cids INNER JOIN eth.header_cids ON (transaction_cids.header_id = header_cids.block_hash)
|
transaction_cids.src, transaction_cids.index, transaction_cids.tx_data
|
||||||
WHERE header_cids.block_hash = $%d`, id)
|
FROM eth.transaction_cids
|
||||||
|
INNER JOIN eth.header_cids ON (
|
||||||
|
transaction_cids.header_id = header_cids.block_hash
|
||||||
|
AND transaction_cids.block_number = header_cids.block_number
|
||||||
|
)
|
||||||
|
WHERE header_cids.block_hash = $%d`, id)
|
||||||
args = append(args, headerID)
|
args = append(args, headerID)
|
||||||
id++
|
id++
|
||||||
if len(txFilter.Dst) > 0 {
|
if len(txFilter.Dst) > 0 {
|
||||||
@@ -292,11 +299,13 @@ func receiptFilterConditions(id *int, pgStr string, args []interface{}, rctFilte
|
|||||||
func (ecr *CIDRetriever) RetrieveRctCIDsByHeaderID(tx *sqlx.Tx, rctFilter ReceiptFilter, headerID string, trxHashes []string) ([]models.ReceiptModel, error) {
|
func (ecr *CIDRetriever) RetrieveRctCIDsByHeaderID(tx *sqlx.Tx, rctFilter ReceiptFilter, headerID string, trxHashes []string) ([]models.ReceiptModel, error) {
|
||||||
log.Debug("retrieving receipt cids for header id ", headerID)
|
log.Debug("retrieving receipt cids for header id ", headerID)
|
||||||
args := make([]interface{}, 0, 4)
|
args := make([]interface{}, 0, 4)
|
||||||
pgStr := `SELECT receipt_cids.tx_id, receipt_cids.leaf_cid, receipt_cids.leaf_mh_key,
|
pgStr := `SELECT CAST(receipt_cids.block_number as Text), receipt_cids.tx_id, receipt_cids.leaf_cid,
|
||||||
receipt_cids.contract, receipt_cids.contract_hash
|
receipt_cids.leaf_mh_key, receipt_cids.contract, receipt_cids.contract_hash
|
||||||
FROM eth.receipt_cids, eth.transaction_cids, eth.header_cids
|
FROM eth.receipt_cids, eth.transaction_cids, eth.header_cids
|
||||||
WHERE receipt_cids.tx_id = transaction_cids.tx_hash
|
WHERE receipt_cids.tx_id = transaction_cids.tx_hash
|
||||||
|
AND receipt_cids.block_number = transaction_cids.block_number
|
||||||
AND transaction_cids.header_id = header_cids.block_hash
|
AND transaction_cids.header_id = header_cids.block_hash
|
||||||
|
AND transaction_cids.block_number = header_cids.block_number
|
||||||
AND header_cids.block_hash = $1`
|
AND header_cids.block_hash = $1`
|
||||||
id := 2
|
id := 2
|
||||||
args = append(args, headerID)
|
args = append(args, headerID)
|
||||||
@@ -308,20 +317,25 @@ func (ecr *CIDRetriever) RetrieveRctCIDsByHeaderID(tx *sqlx.Tx, rctFilter Receip
|
|||||||
return receiptCids, tx.Select(&receiptCids, pgStr, args...)
|
return receiptCids, tx.Select(&receiptCids, pgStr, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RetrieveFilteredGQLLogs retrieves and returns all the log cIDs provided blockHash that conform to the provided
|
// RetrieveFilteredGQLLogs retrieves and returns all the log CIDs provided blockHash that conform to the provided
|
||||||
// filter parameters.
|
// filter parameters.
|
||||||
func (ecr *CIDRetriever) RetrieveFilteredGQLLogs(tx *sqlx.Tx, rctFilter ReceiptFilter, blockHash *common.Hash) ([]LogResult, error) {
|
func (ecr *CIDRetriever) RetrieveFilteredGQLLogs(tx *sqlx.Tx, rctFilter ReceiptFilter, blockHash *common.Hash) ([]LogResult, error) {
|
||||||
log.Debug("retrieving log cids for receipt ids")
|
log.Debug("retrieving log cids for receipt ids")
|
||||||
args := make([]interface{}, 0, 4)
|
args := make([]interface{}, 0, 4)
|
||||||
id := 1
|
id := 1
|
||||||
pgStr := `SELECT eth.log_cids.leaf_cid, eth.log_cids.index, eth.log_cids.rct_id,
|
pgStr := `SELECT CAST(eth.log_cids.block_number as Text), eth.log_cids.leaf_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.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, data, eth.receipt_cids.leaf_cid as cid, eth.receipt_cids.post_status
|
eth.log_cids.log_data, eth.transaction_cids.tx_hash, data, eth.receipt_cids.leaf_cid as cid, eth.receipt_cids.post_status
|
||||||
FROM eth.log_cids, eth.receipt_cids, eth.transaction_cids, eth.header_cids, public.blocks
|
FROM eth.log_cids, eth.receipt_cids, eth.transaction_cids, eth.header_cids, public.blocks
|
||||||
WHERE eth.log_cids.rct_id = receipt_cids.tx_id
|
WHERE eth.log_cids.rct_id = receipt_cids.tx_id
|
||||||
|
AND eth.log_cids.block_number = eth.receipt_cids.block_number
|
||||||
AND receipt_cids.tx_id = transaction_cids.tx_hash
|
AND receipt_cids.tx_id = transaction_cids.tx_hash
|
||||||
AND transaction_cids.header_id = header_cids.block_hash
|
AND receipt_cids.block_number = transaction_cids.block_number
|
||||||
AND log_cids.leaf_mh_key = blocks.key AND header_cids.block_hash = $1`
|
AND transaction_cids.header_id = header_cids.block_hash
|
||||||
|
AND transaction_cids.block_number = header_cids.block_number
|
||||||
|
AND log_cids.leaf_mh_key = blocks.key
|
||||||
|
AND log_cids.block_number = blocks.block_number
|
||||||
|
AND header_cids.block_hash = $1`
|
||||||
|
|
||||||
args = append(args, blockHash.String())
|
args = append(args, blockHash.String())
|
||||||
id++
|
id++
|
||||||
@@ -343,14 +357,17 @@ func (ecr *CIDRetriever) RetrieveFilteredGQLLogs(tx *sqlx.Tx, rctFilter ReceiptF
|
|||||||
func (ecr *CIDRetriever) RetrieveFilteredLog(tx *sqlx.Tx, rctFilter ReceiptFilter, blockNumber int64, blockHash *common.Hash) ([]LogResult, error) {
|
func (ecr *CIDRetriever) RetrieveFilteredLog(tx *sqlx.Tx, rctFilter ReceiptFilter, blockNumber int64, blockHash *common.Hash) ([]LogResult, error) {
|
||||||
log.Debug("retrieving log cids for receipt ids")
|
log.Debug("retrieving log cids for receipt ids")
|
||||||
args := make([]interface{}, 0, 4)
|
args := make([]interface{}, 0, 4)
|
||||||
pgStr := `SELECT eth.log_cids.leaf_cid, eth.log_cids.index, eth.log_cids.rct_id,
|
pgStr := `SELECT CAST(eth.log_cids.block_number as Text), eth.log_cids.leaf_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.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.log_cids.log_data, eth.transaction_cids.tx_hash, eth.transaction_cids.index as txn_index,
|
||||||
header_cids.block_hash, CAST(header_cids.block_number as Text)
|
header_cids.block_hash, CAST(header_cids.block_number as Text)
|
||||||
FROM eth.log_cids, eth.receipt_cids, eth.transaction_cids, eth.header_cids
|
FROM eth.log_cids, eth.receipt_cids, eth.transaction_cids, eth.header_cids
|
||||||
WHERE eth.log_cids.rct_id = receipt_cids.tx_id
|
WHERE eth.log_cids.rct_id = receipt_cids.tx_id
|
||||||
|
AND eth.log_cids.block_number = eth.receipt_cids.block_number
|
||||||
AND receipt_cids.tx_id = transaction_cids.tx_hash
|
AND receipt_cids.tx_id = transaction_cids.tx_hash
|
||||||
AND transaction_cids.header_id = header_cids.block_hash`
|
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`
|
||||||
id := 1
|
id := 1
|
||||||
if blockNumber > 0 {
|
if blockNumber > 0 {
|
||||||
pgStr += fmt.Sprintf(` AND header_cids.block_number = $%d`, id)
|
pgStr += fmt.Sprintf(` AND header_cids.block_number = $%d`, id)
|
||||||
@@ -380,10 +397,13 @@ func (ecr *CIDRetriever) RetrieveFilteredLog(tx *sqlx.Tx, rctFilter ReceiptFilte
|
|||||||
func (ecr *CIDRetriever) RetrieveRctCIDs(tx *sqlx.Tx, rctFilter ReceiptFilter, blockNumber int64, blockHash *common.Hash, txHashes []string) ([]models.ReceiptModel, error) {
|
func (ecr *CIDRetriever) RetrieveRctCIDs(tx *sqlx.Tx, rctFilter ReceiptFilter, blockNumber int64, blockHash *common.Hash, txHashes []string) ([]models.ReceiptModel, error) {
|
||||||
log.Debug("retrieving receipt cids for block ", blockNumber)
|
log.Debug("retrieving receipt cids for block ", blockNumber)
|
||||||
args := make([]interface{}, 0, 5)
|
args := make([]interface{}, 0, 5)
|
||||||
pgStr := `SELECT receipt_cids.tx_id, receipt_cids.leaf_cid, receipt_cids.leaf_mh_key, receipt_cids.tx_id
|
pgStr := `SELECT CAST(receipt_cids.block_number as Text), receipt_cids.tx_id, receipt_cids.leaf_cid,
|
||||||
|
receipt_cids.leaf_mh_key,
|
||||||
FROM eth.receipt_cids, eth.transaction_cids, eth.header_cids
|
FROM eth.receipt_cids, eth.transaction_cids, eth.header_cids
|
||||||
WHERE receipt_cids.tx_id = transaction_cids.tx_hash
|
WHERE receipt_cids.tx_id = transaction_cids.tx_hash
|
||||||
AND transaction_cids.header_id = header_cids.block_hash`
|
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`
|
||||||
id := 1
|
id := 1
|
||||||
if blockNumber > 0 {
|
if blockNumber > 0 {
|
||||||
pgStr += fmt.Sprintf(` AND header_cids.block_number = $%d`, id)
|
pgStr += fmt.Sprintf(` AND header_cids.block_number = $%d`, id)
|
||||||
@@ -416,9 +436,13 @@ func hasTopics(topics [][]string) bool {
|
|||||||
func (ecr *CIDRetriever) RetrieveStateCIDs(tx *sqlx.Tx, stateFilter StateFilter, headerID string) ([]models.StateNodeModel, error) {
|
func (ecr *CIDRetriever) RetrieveStateCIDs(tx *sqlx.Tx, stateFilter StateFilter, headerID string) ([]models.StateNodeModel, error) {
|
||||||
log.Debug("retrieving state cids for header id ", headerID)
|
log.Debug("retrieving state cids for header id ", headerID)
|
||||||
args := make([]interface{}, 0, 2)
|
args := make([]interface{}, 0, 2)
|
||||||
pgStr := `SELECT state_cids.header_id,
|
pgStr := `SELECT CAST(state_cids.block_number as Text), state_cids.header_id,
|
||||||
state_cids.state_leaf_key, state_cids.node_type, state_cids.cid, state_cids.mh_key, state_cids.state_path
|
state_cids.state_leaf_key, state_cids.node_type, state_cids.cid, state_cids.mh_key, state_cids.state_path
|
||||||
FROM eth.state_cids INNER JOIN eth.header_cids ON (state_cids.header_id = header_cids.block_hash)
|
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 header_cids.block_hash = $1`
|
WHERE header_cids.block_hash = $1`
|
||||||
args = append(args, headerID)
|
args = append(args, headerID)
|
||||||
addrLen := len(stateFilter.Addresses)
|
addrLen := len(stateFilter.Addresses)
|
||||||
@@ -441,11 +465,15 @@ func (ecr *CIDRetriever) RetrieveStateCIDs(tx *sqlx.Tx, stateFilter StateFilter,
|
|||||||
func (ecr *CIDRetriever) RetrieveStorageCIDs(tx *sqlx.Tx, storageFilter StorageFilter, headerID string) ([]models.StorageNodeWithStateKeyModel, error) {
|
func (ecr *CIDRetriever) RetrieveStorageCIDs(tx *sqlx.Tx, storageFilter StorageFilter, headerID string) ([]models.StorageNodeWithStateKeyModel, error) {
|
||||||
log.Debug("retrieving storage cids for header id ", headerID)
|
log.Debug("retrieving storage cids for header id ", headerID)
|
||||||
args := make([]interface{}, 0, 3)
|
args := make([]interface{}, 0, 3)
|
||||||
pgStr := `SELECT storage_cids.header_id, storage_cids.storage_leaf_key, storage_cids.node_type,
|
pgStr := `SELECT CAST(storage_cids.block_number as Text), storage_cids.header_id, storage_cids.storage_leaf_key,
|
||||||
storage_cids.cid, storage_cids.mh_key, storage_cids.storage_path, storage_cids.state_path, state_cids.state_leaf_key
|
storage_cids.node_type, storage_cids.cid, storage_cids.mh_key, storage_cids.storage_path, storage_cids.state_path,
|
||||||
|
state_cids.state_leaf_key
|
||||||
FROM eth.storage_cids, eth.state_cids, eth.header_cids
|
FROM eth.storage_cids, eth.state_cids, eth.header_cids
|
||||||
WHERE storage_cids.header_id = state_cids.header_id AND storage_cids.state_path = state_cids.state_path
|
WHERE storage_cids.header_id = state_cids.header_id
|
||||||
|
AND storage_cids.state_path = state_cids.state_path
|
||||||
|
AND storage_cids.block_number = state_cids.block_number
|
||||||
AND state_cids.header_id = header_cids.block_hash
|
AND state_cids.header_id = header_cids.block_hash
|
||||||
|
AND state_cids.block_number = header_cids.block_number
|
||||||
AND header_cids.block_hash = $1`
|
AND header_cids.block_hash = $1`
|
||||||
args = append(args, headerID)
|
args = append(args, headerID)
|
||||||
id := 2
|
id := 2
|
||||||
@@ -496,6 +524,10 @@ func (ecr *CIDRetriever) RetrieveBlockByHash(blockHash common.Hash) (models.Head
|
|||||||
log.Error("header cid retrieval error")
|
log.Error("header cid retrieval error")
|
||||||
return models.HeaderModel{}, nil, nil, nil, err
|
return models.HeaderModel{}, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
blockNumber, err := strconv.ParseInt(headerCID.BlockNumber, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return models.HeaderModel{}, nil, nil, nil, err
|
||||||
|
}
|
||||||
var uncleCIDs []models.UncleModel
|
var uncleCIDs []models.UncleModel
|
||||||
uncleCIDs, err = ecr.RetrieveUncleCIDsByHeaderID(tx, headerCID.BlockHash)
|
uncleCIDs, err = ecr.RetrieveUncleCIDsByHeaderID(tx, headerCID.BlockHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -503,7 +535,7 @@ func (ecr *CIDRetriever) RetrieveBlockByHash(blockHash common.Hash) (models.Head
|
|||||||
return models.HeaderModel{}, nil, nil, nil, err
|
return models.HeaderModel{}, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
var txCIDs []models.TxModel
|
var txCIDs []models.TxModel
|
||||||
txCIDs, err = ecr.RetrieveTxCIDsByHeaderID(tx, headerCID.BlockHash)
|
txCIDs, err = ecr.RetrieveTxCIDsByHeaderID(tx, headerCID.BlockHash, blockNumber)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("tx cid retrieval error")
|
log.Error("tx cid retrieval error")
|
||||||
return models.HeaderModel{}, nil, nil, nil, err
|
return models.HeaderModel{}, nil, nil, nil, err
|
||||||
@@ -556,7 +588,7 @@ func (ecr *CIDRetriever) RetrieveBlockByNumber(blockNumber int64) (models.Header
|
|||||||
return models.HeaderModel{}, nil, nil, nil, err
|
return models.HeaderModel{}, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
var txCIDs []models.TxModel
|
var txCIDs []models.TxModel
|
||||||
txCIDs, err = ecr.RetrieveTxCIDsByHeaderID(tx, headerCID[0].BlockHash)
|
txCIDs, err = ecr.RetrieveTxCIDsByHeaderID(tx, headerCID[0].BlockHash, blockNumber)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("tx cid retrieval error")
|
log.Error("tx cid retrieval error")
|
||||||
return models.HeaderModel{}, nil, nil, nil, err
|
return models.HeaderModel{}, nil, nil, nil, err
|
||||||
@@ -576,30 +608,33 @@ func (ecr *CIDRetriever) RetrieveBlockByNumber(blockNumber int64) (models.Header
|
|||||||
// RetrieveHeaderCIDByHash returns the header for the given block hash
|
// RetrieveHeaderCIDByHash returns the header for the given block hash
|
||||||
func (ecr *CIDRetriever) RetrieveHeaderCIDByHash(tx *sqlx.Tx, blockHash common.Hash) (models.HeaderModel, error) {
|
func (ecr *CIDRetriever) RetrieveHeaderCIDByHash(tx *sqlx.Tx, blockHash common.Hash) (models.HeaderModel, error) {
|
||||||
log.Debug("retrieving header cids for block hash ", blockHash.String())
|
log.Debug("retrieving header cids for block hash ", blockHash.String())
|
||||||
pgStr := `SELECT block_hash,cid,mh_key FROM eth.header_cids
|
pgStr := `SELECT block_hash, CAST(block_number as Text), cid, mh_key FROM eth.header_cids
|
||||||
WHERE block_hash = $1`
|
WHERE block_hash = $1`
|
||||||
var headerCID models.HeaderModel
|
var headerCID models.HeaderModel
|
||||||
return headerCID, tx.Get(&headerCID, pgStr, blockHash.String())
|
return headerCID, tx.Get(&headerCID, pgStr, blockHash.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
// RetrieveTxCIDsByHeaderID retrieves all tx CIDs for the given header id
|
// RetrieveTxCIDsByHeaderID retrieves all tx CIDs for the given header id
|
||||||
func (ecr *CIDRetriever) RetrieveTxCIDsByHeaderID(tx *sqlx.Tx, headerID string) ([]models.TxModel, error) {
|
func (ecr *CIDRetriever) RetrieveTxCIDsByHeaderID(tx *sqlx.Tx, headerID string, blockNumber int64) ([]models.TxModel, error) {
|
||||||
log.Debug("retrieving tx cids for block id ", headerID)
|
log.Debug("retrieving tx cids for block id ", headerID)
|
||||||
pgStr := `SELECT * FROM eth.transaction_cids
|
pgStr := `SELECT CAST(block_number as Text), header_id, index, tx_hash, cid, mh_key,
|
||||||
WHERE header_id = $1
|
dst, src, tx_data, tx_type, value
|
||||||
|
FROM eth.transaction_cids
|
||||||
|
WHERE header_id = $1 AND block_number = $2
|
||||||
ORDER BY index`
|
ORDER BY index`
|
||||||
var txCIDs []models.TxModel
|
var txCIDs []models.TxModel
|
||||||
return txCIDs, tx.Select(&txCIDs, pgStr, headerID)
|
return txCIDs, tx.Select(&txCIDs, pgStr, headerID, blockNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RetrieveReceiptCIDsByTxIDs retrieves receipt CIDs by their associated tx IDs
|
// RetrieveReceiptCIDsByTxIDs retrieves receipt CIDs by their associated tx IDs
|
||||||
func (ecr *CIDRetriever) RetrieveReceiptCIDsByTxIDs(tx *sqlx.Tx, txHashes []string) ([]models.ReceiptModel, error) {
|
func (ecr *CIDRetriever) RetrieveReceiptCIDsByTxIDs(tx *sqlx.Tx, txHashes []string) ([]models.ReceiptModel, error) {
|
||||||
log.Debugf("retrieving receipt cids for tx hashes %v", txHashes)
|
log.Debugf("retrieving receipt cids for tx hashes %v", txHashes)
|
||||||
pgStr := `SELECT receipt_cids.tx_id, receipt_cids.leaf_cid, receipt_cids.leaf_mh_key,
|
pgStr := `SELECT CAST(receipt_cids.block_number as Text), receipt_cids.tx_id, receipt_cids.leaf_cid, receipt_cids.leaf_mh_key,
|
||||||
receipt_cids.contract, receipt_cids.contract_hash
|
receipt_cids.contract, receipt_cids.contract_hash
|
||||||
FROM eth.receipt_cids, eth.transaction_cids
|
FROM eth.receipt_cids, eth.transaction_cids
|
||||||
WHERE tx_id = ANY($1)
|
WHERE tx_id = ANY($1)
|
||||||
AND receipt_cids.tx_id = transaction_cids.tx_hash
|
AND receipt_cids.tx_id = transaction_cids.tx_hash
|
||||||
|
AND receipt_cids.block_number = transaction_cids.block_number
|
||||||
ORDER BY transaction_cids.index`
|
ORDER BY transaction_cids.index`
|
||||||
var rctCIDs []models.ReceiptModel
|
var rctCIDs []models.ReceiptModel
|
||||||
return rctCIDs, tx.Select(&rctCIDs, pgStr, pq.Array(txHashes))
|
return rctCIDs, tx.Select(&rctCIDs, pgStr, pq.Array(txHashes))
|
||||||
|
|||||||
@@ -29,9 +29,9 @@ import (
|
|||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth/test_helpers"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth/test_helpers"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/shared"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -249,6 +249,7 @@ var _ = Describe("Retriever", func() {
|
|||||||
AND header_cids.block_number = $1
|
AND header_cids.block_number = $1
|
||||||
ORDER BY transaction_cids.index`
|
ORDER BY transaction_cids.index`
|
||||||
err := db.Select(&expectedRctCIDsAndLeafNodes, pgStr, test_helpers.BlockNumber.Uint64())
|
err := db.Select(&expectedRctCIDsAndLeafNodes, pgStr, test_helpers.BlockNumber.Uint64())
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
cids, empty, err := retriever.Retrieve(openFilter, 1)
|
cids, empty, err := retriever.Retrieve(openFilter, 1)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(empty).ToNot(BeTrue())
|
Expect(empty).ToNot(BeTrue())
|
||||||
@@ -412,12 +413,13 @@ var _ = Describe("Retriever", func() {
|
|||||||
Expect(len(cids7[0].StorageNodes)).To(Equal(0))
|
Expect(len(cids7[0].StorageNodes)).To(Equal(0))
|
||||||
Expect(len(cids7[0].StateNodes)).To(Equal(1))
|
Expect(len(cids7[0].StateNodes)).To(Equal(1))
|
||||||
Expect(cids7[0].StateNodes[0]).To(Equal(models.StateNodeModel{
|
Expect(cids7[0].StateNodes[0]).To(Equal(models.StateNodeModel{
|
||||||
HeaderID: cids7[0].StateNodes[0].HeaderID,
|
BlockNumber: "1",
|
||||||
NodeType: 2,
|
HeaderID: cids7[0].StateNodes[0].HeaderID,
|
||||||
StateKey: common.BytesToHash(test_helpers.AccountLeafKey).Hex(),
|
NodeType: 2,
|
||||||
CID: test_helpers.State2CID.String(),
|
StateKey: common.BytesToHash(test_helpers.AccountLeafKey).Hex(),
|
||||||
MhKey: test_helpers.State2MhKey,
|
CID: test_helpers.State2CID.String(),
|
||||||
Path: []byte{'\x0c'},
|
MhKey: test_helpers.State2MhKey,
|
||||||
|
Path: []byte{'\x0c'},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
_, empty, err = retriever.Retrieve(rctTopicsAndAddressFilterFail, 1)
|
_, empty, err = retriever.Retrieve(rctTopicsAndAddressFilterFail, 1)
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ import (
|
|||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth/test_helpers"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth/test_helpers"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/shared"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/shared"
|
||||||
ethServerShared "github.com/vulcanize/ipld-eth-server/v3/pkg/shared"
|
ethServerShared "github.com/vulcanize/ipld-eth-server/v4/pkg/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
+15
-10
@@ -82,8 +82,9 @@ func (s *ResponseFilterer) filterHeaders(headerFilter HeaderFilter, response *IP
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
response.Header = models.IPLDModel{
|
response.Header = models.IPLDModel{
|
||||||
Data: headerRLP,
|
BlockNumber: payload.Block.Number().String(),
|
||||||
Key: cid.String(),
|
Data: headerRLP,
|
||||||
|
Key: cid.String(),
|
||||||
}
|
}
|
||||||
if headerFilter.Uncles {
|
if headerFilter.Uncles {
|
||||||
response.Uncles = make([]models.IPLDModel, len(payload.Block.Body().Uncles))
|
response.Uncles = make([]models.IPLDModel, len(payload.Block.Body().Uncles))
|
||||||
@@ -97,8 +98,9 @@ func (s *ResponseFilterer) filterHeaders(headerFilter HeaderFilter, response *IP
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
response.Uncles[i] = models.IPLDModel{
|
response.Uncles[i] = models.IPLDModel{
|
||||||
Data: uncleRlp,
|
BlockNumber: uncle.Number.String(),
|
||||||
Key: cid.String(),
|
Data: uncleRlp,
|
||||||
|
Key: cid.String(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,8 +185,9 @@ func (s *ResponseFilterer) filerReceipts(receiptFilter ReceiptFilter, response *
|
|||||||
// TODO: Verify this filter logic.
|
// TODO: Verify this filter logic.
|
||||||
if checkReceipts(receipt, receiptFilter.Topics, topics, receiptFilter.LogAddresses, contracts, trxHashes) {
|
if checkReceipts(receipt, receiptFilter.Topics, topics, receiptFilter.LogAddresses, contracts, trxHashes) {
|
||||||
response.Receipts = append(response.Receipts, models.IPLDModel{
|
response.Receipts = append(response.Receipts, models.IPLDModel{
|
||||||
Data: rctIPLDData[idx],
|
BlockNumber: payload.Block.Number().String(),
|
||||||
Key: rctLeafCID[idx].String(),
|
Data: rctIPLDData[idx],
|
||||||
|
Key: rctLeafCID[idx].String(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -282,8 +285,9 @@ func (s *ResponseFilterer) filterStateAndStorage(stateFilter StateFilter, storag
|
|||||||
StateLeafKey: common.BytesToHash(stateNode.LeafKey),
|
StateLeafKey: common.BytesToHash(stateNode.LeafKey),
|
||||||
Path: stateNode.Path,
|
Path: stateNode.Path,
|
||||||
IPLD: models.IPLDModel{
|
IPLD: models.IPLDModel{
|
||||||
Data: stateNode.NodeValue,
|
BlockNumber: payload.Block.Number().String(),
|
||||||
Key: cid.String(),
|
Data: stateNode.NodeValue,
|
||||||
|
Key: cid.String(),
|
||||||
},
|
},
|
||||||
Type: stateNode.NodeType,
|
Type: stateNode.NodeType,
|
||||||
})
|
})
|
||||||
@@ -300,8 +304,9 @@ func (s *ResponseFilterer) filterStateAndStorage(stateFilter StateFilter, storag
|
|||||||
StateLeafKey: common.BytesToHash(stateNode.LeafKey),
|
StateLeafKey: common.BytesToHash(stateNode.LeafKey),
|
||||||
StorageLeafKey: common.BytesToHash(storageNode.LeafKey),
|
StorageLeafKey: common.BytesToHash(storageNode.LeafKey),
|
||||||
IPLD: models.IPLDModel{
|
IPLD: models.IPLDModel{
|
||||||
Data: storageNode.NodeValue,
|
BlockNumber: payload.Block.Number().String(),
|
||||||
Key: cid.String(),
|
Data: storageNode.NodeValue,
|
||||||
|
Key: cid.String(),
|
||||||
},
|
},
|
||||||
Type: storageNode.NodeType,
|
Type: storageNode.NodeType,
|
||||||
Path: storageNode.Path,
|
Path: storageNode.Path,
|
||||||
|
|||||||
+27
-19
@@ -25,9 +25,9 @@ import (
|
|||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth/test_helpers"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth/test_helpers"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/shared"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -61,14 +61,16 @@ var _ = Describe("Filterer", func() {
|
|||||||
Expect(stateNode.Type).To(Equal(sdtypes.Leaf))
|
Expect(stateNode.Type).To(Equal(sdtypes.Leaf))
|
||||||
if bytes.Equal(stateNode.StateLeafKey.Bytes(), test_helpers.AccountLeafKey) {
|
if bytes.Equal(stateNode.StateLeafKey.Bytes(), test_helpers.AccountLeafKey) {
|
||||||
Expect(stateNode.IPLD).To(Equal(models.IPLDModel{
|
Expect(stateNode.IPLD).To(Equal(models.IPLDModel{
|
||||||
Data: test_helpers.State2IPLD.RawData(),
|
BlockNumber: test_helpers.BlockNumber.String(),
|
||||||
Key: test_helpers.State2IPLD.Cid().String(),
|
Data: test_helpers.State2IPLD.RawData(),
|
||||||
|
Key: test_helpers.State2IPLD.Cid().String(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
if bytes.Equal(stateNode.StateLeafKey.Bytes(), test_helpers.ContractLeafKey) {
|
if bytes.Equal(stateNode.StateLeafKey.Bytes(), test_helpers.ContractLeafKey) {
|
||||||
Expect(stateNode.IPLD).To(Equal(models.IPLDModel{
|
Expect(stateNode.IPLD).To(Equal(models.IPLDModel{
|
||||||
Data: test_helpers.State1IPLD.RawData(),
|
BlockNumber: test_helpers.BlockNumber.String(),
|
||||||
Key: test_helpers.State1IPLD.Cid().String(),
|
Data: test_helpers.State1IPLD.RawData(),
|
||||||
|
Key: test_helpers.State1IPLD.Cid().String(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,8 +89,9 @@ var _ = Describe("Filterer", func() {
|
|||||||
Expect(len(iplds1.StateNodes)).To(Equal(0))
|
Expect(len(iplds1.StateNodes)).To(Equal(0))
|
||||||
Expect(len(iplds1.Receipts)).To(Equal(1))
|
Expect(len(iplds1.Receipts)).To(Equal(1))
|
||||||
Expect(iplds1.Receipts[0]).To(Equal(models.IPLDModel{
|
Expect(iplds1.Receipts[0]).To(Equal(models.IPLDModel{
|
||||||
Data: test_helpers.Rct1IPLD,
|
BlockNumber: test_helpers.BlockNumber.String(),
|
||||||
Key: test_helpers.Rct1CID.String(),
|
Data: test_helpers.Rct1IPLD,
|
||||||
|
Key: test_helpers.Rct1CID.String(),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
iplds2, err := filterer.Filter(rctTopicsFilter, test_helpers.MockConvertedPayload)
|
iplds2, err := filterer.Filter(rctTopicsFilter, test_helpers.MockConvertedPayload)
|
||||||
@@ -102,8 +105,9 @@ var _ = Describe("Filterer", func() {
|
|||||||
Expect(len(iplds2.StateNodes)).To(Equal(0))
|
Expect(len(iplds2.StateNodes)).To(Equal(0))
|
||||||
Expect(len(iplds2.Receipts)).To(Equal(1))
|
Expect(len(iplds2.Receipts)).To(Equal(1))
|
||||||
Expect(iplds2.Receipts[0]).To(Equal(models.IPLDModel{
|
Expect(iplds2.Receipts[0]).To(Equal(models.IPLDModel{
|
||||||
Data: test_helpers.Rct1IPLD,
|
BlockNumber: test_helpers.BlockNumber.String(),
|
||||||
Key: test_helpers.Rct1CID.String(),
|
Data: test_helpers.Rct1IPLD,
|
||||||
|
Key: test_helpers.Rct1CID.String(),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
iplds3, err := filterer.Filter(rctTopicsAndAddressFilter, test_helpers.MockConvertedPayload)
|
iplds3, err := filterer.Filter(rctTopicsAndAddressFilter, test_helpers.MockConvertedPayload)
|
||||||
@@ -117,8 +121,9 @@ var _ = Describe("Filterer", func() {
|
|||||||
Expect(len(iplds3.StateNodes)).To(Equal(0))
|
Expect(len(iplds3.StateNodes)).To(Equal(0))
|
||||||
Expect(len(iplds3.Receipts)).To(Equal(1))
|
Expect(len(iplds3.Receipts)).To(Equal(1))
|
||||||
Expect(iplds3.Receipts[0]).To(Equal(models.IPLDModel{
|
Expect(iplds3.Receipts[0]).To(Equal(models.IPLDModel{
|
||||||
Data: test_helpers.Rct1IPLD,
|
BlockNumber: test_helpers.BlockNumber.String(),
|
||||||
Key: test_helpers.Rct1CID.String(),
|
Data: test_helpers.Rct1IPLD,
|
||||||
|
Key: test_helpers.Rct1CID.String(),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
iplds4, err := filterer.Filter(rctAddressesAndTopicFilter, test_helpers.MockConvertedPayload)
|
iplds4, err := filterer.Filter(rctAddressesAndTopicFilter, test_helpers.MockConvertedPayload)
|
||||||
@@ -132,8 +137,9 @@ var _ = Describe("Filterer", func() {
|
|||||||
Expect(len(iplds4.StateNodes)).To(Equal(0))
|
Expect(len(iplds4.StateNodes)).To(Equal(0))
|
||||||
Expect(len(iplds4.Receipts)).To(Equal(1))
|
Expect(len(iplds4.Receipts)).To(Equal(1))
|
||||||
Expect(iplds4.Receipts[0]).To(Equal(models.IPLDModel{
|
Expect(iplds4.Receipts[0]).To(Equal(models.IPLDModel{
|
||||||
Data: test_helpers.Rct2IPLD,
|
BlockNumber: test_helpers.BlockNumber.String(),
|
||||||
Key: test_helpers.Rct2CID.String(),
|
Data: test_helpers.Rct2IPLD,
|
||||||
|
Key: test_helpers.Rct2CID.String(),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
iplds5, err := filterer.Filter(rctsForAllCollectedTrxs, test_helpers.MockConvertedPayload)
|
iplds5, err := filterer.Filter(rctsForAllCollectedTrxs, test_helpers.MockConvertedPayload)
|
||||||
@@ -165,8 +171,9 @@ var _ = Describe("Filterer", func() {
|
|||||||
Expect(len(iplds6.StateNodes)).To(Equal(0))
|
Expect(len(iplds6.StateNodes)).To(Equal(0))
|
||||||
Expect(len(iplds6.Receipts)).To(Equal(1))
|
Expect(len(iplds6.Receipts)).To(Equal(1))
|
||||||
Expect(iplds4.Receipts[0]).To(Equal(models.IPLDModel{
|
Expect(iplds4.Receipts[0]).To(Equal(models.IPLDModel{
|
||||||
Data: test_helpers.Rct2IPLD,
|
BlockNumber: test_helpers.BlockNumber.String(),
|
||||||
Key: test_helpers.Rct2CID.String(),
|
Data: test_helpers.Rct2IPLD,
|
||||||
|
Key: test_helpers.Rct2CID.String(),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
iplds7, err := filterer.Filter(stateFilter, test_helpers.MockConvertedPayload)
|
iplds7, err := filterer.Filter(stateFilter, test_helpers.MockConvertedPayload)
|
||||||
@@ -181,8 +188,9 @@ var _ = Describe("Filterer", func() {
|
|||||||
Expect(len(iplds7.StateNodes)).To(Equal(1))
|
Expect(len(iplds7.StateNodes)).To(Equal(1))
|
||||||
Expect(iplds7.StateNodes[0].StateLeafKey.Bytes()).To(Equal(test_helpers.AccountLeafKey))
|
Expect(iplds7.StateNodes[0].StateLeafKey.Bytes()).To(Equal(test_helpers.AccountLeafKey))
|
||||||
Expect(iplds7.StateNodes[0].IPLD).To(Equal(models.IPLDModel{
|
Expect(iplds7.StateNodes[0].IPLD).To(Equal(models.IPLDModel{
|
||||||
Data: test_helpers.State2IPLD.RawData(),
|
BlockNumber: test_helpers.BlockNumber.String(),
|
||||||
Key: test_helpers.State2IPLD.Cid().String(),
|
Data: test_helpers.State2IPLD.RawData(),
|
||||||
|
Key: test_helpers.State2IPLD.Cid().String(),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
iplds8, err := filterer.Filter(rctTopicsAndAddressFilterFail, test_helpers.MockConvertedPayload)
|
iplds8, err := filterer.Filter(rctTopicsAndAddressFilterFail, test_helpers.MockConvertedPayload)
|
||||||
|
|||||||
+51
-19
@@ -20,12 +20,13 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/statediff/indexer/models"
|
"github.com/ethereum/go-ethereum/statediff/indexer/models"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/shared"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Fetcher interface for substituting mocks in tests
|
// Fetcher interface for substituting mocks in tests
|
||||||
@@ -102,13 +103,19 @@ func (f *IPLDFetcher) Fetch(cids CIDWrapper) (*IPLDs, error) {
|
|||||||
// FetchHeaders fetches headers
|
// FetchHeaders fetches headers
|
||||||
func (f *IPLDFetcher) FetchHeader(tx *sqlx.Tx, c models.HeaderModel) (models.IPLDModel, error) {
|
func (f *IPLDFetcher) FetchHeader(tx *sqlx.Tx, c models.HeaderModel) (models.IPLDModel, error) {
|
||||||
log.Debug("fetching header ipld")
|
log.Debug("fetching header ipld")
|
||||||
headerBytes, err := shared.FetchIPLDByMhKey(tx, c.MhKey)
|
blockNumber, err := strconv.ParseUint(c.BlockNumber, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return models.IPLDModel{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
headerBytes, err := shared.FetchIPLDByMhKeyAndBlockNumber(tx, c.MhKey, blockNumber)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return models.IPLDModel{}, err
|
return models.IPLDModel{}, err
|
||||||
}
|
}
|
||||||
return models.IPLDModel{
|
return models.IPLDModel{
|
||||||
Data: headerBytes,
|
BlockNumber: c.BlockNumber,
|
||||||
Key: c.CID,
|
Data: headerBytes,
|
||||||
|
Key: c.CID,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,13 +124,18 @@ func (f *IPLDFetcher) FetchUncles(tx *sqlx.Tx, cids []models.UncleModel) ([]mode
|
|||||||
log.Debug("fetching uncle iplds")
|
log.Debug("fetching uncle iplds")
|
||||||
uncleIPLDs := make([]models.IPLDModel, len(cids))
|
uncleIPLDs := make([]models.IPLDModel, len(cids))
|
||||||
for i, c := range cids {
|
for i, c := range cids {
|
||||||
uncleBytes, err := shared.FetchIPLDByMhKey(tx, c.MhKey)
|
blockNumber, err := strconv.ParseUint(c.BlockNumber, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
uncleBytes, err := shared.FetchIPLDByMhKeyAndBlockNumber(tx, c.MhKey, blockNumber)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
uncleIPLDs[i] = models.IPLDModel{
|
uncleIPLDs[i] = models.IPLDModel{
|
||||||
Data: uncleBytes,
|
BlockNumber: c.BlockNumber,
|
||||||
Key: c.CID,
|
Data: uncleBytes,
|
||||||
|
Key: c.CID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return uncleIPLDs, nil
|
return uncleIPLDs, nil
|
||||||
@@ -134,13 +146,18 @@ func (f *IPLDFetcher) FetchTrxs(tx *sqlx.Tx, cids []models.TxModel) ([]models.IP
|
|||||||
log.Debug("fetching transaction iplds")
|
log.Debug("fetching transaction iplds")
|
||||||
trxIPLDs := make([]models.IPLDModel, len(cids))
|
trxIPLDs := make([]models.IPLDModel, len(cids))
|
||||||
for i, c := range cids {
|
for i, c := range cids {
|
||||||
txBytes, err := shared.FetchIPLDByMhKey(tx, c.MhKey)
|
blockNumber, err := strconv.ParseUint(c.BlockNumber, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
txBytes, err := shared.FetchIPLDByMhKeyAndBlockNumber(tx, c.MhKey, blockNumber)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
trxIPLDs[i] = models.IPLDModel{
|
trxIPLDs[i] = models.IPLDModel{
|
||||||
Data: txBytes,
|
BlockNumber: c.BlockNumber,
|
||||||
Key: c.CID,
|
Data: txBytes,
|
||||||
|
Key: c.CID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return trxIPLDs, nil
|
return trxIPLDs, nil
|
||||||
@@ -151,14 +168,19 @@ func (f *IPLDFetcher) FetchRcts(tx *sqlx.Tx, cids []models.ReceiptModel) ([]mode
|
|||||||
log.Debug("fetching receipt iplds")
|
log.Debug("fetching receipt iplds")
|
||||||
rctIPLDs := make([]models.IPLDModel, len(cids))
|
rctIPLDs := make([]models.IPLDModel, len(cids))
|
||||||
for i, c := range cids {
|
for i, c := range cids {
|
||||||
rctBytes, err := shared.FetchIPLDByMhKey(tx, c.LeafMhKey)
|
blockNumber, err := strconv.ParseUint(c.BlockNumber, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rctBytes, err := shared.FetchIPLDByMhKeyAndBlockNumber(tx, c.LeafMhKey, blockNumber)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
//nodeVal, err := DecodeLeafNode(rctBytes)
|
//nodeVal, err := DecodeLeafNode(rctBytes)
|
||||||
rctIPLDs[i] = models.IPLDModel{
|
rctIPLDs[i] = models.IPLDModel{
|
||||||
Data: rctBytes,
|
BlockNumber: c.BlockNumber,
|
||||||
Key: c.LeafCID,
|
Data: rctBytes,
|
||||||
|
Key: c.LeafCID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rctIPLDs, nil
|
return rctIPLDs, nil
|
||||||
@@ -172,14 +194,19 @@ func (f *IPLDFetcher) FetchState(tx *sqlx.Tx, cids []models.StateNodeModel) ([]S
|
|||||||
if stateNode.CID == "" {
|
if stateNode.CID == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
stateBytes, err := shared.FetchIPLDByMhKey(tx, stateNode.MhKey)
|
blockNumber, err := strconv.ParseUint(stateNode.BlockNumber, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
stateBytes, err := shared.FetchIPLDByMhKeyAndBlockNumber(tx, stateNode.MhKey, blockNumber)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
stateNodes = append(stateNodes, StateNode{
|
stateNodes = append(stateNodes, StateNode{
|
||||||
IPLD: models.IPLDModel{
|
IPLD: models.IPLDModel{
|
||||||
Data: stateBytes,
|
BlockNumber: stateNode.BlockNumber,
|
||||||
Key: stateNode.CID,
|
Data: stateBytes,
|
||||||
|
Key: stateNode.CID,
|
||||||
},
|
},
|
||||||
StateLeafKey: common.HexToHash(stateNode.StateKey),
|
StateLeafKey: common.HexToHash(stateNode.StateKey),
|
||||||
Type: ResolveToNodeType(stateNode.NodeType),
|
Type: ResolveToNodeType(stateNode.NodeType),
|
||||||
@@ -197,14 +224,19 @@ func (f *IPLDFetcher) FetchStorage(tx *sqlx.Tx, cids []models.StorageNodeWithSta
|
|||||||
if storageNode.CID == "" || storageNode.StateKey == "" {
|
if storageNode.CID == "" || storageNode.StateKey == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
storageBytes, err := shared.FetchIPLDByMhKey(tx, storageNode.MhKey)
|
blockNumber, err := strconv.ParseUint(storageNode.BlockNumber, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
storageBytes, err := shared.FetchIPLDByMhKeyAndBlockNumber(tx, storageNode.MhKey, blockNumber)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
storageNodes = append(storageNodes, StorageNode{
|
storageNodes = append(storageNodes, StorageNode{
|
||||||
IPLD: models.IPLDModel{
|
IPLD: models.IPLDModel{
|
||||||
Data: storageBytes,
|
BlockNumber: storageNode.BlockNumber,
|
||||||
Key: storageNode.CID,
|
Data: storageBytes,
|
||||||
|
Key: storageNode.CID,
|
||||||
},
|
},
|
||||||
StateLeafKey: common.HexToHash(storageNode.StateKey),
|
StateLeafKey: common.HexToHash(storageNode.StateKey),
|
||||||
StorageLeafKey: common.HexToHash(storageNode.StorageKey),
|
StorageLeafKey: common.HexToHash(storageNode.StorageKey),
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ import (
|
|||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth/test_helpers"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth/test_helpers"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/shared"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("IPLDFetcher", func() {
|
var _ = Describe("IPLDFetcher", func() {
|
||||||
|
|||||||
+140
-39
@@ -36,93 +36,180 @@ const (
|
|||||||
|
|
||||||
RetrieveHeadersByHashesPgStr = `SELECT cid, data
|
RetrieveHeadersByHashesPgStr = `SELECT cid, data
|
||||||
FROM eth.header_cids
|
FROM eth.header_cids
|
||||||
INNER JOIN public.blocks ON (header_cids.mh_key = blocks.key)
|
INNER JOIN public.blocks ON (
|
||||||
|
header_cids.mh_key = blocks.key
|
||||||
|
AND header_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
WHERE block_hash = ANY($1::VARCHAR(66)[])`
|
WHERE block_hash = ANY($1::VARCHAR(66)[])`
|
||||||
RetrieveHeadersByBlockNumberPgStr = `SELECT cid, data
|
RetrieveHeadersByBlockNumberPgStr = `SELECT cid, data
|
||||||
FROM eth.header_cids
|
FROM eth.header_cids
|
||||||
INNER JOIN public.blocks ON (header_cids.mh_key = blocks.key)
|
INNER JOIN public.blocks ON (
|
||||||
|
header_cids.mh_key = blocks.key
|
||||||
|
AND header_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
WHERE block_number = $1`
|
WHERE block_number = $1`
|
||||||
RetrieveHeaderByHashPgStr = `SELECT cid, data
|
RetrieveHeaderByHashPgStr = `SELECT cid, data
|
||||||
FROM eth.header_cids
|
FROM eth.header_cids
|
||||||
INNER JOIN public.blocks ON (header_cids.mh_key = blocks.key)
|
INNER JOIN public.blocks ON (
|
||||||
|
header_cids.mh_key = blocks.key
|
||||||
|
AND header_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
WHERE block_hash = $1`
|
WHERE block_hash = $1`
|
||||||
RetrieveUnclesByHashesPgStr = `SELECT cid, data
|
RetrieveUnclesByHashesPgStr = `SELECT cid, data
|
||||||
FROM eth.uncle_cids
|
FROM eth.uncle_cids
|
||||||
INNER JOIN public.blocks ON (uncle_cids.mh_key = blocks.key)
|
INNER JOIN public.blocks ON (
|
||||||
|
uncle_cids.mh_key = blocks.key
|
||||||
|
AND uncle_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
WHERE block_hash = ANY($1::VARCHAR(66)[])`
|
WHERE block_hash = ANY($1::VARCHAR(66)[])`
|
||||||
RetrieveUnclesByBlockHashPgStr = `SELECT uncle_cids.cid, data
|
RetrieveUnclesByBlockHashPgStr = `SELECT uncle_cids.cid, data
|
||||||
FROM eth.uncle_cids
|
FROM eth.uncle_cids
|
||||||
INNER JOIN eth.header_cids ON (uncle_cids.header_id = header_cids.block_hash)
|
INNER JOIN eth.header_cids ON (
|
||||||
INNER JOIN public.blocks ON (uncle_cids.mh_key = blocks.key)
|
uncle_cids.header_id = header_cids.block_hash
|
||||||
|
AND uncle_cids.block_number = header_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN public.blocks ON (
|
||||||
|
uncle_cids.mh_key = blocks.key
|
||||||
|
AND uncle_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
WHERE block_hash = $1`
|
WHERE block_hash = $1`
|
||||||
RetrieveUnclesByBlockNumberPgStr = `SELECT uncle_cids.cid, data
|
RetrieveUnclesByBlockNumberPgStr = `SELECT uncle_cids.cid, data
|
||||||
FROM eth.uncle_cids
|
FROM eth.uncle_cids
|
||||||
INNER JOIN eth.header_cids ON (uncle_cids.header_id = header_cids.block_hash)
|
INNER JOIN eth.header_cids ON (
|
||||||
INNER JOIN public.blocks ON (uncle_cids.mh_key = blocks.key)
|
uncle_cids.header_id = header_cids.block_hash
|
||||||
|
AND uncle_cids.block_number = header_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN public.blocks ON (
|
||||||
|
uncle_cids.mh_key = blocks.key
|
||||||
|
AND uncle_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
WHERE block_number = $1`
|
WHERE block_number = $1`
|
||||||
RetrieveUncleByHashPgStr = `SELECT cid, data
|
RetrieveUncleByHashPgStr = `SELECT cid, data
|
||||||
FROM eth.uncle_cids
|
FROM eth.uncle_cids
|
||||||
INNER JOIN public.blocks ON (uncle_cids.mh_key = blocks.key)
|
INNER JOIN public.blocks ON (
|
||||||
|
uncle_cids.mh_key = blocks.key
|
||||||
|
AND uncle_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
WHERE block_hash = $1`
|
WHERE block_hash = $1`
|
||||||
RetrieveTransactionsByHashesPgStr = `SELECT cid, data
|
RetrieveTransactionsByHashesPgStr = `SELECT cid, data
|
||||||
FROM eth.transaction_cids
|
FROM eth.transaction_cids
|
||||||
INNER JOIN public.blocks ON (transaction_cids.mh_key = blocks.key)
|
INNER JOIN public.blocks ON (
|
||||||
|
transaction_cids.mh_key = blocks.key
|
||||||
|
AND transaction_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
WHERE tx_hash = ANY($1::VARCHAR(66)[])`
|
WHERE tx_hash = ANY($1::VARCHAR(66)[])`
|
||||||
RetrieveTransactionsByBlockHashPgStr = `SELECT transaction_cids.cid, data
|
RetrieveTransactionsByBlockHashPgStr = `SELECT transaction_cids.cid, data
|
||||||
FROM eth.transaction_cids
|
FROM eth.transaction_cids
|
||||||
INNER JOIN eth.header_cids ON (transaction_cids.header_id = header_cids.block_hash)
|
INNER JOIN eth.header_cids ON (
|
||||||
INNER JOIN public.blocks ON (transaction_cids.mh_key = blocks.key)
|
transaction_cids.header_id = header_cids.block_hash
|
||||||
|
AND transaction_cids.block_number = header_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN public.blocks ON (
|
||||||
|
transaction_cids.mh_key = blocks.key
|
||||||
|
AND transaction_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
WHERE block_hash = $1
|
WHERE block_hash = $1
|
||||||
ORDER BY eth.transaction_cids.index ASC`
|
ORDER BY eth.transaction_cids.index ASC`
|
||||||
RetrieveTransactionsByBlockNumberPgStr = `SELECT transaction_cids.cid, data
|
RetrieveTransactionsByBlockNumberPgStr = `SELECT transaction_cids.cid, data
|
||||||
FROM eth.transaction_cids
|
FROM eth.transaction_cids
|
||||||
INNER JOIN eth.header_cids ON (transaction_cids.header_id = header_cids.block_hash)
|
INNER JOIN eth.header_cids ON (
|
||||||
INNER JOIN public.blocks ON (transaction_cids.mh_key = blocks.key)
|
transaction_cids.header_id = header_cids.block_hash
|
||||||
|
AND transaction_cids.block_number = header_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN public.blocks ON (
|
||||||
|
transaction_cids.mh_key = blocks.key
|
||||||
|
AND transaction_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
WHERE block_number = $1
|
WHERE block_number = $1
|
||||||
ORDER BY eth.transaction_cids.index ASC`
|
ORDER BY eth.transaction_cids.index ASC`
|
||||||
RetrieveTransactionByHashPgStr = `SELECT cid, data
|
RetrieveTransactionByHashPgStr = `SELECT cid, data
|
||||||
FROM eth.transaction_cids
|
FROM eth.transaction_cids
|
||||||
INNER JOIN public.blocks ON (transaction_cids.mh_key = blocks.key)
|
INNER JOIN public.blocks ON (
|
||||||
|
transaction_cids.mh_key = blocks.key
|
||||||
|
AND transaction_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
WHERE tx_hash = $1`
|
WHERE tx_hash = $1`
|
||||||
RetrieveReceiptsByTxHashesPgStr = `SELECT receipt_cids.leaf_cid, data
|
RetrieveReceiptsByTxHashesPgStr = `SELECT receipt_cids.leaf_cid, data
|
||||||
FROM eth.receipt_cids
|
FROM eth.receipt_cids
|
||||||
INNER JOIN eth.transaction_cids ON (receipt_cids.tx_id = transaction_cids.tx_hash)
|
INNER JOIN eth.transaction_cids ON (
|
||||||
INNER JOIN public.blocks ON (receipt_cids.leaf_mh_key = blocks.key)
|
receipt_cids.tx_id = transaction_cids.tx_hash
|
||||||
|
AND receipt_cids.block_number = transaction_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN public.blocks ON (
|
||||||
|
receipt_cids.leaf_mh_key = blocks.key
|
||||||
|
AND receipt_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
WHERE tx_hash = ANY($1::VARCHAR(66)[])`
|
WHERE tx_hash = ANY($1::VARCHAR(66)[])`
|
||||||
RetrieveReceiptsByBlockHashPgStr = `SELECT receipt_cids.leaf_cid, data, eth.transaction_cids.tx_hash
|
RetrieveReceiptsByBlockHashPgStr = `SELECT receipt_cids.leaf_cid, data, eth.transaction_cids.tx_hash
|
||||||
FROM eth.receipt_cids
|
FROM eth.receipt_cids
|
||||||
INNER JOIN eth.transaction_cids ON (receipt_cids.tx_id = transaction_cids.tx_hash)
|
INNER JOIN eth.transaction_cids ON (
|
||||||
INNER JOIN eth.header_cids ON (transaction_cids.header_id = header_cids.block_hash)
|
receipt_cids.tx_id = transaction_cids.tx_hash
|
||||||
INNER JOIN public.blocks ON (receipt_cids.leaf_mh_key = blocks.key)
|
AND receipt_cids.block_number = transaction_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN eth.header_cids ON (
|
||||||
|
transaction_cids.header_id = header_cids.block_hash
|
||||||
|
AND transaction_cids.block_number = header_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN public.blocks ON (
|
||||||
|
receipt_cids.leaf_mh_key = blocks.key
|
||||||
|
AND receipt_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
WHERE block_hash = $1
|
WHERE block_hash = $1
|
||||||
ORDER BY eth.transaction_cids.index ASC`
|
ORDER BY eth.transaction_cids.index ASC`
|
||||||
RetrieveReceiptsByBlockNumberPgStr = `SELECT receipt_cids.leaf_cid, data
|
RetrieveReceiptsByBlockNumberPgStr = `SELECT receipt_cids.leaf_cid, data
|
||||||
FROM eth.receipt_cids
|
FROM eth.receipt_cids
|
||||||
INNER JOIN eth.transaction_cids ON (receipt_cids.tx_id = transaction_cids.tx_hash)
|
INNER JOIN eth.transaction_cids ON (
|
||||||
INNER JOIN eth.header_cids ON (transaction_cids.header_id = header_cids.block_hash)
|
receipt_cids.tx_id = transaction_cids.tx_hash
|
||||||
INNER JOIN public.blocks ON (receipt_cids.leaf_mh_key = blocks.key)
|
AND receipt_cids.block_number = transaction_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN eth.header_cids ON (
|
||||||
|
transaction_cids.header_id = header_cids.block_hash
|
||||||
|
AND transaction_cids.block_number = header_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN public.blocks ON (
|
||||||
|
receipt_cids.leaf_mh_key = blocks.key
|
||||||
|
AND receipt_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
WHERE block_number = $1
|
WHERE block_number = $1
|
||||||
ORDER BY eth.transaction_cids.index ASC`
|
ORDER BY eth.transaction_cids.index ASC`
|
||||||
RetrieveReceiptByTxHashPgStr = `SELECT receipt_cids.leaf_cid, data
|
RetrieveReceiptByTxHashPgStr = `SELECT receipt_cids.leaf_cid, data
|
||||||
FROM eth.receipt_cids
|
FROM eth.receipt_cids
|
||||||
INNER JOIN eth.transaction_cids ON (receipt_cids.tx_id = transaction_cids.tx_hash)
|
INNER JOIN eth.transaction_cids ON (
|
||||||
INNER JOIN public.blocks ON (receipt_cids.leaf_mh_key = blocks.key)
|
receipt_cids.tx_id = transaction_cids.tx_hash
|
||||||
|
AND receipt_cids.block_number = transaction_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN public.blocks ON (
|
||||||
|
receipt_cids.leaf_mh_key = blocks.key
|
||||||
|
AND receipt_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
WHERE tx_hash = $1`
|
WHERE tx_hash = $1`
|
||||||
RetrieveAccountByLeafKeyAndBlockHashPgStr = `SELECT state_cids.cid, data, state_cids.node_type
|
RetrieveAccountByLeafKeyAndBlockHashPgStr = `SELECT state_cids.cid, data, state_cids.node_type
|
||||||
FROM eth.state_cids
|
FROM eth.state_cids
|
||||||
INNER JOIN eth.header_cids ON (state_cids.header_id = header_cids.block_hash)
|
INNER JOIN eth.header_cids ON (
|
||||||
INNER JOIN public.blocks ON (state_cids.mh_key = blocks.key)
|
state_cids.header_id = header_cids.block_hash
|
||||||
|
AND state_cids.block_number = header_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN public.blocks ON (
|
||||||
|
state_cids.mh_key = blocks.key
|
||||||
|
AND state_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
WHERE state_leaf_key = $1
|
WHERE state_leaf_key = $1
|
||||||
AND block_number <= (SELECT block_number
|
AND header_cids.block_number <= (SELECT block_number
|
||||||
FROM eth.header_cids
|
FROM eth.header_cids
|
||||||
WHERE block_hash = $2)
|
WHERE block_hash = $2)
|
||||||
AND header_cids.block_hash = (SELECT canonical_header_hash(block_number))
|
AND header_cids.block_hash = (SELECT canonical_header_hash(header_cids.block_number))
|
||||||
ORDER BY block_number DESC
|
ORDER BY header_cids.block_number DESC
|
||||||
LIMIT 1`
|
LIMIT 1`
|
||||||
RetrieveAccountByLeafKeyAndBlockNumberPgStr = `SELECT state_cids.cid, data, state_cids.node_type
|
RetrieveAccountByLeafKeyAndBlockNumberPgStr = `SELECT state_cids.cid, data, state_cids.node_type
|
||||||
FROM eth.state_cids
|
FROM eth.state_cids
|
||||||
INNER JOIN eth.header_cids ON (state_cids.header_id = header_cids.block_hash)
|
INNER JOIN eth.header_cids ON (
|
||||||
INNER JOIN public.blocks ON (state_cids.mh_key = blocks.key)
|
state_cids.header_id = header_cids.block_hash
|
||||||
|
AND state_cids.block_number = header_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN public.blocks ON (
|
||||||
|
state_cids.mh_key = blocks.key
|
||||||
|
AND state_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
WHERE state_leaf_key = $1
|
WHERE state_leaf_key = $1
|
||||||
AND block_number <= $2
|
AND block_number <= $2
|
||||||
ORDER BY block_number DESC
|
ORDER BY block_number DESC
|
||||||
@@ -132,9 +219,16 @@ const (
|
|||||||
INNER JOIN eth.state_cids ON (
|
INNER JOIN eth.state_cids ON (
|
||||||
storage_cids.header_id = state_cids.header_id
|
storage_cids.header_id = state_cids.header_id
|
||||||
AND storage_cids.state_path = state_cids.state_path
|
AND storage_cids.state_path = state_cids.state_path
|
||||||
|
AND storage_cids.block_number = state_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN eth.header_cids ON (
|
||||||
|
state_cids.header_id = header_cids.block_hash
|
||||||
|
AND state_cids.block_number = header_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN public.blocks ON (
|
||||||
|
storage_cids.mh_key = blocks.key
|
||||||
|
AND storage_cids.block_number = blocks.block_number
|
||||||
)
|
)
|
||||||
INNER JOIN eth.header_cids ON (state_cids.header_id = header_cids.block_hash)
|
|
||||||
INNER JOIN public.blocks ON (storage_cids.mh_key = blocks.key)
|
|
||||||
WHERE state_leaf_key = $1
|
WHERE state_leaf_key = $1
|
||||||
AND storage_leaf_key = $2
|
AND storage_leaf_key = $2
|
||||||
AND block_number <= $3
|
AND block_number <= $3
|
||||||
@@ -145,16 +239,23 @@ const (
|
|||||||
INNER JOIN eth.state_cids ON (
|
INNER JOIN eth.state_cids ON (
|
||||||
storage_cids.header_id = state_cids.header_id
|
storage_cids.header_id = state_cids.header_id
|
||||||
AND storage_cids.state_path = state_cids.state_path
|
AND storage_cids.state_path = state_cids.state_path
|
||||||
|
AND storage_cids.block_number = state_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN eth.header_cids ON (
|
||||||
|
state_cids.header_id = header_cids.block_hash
|
||||||
|
AND state_cids.block_number = header_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN public.blocks ON (
|
||||||
|
storage_cids.mh_key = blocks.key
|
||||||
|
AND storage_cids.block_number = blocks.block_number
|
||||||
)
|
)
|
||||||
INNER JOIN eth.header_cids ON (state_cids.header_id = header_cids.block_hash)
|
|
||||||
INNER JOIN public.blocks ON (storage_cids.mh_key = blocks.key)
|
|
||||||
WHERE state_leaf_key = $1
|
WHERE state_leaf_key = $1
|
||||||
AND storage_leaf_key = $2
|
AND storage_leaf_key = $2
|
||||||
AND block_number <= (SELECT block_number
|
AND header_cids.block_number <= (SELECT block_number
|
||||||
FROM eth.header_cids
|
FROM eth.header_cids
|
||||||
WHERE block_hash = $3)
|
WHERE block_hash = $3)
|
||||||
AND header_cids.block_hash = (SELECT canonical_header_hash(block_number))
|
AND header_cids.block_hash = (SELECT canonical_header_hash(header_cids.block_number))
|
||||||
ORDER BY block_number DESC
|
ORDER BY header_cids.block_number DESC
|
||||||
LIMIT 1`
|
LIMIT 1`
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import (
|
|||||||
"github.com/multiformats/go-multihash"
|
"github.com/multiformats/go-multihash"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Test variables
|
// Test variables
|
||||||
@@ -231,40 +231,44 @@ var (
|
|||||||
}
|
}
|
||||||
MockTrxMetaPostPublsh = []models.TxModel{
|
MockTrxMetaPostPublsh = []models.TxModel{
|
||||||
{
|
{
|
||||||
CID: Trx1CID.String(), // This is empty until we go to publish to ipfs
|
BlockNumber: "1",
|
||||||
MhKey: Trx1MhKey,
|
CID: Trx1CID.String(), // This is empty until we go to publish to ipfs
|
||||||
Src: SenderAddr.Hex(),
|
MhKey: Trx1MhKey,
|
||||||
Dst: Address.String(),
|
Src: SenderAddr.Hex(),
|
||||||
Index: 0,
|
Dst: Address.String(),
|
||||||
TxHash: MockTransactions[0].Hash().String(),
|
Index: 0,
|
||||||
Data: []byte{},
|
TxHash: MockTransactions[0].Hash().String(),
|
||||||
|
Data: []byte{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
CID: Trx2CID.String(),
|
BlockNumber: "1",
|
||||||
MhKey: Trx2MhKey,
|
CID: Trx2CID.String(),
|
||||||
Src: SenderAddr.Hex(),
|
MhKey: Trx2MhKey,
|
||||||
Dst: AnotherAddress.String(),
|
Src: SenderAddr.Hex(),
|
||||||
Index: 1,
|
Dst: AnotherAddress.String(),
|
||||||
TxHash: MockTransactions[1].Hash().String(),
|
Index: 1,
|
||||||
Data: []byte{},
|
TxHash: MockTransactions[1].Hash().String(),
|
||||||
|
Data: []byte{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
CID: Trx3CID.String(),
|
BlockNumber: "1",
|
||||||
MhKey: Trx3MhKey,
|
CID: Trx3CID.String(),
|
||||||
Src: SenderAddr.Hex(),
|
MhKey: Trx3MhKey,
|
||||||
Dst: "",
|
Src: SenderAddr.Hex(),
|
||||||
Index: 2,
|
Dst: "",
|
||||||
TxHash: MockTransactions[2].Hash().String(),
|
Index: 2,
|
||||||
Data: MockContractByteCode,
|
TxHash: MockTransactions[2].Hash().String(),
|
||||||
|
Data: MockContractByteCode,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
CID: Trx4CID.String(),
|
BlockNumber: "1",
|
||||||
MhKey: Trx4MhKey,
|
CID: Trx4CID.String(),
|
||||||
Src: SenderAddr.Hex(),
|
MhKey: Trx4MhKey,
|
||||||
Dst: AnotherAddress1.String(),
|
Src: SenderAddr.Hex(),
|
||||||
Index: 3,
|
Dst: AnotherAddress1.String(),
|
||||||
TxHash: MockTransactions[3].Hash().String(),
|
Index: 3,
|
||||||
Data: []byte{},
|
TxHash: MockTransactions[3].Hash().String(),
|
||||||
|
Data: []byte{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
MockRctMeta = []models.ReceiptModel{
|
MockRctMeta = []models.ReceiptModel{
|
||||||
@@ -296,24 +300,28 @@ var (
|
|||||||
|
|
||||||
MockRctMetaPostPublish = []models.ReceiptModel{
|
MockRctMetaPostPublish = []models.ReceiptModel{
|
||||||
{
|
{
|
||||||
|
BlockNumber: "1",
|
||||||
LeafCID: Rct1CID.String(),
|
LeafCID: Rct1CID.String(),
|
||||||
LeafMhKey: Rct1MhKey,
|
LeafMhKey: Rct1MhKey,
|
||||||
Contract: "",
|
Contract: "",
|
||||||
ContractHash: "",
|
ContractHash: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
BlockNumber: "1",
|
||||||
LeafCID: Rct2CID.String(),
|
LeafCID: Rct2CID.String(),
|
||||||
LeafMhKey: Rct2MhKey,
|
LeafMhKey: Rct2MhKey,
|
||||||
Contract: "",
|
Contract: "",
|
||||||
ContractHash: "",
|
ContractHash: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
BlockNumber: "1",
|
||||||
LeafCID: Rct3CID.String(),
|
LeafCID: Rct3CID.String(),
|
||||||
LeafMhKey: Rct3MhKey,
|
LeafMhKey: Rct3MhKey,
|
||||||
Contract: ContractAddress.String(),
|
Contract: ContractAddress.String(),
|
||||||
ContractHash: ContractHash,
|
ContractHash: ContractHash,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
BlockNumber: "1",
|
||||||
LeafCID: Rct4CID.String(),
|
LeafCID: Rct4CID.String(),
|
||||||
LeafMhKey: Rct4MhKey,
|
LeafMhKey: Rct4MhKey,
|
||||||
Contract: "",
|
Contract: "",
|
||||||
@@ -391,18 +399,20 @@ var (
|
|||||||
}
|
}
|
||||||
MockStateMetaPostPublish = []models.StateNodeModel{
|
MockStateMetaPostPublish = []models.StateNodeModel{
|
||||||
{
|
{
|
||||||
CID: State1CID.String(),
|
BlockNumber: "1",
|
||||||
MhKey: State1MhKey,
|
CID: State1CID.String(),
|
||||||
Path: []byte{'\x06'},
|
MhKey: State1MhKey,
|
||||||
NodeType: 2,
|
Path: []byte{'\x06'},
|
||||||
StateKey: common.BytesToHash(ContractLeafKey).Hex(),
|
NodeType: 2,
|
||||||
|
StateKey: common.BytesToHash(ContractLeafKey).Hex(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
CID: State2CID.String(),
|
BlockNumber: "1",
|
||||||
MhKey: State2MhKey,
|
CID: State2CID.String(),
|
||||||
Path: []byte{'\x0c'},
|
MhKey: State2MhKey,
|
||||||
NodeType: 2,
|
Path: []byte{'\x0c'},
|
||||||
StateKey: common.BytesToHash(AccountLeafKey).Hex(),
|
NodeType: 2,
|
||||||
|
StateKey: common.BytesToHash(AccountLeafKey).Hex(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
MockStorageNodes = map[string][]sdtypes.StorageNode{
|
MockStorageNodes = map[string][]sdtypes.StorageNode{
|
||||||
@@ -461,12 +471,13 @@ var (
|
|||||||
StateNodes: MockStateMetaPostPublish,
|
StateNodes: MockStateMetaPostPublish,
|
||||||
StorageNodes: []models.StorageNodeWithStateKeyModel{
|
StorageNodes: []models.StorageNodeWithStateKeyModel{
|
||||||
{
|
{
|
||||||
Path: []byte{},
|
BlockNumber: "1",
|
||||||
CID: StorageCID.String(),
|
Path: []byte{},
|
||||||
MhKey: StorageMhKey,
|
CID: StorageCID.String(),
|
||||||
NodeType: 2,
|
MhKey: StorageMhKey,
|
||||||
StateKey: common.BytesToHash(ContractLeafKey).Hex(),
|
NodeType: 2,
|
||||||
StorageKey: common.BytesToHash(StorageLeafKey).Hex(),
|
StateKey: common.BytesToHash(ContractLeafKey).Hex(),
|
||||||
|
StorageKey: common.BytesToHash(StorageLeafKey).Hex(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -483,43 +494,52 @@ var (
|
|||||||
MockIPLDs = eth.IPLDs{
|
MockIPLDs = eth.IPLDs{
|
||||||
BlockNumber: new(big.Int).Set(BlockNumber),
|
BlockNumber: new(big.Int).Set(BlockNumber),
|
||||||
Header: models.IPLDModel{
|
Header: models.IPLDModel{
|
||||||
Data: HeaderIPLD.RawData(),
|
BlockNumber: BlockNumber.String(),
|
||||||
Key: HeaderIPLD.Cid().String(),
|
Data: HeaderIPLD.RawData(),
|
||||||
|
Key: HeaderIPLD.Cid().String(),
|
||||||
},
|
},
|
||||||
Transactions: []models.IPLDModel{
|
Transactions: []models.IPLDModel{
|
||||||
{
|
{
|
||||||
Data: Trx1IPLD.RawData(),
|
BlockNumber: BlockNumber.String(),
|
||||||
Key: Trx1IPLD.Cid().String(),
|
Data: Trx1IPLD.RawData(),
|
||||||
|
Key: Trx1IPLD.Cid().String(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Data: Trx2IPLD.RawData(),
|
BlockNumber: BlockNumber.String(),
|
||||||
Key: Trx2IPLD.Cid().String(),
|
Data: Trx2IPLD.RawData(),
|
||||||
|
Key: Trx2IPLD.Cid().String(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Data: Trx3IPLD.RawData(),
|
BlockNumber: BlockNumber.String(),
|
||||||
Key: Trx3IPLD.Cid().String(),
|
Data: Trx3IPLD.RawData(),
|
||||||
|
Key: Trx3IPLD.Cid().String(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Data: Trx4IPLD.RawData(),
|
BlockNumber: BlockNumber.String(),
|
||||||
Key: Trx4IPLD.Cid().String(),
|
Data: Trx4IPLD.RawData(),
|
||||||
|
Key: Trx4IPLD.Cid().String(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Receipts: []models.IPLDModel{
|
Receipts: []models.IPLDModel{
|
||||||
{
|
{
|
||||||
Data: Rct1IPLD,
|
BlockNumber: BlockNumber.String(),
|
||||||
Key: Rct1CID.String(),
|
Data: Rct1IPLD,
|
||||||
|
Key: Rct1CID.String(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Data: Rct2IPLD,
|
BlockNumber: BlockNumber.String(),
|
||||||
Key: Rct2CID.String(),
|
Data: Rct2IPLD,
|
||||||
|
Key: Rct2CID.String(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Data: Rct3IPLD,
|
BlockNumber: BlockNumber.String(),
|
||||||
Key: Rct3CID.String(),
|
Data: Rct3IPLD,
|
||||||
|
Key: Rct3CID.String(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Data: Rct4IPLD,
|
BlockNumber: BlockNumber.String(),
|
||||||
Key: Rct4CID.String(),
|
Data: Rct4IPLD,
|
||||||
|
Key: Rct4CID.String(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
StateNodes: []eth.StateNode{
|
StateNodes: []eth.StateNode{
|
||||||
@@ -527,8 +547,9 @@ var (
|
|||||||
StateLeafKey: common.BytesToHash(ContractLeafKey),
|
StateLeafKey: common.BytesToHash(ContractLeafKey),
|
||||||
Type: sdtypes.Leaf,
|
Type: sdtypes.Leaf,
|
||||||
IPLD: models.IPLDModel{
|
IPLD: models.IPLDModel{
|
||||||
Data: State1IPLD.RawData(),
|
BlockNumber: BlockNumber.String(),
|
||||||
Key: State1IPLD.Cid().String(),
|
Data: State1IPLD.RawData(),
|
||||||
|
Key: State1IPLD.Cid().String(),
|
||||||
},
|
},
|
||||||
Path: []byte{'\x06'},
|
Path: []byte{'\x06'},
|
||||||
},
|
},
|
||||||
@@ -536,8 +557,9 @@ var (
|
|||||||
StateLeafKey: common.BytesToHash(AccountLeafKey),
|
StateLeafKey: common.BytesToHash(AccountLeafKey),
|
||||||
Type: sdtypes.Leaf,
|
Type: sdtypes.Leaf,
|
||||||
IPLD: models.IPLDModel{
|
IPLD: models.IPLDModel{
|
||||||
Data: State2IPLD.RawData(),
|
BlockNumber: BlockNumber.String(),
|
||||||
Key: State2IPLD.Cid().String(),
|
Data: State2IPLD.RawData(),
|
||||||
|
Key: State2IPLD.Cid().String(),
|
||||||
},
|
},
|
||||||
Path: []byte{'\x0c'},
|
Path: []byte{'\x0c'},
|
||||||
},
|
},
|
||||||
@@ -548,8 +570,9 @@ var (
|
|||||||
StorageLeafKey: common.BytesToHash(StorageLeafKey),
|
StorageLeafKey: common.BytesToHash(StorageLeafKey),
|
||||||
Type: sdtypes.Leaf,
|
Type: sdtypes.Leaf,
|
||||||
IPLD: models.IPLDModel{
|
IPLD: models.IPLDModel{
|
||||||
Data: StorageIPLD.RawData(),
|
BlockNumber: BlockNumber.String(),
|
||||||
Key: StorageIPLD.Cid().String(),
|
Data: StorageIPLD.RawData(),
|
||||||
|
Key: StorageIPLD.Cid().String(),
|
||||||
},
|
},
|
||||||
Path: []byte{},
|
Path: []byte{},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
// VulcanizeDB
|
||||||
|
// Copyright © 2022 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 fill_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFill(t *testing.T) {
|
||||||
|
RegisterFailHandler(Fail)
|
||||||
|
RunSpecs(t, "ipld eth server fill test suite")
|
||||||
|
}
|
||||||
@@ -0,0 +1,206 @@
|
|||||||
|
// VulcanizeDB
|
||||||
|
// Copyright © 2022 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 fill
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
"github.com/ethereum/go-ethereum/statediff"
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/serve"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WatchedAddress type is used to process currently watched addresses
|
||||||
|
type WatchedAddress struct {
|
||||||
|
Address string `db:"address"`
|
||||||
|
CreatedAt uint64 `db:"created_at"`
|
||||||
|
WatchedAt uint64 `db:"watched_at"`
|
||||||
|
LastFilledAt uint64 `db:"last_filled_at"`
|
||||||
|
|
||||||
|
StartBlock uint64
|
||||||
|
EndBlock uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Service is the underlying struct for the watched address gap filling service
|
||||||
|
type Service struct {
|
||||||
|
db *sqlx.DB
|
||||||
|
client *rpc.Client
|
||||||
|
interval int
|
||||||
|
quitChan chan bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewServer creates a new Service
|
||||||
|
func New(config *serve.Config) *Service {
|
||||||
|
return &Service{
|
||||||
|
db: config.DB,
|
||||||
|
client: config.Client,
|
||||||
|
interval: config.WatchedAddressGapFillInterval,
|
||||||
|
quitChan: make(chan bool),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start is used to begin the service
|
||||||
|
func (s *Service) Start(wg *sync.WaitGroup) {
|
||||||
|
defer wg.Done()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-s.quitChan:
|
||||||
|
log.Info("quiting eth ipld server process")
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
s.fill()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop is used to gracefully stop the service
|
||||||
|
func (s *Service) Stop() {
|
||||||
|
log.Info("stopping watched address gap filler")
|
||||||
|
close(s.quitChan)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill performs the filling of indexing gap for watched addresses
|
||||||
|
func (s *Service) fill() {
|
||||||
|
// Wait for specified interval duration
|
||||||
|
time.Sleep(time.Duration(s.interval) * time.Second)
|
||||||
|
|
||||||
|
// Get watched addresses from the db
|
||||||
|
rows := s.fetchWatchedAddresses()
|
||||||
|
|
||||||
|
// Get the block number to start fill at
|
||||||
|
// Get the block number to end fill at
|
||||||
|
fillWatchedAddresses, minStartBlock, maxEndBlock := s.GetFillAddresses(rows)
|
||||||
|
|
||||||
|
if len(fillWatchedAddresses) > 0 {
|
||||||
|
log.Infof("running watched address gap filler for block range: (%d, %d)", minStartBlock, maxEndBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill the missing diffs
|
||||||
|
for blockNumber := minStartBlock; blockNumber <= maxEndBlock; blockNumber++ {
|
||||||
|
params := statediff.Params{
|
||||||
|
IntermediateStateNodes: true,
|
||||||
|
IntermediateStorageNodes: true,
|
||||||
|
IncludeBlock: true,
|
||||||
|
IncludeReceipts: true,
|
||||||
|
IncludeTD: true,
|
||||||
|
IncludeCode: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
fillAddresses := []interface{}{}
|
||||||
|
for _, fillWatchedAddress := range fillWatchedAddresses {
|
||||||
|
if blockNumber >= fillWatchedAddress.StartBlock && blockNumber <= fillWatchedAddress.EndBlock {
|
||||||
|
params.WatchedAddresses = append(params.WatchedAddresses, common.HexToAddress(fillWatchedAddress.Address))
|
||||||
|
fillAddresses = append(fillAddresses, fillWatchedAddress.Address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(fillAddresses) > 0 {
|
||||||
|
s.writeStateDiffAt(blockNumber, params)
|
||||||
|
s.UpdateLastFilledAt(blockNumber, fillAddresses)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFillAddresses finds the encompassing range to perform fill for the given watched addresses
|
||||||
|
// it also sets the address specific fill range
|
||||||
|
func (s *Service) GetFillAddresses(rows []WatchedAddress) ([]WatchedAddress, uint64, uint64) {
|
||||||
|
fillWatchedAddresses := []WatchedAddress{}
|
||||||
|
minStartBlock := uint64(math.MaxUint64)
|
||||||
|
maxEndBlock := uint64(0)
|
||||||
|
|
||||||
|
for _, row := range rows {
|
||||||
|
// Check for a gap between created_at and watched_at
|
||||||
|
// CreatedAt and WatchedAt being equal is considered a gap of one block
|
||||||
|
if row.CreatedAt > row.WatchedAt {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
startBlock := uint64(0)
|
||||||
|
endBlock := uint64(0)
|
||||||
|
|
||||||
|
// Check if some of the gap was filled earlier
|
||||||
|
if row.LastFilledAt > 0 {
|
||||||
|
if row.LastFilledAt < row.WatchedAt {
|
||||||
|
startBlock = row.LastFilledAt + 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
startBlock = row.CreatedAt
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the address for filling
|
||||||
|
if startBlock > 0 {
|
||||||
|
row.StartBlock = startBlock
|
||||||
|
if startBlock < minStartBlock {
|
||||||
|
minStartBlock = startBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
endBlock = row.WatchedAt
|
||||||
|
row.EndBlock = endBlock
|
||||||
|
if endBlock > maxEndBlock {
|
||||||
|
maxEndBlock = endBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
fillWatchedAddresses = append(fillWatchedAddresses, row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fillWatchedAddresses, minStartBlock, maxEndBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateLastFilledAt updates the fill status for the provided addresses in the db
|
||||||
|
func (s *Service) UpdateLastFilledAt(blockNumber uint64, fillAddresses []interface{}) {
|
||||||
|
// Prepare the query
|
||||||
|
query := "UPDATE eth_meta.watched_addresses SET last_filled_at=? WHERE address IN (?" + strings.Repeat(",?", len(fillAddresses)-1) + ")"
|
||||||
|
query = s.db.Rebind(query)
|
||||||
|
|
||||||
|
args := []interface{}{blockNumber}
|
||||||
|
args = append(args, fillAddresses...)
|
||||||
|
|
||||||
|
// Execute the update query
|
||||||
|
_, err := s.db.Exec(query, args...)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetchWatchedAddresses fetches watched addresses from the db
|
||||||
|
func (s *Service) fetchWatchedAddresses() []WatchedAddress {
|
||||||
|
rows := []WatchedAddress{}
|
||||||
|
pgStr := "SELECT * FROM eth_meta.watched_addresses"
|
||||||
|
|
||||||
|
err := s.db.Select(&rows, pgStr)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error fetching watched addreesses: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return rows
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeStateDiffAt makes a RPC call to writeout statediffs at a blocknumber with the given params
|
||||||
|
func (s *Service) writeStateDiffAt(blockNumber uint64, params statediff.Params) {
|
||||||
|
err := s.client.Call(nil, "statediff_writeStateDiffAt", blockNumber, params)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error making a RPC call to write statediff at block number %d: %s", blockNumber, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,411 @@
|
|||||||
|
// VulcanizeDB
|
||||||
|
// Copyright © 2022 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 fill_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/ethereum/go-ethereum/statediff/indexer/interfaces"
|
||||||
|
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
|
||||||
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth/test_helpers"
|
||||||
|
fill "github.com/vulcanize/ipld-eth-server/v4/pkg/fill"
|
||||||
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/serve"
|
||||||
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/shared"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Service", func() {
|
||||||
|
|
||||||
|
var (
|
||||||
|
db *sqlx.DB
|
||||||
|
watchedAddressGapFiller *fill.Service
|
||||||
|
statediffIndexer interfaces.StateDiffIndexer
|
||||||
|
err error
|
||||||
|
|
||||||
|
contract1Address = "0x5d663F5269090bD2A7DC2390c911dF6083D7b28F"
|
||||||
|
contract2Address = "0x6Eb7e5C66DB8af2E96159AC440cbc8CDB7fbD26B"
|
||||||
|
contract3Address = "0xcfeB164C328CA13EFd3C77E1980d94975aDfedfc"
|
||||||
|
|
||||||
|
chainConfig = params.TestChainConfig
|
||||||
|
ctx = context.Background()
|
||||||
|
)
|
||||||
|
|
||||||
|
It("test init", func() {
|
||||||
|
// db initialization
|
||||||
|
db = shared.SetupDB()
|
||||||
|
|
||||||
|
// indexer initialization
|
||||||
|
// statediffIndexer, err = indexer.NewStateDiffIndexer(nil, db)
|
||||||
|
statediffIndexer = shared.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash())
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// fill service intialization
|
||||||
|
watchedAddressGapFiller = fill.New(&serve.Config{
|
||||||
|
DB: db,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
defer It("test teardown", func() {
|
||||||
|
shared.TearDownDB(db)
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("GetFillAddresses", func() {
|
||||||
|
Context("overlapping fill ranges", func() {
|
||||||
|
It("gives the range to run fill for each address", func() {
|
||||||
|
// input data
|
||||||
|
rows := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: 50,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract2Address,
|
||||||
|
CreatedAt: 40,
|
||||||
|
WatchedAt: 70,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract3Address,
|
||||||
|
CreatedAt: 20,
|
||||||
|
WatchedAt: 30,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// expected output data
|
||||||
|
expectedOutputAddresses := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: 50,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
StartBlock: 10,
|
||||||
|
EndBlock: 50,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract2Address,
|
||||||
|
CreatedAt: 40,
|
||||||
|
WatchedAt: 70,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
StartBlock: 40,
|
||||||
|
EndBlock: 70,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract3Address,
|
||||||
|
CreatedAt: 20,
|
||||||
|
WatchedAt: 30,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
StartBlock: 20,
|
||||||
|
EndBlock: 30,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
expectedOutputStartBlock := uint64(10)
|
||||||
|
expectedOutputEndBlock := uint64(70)
|
||||||
|
|
||||||
|
fillWatchedAddresses, minStartBlock, maxEndBlock := watchedAddressGapFiller.GetFillAddresses(rows)
|
||||||
|
|
||||||
|
Expect(fillWatchedAddresses).To(Equal(expectedOutputAddresses))
|
||||||
|
Expect(minStartBlock).To(Equal(expectedOutputStartBlock))
|
||||||
|
Expect(maxEndBlock).To(Equal(expectedOutputEndBlock))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("non-overlapping fill ranges", func() {
|
||||||
|
It("gives the range to run fill for each address", func() {
|
||||||
|
// input data
|
||||||
|
rows := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: 50,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract2Address,
|
||||||
|
CreatedAt: 70,
|
||||||
|
WatchedAt: 90,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// expected output data
|
||||||
|
expectedOutputAddresses := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: 50,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
StartBlock: 10,
|
||||||
|
EndBlock: 50,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract2Address,
|
||||||
|
CreatedAt: 70,
|
||||||
|
WatchedAt: 90,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
StartBlock: 70,
|
||||||
|
EndBlock: 90,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
expectedOutputStartBlock := uint64(10)
|
||||||
|
expectedOutputEndBlock := uint64(90)
|
||||||
|
|
||||||
|
fillWatchedAddresses, minStartBlock, maxEndBlock := watchedAddressGapFiller.GetFillAddresses(rows)
|
||||||
|
|
||||||
|
Expect(fillWatchedAddresses).To(Equal(expectedOutputAddresses))
|
||||||
|
Expect(minStartBlock).To(Equal(expectedOutputStartBlock))
|
||||||
|
Expect(maxEndBlock).To(Equal(expectedOutputEndBlock))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("a contract watched before it was created", func() {
|
||||||
|
It("gives no range for an address when it is watched before it's created", func() {
|
||||||
|
// input data
|
||||||
|
rows := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: 50,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract2Address,
|
||||||
|
CreatedAt: 90,
|
||||||
|
WatchedAt: 70,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// expected output data
|
||||||
|
expectedOutputAddresses := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: 50,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
StartBlock: 10,
|
||||||
|
EndBlock: 50,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
expectedOutputStartBlock := uint64(10)
|
||||||
|
expectedOutputEndBlock := uint64(50)
|
||||||
|
|
||||||
|
fillWatchedAddresses, minStartBlock, maxEndBlock := watchedAddressGapFiller.GetFillAddresses(rows)
|
||||||
|
|
||||||
|
Expect(fillWatchedAddresses).To(Equal(expectedOutputAddresses))
|
||||||
|
Expect(minStartBlock).To(Equal(expectedOutputStartBlock))
|
||||||
|
Expect(maxEndBlock).To(Equal(expectedOutputEndBlock))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("a contract having some of the gap filled earlier", func() {
|
||||||
|
It("gives the remaining range for an address to run fill for", func() {
|
||||||
|
// input data
|
||||||
|
rows := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: 50,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract2Address,
|
||||||
|
CreatedAt: 40,
|
||||||
|
WatchedAt: 70,
|
||||||
|
LastFilledAt: 50,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// expected output data
|
||||||
|
expectedOutputAddresses := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: 50,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
StartBlock: 10,
|
||||||
|
EndBlock: 50,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract2Address,
|
||||||
|
CreatedAt: 40,
|
||||||
|
WatchedAt: 70,
|
||||||
|
LastFilledAt: 50,
|
||||||
|
StartBlock: 51,
|
||||||
|
EndBlock: 70,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
expectedOutputStartBlock := uint64(10)
|
||||||
|
expectedOutputEndBlock := uint64(70)
|
||||||
|
|
||||||
|
fillWatchedAddresses, minStartBlock, maxEndBlock := watchedAddressGapFiller.GetFillAddresses(rows)
|
||||||
|
|
||||||
|
Expect(fillWatchedAddresses).To(Equal(expectedOutputAddresses))
|
||||||
|
Expect(minStartBlock).To(Equal(expectedOutputStartBlock))
|
||||||
|
Expect(maxEndBlock).To(Equal(expectedOutputEndBlock))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("gives no range for an address when the gap is already filled", func() {
|
||||||
|
// input data
|
||||||
|
rows := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: 50,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract2Address,
|
||||||
|
CreatedAt: 40,
|
||||||
|
WatchedAt: 70,
|
||||||
|
LastFilledAt: 70,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// expected output data
|
||||||
|
expectedOutputAddresses := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: 50,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
StartBlock: 10,
|
||||||
|
EndBlock: 50,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
expectedOutputStartBlock := uint64(10)
|
||||||
|
expectedOutputEndBlock := uint64(50)
|
||||||
|
|
||||||
|
fillWatchedAddresses, minStartBlock, maxEndBlock := watchedAddressGapFiller.GetFillAddresses(rows)
|
||||||
|
|
||||||
|
Expect(fillWatchedAddresses).To(Equal(expectedOutputAddresses))
|
||||||
|
Expect(minStartBlock).To(Equal(expectedOutputStartBlock))
|
||||||
|
Expect(maxEndBlock).To(Equal(expectedOutputEndBlock))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("UpdateLastFilledAt", func() {
|
||||||
|
pgStr := "SELECT * FROM eth_meta.watched_addresses"
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
shared.TearDownDB(db)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("updates last filled at for a single address", func() {
|
||||||
|
// fill db with watched addresses
|
||||||
|
watchedAddresses := []sdtypes.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
watchedAt := uint64(50)
|
||||||
|
err = statediffIndexer.InsertWatchedAddresses(watchedAddresses, big.NewInt(int64(watchedAt)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// update last filled at block in the db
|
||||||
|
fillAddresses := []interface{}{
|
||||||
|
contract1Address,
|
||||||
|
}
|
||||||
|
fillAt := uint64(12)
|
||||||
|
watchedAddressGapFiller.UpdateLastFilledAt(fillAt, fillAddresses)
|
||||||
|
|
||||||
|
// expected data
|
||||||
|
expectedData := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: watchedAt,
|
||||||
|
LastFilledAt: fillAt,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
rows := []fill.WatchedAddress{}
|
||||||
|
err = db.Select(&rows, pgStr)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(rows).To(Equal(expectedData))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("updates last filled at for multiple address", func() {
|
||||||
|
// fill db with watched addresses
|
||||||
|
watchedAddresses := []sdtypes.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract2Address,
|
||||||
|
CreatedAt: 20,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract3Address,
|
||||||
|
CreatedAt: 30,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
watchedAt := uint64(50)
|
||||||
|
err = statediffIndexer.InsertWatchedAddresses(watchedAddresses, big.NewInt(int64(watchedAt)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// update last filled at block in the db
|
||||||
|
fillAddresses := []interface{}{
|
||||||
|
contract1Address,
|
||||||
|
contract2Address,
|
||||||
|
contract3Address,
|
||||||
|
}
|
||||||
|
fillAt := uint64(50)
|
||||||
|
watchedAddressGapFiller.UpdateLastFilledAt(fillAt, fillAddresses)
|
||||||
|
|
||||||
|
// expected data
|
||||||
|
expectedData := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: watchedAt,
|
||||||
|
LastFilledAt: fillAt,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract2Address,
|
||||||
|
CreatedAt: 20,
|
||||||
|
WatchedAt: watchedAt,
|
||||||
|
LastFilledAt: fillAt,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract3Address,
|
||||||
|
CreatedAt: 30,
|
||||||
|
WatchedAt: watchedAt,
|
||||||
|
LastFilledAt: fillAt,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
rows := []fill.WatchedAddress{}
|
||||||
|
err = db.Select(&rows, pgStr)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(rows).To(Equal(expectedData))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -33,7 +33,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -35,11 +35,11 @@ import (
|
|||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth/test_helpers"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth/test_helpers"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/graphql"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/graphql"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/shared"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/shared"
|
||||||
ethServerShared "github.com/vulcanize/ipld-eth-server/v3/pkg/shared"
|
ethServerShared "github.com/vulcanize/ipld-eth-server/v4/pkg/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("GraphQL", func() {
|
var _ = Describe("GraphQL", func() {
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import (
|
|||||||
"github.com/graph-gophers/graphql-go/relay"
|
"github.com/graph-gophers/graphql-go/relay"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Service encapsulates a GraphQL service.
|
// Service encapsulates a GraphQL service.
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ import (
|
|||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/net"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("API", func() {
|
var _ = Describe("API", func() {
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/p2p/netutil"
|
"github.com/ethereum/go-ethereum/p2p/netutil"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/prom"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/prom"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/prom"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/prom"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StartWSEndpoint starts a websocket endpoint.
|
// StartWSEndpoint starts a websocket endpoint.
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/statediff/types"
|
"github.com/ethereum/go-ethereum/statediff/types"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth"
|
||||||
)
|
)
|
||||||
|
|
||||||
// APIName is the namespace used for the state diffing service API
|
// APIName is the namespace used for the state diffing service API
|
||||||
|
|||||||
+18
-2
@@ -32,8 +32,8 @@ import (
|
|||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/prom"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/prom"
|
||||||
ethServerShared "github.com/vulcanize/ipld-eth-server/v3/pkg/shared"
|
ethServerShared "github.com/vulcanize/ipld-eth-server/v4/pkg/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Env variables
|
// Env variables
|
||||||
@@ -55,6 +55,9 @@ const (
|
|||||||
|
|
||||||
VALIDATOR_ENABLED = "VALIDATOR_ENABLED"
|
VALIDATOR_ENABLED = "VALIDATOR_ENABLED"
|
||||||
VALIDATOR_EVERY_NTH_BLOCK = "VALIDATOR_EVERY_NTH_BLOCK"
|
VALIDATOR_EVERY_NTH_BLOCK = "VALIDATOR_EVERY_NTH_BLOCK"
|
||||||
|
|
||||||
|
WATCHED_ADDRESS_GAP_FILLER_ENABLED = "WATCHED_ADDRESS_GAP_FILLER_ENABLED"
|
||||||
|
WATCHED_ADDRESS_GAP_FILLER_INTERVAL = "WATCHED_ADDRESS_GAP_FILLER_INTERVAL"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config struct
|
// Config struct
|
||||||
@@ -95,6 +98,9 @@ type Config struct {
|
|||||||
|
|
||||||
StateValidationEnabled bool
|
StateValidationEnabled bool
|
||||||
StateValidationEveryNthBlock uint64
|
StateValidationEveryNthBlock uint64
|
||||||
|
|
||||||
|
WatchedAddressGapFillerEnabled bool
|
||||||
|
WatchedAddressGapFillInterval int
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConfig is used to initialize a watcher config from a .toml file
|
// NewConfig is used to initialize a watcher config from a .toml file
|
||||||
@@ -231,6 +237,8 @@ func NewConfig() (*Config, error) {
|
|||||||
|
|
||||||
c.loadValidatorConfig()
|
c.loadValidatorConfig()
|
||||||
|
|
||||||
|
c.loadWatchedAddressGapFillerConfig()
|
||||||
|
|
||||||
return c, err
|
return c, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,3 +301,11 @@ func (c *Config) loadValidatorConfig() {
|
|||||||
c.StateValidationEnabled = viper.GetBool("validator.enabled")
|
c.StateValidationEnabled = viper.GetBool("validator.enabled")
|
||||||
c.StateValidationEveryNthBlock = viper.GetUint64("validator.everyNthBlock")
|
c.StateValidationEveryNthBlock = viper.GetUint64("validator.everyNthBlock")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Config) loadWatchedAddressGapFillerConfig() {
|
||||||
|
viper.BindEnv("watch.fill.enabled", WATCHED_ADDRESS_GAP_FILLER_ENABLED)
|
||||||
|
viper.BindEnv("watch.fill.interval", WATCHED_ADDRESS_GAP_FILLER_INTERVAL)
|
||||||
|
|
||||||
|
c.WatchedAddressGapFillerEnabled = viper.GetBool("watch.fill.enabled")
|
||||||
|
c.WatchedAddressGapFillInterval = viper.GetInt("watch.fill.interval")
|
||||||
|
}
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ import (
|
|||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth"
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/net"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
+4
-38
@@ -18,11 +18,9 @@ package shared
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/statediff/indexer/ipld"
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||||
dshelp "github.com/ipfs/go-ipfs-ds-help"
|
dshelp "github.com/ipfs/go-ipfs-ds-help"
|
||||||
node "github.com/ipfs/go-ipld-format"
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@@ -50,31 +48,11 @@ func Rollback(tx *sqlx.Tx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PublishIPLD is used to insert an ipld into Postgres blockstore with the provided tx
|
// FetchIPLDByMhKeyAndBlockNumber is used to retrieve an ipld from Postgres blockstore with the provided tx, mhkey string and blockNumber
|
||||||
func PublishIPLD(tx *sqlx.Tx, i node.Node) error {
|
func FetchIPLDByMhKeyAndBlockNumber(tx *sqlx.Tx, mhKey string, blockNumber uint64) ([]byte, error) {
|
||||||
dbKey := dshelp.MultihashToDsKey(i.Cid().Hash())
|
pgStr := `SELECT data FROM public.blocks WHERE key = $1 AND block_number = $2`
|
||||||
prefixedKey := blockstore.BlockPrefix.String() + dbKey.String()
|
|
||||||
raw := i.RawData()
|
|
||||||
_, err := tx.Exec(`INSERT INTO public.blocks (key, data) VALUES ($1, $2) ON CONFLICT (key) DO NOTHING`, prefixedKey, raw)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// FetchIPLD is used to retrieve an ipld from Postgres blockstore with the provided tx and cid string
|
|
||||||
func FetchIPLD(tx *sqlx.Tx, cid string) ([]byte, error) {
|
|
||||||
mhKey, err := MultihashKeyFromCIDString(cid)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pgStr := `SELECT data FROM public.blocks WHERE key = $1`
|
|
||||||
var block []byte
|
var block []byte
|
||||||
return block, tx.Get(&block, pgStr, mhKey)
|
return block, tx.Get(&block, pgStr, mhKey, blockNumber)
|
||||||
}
|
|
||||||
|
|
||||||
// FetchIPLDByMhKey is used to retrieve an ipld from Postgres blockstore with the provided tx and mhkey string
|
|
||||||
func FetchIPLDByMhKey(tx *sqlx.Tx, mhKey string) ([]byte, error) {
|
|
||||||
pgStr := `SELECT data FROM public.blocks WHERE key = $1`
|
|
||||||
var block []byte
|
|
||||||
return block, tx.Get(&block, pgStr, mhKey)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MultihashKeyFromCID converts a cid into a blockstore-prefixed multihash db key string
|
// MultihashKeyFromCID converts a cid into a blockstore-prefixed multihash db key string
|
||||||
@@ -92,15 +70,3 @@ func MultihashKeyFromCIDString(c string) (string, error) {
|
|||||||
dbKey := dshelp.MultihashToDsKey(dc.Hash())
|
dbKey := dshelp.MultihashToDsKey(dc.Hash())
|
||||||
return blockstore.BlockPrefix.String() + dbKey.String(), nil
|
return blockstore.BlockPrefix.String() + dbKey.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PublishRaw derives a cid from raw bytes and provided codec and multihash type, and writes it to the db tx
|
|
||||||
func PublishRaw(tx *sqlx.Tx, codec, mh uint64, raw []byte) (string, error) {
|
|
||||||
c, err := ipld.RawdataToCid(codec, raw, mh)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
dbKey := dshelp.MultihashToDsKey(c.Hash())
|
|
||||||
prefixedKey := blockstore.BlockPrefix.String() + dbKey.String()
|
|
||||||
_, err = tx.Exec(`INSERT INTO public.blocks (key, data) VALUES ($1, $2) ON CONFLICT (key) DO NOTHING`, prefixedKey, raw)
|
|
||||||
return c.String(), err
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -58,8 +58,12 @@ func SetupDB() *sqlx.DB {
|
|||||||
func TearDownDB(db *sqlx.DB) {
|
func TearDownDB(db *sqlx.DB) {
|
||||||
tx, err := db.Beginx()
|
tx, err := db.Beginx()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
_, err = tx.Exec(`DELETE FROM nodes`)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
_, err = tx.Exec(`DELETE FROM eth.header_cids`)
|
_, err = tx.Exec(`DELETE FROM eth.header_cids`)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
_, err = tx.Exec(`DELETE FROM eth.uncle_cids`)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
_, err = tx.Exec(`DELETE FROM eth.transaction_cids`)
|
_, err = tx.Exec(`DELETE FROM eth.transaction_cids`)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
_, err = tx.Exec(`DELETE FROM eth.receipt_cids`)
|
_, err = tx.Exec(`DELETE FROM eth.receipt_cids`)
|
||||||
@@ -68,6 +72,10 @@ func TearDownDB(db *sqlx.DB) {
|
|||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
_, err = tx.Exec(`DELETE FROM eth.storage_cids`)
|
_, err = tx.Exec(`DELETE FROM eth.storage_cids`)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
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`)
|
_, err = tx.Exec(`DELETE FROM blocks`)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
_, err = tx.Exec(`DELETE FROM eth.log_cids`)
|
_, err = tx.Exec(`DELETE FROM eth.log_cids`)
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ set -o xtrace
|
|||||||
export ETH_FORWARD_ETH_CALLS=false
|
export ETH_FORWARD_ETH_CALLS=false
|
||||||
export DB_WRITE=true
|
export DB_WRITE=true
|
||||||
export ETH_PROXY_ON_ERROR=false
|
export ETH_PROXY_ON_ERROR=false
|
||||||
|
export WATCHED_ADDRESS_GAP_FILLER_ENABLED=false
|
||||||
|
export WATCHED_ADDRESS_GAP_FILLER_INTERVAL=5
|
||||||
|
|
||||||
export PGPASSWORD=password
|
export PGPASSWORD=password
|
||||||
export DATABASE_USER=vdbm
|
export DATABASE_USER=vdbm
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ set -o xtrace
|
|||||||
export ETH_FORWARD_ETH_CALLS=true
|
export ETH_FORWARD_ETH_CALLS=true
|
||||||
export DB_WRITE=false
|
export DB_WRITE=false
|
||||||
export ETH_PROXY_ON_ERROR=false
|
export ETH_PROXY_ON_ERROR=false
|
||||||
|
export WATCHED_ADDRESS_GAP_FILLER_ENABLED=false
|
||||||
|
export WATCHED_ADDRESS_GAP_FILLER_INTERVAL=5
|
||||||
|
|
||||||
export PGPASSWORD=password
|
export PGPASSWORD=password
|
||||||
export DATABASE_USER=vdbm
|
export DATABASE_USER=vdbm
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
set -e
|
||||||
|
set -o xtrace
|
||||||
|
|
||||||
|
export ETH_FORWARD_ETH_CALLS=false
|
||||||
|
export DB_WRITE=true
|
||||||
|
export ETH_PROXY_ON_ERROR=false
|
||||||
|
export WATCHED_ADDRESS_GAP_FILLER_ENABLED=true
|
||||||
|
export WATCHED_ADDRESS_GAP_FILLER_INTERVAL=5
|
||||||
|
|
||||||
|
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
|
||||||
@@ -1,8 +1,26 @@
|
|||||||
# Clear up existing docker images and volume.
|
#!/bin/bash
|
||||||
docker-compose down --remove-orphans --volumes
|
|
||||||
|
|
||||||
docker-compose -f docker-compose.yml up -d ipld-eth-db
|
set -e
|
||||||
sleep 10
|
|
||||||
PGPASSWORD=password DATABASE_USER=vdbm DATABASE_PORT=8077 DATABASE_PASSWORD=password DATABASE_HOSTNAME=127.0.0.1 DATABASE_NAME=vulcanize_testing make test
|
|
||||||
|
|
||||||
docker-compose down --remove-orphans --volumes
|
mkdir -p out
|
||||||
|
|
||||||
|
# Remove existing docker-tsdb directory
|
||||||
|
rm -rf out/docker-tsdb/
|
||||||
|
|
||||||
|
# Copy over files to setup TimescaleDB
|
||||||
|
ID=$(docker create vulcanize/ipld-eth-db:v4.1.1-alpha)
|
||||||
|
docker cp $ID:/app/docker-tsdb out/docker-tsdb/
|
||||||
|
docker rm -v $ID
|
||||||
|
|
||||||
|
# Spin up TimescaleDB
|
||||||
|
docker-compose -f out/docker-tsdb/docker-compose.test.yml -f docker-compose.yml up ipld-eth-db
|
||||||
|
trap "docker-compose -f out/docker-tsdb/docker-compose.test.yml -f docker-compose.yml down --remove-orphans --volumes; rm -rf out/" SIGINT SIGTERM ERR
|
||||||
|
sleep 45
|
||||||
|
|
||||||
|
# Run unit tests
|
||||||
|
go clean -testcache
|
||||||
|
PGPASSWORD=password DATABASE_USER=vdbm DATABASE_PORT=8066 DATABASE_PASSWORD=password DATABASE_HOSTNAME=127.0.0.1 DATABASE_NAME=vulcanize_testing_v4 make test
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
docker-compose -f out/docker-tsdb/docker-compose.test.yml -f docker-compose.yml down --remove-orphans --volumes
|
||||||
|
rm -rf out/
|
||||||
|
|||||||
+55
-6
@@ -4,16 +4,16 @@
|
|||||||
|
|
||||||
- Clone [stack-orchestrator](https://github.com/vulcanize/stack-orchestrator) and [go-ethereum](https://github.com/vulcanize/go-ethereum) repositories.
|
- Clone [stack-orchestrator](https://github.com/vulcanize/stack-orchestrator) and [go-ethereum](https://github.com/vulcanize/go-ethereum) repositories.
|
||||||
|
|
||||||
- Checkout [v3 release](https://github.com/vulcanize/go-ethereum/releases/tag/v1.10.17-statediff-3.2.1) in go-ethereum repo.
|
- Checkout [v4 release](https://github.com/vulcanize/go-ethereum/releases/tag/v1.10.17-statediff-4.0.1-alpha) in go-ethereum repo.
|
||||||
```bash
|
```bash
|
||||||
# In go-ethereum repo.
|
# In go-ethereum repo.
|
||||||
git checkout v1.10.17-statediff-3.2.1
|
git checkout v1.10.17-statediff-4.0.1-alpha
|
||||||
```
|
```
|
||||||
|
|
||||||
- Checkout working commit in stack-orchestrator repo.
|
- Checkout working commit in stack-orchestrator repo.
|
||||||
```bash
|
```bash
|
||||||
# In stack-orchestrator repo.
|
# In stack-orchestrator repo.
|
||||||
git checkout fcbc74451c5494664fe21f765e89c9c6565c07cb
|
git checkout 35c677433aee5fafdf74eb3c251a453691b818d0
|
||||||
```
|
```
|
||||||
|
|
||||||
## Run
|
## Run
|
||||||
@@ -27,7 +27,18 @@
|
|||||||
|
|
||||||
- Run integration tests:
|
- Run integration tests:
|
||||||
|
|
||||||
- Update (Replace existing content) config file [config.sh](https://github.com/vulcanize/stack-orchestrator/blob/main/config.sh) in stack-orchestrator repo:
|
- 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
|
```bash
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
@@ -37,13 +48,17 @@
|
|||||||
# Path to ipld-eth-server repo.
|
# Path to ipld-eth-server repo.
|
||||||
vulcanize_ipld_eth_server=~/ipld-eth-server/
|
vulcanize_ipld_eth_server=~/ipld-eth-server/
|
||||||
|
|
||||||
|
# Path to test contract.
|
||||||
|
vulcanize_test_contract=~/ipld-eth-server/test/contract
|
||||||
|
|
||||||
db_write=true
|
db_write=true
|
||||||
eth_forward_eth_calls=false
|
eth_forward_eth_calls=false
|
||||||
eth_proxy_on_error=false
|
eth_proxy_on_error=false
|
||||||
eth_http_path="go-ethereum:8545"
|
eth_http_path="go-ethereum:8545"
|
||||||
```
|
```
|
||||||
|
|
||||||
- Run stack-orchestrator:
|
- Run stack-orchestrator:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# In stack-orchestrator root directory.
|
# In stack-orchestrator root directory.
|
||||||
cd helper-scripts
|
cd helper-scripts
|
||||||
@@ -53,17 +68,20 @@
|
|||||||
-d ../docker/latest/docker-compose-db.yml \
|
-d ../docker/latest/docker-compose-db.yml \
|
||||||
-d ../docker/local/docker-compose-go-ethereum.yml \
|
-d ../docker/local/docker-compose-go-ethereum.yml \
|
||||||
-d ../docker/local/docker-compose-ipld-eth-server.yml \
|
-d ../docker/local/docker-compose-ipld-eth-server.yml \
|
||||||
|
-d ../docker/local/docker-compose-contract.yml \
|
||||||
-v remove \
|
-v remove \
|
||||||
-p ../config.sh
|
-p ../config.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
- Run test:
|
- Run test:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# In ipld-eth-server root directory.
|
# In ipld-eth-server root directory.
|
||||||
./scripts/run_integration_test.sh
|
./scripts/run_integration_test.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
- Update `config.sh` file:
|
- Update stack-orchestrator `config.sh` file:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
@@ -73,6 +91,9 @@
|
|||||||
# Path to ipld-eth-server repo.
|
# Path to ipld-eth-server repo.
|
||||||
vulcanize_ipld_eth_server=~/ipld-eth-server/
|
vulcanize_ipld_eth_server=~/ipld-eth-server/
|
||||||
|
|
||||||
|
# Path to test contract.
|
||||||
|
vulcanize_test_contract=~/ipld-eth-server/test/contract
|
||||||
|
|
||||||
db_write=false
|
db_write=false
|
||||||
eth_forward_eth_calls=true
|
eth_forward_eth_calls=true
|
||||||
eth_proxy_on_error=false
|
eth_proxy_on_error=false
|
||||||
@@ -85,3 +106,31 @@
|
|||||||
```bash
|
```bash
|
||||||
./scripts/run_integration_test_forward_eth_calls.sh
|
./scripts/run_integration_test_forward_eth_calls.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
|
||||||
|
|
||||||
|
db_write=true
|
||||||
|
eth_forward_eth_calls=false
|
||||||
|
eth_proxy_on_error=false
|
||||||
|
eth_http_path="go-ethereum:8545"
|
||||||
|
watched_addres_gap_filler_enabled=true
|
||||||
|
watched_addres_gap_filler_interval=5
|
||||||
|
```
|
||||||
|
|
||||||
|
- Stop the stack-orchestrator and start again using the same command
|
||||||
|
|
||||||
|
- Run integration tests for watched addresses with gap filling service enabled:
|
||||||
|
```bash
|
||||||
|
./scripts/run_integration_test_watched_address_gap_filler.sh
|
||||||
|
```
|
||||||
|
|||||||
@@ -13,13 +13,15 @@ import (
|
|||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth"
|
||||||
integration "github.com/vulcanize/ipld-eth-server/v3/test"
|
integration "github.com/vulcanize/ipld-eth-server/v4/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("Integration test", func() {
|
var _ = Describe("Integration test", func() {
|
||||||
directProxyEthCalls, err := strconv.ParseBool(os.Getenv("ETH_FORWARD_ETH_CALLS"))
|
directProxyEthCalls, err := strconv.ParseBool(os.Getenv("ETH_FORWARD_ETH_CALLS"))
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
watchedAddressServiceEnabled, err := strconv.ParseBool(os.Getenv("WATCHED_ADDRESS_GAP_FILLER_ENABLED"))
|
||||||
|
Expect(err).To(BeNil())
|
||||||
gethHttpPath := "http://127.0.0.1:8545"
|
gethHttpPath := "http://127.0.0.1:8545"
|
||||||
gethClient, err := ethclient.Dial(gethHttpPath)
|
gethClient, err := ethclient.Dial(gethHttpPath)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
@@ -39,7 +41,7 @@ var _ = Describe("Integration test", func() {
|
|||||||
sleepInterval := 2 * time.Second
|
sleepInterval := 2 * time.Second
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
if !directProxyEthCalls {
|
if !directProxyEthCalls || watchedAddressServiceEnabled {
|
||||||
Skip("skipping direct-proxy-forwarding integration tests")
|
Skip("skipping direct-proxy-forwarding integration tests")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ import (
|
|||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/v3/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/v4/pkg/eth"
|
||||||
integration "github.com/vulcanize/ipld-eth-server/v3/test"
|
integration "github.com/vulcanize/ipld-eth-server/v4/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
const nonExistingBlockHash = "0x111111111111111111111111111111111111111111111111111111111111111"
|
const nonExistingBlockHash = "0x111111111111111111111111111111111111111111111111111111111111111"
|
||||||
@@ -31,6 +31,8 @@ var (
|
|||||||
var _ = Describe("Integration test", func() {
|
var _ = Describe("Integration test", func() {
|
||||||
directProxyEthCalls, err := strconv.ParseBool(os.Getenv("ETH_FORWARD_ETH_CALLS"))
|
directProxyEthCalls, err := strconv.ParseBool(os.Getenv("ETH_FORWARD_ETH_CALLS"))
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
watchedAddressServiceEnabled, err := strconv.ParseBool(os.Getenv("WATCHED_ADDRESS_GAP_FILLER_ENABLED"))
|
||||||
|
Expect(err).To(BeNil())
|
||||||
gethHttpPath := "http://127.0.0.1:8545"
|
gethHttpPath := "http://127.0.0.1:8545"
|
||||||
gethClient, err := ethclient.Dial(gethHttpPath)
|
gethClient, err := ethclient.Dial(gethHttpPath)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
@@ -50,7 +52,7 @@ var _ = Describe("Integration test", func() {
|
|||||||
sleepInterval := 2 * time.Second
|
sleepInterval := 2 * time.Second
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
if directProxyEthCalls {
|
if directProxyEthCalls || watchedAddressServiceEnabled {
|
||||||
Skip("skipping no-direct-proxy-forwarding integration tests")
|
Skip("skipping no-direct-proxy-forwarding integration tests")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -10,11 +10,10 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/ethclient"
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/ethereum/go-ethereum/statediff/types"
|
|
||||||
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
|
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
integration "github.com/vulcanize/ipld-eth-server/v3/test"
|
integration "github.com/vulcanize/ipld-eth-server/v4/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -28,6 +27,9 @@ var _ = Describe("WatchAddress integration test", func() {
|
|||||||
dbWrite, err := strconv.ParseBool(os.Getenv("DB_WRITE"))
|
dbWrite, err := strconv.ParseBool(os.Getenv("DB_WRITE"))
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
watchedAddressServiceEnabled, err := strconv.ParseBool(os.Getenv("WATCHED_ADDRESS_GAP_FILLER_ENABLED"))
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
gethHttpPath := "http://127.0.0.1:8545"
|
gethHttpPath := "http://127.0.0.1:8545"
|
||||||
gethRPCClient, err := rpc.Dial(gethHttpPath)
|
gethRPCClient, err := rpc.Dial(gethHttpPath)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
@@ -69,7 +71,7 @@ var _ = Describe("WatchAddress integration test", func() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
if !dbWrite {
|
if !dbWrite || watchedAddressServiceEnabled {
|
||||||
Skip("skipping WatchAddress API integration tests")
|
Skip("skipping WatchAddress API integration tests")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -226,8 +228,8 @@ var _ = Describe("WatchAddress integration test", func() {
|
|||||||
|
|
||||||
Context("one contract being watched", func() {
|
Context("one contract being watched", func() {
|
||||||
It("indexes state only for the watched contract", func() {
|
It("indexes state only for the watched contract", func() {
|
||||||
operation := types.Add
|
operation := sdtypes.Add
|
||||||
args := []types.WatchAddressArg{
|
args := []sdtypes.WatchAddressArg{
|
||||||
{
|
{
|
||||||
Address: contract1.Address,
|
Address: contract1.Address,
|
||||||
CreatedAt: uint64(contract1.BlockNumber),
|
CreatedAt: uint64(contract1.BlockNumber),
|
||||||
@@ -308,8 +310,8 @@ var _ = Describe("WatchAddress integration test", func() {
|
|||||||
|
|
||||||
Context("contract added to a non-empty watch-list", func() {
|
Context("contract added to a non-empty watch-list", func() {
|
||||||
It("indexes state only for the watched contracts", func() {
|
It("indexes state only for the watched contracts", func() {
|
||||||
operation := types.Add
|
operation := sdtypes.Add
|
||||||
args := []types.WatchAddressArg{
|
args := []sdtypes.WatchAddressArg{
|
||||||
{
|
{
|
||||||
Address: contract2.Address,
|
Address: contract2.Address,
|
||||||
CreatedAt: uint64(contract2.BlockNumber),
|
CreatedAt: uint64(contract2.BlockNumber),
|
||||||
@@ -392,8 +394,8 @@ var _ = Describe("WatchAddress integration test", func() {
|
|||||||
|
|
||||||
Context("contract removed from the watch-list", func() {
|
Context("contract removed from the watch-list", func() {
|
||||||
It("indexes state only for the watched contract", func() {
|
It("indexes state only for the watched contract", func() {
|
||||||
operation := types.Remove
|
operation := sdtypes.Remove
|
||||||
args := []types.WatchAddressArg{
|
args := []sdtypes.WatchAddressArg{
|
||||||
{
|
{
|
||||||
Address: contract1.Address,
|
Address: contract1.Address,
|
||||||
CreatedAt: uint64(contract1.BlockNumber),
|
CreatedAt: uint64(contract1.BlockNumber),
|
||||||
@@ -474,8 +476,8 @@ var _ = Describe("WatchAddress integration test", func() {
|
|||||||
|
|
||||||
Context("list of watched addresses set", func() {
|
Context("list of watched addresses set", func() {
|
||||||
It("indexes state only for the watched contracts", func() {
|
It("indexes state only for the watched contracts", func() {
|
||||||
operation := types.Set
|
operation := sdtypes.Set
|
||||||
args := []types.WatchAddressArg{
|
args := []sdtypes.WatchAddressArg{
|
||||||
{
|
{
|
||||||
Address: contract1.Address,
|
Address: contract1.Address,
|
||||||
CreatedAt: uint64(contract1.BlockNumber),
|
CreatedAt: uint64(contract1.BlockNumber),
|
||||||
@@ -562,8 +564,8 @@ var _ = Describe("WatchAddress integration test", func() {
|
|||||||
|
|
||||||
Context("list of watched addresses cleared", func() {
|
Context("list of watched addresses cleared", func() {
|
||||||
It("indexes state for all the contracts", func() {
|
It("indexes state for all the contracts", func() {
|
||||||
operation := types.Clear
|
operation := sdtypes.Clear
|
||||||
args := []types.WatchAddressArg{}
|
args := []sdtypes.WatchAddressArg{}
|
||||||
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
|
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
|
||||||
Expect(ipldErr).ToNot(HaveOccurred())
|
Expect(ipldErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
@@ -656,7 +658,7 @@ var _ = Describe("WatchAddress integration test", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("returns an error on args of invalid type", func() {
|
It("returns an error on args of invalid type", func() {
|
||||||
operation := types.Add
|
operation := sdtypes.Add
|
||||||
args := []string{"WrongArg"}
|
args := []string{"WrongArg"}
|
||||||
|
|
||||||
gethErr := gethRPCClient.Call(nil, gethMethod, operation, args)
|
gethErr := gethRPCClient.Call(nil, gethMethod, operation, args)
|
||||||
|
|||||||
@@ -0,0 +1,318 @@
|
|||||||
|
package integration_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"math/big"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
"github.com/ethereum/go-ethereum/statediff/types"
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
|
integration "github.com/vulcanize/ipld-eth-server/v4/test"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Watched address gap filling service integration test", func() {
|
||||||
|
dbWrite, err := strconv.ParseBool(os.Getenv("DB_WRITE"))
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
watchedAddressServiceEnabled, err := strconv.ParseBool(os.Getenv("WATCHED_ADDRESS_GAP_FILLER_ENABLED"))
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
serviceInterval, err := strconv.ParseInt(os.Getenv("WATCHED_ADDRESS_GAP_FILLER_INTERVAL"), 10, 0)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
gethHttpPath := "http://127.0.0.1:8545"
|
||||||
|
gethRPCClient, err := rpc.Dial(gethHttpPath)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldEthHttpPath := "http://127.0.0.1:8081"
|
||||||
|
ipldClient, err := ethclient.Dial(ipldEthHttpPath)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
ipldRPCClient, err := rpc.Dial(ipldEthHttpPath)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
var (
|
||||||
|
ctx = context.Background()
|
||||||
|
|
||||||
|
contractErr error
|
||||||
|
txErr error
|
||||||
|
|
||||||
|
GLD1 *integration.ContractDeployed
|
||||||
|
SLV1 *integration.ContractDeployed
|
||||||
|
SLV2 *integration.ContractDeployed
|
||||||
|
|
||||||
|
countAIndex string
|
||||||
|
countBIndex string
|
||||||
|
|
||||||
|
oldCountA1 = big.NewInt(0)
|
||||||
|
oldCountA2 = big.NewInt(0)
|
||||||
|
oldCountB2 = big.NewInt(0)
|
||||||
|
|
||||||
|
updatedCountA1 = big.NewInt(1)
|
||||||
|
updatedCountA2 = big.NewInt(1)
|
||||||
|
updatedCountB2 = big.NewInt(1)
|
||||||
|
|
||||||
|
SLV2CountBIncrementedAt *integration.CountIncremented
|
||||||
|
|
||||||
|
contract1Salt = "contract1SLV"
|
||||||
|
)
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
if !dbWrite || !watchedAddressServiceEnabled {
|
||||||
|
Skip("skipping watched address gap filling service integration tests")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
It("test init", func() {
|
||||||
|
// Clear out watched addresses
|
||||||
|
err := integration.ClearWatchedAddresses(gethRPCClient)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Deploy a GLD contract
|
||||||
|
GLD1, contractErr = integration.DeployContract()
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Watch GLD1 contract
|
||||||
|
operation := types.Add
|
||||||
|
args := []types.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: GLD1.Address,
|
||||||
|
CreatedAt: uint64(GLD1.BlockNumber),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
|
||||||
|
Expect(ipldErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Deploy two SLV contracts and update storage slots
|
||||||
|
SLV1, contractErr = integration.Create2Contract("SLVToken", contract1Salt)
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
_, txErr = integration.IncrementCount(SLV1.Address, "A")
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
SLV2, contractErr = integration.DeploySLVContract()
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
_, txErr = integration.IncrementCount(SLV2.Address, "A")
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
SLV2CountBIncrementedAt, txErr = integration.IncrementCount(SLV2.Address, "B")
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Get storage slot keys
|
||||||
|
storageSlotAKey, err := integration.GetStorageSlotKey("SLVToken", "countA")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countAIndex = storageSlotAKey.Key
|
||||||
|
|
||||||
|
storageSlotBKey, err := integration.GetStorageSlotKey("SLVToken", "countB")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countBIndex = storageSlotBKey.Key
|
||||||
|
})
|
||||||
|
|
||||||
|
defer It("test cleanup", func() {
|
||||||
|
// Destroy create2 contract
|
||||||
|
_, err := integration.DestroySLVContract(SLV1.Address)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Clear out watched addresses
|
||||||
|
err = integration.ClearWatchedAddresses(gethRPCClient)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("previously unwatched contract watched", func() {
|
||||||
|
It("indexes state only for watched contract", func() {
|
||||||
|
// WatchedAddresses = [GLD1]
|
||||||
|
// SLV1, countA
|
||||||
|
countA1Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV1.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA1 := new(big.Int).SetBytes(countA1Storage)
|
||||||
|
Expect(countA1.String()).To(Equal(oldCountA1.String()))
|
||||||
|
|
||||||
|
// SLV2, countA
|
||||||
|
countA2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA2 := new(big.Int).SetBytes(countA2Storage)
|
||||||
|
Expect(countA2.String()).To(Equal(oldCountA2.String()))
|
||||||
|
|
||||||
|
// SLV2, countB
|
||||||
|
countB2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countBIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countB2 := new(big.Int).SetBytes(countB2Storage)
|
||||||
|
Expect(countB2.String()).To(Equal(oldCountB2.String()))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("indexes past state on watching a contract", func() {
|
||||||
|
// Watch SLV1 contract
|
||||||
|
args := []types.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: SLV1.Address,
|
||||||
|
CreatedAt: uint64(SLV1.BlockNumber),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ipldErr := ipldRPCClient.Call(nil, ipldMethod, types.Add, args)
|
||||||
|
Expect(ipldErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Sleep for service interval + few extra seconds
|
||||||
|
time.Sleep(time.Duration(serviceInterval+2) * time.Second)
|
||||||
|
|
||||||
|
// WatchedAddresses = [GLD1, SLV1]
|
||||||
|
// SLV1, countA
|
||||||
|
countA1Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV1.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA1 := new(big.Int).SetBytes(countA1Storage)
|
||||||
|
Expect(countA1.String()).To(Equal(updatedCountA1.String()))
|
||||||
|
|
||||||
|
// SLV2, countA
|
||||||
|
countA2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA2 := new(big.Int).SetBytes(countA2Storage)
|
||||||
|
Expect(countA2.String()).To(Equal(oldCountA2.String()))
|
||||||
|
|
||||||
|
// SLV2, countB
|
||||||
|
countB2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countBIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countB2 := new(big.Int).SetBytes(countB2Storage)
|
||||||
|
Expect(countB2.String()).To(Equal(oldCountB2.String()))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("previously unwatched contract watched (different 'created_at')", func() {
|
||||||
|
It("indexes past state from 'created_at' onwards on watching a contract", func() {
|
||||||
|
// Watch SLV2 (created_at -> countB incremented) contract
|
||||||
|
args := []types.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: SLV2.Address,
|
||||||
|
CreatedAt: uint64(SLV2CountBIncrementedAt.BlockNumber),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ipldErr := ipldRPCClient.Call(nil, ipldMethod, types.Add, args)
|
||||||
|
Expect(ipldErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Sleep for service interval + few extra seconds
|
||||||
|
time.Sleep(time.Duration(serviceInterval+2) * time.Second)
|
||||||
|
|
||||||
|
// WatchedAddresses = [GLD1, SLV1, SLV2]
|
||||||
|
// SLV2, countA
|
||||||
|
countA2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA2 := new(big.Int).SetBytes(countA2Storage)
|
||||||
|
Expect(countA2.String()).To(Equal(oldCountA2.String()))
|
||||||
|
|
||||||
|
// SLV2, countB
|
||||||
|
countB2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countBIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countB2 := new(big.Int).SetBytes(countB2Storage)
|
||||||
|
Expect(countB2.String()).To(Equal(updatedCountB2.String()))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("indexes missing past state on watching a contract from an earlier 'created_at'", func() {
|
||||||
|
// Remove SLV2 (created_at -> countB incremented) watched contract
|
||||||
|
args := []types.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: SLV2.Address,
|
||||||
|
CreatedAt: uint64(SLV2CountBIncrementedAt.BlockNumber),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ipldErr := ipldRPCClient.Call(nil, ipldMethod, types.Remove, args)
|
||||||
|
Expect(ipldErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Watch SLV2 (created_at -> deployment) contract
|
||||||
|
args = []types.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: SLV2.Address,
|
||||||
|
CreatedAt: uint64(SLV2.BlockNumber),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ipldErr = ipldRPCClient.Call(nil, ipldMethod, types.Add, args)
|
||||||
|
Expect(ipldErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Sleep for service interval + few extra seconds
|
||||||
|
time.Sleep(time.Duration(serviceInterval+2) * time.Second)
|
||||||
|
|
||||||
|
// WatchedAddresses = [GLD1, SLV1, SLV2]
|
||||||
|
// SLV2, countA
|
||||||
|
countA2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA2 := new(big.Int).SetBytes(countA2Storage)
|
||||||
|
Expect(countA2.String()).To(Equal(updatedCountA2.String()))
|
||||||
|
|
||||||
|
// SLV2, countB
|
||||||
|
countB2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countBIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countB2 := new(big.Int).SetBytes(countB2Storage)
|
||||||
|
Expect(countB2.String()).To(Equal(updatedCountB2.String()))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("destroyed contract redeployed and watched", func() {
|
||||||
|
It("returns zero value for destroyed contract", func() {
|
||||||
|
_, err := integration.DestroySLVContract(SLV1.Address)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
updatedCountA1 = big.NewInt(0)
|
||||||
|
|
||||||
|
operation := types.Remove
|
||||||
|
args := []types.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: SLV1.Address,
|
||||||
|
CreatedAt: uint64(SLV1.BlockNumber),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
|
||||||
|
Expect(ipldErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// WatchedAddresses = [GLD1, SLV2]
|
||||||
|
// SLV1, countA
|
||||||
|
countA1Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV1.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA1 := new(big.Int).SetBytes(countA1Storage)
|
||||||
|
Expect(countA1.String()).To(Equal(updatedCountA1.String()))
|
||||||
|
oldCountA1.Set(updatedCountA1)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("indexes state for redeployed contract", func() {
|
||||||
|
// Redeploy contract
|
||||||
|
SLV1, contractErr = integration.Create2Contract("SLVToken", contract1Salt)
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Add to watched address
|
||||||
|
operation := types.Add
|
||||||
|
args := []types.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: SLV1.Address,
|
||||||
|
CreatedAt: uint64(SLV1.BlockNumber),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
|
||||||
|
Expect(ipldErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Sleep for service interval + few extra seconds
|
||||||
|
time.Sleep(time.Duration(serviceInterval+2) * time.Second)
|
||||||
|
|
||||||
|
// WatchedAddresses = [GLD1, SLV2, SLV1]
|
||||||
|
// SLV1, countA
|
||||||
|
countA1Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV1.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA1 := new(big.Int).SetBytes(countA1Storage)
|
||||||
|
Expect(countA1.String()).To(Equal(updatedCountA1.String()))
|
||||||
|
oldCountA1.Set(updatedCountA1)
|
||||||
|
|
||||||
|
// Update storage slots
|
||||||
|
_, txErr = integration.IncrementCount(SLV1.Address, "A")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
updatedCountA1.Add(updatedCountA1, big.NewInt(1))
|
||||||
|
|
||||||
|
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV1.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage)
|
||||||
|
Expect(countA1AfterIncrement.String()).To(Equal(updatedCountA1.String()))
|
||||||
|
oldCountA1.Set(updatedCountA1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user