Skip to content

Commit

Permalink
[mining] Several segwit2x seasoning differential related fixes.
Browse files Browse the repository at this point in the history
Fixes #28
  • Loading branch information
jgarzik committed Jun 30, 2017
1 parent d2431c0 commit 32daff9
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 11 deletions.
17 changes: 14 additions & 3 deletions qa/rpc-tests/segwit.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def run_test(self):
assert(tmpl['sigoplimit'] == 20000)
assert(tmpl['transactions'][0]['hash'] == txid)
assert(tmpl['transactions'][0]['sigops'] == 2)
tmpl = self.nodes[0].getblocktemplate({'rules':['segwit','segwit2x']})
tmpl = self.nodes[0].getblocktemplate({'rules':['segwit']})
assert(tmpl['sizelimit'] == 1000000)
assert('weightlimit' not in tmpl)
assert(tmpl['sigoplimit'] == 20000)
Expand Down Expand Up @@ -244,10 +244,21 @@ def run_test(self):

print("Verify sigops are counted in GBT with BIP141 rules after the fork")
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
tmpl = self.nodes[0].getblocktemplate({'rules':['segwit']})
assert(tmpl['sizelimit'] >= 3999577) # actual maximum size is lower due to minimum mandatory non-witness data
assert(tmpl['weightlimit'] == 4000000)
assert(tmpl['sigoplimit'] == 80000)
assert(tmpl['transactions'][0]['txid'] == txid)
assert(tmpl['transactions'][0]['sigops'] == 8)

self.nodes[0].generate(1) # Mine a block to clear the gbt cache

print("Verify sigops are counted in GBT with BIP141 rules after the 2x fork")
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
tmpl = self.nodes[0].getblocktemplate({'rules':['segwit','segwit2x']})
assert(tmpl['sizelimit'] >= 3999577) # actual maximum size is lower due to minimum mandatory non-witness data
assert(tmpl['weightlimit'] == 4000000) # limit at first step
assert(tmpl['sigoplimit'] == 160000) # limit at first step
assert(tmpl['weightlimit'] == (4000000*2))
assert(tmpl['sigoplimit'] == (80000*2))
assert(tmpl['transactions'][0]['txid'] == txid)
assert(tmpl['transactions'][0]['sigops'] == 8)

Expand Down
5 changes: 5 additions & 0 deletions src/consensus/consensus.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ inline unsigned int MaxBlockWeight()
return MaxBlockWeight(true);
}

inline unsigned int MaxBlockSerSize(bool fSegwitSeasoned)
{
return (MaxBlockBaseSize(fSegwitSeasoned) * 4);
}

/** The maximum allowed number of transactions per block */
static const unsigned int MAX_BLOCK_VTX_SIZE = 1000000;

Expand Down
14 changes: 8 additions & 6 deletions src/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ BlockAssembler::BlockAssembler(const CChainParams& _chainparams)
bool fWeightSet = false;
if (IsArgSet("-blockmaxweight")) {
nBlockMaxWeight = GetArg("-blockmaxweight", DEFAULT_BLOCK_MAX_WEIGHT);
nBlockMaxSize = MAX_BLOCK_SERIALIZED_SIZE;
nBlockMaxSize = MaxBlockSerSize(fWitnessSeasoned);
fWeightSet = true;
}
if (IsArgSet("-blockmaxsize")) {
Expand All @@ -102,11 +102,11 @@ BlockAssembler::BlockAssembler(const CChainParams& _chainparams)
}

// Limit weight to between 4K and MAX_BLOCK_WEIGHT-4K for sanity:
nBlockMaxWeight = std::max((unsigned int)4000, std::min((unsigned int)(MaxBlockWeight(false)-4000), nBlockMaxWeight));
nBlockMaxWeight = std::max((unsigned int)4000, std::min((unsigned int)(MaxBlockWeight(fWitnessSeasoned)-4000), nBlockMaxWeight));
// Limit size to between 1K and MAX_BLOCK_SERIALIZED_SIZE-1K for sanity:
nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SERIALIZED_SIZE-1000), nBlockMaxSize));
nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MaxBlockSerSize(fWitnessSeasoned)-1000), nBlockMaxSize));
// Whether we need to account for byte usage (in addition to weight usage)
fNeedSizeAccounting = (nBlockMaxSize < MAX_BLOCK_SERIALIZED_SIZE-1000);
fNeedSizeAccounting = (nBlockMaxSize < MaxBlockSerSize(fWitnessSeasoned)-1000);
}

