Merge pull request #55 from apoelstra/scriptdest

Add commandline flag to set genesis block script destination
This commit is contained in:
Jorge Timón 2015-11-22 11:15:17 +01:00
commit 2f7f3bfb00
9 changed files with 159 additions and 38 deletions

View file

@ -38,6 +38,7 @@ BITCOIN_TESTS =\
test/compress_tests.cpp \
test/crypto_tests.cpp \
test/DoS_tests.cpp \
test/genesis_tests.cpp \
test/getarg_tests.cpp \
test/hash_tests.cpp \
test/key_tests.cpp \

View file

@ -80,7 +80,7 @@ static const Checkpoints::CCheckpointData dataRegtest = {
class CMainParams : public CChainParams {
public:
CMainParams() {
CMainParams(CScript scriptDestination) {
networkID = CBaseChainParams::MAIN;
strNetworkID = "main";
/**
@ -127,7 +127,9 @@ public:
genesis.hashMerkleRoot = genesis.BuildMerkleTree();
genesis.nVersion = 1;
genesis.nTime = 1231006505;
CScript scriptDestination(CScript() << OP_5 << ParseHex("027d5d62861df77fc9a37dbe901a579d686d1423be5f56d6fc50bb9de3480871d1") << ParseHex("03b41ea6ba73b94c901fdd43e782aaf70016cc124b72a086e77f6e9f4f942ca9bb") << ParseHex("02be643c3350bade7c96f6f28d1750af2ef507bc1f08dd38f82749214ab90d9037") << ParseHex("021df31471281d4478df85bfce08a10aab82601dca949a79950f8ddf7002bd915a") << ParseHex("0320ea4fcf77b63e89094e681a5bd50355900bf961c10c9c82876cb3238979c0ed") << ParseHex("021c4c92c8380659eb567b497b936b274424662909e1ffebc603672ed8433f4aa1") << ParseHex("027841250cfadc06c603da8bc58f6cd91e62f369826c8718eb6bd114601dd0c5ac") << OP_7 << OP_CHECKMULTISIG);
if (scriptDestination.empty()) {
scriptDestination = CScript() << OP_5 << ParseHex("027d5d62861df77fc9a37dbe901a579d686d1423be5f56d6fc50bb9de3480871d1") << ParseHex("03b41ea6ba73b94c901fdd43e782aaf70016cc124b72a086e77f6e9f4f942ca9bb") << ParseHex("02be643c3350bade7c96f6f28d1750af2ef507bc1f08dd38f82749214ab90d9037") << ParseHex("021df31471281d4478df85bfce08a10aab82601dca949a79950f8ddf7002bd915a") << ParseHex("0320ea4fcf77b63e89094e681a5bd50355900bf961c10c9c82876cb3238979c0ed") << ParseHex("021c4c92c8380659eb567b497b936b274424662909e1ffebc603672ed8433f4aa1") << ParseHex("027841250cfadc06c603da8bc58f6cd91e62f369826c8718eb6bd114601dd0c5ac") << OP_7 << OP_CHECKMULTISIG;
}
genesis.proof = CProof(scriptDestination, CScript()); // genesis block gets a PoW pass
hashGenesisBlock = genesis.GetHash();
@ -163,14 +165,13 @@ public:
return data;
}
};
static CMainParams mainParams;
/**
* Testnet (v3)
*/
class CTestNetParams : public CMainParams {
public:
CTestNetParams() {
CTestNetParams(CScript scriptDestination) : CMainParams(scriptDestination) {
networkID = CBaseChainParams::TESTNET;
strNetworkID = "test";
pchMessageStart[0] = 0xee;
@ -217,14 +218,13 @@ public:
return dataTestnet;
}
};
static CTestNetParams testNetParams;
/**
* Regression test
*/
class CRegTestParams : public CTestNetParams {
public:
CRegTestParams() {
CRegTestParams(CScript scriptDestination) : CTestNetParams(scriptDestination) {
networkID = CBaseChainParams::REGTEST;
strNetworkID = "regtest";
pchMessageStart[0] = 0xfa;
@ -249,7 +249,9 @@ public:
txNew.vout[1].scriptPubKey = CScript() << OP_TRUE;
genesis.vtx[0] = CTransaction(txNew);
CScript scriptDestination(CScript() << OP_TRUE);
if (scriptDestination.empty()) {
scriptDestination = CScript() << OP_TRUE;
}
genesis.proof = CProof(scriptDestination, CScript()); // genesis block gets a PoW pass
genesis.hashMerkleRoot = genesis.BuildMerkleTree();
@ -272,14 +274,13 @@ public:
return dataRegtest;
}
};
static CRegTestParams regTestParams;
/**
* Unit test
*/
class CUnitTestParams : public CMainParams, public CModifiableParams {
public:
CUnitTestParams() {
CUnitTestParams(CScript scriptDestination) : CMainParams(scriptDestination) {
networkID = CBaseChainParams::UNITTEST;
strNetworkID = "unittest";
nDefaultPort = 18445;
@ -308,50 +309,47 @@ public:
virtual void setAllowMinDifficultyBlocks(bool afAllowMinDifficultyBlocks) { fAllowMinDifficultyBlocks=afAllowMinDifficultyBlocks; }
virtual void setSkipProofOfWorkCheck(bool afSkipProofOfWorkCheck) { fSkipProofOfWorkCheck = afSkipProofOfWorkCheck; }
};
static CUnitTestParams unitTestParams;
static CChainParams *pCurrentParams = 0;
CModifiableParams *ModifiableParams()
{
assert(pCurrentParams);
assert(pCurrentParams==&unitTestParams);
return (CModifiableParams*)&unitTestParams;
}
static CChainParams *pCurrentParams;
const CChainParams &Params() {
assert(pCurrentParams);
return *pCurrentParams;
}
CChainParams &Params(CBaseChainParams::Network network) {
CChainParams* CChainParams::Factory(CBaseChainParams::Network network, CScript scriptDestination) {
switch (network) {
case CBaseChainParams::MAIN:
return mainParams;
return new CMainParams(scriptDestination);
case CBaseChainParams::TESTNET:
return testNetParams;
return new CTestNetParams(scriptDestination);
case CBaseChainParams::REGTEST:
return regTestParams;
return new CRegTestParams(scriptDestination);
case CBaseChainParams::UNITTEST:
return unitTestParams;
return new CUnitTestParams(scriptDestination);
default:
assert(false && "Unimplemented network");
return mainParams;
return NULL;
}
}
void SelectParams(CBaseChainParams::Network network) {
void SelectParams(CBaseChainParams::Network network, CScript scriptDestination) {
SelectBaseParams(network);
pCurrentParams = &Params(network);
pCurrentParams = CChainParams::Factory(network, scriptDestination);
}
void SelectParams(CBaseChainParams::Network network) {
SelectParams(network, CScript());
}
bool SelectParamsFromCommandLine()
{
CBaseChainParams::Network network = NetworkIdFromCommandLine();
CScript scriptDestination = ScriptDestinationFromCommandLine();
if (network == CBaseChainParams::MAX_NETWORK_TYPES)
return false;
SelectParams(network);
SelectParams(network, scriptDestination);
return true;
}

View file

@ -80,6 +80,12 @@ public:
const std::vector<unsigned char>& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; }
const std::vector<CAddress>& FixedSeeds() const { return vFixedSeeds; }
virtual const Checkpoints::CCheckpointData& Checkpoints() const = 0;
/**
* Creates and returns a CChainParams* of the chosen chain. The caller has to delete the object.
* @returns a CChainParams* of the chosen chain.
* @throws a std::runtime_error if the chain is not supported.
*/
static CChainParams* Factory(CBaseChainParams::Network network, CScript scriptDestination);
protected:
CChainParams() {}
@ -139,12 +145,14 @@ const CChainParams &Params();
/** Return parameters for the given network. */
CChainParams &Params(CBaseChainParams::Network network);
/** Get modifiable network parameters (UNITTEST only) */
CModifiableParams *ModifiableParams();
/** Sets the params returned by Params() to those for the given network. */
void SelectParams(CBaseChainParams::Network network);
/**
* Sets the params returned by Params() to those for the given network
* with given blocksigning pubkey */
void SelectParams(CBaseChainParams::Network network, CScript scriptDestination);
/**
* Looks for -regtest or -testnet and then calls SelectParams as appropriate.
* Returns false if an invalid combination is given.

View file

@ -5,9 +5,12 @@
#include "chainparamsbase.h"
#include "script/script.h"
#include "util.h"
#include "utilstrencodings.h"
#include <assert.h>
#include <stdio.h>
#include <boost/assign/list_of.hpp>
@ -114,6 +117,20 @@ CBaseChainParams::Network NetworkIdFromCommandLine()
return CBaseChainParams::MAIN;
}
CScript ScriptDestinationFromCommandLine()
{
std::string sd = GetArg("-genesisscriptdestination", "");
if (!sd.empty()) {
if (IsHex(sd)) {
std::vector<unsigned char> sd_raw(ParseHex(sd));
return CScript(sd_raw.begin(), sd_raw.end());
} else {
fprintf(stderr, "Warning: Genesis script destination was not valid hex, ignoring it.\n");
}
}
return CScript();
}
bool SelectBaseParamsFromCommandLine()
{
CBaseChainParams::Network network = NetworkIdFromCommandLine();

View file

@ -8,6 +8,8 @@
#include <string>
#include <vector>
#include "script/script.h"
/**
* CBaseChainParams defines the base parameters (shared between bitcoin-cli and bitcoind)
* of a given instance of the Bitcoin system.
@ -50,6 +52,12 @@ void SelectBaseParams(CBaseChainParams::Network network);
*/
CBaseChainParams::Network NetworkIdFromCommandLine();
/**
* Looks for hex-encoded -genesisscriptdistenation and returns a CScript of it.
* Returns an empty script if the flag is missing or badly encoded.
*/
CScript ScriptDestinationFromCommandLine();
/**
* Calls NetworkIdFromCommandLine() and then calls SelectParams as appropriate.
* Returns false if an invalid combination is given.

View file

@ -346,6 +346,8 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += " -gen " + strprintf(_("Generate coins (default: %u)"), 0) + "\n";
strUsage += " -genproclimit=<n> " + strprintf(_("Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)"), 1) + "\n";
#endif
strUsage += " -genesisscriptdestination " + _("Set the scriptPubKey used when signing blocks. This is intended for testing, "
"as changing it forks the node off of the network") + "\n";
strUsage += " -help-debug " + _("Show all debugging options (usage: --help -help-debug)") + "\n";
strUsage += " -logips " + strprintf(_("Include IP addresses in debug output (default: %u)"), 0) + "\n";
strUsage += " -logtimestamps " + strprintf(_("Prepend debug output with timestamp (default: %u)"), 1) + "\n";

View file

@ -1288,7 +1288,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
// CBlock and CBlockIndex
//
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos)
bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos)
{
// Open history file to append
CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION);
@ -2215,7 +2215,7 @@ static int64_t nTimeProofTxn = 0;
* Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock
* corresponding to pindexNew, to bypass loading it again from disk.
*/
bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *pblock) {
bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, const CBlock *pblock) {
assert(pindexNew->pprev == chainActive.Tip());
mempool.check(pcoinsTip);
// Read block from disk.
@ -2354,7 +2354,7 @@ static void PruneBlockIndexCandidates() {
* Try to make some progress towards making pindexMostWork the active block.
* pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork.
*/
static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork, CBlock *pblock) {
static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork, const CBlock *pblock) {
AssertLockHeld(cs_main);
bool fInvalidFound = false;
const CBlockIndex *pindexOldTip = chainActive.Tip();
@ -2423,7 +2423,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
* or an activated best chain. pblock is either NULL or a pointer to a block
* that is already loaded (to avoid loading it again from disk).
*/
bool ActivateBestChain(CValidationState &state, CBlock *pblock) {
bool ActivateBestChain(CValidationState &state, const CBlock *pblock) {
CBlockIndex *pindexNewTip = NULL;
CBlockIndex *pindexMostWork = NULL;
do {
@ -3359,7 +3359,7 @@ bool InitBlockIndex() {
// Only add the genesis block if not reindexing (in which case we reuse the one already on disk)
if (!fReindex) {
try {
CBlock &block = const_cast<CBlock&>(Params().GenesisBlock());
const CBlock &block = Params().GenesisBlock();
// Start new block file
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
CDiskBlockPos blockPos;

View file

@ -196,7 +196,7 @@ std::string GetWarnings(std::string strFor);
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, bool fAllowSlow = false);
/** Find the best known block, and make it the tip of the block chain */
bool ActivateBestChain(CValidationState &state, CBlock *pblock = NULL);
bool ActivateBestChain(CValidationState &state, const CBlock *pblock = NULL);
CAmount GetBlockValue(int nHeight, const CAmount& nFees);
/** Create a new block index entry for a given block hash */
@ -390,7 +390,7 @@ public:
/** Functions for disk access for blocks */
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos);
bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos);
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos);
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex);

View file

@ -0,0 +1,87 @@
// Copyright (c) 2011-2014 The Bitcoin Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "chainparams.h"
#include "uint256.h"
#include "utilstrencodings.h"
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_SUITE(genesis_tests)
// Goal: check that the standard mainnet genesis block is computed correctly
BOOST_AUTO_TEST_CASE(genesis_mainnet)
{
SelectParams(CBaseChainParams::MAIN);
const CChainParams *params = &Params();
BOOST_CHECK_EQUAL(params->HashGenesisBlock().GetHex(),
params->GenesisBlock().GetHash().GetHex());
BOOST_CHECK_EQUAL(params->HashGenesisBlock().GetHex(),
"b811a5eeaf27432278c032a0b520f829be2b92fafff9789efe2755fff8ef547b");
// Check that unittest genesis hash is same as the mainnet one
const CChainParams *params2 = &Params();
BOOST_CHECK_EQUAL(params2->HashGenesisBlock().GetHex(),
params2->GenesisBlock().GetHash().GetHex());
BOOST_CHECK_EQUAL(params2->HashGenesisBlock().GetHex(),
"b811a5eeaf27432278c032a0b520f829be2b92fafff9789efe2755fff8ef547b");
}
// Goal: check that the standard testnet genesis block is computed correctly
BOOST_AUTO_TEST_CASE(genesis_testnet)
{
SelectParams(CBaseChainParams::TESTNET);
const CChainParams *params = &Params();
BOOST_CHECK_EQUAL(params->HashGenesisBlock().GetHex(),
params->GenesisBlock().GetHash().GetHex());
BOOST_CHECK_EQUAL(params->HashGenesisBlock().GetHex(),
"f7f0ca371b1003dc7346bab766b4a131f9e3a5d68820a364d70921cb15b95eaa");
// Return params to base case for other tests
SelectParams(CBaseChainParams::MAIN);
}
// Goal: check that the default regtest genesis block is computed correctly
BOOST_AUTO_TEST_CASE(genesis_regtest)
{
SelectParams(CBaseChainParams::REGTEST);
const CChainParams *params = &Params();
BOOST_CHECK_EQUAL(params->HashGenesisBlock().GetHex(),
params->GenesisBlock().GetHash().GetHex());
BOOST_CHECK_EQUAL(params->HashGenesisBlock().GetHex(),
"b41d03dc310957765223df2bf2f4b3609c79b8b6ac0a0764b20754f972d48b6c");
// Return params to base case for other tests
SelectParams(CBaseChainParams::MAIN);
}
// Goal: check that the replacing the signing script pubkey works correctly
BOOST_AUTO_TEST_CASE(genesis_customscript)
{
CScript unsignable = CScript() << OP_FALSE;
SelectParams(CBaseChainParams::MAIN, unsignable);
const CChainParams *params1 = &Params();
BOOST_CHECK_EQUAL(params1->HashGenesisBlock().GetHex(),
params1->GenesisBlock().GetHash().GetHex());
BOOST_CHECK_EQUAL(params1->HashGenesisBlock().GetHex(),
"2ec431e3858cef95882cd7d627599fd757afa81938f0b886bee691a48b1e9b58");
SelectParams(CBaseChainParams::TESTNET, unsignable);
const CChainParams *params2 = &Params();
BOOST_CHECK_EQUAL(params2->HashGenesisBlock().GetHex(),
params2->GenesisBlock().GetHash().GetHex());
BOOST_CHECK_EQUAL(params2->HashGenesisBlock().GetHex(),
"e28e10e75c6f55edfdb914831b8d48c79fd858b6020963a038ee97dcaae2b355");
SelectParams(CBaseChainParams::REGTEST, unsignable);
const CChainParams *params3 = &Params();
BOOST_CHECK_EQUAL(params3->HashGenesisBlock().GetHex(),
params3->GenesisBlock().GetHash().GetHex());
BOOST_CHECK_EQUAL(params3->HashGenesisBlock().GetHex(),
"a99a962c80d71fe1eb0b30217a6f14bc571e3eee97bc16663cf42d9e22eb6cb2");
// Return params to base case for other tests
SelectParams(CBaseChainParams::MAIN);
}
BOOST_AUTO_TEST_SUITE_END()