Skip to content

Commit

Permalink
Signet implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
kallewoof committed Jun 21, 2019
1 parent 44d8172 commit 67735fe
Show file tree
Hide file tree
Showing 34 changed files with 805 additions and 74 deletions.
66 changes: 66 additions & 0 deletions contrib/signet/issuer/issuer.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/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 <idle time> <bitcoin-cli path> [<bitcoin-cli args>]" ; exit 1
fi

function log()
{
echo "- $(date +%H:%M:%S): $*"
}

idletime=$1
shift

bcli=$1
shift

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 at maximum capacity with $idletime second delay between each block"
log "hit ^C to stop"

while true; do
log "generating next block"
# get address for coinbase output
addr=$($bcli "$@" getnewaddress)
# create an unsigned, un-PoW'd block
unsigned=$($bcli "$@" getnewblockhex $addr)
# sign it
signed=$($bcli "$@" signblock $unsigned)
# grind proof of work; this ends up broadcasting the block, if successful (akin to "generatetoaddress")
while true; do
blockhash=$($bcli "$@" grindblock $signed 100000000)
if [ "$blockhash" = "false" ]; then continue; fi
break;
done
if [ $? -ne 0 ]; then echo "node error; aborting" ; exit 1; fi
log "mined block $($bcli "$@" getblockcount) $blockhash to $($bcli "$@" getconnectioncount) peer(s); idling for $idletime seconds"
sleep $idletime
done
97 changes: 95 additions & 2 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>

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 <hash.h> // for signet block challenge hash

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<unsigned char>((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;

Expand All @@ -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<unsigned char>((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
Expand Down Expand Up @@ -268,6 +276,87 @@ class CTestNetParams : public CChainParams {
}
};

/**
* SigNet version 2018-07-20
*/
class SigNetParams : public CChainParams {
public:
SigNetParams(const ArgsManager& args) {
if (!args.IsArgSet("-signet_blockscript")) {
throw std::runtime_error(strprintf("%s: -signet_blockscript is mandatory for signet networks", __func__));
}
if (args.GetArgs("-signet_blockscript").size() != 1) {
throw std::runtime_error(strprintf("%s: -signet_blockscript cannot be multiple values.", __func__));
}

LogPrintf("SigNet with block script %s\n", gArgs.GetArgs("-signet_blockscript")[0]);

strNetworkID = "signet";
consensus.signature_pow = true;
consensus.blockscript = ParseHex(args.GetArgs("-signet_blockscript")[0]);
consensus.nSubsidyHalvingInterval = 210000;
consensus.BIP34Height = 1;
consensus.BIP65Height = 1;
consensus.BIP66Height = 1;
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 10 * 60;
consensus.fPowAllowMinDifficultyBlocks = false;
consensus.fPowNoRetargeting = false;
consensus.nRuleChangeActivationThreshold = 1916;
consensus.nMinerConfirmationWindow = 2016;
consensus.powLimit = uint256S("00002adc28cf53b63c82faa55d83e40ac63b5f100aa5d8df62a429192f9e8ce5");
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1539478800;
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;

// Deployment of BIP68, BIP112, and BIP113.
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0;
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1539478800;
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;

// Deployment of SegWit (BIP141, BIP143, and BIP147)
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;

pchMessageStart[0] = 0xf0;
pchMessageStart[1] = 0xc7;
pchMessageStart[2] = 0x70;
pchMessageStart[3] = 0x6a;
nDefaultPort = 38333;
nPruneAfterHeight = 1000;

CHashWriter h(SER_DISK, 0);
h << consensus.blockscript;
uint256 hash = h.GetHash();
CScript coinbase_sig = CScript() << std::vector<uint8_t>(hash.begin(), hash.end());
CScript genesis_out = CScript() << OP_RETURN;
genesis = CreateGenesisBlock(coinbase_sig, genesis_out, 1534313275, 0, 0x1e2adc28, 1, 50 * COIN);
consensus.hashGenesisBlock = genesis.GetHash();

vFixedSeeds.clear();
vSeeds.clear();
if (args.IsArgSet("-signet_seednode")) {
vSeeds = gArgs.GetArgs("-signet_seednode");
}

base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>{125};
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>{87};
base58Prefixes[SECRET_KEY] = std::vector<unsigned char>{217};
base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF};
base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94};

bech32_hrp = "sb";

fDefaultConsistencyChecks = false;
fRequireStandard = false;
fMineBlocksOnDemand = false;

/* enable fallback fee on signet */
m_fallback_fee_enabled = true;
}
};

/**
* Regression test
*/
Expand Down Expand Up @@ -409,6 +498,10 @@ std::unique_ptr<const CChainParams> CreateChainParams(const std::string& chain)
return std::unique_ptr<CChainParams>(new CTestNetParams());
else if (chain == CBaseChainParams::REGTEST)
return std::unique_ptr<CChainParams>(new CRegTestParams(gArgs));
else if (chain == CBaseChainParams::SIGNET) {
g_solution_blocks = true;
return std::unique_ptr<CChainParams>(new SigNetParams(gArgs));
}
throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
}

