2020-06-25 20:12:02 +00:00
// Copyright © 2020 Vulcanize, Inc
//
// 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 <http://www.gnu.org/licenses/>.
package cmd
import (
2020-06-26 18:11:30 +00:00
"strings"
2020-06-25 20:12:02 +00:00
"github.com/ethereum/go-ethereum/common"
_ "github.com/lib/pq" //postgres driver
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
2020-07-13 04:30:28 +00:00
"github.com/spf13/viper"
2020-06-25 20:12:02 +00:00
2021-08-25 08:20:31 +00:00
validator "github.com/vulcanize/eth-ipfs-state-validator/pkg"
2020-06-25 20:12:02 +00:00
)
// validateTrieCmd represents the validateTrie command
var validateTrieCmd = & cobra . Command {
Use : "validateTrie" ,
Short : "Validate completeness of state data on IPFS" ,
2020-06-26 18:11:30 +00:00
Long : ` This command is used to validate the completeness of state data corresponding specific to a specific root
2020-07-13 00:57:47 +00:00
If an ipfs - path is provided it will use a blockservice , otherwise it expects Postgres db configuration in a linked config file .
2021-08-25 08:20:31 +00:00
It can operate at three levels :
2020-06-26 18:11:30 +00:00
"full" validates completeness of the entire state corresponding to a provided state root , including both state and storage tries
. / eth - ipfs - state - validator validateTrie -- config = { path to db config } -- type = full -- state - root = { state root hex string }
"state" validates completeness of the state trie corresponding to a provided state root , excluding the storage tries
. / eth - ipfs - state - validator validateTrie -- config = { path to db config } -- type = state -- state - root = { state root hex string }
"storage" validates completeness of only the storage trie corresponding to a provided storage root and contract address
. / eth - ipfs - state - validator validateTrie -- config = { path to db config } -- type = storage -- storage - root = { state root hex string } -- address = { contract address hex string }
" ` ,
2020-06-25 20:12:02 +00:00
Run : func ( cmd * cobra . Command , args [ ] string ) {
subCommand = cmd . CalledAs ( )
logWithCommand = * logrus . WithField ( "SubCommand" , subCommand )
validateTrie ( )
} ,
}
func validateTrie ( ) {
2020-07-13 00:57:47 +00:00
v , err := newValidator ( )
2020-06-25 20:12:02 +00:00
if err != nil {
logWithCommand . Fatal ( err )
}
2020-07-13 04:30:28 +00:00
stateRootStr := viper . GetString ( "validator.stateRoot" )
storageRootStr := viper . GetString ( "validator.storageRoot" )
contractAddrStr := viper . GetString ( "validator.address" )
switch strings . ToLower ( viper . GetString ( "validator.type" ) ) {
2020-06-26 18:11:30 +00:00
case "f" , "full" :
if stateRootStr == "" {
logWithCommand . Fatal ( "must provide a state root for full state validation" )
}
stateRoot := common . HexToHash ( stateRootStr )
if err = v . ValidateTrie ( stateRoot ) ; err != nil {
logWithCommand . Fatalf ( "State for root %s is not complete\r\nerr: %v" , stateRoot . String ( ) , err )
}
logWithCommand . Infof ( "State for root %s is complete" , stateRoot . String ( ) )
case "state" :
if stateRootStr == "" {
logWithCommand . Fatal ( "must provide a state root for state trie validation" )
}
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" :
if storageRootStr == "" {
logWithCommand . Fatal ( "must provide a storage root for storage trie validation" )
}
if contractAddrStr == "" {
logWithCommand . Fatal ( "must provide a contract address for storage trie validation" )
}
storageRoot := common . HexToHash ( storageRootStr )
addr := common . HexToAddress ( contractAddrStr )
if err = v . ValidateStorageTrie ( addr , storageRoot ) ; err != nil {
logWithCommand . Fatalf ( "Storage trie for contract %s and root %s not complete\r\nerr: %v" , addr . String ( ) , storageRoot . String ( ) , err )
}
logWithCommand . Infof ( "Storage trie for contract %s and root %s is complete" , addr . String ( ) , storageRoot . String ( ) )
2020-06-25 20:12:02 +00:00
}
2021-08-25 08:20:31 +00:00
stats := v . GetCacheStats ( )
logWithCommand . Debugf ( "groupcache stats %+v" , stats )
2020-06-25 20:12:02 +00:00
}
2020-07-13 00:57:47 +00:00
func newValidator ( ) ( * validator . Validator , error ) {
2020-07-13 04:30:28 +00:00
ipfsPath := viper . GetString ( "ipfs.path" )
2020-07-13 00:57:47 +00:00
if ipfsPath == "" {
db , err := validator . NewDB ( )
if err != nil {
logWithCommand . Fatal ( err )
}
return validator . NewPGIPFSValidator ( db ) , nil
}
bs , err := validator . InitIPFSBlockService ( ipfsPath )
if err != nil {
return nil , err
}
return validator . NewIPFSValidator ( bs ) , nil
}
2020-06-25 20:12:02 +00:00
func init ( ) {
rootCmd . AddCommand ( validateTrieCmd )
2020-07-13 04:30:28 +00:00
validateTrieCmd . PersistentFlags ( ) . String ( "state-root" , "" , "Root of the state trie we wish to validate; for full or state validation" )
validateTrieCmd . PersistentFlags ( ) . String ( "type" , "" , "Type of validations: full, state, storage" )
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 ( "ipfs-path" , "" , "Path to IPFS repository; if provided operations move through the IPFS repo otherwise Postgres connection params are expected in the provided config" )
viper . BindPFlag ( "validator.stateRoot" , validateTrieCmd . PersistentFlags ( ) . Lookup ( "state-root" ) )
viper . BindPFlag ( "validator.type" , validateTrieCmd . PersistentFlags ( ) . Lookup ( "type" ) )
viper . BindPFlag ( "validator.storageRoot" , validateTrieCmd . PersistentFlags ( ) . Lookup ( "storage-root" ) )
viper . BindPFlag ( "validator.address" , validateTrieCmd . PersistentFlags ( ) . Lookup ( "address" ) )
viper . BindPFlag ( "ipfs.path" , validateTrieCmd . PersistentFlags ( ) . Lookup ( "ipfs-path" ) )
2020-06-25 20:12:02 +00:00
}