Compare commits

..

4 Commits
v5 ... payments

Author SHA1 Message Date
07df0337d1 Remaining Nitro config and refactoring (#259)
Part of [Implement remaining ipld-eth-server config and load payment channels on startup](https://www.notion.so/Implement-remaining-ipld-eth-server-config-and-load-payment-channels-on-startup-5fcb33e49d504d618169a2089740eb67)

Co-authored-by: neeraj <neeraj.rtly@gmail.com>
Co-authored-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
Reviewed-on: #259
Co-authored-by: Prathamesh Musale <prathamesh@noreply.git.vdb.to>
Co-committed-by: Prathamesh Musale <prathamesh@noreply.git.vdb.to>
2023-10-19 05:49:14 +00:00
551efea107 Upgrade go-nitro and add support for remote Nitro node (#258)
Part of [Support running go-nitro node out of process in ipld-eth-server](https://www.notion.so/Support-running-go-nitro-node-out-of-process-in-ipld-eth-server-f0a064ff933a435999104dda2aba5657)

Co-authored-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
Reviewed-on: #258
Co-authored-by: Prathamesh Musale <prathamesh@noreply.git.vdb.to>
Co-committed-by: Prathamesh Musale <prathamesh@noreply.git.vdb.to>
2023-10-18 08:15:33 +00:00
ebaacb3733 Integrate go-nitro node for payments (#256)
Part of [Support running go-nitro node in/out of process in ipld-eth-server](https://www.notion.so/Support-running-go-nitro-node-in-out-of-process-in-ipld-eth-server-f592e29f0e5b474aa65db1509e5ddf1b)

- Added in-process go-nitro node support
- To be handled in upcoming PRs:
  - Out of process go-nitro node support to be added in an upcoming PR
  - Refactoring and remaining todos

Co-authored-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
Reviewed-on: #256
Co-authored-by: Prathamesh Musale <prathamesh@noreply.git.vdb.to>
Co-committed-by: Prathamesh Musale <prathamesh@noreply.git.vdb.to>
2023-10-13 09:03:09 +00:00
a295e7d4b2 Upgrade Go to v1.21 (#255)
Part of [Upgrade Go to v1.21 in ipld-eth-server](https://www.notion.so/Upgrade-Go-to-v1-21-in-ipld-eth-server-b78717fc055a4fc38616e09621b32b9b)

Co-authored-by: neeraj <neeraj.rtly@gmail.com>
Co-authored-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
Reviewed-on: #255
Co-authored-by: Prathamesh Musale <prathamesh@noreply.git.vdb.to>
Co-committed-by: Prathamesh Musale <prathamesh@noreply.git.vdb.to>
2023-10-13 08:20:18 +00:00
44 changed files with 2873 additions and 2192 deletions

View File

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

View File

@ -12,9 +12,9 @@ on:
- ci-test
env:
SO_VERSION: v1.1.0-36d4969-202407091537
FIXTURENET_ETH_STACKS_REF: main
SYSTEM_TESTS_REF: main
# 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
jobs:
test:
@ -26,12 +26,21 @@ 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 --skip-package=./integration
ginkgo -v -r --skipPackage=./integration
integration-test:
name: Run integration tests
@ -42,6 +51,10 @@ 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:
@ -51,18 +64,10 @@ jobs:
env:
DEBIAN_FRONTEND: noninteractive
run: apt-get update && apt-get install -y jq
# 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') }}
- name: Install Python
uses: actions/setup-python@v4
with:
python-version: 3.11
python-version: '3.11'
- name: Install stack-orchestrator
uses: actions/checkout@v3
with:
@ -70,18 +75,16 @@ jobs:
ref: ${{ env.SO_VERSION }}
path: ./stack-orchestrator
- run: pip install ./stack-orchestrator
- 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: 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: Run testnet stack
env:
CERC_GO_AUTH_TOKEN: ${{ secrets.CICD_REPO_TOKEN }}
run: ./scripts/run-test-stack.sh ./fixturenet-eth-stacks/stack-orchestrator/stacks/fixturenet-plugeth
run: ./scripts/integration-setup.sh
- name: Run server
env:
ETH_FORWARD_ETH_CALLS: false
@ -92,31 +95,11 @@ 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/run-test-stack.sh ./fixturenet-eth-stacks/stack-orchestrator/stacks/fixturenet-plugeth
run: ./scripts/integration-setup.sh
- name: Run server with call forwarding
env:
ETH_FORWARD_ETH_CALLS: true

View File

@ -1,9 +1,9 @@
FROM golang:1.21-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.21-alpine AS builder
FROM golang:1.21-alpine as builder
RUN apk --update --no-cache add gcc musl-dev binutils-gold git
@ -28,7 +28,10 @@ RUN GOOS=linux go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -
# app container
FROM alpine
RUN apk --update --no-cache add bash jq curl
ARG USER="vdm"
ARG CONFIG_FILE="./environments/example.toml"
RUN adduser -Du 5000 $USER
WORKDIR /app
@ -37,10 +40,14 @@ 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 .
RUN mkdir -p nitro-data && chown -R 5000:5000 nitro-data
# 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 Normal file
View File

@ -0,0 +1,138 @@
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

@ -35,3 +35,49 @@ func addDatabaseFlags(command *cobra.Command) {
viper.BindPFlag("database.user", command.PersistentFlags().Lookup("database-user"))
viper.BindPFlag("database.password", command.PersistentFlags().Lookup("database-password"))
}
func addNitroFlags(command *cobra.Command) {
// nitro flags
command.PersistentFlags().Bool("nitro-run-node-in-process", false, "nitro run node in process")
command.PersistentFlags().String("nitro-rpc-query-rates-file", "", "nitro rpcQueryRatesFile")
command.PersistentFlags().String("nitro-pk", "", "nitro pk")
command.PersistentFlags().String("nitro-chain-pk", "", "nitro chainPk")
command.PersistentFlags().String("nitro-chain-url", "ws://127.0.0.1:8545", "nitro chainUrl")
command.PersistentFlags().String("nitro-na-address", "", "nitro naAddress")
command.PersistentFlags().String("nitro-vpa-address", "", "nitro vpaAddress")
command.PersistentFlags().String("nitro-ca-address", "", "nitro caAddress")
command.PersistentFlags().Bool("nitro-use-durable-store", false, "nitro useDurableStore")
command.PersistentFlags().String("nitro-durable-store-folder", "", "nitro durableStoreFolder")
command.PersistentFlags().Int("nitro-msg-port", 3005, "nitro msgPort")
command.PersistentFlags().Int("nitro-rpc-port", 4005, "nitro rpcPort")
command.PersistentFlags().Int("nitro-ws-msg-port", 5005, "nitro wsMsgPort")
command.PersistentFlags().Uint("nitro-chain-start-block", 0, "nitro chainStartBlock")
command.PersistentFlags().String("nitro-tls-cert-filepath", "", "nitro tlsCertFilepath")
command.PersistentFlags().String("nitro-tls-key-filepath", "", "nitro tlsKeyFilepath")
command.PersistentFlags().String("nitro-endpoint", "", "nitro endpoint")
command.PersistentFlags().Bool("nitro-is-secure", false, "nitro isSecure")
// nitro flag bindings
viper.BindPFlag("nitro.runNodeInProcess", command.PersistentFlags().Lookup("nitro-run-node-in-process"))
viper.BindPFlag("nitro.rpcQueryRatesFile", command.PersistentFlags().Lookup("nitro-rpc-query-rates-file"))
viper.BindPFlag("nitro.inProcesssNode.pk", command.PersistentFlags().Lookup("nitro-pk"))
viper.BindPFlag("nitro.inProcesssNode.chainPk", command.PersistentFlags().Lookup("nitro-chain-pk"))
viper.BindPFlag("nitro.inProcesssNode.chainUrl", command.PersistentFlags().Lookup("nitro-chain-url"))
viper.BindPFlag("nitro.inProcesssNode.naAddress", command.PersistentFlags().Lookup("nitro-na-address"))
viper.BindPFlag("nitro.inProcesssNode.vpaAddress", command.PersistentFlags().Lookup("nitro-vpa-address"))
viper.BindPFlag("nitro.inProcesssNode.caAddress", command.PersistentFlags().Lookup("nitro-ca-address"))
viper.BindPFlag("nitro.inProcesssNode.useDurableStore", command.PersistentFlags().Lookup("nitro-use-durable-store"))
viper.BindPFlag("nitro.inProcesssNode.durableStoreFolder", command.PersistentFlags().Lookup("nitro-durable-store"))
viper.BindPFlag("nitro.inProcesssNode.msgPort", command.PersistentFlags().Lookup("nitro-msg-port"))
viper.BindPFlag("nitro.inProcesssNode.rpcPort", command.PersistentFlags().Lookup("nitro-rpc-port"))
viper.BindPFlag("nitro.inProcesssNode.wsMsgPort", command.PersistentFlags().Lookup("nitro-ws-msg-port"))
viper.BindPFlag("nitro.inProcesssNode.chainStartBlock", command.PersistentFlags().Lookup("nitro-chain-start-block"))
viper.BindPFlag("nitro.inProcesssNode.tlsCertFilepath", command.PersistentFlags().Lookup("nitro-tls-cert-filepath"))
viper.BindPFlag("nitro.inProcesssNode.tlsKeyFilepath", command.PersistentFlags().Lookup("nitro-tls-key-filepath"))
viper.BindPFlag("nitro.remoteNode.nitroEndpoint", command.PersistentFlags().Lookup("nitro-endpoint"))
viper.BindPFlag("nitro.remoteNode.isSecure", command.PersistentFlags().Lookup("nitro-is-secure"))
}

View File

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

View File

@ -16,7 +16,12 @@
package cmd
import (
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"io/fs"
"math/big"
"net/http"
"net/url"
"os"
@ -26,15 +31,26 @@ import (
"time"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rpc"
"github.com/mailgun/groupcache/v2"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/statechannels/go-nitro/node/engine"
"github.com/statechannels/go-nitro/node/engine/chainservice"
nitroStore "github.com/statechannels/go-nitro/node/engine/store"
"github.com/statechannels/go-nitro/paymentsmanager"
"github.com/statechannels/go-nitro/rpc/transport"
"golang.org/x/exp/slog"
"github.com/cerc-io/ipld-eth-server/v5/pkg/graphql"
srpc "github.com/cerc-io/ipld-eth-server/v5/pkg/rpc"
s "github.com/cerc-io/ipld-eth-server/v5/pkg/serve"
v "github.com/cerc-io/ipld-eth-server/v5/version"
nitroNode "github.com/statechannels/go-nitro/node"
nitrop2pms "github.com/statechannels/go-nitro/node/engine/messageservice/p2p-message-service"
nitroRpc "github.com/statechannels/go-nitro/rpc"
nitroHttpTransport "github.com/statechannels/go-nitro/rpc/transport/http"
)
var ErrNoRpcEndpoints = errors.New("no rpc endpoints is available")
@ -55,12 +71,13 @@ func serve() {
logWithCommand.Infof("ipld-eth-server version: %s", v.VersionWithMeta)
wg := new(sync.WaitGroup)
defer wg.Wait()
serverConfig, err := s.NewConfig()
if err != nil {
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)
@ -76,7 +93,41 @@ func serve() {
}
server.Serve(wg)
if err := startServers(server, serverConfig); err != nil {
var voucherValidator paymentsmanager.VoucherValidator
nitroConfig := serverConfig.Nitro
if nitroConfig.RunNodeInProcess {
log.Info("Running an in-process Nitro node")
pm, nitroRpcServer := initNitroInProcess(wg, nitroConfig)
defer pm.Stop()
defer nitroRpcServer.Close()
voucherValidator = paymentsmanager.InProcessVoucherValidator{PaymentsManager: *pm}
} else {
log.Info("Connecting to a remote Nitro node")
isSecure := nitroConfig.RemoteNode.IsSecure
nitroRpcClient, err := nitroRpc.NewHttpRpcClient(nitroConfig.RemoteNode.NitroEndpoint, isSecure)
if err != nil {
logWithCommand.Fatal(err)
}
defer nitroRpcClient.Close()
voucherValidator = nitroRpc.RemoteVoucherValidator{Client: nitroRpcClient}
}
queryRates, err := readRpcQueryRates(nitroConfig.RpcQueryRatesFile)
if err != nil {
logWithCommand.Fatal(err)
}
paymentMiddleware := func(next http.Handler) http.Handler {
return paymentsmanager.HTTPMiddleware(next, voucherValidator, queryRates)
}
if err := startServers(server, serverConfig, [](func(next http.Handler) http.Handler){paymentMiddleware}); err != nil {
logWithCommand.Fatal(err)
}
graphQL, err := startEthGraphQL(server, serverConfig)
@ -103,10 +154,9 @@ func serve() {
graphQL.Stop()
}
server.Stop()
wg.Wait()
}
func startServers(server s.Server, settings *s.Config) error {
func startServers(server s.Server, settings *s.Config, httpMiddlewares [](func(next http.Handler) http.Handler)) error {
if settings.IPCEnabled {
logWithCommand.Debug("starting up IPC server")
_, _, err := srpc.StartIPCEndpoint(settings.IPCEndpoint, server.APIs())
@ -129,7 +179,7 @@ func startServers(server s.Server, settings *s.Config) error {
if settings.HTTPEnabled {
logWithCommand.Debug("starting up HTTP server")
_, err := srpc.StartHTTPEndpoint(settings.HTTPEndpoint, server.APIs(), []string{"vdb", "eth", "debug", "net"}, nil, []string{"*"}, rpc.HTTPTimeouts{})
_, err := srpc.StartHTTPEndpoint(settings.HTTPEndpoint, server.APIs(), []string{"vdb", "eth", "debug", "net"}, nil, []string{"*"}, rpc.HTTPTimeouts{}, httpMiddlewares)
if err != nil {
return err
}
@ -261,6 +311,8 @@ func init() {
addDatabaseFlags(serveCmd)
addNitroFlags(serveCmd)
// flags for all config variables
// eth graphql and json-rpc parameters
serveCmd.PersistentFlags().Bool("server-graphql", false, "turn on the eth graphql server")
@ -277,10 +329,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", "", "eth chain id")
serveCmd.PersistentFlags().String("eth-chain-config", "", "json chain config file location")
serveCmd.PersistentFlags().String("eth-chain-id", "1", "eth chain id")
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")
@ -340,3 +392,158 @@ func init() {
viper.BindPFlag("validator.enabled", serveCmd.PersistentFlags().Lookup("validator-enabled"))
viper.BindPFlag("validator.everyNthBlock", serveCmd.PersistentFlags().Lookup("validator-every-nth-block"))
}
// Initializes an in-process Nitro node, payments manager and a Nitro RPC server
func initNitroInProcess(wg *sync.WaitGroup, nitroConfig *s.NitroConfig) (*paymentsmanager.PaymentsManager, *nitroRpc.RpcServer) {
nitroNode, err := initNitroNode(&nitroConfig.InProcessNode)
if err != nil {
logWithCommand.Fatal(err)
}
pm, err := paymentsmanager.NewPaymentsManager(nitroNode)
if err != nil {
logWithCommand.Fatal(err)
}
pm.Start(wg)
tlsCertFilepath := nitroConfig.InProcessNode.TlsCertFilepath
tlsKeyFilepath := nitroConfig.InProcessNode.TlsKeyFilepath
var cert *tls.Certificate
if tlsCertFilepath != "" && tlsKeyFilepath != "" {
*cert, err = tls.LoadX509KeyPair(tlsCertFilepath, tlsKeyFilepath)
if err != nil {
logWithCommand.Fatal(err)
}
}
nitroRpcServer, err := initNitroRpcServer(nitroNode, pm, cert, nitroConfig.InProcessNode.RpcPort)
if err != nil {
logWithCommand.Fatal(err)
}
return &pm, nitroRpcServer
}
// https://github.com/cerc-io/go-nitro/blob/release-v0.1.1-ts-port-0.1.7/internal/node/node.go#L17
func initNitroNode(config *s.InProcessNitroNodeConfig) (*nitroNode.Node, error) {
pkString := config.Pk
useDurableStore := config.UseDurableStore
durableStoreFolder := config.DurableStoreFolder
msgPort := config.MsgPort
wsMsgPort := config.WsMsgPort
chainUrl := config.ChainUrl
chainStartBlock := config.ChainStartBlock
chainPk := config.ChainPk
naAddress := config.NaAddress
vpaAddress := config.VpaAddress
caAddress := config.CaAddress
chainAuthToken := ""
publicIp := "0.0.0.0"
chainOpts := chainservice.ChainOpts{
ChainUrl: chainUrl,
ChainStartBlock: chainStartBlock,
ChainAuthToken: chainAuthToken,
ChainPk: chainPk,
NaAddress: common.HexToAddress(naAddress),
VpaAddress: common.HexToAddress(vpaAddress),
CaAddress: common.HexToAddress(caAddress),
}
storeOpts := nitroStore.StoreOpts{
PkBytes: common.Hex2Bytes(pkString),
UseDurableStore: useDurableStore,
DurableStoreFolder: durableStoreFolder,
}
bootPeers := []string{}
messageOpts := nitrop2pms.MessageOpts{
PkBytes: common.Hex2Bytes(pkString),
TcpPort: msgPort,
WsMsgPort: wsMsgPort,
BootPeers: bootPeers,
PublicIp: publicIp,
}
ourStore, err := nitroStore.NewStore(storeOpts)
if err != nil {
return nil, err
}
log.Info("Initializing message service...", " tcp port=", msgPort, " web socket port=", wsMsgPort)
messageService := nitrop2pms.NewMessageService(messageOpts)
// Compare chainOpts.ChainStartBlock to lastBlockNum seen in store. The larger of the two
// gets passed as an argument when creating NewEthChainService
storeBlockNum, err := ourStore.GetLastBlockNumSeen()
if err != nil {
return nil, err
}
if storeBlockNum > chainOpts.ChainStartBlock {
chainOpts.ChainStartBlock = storeBlockNum
}
log.Info("Initializing chain service...")
ourChain, err := chainservice.NewEthChainService(chainOpts)
if err != nil {
return nil, err
}
node := nitroNode.New(
messageService,
ourChain,
ourStore,
&engine.PermissivePolicy{},
)
return &node, nil
}
func initNitroRpcServer(node *nitroNode.Node, pm paymentsmanager.PaymentsManager, cert *tls.Certificate, rpcPort int) (*nitroRpc.RpcServer, error) {
var transport transport.Responder
var err error
slog.Info("Initializing Nitro HTTP RPC transport...")
transport, err = nitroHttpTransport.NewHttpTransportAsServer(fmt.Sprint(rpcPort), cert)
if err != nil {
return nil, err
}
rpcServer, err := nitroRpc.NewRpcServer(node, pm, transport)
if err != nil {
return nil, err
}
slog.Info("Completed Nitro RPC server initialization")
return rpcServer, nil
}
func readRpcQueryRates(filepath string) (map[string]*big.Int, error) {
result := make(map[string]*big.Int)
if filepath == "" {
logWithCommand.Warn("RPC query rates file path not provided")
return result, nil
}
jsonFile, err := os.Open(filepath)
defer jsonFile.Close()
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
logWithCommand.Warn("RPC query rates file does not exist")
return result, nil
}
return nil, err
}
decoder := json.NewDecoder(jsonFile)
err = decoder.Decode(&result)
if err != nil {
return nil, err
}
return result, nil
}

87
cmd/validate.go Normal file
View File

@ -0,0 +1,87 @@
// 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,8 +1,17 @@
#!/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
exec $START_CMD ${VDB_COMMAND:-serve}
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

View File

@ -31,3 +31,27 @@
clientName = "Geth" # $ETH_CLIENT_NAME
genesisBlock = "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" # $ETH_GENESIS_BLOCK
networkID = "1" # $ETH_NETWORK_ID
[nitro]
runNodeInProcess = false # NITRO_RUN_NODE_IN_PROCESS
rpcQueryRatesFile = "environments/rpcQueryRates.json" # NITRO_RPC_QUERY_RATES_FILE
[nitro.inProcesssNode]
pk = "" # NITRO_PK
chainPk = "" # NITRO_CHAIN_PK
chainUrl = "ws://127.0.0.1:8545" # NITRO_CHAIN_URL
naAddress = "" # NITRO_NA_ADDRESS
vpaAddress = "" # NITRO_VPA_ADDRESS
caAddress = "" # NITRO_CA_ADDRESS
useDurableStore = true # NITRO_USE_DURABLE_STORE
durableStoreFolder = "./data/nitronode" # NITRO_DURABLE_STORE_FOLDER
msgPort = 3005 # NITRO_MSG_PORT
rpcPort = 4005 # NITRO_RPC_PORT
wsMsgPort = 5005 # NITRO_WS_MSG_PORT
chainStartBlock = 0 # NITRO_CHAIN_START_BLOCK
tlsCertFilepath = "" # NITRO_TLS_CERT_FILEPATH
tlsKeyFilepath = "" # NITRO_TLS_KEY_FILEPATH
[nitro.remoteNode]
nitroEndpoint = "127.0.0.1:4005/api/v1" # NITRO_ENDPOINT
isSecure = false # NITRO_IS_SECURE

View File

@ -0,0 +1,6 @@
{
"eth_getBlockByNumber": 50,
"eth_getBlockByHash": 50,
"eth_getStorageAt": 50,
"eth_getLogs": 50
}

View File

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

259
go.mod
View File

@ -3,27 +3,28 @@ module github.com/cerc-io/ipld-eth-server/v5
go 1.21
require (
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/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.12.0 // TODO: Investigate
github.com/google/uuid v1.3.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.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
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/statechannels/go-nitro v0.1.2
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63
gorm.io/driver/postgres v1.3.7
gorm.io/gorm v1.23.5
)
@ -32,12 +33,10 @@ 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/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/VictoriaMetrics/fastcache v1.12.1 // indirect
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // 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
@ -45,108 +44,107 @@ 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-20230928194634-aa077af62593 // indirect
github.com/cockroachdb/pebble v0.0.0-20230720154706-692f3b61a3c4 // indirect
github.com/cockroachdb/redact v1.1.5 // 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/cockroachdb/tokenbucket v0.0.0-20230613231145-182959a1fad6 // 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.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/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect
github.com/cskr/pubsub v1.0.2 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/deckarep/golang-set/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/ferranbt/fastssz v0.1.2 // indirect
github.com/fjl/memsize v0.0.2 // indirect
github.com/flynn/noise v1.1.0 // indirect
github.com/fjl/memsize v0.0.1 // indirect
github.com/flynn/noise v1.0.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.1 // 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.4.1 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/go-task/slim-sprig v0.0.0-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-jwt/jwt/v5 v5.0.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.6.0 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 // indirect
github.com/gorilla/websocket v1.5.1 // 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/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 v1.0.2 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // 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/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/huin/goupnp v1.3.0 // indirect
github.com/holiman/uint256 v1.2.3 // indirect
github.com/huin/goupnp v1.2.0 // indirect
github.com/inconshreveable/log15 v2.16.0+incompatible // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/inconshreveable/mousetrap v1.0.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.19.0 // indirect
github.com/ipfs/boxo v0.13.1 // indirect
github.com/ipfs/go-bitfield v1.1.0 // indirect
github.com/ipfs/go-block-format v0.2.0 // indirect
github.com/ipfs/go-block-format v0.1.2 // 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.1.0 // indirect
github.com/ipfs/go-ipld-format v0.6.0 // 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-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.9.0 // indirect
github.com/ipfs/kubo v0.27.0 // indirect
github.com/ipld/go-car/v2 v2.13.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/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.3 // indirect
github.com/jackc/pgconn v1.14.0 // indirect
github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.3.3 // indirect
github.com/jackc/pgproto3/v2 v2.3.2 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgtype v1.14.0 // indirect
github.com/jackc/pgx/v4 v4.18.3 // indirect
github.com/jackc/pgx/v4 v4.18.1 // indirect
github.com/jackc/puddle v1.3.0 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.4 // indirect
github.com/klauspost/compress v1.17.6 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // 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
@ -154,143 +152,154 @@ 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.33.0 // indirect
github.com/libp2p/go-libp2p-asn-util v0.4.1 // 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-kad-dht v0.24.4 // indirect
github.com/libp2p/go-libp2p-kbucket v0.6.3 // indirect
github.com/libp2p/go-libp2p-pubsub v0.10.0 // indirect
github.com/libp2p/go-libp2p-pubsub v0.9.3 // 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.7 // indirect
github.com/magiconair/properties v1.8.6 // 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.20 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/miekg/dns v1.1.58 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/miekg/dns v1.1.55 // 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.12.2 // indirect
github.com/multiformats/go-multiaddr v0.11.0 // indirect
github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect
github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
github.com/multiformats/go-multibase v0.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.5.0 // indirect
github.com/multiformats/go-multistream v0.4.1 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/opencontainers/runtime-spec v1.2.0 // indirect
github.com/openrelayxyz/plugeth-utils v1.5.0 // indirect
github.com/opencontainers/runtime-spec v1.1.0 // indirect
github.com/openrelayxyz/plugeth-utils v1.2.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/v2 v2.1.0 // indirect
github.com/pelletier/go-toml v1.9.4 // indirect
github.com/pelletier/go-toml/v2 v2.0.5 // 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.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/polydawn/refmt v0.89.0 // 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/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/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/quic-go v0.41.0 // indirect
github.com/quic-go/webtransport-go v0.6.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/raulk/go-watchdog v1.3.0 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/rs/cors v1.9.0 // indirect
github.com/russross/blackfriday/v2 v2.1.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/samber/lo v1.36.0 // indirect
github.com/segmentio/fasthash v1.0.3 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/afero v1.8.2 // indirect
github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/status-im/keycard-go v0.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/stretchr/objx v0.5.0 // indirect
github.com/stretchr/testify v1.8.4 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect
github.com/thoas/go-funk v0.9.3 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tidwall/btree v1.6.0 // indirect
github.com/tidwall/buntdb v1.2.10 // indirect
github.com/tidwall/gjson v1.14.4 // indirect
github.com/tidwall/grect v0.1.4 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/rtred v0.1.2 // indirect
github.com/tidwall/tinyqueue v0.1.1 // indirect
github.com/tklauser/go-sysconf v0.3.11 // 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-20240109153615-66e95c3e8a87 // indirect
github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa // 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.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.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.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
go.uber.org/zap v1.25.0 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // 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
golang.org/x/crypto v0.12.0 // 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
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.2 // indirect
rsc.io/tmplfunc v0.0.3 // 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
)
replace github.com/statechannels/go-nitro v0.1.2 => github.com/cerc-io/go-nitro v0.1.2-ts-port-0.1.9

785
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("gets not existing block by number", func() {
It("get 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("gets not existing block by hash", func() {
It("get 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("gets block by number", func() {
It("get 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("gets block by hash", func() {
It("get 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("gets not existing block by number", func() {
It("get 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("gets not existing block by hash", func() {
It("get 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("gets block by number", func() {
It("get 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("gets block by hash", func() {
It("get 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", func() {
It("gets storage after destruction and redeploy", func() {
slvContract, contractErr := integration.Create2Contract("SLVToken", contractSalt)
Expect(contractErr).ToNot(HaveOccurred())
@ -431,6 +431,21 @@ 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,25 +19,19 @@ package eth
import (
"context"
"database/sql"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"math/big"
"strconv"
"strings"
"time"
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/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"
@ -45,9 +39,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 (
@ -112,25 +106,6 @@ 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
@ -247,7 +222,8 @@ Uncles
*/
// GetUncleByBlockNumberAndIndex returns the uncle block for the given block hash and index.
// 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.
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 {
@ -403,7 +379,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), pea.B.ChainConfig())
return newRPCTransactionFromBlockIndex(block, uint64(index))
}
if pea.config.ProxyOnError {
@ -420,7 +396,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), pea.B.ChainConfig())
return newRPCTransactionFromBlockIndex(block, uint64(index))
}
if pea.config.ProxyOnError {
@ -467,14 +443,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, header.Time, index, header.BaseFee, pea.B.ChainConfig()), nil
return NewRPCTransaction(tx, blockHash, blockNumber, index, header.BaseFee), nil
}
if pea.config.ProxyOnError {
var tx *RPCTransaction
@ -489,7 +465,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()
}
@ -604,7 +580,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
}
@ -619,11 +595,7 @@ func (pea *PublicEthAPI) localGetTransactionReceipt(ctx context.Context, hash co
if err != nil {
return nil, err
}
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())
err = receipts.DeriveFields(pea.B.Config.ChainConfig, blockHash, blockNumber, block.BaseFee(), block.Transactions())
if err != nil {
return nil, err
}
@ -660,12 +632,6 @@ 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
@ -827,7 +793,7 @@ func (pea *PublicEthAPI) localGetBalance(ctx context.Context, address common.Add
if err != nil {
return nil, err
}
return (*hexutil.Big)(account.Balance.ToBig()), nil
return (*hexutil.Big)(account.Balance), nil
}
// GetStorageAt returns the storage from the state at the given address, key and
@ -856,7 +822,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, key, blockNrOrHash.String())
log.Warnxf(ctx, "Missing eth_getStorageAt(%s, %s, %s)", address.Hash().String(), 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
@ -902,95 +868,57 @@ 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) {
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 {
state, _, err := pea.B.IPLDTrieStateDBAndHeaderByNumberOrHash(ctx, blockNrOrHash)
if state == nil || err != nil {
return nil, err
}
}
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 {
storageTrie, err := state.StorageTrie(address)
if storageTrie == nil || 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())
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 {
outputKey = hexutil.Encode(key[:])
// no storageTrie means the account does not exist, so the codeHash is the hash of an empty bytearray.
codeHash = crypto.Keccak256Hash(nil)
}
if storageTrie == nil {
storageProof[i] = StorageResult{outputKey, &hexutil.Big{}, []string{}}
continue
// 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
}
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}
storageProof[i] = StorageResult{key, (*hexutil.Big)(state.GetState(address, common.HexToHash(key)).Big()), toHexSlice(proof)}
} else {
storageProof[i] = StorageResult{key, &hexutil.Big{}, []string{}}
}
}
// Create the accountProof.
tr, err := trie.NewStateTrie(trie.StateTrieID(header.Root), statedb.Database().TrieDB())
if err != nil {
return nil, err
// create the accountProof
accountProof, proofErr := state.GetProof(address)
if proofErr != nil {
return nil, proofErr
}
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: accountProof,
Balance: (*hexutil.Big)(balance),
AccountProof: toHexSlice(accountProof),
Balance: (*hexutil.Big)(state.GetBalance(address)),
CodeHash: codeHash,
Nonce: hexutil.Uint64(statedb.GetNonce(address)),
StorageHash: storageRoot,
Nonce: hexutil.Uint64(state.GetNonce(address)),
StorageHash: storageHash,
StorageProof: storageProof,
}, statedb.Error()
}, state.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
@ -1061,7 +989,7 @@ func (diff *StateOverride) Apply(state *ipld_direct_state.StateDB) error {
}
// Override account balance.
if account.Balance != nil {
state.SetBalance(addr, uint256.MustFromBig((*big.Int)(*account.Balance)))
state.SetBalance(addr, (*big.Int)(*account.Balance))
}
if account.State != nil && account.StateDiff != nil {
return fmt.Errorf("account %s has both 'state' and 'stateDiff'", addr.Hex())
@ -1247,22 +1175,25 @@ 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 := RPCMarshalBlock(b, inclTx, fullTx, pea.B.ChainConfig())
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
}
if inclTx {
td, err := pea.B.GetTd(b.Hash())
if err != nil {
err = fmt.Errorf("error getting TD for block at (%s, %s): %s", b.Number(), b.Hash(), err)
log.Error(err)
log.Errorf("error getting td for block with hash and number %s, %s: %s", b.Hash().String(), b.Number().String(), err)
return nil, err
}
fields["totalDifficulty"] = (*hexutil.Big)(td)
}
return fields, nil
return fields, err
}
// 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, pea.B.ChainConfig())
fields, err := RPCMarshalBlockWithUncleHashes(b, uncleHashes, inclTx, fullTx)
if err != nil {
return nil, err
}

View File

@ -19,6 +19,7 @@ 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"
@ -43,14 +44,12 @@ import (
var (
randomAddr = common.HexToAddress("0x1C3ab14BBaD3D99F4203bd7a11aCB94882050E6f")
randomHash = crypto.Keccak256Hash(randomAddr.Bytes())
number = rpc.BlockNumber(test_helpers.BlockNumber1)
blockTime = test_helpers.BlockTime1
londonBlockNum = rpc.BlockNumber(test_helpers.LondonBlockNum)
number = rpc.BlockNumber(test_helpers.BlockNumber.Int64())
londonBlockNum = rpc.BlockNumber(test_helpers.LondonBlockNum.Int64())
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()),
@ -84,6 +83,7 @@ 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,18 +131,10 @@ 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(), 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,
)
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()
@ -195,10 +187,10 @@ var (
"type": hexutil.Uint64(types.LegacyTxType),
}
)
var (
db *sqlx.DB
api *eth.PublicEthAPI
chainConfig = params.TestChainConfig
)
var _ = BeforeSuite(func() {
@ -301,7 +293,9 @@ var _ = Describe("API", func() {
Describe("eth_blockNumber", func() {
It("Retrieves the head block number", func() {
bn := api.BlockNumber()
Expect(bn).To(Equal(hexutil.Uint64(test_helpers.LondonBlockNum)))
ubn := (uint64)(bn)
subn := strconv.FormatUint(ubn, 10)
Expect(subn).To(Equal(test_helpers.LondonBlockNum.String()))
})
})
@ -323,7 +317,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(), chainConfig)
transactions[i] = eth.NewRPCTransactionFromBlockHash(test_helpers.MockBlock, trx.Hash())
}
expectedBlock["transactions"] = transactions
for key, val := range expectedBlock {
@ -377,7 +371,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(), chainConfig)
transactions[i] = eth.NewRPCTransactionFromBlockHash(test_helpers.MockBlock, trx.Hash())
}
expectedBlock["transactions"] = transactions
for key, val := range expectedBlock {
@ -390,7 +384,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(), false)
block, err := api.GetBlockByHash(ctx, test_helpers.MockBlock.Hash(), true)
Expect(err).ToNot(HaveOccurred())
_, ok := block["baseFeePerGas"]
Expect(ok).To(Equal(false))
@ -1110,20 +1104,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.ToBig())))
Expect(bal).To(Equal((*hexutil.Big)(test_helpers.AccountBalance)))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddress, rpc.BlockNumberOrHashWithNumber(number))
Expect(err).ToNot(HaveOccurred())
Expect(bal.ToInt().Cmp(common.Big0)).To(Equal(0))
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
})
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.ToBig())))
Expect(bal).To(Equal((*hexutil.Big)(test_helpers.AccountBalance)))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddress, rpc.BlockNumberOrHashWithHash(blockHash, true))
Expect(err).ToNot(HaveOccurred())
Expect(bal.ToInt().Cmp(common.Big0)).To(Equal(0))
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
})
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,12 +25,6 @@ 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"
@ -48,11 +42,15 @@ 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 (
@ -82,7 +80,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.Database
IpldDirectStateDatabase ipld_direct_state.StateDatabase
// We use this where state must be accessed by trie
IpldTrieStateDatabase ipld_trie_state.Database
@ -117,7 +115,7 @@ func NewEthBackend(db *sqlx.DB, c *Config) (*Backend, error) {
DB: db,
Retriever: r,
EthDB: ethDB,
IpldDirectStateDatabase: ipld_direct_state.NewDatabase(driver),
IpldDirectStateDatabase: ipld_direct_state.NewStateDatabase(driver),
IpldTrieStateDatabase: ipld_trie_state.NewDatabase(ethDB),
Config: c,
}, nil
@ -271,7 +269,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, fmt.Errorf("failed to normalize block number: %w", err)
return nil, err
}
canonicalHash, err := b.GetCanonicalHash(uint64(number))
if err != nil {
@ -349,20 +347,8 @@ 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.NewBlockWithWithdrawals(header, transactions, uncles, receipts, withdrawals, trie.NewEmpty(nil)), err
return types.NewBlock(header, transactions, uncles, receipts, trie.NewEmpty(nil)), err
}
// GetHeaderByBlockHash retrieves header for a provided block hash
@ -506,26 +492,9 @@ 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) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
func (b *Backend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
type txRes struct {
Data []byte `db:"data"`
HeaderID string `db:"header_id"`
@ -534,22 +503,22 @@ func (b *Backend) GetTransaction(ctx context.Context, txHash common.Hash) (bool,
}
var res = make([]txRes, 0)
if err := b.DB.Select(&res, RetrieveRPCTransaction, txHash.String()); err != nil {
return false, nil, common.Hash{}, 0, 0, err
return nil, common.Hash{}, 0, 0, err
}
if len(res) == 0 {
return false, nil, common.Hash{}, 0, 0, errTxHashNotFound
return nil, common.Hash{}, 0, 0, errTxHashNotFound
} else if len(res) > 1 {
// a transaction can be part of a only one canonical block
return false, nil, common.Hash{}, 0, 0, errTxHashInMultipleBlocks
return nil, common.Hash{}, 0, 0, errTxHashInMultipleBlocks
}
var transaction types.Transaction
if err := transaction.UnmarshalBinary(res[0].Data); err != nil {
return false, nil, common.Hash{}, 0, 0, err
return nil, common.Hash{}, 0, 0, err
}
return true, &transaction, common.HexToHash(res[0].HeaderID), res[0].BlockNumber, res[0].Index, nil
return &transaction, common.HexToHash(res[0].HeaderID), res[0].BlockNumber, res[0].Index, nil
}
// GetReceipts retrieves receipts for provided block hash
@ -809,7 +778,7 @@ func (b *Backend) GetAccountByHash(ctx context.Context, address common.Address,
}
return &types.StateAccount{
Nonce: acctRecord.Nonce,
Balance: uint256.MustFromBig(balance),
Balance: balance,
Root: common.HexToHash(acctRecord.Root),
CodeHash: acctRecord.CodeHash,
}, nil
@ -948,10 +917,7 @@ func (b *Backend) GetSlice(path string, depth int, root common.Hash, storage boo
var t ipld_trie_state.Trie
var err error
if storage {
// 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)
t, err = b.IpldTrieStateDatabase.OpenStorageTrie(common.Hash{}, common.Hash{}, root)
} else {
t, err = b.IpldTrieStateDatabase.OpenTrie(root)
}
@ -963,24 +929,21 @@ 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, stateTrie, response, &metaData, storage)
err = b.getSliceStem(headPath, t, response, &metaData, storage)
if err != nil {
return nil, err
}
// Get Head node
err = b.getSliceHead(headPath, stateTrie, response, &metaData, storage)
err = b.getSliceHead(headPath, t, response, &metaData, storage)
if err != nil {
return nil, err
}
if depth > 0 {
// Get Slice nodes
err = b.getSliceTrie(headPath, stateTrie, response, &metaData, depth, storage)
err = b.getSliceTrie(headPath, t, response, &metaData, depth, storage)
if err != nil {
return nil, err
}
@ -991,7 +954,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.StateTrie, response *GetSliceResponse, metaData *metaDataFields, storage bool) error {
func (b *Backend) getSliceStem(headPath []byte, t ipld_trie_state.Trie, response *GetSliceResponse, metaData *metaDataFields, storage bool) error {
leavesFetchTime := int64(0)
totalStemStartTime := makeTimestamp()
@ -1000,7 +963,7 @@ func (b *Backend) getSliceStem(headPath []byte, t *ipld_trie.StateTrie, response
// nodePath := make([]byte, len(headPath[:i]))
nodePath := headPath[:i]
rawNode, _, err := t.GetNode(utils.HexToCompact(nodePath))
rawNode, _, err := t.TryGetNode(utils.HexToCompact(nodePath))
if err != nil {
return err
}
@ -1039,10 +1002,10 @@ func (b *Backend) getSliceStem(headPath []byte, t *ipld_trie.StateTrie, response
return nil
}
func (b *Backend) getSliceHead(headPath []byte, t *ipld_trie.StateTrie, response *GetSliceResponse, metaData *metaDataFields, storage bool) error {
func (b *Backend) getSliceHead(headPath []byte, t ipld_trie_state.Trie, response *GetSliceResponse, metaData *metaDataFields, storage bool) error {
totalHeadStartTime := makeTimestamp()
rawNode, _, err := t.GetNode(utils.HexToCompact(headPath))
rawNode, _, err := t.TryGetNode(utils.HexToCompact(headPath))
if err != nil {
return err
}
@ -1080,10 +1043,7 @@ func (b *Backend) getSliceHead(headPath []byte, t *ipld_trie.StateTrie, response
}
func (b *Backend) getSliceTrie(headPath []byte, t ipld_trie_state.Trie, response *GetSliceResponse, metaData *metaDataFields, depth int, storage bool) error {
it, timeTaken, err := getIteratorAtPath(t, headPath)
if err != nil {
return nil
}
it, timeTaken := getIteratorAtPath(t, headPath)
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,11 +41,10 @@ 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{} {
result := map[string]interface{}{
headerMap := map[string]interface{}{
"number": (*hexutil.Big)(head.Number),
"hash": head.Hash(),
"parentHash": head.ParentHash,
@ -57,67 +56,24 @@ 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 {
result["baseFeePerGas"] = (*hexutil.Big)(head.BaseFee)
headerMap["baseFeePerGas"] = (*hexutil.Big)(head.BaseFee)
}
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
return headerMap
}
// 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, config *params.ChainConfig) map[string]interface{} {
fields := RPCMarshalHeader(block.Header())
fields["size"] = hexutil.Uint64(block.Size())
if inclTx {
formatTx := func(idx int, tx *types.Transaction) interface{} {
return tx.Hash()
}
if fullTx {
formatTx = func(idx int, tx *types.Transaction) interface{} {
return newRPCTransactionFromBlockIndex(block, uint64(idx), config)
}
}
txs := block.Transactions()
transactions := make([]interface{}, len(txs))
for i, tx := range txs {
transactions[i] = formatTx(i, tx)
}
fields["transactions"] = transactions
}
uncles := block.Uncles()
uncleHashes := make([]common.Hash, len(uncles))
for i, uncle := range uncles {
uncleHashes[i] = uncle.Hash()
}
fields["uncles"] = uncleHashes
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, config *params.ChainConfig) (map[string]interface{}, error) {
func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
fields := RPCMarshalHeader(block.Header())
fields["size"] = hexutil.Uint64(block.Size())
@ -127,7 +83,41 @@ func RPCMarshalBlockWithUncleHashes(block *types.Block, uncleHashes []common.Has
}
if fullTx {
formatTx = func(tx *types.Transaction) (interface{}, error) {
return NewRPCTransactionFromBlockHash(block, tx.Hash(), config), nil
return NewRPCTransactionFromBlockHash(block, tx.Hash()), nil
}
}
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
}
}
fields["transactions"] = transactions
}
uncles := block.Uncles()
uncleHashes := make([]common.Hash, len(uncles))
for i, uncle := range uncles {
uncleHashes[i] = uncle.Hash()
}
fields["uncles"] = uncleHashes
return fields, nil
}
// 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) {
fields := RPCMarshalHeader(block.Header())
fields["size"] = hexutil.Uint64(block.Size())
if inclTx {
formatTx := func(tx *types.Transaction) (interface{}, error) {
return tx.Hash(), nil
}
if fullTx {
formatTx = func(tx *types.Transaction) (interface{}, error) {
return NewRPCTransactionFromBlockHash(block, tx.Hash()), nil
}
}
txs := block.Transactions()
@ -145,11 +135,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, config *params.ChainConfig) *RPCTransaction {
// NewRPCTransactionFromBlockHash returns a transaction that will serialize to the RPC representation.
func NewRPCTransactionFromBlockHash(b *types.Block, hash common.Hash) *RPCTransaction {
for idx, tx := range b.Transactions() {
if tx.Hash() == hash {
return newRPCTransactionFromBlockIndex(b, uint64(idx), config)
return newRPCTransactionFromBlockIndex(b, uint64(idx))
}
}
return nil
@ -168,12 +158,11 @@ 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, blockTime uint64, index uint64, baseFee *big.Int, config *params.ChainConfig) *RPCTransaction {
signer := types.MakeSigner(config, new(big.Int).SetUint64(blockNumber), blockTime)
func NewRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber uint64, index uint64, baseFee *big.Int) *RPCTransaction {
signer := SignerForTx(tx)
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()),
@ -182,6 +171,7 @@ 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),
@ -191,69 +181,34 @@ 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(gasTipCap + baseFee, gasFeeCap)
result.GasPrice = (*hexutil.Big)(effectiveGasPrice(tx, baseFee))
// price = min(tip, gasFeeCap - baseFee) + baseFee
price := math.BigMin(new(big.Int).Add(tx.GasTipCap(), baseFee), tx.GasFeeCap())
result.GasPrice = (*hexutil.Big)(price)
} 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"`
@ -315,15 +270,6 @@ 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()
@ -334,6 +280,15 @@ 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,
@ -362,28 +317,21 @@ func toBlockNumArg(number *big.Int) string {
return hexutil.EncodeBig(number)
}
func getIteratorAtPath(t state.Trie, startKey []byte) (trie.NodeIterator, int64, error) {
func getIteratorAtPath(t state.Trie, startKey []byte) (trie.NodeIterator, int64) {
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, err = t.NodeIterator(nodeiter.HexToKeyBytes(startKey))
if err != nil {
return nil, 0, err
}
it = t.NodeIterator(nodeiter.HexToKeyBytes(startKey))
} else {
it, err = t.NodeIterator(nodeiter.HexToKeyBytes(startKey))
if err != nil {
return nil, 0, err
}
it = t.NodeIterator(nodeiter.HexToKeyBytes(startKey))
// Step to the required node (not required if original startKey was odd-length)
it.Next(true)
}
return it, makeTimestamp() - startTime, nil
return it, makeTimestamp() - startTime
}
func fillSliceNodeData(
@ -403,7 +351,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: %w", err)
return 0, fmt.Errorf("GetSlice account lookup error: %s", err.Error())
}
if len(code) > 0 {
@ -439,7 +387,7 @@ func extractContractAccountInfo(sdb state.Database, node StateNode, nodeElements
// Extract codeHash and get code
codeHash := common.BytesToHash(account.CodeHash)
codeBytes, err := sdb.ContractCode(common.Address{}, codeHash)
codeBytes, err := sdb.ContractCode(codeHash)
if err != nil {
return "", "", nil, err
}

View File

@ -6,7 +6,6 @@ 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
@ -74,7 +73,7 @@ type StorageNode struct {
LeafKey []byte `json:"leafKey"`
}
func ResolveNode(path []byte, node []byte, trieDB *triedb.Database) (StateNode, []interface{}, error) {
func ResolveNode(path []byte, node []byte, trieDB *trie.Database) (StateNode, []interface{}, error) {
var nodeElements []interface{}
if err := rlp.DecodeBytes(node, &nodeElements); err != nil {
return StateNode{}, nil, err
@ -94,7 +93,7 @@ func ResolveNode(path []byte, node []byte, trieDB *triedb.Database) (StateNode,
}
// ResolveNodeIt return the state diff node pointed by the iterator.
func ResolveNodeIt(it trie.NodeIterator, trieDB *triedb.Database) (StateNode, []interface{}, error) {
func ResolveNodeIt(it trie.NodeIterator, trieDB *trie.Database) (StateNode, []interface{}, error) {
node, err := it.NodeBlob(), it.Error()
if err != nil {
return StateNode{}, nil, err

View File

@ -506,24 +506,6 @@ 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,21 +107,6 @@ 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,15 +1,8 @@
package eth_state_test
import (
"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"
. "github.com/onsi/gomega"
)
func CheckGetSliceResponse(sliceResponse eth.GetSliceResponse, expectedResponse eth.GetSliceResponse) {
@ -18,54 +11,3 @@ 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.BlockNumber1)
number = rpc.BlockNumber(test_helpers.BlockNumber.Int64())
block1StateRoot = common.HexToHash("0xa1f614839ebdd58677df2c9d66a3e0acc9462acc49fad6006d0b6e5d2b98ed21")
rootDataHashBlock1 = "a1f614839ebdd58677df2c9d66a3e0acc9462acc49fad6006d0b6e5d2b98ed21"
@ -152,6 +152,7 @@ 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),
@ -293,198 +294,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(EqualBigHex(expectedBankBalanceBlock0))
Expect(bal).To(Equal(expectedBankBalanceBlock0))
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(1))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(1))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigInt((common.Big0)))
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(1))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigInt((common.Big0)))
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(1))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock1))
Expect(bal).To(Equal(expectedBankBalanceBlock1))
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(2))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(2))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock2))
Expect(bal).To(Equal(expectedAcct2BalanceBlock2))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(2))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedContractBalance))
Expect(bal).To(Equal(expectedContractBalance))
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(2))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
Expect(bal).To(Equal(expectedBankBalanceBlock2))
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(3))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(3))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock3))
Expect(bal).To(Equal(expectedAcct2BalanceBlock3))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(3))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedContractBalance))
Expect(bal).To(Equal(expectedContractBalance))
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(3))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
Expect(bal).To(Equal(expectedBankBalanceBlock2))
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(4))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(4))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock4))
Expect(bal).To(Equal(expectedAcct2BalanceBlock4))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(4))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedContractBalance))
Expect(bal).To(Equal(expectedContractBalance))
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(4))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
Expect(bal).To(Equal(expectedBankBalanceBlock2))
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(5))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock5))
Expect(bal).To(Equal(expectedAcct1BalanceBlock5))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(5))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock4))
Expect(bal).To(Equal(expectedAcct2BalanceBlock4))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(5))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedContractBalance))
Expect(bal).To(Equal(expectedContractBalance))
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(5))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
Expect(bal).To(Equal(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(EqualBigHex(expectedBankBalanceBlock0))
Expect(bal).To(Equal(expectedBankBalanceBlock0))
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigInt((common.Big0)))
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
_, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigInt((common.Big0)))
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock1))
Expect(bal).To(Equal(expectedBankBalanceBlock1))
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock2))
Expect(bal).To(Equal(expectedAcct2BalanceBlock2))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedContractBalance))
Expect(bal).To(Equal(expectedContractBalance))
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
Expect(bal).To(Equal(expectedBankBalanceBlock2))
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock3))
Expect(bal).To(Equal(expectedAcct2BalanceBlock3))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedContractBalance))
Expect(bal).To(Equal(expectedContractBalance))
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
Expect(bal).To(Equal(expectedBankBalanceBlock2))
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock4))
Expect(bal).To(Equal(expectedAcct2BalanceBlock4))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedContractBalance))
Expect(bal).To(Equal(expectedContractBalance))
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
Expect(bal).To(Equal(expectedBankBalanceBlock2))
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock5))
Expect(bal).To(Equal(expectedAcct1BalanceBlock5))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock4))
Expect(bal).To(Equal(expectedAcct2BalanceBlock4))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedContractBalance))
Expect(bal).To(Equal(expectedContractBalance))
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
Expect(bal).To(Equal(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(EqualBigInt(common.Big0))
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(0))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigInt(common.Big0))
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(0))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigInt(common.Big0))
Expect(bal).To(Equal((*hexutil.Big)(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(EqualBigInt(common.Big0))
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigInt(common.Big0))
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
Expect(err).ToNot(HaveOccurred())
Expect(bal).To(EqualBigInt(common.Big0))
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
})
})

