diff --git a/pkg/postgres.go b/pkg/postgres.go new file mode 100644 index 0000000..37f0ceb --- /dev/null +++ b/pkg/postgres.go @@ -0,0 +1,32 @@ +// VulcanizeDB +// 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 +// 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 . + +package validator + +import ( + "github.com/jmoiron/sqlx" + _ "github.com/lib/pq" //postgres driver + + "github.com/vulcanize/ipfs-blockchain-watcher/pkg/config" +) + +// NewDB returns a new sqlx.DB from env variables +func NewDB() (*sqlx.DB, error) { + c := config.Database{} + c.Init() + connectStr := config.DbConnectionString(c) + return sqlx.Connect("postgres", connectStr) +} diff --git a/pkg/validator.go b/pkg/validator.go new file mode 100644 index 0000000..ce8b445 --- /dev/null +++ b/pkg/validator.go @@ -0,0 +1,68 @@ +// VulcanizeDB +// 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 +// 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 . + +package validator + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/state/snapshot" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/trie" + "github.com/jmoiron/sqlx" + + "github.com/vulcanize/pg-ipfs-ethdb" +) + +// Validator is used for validating Ethereum state and storage tries on PG-IPFS +type Validator struct { + kvs ethdb.KeyValueStore + trieDB *trie.Database + stateDatabase state.Database +} + +// NewValidator returns a new trie validator +func NewValidator(db *sqlx.DB) *Validator { + kvs := ipfsethdb.NewKeyValueStore(db) + database := ipfsethdb.NewDatabase(db) + return &Validator{ + kvs: kvs, + trieDB: trie.NewDatabase(kvs), + stateDatabase: state.NewDatabase(database), + } +} + +// ValidateTrie returns whether or not the trie for the provided root hash is valid and complete +// Validating the completeness of a modified merkle patricia trie requires traversing the entire trie and verifying that +// every node is present, this is an expensive operation +func (v *Validator) ValidateTrie(root common.Hash) (bool, error) { + // Generate the state.NodeIterator for this root + snapshotTree := snapshot.New(v.kvs, v.trieDB, 0, root, false) + stateDB, err := state.New(common.Hash{}, v.stateDatabase, snapshotTree) + if err != nil { + return false, err + } + it := state.NewNodeIterator(stateDB) + for it.Next() { + // iterate through entire trie + // it.Next() will return false when we have either completed iteration of the entire trie or have ran into an error + // if we are able to iterate through the entire trie without error then the trie is complete + } + if it.Error != nil { + return false, it.Error + } + return true, nil +}