From f89ad552ca8c10bc11ce3ffbce7303bcd641982f Mon Sep 17 00:00:00 2001 From: Malta Micael Date: Thu, 10 Jun 2021 21:50:10 -0400 Subject: [PATCH] Merge AuxPoW support from Namecore Changes are as below: * Wrap CBlockHeader::nVersion into a new class (CBlockVersion). This allows to take care of interpreting the field into a base version, auxpow flag and the chain ID. * Update getauxblock.py for new 'generate' RPC call. * Add 'auxpow' to block JSON. * Accept auxpow as PoW verification. * Add unit tests for auxpow verification. * Add check for memory-layout of CBlockVersion. * Weaken auxpow chain ID checks for the testnet. * Allow Params() to overrule when to check the auxpow chain ID and for legacy blocks. Use this to disable the checks on testnet. * Split the block header part that is used by auxpow and the "real" block header (that uses auxpow) to resolve the cyclic dependency between the two. * Differentiate between uint256 and arith_uint256. * Add missing lock in auxpow_tests. * Fix REST header check for auxpow headers. * Those can be longer, thus take that into account. Also perform the check actually on an auxpow header. * Correctly set the coinbase for getauxblock results. * Call IncrementExtraNonce in getauxblock so that the coinbase is actually initialised with the stuff it should be. (BIP30 block height and COINBASE_FLAGS.) * Implement getauxblock plus regression test. * Turn auxpow test into FIXTURE test. * This allows using of the Params() calls. * Move CMerkleTx code to auxpow.cpp. * Otherwise we get linker errors when building without wallet. * Fix rebase with BIP66. * Update the code to handle BIP66's nVersion=3. * Enforce that auxpow parent blocks have no auxpow block version. * This is for compatibility with namecoind. See also https://github.com/namecoin/namecoin/pull/199. * Move auxpow-related parameters to Consensus::Params. --- .travis.yml | 4 +- src/Makefile.am | 5 + src/chain.cpp | 2 +- src/chain.h | 4 +- src/chainparams.h | 3 + src/init.cpp | 3 +- src/miner.h | 3 + src/pow.cpp | 40 ++ src/pow.h | 8 + src/protocol.cpp | 1 - src/qt/test/wallettests.cpp | 2 +- src/rpc/blockchain.cpp | 41 ++ src/rpc/mining.cpp | 110 +++- src/rpc/rawtransaction.cpp | 3 +- src/rpc/rawtransaction.h | 15 + src/test/auxpow_tests.cpp | 64 +-- src/test/fuzz/chain.cpp | 3 +- src/validation.cpp | 4 +- src/wallet/context.h | 6 +- src/wallet/rpcwallet.cpp | 205 ++++++++ test/functional/auxpow_invalidpow.py | 100 ++++ test/functional/auxpow_mining.py | 216 ++++++++ test/functional/auxpow_zerohash.py | 134 +++++ test/functional/data/rpc_getblockstats.json | 492 +++++++++--------- test/functional/interface_rest.py | 14 +- test/functional/rpc_dumptxoutset.py | 4 +- test/functional/test_framework/auxpow.py | 114 ++++ .../test_framework/auxpow_testing.py | 82 +++ test/functional/test_runner.py | 7 + test/lint/lint-circular-dependencies.sh | 10 + 30 files changed, 1395 insertions(+), 304 deletions(-) create mode 100644 src/rpc/rawtransaction.h create mode 100755 test/functional/auxpow_invalidpow.py create mode 100755 test/functional/auxpow_mining.py create mode 100755 test/functional/auxpow_zerohash.py create mode 100644 test/functional/test_framework/auxpow.py create mode 100644 test/functional/test_framework/auxpow_testing.py diff --git a/.travis.yml b/.travis.yml index 0b197be7598..6763029af76 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,10 +39,10 @@ install: before_script: # Temporary workaround for https://github.com/bitcoin/bitcoin/issues/16368 - for i in {1..4}; do echo "$(sleep 500)" ; done & - - set -o errexit; source ./ci/test/05_before_script.sh &> "/dev/null" + - set -o errexit; source ./ci/test/05_before_script.sh script: - export CONTINUE=1 - - if [ $SECONDS -gt 1200 ]; then export CONTINUE=0; fi # Likely the depends build took very long + - if [ $SECONDS -gt 1800 ]; then export CONTINUE=0; fi # Likely the depends build took very long - if [ $TRAVIS_REPO_SLUG = "bitcoin/bitcoin" ]; then export CONTINUE=1; fi # continue on repos with extended build time (90 minutes) - if [ $CONTINUE = "1" ]; then set -o errexit; source ./ci/test/06_script_a.sh; else set +o errexit; echo "$CACHE_ERR_MSG"; false; fi - if [[ $SECONDS -gt 50*60-$EXPECTED_TESTS_DURATION_IN_SECONDS ]]; then export CONTINUE=0; fi diff --git a/src/Makefile.am b/src/Makefile.am index df7cee91c2b..c38ef0e08ae 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -186,10 +186,12 @@ BITCOIN_CORE_H = \ random.h \ randomenv.h \ reverse_iterator.h \ + rpc/auxpow_miner.h \ rpc/blockchain.h \ rpc/client.h \ rpc/mining.h \ rpc/protocol.h \ + rpc/rawtransaction.h \ rpc/rawtransaction_util.h \ rpc/register.h \ rpc/request.h \ @@ -318,6 +320,7 @@ libbitcoin_server_a_SOURCES = \ policy/settings.cpp \ pow.cpp \ rest.cpp \ + rpc/auxpow_miner.cpp \ rpc/blockchain.cpp \ rpc/mining.cpp \ rpc/misc.cpp \ @@ -590,8 +593,10 @@ if TARGET_WINDOWS dogecoin_daemon_sources += bitcoind-res.rc endif +# FIXME: Remove SERVER once we have cleaned up getauxblock. dogecoin_bin_ldadd = \ $(LIBBITCOIN_WALLET) \ + $(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_UTIL) \ $(LIBUNIVALUE) \ diff --git a/src/chain.cpp b/src/chain.cpp index 7a4ce6b0959..f88b79148d4 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -11,7 +11,7 @@ bool ReadBlockHeaderFromDisk(CBlockHeader& block, const CBlockIndex* pindex, con /* Moved here from the header, because we need auxpow and the logic becomes more involved. */ -CBlockHeader CBlockIndex::GetBlockHeader(const Consensus::Params& consensusParams, bool fCheckPOW) const +CBlockHeader CBlockIndex::GetBlockHeader(const Consensus::Params& consensusParams, const bool fCheckPOW) const { CBlockHeader block; diff --git a/src/chain.h b/src/chain.h index 663a8b40824..492ce0dce2c 100644 --- a/src/chain.h +++ b/src/chain.h @@ -191,7 +191,7 @@ class CBlockIndex { } - explicit CBlockIndex(const CBlockHeader& block) + explicit CBlockIndex(const CPureBlockHeader& block) : nVersion{block.nVersion}, hashMerkleRoot{block.hashMerkleRoot}, nTime{block.nTime}, @@ -218,7 +218,7 @@ class CBlockIndex return ret; } - CBlockHeader GetBlockHeader(const Consensus::Params& consensusParams, bool fCheckPOW = true) const; + CBlockHeader GetBlockHeader(const Consensus::Params& consensusParams, const bool fCheckPOW = true) const; uint256 GetBlockHash() const { diff --git a/src/chainparams.h b/src/chainparams.h index d8b25c72204..7f28a6912ca 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -91,6 +91,9 @@ class CChainParams const std::vector& FixedSeeds() const { return vFixedSeeds; } const CCheckpointData& Checkpoints() const { return checkpointData; } const ChainTxData& TxData() const { return chainTxData; } + + void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout); + protected: CChainParams() {} diff --git a/src/init.cpp b/src/init.cpp index 0838472dc78..31f5ae7d422 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -600,7 +601,7 @@ void SetupServerArgs(NodeContext& node) std::string LicenseInfo() { - const std::string URL_SOURCE_CODE = ""; + const std::string URL_SOURCE_CODE = ""; return CopyrightHolders(strprintf(_("Copyright (C) %i-%i").translated, 2009, COPYRIGHT_YEAR) + " ") + "\n" + "\n" + diff --git a/src/miner.h b/src/miner.h index bb7a30b1840..ae123812fd2 100644 --- a/src/miner.h +++ b/src/miner.h @@ -132,10 +132,12 @@ class BlockAssembler // Configuration parameters for the block size bool fIncludeWitness; unsigned int nBlockMaxWeight; + bool fNeedSizeAccounting; CFeeRate blockMinFeeRate; // Information on the current status of the block uint64_t nBlockWeight; + uint64_t nBlockSize; uint64_t nBlockTx; uint64_t nBlockSigOpsCost; CAmount nFees; @@ -200,6 +202,7 @@ class BlockAssembler /** Modify the extranonce in a block */ void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce); int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev); +bool ProcessBlockFound(const CBlock* pblock, const CChainParams& chainParams); /** Update an old GenerateCoinbaseCommitment from CreateNewBlock after the block txs have changed */ void RegenerateCommitments(CBlock& block); diff --git a/src/pow.cpp b/src/pow.cpp index de8ba9be2fd..442b49942e8 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -5,10 +5,12 @@ #include +#include #include #include #include #include +#include #include unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) @@ -114,3 +116,41 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& return true; } + +bool CheckAuxPowProofOfWork(const CBlockHeader& block, const Consensus::Params& params) +{ + /* Except for legacy blocks with full version 1, ensure that + the chain ID is correct. Legacy blocks are not allowed since + the merge-mining start, which is checked in AcceptBlockHeader + where the height is known. */ + if (!block.IsLegacy() && params.fStrictChainId + && block.GetChainId() != params.nAuxpowChainId) + return error("%s : block does not have our chain ID" + " (got %d, expected %d, full nVersion %d)", + __func__, block.GetChainId(), + params.nAuxpowChainId, block.nVersion); + + /* If there is no auxpow, just check the block hash. */ + if (!block.auxpow) { + if (block.IsAuxpow()) + return error("%s : no auxpow on block with auxpow version", + __func__); + + if (!CheckProofOfWork(block.GetPoWHash(), block.nBits, params)) + return error("%s : non-AUX proof of work failed", __func__); + + return true; + } + + /* We have auxpow. Check it. */ + + if (!block.IsAuxpow()) + return error("%s : auxpow on block with non-auxpow version", __func__); + + if (!block.auxpow->check(block.GetHash(), block.GetChainId(), params)) + return error("%s : AUX POW is not valid", __func__); + if (!CheckProofOfWork(block.auxpow->getParentBlockPoWHash(), block.nBits, params)) + return error("%s : AUX proof of work failed", __func__); + + return true; +} diff --git a/src/pow.h b/src/pow.h index 1d802cd01e4..980f2bc46a2 100644 --- a/src/pow.h +++ b/src/pow.h @@ -20,4 +20,12 @@ unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nF /** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */ bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&); +/** + * Check proof-of-work of a block header, taking auxpow into account. + * @param block The block header. + * @param params Consensus parameters. + * @return True iff the PoW is correct. + */ +bool CheckAuxPowProofOfWork(const CBlockHeader& block, const Consensus::Params& params); + #endif // BITCOIN_POW_H diff --git a/src/protocol.cpp b/src/protocol.cpp index dc8f795a0cc..55261984c6d 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -134,7 +134,6 @@ bool CMessageHeader::IsCommandValid() const return true; } - ServiceFlags GetDesirableServiceFlags(ServiceFlags services) { if ((services & NODE_NETWORK_LIMITED) && g_initial_block_download_completed) { return ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS); diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index 9fcfb081ce4..1963639ce51 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -133,7 +133,7 @@ void BumpFee(TransactionView& view, const uint256& txid, bool expectDisabled, st // QT_QPA_PLATFORM=cocoa src/qt/test/test_bitcoin-qt # macOS void TestGUI(interfaces::Node& node) { - // Set up wallet and chain with 105 blocks (5 mature blocks for spending). + // Set up wallet and chain with 245 blocks (5 mature blocks for spending). TestChain240Setup test; for (int i = 0; i < 5; ++i) { test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey())); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 986898196b4..72e7e09749a 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include