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
+}