diff --git a/Makefile b/Makefile index bed4752d0..622a91ec2 100644 --- a/Makefile +++ b/Makefile @@ -81,13 +81,13 @@ else MD5SUM := md5sum endif -.PHONY: all premix persist debug dumper hunter deps github-ssh build-nim update status ntags ctags nimbus test clean mrproper fetch-dlls beacon_node validator_keygen clean_eth2_network_simulation_files eth2_network_simulation +.PHONY: all premix persist debug dumper hunter regress deps github-ssh build-nim update status ntags ctags nimbus test clean mrproper fetch-dlls beacon_node validator_keygen clean_eth2_network_simulation_files eth2_network_simulation # default target, because it's the first one that doesn't start with '.' -all: premix persist debug dumper hunter nimbus +all: premix persist debug dumper hunter regress nimbus # debugging tools -premix persist debug dumper hunter: | build deps +premix persist debug dumper hunter regress: | build deps $(ENV_SCRIPT) nim c $(NIM_PARAMS) -o:build/$@ premix/$@.nim && \ echo -e "\nThe binary is in './build/$@'.\n" @@ -137,7 +137,7 @@ test-reproducibility: # usual cleaning clean: - rm -rf build/{nimbus,premix,persist,debug,dumper,hunter,all_tests,beacon_node,validator_keygen,*.exe} vendor/go/bin \ + rm -rf build/{nimbus,premix,persist,debug,dumper,hunter,regress,all_tests,beacon_node,validator_keygen,*.exe} vendor/go/bin \ $(NIMBLE_DIR) $(NIM_BINARY) $(NIM_DIR)/nimcache nimcache # dangerous cleaning, because you may have not-yet-pushed branches and commits in those vendor repos you're about to delete diff --git a/nimbus.nimble b/nimbus.nimble index 0ef84be8b..0c2e9be4e 100644 --- a/nimbus.nimble +++ b/nimbus.nimble @@ -39,6 +39,7 @@ task test, "Run tests": "premix/debug", "premix/dumper", "premix/hunter", + "premix/regress", "tests/tracerTestGen", "tests/persistBlockTestGen", ]: diff --git a/premix/readme.md b/premix/readme.md index 001517eb6..743fef48c 100644 --- a/premix/readme.md +++ b/premix/readme.md @@ -140,3 +140,14 @@ have this implemented). `maxBlocks` is the number of problematic blocks you want to capture before stopping the hunt. +### Regress + +Regress is an offline block validation tool. It will not download block +information from anywhere like Persist tool. Regress will validate your +already persisted block in database. It will try to find any regression +introduced either by bugfixing or refactoring. + +```bash +# usage: +./build/regress [--dataDir:your_db_path] --head:blockNumber +``` diff --git a/premix/regress.nim b/premix/regress.nim new file mode 100644 index 000000000..578659675 --- /dev/null +++ b/premix/regress.nim @@ -0,0 +1,80 @@ +import + eth/[common, rlp], stint, byteutils, + nimcrypto, chronicles, configuration, + eth/trie/[hexary, db, trie_defs] + +import + ../nimbus/db/[storage_types, db_chain, select_backend], + ../nimbus/[utils, vm_state, errors], + ../nimbus/p2p/executor + +const + numBlocks = 256 + +proc validateBlock(chainDB: BaseChainDB, blockNumber: BlockNumber): BlockNumber = + var + parentNumber = blockNumber - 1 + parent = chainDB.getBlockHeader(parentNumber) + headers = newSeq[BlockHeader](numBlocks) + bodies = newSeq[BlockBody](numBlocks) + + for i in 0 ..< numBlocks: + headers[i] = chainDB.getBlockHeader(blockNumber + i.u256) + bodies[i] = chainDB.getBlockBody(headers[i].blockHash) + + let transaction = chainDB.db.beginTransaction() + defer: transaction.dispose() + + for i in 0 ..< numBlocks: + stdout.write blockNumber + i.u256 + stdout.write "\r" + + let + vmState = newBaseVMState(parent.stateRoot, headers[i], chainDB) + validationResult = processBlock(chainDB, parent, headers[i], bodies[i], vmState) + + if validationResult != ValidationResult.OK: + error "block validation error", validationResult, blockNumber = blockNumber + i.u256 + + parent = headers[i] + + transaction.rollback() + result = blockNumber + numBlocks.u256 + +proc main() = + let + conf = getConfiguration() + db = newChainDb(conf.dataDir) + trieDB = trieDB db + chainDB = newBaseChainDB(trieDB, false) + + # move head to block number ... + if conf.head == 0.u256: + raise newException(ValueError, "please set block number with --head: blockNumber") + + var counter = 0 + var blockNumber = conf.head + + while true: + blockNumber = chainDB.validateBlock(blockNumber) + + inc counter + if conf.maxBlocks != 0 and counter >= conf.maxBlocks: + break + +when isMainModule: + var message: string + + ## Processing command line arguments + if processArguments(message) != Success: + echo message + quit(QuitFailure) + else: + if len(message) > 0: + echo message + quit(QuitSuccess) + + try: + main() + except: + echo getCurrentExceptionMsg()