Expand Down
9 changes: 7 additions & 2 deletions src/chainparamsbase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

const std::string CBaseChainParams::MAIN = "main";
const std::string CBaseChainParams::TESTNET = "test";
const std::string CBaseChainParams::SIGNET = "signet";
const std::string CBaseChainParams::REGTEST = "regtest";

void SetupChainParamsBaseOptions()
Expand All @@ -21,6 +22,9 @@ void SetupChainParamsBaseOptions()
"This is intended for regression testing tools and app development.", true, OptionsCategory::CHAINPARAMS);
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-only)", true, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-signet", "Use the signet chain. Note that the network is defined by the signet_blockscript parameter", false, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-signet_blockscript", "Blocks must satisfy the given script to be considered valid (only for -signet networks)", false, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-signet_seednode", "Specify a seed node for the signet network (may be used multiple times to specify multiple seed nodes)", false, OptionsCategory::CHAINPARAMS);
}

static std::unique_ptr<CBaseChainParams> globalChainBaseParams;
Expand All @@ -39,8 +43,9 @@ std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const std::string& chain
return MakeUnique<CBaseChainParams>("testnet3", 18332);
else if (chain == CBaseChainParams::REGTEST)
return MakeUnique<CBaseChainParams>("regtest", 18443);
else
throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
else if (chain == CBaseChainParams::SIGNET)
return MakeUnique<CBaseChainParams>("signet", 38332);
throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
}

void SelectBaseParams(const std::string& chain)
Expand Down
3 changes: 2 additions & 1 deletion src/chainparamsbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@
class CBaseChainParams
{
public:
/** BIP70 chain name strings (main, test or regtest) */
/** BIP70 chain name strings (main, test, sigtest or regtest) */
static const std::string MAIN;
static const std::string TESTNET;
static const std::string SIGNET;
static const std::string REGTEST;

const std::string& DataDir() const { return strDataDir; }
Expand Down
3 changes: 3 additions & 0 deletions src/consensus/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ struct Params {
int64_t DifficultyAdjustmentInterval() const { return nPowTargetTimespan / nPowTargetSpacing; }
uint256 nMinimumChainWork;
uint256 defaultAssumeValid;

bool signature_pow{false};
std::vector<uint8_t> blockscript;
};
} // namespace Consensus

Expand Down
6 changes: 5 additions & 1 deletion src/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ 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 signet extension in the witness commitment, if this
// is a signet block (4 byte magic, 2 byte size, 64 byte signature (TODO: determine if this should be given, e.g. for multisig nets))
if (g_solution_blocks) nBlockMaxWeight -= 4 + 2 + 64;
}

BlockAssembler::BlockAssembler(const CChainParams& params, const Options& options) : chainparams(params)
Expand Down Expand Up @@ -165,7 +169,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]);

CValidationState state;
if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) {
if (!TestBlockValidity(state, chainparams, *pblock, false, false)) {
throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state)));
}
int64_t nTime2 = GetTimeMicros();
Expand Down
1 change: 1 addition & 0 deletions src/policy/policy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <consensus/validation.h>
#include <coins.h>

unsigned int GetStandardScriptVerifyFlags() { return STANDARD_SCRIPT_VERIFY_FLAGS; }

CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
{
Expand Down
2 changes: 2 additions & 0 deletions src/policy/policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,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;

Expand Down
13 changes: 12 additions & 1 deletion src/pow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#include <chain.h>
#include <primitives/block.h>
#include <uint256.h>
#include <script/interpreter.h>

unsigned int GetStandardScriptVerifyFlags();

unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
{
Expand Down Expand Up @@ -71,7 +74,7 @@ unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nF
return bnNew.GetCompact();
}

bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params)
bool CheckProofOfWork(const uint256& hash, unsigned int nBits, const Consensus::Params& params)
{
bool fNegative;
bool fOverflow;
Expand All @@ -89,3 +92,11 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&

return true;
}

bool CheckBlockSolution(const uint256& signet_hash, const std::vector<uint8_t>& signature, const Consensus::Params& params)
{
SimpleSignatureChecker bsc(signet_hash);
CScript solution = CScript(signature.begin(), signature.end());
CScript challenge = CScript(params.blockscript.begin(), params.blockscript.end());
return VerifyScript(solution, challenge, nullptr, GetStandardScriptVerifyFlags(), bsc);
}
5 changes: 4 additions & 1 deletion src/pow.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params&);

/** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&);
bool CheckProofOfWork(const uint256& hash, unsigned int nBits, const Consensus::Params&);

/** Signet: Check whether a block has a valid solution */
bool CheckBlockSolution(const uint256& signet_hash, const std::vector<uint8_t>& signature, const Consensus::Params&);

#endif // BITCOIN_POW_H
Loading

0 comments on commit 67735fe

Please sign in to comment.