From 0d851b3b2814be8958701a9386cd96e130a52544 Mon Sep 17 00:00:00 2001 From: Karl-Johan Alm Date: Tue, 24 Jul 2018 17:11:13 +0900 Subject: [PATCH] Signet implementation test/functional/data/rpc_getblockstats.json needs to be touched because: Signet implementation changes the genesis block for custom chains --- contrib/example.conf | 13 ++ contrib/signet/issuer/issuer.sh | 75 +++++++ src/chain.h | 10 + src/chainparams.cpp | 26 ++- src/chainparamsbase.cpp | 2 + src/consensus/params.h | 4 + src/miner.cpp | 3 + src/policy/policy.cpp | 1 + src/policy/policy.h | 2 + src/pow.cpp | 14 +- src/pow.h | 2 +- src/primitives/block.cpp | 4 + src/primitives/block.h | 26 +++ src/rpc/blockchain.cpp | 27 ++- src/rpc/client.cpp | 1 + src/rpc/mining.cpp | 8 +- src/script/interpreter.cpp | 16 ++ src/script/interpreter.h | 11 + src/script/sign.cpp | 9 + src/script/sign.h | 10 + src/txdb.cpp | 5 +- src/wallet/rpcwallet.cpp | 191 ++++++++++++++++ test/functional/data/rpc_getblockstats.json | 228 ++++++++++---------- test/functional/test_framework/mininode.py | 1 + 24 files changed, 556 insertions(+), 133 deletions(-) create mode 100644 contrib/example.conf create mode 100755 contrib/signet/issuer/issuer.sh diff --git a/contrib/example.conf b/contrib/example.conf new file mode 100644 index 0000000000..1488d529ea --- /dev/null +++ b/contrib/example.conf @@ -0,0 +1,13 @@ + +[signet] +signet_blockscript=512103e464a9f3070da4d3e0b34ce971ff36f3e07c47a8f4beadf32e8ea7e2afa8a82451ae +signet_siglen=77 +# DG seed node +seednode=178.128.221.177 +bech32_hrp=sb +pchmessagestart=F0C7706A +pubkeyprefix=125 +scriptprefix=87 +secretprefix=217 +extpubkeyprefix=043587CF +extprvkeyprefix=04358394 diff --git a/contrib/signet/issuer/issuer.sh b/contrib/signet/issuer/issuer.sh new file mode 100755 index 0000000000..f21a9153d7 --- /dev/null +++ b/contrib/signet/issuer/issuer.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash +# Copyright (c) 2018 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +export LC_ALL=C + +# +# Issue blocks using a local node at a given interval. +# + +if [ $# -lt 3 ]; then + echo "syntax: $0 []" ; exit 1 +fi + +function log() +{ + echo "- $(date +%H:%M:%S): $*" +} + +min_time=$1 +shift +max_time=$1 +shift +bcli=$1 +shift + +# https://stackoverflow.com/questions/806906/how-do-i-test-if-a-variable-is-a-number-in-bash +re='^[0-9]+$' +if ! [[ $min_time =~ $re ]] ; then + echo "error: min_time $min_time is not a number" ; exit 1 +fi +if ! [[ $max_time =~ $re ]] ; then + echo "error: max_time $max_time is not a number" ; exit 1 +fi + +let randinterval=max_time-min_time +if [ $randinterval -lt 1 ]; then + echo "error: interval min..max must be positive and greater than 0" ; exit 1 +fi + +if ! [ -e "$bcli" ]; then + which "$bcli" &> /dev/null + if [ $? -ne 0 ]; then + echo "error: unable to find bitcoin binary: $bcli" ; exit 1 + fi +fi + +echo "- checking node status" +conns=$($bcli "$@" getconnectioncount) + +if [ $? -ne 0 ]; then + echo "node error" ; exit 1 +fi + +if [ $conns -lt 1 ]; then + echo "warning: node is not connected to any other node" +fi + +log "node OK with $conns connection(s)" +log "mining in random intervals between $min_time .. $max_time seconds" +log "hit ^C to stop" + +while true; do + let rv=$RANDOM%$randinterval + echo -n -e "- $(date +%H:%M:%S): next block in $rv seconds..." + sleep $rv + echo -n -e " [submit]" + blockhash=$($bcli "$@" getnewblockhex true) + if [ $? -ne 0 ]; then + echo "node error; aborting" ; exit 1 + fi + echo "" + log "broadcasting block $($bcli "$@" getblockcount) $blockhash to $($bcli "$@" getconnectioncount) peer(s)" +done diff --git a/src/chain.h b/src/chain.h index 01011d54f1..5ebac95290 100644 --- a/src/chain.h +++ b/src/chain.h @@ -405,6 +405,16 @@ class CDiskBlockIndex : public CBlockIndex READWRITE(nTime); READWRITE(nBits); READWRITE(nNonce); + if (g_solution_blocks && !(s.GetType() & SER_GETHASH)) { + uint256 hash = GetBlockHash(); + READWRITE(g_blockheader_payload_map[hash]); + size_t len = GetSizeOfCompactSize(g_blockheader_payload_map[hash].size()) + g_blockheader_payload_map[hash].size(); + while (len < g_solution_block_len) { + uint8_t padding = 0; + READWRITE(padding); + len++; + } + } } uint256 GetBlockHash() const diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 2c08370767..60aa585cf4 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -17,13 +17,15 @@ #include #include -static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) +#include + +static CBlock CreateGenesisBlock(const CScript& coinbase_sig, const CScript& genesisOutputScript, uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) { CMutableTransaction txNew; txNew.nVersion = 1; txNew.vin.resize(1); txNew.vout.resize(1); - txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << std::vector((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp)); + txNew.vin[0].scriptSig = coinbase_sig; txNew.vout[0].nValue = genesisReward; txNew.vout[0].scriptPubKey = genesisOutputScript; @@ -38,6 +40,12 @@ static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesi return genesis; } +static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) +{ + CScript coinbase_sig = CScript() << 486604799 << CScriptNum(4) << std::vector((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp)); + return CreateGenesisBlock(coinbase_sig, genesisOutputScript, nTime, nNonce, nBits, nVersion, genesisReward); +} + /** * Build the genesis block. Note that the output of its generation * transaction cannot be spent since it did not originally exist in the @@ -421,6 +429,10 @@ class CCustomParams : public CRegTestParams { consensus.nMinimumChainWork = uint256S(args.GetArg("-con_nminimumchainwork", "0x0")); consensus.defaultAssumeValid = uint256S(args.GetArg("-con_defaultassumevalid", "0x00")); + consensus.blockscript = ParseHex(args.GetArg("-signet_blockscript", "")); + g_solution_blocks = !consensus.blockscript.empty(); + g_solution_block_len = consensus.siglen = args.GetArg("-signet_siglen", 77); + nPruneAfterHeight = args.GetArg("-npruneafterheight", nPruneAfterHeight); fDefaultConsistencyChecks = args.GetBoolArg("-fdefaultconsistencychecks", fDefaultConsistencyChecks); fMineBlocksOnDemand = args.GetBoolArg("-fmineblocksondemand", fMineBlocksOnDemand); @@ -464,7 +476,15 @@ class CCustomParams : public CRegTestParams { { strNetworkID = chain; UpdateFromArgs(args); - genesis = CreateGenesisBlock(strNetworkID.c_str(), CScript(OP_TRUE), 1296688602, 2, 0x207fffff, 1, 50 * COIN); + CHashWriter h(SER_DISK, 0); + h << strNetworkID; + if (g_solution_blocks) { + h << consensus.blockscript << consensus.siglen; + } + uint256 hash = h.GetHash(); + CScript coinbase_sig = CScript() << std::vector(hash.begin(), hash.end()); + CScript genesis_out = CScript() << OP_RETURN; + genesis = CreateGenesisBlock(coinbase_sig, genesis_out, 1296688602, 2, 0x207fffff, 1, 50 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); } }; diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index 1a4b53a352..3715e9b863 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -23,6 +23,8 @@ void SetupChainParamsBaseOptions() gArgs.AddArg("-testnet", "Use the test chain", false, OptionsCategory::CHAINPARAMS); gArgs.AddArg("-vbparams=deployment:start:end", "Use given start/end times for specified version bits deployment (regtest or custom only)", true, OptionsCategory::CHAINPARAMS); gArgs.AddArg("-seednode=", "Use specified node as seed node. This option can be specified multiple times to connect to multiple nodes. (custom only)", true, OptionsCategory::CHAINPARAMS); + gArgs.AddArg("-signet_blockscript", "Blocks must satisfy the given script to be considered valid instead of using pow. If empty, and by default, it is ignored. (custom only)", true, OptionsCategory::CHAINPARAMS); + gArgs.AddArg("-signet_siglen", "The length of the signature must be exactly this long (padded to this length, if shorter). All block headers in this network are of length 80 + this value (custom only)", true, OptionsCategory::CHAINPARAMS); } static std::unique_ptr globalChainBaseParams; diff --git a/src/consensus/params.h b/src/consensus/params.h index 6c3a201f4f..642cb2bbac 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -75,7 +75,11 @@ struct Params { int64_t DifficultyAdjustmentInterval() const { return nPowTargetTimespan / nPowTargetSpacing; } uint256 nMinimumChainWork; uint256 defaultAssumeValid; + + std::vector blockscript; + uint32_t siglen; }; + } // namespace Consensus #endif // BITCOIN_CONSENSUS_PARAMS_H diff --git a/src/miner.cpp b/src/miner.cpp index 6d35f9ac37..2d56f4a441 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -55,6 +55,9 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam BlockAssembler::Options::Options() { blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE); nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT; + + // Make room for the signature in the block header, if this is a signet block + if (g_solution_blocks) nBlockMaxWeight -= g_solution_block_len; } BlockAssembler::BlockAssembler(const CChainParams& params, const Options& options) : chainparams(params) diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index b8f7963a0c..623e6d0a5c 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -14,6 +14,7 @@ #include #include +unsigned int GetStandardScriptVerifyFlags() { return STANDARD_SCRIPT_VERIFY_FLAGS; } CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn) { diff --git a/src/policy/policy.h b/src/policy/policy.h index 3d47ac1267..28e9eb1877 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -68,6 +68,8 @@ static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VE SCRIPT_VERIFY_WITNESS_PUBKEYTYPE | SCRIPT_VERIFY_CONST_SCRIPTCODE; +unsigned int GetStandardScriptVerifyFlags(); + /** For convenience, standard but not mandatory verify flags. */ static constexpr unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS; diff --git a/src/pow.cpp b/src/pow.cpp index 1414d37564..ef7dfba9e0 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -9,6 +9,9 @@ #include #include #include +#include