Merge #14811: Mining: Enforce that segwit option must be set in GBT
d2ce315fbf
[docs] add release note for change to GBT (John Newbery)0025c9eae4
[mining] segwit option must be set in GBT (John Newbery) Pull request description: Calling getblocktemplate without the segwit rule specified is most likely a client error, since it results in lower fees for the miner. Prevent this client error by failing getblocktemplate if called without the segwit rule specified. Of the previous 1000 blocks (measured at block [551591 (hash 0x...173c811)](https://blockstream.info/block/000000000000000000173c811e79858808abc3216af607035973f002bef60a7a)), 991 included segwit transactions. Tree-SHA512: 7933b073d72683c9ab9318db46a085ec19a56a14937945c73f783ac7656887619a86b74db0bdfcb8121df44f63a1d6a6fb19e98505b2a26a6a8a6e768e442fee
This commit is contained in:
commit
feda41e0a7
11 changed files with 39 additions and 62 deletions
|
@ -65,6 +65,13 @@ platform.
|
||||||
Notable changes
|
Notable changes
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
Mining
|
||||||
|
------
|
||||||
|
|
||||||
|
- Calls to `getblocktemplate` will fail if the segwit rule is not specified.
|
||||||
|
Calling `getblocktemplate` without segwit specified is almost certainly
|
||||||
|
a misconfiguration since doing so results in lower rewards for the miner.
|
||||||
|
|
||||||
Command line option changes
|
Command line option changes
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
@ -182,6 +189,8 @@ in the Low-level Changes section below.
|
||||||
P2SH-P2WPKH, and P2SH-P2WSH. Requests for P2WSH and P2SH-P2WSH accept
|
P2SH-P2WPKH, and P2SH-P2WSH. Requests for P2WSH and P2SH-P2WSH accept
|
||||||
an additional `witnessscript` parameter.
|
an additional `witnessscript` parameter.
|
||||||
|
|
||||||
|
- See the [Mining](#mining) section for changes to `getblocktemplate`.
|
||||||
|
|
||||||
Low-level changes
|
Low-level changes
|
||||||
=================
|
=================
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ static std::shared_ptr<CBlock> PrepareBlock(const CScript& coinbase_scriptPubKey
|
||||||
{
|
{
|
||||||
auto block = std::make_shared<CBlock>(
|
auto block = std::make_shared<CBlock>(
|
||||||
BlockAssembler{Params()}
|
BlockAssembler{Params()}
|
||||||
.CreateNewBlock(coinbase_scriptPubKey, /* fMineWitnessTx */ true)
|
.CreateNewBlock(coinbase_scriptPubKey)
|
||||||
->block);
|
->block);
|
||||||
|
|
||||||
block->nTime = ::chainActive.Tip()->GetMedianTimePast() + 1;
|
block->nTime = ::chainActive.Tip()->GetMedianTimePast() + 1;
|
||||||
|
|
|
@ -95,7 +95,7 @@ void BlockAssembler::resetBlock()
|
||||||
nFees = 0;
|
nFees = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn, bool fMineWitnessTx)
|
std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||||
{
|
{
|
||||||
int64_t nTimeStart = GetTimeMicros();
|
int64_t nTimeStart = GetTimeMicros();
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
|
||||||
// not activated.
|
// not activated.
|
||||||
// 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()) && fMineWitnessTx;
|
fIncludeWitness = IsWitnessEnabled(pindexPrev, chainparams.GetConsensus());
|
||||||
|
|
||||||
int nPackagesSelected = 0;
|
int nPackagesSelected = 0;
|
||||||
int nDescendantsUpdated = 0;
|
int nDescendantsUpdated = 0;
|
||||||
|
|
|
@ -157,7 +157,7 @@ public:
|
||||||
BlockAssembler(const CChainParams& params, const Options& options);
|
BlockAssembler(const CChainParams& params, const Options& options);
|
||||||
|
|
||||||
/** 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, bool fMineWitnessTx=true);
|
std::unique_ptr<CBlockTemplate> CreateNewBlock(const CScript& scriptPubKeyIn);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// utility functions
|
// utility functions
|
||||||
|
|
|
@ -311,7 +311,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
|
||||||
" https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n"
|
" https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n"
|
||||||
" https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki\n",
|
" https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki\n",
|
||||||
{
|
{
|
||||||
{"template_request", RPCArg::Type::OBJ, /* opt */ true, /* default_val */ "", "A json object in the following spec",
|
{"template_request", RPCArg::Type::OBJ, /* opt */ false, /* default_val */ "", "A json object in the following spec",
|
||||||
{
|
{
|
||||||
{"mode", RPCArg::Type::STR, /* opt */ true, /* default_val */ "", "This must be set to \"template\", \"proposal\" (see BIP 23), or omitted"},
|
{"mode", RPCArg::Type::STR, /* opt */ true, /* default_val */ "", "This must be set to \"template\", \"proposal\" (see BIP 23), or omitted"},
|
||||||
{"capabilities", RPCArg::Type::ARR, /* opt */ true, /* default_val */ "", "A list of strings",
|
{"capabilities", RPCArg::Type::ARR, /* opt */ true, /* default_val */ "", "A list of strings",
|
||||||
|
@ -319,7 +319,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
|
||||||
{"support", RPCArg::Type::STR, /* opt */ true, /* default_val */ "", "client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'"},
|
{"support", RPCArg::Type::STR, /* opt */ true, /* default_val */ "", "client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{"rules", RPCArg::Type::ARR, /* opt */ true, /* default_val */ "", "A list of strings",
|
{"rules", RPCArg::Type::ARR, /* opt */ false, /* default_val */ "", "A list of strings",
|
||||||
{
|
{
|
||||||
{"support", RPCArg::Type::STR, /* opt */ true, /* default_val */ "", "client side supported softfork deployment"},
|
{"support", RPCArg::Type::STR, /* opt */ true, /* default_val */ "", "client side supported softfork deployment"},
|
||||||
},
|
},
|
||||||
|
@ -503,21 +503,17 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct VBDeploymentInfo& segwit_info = VersionBitsDeploymentInfo[Consensus::DEPLOYMENT_SEGWIT];
|
const struct VBDeploymentInfo& segwit_info = VersionBitsDeploymentInfo[Consensus::DEPLOYMENT_SEGWIT];
|
||||||
// If the caller is indicating segwit support, then allow CreateNewBlock()
|
// GBT must be called with 'segwit' set in the rules
|
||||||
// to select witness transactions, after segwit activates (otherwise
|
if (setClientRules.count(segwit_info.name) != 1) {
|
||||||
// don't).
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "getblocktemplate must be called with the segwit rule set (call with {\"rules\": [\"segwit\"]})");
|
||||||
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;
|
||||||
|
@ -526,11 +522,10 @@ static 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, fSupportsSegwit);
|
pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy);
|
||||||
if (!pblocktemplate)
|
if (!pblocktemplate)
|
||||||
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
|
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
|
||||||
|
|
||||||
|
@ -682,7 +677,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
|
||||||
result.pushKV("bits", strprintf("%08x", pblock->nBits));
|
result.pushKV("bits", strprintf("%08x", pblock->nBits));
|
||||||
result.pushKV("height", (int64_t)(pindexPrev->nHeight+1));
|
result.pushKV("height", (int64_t)(pindexPrev->nHeight+1));
|
||||||
|
|
||||||
if (!pblocktemplate->vchCoinbaseCommitment.empty() && fSupportsSegwit) {
|
if (!pblocktemplate->vchCoinbaseCommitment.empty()) {
|
||||||
result.pushKV("default_witness_commitment", HexStr(pblocktemplate->vchCoinbaseCommitment.begin(), pblocktemplate->vchCoinbaseCommitment.end()));
|
result.pushKV("default_witness_commitment", HexStr(pblocktemplate->vchCoinbaseCommitment.begin(), pblocktemplate->vchCoinbaseCommitment.end()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ std::shared_ptr<CBlock> Block(const uint256& prev_hash)
|
||||||
CScript pubKey;
|
CScript pubKey;
|
||||||
pubKey << i++ << OP_TRUE;
|
pubKey << i++ << OP_TRUE;
|
||||||
|
|
||||||
auto ptemplate = BlockAssembler(Params()).CreateNewBlock(pubKey, false);
|
auto ptemplate = BlockAssembler(Params()).CreateNewBlock(pubKey);
|
||||||
auto pblock = std::make_shared<CBlock>(ptemplate->block);
|
auto pblock = std::make_shared<CBlock>(ptemplate->block);
|
||||||
pblock->hashPrevBlock = prev_hash;
|
pblock->hashPrevBlock = prev_hash;
|
||||||
pblock->nTime = ++time;
|
pblock->nTime = ++time;
|
||||||
|
|
|
@ -90,7 +90,7 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
|
|
||||||
self.log.info("Verify sigops are counted in GBT with pre-BIP141 rules before the fork")
|
self.log.info("Verify sigops are counted in GBT with pre-BIP141 rules before the fork")
|
||||||
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
|
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
|
||||||
tmpl = self.nodes[0].getblocktemplate({})
|
tmpl = self.nodes[0].getblocktemplate({'rules': ['segwit']})
|
||||||
assert(tmpl['sizelimit'] == 1000000)
|
assert(tmpl['sizelimit'] == 1000000)
|
||||||
assert('weightlimit' not in tmpl)
|
assert('weightlimit' not in tmpl)
|
||||||
assert(tmpl['sigoplimit'] == 20000)
|
assert(tmpl['sigoplimit'] == 20000)
|
||||||
|
@ -232,15 +232,7 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
assert(tx.wit.is_null())
|
assert(tx.wit.is_null())
|
||||||
assert(txid3 in self.nodes[0].getrawmempool())
|
assert(txid3 in self.nodes[0].getrawmempool())
|
||||||
|
|
||||||
# Now try calling getblocktemplate() without segwit support.
|
# Check that getblocktemplate includes all transactions.
|
||||||
template = self.nodes[0].getblocktemplate()
|
|
||||||
|
|
||||||
# Check that tx1 is the only transaction of the 3 in the template.
|
|
||||||
template_txids = [t['txid'] for t in template['transactions']]
|
|
||||||
assert(txid2 not in template_txids and txid3 not in template_txids)
|
|
||||||
assert(txid1 in template_txids)
|
|
||||||
|
|
||||||
# Check that running with segwit support results in all 3 being included.
|
|
||||||
template = self.nodes[0].getblocktemplate({"rules": ["segwit"]})
|
template = self.nodes[0].getblocktemplate({"rules": ["segwit"]})
|
||||||
template_txids = [t['txid'] for t in template['transactions']]
|
template_txids = [t['txid'] for t in template['transactions']]
|
||||||
assert(txid1 in template_txids)
|
assert(txid1 in template_txids)
|
||||||
|
|
|
@ -30,7 +30,7 @@ from test_framework.script import CScriptNum
|
||||||
def assert_template(node, block, expect, rehash=True):
|
def assert_template(node, block, expect, rehash=True):
|
||||||
if rehash:
|
if rehash:
|
||||||
block.hashMerkleRoot = block.calc_merkle_root()
|
block.hashMerkleRoot = block.calc_merkle_root()
|
||||||
rsp = node.getblocktemplate(template_request={'data': b2x(block.serialize()), 'mode': 'proposal'})
|
rsp = node.getblocktemplate(template_request={'data': b2x(block.serialize()), 'mode': 'proposal', 'rules': ['segwit']})
|
||||||
assert_equal(rsp, expect)
|
assert_equal(rsp, expect)
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ class MiningTest(BitcoinTestFramework):
|
||||||
|
|
||||||
# Mine a block to leave initial block download
|
# Mine a block to leave initial block download
|
||||||
node.generatetoaddress(1, node.get_deterministic_priv_key().address)
|
node.generatetoaddress(1, node.get_deterministic_priv_key().address)
|
||||||
tmpl = node.getblocktemplate()
|
tmpl = node.getblocktemplate({'rules': ['segwit']})
|
||||||
self.log.info("getblocktemplate: Test capability advertised")
|
self.log.info("getblocktemplate: Test capability advertised")
|
||||||
assert 'proposal' in tmpl['capabilities']
|
assert 'proposal' in tmpl['capabilities']
|
||||||
assert 'coinbasetxn' not in tmpl
|
assert 'coinbasetxn' not in tmpl
|
||||||
|
@ -86,6 +86,9 @@ class MiningTest(BitcoinTestFramework):
|
||||||
block.nNonce = 0
|
block.nNonce = 0
|
||||||
block.vtx = [coinbase_tx]
|
block.vtx = [coinbase_tx]
|
||||||
|
|
||||||
|
self.log.info("getblocktemplate: segwit rule must be set")
|
||||||
|
assert_raises_rpc_error(-8, "getblocktemplate must be called with the segwit rule set", node.getblocktemplate)
|
||||||
|
|
||||||
self.log.info("getblocktemplate: Test valid block")
|
self.log.info("getblocktemplate: Test valid block")
|
||||||
assert_template(node, block, None)
|
assert_template(node, block, None)
|
||||||
|
|
||||||
|
@ -102,7 +105,7 @@ class MiningTest(BitcoinTestFramework):
|
||||||
assert_raises_rpc_error(-22, "Block does not start with a coinbase", node.submitblock, b2x(bad_block.serialize()))
|
assert_raises_rpc_error(-22, "Block does not start with a coinbase", node.submitblock, b2x(bad_block.serialize()))
|
||||||
|
|
||||||
self.log.info("getblocktemplate: Test truncated final transaction")
|
self.log.info("getblocktemplate: Test truncated final transaction")
|
||||||
assert_raises_rpc_error(-22, "Block decode failed", node.getblocktemplate, {'data': b2x(block.serialize()[:-1]), 'mode': 'proposal'})
|
assert_raises_rpc_error(-22, "Block decode failed", node.getblocktemplate, {'data': b2x(block.serialize()[:-1]), 'mode': 'proposal', 'rules': ['segwit']})
|
||||||
|
|
||||||
self.log.info("getblocktemplate: Test duplicate transaction")
|
self.log.info("getblocktemplate: Test duplicate transaction")
|
||||||
bad_block = copy.deepcopy(block)
|
bad_block = copy.deepcopy(block)
|
||||||
|
@ -132,7 +135,7 @@ class MiningTest(BitcoinTestFramework):
|
||||||
bad_block_sn = bytearray(block.serialize())
|
bad_block_sn = bytearray(block.serialize())
|
||||||
assert_equal(bad_block_sn[TX_COUNT_OFFSET], 1)
|
assert_equal(bad_block_sn[TX_COUNT_OFFSET], 1)
|
||||||
bad_block_sn[TX_COUNT_OFFSET] += 1
|
bad_block_sn[TX_COUNT_OFFSET] += 1
|
||||||
assert_raises_rpc_error(-22, "Block decode failed", node.getblocktemplate, {'data': b2x(bad_block_sn), 'mode': 'proposal'})
|
assert_raises_rpc_error(-22, "Block decode failed", node.getblocktemplate, {'data': b2x(bad_block_sn), 'mode': 'proposal', 'rules': ['segwit']})
|
||||||
|
|
||||||
self.log.info("getblocktemplate: Test bad bits")
|
self.log.info("getblocktemplate: Test bad bits")
|
||||||
bad_block = copy.deepcopy(block)
|
bad_block = copy.deepcopy(block)
|
||||||
|
|
|
@ -15,14 +15,14 @@ class LongpollThread(threading.Thread):
|
||||||
def __init__(self, node):
|
def __init__(self, node):
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
# query current longpollid
|
# query current longpollid
|
||||||
template = node.getblocktemplate()
|
template = node.getblocktemplate({'rules': ['segwit']})
|
||||||
self.longpollid = template['longpollid']
|
self.longpollid = template['longpollid']
|
||||||
# create a new connection to the node, we can't use the same
|
# create a new connection to the node, we can't use the same
|
||||||
# connection from two threads
|
# connection from two threads
|
||||||
self.node = get_rpc_proxy(node.url, 1, timeout=600, coveragedir=node.coverage_dir)
|
self.node = get_rpc_proxy(node.url, 1, timeout=600, coveragedir=node.coverage_dir)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self.node.getblocktemplate({'longpollid':self.longpollid})
|
self.node.getblocktemplate({'longpollid': self.longpollid, 'rules': ['segwit']})
|
||||||
|
|
||||||
class GetBlockTemplateLPTest(BitcoinTestFramework):
|
class GetBlockTemplateLPTest(BitcoinTestFramework):
|
||||||
def set_test_params(self):
|
def set_test_params(self):
|
||||||
|
@ -34,10 +34,10 @@ class GetBlockTemplateLPTest(BitcoinTestFramework):
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
self.log.info("Warning: this test will take about 70 seconds in the best case. Be patient.")
|
self.log.info("Warning: this test will take about 70 seconds in the best case. Be patient.")
|
||||||
self.nodes[0].generate(10)
|
self.nodes[0].generate(10)
|
||||||
template = self.nodes[0].getblocktemplate()
|
template = self.nodes[0].getblocktemplate({'rules': ['segwit']})
|
||||||
longpollid = template['longpollid']
|
longpollid = template['longpollid']
|
||||||
# longpollid should not change between successive invocations if nothing else happens
|
# longpollid should not change between successive invocations if nothing else happens
|
||||||
template2 = self.nodes[0].getblocktemplate()
|
template2 = self.nodes[0].getblocktemplate({'rules': ['segwit']})
|
||||||
assert(template2['longpollid'] == longpollid)
|
assert(template2['longpollid'] == longpollid)
|
||||||
|
|
||||||
# Test 1: test that the longpolling wait if we do nothing
|
# Test 1: test that the longpolling wait if we do nothing
|
||||||
|
|
|
@ -142,10 +142,10 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
|
||||||
# getblocktemplate to (eventually) return a new block.
|
# getblocktemplate to (eventually) return a new block.
|
||||||
mock_time = int(time.time())
|
mock_time = int(time.time())
|
||||||
self.nodes[0].setmocktime(mock_time)
|
self.nodes[0].setmocktime(mock_time)
|
||||||
template = self.nodes[0].getblocktemplate()
|
template = self.nodes[0].getblocktemplate({'rules': ['segwit']})
|
||||||
self.nodes[0].prioritisetransaction(txid=tx_id, fee_delta=-int(self.relayfee*COIN))
|
self.nodes[0].prioritisetransaction(txid=tx_id, fee_delta=-int(self.relayfee*COIN))
|
||||||
self.nodes[0].setmocktime(mock_time+10)
|
self.nodes[0].setmocktime(mock_time+10)
|
||||||
new_template = self.nodes[0].getblocktemplate()
|
new_template = self.nodes[0].getblocktemplate({'rules': ['segwit']})
|
||||||
|
|
||||||
assert(template != new_template)
|
assert(template != new_template)
|
||||||
|
|
||||||
|
|
|
@ -545,31 +545,13 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
|
|
||||||
@subtest
|
@subtest
|
||||||
def test_getblocktemplate_before_lockin(self):
|
def test_getblocktemplate_before_lockin(self):
|
||||||
# Node0 is segwit aware, node2 is not.
|
|
||||||
for node in [self.nodes[0], self.nodes[2]]:
|
|
||||||
gbt_results = node.getblocktemplate()
|
|
||||||
block_version = gbt_results['version']
|
|
||||||
# If we're not indicating segwit support, we will still be
|
|
||||||
# signalling for segwit activation.
|
|
||||||
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)
|
|
||||||
|
|
||||||
# Workaround:
|
|
||||||
# Can either change the tip, or change the mempool and wait 5 seconds
|
|
||||||
# to trigger a recomputation of getblocktemplate.
|
|
||||||
txid = int(self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1), 16)
|
txid = int(self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1), 16)
|
||||||
# Using mocktime lets us avoid sleep()
|
|
||||||
sync_mempools(self.nodes)
|
|
||||||
self.nodes[0].setmocktime(int(time.time()) + 10)
|
|
||||||
self.nodes[2].setmocktime(int(time.time()) + 10)
|
|
||||||
|
|
||||||
for node in [self.nodes[0], self.nodes[2]]:
|
for node in [self.nodes[0], self.nodes[2]]:
|
||||||
gbt_results = node.getblocktemplate({"rules": ["segwit"]})
|
gbt_results = node.getblocktemplate({"rules": ["segwit"]})
|
||||||
block_version = gbt_results['version']
|
block_version = gbt_results['version']
|
||||||
if node == self.nodes[2]:
|
if node == self.nodes[2]:
|
||||||
# If this is a non-segwit node, we should still not get a witness
|
# If this is a non-segwit node, we should not get a witness
|
||||||
# commitment, nor a version bit signalling segwit.
|
# commitment, nor a version bit signalling segwit.
|
||||||
assert_equal(block_version & (1 << VB_WITNESS_BIT), 0)
|
assert_equal(block_version & (1 << VB_WITNESS_BIT), 0)
|
||||||
assert('default_witness_commitment' not in gbt_results)
|
assert('default_witness_commitment' not in gbt_results)
|
||||||
|
@ -586,10 +568,6 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
script = get_witness_script(witness_root, 0)
|
script = get_witness_script(witness_root, 0)
|
||||||
assert_equal(witness_commitment, bytes_to_hex_str(script))
|
assert_equal(witness_commitment, bytes_to_hex_str(script))
|
||||||
|
|
||||||
# undo mocktime
|
|
||||||
self.nodes[0].setmocktime(0)
|
|
||||||
self.nodes[2].setmocktime(0)
|
|
||||||
|
|
||||||
@subtest
|
@subtest
|
||||||
def advance_to_segwit_lockin(self):
|
def advance_to_segwit_lockin(self):
|
||||||
"""Mine enough blocks to lock in segwit, but don't activate."""
|
"""Mine enough blocks to lock in segwit, but don't activate."""
|
||||||
|
|
Loading…
Reference in a new issue