void BlockAssembler::resetBlock()
Expand All @@ -118,6 +118,7 @@ void BlockAssembler::resetBlock()
nBlockWeight = 4000;
nBlockSigOpsCost = 400;
fIncludeWitness = false;
fWitnessSeasoned = false;

// These counters do not include coinbase tx
nBlockTx = 0;
Expand Down Expand Up @@ -168,6 +169,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
// TODO: replace this with a call to main to assess validity of a mempool
// transaction (which in most cases can be a no-op).
fIncludeWitness = IsWitnessEnabled(pindexPrev, chainparams.GetConsensus()) && fMineWitnessTx;
fWitnessSeasoned = IsWitnessSeasoned(pindexPrev, chainparams.GetConsensus());

addPriorityTxs();
int nPackagesSelected = 0;
Expand Down Expand Up @@ -242,7 +244,7 @@ bool BlockAssembler::TestPackage(uint64_t packageSize, int64_t packageSigOpsCost
// TODO: switch to weight-based accounting for packages instead of vsize-based accounting.
if (nBlockWeight + WITNESS_SCALE_FACTOR * packageSize >= nBlockMaxWeight)
return false;
if (nBlockSigOpsCost + packageSigOpsCost >= (uint64_t)MaxBlockSigOpsCost(fIncludeWitness)) // note - excludes bip102 buffer
if (nBlockSigOpsCost + packageSigOpsCost >= (uint64_t)MaxBlockSigOpsCost(fWitnessSeasoned))
return false;
return true;
}
Expand Down Expand Up @@ -302,7 +304,7 @@ bool BlockAssembler::TestForBlock(CTxMemPool::txiter iter)
}
}

uint64_t sigOpMax = MaxBlockSigOpsCost(fIncludeWitness); // excludes bip102 buffer
uint64_t sigOpMax = MaxBlockSigOpsCost(fWitnessSeasoned);
if (nBlockSigOpsCost + iter->GetSigOpCost() >= sigOpMax) {
// If the block has room for no more sig ops then
// flag that the block is finished
Expand Down
1 change: 1 addition & 0 deletions src/miner.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ class BlockAssembler

// Configuration parameters for the block size
bool fIncludeWitness;
bool fWitnessSeasoned;
unsigned int nBlockMaxWeight, nBlockMaxSize;
bool fNeedSizeAccounting;
CFeeRate blockMinFeeRate;
Expand Down
6 changes: 4 additions & 2 deletions src/rpc/mining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,10 +520,12 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
}

const struct BIP9DeploymentInfo& segwit_info = VersionBitsDeploymentInfo[Consensus::DEPLOYMENT_SEGWIT];
const struct BIP9DeploymentInfo& segwit2x_info = VersionBitsDeploymentInfo[Consensus::DEPLOYMENT_SEGWIT2X];
// 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();
bool fSupportsSegwit2x = setClientRules.find(segwit2x_info.name) != setClientRules.end();

// Update block
static CBlockIndex* pindexPrev;
Expand Down Expand Up @@ -681,7 +683,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
result.push_back(Pair("mutable", aMutable));
result.push_back(Pair("noncerange", "00000000ffffffff"));
int64_t nSigOpLimit = MaxBlockSigOpsCost(fPreSegWit?false:true); // excl bip102 buffer
int64_t nSigOpLimit = MaxBlockSigOpsCost(fSupportsSegwit2x); // excl bip102 buffer
if (fPreSegWit) {
assert(nSigOpLimit % WITNESS_SCALE_FACTOR == 0);
nSigOpLimit /= WITNESS_SCALE_FACTOR;
Expand All @@ -691,7 +693,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
result.push_back(Pair("sizelimit", (int64_t)MAX_LEGACY_BLOCK_SIZE));
} else {
result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SERIALIZED_SIZE));
result.push_back(Pair("weightlimit", (int64_t)MaxBlockWeight(false)));
result.push_back(Pair("weightlimit", (int64_t)MaxBlockWeight(fSupportsSegwit2x)));
}
result.push_back(Pair("curtime", pblock->GetBlockTime()));
result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
Expand Down

0 comments on commit 32daff9

Please sign in to comment.