View File

@ -0,0 +1,84 @@
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,7 +31,6 @@ 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"
@ -41,11 +40,10 @@ import (
// Test variables
var (
// block data
BlockNumber1 = int64(1)
BlockTime1 = uint64(0)
BlockNumber = big.NewInt(1)
MockHeader = types.Header{
Time: 0,
Number: big.NewInt(BlockNumber1),
Number: new(big.Int).Set(BlockNumber),
Root: common.HexToHash("0x0"),
TxHash: common.HexToHash("0x0"),
ReceiptHash: common.HexToHash("0x0"),
@ -53,14 +51,10 @@ var (
Extra: []byte{},
}
MockTransactions, MockReceipts, SenderAddr = createLegacyTransactionsAndReceipts()
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: big.NewInt(BlockNumber1 + 1),
Number: new(big.Int).Add(BlockNumber, big.NewInt(1)),
Root: common.HexToHash("0x1"),
TxHash: common.HexToHash("0x1"),
ReceiptHash: common.HexToHash("0x1"),
@ -70,7 +64,7 @@ var (
},
{
Time: 2,
Number: big.NewInt(BlockNumber1 + 2),
Number: new(big.Int).Add(BlockNumber, big.NewInt(2)),
Root: common.HexToHash("0x2"),
TxHash: common.HexToHash("0x2"),
ReceiptHash: common.HexToHash("0x2"),
@ -79,10 +73,10 @@ var (
ParentHash: Genesis.Hash(),
},
}
MockBlock = createNewBlock(&MockHeader, MockTransactions, MockUncles, MockReceipts, nil, trie.NewEmpty(nil))
MockBlock = createNewBlock(&MockHeader, MockTransactions, MockUncles, MockReceipts, trie.NewEmpty(nil))
MockChildHeader = types.Header{
Time: 0,
Number: big.NewInt(BlockNumber1 + 1),
Number: new(big.Int).Add(BlockNumber, common.Big1),
Root: common.HexToHash("0x0"),
TxHash: common.HexToHash("0x0"),
ReceiptHash: common.HexToHash("0x0"),
@ -110,7 +104,7 @@ var (
Address: Address,
Topics: []common.Hash{mockTopic11, mockTopic12},
Data: []byte{},
BlockNumber: uint64(BlockNumber1),
BlockNumber: BlockNumber.Uint64(),
TxIndex: 0,
Index: 0,
}
@ -118,7 +112,7 @@ var (
Address: AnotherAddress,
Topics: []common.Hash{mockTopic21, mockTopic22},
Data: []byte{},
BlockNumber: uint64(BlockNumber1),
BlockNumber: BlockNumber.Uint64(),
TxIndex: 1,
Index: 1,
}
@ -126,7 +120,7 @@ var (
Address: AnotherAddress1,
Topics: []common.Hash{mockTopic31},
Data: []byte{},
BlockNumber: uint64(BlockNumber1),
BlockNumber: BlockNumber.Uint64(),
TxIndex: 2,
Index: 2,
}
@ -135,7 +129,7 @@ var (
Address: AnotherAddress1,
Topics: []common.Hash{mockTopic41, mockTopic42, mockTopic43},
Data: []byte{},
BlockNumber: uint64(BlockNumber1),
BlockNumber: BlockNumber.Uint64(),
TxIndex: 2,
Index: 3,
}
@ -143,7 +137,7 @@ var (
Address: AnotherAddress1,
Topics: []common.Hash{mockTopic51},
Data: []byte{},
BlockNumber: uint64(BlockNumber1),
BlockNumber: BlockNumber.Uint64(),
TxIndex: 2,
Index: 4,
}
@ -151,7 +145,7 @@ var (
Address: AnotherAddress2,
Topics: []common.Hash{mockTopic61},
Data: []byte{},
BlockNumber: uint64(BlockNumber1),
BlockNumber: BlockNumber.Uint64(),
TxIndex: 3,
Index: 5,
}
@ -223,7 +217,7 @@ var (
ContractLeafKey = crypto.Keccak256(ContractAddress[:])
ContractAccount = types.StateAccount{
Nonce: uint64(1),
Balance: uint256.NewInt(0),
Balance: big.NewInt(0),
CodeHash: CodeHash.Bytes(),
Root: common.HexToHash(ContractRoot),
}
@ -235,7 +229,7 @@ var (
})
nonce0 = uint64(0)
AccountBalance = uint256.NewInt(1000)
AccountBalance = big.NewInt(1000)
AccountRoot = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
AccountCodeHash = common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
AccountAddresss = common.HexToAddress("0x0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e")
@ -296,22 +290,21 @@ var (
StateNodes: MockStateNodes,
}
LondonBlockNum = (BlockNumber1 + 2)
LondonBlockTime = BlockTime1 + 1
LondonBlockNum = new(big.Int).Add(BlockNumber, big.NewInt(2))
MockLondonHeader = types.Header{
Time: LondonBlockTime,
Number: big.NewInt(LondonBlockNum),
Time: 0,
Number: LondonBlockNum,
Root: common.HexToHash("0x00"),
Difficulty: big.NewInt(5000000),
Extra: []byte{},
BaseFee: big.NewInt(params.InitialBaseFee),
}
MockLondonTransactions, MockLondonReceipts, _ = createDynamicTransactionsAndReceipts(big.NewInt(LondonBlockNum), LondonBlockTime)
MockLondonTransactions, MockLondonReceipts, _ = createDynamicTransactionsAndReceipts(LondonBlockNum)
MockLondonUncles = []*types.Header{
{
Time: 1,
Number: big.NewInt(BlockNumber1 + 1),
Number: new(big.Int).Add(BlockNumber, big.NewInt(1)),
ParentHash: common.HexToHash("0x2"),
Root: common.HexToHash("0x1"),
TxHash: common.HexToHash("0x1"),
@ -321,7 +314,7 @@ var (
},
{
Time: 2,
Number: big.NewInt(BlockNumber1 + 1),
Number: new(big.Int).Add(BlockNumber, big.NewInt(1)),
ParentHash: common.HexToHash("0x1"),
Root: common.HexToHash("0x2"),
TxHash: common.HexToHash("0x2"),
@ -330,11 +323,11 @@ var (
Extra: []byte{},
},
}
MockLondonBlock = createNewBlock(&MockLondonHeader, MockLondonTransactions, MockLondonUncles, MockLondonReceipts, MockWithdrawals, trie.NewEmpty(nil))
MockLondonBlock = createNewBlock(&MockLondonHeader, MockLondonTransactions, MockLondonUncles, MockLondonReceipts, trie.NewEmpty(nil))
)
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)
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)
bHash := block.Hash()
for _, r := range receipts {
for _, l := range r.Logs {
@ -345,7 +338,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, blockTime uint64) (types.Transactions, types.Receipts, common.Address) {
func createDynamicTransactionsAndReceipts(blockNumber *big.Int) (types.Transactions, types.Receipts, common.Address) {
// make transactions
config := *params.TestChainConfig
config.LondonBlock = blockNumber
@ -360,7 +353,7 @@ func createDynamicTransactionsAndReceipts(blockNumber *big.Int, blockTime uint64
Data: []byte{},
})
transactionSigner := types.MakeSigner(&config, blockNumber, blockTime)
transactionSigner := types.MakeSigner(&config, blockNumber)
mockCurve := elliptic.P256()
mockPrvKey, err := ecdsa.GenerateKey(mockCurve, rand.Reader)
if err != nil {
@ -398,7 +391,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, big.NewInt(BlockNumber1), 0)
transactionSigner := types.MakeSigner(params.MainnetChainConfig, new(big.Int).Set(BlockNumber))
mockCurve := elliptic.P256()
mockPrvKey, err := ecdsa.GenerateKey(mockCurve, rand.Reader)
if err != nil {
@ -459,7 +452,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.EncodeReceipt(rct)
ethRct, err := ipld.NewReceipt(rct)
if err != nil {
return nil, err
}

View File

@ -33,7 +33,6 @@ 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"`
@ -42,7 +41,6 @@ type RPCTransaction struct {
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"`
@ -52,11 +50,9 @@ type RPCTransaction struct {
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).ToBig()), nil
return hexutil.Big(*state.GetBalance(a.address)), nil
}
func (a *Account) TransactionCount(ctx context.Context) (hexutil.Uint64, error) {

View File

@ -18,6 +18,7 @@ package rpc
import (
"fmt"
"net/http"
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
"github.com/ethereum/go-ethereum/cmd/utils"
@ -28,16 +29,23 @@ import (
)
// StartHTTPEndpoint starts the HTTP RPC endpoint, configured with cors/vhosts/modules.
func StartHTTPEndpoint(endpoint string, apis []rpc.API, modules []string, cors []string, vhosts []string, timeouts rpc.HTTPTimeouts) (*rpc.Server, error) {
func StartHTTPEndpoint(endpoint string, apis []rpc.API, modules []string, cors []string, vhosts []string, timeouts rpc.HTTPTimeouts, httpMiddlewares [](func(next http.Handler) http.Handler)) (*rpc.Server, error) {
srv := rpc.NewServer()
err := node.RegisterApis(apis, modules, srv)
if err != nil {
utils.Fatalf("Could not register HTTP API: %w", err)
}
handler := prom.HTTPMiddleware(node.NewHTTPHandlerStack(srv, cors, vhosts, nil))
promHandler := prom.HTTPMiddleware(node.NewHTTPHandlerStack(srv, cors, vhosts, nil))
// Chain the HTTP middlewares
handler := promHandler
for _, middleware := range httpMiddlewares {
handler = middleware(handler)
}
// start http server
// request -> payments -> metrics -> server
_, addr, err := node.StartHTTPEndpoint(endpoint, rpc.DefaultHTTPTimeouts, handler)
if err != nil {
utils.Fatalf("Could not start RPC api: %v", err)

View File

@ -79,8 +79,56 @@ const (
DATABASE_MAX_IDLE_CONNECTIONS = "DATABASE_MAX_IDLE_CONNECTIONS"
DATABASE_MAX_OPEN_CONNECTIONS = "DATABASE_MAX_OPEN_CONNECTIONS"
DATABASE_MAX_CONN_LIFETIME = "DATABASE_MAX_CONN_LIFETIME"
NITRO_RUN_NODE_IN_PROCESS = "NITRO_RUN_NODE_IN_PROCESS"
NITRO_RPC_QUERY_RATES_FILE = "NITRO_RPC_QUERY_RATES_FILE"
NITRO_PK = "NITRO_PK"
NITRO_CHAIN_PK = "NITRO_CHAIN_PK"
NITRO_CHAIN_URL = "NITRO_CHAIN_URL"
NITRO_NA_ADDRESS = "NITRO_NA_ADDRESS"
NITRO_VPA_ADDRESS = "NITRO_VPA_ADDRESS"
NITRO_CA_ADDRESS = "NITRO_CA_ADDRESS"
NITRO_USE_DURABLE_STORE = "NITRO_USE_DURABLE_STORE"
NITRO_DURABLE_STORE_FOLDER = "NITRO_DURABLE_STORE_FOLDER"
NITRO_ENDPOINT = "NITRO_ENDPOINT"
NITRO_IS_SECURE = "NITRO_IS_SECURE"
NITRO_MSG_PORT = "NITRO_MSG_PORT"
NITRO_WS_MSG_PORT = "NITRO_WS_MSG_PORT"
NITRO_RPC_PORT = "NITRO_RPC_PORT"
NITRO_CHAIN_START_BLOCK = "NITRO_CHAIN_START_BLOCK"
NITRO_TLS_CERT_FILEPATH = "NITRO_TLS_CERT_FILEPATH"
NITRO_TLS_KEY_FILEPATH = "NITRO_TLS_KEY_FILEPATH"
)
type InProcessNitroNodeConfig struct {
Pk string
ChainPk string
ChainUrl string
NaAddress string
VpaAddress string
CaAddress string
UseDurableStore bool
DurableStoreFolder string
RpcPort int
MsgPort int
WsMsgPort int
ChainStartBlock uint64
TlsCertFilepath string
TlsKeyFilepath string
}
type RemoteNitroNodeConfig struct {
NitroEndpoint string
IsSecure bool
}
type NitroConfig struct {
RunNodeInProcess bool
RpcQueryRatesFile string
InProcessNode InProcessNitroNodeConfig
RemoteNode RemoteNitroNodeConfig
}
// Config struct
type Config struct {
DB *sqlx.DB
@ -116,6 +164,8 @@ type Config struct {
StateValidationEnabled bool
StateValidationEveryNthBlock uint64
Nitro *NitroConfig
}
// NewConfig is used to initialize a watcher config from a .toml file
@ -128,10 +178,9 @@ 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)
@ -144,32 +193,11 @@ func NewConfig() (*Config, error) {
c.dbInit()
ethHTTP := viper.GetString("ethereum.httpPath")
ethHTTPEndpoint := fmt.Sprintf("http://%s", ethHTTP)
// 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)
nodeInfo, cli, err := getEthNodeAndClient(ethHTTPEndpoint)
c.NodeNetworkID = nodeInfo.NetworkID
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")
@ -259,11 +287,19 @@ 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()
c.loadValidatorConfig()
c.loadNitroConfig()
return c, err
}
@ -296,6 +332,52 @@ func (c *Config) dbInit() {
c.DBConfig.MaxConnLifetime = time.Duration(viper.GetInt("database.maxLifetime"))
}
func (c *Config) loadNitroConfig() {
c.Nitro = &NitroConfig{InProcessNode: InProcessNitroNodeConfig{}, RemoteNode: RemoteNitroNodeConfig{}}
viper.BindEnv("nitro.runNodeInProcess", NITRO_RUN_NODE_IN_PROCESS)
viper.BindEnv("nitro.rpcQueryRatesFile", NITRO_RPC_QUERY_RATES_FILE)
viper.BindEnv("nitro.inProcesssNode.pk", NITRO_PK)
viper.BindEnv("nitro.inProcesssNode.chainPk", NITRO_CHAIN_PK)
viper.BindEnv("nitro.inProcesssNode.chainUrl", NITRO_CHAIN_URL)
viper.BindEnv("nitro.inProcesssNode.naAddress", NITRO_NA_ADDRESS)
viper.BindEnv("nitro.inProcesssNode.vpaAddress", NITRO_VPA_ADDRESS)
viper.BindEnv("nitro.inProcesssNode.caAddress", NITRO_CA_ADDRESS)
viper.BindEnv("nitro.inProcesssNode.useDurableStore", NITRO_USE_DURABLE_STORE)
viper.BindEnv("nitro.inProcesssNode.durableStoreFolder", NITRO_DURABLE_STORE_FOLDER)
viper.BindEnv("nitro.inProcesssNode.msgPort", NITRO_MSG_PORT)
viper.BindEnv("nitro.inProcesssNode.rpcPort", NITRO_RPC_PORT)
viper.BindEnv("nitro.inProcesssNode.wsMsgPort", NITRO_WS_MSG_PORT)
viper.BindEnv("nitro.inProcesssNode.chainStartBlock", NITRO_CHAIN_START_BLOCK)
viper.BindEnv("nitro.inProcesssNode.tlsCertFilepath", NITRO_TLS_CERT_FILEPATH)
viper.BindEnv("nitro.inProcesssNode.tlsKeyFilepath", NITRO_TLS_KEY_FILEPATH)
viper.BindEnv("nitro.remoteNode.nitroEndpoint", NITRO_ENDPOINT)
viper.BindEnv("nitro.remoteNode.isSecure", NITRO_IS_SECURE)
c.Nitro.RunNodeInProcess = viper.GetBool("nitro.runNodeInProcess")
c.Nitro.RpcQueryRatesFile = viper.GetString("nitro.rpcQueryRatesFile")
c.Nitro.InProcessNode.Pk = viper.GetString("nitro.inProcesssNode.pk")
c.Nitro.InProcessNode.ChainPk = viper.GetString("nitro.inProcesssNode.chainPk")
c.Nitro.InProcessNode.ChainUrl = viper.GetString("nitro.inProcesssNode.chainUrl")
c.Nitro.InProcessNode.NaAddress = viper.GetString("nitro.inProcesssNode.naAddress")
c.Nitro.InProcessNode.VpaAddress = viper.GetString("nitro.inProcesssNode.vpaAddress")
c.Nitro.InProcessNode.CaAddress = viper.GetString("nitro.inProcesssNode.caAddress")
c.Nitro.InProcessNode.UseDurableStore = viper.GetBool("nitro.inProcesssNode.useDurableStore")
c.Nitro.InProcessNode.DurableStoreFolder = viper.GetString("nitro.inProcesssNode.durableStoreFolder")
c.Nitro.InProcessNode.MsgPort = viper.GetInt("nitro.inProcesssNode.msgPort")
c.Nitro.InProcessNode.RpcPort = viper.GetInt("nitro.inProcesssNode.rpcPort")
c.Nitro.InProcessNode.WsMsgPort = viper.GetInt("nitro.inProcesssNode.wsMsgPort")
c.Nitro.InProcessNode.ChainStartBlock = viper.GetUint64("nitro.inProcesssNode.chainStartBlock")
c.Nitro.InProcessNode.TlsCertFilepath = viper.GetString("nitro.inProcesssNode.tlsCertFilepath")
c.Nitro.InProcessNode.TlsKeyFilepath = viper.GetString("nitro.inProcesssNode.tlsKeyFilepath")
c.Nitro.RemoteNode.NitroEndpoint = viper.GetString("nitro.remoteNode.nitroEndpoint")
c.Nitro.RemoteNode.IsSecure = viper.GetBool("nitro.remoteNode.isSecure")
}
func (c *Config) loadGroupCacheConfig() {
viper.BindEnv("groupcache.pool.enabled", ethServerShared.GcachePoolEnabled)
viper.BindEnv("groupcache.pool.httpEndpoint", ethServerShared.GcachePoolHttpPath)
@ -328,11 +410,12 @@ func (c *Config) loadValidatorConfig() {
}
// GetEthNodeAndClient returns eth node info and client from path url
func getEthNodeAndClient(path string, chainid uint64) (node.Info, *rpc.Client, error) {
func getEthNodeAndClient(path string) (node.Info, *rpc.Client, error) {
viper.BindEnv("ethereum.nodeID", ETH_NODE_ID)
viper.BindEnv("ethereum.clientName", ETH_CLIENT_NAME)
viper.BindEnv("ethereum.genesisBlock", ETH_GENESIS_BLOCK)
viper.BindEnv("ethereum.networkID", ETH_NETWORK_ID)
viper.BindEnv("ethereum.chainID", ETH_CHAIN_ID)
rpcClient, err := rpc.Dial(path)
if err != nil {
@ -343,6 +426,6 @@ func getEthNodeAndClient(path string, chainid uint64) (node.Info, *rpc.Client, e
ClientName: viper.GetString("ethereum.clientName"),
GenesisBlock: viper.GetString("ethereum.genesisBlock"),
NetworkID: viper.GetString("ethereum.networkID"),
ChainID: chainid,
ChainID: viper.GetUint64("ethereum.chainID"),
}, rpcClient, nil
}

View File

@ -27,7 +27,6 @@ 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"
@ -56,7 +55,30 @@ func SetupDB() *sqlx.DB {
// TearDownDB is used to tear down the watcher dbs after tests
func TearDownDB(db *sqlx.DB) {
err := test_helpers.ClearSqlxDB(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()
Expect(err).NotTo(HaveOccurred())
}

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

@ -0,0 +1,53 @@
#!/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

View File

@ -1,56 +0,0 @@
#!/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.4.0-alpha
image: git.vdb.to/cerc-io/ipld-eth-db/ipld-eth-db:v5.0.5-alpha
environment:
DATABASE_USER: "vdbm"
DATABASE_NAME: "cerc_testing"

View File

@ -4,8 +4,6 @@ services:
ipld-eth-server:
restart: unless-stopped
image: cerc/ipld-eth-server:local
build:
context: ..
networks:
- test_default
environment:
@ -30,7 +28,7 @@ services:
contract-deployer:
restart: on-failure
image: cerc/ipld-eth-server/test-contract-deployer:local
image: cerc/ipld-eth-server/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:20-slim
FROM node:18.15-slim
WORKDIR /usr/src/app
COPY package*.json ./

View File

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

View File

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

View File

@ -28,7 +28,7 @@ if (process.env.DEPLOYER_PRIVATE_KEY) {
module.exports = {
solidity: {
version: "0.8.25",
version: "0.8.0",
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": "^5.0.2",
"fastify": "^4.26.2",
"hardhat": "^2.22.3",
"@openzeppelin/contracts": "^4.0.0",
"fastify": "^4.0.0",
"hardhat": "^2.14.0",
"solidity-create2-deployer": "^0.4.0"
},
"devDependencies": {

2
test/stack-refs.txt Normal file
View File

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

View File

@ -20,9 +20,9 @@ import "fmt"
const (
Major = 5 // Major version component of the current release
Minor = 2 // Minor 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 = "" // Version metadata to append to the version string
Meta = "alpha" // Version metadata to append to the version string
)
// Version holds the textual version string.