Compare commits

..

No commits in common. "v5" and "release-v4.0.6-alpha" have entirely different histories.

17 changed files with 1689 additions and 1323 deletions

View File

@ -1,38 +0,0 @@
name: Run tests
on:
- pull_request
env:
# Needed until we can incorporate docker startup into the executor container
DOCKER_HOST: unix:///var/run/dind.sock
jobs:
unit-tests:
name: Run unit tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
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
working-directory: ./test
run: docker compose up --wait --quiet-pull
- name: Set Gitea access token
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: |
until [[ "$(docker inspect -f '{{.State.Status}}' test-ipld-eth-db)" = 'running' ]]
do sleep 1; done &
go build ./...
wait $!
go test -p 1 -v ./...

View File

@ -1,8 +1,8 @@
# eth-ipfs-state-validator # eth-ipfs-state-validator
[![Go Report Card](https://goreportcard.com/badge/github.com/cerc-io/eth-ipfs-state-validator)](https://goreportcard.com/report/github.com/cerc-io/eth-ipfs-state-validator) [![Go Report Card](https://goreportcard.com/badge/github.com/vulcanize/eth-ipfs-state-validator)](https://goreportcard.com/report/github.com/vulcanize/eth-ipfs-state-validator)
> Uses [ipfs-ethdb](https://github.com/cerc-io/ipfs-ethdb/tree/master/postgres) to validate completeness of IPFS Ethereum state data > Uses [ipfs-ethdb](https://github.com/vulcanize/ipfs-ethdb/tree/master/postgres) to validate completeness of IPFS Ethereum state data
## Background ## Background
@ -42,7 +42,7 @@ Postgres DB config:
```toml ```toml
[database] [database]
name = "cerc_public" name = "vulcanize_public"
hostname = "localhost" hostname = "localhost"
user = "postgres" user = "postgres"
password = "" password = ""
@ -50,7 +50,7 @@ Postgres DB config:
``` ```
## Maintainers ## Maintainers
@cerc-io @vulcanize
@AFDudley @AFDudley
@i-norden @i-norden
@ -60,4 +60,4 @@ Contributions are welcome!
VulcanizeDB follows the [Contributor Covenant Code of Conduct](https://www.contributor-covenant.org/version/1/4/code-of-conduct). VulcanizeDB follows the [Contributor Covenant Code of Conduct](https://www.contributor-covenant.org/version/1/4/code-of-conduct).
## License ## License
[AGPL-3.0](LICENSE) © Vulcanize Inc [AGPL-3.0](LICENSE) © Vulcanize Inc

View File

@ -85,7 +85,7 @@ func init() {
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file location") rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file location")
rootCmd.PersistentFlags().String("logfile", "", "file path for logging") rootCmd.PersistentFlags().String("logfile", "", "file path for logging")
rootCmd.PersistentFlags().String("database-name", "cerc_public", "database name") rootCmd.PersistentFlags().String("database-name", "vulcanize_public", "database name")
rootCmd.PersistentFlags().Int("database-port", 5432, "database port") rootCmd.PersistentFlags().Int("database-port", 5432, "database port")
rootCmd.PersistentFlags().String("database-hostname", "localhost", "database hostname") rootCmd.PersistentFlags().String("database-hostname", "localhost", "database hostname")
rootCmd.PersistentFlags().String("database-user", "", "database user") rootCmd.PersistentFlags().String("database-user", "", "database user")

View File

@ -24,7 +24,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
validator "github.com/cerc-io/eth-ipfs-state-validator/v5/pkg" validator "github.com/vulcanize/eth-ipfs-state-validator/v4/pkg"
) )
// validateTrieCmd represents the validateTrie command // validateTrieCmd represents the validateTrie command
@ -59,41 +59,32 @@ It can operate at three levels:
} }
func validateTrie() { func validateTrie() {
params := validator.Params{ v, err := newValidator()
Workers: viper.GetUint("validator.workers"),
RecoveryFormat: viper.GetString("validator.recoveryFormat"),
}
v, err := newValidator(params)
if err != nil { if err != nil {
logWithCommand.Fatal(err) logWithCommand.Fatal(err)
} }
stateRootStr := viper.GetString("validator.stateRoot") stateRootStr := viper.GetString("validator.stateRoot")
storageRootStr := viper.GetString("validator.storageRoot") storageRootStr := viper.GetString("validator.storageRoot")
contractAddrStr := viper.GetString("validator.address") contractAddrStr := viper.GetString("validator.address")
switch strings.ToLower(viper.GetString("validator.type")) {
if stateRootStr == "" {
logWithCommand.Fatal("must provide a state root for state trie validation")
}
stateRoot := common.HexToHash(stateRootStr)
traversal := strings.ToLower(viper.GetString("validator.type"))
switch traversal {
case "f", "full": case "f", "full":
logWithCommand. if stateRootStr == "" {
WithField("root", stateRoot). logWithCommand.Fatal("must provide a state root for full state validation")
Debug("Validating full state") }
stateRoot := common.HexToHash(stateRootStr)
if err = v.ValidateTrie(stateRoot); err != nil { if err = v.ValidateTrie(stateRoot); err != nil {
logWithCommand.Fatalf("Validation failed: %v", err) logWithCommand.Fatalf("State for root %s is not complete\r\nerr: %v", stateRoot.String(), err)
} }
logWithCommand.Infof("State for root %s is complete", stateRoot) logWithCommand.Infof("State for root %s is complete", stateRoot.String())
case "state": case "state":
logWithCommand. if stateRootStr == "" {
WithField("root", stateRoot). logWithCommand.Fatal("must provide a state root for state trie validation")
Debug("Validating state trie")
if err = v.ValidateStateTrie(stateRoot); err != nil {
logWithCommand.Fatalf("Validation failed: %s", err)
} }
logWithCommand.Infof("State trie for root %s is complete", stateRoot) stateRoot := common.HexToHash(stateRootStr)
if err = v.ValidateStateTrie(stateRoot); err != nil {
logWithCommand.Fatalf("State trie for root %s is not complete\r\nerr: %v", stateRoot.String(), err)
}
logWithCommand.Infof("State trie for root %s is complete", stateRoot.String())
case "storage": case "storage":
if storageRootStr == "" { if storageRootStr == "" {
logWithCommand.Fatal("must provide a storage root for storage trie validation") logWithCommand.Fatal("must provide a storage root for storage trie validation")
@ -103,36 +94,30 @@ func validateTrie() {
} }
storageRoot := common.HexToHash(storageRootStr) storageRoot := common.HexToHash(storageRootStr)
addr := common.HexToAddress(contractAddrStr) addr := common.HexToAddress(contractAddrStr)
logWithCommand. if err = v.ValidateStorageTrie(addr, storageRoot); err != nil {
WithField("contract", addr). logWithCommand.Fatalf("Storage trie for contract %s and root %s not complete\r\nerr: %v", addr.String(), storageRoot.String(), err)
WithField("storage root", storageRoot).
Debug("Validating storage trie")
if err = v.ValidateStorageTrie(stateRoot, addr, storageRoot); err != nil {
logWithCommand.Fatal("Validation failed", err)
} }
logWithCommand.Infof("Storage trie for contract %s and root %s is complete", addr, storageRoot) logWithCommand.Infof("Storage trie for contract %s and root %s is complete", addr.String(), storageRoot.String())
default:
logWithCommand.Fatal("Invalid traversal level:", traversal)
} }
stats := v.GetCacheStats() stats := v.GetCacheStats()
logWithCommand.Debugf("groupcache stats %+v", stats) logWithCommand.Debugf("groupcache stats %+v", stats)
} }
func newValidator(params validator.Params) (*validator.Validator, error) { func newValidator() (*validator.Validator, error) {
ipfsPath := viper.GetString("ipfs.path") ipfsPath := viper.GetString("ipfs.path")
if ipfsPath == "" { if ipfsPath == "" {
db, err := validator.NewDB() db, err := validator.NewDB()
if err != nil { if err != nil {
logWithCommand.Fatal(err) logWithCommand.Fatal(err)
} }
return validator.NewPGIPFSValidator(db, params), nil return validator.NewPGIPFSValidator(db), nil
} }
bs, err := validator.InitIPFSBlockService(ipfsPath) bs, err := validator.InitIPFSBlockService(ipfsPath)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return validator.NewIPFSValidator(bs, params), nil return validator.NewIPFSValidator(bs), nil
} }
func init() { func init() {
@ -143,14 +128,10 @@ func init() {
validateTrieCmd.PersistentFlags().String("storage-root", "", "Root of the storage trie we wish to validate; for storage validation") validateTrieCmd.PersistentFlags().String("storage-root", "", "Root of the storage trie we wish to validate; for storage validation")
validateTrieCmd.PersistentFlags().String("address", "", "Contract address for the storage trie we wish to validate; for storage validation") validateTrieCmd.PersistentFlags().String("address", "", "Contract address for the storage trie we wish to validate; for storage validation")
validateTrieCmd.PersistentFlags().String("ipfs-path", "", "Path to IPFS repository; if provided operations move through the IPFS repo otherwise Postgres connection params are expected in the provided config") validateTrieCmd.PersistentFlags().String("ipfs-path", "", "Path to IPFS repository; if provided operations move through the IPFS repo otherwise Postgres connection params are expected in the provided config")
validateTrieCmd.PersistentFlags().Int("workers", 4, "number of concurrent workers to use")
validateTrieCmd.PersistentFlags().String("recovery-format", validator.DefaultRecoveryFormat, "format pattern for recovery files")
viper.BindPFlag("validator.stateRoot", validateTrieCmd.PersistentFlags().Lookup("state-root")) viper.BindPFlag("validator.stateRoot", validateTrieCmd.PersistentFlags().Lookup("state-root"))
viper.BindPFlag("validator.type", validateTrieCmd.PersistentFlags().Lookup("type")) viper.BindPFlag("validator.type", validateTrieCmd.PersistentFlags().Lookup("type"))
viper.BindPFlag("validator.storageRoot", validateTrieCmd.PersistentFlags().Lookup("storage-root")) viper.BindPFlag("validator.storageRoot", validateTrieCmd.PersistentFlags().Lookup("storage-root"))
viper.BindPFlag("validator.address", validateTrieCmd.PersistentFlags().Lookup("address")) viper.BindPFlag("validator.address", validateTrieCmd.PersistentFlags().Lookup("address"))
viper.BindPFlag("validator.workers", validateTrieCmd.PersistentFlags().Lookup("workers"))
viper.BindPFlag("validator.recoveryFormat", validateTrieCmd.PersistentFlags().Lookup("recovery-format"))
viper.BindPFlag("ipfs.path", validateTrieCmd.PersistentFlags().Lookup("ipfs-path")) viper.BindPFlag("ipfs.path", validateTrieCmd.PersistentFlags().Lookup("ipfs-path"))
} }

View File

@ -1,5 +1,5 @@
[database] [database]
name = "cerc_public" name = "vulcanize_public"
hostname = "localhost" hostname = "localhost"
port = 5432 port = 5432
user = "postgres" user = "postgres"

View File

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

385
go.mod
View File

@ -1,265 +1,238 @@
module github.com/cerc-io/eth-ipfs-state-validator/v5 module github.com/vulcanize/eth-ipfs-state-validator/v4
go 1.21 go 1.18
require ( require (
github.com/cerc-io/eth-iterator-utils v0.2.0 github.com/ethereum/go-ethereum v1.10.21
github.com/cerc-io/ipfs-ethdb/v5 v5.1.0-alpha github.com/ipfs/go-blockservice v0.4.0
github.com/cerc-io/ipld-eth-statedb v0.1.0 github.com/ipfs/go-cid v0.2.0
github.com/ethereum/go-ethereum v1.13.14 github.com/ipfs/go-ipfs-blockstore v1.2.0
github.com/holiman/uint256 v1.2.4 github.com/ipfs/go-ipfs-ds-help v1.1.0
github.com/ipfs/boxo v0.19.0 github.com/ipfs/kubo v0.14.0
github.com/ipfs/go-cid v0.4.1
github.com/ipfs/kubo v0.27.0
github.com/jmoiron/sqlx v1.3.5 github.com/jmoiron/sqlx v1.3.5
github.com/lib/pq v1.10.9 github.com/lib/pq v1.10.5
github.com/mailgun/groupcache/v2 v2.3.0 github.com/mailgun/groupcache/v2 v2.3.0
github.com/multiformats/go-multihash v0.2.3 github.com/multiformats/go-multihash v0.2.0
github.com/onsi/ginkgo/v2 v2.15.0 github.com/onsi/ginkgo v1.16.5
github.com/onsi/gomega v1.30.0 github.com/onsi/gomega v1.19.0
github.com/sirupsen/logrus v1.9.0 github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.8.0 github.com/spf13/cobra v1.4.0
github.com/spf13/viper v1.18.2 github.com/spf13/viper v1.11.0
golang.org/x/sync v0.7.0 github.com/vulcanize/ipfs-ethdb/v4 v4.0.5-alpha
) )
require ( require (
bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc // indirect bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc // indirect
github.com/DataDog/zstd v1.5.5 // indirect github.com/Stebalien/go-bitfield v0.0.1 // indirect
github.com/Jorropo/jsync v1.0.1 // indirect github.com/VictoriaMetrics/fastcache v1.6.0 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a // indirect
github.com/VictoriaMetrics/fastcache v1.12.2 // indirect github.com/benbjohnson/clock v1.3.0 // indirect
github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect
github.com/benbjohnson/clock v1.3.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/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/blang/semver/v4 v4.0.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd v0.22.1 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect
github.com/cerc-io/plugeth-statediff v0.2.1 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect
github.com/cockroachdb/errors v1.10.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cheekybits/genny v1.0.0 // indirect
github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 // indirect github.com/containerd/cgroups v1.0.3 // indirect
github.com/cockroachdb/redact v1.1.5 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect
github.com/consensys/bavard v0.1.13 // indirect
github.com/consensys/gnark-crypto v0.12.1 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/crackcomm/go-gitignore v0.0.0-20231225121904-e25f5bc08668 // indirect
github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 // indirect
github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect
github.com/cskr/pubsub v1.0.2 // indirect github.com/cskr/pubsub v1.0.2 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/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.0.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/docker/go-units v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/elastic/gosigar v0.14.2 // 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/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect
github.com/flynn/noise v1.1.0 // indirect github.com/flynn/noise v1.0.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect github.com/francoispqt/gojay v1.2.13 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/go-logr/logr v1.2.3 // 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/stdr v1.2.2 // 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-stack/stack v1.8.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/godbus/dbus/v5 v5.1.0 // 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/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gopacket v1.1.19 // indirect github.com/google/gopacket v1.1.19 // indirect
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 // indirect github.com/google/uuid v1.3.0 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect
github.com/gorilla/websocket v1.5.1 // indirect github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
github.com/huin/goupnp v1.3.0 // indirect github.com/huin/goupnp v1.0.3 // indirect
github.com/inconshreveable/log15 v2.16.0+incompatible // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/ipfs/bbloom v0.0.4 // indirect github.com/ipfs/bbloom v0.0.4 // indirect
github.com/ipfs/go-bitfield v1.1.0 // indirect github.com/ipfs/go-bitfield v1.0.0 // indirect
github.com/ipfs/go-block-format v0.2.0 // indirect github.com/ipfs/go-bitswap v0.8.0 // indirect
github.com/ipfs/go-block-format v0.0.3 // indirect
github.com/ipfs/go-cidutil v0.1.0 // indirect github.com/ipfs/go-cidutil v0.1.0 // indirect
github.com/ipfs/go-datastore v0.6.0 // indirect github.com/ipfs/go-datastore v0.5.1 // indirect
github.com/ipfs/go-delegated-routing v0.3.0 // indirect
github.com/ipfs/go-ds-measure v0.2.0 // indirect github.com/ipfs/go-ds-measure v0.2.0 // indirect
github.com/ipfs/go-fetcher v1.6.1 // indirect
github.com/ipfs/go-filestore v1.2.0 //indirect
github.com/ipfs/go-fs-lock v0.0.7 // indirect github.com/ipfs/go-fs-lock v0.0.7 // indirect
github.com/ipfs/go-graphsync v0.13.1 // indirect
github.com/ipfs/go-ipfs-chunker v0.0.5 // indirect
github.com/ipfs/go-ipfs-delay v0.0.1 // indirect github.com/ipfs/go-ipfs-delay v0.0.1 // indirect
github.com/ipfs/go-ipfs-ds-help v1.1.0 // indirect github.com/ipfs/go-ipfs-exchange-interface v0.2.0 // indirect
github.com/ipfs/go-ipfs-pq v0.0.3 // indirect github.com/ipfs/go-ipfs-exchange-offline v0.3.0 // indirect
github.com/ipfs/go-ipfs-redirects-file v0.1.1 // indirect github.com/ipfs/go-ipfs-files v0.1.1 // indirect
github.com/ipfs/go-ipfs-util v0.0.3 // indirect github.com/ipfs/go-ipfs-keystore v0.0.2 // indirect
github.com/ipfs/go-ipld-cbor v0.1.0 // indirect github.com/ipfs/go-ipfs-pinner v0.2.1 // indirect
github.com/ipfs/go-ipld-format v0.6.0 // indirect github.com/ipfs/go-ipfs-posinfo v0.0.1 // indirect
github.com/ipfs/go-ipld-legacy v0.2.1 // indirect github.com/ipfs/go-ipfs-pq v0.0.2 // indirect
github.com/ipfs/go-ipfs-provider v0.7.1 // indirect
github.com/ipfs/go-ipfs-routing v0.2.1 // indirect
github.com/ipfs/go-ipfs-util v0.0.2 // indirect
github.com/ipfs/go-ipld-cbor v0.0.5 // indirect
github.com/ipfs/go-ipld-format v0.4.0 // indirect
github.com/ipfs/go-ipld-legacy v0.1.1 // indirect
github.com/ipfs/go-ipns v0.1.2 // indirect
github.com/ipfs/go-log v1.0.5 // indirect github.com/ipfs/go-log v1.0.5 // indirect
github.com/ipfs/go-log/v2 v2.5.1 // indirect github.com/ipfs/go-log/v2 v2.5.1 // indirect
github.com/ipfs/go-merkledag v0.6.0 // indirect
github.com/ipfs/go-metrics-interface v0.0.1 // indirect github.com/ipfs/go-metrics-interface v0.0.1 // indirect
github.com/ipfs/go-peertaskqueue v0.8.1 // indirect github.com/ipfs/go-mfs v0.2.1 // indirect
github.com/ipfs/go-unixfsnode v1.9.0 // indirect github.com/ipfs/go-namesys v0.5.0 // indirect
github.com/ipld/go-car/v2 v2.13.1 // indirect github.com/ipfs/go-path v0.3.0 // indirect
github.com/ipld/go-codec-dagpb v1.6.0 // indirect github.com/ipfs/go-peertaskqueue v0.7.1 // indirect
github.com/ipld/go-ipld-prime v0.21.0 // indirect github.com/ipfs/go-unixfs v0.4.0 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/ipfs/go-unixfsnode v1.4.0 // indirect
github.com/jackc/pgconn v1.14.3 // indirect github.com/ipfs/go-verifcid v0.0.1 // indirect
github.com/jackc/pgio v1.0.0 // indirect github.com/ipfs/interface-go-ipfs-core v0.7.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect github.com/ipld/edelweiss v0.1.4 // indirect
github.com/jackc/pgproto3/v2 v2.3.3 // indirect github.com/ipld/go-codec-dagpb v1.4.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/ipld/go-ipld-prime v0.17.0 // indirect
github.com/jackc/pgtype v1.14.0 // indirect
github.com/jackc/pgx/v4 v4.18.3 // indirect
github.com/jackc/puddle v1.3.0 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect github.com/jbenet/goprocess v0.1.4 // indirect
github.com/klauspost/compress v1.17.6 // indirect github.com/klauspost/compress v1.15.1 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/klauspost/cpuid/v2 v2.0.12 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect github.com/koron/go-ssdp v0.0.2 // indirect
github.com/kr/pretty v0.3.1 // indirect github.com/libp2p/go-buffer-pool v0.0.2 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-cidranger v1.1.0 // indirect
github.com/libp2p/go-doh-resolver v0.4.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-eventbus v0.2.1 // indirect
github.com/libp2p/go-libp2p v0.33.0 // indirect github.com/libp2p/go-flow-metrics v0.0.3 // indirect
github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect github.com/libp2p/go-libp2p v0.20.3 // indirect
github.com/libp2p/go-libp2p-kad-dht v0.24.4 // indirect github.com/libp2p/go-libp2p-asn-util v0.2.0 // indirect
github.com/libp2p/go-libp2p-kbucket v0.6.3 // indirect github.com/libp2p/go-libp2p-core v0.16.1 // indirect
github.com/libp2p/go-libp2p-pubsub v0.10.0 // indirect github.com/libp2p/go-libp2p-discovery v0.7.0 // indirect
github.com/libp2p/go-libp2p-pubsub-router v0.6.0 // indirect github.com/libp2p/go-libp2p-kad-dht v0.16.0 // indirect
github.com/libp2p/go-libp2p-record v0.2.0 // indirect github.com/libp2p/go-libp2p-kbucket v0.4.7 // indirect
github.com/libp2p/go-libp2p-routing-helpers v0.7.3 // indirect github.com/libp2p/go-libp2p-loggables v0.1.0 // indirect
github.com/libp2p/go-libp2p-peerstore v0.6.0 // indirect
github.com/libp2p/go-libp2p-pubsub v0.6.1 // indirect
github.com/libp2p/go-libp2p-pubsub-router v0.5.0 // indirect
github.com/libp2p/go-libp2p-record v0.1.3 // indirect
github.com/libp2p/go-libp2p-resource-manager v0.3.0 // indirect
github.com/libp2p/go-libp2p-routing-helpers v0.2.3 // indirect
github.com/libp2p/go-libp2p-swarm v0.11.0 // indirect
github.com/libp2p/go-libp2p-xor v0.1.0 // indirect github.com/libp2p/go-libp2p-xor v0.1.0 // indirect
github.com/libp2p/go-msgio v0.3.0 // indirect github.com/libp2p/go-mplex v0.7.0 // indirect
github.com/libp2p/go-nat v0.2.0 // indirect github.com/libp2p/go-msgio v0.2.0 // indirect
github.com/libp2p/go-netroute v0.2.1 // indirect github.com/libp2p/go-nat v0.1.0 // indirect
github.com/libp2p/go-reuseport v0.4.0 // indirect github.com/libp2p/go-netroute v0.2.0 // indirect
github.com/libp2p/go-yamux/v4 v4.0.1 // indirect github.com/libp2p/go-openssl v0.0.7 // indirect
github.com/libp2p/zeroconf/v2 v2.2.0 // indirect github.com/libp2p/go-reuseport v0.2.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect github.com/libp2p/go-yamux/v3 v3.1.2 // indirect
github.com/libp2p/zeroconf/v2 v2.1.1 // indirect
github.com/lucas-clemente/quic-go v0.27.1 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/marten-seemann/qtls-go1-16 v0.1.5 // indirect
github.com/marten-seemann/qtls-go1-17 v0.1.1 // indirect
github.com/marten-seemann/qtls-go1-18 v0.1.1 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/miekg/dns v1.1.58 // indirect github.com/miekg/dns v1.1.48 // indirect
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
github.com/minio/sha256-simd v1.0.1 // indirect github.com/minio/sha256-simd v1.0.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/mapstructure v1.4.3 // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base32 v0.0.4 // indirect
github.com/multiformats/go-base36 v0.2.0 // indirect github.com/multiformats/go-base36 v0.1.0 // indirect
github.com/multiformats/go-multiaddr v0.12.2 // indirect github.com/multiformats/go-multiaddr v0.5.0 // indirect
github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect
github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
github.com/multiformats/go-multibase v0.2.0 // indirect github.com/multiformats/go-multibase v0.1.0 // indirect
github.com/multiformats/go-multicodec v0.9.0 // indirect github.com/multiformats/go-multicodec v0.5.0 // indirect
github.com/multiformats/go-multistream v0.5.0 // indirect github.com/multiformats/go-multistream v0.3.3 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect github.com/multiformats/go-varint v0.0.6 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/opencontainers/runtime-spec v1.2.0 // indirect github.com/opencontainers/runtime-spec v1.0.2 // indirect
github.com/openrelayxyz/plugeth-utils v1.5.0 // indirect
github.com/opentracing/opentracing-go 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/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/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 // indirect github.com/pelletier/go-toml/v2 v2.0.0-beta.8 // 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/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e // indirect
github.com/polydawn/refmt v0.89.0 // indirect github.com/prometheus/client_golang v1.12.1 // indirect
github.com/prometheus/client_golang v1.18.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/client_model v0.6.0 // indirect github.com/prometheus/common v0.33.0 // indirect
github.com/prometheus/common v0.47.0 // indirect github.com/prometheus/procfs v0.7.3 // indirect
github.com/prometheus/procfs v0.12.0 // indirect github.com/prometheus/tsdb v0.10.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect github.com/raulk/clock v1.1.0 // indirect
github.com/quic-go/quic-go v0.41.0 // indirect github.com/raulk/go-watchdog v1.2.0 // indirect
github.com/quic-go/webtransport-go v0.6.0 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/samber/lo v1.39.0 // indirect
github.com/segmentio/fasthash v1.0.3 // indirect github.com/segmentio/fasthash v1.0.3 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/shopspring/decimal v1.2.0 // indirect github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.11.0 // indirect github.com/spf13/afero v1.8.2 // indirect
github.com/spf13/cast v1.6.0 // 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/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.2.0 // indirect
github.com/stretchr/testify v1.9.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect
github.com/subosito/gotenv v1.6.0 // indirect github.com/tidwall/gjson v1.14.0 // indirect
github.com/supranational/blst v0.3.11 // indirect github.com/tidwall/match v1.1.1 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/tidwall/pretty v1.2.0 // indirect
github.com/thoas/go-funk v0.9.3 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.2.2 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect github.com/wI2L/jsondiff v0.2.0 // indirect
github.com/ucarion/urlpath v0.0.0-20200424170820-7ccc79b76bbb // indirect
github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // 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-20210219115102-f37d292932f2 // indirect
github.com/whyrusleeping/cbor-gen v0.0.0-20240109153615-66e95c3e8a87 // indirect
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee // indirect
go.opencensus.io v0.24.0 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.opentelemetry.io/otel v1.25.0 // indirect go.opencensus.io v0.23.0 // indirect
go.opentelemetry.io/otel/metric v1.25.0 // indirect go.opentelemetry.io/otel v1.7.0 // indirect
go.opentelemetry.io/otel/trace v1.25.0 // indirect go.opentelemetry.io/otel/trace v1.7.0 // indirect
go.uber.org/dig v1.17.1 // indirect go.uber.org/atomic v1.9.0 // indirect
go.uber.org/fx v1.20.1 // indirect go.uber.org/dig v1.14.0 // indirect
go.uber.org/mock v0.4.0 // indirect go.uber.org/fx v1.16.0 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.27.0 // indirect go.uber.org/zap v1.21.0 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // indirect go4.org v0.0.0-20200411211856-f5505b9728dd // indirect
golang.org/x/crypto v0.22.0 // indirect golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 // indirect golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
golang.org/x/mod v0.17.0 // indirect golang.org/x/net v0.0.0-20220607020251-c690dde0001d // indirect
golang.org/x/net v0.24.0 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.19.0 // indirect golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
golang.org/x/term v0.19.0 // indirect golang.org/x/text v0.3.7 // indirect
golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.1.10 // indirect
golang.org/x/tools v0.20.0 // indirect golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect google.golang.org/protobuf v1.28.0 // indirect
gonum.org/v1/gonum v0.14.0 // indirect gopkg.in/ini.v1 v1.66.4 // indirect
google.golang.org/protobuf v1.32.0 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.2.2 // indirect lukechampine.com/blake3 v1.1.7 // indirect
rsc.io/tmplfunc v0.0.3 // indirect
) )
replace github.com/ethereum/go-ethereum v1.10.21 => github.com/vulcanize/go-ethereum v1.10.21-statediff-4.1.2-alpha

2047
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,7 @@ package main
import ( import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/cerc-io/eth-ipfs-state-validator/v5/cmd" "github.com/vulcanize/eth-ipfs-state-validator/v4/cmd"
) )
func main() { func main() {

View File

@ -18,8 +18,6 @@ package validator
import ( import (
"fmt" "fmt"
"os"
"strconv"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/spf13/viper" "github.com/spf13/viper"
@ -34,6 +32,13 @@ const (
DATABASE_PASSWORD = "DATABASE_PASSWORD" DATABASE_PASSWORD = "DATABASE_PASSWORD"
) )
// NewDB returns a new sqlx.DB from config/cli/env variables
func NewDB() (*sqlx.DB, error) {
c := Config{}
c.Init()
return sqlx.Connect("postgres", c.ConnString())
}
type Config struct { type Config struct {
Hostname string Hostname string
Name string Name string
@ -42,13 +47,6 @@ type Config struct {
Port int Port int
} }
// NewDB returns a new sqlx.DB from config/cli/env variables
func NewDB() (*sqlx.DB, error) {
c := Config{}
LoadViper(&c)
return sqlx.Connect("postgres", c.ConnString())
}
func (c *Config) ConnString() string { func (c *Config) ConnString() string {
if len(c.User) > 0 && len(c.Password) > 0 { if len(c.User) > 0 && len(c.Password) > 0 {
return fmt.Sprintf("postgresql://%s:%s@%s:%d/%s?sslmode=disable", return fmt.Sprintf("postgresql://%s:%s@%s:%d/%s?sslmode=disable",
@ -61,30 +59,7 @@ func (c *Config) ConnString() string {
return fmt.Sprintf("postgresql://%s:%d/%s?sslmode=disable", c.Hostname, c.Port, c.Name) return fmt.Sprintf("postgresql://%s:%d/%s?sslmode=disable", c.Hostname, c.Port, c.Name)
} }
func LoadEnv(c *Config) error { func (c *Config) Init() {
if val := os.Getenv(DATABASE_NAME); val != "" {
c.Name = val
}
if val := os.Getenv(DATABASE_HOSTNAME); val != "" {
c.Hostname = val
}
if val := os.Getenv(DATABASE_PORT); val != "" {
port, err := strconv.Atoi(val)
if err != nil {
return err
}
c.Port = port
}
if val := os.Getenv(DATABASE_USER); val != "" {
c.User = val
}
if val := os.Getenv(DATABASE_PASSWORD); val != "" {
c.Password = val
}
return nil
}
func LoadViper(c *Config) {
viper.BindEnv("database.name", DATABASE_NAME) viper.BindEnv("database.name", DATABASE_NAME)
viper.BindEnv("database.hostname", DATABASE_HOSTNAME) viper.BindEnv("database.hostname", DATABASE_HOSTNAME)
viper.BindEnv("database.port", DATABASE_PORT) viper.BindEnv("database.port", DATABASE_PORT)

View File

@ -19,7 +19,7 @@ package validator_test
import ( import (
"testing" "testing"
. "github.com/onsi/ginkgo/v2" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )

View File

@ -1,9 +0,0 @@
package validator
type TraversalType = string
const (
fullTraversal = "full"
stateTraversal = "state"
storageTraversal = "storage"
)

View File

@ -19,11 +19,42 @@ package validator
import ( import (
"context" "context"
"github.com/ipfs/boxo/blockservice" "github.com/ipfs/go-blockservice"
"github.com/ipfs/go-cid"
blockstore "github.com/ipfs/go-ipfs-blockstore"
dshelp "github.com/ipfs/go-ipfs-ds-help"
"github.com/ipfs/kubo/core" "github.com/ipfs/kubo/core"
"github.com/ipfs/kubo/repo/fsrepo" "github.com/ipfs/kubo/repo/fsrepo"
"github.com/jmoiron/sqlx"
) )
// PublishRaw derives a cid from raw bytes and provided codec and multihash type, and writes it to the db tx
func PublishRaw(tx *sqlx.Tx, codec, mh uint64, raw []byte, blockNumber uint64) (string, error) {
c, err := RawdataToCid(codec, raw, mh)
if err != nil {
return "", err
}
dbKey := dshelp.MultihashToDsKey(c.Hash())
prefixedKey := blockstore.BlockPrefix.String() + dbKey.String()
_, err = tx.Exec(`INSERT INTO public.blocks (key, data, block_number) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING`, prefixedKey, raw, blockNumber)
return c.String(), err
}
// RawdataToCid takes the desired codec, multihash type, and a slice of bytes
// and returns the proper cid of the object.
func RawdataToCid(codec uint64, rawdata []byte, multiHash uint64) (cid.Cid, error) {
c, err := cid.Prefix{
Codec: codec,
Version: 1,
MhType: multiHash,
MhLength: -1,
}.Sum(rawdata)
if err != nil {
return cid.Cid{}, err
}
return c, nil
}
// InitIPFSBlockService is used to configure and return a BlockService using an ipfs repo path (e.g. ~/.ipfs) // InitIPFSBlockService is used to configure and return a BlockService using an ipfs repo path (e.g. ~/.ipfs)
func InitIPFSBlockService(ipfsPath string) (blockservice.BlockService, error) { func InitIPFSBlockService(ipfsPath string) (blockservice.BlockService, error) {
r, openErr := fsrepo.Open(ipfsPath) r, openErr := fsrepo.Open(ipfsPath)
@ -41,3 +72,9 @@ func InitIPFSBlockService(ipfsPath string) (blockservice.BlockService, error) {
} }
return ipfsNode.Blocks, nil return ipfsNode.Blocks, nil
} }
// ResetTestDB drops all rows in the test db public.blocks table
func ResetTestDB(db *sqlx.DB) error {
_, err := db.Exec("DELETE FROM public.blocks")
return err
}

View File

@ -1,39 +0,0 @@
package validator_test
import (
"github.com/ipfs/go-cid"
"github.com/jmoiron/sqlx"
)
// PublishRaw derives a cid from raw bytes and provided codec and multihash type, and writes it to the db tx
func PublishRaw(tx *sqlx.Tx, codec, mh uint64, raw []byte, blockNumber uint64) error {
c, err := RawdataToCid(codec, raw, mh)
if err != nil {
return err
}
_, err = tx.Exec(
`INSERT INTO ipld.blocks (key, data, block_number) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING`,
c.String(), raw, blockNumber)
return err
}
// RawdataToCid takes the desired codec, multihash type, and a slice of bytes
// and returns the proper cid of the object.
func RawdataToCid(codec uint64, rawdata []byte, multiHash uint64) (cid.Cid, error) {
c, err := cid.Prefix{
Codec: codec,
Version: 1,
MhType: multiHash,
MhLength: -1,
}.Sum(rawdata)
if err != nil {
return cid.Cid{}, err
}
return c, nil
}
// ResetTestDB truncates all used tables from the test DB
func ResetTestDB(db *sqlx.DB) error {
_, err := db.Exec("TRUNCATE ipld.blocks")
return err
}

View File

@ -17,67 +17,31 @@
package validator package validator
import ( import (
"bytes"
"context"
"fmt"
"os"
"os/signal"
"syscall"
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie"
"github.com/ipfs/boxo/blockservice" "github.com/ipfs/go-blockservice"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/mailgun/groupcache/v2" "github.com/mailgun/groupcache/v2"
log "github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
iterutils "github.com/cerc-io/eth-iterator-utils" ipfsethdb "github.com/vulcanize/ipfs-ethdb/v4"
"github.com/cerc-io/eth-iterator-utils/tracker" pgipfsethdb "github.com/vulcanize/ipfs-ethdb/v4/postgres"
ipfsethdb "github.com/cerc-io/ipfs-ethdb/v5"
pgipfsethdb "github.com/cerc-io/ipfs-ethdb/v5/postgres/v0"
"github.com/cerc-io/ipld-eth-statedb/trie_by_cid/state"
"github.com/cerc-io/ipld-eth-statedb/trie_by_cid/trie"
"github.com/cerc-io/ipld-eth-statedb/trie_by_cid/triedb"
) )
// Validator is used for validating Ethereum state and storage tries on PG-IPFS // Validator is used for validating Ethereum state and storage tries on PG-IPFS
type Validator struct { type Validator struct {
kvs ethdb.KeyValueStore kvs ethdb.KeyValueStore
trieDB *triedb.Database trieDB *trie.Database
stateDatabase state.Database stateDatabase state.Database
db *pgipfsethdb.Database db *pgipfsethdb.Database
params Params
}
type Params struct {
Workers uint
RecoveryFormat string // %s substituted with traversal type
}
var (
DefaultRecoveryFormat = "./recover_validate_%s"
emptyCodeHash = crypto.Keccak256(nil)
)
type KVSWithAncient struct {
kvs ethdb.KeyValueStore
ethdb.Database
}
func NewKVSDatabaseWithAncient(kvs ethdb.KeyValueStore) ethdb.Database {
return &KVSWithAncient{
kvs: kvs,
}
} }
// NewPGIPFSValidator returns a new trie validator ontop of a connection pool for an IPFS backing Postgres database // NewPGIPFSValidator returns a new trie validator ontop of a connection pool for an IPFS backing Postgres database
func NewPGIPFSValidator(db *sqlx.DB, par Params) *Validator { func NewPGIPFSValidator(db *sqlx.DB) *Validator {
kvs := pgipfsethdb.NewKeyValueStore(db, pgipfsethdb.CacheConfig{ kvs := pgipfsethdb.NewKeyValueStore(db, pgipfsethdb.CacheConfig{
Name: "kv", Name: "kv",
Size: 16 * 1000 * 1000, // 16MB Size: 16 * 1000 * 1000, // 16MB
@ -90,13 +54,11 @@ func NewPGIPFSValidator(db *sqlx.DB, par Params) *Validator {
ExpiryDuration: time.Hour * 8, // 8 hours ExpiryDuration: time.Hour * 8, // 8 hours
}) })
normalizeParams(&par)
return &Validator{ return &Validator{
kvs: kvs, kvs: kvs,
trieDB: triedb.NewDatabase(NewKVSDatabaseWithAncient(kvs), nil), trieDB: trie.NewDatabase(kvs),
stateDatabase: state.NewDatabase(database), stateDatabase: state.NewDatabase(database),
db: database.(*pgipfsethdb.Database), db: database.(*pgipfsethdb.Database),
params: par,
} }
} }
@ -105,15 +67,13 @@ func (v *Validator) GetCacheStats() groupcache.Stats {
} }
// NewIPFSValidator returns a new trie validator ontop of an IPFS blockservice // NewIPFSValidator returns a new trie validator ontop of an IPFS blockservice
func NewIPFSValidator(bs blockservice.BlockService, par Params) *Validator { func NewIPFSValidator(bs blockservice.BlockService) *Validator {
kvs := ipfsethdb.NewKeyValueStore(bs) kvs := ipfsethdb.NewKeyValueStore(bs)
database := ipfsethdb.NewDatabase(bs) database := ipfsethdb.NewDatabase(bs)
normalizeParams(&par)
return &Validator{ return &Validator{
kvs: kvs, kvs: kvs,
trieDB: triedb.NewDatabase(NewKVSDatabaseWithAncient(kvs), nil), trieDB: trie.NewDatabase(kvs),
stateDatabase: state.NewDatabase(database), stateDatabase: state.NewDatabase(database),
params: par,
} }
} }
@ -123,30 +83,26 @@ func NewIPFSValidator(bs blockservice.BlockService, par Params) *Validator {
func NewValidator(kvs ethdb.KeyValueStore, database ethdb.Database) *Validator { func NewValidator(kvs ethdb.KeyValueStore, database ethdb.Database) *Validator {
return &Validator{ return &Validator{
kvs: kvs, kvs: kvs,
trieDB: triedb.NewDatabase(NewKVSDatabaseWithAncient(kvs), nil), trieDB: trie.NewDatabase(kvs),
stateDatabase: state.NewDatabase(database), stateDatabase: state.NewDatabase(database),
} }
} }
// Ensure params are valid
func normalizeParams(p *Params) {
if p.Workers == 0 {
p.Workers = 1
}
if len(p.RecoveryFormat) == 0 {
p.RecoveryFormat = DefaultRecoveryFormat
}
}
// ValidateTrie returns an error if the state and storage tries for the provided state root cannot be confirmed as complete // ValidateTrie returns an error if the state and storage tries for the provided state root cannot be confirmed as complete
// This does consider child storage tries // This does consider child storage tries
func (v *Validator) ValidateTrie(stateRoot common.Hash) error { func (v *Validator) ValidateTrie(stateRoot common.Hash) error {
t, err := v.stateDatabase.OpenTrie(stateRoot) // Generate the state.NodeIterator for this root
stateDB, err := state.New(stateRoot, v.stateDatabase, nil)
if err != nil { if err != nil {
return err return err
} }
iterate := func(ctx context.Context, it trie.NodeIterator) error { return v.iterate(ctx, stateRoot, it, true) } it := state.NewNodeIterator(stateDB)
return iterateTracked(t, fmt.Sprintf(v.params.RecoveryFormat, fullTraversal), v.params.Workers, iterate) for it.Next() {
// iterate through entire state trie and descendent storage tries
// it.Next() will return false when we have either completed iteration of the entire trie or have ran into an error (e.g. a missing node)
// if we are able to iterate through the entire trie without error then the trie is complete
}
return it.Error
} }
// ValidateStateTrie returns an error if the state trie for the provided state root cannot be confirmed as complete // ValidateStateTrie returns an error if the state trie for the provided state root cannot be confirmed as complete
@ -157,21 +113,30 @@ func (v *Validator) ValidateStateTrie(stateRoot common.Hash) error {
if err != nil { if err != nil {
return err return err
} }
iterate := func(ctx context.Context, it trie.NodeIterator) error { return v.iterate(ctx, stateRoot, it, false) } it := t.NodeIterator(nil)
return iterateTracked(t, fmt.Sprintf(v.params.RecoveryFormat, stateTraversal), v.params.Workers, iterate) for it.Next(true) {
// iterate through entire state trie
// it.Next() will return false when we have either completed iteration of the entire trie or have ran into an error (e.g. a missing node)
// if we are able to iterate through the entire trie without error then the trie is complete
}
return it.Error()
} }
// ValidateStorageTrie returns an error if the storage trie for the provided storage root and contract address cannot be confirmed as complete // ValidateStorageTrie returns an error if the storage trie for the provided storage root and contract address cannot be confirmed as complete
func (v *Validator) ValidateStorageTrie(stateRoot common.Hash, address common.Address, storageRoot common.Hash) error { func (v *Validator) ValidateStorageTrie(address common.Address, storageRoot common.Hash) error {
// Generate the state.NodeIterator for this root // Generate the state.NodeIterator for this root
addrHash := crypto.Keccak256Hash(address.Bytes()) addrHash := crypto.Keccak256Hash(address.Bytes())
// Note: the last argument is the redundant state trie, but will be needed for Verkle tries t, err := v.stateDatabase.OpenStorageTrie(addrHash, storageRoot)
storage, err := v.stateDatabase.OpenStorageTrie(stateRoot, addrHash, storageRoot, nil)
if err != nil { if err != nil {
return err return err
} }
iterate := func(ctx context.Context, it trie.NodeIterator) error { return v.iterate(ctx, stateRoot, it, false) } it := t.NodeIterator(nil)
return iterateTracked(storage, fmt.Sprintf(v.params.RecoveryFormat, storageTraversal), v.params.Workers, iterate) for it.Next(true) {
// iterate through entire storage trie
// it.Next() will return false when we have either completed iteration of the entire trie or have ran into an error (e.g. a missing node)
// if we are able to iterate through the entire trie without error then the trie is complete
}
return it.Error()
} }
// Close implements io.Closer // Close implements io.Closer
@ -181,111 +146,3 @@ func (v *Validator) Close() error {
groupcache.DeregisterGroup("db") groupcache.DeregisterGroup("db")
return nil return nil
} }
// Traverses one iterator fully
// If storage = true, also traverse storage tries for each leaf.
func (v *Validator) iterate(ctx context.Context, stateRoot common.Hash, it trie.NodeIterator, storage bool) error {
// Iterate through entire state trie. it.Next() will return false when we have
// either completed iteration of the entire trie or run into an error (e.g. a
// missing node). If we are able to iterate through the entire trie without error
// then the trie is complete.
for it.Next(true) {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
// This block adapted from geth - core/state/iterator.go
// If storage is not requested, or the state trie node is an internal entry, skip
if !storage || !it.Leaf() {
continue
}
// Otherwise we've reached an account node, initiate data iteration
var account types.StateAccount
if err := rlp.Decode(bytes.NewReader(it.LeafBlob()), &account); err != nil {
return err
}
// Note: the last argument is the redundant state trie, but will be needed for Verkle tries
dataTrie, err := v.stateDatabase.OpenStorageTrie(stateRoot, common.BytesToHash(it.LeafKey()), account.Root, nil)
if err != nil {
return err
}
dataIt, err := dataTrie.NodeIterator(nil)
if err != nil {
return err
}
if !bytes.Equal(account.CodeHash, emptyCodeHash) {
_, err := v.stateDatabase.ContractCode(common.Address{}, common.BytesToHash(account.CodeHash))
if err != nil {
return fmt.Errorf("code hash %x: %w (path %x)", account.CodeHash, err, iterutils.HexToKeyBytes(it.Path()))
}
}
for dataIt.Next(true) {
}
if dataIt.Error() != nil {
return fmt.Errorf("data iterator error (path %x): %w", iterutils.HexToKeyBytes(dataIt.Path()), dataIt.Error())
}
}
return it.Error()
}
// Traverses each iterator in a separate goroutine.
// Dumps to a recovery file on failure or interrupt.
func iterateTracked(
tree state.Trie,
recoveryFile string,
iterCount uint,
fn func(context.Context, trie.NodeIterator) error,
) error {
tracker := tracker.New(recoveryFile, iterCount)
halt := func() {
if err := tracker.CloseAndSave(); err != nil {
log.Errorf("failed to write recovery file: %v", err)
}
}
// attempt to restore from recovery file if it exists
iters, _, err := tracker.Restore(tree.NodeIterator)
if err != nil {
return err
}
if iterCount < uint(len(iters)) {
return fmt.Errorf("recovered too many iterators: got %d, expected %d", len(iters), iterCount)
}
if iters == nil { // nothing restored
iters, err = iterutils.SubtrieIterators(tree.NodeIterator, iterCount)
if err != nil {
return err
}
for i, it := range iters {
iters[i] = tracker.Tracked(it)
}
} else {
log.Debugf("restored %d iterators from: %s", len(iters), recoveryFile)
}
ctx, cancel := context.WithCancel(context.Background())
g, ctx := errgroup.WithContext(ctx)
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
go func() {
sig := <-sigChan
log.Errorf("Signal received (%v), stopping", sig)
cancel()
}()
defer halt()
for _, it := range iters {
func(it trie.NodeIterator) {
g.Go(func() error {
return fn(ctx, it)
})
}(it)
}
return g.Wait()
}

View File

@ -17,21 +17,21 @@
package validator_test package validator_test
import ( import (
"os" "fmt"
"path/filepath" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/holiman/uint256"
cid "github.com/ipfs/go-cid/_rsrch/cidiface" cid "github.com/ipfs/go-cid/_rsrch/cidiface"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/multiformats/go-multihash" "github.com/multiformats/go-multihash"
. "github.com/onsi/ginkgo/v2" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
validator "github.com/cerc-io/eth-ipfs-state-validator/v5/pkg" validator "github.com/vulcanize/eth-ipfs-state-validator/v4/pkg"
pgipfsethdb "github.com/vulcanize/ipfs-ethdb/v4/postgres"
) )
var ( var (
@ -66,10 +66,9 @@ var (
mockCode = []byte{1, 2, 3, 4, 5} mockCode = []byte{1, 2, 3, 4, 5}
codeHash = crypto.Keccak256Hash(mockCode) codeHash = crypto.Keccak256Hash(mockCode)
codePath = common.Hex2Bytes("6114658a74d9cc9f7acf2c5cd696c3494d7c344d78bfec3add0d91ec4e8d1c45")
contractAccount, _ = rlp.EncodeToBytes(&types.StateAccount{ contractAccount, _ = rlp.EncodeToBytes(&types.StateAccount{
Nonce: 1, Nonce: 1,
Balance: uint256.NewInt(0), Balance: big.NewInt(0),
CodeHash: codeHash.Bytes(), CodeHash: codeHash.Bytes(),
Root: crypto.Keccak256Hash(storageBranchRootNode), Root: crypto.Keccak256Hash(storageBranchRootNode),
}) })
@ -80,7 +79,7 @@ var (
minerAccount, _ = rlp.EncodeToBytes(&types.StateAccount{ minerAccount, _ = rlp.EncodeToBytes(&types.StateAccount{
Nonce: 0, Nonce: 0,
Balance: uint256.NewInt(1000), Balance: big.NewInt(1000),
CodeHash: nullCodeHash.Bytes(), CodeHash: nullCodeHash.Bytes(),
Root: emptyContractRoot, Root: emptyContractRoot,
}) })
@ -91,7 +90,7 @@ var (
account1, _ = rlp.EncodeToBytes(&types.StateAccount{ account1, _ = rlp.EncodeToBytes(&types.StateAccount{
Nonce: 2, Nonce: 2,
Balance: uint256.NewInt(1000), Balance: big.NewInt(1000),
CodeHash: nullCodeHash.Bytes(), CodeHash: nullCodeHash.Bytes(),
Root: emptyContractRoot, Root: emptyContractRoot,
}) })
@ -102,7 +101,7 @@ var (
account2, _ = rlp.EncodeToBytes(&types.StateAccount{ account2, _ = rlp.EncodeToBytes(&types.StateAccount{
Nonce: 0, Nonce: 0,
Balance: uint256.NewInt(1000), Balance: big.NewInt(1000),
CodeHash: nullCodeHash.Bytes(), CodeHash: nullCodeHash.Bytes(),
Root: emptyContractRoot, Root: emptyContractRoot,
}) })
@ -113,7 +112,7 @@ var (
bankAccount, _ = rlp.EncodeToBytes(&types.StateAccount{ bankAccount, _ = rlp.EncodeToBytes(&types.StateAccount{
Nonce: 2, Nonce: 2,
Balance: uint256.NewInt(1000), Balance: big.NewInt(1000),
CodeHash: nullCodeHash.Bytes(), CodeHash: nullCodeHash.Bytes(),
Root: emptyContractRoot, Root: emptyContractRoot,
}) })
@ -189,84 +188,63 @@ var (
storageBranchRootNode, storageBranchRootNode,
slot1StorageLeafNode, slot1StorageLeafNode,
} }
missingStateNodePath = common.Hex2Bytes("0e")
missingStorageNodePath = common.Hex2Bytes("02")
) )
var ( var (
v *validator.Validator v *validator.Validator
db *sqlx.DB db *sqlx.DB
err error err error
tmp string
config = validator.Config{
Hostname: "localhost",
Name: "cerc_testing",
User: "vdbm",
Password: "password",
Port: 8077,
}
) )
var _ = Describe("PG-IPFS Validator", func() { var _ = Describe("PG-IPFS Validator", func() {
BeforeEach(func() { BeforeEach(func() {
err = validator.LoadEnv(&config) db, err = pgipfsethdb.TestDB()
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
db, err = sqlx.Connect("postgres", config.ConnString()) v = validator.NewPGIPFSValidator(db)
Expect(err).ToNot(HaveOccurred())
tmp, err = os.MkdirTemp("", "test_validator")
Expect(err).ToNot(HaveOccurred())
params := validator.Params{Workers: 4, RecoveryFormat: filepath.Join(tmp, "recover_%s")}
v = validator.NewPGIPFSValidator(db, params)
}) })
AfterEach(func() { AfterEach(func() {
os.RemoveAll(tmp)
v.Close() v.Close()
db.Close()
}) })
Describe("ValidateTrie", func() { Describe("ValidateTrie", func() {
AfterEach(func() { AfterEach(func() {
err = ResetTestDB(db) err = validator.ResetTestDB(db)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
}) })
It("Returns an error if the state root node is missing", func() { It("Returns an error the state root node is missing", func() {
// we write code to ethdb, there should probably be an EthCode IPLD codec // we write code to ethdb, there should probably be an EthCode IPLD codec
// but there isn't, and we don't need one here since blockstore keys are mh-derived // but there isn't, and we don't need one here since blockstore keys are mh-derived
loadTrie(missingRootStateNodes, trieStorageNodes, mockCode) loadTrie(append(missingRootStateNodes, mockCode), trieStorageNodes)
err = v.ValidateTrie(stateRoot) err = v.ValidateTrie(stateRoot)
Expect(err).To(HaveOccurred()) Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("missing trie node")) Expect(err.Error()).To(ContainSubstring("missing trie node"))
}) })
It("Returns an error if the storage root node is missing", func() { It("Returns an error if the storage root node is missing", func() {
loadTrie(trieStateNodes, missingRootStorageNodes, mockCode) loadTrie(append(trieStateNodes, mockCode), missingRootStorageNodes)
err = v.ValidateTrie(stateRoot) err = v.ValidateTrie(stateRoot)
Expect(err).To(HaveOccurred()) Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("missing trie node")) Expect(err.Error()).To(ContainSubstring("missing trie node"))
}) })
It("Returns an error if the state trie is missing node(s)", func() { It("Returns an error if the state trie is missing node(s)", func() {
loadTrie(missingNodeStateNodes, trieStorageNodes, mockCode) loadTrie(append(missingNodeStateNodes, mockCode), trieStorageNodes)
err = v.ValidateTrie(stateRoot) err = v.ValidateTrie(stateRoot)
Expect(err).To(HaveOccurred()) Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("missing trie node")) Expect(err.Error()).To(ContainSubstring("missing trie node"))
Expect(err.Error()).To(ContainSubstring("path %x", missingStateNodePath))
}) })
It("Returns an error if the storage trie is missing node(s)", func() { It("Returns an error if the storage trie is missing node(s)", func() {
loadTrie(trieStateNodes, missingNodeStorageNodes, mockCode) loadTrie(append(trieStateNodes, mockCode), missingNodeStorageNodes)
err = v.ValidateTrie(stateRoot) err = v.ValidateTrie(stateRoot)
Expect(err).To(HaveOccurred()) Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("missing trie node")) Expect(err.Error()).To(ContainSubstring("missing trie node"))
Expect(err.Error()).To(ContainSubstring("path %x", missingStorageNodePath))
}) })
It("Returns an error if contract code is missing", func() { It("Returns an error if contract code is missing", func() {
loadTrie(trieStateNodes, trieStorageNodes) loadTrie(trieStateNodes, trieStorageNodes)
err = v.ValidateTrie(stateRoot) err = v.ValidateTrie(stateRoot)
Expect(err).To(HaveOccurred()) Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("%x", codeHash)) subStr := fmt.Sprintf("code %s: not found", codeHash.Hex()[2:])
Expect(err.Error()).To(ContainSubstring("%x", codePath)) Expect(err.Error()).To(ContainSubstring(subStr))
}) })
It("Returns no error if the entire state (state trie and storage tries) can be validated", func() { It("Returns no error if the entire state (state trie and storage tries) can be validated", func() {
loadTrie(trieStateNodes, trieStorageNodes, mockCode) loadTrie(append(trieStateNodes, mockCode), trieStorageNodes)
err = v.ValidateTrie(stateRoot) err = v.ValidateTrie(stateRoot)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
}) })
@ -274,7 +252,7 @@ var _ = Describe("PG-IPFS Validator", func() {
Describe("ValidateStateTrie", func() { Describe("ValidateStateTrie", func() {
AfterEach(func() { AfterEach(func() {
err = ResetTestDB(db) err = validator.ResetTestDB(db)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
}) })
It("Returns an error the state root node is missing", func() { It("Returns an error the state root node is missing", func() {
@ -288,7 +266,6 @@ var _ = Describe("PG-IPFS Validator", func() {
err = v.ValidateStateTrie(stateRoot) err = v.ValidateStateTrie(stateRoot)
Expect(err).To(HaveOccurred()) Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("missing trie node")) Expect(err.Error()).To(ContainSubstring("missing trie node"))
Expect(err.Error()).To(ContainSubstring("path %x", missingStateNodePath))
}) })
It("Returns no error if the entire state trie can be validated", func() { It("Returns no error if the entire state trie can be validated", func() {
loadTrie(trieStateNodes, nil) loadTrie(trieStateNodes, nil)
@ -299,43 +276,38 @@ var _ = Describe("PG-IPFS Validator", func() {
Describe("ValidateStorageTrie", func() { Describe("ValidateStorageTrie", func() {
AfterEach(func() { AfterEach(func() {
err = ResetTestDB(db) err = validator.ResetTestDB(db)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
}) })
It("Returns an error if the storage root node is missing", func() { It("Returns an error the storage root node is missing", func() {
loadTrie(nil, missingRootStorageNodes) loadTrie(nil, missingRootStorageNodes)
err = v.ValidateStorageTrie(common.Hash{}, contractAddr, storageRoot) err = v.ValidateStorageTrie(contractAddr, storageRoot)
Expect(err).To(HaveOccurred()) Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("missing trie node")) Expect(err.Error()).To(ContainSubstring("missing trie node"))
}) })
It("Returns an error if the entire storage trie cannot be validated", func() { It("Returns an error if the entire storage trie cannot be validated", func() {
loadTrie(nil, missingNodeStorageNodes) loadTrie(nil, missingNodeStorageNodes)
err = v.ValidateStorageTrie(common.Hash{}, contractAddr, storageRoot) err = v.ValidateStorageTrie(contractAddr, storageRoot)
Expect(err).To(HaveOccurred()) Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("missing trie node")) Expect(err.Error()).To(ContainSubstring("missing trie node"))
Expect(err.Error()).To(ContainSubstring("path %x", missingStorageNodePath))
}) })
It("Returns no error if the entire storage trie can be validated", func() { It("Returns no error if the entire storage trie can be validated", func() {
loadTrie(nil, trieStorageNodes) loadTrie(nil, trieStorageNodes)
err = v.ValidateStorageTrie(common.Hash{}, contractAddr, storageRoot) err = v.ValidateStorageTrie(contractAddr, storageRoot)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
}) })
}) })
}) })
func loadTrie(stateNodes, storageNodes [][]byte, contractCode ...[]byte) { func loadTrie(stateNodes, storageNodes [][]byte) {
tx, err := db.Beginx() tx, err := db.Beginx()
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
for _, node := range stateNodes { for _, node := range stateNodes {
err := PublishRaw(tx, cid.EthStateTrie, multihash.KECCAK_256, node, blockNumber) _, err := validator.PublishRaw(tx, cid.EthStateTrie, multihash.KECCAK_256, node, blockNumber)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
} }
for _, node := range storageNodes { for _, node := range storageNodes {
err := PublishRaw(tx, cid.EthStorageTrie, multihash.KECCAK_256, node, blockNumber) _, err := validator.PublishRaw(tx, cid.EthStorageTrie, multihash.KECCAK_256, node, blockNumber)
Expect(err).ToNot(HaveOccurred())
}
for _, code := range contractCode {
err := PublishRaw(tx, cid.Raw, multihash.KECCAK_256, code, blockNumber)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
} }
err = tx.Commit() err = tx.Commit()

View File

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