Browse Source

Don't require segwit in getblocktemplate for segwit signalling or mining

Segwit's version bit will be signalled for all invocations of CreateNewBlock,
and not specifying segwit only will cause CreateNewBlock to skip transactions
with witness from being selected.

Github-Pull: #9955
Rebased-From: abe7b3d3ab
0.14
Suhas Daftuar 8 years ago
parent
commit
569596cc51
  1. 8
      qa/rpc-tests/p2p-segwit.py
  2. 19
      qa/rpc-tests/segwit.py
  3. 4
      src/miner.cpp
  4. 2
      src/miner.h
  5. 18
      src/rpc/mining.cpp
  6. 2
      src/versionbits.cpp

8
qa/rpc-tests/p2p-segwit.py

@ -1701,9 +1701,11 @@ class SegWitTest(BitcoinTestFramework):
for node in [self.nodes[0], self.nodes[2]]: for node in [self.nodes[0], self.nodes[2]]:
gbt_results = node.getblocktemplate() gbt_results = node.getblocktemplate()
block_version = gbt_results['version'] block_version = gbt_results['version']
# If we're not indicating segwit support, we should not be signalling # If we're not indicating segwit support, we will still be
# for segwit activation, nor should we get a witness commitment. # signalling for segwit activation.
assert_equal(block_version & (1 << VB_WITNESS_BIT), 0) assert_equal((block_version & (1 << VB_WITNESS_BIT) != 0), node == self.nodes[0])
# If we don't specify the segwit rule, then we won't get a default
# commitment.
assert('default_witness_commitment' not in gbt_results) assert('default_witness_commitment' not in gbt_results)
# Workaround: # Workaround:

19
qa/rpc-tests/segwit.py

@ -251,20 +251,11 @@ class SegWitTest(BitcoinTestFramework):
assert(tmpl['transactions'][0]['txid'] == txid) assert(tmpl['transactions'][0]['txid'] == txid)
assert(tmpl['transactions'][0]['sigops'] == 8) assert(tmpl['transactions'][0]['sigops'] == 8)
print("Verify non-segwit miners get a valid GBT response after the fork") print("Non-segwit miners are able to use GBT response after activation.")
send_to_witness(1, self.nodes[0], find_unspent(self.nodes[0], 50), self.pubkey[0], False, Decimal("49.998")) txid = send_to_witness(1, self.nodes[0], find_unspent(self.nodes[0], 50), self.pubkey[0], False, Decimal("49.998"))
try: tmpl = self.nodes[0].getblocktemplate()
tmpl = self.nodes[0].getblocktemplate({}) # TODO: add a transaction with witness to mempool, and verify it's not
assert(len(tmpl['transactions']) == 1) # Doesn't include witness tx # selected for mining.
assert(tmpl['sizelimit'] == 1000000)
assert('weightlimit' not in tmpl)
assert(tmpl['sigoplimit'] == 20000)
assert(tmpl['transactions'][0]['hash'] == txid)
assert(tmpl['transactions'][0]['sigops'] == 2)
assert(('!segwit' in tmpl['rules']) or ('segwit' not in tmpl['rules']))
except JSONRPCException:
# This is an acceptable outcome
pass
print("Verify behaviour of importaddress, addwitnessaddress and listunspent") print("Verify behaviour of importaddress, addwitnessaddress and listunspent")

4
src/miner.cpp

