ipfs blockservice based validator
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
// VulcanizeDB
|
||||
// Copyright © 2019 Vulcanize
|
||||
// Copyright © 2020 Vulcanize
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
|
||||
+29
@@ -17,9 +17,14 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ipfs/go-blockservice"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-ipfs-blockstore"
|
||||
"github.com/ipfs/go-ipfs-ds-help"
|
||||
"github.com/ipfs/go-ipfs/core"
|
||||
"github.com/ipfs/go-ipfs/repo/fsrepo"
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
@@ -49,3 +54,27 @@ func RawdataToCid(codec uint64, rawdata []byte, multiHash uint64) (cid.Cid, erro
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// InitIPFSBlockService is used to configure and return a BlockService using an ipfs repo path (e.g. ~/.ipfs)
|
||||
func InitIPFSBlockService(ipfsPath string) (blockservice.BlockService, error) {
|
||||
r, openErr := fsrepo.Open(ipfsPath)
|
||||
if openErr != nil {
|
||||
return nil, openErr
|
||||
}
|
||||
ctx := context.Background()
|
||||
cfg := &core.BuildCfg{
|
||||
Online: false,
|
||||
Repo: r,
|
||||
}
|
||||
ipfsNode, newNodeErr := core.NewNode(ctx, cfg)
|
||||
if newNodeErr != nil {
|
||||
return nil, newNodeErr
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
+26
-4
@@ -24,9 +24,11 @@ import (
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ipfs/go-blockservice"
|
||||
"github.com/jmoiron/sqlx"
|
||||
|
||||
pgipfsethdb "github.com/vulcanize/pg-ipfs-ethdb/postgres"
|
||||
"github.com/vulcanize/ipfs-ethdb"
|
||||
"github.com/vulcanize/ipfs-ethdb/postgres"
|
||||
)
|
||||
|
||||
// Validator is used for validating Ethereum state and storage tries on PG-IPFS
|
||||
@@ -36,12 +38,32 @@ type Validator struct {
|
||||
stateDatabase state.Database
|
||||
}
|
||||
|
||||
// NewPGIPFSValidator returns a new trie validator ontop of a connection pool for an IPFS backing Postgres database
|
||||
func NewPGIPFSValidator(db *sqlx.DB) *Validator {
|
||||
kvs := pgipfsethdb.NewKeyValueStore(db)
|
||||
database := pgipfsethdb.NewDatabase(db)
|
||||
return &Validator{
|
||||
kvs: kvs,
|
||||
trieDB: trie.NewDatabase(kvs),
|
||||
stateDatabase: state.NewDatabase(database),
|
||||
}
|
||||
}
|
||||
|
||||
// NewIPFSValidator returns a new trie validator ontop of an IPFS blockservice
|
||||
func NewIPFSValidator(bs blockservice.BlockService) *Validator {
|
||||
kvs := ipfsethdb.NewKeyValueStore(bs)
|
||||
database := ipfsethdb.NewDatabase(bs)
|
||||
return &Validator{
|
||||
kvs: kvs,
|
||||
trieDB: trie.NewDatabase(kvs),
|
||||
stateDatabase: state.NewDatabase(database),
|
||||
}
|
||||
}
|
||||
|
||||
// NewValidator returns a new trie validator
|
||||
// Validating the completeness of a modified merkle patricia tries requires traversing the entire trie and verifying that
|
||||
// every node is present, this is an expensive operation
|
||||
func NewValidator(db *sqlx.DB) *Validator {
|
||||
kvs := pgipfsethdb.NewKeyValueStore(db)
|
||||
database := pgipfsethdb.NewDatabase(db)
|
||||
func NewValidator(kvs ethdb.KeyValueStore, database ethdb.Database) *Validator {
|
||||
return &Validator{
|
||||
kvs: kvs,
|
||||
trieDB: trie.NewDatabase(kvs),
|
||||
|
||||
+15
-8
@@ -30,7 +30,7 @@ import (
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"github.com/vulcanize/eth-ipfs-state-validator/pkg"
|
||||
"github.com/vulcanize/pg-ipfs-ethdb/postgres"
|
||||
"github.com/vulcanize/ipfs-ethdb/postgres"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -192,18 +192,17 @@ var (
|
||||
err error
|
||||
)
|
||||
|
||||
var _ = Describe("Validator", func() {
|
||||
var _ = Describe("PG-IPFS Validator", func() {
|
||||
BeforeEach(func() {
|
||||
db, err = pgipfsethdb.TestDB()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
v = validator.NewValidator(db)
|
||||
v = validator.NewPGIPFSValidator(db)
|
||||
})
|
||||
AfterEach(func() {
|
||||
err = pgipfsethdb.ResetTestDB(db)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
Describe("ValidateTrie", func() {
|
||||
AfterEach(func() {
|
||||
err = validator.ResetTestDB(db)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
It("Returns an error the state root node is missing", func() {
|
||||
loadTrie(missingRootStateNodes, trieStorageNodes)
|
||||
err = v.ValidateTrie(stateRoot)
|
||||
@@ -236,6 +235,10 @@ var _ = Describe("Validator", func() {
|
||||
})
|
||||
|
||||
Describe("ValidateStateTrie", func() {
|
||||
AfterEach(func() {
|
||||
err = validator.ResetTestDB(db)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
It("Returns an error the state root node is missing", func() {
|
||||
loadTrie(missingRootStateNodes, nil)
|
||||
err = v.ValidateStateTrie(stateRoot)
|
||||
@@ -256,6 +259,10 @@ var _ = Describe("Validator", func() {
|
||||
})
|
||||
|
||||
Describe("ValidateStorageTrie", func() {
|
||||
AfterEach(func() {
|
||||
err = validator.ResetTestDB(db)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
It("Returns an error the storage root node is missing", func() {
|
||||
loadTrie(nil, missingRootStorageNodes)
|
||||
err = v.ValidateStorageTrie(contractAddr, storageRoot)
|
||||
|
||||
Reference in New Issue
Block a user