Compare commits

...
101 Commits
Author SHA1 Message Date
prathamesh0 2c03c8cbd0 Support debug_traceCall API (#192)
* Implement debug_traceCall API

* Use API implementation from geth with custom backend

* Update refs in GitHub workflow
2022-09-21 17:15:03 +05:30
prathamesh0 4d99ecdee3 Increase EVM timeout for eth-calls (#191)
* Increase EVM timeout for eth-calls

* Remove goose prerequisite from test targets in Makefile
2022-09-21 16:28:19 +05:30
Michael fc0d7a6dd6 Cerc refactor (#193)
* cerc refactor waiting on unpublished dependencies

* cerc refactor updates for dependencies

* Describe imports got removed

* cleaning up more vulcanize refs in ci/cd

* another test lost Describe imports

* another test lost Describe imports... not caught in go build -a???

* more cerc-io migrations to utilize new git.vdb.to gitea instance

* switching back to github for running unit test

* first try at git.vdb.to as conatiner repository

* targeted tag was incomplete
2022-09-20 11:52:06 -04:00
Michael 3201ed60f0 Merge pull request #189 from vulcanize/rebase-1.10.23-wip
first pass updating for statediffing geth 1.10.23... filters changed
2022-09-02 11:46:00 -04:00
Michael Shaw d24be29ef0 use mgirated test helper func GenesisBlockForTesting 2022-09-02 11:05:54 -04:00
Michael Shaw 0e91e42128 first pass updating for statediffing geth 1.10.23... filters changed 2022-09-01 18:37:51 -04:00
prathamesh0 4e9f4bbad6 Re-order uncles if calculated uncle hash doesn't match (#188)
* Re-order uncles if calculated uncle hash doesn't match

* Add a spec to test out of order uncles
2022-08-25 15:54:32 +05:30
prathamesh0 e40e8a7335 Optimize eth_getBlockByNumber and eth_getBlockByHash implementations (#187)
* Avoid two step queries for creating a block object

* Use a db tx while fetching block objects

* Upgrade ipfs-ethdb
2022-08-23 12:42:19 +05:30
Ian Norden ddc7485c08 Merge pull request #185 from vulcanize/ian_v4
ChainID adjustment
2022-08-08 14:38:02 -05:00
i-norden cc35b06ddf use go 1.18 2022-08-08 14:20:12 -05:00
i-norden 1a24075da7 ChainID adjustment 2022-08-08 13:57:36 -05:00
Michael c9e6055cfd Merge pull request #182 from vulcanize/geth1.10.21-update-wip
geth 1.10.21 update with changes for API update in issue 177
2022-08-03 09:21:30 -04:00
Michael Shaw 9eb7b22f47 changes in ethapi for ChainId always return something now 2022-08-02 16:18:36 -04:00
Michael Shaw 4cf523b626 PEBKAC 2022-08-02 15:51:18 -04:00
Michael Shaw 451d71a528 trying pre-merge commit to avoid not our ref error in CI 2022-08-02 14:53:59 -04:00
Michael Shaw ec21e95182 dependency update and on pr yaml update 2022-08-02 11:46:36 -04:00
Michael Shaw 0d1da46d6d ipfs related dependency updates 2022-08-02 10:39:42 -04:00
Michael Shaw 45502e7117 go blockservice version update 2022-08-01 17:37:47 -04:00
Michael Shaw 74a7748483 on pr yaml dependency ref updates 2022-08-01 14:49:59 -04:00
Michael Shaw 415e426946 geth 1.10.21 update with changes for API update in issue 177 2022-08-01 13:27:29 -04:00
prathamesh0 ba01123f54 Use geth's eth API on missing blocks for getHeaderByHash (#181) 2022-07-20 09:34:44 +05:30
prathamesh0 b90c28906a Add log while serving getBlockByNumber (#176)
* Add log while serving getBlockByNumber

* Update GQL API to return empty result when header not found for hash
2022-07-15 16:19:31 +05:30
prathamesh0 6cb54ca790 Update transactions, receipts and logs queries (#173)
* Update queries to fetch data from cids tables

* Fix eth_getTransactionByHash to return tx from canonical block

* Fetch transaction by hash in a single query

* Update queries to fetch data from IPLD blocks table

* Avoid NULL result from canonical block hash query

* Update GitHub workflow and script to run unit tests

* Avoid usage of LIMIT 1 in queries for GQL API

* Fetch IPLD data separately when retrieving latest account data or storage value

* Upgrade geth dependency

* Update GitHub workflow
2022-07-12 13:40:45 +05:30
Ashwin Phatak bcd00c6e2b Merge pull request #171 from vulcanize/pm-error-logging
Add misssing error logs
2022-06-28 17:49:26 +05:30
prathamesh 923a8c3241 Update refs in GitHub workflows 2022-06-28 17:28:41 +05:30
prathamesh 07a991d3e4 Add misssing error logs 2022-06-28 16:40:07 +05:30
Abdul Rabbani a63640933e Merge pull request #168 from vulcanize/feature/re-test-v1.10.19
RE-test release with correct commit hash
2022-06-17 13:16:32 -04:00
Abdul Rabbani a5ac6c19cf Update stack-orch retry 2022-06-17 13:02:00 -04:00
Abdul Rabbani 45c5a25d54 Update write to file 2022-06-17 12:53:22 -04:00
Abdul Rabbani 72e903cf68 clean up before 2022-06-17 12:49:39 -04:00
Abdul Rabbani b7b4631231 Update unit test to use stack-orchestrator 2022-06-17 12:48:50 -04:00
Abdul Rabbani f8de0defad RE-test release with correct commit hash 2022-06-17 11:37:50 -04:00
Abdul Rabbani aaf571b04c Merge pull request #167 from vulcanize/feature/update-geth-v1.10.19
Update Geth and CICD
2022-06-17 11:15:39 -04:00
Abdul Rabbani 4121863a4c Update Geth and CICD 2022-06-17 10:45:54 -04:00
Ashwin Phatak fa4428b167 Merge pull request #166 from vulcanize/ng-watcher-queries-v4
Merge changes to implement postgraphile GraphQL queries
2022-06-08 12:04:08 +05:30
nikugogoi 221114cf56 Merge changes to implement postgraphile graphql queries 2022-06-07 17:37:01 +05:30
Ashwin Phatak 8e652a634f Merge pull request #160 from vulcanize/ng-watcher-queries-v3
Implement postgraphile graphql queries in V3
2022-06-07 10:35:40 +05:30
nikugogoi 1fc53ccab1 Rename Cid to CID 2022-06-06 16:46:53 +05:30
nikugogoi 31e9a7dc5e Review changes 2022-06-06 15:54:06 +05:30
nabarun c19cc5c44d Select required fields in transaction_cids 2022-06-03 15:08:45 +05:30
nabarun 6bd563e3d5 Use GORM to retrieve data from database 2022-06-03 15:08:45 +05:30
nabarun b3d9e01d67 Add test for ethTransactionCidByTxHash query 2022-06-03 15:05:46 +05:30
nabarun 0c44882cb2 Added test for allEthHeaderCids query 2022-06-03 15:05:46 +05:30
nabarun 80413211c2 Remove block_number from queries for v3 schema 2022-06-03 15:05:46 +05:30
prathamesh 7f15befdee Add custom implementation for Bytes to be returned as string 2022-06-03 15:05:46 +05:30
nabarun 217cfc63ec Return empty headerCIDs and commit db tx 2022-06-03 15:05:46 +05:30
nabarun 9550d60467 Add query ethTransactionCidByTxHash 2022-06-03 15:05:46 +05:30
nabarun da1c8b2332 Implement single query for transactions and blockByMhKey 2022-06-03 15:05:46 +05:30
prathamesh fe7329c284 Add custom implementation for graphql scalar BigInt 2022-06-03 15:04:54 +05:30
prathamesh f144d932cd Implement graphql query to get header with transactions 2022-06-03 15:04:54 +05:30
Abdul Rabbani 491939b35f Feature/update cicd tag sharding (#165)
* Update geth version: 1.10.18

* Upgrade to Go18 and fix broken interfaces

* Update Go version in dockerfile

* Update make file to download dependencies

* Update go version for integration tests.

* update file name

* install packages.

* Update gingko version and secret

* Update unit test download package

* Update vulcanize dependencies

* Update commands for calling unit tests

* Use latest version of statediff

* Update github variable to work with tags (#164)

* Update github variable to work with tags

* Update tests.yaml

* Use conditional for reference
2022-06-02 09:18:01 -04:00
Abdul Rabbani 248d9eb7a2 Update github variable to work with tags (#164)
* Update github variable to work with tags

* Update tests.yaml

* Use conditional for reference
2022-06-02 08:49:23 -04:00
Abdul Rabbaniandnabarun a3d2e71ca6 Feature/update go geth sharding (#162)
* Update geth version: 1.10.18

* Upgrade to Go18 and fix broken interfaces

* Update Go version in dockerfile

* Update make file to download dependencies

* Update go version for integration tests.

* update file name

* install packages.

* Update gingko version and secret

* Update unit test download package

* Update vulcanize dependencies

* Update commands for calling unit tests

* Use latest version of statediff

* Update go, geth, and tests

* Update all the quotes

* Update stack-orchestrator

* Update docker-compose ref

* Add ipld-eth-db locally

* Deploy contracts

* Update tests.yaml

* Update config file properly

* Fix steps for integration test after geth update

Co-authored-by: nabarun <nabarun@deepstacksoft.com>
2022-06-02 07:59:44 -04:00
Abdul Rabbani be1d4281e8 Merge pull request #161 from vulcanize/feature/upgrade-geth-and-go
Feature/upgrade geth and go
2022-06-01 14:00:07 -04:00
Abdul Rabbani e2b83a5737 Use latest version of statediff 2022-06-01 08:26:11 -04:00
Abdul Rabbani 613dd6acf4 Update commands for calling unit tests 2022-06-01 08:23:03 -04:00
Abdul Rabbani 8966d1b6c2 Update vulcanize dependencies 2022-05-31 13:29:48 -04:00
Abdul Rabbani c556845d1a Update unit test download package 2022-05-31 10:15:04 -04:00
Abdul Rabbani cf8c08f01e Update gingko version and secret 2022-05-31 09:49:37 -04:00
Abdul Rabbani 5c6fb45d36 install packages. 2022-05-27 15:42:02 -04:00
Abdul Rabbani 222fa6d6ed update file name 2022-05-27 15:28:01 -04:00
Abdul Rabbani 6c82eafef1 Update go version for integration tests. 2022-05-27 15:27:23 -04:00
Abdul Rabbani 89b9a05234 Update make file to download dependencies 2022-05-27 14:42:45 -04:00
Abdul Rabbani 27d9413544 Update Go version in dockerfile 2022-05-27 14:12:23 -04:00
Abdul Rabbani 4817674c5c Upgrade to Go18 and fix broken interfaces 2022-05-27 14:06:38 -04:00
Abdul Rabbani 8556332ff8 Update geth version: 1.10.18 2022-05-26 09:04:39 -04:00
Ashwin Phatak 81884d4826 Merge pull request #156 from vulcanize/ng-v4-remove-fill
Merge changes to remove watched addresses fill service
2022-05-23 20:31:23 +05:30
nabarun 389ba2e360 Merge changes to remove watched addresses fill service code 2022-05-23 19:12:11 +05:30
nabarun c25d220f71 Remove watched addresses fill service code 2022-05-23 10:37:59 +05:30
Ashwin Phatak 8ea4d1e40d Merge pull request #154 from vulcanize/pm-docker-publish
Docker publish and stack orchestrator changes
2022-05-20 19:11:37 +05:30
prathamesh ace12fbc35 Update module path for v4 2022-05-20 18:50:50 +05:30
prathamesh 8b8f644b2a Update instructions to run integration tests locally 2022-05-20 18:50:39 +05:30
prathamesh 8bfcce95ca Merge changes to combine docker build and push steps 2022-05-20 17:51:34 +05:30
prathamesh 0b12c3c329 Update stack-orchestrator commit hash for running tests 2022-05-20 17:51:07 +05:30
Ashwin Phatak 037131528c Merge pull request #152 from vulcanize/pm-v4-single-node
Updates to use v4 db schema
2022-05-20 17:30:35 +05:30
Abdul Rabbani be34f0e8fd Merge pull request #151 from vulcanize/feature/cicd-docker-tag
Combine the build and push steps.
2022-05-19 12:50:30 -04:00
nabarun 04096fab0c Update stack-orchestrator versions for CI 2022-05-19 11:21:15 +05:30
prathamesh dc14656bbc Update scripts to run unit tests using TimescaleDB 2022-05-19 10:13:33 +05:30
prathamesh 9676690a2d Remove unused functions 2022-05-19 08:14:43 +05:30
Abdul Rabbani 025b1c7c9e Combine the build and push steps. 2022-05-18 14:45:55 -04:00
prathamesh 36e590c092 Delete from all tables when tearing down db for tests 2022-05-18 20:23:40 +05:30
prathamesh 384d939dc2 Upgrade dependencies 2022-05-18 14:53:09 +05:30
prathamesh 24a45a3f00 Update unit tests and queries to fetch data from cids tables 2022-05-18 14:38:09 +05:30
prathamesh 867323a1ab Update queries to get data from IPLD blocks table 2022-05-18 14:36:51 +05:30
Ashwin Phatak da30a957a7 Merge pull request #149 from vulcanize/ng-watched-addresses-v3
Add a service (v3) to fill indexing gap for watched addresses
2022-05-18 14:24:04 +05:30
prathamesh 705835512e Update module path for v3 2022-05-18 13:35:16 +05:30
prathamesh 2a0e9f8dfd Upgrade geth 2022-05-18 13:05:26 +05:30
prathamesh c8bdaefe97 Gracefully shutdown watched address fill service on interrupt 2022-05-18 11:08:15 +05:30
nabarun a141d154b7 Remove dapptools and update test readme to use stack-orchestrator 2022-05-05 14:34:09 +05:30
nabarun 76986d9497 Update stack-orchestrator commit hash in CI 2022-05-05 09:52:42 +05:30
prathamesh 233fa29740 Upgrade eth-ipfs-state-validator to v3 2022-05-04 13:06:07 +05:30
prathamesh 4883590d85 Upgrade ipfs-ethdb to v3 2022-05-04 13:06:07 +05:30
nabarun 181e3745f1 Run CI tests using stack-orchestrator 2022-05-04 13:05:48 +05:30
prathamesh 4b697b2a98 Upgrade dependencies 2022-05-02 17:48:03 +05:30
nabarun 77812f2673 Move SetupTestStateDiffIndexer to shared test helpers 2022-04-21 17:06:29 +05:30
nabarun 849b17f4bd Add test for destroying and redeploying contract to same address 2022-04-21 17:06:25 +05:30
nabarun 56c85709c1 Add unit tests for fill service 2022-04-21 17:03:59 +05:30
nabarun 2be2a06575 Add integration tests for service to fill indexing gap 2022-04-21 17:03:37 +05:30
nabarun 39fb9207b2 Add integration tests for API to change addresses watched by geth 2022-04-19 19:32:18 +05:30
nabarun 3914889d53 Add a service to fill indexing gap for watched addresses 2022-04-19 19:32:18 +05:30
nabarun 1a6ff273ba Add an API to change addresses being watched by geth for direct indexing 2022-04-19 19:32:18 +05:30
70 changed files with 4288 additions and 1636 deletions
-25
View File
@@ -1,25 +0,0 @@
name: Docker Compose Build
on:
push:
branches:
- master
jobs:
build:
name: Run docker build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Get the version
id: vars
run: echo ::set-output name=sha::$(echo ${GITHUB_SHA:0:7})
- name: Run docker build
run: make docker-build
- name: Tag docker image
run: docker tag vulcanize/ipld-eth-server docker.pkg.github.com/vulcanize/ipld-eth-server/ipld-eth-server:${{steps.vars.outputs.sha}}
- name: Docker Login
run: echo ${{ secrets.GITHUB_TOKEN }} | docker login https://docker.pkg.github.com -u vulcanize --password-stdin
- name: Docker Push
run: docker push docker.pkg.github.com/vulcanize/ipld-eth-server/ipld-eth-server:${{steps.vars.outputs.sha}}
+79
View File
@@ -0,0 +1,79 @@
name: Test, Build, and/or Publish
on:
release:
types: [published]
pull_request:
jobs:
pre_job:
# continue-on-error: true # Uncomment once integration is finished
runs-on: ubuntu-latest
# Map a step output to a job output
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
steps:
- id: skip_check
uses: fkirc/skip-duplicate-actions@v4
with:
# All of these options are optional, so you can remove them if you are happy with the defaults
concurrent_skipping: "never"
skip_after_successful_duplicate: "true"
do_not_skip: '["workflow_dispatch", "schedule"]'
run-tests:
uses: ./.github/workflows/tests.yaml
if: ${{ needs.pre_job.outputs.should_skip != 'true' }}
needs: pre_job
secrets:
BUILD_HOSTNAME: ${{ secrets.BUILD_HOSTNAME }}
BUILD_USERNAME: ${{ secrets.BUILD_USERNAME }}
BUILD_KEY: ${{ secrets.BUILD_KEY }}
with:
STACK_ORCHESTRATOR_REF: "f2fd766f5400fcb9eb47b50675d2e3b1f2753702"
GO_ETHEREUM_REF: "0c1e451c9865d8d47797b35526c4875f0d224772"
IPLD_ETH_DB_REF: "be345e0733d2c025e4082c5154e441317ae94cf7"
build:
name: Run docker build
runs-on: ubuntu-latest
needs: run-tests
if: |
always() &&
(needs.run-tests.result == 'success' || needs.run-tests.result == 'skipped') &&
github.event_name == 'release'
steps:
- uses: actions/checkout@v2
- name: Get the version
id: vars
run: echo ::set-output name=sha::$(echo ${GITHUB_SHA:0:7})
- name: Run docker build
run: make docker-build
- name: Tag docker image
run: docker tag cerc-io/ipld-eth-server git.vdb.to/cerc-io/ipld-eth-server/ipld-eth-server:${{steps.vars.outputs.sha}}
- name: Docker Login
run: echo ${{ secrets.GITHUB_TOKEN }} | docker login https://git.vdb.to -u cerccicd --password-stdin
- name: Docker Push
run: docker push git.vdb.to/cerc-io/ipld-eth-server/ipld-eth-server:${{steps.vars.outputs.sha}}
push_to_registries:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
if: |
always() &&
(needs.build.result == 'success') &&
github.event_name == 'release'
needs: build
steps:
- name: Get the version
id: vars
run: |
echo ::set-output name=sha::$(echo ${GITHUB_SHA:0:7})
echo ::set-output name=tag::$(echo ${GITHUB_REF#refs/tags/})
- name: Docker Login to Github Registry
run: echo ${{ secrets.GITHUB_TOKEN }} | docker login https://git.vdb.to -u cerccicd --password-stdin
- name: Docker Pull
run: docker pull git.vdb.to/cerc-io/ipld-eth-server/ipld-eth-server:${{steps.vars.outputs.sha}}
- name: Docker Login to Docker Registry
run: echo ${{ secrets.VULCANIZEJENKINS_PAT }} | docker login -u vulcanizejenkins --password-stdin
- name: Tag docker image
run: docker tag git.vdb.to/cerc-io/ipld-eth-server/ipld-eth-server:${{steps.vars.outputs.sha}} cerc-io/ipld-eth-server:${{steps.vars.outputs.tag}}
- name: Docker Push to Docker Hub
run: docker push cerc-io/ipld-eth-server:${{steps.vars.outputs.tag}}
-116
View File
@@ -1,116 +0,0 @@
name: Docker Build
on: [pull_request]
jobs:
build:
name: Run docker build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run docker build
run: make docker-build
test:
name: Run unit tests
env:
GOPATH: /tmp/go
# To run the unit tests you need to add secrets to your repository.
BUILD_HOSTNAME: ${{ secrets.BUILD_HOSTNAME }}
BUILD_USERNAME: ${{ secrets.BUILD_USERNAME }}
BUILD_KEY: ${{ secrets.BUILD_KEY }}
#strategy:
# matrix:
# go-version: [1.16.x, 1.17.x]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
# Passed experience with GHA has taught me to store variables in files instead of passing them as variables.
- name: Output variables to files
run: |
echo $GITHUB_REPOSITORY > /tmp/git_repository
echo $GITHUB_HEAD_REF > /tmp/git_head_ref
echo "-----BEGIN OPENSSH PRIVATE KEY-----" >> /tmp/key
echo ${{ env.BUILD_KEY }} >> /tmp/key
echo "-----END OPENSSH PRIVATE KEY-----" >> /tmp/key
chmod 400 /tmp/key
cat /tmp/git_repository
cat /tmp/git_head_ref
- name: Raw SCP
run: |
scp -o 'StrictHostKeyChecking no' -o UserKnownHostsFile=/dev/null -q -i /tmp/key /tmp/git_repository ${{ env.BUILD_USERNAME }}@${{ env.BUILD_HOSTNAME }}:/tmp/git_repository
scp -o 'StrictHostKeyChecking no' -o UserKnownHostsFile=/dev/null -q -i /tmp/key /tmp/git_head_ref ${{ env.BUILD_USERNAME }}@${{ env.BUILD_HOSTNAME }}:/tmp/git_head_ref
scp -o 'StrictHostKeyChecking no' -o UserKnownHostsFile=/dev/null -q -i /tmp/key .github/workflows/run_unit_test.sh ${{ env.BUILD_USERNAME }}@${{ env.BUILD_HOSTNAME }}:/tmp/run_unit_test.sh
- name: Trigger Unit Test
run: |
ssh -o 'StrictHostKeyChecking no' -o UserKnownHostsFile=/dev/null -q -i /tmp/key ${{ env.BUILD_USERNAME }}@${{ env.BUILD_HOSTNAME }} chmod +x /tmp/run_unit_test.sh /tmp/run_unit_test.sh
ssh -o 'StrictHostKeyChecking no' -o UserKnownHostsFile=/dev/null -q -i /tmp/key ${{ env.BUILD_USERNAME }}@${{ env.BUILD_HOSTNAME }} /tmp/run_unit_test.sh
- name: Get the logs and cat them
run: |
scp -o 'StrictHostKeyChecking no' -o UserKnownHostsFile=/dev/null -q -i /tmp/key ${{ env.BUILD_USERNAME }}@${{ env.BUILD_HOSTNAME }}:/tmp/test.log .
cat ./test.log
- name: Check Error Code
run: |
scp -o 'StrictHostKeyChecking no' -o UserKnownHostsFile=/dev/null -q -i /tmp/key ${{ env.BUILD_USERNAME }}@${{ env.BUILD_HOSTNAME }}:/tmp/return_test.txt .
[ $(cat ./return_test.txt) -eq 0 ]
integrationtest:
name: Run integration tests
env:
GOPATH: /tmp/go
DB_WRITE: true
ETH_FORWARD_ETH_CALLS: false
ETH_PROXY_ON_ERROR: false
ETH_HTTP_PATH: ""
strategy:
matrix:
go-version: [1.16.x]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Create GOPATH
run: mkdir -p /tmp/go
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- uses: actions/checkout@v2
- name: Run database
run: docker-compose -f docker-compose.test.yml -f docker-compose.yml up -d ipld-eth-db dapptools contract eth-server
- name: Test
run: |
while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8081)" != "200" ]; do echo "waiting for ipld-eth-server..." && sleep 5; done && \
while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8545)" != "200" ]; do echo "waiting for geth-statediff..." && sleep 5; done && \
make integrationtest
integrationtest_forwardethcalls:
name: Run integration tests for direct proxy fall-through of eth_calls
env:
GOPATH: /tmp/go
DB_WRITE: false
ETH_FORWARD_ETH_CALLS: true
ETH_PROXY_ON_ERROR: false
ETH_HTTP_PATH: "dapptools:8545"
strategy:
matrix:
go-version: [1.16.x]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Create GOPATH
run: mkdir -p /tmp/go
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- uses: actions/checkout@v2
- name: Run database
run: docker-compose -f docker-compose.test.yml -f docker-compose.yml up -d ipld-eth-db dapptools contract eth-server
- name: Test
run: |
while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8081)" != "200" ]; do echo "waiting for ipld-eth-server..." && sleep 5; done && \
while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8545)" != "200" ]; do echo "waiting for geth-statediff..." && sleep 5; done && \
make integrationtest
-25
View File
@@ -1,25 +0,0 @@
name: Publish Docker image
on:
release:
types: [published]
jobs:
push_to_registries:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
steps:
- name: Get the version
id: vars
run: |
echo ::set-output name=sha::$(echo ${GITHUB_SHA:0:7})
echo ::set-output name=tag::$(echo ${GITHUB_REF#refs/tags/})
- name: Docker Login to Github Registry
run: echo ${{ secrets.GITHUB_TOKEN }} | docker login https://docker.pkg.github.com -u vulcanize --password-stdin
- name: Docker Pull
run: docker pull docker.pkg.github.com/vulcanize/ipld-eth-server/ipld-eth-server:${{steps.vars.outputs.sha}}
- name: Docker Login to Docker Registry
run: echo ${{ secrets.VULCANIZEJENKINS_PAT }} | docker login -u vulcanizejenkins --password-stdin
- name: Tag docker image
run: docker tag docker.pkg.github.com/vulcanize/ipld-eth-server/ipld-eth-server:${{steps.vars.outputs.sha}} vulcanize/ipld-eth-server:${{steps.vars.outputs.tag}}
- name: Docker Push to Docker Hub
run: docker push vulcanize/ipld-eth-server:${{steps.vars.outputs.tag}}
+6 -6
View File
@@ -12,18 +12,18 @@ cd ipld-eth-server
## 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 # Spin up DB and run migrations
docker-compose up -d ipld-eth-db echo 'docker-compose up -d migrations ipld-eth-db'
trap "docker-compose down --remove-orphans; cd $start_dir ; rm -r $temp_dir" SIGINT SIGTERM ERR docker-compose up -d migrations ipld-eth-db
sleep 10 trap "docker-compose down -v --remove-orphans; cd $start_dir ; rm -r $temp_dir" SIGINT SIGTERM ERR
sleep 30
# 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=8077 DATABASE_PASSWORD=password DATABASE_HOSTNAME=localhost DATABASE_NAME=vulcanize_testing 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 down -v --remove-orphans
cd $start_dir cd $start_dir
rm -fr $temp_dir rm -fr $temp_dir
+212
View File
@@ -0,0 +1,212 @@
name: Test the stack.
on:
workflow_call:
secrets:
BUILD_HOSTNAME:
required: true
BUILD_USERNAME:
required: true
BUILD_KEY:
required: true
inputs:
STACK_ORCHESTRATOR_REF:
required: true
type: string
GO_ETHEREUM_REF:
required: true
type: string
IPLD_ETH_DB_REF:
required: true
type: string
jobs:
build:
name: Run docker build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run docker build
run: make docker-build
test:
name: Run unit tests
env:
GOPATH: /tmp/go
# To run the unit tests you need to add secrets to your repository.
BUILD_HOSTNAME: ${{ secrets.BUILD_HOSTNAME }}
BUILD_USERNAME: ${{ secrets.BUILD_USERNAME }}
BUILD_KEY: ${{ secrets.BUILD_KEY }}
#strategy:
# matrix:
# go-version: [1.16.x, 1.17.x, 1.18.x]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
# Passed experience with GHA has taught me to store variables in files instead of passing them as variables.
- name: Output variables to files
run: |
echo $GITHUB_REPOSITORY > /tmp/git_repository
[ -z "$GITHUB_HEAD_REF" ] && echo $GITHUB_REF_NAME > /tmp/git_head_ref || echo $GITHUB_HEAD_REF > /tmp/git_head_ref
echo "-----BEGIN OPENSSH PRIVATE KEY-----" >> /tmp/key
echo ${{ env.BUILD_KEY }} >> /tmp/key
echo "-----END OPENSSH PRIVATE KEY-----" >> /tmp/key
chmod 400 /tmp/key
cat /tmp/git_repository
cat /tmp/git_head_ref
- name: Raw SCP
run: |
scp -o 'StrictHostKeyChecking no' -o UserKnownHostsFile=/dev/null -q -i /tmp/key /tmp/git_repository ${{ env.BUILD_USERNAME }}@${{ env.BUILD_HOSTNAME }}:/tmp/git_repository
scp -o 'StrictHostKeyChecking no' -o UserKnownHostsFile=/dev/null -q -i /tmp/key /tmp/git_head_ref ${{ env.BUILD_USERNAME }}@${{ env.BUILD_HOSTNAME }}:/tmp/git_head_ref
scp -o 'StrictHostKeyChecking no' -o UserKnownHostsFile=/dev/null -q -i /tmp/key .github/workflows/run_unit_test.sh ${{ env.BUILD_USERNAME }}@${{ env.BUILD_HOSTNAME }}:/tmp/run_unit_test.sh
- name: Trigger Unit Test
run: |
ssh -o 'StrictHostKeyChecking no' -o UserKnownHostsFile=/dev/null -q -i /tmp/key ${{ env.BUILD_USERNAME }}@${{ env.BUILD_HOSTNAME }} go install github.com/onsi/ginkgo/ginkgo@latest
ssh -o 'StrictHostKeyChecking no' -o UserKnownHostsFile=/dev/null -q -i /tmp/key ${{ env.BUILD_USERNAME }}@${{ env.BUILD_HOSTNAME }} /tmp/run_unit_test.sh
- name: Get the logs and cat them
run: |
scp -o 'StrictHostKeyChecking no' -o UserKnownHostsFile=/dev/null -q -i /tmp/key ${{ env.BUILD_USERNAME }}@${{ env.BUILD_HOSTNAME }}:/tmp/test.log .
cat ./test.log
- name: Check Error Code
run: |
scp -o 'StrictHostKeyChecking no' -o UserKnownHostsFile=/dev/null -q -i /tmp/key ${{ env.BUILD_USERNAME }}@${{ env.BUILD_HOSTNAME }}:/tmp/return_test.txt .
[ $(cat ./return_test.txt) -eq 0 ]
integrationtest:
name: Run integration tests
env:
GOPATH: /tmp/go
DB_WRITE: true
ETH_FORWARD_ETH_CALLS: false
ETH_PROXY_ON_ERROR: false
ETH_HTTP_PATH: "go-ethereum:8545"
runs-on: ubuntu-latest
steps:
- name: Create GOPATH
run: mkdir -p /tmp/go
- uses: actions/setup-go@v3
with:
go-version: "1.18.x"
check-latest: true
- uses: actions/checkout@v2
with:
path: "./ipld-eth-server"
- uses: actions/checkout@v2
with:
ref: ${{ inputs.STACK_ORCHESTRATOR_REF }}
path: "./stack-orchestrator/"
repository: vulcanize/stack-orchestrator
- uses: actions/checkout@v2
with:
ref: ${{ inputs.GO_ETHEREUM_REF }}
repository: cerc-io/go-ethereum
path: "./go-ethereum/"
- uses: actions/checkout@v2
with:
ref: ${{ inputs.IPLD_ETH_DB_REF }}
repository: cerc-io/ipld-eth-db
path: "./ipld-eth-db/"
- name: Create config file
run: |
echo vulcanize_go_ethereum=$GITHUB_WORKSPACE/go-ethereum/ > ./config.sh
echo vulcanize_ipld_eth_db=$GITHUB_WORKSPACE/ipld-eth-db/ >> ./config.sh
echo vulcanize_ipld_eth_server=$GITHUB_WORKSPACE/ipld-eth-server/ >> ./config.sh
echo vulcanize_test_contract=$GITHUB_WORKSPACE/ipld-eth-server/test/contract >> ./config.sh
echo genesis_file_path=start-up-files/go-ethereum/genesis.json >> ./config.sh
echo db_write=$DB_WRITE >> ./config.sh
echo eth_forward_eth_calls=$ETH_FORWARD_ETH_CALLS >> ./config.sh
echo eth_proxy_on_error=$ETH_PROXY_ON_ERROR >> ./config.sh
echo eth_http_path=$ETH_HTTP_PATH >> ./config.sh
cat ./config.sh
- name: Build geth
run: |
cd $GITHUB_WORKSPACE/stack-orchestrator/helper-scripts
./compile-geth.sh \
-p "$GITHUB_WORKSPACE/config.sh" \
-e docker
- name: Run docker compose
run: |
docker-compose \
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/local/docker-compose-db-sharding.yml" \
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/local/docker-compose-go-ethereum.yml" \
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/local/docker-compose-ipld-eth-server.yml" \
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/local/docker-compose-contract.yml" \
--env-file "$GITHUB_WORKSPACE/config.sh" \
up -d --build
- name: Test
run: |
cd $GITHUB_WORKSPACE/ipld-eth-server
while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8081)" != "200" ]; do echo "waiting for ipld-eth-server..." && sleep 5; done && \
while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8545)" != "200" ]; do echo "waiting for geth-statediff..." && sleep 5; done && \
make integrationtest
integrationtest_forwardethcalls:
name: Run integration tests for direct proxy fall-through of eth_calls
env:
GOPATH: /tmp/go
DB_WRITE: false
ETH_FORWARD_ETH_CALLS: true
ETH_PROXY_ON_ERROR: false
ETH_HTTP_PATH: "go-ethereum:8545"
runs-on: ubuntu-latest
steps:
- name: Create GOPATH
run: mkdir -p /tmp/go
- uses: actions/setup-go@v3
with:
go-version: "1.18.x"
check-latest: true
- uses: actions/checkout@v2
with:
path: "./ipld-eth-server"
- uses: actions/checkout@v2
with:
ref: ${{ inputs.STACK_ORCHESTRATOR_REF }}
path: "./stack-orchestrator/"
repository: vulcanize/stack-orchestrator
- uses: actions/checkout@v2
with:
ref: ${{ inputs.GO_ETHEREUM_REF }}
repository: cerc-io/go-ethereum
path: "./go-ethereum/"
- uses: actions/checkout@v2
with:
ref: ${{ inputs.IPLD_ETH_DB_REF }}
repository: cerc-io/ipld-eth-db
path: "./ipld-eth-db/"
- name: Create config file
run: |
echo vulcanize_go_ethereum=$GITHUB_WORKSPACE/go-ethereum/ > ./config.sh
echo vulcanize_ipld_eth_db=$GITHUB_WORKSPACE/ipld-eth-db/ >> ./config.sh
echo vulcanize_ipld_eth_server=$GITHUB_WORKSPACE/ipld-eth-server/ >> ./config.sh
echo vulcanize_test_contract=$GITHUB_WORKSPACE/ipld-eth-server/test/contract >>./config.sh
echo genesis_file_path=start-up-files/go-ethereum/genesis.json >> ./config.sh
echo db_write=$DB_WRITE >> ./config.sh
echo eth_forward_eth_calls=$ETH_FORWARD_ETH_CALLS >> ./config.sh
echo eth_proxy_on_error=$ETH_PROXY_ON_ERROR >> ./config.sh
echo eth_http_path=$ETH_HTTP_PATH >> ./config.sh
cat ./config.sh
- name: Build geth
run: |
cd $GITHUB_WORKSPACE/stack-orchestrator/helper-scripts
./compile-geth.sh \
-p "$GITHUB_WORKSPACE/config.sh" \
-e docker
- name: Run docker compose
run: |
docker-compose \
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/local/docker-compose-db-sharding.yml" \
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/local/docker-compose-go-ethereum.yml" \
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/local/docker-compose-ipld-eth-server.yml" \
-f "$GITHUB_WORKSPACE/stack-orchestrator/docker/local/docker-compose-contract.yml" \
--env-file "$GITHUB_WORKSPACE/config.sh" \
up -d --build
- name: Test
run: |
cd $GITHUB_WORKSPACE/ipld-eth-server
while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8081)" != "200" ]; do echo "waiting for ipld-eth-server..." && sleep 5; done && \
while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8545)" != "200" ]; do echo "waiting for geth-statediff..." && sleep 5; done && \
make integrationtest
+6 -6
View File
@@ -1,11 +1,11 @@
FROM golang:1.16-alpine as builder FROM golang:1.18-alpine as builder
RUN apk --update --no-cache add make git g++ linux-headers RUN apk --update --no-cache add make git g++ linux-headers
# DEBUG # DEBUG
RUN apk add busybox-extras RUN apk add busybox-extras
# Build ipld-eth-server # Build ipld-eth-server
WORKDIR /go/src/github.com/vulcanize/ipld-eth-server WORKDIR /go/src/github.com/cerc-io/ipld-eth-server
# Cache the modules # Cache the modules
ENV GO111MODULE=on ENV GO111MODULE=on
@@ -37,13 +37,13 @@ USER $USER
# chown first so dir is writable # chown first so dir is writable
# note: using $USER is merged, but not in the stable release yet # note: using $USER is merged, but not in the stable release yet
COPY --chown=5000:5000 --from=builder /go/src/github.com/vulcanize/ipld-eth-server/$CONFIG_FILE config.toml COPY --chown=5000:5000 --from=builder /go/src/github.com/cerc-io/ipld-eth-server/$CONFIG_FILE config.toml
COPY --chown=5000:5000 --from=builder /go/src/github.com/vulcanize/ipld-eth-server/entrypoint.sh . COPY --chown=5000:5000 --from=builder /go/src/github.com/cerc-io/ipld-eth-server/entrypoint.sh .
# keep binaries immutable # keep binaries immutable
COPY --from=builder /go/src/github.com/vulcanize/ipld-eth-server/ipld-eth-server ipld-eth-server COPY --from=builder /go/src/github.com/cerc-io/ipld-eth-server/ipld-eth-server ipld-eth-server
COPY --from=builder /goose goose COPY --from=builder /goose goose
COPY --from=builder /go/src/github.com/vulcanize/ipld-eth-server/environments environments COPY --from=builder /go/src/github.com/cerc-io/ipld-eth-server/environments environments
ENTRYPOINT ["/app/entrypoint.sh"] ENTRYPOINT ["/app/entrypoint.sh"]
+8 -18
View File
@@ -3,10 +3,6 @@ BASE = $(GOPATH)/src/$(PACKAGE)
PKGS = go list ./... | grep -v "^vendor/" PKGS = go list ./... | grep -v "^vendor/"
# Tools # Tools
## Testing library
GINKGO = $(BIN)/ginkgo
$(BIN)/ginkgo:
go get -u github.com/onsi/ginkgo/ginkgo
## Migration tool ## Migration tool
GOOSE = $(BIN)/goose GOOSE = $(BIN)/goose
@@ -26,8 +22,9 @@ $(BIN)/gometalinter.v2:
.PHONY: installtools .PHONY: installtools
installtools: | $(LINT) $(GOOSE) $(GINKGO) installtools: | $(LINT) $(GOOSE)
echo "Installing tools" echo "Installing tools"
go mod download
.PHONY: metalint .PHONY: metalint
metalint: | $(METALINT) metalint: | $(METALINT)
@@ -54,30 +51,23 @@ TEST_CONNECT_STRING = postgresql://$(DATABASE_USER):$(DATABASE_PASSWORD)@$(DATAB
TEST_CONNECT_STRING_LOCAL = postgresql://$(USER)@$(HOST_NAME):$(PORT)/$(TEST_DB)?sslmode=disable TEST_CONNECT_STRING_LOCAL = postgresql://$(USER)@$(HOST_NAME):$(PORT)/$(TEST_DB)?sslmode=disable
.PHONY: test .PHONY: test
test: | $(GINKGO) $(GOOSE) test:
go vet ./... go vet ./...
go fmt ./... go fmt ./...
$(GINKGO) -r --skipPackage=test go run github.com/onsi/ginkgo/ginkgo -r --skipPackage=test
.PHONY: integrationtest .PHONY: integrationtest
integrationtest: | $(GINKGO) $(GOOSE) integrationtest:
go vet ./... go vet ./...
go fmt ./... go fmt ./...
$(GINKGO) -r test/ -v go run github.com/onsi/ginkgo/ginkgo -r test/ -v
.PHONY: test_local .PHONY: test_local
test_local: | $(GINKGO) $(GOOSE) test_local:
go vet ./... go vet ./...
go fmt ./... go fmt ./...
./scripts/run_unit_test.sh ./scripts/run_unit_test.sh
.PHONY: integrationtest_local
integrationtest_local: | $(GINKGO) $(GOOSE)
go vet ./...
go fmt ./...
./scripts/run_integration_test.sh
./scripts/run_integration_test_forward_eth_calls.sh
build: build:
go fmt ./... go fmt ./...
GO111MODULE=on go build GO111MODULE=on go build
@@ -145,4 +135,4 @@ import:
## Build docker image ## Build docker image
.PHONY: docker-build .PHONY: docker-build
docker-build: docker-build:
docker build -t vulcanize/ipld-eth-server . docker build -t cerc-io/ipld-eth-server .
+6 -6
View File
@@ -22,20 +22,20 @@ Additional, unique endpoints are exposed which utilize the new indexes and state
## Dependencies ## Dependencies
Minimal build dependencies Minimal build dependencies
* Go (1.13) * Go (1.18)
* Git * Git
* GCC compiler * GCC compiler
* This repository * This repository
External dependency External dependency
* Postgres database populated by [ipld-eth-indexer](https://github.com/vulcanize/ipld-eth-indexer) * Postgres database populated by [ipld-eth-db](https://github.com/cerc-io/ipld-eth-db)
## 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` `GO111MODULE=off go get -d github.com/cerc-io/ipld-eth-server/v4`
`cd $GOPATH/src/github.com/vulcanize/ipld-eth-server` `cd $GOPATH/src/github.com/cerc-io/ipld-eth-server/v4@v4.x.x`
Then, build the binary: Then, build the binary:
@@ -148,8 +148,8 @@ TODO: Add the rest of the standard endpoints and unique endpoints (e.g. getSlice
### Testing ### Testing
`make test` will run the unit tests
`make test` setups a clean `vulcanize_testing` db Follow steps in [test/README.md](./test/README.md)
## Monitoring ## Monitoring
+1 -1
View File
@@ -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/pkg/prom" "github.com/cerc-io/ipld-eth-server/v4/pkg/prom"
) )
var ( var (
+8 -8
View File
@@ -17,6 +17,7 @@ package cmd
import ( import (
"errors" "errors"
"github.com/mailgun/groupcache/v2"
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
@@ -26,17 +27,16 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/mailgun/groupcache/v2"
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"
"github.com/vulcanize/gap-filler/pkg/mux" "github.com/vulcanize/gap-filler/pkg/mux"
"github.com/vulcanize/ipld-eth-server/pkg/eth" "github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/vulcanize/ipld-eth-server/pkg/graphql" "github.com/cerc-io/ipld-eth-server/v4/pkg/graphql"
srpc "github.com/vulcanize/ipld-eth-server/pkg/rpc" srpc "github.com/cerc-io/ipld-eth-server/v4/pkg/rpc"
s "github.com/vulcanize/ipld-eth-server/pkg/serve" s "github.com/cerc-io/ipld-eth-server/v4/pkg/serve"
v "github.com/vulcanize/ipld-eth-server/version" v "github.com/cerc-io/ipld-eth-server/v4/version"
) )
var ErrNoRpcEndpoints = errors.New("no rpc endpoints is available") var ErrNoRpcEndpoints = errors.New("no rpc endpoints is available")
@@ -123,7 +123,7 @@ func startServers(server s.Server, settings *s.Config) error {
if settings.WSEnabled { if settings.WSEnabled {
logWithCommand.Info("starting up WS server") logWithCommand.Info("starting up WS server")
_, _, err := srpc.StartWSEndpoint(settings.WSEndpoint, server.APIs(), []string{"vdb", "net"}, nil, true) _, _, err := srpc.StartWSEndpoint(settings.WSEndpoint, server.APIs(), []string{"vdb", "net"}, nil)
if err != nil { if err != nil {
return err return err
} }
@@ -133,7 +133,7 @@ func startServers(server s.Server, settings *s.Config) error {
if settings.HTTPEnabled { if settings.HTTPEnabled {
logWithCommand.Info("starting up HTTP server") logWithCommand.Info("starting up HTTP server")
_, err := srpc.StartHTTPEndpoint(settings.HTTPEndpoint, server.APIs(), []string{"eth", "net"}, nil, []string{"*"}, rpc.HTTPTimeouts{}) _, err := srpc.StartHTTPEndpoint(settings.HTTPEndpoint, server.APIs(), []string{"vdb", "eth", "debug", "net"}, nil, []string{"*"}, rpc.HTTPTimeouts{})
if err != nil { if err != nil {
return err return err
} }
+3 -3
View File
@@ -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/pkg/client" "github.com/cerc-io/ipld-eth-server/v4/pkg/client"
"github.com/vulcanize/ipld-eth-server/pkg/eth" "github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
w "github.com/vulcanize/ipld-eth-server/pkg/serve" w "github.com/cerc-io/ipld-eth-server/v4/pkg/serve"
) )
// subscribeCmd represents the subscribe command // subscribeCmd represents the subscribe command
+3 -3
View File
@@ -18,14 +18,14 @@ package cmd
import ( import (
"time" "time"
validator "github.com/cerc-io/eth-ipfs-state-validator/v4/pkg"
ipfsethdb "github.com/cerc-io/ipfs-ethdb/v4/postgres"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
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/pkg"
ipfsethdb "github.com/vulcanize/ipfs-ethdb/postgres"
s "github.com/vulcanize/ipld-eth-server/pkg/serve" s "github.com/cerc-io/ipld-eth-server/v4/pkg/serve"
) )
const GroupName = "statedb-validate" const GroupName = "statedb-validate"
+1 -1
View File
@@ -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/version" v "github.com/cerc-io/ipld-eth-server/v4/version"
) )
// versionCmd represents the version command // versionCmd represents the version command
+2 -4
View File
@@ -2,13 +2,11 @@ version: '3.2'
services: services:
contract: contract:
depends_on:
- dapptools
build: build:
context: ./test/contract context: ./test/contract
args: args:
ETH_ADDR: "http://dapptools:8545" ETH_ADDR: "http://go-ethereum:8545"
environment: environment:
ETH_ADDR: "http://dapptools:8545" ETH_ADDR: "http://go-ethereum:8545"
ports: ports:
- "127.0.0.1:3000:3000" - "127.0.0.1:3000:3000"
+10 -33
View File
@@ -1,36 +1,28 @@
version: '3.2' version: '3.2'
services: services:
dapptools: migrations:
restart: unless-stopped restart: on-failure
depends_on: depends_on:
- ipld-eth-db - ipld-eth-db
image: vulcanize/dapptools:v0.30.0-v1.10.16-statediff-3.0.2a image: git.vdb.to/cerc-io/ipld-eth-db/ipld-eth-db:v4.2.1-alpha-unstable
environment: environment:
DB_USER: vdbm DATABASE_USER: "vdbm"
DB_NAME: vulcanize_testing DATABASE_NAME: "vulcanize_testing"
DB_HOST: ipld-eth-db DATABASE_PASSWORD: "password"
DB_PORT: 5432 DATABASE_HOSTNAME: "ipld-eth-db"
DB_PASSWORD: password DATABASE_PORT: 5432
DB_WRITE: $DB_WRITE
DB_TYPE: postgres
DB_DRIVER: sqlx
ports:
- "127.0.0.1:8545:8545"
- "127.0.0.1:8546:8546"
ipld-eth-db: ipld-eth-db:
image: timescale/timescaledb:latest-pg14
restart: always restart: always
image: vulcanize/ipld-eth-db:v3.0.7 command: ["postgres", "-c", "log_statement=all"]
environment: environment:
POSTGRES_USER: "vdbm" POSTGRES_USER: "vdbm"
POSTGRES_DB: "vulcanize_testing" POSTGRES_DB: "vulcanize_testing"
POSTGRES_PASSWORD: "password" POSTGRES_PASSWORD: "password"
volumes:
- vdb_db_eth_server:/var/lib/postgresql/data
ports: ports:
- "127.0.0.1:8077:5432" - "127.0.0.1:8077:5432"
command: ["postgres", "-c", "log_statement=all"]
eth-server: eth-server:
restart: unless-stopped restart: unless-stopped
@@ -63,20 +55,5 @@ services:
ports: ports:
- "127.0.0.1:8081:8081" - "127.0.0.1:8081:8081"
graphql:
restart: unless-stopped
depends_on:
- ipld-eth-db
image: vulcanize/postgraphile:v1.0.1
environment:
- PG_HOST=db
- PG_PORT=5432
- PG_DATABASE=vulcanize_public
- PG_USER=vdbm
- PG_PASSWORD=password
- SCHEMA=public,eth
ports:
- "127.0.0.1:5000:5000"
volumes: volumes:
vdb_db_eth_server: vdb_db_eth_server:
+6 -6
View File
@@ -40,9 +40,9 @@ An example of how to subscribe to a real-time Ethereum data feed from ipld-eth-s
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/vulcanize/ipld-eth-server/pkg/client" "github.com/cerc-io/ipld-eth-server/v4/pkg/client"
"github.com/vulcanize/ipld-eth-server/pkg/eth" "github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/vulcanize/ipld-eth-server/pkg/watch" "github.com/cerc-io/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/pkg/btc" "github.com/vulcanize/ipld-eth-server/v4/pkg/btc"
"github.com/vulcanize/ipld-eth-server/pkg/client" "github.com/vulcanize/ipld-eth-server/v4/pkg/client"
"github.com/vulcanize/ipld-eth-server/pkg/watch" "github.com/vulcanize/ipld-eth-server/v4/pkg/watch"
) )
config, _ := btc.NewBtcSubscriptionConfig() config, _ := btc.NewBtcSubscriptionConfig()
+1
View File
@@ -16,6 +16,7 @@
graphqlEndpoint = "127.0.0.1:8083" # $SERVER_GRAPHQL_ENDPOINT graphqlEndpoint = "127.0.0.1:8083" # $SERVER_GRAPHQL_ENDPOINT
[ethereum] [ethereum]
chainConfig = "./chain.json" # ETH_CHAIN_CONFIG
chainID = "1" # $ETH_CHAIN_ID chainID = "1" # $ETH_CHAIN_ID
defaultSender = "" # $ETH_DEFAULT_SENDER_ADDR defaultSender = "" # $ETH_DEFAULT_SENDER_ADDR
rpcGasCap = "1000000000000" # $ETH_RPC_GAS_CAP rpcGasCap = "1000000000000" # $ETH_RPC_GAS_CAP
+286 -28
View File
@@ -1,38 +1,296 @@
module github.com/vulcanize/ipld-eth-server module github.com/cerc-io/ipld-eth-server/v4
go 1.15 go 1.18
require ( require (
github.com/ethereum/go-ethereum v1.10.16 github.com/cerc-io/eth-ipfs-state-validator/v4 v4.0.8-alpha
github.com/fsnotify/fsnotify v1.5.1 // indirect github.com/cerc-io/ipfs-ethdb/v4 v4.0.8-alpha
github.com/go-sql-driver/mysql v1.6.0 // indirect github.com/ethereum/go-ethereum v1.10.23
github.com/graph-gophers/graphql-go v1.3.0 github.com/graph-gophers/graphql-go v1.3.0
github.com/ipfs/go-block-format v0.0.3 github.com/ipfs/go-block-format v0.0.3
github.com/ipfs/go-cid v0.0.7 github.com/ipfs/go-cid v0.2.0
github.com/ipfs/go-ipfs-blockstore v1.0.1 github.com/ipfs/go-ipfs-blockstore v1.2.0
github.com/ipfs/go-ipfs-ds-help v1.0.0 github.com/ipfs/go-ipfs-ds-help v1.1.0
github.com/ipfs/go-ipld-format v0.2.0 github.com/jmoiron/sqlx v1.3.5
github.com/jmoiron/sqlx v1.2.0
github.com/joho/godotenv v1.4.0 github.com/joho/godotenv v1.4.0
github.com/lib/pq v1.10.4 github.com/lib/pq v1.10.6
github.com/machinebox/graphql v0.2.2 github.com/machinebox/graphql v0.2.2
github.com/mailgun/groupcache/v2 v2.2.1 github.com/mailgun/groupcache/v2 v2.3.0
github.com/matryer/is v1.4.0 // indirect github.com/multiformats/go-multihash v0.2.0
github.com/multiformats/go-multihash v0.0.15
github.com/onsi/ginkgo v1.16.5 github.com/onsi/ginkgo v1.16.5
github.com/onsi/gomega v1.13.0 github.com/onsi/gomega v1.19.0
github.com/prometheus/client_golang v1.11.0 github.com/prometheus/client_golang v1.12.1
github.com/shirou/gopsutil v3.21.5+incompatible // indirect github.com/sirupsen/logrus v1.9.0
github.com/sirupsen/logrus v1.7.0 github.com/spf13/cobra v1.4.0
github.com/spf13/cobra v1.1.1 github.com/spf13/viper v1.11.0
github.com/spf13/viper v1.7.0 github.com/vulcanize/gap-filler v0.4.0
github.com/tklauser/go-sysconf v0.3.6 // indirect gorm.io/driver/postgres v1.3.7
github.com/vulcanize/eth-ipfs-state-validator v0.1.0 gorm.io/gorm v1.23.5
github.com/vulcanize/gap-filler v0.3.1
github.com/vulcanize/ipfs-ethdb v0.0.6
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e // indirect
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d // indirect
golang.org/x/tools v0.1.8 // indirect
) )
replace github.com/ethereum/go-ethereum v1.10.16 => github.com/vulcanize/go-ethereum v1.10.16-statediff-3.0.2 require (
bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc // indirect
github.com/Stebalien/go-bitfield v0.0.1 // indirect
github.com/VictoriaMetrics/fastcache v1.6.0 // indirect
github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a // indirect
github.com/benbjohnson/clock v1.3.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/btcsuite/btcd v0.22.1 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
github.com/cerc-io/go-eth-state-node-iterator v1.1.7 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/cheekybits/genny v1.0.0 // indirect
github.com/containerd/cgroups v1.0.3 // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect
github.com/cskr/pubsub v1.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/deckarep/golang-set v1.8.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/deepmap/oapi-codegen v1.8.2 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/edsrzf/mmap-go v1.0.0 // indirect
github.com/elastic/gosigar v0.14.2 // indirect
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect
github.com/flynn/noise v1.0.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/friendsofgo/graphiql v0.2.2 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
github.com/georgysavva/scany v0.2.9 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-stack/stack v1.8.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.3.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/graphql-go/graphql v0.7.9 // indirect
github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-bexpr v0.1.10 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
github.com/holiman/uint256 v1.2.0 // indirect
github.com/huin/goupnp v1.0.3 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/influxdata/influxdb v1.8.3 // indirect
github.com/influxdata/influxdb-client-go/v2 v2.4.0 // indirect
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
github.com/ipfs/bbloom v0.0.4 // indirect
github.com/ipfs/go-bitfield v1.0.0 // indirect
github.com/ipfs/go-bitswap v0.8.0 // indirect
github.com/ipfs/go-blockservice v0.4.0 // indirect
github.com/ipfs/go-cidutil v0.1.0 // indirect
github.com/ipfs/go-datastore v0.5.1 // indirect
github.com/ipfs/go-delegated-routing v0.3.0 // indirect
github.com/ipfs/go-ds-measure v0.2.0 // indirect
github.com/ipfs/go-fetcher v1.6.1 // indirect
github.com/ipfs/go-filestore v1.2.0 // indirect
github.com/ipfs/go-fs-lock v0.0.7 // indirect
github.com/ipfs/go-graphsync v0.13.1 // indirect
github.com/ipfs/go-ipfs-chunker v0.0.5 // indirect
github.com/ipfs/go-ipfs-delay v0.0.1 // indirect
github.com/ipfs/go-ipfs-exchange-interface v0.2.0 // indirect
github.com/ipfs/go-ipfs-exchange-offline v0.3.0 // indirect
github.com/ipfs/go-ipfs-files v0.1.1 // indirect
github.com/ipfs/go-ipfs-keystore v0.0.2 // indirect
github.com/ipfs/go-ipfs-pinner v0.2.1 // indirect
github.com/ipfs/go-ipfs-posinfo v0.0.1 // indirect
github.com/ipfs/go-ipfs-pq v0.0.2 // indirect
github.com/ipfs/go-ipfs-provider v0.7.1 // indirect
github.com/ipfs/go-ipfs-routing v0.2.1 // indirect
github.com/ipfs/go-ipfs-util v0.0.2 // indirect
github.com/ipfs/go-ipld-cbor v0.0.5 // indirect
github.com/ipfs/go-ipld-format v0.4.0 // indirect
github.com/ipfs/go-ipld-legacy v0.1.1 // indirect
github.com/ipfs/go-ipns v0.1.2 // indirect
github.com/ipfs/go-log v1.0.5 // indirect
github.com/ipfs/go-log/v2 v2.5.1 // indirect
github.com/ipfs/go-merkledag v0.6.0 // indirect
github.com/ipfs/go-metrics-interface v0.0.1 // indirect
github.com/ipfs/go-mfs v0.2.1 // indirect
github.com/ipfs/go-namesys v0.5.0 // indirect
github.com/ipfs/go-path v0.3.0 // indirect
github.com/ipfs/go-peertaskqueue v0.7.1 // indirect
github.com/ipfs/go-unixfs v0.4.0 // indirect
github.com/ipfs/go-unixfsnode v1.4.0 // indirect
github.com/ipfs/go-verifcid v0.0.1 // indirect
github.com/ipfs/interface-go-ipfs-core v0.7.0 // indirect
github.com/ipfs/kubo v0.14.0 // indirect
github.com/ipld/edelweiss v0.1.4 // indirect
github.com/ipld/go-codec-dagpb v1.4.0 // indirect
github.com/ipld/go-ipld-prime v0.17.0 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.12.1 // indirect
github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.3.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
github.com/jackc/pgtype v1.11.0 // indirect
github.com/jackc/pgx/v4 v4.16.1 // indirect
github.com/jackc/puddle v1.2.1 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect
github.com/jinzhu/copier v0.2.4 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.4 // indirect
github.com/klauspost/compress v1.15.1 // indirect
github.com/klauspost/cpuid/v2 v2.0.12 // indirect
github.com/koron/go-ssdp v0.0.2 // indirect
github.com/libp2p/go-buffer-pool v0.0.2 // indirect
github.com/libp2p/go-cidranger v1.1.0 // indirect
github.com/libp2p/go-doh-resolver v0.4.0 // indirect
github.com/libp2p/go-eventbus v0.2.1 // indirect
github.com/libp2p/go-flow-metrics v0.0.3 // indirect
github.com/libp2p/go-libp2p v0.20.3 // indirect
github.com/libp2p/go-libp2p-asn-util v0.2.0 // indirect
github.com/libp2p/go-libp2p-core v0.16.1 // indirect
github.com/libp2p/go-libp2p-discovery v0.7.0 // indirect
github.com/libp2p/go-libp2p-kad-dht v0.16.0 // indirect
github.com/libp2p/go-libp2p-kbucket v0.4.7 // indirect
github.com/libp2p/go-libp2p-loggables v0.1.0 // indirect
github.com/libp2p/go-libp2p-peerstore v0.6.0 // indirect
github.com/libp2p/go-libp2p-pubsub v0.6.1 // indirect
github.com/libp2p/go-libp2p-pubsub-router v0.5.0 // indirect
github.com/libp2p/go-libp2p-record v0.1.3 // indirect
github.com/libp2p/go-libp2p-resource-manager v0.3.0 // indirect
github.com/libp2p/go-libp2p-routing-helpers v0.2.3 // indirect
github.com/libp2p/go-libp2p-swarm v0.11.0 // indirect
github.com/libp2p/go-libp2p-xor v0.1.0 // indirect
github.com/libp2p/go-mplex v0.7.0 // indirect
github.com/libp2p/go-msgio v0.2.0 // indirect
github.com/libp2p/go-nat v0.1.0 // indirect
github.com/libp2p/go-netroute v0.2.0 // indirect
github.com/libp2p/go-openssl v0.0.7 // indirect
github.com/libp2p/go-reuseport v0.2.0 // indirect
github.com/libp2p/go-yamux/v3 v3.1.2 // indirect
github.com/libp2p/zeroconf/v2 v2.1.1 // indirect
github.com/lucas-clemente/quic-go v0.27.1 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/marten-seemann/qtls-go1-16 v0.1.5 // indirect
github.com/marten-seemann/qtls-go1-17 v0.1.1 // indirect
github.com/marten-seemann/qtls-go1-18 v0.1.1 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
github.com/matryer/is v1.4.0 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/miekg/dns v1.1.48 // indirect
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
github.com/minio/sha256-simd v1.0.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.4.3 // indirect
github.com/mitchellh/pointerstructure v1.2.0 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiformats/go-base32 v0.0.4 // indirect
github.com/multiformats/go-base36 v0.1.0 // indirect
github.com/multiformats/go-multiaddr v0.5.0 // indirect
github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect
github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
github.com/multiformats/go-multibase v0.1.0 // indirect
github.com/multiformats/go-multicodec v0.5.0 // indirect
github.com/multiformats/go-multistream v0.3.3 // indirect
github.com/multiformats/go-varint v0.0.6 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/opencontainers/runtime-spec v1.0.2 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/pelletier/go-toml v1.9.4 // indirect
github.com/pelletier/go-toml/v2 v2.0.0-beta.8 // indirect
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 // indirect
github.com/pganalyze/pg_query_go/v2 v2.1.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.33.0 // indirect
github.com/prometheus/procfs v0.7.3 // indirect
github.com/prometheus/tsdb v0.10.0 // indirect
github.com/raulk/clock v1.1.0 // indirect
github.com/raulk/go-watchdog v1.2.0 // indirect
github.com/rjeczalik/notify v0.9.1 // indirect
github.com/rs/cors v1.7.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/segmentio/fasthash v1.0.3 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/smartystreets/assertions v1.0.1 // indirect
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.8.2 // indirect
github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 // indirect
github.com/stretchr/objx v0.2.0 // indirect
github.com/stretchr/testify v1.7.2 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect
github.com/thoas/go-funk v0.9.2 // indirect
github.com/tidwall/gjson v1.14.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tklauser/go-sysconf v0.3.5 // indirect
github.com/tklauser/numcpus v0.2.2 // indirect
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef // indirect
github.com/urfave/cli/v2 v2.10.2 // indirect
github.com/valyala/fastjson v1.6.3 // indirect
github.com/wI2L/jsondiff v0.2.0 // indirect
github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect
github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2 // indirect
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect
github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.opencensus.io v0.23.0 // indirect
go.opentelemetry.io/otel v1.7.0 // indirect
go.opentelemetry.io/otel/trace v1.7.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/dig v1.14.0 // indirect
go.uber.org/fx v1.16.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.21.0 // indirect
go4.org v0.0.0-20200411211856-f5505b9728dd // indirect
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
golang.org/x/net v0.0.0-20220607020251-c690dde0001d // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
golang.org/x/tools v0.1.10 // indirect
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/ini.v1 v1.66.4 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.1.7 // indirect
)
replace github.com/ethereum/go-ethereum v1.10.23 => github.com/cerc-io/go-ethereum v1.10.23-statediff-4.2.0-alpha
+552 -414
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -18,7 +18,7 @@ package main
import ( import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/vulcanize/ipld-eth-server/cmd" "github.com/cerc-io/ipld-eth-server/v4/cmd"
) )
func main() { func main() {
+2 -3
View File
@@ -20,11 +20,10 @@ package client
import ( import (
"context" "context"
"github.com/vulcanize/ipld-eth-server/pkg/eth"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/vulcanize/ipld-eth-server/pkg/serve" "github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/cerc-io/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
+54
View File
@@ -0,0 +1,54 @@
// 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 debug
import (
"context"
"errors"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/rpc"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
)
var _ tracers.Backend = &Backend{}
var (
errMethodNotSupported = errors.New("backend method not supported")
)
// Backend implements tracers.Backend interface
type Backend struct {
eth.Backend
}
// StateAtBlock retrieves the state database associated with a certain block
func (b *Backend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive, preferDisk bool) (*state.StateDB, error) {
rpcBlockNumber := rpc.BlockNumber(block.NumberU64())
statedb, _, err := b.StateAndHeaderByNumberOrHash(ctx, rpc.BlockNumberOrHashWithNumber(rpcBlockNumber))
return statedb, err
}
// StateAtTransaction returns the execution environment of a certain transaction
func (b *Backend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error) {
return nil, vm.BlockContext{}, nil, errMethodNotSupported
}
+29 -17
View File
@@ -42,7 +42,12 @@ 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/pkg/shared" "github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
)
const (
defaultEVMTimeout = 30 * time.Second
defaultStateDiffTimeout = 240 * time.Second
) )
// APIName is the namespace for the watcher's eth api // APIName is the namespace for the watcher's eth api
@@ -66,6 +71,9 @@ type PublicEthAPI struct {
// NewPublicEthAPI creates a new PublicEthAPI with the provided underlying Backend // NewPublicEthAPI creates a new PublicEthAPI with the provided underlying Backend
func NewPublicEthAPI(b *Backend, client *rpc.Client, supportsStateDiff, forwardEthCalls, proxyOnError bool) (*PublicEthAPI, error) { func NewPublicEthAPI(b *Backend, client *rpc.Client, supportsStateDiff, forwardEthCalls, proxyOnError bool) (*PublicEthAPI, error) {
if b == nil {
return nil, errors.New("ipld-eth-server must be configured with an ethereum backend")
}
if forwardEthCalls && client == nil { if forwardEthCalls && client == nil {
return nil, errors.New("ipld-eth-server is configured to forward eth_calls to proxy node but no proxy node is configured") return nil, errors.New("ipld-eth-server is configured to forward eth_calls to proxy node but no proxy node is configured")
} }
@@ -120,11 +128,10 @@ func (pea *PublicEthAPI) GetHeaderByHash(ctx context.Context, hash common.Hash)
} }
if pea.proxyOnError { if pea.proxyOnError {
if header, err := pea.ethClient.HeaderByHash(ctx, hash); header != nil && err == nil { var result map[string]interface{}
if err := pea.rpc.CallContext(ctx, &result, "eth_getHeaderByHash", hash); result != nil && err == nil {
go pea.writeStateDiffFor(hash) go pea.writeStateDiffFor(hash)
if res, err := pea.rpcMarshalHeader(header); err != nil { return result
return res
}
} }
} }
@@ -156,6 +163,7 @@ func (pea *PublicEthAPI) BlockNumber() hexutil.Uint64 {
// * When fullTx is true all transactions in the block are returned, otherwise // * When fullTx is true all transactions in the block are returned, otherwise
// only the transaction hash is returned. // only the transaction hash is returned.
func (pea *PublicEthAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) { func (pea *PublicEthAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
logrus.Debug("Received getBlockByNumber request for number ", number.Int64())
block, err := pea.B.BlockByNumber(ctx, number) block, err := pea.B.BlockByNumber(ctx, number)
if block != nil && err == nil { if block != nil && err == nil {
return pea.rpcMarshalBlock(block, true, fullTx) return pea.rpcMarshalBlock(block, true, fullTx)
@@ -174,6 +182,7 @@ func (pea *PublicEthAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockN
// GetBlockByHash returns the requested block. When fullTx is true all transactions in the block are returned in full // GetBlockByHash returns the requested block. When fullTx is true all transactions in the block are returned in full
// detail, otherwise only the transaction hash is returned. // detail, otherwise only the transaction hash is returned.
func (pea *PublicEthAPI) GetBlockByHash(ctx context.Context, hash common.Hash, fullTx bool) (map[string]interface{}, error) { func (pea *PublicEthAPI) GetBlockByHash(ctx context.Context, hash common.Hash, fullTx bool) (map[string]interface{}, error) {
logrus.Debug("Received getBlockByHash request for hash ", hash.Hex())
block, err := pea.B.BlockByHash(ctx, hash) block, err := pea.B.BlockByHash(ctx, hash)
if block != nil && err == nil { if block != nil && err == nil {
return pea.rpcMarshalBlock(block, true, fullTx) return pea.rpcMarshalBlock(block, true, fullTx)
@@ -190,21 +199,17 @@ func (pea *PublicEthAPI) GetBlockByHash(ctx context.Context, hash common.Hash, f
} }
// ChainId is the EIP-155 replay-protection chain id for the current ethereum chain config. // ChainId is the EIP-155 replay-protection chain id for the current ethereum chain config.
func (pea *PublicEthAPI) ChainId() (*hexutil.Big, error) { func (pea *PublicEthAPI) ChainId() *hexutil.Big {
block, err := pea.B.CurrentBlock() if pea.B.Config.ChainConfig.ChainID == nil || pea.B.Config.ChainConfig.ChainID.Cmp(big.NewInt(0)) <= 0 {
if err != nil {
if pea.proxyOnError { if pea.proxyOnError {
if id, err := pea.ethClient.ChainID(context.Background()); err == nil { if id, err := pea.ethClient.ChainID(context.Background()); err == nil {
return (*hexutil.Big)(id), nil return (*hexutil.Big)(id)
} }
} }
return nil, err return nil
} }
if config := pea.B.Config.ChainConfig; config.IsEIP155(block.Number()) { return (*hexutil.Big)(pea.B.Config.ChainConfig.ChainID)
return (*hexutil.Big)(config.ChainID), nil
}
return nil, fmt.Errorf("chain not synced beyond EIP-155 replay-protection fork block")
} }
/* /*
@@ -927,7 +932,7 @@ func (pea *PublicEthAPI) Call(ctx context.Context, args CallArgs, blockNrOrHash
return hex, err return hex, err
} }
result, err := DoCall(ctx, pea.B, args, blockNrOrHash, overrides, 5*time.Second, pea.B.Config.RPCGasCap.Uint64()) result, err := DoCall(ctx, pea.B, args, blockNrOrHash, overrides, defaultEVMTimeout, pea.B.Config.RPCGasCap.Uint64())
// If the result contains a revert reason, try to unpack and return it. // If the result contains a revert reason, try to unpack and return it.
if err == nil { if err == nil {
@@ -945,7 +950,12 @@ func (pea *PublicEthAPI) Call(ctx context.Context, args CallArgs, blockNrOrHash
return hex, nil return hex, nil
} }
} }
if result != nil {
return result.Return(), err return result.Return(), err
} else {
return nil, err
}
} }
func DoCall(ctx context.Context, b *Backend, args CallArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) { func DoCall(ctx context.Context, b *Backend, args CallArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) {
@@ -1054,7 +1064,7 @@ func (pea *PublicEthAPI) writeStateDiffAt(height int64) {
return return
} }
// we use a separate context than the one provided by the client // we use a separate context than the one provided by the client
ctx, cancel := context.WithTimeout(context.Background(), 240*time.Second) ctx, cancel := context.WithTimeout(context.Background(), defaultStateDiffTimeout)
defer cancel() defer cancel()
var data json.RawMessage var data json.RawMessage
params := statediff.Params{ params := statediff.Params{
@@ -1076,7 +1086,7 @@ func (pea *PublicEthAPI) writeStateDiffFor(blockHash common.Hash) {
return return
} }
// we use a separate context than the one provided by the client // we use a separate context than the one provided by the client
ctx, cancel := context.WithTimeout(context.Background(), 240*time.Second) ctx, cancel := context.WithTimeout(context.Background(), defaultStateDiffTimeout)
defer cancel() defer cancel()
var data json.RawMessage var data json.RawMessage
params := statediff.Params{ params := statediff.Params{
@@ -1096,11 +1106,13 @@ func (pea *PublicEthAPI) writeStateDiffFor(blockHash common.Hash) {
func (pea *PublicEthAPI) rpcMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) { func (pea *PublicEthAPI) rpcMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
fields, err := RPCMarshalBlock(b, inclTx, fullTx) fields, err := RPCMarshalBlock(b, inclTx, fullTx)
if err != nil { if err != nil {
logrus.Errorf("error RPC marshalling block with hash %s: %s", b.Hash().String(), err)
return nil, err return nil, err
} }
if inclTx { if inclTx {
td, err := pea.B.GetTd(b.Hash()) td, err := pea.B.GetTd(b.Hash())
if err != nil { if err != nil {
logrus.Errorf("error getting td for block with hash and number %s, %s: %s", b.Hash().String(), b.Number().String(), err)
return nil, err return nil, err
} }
fields["totalDifficulty"] = (*hexutil.Big)(td) fields["totalDifficulty"] = (*hexutil.Big)(td)
+32 -8
View File
@@ -21,6 +21,10 @@ import (
"math/big" "math/big"
"strconv" "strconv"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth/test_helpers"
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
ethServerShared "github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
@@ -35,10 +39,6 @@ import (
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
"github.com/vulcanize/ipld-eth-server/pkg/eth"
"github.com/vulcanize/ipld-eth-server/pkg/eth/test_helpers"
ethServerShared "github.com/vulcanize/ipld-eth-server/pkg/shared"
) )
var ( var (
@@ -195,8 +195,8 @@ var _ = Describe("API", func() {
tx interfaces.Batch tx interfaces.Batch
) )
db = eth.SetupTestDB() db = shared.SetupDB()
indexAndPublisher := eth.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash()) indexAndPublisher := shared.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash())
backend, err := eth.NewEthBackend(db, &eth.Config{ backend, err := eth.NewEthBackend(db, &eth.Config{
ChainConfig: chainConfig, ChainConfig: chainConfig,
@@ -241,7 +241,7 @@ var _ = Describe("API", func() {
// setting chain config to for london block // setting chain config to for london block
chainConfig.LondonBlock = big.NewInt(2) chainConfig.LondonBlock = big.NewInt(2)
indexAndPublisher = eth.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash()) indexAndPublisher = shared.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash())
tx, err = indexAndPublisher.PushBlock(test_helpers.MockLondonBlock, test_helpers.MockLondonReceipts, test_helpers.MockLondonBlock.Difficulty()) tx, err = indexAndPublisher.PushBlock(test_helpers.MockLondonBlock, test_helpers.MockLondonReceipts, test_helpers.MockLondonBlock.Difficulty())
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@@ -251,7 +251,7 @@ var _ = Describe("API", func() {
}) })
// Single test db tear down at end of all tests // Single test db tear down at end of all tests
defer It("test teardown", func() { eth.TearDownTestDB(db) }) defer It("test teardown", func() { shared.TearDownDB(db) })
/* /*
Headers and blocks Headers and blocks
@@ -333,6 +333,18 @@ var _ = Describe("API", func() {
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(block["baseFee"].(*big.Int)).To(Equal(baseFee)) Expect(block["baseFee"].(*big.Int)).To(Equal(baseFee))
}) })
It("Retrieves a block by number with uncles in correct order", func() {
block, err := api.GetBlockByNumber(ctx, londonBlockNum, false)
Expect(err).ToNot(HaveOccurred())
expectedUncles := []common.Hash{
test_helpers.MockLondonUncles[0].Hash(),
test_helpers.MockLondonUncles[1].Hash(),
}
Expect(block["uncles"]).To(Equal(expectedUncles))
Expect(block["sha3Uncles"]).To(Equal(test_helpers.MockLondonBlock.UncleHash()))
Expect(block["hash"]).To(Equal(test_helpers.MockLondonBlock.Hash()))
})
}) })
Describe("eth_getBlockByHash", func() { Describe("eth_getBlockByHash", func() {
@@ -374,6 +386,18 @@ var _ = Describe("API", func() {
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(block["baseFee"].(*big.Int)).To(Equal(baseFee)) Expect(block["baseFee"].(*big.Int)).To(Equal(baseFee))
}) })
It("Retrieves a block by hash with uncles in correct order", func() {
block, err := api.GetBlockByHash(ctx, test_helpers.MockLondonBlock.Hash(), false)
Expect(err).ToNot(HaveOccurred())
expectedUncles := []common.Hash{
test_helpers.MockLondonUncles[0].Hash(),
test_helpers.MockLondonUncles[1].Hash(),
}
Expect(block["uncles"]).To(Equal(expectedUncles))
Expect(block["sha3Uncles"]).To(Equal(test_helpers.MockLondonBlock.UncleHash()))
Expect(block["hash"]).To(Equal(test_helpers.MockLondonBlock.Hash()))
})
}) })
/* /*
+206 -184
View File
@@ -24,6 +24,8 @@ import (
"math/big" "math/big"
"time" "time"
validator "github.com/cerc-io/eth-ipfs-state-validator/v4/pkg"
ipfsethdb "github.com/cerc-io/ipfs-ethdb/v4/postgres"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus"
@@ -39,16 +41,13 @@ import (
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/statediff/indexer/models"
"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/pkg"
ipfsethdb "github.com/vulcanize/ipfs-ethdb/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/pkg/shared" "github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
) )
var ( var (
@@ -56,34 +55,44 @@ var (
errNegativeBlockNumber = errors.New("negative block number not supported") errNegativeBlockNumber = errors.New("negative block number not supported")
errHeaderHashNotFound = errors.New("header for hash not found") errHeaderHashNotFound = errors.New("header for hash not found")
errHeaderNotFound = errors.New("header not found") errHeaderNotFound = errors.New("header not found")
errMultipleHeadersForHash = errors.New("more than one headers for the given hash")
errTxHashNotFound = errors.New("transaction for hash not found")
errTxHashInMultipleBlocks = errors.New("transaction for hash found in more than one canonical block")
// 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
INNER JOIN public.blocks ON (header_cids.mh_key = blocks.key) FROM canonical_header_hash($1) AS block_hash
WHERE block_hash = (SELECT canonical_header_hash($1))` WHERE block_hash IS NOT NULL`
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, header_id, transaction_cids.block_number, index
FROM public.blocks, eth.transaction_cids
WHERE blocks.key = transaction_cids.mh_key WHERE blocks.key = transaction_cids.mh_key
AND transaction_cids.header_id = header_cids.block_hash AND blocks.block_number = transaction_cids.block_number
AND transaction_cids.tx_hash = $1` AND transaction_cids.tx_hash = $1
AND transaction_cids.header_id = (SELECT canonical_header_hash(transaction_cids.block_number))`
RetrieveCodeHashByLeafKeyAndBlockHash = `SELECT code_hash FROM eth.state_accounts, eth.state_cids, eth.header_cids 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`
) )
@@ -182,7 +191,23 @@ func (b *Backend) HeaderByNumber(ctx context.Context, blockNumber rpc.BlockNumbe
// HeaderByHash gets the header for the provided block hash // HeaderByHash gets the header for the provided block hash
func (b *Backend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { func (b *Backend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
_, headerRLP, err := b.IPLDRetriever.RetrieveHeaderByHash(hash) // Begin tx
tx, err := b.DB.Beginx()
if err != nil {
return nil, err
}
defer func() {
if p := recover(); p != nil {
shared.Rollback(tx)
panic(p)
} else if err != nil {
shared.Rollback(tx)
} else {
err = tx.Commit()
}
}()
_, headerRLP, err := b.IPLDRetriever.RetrieveHeaderByHash(tx, hash)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -215,6 +240,10 @@ func (b *Backend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.Bl
return nil, errors.New("invalid arguments; neither block nor hash specified") return nil, errors.New("invalid arguments; neither block nor hash specified")
} }
func (b *Backend) PendingBlockAndReceipts() (*types.Block, types.Receipts) {
return nil, nil
}
// GetTd gets the total difficulty at the given block hash // GetTd gets the total difficulty at the given block hash
func (b *Backend) GetTd(blockHash common.Hash) (*big.Int, error) { func (b *Backend) GetTd(blockHash common.Hash) (*big.Int, error) {
var tdStr string var tdStr string
@@ -229,6 +258,11 @@ func (b *Backend) GetTd(blockHash common.Hash) (*big.Int, error) {
return td, nil return td, nil
} }
// ChainConfig returns the active chain configuration.
func (b *Backend) ChainConfig() *params.ChainConfig {
return b.Config.ChainConfig
}
// CurrentBlock returns the current block // CurrentBlock returns the current block
func (b *Backend) CurrentBlock() (*types.Block, error) { func (b *Backend) CurrentBlock() (*types.Block, error) {
block, err := b.BlockByNumber(context.Background(), rpc.LatestBlockNumber) block, err := b.BlockByNumber(context.Background(), rpc.LatestBlockNumber)
@@ -267,7 +301,7 @@ func (b *Backend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.Blo
return nil, errors.New("invalid arguments; neither block nor hash specified") return nil, errors.New("invalid arguments; neither block nor hash specified")
} }
// BlockByNumber returns the requested canonical block. // BlockByNumber returns the requested canonical block
func (b *Backend) BlockByNumber(ctx context.Context, blockNumber rpc.BlockNumber) (*types.Block, error) { func (b *Backend) BlockByNumber(ctx context.Context, blockNumber rpc.BlockNumber) (*types.Block, error) {
var err error var err error
number := blockNumber.Int64() number := blockNumber.Int64()
@@ -289,6 +323,7 @@ func (b *Backend) BlockByNumber(ctx context.Context, blockNumber rpc.BlockNumber
if number < 0 { if number < 0 {
return nil, errNegativeBlockNumber return nil, errNegativeBlockNumber
} }
// Get the canonical hash // Get the canonical hash
canonicalHash, err := b.GetCanonicalHash(uint64(number)) canonicalHash, err := b.GetCanonicalHash(uint64(number))
if err != nil { if err != nil {
@@ -297,112 +332,12 @@ func (b *Backend) BlockByNumber(ctx context.Context, blockNumber rpc.BlockNumber
} }
return nil, err return nil, err
} }
// Retrieve all the CIDs for the block
// TODO: optimize this by retrieving iplds directly rather than the cids first (this is remanent from when we fetched iplds through ipfs blockservice interface)
headerCID, uncleCIDs, txCIDs, rctCIDs, err := b.Retriever.RetrieveBlockByHash(canonicalHash)
if err != nil {
if err == sql.ErrNoRows {
return nil, nil
}
return nil, err
}
// Begin tx return b.BlockByHash(ctx, canonicalHash)
tx, err := b.DB.Beginx()
if err != nil {
return nil, err
}
defer func() {
if p := recover(); p != nil {
shared.Rollback(tx)
panic(p)
} else if err != nil {
shared.Rollback(tx)
} else {
err = tx.Commit()
}
}()
// Fetch and decode the header IPLD
var headerIPLD models.IPLDModel
headerIPLD, err = b.Fetcher.FetchHeader(tx, headerCID)
if err != nil {
if err == sql.ErrNoRows {
return nil, nil
}
return nil, err
}
var header types.Header
err = rlp.DecodeBytes(headerIPLD.Data, &header)
if err != nil {
return nil, err
}
// Fetch and decode the uncle IPLDs
var uncleIPLDs []models.IPLDModel
uncleIPLDs, err = b.Fetcher.FetchUncles(tx, uncleCIDs)
if err != nil {
return nil, err
}
var uncles []*types.Header
for _, uncleIPLD := range uncleIPLDs {
var uncle types.Header
err = rlp.DecodeBytes(uncleIPLD.Data, &uncle)
if err != nil {
return nil, err
}
uncles = append(uncles, &uncle)
}
// Fetch and decode the transaction IPLDs
var txIPLDs []models.IPLDModel
txIPLDs, err = b.Fetcher.FetchTrxs(tx, txCIDs)
if err != nil {
return nil, err
}
var transactions []*types.Transaction
for _, txIPLD := range txIPLDs {
var transaction types.Transaction
err = transaction.UnmarshalBinary(txIPLD.Data)
if err != nil {
return nil, err
}
transactions = append(transactions, &transaction)
}
// Fetch and decode the receipt IPLDs
var rctIPLDs []models.IPLDModel
rctIPLDs, err = b.Fetcher.FetchRcts(tx, rctCIDs)
if err != nil {
return nil, err
}
var receipts []*types.Receipt
for _, rctIPLD := range rctIPLDs {
var receipt types.Receipt
nodeVal, err := DecodeLeafNode(rctIPLD.Data)
if err != nil {
return nil, err
}
err = receipt.UnmarshalBinary(nodeVal)
if err != nil {
return nil, err
}
receipts = append(receipts, &receipt)
}
// Compose everything together into a complete block
return types.NewBlock(&header, transactions, uncles, receipts, new(trie.Trie)), err
} }
// BlockByHash returns the requested block. When fullTx is true all transactions in the block are returned in full // BlockByHash returns the requested block
// detail, otherwise only the transaction hash is returned.
func (b *Backend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { func (b *Backend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
// Retrieve all the CIDs for the block
headerCID, uncleCIDs, txCIDs, rctCIDs, err := b.Retriever.RetrieveBlockByHash(hash)
if err != nil {
if err == sql.ErrNoRows {
return nil, nil
}
return nil, err
}
// Begin tx // Begin tx
tx, err := b.DB.Beginx() tx, err := b.DB.Beginx()
if err != nil { if err != nil {
@@ -419,105 +354,176 @@ func (b *Backend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Blo
} }
}() }()
// Fetch and decode the header IPLD // Fetch header
var headerIPLD models.IPLDModel header, err := b.GetHeaderByBlockHash(tx, hash)
headerIPLD, err = b.Fetcher.FetchHeader(tx, headerCID)
if err != nil { if err != nil {
log.Error("error fetching header: ", err)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
return nil, nil return nil, nil
} }
return nil, err return nil, err
} }
var header types.Header
err = rlp.DecodeBytes(headerIPLD.Data, &header) // Fetch uncles
if err != nil { uncles, err := b.GetUnclesByBlockHash(tx, hash)
if err != nil && err != sql.ErrNoRows {
log.Error("error fetching uncles: ", err)
return nil, err return nil, err
} }
// Fetch and decode the uncle IPLDs
var uncleIPLDs []models.IPLDModel // When num. of uncles = 2,
uncleIPLDs, err = b.Fetcher.FetchUncles(tx, uncleCIDs) // Check if calculated uncle hash matches the one in header
if err != nil { // If not, re-order the two uncles
if err == sql.ErrNoRows { // Assumption: Max num. of uncles in mainnet = 2
return nil, nil if len(uncles) == 2 {
uncleHash := types.CalcUncleHash(uncles)
if uncleHash != header.UncleHash {
uncles[0], uncles[1] = uncles[1], uncles[0]
uncleHash = types.CalcUncleHash(uncles)
// Check if uncle hash matches after re-ordering
if uncleHash != header.UncleHash {
log.Error("uncle hash mismatch for block hash: ", hash.Hex())
} }
}
}
// Fetch transactions
transactions, err := b.GetTransactionsByBlockHash(tx, hash)
if err != nil && err != sql.ErrNoRows {
log.Error("error fetching transactions: ", err)
return nil, err return nil, err
} }
var uncles []*types.Header
for _, uncleIPLD := range uncleIPLDs { // Fetch receipts
var uncle types.Header receipts, err := b.GetReceiptsByBlockHash(tx, hash)
err = rlp.DecodeBytes(uncleIPLD.Data, &uncle) if err != nil && err != sql.ErrNoRows {
if err != nil { log.Error("error fetching receipts: ", err)
return nil, err return nil, err
} }
uncles = append(uncles, &uncle)
} // Compose everything together into a complete block
// Fetch and decode the transaction IPLDs return types.NewBlock(header, transactions, uncles, receipts, new(trie.Trie)), err
var txIPLDs []models.IPLDModel }
txIPLDs, err = b.Fetcher.FetchTrxs(tx, txCIDs)
if err != nil { // GetHeaderByBlockHash retrieves header for a provided block hash
if err == sql.ErrNoRows { func (b *Backend) GetHeaderByBlockHash(tx *sqlx.Tx, hash common.Hash) (*types.Header, error) {
return nil, nil _, headerRLP, err := b.IPLDRetriever.RetrieveHeaderByHash(tx, hash)
}
return nil, err
}
var transactions []*types.Transaction
for _, txIPLD := range txIPLDs {
var transaction types.Transaction
err = transaction.UnmarshalBinary(txIPLD.Data)
if err != nil {
return nil, err
}
transactions = append(transactions, &transaction)
}
// Fetch and decode the receipt IPLDs
var rctIPLDs []models.IPLDModel
rctIPLDs, err = b.Fetcher.FetchRcts(tx, rctCIDs)
if err != nil {
if err == sql.ErrNoRows {
return nil, nil
}
return nil, err
}
var receipts []*types.Receipt
for _, rctIPLD := range rctIPLDs {
var receipt types.Receipt
nodeVal, err := DecodeLeafNode(rctIPLD.Data)
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = receipt.UnmarshalBinary(nodeVal) header := new(types.Header)
return header, rlp.DecodeBytes(headerRLP, header)
}
// GetUnclesByBlockHash retrieves uncles for a provided block hash
func (b *Backend) GetUnclesByBlockHash(tx *sqlx.Tx, hash common.Hash) ([]*types.Header, error) {
_, uncleBytes, err := b.IPLDRetriever.RetrieveUnclesByBlockHash(tx, hash)
if err != nil { if err != nil {
return nil, err return nil, err
} }
receipts = append(receipts, &receipt)
uncles := make([]*types.Header, len(uncleBytes))
for i, bytes := range uncleBytes {
var uncle types.Header
err = rlp.DecodeBytes(bytes, &uncle)
if err != nil {
return nil, err
} }
// Compose everything together into a complete block
return types.NewBlock(&header, transactions, uncles, receipts, new(trie.Trie)), err uncles[i] = &uncle
}
return uncles, nil
}
// GetTransactionsByBlockHash retrieves transactions for a provided block hash
func (b *Backend) GetTransactionsByBlockHash(tx *sqlx.Tx, hash common.Hash) (types.Transactions, error) {
_, transactionBytes, err := b.IPLDRetriever.RetrieveTransactionsByBlockHash(tx, hash)
if err != nil {
return nil, err
}
txs := make(types.Transactions, len(transactionBytes))
for i, txBytes := range transactionBytes {
var tx types.Transaction
if err := tx.UnmarshalBinary(txBytes); err != nil {
return nil, err
}
txs[i] = &tx
}
return txs, nil
}
// GetReceiptsByBlockHash retrieves receipts for a provided block hash
func (b *Backend) GetReceiptsByBlockHash(tx *sqlx.Tx, hash common.Hash) (types.Receipts, error) {
_, receiptBytes, txs, err := b.IPLDRetriever.RetrieveReceiptsByBlockHash(tx, hash)
if err != nil {
return nil, err
}
rcts := make(types.Receipts, len(receiptBytes))
for i, rctBytes := range receiptBytes {
rct := new(types.Receipt)
if err := rct.UnmarshalBinary(rctBytes); err != nil {
return nil, err
}
rct.TxHash = txs[i]
rcts[i] = rct
}
return rcts, nil
} }
// GetTransaction retrieves a tx by hash // GetTransaction retrieves a tx by hash
// It also returns the blockhash, blocknumber, and tx index associated with the transaction // It also returns the blockhash, blocknumber, and tx index associated with the transaction
func (b *Backend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) { func (b *Backend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
var tempTxStruct struct { type txRes struct {
Data []byte `db:"data"` Data []byte `db:"data"`
BlockHash string `db:"block_hash"` HeaderID string `db:"header_id"`
BlockNumber uint64 `db:"block_number"` BlockNumber uint64 `db:"block_number"`
Index uint64 `db:"index"` Index uint64 `db:"index"`
} }
if err := b.DB.Get(&tempTxStruct, RetrieveRPCTransaction, txHash.String()); err != nil { var res = make([]txRes, 0)
if err := b.DB.Select(&res, RetrieveRPCTransaction, txHash.String()); err != nil {
return nil, common.Hash{}, 0, 0, err return nil, common.Hash{}, 0, 0, err
} }
if len(res) == 0 {
return nil, common.Hash{}, 0, 0, errTxHashNotFound
} else if len(res) > 1 {
// a transaction can be part of a only one canonical block
return nil, common.Hash{}, 0, 0, errTxHashInMultipleBlocks
}
var transaction types.Transaction var transaction types.Transaction
if err := transaction.UnmarshalBinary(tempTxStruct.Data); err != nil { if err := transaction.UnmarshalBinary(res[0].Data); err != nil {
return nil, common.Hash{}, 0, 0, err return nil, common.Hash{}, 0, 0, err
} }
return &transaction, common.HexToHash(tempTxStruct.BlockHash), tempTxStruct.BlockNumber, tempTxStruct.Index, nil
return &transaction, common.HexToHash(res[0].HeaderID), res[0].BlockNumber, res[0].Index, nil
} }
// GetReceipts retrieves receipts for provided block hash // GetReceipts retrieves receipts for provided block hash
func (b *Backend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { func (b *Backend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
_, receiptBytes, txs, err := b.IPLDRetriever.RetrieveReceiptsByBlockHash(hash) // Begin tx
tx, err := b.DB.Beginx()
if err != nil {
return nil, err
}
defer func() {
if p := recover(); p != nil {
shared.Rollback(tx)
panic(p)
} else if err != nil {
shared.Rollback(tx)
} else {
err = tx.Commit()
}
}()
_, receiptBytes, txs, err := b.IPLDRetriever.RetrieveReceiptsByBlockHash(tx, hash)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -534,8 +540,24 @@ func (b *Backend) GetReceipts(ctx context.Context, hash common.Hash) (types.Rece
} }
// GetLogs returns all the logs for the given block hash // GetLogs returns all the logs for the given block hash
func (b *Backend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) { func (b *Backend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) {
_, receiptBytes, txs, err := b.IPLDRetriever.RetrieveReceiptsByBlockHash(hash) // Begin tx
tx, err := b.DB.Beginx()
if err != nil {
return nil, err
}
defer func() {
if p := recover(); p != nil {
shared.Rollback(tx)
panic(p)
} else if err != nil {
shared.Rollback(tx)
} else {
err = tx.Commit()
}
}()
_, receiptBytes, txs, err := b.IPLDRetriever.RetrieveReceiptsByBlockHash(tx, hash)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -832,8 +854,8 @@ func (b *Backend) ValidateTrie(stateRoot common.Hash) error {
} }
// RPCGasCap returns the configured gas cap for the rpc server // RPCGasCap returns the configured gas cap for the rpc server
func (b *Backend) RPCGasCap() *big.Int { func (b *Backend) RPCGasCap() uint64 {
return b.Config.RPCGasCap return b.Config.RPCGasCap.Uint64()
} }
func (b *Backend) SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription { func (b *Backend) SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription {
+5
View File
@@ -166,6 +166,11 @@ func NewRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
result.TransactionIndex = (*hexutil.Uint64)(&index) result.TransactionIndex = (*hexutil.Uint64)(&index)
} }
switch tx.Type() { switch tx.Type() {
case types.LegacyTxType:
// if a legacy transaction has an EIP-155 chain id, include it explicitly
if id := tx.ChainId(); id.Sign() != 0 {
result.ChainID = (*hexutil.Big)(id)
}
case types.AccessListTxType: case types.AccessListTxType:
al := tx.AccessList() al := tx.AccessList()
result.Accesses = &al result.Accesses = &al
+221 -67
View File
@@ -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"
@@ -26,8 +27,10 @@ import (
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/lib/pq" "github.com/lib/pq"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"github.com/vulcanize/ipld-eth-server/pkg/shared" "github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
) )
// Retriever interface for substituting mocks in tests // Retriever interface for substituting mocks in tests
@@ -40,12 +43,74 @@ type Retriever interface {
// CIDRetriever satisfies the CIDRetriever interface for ethereum // CIDRetriever satisfies the CIDRetriever interface for ethereum
type CIDRetriever struct { type CIDRetriever struct {
db *sqlx.DB db *sqlx.DB
gormDB *gorm.DB
}
type IPLDModelRecord struct {
models.IPLDModel
}
// TableName overrides the table name used by IPLD
func (IPLDModelRecord) TableName() string {
return "public.blocks"
}
type HeaderCIDRecord struct {
CID string `gorm:"column:cid"`
BlockHash string `gorm:"primaryKey"`
BlockNumber string `gorm:"primaryKey"`
ParentHash string
Timestamp uint64
StateRoot string
TotalDifficulty string `gorm:"column:td"`
TxRoot string
RctRoot string `gorm:"column:receipt_root"`
UncleRoot string
Bloom []byte
MhKey string
// gorm doesn't check if foreign key exists in database.
// It is required to eager load relations using preload.
TransactionCIDs []TransactionCIDRecord `gorm:"foreignKey:HeaderID,BlockNumber;references:BlockHash,BlockNumber"`
IPLD IPLDModelRecord `gorm:"foreignKey:MhKey,BlockNumber;references:Key,BlockNumber"`
}
// TableName overrides the table name used by HeaderCIDRecord
func (HeaderCIDRecord) TableName() string {
return "eth.header_cids"
}
type TransactionCIDRecord struct {
CID string `gorm:"column:cid"`
TxHash string `gorm:"primaryKey"`
BlockNumber string `gorm:"primaryKey"`
HeaderID string `gorm:"column:header_id"`
Index int64
Src string
Dst string
MhKey string
IPLD IPLDModelRecord `gorm:"foreignKey:MhKey,BlockNumber;references:Key,BlockNumber"`
}
// TableName overrides the table name used by TransactionCIDRecord
func (TransactionCIDRecord) TableName() string {
return "eth.transaction_cids"
} }
// NewCIDRetriever returns a pointer to a new CIDRetriever which supports the CIDRetriever interface // NewCIDRetriever returns a pointer to a new CIDRetriever which supports the CIDRetriever interface
func NewCIDRetriever(db *sqlx.DB) *CIDRetriever { func NewCIDRetriever(db *sqlx.DB) *CIDRetriever {
gormDB, err := gorm.Open(postgres.New(postgres.Config{
Conn: db,
}), &gorm.Config{})
if err != nil {
log.Error(err)
return nil
}
return &CIDRetriever{ return &CIDRetriever{
db: db, db: db,
gormDB: gormDB,
} }
} }
@@ -59,7 +124,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
} }
@@ -126,7 +191,7 @@ func (ecr *CIDRetriever) Retrieve(filter SubscriptionSettings, blockNumber int64
} }
// Retrieve cached receipt CIDs // Retrieve cached receipt CIDs
if !filter.ReceiptFilter.Off { if !filter.ReceiptFilter.Off {
cw.Receipts, err = ecr.RetrieveRctCIDsByHeaderID(tx, filter.ReceiptFilter, header.BlockHash, trxHashes) cw.Receipts, err = ecr.RetrieveRctCIDs(tx, filter.ReceiptFilter, 0, header.BlockHash, trxHashes)
if err != nil { if err != nil {
log.Error("receipt cid retrieval error") log.Error("receipt cid retrieval error")
return nil, true, err return nil, true, err
@@ -167,9 +232,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 +243,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,9 +256,14 @@ 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, transaction_cids.tx_type
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) WHERE header_cids.block_hash = $%d`, id)
args = append(args, headerID) args = append(args, headerID)
id++ id++
@@ -287,41 +358,28 @@ func receiptFilterConditions(id *int, pgStr string, args []interface{}, rctFilte
return pgStr, args return pgStr, args
} }
// RetrieveRctCIDsByHeaderID retrieves and returns all of the rct cids at the provided header ID that conform to the provided // RetrieveFilteredGQLLogs retrieves and returns all the log CIDs provided blockHash that conform to the provided
// filter parameters and correspond to the provided tx ids
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)
args := make([]interface{}, 0, 4)
pgStr := `SELECT receipt_cids.tx_id, receipt_cids.leaf_cid, receipt_cids.leaf_mh_key,
receipt_cids.contract, receipt_cids.contract_hash
FROM eth.receipt_cids, eth.transaction_cids, eth.header_cids
WHERE receipt_cids.tx_id = transaction_cids.tx_hash
AND transaction_cids.header_id = header_cids.block_hash
AND header_cids.block_hash = $1`
id := 2
args = append(args, headerID)
pgStr, args = receiptFilterConditions(&id, pgStr, args, rctFilter, trxHashes)
pgStr += ` ORDER BY transaction_cids.index`
receiptCids := make([]models.ReceiptModel, 0)
return receiptCids, tx.Select(&receiptCids, pgStr, args...)
}
// 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 with block hash", blockHash.String())
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, eth.transaction_cids.index as txn_index, data,
eth.receipt_cids.leaf_cid as cid, eth.receipt_cids.post_status, header_cids.block_hash
FROM eth.log_cids, eth.receipt_cids, eth.transaction_cids, eth.header_cids, 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.header_id = eth.receipt_cids.header_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 receipt_cids.header_id = transaction_cids.header_id
AND receipt_cids.block_number = transaction_cids.block_number
AND transaction_cids.header_id = header_cids.block_hash AND transaction_cids.header_id = header_cids.block_hash
AND log_cids.leaf_mh_key = blocks.key AND header_cids.block_hash = $1` 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++
@@ -338,19 +396,24 @@ func (ecr *CIDRetriever) RetrieveFilteredGQLLogs(tx *sqlx.Tx, rctFilter ReceiptF
return logCIDs, nil return logCIDs, nil
} }
// RetrieveFilteredLog retrieves and returns all the log cIDs provided blockHeight or blockHash that conform to the provided // RetrieveFilteredLog retrieves and returns all the log CIDs provided blockHeight or blockHash that conform to the provided
// filter parameters. // filter parameters.
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) eth.receipt_cids.leaf_cid as cid, eth.receipt_cids.post_status, header_cids.block_hash
FROM eth.log_cids, eth.receipt_cids, eth.transaction_cids, eth.header_cids 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.header_id = eth.receipt_cids.header_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.header_id = transaction_cids.header_id
AND receipt_cids.block_number = transaction_cids.block_number
AND transaction_cids.header_id = header_cids.block_hash
AND transaction_cids.block_number = header_cids.block_number`
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)
@@ -377,30 +440,34 @@ func (ecr *CIDRetriever) RetrieveFilteredLog(tx *sqlx.Tx, rctFilter ReceiptFilte
// RetrieveRctCIDs retrieves and returns all of the rct cids at the provided blockheight or block hash that conform to the provided // RetrieveRctCIDs retrieves and returns all of the rct cids at the provided blockheight or block hash that conform to the provided
// filter parameters and correspond to the provided tx ids // filter parameters and correspond to the provided tx ids
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 string, 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.header_id, receipt_cids.tx_id,
receipt_cids.leaf_cid, 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 transaction_cids.header_id = header_cids.block_hash` AND receipt_cids.header_id = transaction_cids.header_id
AND receipt_cids.block_number = transaction_cids.block_number
AND transaction_cids.header_id = header_cids.block_hash
AND transaction_cids.block_number = header_cids.block_number`
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)
args = append(args, blockNumber) args = append(args, blockNumber)
id++ id++
} }
if blockHash != nil { if blockHash != "" {
pgStr += fmt.Sprintf(` AND header_cids.block_hash = $%d`, id) pgStr += fmt.Sprintf(` AND header_cids.block_hash = $%d`, id)
args = append(args, blockHash.String()) args = append(args, blockHash)
id++ id++
} }
pgStr, args = receiptFilterConditions(&id, pgStr, args, rctFilter, txHashes) pgStr, args = receiptFilterConditions(&id, pgStr, args, rctFilter, txHashes)
pgStr += ` ORDER BY transaction_cids.index` pgStr += ` ORDER BY transaction_cids.index`
receiptCids := make([]models.ReceiptModel, 0) receiptCIDs := make([]models.ReceiptModel, 0)
return receiptCids, tx.Select(&receiptCids, pgStr, args...) return receiptCIDs, tx.Select(&receiptCIDs, pgStr, args...)
} }
func hasTopics(topics [][]string) bool { func hasTopics(topics [][]string) bool {
@@ -416,9 +483,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 +512,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 +571,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 +582,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
@@ -513,7 +592,7 @@ func (ecr *CIDRetriever) RetrieveBlockByHash(blockHash common.Hash) (models.Head
txHashes[i] = txCID.TxHash txHashes[i] = txCID.TxHash
} }
var rctCIDs []models.ReceiptModel var rctCIDs []models.ReceiptModel
rctCIDs, err = ecr.RetrieveReceiptCIDsByTxIDs(tx, txHashes) rctCIDs, err = ecr.RetrieveReceiptCIDsByByHeaderIDAndTxIDs(tx, headerCID.BlockHash, txHashes, blockNumber)
if err != nil { if err != nil {
log.Error("rct cid retrieval error") log.Error("rct cid retrieval error")
} }
@@ -556,7 +635,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
@@ -566,7 +645,7 @@ func (ecr *CIDRetriever) RetrieveBlockByNumber(blockNumber int64) (models.Header
txHashes[i] = txCID.TxHash txHashes[i] = txCID.TxHash
} }
var rctCIDs []models.ReceiptModel var rctCIDs []models.ReceiptModel
rctCIDs, err = ecr.RetrieveReceiptCIDsByTxIDs(tx, txHashes) rctCIDs, err = ecr.RetrieveReceiptCIDsByByHeaderIDAndTxIDs(tx, headerCID[0].BlockHash, txHashes, blockNumber)
if err != nil { if err != nil {
log.Error("rct cid retrieval error") log.Error("rct cid retrieval error")
} }
@@ -576,31 +655,106 @@ 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), parent_hash, cid, mh_key, CAST(td as Text),
state_root, uncle_root, tx_root, receipt_root, bloom, timestamp 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 // RetrieveReceiptCIDsByByHeaderIDAndTxIDs retrieves receipt CIDs by their associated tx IDs for the given header id
func (ecr *CIDRetriever) RetrieveReceiptCIDsByTxIDs(tx *sqlx.Tx, txHashes []string) ([]models.ReceiptModel, error) { func (ecr *CIDRetriever) RetrieveReceiptCIDsByByHeaderIDAndTxIDs(tx *sqlx.Tx, headerID string, txHashes []string, blockNumber int64) ([]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.header_id, 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 FROM eth.receipt_cids, eth.transaction_cids
WHERE tx_id = ANY($1) WHERE tx_id = ANY($2)
AND receipt_cids.tx_id = transaction_cids.tx_hash AND receipt_cids.tx_id = transaction_cids.tx_hash
AND receipt_cids.header_id = transaction_cids.header_id
AND receipt_cids.block_number = transaction_cids.block_number
AND transaction_cids.header_id = $1
AND transaction_cids.block_number = $3
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, headerID, pq.Array(txHashes), blockNumber)
}
// RetrieveHeaderAndTxCIDsByBlockNumber retrieves header CIDs and their associated tx CIDs by block number
func (ecr *CIDRetriever) RetrieveHeaderAndTxCIDsByBlockNumber(blockNumber int64) ([]HeaderCIDRecord, error) {
log.Debug("retrieving header cids and tx cids for block number ", blockNumber)
var headerCIDs []HeaderCIDRecord
// https://github.com/go-gorm/gorm/issues/4083#issuecomment-778883283
// Will use join for TransactionCIDs once preload for 1:N is supported.
err := ecr.gormDB.Preload("TransactionCIDs", func(tx *gorm.DB) *gorm.DB {
return tx.Select("cid", "tx_hash", "index", "src", "dst", "header_id", "block_number")
}).Joins("IPLD").Find(&headerCIDs, "header_cids.block_number = ?", blockNumber).Error
if err != nil {
log.Error("header cid retrieval error")
return nil, err
}
return headerCIDs, nil
}
// RetrieveHeaderAndTxCIDsByBlockHash retrieves header CID and their associated tx CIDs by block hash
func (ecr *CIDRetriever) RetrieveHeaderAndTxCIDsByBlockHash(blockHash common.Hash) (HeaderCIDRecord, error) {
log.Debug("retrieving header cid and tx cids for block hash ", blockHash.String())
var headerCIDs []HeaderCIDRecord
// https://github.com/go-gorm/gorm/issues/4083#issuecomment-778883283
// Will use join for TransactionCIDs once preload for 1:N is supported.
err := ecr.gormDB.Preload("TransactionCIDs", func(tx *gorm.DB) *gorm.DB {
return tx.Select("cid", "tx_hash", "index", "src", "dst", "header_id", "block_number")
}).Joins("IPLD").Find(&headerCIDs, "block_hash = ?", blockHash.String()).Error
if err != nil {
log.Error("header cid retrieval error")
return HeaderCIDRecord{}, err
}
if len(headerCIDs) == 0 {
return HeaderCIDRecord{}, errHeaderHashNotFound
} else if len(headerCIDs) > 1 {
return HeaderCIDRecord{}, errMultipleHeadersForHash
}
return headerCIDs[0], nil
}
// RetrieveTxCIDByHash returns the tx for the given tx hash
func (ecr *CIDRetriever) RetrieveTxCIDByHash(txHash string) (TransactionCIDRecord, error) {
log.Debug("retrieving tx cid for tx hash ", txHash)
var txCIDs []TransactionCIDRecord
err := ecr.gormDB.Joins("IPLD").Find(&txCIDs, "tx_hash = ? AND transaction_cids.header_id = (SELECT canonical_header_hash(transaction_cids.block_number))", txHash).Error
if err != nil {
log.Error("header cid retrieval error")
return TransactionCIDRecord{}, err
}
if len(txCIDs) == 0 {
return TransactionCIDRecord{}, errTxHashNotFound
} else if len(txCIDs) > 1 {
// a transaction can be part of a only one canonical block
return TransactionCIDRecord{}, errTxHashInMultipleBlocks
}
return txCIDs[0], nil
} }
+8 -6
View File
@@ -19,6 +19,9 @@ package eth_test
import ( import (
"math/big" "math/big"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth/test_helpers"
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
@@ -28,9 +31,6 @@ import (
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
"github.com/vulcanize/ipld-eth-server/pkg/eth"
"github.com/vulcanize/ipld-eth-server/pkg/eth/test_helpers"
) )
var ( var (
@@ -215,13 +215,13 @@ var _ = Describe("Retriever", func() {
retriever *eth.CIDRetriever retriever *eth.CIDRetriever
) )
BeforeEach(func() { BeforeEach(func() {
db = eth.SetupTestDB() db = shared.SetupDB()
diffIndexer = eth.SetupTestStateDiffIndexer(ctx, params.TestChainConfig, test_helpers.Genesis.Hash()) diffIndexer = shared.SetupTestStateDiffIndexer(ctx, params.TestChainConfig, test_helpers.Genesis.Hash())
retriever = eth.NewCIDRetriever(db) retriever = eth.NewCIDRetriever(db)
}) })
AfterEach(func() { AfterEach(func() {
eth.TearDownTestDB(db) shared.TearDownDB(db)
}) })
Describe("Retrieve", func() { Describe("Retrieve", func() {
@@ -248,6 +248,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())
@@ -411,6 +412,7 @@ 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{
BlockNumber: "1",
HeaderID: cids7[0].StateNodes[0].HeaderID, HeaderID: cids7[0].StateNodes[0].HeaderID,
NodeType: 2, NodeType: 2,
StateKey: common.BytesToHash(test_helpers.AccountLeafKey).Hex(), StateKey: common.BytesToHash(test_helpers.AccountLeafKey).Hex(),
+8 -8
View File
@@ -23,6 +23,10 @@ import (
"math/big" "math/big"
"time" "time"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v4/pkg/eth/test_helpers"
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
ethServerShared "github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
"github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
@@ -36,10 +40,6 @@ import (
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
"github.com/vulcanize/ipld-eth-server/pkg/eth"
"github.com/vulcanize/ipld-eth-server/pkg/eth/test_helpers"
ethServerShared "github.com/vulcanize/ipld-eth-server/pkg/shared"
) )
var ( var (
@@ -74,8 +74,8 @@ var _ = Describe("eth state reading tests", func() {
It("test init", func() { It("test init", func() {
// db and type initializations // db and type initializations
var err error var err error
db = eth.SetupTestDB() db = shared.SetupDB()
transformer := eth.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash()) transformer := shared.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash())
backend, err = eth.NewEthBackend(db, &eth.Config{ backend, err = eth.NewEthBackend(db, &eth.Config{
ChainConfig: chainConfig, ChainConfig: chainConfig,
@@ -155,7 +155,7 @@ var _ = Describe("eth state reading tests", func() {
} }
// Insert some non-canonical data into the database so that we test our ability to discern canonicity // Insert some non-canonical data into the database so that we test our ability to discern canonicity
indexAndPublisher := eth.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash()) indexAndPublisher := shared.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash())
tx, err := indexAndPublisher.PushBlock(test_helpers.MockBlock, test_helpers.MockReceipts, test_helpers.MockBlock.Difficulty()) tx, err := indexAndPublisher.PushBlock(test_helpers.MockBlock, test_helpers.MockReceipts, test_helpers.MockBlock.Difficulty())
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@@ -181,7 +181,7 @@ var _ = Describe("eth state reading tests", func() {
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
}) })
defer It("test teardown", func() { defer It("test teardown", func() {
eth.TearDownTestDB(db) shared.TearDownDB(db)
chain.Stop() chain.Stop()
}) })
+5
View File
@@ -82,6 +82,7 @@ func (s *ResponseFilterer) filterHeaders(headerFilter HeaderFilter, response *IP
return err return err
} }
response.Header = models.IPLDModel{ response.Header = models.IPLDModel{
BlockNumber: payload.Block.Number().String(),
Data: headerRLP, Data: headerRLP,
Key: cid.String(), Key: cid.String(),
} }
@@ -97,6 +98,7 @@ func (s *ResponseFilterer) filterHeaders(headerFilter HeaderFilter, response *IP
return err return err
} }
response.Uncles[i] = models.IPLDModel{ response.Uncles[i] = models.IPLDModel{
BlockNumber: uncle.Number.String(),
Data: uncleRlp, Data: uncleRlp,
Key: cid.String(), Key: cid.String(),
} }
@@ -183,6 +185,7 @@ 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{
BlockNumber: payload.Block.Number().String(),
Data: rctIPLDData[idx], Data: rctIPLDData[idx],
Key: rctLeafCID[idx].String(), Key: rctLeafCID[idx].String(),
}) })
@@ -282,6 +285,7 @@ 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{
BlockNumber: payload.Block.Number().String(),
Data: stateNode.NodeValue, Data: stateNode.NodeValue,
Key: cid.String(), Key: cid.String(),
}, },
@@ -300,6 +304,7 @@ 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{
BlockNumber: payload.Block.Number().String(),
Data: storageNode.NodeValue, Data: storageNode.NodeValue,
Key: cid.String(), Key: cid.String(),
}, },
+11 -3
View File
@@ -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/pkg/eth" "github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/vulcanize/ipld-eth-server/pkg/eth/test_helpers" "github.com/cerc-io/ipld-eth-server/v4/pkg/eth/test_helpers"
"github.com/vulcanize/ipld-eth-server/pkg/shared" "github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
) )
var ( var (
@@ -61,12 +61,14 @@ 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{
BlockNumber: test_helpers.BlockNumber.String(),
Data: test_helpers.State2IPLD.RawData(), Data: test_helpers.State2IPLD.RawData(),
Key: test_helpers.State2IPLD.Cid().String(), 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{
BlockNumber: test_helpers.BlockNumber.String(),
Data: test_helpers.State1IPLD.RawData(), Data: test_helpers.State1IPLD.RawData(),
Key: test_helpers.State1IPLD.Cid().String(), Key: test_helpers.State1IPLD.Cid().String(),
})) }))
@@ -87,6 +89,7 @@ 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{
BlockNumber: test_helpers.BlockNumber.String(),
Data: test_helpers.Rct1IPLD, Data: test_helpers.Rct1IPLD,
Key: test_helpers.Rct1CID.String(), Key: test_helpers.Rct1CID.String(),
})) }))
@@ -102,6 +105,7 @@ 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{
BlockNumber: test_helpers.BlockNumber.String(),
Data: test_helpers.Rct1IPLD, Data: test_helpers.Rct1IPLD,
Key: test_helpers.Rct1CID.String(), Key: test_helpers.Rct1CID.String(),
})) }))
@@ -117,6 +121,7 @@ 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{
BlockNumber: test_helpers.BlockNumber.String(),
Data: test_helpers.Rct1IPLD, Data: test_helpers.Rct1IPLD,
Key: test_helpers.Rct1CID.String(), Key: test_helpers.Rct1CID.String(),
})) }))
@@ -132,6 +137,7 @@ 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{
BlockNumber: test_helpers.BlockNumber.String(),
Data: test_helpers.Rct2IPLD, Data: test_helpers.Rct2IPLD,
Key: test_helpers.Rct2CID.String(), Key: test_helpers.Rct2CID.String(),
})) }))
@@ -165,6 +171,7 @@ 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{
BlockNumber: test_helpers.BlockNumber.String(),
Data: test_helpers.Rct2IPLD, Data: test_helpers.Rct2IPLD,
Key: test_helpers.Rct2CID.String(), Key: test_helpers.Rct2CID.String(),
})) }))
@@ -181,6 +188,7 @@ 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{
BlockNumber: test_helpers.BlockNumber.String(),
Data: test_helpers.State2IPLD.RawData(), Data: test_helpers.State2IPLD.RawData(),
Key: test_helpers.State2IPLD.Cid().String(), Key: test_helpers.State2IPLD.Cid().String(),
})) }))
-47
View File
@@ -17,16 +17,7 @@
package eth package eth
import ( import (
"encoding/json"
"fmt"
"os"
"github.com/ethereum/go-ethereum/cmd/utils"
log "github.com/sirupsen/logrus"
sdtypes "github.com/ethereum/go-ethereum/statediff/types" sdtypes "github.com/ethereum/go-ethereum/statediff/types"
"github.com/ethereum/go-ethereum/params"
) )
func ResolveToNodeType(nodeType int) sdtypes.NodeType { func ResolveToNodeType(nodeType int) sdtypes.NodeType {
@@ -43,41 +34,3 @@ func ResolveToNodeType(nodeType int) sdtypes.NodeType {
return sdtypes.Unknown return sdtypes.Unknown
} }
} }
// LoadConfig loads chain config from json file
func LoadConfig(chainConfigPath string) (*params.ChainConfig, error) {
file, err := os.Open(chainConfigPath)
if err != nil {
utils.Fatalf("Failed to read chain config file: %v", err)
return nil, err
}
defer file.Close()
chainConfig := new(params.ChainConfig)
if err := json.NewDecoder(file).Decode(chainConfig); err != nil {
utils.Fatalf("invalid chain config file: %v", err)
return nil, err
}
log.Infof("Using chain config from %s file. Content %+v", chainConfigPath, chainConfig)
return chainConfig, nil
}
// ChainConfig returns the appropriate ethereum chain config for the provided chain id
func ChainConfig(chainID uint64) (*params.ChainConfig, error) {
switch chainID {
case 1:
return params.MainnetChainConfig, nil
case 3:
return params.RopstenChainConfig, nil
case 4:
return params.RinkebyChainConfig, nil
case 5:
return params.GoerliChainConfig, nil
default:
return nil, fmt.Errorf("chain config for chainid %d not available", chainID)
}
}
+40 -8
View File
@@ -20,12 +20,13 @@ import (
"errors" "errors"
"fmt" "fmt"
"math/big" "math/big"
"strconv"
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
"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/pkg/shared"
) )
// Fetcher interface for substituting mocks in tests // Fetcher interface for substituting mocks in tests
@@ -99,14 +100,20 @@ func (f *IPLDFetcher) Fetch(cids CIDWrapper) (*IPLDs, error) {
return iplds, err return iplds, err
} }
// FetchHeaders fetches headers // FetchHeader fetches header
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{
BlockNumber: c.BlockNumber,
Data: headerBytes, Data: headerBytes,
Key: c.CID, Key: c.CID,
}, nil }, nil
@@ -117,11 +124,16 @@ 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{
BlockNumber: c.BlockNumber,
Data: uncleBytes, Data: uncleBytes,
Key: c.CID, Key: c.CID,
} }
@@ -134,11 +146,16 @@ 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{
BlockNumber: c.BlockNumber,
Data: txBytes, Data: txBytes,
Key: c.CID, Key: c.CID,
} }
@@ -151,12 +168,17 @@ 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{
BlockNumber: c.BlockNumber,
Data: rctBytes, Data: rctBytes,
Key: c.LeafCID, Key: c.LeafCID,
} }
@@ -172,12 +194,17 @@ 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{
BlockNumber: stateNode.BlockNumber,
Data: stateBytes, Data: stateBytes,
Key: stateNode.CID, Key: stateNode.CID,
}, },
@@ -197,12 +224,17 @@ 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{
BlockNumber: storageNode.BlockNumber,
Data: storageBytes, Data: storageBytes,
Key: storageNode.CID, Key: storageNode.CID,
}, },
+6 -5
View File
@@ -23,8 +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/pkg/eth" "github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/vulcanize/ipld-eth-server/pkg/eth/test_helpers" "github.com/cerc-io/ipld-eth-server/v4/pkg/eth/test_helpers"
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
) )
var _ = Describe("IPLDFetcher", func() { var _ = Describe("IPLDFetcher", func() {
@@ -39,8 +40,8 @@ var _ = Describe("IPLDFetcher", func() {
err error err error
tx interfaces.Batch tx interfaces.Batch
) )
db = eth.SetupTestDB() db = shared.SetupDB()
pubAndIndexer = eth.SetupTestStateDiffIndexer(ctx, params.TestChainConfig, test_helpers.Genesis.Hash()) pubAndIndexer = shared.SetupTestStateDiffIndexer(ctx, params.TestChainConfig, test_helpers.Genesis.Hash())
tx, err = pubAndIndexer.PushBlock(test_helpers.MockBlock, test_helpers.MockReceipts, test_helpers.MockBlock.Difficulty()) tx, err = pubAndIndexer.PushBlock(test_helpers.MockBlock, test_helpers.MockReceipts, test_helpers.MockBlock.Difficulty())
for _, node := range test_helpers.MockStateNodes { for _, node := range test_helpers.MockStateNodes {
@@ -54,7 +55,7 @@ var _ = Describe("IPLDFetcher", func() {
}) })
AfterEach(func() { AfterEach(func() {
eth.TearDownTestDB(db) shared.TearDownDB(db)
}) })
It("Fetches and returns IPLDs for the CIDs provided in the CIDWrapper", func() { It("Fetches and returns IPLDs for the CIDs provided in the CIDWrapper", func() {
+195 -65
View File
@@ -18,7 +18,9 @@ package eth
import ( import (
"fmt" "fmt"
"strconv"
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
"github.com/ethereum/go-ethereum/statediff/trie_helpers" "github.com/ethereum/go-ethereum/statediff/trie_helpers"
sdtypes "github.com/ethereum/go-ethereum/statediff/types" sdtypes "github.com/ethereum/go-ethereum/statediff/types"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
@@ -31,130 +33,224 @@ import (
const ( const (
// node type removed value. // node type removed value.
// https://github.com/vulcanize/go-ethereum/blob/271f4d01e7e2767ffd8e0cd469bf545be96f2a84/statediff/indexer/helpers.go#L34 // https://github.com/cerc-io/go-ethereum/blob/271f4d01e7e2767ffd8e0cd469bf545be96f2a84/statediff/indexer/helpers.go#L34
removedNode = 3 removedNode = 3
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 (
WHERE block_number = $1` header_cids.mh_key = blocks.key
AND header_cids.block_number = blocks.block_number
)
WHERE header_cids.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
WHERE block_hash = $1` 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 header_cids.block_hash = $1
ORDER BY uncle_cids.parent_hash`
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
WHERE block_number = $1` 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 header_cids.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 DISTINCT ON (tx_hash) 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
WHERE block_number = $1 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 header_cids.block_number = $1
AND block_hash = (SELECT canonical_header_hash(header_cids.block_number))
ORDER BY eth.transaction_cids.index ASC` ORDER BY eth.transaction_cids.index ASC`
RetrieveTransactionByHashPgStr = `SELECT cid, data RetrieveTransactionByHashPgStr = `SELECT DISTINCT ON (tx_hash) 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
WHERE tx_hash = ANY($1::VARCHAR(66)[])` AND receipt_cids.header_id = transaction_cids.header_id
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)[])
AND transaction_cids.header_id = (SELECT canonical_header_hash(transaction_cids.block_number))`
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.header_id = transaction_cids.header_id
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.header_id = transaction_cids.header_id
WHERE block_number = $1 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 header_cids.block_number = $1
AND block_hash = (SELECT canonical_header_hash(header_cids.block_number))
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
WHERE tx_hash = $1` AND receipt_cids.header_id = transaction_cids.header_id
RetrieveAccountByLeafKeyAndBlockHashPgStr = `SELECT state_cids.cid, data, state_cids.node_type 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
AND transaction_cids.header_id = (SELECT canonical_header_hash(transaction_cids.block_number))`
RetrieveAccountByLeafKeyAndBlockHashPgStr = `SELECT state_cids.cid, state_cids.mh_key, state_cids.block_number, 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
)
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, state_cids.mh_key, 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
)
WHERE state_leaf_key = $1 WHERE state_leaf_key = $1
AND block_number <= $2 AND header_cids.block_number <= $2
ORDER BY block_number DESC ORDER BY header_cids.block_number DESC
LIMIT 1` LIMIT 1`
RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockNumberPgStr = `SELECT storage_cids.cid, data, storage_cids.node_type, was_state_leaf_removed($1, $3) AS state_leaf_removed RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockNumberPgStr = `SELECT storage_cids.cid, storage_cids.mh_key, storage_cids.node_type, was_state_leaf_removed($1, $3) AS state_leaf_removed
FROM eth.storage_cids FROM eth.storage_cids
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 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 header_cids.block_number <= $3
ORDER BY block_number DESC ORDER BY header_cids.block_number DESC
LIMIT 1` LIMIT 1`
RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr = `SELECT storage_cids.cid, data, storage_cids.node_type, was_state_leaf_removed($1, $3) AS state_leaf_removed RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr = `SELECT storage_cids.cid, storage_cids.mh_key, storage_cids.block_number, storage_cids.node_type, was_state_leaf_removed($1, $3) AS state_leaf_removed
FROM eth.storage_cids FROM eth.storage_cids
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 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`
) )
@@ -218,9 +314,9 @@ func (r *IPLDRetriever) RetrieveHeadersByBlockNumber(number uint64) ([]string, [
} }
// RetrieveHeaderByHash returns the cid and rlp bytes for the header corresponding to the provided block hash // RetrieveHeaderByHash returns the cid and rlp bytes for the header corresponding to the provided block hash
func (r *IPLDRetriever) RetrieveHeaderByHash(hash common.Hash) (string, []byte, error) { func (r *IPLDRetriever) RetrieveHeaderByHash(tx *sqlx.Tx, hash common.Hash) (string, []byte, error) {
headerResult := new(ipldResult) headerResult := new(ipldResult)
return headerResult.CID, headerResult.Data, r.db.Get(headerResult, RetrieveHeaderByHashPgStr, hash.Hex()) return headerResult.CID, headerResult.Data, tx.Get(headerResult, RetrieveHeaderByHashPgStr, hash.Hex())
} }
// RetrieveUnclesByHashes returns the cids and rlp bytes for the uncles corresponding to the provided uncle hashes // RetrieveUnclesByHashes returns the cids and rlp bytes for the uncles corresponding to the provided uncle hashes
@@ -243,9 +339,9 @@ func (r *IPLDRetriever) RetrieveUnclesByHashes(hashes []common.Hash) ([]string,
} }
// RetrieveUnclesByBlockHash returns the cids and rlp bytes for the uncles corresponding to the provided block hash (of non-omner root block) // RetrieveUnclesByBlockHash returns the cids and rlp bytes for the uncles corresponding to the provided block hash (of non-omner root block)
func (r *IPLDRetriever) RetrieveUnclesByBlockHash(hash common.Hash) ([]string, [][]byte, error) { func (r *IPLDRetriever) RetrieveUnclesByBlockHash(tx *sqlx.Tx, hash common.Hash) ([]string, [][]byte, error) {
uncleResults := make([]ipldResult, 0) uncleResults := make([]ipldResult, 0)
if err := r.db.Select(&uncleResults, RetrieveUnclesByBlockHashPgStr, hash.Hex()); err != nil { if err := tx.Select(&uncleResults, RetrieveUnclesByBlockHashPgStr, hash.Hex()); err != nil {
return nil, nil, err return nil, nil, err
} }
cids := make([]string, len(uncleResults)) cids := make([]string, len(uncleResults))
@@ -298,9 +394,9 @@ func (r *IPLDRetriever) RetrieveTransactionsByHashes(hashes []common.Hash) ([]st
} }
// RetrieveTransactionsByBlockHash returns the cids and rlp bytes for the transactions corresponding to the provided block hash // RetrieveTransactionsByBlockHash returns the cids and rlp bytes for the transactions corresponding to the provided block hash
func (r *IPLDRetriever) RetrieveTransactionsByBlockHash(hash common.Hash) ([]string, [][]byte, error) { func (r *IPLDRetriever) RetrieveTransactionsByBlockHash(tx *sqlx.Tx, hash common.Hash) ([]string, [][]byte, error) {
txResults := make([]ipldResult, 0) txResults := make([]ipldResult, 0)
if err := r.db.Select(&txResults, RetrieveTransactionsByBlockHashPgStr, hash.Hex()); err != nil { if err := tx.Select(&txResults, RetrieveTransactionsByBlockHashPgStr, hash.Hex()); err != nil {
return nil, nil, err return nil, nil, err
} }
cids := make([]string, len(txResults)) cids := make([]string, len(txResults))
@@ -375,9 +471,9 @@ func (r *IPLDRetriever) RetrieveReceiptsByTxHashes(hashes []common.Hash) ([]stri
// RetrieveReceiptsByBlockHash returns the cids and rlp bytes for the receipts corresponding to the provided block hash. // RetrieveReceiptsByBlockHash returns the cids and rlp bytes for the receipts corresponding to the provided block hash.
// cid returned corresponds to the leaf node data which contains the receipt. // cid returned corresponds to the leaf node data which contains the receipt.
func (r *IPLDRetriever) RetrieveReceiptsByBlockHash(hash common.Hash) ([]string, [][]byte, []common.Hash, error) { func (r *IPLDRetriever) RetrieveReceiptsByBlockHash(tx *sqlx.Tx, hash common.Hash) ([]string, [][]byte, []common.Hash, error) {
rctResults := make([]rctIpldResult, 0) rctResults := make([]rctIpldResult, 0)
if err := r.db.Select(&rctResults, RetrieveReceiptsByBlockHashPgStr, hash.Hex()); err != nil { if err := tx.Select(&rctResults, RetrieveReceiptsByBlockHashPgStr, hash.Hex()); err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }
cids := make([]string, len(rctResults)) cids := make([]string, len(rctResults))
@@ -434,6 +530,8 @@ func (r *IPLDRetriever) RetrieveReceiptByHash(hash common.Hash) (string, []byte,
type nodeInfo struct { type nodeInfo struct {
CID string `db:"cid"` CID string `db:"cid"`
MhKey string `db:"mh_key"`
BlockNumber string `db:"block_number"`
Data []byte `db:"data"` Data []byte `db:"data"`
NodeType int `db:"node_type"` NodeType int `db:"node_type"`
StateLeafRemoved bool `db:"state_leaf_removed"` StateLeafRemoved bool `db:"state_leaf_removed"`
@@ -452,6 +550,15 @@ func (r *IPLDRetriever) RetrieveAccountByAddressAndBlockHash(address common.Addr
return "", EmptyNodeValue, nil return "", EmptyNodeValue, nil
} }
blockNumber, err := strconv.ParseUint(accountResult.BlockNumber, 10, 64)
if err != nil {
return "", nil, err
}
accountResult.Data, err = shared.FetchIPLD(r.db, accountResult.MhKey, blockNumber)
if err != nil {
return "", nil, err
}
var i []interface{} var i []interface{}
if err := rlp.DecodeBytes(accountResult.Data, &i); err != nil { if err := rlp.DecodeBytes(accountResult.Data, &i); err != nil {
return "", nil, fmt.Errorf("error decoding state leaf node rlp: %s", err.Error()) return "", nil, fmt.Errorf("error decoding state leaf node rlp: %s", err.Error())
@@ -475,6 +582,12 @@ func (r *IPLDRetriever) RetrieveAccountByAddressAndBlockNumber(address common.Ad
return "", EmptyNodeValue, nil return "", EmptyNodeValue, nil
} }
var err error
accountResult.Data, err = shared.FetchIPLD(r.db, accountResult.MhKey, number)
if err != nil {
return "", nil, err
}
var i []interface{} var i []interface{}
if err := rlp.DecodeBytes(accountResult.Data, &i); err != nil { if err := rlp.DecodeBytes(accountResult.Data, &i); err != nil {
return "", nil, fmt.Errorf("error decoding state leaf node rlp: %s", err.Error()) return "", nil, fmt.Errorf("error decoding state leaf node rlp: %s", err.Error())
@@ -496,6 +609,16 @@ func (r *IPLDRetriever) RetrieveStorageAtByAddressAndStorageSlotAndBlockHash(add
if storageResult.StateLeafRemoved || storageResult.NodeType == removedNode { if storageResult.StateLeafRemoved || storageResult.NodeType == removedNode {
return "", EmptyNodeValue, EmptyNodeValue, nil return "", EmptyNodeValue, EmptyNodeValue, nil
} }
blockNumber, err := strconv.ParseUint(storageResult.BlockNumber, 10, 64)
if err != nil {
return "", nil, nil, err
}
storageResult.Data, err = shared.FetchIPLD(r.db, storageResult.MhKey, blockNumber)
if err != nil {
return "", nil, nil, err
}
var i []interface{} var i []interface{}
if err := rlp.DecodeBytes(storageResult.Data, &i); err != nil { if err := rlp.DecodeBytes(storageResult.Data, &i); err != nil {
err = fmt.Errorf("error decoding storage leaf node rlp: %s", err.Error()) err = fmt.Errorf("error decoding storage leaf node rlp: %s", err.Error())
@@ -519,6 +642,13 @@ func (r *IPLDRetriever) RetrieveStorageAtByAddressAndStorageKeyAndBlockNumber(ad
if storageResult.StateLeafRemoved || storageResult.NodeType == removedNode { if storageResult.StateLeafRemoved || storageResult.NodeType == removedNode {
return "", EmptyNodeValue, nil return "", EmptyNodeValue, nil
} }
var err error
storageResult.Data, err = shared.FetchIPLD(r.db, storageResult.MhKey, number)
if err != nil {
return "", nil, err
}
var i []interface{} var i []interface{}
if err := rlp.DecodeBytes(storageResult.Data, &i); err != nil { if err := rlp.DecodeBytes(storageResult.Data, &i); err != nil {
return "", nil, fmt.Errorf("error decoding storage leaf node rlp: %s", err.Error()) return "", nil, fmt.Errorf("error decoding storage leaf node rlp: %s", err.Error())
-70
View File
@@ -17,67 +17,9 @@
package eth package eth
import ( import (
"context"
"os"
"strconv"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/statediff/indexer"
"github.com/ethereum/go-ethereum/statediff/indexer/database/sql/postgres"
"github.com/ethereum/go-ethereum/statediff/indexer/interfaces"
"github.com/ethereum/go-ethereum/statediff/indexer/models" "github.com/ethereum/go-ethereum/statediff/indexer/models"
"github.com/ethereum/go-ethereum/statediff/indexer/node"
"github.com/jmoiron/sqlx"
. "github.com/onsi/gomega"
"github.com/vulcanize/ipld-eth-server/pkg/shared"
) )
func SetupTestDB() *sqlx.DB {
config := getTestDBConfig()
db, err := shared.NewDB(config.DbConnectionString(), config)
Expect(err).NotTo(HaveOccurred())
return db
}
// TearDownTestDB is used to tear down the watcher dbs after tests
func TearDownTestDB(db *sqlx.DB) {
tx, err := db.Beginx()
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.transaction_cids`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.receipt_cids`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.state_cids`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.storage_cids`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM blocks`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.log_cids`)
Expect(err).NotTo(HaveOccurred())
err = tx.Commit()
Expect(err).NotTo(HaveOccurred())
}
func SetupTestStateDiffIndexer(ctx context.Context, chainConfig *params.ChainConfig, genHash common.Hash) interfaces.StateDiffIndexer {
testInfo := node.Info{
GenesisBlock: genHash.String(),
NetworkID: "1",
ID: "1",
ClientName: "geth",
ChainID: params.TestChainConfig.ChainID.Uint64(),
}
stateDiffIndexer, err := indexer.NewStateDiffIndexer(ctx, chainConfig, testInfo, getTestDBConfig())
Expect(err).NotTo(HaveOccurred())
return stateDiffIndexer
}
// TxModelsContainsCID used to check if a list of TxModels contains a specific cid string // TxModelsContainsCID used to check if a list of TxModels contains a specific cid string
func TxModelsContainsCID(txs []models.TxModel, cid string) bool { func TxModelsContainsCID(txs []models.TxModel, cid string) bool {
for _, tx := range txs { for _, tx := range txs {
@@ -97,15 +39,3 @@ func ReceiptModelsContainsCID(rcts []models.ReceiptModel, cid string) bool {
} }
return false return false
} }
func getTestDBConfig() postgres.Config {
port, _ := strconv.Atoi(os.Getenv("DATABASE_PORT"))
return postgres.Config{
Hostname: os.Getenv("DATABASE_HOSTNAME"),
DatabaseName: os.Getenv("DATABASE_NAME"),
Username: os.Getenv("DATABASE_USER"),
Password: os.Getenv("DATABASE_PASSWORD"),
Port: port,
Driver: postgres.PGX,
}
}
+2 -1
View File
@@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/statediff/test_helpers"
) )
// Test variables // Test variables
@@ -35,7 +36,7 @@ var (
TestBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") TestBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
TestBankAddress = crypto.PubkeyToAddress(TestBankKey.PublicKey) //0x71562b71999873DB5b286dF957af199Ec94617F7 TestBankAddress = crypto.PubkeyToAddress(TestBankKey.PublicKey) //0x71562b71999873DB5b286dF957af199Ec94617F7
TestBankFunds = big.NewInt(100000000) TestBankFunds = big.NewInt(100000000)
Genesis = core.GenesisBlockForTesting(Testdb, TestBankAddress, TestBankFunds) Genesis = test_helpers.GenesisBlockForTesting(Testdb, TestBankAddress, TestBankFunds)
Account1Key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") Account1Key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
Account2Key, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") Account2Key, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
+56 -7
View File
@@ -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/pkg/eth" "github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
) )
// Test variables // Test variables
@@ -231,6 +231,7 @@ var (
} }
MockTrxMetaPostPublsh = []models.TxModel{ MockTrxMetaPostPublsh = []models.TxModel{
{ {
BlockNumber: "1",
CID: Trx1CID.String(), // This is empty until we go to publish to ipfs CID: Trx1CID.String(), // This is empty until we go to publish to ipfs
MhKey: Trx1MhKey, MhKey: Trx1MhKey,
Src: SenderAddr.Hex(), Src: SenderAddr.Hex(),
@@ -240,6 +241,7 @@ var (
Data: []byte{}, Data: []byte{},
}, },
{ {
BlockNumber: "1",
CID: Trx2CID.String(), CID: Trx2CID.String(),
MhKey: Trx2MhKey, MhKey: Trx2MhKey,
Src: SenderAddr.Hex(), Src: SenderAddr.Hex(),
@@ -249,6 +251,7 @@ var (
Data: []byte{}, Data: []byte{},
}, },
{ {
BlockNumber: "1",
CID: Trx3CID.String(), CID: Trx3CID.String(),
MhKey: Trx3MhKey, MhKey: Trx3MhKey,
Src: SenderAddr.Hex(), Src: SenderAddr.Hex(),
@@ -258,6 +261,7 @@ var (
Data: MockContractByteCode, Data: MockContractByteCode,
}, },
{ {
BlockNumber: "1",
CID: Trx4CID.String(), CID: Trx4CID.String(),
MhKey: Trx4MhKey, MhKey: Trx4MhKey,
Src: SenderAddr.Hex(), Src: SenderAddr.Hex(),
@@ -296,24 +300,32 @@ var (
MockRctMetaPostPublish = []models.ReceiptModel{ MockRctMetaPostPublish = []models.ReceiptModel{
{ {
BlockNumber: "1",
HeaderID: MockBlock.Hash().String(),
LeafCID: Rct1CID.String(), LeafCID: Rct1CID.String(),
LeafMhKey: Rct1MhKey, LeafMhKey: Rct1MhKey,
Contract: "", Contract: "",
ContractHash: "", ContractHash: "",
}, },
{ {
BlockNumber: "1",
HeaderID: MockBlock.Hash().String(),
LeafCID: Rct2CID.String(), LeafCID: Rct2CID.String(),
LeafMhKey: Rct2MhKey, LeafMhKey: Rct2MhKey,
Contract: "", Contract: "",
ContractHash: "", ContractHash: "",
}, },
{ {
BlockNumber: "1",
HeaderID: MockBlock.Hash().String(),
LeafCID: Rct3CID.String(), LeafCID: Rct3CID.String(),
LeafMhKey: Rct3MhKey, LeafMhKey: Rct3MhKey,
Contract: ContractAddress.String(), Contract: ContractAddress.String(),
ContractHash: ContractHash, ContractHash: ContractHash,
}, },
{ {
BlockNumber: "1",
HeaderID: MockBlock.Hash().String(),
LeafCID: Rct4CID.String(), LeafCID: Rct4CID.String(),
LeafMhKey: Rct4MhKey, LeafMhKey: Rct4MhKey,
Contract: "", Contract: "",
@@ -326,7 +338,7 @@ var (
StorageLeafKey = crypto.Keccak256Hash(storageLocation[:]).Bytes() StorageLeafKey = crypto.Keccak256Hash(storageLocation[:]).Bytes()
StorageValue = crypto.Keccak256([]byte{1, 2, 3, 4, 5}) StorageValue = crypto.Keccak256([]byte{1, 2, 3, 4, 5})
StoragePartialPath = common.Hex2Bytes("20290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563") StoragePartialPath = common.Hex2Bytes("20290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
StorageLeafNode, _ = rlp.EncodeToBytes([]interface{}{ StorageLeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
StoragePartialPath, StoragePartialPath,
StorageValue, StorageValue,
}) })
@@ -336,14 +348,14 @@ var (
ContractCodeHash = crypto.Keccak256Hash(MockContractByteCode) ContractCodeHash = crypto.Keccak256Hash(MockContractByteCode)
contractPath = common.Bytes2Hex([]byte{'\x06'}) contractPath = common.Bytes2Hex([]byte{'\x06'})
ContractLeafKey = testhelpers.AddressToLeafKey(ContractAddress) ContractLeafKey = testhelpers.AddressToLeafKey(ContractAddress)
ContractAccount, _ = rlp.EncodeToBytes(types.StateAccount{ ContractAccount, _ = rlp.EncodeToBytes(&types.StateAccount{
Nonce: nonce1, Nonce: nonce1,
Balance: big.NewInt(0), Balance: big.NewInt(0),
CodeHash: ContractCodeHash.Bytes(), CodeHash: ContractCodeHash.Bytes(),
Root: common.HexToHash(ContractRoot), Root: common.HexToHash(ContractRoot),
}) })
ContractPartialPath = common.Hex2Bytes("3114658a74d9cc9f7acf2c5cd696c3494d7c344d78bfec3add0d91ec4e8d1c45") ContractPartialPath = common.Hex2Bytes("3114658a74d9cc9f7acf2c5cd696c3494d7c344d78bfec3add0d91ec4e8d1c45")
ContractLeafNode, _ = rlp.EncodeToBytes([]interface{}{ ContractLeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
ContractPartialPath, ContractPartialPath,
ContractAccount, ContractAccount,
}) })
@@ -354,14 +366,14 @@ var (
AccountCodeHash = common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470") AccountCodeHash = common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
AccountAddresss = common.HexToAddress("0x0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e") AccountAddresss = common.HexToAddress("0x0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e")
AccountLeafKey = testhelpers.Account2LeafKey AccountLeafKey = testhelpers.Account2LeafKey
Account, _ = rlp.EncodeToBytes(types.StateAccount{ Account, _ = rlp.EncodeToBytes(&types.StateAccount{
Nonce: nonce0, Nonce: nonce0,
Balance: AccountBalance, Balance: AccountBalance,
CodeHash: AccountCodeHash.Bytes(), CodeHash: AccountCodeHash.Bytes(),
Root: common.HexToHash(AccountRoot), Root: common.HexToHash(AccountRoot),
}) })
AccountPartialPath = common.Hex2Bytes("3957f3e2f04a0764c3a0491b175f69926da61efbcc8f61fa1455fd2d2b4cdd45") AccountPartialPath = common.Hex2Bytes("3957f3e2f04a0764c3a0491b175f69926da61efbcc8f61fa1455fd2d2b4cdd45")
AccountLeafNode, _ = rlp.EncodeToBytes([]interface{}{ AccountLeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
AccountPartialPath, AccountPartialPath,
Account, Account,
}) })
@@ -391,6 +403,7 @@ var (
} }
MockStateMetaPostPublish = []models.StateNodeModel{ MockStateMetaPostPublish = []models.StateNodeModel{
{ {
BlockNumber: "1",
CID: State1CID.String(), CID: State1CID.String(),
MhKey: State1MhKey, MhKey: State1MhKey,
Path: []byte{'\x06'}, Path: []byte{'\x06'},
@@ -398,6 +411,7 @@ var (
StateKey: common.BytesToHash(ContractLeafKey).Hex(), StateKey: common.BytesToHash(ContractLeafKey).Hex(),
}, },
{ {
BlockNumber: "1",
CID: State2CID.String(), CID: State2CID.String(),
MhKey: State2MhKey, MhKey: State2MhKey,
Path: []byte{'\x0c'}, Path: []byte{'\x0c'},
@@ -461,6 +475,7 @@ var (
StateNodes: MockStateMetaPostPublish, StateNodes: MockStateMetaPostPublish,
StorageNodes: []models.StorageNodeWithStateKeyModel{ StorageNodes: []models.StorageNodeWithStateKeyModel{
{ {
BlockNumber: "1",
Path: []byte{}, Path: []byte{},
CID: StorageCID.String(), CID: StorageCID.String(),
MhKey: StorageMhKey, MhKey: StorageMhKey,
@@ -483,41 +498,50 @@ 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{
BlockNumber: BlockNumber.String(),
Data: HeaderIPLD.RawData(), Data: HeaderIPLD.RawData(),
Key: HeaderIPLD.Cid().String(), Key: HeaderIPLD.Cid().String(),
}, },
Transactions: []models.IPLDModel{ Transactions: []models.IPLDModel{
{ {
BlockNumber: BlockNumber.String(),
Data: Trx1IPLD.RawData(), Data: Trx1IPLD.RawData(),
Key: Trx1IPLD.Cid().String(), Key: Trx1IPLD.Cid().String(),
}, },
{ {
BlockNumber: BlockNumber.String(),
Data: Trx2IPLD.RawData(), Data: Trx2IPLD.RawData(),
Key: Trx2IPLD.Cid().String(), Key: Trx2IPLD.Cid().String(),
}, },
{ {
BlockNumber: BlockNumber.String(),
Data: Trx3IPLD.RawData(), Data: Trx3IPLD.RawData(),
Key: Trx3IPLD.Cid().String(), Key: Trx3IPLD.Cid().String(),
}, },
{ {
BlockNumber: BlockNumber.String(),
Data: Trx4IPLD.RawData(), Data: Trx4IPLD.RawData(),
Key: Trx4IPLD.Cid().String(), Key: Trx4IPLD.Cid().String(),
}, },
}, },
Receipts: []models.IPLDModel{ Receipts: []models.IPLDModel{
{ {
BlockNumber: BlockNumber.String(),
Data: Rct1IPLD, Data: Rct1IPLD,
Key: Rct1CID.String(), Key: Rct1CID.String(),
}, },
{ {
BlockNumber: BlockNumber.String(),
Data: Rct2IPLD, Data: Rct2IPLD,
Key: Rct2CID.String(), Key: Rct2CID.String(),
}, },
{ {
BlockNumber: BlockNumber.String(),
Data: Rct3IPLD, Data: Rct3IPLD,
Key: Rct3CID.String(), Key: Rct3CID.String(),
}, },
{ {
BlockNumber: BlockNumber.String(),
Data: Rct4IPLD, Data: Rct4IPLD,
Key: Rct4CID.String(), Key: Rct4CID.String(),
}, },
@@ -527,6 +551,7 @@ var (
StateLeafKey: common.BytesToHash(ContractLeafKey), StateLeafKey: common.BytesToHash(ContractLeafKey),
Type: sdtypes.Leaf, Type: sdtypes.Leaf,
IPLD: models.IPLDModel{ IPLD: models.IPLDModel{
BlockNumber: BlockNumber.String(),
Data: State1IPLD.RawData(), Data: State1IPLD.RawData(),
Key: State1IPLD.Cid().String(), Key: State1IPLD.Cid().String(),
}, },
@@ -536,6 +561,7 @@ var (
StateLeafKey: common.BytesToHash(AccountLeafKey), StateLeafKey: common.BytesToHash(AccountLeafKey),
Type: sdtypes.Leaf, Type: sdtypes.Leaf,
IPLD: models.IPLDModel{ IPLD: models.IPLDModel{
BlockNumber: BlockNumber.String(),
Data: State2IPLD.RawData(), Data: State2IPLD.RawData(),
Key: State2IPLD.Cid().String(), Key: State2IPLD.Cid().String(),
}, },
@@ -548,6 +574,7 @@ var (
StorageLeafKey: common.BytesToHash(StorageLeafKey), StorageLeafKey: common.BytesToHash(StorageLeafKey),
Type: sdtypes.Leaf, Type: sdtypes.Leaf,
IPLD: models.IPLDModel{ IPLD: models.IPLDModel{
BlockNumber: BlockNumber.String(),
Data: StorageIPLD.RawData(), Data: StorageIPLD.RawData(),
Key: StorageIPLD.Cid().String(), Key: StorageIPLD.Cid().String(),
}, },
@@ -567,7 +594,29 @@ var (
} }
MockLondonTransactions, MockLondonReceipts, _ = createDynamicTransactionsAndReceipts(LondonBlockNum) MockLondonTransactions, MockLondonReceipts, _ = createDynamicTransactionsAndReceipts(LondonBlockNum)
MockLondonBlock = createNewBlock(&MockLondonHeader, MockLondonTransactions, nil, MockLondonReceipts, new(trie.Trie)) MockLondonUncles = []*types.Header{
{
Time: 1,
Number: new(big.Int).Add(BlockNumber, big.NewInt(1)),
ParentHash: common.HexToHash("0x2"),
Root: common.HexToHash("0x1"),
TxHash: common.HexToHash("0x1"),
ReceiptHash: common.HexToHash("0x1"),
Difficulty: big.NewInt(500001),
Extra: []byte{},
},
{
Time: 2,
Number: new(big.Int).Add(BlockNumber, big.NewInt(1)),
ParentHash: common.HexToHash("0x1"),
Root: common.HexToHash("0x2"),
TxHash: common.HexToHash("0x2"),
ReceiptHash: common.HexToHash("0x2"),
Difficulty: big.NewInt(500002),
Extra: []byte{},
},
}
MockLondonBlock = createNewBlock(&MockLondonHeader, MockLondonTransactions, MockLondonUncles, MockLondonReceipts, new(trie.Trie))
) )
func createNewBlock(header *types.Header, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, hasher types.TrieHasher) *types.Block { func createNewBlock(header *types.Header, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, hasher types.TrieHasher) *types.Block {
+151 -3
View File
@@ -11,7 +11,7 @@ import (
) )
type StorageResponse struct { type StorageResponse struct {
Cid string `json:"cid"` CID string `json:"cid"`
Value common.Hash `json:"value"` Value common.Hash `json:"value"`
IpldBlock hexutil.Bytes `json:"ipldBlock"` IpldBlock hexutil.Bytes `json:"ipldBlock"`
} }
@@ -23,12 +23,12 @@ type GetStorageAt struct {
type LogResponse struct { type LogResponse struct {
Topics []common.Hash `json:"topics"` Topics []common.Hash `json:"topics"`
Data hexutil.Bytes `json:"data"` Data hexutil.Bytes `json:"data"`
Transaction TransactionResp `json:"transaction"` Transaction TransactionResponse `json:"transaction"`
ReceiptCID string `json:"receiptCID"` ReceiptCID string `json:"receiptCID"`
Status int32 `json:"status"` Status int32 `json:"status"`
} }
type TransactionResp struct { type TransactionResponse struct {
Hash common.Hash `json:"hash"` Hash common.Hash `json:"hash"`
} }
@@ -36,6 +36,52 @@ type GetLogs struct {
Responses []LogResponse `json:"getLogs"` Responses []LogResponse `json:"getLogs"`
} }
type IPFSBlockResponse struct {
Key string `json:"key"`
Data string `json:"data"`
}
type EthTransactionCIDResponse struct {
CID string `json:"cid"`
TxHash string `json:"txHash"`
Index int32 `json:"index"`
Src string `json:"src"`
Dst string `json:"dst"`
BlockByMhKey IPFSBlockResponse `json:"blockByMhKey"`
}
type EthTransactionCIDByTxHash struct {
Response EthTransactionCIDResponse `json:"ethTransactionCidByTxHash"`
}
type EthTransactionCIDsByHeaderIdResponse struct {
Nodes []EthTransactionCIDResponse `json:"nodes"`
}
type EthHeaderCIDResponse struct {
CID string `json:"cid"`
BlockNumber BigInt `json:"blockNumber"`
BlockHash string `json:"blockHash"`
ParentHash string `json:"parentHash"`
Timestamp BigInt `json:"timestamp"`
StateRoot string `json:"stateRoot"`
Td BigInt `json:"td"`
TxRoot string `json:"txRoot"`
ReceiptRoot string `json:"receiptRoot"`
UncleRoot string `json:"uncleRoot"`
Bloom string `json:"bloom"`
EthTransactionCIDsByHeaderId EthTransactionCIDsByHeaderIdResponse `json:"ethTransactionCidsByHeaderId"`
BlockByMhKey IPFSBlockResponse `json:"blockByMhKey"`
}
type AllEthHeaderCIDsResponse struct {
Nodes []EthHeaderCIDResponse `json:"nodes"`
}
type AllEthHeaderCIDs struct {
Response AllEthHeaderCIDsResponse `json:"allEthHeaderCids"`
}
type Client struct { type Client struct {
client *gqlclient.Client client *gqlclient.Client
} }
@@ -117,3 +163,105 @@ func (c *Client) GetStorageAt(ctx context.Context, hash common.Hash, address com
} }
return &storageAt.Response, nil return &storageAt.Response, nil
} }
func (c *Client) AllEthHeaderCIDs(ctx context.Context, condition EthHeaderCIDCondition) (*AllEthHeaderCIDsResponse, error) {
var params string
if condition.BlockHash != nil {
params = fmt.Sprintf(`blockHash: "%s"`, *condition.BlockHash)
}
if condition.BlockNumber != nil {
params += fmt.Sprintf(`blockNumber: "%s"`, condition.BlockNumber.String())
}
getHeadersQuery := fmt.Sprintf(`
query{
allEthHeaderCids(condition: { %s }) {
nodes {
cid
blockNumber
blockHash
parentHash
timestamp
stateRoot
td
txRoot
receiptRoot
uncleRoot
bloom
blockByMhKey {
key
data
}
ethTransactionCidsByHeaderId {
nodes {
cid
txHash
index
src
dst
}
}
}
}
}
`, params)
req := gqlclient.NewRequest(getHeadersQuery)
req.Header.Set("Cache-Control", "no-cache")
var respData map[string]interface{}
err := c.client.Run(ctx, req, &respData)
if err != nil {
return nil, err
}
jsonStr, err := json.Marshal(respData)
if err != nil {
return nil, err
}
var allEthHeaderCIDs AllEthHeaderCIDs
err = json.Unmarshal(jsonStr, &allEthHeaderCIDs)
if err != nil {
return nil, err
}
return &allEthHeaderCIDs.Response, nil
}
func (c *Client) EthTransactionCIDByTxHash(ctx context.Context, txHash string) (*EthTransactionCIDResponse, error) {
getTxQuery := fmt.Sprintf(`
query{
ethTransactionCidByTxHash(txHash: "%s") {
cid
txHash
index
src
dst
blockByMhKey {
data
}
}
}
`, txHash)
req := gqlclient.NewRequest(getTxQuery)
req.Header.Set("Cache-Control", "no-cache")
var respData map[string]interface{}
err := c.client.Run(ctx, req, &respData)
if err != nil {
return nil, err
}
jsonStr, err := json.Marshal(respData)
if err != nil {
return nil, err
}
var ethTxCID EthTransactionCIDByTxHash
err = json.Unmarshal(jsonStr, &ethTxCID)
if err != nil {
return nil, err
}
return &ethTxCID.Response, nil
}
+253 -6
View File
@@ -22,6 +22,8 @@ import (
"context" "context"
"database/sql" "database/sql"
"errors" "errors"
"fmt"
"strings"
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@@ -33,7 +35,8 @@ 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/pkg/eth" "github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
) )
var ( var (
@@ -774,8 +777,8 @@ func (b *Block) Logs(ctx context.Context, args struct{ Filter BlockFilterCriteri
hash = header.Hash() hash = header.Hash()
} }
// Construct the range filter // Construct the range filter
filter := filters.NewBlockFilter(b.backend, hash, addresses, topics) filterSys := filters.NewFilterSystem(b.backend, filters.Config{})
filter := filterSys.NewBlockFilter(hash, addresses, topics)
// Run the filter and return all the logs // Run the filter and return all the logs
return runFilter(ctx, b.backend, filter) return runFilter(ctx, b.backend, filter)
} }
@@ -835,7 +838,7 @@ func (b *Block) Call(ctx context.Context, args struct {
return nil, err return nil, err
} }
} }
result, err := eth.DoCall(ctx, b.backend, args.Data, *b.numberOrHash, nil, 5*time.Second, b.backend.RPCGasCap().Uint64()) result, err := eth.DoCall(ctx, b.backend, args.Data, *b.numberOrHash, nil, 5*time.Second, b.backend.RPCGasCap())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -977,7 +980,8 @@ func (r *Resolver) Logs(ctx context.Context, args struct{ Filter FilterCriteria
topics = *args.Filter.Topics topics = *args.Filter.Topics
} }
// Construct the range filter // Construct the range filter
filter := filters.NewRangeFilter(filters.Backend(r.backend), begin, end, addresses, topics) filterSys := filters.NewFilterSystem(r.backend, filters.Config{})
filter := filterSys.NewRangeFilter(begin, end, addresses, topics)
return runFilter(ctx, r.backend, filter) return runFilter(ctx, r.backend, filter)
} }
@@ -1017,7 +1021,7 @@ func (r *Resolver) GetStorageAt(ctx context.Context, args struct {
return nil, err return nil, err
} }
if bytes.Compare(rlpValue, eth.EmptyNodeValue) == 0 { if bytes.Equal(rlpValue, eth.EmptyNodeValue) {
return &StorageResult{value: eth.EmptyNodeValue, cid: cid, ipldBlock: ipldBlock}, nil return &StorageResult{value: eth.EmptyNodeValue, cid: cid, ipldBlock: ipldBlock}, nil
} }
@@ -1122,3 +1126,246 @@ func decomposeGQLLogs(logCIDs []eth.LogResult) []logsCID {
return logs return logs
} }
type EthTransactionCID struct {
cid string
txHash string
index int32
src string
dst string
ipfsBlock IPFSBlock
}
func (t EthTransactionCID) Cid(ctx context.Context) string {
return t.cid
}
func (t EthTransactionCID) TxHash(ctx context.Context) string {
return t.txHash
}
func (t EthTransactionCID) Index(ctx context.Context) int32 {
return t.index
}
func (t EthTransactionCID) Src(ctx context.Context) string {
return t.src
}
func (t EthTransactionCID) Dst(ctx context.Context) string {
return t.dst
}
func (t EthTransactionCID) BlockByMhKey(ctx context.Context) IPFSBlock {
return t.ipfsBlock
}
type EthTransactionCIDsConnection struct {
nodes []*EthTransactionCID
}
func (transactionCIDResult EthTransactionCIDsConnection) Nodes(ctx context.Context) []*EthTransactionCID {
return transactionCIDResult.nodes
}
type IPFSBlock struct {
key string
data string
}
func (b IPFSBlock) Key(ctx context.Context) string {
return b.key
}
func (b IPFSBlock) Data(ctx context.Context) string {
return b.data
}
type EthHeaderCID struct {
cid string
blockNumber BigInt
blockHash string
parentHash string
timestamp BigInt
stateRoot string
td BigInt
txRoot string
receiptRoot string
uncleRoot string
bloom string
transactions []*EthTransactionCID
ipfsBlock IPFSBlock
}
func (h EthHeaderCID) Cid(ctx context.Context) string {
return h.cid
}
func (h EthHeaderCID) BlockNumber(ctx context.Context) BigInt {
return h.blockNumber
}
func (h EthHeaderCID) BlockHash(ctx context.Context) string {
return h.blockHash
}
func (h EthHeaderCID) ParentHash(ctx context.Context) string {
return h.parentHash
}
func (h EthHeaderCID) Timestamp(ctx context.Context) BigInt {
return h.timestamp
}
func (h EthHeaderCID) StateRoot(ctx context.Context) string {
return h.stateRoot
}
func (h EthHeaderCID) Td(ctx context.Context) BigInt {
return h.td
}
func (h EthHeaderCID) TxRoot(ctx context.Context) string {
return h.txRoot
}
func (h EthHeaderCID) ReceiptRoot(ctx context.Context) string {
return h.receiptRoot
}
func (h EthHeaderCID) UncleRoot(ctx context.Context) string {
return h.uncleRoot
}
func (h EthHeaderCID) Bloom(ctx context.Context) string {
return h.bloom
}
func (h EthHeaderCID) EthTransactionCidsByHeaderId(ctx context.Context) EthTransactionCIDsConnection {
return EthTransactionCIDsConnection{nodes: h.transactions}
}
func (h EthHeaderCID) BlockByMhKey(ctx context.Context) IPFSBlock {
return h.ipfsBlock
}
type EthHeaderCIDsConnection struct {
nodes []*EthHeaderCID
}
func (headerCIDResult EthHeaderCIDsConnection) Nodes(ctx context.Context) []*EthHeaderCID {
return headerCIDResult.nodes
}
type EthHeaderCIDCondition struct {
BlockNumber *BigInt
BlockHash *string
}
func (r *Resolver) AllEthHeaderCids(ctx context.Context, args struct {
Condition *EthHeaderCIDCondition
}) (*EthHeaderCIDsConnection, error) {
var headerCIDs []eth.HeaderCIDRecord
var err error
if args.Condition.BlockHash != nil {
headerCID, err := r.backend.Retriever.RetrieveHeaderAndTxCIDsByBlockHash(common.HexToHash(*args.Condition.BlockHash))
if err != nil {
if !strings.Contains(err.Error(), "not found") {
return nil, err
}
} else {
headerCIDs = append(headerCIDs, headerCID)
}
} else if args.Condition.BlockNumber != nil {
headerCIDs, err = r.backend.Retriever.RetrieveHeaderAndTxCIDsByBlockNumber(args.Condition.BlockNumber.ToInt().Int64())
if err != nil {
return nil, err
}
} else {
return nil, fmt.Errorf("provide block number or block hash")
}
// Begin tx
tx, err := r.backend.DB.Beginx()
if err != nil {
return nil, err
}
defer func() {
if p := recover(); p != nil {
shared.Rollback(tx)
panic(p)
} else if err != nil {
shared.Rollback(tx)
} else {
err = tx.Commit()
}
}()
var resultNodes []*EthHeaderCID
for _, headerCID := range headerCIDs {
var blockNumber BigInt
blockNumber.UnmarshalText([]byte(headerCID.BlockNumber))
var timestamp BigInt
timestamp.SetUint64(headerCID.Timestamp)
var td BigInt
td.UnmarshalText([]byte(headerCID.TotalDifficulty))
ethHeaderCIDNode := EthHeaderCID{
cid: headerCID.CID,
blockNumber: blockNumber,
blockHash: headerCID.BlockHash,
parentHash: headerCID.ParentHash,
timestamp: timestamp,
stateRoot: headerCID.StateRoot,
td: td,
txRoot: headerCID.TxRoot,
receiptRoot: headerCID.RctRoot,
uncleRoot: headerCID.UncleRoot,
bloom: Bytes(headerCID.Bloom).String(),
ipfsBlock: IPFSBlock{
key: headerCID.IPLD.Key,
data: Bytes(headerCID.IPLD.Data).String(),
},
}
for _, txCID := range headerCID.TransactionCIDs {
ethHeaderCIDNode.transactions = append(ethHeaderCIDNode.transactions, &EthTransactionCID{
cid: txCID.CID,
txHash: txCID.TxHash,
index: int32(txCID.Index),
src: txCID.Src,
dst: txCID.Dst,
})
}
resultNodes = append(resultNodes, &ethHeaderCIDNode)
}
return &EthHeaderCIDsConnection{
nodes: resultNodes,
}, nil
}
func (r *Resolver) EthTransactionCidByTxHash(ctx context.Context, args struct {
TxHash string
}) (*EthTransactionCID, error) {
txCID, err := r.backend.Retriever.RetrieveTxCIDByHash(args.TxHash)
if err != nil {
return nil, err
}
return &EthTransactionCID{
cid: txCID.CID,
txHash: txCID.TxHash,
index: int32(txCID.Index),
src: txCID.Src,
dst: txCID.Dst,
ipfsBlock: IPFSBlock{
key: txCID.IPLD.Key,
data: Bytes(txCID.IPLD.Data).String(),
},
}, nil
}
+92 -10
View File
@@ -20,6 +20,7 @@ import (
"context" "context"
"fmt" "fmt"
"math/big" "math/big"
"strconv"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
@@ -35,10 +36,11 @@ import (
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
"github.com/vulcanize/ipld-eth-server/pkg/eth" "github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/vulcanize/ipld-eth-server/pkg/eth/test_helpers" "github.com/cerc-io/ipld-eth-server/v4/pkg/eth/test_helpers"
"github.com/vulcanize/ipld-eth-server/pkg/graphql" "github.com/cerc-io/ipld-eth-server/v4/pkg/graphql"
ethServerShared "github.com/vulcanize/ipld-eth-server/pkg/shared" "github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
ethServerShared "github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
) )
var _ = Describe("GraphQL", func() { var _ = Describe("GraphQL", func() {
@@ -65,8 +67,8 @@ var _ = Describe("GraphQL", func() {
It("test init", func() { It("test init", func() {
var err error var err error
db = eth.SetupTestDB() db = shared.SetupDB()
transformer := eth.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash()) transformer := shared.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash())
backend, err = eth.NewEthBackend(db, &eth.Config{ backend, err = eth.NewEthBackend(db, &eth.Config{
ChainConfig: chainConfig, ChainConfig: chainConfig,
@@ -130,7 +132,7 @@ var _ = Describe("GraphQL", func() {
} }
// Insert some non-canonical data into the database so that we test our ability to discern canonicity // Insert some non-canonical data into the database so that we test our ability to discern canonicity
indexAndPublisher := eth.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash()) indexAndPublisher := shared.SetupTestStateDiffIndexer(ctx, chainConfig, test_helpers.Genesis.Hash())
blockHash = test_helpers.MockBlock.Hash() blockHash = test_helpers.MockBlock.Hash()
contractAddress = test_helpers.ContractAddr contractAddress = test_helpers.ContractAddr
@@ -166,7 +168,7 @@ var _ = Describe("GraphQL", func() {
defer It("test teardown", func() { defer It("test teardown", func() {
err := graphQLServer.Stop() err := graphQLServer.Stop()
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
eth.TearDownTestDB(db) shared.TearDownDB(db)
chain.Stop() chain.Stop()
}) })
@@ -179,7 +181,7 @@ var _ = Describe("GraphQL", func() {
{ {
Topics: test_helpers.MockLog1.Topics, Topics: test_helpers.MockLog1.Topics,
Data: hexutil.Bytes(test_helpers.MockLog1.Data), Data: hexutil.Bytes(test_helpers.MockLog1.Data),
Transaction: graphql.TransactionResp{Hash: test_helpers.MockTransactions[0].Hash()}, Transaction: graphql.TransactionResponse{Hash: test_helpers.MockTransactions[0].Hash()},
ReceiptCID: test_helpers.Rct1CID.String(), ReceiptCID: test_helpers.Rct1CID.String(),
Status: int32(test_helpers.MockReceipts[0].Status), Status: int32(test_helpers.MockReceipts[0].Status),
}, },
@@ -196,7 +198,7 @@ var _ = Describe("GraphQL", func() {
{ {
Topics: test_helpers.MockLog6.Topics, Topics: test_helpers.MockLog6.Topics,
Data: hexutil.Bytes(test_helpers.MockLog6.Data), Data: hexutil.Bytes(test_helpers.MockLog6.Data),
Transaction: graphql.TransactionResp{Hash: test_helpers.MockTransactions[3].Hash()}, Transaction: graphql.TransactionResponse{Hash: test_helpers.MockTransactions[3].Hash()},
ReceiptCID: test_helpers.Rct4CID.String(), ReceiptCID: test_helpers.Rct4CID.String(),
Status: int32(test_helpers.MockReceipts[3].Status), Status: int32(test_helpers.MockReceipts[3].Status),
}, },
@@ -249,4 +251,84 @@ var _ = Describe("GraphQL", func() {
Expect(storageRes.Value).To(Equal(common.Hash{})) Expect(storageRes.Value).To(Equal(common.Hash{}))
}) })
}) })
Describe("allEthHeaderCids", func() {
It("Retrieves header_cids that matches the provided blockNumber", func() {
allEthHeaderCIDsResp, err := client.AllEthHeaderCIDs(ctx, graphql.EthHeaderCIDCondition{BlockNumber: new(graphql.BigInt).SetUint64(2)})
Expect(err).ToNot(HaveOccurred())
headerCIDs, err := backend.Retriever.RetrieveHeaderAndTxCIDsByBlockNumber(2)
Expect(err).ToNot(HaveOccurred())
for idx, headerCID := range headerCIDs {
ethHeaderCID := allEthHeaderCIDsResp.Nodes[idx]
compareEthHeaderCID(ethHeaderCID, headerCID)
}
})
It("Retrieves header_cids that matches the provided blockHash", func() {
blockHash := blocks[1].Hash().String()
allEthHeaderCIDsResp, err := client.AllEthHeaderCIDs(ctx, graphql.EthHeaderCIDCondition{BlockHash: &blockHash})
Expect(err).ToNot(HaveOccurred())
headerCID, err := backend.Retriever.RetrieveHeaderAndTxCIDsByBlockHash(blocks[1].Hash())
Expect(err).ToNot(HaveOccurred())
Expect(len(allEthHeaderCIDsResp.Nodes)).To(Equal(1))
ethHeaderCID := allEthHeaderCIDsResp.Nodes[0]
compareEthHeaderCID(ethHeaderCID, headerCID)
})
})
Describe("ethTransactionCidByTxHash", func() {
It("Retrieves tx_cid that matches the provided txHash", func() {
txHash := blocks[2].Transactions()[0].Hash().String()
ethTransactionCIDResp, err := client.EthTransactionCIDByTxHash(ctx, txHash)
Expect(err).ToNot(HaveOccurred())
txCID, err := backend.Retriever.RetrieveTxCIDByHash(txHash)
Expect(err).ToNot(HaveOccurred())
compareEthTxCID(*ethTransactionCIDResp, txCID)
Expect(ethTransactionCIDResp.BlockByMhKey.Data).To(Equal(graphql.Bytes(txCID.IPLD.Data).String()))
})
})
}) })
func compareEthHeaderCID(ethHeaderCID graphql.EthHeaderCIDResponse, headerCID eth.HeaderCIDRecord) {
blockNumber, err := strconv.ParseInt(headerCID.BlockNumber, 10, 64)
Expect(err).ToNot(HaveOccurred())
td, err := strconv.ParseInt(headerCID.TotalDifficulty, 10, 64)
Expect(err).ToNot(HaveOccurred())
Expect(ethHeaderCID.CID).To(Equal(headerCID.CID))
Expect(ethHeaderCID.BlockNumber).To(Equal(*new(graphql.BigInt).SetUint64(uint64(blockNumber))))
Expect(ethHeaderCID.BlockHash).To(Equal(headerCID.BlockHash))
Expect(ethHeaderCID.ParentHash).To(Equal(headerCID.ParentHash))
Expect(ethHeaderCID.Timestamp).To(Equal(*new(graphql.BigInt).SetUint64(headerCID.Timestamp)))
Expect(ethHeaderCID.StateRoot).To(Equal(headerCID.StateRoot))
Expect(ethHeaderCID.Td).To(Equal(*new(graphql.BigInt).SetUint64(uint64(td))))
Expect(ethHeaderCID.TxRoot).To(Equal(headerCID.TxRoot))
Expect(ethHeaderCID.ReceiptRoot).To(Equal(headerCID.RctRoot))
Expect(ethHeaderCID.UncleRoot).To(Equal(headerCID.UncleRoot))
Expect(ethHeaderCID.Bloom).To(Equal(graphql.Bytes(headerCID.Bloom).String()))
for tIdx, txCID := range headerCID.TransactionCIDs {
ethTxCID := ethHeaderCID.EthTransactionCIDsByHeaderId.Nodes[tIdx]
compareEthTxCID(ethTxCID, txCID)
}
Expect(ethHeaderCID.BlockByMhKey.Data).To(Equal(graphql.Bytes(headerCID.IPLD.Data).String()))
Expect(ethHeaderCID.BlockByMhKey.Key).To(Equal(headerCID.IPLD.Key))
}
func compareEthTxCID(ethTxCID graphql.EthTransactionCIDResponse, txCID eth.TransactionCIDRecord) {
Expect(ethTxCID.CID).To(Equal(txCID.CID))
Expect(ethTxCID.TxHash).To(Equal(txCID.TxHash))
Expect(ethTxCID.Index).To(Equal(int32(txCID.Index)))
Expect(ethTxCID.Src).To(Equal(txCID.Src))
Expect(ethTxCID.Dst).To(Equal(txCID.Dst))
}
+50 -2
View File
@@ -25,8 +25,7 @@ const schema string = `
# An empty byte string is represented as '0x'. Byte strings must have an even number of hexadecimal nybbles. # An empty byte string is represented as '0x'. Byte strings must have an even number of hexadecimal nybbles.
scalar Bytes scalar Bytes
# BigInt is a large integer. Input is accepted as either a JSON number or as a string. # BigInt is a large integer. Input is accepted as either a JSON number or as a string.
# Strings may be either decimal or 0x-prefixed hexadecimal. Output values are all # Input and output strings may be either decimal or 0x-prefixed hexadecimal depending upon the resolver implementation.
# 0x-prefixed hexadecimal.
scalar BigInt scalar BigInt
# Long is a 64 bit unsigned integer. # Long is a 64 bit unsigned integer.
scalar Long scalar Long
@@ -282,6 +281,49 @@ const schema string = `
ipldBlock: Bytes! ipldBlock: Bytes!
} }
input EthHeaderCidCondition {
blockNumber: BigInt
blockHash: String
}
type EthTransactionCid {
cid: String!
txHash: String!
index: Int!
src: String!
dst: String!
blockByMhKey: IPFSBlock!
}
type EthTransactionCidsConnection {
nodes: [EthTransactionCid]!
}
type IPFSBlock {
key: String!
data: String!
}
type EthHeaderCid {
cid: String!
blockNumber: BigInt!
blockHash: String!
parentHash: String!
timestamp: BigInt!
stateRoot: String!
td: BigInt!
txRoot: String!
receiptRoot: String!
uncleRoot: String!
bloom: String!
ethTransactionCidsByHeaderId: EthTransactionCidsConnection!
blockByMhKey: IPFSBlock!
}
type EthHeaderCidsConnection {
nodes: [EthHeaderCid]!
}
type Query { type Query {
# Block fetches an Ethereum block by number or by hash. If neither is # Block fetches an Ethereum block by number or by hash. If neither is
# supplied, the most recent known block is returned. # supplied, the most recent known block is returned.
@@ -302,5 +344,11 @@ const schema string = `
# Get contract logs by block hash and contract address. # Get contract logs by block hash and contract address.
getLogs(blockHash: Bytes32!, contract: Address): [Log!] getLogs(blockHash: Bytes32!, contract: Address): [Log!]
# PostGraphile alternative to get headers with transactions using block number or block hash.
allEthHeaderCids(condition: EthHeaderCidCondition): EthHeaderCidsConnection
# PostGraphile alternative to get transactions using transaction hash.
ethTransactionCidByTxHash(txHash: String!): EthTransactionCid
} }
` `
+2 -2
View File
@@ -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/pkg/eth" "github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
) )
// Service encapsulates a GraphQL service. // Service encapsulates a GraphQL service.
@@ -69,7 +69,7 @@ func (s *Service) Start(server *p2p.Server) error {
return err return err
} }
handler := node.NewHTTPHandlerStack(s.handler, s.cors, s.vhosts) handler := node.NewHTTPHandlerStack(s.handler, s.cors, s.vhosts, nil)
// start http server // start http server
_, addr, err := node.StartHTTPEndpoint(s.endpoint, rpc.DefaultHTTPTimeouts, handler) _, addr, err := node.StartHTTPEndpoint(s.endpoint, rpc.DefaultHTTPTimeouts, handler)
+122
View File
@@ -0,0 +1,122 @@
// 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 graphql
import (
"encoding/hex"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common/hexutil"
)
// Bytes marshals as a JSON string with \x prefix.
// The empty slice marshals as "\x".
type Bytes []byte
// MarshalText implements encoding.TextMarshaler
func (b Bytes) MarshalText() ([]byte, error) {
result := make([]byte, len(b)*2+2)
copy(result, `\x`)
hex.Encode(result[2:], b)
return result, nil
}
// String returns the hex encoding of b.
func (b Bytes) String() string {
return b.encode()
}
// Encode encodes b as a hex string with "\x" prefix.
// This is to make the output to be the same as given by postgraphile.
// graphql-go prepends another "\" to the output resulting in prefix "\\x".
func (b Bytes) encode() string {
result := make([]byte, len(b)*2+2)
copy(result, `\x`)
hex.Encode(result[2:], b)
return string(result)
}
type BigInt big.Int
// ToInt converts b to a big.Int.
func (b *BigInt) ToInt() *big.Int {
return (*big.Int)(b)
}
// String returns value of b as a decimal string.
func (b *BigInt) String() string {
return b.ToInt().String()
}
// SetUint64 sets b to x and returns x.
func (b *BigInt) SetUint64(x uint64) *BigInt {
var val big.Int
val.SetUint64(x)
*b = (BigInt)(val)
return b
}
// MarshalText implements encoding.TextMarshaler
func (b BigInt) MarshalText() ([]byte, error) {
return []byte(b.String()), nil
}
// UnmarshalText implements encoding.TextUnmarshaler
func (b *BigInt) UnmarshalText(input []byte) error {
raw, err := checkNumberText(input)
if err != nil {
return err
}
if len(raw) > 64 {
return hexutil.ErrBig256Range
}
var val big.Int
val.SetString(string(input[:]), 10)
*b = (BigInt)(val)
return nil
}
// ImplementsGraphQLType returns true if BigInt implements the provided GraphQL type.
func (b BigInt) ImplementsGraphQLType(name string) bool { return name == "BigInt" }
// UnmarshalGraphQL unmarshals the provided GraphQL query data.
func (b *BigInt) UnmarshalGraphQL(input interface{}) error {
var err error
switch input := input.(type) {
case string:
return b.UnmarshalText([]byte(input))
case int32:
var num big.Int
num.SetInt64(int64(input))
*b = BigInt(num)
default:
err = fmt.Errorf("unexpected type %T for BigInt", input)
}
return err
}
func checkNumberText(input []byte) (raw []byte, err error) {
if len(input) == 0 {
return nil, nil // empty strings are allowed
}
if len(input) > 1 && input[0] == '0' {
return nil, hexutil.ErrLeadingZero
}
return input, nil
}
+1 -1
View File
@@ -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/pkg/net" "github.com/cerc-io/ipld-eth-server/v4/pkg/net"
) )
var _ = Describe("API", func() { var _ = Describe("API", func() {
+2 -2
View File
@@ -29,11 +29,11 @@ import (
func StartHTTPEndpoint(endpoint string, apis []rpc.API, modules []string, cors []string, vhosts []string, timeouts rpc.HTTPTimeouts) (*rpc.Server, error) { func StartHTTPEndpoint(endpoint string, apis []rpc.API, modules []string, cors []string, vhosts []string, timeouts rpc.HTTPTimeouts) (*rpc.Server, error) {
srv := rpc.NewServer() srv := rpc.NewServer()
err := node.RegisterApis(apis, modules, srv, false) err := node.RegisterApis(apis, modules, srv)
if err != nil { if err != nil {
utils.Fatalf("Could not register HTTP API: %w", err) utils.Fatalf("Could not register HTTP API: %w", err)
} }
handler := node.NewHTTPHandlerStack(srv, cors, vhosts) handler := node.NewHTTPHandlerStack(srv, cors, vhosts, nil)
// start http server // start http server
_, addr, err := node.StartHTTPEndpoint(endpoint, rpc.DefaultHTTPTimeouts, handler) _, addr, err := node.StartHTTPEndpoint(endpoint, rpc.DefaultHTTPTimeouts, handler)
+2 -1
View File
@@ -25,7 +25,8 @@ 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/pkg/prom"
"github.com/cerc-io/ipld-eth-server/v4/pkg/prom"
) )
var ( var (
+3 -3
View File
@@ -24,11 +24,11 @@ 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/pkg/prom" "github.com/cerc-io/ipld-eth-server/v4/pkg/prom"
) )
// StartWSEndpoint starts a websocket endpoint. // StartWSEndpoint starts a websocket endpoint.
func StartWSEndpoint(endpoint string, apis []rpc.API, modules []string, wsOrigins []string, exposeAll bool) (net.Listener, *rpc.Server, error) { func StartWSEndpoint(endpoint string, apis []rpc.API, modules []string, wsOrigins []string) (net.Listener, *rpc.Server, error) {
// All APIs registered, start the HTTP listener // All APIs registered, start the HTTP listener
var ( var (
listener net.Listener listener net.Listener
@@ -37,7 +37,7 @@ func StartWSEndpoint(endpoint string, apis []rpc.API, modules []string, wsOrigin
// Register all the APIs exposed by the services // Register all the APIs exposed by the services
handler := rpc.NewServer() handler := rpc.NewServer()
err = node.RegisterApis(apis, modules, handler, exposeAll) err = node.RegisterApis(apis, modules, handler)
if err != nil { if err != nil {
utils.Fatalf("Could not register WS API: %w", err) utils.Fatalf("Could not register WS API: %w", err)
} }
+15 -2
View File
@@ -20,9 +20,10 @@ import (
"context" "context"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/statediff/types"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/vulcanize/ipld-eth-server/pkg/eth" "github.com/cerc-io/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
@@ -34,12 +35,14 @@ const APIVersion = "0.0.1"
// PublicServerAPI is the public api for the watcher // PublicServerAPI is the public api for the watcher
type PublicServerAPI struct { type PublicServerAPI struct {
w Server w Server
rpc *rpc.Client
} }
// NewPublicServerAPI creates a new PublicServerAPI with the provided underlying Server process // NewPublicServerAPI creates a new PublicServerAPI with the provided underlying Server process
func NewPublicServerAPI(w Server) *PublicServerAPI { func NewPublicServerAPI(w Server, client *rpc.Client) *PublicServerAPI {
return &PublicServerAPI{ return &PublicServerAPI{
w: w, w: w,
rpc: client,
} }
} }
@@ -81,3 +84,13 @@ func (api *PublicServerAPI) Stream(ctx context.Context, params eth.SubscriptionS
return rpcSub, nil return rpcSub, nil
} }
// WatchAddress makes a geth WatchAddress API call with the given operation and args
func (api *PublicServerAPI) WatchAddress(operation types.OperationType, args []types.WatchAddressArg) error {
err := api.rpc.Call(nil, "statediff_watchAddress", operation, args)
if err != nil {
return err
}
return nil
}
+8 -7
View File
@@ -27,14 +27,13 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/statediff"
"github.com/ethereum/go-ethereum/statediff/indexer/database/sql/postgres" "github.com/ethereum/go-ethereum/statediff/indexer/database/sql/postgres"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/vulcanize/ipld-eth-server/pkg/eth" "github.com/cerc-io/ipld-eth-server/v4/pkg/prom"
"github.com/vulcanize/ipld-eth-server/pkg/prom" ethServerShared "github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
"github.com/vulcanize/ipld-eth-server/pkg/shared"
ethServerShared "github.com/vulcanize/ipld-eth-server/pkg/shared"
) )
// Env variables // Env variables
@@ -202,7 +201,7 @@ func NewConfig() (*Config, error) {
c.IpldGraphqlEnabled = ipldGraphqlEnabled c.IpldGraphqlEnabled = ipldGraphqlEnabled
overrideDBConnConfig(&c.DBConfig) overrideDBConnConfig(&c.DBConfig)
serveDB, err := shared.NewDB(c.DBConfig.DbConnectionString(), c.DBConfig) serveDB, err := ethServerShared.NewDB(c.DBConfig.DbConnectionString(), c.DBConfig)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -220,12 +219,14 @@ func NewConfig() (*Config, error) {
if rpcGasCap, ok := new(big.Int).SetString(rpcGasCapStr, 10); ok { if rpcGasCap, ok := new(big.Int).SetString(rpcGasCapStr, 10); ok {
c.RPCGasCap = rpcGasCap c.RPCGasCap = rpcGasCap
} }
} else {
c.RPCGasCap = big.NewInt(0)
} }
chainConfigPath := viper.GetString("ethereum.chainConfig") chainConfigPath := viper.GetString("ethereum.chainConfig")
if chainConfigPath != "" { if chainConfigPath != "" {
c.ChainConfig, err = eth.LoadConfig(chainConfigPath) c.ChainConfig, err = statediff.LoadConfig(chainConfigPath)
} else { } else {
c.ChainConfig, err = eth.ChainConfig(nodeInfo.ChainID) c.ChainConfig, err = statediff.ChainConfig(nodeInfo.ChainID)
} }
c.loadGroupCacheConfig() c.loadGroupCacheConfig()
+14 -5
View File
@@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/tracers"
ethnode "github.com/ethereum/go-ethereum/node" ethnode "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
@@ -31,8 +32,9 @@ 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/pkg/eth" "github.com/cerc-io/ipld-eth-server/v4/pkg/debug"
"github.com/vulcanize/ipld-eth-server/pkg/net" "github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
"github.com/cerc-io/ipld-eth-server/v4/pkg/net"
) )
const ( const (
@@ -129,7 +131,7 @@ func (sap *Service) APIs() []rpc.API {
{ {
Namespace: APIName, Namespace: APIName,
Version: APIVersion, Version: APIVersion,
Service: NewPublicServerAPI(sap), Service: NewPublicServerAPI(sap, sap.client),
Public: true, Public: true,
}, },
{ {
@@ -139,16 +141,23 @@ func (sap *Service) APIs() []rpc.API {
Public: true, Public: true,
}, },
} }
ethAPI, err := eth.NewPublicEthAPI(sap.backend, sap.client, sap.supportsStateDiffing, sap.forwardEthCalls, sap.proxyOnError) ethAPI, err := eth.NewPublicEthAPI(sap.backend, sap.client, sap.supportsStateDiffing, sap.forwardEthCalls, sap.proxyOnError)
if err != nil { if err != nil {
log.Fatalf("unable to create public eth api: %v", err) log.Fatalf("unable to create public eth api: %v", err)
} }
return append(apis, rpc.API{
debugTracerAPI := tracers.APIs(&debug.Backend{Backend: *sap.backend})[0]
return append(apis,
rpc.API{
Namespace: eth.APIName, Namespace: eth.APIName,
Version: eth.APIVersion, Version: eth.APIVersion,
Service: ethAPI, Service: ethAPI,
Public: true, Public: true,
}) },
debugTracerAPI,
)
} }
// Serve listens for incoming converter data off the screenAndServePayload from the Sync process // Serve listens for incoming converter data off the screenAndServePayload from the Sync process
+9 -36
View File
@@ -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,18 @@ 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() var block []byte
raw := i.RawData() return block, tx.Get(&block, pgStr, mhKey, blockNumber)
_, 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 // FetchIPLD is used to retrieve an IPLD from Postgres mhkey and blockNumber
func FetchIPLD(tx *sqlx.Tx, cid string) ([]byte, error) { func FetchIPLD(db *sqlx.DB, mhKey string, blockNumber uint64) ([]byte, error) {
mhKey, err := MultihashKeyFromCIDString(cid) pgStr := `SELECT data FROM public.blocks WHERE key = $1 AND block_number = $2`
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, db.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 +77,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
}
+82
View File
@@ -18,8 +18,20 @@ package shared
import ( import (
"bytes" "bytes"
"context"
"os"
"strconv"
. "github.com/onsi/gomega"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/statediff/indexer"
"github.com/ethereum/go-ethereum/statediff/indexer/database/sql/postgres"
"github.com/ethereum/go-ethereum/statediff/indexer/interfaces"
"github.com/ethereum/go-ethereum/statediff/indexer/models" "github.com/ethereum/go-ethereum/statediff/indexer/models"
"github.com/ethereum/go-ethereum/statediff/indexer/node"
"github.com/jmoiron/sqlx"
) )
// IPLDsContainBytes used to check if a list of strings contains a particular string // IPLDsContainBytes used to check if a list of strings contains a particular string
@@ -31,3 +43,73 @@ func IPLDsContainBytes(iplds []models.IPLDModel, b []byte) bool {
} }
return false return false
} }
// SetupDB is use to setup a db for watcher tests
func SetupDB() *sqlx.DB {
config := getTestDBConfig()
db, err := NewDB(config.DbConnectionString(), config)
Expect(err).NotTo(HaveOccurred())
return db
}
// TearDownDB is used to tear down the watcher dbs after tests
func TearDownDB(db *sqlx.DB) {
tx, err := db.Beginx()
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM nodes`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.header_cids`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.uncle_cids`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.transaction_cids`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.receipt_cids`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.state_cids`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.storage_cids`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.state_accounts`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.access_list_elements`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM blocks`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.log_cids`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth_meta.watched_addresses`)
Expect(err).NotTo(HaveOccurred())
err = tx.Commit()
Expect(err).NotTo(HaveOccurred())
}
func SetupTestStateDiffIndexer(ctx context.Context, chainConfig *params.ChainConfig, genHash common.Hash) interfaces.StateDiffIndexer {
testInfo := node.Info{
GenesisBlock: genHash.String(),
NetworkID: "1",
ID: "1",
ClientName: "geth",
ChainID: params.TestChainConfig.ChainID.Uint64(),
}
_, stateDiffIndexer, err := indexer.NewStateDiffIndexer(ctx, chainConfig, testInfo, getTestDBConfig())
Expect(err).NotTo(HaveOccurred())
return stateDiffIndexer
}
func getTestDBConfig() postgres.Config {
port, _ := strconv.Atoi(os.Getenv("DATABASE_PORT"))
return postgres.Config{
Hostname: os.Getenv("DATABASE_HOSTNAME"),
DatabaseName: os.Getenv("DATABASE_NAME"),
Username: os.Getenv("DATABASE_USER"),
Password: os.Getenv("DATABASE_PASSWORD"),
Port: port,
Driver: postgres.SQLX,
}
}
-9
View File
@@ -3,17 +3,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_HTTP_PATH=""
export ETH_PROXY_ON_ERROR=false export ETH_PROXY_ON_ERROR=false
# Clear up existing docker images and volume.
docker-compose down --remove-orphans --volumes
# Build and start the containers.
# Note: Build only if `ipld-eth-server` or other container code is modified. Otherwise comment this line.
docker-compose -f docker-compose.test.yml -f docker-compose.yml build eth-server
docker-compose -f docker-compose.test.yml -f docker-compose.yml up -d ipld-eth-db dapptools contract eth-server
export PGPASSWORD=password export PGPASSWORD=password
export DATABASE_USER=vdbm export DATABASE_USER=vdbm
export DATABASE_PORT=8077 export DATABASE_PORT=8077
-9
View File
@@ -3,17 +3,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_HTTP_PATH="dapptools:8545"
export ETH_PROXY_ON_ERROR=false export ETH_PROXY_ON_ERROR=false
# Clear up existing docker images and volume.
docker-compose down --remove-orphans --volumes
# Build and start the containers.
# Note: Build only if `ipld-eth-server` or other container code is modified. Otherwise comment this line.
docker-compose -f docker-compose.test.yml -f docker-compose.yml build eth-server
docker-compose -f docker-compose.test.yml -f docker-compose.yml up -d ipld-eth-db dapptools contract eth-server
export PGPASSWORD=password export PGPASSWORD=password
export DATABASE_USER=vdbm export DATABASE_USER=vdbm
export DATABASE_PORT=8077 export DATABASE_PORT=8077
+13 -2
View File
@@ -1,5 +1,16 @@
# Clear up existing docker images and volume. #!/bin/bash
# Remove any existing containers / volumes
docker-compose down --remove-orphans --volumes docker-compose down --remove-orphans --volumes
docker-compose -f docker-compose.test.yml -f docker-compose.yml up -d ipld-eth-db # Spin up DB and run migrations
docker-compose up -d migrations ipld-eth-db
sleep 30
# Run unit tests
go clean -testcache
PGPASSWORD=password DATABASE_USER=vdbm DATABASE_PORT=8077 DATABASE_PASSWORD=password DATABASE_HOSTNAME=127.0.0.1 DATABASE_NAME=vulcanize_testing make test PGPASSWORD=password DATABASE_USER=vdbm DATABASE_PORT=8077 DATABASE_PASSWORD=password DATABASE_HOSTNAME=127.0.0.1 DATABASE_NAME=vulcanize_testing make test
# Clean up
docker-compose down --remove-orphans --volumes
rm -rf out/
+116 -12
View File
@@ -1,15 +1,119 @@
# Test Insructions
Spin up services: ## Setup
```
docker-compose -f docker-compose.test.yml -f docker-compose.yml up -d db dapptools contract eth-server
```
Running unit tests: - Clone [stack-orchestrator](https://github.com/vulcanize/stack-orchestrator), [ipld-eth-db](https://github.com/vulcanize/ipld-eth-db) [go-ethereum](https://github.com/vulcanize/go-ethereum) repositories.
```bash
make test_local
```
Running integration test: - Checkout [v4 release](https://github.com/vulcanize/ipld-eth-db/releases/tag/v4.2.1-alpha) in ipld-eth-db repo.
```bash ```bash
make integrationtest_local # In ipld-eth-db repo.
``` git checkout v4.2.1-alpha
```
- Checkout [v4 release](https://github.com/vulcanize/go-ethereum/releases/tag/v1.10.23-statediff-4.2.0-alpha) in go-ethereum repo.
```bash
# In go-ethereum repo.
git checkout v1.10.23-statediff-4.2.0-alpha
```
- Checkout working commit in stack-orchestrator repo.
```bash
# In stack-orchestrator repo.
git checkout f2fd766f5400fcb9eb47b50675d2e3b1f2753702
```
## Run
- Run unit tests:
```bash
# In ipld-eth-server root directory.
./scripts/run_unit_test.sh
```
- Run integration tests:
- In stack-orchestrator repo, create config file:
```bash
cd helper-scripts
./create-config.sh
```
A `config.sh` will be created in the root directory.
- Update/Edit the generated config file with:
```bash
#!/bin/bash
# Path to ipld-eth-server repo.
vulcanize_ipld_eth_db=~/ipld-eth-db/
# Path to go-ethereum repo.
vulcanize_go_ethereum=~/go-ethereum/
# Path to ipld-eth-server repo.
vulcanize_ipld_eth_server=~/ipld-eth-server/
# Path to test contract.
vulcanize_test_contract=~/ipld-eth-server/test/contract
genesis_file_path='start-up-files/go-ethereum/genesis.json'
db_write=true
eth_forward_eth_calls=false
eth_proxy_on_error=false
eth_http_path="go-ethereum:8545"
```
- Run stack-orchestrator:
```bash
# In stack-orchestrator root directory.
cd helper-scripts
./wrapper.sh \
-e docker \
-d ../docker/local/docker-compose-db-sharding.yml \
-d ../docker/local/docker-compose-go-ethereum.yml \
-d ../docker/local/docker-compose-ipld-eth-server.yml \
-d ../docker/local/docker-compose-contract.yml \
-v remove \
-p ../config.sh
```
- Run test:
```bash
# In ipld-eth-server root directory.
./scripts/run_integration_test.sh
```
- Update stack-orchestrator `config.sh` file:
```bash
#!/bin/bash
# Path to go-ethereum repo.
vulcanize_go_ethereum=~/go-ethereum/
# Path to ipld-eth-server repo.
vulcanize_ipld_eth_server=~/ipld-eth-server/
# Path to test contract.
vulcanize_test_contract=~/ipld-eth-server/test/contract
genesis_file_path='start-up-files/go-ethereum/genesis.json'
db_write=false
eth_forward_eth_calls=true
eth_proxy_on_error=false
eth_http_path="go-ethereum:8545"
```
- Stop the stack-orchestrator and start again using the same command
- Run integration tests for direct proxy fall-through of eth_calls:
```bash
./scripts/run_integration_test_forward_eth_calls.sh
```
+25
View File
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract SLVToken is ERC20 {
uint256 private countA;
uint256 private countB;
constructor() ERC20("Silver", "SLV") {}
function incrementCountA() public {
countA = countA + 1;
}
function incrementCountB() public {
countB = countB + 1;
}
receive() external payable {}
function destroy() public {
selfdestruct(payable(msg.sender));
}
}
+14 -3
View File
@@ -17,15 +17,26 @@ task("accounts", "Prints the list of accounts", async () => {
* @type import('hardhat/config').HardhatUserConfig * @type import('hardhat/config').HardhatUserConfig
*/ */
module.exports = { module.exports = {
solidity: "0.8.0", solidity: {
version: "0.8.0",
settings: {
outputSelection: {
'*': {
'*': [
'abi', 'storageLayout',
]
}
}
}
},
networks: { networks: {
local: { local: {
url: 'http://127.0.0.1:8545', url: 'http://127.0.0.1:8545',
chainId: 4 chainId: 99
}, },
docker: { docker: {
url: process.env.ETH_ADDR, url: process.env.ETH_ADDR,
chainId: 4 chainId: 99
} }
} }
}; };
+36 -88
View File
@@ -11,7 +11,8 @@
"dependencies": { "dependencies": {
"@openzeppelin/contracts": "^4.0.0", "@openzeppelin/contracts": "^4.0.0",
"fastify": "^3.14.2", "fastify": "^3.14.2",
"hardhat": "^2.2.0" "hardhat": "^2.2.0",
"solidity-create2-deployer": "^0.4.0"
}, },
"devDependencies": { "devDependencies": {
"@nomiclabs/hardhat-ethers": "^2.0.2", "@nomiclabs/hardhat-ethers": "^2.0.2",
@@ -469,7 +470,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.1.0.tgz",
"integrity": "sha512-N/W9Sbn1/C6Kh2kuHRjf/hX6euMK4+9zdJRBB8sDWmihVntjUAfxbusGZKzDQD8i3szAHhTz8K7XADV5iFNfJw==", "integrity": "sha512-N/W9Sbn1/C6Kh2kuHRjf/hX6euMK4+9zdJRBB8sDWmihVntjUAfxbusGZKzDQD8i3szAHhTz8K7XADV5iFNfJw==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -496,7 +496,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.1.0.tgz",
"integrity": "sha512-8dJUnT8VNvPwWhYIau4dwp7qe1g+KgdRm4XTWvjkI9gAT2zZa90WF5ApdZ3vl1r6NDmnn6vUVvyphClRZRteTQ==", "integrity": "sha512-8dJUnT8VNvPwWhYIau4dwp7qe1g+KgdRm4XTWvjkI9gAT2zZa90WF5ApdZ3vl1r6NDmnn6vUVvyphClRZRteTQ==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -521,7 +520,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.1.0.tgz",
"integrity": "sha512-qQDMkjGZSSJSKl6AnfTgmz9FSnzq3iEoEbHTYwjDlEAv+LNP7zd4ixCcVWlWyk+2siud856M5CRhAmPdupeN9w==", "integrity": "sha512-qQDMkjGZSSJSKl6AnfTgmz9FSnzq3iEoEbHTYwjDlEAv+LNP7zd4ixCcVWlWyk+2siud856M5CRhAmPdupeN9w==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -544,7 +542,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.1.0.tgz",
"integrity": "sha512-rfWQR12eHn2cpstCFS4RF7oGjfbkZb0oqep+BfrT+gWEGWG2IowJvIsacPOvzyS1jhNF4MQ4BS59B04Mbovteg==", "integrity": "sha512-rfWQR12eHn2cpstCFS4RF7oGjfbkZb0oqep+BfrT+gWEGWG2IowJvIsacPOvzyS1jhNF4MQ4BS59B04Mbovteg==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -567,7 +564,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.1.0.tgz",
"integrity": "sha512-npD1bLvK4Bcxz+m4EMkx+F8Rd7CnqS9DYnhNu0/GlQBXhWjvfoAZzk5HJ0f1qeyp8d+A86PTuzLOGOXf4/CN8g==", "integrity": "sha512-npD1bLvK4Bcxz+m4EMkx+F8Rd7CnqS9DYnhNu0/GlQBXhWjvfoAZzk5HJ0f1qeyp8d+A86PTuzLOGOXf4/CN8g==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -586,7 +582,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.1.0.tgz",
"integrity": "sha512-vBKr39bum7DDbOvkr1Sj19bRMEPA4FnST6Utt6xhDzI7o7L6QNkDn2yrCfP+hnvJGhZFKtLygWwqlTBZoBXYLg==", "integrity": "sha512-vBKr39bum7DDbOvkr1Sj19bRMEPA4FnST6Utt6xhDzI7o7L6QNkDn2yrCfP+hnvJGhZFKtLygWwqlTBZoBXYLg==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -606,7 +601,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.1.0.tgz",
"integrity": "sha512-wUvQlhTjPjFXIdLPOuTrFeQmSa6Wvls1bGXQNQWvB/SEn1NsTCE8PmumIEZxmOPjSHl1eV2uyHP5jBm5Cgj92Q==", "integrity": "sha512-wUvQlhTjPjFXIdLPOuTrFeQmSa6Wvls1bGXQNQWvB/SEn1NsTCE8PmumIEZxmOPjSHl1eV2uyHP5jBm5Cgj92Q==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -627,7 +621,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.1.0.tgz",
"integrity": "sha512-sGTxb+LVjFxJcJeUswAIK6ncgOrh3D8c192iEJd7mLr95V6du119rRfYT/b87WPkZ5I3gRBUYIYXtdgCWACe8g==", "integrity": "sha512-sGTxb+LVjFxJcJeUswAIK6ncgOrh3D8c192iEJd7mLr95V6du119rRfYT/b87WPkZ5I3gRBUYIYXtdgCWACe8g==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -646,7 +639,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.1.0.tgz",
"integrity": "sha512-0/SuHrxc8R8k+JiLmJymxHJbojUDWBQqO+b+XFdwaP0jGzqC09YDy/CAlSZB6qHsBifY8X3I89HcK/oMqxRdBw==", "integrity": "sha512-0/SuHrxc8R8k+JiLmJymxHJbojUDWBQqO+b+XFdwaP0jGzqC09YDy/CAlSZB6qHsBifY8X3I89HcK/oMqxRdBw==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -665,7 +657,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.1.0.tgz",
"integrity": "sha512-dvTMs/4XGSc57cYOW0KjgX1NdTujUu7mNb6PQdJWg08m9ULzPyGZuBkFJnijBcp6vTOCQ59RwjboWgNWw393og==", "integrity": "sha512-dvTMs/4XGSc57cYOW0KjgX1NdTujUu7mNb6PQdJWg08m9ULzPyGZuBkFJnijBcp6vTOCQ59RwjboWgNWw393og==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -693,7 +684,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.1.0.tgz",
"integrity": "sha512-fNwry20yLLPpnRRwm3fBL+2ksgO+KMadxM44WJmRIoTKzy4269+rbq9KFoe2LTqq2CXJM2CE70beGaNrpuqflQ==", "integrity": "sha512-fNwry20yLLPpnRRwm3fBL+2ksgO+KMadxM44WJmRIoTKzy4269+rbq9KFoe2LTqq2CXJM2CE70beGaNrpuqflQ==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -719,7 +709,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.1.0.tgz",
"integrity": "sha512-obIWdlujloExPHWJGmhJO/sETOOo7SEb6qemV4f8kyFoXg+cJK+Ta9SvBrj7hsUK85n3LZeZJZRjjM7oez3Clg==", "integrity": "sha512-obIWdlujloExPHWJGmhJO/sETOOo7SEb6qemV4f8kyFoXg+cJK+Ta9SvBrj7hsUK85n3LZeZJZRjjM7oez3Clg==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -749,7 +738,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.1.0.tgz",
"integrity": "sha512-00n2iBy27w8zrGZSiU762UOVuzCQZxUZxopsZC47++js6xUFuI74DHcJ5K/2pddlF1YBskvmMuboEu1geK8mnA==", "integrity": "sha512-00n2iBy27w8zrGZSiU762UOVuzCQZxUZxopsZC47++js6xUFuI74DHcJ5K/2pddlF1YBskvmMuboEu1geK8mnA==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -780,7 +768,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.1.0.tgz",
"integrity": "sha512-vrTB1W6AEYoadww5c9UyVJ2YcSiyIUTNDRccZIgwTmFFoSHwBtcvG1hqy9RzJ1T0bMdATbM9Hfx2mJ6H0i7Hig==", "integrity": "sha512-vrTB1W6AEYoadww5c9UyVJ2YcSiyIUTNDRccZIgwTmFFoSHwBtcvG1hqy9RzJ1T0bMdATbM9Hfx2mJ6H0i7Hig==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -799,14 +786,12 @@
"node_modules/@ethersproject/keccak256/node_modules/js-sha3": { "node_modules/@ethersproject/keccak256/node_modules/js-sha3": {
"version": "0.5.7", "version": "0.5.7",
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz",
"integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc="
"dev": true
}, },
"node_modules/@ethersproject/logger": { "node_modules/@ethersproject/logger": {
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.1.0.tgz",
"integrity": "sha512-wtUaD1lBX10HBXjjKV9VHCBnTdUaKQnQ2XSET1ezglqLdPdllNOIlLfhyCRqXm5xwcjExVI5ETokOYfjPtaAlw==", "integrity": "sha512-wtUaD1lBX10HBXjjKV9VHCBnTdUaKQnQ2XSET1ezglqLdPdllNOIlLfhyCRqXm5xwcjExVI5ETokOYfjPtaAlw==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -822,7 +807,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.1.0.tgz",
"integrity": "sha512-A/NIrIED/G/IgU1XUukOA3WcFRxn2I4O5GxsYGA5nFlIi+UZWdGojs85I1VXkR1gX9eFnDXzjE6OtbgZHjFhIA==", "integrity": "sha512-A/NIrIED/G/IgU1XUukOA3WcFRxn2I4O5GxsYGA5nFlIi+UZWdGojs85I1VXkR1gX9eFnDXzjE6OtbgZHjFhIA==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -841,7 +825,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.1.0.tgz",
"integrity": "sha512-B8cUbHHTgs8OtgJIafrRcz/YPDobVd5Ru8gTnShOiM9EBuFpYHQpq3+8iQJ6pyczDu6HP/oc/njAsIBhwFZYew==", "integrity": "sha512-B8cUbHHTgs8OtgJIafrRcz/YPDobVd5Ru8gTnShOiM9EBuFpYHQpq3+8iQJ6pyczDu6HP/oc/njAsIBhwFZYew==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -861,7 +844,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.1.0.tgz",
"integrity": "sha512-519KKTwgmH42AQL3+GFV3SX6khYEfHsvI6v8HYejlkigSDuqttdgVygFTDsGlofNFchhDwuclrxQnD5B0YLNMg==", "integrity": "sha512-519KKTwgmH42AQL3+GFV3SX6khYEfHsvI6v8HYejlkigSDuqttdgVygFTDsGlofNFchhDwuclrxQnD5B0YLNMg==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -880,7 +862,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.1.0.tgz",
"integrity": "sha512-FjpZL2lSXrYpQDg2fMjugZ0HjQD9a+2fOOoRhhihh+Z+qi/xZ8vIlPoumrEP1DzIG4DBV6liUqLNqnX2C6FIAA==", "integrity": "sha512-FjpZL2lSXrYpQDg2fMjugZ0HjQD9a+2fOOoRhhihh+Z+qi/xZ8vIlPoumrEP1DzIG4DBV6liUqLNqnX2C6FIAA==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -917,7 +898,6 @@
"version": "7.2.3", "version": "7.2.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz",
"integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==", "integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==",
"dev": true,
"engines": { "engines": {
"node": ">=8.3.0" "node": ">=8.3.0"
}, },
@@ -938,7 +918,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.1.0.tgz",
"integrity": "sha512-+uuczLQZ4+no9cP6TCoCktXx0u2YbNaRT7lRkSt12d8263e702f0u+4JnnRO8Qmv5nylWJebnqCHzyxP+6mLqw==", "integrity": "sha512-+uuczLQZ4+no9cP6TCoCktXx0u2YbNaRT7lRkSt12d8263e702f0u+4JnnRO8Qmv5nylWJebnqCHzyxP+6mLqw==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -958,7 +937,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.1.0.tgz",
"integrity": "sha512-vDTyHIwNPrecy55gKGZ47eJZhBm8LLBxihzi5ou+zrSvYTpkSTWRcKUlXFDFQVwfWB+P5PGyERAdiDEI76clxw==", "integrity": "sha512-vDTyHIwNPrecy55gKGZ47eJZhBm8LLBxihzi5ou+zrSvYTpkSTWRcKUlXFDFQVwfWB+P5PGyERAdiDEI76clxw==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -978,7 +956,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.1.0.tgz",
"integrity": "sha512-+fNSeZRstOpdRJpdGUkRONFCaiAqWkc91zXgg76Nlp5ndBQE25Kk5yK8gCPG1aGnCrbariiPr5j9DmrYH78JCA==", "integrity": "sha512-+fNSeZRstOpdRJpdGUkRONFCaiAqWkc91zXgg76Nlp5ndBQE25Kk5yK8gCPG1aGnCrbariiPr5j9DmrYH78JCA==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -999,7 +976,6 @@
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz",
"integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==",
"dev": true,
"dependencies": { "dependencies": {
"inherits": "^2.0.3", "inherits": "^2.0.3",
"minimalistic-assert": "^1.0.0" "minimalistic-assert": "^1.0.0"
@@ -1009,7 +985,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.1.0.tgz",
"integrity": "sha512-tE5LFlbmdObG8bY04NpuwPWSRPgEswfxweAI1sH7TbP0ml1elNfqcq7ii/3AvIN05i5U0Pkm3Tf8bramt8MmLw==", "integrity": "sha512-tE5LFlbmdObG8bY04NpuwPWSRPgEswfxweAI1sH7TbP0ml1elNfqcq7ii/3AvIN05i5U0Pkm3Tf8bramt8MmLw==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -1032,7 +1007,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.1.0.tgz",
"integrity": "sha512-kPodsGyo9zg1g9XSXp1lGhFaezBAUUsAUB1Vf6OkppE5Wksg4Et+x3kG4m7J/uShDMP2upkJtHNsIBK2XkVpKQ==", "integrity": "sha512-kPodsGyo9zg1g9XSXp1lGhFaezBAUUsAUB1Vf6OkppE5Wksg4Et+x3kG4m7J/uShDMP2upkJtHNsIBK2XkVpKQ==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -1055,7 +1029,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.1.0.tgz",
"integrity": "sha512-perBZy0RrmmL0ejiFGUOlBVjMsUceqLut3OBP3zP96LhiJWWbS8u1NqQVgN4/Gyrbziuda66DxiQocXhsvx+Sw==", "integrity": "sha512-perBZy0RrmmL0ejiFGUOlBVjMsUceqLut3OBP3zP96LhiJWWbS8u1NqQVgN4/Gyrbziuda66DxiQocXhsvx+Sw==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -1076,7 +1049,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.1.0.tgz",
"integrity": "sha512-s10crRLZEA0Bgv6FGEl/AKkTw9f+RVUrlWDX1rHnD4ZncPFeiV2AJr4nT7QSUhxJdFPvjyKRDb3nEH27dIqcPQ==", "integrity": "sha512-s10crRLZEA0Bgv6FGEl/AKkTw9f+RVUrlWDX1rHnD4ZncPFeiV2AJr4nT7QSUhxJdFPvjyKRDb3nEH27dIqcPQ==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -1103,7 +1075,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.1.0.tgz",
"integrity": "sha512-isvJrx6qG0nKWfxsGORNjmOq/nh175fStfvRTA2xEKrGqx8JNJY83fswu4GkILowfriEM/eYpretfJnfzi7YhA==", "integrity": "sha512-isvJrx6qG0nKWfxsGORNjmOq/nh175fStfvRTA2xEKrGqx8JNJY83fswu4GkILowfriEM/eYpretfJnfzi7YhA==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -1124,7 +1095,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.1.0.tgz",
"integrity": "sha512-ULmUtiYQLTUS+y3DgkLzRhFEK10zMwmjOthnjiZxee3Q/MVwr3rnmuAnXIUZrPjna6hvUPnyRIdW5XuF0Ld0YQ==", "integrity": "sha512-ULmUtiYQLTUS+y3DgkLzRhFEK10zMwmjOthnjiZxee3Q/MVwr3rnmuAnXIUZrPjna6hvUPnyRIdW5XuF0Ld0YQ==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -1157,7 +1127,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.1.0.tgz",
"integrity": "sha512-LTeluWgTq04+RNqAkVhpydPcRZK/kKxD2Vy7PYGrAD27ABO9kTqTBKwiOuzTyAHKUQHfnvZbXmxBXJAGViSDcA==", "integrity": "sha512-LTeluWgTq04+RNqAkVhpydPcRZK/kKxD2Vy7PYGrAD27ABO9kTqTBKwiOuzTyAHKUQHfnvZbXmxBXJAGViSDcA==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -1180,7 +1149,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.1.0.tgz",
"integrity": "sha512-NsUCi/TpBb+oTFvMSccUkJGtp5o/84eOyqp5q5aBeiNBSLkYyw21znRn9mAmxZgySpxgruVgKbaapnYPgvctPQ==", "integrity": "sha512-NsUCi/TpBb+oTFvMSccUkJGtp5o/84eOyqp5q5aBeiNBSLkYyw21znRn9mAmxZgySpxgruVgKbaapnYPgvctPQ==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -1630,8 +1598,7 @@
"node_modules/aes-js": { "node_modules/aes-js": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz",
"integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=", "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0="
"dev": true
}, },
"node_modules/agent-base": { "node_modules/agent-base": {
"version": "6.0.2", "version": "6.0.2",
@@ -1870,8 +1837,7 @@
"node_modules/bech32": { "node_modules/bech32": {
"version": "1.1.4", "version": "1.1.4",
"resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz",
"integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ=="
"dev": true
}, },
"node_modules/binary-extensions": { "node_modules/binary-extensions": {
"version": "2.2.0", "version": "2.2.0",
@@ -2774,7 +2740,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/ethers/-/ethers-5.1.0.tgz", "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.1.0.tgz",
"integrity": "sha512-2L6Ge6wMBw02FlRoCLg4E0Elt3khMNlW6ULawa10mMeeZToYJ5+uCfiuTuB+XZ6om1Y7wuO9ZzezP8FsU2M/+g==", "integrity": "sha512-2L6Ge6wMBw02FlRoCLg4E0Elt3khMNlW6ULawa10mMeeZToYJ5+uCfiuTuB+XZ6om1Y7wuO9ZzezP8FsU2M/+g==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -5427,7 +5392,7 @@
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"node-fetch": "^2.6.7", "node-fetch": "2.1.2",
"whatwg-fetch": "2.0.4" "whatwg-fetch": "2.0.4"
} }
}, },
@@ -7533,7 +7498,7 @@
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"node-fetch": "^2.6.7" "node-fetch": "~1.7.1"
} }
}, },
"node_modules/ganache-core/node_modules/fetch-ponyfill/node_modules/is-stream": { "node_modules/ganache-core/node_modules/fetch-ponyfill/node_modules/is-stream": {
@@ -7545,7 +7510,7 @@
} }
}, },
"node_modules/ganache-core/node_modules/fetch-ponyfill/node_modules/node-fetch": { "node_modules/ganache-core/node_modules/fetch-ponyfill/node_modules/node-fetch": {
"version": "2.6.7", "version": "1.7.3",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -9217,7 +9182,7 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/ganache-core/node_modules/node-fetch": { "node_modules/ganache-core/node_modules/node-fetch": {
"version": "2.6.7", "version": "2.1.2",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -14740,6 +14705,17 @@
"semver": "bin/semver" "semver": "bin/semver"
} }
}, },
"node_modules/solidity-create2-deployer": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/solidity-create2-deployer/-/solidity-create2-deployer-0.4.0.tgz",
"integrity": "sha512-bB5d8fPt4dWsOoRodrsyfWKcjiv77IFl84+e6EckMMGYlfL2ZFqUoMz6tnqqiUFrM9abF1p6dWFOgJ/3zVc8yQ==",
"dependencies": {
"ethers": "^5.0.14"
},
"engines": {
"node": ">=10"
}
},
"node_modules/sonic-boom": { "node_modules/sonic-boom": {
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz",
@@ -16056,7 +16032,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.1.0.tgz",
"integrity": "sha512-N/W9Sbn1/C6Kh2kuHRjf/hX6euMK4+9zdJRBB8sDWmihVntjUAfxbusGZKzDQD8i3szAHhTz8K7XADV5iFNfJw==", "integrity": "sha512-N/W9Sbn1/C6Kh2kuHRjf/hX6euMK4+9zdJRBB8sDWmihVntjUAfxbusGZKzDQD8i3szAHhTz8K7XADV5iFNfJw==",
"dev": true,
"requires": { "requires": {
"@ethersproject/address": "^5.1.0", "@ethersproject/address": "^5.1.0",
"@ethersproject/bignumber": "^5.1.0", "@ethersproject/bignumber": "^5.1.0",
@@ -16073,7 +16048,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.1.0.tgz",
"integrity": "sha512-8dJUnT8VNvPwWhYIau4dwp7qe1g+KgdRm4XTWvjkI9gAT2zZa90WF5ApdZ3vl1r6NDmnn6vUVvyphClRZRteTQ==", "integrity": "sha512-8dJUnT8VNvPwWhYIau4dwp7qe1g+KgdRm4XTWvjkI9gAT2zZa90WF5ApdZ3vl1r6NDmnn6vUVvyphClRZRteTQ==",
"dev": true,
"requires": { "requires": {
"@ethersproject/bignumber": "^5.1.0", "@ethersproject/bignumber": "^5.1.0",
"@ethersproject/bytes": "^5.1.0", "@ethersproject/bytes": "^5.1.0",
@@ -16088,7 +16062,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.1.0.tgz",
"integrity": "sha512-qQDMkjGZSSJSKl6AnfTgmz9FSnzq3iEoEbHTYwjDlEAv+LNP7zd4ixCcVWlWyk+2siud856M5CRhAmPdupeN9w==", "integrity": "sha512-qQDMkjGZSSJSKl6AnfTgmz9FSnzq3iEoEbHTYwjDlEAv+LNP7zd4ixCcVWlWyk+2siud856M5CRhAmPdupeN9w==",
"dev": true,
"requires": { "requires": {
"@ethersproject/abstract-provider": "^5.1.0", "@ethersproject/abstract-provider": "^5.1.0",
"@ethersproject/bignumber": "^5.1.0", "@ethersproject/bignumber": "^5.1.0",
@@ -16101,7 +16074,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.1.0.tgz",
"integrity": "sha512-rfWQR12eHn2cpstCFS4RF7oGjfbkZb0oqep+BfrT+gWEGWG2IowJvIsacPOvzyS1jhNF4MQ4BS59B04Mbovteg==", "integrity": "sha512-rfWQR12eHn2cpstCFS4RF7oGjfbkZb0oqep+BfrT+gWEGWG2IowJvIsacPOvzyS1jhNF4MQ4BS59B04Mbovteg==",
"dev": true,
"requires": { "requires": {
"@ethersproject/bignumber": "^5.1.0", "@ethersproject/bignumber": "^5.1.0",
"@ethersproject/bytes": "^5.1.0", "@ethersproject/bytes": "^5.1.0",
@@ -16114,7 +16086,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.1.0.tgz",
"integrity": "sha512-npD1bLvK4Bcxz+m4EMkx+F8Rd7CnqS9DYnhNu0/GlQBXhWjvfoAZzk5HJ0f1qeyp8d+A86PTuzLOGOXf4/CN8g==", "integrity": "sha512-npD1bLvK4Bcxz+m4EMkx+F8Rd7CnqS9DYnhNu0/GlQBXhWjvfoAZzk5HJ0f1qeyp8d+A86PTuzLOGOXf4/CN8g==",
"dev": true,
"requires": { "requires": {
"@ethersproject/bytes": "^5.1.0" "@ethersproject/bytes": "^5.1.0"
} }
@@ -16123,7 +16094,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.1.0.tgz",
"integrity": "sha512-vBKr39bum7DDbOvkr1Sj19bRMEPA4FnST6Utt6xhDzI7o7L6QNkDn2yrCfP+hnvJGhZFKtLygWwqlTBZoBXYLg==", "integrity": "sha512-vBKr39bum7DDbOvkr1Sj19bRMEPA4FnST6Utt6xhDzI7o7L6QNkDn2yrCfP+hnvJGhZFKtLygWwqlTBZoBXYLg==",
"dev": true,
"requires": { "requires": {
"@ethersproject/bytes": "^5.1.0", "@ethersproject/bytes": "^5.1.0",
"@ethersproject/properties": "^5.1.0" "@ethersproject/properties": "^5.1.0"
@@ -16133,7 +16103,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.1.0.tgz",
"integrity": "sha512-wUvQlhTjPjFXIdLPOuTrFeQmSa6Wvls1bGXQNQWvB/SEn1NsTCE8PmumIEZxmOPjSHl1eV2uyHP5jBm5Cgj92Q==", "integrity": "sha512-wUvQlhTjPjFXIdLPOuTrFeQmSa6Wvls1bGXQNQWvB/SEn1NsTCE8PmumIEZxmOPjSHl1eV2uyHP5jBm5Cgj92Q==",
"dev": true,
"requires": { "requires": {
"@ethersproject/bytes": "^5.1.0", "@ethersproject/bytes": "^5.1.0",
"@ethersproject/logger": "^5.1.0", "@ethersproject/logger": "^5.1.0",
@@ -16144,7 +16113,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.1.0.tgz",
"integrity": "sha512-sGTxb+LVjFxJcJeUswAIK6ncgOrh3D8c192iEJd7mLr95V6du119rRfYT/b87WPkZ5I3gRBUYIYXtdgCWACe8g==", "integrity": "sha512-sGTxb+LVjFxJcJeUswAIK6ncgOrh3D8c192iEJd7mLr95V6du119rRfYT/b87WPkZ5I3gRBUYIYXtdgCWACe8g==",
"dev": true,
"requires": { "requires": {
"@ethersproject/logger": "^5.1.0" "@ethersproject/logger": "^5.1.0"
} }
@@ -16153,7 +16121,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.1.0.tgz",
"integrity": "sha512-0/SuHrxc8R8k+JiLmJymxHJbojUDWBQqO+b+XFdwaP0jGzqC09YDy/CAlSZB6qHsBifY8X3I89HcK/oMqxRdBw==", "integrity": "sha512-0/SuHrxc8R8k+JiLmJymxHJbojUDWBQqO+b+XFdwaP0jGzqC09YDy/CAlSZB6qHsBifY8X3I89HcK/oMqxRdBw==",
"dev": true,
"requires": { "requires": {
"@ethersproject/bignumber": "^5.1.0" "@ethersproject/bignumber": "^5.1.0"
} }
@@ -16162,7 +16129,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.1.0.tgz",
"integrity": "sha512-dvTMs/4XGSc57cYOW0KjgX1NdTujUu7mNb6PQdJWg08m9ULzPyGZuBkFJnijBcp6vTOCQ59RwjboWgNWw393og==", "integrity": "sha512-dvTMs/4XGSc57cYOW0KjgX1NdTujUu7mNb6PQdJWg08m9ULzPyGZuBkFJnijBcp6vTOCQ59RwjboWgNWw393og==",
"dev": true,
"requires": { "requires": {
"@ethersproject/abi": "^5.1.0", "@ethersproject/abi": "^5.1.0",
"@ethersproject/abstract-provider": "^5.1.0", "@ethersproject/abstract-provider": "^5.1.0",
@@ -16180,7 +16146,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.1.0.tgz",
"integrity": "sha512-fNwry20yLLPpnRRwm3fBL+2ksgO+KMadxM44WJmRIoTKzy4269+rbq9KFoe2LTqq2CXJM2CE70beGaNrpuqflQ==", "integrity": "sha512-fNwry20yLLPpnRRwm3fBL+2ksgO+KMadxM44WJmRIoTKzy4269+rbq9KFoe2LTqq2CXJM2CE70beGaNrpuqflQ==",
"dev": true,
"requires": { "requires": {
"@ethersproject/abstract-signer": "^5.1.0", "@ethersproject/abstract-signer": "^5.1.0",
"@ethersproject/address": "^5.1.0", "@ethersproject/address": "^5.1.0",
@@ -16196,7 +16161,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.1.0.tgz",
"integrity": "sha512-obIWdlujloExPHWJGmhJO/sETOOo7SEb6qemV4f8kyFoXg+cJK+Ta9SvBrj7hsUK85n3LZeZJZRjjM7oez3Clg==", "integrity": "sha512-obIWdlujloExPHWJGmhJO/sETOOo7SEb6qemV4f8kyFoXg+cJK+Ta9SvBrj7hsUK85n3LZeZJZRjjM7oez3Clg==",
"dev": true,
"requires": { "requires": {
"@ethersproject/abstract-signer": "^5.1.0", "@ethersproject/abstract-signer": "^5.1.0",
"@ethersproject/basex": "^5.1.0", "@ethersproject/basex": "^5.1.0",
@@ -16216,7 +16180,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.1.0.tgz",
"integrity": "sha512-00n2iBy27w8zrGZSiU762UOVuzCQZxUZxopsZC47++js6xUFuI74DHcJ5K/2pddlF1YBskvmMuboEu1geK8mnA==", "integrity": "sha512-00n2iBy27w8zrGZSiU762UOVuzCQZxUZxopsZC47++js6xUFuI74DHcJ5K/2pddlF1YBskvmMuboEu1geK8mnA==",
"dev": true,
"requires": { "requires": {
"@ethersproject/abstract-signer": "^5.1.0", "@ethersproject/abstract-signer": "^5.1.0",
"@ethersproject/address": "^5.1.0", "@ethersproject/address": "^5.1.0",
@@ -16237,7 +16200,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.1.0.tgz",
"integrity": "sha512-vrTB1W6AEYoadww5c9UyVJ2YcSiyIUTNDRccZIgwTmFFoSHwBtcvG1hqy9RzJ1T0bMdATbM9Hfx2mJ6H0i7Hig==", "integrity": "sha512-vrTB1W6AEYoadww5c9UyVJ2YcSiyIUTNDRccZIgwTmFFoSHwBtcvG1hqy9RzJ1T0bMdATbM9Hfx2mJ6H0i7Hig==",
"dev": true,
"requires": { "requires": {
"@ethersproject/bytes": "^5.1.0", "@ethersproject/bytes": "^5.1.0",
"js-sha3": "0.5.7" "js-sha3": "0.5.7"
@@ -16246,22 +16208,19 @@
"js-sha3": { "js-sha3": {
"version": "0.5.7", "version": "0.5.7",
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz",
"integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc="
"dev": true
} }
} }
}, },
"@ethersproject/logger": { "@ethersproject/logger": {
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.1.0.tgz",
"integrity": "sha512-wtUaD1lBX10HBXjjKV9VHCBnTdUaKQnQ2XSET1ezglqLdPdllNOIlLfhyCRqXm5xwcjExVI5ETokOYfjPtaAlw==", "integrity": "sha512-wtUaD1lBX10HBXjjKV9VHCBnTdUaKQnQ2XSET1ezglqLdPdllNOIlLfhyCRqXm5xwcjExVI5ETokOYfjPtaAlw=="
"dev": true
}, },
"@ethersproject/networks": { "@ethersproject/networks": {
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.1.0.tgz",
"integrity": "sha512-A/NIrIED/G/IgU1XUukOA3WcFRxn2I4O5GxsYGA5nFlIi+UZWdGojs85I1VXkR1gX9eFnDXzjE6OtbgZHjFhIA==", "integrity": "sha512-A/NIrIED/G/IgU1XUukOA3WcFRxn2I4O5GxsYGA5nFlIi+UZWdGojs85I1VXkR1gX9eFnDXzjE6OtbgZHjFhIA==",
"dev": true,
"requires": { "requires": {
"@ethersproject/logger": "^5.1.0" "@ethersproject/logger": "^5.1.0"
} }
@@ -16270,7 +16229,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.1.0.tgz",
"integrity": "sha512-B8cUbHHTgs8OtgJIafrRcz/YPDobVd5Ru8gTnShOiM9EBuFpYHQpq3+8iQJ6pyczDu6HP/oc/njAsIBhwFZYew==", "integrity": "sha512-B8cUbHHTgs8OtgJIafrRcz/YPDobVd5Ru8gTnShOiM9EBuFpYHQpq3+8iQJ6pyczDu6HP/oc/njAsIBhwFZYew==",
"dev": true,
"requires": { "requires": {
"@ethersproject/bytes": "^5.1.0", "@ethersproject/bytes": "^5.1.0",
"@ethersproject/sha2": "^5.1.0" "@ethersproject/sha2": "^5.1.0"
@@ -16280,7 +16238,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.1.0.tgz",
"integrity": "sha512-519KKTwgmH42AQL3+GFV3SX6khYEfHsvI6v8HYejlkigSDuqttdgVygFTDsGlofNFchhDwuclrxQnD5B0YLNMg==", "integrity": "sha512-519KKTwgmH42AQL3+GFV3SX6khYEfHsvI6v8HYejlkigSDuqttdgVygFTDsGlofNFchhDwuclrxQnD5B0YLNMg==",
"dev": true,
"requires": { "requires": {
"@ethersproject/logger": "^5.1.0" "@ethersproject/logger": "^5.1.0"
} }
@@ -16289,7 +16246,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.1.0.tgz",
"integrity": "sha512-FjpZL2lSXrYpQDg2fMjugZ0HjQD9a+2fOOoRhhihh+Z+qi/xZ8vIlPoumrEP1DzIG4DBV6liUqLNqnX2C6FIAA==", "integrity": "sha512-FjpZL2lSXrYpQDg2fMjugZ0HjQD9a+2fOOoRhhihh+Z+qi/xZ8vIlPoumrEP1DzIG4DBV6liUqLNqnX2C6FIAA==",
"dev": true,
"requires": { "requires": {
"@ethersproject/abstract-provider": "^5.1.0", "@ethersproject/abstract-provider": "^5.1.0",
"@ethersproject/abstract-signer": "^5.1.0", "@ethersproject/abstract-signer": "^5.1.0",
@@ -16316,7 +16272,6 @@
"version": "7.2.3", "version": "7.2.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz",
"integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==", "integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==",
"dev": true,
"requires": {} "requires": {}
} }
} }
@@ -16325,7 +16280,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.1.0.tgz",
"integrity": "sha512-+uuczLQZ4+no9cP6TCoCktXx0u2YbNaRT7lRkSt12d8263e702f0u+4JnnRO8Qmv5nylWJebnqCHzyxP+6mLqw==", "integrity": "sha512-+uuczLQZ4+no9cP6TCoCktXx0u2YbNaRT7lRkSt12d8263e702f0u+4JnnRO8Qmv5nylWJebnqCHzyxP+6mLqw==",
"dev": true,
"requires": { "requires": {
"@ethersproject/bytes": "^5.1.0", "@ethersproject/bytes": "^5.1.0",
"@ethersproject/logger": "^5.1.0" "@ethersproject/logger": "^5.1.0"
@@ -16335,7 +16289,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.1.0.tgz",
"integrity": "sha512-vDTyHIwNPrecy55gKGZ47eJZhBm8LLBxihzi5ou+zrSvYTpkSTWRcKUlXFDFQVwfWB+P5PGyERAdiDEI76clxw==", "integrity": "sha512-vDTyHIwNPrecy55gKGZ47eJZhBm8LLBxihzi5ou+zrSvYTpkSTWRcKUlXFDFQVwfWB+P5PGyERAdiDEI76clxw==",
"dev": true,
"requires": { "requires": {
"@ethersproject/bytes": "^5.1.0", "@ethersproject/bytes": "^5.1.0",
"@ethersproject/logger": "^5.1.0" "@ethersproject/logger": "^5.1.0"
@@ -16345,7 +16298,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.1.0.tgz",
"integrity": "sha512-+fNSeZRstOpdRJpdGUkRONFCaiAqWkc91zXgg76Nlp5ndBQE25Kk5yK8gCPG1aGnCrbariiPr5j9DmrYH78JCA==", "integrity": "sha512-+fNSeZRstOpdRJpdGUkRONFCaiAqWkc91zXgg76Nlp5ndBQE25Kk5yK8gCPG1aGnCrbariiPr5j9DmrYH78JCA==",
"dev": true,
"requires": { "requires": {
"@ethersproject/bytes": "^5.1.0", "@ethersproject/bytes": "^5.1.0",
"@ethersproject/logger": "^5.1.0", "@ethersproject/logger": "^5.1.0",
@@ -16356,7 +16308,6 @@
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz",
"integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==",
"dev": true,
"requires": { "requires": {
"inherits": "^2.0.3", "inherits": "^2.0.3",
"minimalistic-assert": "^1.0.0" "minimalistic-assert": "^1.0.0"
@@ -16368,7 +16319,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.1.0.tgz",
"integrity": "sha512-tE5LFlbmdObG8bY04NpuwPWSRPgEswfxweAI1sH7TbP0ml1elNfqcq7ii/3AvIN05i5U0Pkm3Tf8bramt8MmLw==", "integrity": "sha512-tE5LFlbmdObG8bY04NpuwPWSRPgEswfxweAI1sH7TbP0ml1elNfqcq7ii/3AvIN05i5U0Pkm3Tf8bramt8MmLw==",
"dev": true,
"requires": { "requires": {
"@ethersproject/bytes": "^5.1.0", "@ethersproject/bytes": "^5.1.0",
"@ethersproject/logger": "^5.1.0", "@ethersproject/logger": "^5.1.0",
@@ -16381,7 +16331,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.1.0.tgz",
"integrity": "sha512-kPodsGyo9zg1g9XSXp1lGhFaezBAUUsAUB1Vf6OkppE5Wksg4Et+x3kG4m7J/uShDMP2upkJtHNsIBK2XkVpKQ==", "integrity": "sha512-kPodsGyo9zg1g9XSXp1lGhFaezBAUUsAUB1Vf6OkppE5Wksg4Et+x3kG4m7J/uShDMP2upkJtHNsIBK2XkVpKQ==",
"dev": true,
"requires": { "requires": {
"@ethersproject/bignumber": "^5.1.0", "@ethersproject/bignumber": "^5.1.0",
"@ethersproject/bytes": "^5.1.0", "@ethersproject/bytes": "^5.1.0",
@@ -16394,7 +16343,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.1.0.tgz",
"integrity": "sha512-perBZy0RrmmL0ejiFGUOlBVjMsUceqLut3OBP3zP96LhiJWWbS8u1NqQVgN4/Gyrbziuda66DxiQocXhsvx+Sw==", "integrity": "sha512-perBZy0RrmmL0ejiFGUOlBVjMsUceqLut3OBP3zP96LhiJWWbS8u1NqQVgN4/Gyrbziuda66DxiQocXhsvx+Sw==",
"dev": true,
"requires": { "requires": {
"@ethersproject/bytes": "^5.1.0", "@ethersproject/bytes": "^5.1.0",
"@ethersproject/constants": "^5.1.0", "@ethersproject/constants": "^5.1.0",
@@ -16405,7 +16353,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.1.0.tgz",
"integrity": "sha512-s10crRLZEA0Bgv6FGEl/AKkTw9f+RVUrlWDX1rHnD4ZncPFeiV2AJr4nT7QSUhxJdFPvjyKRDb3nEH27dIqcPQ==", "integrity": "sha512-s10crRLZEA0Bgv6FGEl/AKkTw9f+RVUrlWDX1rHnD4ZncPFeiV2AJr4nT7QSUhxJdFPvjyKRDb3nEH27dIqcPQ==",
"dev": true,
"requires": { "requires": {
"@ethersproject/address": "^5.1.0", "@ethersproject/address": "^5.1.0",
"@ethersproject/bignumber": "^5.1.0", "@ethersproject/bignumber": "^5.1.0",
@@ -16422,7 +16369,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.1.0.tgz",
"integrity": "sha512-isvJrx6qG0nKWfxsGORNjmOq/nh175fStfvRTA2xEKrGqx8JNJY83fswu4GkILowfriEM/eYpretfJnfzi7YhA==", "integrity": "sha512-isvJrx6qG0nKWfxsGORNjmOq/nh175fStfvRTA2xEKrGqx8JNJY83fswu4GkILowfriEM/eYpretfJnfzi7YhA==",
"dev": true,
"requires": { "requires": {
"@ethersproject/bignumber": "^5.1.0", "@ethersproject/bignumber": "^5.1.0",
"@ethersproject/constants": "^5.1.0", "@ethersproject/constants": "^5.1.0",
@@ -16433,7 +16379,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.1.0.tgz",
"integrity": "sha512-ULmUtiYQLTUS+y3DgkLzRhFEK10zMwmjOthnjiZxee3Q/MVwr3rnmuAnXIUZrPjna6hvUPnyRIdW5XuF0Ld0YQ==", "integrity": "sha512-ULmUtiYQLTUS+y3DgkLzRhFEK10zMwmjOthnjiZxee3Q/MVwr3rnmuAnXIUZrPjna6hvUPnyRIdW5XuF0Ld0YQ==",
"dev": true,
"requires": { "requires": {
"@ethersproject/abstract-provider": "^5.1.0", "@ethersproject/abstract-provider": "^5.1.0",
"@ethersproject/abstract-signer": "^5.1.0", "@ethersproject/abstract-signer": "^5.1.0",
@@ -16456,7 +16401,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.1.0.tgz",
"integrity": "sha512-LTeluWgTq04+RNqAkVhpydPcRZK/kKxD2Vy7PYGrAD27ABO9kTqTBKwiOuzTyAHKUQHfnvZbXmxBXJAGViSDcA==", "integrity": "sha512-LTeluWgTq04+RNqAkVhpydPcRZK/kKxD2Vy7PYGrAD27ABO9kTqTBKwiOuzTyAHKUQHfnvZbXmxBXJAGViSDcA==",
"dev": true,
"requires": { "requires": {
"@ethersproject/base64": "^5.1.0", "@ethersproject/base64": "^5.1.0",
"@ethersproject/bytes": "^5.1.0", "@ethersproject/bytes": "^5.1.0",
@@ -16469,7 +16413,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.1.0.tgz",
"integrity": "sha512-NsUCi/TpBb+oTFvMSccUkJGtp5o/84eOyqp5q5aBeiNBSLkYyw21znRn9mAmxZgySpxgruVgKbaapnYPgvctPQ==", "integrity": "sha512-NsUCi/TpBb+oTFvMSccUkJGtp5o/84eOyqp5q5aBeiNBSLkYyw21znRn9mAmxZgySpxgruVgKbaapnYPgvctPQ==",
"dev": true,
"requires": { "requires": {
"@ethersproject/bytes": "^5.1.0", "@ethersproject/bytes": "^5.1.0",
"@ethersproject/hash": "^5.1.0", "@ethersproject/hash": "^5.1.0",
@@ -16871,8 +16814,7 @@
"aes-js": { "aes-js": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz",
"integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=", "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0="
"dev": true
}, },
"agent-base": { "agent-base": {
"version": "6.0.2", "version": "6.0.2",
@@ -17059,8 +17001,7 @@
"bech32": { "bech32": {
"version": "1.1.4", "version": "1.1.4",
"resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz",
"integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ=="
"dev": true
}, },
"binary-extensions": { "binary-extensions": {
"version": "2.2.0", "version": "2.2.0",
@@ -17807,7 +17748,6 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/ethers/-/ethers-5.1.0.tgz", "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.1.0.tgz",
"integrity": "sha512-2L6Ge6wMBw02FlRoCLg4E0Elt3khMNlW6ULawa10mMeeZToYJ5+uCfiuTuB+XZ6om1Y7wuO9ZzezP8FsU2M/+g==", "integrity": "sha512-2L6Ge6wMBw02FlRoCLg4E0Elt3khMNlW6ULawa10mMeeZToYJ5+uCfiuTuB+XZ6om1Y7wuO9ZzezP8FsU2M/+g==",
"dev": true,
"requires": { "requires": {
"@ethersproject/abi": "5.1.0", "@ethersproject/abi": "5.1.0",
"@ethersproject/abstract-provider": "5.1.0", "@ethersproject/abstract-provider": "5.1.0",
@@ -19810,7 +19750,7 @@
"version": "2.2.3", "version": "2.2.3",
"dev": true, "dev": true,
"requires": { "requires": {
"node-fetch": "^2.6.7", "node-fetch": "2.1.2",
"whatwg-fetch": "2.0.4" "whatwg-fetch": "2.0.4"
} }
}, },
@@ -21621,7 +21561,7 @@
"version": "4.1.0", "version": "4.1.0",
"dev": true, "dev": true,
"requires": { "requires": {
"node-fetch": "^2.6.7" "node-fetch": "~1.7.1"
}, },
"dependencies": { "dependencies": {
"is-stream": { "is-stream": {
@@ -21629,7 +21569,7 @@
"dev": true "dev": true
}, },
"node-fetch": { "node-fetch": {
"version": "2.6.7", "version": "1.7.3",
"dev": true, "dev": true,
"requires": { "requires": {
"encoding": "^0.1.11", "encoding": "^0.1.11",
@@ -22827,7 +22767,7 @@
"dev": true "dev": true
}, },
"node-fetch": { "node-fetch": {
"version": "2.6.7", "version": "2.1.2",
"dev": true "dev": true
}, },
"node-gyp-build": { "node-gyp-build": {
@@ -26969,6 +26909,14 @@
} }
} }
}, },
"solidity-create2-deployer": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/solidity-create2-deployer/-/solidity-create2-deployer-0.4.0.tgz",
"integrity": "sha512-bB5d8fPt4dWsOoRodrsyfWKcjiv77IFl84+e6EckMMGYlfL2ZFqUoMz6tnqqiUFrM9abF1p6dWFOgJ/3zVc8yQ==",
"requires": {
"ethers": "^5.0.14"
}
},
"sonic-boom": { "sonic-boom": {
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz",
+2 -1
View File
@@ -15,7 +15,8 @@
"dependencies": { "dependencies": {
"@openzeppelin/contracts": "^4.0.0", "@openzeppelin/contracts": "^4.0.0",
"fastify": "^3.14.2", "fastify": "^3.14.2",
"hardhat": "^2.2.0" "hardhat": "^2.2.0",
"solidity-create2-deployer": "^0.4.0"
}, },
"devDependencies": { "devDependencies": {
"@nomiclabs/hardhat-ethers": "^2.0.2", "@nomiclabs/hardhat-ethers": "^2.0.2",
+111
View File
@@ -1,6 +1,14 @@
const fastify = require('fastify')({ logger: true }); const fastify = require('fastify')({ logger: true });
const hre = require("hardhat"); const hre = require("hardhat");
const {
deployContract,
isDeployed
} = require("solidity-create2-deployer");
const { getStorageSlotKey, deployCreate2Factory } = require('./utils');
const CREATE2_FACTORY_ADDRESS = '0x4a27c059FD7E383854Ea7DE6Be9c390a795f6eE3'
// readiness check // readiness check
fastify.get('/v1/healthz', async (req, reply) => { fastify.get('/v1/healthz', async (req, reply) => {
@@ -63,6 +71,109 @@ fastify.get('/v1/sendEth', async (req, reply) => {
} }
}); });
fastify.get('/v1/deploySLVContract', async (req, reply) => {
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
const token = await SLVToken.deploy();
const receipt = await token.deployTransaction.wait();
return {
address: token.address,
txHash: token.deployTransaction.hash,
blockNumber: receipt.blockNumber,
blockHash: receipt.blockHash,
}
});
fastify.get('/v1/destroySLVContract', async (req, reply) => {
const addr = req.query.addr;
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
const token = SLVToken.attach(addr);
const tx = await token.destroy();
const receipt = await tx.wait();
return {
blockNumber: receipt.blockNumber,
}
})
fastify.get('/v1/incrementCountA', async (req, reply) => {
const addr = req.query.addr;
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
const token = await SLVToken.attach(addr);
const tx = await token.incrementCountA();
const receipt = await tx.wait();
return {
blockNumber: receipt.blockNumber,
}
});
fastify.get('/v1/incrementCountB', async (req, reply) => {
const addr = req.query.addr;
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
const token = await SLVToken.attach(addr);
const tx = await token.incrementCountB();
const receipt = await tx.wait();
return {
blockNumber: receipt.blockNumber,
}
});
fastify.get('/v1/getStorageKey', async (req, reply) => {
const contract = req.query.contract;
const label = req.query.label;
const key = await getStorageSlotKey(contract, label)
return {
key
}
});
fastify.get('/v1/create2Contract', async (req, reply) => {
const contract = req.query.contract;
const salt = req.query.salt;
const provider = hre.ethers.provider;
const signer = await hre.ethers.getSigner();
const isFactoryDeployed = await isDeployed(CREATE2_FACTORY_ADDRESS, provider);
if (!isFactoryDeployed) {
await deployCreate2Factory(provider, signer)
}
const contractFactory = await hre.ethers.getContractFactory(contract);
const bytecode = contractFactory.bytecode;
const constructorTypes = [];
const constructorArgs = [];
const { txHash, address, receipt } = await deployContract({
salt,
contractBytecode: bytecode,
constructorTypes: constructorTypes,
constructorArgs: constructorArgs,
signer
});
const success = await isDeployed(address, provider);
if (success) {
return {
address,
txHash,
blockNumber: receipt.blockNumber,
blockHash: receipt.blockHash,
}
}
});
async function main() { async function main() {
try { try {
await fastify.listen(3000, '0.0.0.0'); await fastify.listen(3000, '0.0.0.0');
+54
View File
@@ -0,0 +1,54 @@
const { artifacts } = require("hardhat")
const { utils, BigNumber } = require("ethers")
const { deployFactory } = require("solidity-create2-deployer");
const CREATE2_FACTORY_ACCOUNT = '0x2287Fa6efdEc6d8c3E0f4612ce551dEcf89A357A';
async function getStorageLayout(contractName) {
const artifact = await artifacts.readArtifact(contractName);
const buildInfo = await artifacts.getBuildInfo(`${artifact.sourceName}:${artifact.contractName}`);
if (!buildInfo) {
throw new Error('storageLayout not present in compiler output.');
}
const output = buildInfo.output;
const { storageLayout } = output.contracts[artifact.sourceName][artifact.contractName];
if (!storageLayout) {
throw new Error('Contract hasn\'t been compiled.');
}
return storageLayout;
};
async function getStorageSlotKey(contractName, variableName) {
storageLayout = await getStorageLayout(contractName)
const { storage } = storageLayout;
const targetState = storage.find((state) => state.label === variableName);
// Throw if state variable could not be found in storage layout.
if (!targetState) {
throw new Error('Variable not present in storage layout.');
}
key = utils.hexlify(BigNumber.from(targetState.slot));
return key
};
async function deployCreate2Factory(provider, signer) {
// Send eth to account as required to deploy create2 factory contract.
let tx = {
to: CREATE2_FACTORY_ACCOUNT,
value: utils.parseEther('0.01')
}
const txResponse = await signer.sendTransaction(tx);
await txResponse.wait()
// Deploy create2 factory contract.
await deployFactory(provider)
}
module.exports = { getStorageSlotKey, deployCreate2Factory }
+7 -28
View File
@@ -13,8 +13,8 @@ import (
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
"github.com/vulcanize/ipld-eth-server/pkg/eth" "github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
integration "github.com/vulcanize/ipld-eth-server/test" integration "github.com/cerc-io/ipld-eth-server/v4/test"
) )
var _ = Describe("Integration test", func() { var _ = Describe("Integration test", func() {
@@ -38,11 +38,14 @@ var _ = Describe("Integration test", func() {
var txErr error var txErr error
sleepInterval := 2 * time.Second sleepInterval := 2 * time.Second
Describe("get Block", func() {
BeforeEach(func() { BeforeEach(func() {
if !directProxyEthCalls { if !directProxyEthCalls {
Skip("skipping direct-proxy-forwarding integration tests") Skip("skipping direct-proxy-forwarding integration tests")
} }
})
Describe("get Block", func() {
BeforeEach(func() {
contract, contractErr = integration.DeployContract() contract, contractErr = integration.DeployContract()
time.Sleep(sleepInterval) time.Sleep(sleepInterval)
}) })
@@ -94,9 +97,6 @@ var _ = Describe("Integration test", func() {
Describe("Transaction", func() { Describe("Transaction", func() {
BeforeEach(func() { BeforeEach(func() {
if !directProxyEthCalls {
Skip("skipping direct-proxy-forwarding integration tests")
}
contract, contractErr = integration.DeployContract() contract, contractErr = integration.DeployContract()
time.Sleep(sleepInterval) time.Sleep(sleepInterval)
}) })
@@ -122,9 +122,6 @@ var _ = Describe("Integration test", func() {
Describe("Receipt", func() { Describe("Receipt", func() {
BeforeEach(func() { BeforeEach(func() {
if !directProxyEthCalls {
Skip("skipping direct-proxy-forwarding integration tests")
}
contract, contractErr = integration.DeployContract() contract, contractErr = integration.DeployContract()
time.Sleep(sleepInterval) time.Sleep(sleepInterval)
}) })
@@ -142,9 +139,6 @@ var _ = Describe("Integration test", func() {
Describe("FilterLogs", func() { Describe("FilterLogs", func() {
BeforeEach(func() { BeforeEach(func() {
if !directProxyEthCalls {
Skip("skipping direct-proxy-forwarding integration tests")
}
contract, contractErr = integration.DeployContract() contract, contractErr = integration.DeployContract()
time.Sleep(sleepInterval) time.Sleep(sleepInterval)
}) })
@@ -174,9 +168,6 @@ var _ = Describe("Integration test", func() {
Describe("CodeAt", func() { Describe("CodeAt", func() {
BeforeEach(func() { BeforeEach(func() {
if !directProxyEthCalls {
Skip("skipping direct-proxy-forwarding integration tests")
}
contract, contractErr = integration.DeployContract() contract, contractErr = integration.DeployContract()
time.Sleep(sleepInterval) time.Sleep(sleepInterval)
}) })
@@ -224,9 +215,6 @@ var _ = Describe("Integration test", func() {
Describe("Get balance", func() { Describe("Get balance", func() {
address := "0x1111111111111111111111111111111111111112" address := "0x1111111111111111111111111111111111111112"
BeforeEach(func() { BeforeEach(func() {
if !directProxyEthCalls {
Skip("skipping direct-proxy-forwarding integration tests")
}
tx, txErr = integration.SendEth(address, "0.01") tx, txErr = integration.SendEth(address, "0.01")
time.Sleep(sleepInterval) time.Sleep(sleepInterval)
}) })
@@ -286,9 +274,6 @@ var _ = Describe("Integration test", func() {
Describe("Get Storage", func() { Describe("Get Storage", func() {
BeforeEach(func() { BeforeEach(func() {
if !directProxyEthCalls {
Skip("skipping direct-proxy-forwarding integration tests")
}
contract, contractErr = integration.DeployContract() contract, contractErr = integration.DeployContract()
erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10) erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10)
@@ -392,9 +377,6 @@ var _ = Describe("Integration test", func() {
Describe("eth call", func() { Describe("eth call", func() {
BeforeEach(func() { BeforeEach(func() {
if !directProxyEthCalls {
Skip("skipping direct-proxy-forwarding integration tests")
}
contract, contractErr = integration.DeployContract() contract, contractErr = integration.DeployContract()
erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10) erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10)
@@ -445,14 +427,11 @@ var _ = Describe("Integration test", func() {
Describe("Chain ID", func() { Describe("Chain ID", func() {
It("Check chain id", func() { It("Check chain id", func() {
if !directProxyEthCalls {
Skip("skipping direct-proxy-forwarding integration tests")
}
_, err := gethClient.ChainID(ctx) _, err := gethClient.ChainID(ctx)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
_, err = ipldClient.ChainID(ctx) _, err = ipldClient.ChainID(ctx)
Expect(err).To(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
}) })
}) })
}) })
+108
View File
@@ -5,6 +5,9 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"net/http" "net/http"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/statediff/types"
) )
type ContractDeployed struct { type ContractDeployed struct {
@@ -27,6 +30,14 @@ type Tx struct {
BlockHash string `json:"blockHash"` BlockHash string `json:"blockHash"`
} }
type StorageKey struct {
Key string `json:"key"`
}
type CountIncremented struct {
BlockNumber int64 `json:"blockNumber"`
}
const srvUrl = "http://localhost:3000" const srvUrl = "http://localhost:3000"
func DeployContract() (*ContractDeployed, error) { func DeployContract() (*ContractDeployed, error) {
@@ -77,3 +88,100 @@ func SendEth(to string, value string) (*Tx, error) {
return &tx, nil return &tx, nil
} }
func DeploySLVContract() (*ContractDeployed, error) {
res, err := http.Get(fmt.Sprintf("%s/v1/deploySLVContract", srvUrl))
if err != nil {
return nil, err
}
defer res.Body.Close()
var contract ContractDeployed
decoder := json.NewDecoder(res.Body)
err = decoder.Decode(&contract)
if err != nil {
return nil, err
}
return &contract, nil
}
func DestroySLVContract(addr string) (*ContractDestroyed, error) {
res, err := http.Get(fmt.Sprintf("%s/v1/destroySLVContract?addr=%s", srvUrl, addr))
if err != nil {
return nil, err
}
defer res.Body.Close()
var data ContractDestroyed
decoder := json.NewDecoder(res.Body)
return &data, decoder.Decode(&data)
}
func IncrementCount(addr string, count string) (*CountIncremented, error) {
res, err := http.Get(fmt.Sprintf("%s/v1/incrementCount%s?addr=%s", srvUrl, count, addr))
if err != nil {
return nil, err
}
var blockNumber CountIncremented
decoder := json.NewDecoder(res.Body)
err = decoder.Decode(&blockNumber)
if err != nil {
return nil, err
}
return &blockNumber, nil
}
func GetStorageSlotKey(contract string, label string) (*StorageKey, error) {
res, err := http.Get(fmt.Sprintf("%s/v1/getStorageKey?contract=%s&label=%s", srvUrl, contract, label))
if err != nil {
return nil, err
}
defer res.Body.Close()
var key StorageKey
decoder := json.NewDecoder(res.Body)
err = decoder.Decode(&key)
if err != nil {
return nil, err
}
return &key, nil
}
func ClearWatchedAddresses(gethRPCClient *rpc.Client) error {
gethMethod := "statediff_watchAddress"
args := []types.WatchAddressArg{}
// Clear watched addresses
gethErr := gethRPCClient.Call(nil, gethMethod, types.Clear, args)
if gethErr != nil {
return gethErr
}
return nil
}
func Create2Contract(contractName string, salt string) (*ContractDeployed, error) {
res, err := http.Get(fmt.Sprintf("%s/v1/create2Contract?contract=%s&salt=%s", srvUrl, contractName, salt))
if err != nil {
return nil, err
}
defer res.Body.Close()
var contract ContractDeployed
decoder := json.NewDecoder(res.Body)
err = decoder.Decode(&contract)
if err != nil {
return nil, err
}
return &contract, nil
}
+81 -28
View File
@@ -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/pkg/eth" "github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
integration "github.com/vulcanize/ipld-eth-server/test" integration "github.com/cerc-io/ipld-eth-server/v4/test"
) )
const nonExistingBlockHash = "0x111111111111111111111111111111111111111111111111111111111111111" const nonExistingBlockHash = "0x111111111111111111111111111111111111111111111111111111111111111"
@@ -49,11 +49,14 @@ var _ = Describe("Integration test", func() {
var txErr error var txErr error
sleepInterval := 2 * time.Second sleepInterval := 2 * time.Second
Describe("get Block", func() {
BeforeEach(func() { BeforeEach(func() {
if directProxyEthCalls { if directProxyEthCalls {
Skip("skipping no-direct-proxy-forwarding integration tests") Skip("skipping no-direct-proxy-forwarding integration tests")
} }
})
Describe("get Block", func() {
BeforeEach(func() {
contract, contractErr = integration.DeployContract() contract, contractErr = integration.DeployContract()
time.Sleep(sleepInterval) time.Sleep(sleepInterval)
}) })
@@ -123,9 +126,6 @@ var _ = Describe("Integration test", func() {
Describe("Transaction", func() { Describe("Transaction", func() {
BeforeEach(func() { BeforeEach(func() {
if directProxyEthCalls {
Skip("skipping no-direct-proxy-forwarding integration tests")
}
contract, contractErr = integration.DeployContract() contract, contractErr = integration.DeployContract()
time.Sleep(sleepInterval) time.Sleep(sleepInterval)
}) })
@@ -157,9 +157,6 @@ var _ = Describe("Integration test", func() {
Describe("Receipt", func() { Describe("Receipt", func() {
BeforeEach(func() { BeforeEach(func() {
if directProxyEthCalls {
Skip("skipping no-direct-proxy-forwarding integration tests")
}
contract, contractErr = integration.DeployContract() contract, contractErr = integration.DeployContract()
time.Sleep(sleepInterval) time.Sleep(sleepInterval)
}) })
@@ -187,9 +184,6 @@ var _ = Describe("Integration test", func() {
Describe("FilterLogs", func() { Describe("FilterLogs", func() {
BeforeEach(func() { BeforeEach(func() {
if directProxyEthCalls {
Skip("skipping no-direct-proxy-forwarding integration tests")
}
contract, contractErr = integration.DeployContract() contract, contractErr = integration.DeployContract()
time.Sleep(sleepInterval) time.Sleep(sleepInterval)
}) })
@@ -220,9 +214,6 @@ var _ = Describe("Integration test", func() {
Describe("CodeAt", func() { Describe("CodeAt", func() {
BeforeEach(func() { BeforeEach(func() {
if directProxyEthCalls {
Skip("skipping no-direct-proxy-forwarding integration tests")
}
contract, contractErr = integration.DeployContract() contract, contractErr = integration.DeployContract()
time.Sleep(sleepInterval) time.Sleep(sleepInterval)
}) })
@@ -270,9 +261,6 @@ var _ = Describe("Integration test", func() {
Describe("Get balance", func() { Describe("Get balance", func() {
address := "0x1111111111111111111111111111111111111112" address := "0x1111111111111111111111111111111111111112"
BeforeEach(func() { BeforeEach(func() {
if directProxyEthCalls {
Skip("skipping no-direct-proxy-forwarding integration tests")
}
tx, txErr = integration.SendEth(address, "0.01") tx, txErr = integration.SendEth(address, "0.01")
time.Sleep(sleepInterval) time.Sleep(sleepInterval)
}) })
@@ -335,10 +323,12 @@ var _ = Describe("Integration test", func() {
}) })
Describe("Get Storage", func() { Describe("Get Storage", func() {
var slvContract *integration.ContractDeployed
var slvCountA *big.Int
contractSalt := "SLVContractSalt"
BeforeEach(func() { BeforeEach(func() {
if directProxyEthCalls {
Skip("skipping no-direct-proxy-forwarding integration tests")
}
contract, contractErr = integration.DeployContract() contract, contractErr = integration.DeployContract()
erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10) erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10)
@@ -418,12 +408,48 @@ var _ = Describe("Integration test", func() {
Expect(gethStorage).To(Equal(ipldStorage)) Expect(gethStorage).To(Equal(ipldStorage))
}) })
It("get storage for SLV countA after tx", func() {
slvContract, contractErr = integration.Create2Contract("SLVToken", contractSalt)
Expect(contractErr).ToNot(HaveOccurred())
countAIndex := "0x5"
time.Sleep(sleepInterval)
gethStorage, err := gethClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
gethCountA := new(big.Int).SetBytes(gethStorage)
slvCountA = gethCountA
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
ipldCountA := new(big.Int).SetBytes(ipldStorage)
Expect(ipldCountA.String()).To(Equal(slvCountA.String()))
_, txErr = integration.IncrementCount(slvContract.Address, "A")
Expect(txErr).ToNot(HaveOccurred())
slvCountA.Add(slvCountA, big.NewInt(1))
time.Sleep(sleepInterval)
ipldStorage, err = ipldClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
ipldCountA = new(big.Int).SetBytes(ipldStorage)
Expect(ipldCountA.String()).To(Equal(slvCountA.String()))
})
It("get storage after self destruct", func() { It("get storage after self destruct", func() {
totalSupplyIndex := "0x2" totalSupplyIndex := "0x2"
countAIndex := "0x5"
tx, err := integration.DestroyContract(contract.Address) tx, err := integration.DestroyContract(contract.Address)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
slvTx, err := integration.DestroyContract(slvContract.Address)
Expect(err).ToNot(HaveOccurred())
time.Sleep(sleepInterval) time.Sleep(sleepInterval)
gethStorage1, err := gethClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(tx.BlockNumber-1)) gethStorage1, err := gethClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(tx.BlockNumber-1))
@@ -447,14 +473,44 @@ var _ = Describe("Integration test", func() {
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(ipldStorage2).To(Equal(ipldStorage3)) Expect(ipldStorage2).To(Equal(ipldStorage3))
// Check for SLV contract
gethStorage, err := gethClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), big.NewInt(slvTx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(gethStorage).To(Equal(eth.EmptyNodeValue))
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), big.NewInt(slvTx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(ipldStorage).To(Equal(gethStorage))
slvCountA.Set(big.NewInt(0))
})
It("get storage after redeploying", func() {
slvContract, contractErr = integration.Create2Contract("SLVToken", contractSalt)
Expect(contractErr).ToNot(HaveOccurred())
time.Sleep(sleepInterval)
countAIndex := "0x5"
gethStorage, err := gethClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
gethCountA := new(big.Int).SetBytes(gethStorage)
Expect(gethCountA.String()).To(Equal(slvCountA.String()))
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
ipldCountA := new(big.Int).SetBytes(ipldStorage)
Expect(ipldCountA.String()).To(Equal(slvCountA.String()))
Expect(gethStorage).To(Equal(ipldStorage))
}) })
}) })
Describe("eth call", func() { Describe("eth call", func() {
BeforeEach(func() { BeforeEach(func() {
if directProxyEthCalls {
Skip("skipping no-direct-proxy-forwarding integration tests")
}
contract, contractErr = integration.DeployContract() contract, contractErr = integration.DeployContract()
erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10) erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10)
@@ -505,9 +561,6 @@ var _ = Describe("Integration test", func() {
Describe("Chain ID", func() { Describe("Chain ID", func() {
It("Check chain id", func() { It("Check chain id", func() {
if directProxyEthCalls {
Skip("skipping no-direct-proxy-forwarding integration tests")
}
gethChainId, err := gethClient.ChainID(ctx) gethChainId, err := gethClient.ChainID(ctx)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@@ -537,7 +590,7 @@ func compareTxs(tx1 *types.Transaction, tx2 *types.Transaction) {
Expect(tx1.Hash()).To(Equal(tx2.Hash())) Expect(tx1.Hash()).To(Equal(tx2.Hash()))
Expect(tx1.Size()).To(Equal(tx2.Size())) Expect(tx1.Size()).To(Equal(tx2.Size()))
signer := types.NewEIP155Signer(big.NewInt(4)) signer := types.NewEIP155Signer(big.NewInt(99))
gethSender, err := types.Sender(signer, tx1) gethSender, err := types.Sender(signer, tx1)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
+671
View File
@@ -0,0 +1,671 @@
package integration_test
import (
"context"
"math/big"
"os"
"strconv"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
integration "github.com/cerc-io/ipld-eth-server/v4/test"
)
var (
gethMethod = "statediff_watchAddress"
ipldMethod = "vdb_watchAddress"
sleepInterval = 2 * time.Second
)
var _ = Describe("WatchAddress integration test", func() {
dbWrite, err := strconv.ParseBool(os.Getenv("DB_WRITE"))
Expect(err).To(BeNil())
gethHttpPath := "http://127.0.0.1:8545"
gethRPCClient, err := rpc.Dial(gethHttpPath)
Expect(err).ToNot(HaveOccurred())
ipldEthHttpPath := "http://127.0.0.1:8081"
ipldClient, err := ethclient.Dial(ipldEthHttpPath)
Expect(err).ToNot(HaveOccurred())
ipldRPCClient, err := rpc.Dial(ipldEthHttpPath)
Expect(err).ToNot(HaveOccurred())
var (
ctx = context.Background()
txErr error
contractErr error
incErr error
contract1 *integration.ContractDeployed
contract2 *integration.ContractDeployed
contract3 *integration.ContractDeployed
countAIndex string
prevBalance1 *big.Int
prevBalance2 *big.Int
prevBalance3 *big.Int
actualBalance1 *big.Int
actualBalance2 *big.Int
actualBalance3 *big.Int
prevCountA1 *big.Int
prevCountA2 *big.Int
prevCountA3 *big.Int
actualCountA1 *big.Int
actualCountA2 *big.Int
actualCountA3 *big.Int
)
BeforeEach(func() {
if !dbWrite {
Skip("skipping WatchAddress API integration tests")
}
})
It("test init", func() {
// Deploy three contracts
contract1, contractErr = integration.DeploySLVContract()
Expect(contractErr).ToNot(HaveOccurred())
contract2, contractErr = integration.DeploySLVContract()
Expect(contractErr).ToNot(HaveOccurred())
contract3, contractErr = integration.DeploySLVContract()
Expect(contractErr).ToNot(HaveOccurred())
// Get the storage slot key
storageSlotAKey, err := integration.GetStorageSlotKey("SLVToken", "countA")
Expect(err).ToNot(HaveOccurred())
countAIndex = storageSlotAKey.Key
// Clear out watched addresses
err = integration.ClearWatchedAddresses(gethRPCClient)
Expect(err).ToNot(HaveOccurred())
// Get initial balances for all the contracts
// Contract 1
actualBalance1 = big.NewInt(0)
initBalance1, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(initBalance1.String()).To(Equal(actualBalance1.String()))
prevBalance1 = big.NewInt(0)
// Contract 2
actualBalance2 = big.NewInt(0)
initBalance2, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(initBalance2.String()).To(Equal(actualBalance2.String()))
prevBalance2 = big.NewInt(0)
// Contract 3
actualBalance3 = big.NewInt(0)
initBalance3, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(initBalance3.String()).To(Equal(actualBalance3.String()))
prevBalance3 = big.NewInt(0)
// Get initial storage values for the contracts
// Contract 1, countA
actualCountA1 = big.NewInt(0)
ipldCountA1Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
ipldCountA1 := new(big.Int).SetBytes(ipldCountA1Storage)
Expect(ipldCountA1.String()).To(Equal(actualCountA1.String()))
prevCountA1 = big.NewInt(0)
// Contract 2, countA
actualCountA2 = big.NewInt(0)
ipldCountA2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
ipldCountA2 := new(big.Int).SetBytes(ipldCountA2Storage)
Expect(ipldCountA2.String()).To(Equal(actualCountA2.String()))
prevCountA2 = big.NewInt(0)
// Contract 3, countA
actualCountA3 = big.NewInt(0)
ipldCountA3Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
ipldCountA3 := new(big.Int).SetBytes(ipldCountA3Storage)
Expect(ipldCountA3.String()).To(Equal(actualCountA2.String()))
prevCountA3 = big.NewInt(0)
})
defer It("test cleanup", func() {
// Clear out watched addresses
err := integration.ClearWatchedAddresses(gethRPCClient)
Expect(err).ToNot(HaveOccurred())
})
Context("no contracts being watched", func() {
It("indexes state for all the contracts", func() {
// WatchedAddresses = []
// Send eth to all three contract accounts
// Contract 1
_, txErr = integration.SendEth(contract1.Address, "0.01")
time.Sleep(sleepInterval)
Expect(txErr).ToNot(HaveOccurred())
actualBalance1.Add(actualBalance1, big.NewInt(10000000000000000))
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(balance1AfterTransfer.String()).To(Equal(actualBalance1.String()))
prevBalance1.Set(actualBalance1)
// Contract 2
_, txErr = integration.SendEth(contract2.Address, "0.01")
time.Sleep(sleepInterval)
Expect(txErr).ToNot(HaveOccurred())
actualBalance2.Add(actualBalance2, big.NewInt(10000000000000000))
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(balance2AfterTransfer.String()).To(Equal(actualBalance2.String()))
prevBalance2.Set(actualBalance2)
// Contract 3
_, txErr = integration.SendEth(contract3.Address, "0.01")
time.Sleep(sleepInterval)
Expect(txErr).ToNot(HaveOccurred())
actualBalance3.Add(actualBalance3, big.NewInt(10000000000000000))
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(balance3AfterTransfer.String()).To(Equal(actualBalance3.String()))
prevBalance3.Set(actualBalance3)
// Increment counts
// Contract 1, countA
_, incErr = integration.IncrementCount(contract1.Address, "A")
time.Sleep(sleepInterval)
Expect(incErr).ToNot(HaveOccurred())
actualCountA1.Add(actualCountA1, big.NewInt(1))
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage)
Expect(countA1AfterIncrement.String()).To(Equal(actualCountA1.String()))
prevCountA1.Set(actualCountA1)
// Contract 2, countA
_, incErr = integration.IncrementCount(contract2.Address, "A")
time.Sleep(sleepInterval)
Expect(incErr).ToNot(HaveOccurred())
actualCountA2.Add(actualCountA2, big.NewInt(1))
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
countA2AfterIncrement := new(big.Int).SetBytes(countA2AfterIncrementStorage)
Expect(countA2AfterIncrement.String()).To(Equal(actualCountA2.String()))
prevCountA2.Set(actualCountA2)
// Contract 3, countA
_, incErr = integration.IncrementCount(contract3.Address, "A")
time.Sleep(sleepInterval)
Expect(incErr).ToNot(HaveOccurred())
actualCountA3.Add(actualCountA3, big.NewInt(1))
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
countA3AfterIncrement := new(big.Int).SetBytes(countA3AfterIncrementStorage)
Expect(countA3AfterIncrement.String()).To(Equal(actualCountA3.String()))
prevCountA3.Set(actualCountA3)
})
})
Context("one contract being watched", func() {
It("indexes state only for the watched contract", func() {
operation := sdtypes.Add
args := []sdtypes.WatchAddressArg{
{
Address: contract1.Address,
CreatedAt: uint64(contract1.BlockNumber),
},
}
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
Expect(ipldErr).ToNot(HaveOccurred())
// WatchedAddresses = [Contract1]
// Send eth to all three contract accounts
// Contract 1
_, txErr = integration.SendEth(contract1.Address, "0.01")
time.Sleep(sleepInterval)
Expect(txErr).ToNot(HaveOccurred())
actualBalance1.Add(actualBalance1, big.NewInt(10000000000000000))
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(balance1AfterTransfer.String()).To(Equal(actualBalance1.String()))
prevBalance1.Set(actualBalance1)
// Contract 2
_, txErr = integration.SendEth(contract2.Address, "0.01")
time.Sleep(sleepInterval)
Expect(txErr).ToNot(HaveOccurred())
actualBalance2.Add(actualBalance2, big.NewInt(10000000000000000))
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(balance2AfterTransfer.String()).To(Equal(prevBalance2.String()))
// Contract 3
_, txErr = integration.SendEth(contract3.Address, "0.01")
time.Sleep(sleepInterval)
Expect(txErr).ToNot(HaveOccurred())
actualBalance3.Add(actualBalance3, big.NewInt(10000000000000000))
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(balance3AfterTransfer.String()).To(Equal(prevBalance3.String()))
// Increment counts
// Contract 1, countA
_, incErr = integration.IncrementCount(contract1.Address, "A")
time.Sleep(sleepInterval)
Expect(incErr).ToNot(HaveOccurred())
actualCountA1.Add(actualCountA1, big.NewInt(1))
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage)
Expect(countA1AfterIncrement.String()).To(Equal(actualCountA1.String()))
prevCountA1.Set(actualCountA1)
// Contract 2, countA
_, incErr = integration.IncrementCount(contract2.Address, "A")
time.Sleep(sleepInterval)
Expect(incErr).ToNot(HaveOccurred())
actualCountA2.Add(actualCountA2, big.NewInt(1))
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
countA2AfterIncrement := new(big.Int).SetBytes(countA2AfterIncrementStorage)
Expect(countA2AfterIncrement.String()).To(Equal(prevCountA2.String()))
// Contract 3, countA
_, incErr = integration.IncrementCount(contract3.Address, "A")
time.Sleep(sleepInterval)
Expect(incErr).ToNot(HaveOccurred())
actualCountA3.Add(actualCountA3, big.NewInt(1))
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
countA3AfterIncrement := new(big.Int).SetBytes(countA3AfterIncrementStorage)
Expect(countA3AfterIncrement.String()).To(Equal(prevCountA3.String()))
})
})
Context("contract added to a non-empty watch-list", func() {
It("indexes state only for the watched contracts", func() {
operation := sdtypes.Add
args := []sdtypes.WatchAddressArg{
{
Address: contract2.Address,
CreatedAt: uint64(contract2.BlockNumber),
},
}
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
Expect(ipldErr).ToNot(HaveOccurred())
// WatchedAddresses = [Contract1, Contract2]
// Send eth to all three contract accounts
// Contract 1
_, txErr = integration.SendEth(contract1.Address, "0.01")
time.Sleep(sleepInterval)
Expect(txErr).ToNot(HaveOccurred())
actualBalance1.Add(actualBalance1, big.NewInt(10000000000000000))
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(balance1AfterTransfer.String()).To(Equal(actualBalance1.String()))
prevBalance1.Set(actualBalance1)
// Contract 2
_, txErr = integration.SendEth(contract2.Address, "0.01")
time.Sleep(sleepInterval)
Expect(txErr).ToNot(HaveOccurred())
actualBalance2.Add(actualBalance2, big.NewInt(10000000000000000))
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(balance2AfterTransfer.String()).To(Equal(actualBalance2.String()))
prevBalance2.Set(actualBalance2)
// Contract 3
_, txErr = integration.SendEth(contract3.Address, "0.01")
time.Sleep(sleepInterval)
Expect(txErr).ToNot(HaveOccurred())
actualBalance3.Add(actualBalance3, big.NewInt(10000000000000000))
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(balance3AfterTransfer.String()).To(Equal(prevBalance3.String()))
// Increment counts
// Contract 1, countA
_, incErr = integration.IncrementCount(contract1.Address, "A")
time.Sleep(sleepInterval)
Expect(incErr).ToNot(HaveOccurred())
actualCountA1.Add(actualCountA1, big.NewInt(1))
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage)
Expect(countA1AfterIncrement.String()).To(Equal(actualCountA1.String()))
prevCountA1.Set(actualCountA1)
// Contract 2, countA
_, incErr = integration.IncrementCount(contract2.Address, "A")
time.Sleep(sleepInterval)
Expect(incErr).ToNot(HaveOccurred())
actualCountA2.Add(actualCountA2, big.NewInt(1))
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
countA2AfterIncrement := new(big.Int).SetBytes(countA2AfterIncrementStorage)
Expect(countA2AfterIncrement.String()).To(Equal(actualCountA2.String()))
prevCountA2.Set(actualCountA2)
// Contract 3, countA
_, incErr = integration.IncrementCount(contract3.Address, "A")
time.Sleep(sleepInterval)
Expect(incErr).ToNot(HaveOccurred())
actualCountA3.Add(actualCountA3, big.NewInt(1))
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
countA3AfterIncrement := new(big.Int).SetBytes(countA3AfterIncrementStorage)
Expect(countA3AfterIncrement.String()).To(Equal(prevCountA3.String()))
})
})
Context("contract removed from the watch-list", func() {
It("indexes state only for the watched contract", func() {
operation := sdtypes.Remove
args := []sdtypes.WatchAddressArg{
{
Address: contract1.Address,
CreatedAt: uint64(contract1.BlockNumber),
},
}
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
Expect(ipldErr).ToNot(HaveOccurred())
// WatchedAddresses = [Contract2]
// Send eth to all three contract accounts
// Contract 1
_, txErr = integration.SendEth(contract1.Address, "0.01")
time.Sleep(sleepInterval)
Expect(txErr).ToNot(HaveOccurred())
actualBalance1.Add(actualBalance1, big.NewInt(10000000000000000))
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(balance1AfterTransfer.String()).To(Equal(prevBalance1.String()))
// Contract 2
_, txErr = integration.SendEth(contract2.Address, "0.01")
time.Sleep(sleepInterval)
Expect(txErr).ToNot(HaveOccurred())
actualBalance2.Add(actualBalance2, big.NewInt(10000000000000000))
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(balance2AfterTransfer.String()).To(Equal(actualBalance2.String()))
prevBalance2.Set(actualBalance2)
// Contract 3
_, txErr = integration.SendEth(contract3.Address, "0.01")
time.Sleep(sleepInterval)
Expect(txErr).ToNot(HaveOccurred())
actualBalance3.Add(actualBalance3, big.NewInt(10000000000000000))
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(balance3AfterTransfer.String()).To(Equal(prevBalance3.String()))
// Increment counts
// Contract 1, countA
_, incErr = integration.IncrementCount(contract1.Address, "A")
time.Sleep(sleepInterval)
Expect(incErr).ToNot(HaveOccurred())
actualCountA1.Add(actualCountA1, big.NewInt(1))
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage)
Expect(countA1AfterIncrement.String()).To(Equal(prevCountA1.String()))
// Contract 2, countA
_, incErr = integration.IncrementCount(contract2.Address, "A")
time.Sleep(sleepInterval)
Expect(incErr).ToNot(HaveOccurred())
actualCountA2.Add(actualCountA2, big.NewInt(1))
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
countA2AfterIncrement := new(big.Int).SetBytes(countA2AfterIncrementStorage)
Expect(countA2AfterIncrement.String()).To(Equal(actualCountA2.String()))
prevCountA2.Set(actualCountA2)
// Contract 3, countA
_, incErr = integration.IncrementCount(contract3.Address, "A")
time.Sleep(sleepInterval)
Expect(incErr).ToNot(HaveOccurred())
actualCountA3.Add(actualCountA3, big.NewInt(1))
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
countA3AfterIncrement := new(big.Int).SetBytes(countA3AfterIncrementStorage)
Expect(countA3AfterIncrement.String()).To(Equal(prevCountA3.String()))
})
})
Context("list of watched addresses set", func() {
It("indexes state only for the watched contracts", func() {
operation := sdtypes.Set
args := []sdtypes.WatchAddressArg{
{
Address: contract1.Address,
CreatedAt: uint64(contract1.BlockNumber),
},
{
Address: contract3.Address,
CreatedAt: uint64(contract3.BlockNumber),
},
}
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
Expect(ipldErr).ToNot(HaveOccurred())
// WatchedAddresses = [Contract1, Contract3]
// Send eth to all three contract accounts
// Contract 1
_, txErr = integration.SendEth(contract1.Address, "0.01")
time.Sleep(sleepInterval)
Expect(txErr).ToNot(HaveOccurred())
actualBalance1.Add(actualBalance1, big.NewInt(10000000000000000))
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(balance1AfterTransfer.String()).To(Equal(actualBalance1.String()))
prevBalance1.Set(actualBalance1)
// Contract 2
_, txErr = integration.SendEth(contract2.Address, "0.01")
time.Sleep(sleepInterval)
Expect(txErr).ToNot(HaveOccurred())
actualBalance2.Add(actualBalance2, big.NewInt(10000000000000000))
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(balance2AfterTransfer.String()).To(Equal(prevBalance2.String()))
// Contract 3
_, txErr = integration.SendEth(contract3.Address, "0.01")
time.Sleep(sleepInterval)
Expect(txErr).ToNot(HaveOccurred())
actualBalance3.Add(actualBalance3, big.NewInt(10000000000000000))
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(balance3AfterTransfer.String()).To(Equal(actualBalance3.String()))
prevBalance3.Set(actualBalance3)
// Increment counts
// Contract 1, countA
_, incErr = integration.IncrementCount(contract1.Address, "A")
time.Sleep(sleepInterval)
Expect(incErr).ToNot(HaveOccurred())
actualCountA1.Add(actualCountA1, big.NewInt(1))
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage)
Expect(countA1AfterIncrement.String()).To(Equal(actualCountA1.String()))
prevCountA1.Set(actualCountA1)
// Contract 2, countA
_, incErr = integration.IncrementCount(contract2.Address, "A")
time.Sleep(sleepInterval)
Expect(incErr).ToNot(HaveOccurred())
actualCountA2.Add(actualCountA2, big.NewInt(1))
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
countA2AfterIncrement := new(big.Int).SetBytes(countA2AfterIncrementStorage)
Expect(countA2AfterIncrement.String()).To(Equal(prevCountA2.String()))
// Contract 3, countA
_, incErr = integration.IncrementCount(contract3.Address, "A")
time.Sleep(sleepInterval)
Expect(incErr).ToNot(HaveOccurred())
actualCountA3.Add(actualCountA3, big.NewInt(1))
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
countA3AfterIncrement := new(big.Int).SetBytes(countA3AfterIncrementStorage)
Expect(countA3AfterIncrement.String()).To(Equal(actualCountA3.String()))
prevCountA3.Set(actualCountA3)
})
})
Context("list of watched addresses cleared", func() {
It("indexes state for all the contracts", func() {
operation := sdtypes.Clear
args := []sdtypes.WatchAddressArg{}
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
Expect(ipldErr).ToNot(HaveOccurred())
// WatchedAddresses = []
// Send eth to all three contract accounts
// Contract 1
_, txErr = integration.SendEth(contract1.Address, "0.01")
time.Sleep(sleepInterval)
Expect(txErr).ToNot(HaveOccurred())
actualBalance1.Add(actualBalance1, big.NewInt(10000000000000000))
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(balance1AfterTransfer.String()).To(Equal(actualBalance1.String()))
prevBalance1.Set(actualBalance1)
// Contract 2
_, txErr = integration.SendEth(contract2.Address, "0.01")
time.Sleep(sleepInterval)
Expect(txErr).ToNot(HaveOccurred())
actualBalance2.Add(actualBalance2, big.NewInt(10000000000000000))
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(balance2AfterTransfer.String()).To(Equal(actualBalance2.String()))
prevBalance2.Set(actualBalance2)
// Contract 3
_, txErr = integration.SendEth(contract3.Address, "0.01")
time.Sleep(sleepInterval)
Expect(txErr).ToNot(HaveOccurred())
actualBalance3.Add(actualBalance3, big.NewInt(10000000000000000))
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
Expect(err).ToNot(HaveOccurred())
Expect(balance3AfterTransfer.String()).To(Equal(actualBalance3.String()))
prevBalance3.Set(actualBalance3)
// Increment counts
// Contract 1, countA
_, incErr = integration.IncrementCount(contract1.Address, "A")
time.Sleep(sleepInterval)
Expect(incErr).ToNot(HaveOccurred())
actualCountA1.Add(actualCountA1, big.NewInt(1))
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage)
Expect(countA1AfterIncrement.String()).To(Equal(actualCountA1.String()))
prevCountA1.Set(actualCountA1)
// Contract 2, countA
_, incErr = integration.IncrementCount(contract2.Address, "A")
time.Sleep(sleepInterval)
Expect(incErr).ToNot(HaveOccurred())
actualCountA2.Add(actualCountA2, big.NewInt(1))
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
countA2AfterIncrement := new(big.Int).SetBytes(countA2AfterIncrementStorage)
Expect(countA2AfterIncrement.String()).To(Equal(actualCountA2.String()))
prevCountA2.Set(actualCountA2)
// Contract 3, countA
_, incErr = integration.IncrementCount(contract3.Address, "A")
time.Sleep(sleepInterval)
Expect(incErr).ToNot(HaveOccurred())
actualCountA3.Add(actualCountA3, big.NewInt(1))
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
Expect(err).ToNot(HaveOccurred())
countA3AfterIncrement := new(big.Int).SetBytes(countA3AfterIncrementStorage)
Expect(countA3AfterIncrement.String()).To(Equal(actualCountA3.String()))
prevCountA3.Set(actualCountA3)
})
})
Context("with invalid args", func() {
It("returns an error on invalid operation arg", func() {
operation := "WrongOp"
args := []sdtypes.WatchAddressArg{}
gethErr := gethRPCClient.Call(nil, gethMethod, operation, args)
Expect(gethErr).To(HaveOccurred())
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
Expect(ipldErr).To(HaveOccurred())
Expect(ipldErr).To(Equal(gethErr))
})
It("returns an error on args of invalid type", func() {
operation := sdtypes.Add
args := []string{"WrongArg"}
gethErr := gethRPCClient.Call(nil, gethMethod, operation, args)
Expect(gethErr).To(HaveOccurred())
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
Expect(ipldErr).To(HaveOccurred())
Expect(ipldErr).To(Equal(gethErr))
})
})
})
+1 -1
View File
@@ -33,7 +33,7 @@ func init() {
func setTestConfig() { func setTestConfig() {
vip := viper.New() vip := viper.New()
vip.SetConfigName("testing") vip.SetConfigName("testing")
vip.AddConfigPath("$GOPATH/src/github.com/vulcanize/ipld-eth-server/environments/") vip.AddConfigPath("$GOPATH/src/github.com/cerc-io/ipld-eth-server/environments/")
if err := vip.ReadInConfig(); err != nil { if err := vip.ReadInConfig(); err != nil {
logrus.Fatal(err) logrus.Fatal(err)
} }
+4 -4
View File
@@ -19,10 +19,10 @@ package version
import "fmt" import "fmt"
const ( const (
Major = 2 // Major version component of the current release Major = 4 // Major version component of the current release
Minor = 0 // Minor version component of the current release Minor = 1 // Minor version component of the current release
Patch = 0 // Patch version component of the current release Patch = 9 // Patch version component of the current release
Meta = "" // Version metadata to append to the version string Meta = "alpha" // Version metadata to append to the version string
) )
// Version holds the textual version string. // Version holds the textual version string.