Refactor for v5 and IPFS v0 blockstore (#73)
* vulcanize => cerc * Use v0-blockstore based DB via ipld-eth-statedb/trie_by_cid * Update CI workflows * Update modules - concurrent iterator interface - ginkgo v2 - go 1.19
This commit is contained in:
+1
-1
@@ -19,7 +19,7 @@ package validator_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
|
||||
+6
-8
@@ -2,21 +2,19 @@ package validator_test
|
||||
|
||||
import (
|
||||
"github.com/ipfs/go-cid"
|
||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
dshelp "github.com/ipfs/go-ipfs-ds-help"
|
||||
"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) {
|
||||
func PublishRaw(tx *sqlx.Tx, codec, mh uint64, raw []byte, blockNumber uint64) error {
|
||||
c, err := RawdataToCid(codec, raw, mh)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
dbKey := dshelp.MultihashToDsKey(c.Hash())
|
||||
prefixedKey := blockstore.BlockPrefix.String() + dbKey.String()
|
||||
_, err = tx.Exec(`INSERT INTO ipld.blocks (key, data, block_number) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING`, prefixedKey, raw, blockNumber)
|
||||
return c.String(), 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
|
||||
|
||||
+7
-8
@@ -25,12 +25,10 @@ import (
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"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/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ipfs/go-blockservice"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/mailgun/groupcache/v2"
|
||||
@@ -38,7 +36,9 @@ import (
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
ipfsethdb "github.com/cerc-io/ipfs-ethdb/v5"
|
||||
pgipfsethdb "github.com/cerc-io/ipfs-ethdb/v5/postgres/v1"
|
||||
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"
|
||||
nodeiter "github.com/ethereum/go-ethereum/trie/concurrent_iterator"
|
||||
"github.com/ethereum/go-ethereum/trie/concurrent_iterator/tracker"
|
||||
)
|
||||
@@ -203,10 +203,9 @@ func (v *Validator) iterate(it trie.NodeIterator, storage bool) error {
|
||||
}
|
||||
dataIt := dataTrie.NodeIterator(nil)
|
||||
if !bytes.Equal(account.CodeHash, emptyCodeHash) {
|
||||
addrHash := common.BytesToHash(it.LeafKey())
|
||||
_, err := v.stateDatabase.ContractCode(addrHash, common.BytesToHash(account.CodeHash))
|
||||
_, err := v.stateDatabase.ContractCode(common.BytesToHash(account.CodeHash))
|
||||
if err != nil {
|
||||
return fmt.Errorf("code %x: %w (path %x)", account.CodeHash, err, nodeiter.HexToKeyBytes(it.Path()))
|
||||
return fmt.Errorf("code hash %x: %w (path %x)", account.CodeHash, err, nodeiter.HexToKeyBytes(it.Path()))
|
||||
}
|
||||
}
|
||||
for dataIt.Next(true) {
|
||||
@@ -231,7 +230,7 @@ func iterateTracked(tree state.Trie, recoveryFile string, iterCount uint, fn fun
|
||||
}
|
||||
|
||||
// attempt to restore from recovery file if it exists
|
||||
iters, err := tracker.Restore(tree)
|
||||
iters, err := tracker.Restore(tree.NodeIterator)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -240,7 +239,7 @@ func iterateTracked(tree state.Trie, recoveryFile string, iterCount uint, fn fun
|
||||
}
|
||||
|
||||
if iters == nil { // nothing restored
|
||||
iters = nodeiter.SubtrieIterators(tree, iterCount)
|
||||
iters = nodeiter.SubtrieIterators(tree.NodeIterator, iterCount)
|
||||
for i, it := range iters {
|
||||
iters[i] = tracker.Tracked(it, nil)
|
||||
}
|
||||
|
||||
+18
-19
@@ -17,7 +17,6 @@
|
||||
package validator_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -29,7 +28,7 @@ import (
|
||||
cid "github.com/ipfs/go-cid/_rsrch/cidiface"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/multiformats/go-multihash"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
validator "github.com/cerc-io/eth-ipfs-state-validator/v5/pkg"
|
||||
@@ -203,7 +202,7 @@ var (
|
||||
|
||||
config = validator.Config{
|
||||
Hostname: "localhost",
|
||||
Name: "vulcanize_testing",
|
||||
Name: "cerc_testing",
|
||||
User: "vdbm",
|
||||
Password: "password",
|
||||
Port: 8077,
|
||||
@@ -234,44 +233,40 @@ var _ = Describe("PG-IPFS Validator", func() {
|
||||
It("Returns an error if the state root node is missing", func() {
|
||||
// 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
|
||||
loadTrie(append(missingRootStateNodes, mockCode), trieStorageNodes)
|
||||
loadTrie(missingRootStateNodes, trieStorageNodes, mockCode)
|
||||
err = v.ValidateTrie(stateRoot)
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err.Error()).To(ContainSubstring("missing trie node"))
|
||||
})
|
||||
It("Returns an error if the storage root node is missing", func() {
|
||||
loadTrie(append(trieStateNodes, mockCode), missingRootStorageNodes)
|
||||
loadTrie(trieStateNodes, missingRootStorageNodes, mockCode)
|
||||
err = v.ValidateTrie(stateRoot)
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err.Error()).To(ContainSubstring("missing trie node"))
|
||||
})
|
||||
It("Returns an error if the state trie is missing node(s)", func() {
|
||||
loadTrie(append(missingNodeStateNodes, mockCode), trieStorageNodes)
|
||||
loadTrie(missingNodeStateNodes, trieStorageNodes, mockCode)
|
||||
err = v.ValidateTrie(stateRoot)
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err.Error()).To(ContainSubstring("missing trie node"))
|
||||
pathSubStr := fmt.Sprintf("path %x", missingStateNodePath)
|
||||
Expect(err.Error()).To(ContainSubstring(pathSubStr))
|
||||
Expect(err.Error()).To(ContainSubstring("%x", missingStateNodePath))
|
||||
})
|
||||
It("Returns an error if the storage trie is missing node(s)", func() {
|
||||
loadTrie(append(trieStateNodes, mockCode), missingNodeStorageNodes)
|
||||
loadTrie(trieStateNodes, missingNodeStorageNodes, mockCode)
|
||||
err = v.ValidateTrie(stateRoot)
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err.Error()).To(ContainSubstring("missing trie node"))
|
||||
pathSubStr := fmt.Sprintf("path %x", missingStorageNodePath)
|
||||
Expect(err.Error()).To(ContainSubstring(pathSubStr))
|
||||
Expect(err.Error()).To(ContainSubstring("%x", missingStorageNodePath))
|
||||
})
|
||||
It("Returns an error if contract code is missing", func() {
|
||||
loadTrie(trieStateNodes, trieStorageNodes)
|
||||
err = v.ValidateTrie(stateRoot)
|
||||
Expect(err).To(HaveOccurred())
|
||||
codeSubStr := fmt.Sprintf("code %s: not found", codeHash.Hex()[2:])
|
||||
Expect(err.Error()).To(ContainSubstring(codeSubStr))
|
||||
pathSubStr := fmt.Sprintf("path %x", codePath)
|
||||
Expect(err.Error()).To(ContainSubstring(pathSubStr))
|
||||
Expect(err.Error()).To(ContainSubstring("%x", codeHash))
|
||||
Expect(err.Error()).To(ContainSubstring("%x", codePath))
|
||||
})
|
||||
It("Returns no error if the entire state (state trie and storage tries) can be validated", func() {
|
||||
loadTrie(append(trieStateNodes, mockCode), trieStorageNodes)
|
||||
loadTrie(trieStateNodes, trieStorageNodes, mockCode)
|
||||
err = v.ValidateTrie(stateRoot)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
@@ -326,15 +321,19 @@ var _ = Describe("PG-IPFS Validator", func() {
|
||||
})
|
||||
})
|
||||
|
||||
func loadTrie(stateNodes, storageNodes [][]byte) {
|
||||
func loadTrie(stateNodes, storageNodes [][]byte, contractCode ...[]byte) {
|
||||
tx, err := db.Beginx()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
for _, node := range stateNodes {
|
||||
_, err := PublishRaw(tx, cid.EthStateTrie, multihash.KECCAK_256, node, blockNumber)
|
||||
err := PublishRaw(tx, cid.EthStateTrie, multihash.KECCAK_256, node, blockNumber)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
for _, node := range storageNodes {
|
||||
_, err := PublishRaw(tx, cid.EthStorageTrie, multihash.KECCAK_256, node, blockNumber)
|
||||
err := 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())
|
||||
}
|
||||
err = tx.Commit()
|
||||
|
||||
Reference in New Issue
Block a user