Skip to content

Commit

Permalink
Merge #8489: Bugfix: Use pre-BIP141 sigops until segwit activates (GBT)
Browse files Browse the repository at this point in the history
239cbd2 qa/rpc-tests/segwit: Test GBT sigops before and after activation (Luke Dashjr)
160f895 Bugfix: Use pre-BIP141 sigops until segwit activates (Luke Dashjr)
  • Loading branch information
laanwj committed Aug 10, 2016
2 parents 484312b + 239cbd2 commit edebf42
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 9 deletions.
52 changes: 45 additions & 7 deletions qa/rpc-tests/segwit.py
Expand Up @@ -69,6 +69,11 @@ def getutxo(txid):
utxo["txid"] = txid
return utxo

def find_unspent(node, min_value):
for utxo in node.listunspent():
if utxo['amount'] >= min_value:
return utxo

class SegWitTest(BitcoinTestFramework):

def setup_chain(self):
Expand Down Expand Up @@ -117,8 +122,21 @@ def fail_mine(self, node, txid, sign, redeem_script=""):
sync_blocks(self.nodes)

def run_test(self):
self.nodes[0].generate(160) #block 160

self.nodes[0].generate(161) #block 161

print("Verify sigops are counted in GBT with pre-BIP141 rules before the fork")
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
tmpl = self.nodes[0].getblocktemplate({})
assert(tmpl['sigoplimit'] == 20000)
assert(tmpl['transactions'][0]['hash'] == txid)
assert(tmpl['transactions'][0]['sigops'] == 2)
tmpl = self.nodes[0].getblocktemplate({'rules':['segwit']})
assert(tmpl['sigoplimit'] == 20000)
assert(tmpl['transactions'][0]['hash'] == txid)
assert(tmpl['transactions'][0]['sigops'] == 2)
self.nodes[0].generate(1) #block 162

balance_presetup = self.nodes[0].getbalance()
self.pubkey = []
p2sh_ids = [] # p2sh_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE embedded in p2sh
wit_ids = [] # wit_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE via bare witness
Expand All @@ -137,18 +155,18 @@ def run_test(self):
for i in range(5):
for n in range(3):
for v in range(2):
wit_ids[n][v].append(send_to_witness(v, self.nodes[0], self.nodes[0].listunspent()[0], self.pubkey[n], False, Decimal("49.999")))
p2sh_ids[n][v].append(send_to_witness(v, self.nodes[0], self.nodes[0].listunspent()[0], self.pubkey[n], True, Decimal("49.999")))
wit_ids[n][v].append(send_to_witness(v, self.nodes[0], find_unspent(self.nodes[0], 50), self.pubkey[n], False, Decimal("49.999")))
p2sh_ids[n][v].append(send_to_witness(v, self.nodes[0], find_unspent(self.nodes[0], 50), self.pubkey[n], True, Decimal("49.999")))

self.nodes[0].generate(1) #block 161
self.nodes[0].generate(1) #block 163
sync_blocks(self.nodes)

# Make sure all nodes recognize the transactions as theirs
assert_equal(self.nodes[0].getbalance(), 60*50 - 60*50 + 20*Decimal("49.999") + 50)
assert_equal(self.nodes[0].getbalance(), balance_presetup - 60*50 + 20*Decimal("49.999") + 50)
assert_equal(self.nodes[1].getbalance(), 20*Decimal("49.999"))
assert_equal(self.nodes[2].getbalance(), 20*Decimal("49.999"))

self.nodes[0].generate(262) #block 423
self.nodes[0].generate(260) #block 423
sync_blocks(self.nodes)

print("Verify default node can't accept any witness format txs before fork")
Expand Down Expand Up @@ -205,5 +223,25 @@ def run_test(self):
self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], True) #block 434
self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], True) #block 435

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['sigoplimit'] == 80000)
assert(tmpl['transactions'][0]['txid'] == txid)
assert(tmpl['transactions'][0]['sigops'] == 8)

print("Verify non-segwit miners get a valid GBT response after the fork")
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({})
assert(len(tmpl['transactions']) == 1) # Doesn't include witness tx
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

if __name__ == '__main__':
SegWitTest().main()
17 changes: 15 additions & 2 deletions src/rpc/mining.cpp
Expand Up @@ -546,6 +546,9 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
UpdateTime(pblock, consensusParams, pindexPrev);
pblock->nNonce = 0;

// NOTE: If at some point we support pre-segwit miners post-segwit-activation, this needs to take segwit support into consideration
const bool fPreSegWit = (THRESHOLD_ACTIVE != VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache));

UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");

UniValue transactions(UniValue::VARR);
Expand Down Expand Up @@ -574,7 +577,12 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)

int index_in_template = i - 1;
entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template]));
entry.push_back(Pair("sigops", pblocktemplate->vTxSigOpsCost[index_in_template]));
int64_t nTxSigOps = pblocktemplate->vTxSigOpsCost[index_in_template];
if (fPreSegWit) {
assert(nTxSigOps % WITNESS_SCALE_FACTOR == 0);
nTxSigOps /= WITNESS_SCALE_FACTOR;
}
entry.push_back(Pair("sigops", nTxSigOps));
entry.push_back(Pair("weight", GetTransactionWeight(tx)));

transactions.push_back(entry);
Expand Down Expand Up @@ -657,7 +665,12 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
result.push_back(Pair("mutable", aMutable));
result.push_back(Pair("noncerange", "00000000ffffffff"));
result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS_COST));
int64_t nSigOpLimit = MAX_BLOCK_SIGOPS_COST;
if (fPreSegWit) {
assert(nSigOpLimit % WITNESS_SCALE_FACTOR == 0);
nSigOpLimit /= WITNESS_SCALE_FACTOR;
}
result.push_back(Pair("sigoplimit", nSigOpLimit));
result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SERIALIZED_SIZE));
result.push_back(Pair("weightlimit", (int64_t)MAX_BLOCK_WEIGHT));
result.push_back(Pair("curtime", pblock->GetBlockTime()));
Expand Down

1 comment on commit edebf42

@zptec
Copy link

@zptec zptec commented on edebf42 Aug 15, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, when can we run segwit on mainnet?

Please sign in to comment.