@ -127,7 +127,7 @@ void BlockAssembler::resetBlock()
blockFinished = false; blockFinished = false;
} }
std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn) std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn, bool fMineWitnessTx)
{ {
resetBlock(); resetBlock();
@ -165,7 +165,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
// -promiscuousmempoolflags is used. // -promiscuousmempoolflags is used.
// TODO: replace this with a call to main to assess validity of a mempool // TODO: replace this with a call to main to assess validity of a mempool
// transaction (which in most cases can be a no-op). // transaction (which in most cases can be a no-op).
fIncludeWitness = IsWitnessEnabled(pindexPrev, chainparams.GetConsensus()); fIncludeWitness = IsWitnessEnabled(pindexPrev, chainparams.GetConsensus()) && fMineWitnessTx;
addPriorityTxs(); addPriorityTxs();
addPackageTxs(); addPackageTxs();

2
src/miner.h

@ -165,7 +165,7 @@ private:
public: public:
BlockAssembler(const CChainParams& chainparams); BlockAssembler(const CChainParams& chainparams);
/** Construct a new block template with coinbase to scriptPubKeyIn */ /** Construct a new block template with coinbase to scriptPubKeyIn */
std::unique_ptr<CBlockTemplate> CreateNewBlock(const CScript& scriptPubKeyIn); std::unique_ptr<CBlockTemplate> CreateNewBlock(const CScript& scriptPubKeyIn, bool fMineWitnessTx=true);
private: private:
// utility functions // utility functions

18
src/rpc/mining.cpp

@ -519,12 +519,22 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
// TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners? // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
} }
const struct BIP9DeploymentInfo& segwit_info = VersionBitsDeploymentInfo[Consensus::DEPLOYMENT_SEGWIT];
// If the caller is indicating segwit support, then allow CreateNewBlock()
// to select witness transactions, after segwit activates (otherwise
// don't).
bool fSupportsSegwit = setClientRules.find(segwit_info.name) != setClientRules.end();
// Update block // Update block
static CBlockIndex* pindexPrev; static CBlockIndex* pindexPrev;
static int64_t nStart; static int64_t nStart;
static std::unique_ptr<CBlockTemplate> pblocktemplate; static std::unique_ptr<CBlockTemplate> pblocktemplate;
// Cache whether the last invocation was with segwit support, to avoid returning
// a segwit-block to a non-segwit caller.
static bool fLastTemplateSupportsSegwit = true;
if (pindexPrev != chainActive.Tip() || if (pindexPrev != chainActive.Tip() ||
(mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5)) (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5) ||
fLastTemplateSupportsSegwit != fSupportsSegwit)
{ {
// Clear pindexPrev so future calls make a new block, despite any failures from here on // Clear pindexPrev so future calls make a new block, despite any failures from here on
pindexPrev = nullptr; pindexPrev = nullptr;
@ -533,10 +543,11 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
CBlockIndex* pindexPrevNew = chainActive.Tip(); CBlockIndex* pindexPrevNew = chainActive.Tip();
nStart = GetTime(); nStart = GetTime();
fLastTemplateSupportsSegwit = fSupportsSegwit;
// Create new block // Create new block
CScript scriptDummy = CScript() << OP_TRUE; CScript scriptDummy = CScript() << OP_TRUE;
pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy); pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy, fSupportsSegwit);
if (!pblocktemplate) if (!pblocktemplate)
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
@ -686,8 +697,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
result.push_back(Pair("bits", strprintf("%08x", pblock->nBits))); result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1))); result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1)));
const struct BIP9DeploymentInfo& segwit_info = VersionBitsDeploymentInfo[Consensus::DEPLOYMENT_SEGWIT]; if (!pblocktemplate->vchCoinbaseCommitment.empty() && fSupportsSegwit) {
if (!pblocktemplate->vchCoinbaseCommitment.empty() && setClientRules.find(segwit_info.name) != setClientRules.end()) {
result.push_back(Pair("default_witness_commitment", HexStr(pblocktemplate->vchCoinbaseCommitment.begin(), pblocktemplate->vchCoinbaseCommitment.end()))); result.push_back(Pair("default_witness_commitment", HexStr(pblocktemplate->vchCoinbaseCommitment.begin(), pblocktemplate->vchCoinbaseCommitment.end())));
} }

2
src/versionbits.cpp

@ -17,7 +17,7 @@ const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION
}, },
{ {
/*.name =*/ "segwit", /*.name =*/ "segwit",
/*.gbt_force =*/ false, /*.gbt_force =*/ true,
} }
}; };

Loading…
Cancel
Save