Compare commits

..

5 Commits

Author SHA1 Message Date
27d1634b5b Fix RPC for blob transactions (#266)
- Fixes RPC for blob transactions
- Allows loading chain ID from chain config file, improving integration in cerc-io/fixturenet-eth-stacks#21

Depends on cerc-io/system-tests#13

Reviewed-on: #266
2024-08-07 04:50:53 +00:00
190b36bcd1 Support validator withdrawals (#265)
- Retrieves indexed withdrawal objects with blocks over RPC.
- Includes system-tests in CI workflow.
- Uses external fixturenet stack in CI tests.

Depends on
- cerc-io/ipld-eth-db#7
- cerc-io/plugeth-statediff#25

To induce and test validator withdrawals:
  - cerc-io/lighthouse#1
  - cerc-io/fixturenet-eth-stacks#19
  - cerc-io/system-tests#16

Reviewed-on: #265
2024-08-05 15:50:53 +00:00
688b5c817a Geth 1.13 (Deneb/Cancun) update (#264)
Most notable changes are the updates to the test contracts: due to https://eips.ethereum.org/EIPS/eip-6780, SELFDESTRUCT no longer destroys a contract (unless it occurs in the creating transaction), so CREATE2 can no longer redeploy contracts to the same address.

Reviewed-on: #264
2024-05-29 12:29:55 +00:00
671868aac6 262: Update test/stack-refs.txt (#263)
This updates the reference to a tag that does exist.  It also switches to the git.vdb.to repo.

Reviewed-on: #263
2023-11-14 00:34:22 +00:00
b0b61a369a Fix checksum build error. 2023-10-27 17:17:42 -05:00
40 changed files with 2161 additions and 2405 deletions

View File

@ -12,5 +12,7 @@ integration
test
scripts
Dockerfile
environments
**/node_modules
build

View File

@ -12,9 +12,9 @@ on:
- ci-test
env:
# Needed until we can incorporate docker startup into the executor container
DOCKER_HOST: unix:///var/run/dind.sock
SO_VERSION: v1.1.0-e0b5318-202309201927 # contains fixes for plugeth stack
SO_VERSION: v1.1.0-36d4969-202407091537
FIXTURENET_ETH_STACKS_REF: main
SYSTEM_TESTS_REF: main
jobs:
test:
@ -26,21 +26,12 @@ jobs:
with:
go-version-file: 'go.mod'
check-latest: true
- name: Run dockerd
run: |
dockerd -H $DOCKER_HOST --userland-proxy=false &
sleep 5
- name: Run DB container
run: docker compose -f test/compose-db.yml up --wait --quiet-pull
- name: Configure Gitea access
env:
TOKEN: ${{ secrets.CICD_REPO_TOKEN }}
run: |
git config --global url."https://$TOKEN:@git.vdb.to/".insteadOf https://git.vdb.to/
- name: Build and run tests
run: |
go install github.com/onsi/ginkgo/v2/ginkgo
ginkgo -v -r --skipPackage=./integration
ginkgo -v -r --skip-package=./integration
integration-test:
name: Run integration tests
@ -51,10 +42,6 @@ jobs:
with:
go-version-file: 'go.mod'
check-latest: true
- name: Run dockerd
run: |
dockerd -H $DOCKER_HOST --userland-proxy=false &
sleep 5
- name: Build server image
env:
@ -64,10 +51,18 @@ jobs:
env:
DEBIAN_FRONTEND: noninteractive
run: apt-get update && apt-get install -y jq
- name: Install Python
# At present the stock setup-python action fails on Linux/aarch64
# Conditional steps below workaroud this by using deadsnakes for that case only
- name: "Install Python for ARM on Linux"
if: ${{ runner.arch == 'arm64' && runner.os == 'Linux' }}
uses: deadsnakes/action@v3.0.1
with:
python-version: 3.11
- name: "Install Python cases other than ARM on Linux"
if: ${{ ! (runner.arch == 'arm64' && runner.os == 'Linux') }}
uses: actions/setup-python@v4
with:
python-version: '3.11'
python-version: 3.11
- name: Install stack-orchestrator
uses: actions/checkout@v3
with:
@ -75,16 +70,18 @@ jobs:
ref: ${{ env.SO_VERSION }}
path: ./stack-orchestrator
- run: pip install ./stack-orchestrator
- name: Configure Gitea access
env:
TOKEN: ${{ secrets.CICD_REPO_TOKEN }}
run: |
git config --global url."https://$TOKEN:@git.vdb.to/".insteadOf https://git.vdb.to/
- name: Clone fixturenet stack repo
uses: actions/checkout@v4
with:
repository: cerc-io/fixturenet-eth-stacks
ref: ${{ env.FIXTURENET_ETH_STACKS_REF }}
path: ./fixturenet-eth-stacks
progress: false
- name: Run testnet stack
env:
CERC_GO_AUTH_TOKEN: ${{ secrets.CICD_REPO_TOKEN }}
run: ./scripts/integration-setup.sh
run: ./scripts/run-test-stack.sh ./fixturenet-eth-stacks/stack-orchestrator/stacks/fixturenet-plugeth
- name: Run server
env:
ETH_FORWARD_ETH_CALLS: false
@ -95,11 +92,31 @@ jobs:
go install github.com/onsi/ginkgo/v2/ginkgo
ginkgo -v --label-filter '!proxy' -r ./integration
- name: Clone system-tests
uses: actions/checkout@v4
with:
repository: cerc-io/system-tests
ref: ${{ env.SYSTEM_TESTS_REF }}
path: ./system-tests
token: ${{ secrets.CICD_REPO_TOKEN }}
progress: false
- name: Run system tests
working-directory: ./system-tests
# Work around dependency conflict in system-tests:
# web3 uses an older eth-account until (unreleased) v7
run: |
pip3 install pytest
pip3 install -r requirements.txt
pip3 install --no-deps 'eth-account>=0.12.3,<0.13'
pip3 install 'pydantic>=2.0.0'
# Skips tests that require Blob indexing
python3 -m pytest -vv -m "not blob_db"
- name: Run testnet stack without statediff
env:
CERC_RUN_STATEDIFF: false
SKIP_BUILD: 1
run: ./scripts/integration-setup.sh
run: ./scripts/run-test-stack.sh ./fixturenet-eth-stacks/stack-orchestrator/stacks/fixturenet-plugeth
- name: Run server with call forwarding
env:
ETH_FORWARD_ETH_CALLS: true

View File

@ -1,9 +1,9 @@
FROM golang:1.19-alpine as debugger
FROM golang:1.21-alpine AS debugger
# Include dlv
RUN go install github.com/go-delve/delve/cmd/dlv@latest
FROM golang:1.19-alpine as builder
FROM golang:1.21-alpine AS builder
RUN apk --update --no-cache add gcc musl-dev binutils-gold git
@ -29,7 +29,6 @@ RUN GOOS=linux go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -
FROM alpine
ARG USER="vdm"
ARG CONFIG_FILE="./environments/example.toml"
RUN adduser -Du 5000 $USER
WORKDIR /app
@ -38,13 +37,10 @@ USER $USER
# chown first so dir is writable
# note: using $USER is merged, but not in the stable release yet
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/cerc-io/ipld-eth-server/entrypoint.sh .
# keep binaries immutable
COPY --from=builder /go/src/github.com/cerc-io/ipld-eth-server/ipld-eth-server ipld-eth-server
COPY --from=builder /go/src/github.com/cerc-io/ipld-eth-server/environments environments
# Allow for debugging
COPY --from=debugger /go/bin/dlv /usr/local/bin/

138
Makefile
View File

@ -1,138 +0,0 @@
BIN = $(GOPATH)/bin
BASE = $(GOPATH)/src/$(PACKAGE)
PKGS = go list ./... | grep -v "^vendor/"
# Tools
## Migration tool
GOOSE = $(BIN)/goose
$(BIN)/goose:
go get -u github.com/pressly/goose/cmd/goose
## Source linter
LINT = $(BIN)/golint
$(BIN)/golint:
go get -u golang.org/x/lint/golint
## Combination linter
METALINT = $(BIN)/gometalinter.v2
$(BIN)/gometalinter.v2:
go get -u gopkg.in/alecthomas/gometalinter.v2
$(METALINT) --install
.PHONY: installtools
installtools: | $(LINT) $(GOOSE)
echo "Installing tools"
go mod download
.PHONY: metalint
metalint: | $(METALINT)
$(METALINT) ./... --vendor \
--fast \
--exclude="exported (function)|(var)|(method)|(type).*should have comment or be unexported" \
--format="{{.Path.Abs}}:{{.Line}}:{{if .Col}}{{.Col}}{{end}}:{{.Severity}}: {{.Message}} ({{.Linter}})"
.PHONY: lint
lint:
$(LINT) $$($(PKGS)) | grep -v -E "exported (function)|(var)|(method)|(type).*should have comment or be unexported"
#Database
HOST_NAME = localhost
PORT = 5432
NAME =
USER = postgres
PASSWORD = password
CONNECT_STRING=postgresql://$(USER):$(PASSWORD)@$(HOST_NAME):$(PORT)/$(NAME)?sslmode=disable
#Test
TEST_DB = vulcanize_testing
TEST_CONNECT_STRING = postgresql://$(DATABASE_USER):$(DATABASE_PASSWORD)@$(DATABASE_HOSTNAME):$(DATABASE_PORT)/$(TEST_DB)?sslmode=disable
TEST_CONNECT_STRING_LOCAL = postgresql://$(USER)@$(HOST_NAME):$(PORT)/$(TEST_DB)?sslmode=disable
.PHONY: test
test:
go vet ./...
go fmt ./...
go run github.com/onsi/ginkgo/ginkgo -r --skipPackage=test
.PHONY: integrationtest
integrationtest:
go vet ./...
go fmt ./...
go run github.com/onsi/ginkgo/ginkgo -r test/ -v
.PHONY: test_local
test_local:
go vet ./...
go fmt ./...
./scripts/run_unit_test.sh
build:
go fmt ./...
GO111MODULE=on go build
# Parameter checks
## Check that DB variables are provided
.PHONY: checkdbvars
checkdbvars:
test -n "$(HOST_NAME)" # $$HOST_NAME
test -n "$(PORT)" # $$PORT
test -n "$(NAME)" # $$NAME
@echo $(CONNECT_STRING)
## Check that the migration variable (id/timestamp) is provided
.PHONY: checkmigration
checkmigration:
test -n "$(MIGRATION)" # $$MIGRATION
# Check that the migration name is provided
.PHONY: checkmigname
checkmigname:
test -n "$(NAME)" # $$NAME
# Migration operations
## Rollback the last migration
.PHONY: rollback
rollback: $(GOOSE) checkdbvars
$(GOOSE) -dir db/migrations postgres "$(CONNECT_STRING)" down
pg_dump -O -s $(CONNECT_STRING) > db/schema.sql
## Rollback to a select migration (id/timestamp)
.PHONY: rollback_to
rollback_to: $(GOOSE) checkmigration checkdbvars
$(GOOSE) -dir db/migrations postgres "$(CONNECT_STRING)" down-to "$(MIGRATION)"
## Apply all migrations not already run
.PHONY: migrate
migrate: $(GOOSE) checkdbvars
$(GOOSE) -dir db/migrations postgres "$(CONNECT_STRING)" up
pg_dump -O -s $(CONNECT_STRING) > db/schema.sql
## Create a new migration file
.PHONY: new_migration
new_migration: $(GOOSE) checkmigname
$(GOOSE) -dir db/migrations create $(NAME) sql
## Check which migrations are applied at the moment
.PHONY: migration_status
migration_status: $(GOOSE) checkdbvars
$(GOOSE) -dir db/migrations postgres "$(CONNECT_STRING)" status
# Convert timestamped migrations to versioned (to be run in CI);
# merge timestamped files to prevent conflict
.PHONY: version_migrations
version_migrations:
$(GOOSE) -dir db/migrations fix
# Import a psql schema to the database
.PHONY: import
import:
test -n "$(NAME)" # $$NAME
psql $(NAME) < db/schema.sql
## Build docker image
.PHONY: docker-build
docker-build:
docker build -t cerc-io/ipld-eth-server .

View File

@ -95,7 +95,7 @@ func init() {
func initConfig() {
if cfgFile == "" && envFile == "" {
log.Fatal("No configuration file specified, use --config , --env flag to provide configuration")
log.Warn("No configuration file specified, use --config , --env flag to provide configuration")
}
if cfgFile != "" {

View File

@ -60,6 +60,7 @@ func serve() {
logWithCommand.Fatal(err)
}
logWithCommand.Debugf("server config: %+v", serverConfig)
logWithCommand.Debugf("chain config: %+v", serverConfig.ChainConfig)
server, err := s.NewServer(serverConfig)
if err != nil {
logWithCommand.Fatal(err)
@ -276,10 +277,10 @@ func init() {
serveCmd.PersistentFlags().String("eth-client-name", "Geth", "eth client name")
serveCmd.PersistentFlags().String("eth-genesis-block", "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "eth genesis block hash")
serveCmd.PersistentFlags().String("eth-network-id", "1", "eth network id")
serveCmd.PersistentFlags().String("eth-chain-id", "1", "eth chain id")
serveCmd.PersistentFlags().String("eth-chain-id", "", "eth chain id")
serveCmd.PersistentFlags().String("eth-chain-config", "", "json chain config file location")
serveCmd.PersistentFlags().String("eth-default-sender", "", "default sender address")
serveCmd.PersistentFlags().String("eth-rpc-gas-cap", "", "rpc gas cap (for eth_Call execution)")
serveCmd.PersistentFlags().String("eth-chain-config", "", "json chain config file location")
serveCmd.PersistentFlags().Bool("eth-supports-state-diff", false, "whether the proxy ethereum client supports statediffing endpoints")
serveCmd.PersistentFlags().Bool("eth-forward-eth-calls", false, "whether to immediately forward eth_calls to proxy client")
serveCmd.PersistentFlags().Bool("eth-proxy-on-error", true, "whether to forward all failed calls to proxy client")

View File

@ -1,87 +0,0 @@
// Copyright © 2021 Vulcanize, Inc
//
// 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 cmd
import (
"time"
validator "github.com/cerc-io/eth-ipfs-state-validator/v5/pkg"
ipfsethdb "github.com/cerc-io/ipfs-ethdb/v5/postgres/v0"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
"github.com/ethereum/go-ethereum/common"
"github.com/spf13/cobra"
"github.com/spf13/viper"
s "github.com/cerc-io/ipld-eth-server/v5/pkg/serve"
)
const GroupName = "statedb-validate"
const CacheExpiryInMins = 8 * 60 // 8 hours
const CacheSizeInMB = 16 // 16 MB
var validateCmd = &cobra.Command{
Use: "validate",
Short: "validate state",
Long: `This command validates the trie for the given state root`,
Run: func(cmd *cobra.Command, args []string) {
subCommand = cmd.CalledAs()
logWithCommand = *log.WithField("SubCommand", subCommand)
validate()
},
}
func validate() {
config, err := s.NewConfig()
if err != nil {
logWithCommand.Fatal(err)
}
stateRootStr := viper.GetString("stateRoot")
if stateRootStr == "" {
logWithCommand.Fatal("must provide a state root for state validation")
}
stateRoot := common.HexToHash(stateRootStr)
cacheSize := viper.GetInt("cacheSize")
ethDB := ipfsethdb.NewDatabase(config.DB, ipfsethdb.CacheConfig{
Name: GroupName,
Size: cacheSize * 1024 * 1024,
ExpiryDuration: time.Minute * time.Duration(CacheExpiryInMins),
})
val := validator.NewValidator(nil, ethDB)
if err = val.ValidateTrie(stateRoot); err != nil {
log.Fatal("Error validating state root")
}
stats := ethDB.(*ipfsethdb.Database).GetCacheStats()
log.Debugf("groupcache stats %+v", stats)
log.Info("Successfully validated state root")
}
func init() {
rootCmd.AddCommand(validateCmd)
addDatabaseFlags(validateCmd)
validateCmd.PersistentFlags().String("state-root", "", "root of the state trie we wish to validate")
viper.BindPFlag("stateRoot", validateCmd.PersistentFlags().Lookup("state-root"))
validateCmd.PersistentFlags().Int("cache-size", CacheSizeInMB, "cache size in MB")
viper.BindPFlag("cacheSize", validateCmd.PersistentFlags().Lookup("cache-size"))
}

View File

@ -1,17 +1,8 @@
#!/bin/sh
echo "Beginning the ipld-eth-server process"
START_CMD="./ipld-eth-server"
if [ "true" == "$CERC_REMOTE_DEBUG" ] && [ -x "/usr/local/bin/dlv" ]; then
START_CMD="/usr/local/bin/dlv --listen=:40000 --headless=true --api-version=2 --accept-multiclient exec `pwd`/ipld-eth-server --continue --"
fi
echo running: $START_CMD ${VDB_COMMAND} --config=`pwd`/config.toml
$START_CMD ${VDB_COMMAND} --config=`pwd`/config.toml
rv=$?
if [ $rv != 0 ]; then
echo "ipld-eth-server startup failed"
exit 1
fi
exec $START_CMD ${VDB_COMMAND:-serve}

View File

@ -1,5 +1,5 @@
[database]
name = "vulcanize_testing"
name = "cerc_testing"
hostname = "localhost"
port = 5432

247
go.mod
View File

@ -3,26 +3,27 @@ module github.com/cerc-io/ipld-eth-server/v5
go 1.21
require (
github.com/cerc-io/eth-ipfs-state-validator/v5 v5.0.0-alpha
github.com/cerc-io/eth-iterator-utils v0.1.1
github.com/cerc-io/ipfs-ethdb/v5 v5.0.0-alpha
github.com/cerc-io/ipld-eth-statedb v0.0.5-alpha
github.com/cerc-io/plugeth-statediff v0.1.1
github.com/ethereum/go-ethereum v1.11.6
github.com/google/uuid v1.3.0
github.com/cerc-io/eth-ipfs-state-validator/v5 v5.2.0-alpha
github.com/cerc-io/eth-iterator-utils v0.3.1
github.com/cerc-io/ipfs-ethdb/v5 v5.1.0-alpha
github.com/cerc-io/ipld-eth-statedb v0.1.1
github.com/cerc-io/plugeth-statediff v0.3.2
github.com/ethereum/go-ethereum v1.13.14
github.com/google/uuid v1.6.0
github.com/graph-gophers/graphql-go v1.3.0
github.com/holiman/uint256 v1.2.4
github.com/ipfs/go-cid v0.4.1
github.com/jmoiron/sqlx v1.3.5
github.com/joho/godotenv v1.4.0
github.com/lib/pq v1.10.9
github.com/machinebox/graphql v0.2.2
github.com/mailgun/groupcache/v2 v2.3.0
github.com/onsi/ginkgo/v2 v2.11.0
github.com/onsi/gomega v1.27.8
github.com/prometheus/client_golang v1.16.0
github.com/sirupsen/logrus v1.9.0
github.com/spf13/cobra v1.4.0
github.com/spf13/viper v1.11.0
github.com/onsi/ginkgo/v2 v2.15.0
github.com/onsi/gomega v1.30.0
github.com/prometheus/client_golang v1.18.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.8.0
github.com/spf13/viper v1.18.2
gorm.io/driver/postgres v1.3.7
gorm.io/gorm v1.23.5
)
@ -31,10 +32,12 @@ require (
bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc // indirect
github.com/DataDog/zstd v1.5.5 // indirect
github.com/Jorropo/jsync v1.0.1 // indirect
github.com/VictoriaMetrics/fastcache v1.12.1 // indirect
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/VictoriaMetrics/fastcache v1.12.2 // indirect
github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect
github.com/benbjohnson/clock v1.3.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.10.0 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect
@ -42,106 +45,108 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cockroachdb/errors v1.10.0 // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cockroachdb/pebble v0.0.0-20230720154706-692f3b61a3c4 // indirect
github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 // indirect
github.com/cockroachdb/redact v1.1.5 // indirect
github.com/cockroachdb/tokenbucket v0.0.0-20230613231145-182959a1fad6 // indirect
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/consensys/bavard v0.1.13 // indirect
github.com/consensys/gnark-crypto v0.12.1 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
github.com/crackcomm/go-gitignore v0.0.0-20231225121904-e25f5bc08668 // indirect
github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 // indirect
github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect
github.com/cskr/pubsub v1.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/deckarep/golang-set/v2 v2.3.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/deepmap/oapi-codegen v1.8.2 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/edsrzf/mmap-go v1.0.0 // indirect
github.com/elastic/gosigar v0.14.2 // indirect
github.com/ethereum/c-kzg-4844 v0.4.0 // indirect
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect
github.com/fjl/memsize v0.0.1 // indirect
github.com/flynn/noise v1.0.0 // indirect
github.com/ferranbt/fastssz v0.1.2 // indirect
github.com/fjl/memsize v0.0.2 // indirect
github.com/flynn/noise v1.1.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.1 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 // indirect
github.com/georgysavva/scany v0.2.9 // indirect
github.com/getsentry/sentry-go v0.22.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e // indirect
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-bexpr v0.1.12 // 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/golang-lru/v2 v2.0.5 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 // indirect
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
github.com/holiman/uint256 v1.2.3 // indirect
github.com/huin/goupnp v1.2.0 // indirect
github.com/huin/goupnp v1.3.0 // indirect
github.com/inconshreveable/log15 v2.16.0+incompatible // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/influxdata/influxdb-client-go/v2 v2.4.0 // indirect
github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c // indirect
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
github.com/ipfs/bbloom v0.0.4 // indirect
github.com/ipfs/boxo v0.13.1 // indirect
github.com/ipfs/boxo v0.19.0 // indirect
github.com/ipfs/go-bitfield v1.1.0 // indirect
github.com/ipfs/go-block-format v0.1.2 // indirect
github.com/ipfs/go-block-format v0.2.0 // indirect
github.com/ipfs/go-cidutil v0.1.0 // indirect
github.com/ipfs/go-datastore v0.6.0 // indirect
github.com/ipfs/go-ds-measure v0.2.0 // indirect
github.com/ipfs/go-fs-lock v0.0.7 // indirect
github.com/ipfs/go-graphsync v0.15.1 // indirect
github.com/ipfs/go-ipfs-blockstore v1.3.0 // indirect
github.com/ipfs/go-ipfs-delay v0.0.1 // indirect
github.com/ipfs/go-ipfs-ds-help v1.1.0 // indirect
github.com/ipfs/go-ipfs-pq v0.0.3 // indirect
github.com/ipfs/go-ipfs-redirects-file v0.1.1 // indirect
github.com/ipfs/go-ipfs-util v0.0.3 // indirect
github.com/ipfs/go-ipld-cbor v0.0.6 // indirect
github.com/ipfs/go-ipld-format v0.5.0 // indirect
github.com/ipfs/go-ipld-cbor v0.1.0 // indirect
github.com/ipfs/go-ipld-format v0.6.0 // indirect
github.com/ipfs/go-ipld-legacy v0.2.1 // indirect
github.com/ipfs/go-log v1.0.5 // indirect
github.com/ipfs/go-log/v2 v2.5.1 // indirect
github.com/ipfs/go-metrics-interface v0.0.1 // indirect
github.com/ipfs/go-peertaskqueue v0.8.1 // indirect
github.com/ipfs/go-unixfsnode v1.8.1 // indirect
github.com/ipfs/kubo v0.23.0 // indirect
github.com/ipld/go-car/v2 v2.10.2-0.20230622090957-499d0c909d33 // indirect
github.com/ipfs/go-unixfsnode v1.9.0 // indirect
github.com/ipfs/kubo v0.27.0 // indirect
github.com/ipld/go-car/v2 v2.13.1 // indirect
github.com/ipld/go-codec-dagpb v1.6.0 // indirect
github.com/ipld/go-ipld-prime v0.21.0 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.14.0 // indirect
github.com/jackc/pgconn v1.14.3 // indirect
github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.3.2 // indirect
github.com/jackc/pgproto3/v2 v2.3.3 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgtype v1.14.0 // indirect
github.com/jackc/pgx/v4 v4.18.1 // indirect
github.com/jackc/pgx/v4 v4.18.3 // indirect
github.com/jackc/puddle v1.3.0 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.4 // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/klauspost/compress v1.17.6 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
@ -149,145 +154,143 @@ require (
github.com/libp2p/go-cidranger v1.1.0 // indirect
github.com/libp2p/go-doh-resolver v0.4.0 // indirect
github.com/libp2p/go-flow-metrics v0.1.0 // indirect
github.com/libp2p/go-libp2p v0.31.0 // indirect
github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect
github.com/libp2p/go-libp2p v0.33.0 // indirect
github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
github.com/libp2p/go-libp2p-kad-dht v0.24.4 // indirect
github.com/libp2p/go-libp2p-kbucket v0.6.3 // indirect
github.com/libp2p/go-libp2p-pubsub v0.9.3 // indirect
github.com/libp2p/go-libp2p-pubsub v0.10.0 // indirect
github.com/libp2p/go-libp2p-pubsub-router v0.6.0 // indirect
github.com/libp2p/go-libp2p-record v0.2.0 // indirect
github.com/libp2p/go-libp2p-routing-helpers v0.7.3 // 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.3.0 // indirect
github.com/libp2p/go-nat v0.2.0 // indirect
github.com/libp2p/go-netroute v0.2.1 // indirect
github.com/libp2p/go-reuseport v0.4.0 // indirect
github.com/libp2p/go-yamux/v4 v4.0.1 // indirect
github.com/libp2p/zeroconf/v2 v2.2.0 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
github.com/matryer/is v1.4.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/miekg/dns v1.1.55 // indirect
github.com/miekg/dns v1.1.58 // 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.1 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/pointerstructure v1.2.1 // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect
github.com/multiformats/go-base36 v0.2.0 // indirect
github.com/multiformats/go-multiaddr v0.11.0 // indirect
github.com/multiformats/go-multiaddr v0.12.2 // 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.2.0 // indirect
github.com/multiformats/go-multicodec v0.9.0 // indirect
github.com/multiformats/go-multihash v0.2.3 // indirect
github.com/multiformats/go-multistream v0.4.1 // indirect
github.com/multiformats/go-multistream v0.5.0 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/opencontainers/runtime-spec v1.1.0 // indirect
github.com/openrelayxyz/plugeth-utils v1.2.0 // indirect
github.com/opencontainers/runtime-spec v1.2.0 // indirect
github.com/openrelayxyz/plugeth-utils v1.5.0 // 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.5 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 // indirect
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 // indirect
github.com/pganalyze/pg_query_go/v4 v4.2.1 // indirect
github.com/pion/datachannel v1.5.5 // indirect
github.com/pion/dtls/v2 v2.2.8 // indirect
github.com/pion/ice/v2 v2.3.11 // indirect
github.com/pion/interceptor v0.1.25 // indirect
github.com/pion/logging v0.2.2 // indirect
github.com/pion/mdns v0.0.9 // indirect
github.com/pion/randutil v0.1.0 // indirect
github.com/pion/rtcp v1.2.13 // indirect
github.com/pion/rtp v1.8.3 // indirect
github.com/pion/sctp v1.8.9 // indirect
github.com/pion/sdp/v3 v3.0.6 // indirect
github.com/pion/srtp/v2 v2.0.18 // indirect
github.com/pion/stun v0.6.1 // indirect
github.com/pion/transport/v2 v2.2.4 // indirect
github.com/pion/turn/v2 v2.1.4 // indirect
github.com/pion/webrtc/v3 v3.2.23 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/polydawn/refmt v0.89.0 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.11.1 // indirect
github.com/prometheus/client_model v0.6.0 // indirect
github.com/prometheus/common v0.47.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-20 v0.3.3 // indirect
github.com/quic-go/quic-go v0.38.1 // indirect
github.com/quic-go/webtransport-go v0.5.3 // indirect
github.com/quic-go/quic-go v0.41.0 // indirect
github.com/quic-go/webtransport-go v0.6.0 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/rs/cors v1.9.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/samber/lo v1.36.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/samber/lo v1.39.0 // indirect
github.com/segmentio/fasthash v1.0.3 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/sourcegraph/conc v0.3.0 // 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/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/status-im/keycard-go v0.2.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/stretchr/testify v1.8.4 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/stretchr/testify v1.9.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/supranational/blst v0.3.11 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect
github.com/thoas/go-funk v0.9.3 // indirect
github.com/tklauser/go-sysconf v0.3.11 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/ucarion/urlpath v0.0.0-20200424170820-7ccc79b76bbb // indirect
github.com/urfave/cli/v2 v2.25.7 // indirect
github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect
github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 // indirect
github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa // indirect
github.com/whyrusleeping/cbor-gen v0.0.0-20240109153615-66e95c3e8a87 // 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/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/otel v1.16.0 // indirect
go.opentelemetry.io/otel/metric v1.16.0 // indirect
go.opentelemetry.io/otel/trace v1.16.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/dig v1.17.0 // indirect
go.uber.org/fx v1.20.0 // indirect
go.opentelemetry.io/otel v1.25.0 // indirect
go.opentelemetry.io/otel/metric v1.25.0 // indirect
go.opentelemetry.io/otel/trace v1.25.0 // indirect
go.uber.org/dig v1.17.1 // indirect
go.uber.org/fx v1.20.1 // indirect
go.uber.org/mock v0.4.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.25.0 // indirect
go.uber.org/zap v1.27.0 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/term v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
gonum.org/v1/gonum v0.13.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/term v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.20.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
gonum.org/v1/gonum v0.14.0 // indirect
google.golang.org/protobuf v1.32.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
)
replace (
// github.com/cerc-io/eth-ipfs-state-validator/v5 => git.vdb.to/cerc-io/eth-ipfs-state-validator/v5 v5.1.1-alpha
github.com/cerc-io/eth-iterator-utils => git.vdb.to/cerc-io/eth-iterator-utils v0.1.2
github.com/cerc-io/eth-testing => git.vdb.to/cerc-io/eth-testing v0.3.1
github.com/cerc-io/ipld-eth-statedb => git.vdb.to/cerc-io/ipld-eth-statedb v0.0.6-alpha
github.com/cerc-io/plugeth-statediff => git.vdb.to/cerc-io/plugeth-statediff v0.1.4
github.com/ethereum/go-ethereum => git.vdb.to/cerc-io/plugeth v0.0.0-20230808125822-691dc334fab1
github.com/openrelayxyz/plugeth-utils => git.vdb.to/cerc-io/plugeth-utils v0.0.0-20230706160122-cd41de354c46
)
// TODO: Use releases after these branches get merged
replace (
// https://git.vdb.to/cerc-io/eth-ipfs-state-validator/src/branch/v5-go-upgrade
github.com/cerc-io/eth-ipfs-state-validator/v5 => github.com/cerc-io/eth-ipfs-state-validator/v5 v5.1.1-alpha.0.20231013075659-56aa03028c43
// https://git.vdb.to/cerc-io/ipfs-ethdb/src/branch/v5-go-upgrade
github.com/cerc-io/ipfs-ethdb/v5 => github.com/cerc-io/ipfs-ethdb/v5 v5.0.1-alpha.0.20231013070931-0b1a36562a28
lukechampine.com/blake3 v1.2.2 // indirect
rsc.io/tmplfunc v0.0.3 // indirect
)

753
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -22,13 +22,13 @@ var _ = Describe("Direct proxy integration test", Label("proxy"), func() {
var contractErr error
var txErr error
Describe("get Block", func() {
Describe("Get Block", func() {
BeforeEach(func() {
contract, contractErr = integration.DeployContract()
Expect(contractErr).ToNot(HaveOccurred())
})
It("get not existing block by number", func() {
It("gets not existing block by number", func() {
blockNum := contract.BlockNumber + 100
gethBlock, err := gethClient.BlockByNumber(ctx, big.NewInt(blockNum))
@ -40,7 +40,7 @@ var _ = Describe("Direct proxy integration test", Label("proxy"), func() {
Expect(ipldBlock).To(BeZero())
})
It("get not existing block by hash", func() {
It("gets not existing block by hash", func() {
gethBlock, err := gethClient.BlockByHash(ctx, nonExistingBlockHash)
Expect(err).To(MatchError(ethereum.NotFound))
Expect(gethBlock).To(BeZero())
@ -50,7 +50,7 @@ var _ = Describe("Direct proxy integration test", Label("proxy"), func() {
Expect(ipldBlock).To(BeZero())
})
It("get block by number", func() {
It("gets block by number", func() {
blockNum := contract.BlockNumber
_, err := gethClient.BlockByNumber(ctx, big.NewInt(blockNum))
@ -60,7 +60,7 @@ var _ = Describe("Direct proxy integration test", Label("proxy"), func() {
Expect(err).To(HaveOccurred())
})
It("get block by hash", func() {
It("gets block by hash", func() {
_, err := gethClient.BlockByHash(ctx, contract.BlockHash)
Expect(err).ToNot(HaveOccurred())

View File

@ -34,7 +34,7 @@ var _ = Describe("Basic integration test", func() {
var contractErr error
var txErr error
Describe("get Block", func() {
Describe("Get Block", func() {
BeforeEach(func() {
contract, contractErr = integration.DeployContract()
Expect(contractErr).ToNot(HaveOccurred())
@ -43,7 +43,7 @@ var _ = Describe("Basic integration test", func() {
Expect(err).ToNot(HaveOccurred())
})
It("get not existing block by number", func() {
It("gets not existing block by number", func() {
blockNum := big.NewInt(contract.BlockNumber + 100)
gethBlock, err := gethClient.BlockByNumber(ctx, blockNum)
@ -55,7 +55,7 @@ var _ = Describe("Basic integration test", func() {
Expect(ipldBlock).To(BeZero())
})
It("get not existing block by hash", func() {
It("gets not existing block by hash", func() {
gethBlock, err := gethClient.BlockByHash(ctx, nonExistingBlockHash)
Expect(err).To(MatchError(ethereum.NotFound))
Expect(gethBlock).To(BeZero())
@ -65,7 +65,7 @@ var _ = Describe("Basic integration test", func() {
Expect(ipldBlock).To(BeZero())
})
It("get block by number", func() {
It("gets block by number", func() {
blockNum := big.NewInt(contract.BlockNumber)
gethBlock, err := gethClient.BlockByNumber(ctx, blockNum)
@ -84,7 +84,7 @@ var _ = Describe("Basic integration test", func() {
Expect(types.TxDifference(gethTxs, ipldTxs).Len()).To(Equal(0))
})
It("get block by hash", func() {
It("gets block by hash", func() {
gethBlock, err := gethClient.BlockByHash(ctx, contract.BlockHash)
Expect(err).ToNot(HaveOccurred())
@ -391,7 +391,7 @@ var _ = Describe("Basic integration test", func() {
Expect(ipldCountA).To(Equal(slvCountA))
})
It("gets storage after destruction and redeploy", func() {
It("gets storage after destruction", func() {
slvContract, contractErr := integration.Create2Contract("SLVToken", contractSalt)
Expect(contractErr).ToNot(HaveOccurred())
@ -431,21 +431,6 @@ var _ = Describe("Basic integration test", func() {
ipldStorage, err := ipldClient.StorageAt(ctx, slvContract.Address, countAIndex, big.NewInt(slvTx.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(ipldStorage).To(Equal(gethStorage))
// Redeploy to same address
slvContract, contractErr = integration.Create2Contract("SLVToken", contractSalt)
Expect(contractErr).ToNot(HaveOccurred())
gethStorage, err = gethClient.StorageAt(ctx, slvContract.Address, countAIndex, big.NewInt(slvContract.BlockNumber))
Expect(err).ToNot(HaveOccurred())
ipldStorage, err = ipldClient.StorageAt(ctx, slvContract.Address, countAIndex, big.NewInt(slvContract.BlockNumber))
Expect(err).ToNot(HaveOccurred())
Expect(gethStorage).To(Equal(ipldStorage))
ipldCountA := new(big.Int).SetBytes(ipldStorage)
Expect(ipldCountA.String()).To(Equal("0"))
})
})

View File

@ -19,19 +19,25 @@ package eth
import (
"context"
"database/sql"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"math/big"
"strconv"
"strings"
"time"
"github.com/cerc-io/plugeth-statediff"
ipld_direct_state "github.com/cerc-io/ipld-eth-statedb/direct_by_leaf"
"github.com/cerc-io/ipld-eth-statedb/trie_by_cid/state"
"github.com/cerc-io/ipld-eth-statedb/trie_by_cid/trie"
statediff "github.com/cerc-io/plugeth-statediff"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
@ -39,9 +45,9 @@ import (
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/holiman/uint256"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
ipld_direct_state "github.com/cerc-io/ipld-eth-statedb/direct_by_leaf"
)
const (
@ -106,6 +112,25 @@ Headers and blocks
*/
// decodeHash parses a hex-encoded 32-byte hash. The input may optionally
// be prefixed by 0x and can have a byte length up to 32.
func decodeHash(s string) (h common.Hash, inputLength int, err error) {
if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") {
s = s[2:]
}
if (len(s) & 1) > 0 {
s = "0" + s
}
b, err := hex.DecodeString(s)
if err != nil {
return common.Hash{}, 0, errors.New("hex string invalid")
}
if len(b) > 32 {
return common.Hash{}, len(b), errors.New("hex string too long, want at most 32 bytes")
}
return common.BytesToHash(b), len(b), nil
}
// GetHeaderByNumber returns the requested canonical block header.
// * When blockNr is -1 the chain head is returned.
// * We cannot support pending block calls since we do not have an active miner
@ -222,8 +247,7 @@ Uncles
*/
// GetUncleByBlockNumberAndIndex returns the uncle block for the given block hash and index. When fullTx is true
// all transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
// GetUncleByBlockNumberAndIndex returns the uncle block for the given block hash and index.
func (pea *PublicEthAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (map[string]interface{}, error) {
block, err := pea.B.BlockByNumber(ctx, blockNr)
if block != nil && err == nil {
@ -379,7 +403,7 @@ func (pea *PublicEthAPI) GetBlockTransactionCountByHash(ctx context.Context, blo
// GetTransactionByBlockNumberAndIndex returns the transaction for the given block number and index.
func (pea *PublicEthAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) *RPCTransaction {
if block, _ := pea.B.BlockByNumber(ctx, blockNr); block != nil {
return newRPCTransactionFromBlockIndex(block, uint64(index))
return newRPCTransactionFromBlockIndex(block, uint64(index), pea.B.ChainConfig())
}
if pea.config.ProxyOnError {
@ -396,7 +420,7 @@ func (pea *PublicEthAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context
// GetTransactionByBlockHashAndIndex returns the transaction for the given block hash and index.
func (pea *PublicEthAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) *RPCTransaction {
if block, _ := pea.B.BlockByHash(ctx, blockHash); block != nil {
return newRPCTransactionFromBlockIndex(block, uint64(index))
return newRPCTransactionFromBlockIndex(block, uint64(index), pea.B.ChainConfig())
}
if pea.config.ProxyOnError {
@ -443,14 +467,14 @@ func (pea *PublicEthAPI) GetRawTransactionByBlockHashAndIndex(ctx context.Contex
// GetTransactionByHash returns the transaction for the given hash
// eth ipld-eth-server cannot currently handle pending/tx_pool txs
func (pea *PublicEthAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (*RPCTransaction, error) {
tx, blockHash, blockNumber, index, err := pea.B.GetTransaction(ctx, hash)
_, tx, blockHash, blockNumber, index, err := pea.B.GetTransaction(ctx, hash)
if tx != nil && err == nil {
header, err := pea.B.HeaderByHash(ctx, blockHash)
if err != nil {
return nil, err
}
return NewRPCTransaction(tx, blockHash, blockNumber, index, header.BaseFee), nil
return NewRPCTransaction(tx, blockHash, blockNumber, header.Time, index, header.BaseFee, pea.B.ChainConfig()), nil
}
if pea.config.ProxyOnError {
var tx *RPCTransaction
@ -465,7 +489,7 @@ func (pea *PublicEthAPI) GetTransactionByHash(ctx context.Context, hash common.H
// GetRawTransactionByHash returns the bytes of the transaction for the given hash.
func (pea *PublicEthAPI) GetRawTransactionByHash(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
// Retrieve a finalized transaction, or a pooled otherwise
tx, _, _, _, err := pea.B.GetTransaction(ctx, hash)
_, tx, _, _, _, err := pea.B.GetTransaction(ctx, hash)
if tx != nil && err == nil {
return tx.MarshalBinary()
}
@ -580,7 +604,7 @@ func (pea *PublicEthAPI) GetTransactionReceipt(ctx context.Context, hash common.
func (pea *PublicEthAPI) localGetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) {
// TODO: this can be optimized for Postgres
tx, blockHash, blockNumber, index, err := pea.B.GetTransaction(ctx, hash)
_, tx, blockHash, blockNumber, index, err := pea.B.GetTransaction(ctx, hash)
if err != nil {
return nil, err
}
@ -595,7 +619,11 @@ func (pea *PublicEthAPI) localGetTransactionReceipt(ctx context.Context, hash co
if err != nil {
return nil, err
}
err = receipts.DeriveFields(pea.B.Config.ChainConfig, blockHash, blockNumber, block.BaseFee(), block.Transactions())
var blobGasPrice *big.Int
if excessBlobGas := block.ExcessBlobGas(); excessBlobGas != nil {
blobGasPrice = eip4844.CalcBlobFee(*excessBlobGas)
}
err = receipts.DeriveFields(pea.B.Config.ChainConfig, blockHash, blockNumber, block.Time(), block.BaseFee(), blobGasPrice, block.Transactions())
if err != nil {
return nil, err
}
@ -632,6 +660,12 @@ func (pea *PublicEthAPI) localGetTransactionReceipt(ctx context.Context, hash co
if receipt.Logs == nil {
fields["logs"] = []*types.Log{}
}
if tx.Type() == types.BlobTxType {
fields["blobGasUsed"] = hexutil.Uint64(receipt.BlobGasUsed)
fields["blobGasPrice"] = (*hexutil.Big)(receipt.BlobGasPrice)
}
// If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation
if receipt.ContractAddress != (common.Address{}) {
fields["contractAddress"] = receipt.ContractAddress
@ -793,7 +827,7 @@ func (pea *PublicEthAPI) localGetBalance(ctx context.Context, address common.Add
if err != nil {
return nil, err
}
return (*hexutil.Big)(account.Balance), nil
return (*hexutil.Big)(account.Balance.ToBig()), nil
}
// GetStorageAt returns the storage from the state at the given address, key and
@ -822,7 +856,7 @@ func (pea *PublicEthAPI) GetStorageAt(ctx context.Context, address common.Addres
return value[:], nil
}
if pea.config.ProxyOnError {
log.Warnxf(ctx, "Missing eth_getStorageAt(%s, %s, %s)", address.Hash().String(), key, blockNrOrHash.String())
log.Warnxf(ctx, "Missing eth_getStorageAt(%s, %s, %s)", address, key, blockNrOrHash.String())
var res hexutil.Bytes
if err := pea.rpc.CallContext(ctx, &res, "eth_getStorageAt", address, key, blockNrOrHash); res != nil && err == nil {
return res, nil
@ -868,57 +902,95 @@ func (pea *PublicEthAPI) GetProof(ctx context.Context, address common.Address, s
return nil, err
}
// proofList implements ethdb.KeyValueWriter and collects the proofs as
// hex-strings for delivery to rpc-caller.
type proofList []string
func (n *proofList) Put(key []byte, value []byte) error {
*n = append(*n, hexutil.Encode(value))
return nil
}
func (n *proofList) Delete(key []byte) error {
panic("not supported")
}
// this continues to use ipfs-ethdb based geth StateDB as it requires trie access
func (pea *PublicEthAPI) localGetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (*AccountResult, error) {
state, _, err := pea.B.IPLDTrieStateDBAndHeaderByNumberOrHash(ctx, blockNrOrHash)
if state == nil || err != nil {
return nil, err
}
storageTrie, err := state.StorageTrie(address)
if storageTrie == nil || err != nil {
return nil, err
}
storageHash := types.EmptyRootHash
codeHash := state.GetCodeHash(address)
storageProof := make([]StorageResult, len(storageKeys))
// if we have a storageTrie, (which means the account exists), we can update the storagehash
if storageTrie != nil {
storageHash = storageTrie.Hash()
} else {
// no storageTrie means the account does not exist, so the codeHash is the hash of an empty bytearray.
codeHash = crypto.Keccak256Hash(nil)
}
// create the proof for the storageKeys
for i, key := range storageKeys {
if storageTrie != nil {
proof, storageError := state.GetStorageProof(address, common.HexToHash(key))
if storageError != nil {
return nil, storageError
}
storageProof[i] = StorageResult{key, (*hexutil.Big)(state.GetState(address, common.HexToHash(key)).Big()), toHexSlice(proof)}
} else {
storageProof[i] = StorageResult{key, &hexutil.Big{}, []string{}}
var (
keys = make([]common.Hash, len(storageKeys))
keyLengths = make([]int, len(storageKeys))
storageProof = make([]StorageResult, len(storageKeys))
)
// Deserialize all keys. This prevents state access on invalid input.
for i, hexKey := range storageKeys {
var err error
keys[i], keyLengths[i], err = decodeHash(hexKey)
if err != nil {
return nil, err
}
}
// create the accountProof
accountProof, proofErr := state.GetProof(address)
if proofErr != nil {
return nil, proofErr
statedb, header, err := pea.B.IPLDTrieStateDBAndHeaderByNumberOrHash(ctx, blockNrOrHash)
// statedb, header, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
if statedb == nil || err != nil {
return nil, err
}
codeHash := statedb.GetCodeHash(address)
storageRoot := statedb.GetStorageRoot(address)
if len(keys) > 0 {
var storageTrie state.Trie
if storageRoot != types.EmptyRootHash && storageRoot != (common.Hash{}) {
id := trie.StorageTrieID(header.Root, crypto.Keccak256Hash(address.Bytes()), storageRoot)
st, err := trie.NewStateTrie(id, statedb.Database().TrieDB())
if err != nil {
return nil, err
}
storageTrie = st
}
// Create the proofs for the storageKeys.
for i, key := range keys {
// Output key encoding is a bit special: if the input was a 32-byte hash, it is
// returned as such. Otherwise, we apply the QUANTITY encoding mandated by the
// JSON-RPC spec for getProof. This behavior exists to preserve backwards
// compatibility with older client versions.
var outputKey string
if keyLengths[i] != 32 {
outputKey = hexutil.EncodeBig(key.Big())
} else {
outputKey = hexutil.Encode(key[:])
}
if storageTrie == nil {
storageProof[i] = StorageResult{outputKey, &hexutil.Big{}, []string{}}
continue
}
var proof proofList
if err := storageTrie.Prove(crypto.Keccak256(key.Bytes()), &proof); err != nil {
return nil, err
}
value := (*hexutil.Big)(statedb.GetState(address, key).Big())
storageProof[i] = StorageResult{outputKey, value, proof}
}
}
// Create the accountProof.
tr, err := trie.NewStateTrie(trie.StateTrieID(header.Root), statedb.Database().TrieDB())
if err != nil {
return nil, err
}
var accountProof proofList
if err := tr.Prove(crypto.Keccak256(address.Bytes()), &accountProof); err != nil {
return nil, err
}
balance := statedb.GetBalance(address).ToBig()
return &AccountResult{
Address: address,
AccountProof: toHexSlice(accountProof),
Balance: (*hexutil.Big)(state.GetBalance(address)),
AccountProof: accountProof,
Balance: (*hexutil.Big)(balance),
CodeHash: codeHash,
Nonce: hexutil.Uint64(state.GetNonce(address)),
StorageHash: storageHash,
Nonce: hexutil.Uint64(statedb.GetNonce(address)),
StorageHash: storageRoot,
StorageProof: storageProof,
}, state.Error()
}, statedb.Error()
}
// GetSlice returns a slice of state or storage nodes from a provided root to a provided path and past it to a certain depth
@ -989,7 +1061,7 @@ func (diff *StateOverride) Apply(state *ipld_direct_state.StateDB) error {
}
// Override account balance.
if account.Balance != nil {
state.SetBalance(addr, (*big.Int)(*account.Balance))
state.SetBalance(addr, uint256.MustFromBig((*big.Int)(*account.Balance)))
}
if account.State != nil && account.StateDiff != nil {
return fmt.Errorf("account %s has both 'state' and 'stateDiff'", addr.Hex())
@ -1175,25 +1247,22 @@ func (pea *PublicEthAPI) writeStateDiffFor(blockHash common.Hash) {
// rpcMarshalBlock uses the generalized output filler, then adds the total difficulty field
func (pea *PublicEthAPI) rpcMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
fields, err := RPCMarshalBlock(b, inclTx, fullTx)
if err != nil {
log.Errorf("error RPC marshalling block with hash %s: %s", b.Hash().String(), err)
return nil, err
}
fields := RPCMarshalBlock(b, inclTx, fullTx, pea.B.ChainConfig())
if inclTx {
td, err := pea.B.GetTd(b.Hash())
if err != nil {
log.Errorf("error getting td for block with hash and number %s, %s: %s", b.Hash().String(), b.Number().String(), err)
err = fmt.Errorf("error getting TD for block at (%s, %s): %s", b.Number(), b.Hash(), err)
log.Error(err)
return nil, err
}
fields["totalDifficulty"] = (*hexutil.Big)(td)
}
return fields, err
return fields, nil
}
// rpcMarshalBlockWithUncleHashes uses the generalized output filler, then adds the total difficulty field
func (pea *PublicEthAPI) rpcMarshalBlockWithUncleHashes(b *types.Block, uncleHashes []common.Hash, inclTx bool, fullTx bool) (map[string]interface{}, error) {
fields, err := RPCMarshalBlockWithUncleHashes(b, uncleHashes, inclTx, fullTx)
fields, err := RPCMarshalBlockWithUncleHashes(b, uncleHashes, inclTx, fullTx, pea.B.ChainConfig())
if err != nil {
return nil, err
}

View File

@ -19,7 +19,6 @@ package eth_api_test
import (
"context"
"math/big"
"strconv"
"github.com/cerc-io/plugeth-statediff/indexer/interfaces"
"github.com/cerc-io/plugeth-statediff/indexer/ipld"
@ -44,12 +43,14 @@ import (
var (
randomAddr = common.HexToAddress("0x1C3ab14BBaD3D99F4203bd7a11aCB94882050E6f")
randomHash = crypto.Keccak256Hash(randomAddr.Bytes())
number = rpc.BlockNumber(test_helpers.BlockNumber.Int64())
londonBlockNum = rpc.BlockNumber(test_helpers.LondonBlockNum.Int64())
number = rpc.BlockNumber(test_helpers.BlockNumber1)
blockTime = test_helpers.BlockTime1
londonBlockNum = rpc.BlockNumber(test_helpers.LondonBlockNum)
wrongNumber = number + 1
blockHash = test_helpers.MockBlock.Header().Hash()
baseFee = test_helpers.MockLondonBlock.BaseFee()
ctx = context.Background()
chainConfig = &*params.MergedTestChainConfig
expectedBlock = map[string]interface{}{
"number": (*hexutil.Big)(test_helpers.MockBlock.Number()),
@ -83,7 +84,6 @@ var (
"miner": test_helpers.MockBlock.Header().Coinbase,
"difficulty": (*hexutil.Big)(test_helpers.MockBlock.Header().Difficulty),
"extraData": hexutil.Bytes(test_helpers.MockBlock.Header().Extra),
"size": hexutil.Uint64(test_helpers.MockBlock.Header().Size()),
"gasLimit": hexutil.Uint64(test_helpers.MockBlock.Header().GasLimit),
"gasUsed": hexutil.Uint64(test_helpers.MockBlock.Header().GasUsed),
"timestamp": hexutil.Uint64(test_helpers.MockBlock.Header().Time),
@ -131,14 +131,22 @@ var (
"receiptsRoot": test_helpers.MockUncles[1].ReceiptHash,
"uncles": []common.Hash{},
}
expectedTransaction = eth.NewRPCTransaction(test_helpers.MockTransactions[0], test_helpers.MockBlock.Hash(), test_helpers.MockBlock.NumberU64(), 0, test_helpers.MockBlock.BaseFee())
expectedTransaction2 = eth.NewRPCTransaction(test_helpers.MockTransactions[1], test_helpers.MockBlock.Hash(), test_helpers.MockBlock.NumberU64(), 1, test_helpers.MockBlock.BaseFee())
expectedTransaction3 = eth.NewRPCTransaction(test_helpers.MockTransactions[2], test_helpers.MockBlock.Hash(), test_helpers.MockBlock.NumberU64(), 2, test_helpers.MockBlock.BaseFee())
expectedLondonTransaction = eth.NewRPCTransaction(test_helpers.MockLondonTransactions[0], test_helpers.MockLondonBlock.Hash(), test_helpers.MockLondonBlock.NumberU64(), 0, test_helpers.MockLondonBlock.BaseFee())
expectRawTx, _ = test_helpers.MockTransactions[0].MarshalBinary()
expectRawTx2, _ = test_helpers.MockTransactions[1].MarshalBinary()
expectRawTx3, _ = test_helpers.MockTransactions[2].MarshalBinary()
expectedReceipt = map[string]interface{}{
expectedTransaction = eth.NewRPCTransaction(test_helpers.MockTransactions[0], test_helpers.MockBlock.Hash(), test_helpers.MockBlock.NumberU64(), blockTime, 0, test_helpers.MockBlock.BaseFee(), chainConfig)
expectedTransaction2 = eth.NewRPCTransaction(test_helpers.MockTransactions[1], test_helpers.MockBlock.Hash(), test_helpers.MockBlock.NumberU64(), blockTime, 1, test_helpers.MockBlock.BaseFee(), chainConfig)
expectedTransaction3 = eth.NewRPCTransaction(test_helpers.MockTransactions[2], test_helpers.MockBlock.Hash(), test_helpers.MockBlock.NumberU64(), blockTime, 2, test_helpers.MockBlock.BaseFee(), chainConfig)
expectedLondonTransaction = eth.NewRPCTransaction(
test_helpers.MockLondonTransactions[0],
test_helpers.MockLondonBlock.Hash(),
test_helpers.MockLondonBlock.NumberU64(),
test_helpers.MockLondonBlock.Time(),
0,
test_helpers.MockLondonBlock.BaseFee(),
chainConfig,
)
expectRawTx, _ = test_helpers.MockTransactions[0].MarshalBinary()
expectRawTx2, _ = test_helpers.MockTransactions[1].MarshalBinary()
expectRawTx3, _ = test_helpers.MockTransactions[2].MarshalBinary()
expectedReceipt = map[string]interface{}{
"blockHash": blockHash,
"blockNumber": hexutil.Uint64(uint64(number.Int64())),
"transactionHash": expectedTransaction.Hash,
@ -187,10 +195,10 @@ var (
"type": hexutil.Uint64(types.LegacyTxType),
}
)
var (
db *sqlx.DB
api *eth.PublicEthAPI
chainConfig = params.TestChainConfig
db *sqlx.DB
api *eth.PublicEthAPI
)
var _ = BeforeSuite(func() {
@ -293,9 +301,7 @@ var _ = Describe("API", func() {
Describe("eth_blockNumber", func() {
It("Retrieves the head block number", func() {
bn := api.BlockNumber()
ubn := (uint64)(bn)
subn := strconv.FormatUint(ubn, 10)
Expect(subn).To(Equal(test_helpers.LondonBlockNum.String()))
Expect(bn).To(Equal(hexutil.Uint64(test_helpers.LondonBlockNum)))
})
})
@ -317,7 +323,7 @@ var _ = Describe("API", func() {
Expect(err).ToNot(HaveOccurred())
transactions := make([]interface{}, len(test_helpers.MockBlock.Transactions()))
for i, trx := range test_helpers.MockBlock.Transactions() {
transactions[i] = eth.NewRPCTransactionFromBlockHash(test_helpers.MockBlock, trx.Hash())
transactions[i] = eth.NewRPCTransactionFromBlockHash(test_helpers.MockBlock, trx.Hash(), chainConfig)
}
expectedBlock["transactions"] = transactions
for key, val := range expectedBlock {
@ -371,7 +377,7 @@ var _ = Describe("API", func() {
Expect(err).ToNot(HaveOccurred())
transactions := make([]interface{}, len(test_helpers.MockBlock.Transactions()))
for i, trx := range test_helpers.MockBlock.Transactions() {
transactions[i] = eth.NewRPCTransactionFromBlockHash(test_helpers.MockBlock, trx.Hash())
transactions[i] = eth.NewRPCTransactionFromBlockHash(test_helpers.MockBlock, trx.Hash(), chainConfig)
}
expectedBlock["transactions"] = transactions
for key, val := range expectedBlock {
@ -384,7 +390,7 @@ var _ = Describe("API", func() {
Expect(block).To(BeZero())
})
It("Fetch BaseFee from london block by block hash, returns `nil` for legacy block", func() {
block, err := api.GetBlockByHash(ctx, test_helpers.MockBlock.Hash(), true)
block, err := api.GetBlockByHash(ctx, test_helpers.MockBlock.Hash(), false)
Expect(err).ToNot(HaveOccurred())
_, ok := block["baseFeePerGas"]
Expect(ok).To(Equal(false))
@ -1104,20 +1110,20 @@ var _ = Describe("API", func() {
It("Retrieves the eth balance for the provided account address at the block with the provided number", func() {
bal, err := api.GetBalance(ctx, test_helpers.AccountAddresss, rpc.BlockNumberOrHashWithNumber(number))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal((*hexutil.Big)(test_helpers.AccountBalance)))
Expect(bal).To(Equal((*hexutil.Big)(test_helpers.AccountBalance.ToBig())))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddress, rpc.BlockNumberOrHashWithNumber(number))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
Expect(bal.ToInt().Cmp(common.Big0)).To(Equal(0))
})
It("Retrieves the eth balance for the provided account address at the block with the provided hash", func() {
bal, err := api.GetBalance(ctx, test_helpers.AccountAddresss, rpc.BlockNumberOrHashWithHash(blockHash, true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal((*hexutil.Big)(test_helpers.AccountBalance)))
Expect(bal).To(Equal((*hexutil.Big)(test_helpers.AccountBalance.ToBig())))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddress, rpc.BlockNumberOrHashWithHash(blockHash, true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
Expect(bal.ToInt().Cmp(common.Big0)).To(Equal(0))
})
It("Retrieves the eth balance for the non-existing account address at the block with the provided hash", func() {
bal, err := api.GetBalance(ctx, randomAddr, rpc.BlockNumberOrHashWithHash(blockHash, true))

View File

@ -25,6 +25,12 @@ import (
"math/big"
"time"
validator "github.com/cerc-io/eth-ipfs-state-validator/v5/pkg"
ipfsethdb "github.com/cerc-io/ipfs-ethdb/v5/postgres/v0"
ipld_direct_state "github.com/cerc-io/ipld-eth-statedb/direct_by_leaf"
ipld_sql "github.com/cerc-io/ipld-eth-statedb/sql"
ipld_trie_state "github.com/cerc-io/ipld-eth-statedb/trie_by_cid/state"
ipld_trie "github.com/cerc-io/ipld-eth-statedb/trie_by_cid/trie"
"github.com/cerc-io/plugeth-statediff/indexer/ipld"
"github.com/cerc-io/plugeth-statediff/utils"
"github.com/ethereum/go-ethereum/common"
@ -42,15 +48,11 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/trie"
"github.com/holiman/uint256"
"github.com/jmoiron/sqlx"
validator "github.com/cerc-io/eth-ipfs-state-validator/v5/pkg"
ipfsethdb "github.com/cerc-io/ipfs-ethdb/v5/postgres/v0"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
"github.com/cerc-io/ipld-eth-server/v5/pkg/shared"
ipld_direct_state "github.com/cerc-io/ipld-eth-statedb/direct_by_leaf"
ipld_sql "github.com/cerc-io/ipld-eth-statedb/sql"
ipld_trie_state "github.com/cerc-io/ipld-eth-statedb/trie_by_cid/state"
)
var (
@ -80,7 +82,7 @@ type Backend struct {
// ethereum interfaces
EthDB ethdb.Database
// We use this state.Database for eth_call and any place we don't need trie access
IpldDirectStateDatabase ipld_direct_state.StateDatabase
IpldDirectStateDatabase ipld_direct_state.Database
// We use this where state must be accessed by trie
IpldTrieStateDatabase ipld_trie_state.Database
@ -115,7 +117,7 @@ func NewEthBackend(db *sqlx.DB, c *Config) (*Backend, error) {
DB: db,
Retriever: r,
EthDB: ethDB,
IpldDirectStateDatabase: ipld_direct_state.NewStateDatabase(driver),
IpldDirectStateDatabase: ipld_direct_state.NewDatabase(driver),
IpldTrieStateDatabase: ipld_trie_state.NewDatabase(ethDB),
Config: c,
}, nil
@ -269,7 +271,7 @@ func (b *Backend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.Blo
func (b *Backend) BlockByNumber(ctx context.Context, blockNumber rpc.BlockNumber) (*types.Block, error) {
number, err := b.NormalizeBlockNumber(blockNumber)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to normalize block number: %w", err)
}
canonicalHash, err := b.GetCanonicalHash(uint64(number))
if err != nil {
@ -347,8 +349,20 @@ func (b *Backend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Blo
return nil, err
}
// Fetch withdrawals
var withdrawals types.Withdrawals
if b.Config.ChainConfig.IsShanghai(header.Number, header.Time) {
withdrawals, err = b.GetWithdrawals(tx, hash, blockNumber)
if err != nil && err != sql.ErrNoRows {
log.Error("error fetching withdrawals: ", err)
return nil, err
}
} else if len(withdrawals) > 0 {
return nil, errors.New("withdrawals set before Shanghai activation")
}
// Compose everything together into a complete block
return types.NewBlock(header, transactions, uncles, receipts, trie.NewEmpty(nil)), err
return types.NewBlockWithWithdrawals(header, transactions, uncles, receipts, withdrawals, trie.NewEmpty(nil)), err
}
// GetHeaderByBlockHash retrieves header for a provided block hash
@ -492,9 +506,26 @@ func (b *Backend) GetReceiptsByBlockHashAndNumber(tx *sqlx.Tx, hash common.Hash,
return rcts, nil
}
// GetWithdrawals retrieves transactions for a provided block hash and number
func (b *Backend) GetWithdrawals(tx *sqlx.Tx, hash common.Hash, number uint64) (types.Withdrawals, error) {
_, rlpBytes, err := b.Retriever.RetrieveWithdrawals(tx, hash, number)
if err != nil {
return nil, err
}
withdrawals := make(types.Withdrawals, len(rlpBytes))
for i, bytes := range rlpBytes {
withdrawals[i] = new(types.Withdrawal)
if err := rlp.DecodeBytes(bytes, withdrawals[i]); err != nil {
return nil, err
}
}
return withdrawals, nil
}
// GetTransaction retrieves a tx by hash
// 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) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
type txRes struct {
Data []byte `db:"data"`
HeaderID string `db:"header_id"`
@ -503,22 +534,22 @@ func (b *Backend) GetTransaction(ctx context.Context, txHash common.Hash) (*type
}
var res = make([]txRes, 0)
if err := b.DB.Select(&res, RetrieveRPCTransaction, txHash.String()); err != nil {
return nil, common.Hash{}, 0, 0, err
return false, nil, common.Hash{}, 0, 0, err
}
if len(res) == 0 {
return nil, common.Hash{}, 0, 0, errTxHashNotFound
return false, 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
return false, nil, common.Hash{}, 0, 0, errTxHashInMultipleBlocks
}
var transaction types.Transaction
if err := transaction.UnmarshalBinary(res[0].Data); err != nil {
return nil, common.Hash{}, 0, 0, err
return false, nil, common.Hash{}, 0, 0, err
}
return &transaction, common.HexToHash(res[0].HeaderID), res[0].BlockNumber, res[0].Index, nil
return true, &transaction, common.HexToHash(res[0].HeaderID), res[0].BlockNumber, res[0].Index, nil
}
// GetReceipts retrieves receipts for provided block hash
@ -778,7 +809,7 @@ func (b *Backend) GetAccountByHash(ctx context.Context, address common.Address,
}
return &types.StateAccount{
Nonce: acctRecord.Nonce,
Balance: balance,
Balance: uint256.MustFromBig(balance),
Root: common.HexToHash(acctRecord.Root),
CodeHash: acctRecord.CodeHash,
}, nil
@ -917,7 +948,10 @@ func (b *Backend) GetSlice(path string, depth int, root common.Hash, storage boo
var t ipld_trie_state.Trie
var err error
if storage {
t, err = b.IpldTrieStateDatabase.OpenStorageTrie(common.Hash{}, common.Hash{}, root)
// Note 1: once Verkle tries are used, this will be the same as state trie
// Note 2: a dummy hash is passed as owner here, and is only used to signal to ipld-eth-statedb
// that a storage, not state trie is being accessed
t, err = b.IpldTrieStateDatabase.OpenStorageTrie(common.Hash{}, common.Hash{1}, root, nil)
} else {
t, err = b.IpldTrieStateDatabase.OpenTrie(root)
}
@ -929,21 +963,24 @@ func (b *Backend) GetSlice(path string, depth int, root common.Hash, storage boo
// Convert the head hex path to a decoded byte path
headPath := common.FromHex(path)
// Convert the Trie object to its concrete type for raw node access
stateTrie := t.(*ipld_trie.StateTrie)
// Get Stem nodes
err = b.getSliceStem(headPath, t, response, &metaData, storage)
err = b.getSliceStem(headPath, stateTrie, response, &metaData, storage)
if err != nil {
return nil, err
}
// Get Head node
err = b.getSliceHead(headPath, t, response, &metaData, storage)
err = b.getSliceHead(headPath, stateTrie, response, &metaData, storage)
if err != nil {
return nil, err
}
if depth > 0 {
// Get Slice nodes
err = b.getSliceTrie(headPath, t, response, &metaData, depth, storage)
err = b.getSliceTrie(headPath, stateTrie, response, &metaData, depth, storage)
if err != nil {
return nil, err
}
@ -954,7 +991,7 @@ func (b *Backend) GetSlice(path string, depth int, root common.Hash, storage boo
return response, nil
}
func (b *Backend) getSliceStem(headPath []byte, t ipld_trie_state.Trie, response *GetSliceResponse, metaData *metaDataFields, storage bool) error {
func (b *Backend) getSliceStem(headPath []byte, t *ipld_trie.StateTrie, response *GetSliceResponse, metaData *metaDataFields, storage bool) error {
leavesFetchTime := int64(0)
totalStemStartTime := makeTimestamp()
@ -963,7 +1000,7 @@ func (b *Backend) getSliceStem(headPath []byte, t ipld_trie_state.Trie, response
// nodePath := make([]byte, len(headPath[:i]))
nodePath := headPath[:i]
rawNode, _, err := t.TryGetNode(utils.HexToCompact(nodePath))
rawNode, _, err := t.GetNode(utils.HexToCompact(nodePath))
if err != nil {
return err
}
@ -1002,10 +1039,10 @@ func (b *Backend) getSliceStem(headPath []byte, t ipld_trie_state.Trie, response
return nil
}
func (b *Backend) getSliceHead(headPath []byte, t ipld_trie_state.Trie, response *GetSliceResponse, metaData *metaDataFields, storage bool) error {
func (b *Backend) getSliceHead(headPath []byte, t *ipld_trie.StateTrie, response *GetSliceResponse, metaData *metaDataFields, storage bool) error {
totalHeadStartTime := makeTimestamp()
rawNode, _, err := t.TryGetNode(utils.HexToCompact(headPath))
rawNode, _, err := t.GetNode(utils.HexToCompact(headPath))
if err != nil {
return err
}
@ -1043,7 +1080,10 @@ func (b *Backend) getSliceHead(headPath []byte, t ipld_trie_state.Trie, response
}
func (b *Backend) getSliceTrie(headPath []byte, t ipld_trie_state.Trie, response *GetSliceResponse, metaData *metaDataFields, depth int, storage bool) error {
it, timeTaken := getIteratorAtPath(t, headPath)
it, timeTaken, err := getIteratorAtPath(t, headPath)
if err != nil {
return nil
}
metaData.trieLoadingTime += timeTaken
leavesFetchTime := int64(0)

View File

@ -28,9 +28,9 @@ import (
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/trie"
@ -41,10 +41,11 @@ import (
var nullHashBytes = common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000")
var emptyCodeHash = crypto.Keccak256([]byte{})
// These marshalling functions are from internal/ethapi so we have to make our own versions here:
// RPCMarshalHeader converts the given header to the RPC output.
// This function is eth/internal so we have to make our own version here...
func RPCMarshalHeader(head *types.Header) map[string]interface{} {
headerMap := map[string]interface{}{
result := map[string]interface{}{
"number": (*hexutil.Big)(head.Number),
"hash": head.Hash(),
"parentHash": head.ParentHash,
@ -56,43 +57,50 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} {
"miner": head.Coinbase,
"difficulty": (*hexutil.Big)(head.Difficulty),
"extraData": hexutil.Bytes(head.Extra),
"size": hexutil.Uint64(head.Size()),
"gasLimit": hexutil.Uint64(head.GasLimit),
"gasUsed": hexutil.Uint64(head.GasUsed),
"timestamp": hexutil.Uint64(head.Time),
"transactionsRoot": head.TxHash,
"receiptsRoot": head.ReceiptHash,
}
if head.BaseFee != nil {
headerMap["baseFeePerGas"] = (*hexutil.Big)(head.BaseFee)
result["baseFeePerGas"] = (*hexutil.Big)(head.BaseFee)
}
return headerMap
if head.WithdrawalsHash != nil {
result["withdrawalsRoot"] = head.WithdrawalsHash
}
if head.BlobGasUsed != nil {
result["blobGasUsed"] = hexutil.Uint64(*head.BlobGasUsed)
}
if head.ExcessBlobGas != nil {
result["excessBlobGas"] = hexutil.Uint64(*head.ExcessBlobGas)
}
if head.ParentBeaconRoot != nil {
result["parentBeaconBlockRoot"] = head.ParentBeaconRoot
}
return result
}
// RPCMarshalBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are
// returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain
// transaction hashes.
func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool, config *params.ChainConfig) map[string]interface{} {
fields := RPCMarshalHeader(block.Header())
fields["size"] = hexutil.Uint64(block.Size())
if inclTx {
formatTx := func(tx *types.Transaction) (interface{}, error) {
return tx.Hash(), nil
formatTx := func(idx int, tx *types.Transaction) interface{} {
return tx.Hash()
}
if fullTx {
formatTx = func(tx *types.Transaction) (interface{}, error) {
return NewRPCTransactionFromBlockHash(block, tx.Hash()), nil
formatTx = func(idx int, tx *types.Transaction) interface{} {
return newRPCTransactionFromBlockIndex(block, uint64(idx), config)
}
}
txs := block.Transactions()
transactions := make([]interface{}, len(txs))
var err error
for i, tx := range txs {
if transactions[i], err = formatTx(tx); err != nil {
return nil, err
}
transactions[i] = formatTx(i, tx)
}
fields["transactions"] = transactions
}
@ -102,12 +110,14 @@ func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool) (map[string]i
uncleHashes[i] = uncle.Hash()
}
fields["uncles"] = uncleHashes
return fields, nil
if block.Header().WithdrawalsHash != nil {
fields["withdrawals"] = block.Withdrawals()
}
return fields
}
// RPCMarshalBlockWithUncleHashes marshals the block with the provided uncle hashes
func RPCMarshalBlockWithUncleHashes(block *types.Block, uncleHashes []common.Hash, inclTx bool, fullTx bool) (map[string]interface{}, error) {
func RPCMarshalBlockWithUncleHashes(block *types.Block, uncleHashes []common.Hash, inclTx bool, fullTx bool, config *params.ChainConfig) (map[string]interface{}, error) {
fields := RPCMarshalHeader(block.Header())
fields["size"] = hexutil.Uint64(block.Size())
@ -117,7 +127,7 @@ func RPCMarshalBlockWithUncleHashes(block *types.Block, uncleHashes []common.Has
}
if fullTx {
formatTx = func(tx *types.Transaction) (interface{}, error) {
return NewRPCTransactionFromBlockHash(block, tx.Hash()), nil
return NewRPCTransactionFromBlockHash(block, tx.Hash(), config), nil
}
}
txs := block.Transactions()
@ -135,11 +145,11 @@ func RPCMarshalBlockWithUncleHashes(block *types.Block, uncleHashes []common.Has
return fields, nil
}
// NewRPCTransactionFromBlockHash returns a transaction that will serialize to the RPC representation.
func NewRPCTransactionFromBlockHash(b *types.Block, hash common.Hash) *RPCTransaction {
// newRPCTransactionFromBlockHash returns a transaction that will serialize to the RPC representation.
func NewRPCTransactionFromBlockHash(b *types.Block, hash common.Hash, config *params.ChainConfig) *RPCTransaction {
for idx, tx := range b.Transactions() {
if tx.Hash() == hash {
return newRPCTransactionFromBlockIndex(b, uint64(idx))
return newRPCTransactionFromBlockIndex(b, uint64(idx), config)
}
}
return nil
@ -158,11 +168,12 @@ func SignerForTx(tx *types.Transaction) types.Signer {
// NewRPCTransaction returns a transaction that will serialize to the RPC
// representation, with the given location metadata set (if available).
func NewRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber uint64, index uint64, baseFee *big.Int) *RPCTransaction {
signer := SignerForTx(tx)
func NewRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber uint64, blockTime uint64, index uint64, baseFee *big.Int, config *params.ChainConfig) *RPCTransaction {
signer := types.MakeSigner(config, new(big.Int).SetUint64(blockNumber), blockTime)
from, _ := types.Sender(signer, tx)
v, r, s := tx.RawSignatureValues()
result := &RPCTransaction{
Type: hexutil.Uint64(tx.Type()),
From: from,
Gas: hexutil.Uint64(tx.Gas()),
GasPrice: (*hexutil.Big)(tx.GasPrice()),
@ -171,7 +182,6 @@ func NewRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
Nonce: hexutil.Uint64(tx.Nonce()),
To: tx.To(),
Value: (*hexutil.Big)(tx.Value()),
Type: hexutil.Uint64(tx.Type()),
V: (*hexutil.Big)(v),
R: (*hexutil.Big)(r),
S: (*hexutil.Big)(s),
@ -181,34 +191,69 @@ func NewRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber))
result.TransactionIndex = (*hexutil.Uint64)(&index)
}
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:
al := tx.AccessList()
yparity := hexutil.Uint64(v.Sign())
result.Accesses = &al
result.ChainID = (*hexutil.Big)(tx.ChainId())
result.YParity = &yparity
case types.DynamicFeeTxType:
al := tx.AccessList()
yparity := hexutil.Uint64(v.Sign())
result.Accesses = &al
result.ChainID = (*hexutil.Big)(tx.ChainId())
result.YParity = &yparity
result.GasFeeCap = (*hexutil.Big)(tx.GasFeeCap())
result.GasTipCap = (*hexutil.Big)(tx.GasTipCap())
// if the transaction has been mined, compute the effective gas price
if baseFee != nil && blockHash != (common.Hash{}) {
// price = min(tip, gasFeeCap - baseFee) + baseFee
price := math.BigMin(new(big.Int).Add(tx.GasTipCap(), baseFee), tx.GasFeeCap())
result.GasPrice = (*hexutil.Big)(price)
// price = min(gasTipCap + baseFee, gasFeeCap)
result.GasPrice = (*hexutil.Big)(effectiveGasPrice(tx, baseFee))
} else {
result.GasPrice = (*hexutil.Big)(tx.GasFeeCap())
}
case types.BlobTxType:
al := tx.AccessList()
yparity := hexutil.Uint64(v.Sign())
result.Accesses = &al
result.ChainID = (*hexutil.Big)(tx.ChainId())
result.YParity = &yparity
result.GasFeeCap = (*hexutil.Big)(tx.GasFeeCap())
result.GasTipCap = (*hexutil.Big)(tx.GasTipCap())
// if the transaction has been mined, compute the effective gas price
if baseFee != nil && blockHash != (common.Hash{}) {
result.GasPrice = (*hexutil.Big)(effectiveGasPrice(tx, baseFee))
} else {
result.GasPrice = (*hexutil.Big)(tx.GasFeeCap())
}
result.MaxFeePerBlobGas = (*hexutil.Big)(tx.BlobGasFeeCap())
result.BlobVersionedHashes = tx.BlobHashes()
}
return result
}
// effectiveGasPrice computes the transaction gas fee, based on the given basefee value.
//
// price = min(gasTipCap + baseFee, gasFeeCap)
func effectiveGasPrice(tx *types.Transaction, baseFee *big.Int) *big.Int {
fee := tx.GasTipCap()
fee = fee.Add(fee, baseFee)
if tx.GasFeeCapIntCmp(fee) < 0 {
return tx.GasFeeCap()
}
return fee
}
type rpcBlock struct {
Hash common.Hash `json:"hash"`
Transactions []rpcTransaction `json:"transactions"`
@ -270,6 +315,15 @@ func getBlockAndUncleHashes(cli *rpc.Client, ctx context.Context, method string,
return types.NewBlockWithHeader(head).WithBody(txs, nil), body.UncleHashes, nil
}
// newRPCTransactionFromBlockIndex returns a transaction that will serialize to the RPC representation.
func newRPCTransactionFromBlockIndex(b *types.Block, index uint64, config *params.ChainConfig) *RPCTransaction {
txs := b.Transactions()
if index >= uint64(len(txs)) {
return nil
}
return NewRPCTransaction(txs[index], b.Hash(), b.NumberU64(), b.Time(), index, b.BaseFee(), config)
}
// newRPCRawTransactionFromBlockIndex returns the bytes of a transaction given a block and a transaction index.
func newRPCRawTransactionFromBlockIndex(b *types.Block, index uint64) hexutil.Bytes {
txs := b.Transactions()
@ -280,15 +334,6 @@ func newRPCRawTransactionFromBlockIndex(b *types.Block, index uint64) hexutil.By
return blob
}
// newRPCTransactionFromBlockIndex returns a transaction that will serialize to the RPC representation.
func newRPCTransactionFromBlockIndex(b *types.Block, index uint64) *RPCTransaction {
txs := b.Transactions()
if index >= uint64(len(txs)) {
return nil
}
return NewRPCTransaction(txs[index], b.Hash(), b.NumberU64(), index, b.BaseFee())
}
func toFilterArg(q ethereum.FilterQuery) (interface{}, error) {
arg := map[string]interface{}{
"address": q.Addresses,
@ -317,21 +362,28 @@ func toBlockNumArg(number *big.Int) string {
return hexutil.EncodeBig(number)
}
func getIteratorAtPath(t state.Trie, startKey []byte) (trie.NodeIterator, int64) {
func getIteratorAtPath(t state.Trie, startKey []byte) (trie.NodeIterator, int64, error) {
startTime := makeTimestamp()
var it trie.NodeIterator
var err error
if len(startKey)%2 != 0 {
// Zero-pad for odd-length keys, required by HexToKeyBytes()
startKey = append(startKey, 0)
it = t.NodeIterator(nodeiter.HexToKeyBytes(startKey))
it, err = t.NodeIterator(nodeiter.HexToKeyBytes(startKey))
if err != nil {
return nil, 0, err
}
} else {
it = t.NodeIterator(nodeiter.HexToKeyBytes(startKey))
it, err = t.NodeIterator(nodeiter.HexToKeyBytes(startKey))
if err != nil {
return nil, 0, err
}
// Step to the required node (not required if original startKey was odd-length)
it.Next(true)
}
return it, makeTimestamp() - startTime
return it, makeTimestamp() - startTime, nil
}
func fillSliceNodeData(
@ -351,7 +403,7 @@ func fillSliceNodeData(
if node.NodeType == Leaf && !storage {
stateLeafKey, storageRoot, code, err := extractContractAccountInfo(sdb, node, nodeElements)
if err != nil {
return 0, fmt.Errorf("GetSlice account lookup error: %s", err.Error())
return 0, fmt.Errorf("GetSlice account lookup error: %w", err)
}
if len(code) > 0 {
@ -387,7 +439,7 @@ func extractContractAccountInfo(sdb state.Database, node StateNode, nodeElements
// Extract codeHash and get code
codeHash := common.BytesToHash(account.CodeHash)
codeBytes, err := sdb.ContractCode(codeHash)
codeBytes, err := sdb.ContractCode(common.Address{}, codeHash)
if err != nil {
return "", "", nil, err
}

View File

@ -6,6 +6,7 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/cerc-io/ipld-eth-statedb/trie_by_cid/trie"
"github.com/cerc-io/ipld-eth-statedb/trie_by_cid/triedb"
)
// NodeType for explicitly setting type of node
@ -73,7 +74,7 @@ type StorageNode struct {
LeafKey []byte `json:"leafKey"`
}
func ResolveNode(path []byte, node []byte, trieDB *trie.Database) (StateNode, []interface{}, error) {
func ResolveNode(path []byte, node []byte, trieDB *triedb.Database) (StateNode, []interface{}, error) {
var nodeElements []interface{}
if err := rlp.DecodeBytes(node, &nodeElements); err != nil {
return StateNode{}, nil, err
@ -93,7 +94,7 @@ func ResolveNode(path []byte, node []byte, trieDB *trie.Database) (StateNode, []
}
// ResolveNodeIt return the state diff node pointed by the iterator.
func ResolveNodeIt(it trie.NodeIterator, trieDB *trie.Database) (StateNode, []interface{}, error) {
func ResolveNodeIt(it trie.NodeIterator, trieDB *triedb.Database) (StateNode, []interface{}, error) {
node, err := it.NodeBlob(), it.Error()
if err != nil {
return StateNode{}, nil, err

View File

@ -506,6 +506,24 @@ func (r *Retriever) RetrieveReceiptsByBlockHash(tx *sqlx.Tx, hash common.Hash) (
return cids, rcts, txs, nil
}
// RetrieveWithdrawals returns the CIDs and RLP bytes for the withdrawals corresponding to the
// provided block hash, number. Returned CIDs correspond to the leaf node data which contains the
// withdrawal object.
func (r *Retriever) RetrieveWithdrawals(tx *sqlx.Tx, hash common.Hash, number uint64) ([]string, [][]byte, error) {
results := make([]ipldResult, 0)
if err := tx.Select(&results, RetrieveWithdrawalsPgStr, hash.Hex(), number); err != nil {
return nil, nil, err
}
cids := make([]string, len(results))
withdrawals := make([][]byte, len(results))
for i, res := range results {
cids[i] = res.CID
withdrawals[i] = res.Data
}
return cids, withdrawals, nil
}
// RetrieveAccountByAddressAndBlockHash returns the cid and rlp bytes for the account corresponding to the provided address and block hash
// TODO: ensure this handles deleted accounts appropriately
func (r *Retriever) RetrieveAccountByAddressAndBlockHash(address common.Address, hash common.Hash) (StateAccountRecord, error) {

View File

@ -107,6 +107,21 @@ WHERE header_cids.block_hash = $1
AND blocks.key = receipt_cids.cid
ORDER BY eth.transaction_cids.index ASC
`
RetrieveWithdrawalsPgStr = `
SELECT withdrawal_cids.cid,
blocks.data
FROM eth.withdrawal_cids
JOIN eth.header_cids
ON header_cids.block_hash = $1
AND header_cids.block_number = $2
AND header_cids.canonical
AND withdrawal_cids.block_number = header_cids.block_number
AND withdrawal_cids.header_id = header_cids.block_hash
JOIN ipld.blocks
ON blocks.block_number = header_cids.block_number
AND blocks.key = withdrawal_cids.cid
ORDER BY eth.withdrawal_cids.index ASC`
RetrieveAccountByLeafKeyAndBlockHashPgStr = `
SELECT state_cids.nonce,
state_cids.balance,

View File

@ -1,8 +1,15 @@
package eth_state_test
import (
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common/hexutil"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/format"
"github.com/onsi/gomega/types"
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth"
)
func CheckGetSliceResponse(sliceResponse eth.GetSliceResponse, expectedResponse eth.GetSliceResponse) {
@ -11,3 +18,54 @@ func CheckGetSliceResponse(sliceResponse eth.GetSliceResponse, expectedResponse
Expect(sliceResponse.Leaves).To(Equal(expectedResponse.Leaves))
Expect(sliceResponse.MetaData.NodeStats).To(Equal(expectedResponse.MetaData.NodeStats))
}
// EqualBigInt compares a hexutil.Big for equality with a big.Int or hexutil.Big value.
// It is an error for both actual and expected to be nil. Use BeNil() instead.
func EqualBigInt(expected *big.Int) types.GomegaMatcher {
return &BigIntEqualMatcher{
Expected: expected,
}
}
// EqualBigHex compares a hexutil.Big for equality with a big.Int or hexutil.Big value.
// It is an error for both actual and expected to be nil. Use BeNil() instead.
func EqualBigHex(expected *hexutil.Big) types.GomegaMatcher {
return &BigIntEqualMatcher{
Expected: expected.ToInt(),
}
}
type BigIntEqualMatcher struct {
Expected *big.Int
}
func (matcher *BigIntEqualMatcher) Match(actual interface{}) (success bool, err error) {
if actual == nil && matcher.Expected == nil {
return false, fmt.Errorf("Refusing to compare <nil> to <nil>.\nBe explicit and use BeNil() instead. This is to avoid mistakes where both sides of an assertion are erroneously uninitialized.")
}
var asInt *big.Int
switch casted := actual.(type) {
case *big.Int:
asInt = casted
case *hexutil.Big:
asInt = (*big.Int)(casted)
default:
return false, fmt.Errorf("BigIntEqualMatcher expects a hexutil.Big or big.Int. Got:\n%s", format.Object(actual, 1))
}
return matcher.Expected.Cmp(asInt) == 0, nil
}
func (matcher *BigIntEqualMatcher) FailureMessage(actual interface{}) (message string) {
actualString, actualOK := actual.(string)
expectedString := matcher.Expected.String()
if actualOK {
return format.MessageWithDiff(actualString, "to equal", expectedString)
}
return format.Message(actual, "to equal", matcher.Expected)
}
func (matcher *BigIntEqualMatcher) NegatedFailureMessage(actual interface{}) (message string) {
return format.Message(actual, "not to equal", matcher.Expected)
}

View File

@ -47,7 +47,7 @@ var (
parsedABI abi.ABI
randomAddress = common.HexToAddress("0x9F4203bd7a11aCB94882050E6f1C3ab14BBaD3D9")
randomHash = crypto.Keccak256Hash(randomAddress.Bytes())
number = rpc.BlockNumber(test_helpers.BlockNumber.Int64())
number = rpc.BlockNumber(test_helpers.BlockNumber1)
block1StateRoot = common.HexToHash("0xa1f614839ebdd58677df2c9d66a3e0acc9462acc49fad6006d0b6e5d2b98ed21")
rootDataHashBlock1 = "a1f614839ebdd58677df2c9d66a3e0acc9462acc49fad6006d0b6e5d2b98ed21"
@ -152,7 +152,6 @@ var _ = BeforeSuite(func() {
"miner": canonicalHeader.Coinbase,
"difficulty": (*hexutil.Big)(canonicalHeader.Difficulty),
"extraData": hexutil.Bytes([]byte{}),
"size": hexutil.Uint64(canonicalHeader.Size()),
"gasLimit": hexutil.Uint64(canonicalHeader.GasLimit),
"gasUsed": hexutil.Uint64(canonicalHeader.GasUsed),
"timestamp": hexutil.Uint64(canonicalHeader.Time),
@ -294,198 +293,198 @@ var _ = Describe("eth state reading tests", func() {
It("Retrieves account balance by block number", func() {
bal, err := api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(0))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedBankBalanceBlock0))
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock0))
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(1))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(1))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
Expect(bal).To(EqualBigInt((common.Big0)))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(1))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
Expect(bal).To(EqualBigInt((common.Big0)))
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(1))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedBankBalanceBlock1))
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock1))
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(2))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(2))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedAcct2BalanceBlock2))
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock2))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(2))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedContractBalance))
Expect(bal).To(EqualBigHex(expectedContractBalance))
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(2))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedBankBalanceBlock2))
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(3))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(3))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedAcct2BalanceBlock3))
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock3))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(3))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedContractBalance))
Expect(bal).To(EqualBigHex(expectedContractBalance))
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(3))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedBankBalanceBlock2))
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(4))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(4))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedAcct2BalanceBlock4))
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock4))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(4))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedContractBalance))
Expect(bal).To(EqualBigHex(expectedContractBalance))
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(4))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedBankBalanceBlock2))
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(5))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedAcct1BalanceBlock5))
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock5))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(5))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedAcct2BalanceBlock4))
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock4))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(5))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedContractBalance))
Expect(bal).To(EqualBigHex(expectedContractBalance))
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(5))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedBankBalanceBlock2))
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
})
It("Retrieves account balance by block hash", func() {
bal, err := api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedBankBalanceBlock0))
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock0))
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
Expect(bal).To(EqualBigInt((common.Big0)))
_, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
Expect(bal).To(EqualBigInt((common.Big0)))
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedBankBalanceBlock1))
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock1))
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedAcct2BalanceBlock2))
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock2))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedContractBalance))
Expect(bal).To(EqualBigHex(expectedContractBalance))
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedBankBalanceBlock2))
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedAcct2BalanceBlock3))
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock3))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedContractBalance))
Expect(bal).To(EqualBigHex(expectedContractBalance))
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedBankBalanceBlock2))
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedAcct2BalanceBlock4))
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock4))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedContractBalance))
Expect(bal).To(EqualBigHex(expectedContractBalance))
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedBankBalanceBlock2))
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedAcct1BalanceBlock5))
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock5))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedAcct2BalanceBlock4))
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock4))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedContractBalance))
Expect(bal).To(EqualBigHex(expectedContractBalance))
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal(expectedBankBalanceBlock2))
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
})
It("Returns 0 if account balance not found by block number", func() {
bal, err := api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(0))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
Expect(bal).To(EqualBigInt(common.Big0))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(0))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
Expect(bal).To(EqualBigInt(common.Big0))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(0))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
Expect(bal).To(EqualBigInt(common.Big0))
})
It("Returns 0 if account balance not found by block hash", func() {
bal, err := api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
Expect(bal).To(EqualBigInt(common.Big0))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
Expect(bal).To(EqualBigInt(common.Big0))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
Expect(bal).To(EqualBigInt(common.Big0))
})
})

View File

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

View File

@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/holiman/uint256"
"github.com/ipfs/go-cid"
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth"
@ -40,10 +41,11 @@ import (
// Test variables
var (
// block data
BlockNumber = big.NewInt(1)
MockHeader = types.Header{
BlockNumber1 = int64(1)
BlockTime1 = uint64(0)
MockHeader = types.Header{
Time: 0,
Number: new(big.Int).Set(BlockNumber),
Number: big.NewInt(BlockNumber1),
Root: common.HexToHash("0x0"),
TxHash: common.HexToHash("0x0"),
ReceiptHash: common.HexToHash("0x0"),
@ -51,10 +53,14 @@ var (
Extra: []byte{},
}
MockTransactions, MockReceipts, SenderAddr = createLegacyTransactionsAndReceipts()
MockUncles = []*types.Header{
MockWithdrawals = types.Withdrawals{
{Index: 0, Validator: 1, Address: Address, Amount: 1000000000},
{Index: 1, Validator: 5, Address: AnotherAddress, Amount: 2000000000},
}
MockUncles = []*types.Header{
{
Time: 1,
Number: new(big.Int).Add(BlockNumber, big.NewInt(1)),
Number: big.NewInt(BlockNumber1 + 1),
Root: common.HexToHash("0x1"),
TxHash: common.HexToHash("0x1"),
ReceiptHash: common.HexToHash("0x1"),
@ -64,7 +70,7 @@ var (
},
{
Time: 2,
Number: new(big.Int).Add(BlockNumber, big.NewInt(2)),
Number: big.NewInt(BlockNumber1 + 2),
Root: common.HexToHash("0x2"),
TxHash: common.HexToHash("0x2"),
ReceiptHash: common.HexToHash("0x2"),
@ -73,10 +79,10 @@ var (
ParentHash: Genesis.Hash(),
},
}
MockBlock = createNewBlock(&MockHeader, MockTransactions, MockUncles, MockReceipts, trie.NewEmpty(nil))
MockBlock = createNewBlock(&MockHeader, MockTransactions, MockUncles, MockReceipts, nil, trie.NewEmpty(nil))
MockChildHeader = types.Header{
Time: 0,
Number: new(big.Int).Add(BlockNumber, common.Big1),
Number: big.NewInt(BlockNumber1 + 1),
Root: common.HexToHash("0x0"),
TxHash: common.HexToHash("0x0"),
ReceiptHash: common.HexToHash("0x0"),
@ -104,7 +110,7 @@ var (
Address: Address,
Topics: []common.Hash{mockTopic11, mockTopic12},
Data: []byte{},
BlockNumber: BlockNumber.Uint64(),
BlockNumber: uint64(BlockNumber1),
TxIndex: 0,
Index: 0,
}
@ -112,7 +118,7 @@ var (
Address: AnotherAddress,
Topics: []common.Hash{mockTopic21, mockTopic22},
Data: []byte{},
BlockNumber: BlockNumber.Uint64(),
BlockNumber: uint64(BlockNumber1),
TxIndex: 1,
Index: 1,
}
@ -120,7 +126,7 @@ var (
Address: AnotherAddress1,
Topics: []common.Hash{mockTopic31},
Data: []byte{},
BlockNumber: BlockNumber.Uint64(),
BlockNumber: uint64(BlockNumber1),
TxIndex: 2,
Index: 2,
}
@ -129,7 +135,7 @@ var (
Address: AnotherAddress1,
Topics: []common.Hash{mockTopic41, mockTopic42, mockTopic43},
Data: []byte{},
BlockNumber: BlockNumber.Uint64(),
BlockNumber: uint64(BlockNumber1),
TxIndex: 2,
Index: 3,
}
@ -137,7 +143,7 @@ var (
Address: AnotherAddress1,
Topics: []common.Hash{mockTopic51},
Data: []byte{},
BlockNumber: BlockNumber.Uint64(),
BlockNumber: uint64(BlockNumber1),
TxIndex: 2,
Index: 4,
}
@ -145,7 +151,7 @@ var (
Address: AnotherAddress2,
Topics: []common.Hash{mockTopic61},
Data: []byte{},
BlockNumber: BlockNumber.Uint64(),
BlockNumber: uint64(BlockNumber1),
TxIndex: 3,
Index: 5,
}
@ -217,7 +223,7 @@ var (
ContractLeafKey = crypto.Keccak256(ContractAddress[:])
ContractAccount = types.StateAccount{
Nonce: uint64(1),
Balance: big.NewInt(0),
Balance: uint256.NewInt(0),
CodeHash: CodeHash.Bytes(),
Root: common.HexToHash(ContractRoot),
}
@ -229,7 +235,7 @@ var (
})
nonce0 = uint64(0)
AccountBalance = big.NewInt(1000)
AccountBalance = uint256.NewInt(1000)
AccountRoot = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
AccountCodeHash = common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
AccountAddresss = common.HexToAddress("0x0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e")
@ -290,21 +296,22 @@ var (
StateNodes: MockStateNodes,
}
LondonBlockNum = new(big.Int).Add(BlockNumber, big.NewInt(2))
LondonBlockNum = (BlockNumber1 + 2)
LondonBlockTime = BlockTime1 + 1
MockLondonHeader = types.Header{
Time: 0,
Number: LondonBlockNum,
Time: LondonBlockTime,
Number: big.NewInt(LondonBlockNum),
Root: common.HexToHash("0x00"),
Difficulty: big.NewInt(5000000),
Extra: []byte{},
BaseFee: big.NewInt(params.InitialBaseFee),
}
MockLondonTransactions, MockLondonReceipts, _ = createDynamicTransactionsAndReceipts(LondonBlockNum)
MockLondonTransactions, MockLondonReceipts, _ = createDynamicTransactionsAndReceipts(big.NewInt(LondonBlockNum), LondonBlockTime)
MockLondonUncles = []*types.Header{
{
Time: 1,
Number: new(big.Int).Add(BlockNumber, big.NewInt(1)),
Number: big.NewInt(BlockNumber1 + 1),
ParentHash: common.HexToHash("0x2"),
Root: common.HexToHash("0x1"),
TxHash: common.HexToHash("0x1"),
@ -314,7 +321,7 @@ var (
},
{
Time: 2,
Number: new(big.Int).Add(BlockNumber, big.NewInt(1)),
Number: big.NewInt(BlockNumber1 + 1),
ParentHash: common.HexToHash("0x1"),
Root: common.HexToHash("0x2"),
TxHash: common.HexToHash("0x2"),
@ -323,11 +330,11 @@ var (
Extra: []byte{},
},
}
MockLondonBlock = createNewBlock(&MockLondonHeader, MockLondonTransactions, MockLondonUncles, MockLondonReceipts, trie.NewEmpty(nil))
MockLondonBlock = createNewBlock(&MockLondonHeader, MockLondonTransactions, MockLondonUncles, MockLondonReceipts, MockWithdrawals, trie.NewEmpty(nil))
)
func createNewBlock(header *types.Header, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, hasher types.TrieHasher) *types.Block {
block := types.NewBlock(header, txs, uncles, receipts, hasher)
func createNewBlock(header *types.Header, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals types.Withdrawals, hasher types.TrieHasher) *types.Block {
block := types.NewBlockWithWithdrawals(header, txs, uncles, receipts, withdrawals, hasher)
bHash := block.Hash()
for _, r := range receipts {
for _, l := range r.Logs {
@ -338,7 +345,7 @@ func createNewBlock(header *types.Header, txs []*types.Transaction, uncles []*ty
}
// createDynamicTransactionsAndReceipts is a helper function to generate signed mock transactions and mock receipts with mock logs
func createDynamicTransactionsAndReceipts(blockNumber *big.Int) (types.Transactions, types.Receipts, common.Address) {
func createDynamicTransactionsAndReceipts(blockNumber *big.Int, blockTime uint64) (types.Transactions, types.Receipts, common.Address) {
// make transactions
config := *params.TestChainConfig
config.LondonBlock = blockNumber
@ -353,7 +360,7 @@ func createDynamicTransactionsAndReceipts(blockNumber *big.Int) (types.Transacti
Data: []byte{},
})
transactionSigner := types.MakeSigner(&config, blockNumber)
transactionSigner := types.MakeSigner(&config, blockNumber, blockTime)
mockCurve := elliptic.P256()
mockPrvKey, err := ecdsa.GenerateKey(mockCurve, rand.Reader)
if err != nil {
@ -391,7 +398,7 @@ func createLegacyTransactionsAndReceipts() (types.Transactions, types.Receipts,
trx2 := types.NewTransaction(1, AnotherAddress, big.NewInt(2000), 100, big.NewInt(200), []byte{})
trx3 := types.NewContractCreation(2, big.NewInt(1500), 75, big.NewInt(150), ContractCode)
trx4 := types.NewTransaction(3, AnotherAddress1, big.NewInt(2000), 100, big.NewInt(200), []byte{})
transactionSigner := types.MakeSigner(params.MainnetChainConfig, new(big.Int).Set(BlockNumber))
transactionSigner := types.MakeSigner(params.MainnetChainConfig, big.NewInt(BlockNumber1), 0)
mockCurve := elliptic.P256()
mockPrvKey, err := ecdsa.GenerateKey(mockCurve, rand.Reader)
if err != nil {
@ -452,7 +459,7 @@ func createLegacyTransactionsAndReceipts() (types.Transactions, types.Receipts,
func getReceiptCIDs(rcts []*types.Receipt) ([]cid.Cid, error) {
cids := make([]cid.Cid, len(rcts))
for i, rct := range rcts {
ethRct, err := ipld.NewReceipt(rct)
ethRct, err := ipld.EncodeReceipt(rct)
if err != nil {
return nil, err
}

View File

@ -33,26 +33,30 @@ import (
)
// RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction
// Note: copied from go-ethereum/internal/ethapi
type RPCTransaction struct {
BlockHash *common.Hash `json:"blockHash"`
BlockNumber *hexutil.Big `json:"blockNumber"`
From common.Address `json:"from"`
Gas hexutil.Uint64 `json:"gas"`
GasPrice *hexutil.Big `json:"gasPrice"`
GasFeeCap *hexutil.Big `json:"maxFeePerGas,omitempty"`
GasTipCap *hexutil.Big `json:"maxPriorityFeePerGas,omitempty"`
Hash common.Hash `json:"hash"`
Input hexutil.Bytes `json:"input"`
Nonce hexutil.Uint64 `json:"nonce"`
To *common.Address `json:"to"`
TransactionIndex *hexutil.Uint64 `json:"transactionIndex"`
Value *hexutil.Big `json:"value"`
Type hexutil.Uint64 `json:"type"`
Accesses *types.AccessList `json:"accessList,omitempty"`
ChainID *hexutil.Big `json:"chainId,omitempty"`
V *hexutil.Big `json:"v"`
R *hexutil.Big `json:"r"`
S *hexutil.Big `json:"s"`
BlockHash *common.Hash `json:"blockHash"`
BlockNumber *hexutil.Big `json:"blockNumber"`
From common.Address `json:"from"`
Gas hexutil.Uint64 `json:"gas"`
GasPrice *hexutil.Big `json:"gasPrice"`
GasFeeCap *hexutil.Big `json:"maxFeePerGas,omitempty"`
GasTipCap *hexutil.Big `json:"maxPriorityFeePerGas,omitempty"`
MaxFeePerBlobGas *hexutil.Big `json:"maxFeePerBlobGas,omitempty"`
Hash common.Hash `json:"hash"`
Input hexutil.Bytes `json:"input"`
Nonce hexutil.Uint64 `json:"nonce"`
To *common.Address `json:"to"`
TransactionIndex *hexutil.Uint64 `json:"transactionIndex"`
Value *hexutil.Big `json:"value"`
Type hexutil.Uint64 `json:"type"`
Accesses *types.AccessList `json:"accessList,omitempty"`
ChainID *hexutil.Big `json:"chainId,omitempty"`
BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"`
V *hexutil.Big `json:"v"`
R *hexutil.Big `json:"r"`
S *hexutil.Big `json:"s"`
YParity *hexutil.Uint64 `json:"yParity,omitempty"`
}
// RPCReceipt represents a receipt that will serialize to the RPC representation of a receipt

View File

@ -64,7 +64,7 @@ func (a *Account) Balance(ctx context.Context) (hexutil.Big, error) {
if err != nil {
return hexutil.Big{}, err
}
return hexutil.Big(*state.GetBalance(a.address)), nil
return hexutil.Big(*state.GetBalance(a.address).ToBig()), nil
}
func (a *Account) TransactionCount(ctx context.Context) (hexutil.Uint64, error) {

View File

@ -128,9 +128,10 @@ func NewConfig() (*Config, error) {
viper.BindEnv("server.ipcPath", SERVER_IPC_PATH)
viper.BindEnv("server.graphqlPath", SERVER_GRAPHQL_PATH)
viper.BindEnv("ethereum.chainID", ETH_CHAIN_ID)
viper.BindEnv("ethereum.chainConfig", ETH_CHAIN_CONFIG)
viper.BindEnv("ethereum.httpPath", ETH_HTTP_PATH)
viper.BindEnv("ethereum.rpcGasCap", ETH_RPC_GAS_CAP)
viper.BindEnv("ethereum.chainConfig", ETH_CHAIN_CONFIG)
viper.BindEnv("ethereum.supportsStateDiff", ETH_SUPPORTS_STATEDIFF)
viper.BindEnv("ethereum.stateDiffTimeout", ETH_STATEDIFF_TIMEOUT)
viper.BindEnv("ethereum.forwardEthCalls", ETH_FORWARD_ETH_CALLS)
@ -143,11 +144,32 @@ func NewConfig() (*Config, error) {
c.dbInit()
ethHTTP := viper.GetString("ethereum.httpPath")
ethHTTPEndpoint := fmt.Sprintf("http://%s", ethHTTP)
nodeInfo, cli, err := getEthNodeAndClient(ethHTTPEndpoint)
c.NodeNetworkID = nodeInfo.NetworkID
// At least one of chain ID and chain config must be passed.
// If both are passed, the chain ID must match the config.
chainID := viper.GetUint64("ethereum.chainID")
chainConfigPath := viper.GetString("ethereum.chainConfig")
var err error
if chainConfigPath != "" {
if c.ChainConfig, err = utils.LoadConfig(chainConfigPath); err != nil {
return nil, err
}
// Only validate the chain ID if it was actually passed
if viper.GetString("ethereum.chainID") != "" && c.ChainConfig.ChainID.Uint64() != chainID {
return nil, fmt.Errorf("passed chain ID %d does not match chain config chain ID %d",
chainID, c.ChainConfig.ChainID.Uint64())
}
} else {
if c.ChainConfig, err = utils.ChainConfig(chainID); err != nil {
return nil, err
}
}
nodeInfo, cli, err := getEthNodeAndClient(ethHTTPEndpoint, chainID)
if err != nil {
return nil, err
}
c.NodeNetworkID = nodeInfo.NetworkID
c.Client = cli
c.SupportStateDiff = viper.GetBool("ethereum.supportsStateDiff")
c.ForwardEthCalls = viper.GetBool("ethereum.forwardEthCalls")
@ -237,12 +259,6 @@ func NewConfig() (*Config, error) {
if c.StateDiffTimeout < 0 {
return nil, errors.New("ethereum.stateDiffTimeout < 0")
}
chainConfigPath := viper.GetString("ethereum.chainConfig")
if chainConfigPath != "" {
c.ChainConfig, err = utils.LoadConfig(chainConfigPath)
} else {
c.ChainConfig, err = utils.ChainConfig(nodeInfo.ChainID)
}
c.loadGroupCacheConfig()
@ -312,12 +328,11 @@ func (c *Config) loadValidatorConfig() {
}
// GetEthNodeAndClient returns eth node info and client from path url
func getEthNodeAndClient(path string) (node.Info, *rpc.Client, error) {
func getEthNodeAndClient(path string, chainid uint64) (node.Info, *rpc.Client, error) {
viper.BindEnv("ethereum.nodeID", ETH_NODE_ID)
viper.BindEnv("ethereum.clientName", ETH_CLIENT_NAME)
viper.BindEnv("ethereum.genesisBlock", ETH_GENESIS_BLOCK)
viper.BindEnv("ethereum.networkID", ETH_NETWORK_ID)
viper.BindEnv("ethereum.chainID", ETH_CHAIN_ID)
rpcClient, err := rpc.Dial(path)
if err != nil {
@ -328,6 +343,6 @@ func getEthNodeAndClient(path string) (node.Info, *rpc.Client, error) {
ClientName: viper.GetString("ethereum.clientName"),
GenesisBlock: viper.GetString("ethereum.genesisBlock"),
NetworkID: viper.GetString("ethereum.networkID"),
ChainID: viper.GetUint64("ethereum.chainID"),
ChainID: chainid,
}, rpcClient, nil
}

View File

@ -27,6 +27,7 @@ import (
"github.com/cerc-io/plugeth-statediff/indexer/interfaces"
"github.com/cerc-io/plugeth-statediff/indexer/models"
"github.com/cerc-io/plugeth-statediff/indexer/node"
"github.com/cerc-io/plugeth-statediff/indexer/test_helpers"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
"github.com/jmoiron/sqlx"
@ -55,30 +56,7 @@ func SetupDB() *sqlx.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 ipld.blocks`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.header_cids`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth.uncle_cids`)
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.log_cids`)
Expect(err).NotTo(HaveOccurred())
_, err = tx.Exec(`DELETE FROM eth_meta.watched_addresses`)
Expect(err).NotTo(HaveOccurred())
err = tx.Commit()
err := test_helpers.ClearSqlxDB(db)
Expect(err).NotTo(HaveOccurred())
}

View File

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

56
scripts/run-test-stack.sh Executable file
View File

@ -0,0 +1,56 @@
#!/bin/bash
set -e
stack_dir=$(readlink -f "$1")
[[ -d "$stack_dir" ]]
laconic_so="laconic-so --verbose --stack $stack_dir"
CONFIG_DIR=$(readlink -f "${CONFIG_DIR:-$(mktemp -d)}")
# By default assume we are running in the project root.
export CERC_REPO_BASE_DIR="${CERC_REPO_BASE_DIR:-$(git rev-parse --show-toplevel)/..}"
# Don't run geth/plugeth in the debugger, it will swallow error backtraces
echo CERC_REMOTE_DEBUG=false >> $CONFIG_DIR/stack.env
# Passing this lets us run eth_call forwarding tests without running ipld-eth-db
echo CERC_RUN_STATEDIFF=${CERC_RUN_STATEDIFF:-true} >> $CONFIG_DIR/stack.env
set -x
if [[ -z $SKIP_BUILD ]]; then
# Prevent conflicting tty output
export BUILDKIT_PROGRESS=plain
# The server itself will be run separately
$laconic_so setup-repositories \
--exclude git.vdb.to/cerc-io/ipld-eth-server
$laconic_so build-containers \
--exclude cerc/ipld-eth-server
fi
if ! $laconic_so deploy \
--exclude ipld-eth-server \
--env-file $CONFIG_DIR/stack.env \
--cluster test up
then
$laconic_so deploy --cluster test logs
exit 1
fi
set +x
# Get IPv4 endpoint of geth bootnode file server
bootnode_endpoint=$(docker port test-fixturenet-eth-bootnode-geth-1 9898 | head -1)
# Extract the chain config and ID from genesis file
curl -s $bootnode_endpoint/geth.json | jq '.config' > $CONFIG_DIR/chain.json
# Output vars if we are running on Github
if [[ -n "$GITHUB_ENV" ]]; then
echo ETH_CHAIN_ID="$(jq '.chainId' $CONFIG_DIR/chain.json)" >> "$GITHUB_ENV"
echo ETH_CHAIN_CONFIG="$CONFIG_DIR/chain.json" >> "$GITHUB_ENV"
echo ETH_HTTP_PATH=$(docker port test-fixturenet-eth-geth-1-1 8545 | head -1) >> "$GITHUB_ENV"
# Read a private key so we can send from a funded account
echo DEPLOYER_PRIVATE_KEY=$(curl -s $bootnode_endpoint/accounts.csv | head -1 | cut -d',' -f3) >> "$GITHUB_ENV"
fi

View File

@ -5,7 +5,7 @@ services:
restart: on-failure
depends_on:
- ipld-eth-db
image: git.vdb.to/cerc-io/ipld-eth-db/ipld-eth-db:v5.0.5-alpha
image: git.vdb.to/cerc-io/ipld-eth-db/ipld-eth-db:v5.4.0-alpha
environment:
DATABASE_USER: "vdbm"
DATABASE_NAME: "cerc_testing"

View File

@ -4,6 +4,8 @@ services:
ipld-eth-server:
restart: unless-stopped
image: cerc/ipld-eth-server:local
build:
context: ..
networks:
- test_default
environment:
@ -28,7 +30,7 @@ services:
contract-deployer:
restart: on-failure
image: cerc/ipld-eth-server/contract-deployer:local
image: cerc/ipld-eth-server/test-contract-deployer:local
build: ./contract
networks:
- test_default

View File

@ -1,5 +1,5 @@
# Downgrade from 18.16, see https://github.com/NomicFoundation/hardhat/issues/3877
FROM node:18.15-slim
FROM node:20-slim
WORKDIR /usr/src/app
COPY package*.json ./

View File

@ -1,11 +1,16 @@
pragma solidity ^0.8.0;
pragma solidity ^0.8.25;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract GLDToken is ERC20 {
constructor() ERC20("Gold", "GLD") {
_mint(msg.sender, 1000000000000000000000);
}
function destroy() public {
selfdestruct(payable(msg.sender));
(bool ok, ) = payable(msg.sender).call{value: address(this).balance}("");
require(ok, "ETH transfer failed");
_burn(msg.sender, balanceOf(msg.sender));
}
}

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
pragma solidity ^0.8.25;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
@ -7,7 +7,9 @@ contract SLVToken is ERC20 {
uint256 private countA;
uint256 private countB;
constructor() ERC20("Silver", "SLV") {}
constructor() ERC20("Silver", "SLV") {
/* _mint(address(this), 1); */
}
function incrementCountA() public {
countA = countA + 1;
@ -20,6 +22,9 @@ contract SLVToken is ERC20 {
receive() external payable {}
function destroy() public {
selfdestruct(payable(msg.sender));
(bool ok, ) = payable(msg.sender).call{value: address(this).balance}("");
require(ok, "ETH transfer failed");
/* _burn(address(this), balanceOf(address(this))); */
}
}

View File

@ -28,7 +28,7 @@ if (process.env.DEPLOYER_PRIVATE_KEY) {
module.exports = {
solidity: {
version: "0.8.0",
version: "0.8.25",
settings: {
outputSelection: {
'*': {

File diff suppressed because it is too large Load Diff

View File

@ -11,9 +11,9 @@
"license": "ISC",
"description": "Solidity contract deployment server for integration testing",
"dependencies": {
"@openzeppelin/contracts": "^4.0.0",
"fastify": "^4.0.0",
"hardhat": "^2.14.0",
"@openzeppelin/contracts": "^5.0.2",
"fastify": "^4.26.2",
"hardhat": "^2.22.3",
"solidity-create2-deployer": "^0.4.0"
},
"devDependencies": {

View File

@ -1,2 +0,0 @@
github.com/cerc-io/ipld-eth-db v5.0.5-alpha
git.vdb.to/cerc-io/plugeth-statediff v0.1.1

View File

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