mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 12:02:48 +01:00
Align with btc 0.12 (#1409)
* Implement BIP 9 GBT changes - BIP9DeploymentInfo struct for static deployment info - VersionBitsDeploymentInfo: Avoid C++11ism by commenting parameter names - getblocktemplate: Make sure to set deployments in the version if it is LOCKED_IN - In this commit, all rules are considered required for clients to support * qa/rpc-tests: bip9-softforks: Add tests for getblocktemplate versionbits updates * getblocktemplate: Explicitly handle the distinction between GBT-affecting softforks vs not * getblocktemplate: Use version/force mutation to support pre-BIP9 clients * Don't use floating point Github-Pull: #8317 Rebased-From:477777f250
* Send tip change notification from invalidateblock This change is needed to prevent sync_blocks timeouts in the mempool_reorg test after the sync_blocks update in the upcoming commit "[qa] Change sync_blocks to pick smarter maxheight". This change was initially suggested by Suhas Daftuar <sdaftuar@chaincode.com> in https://github.com/bitcoin/bitcoin/pull/8680#r78209060 Github-Pull: #9196 Rebased-From:67c6326abd
* torcontrol: Explicitly request RSA1024 private key When generating a new service key, explicitly request a RSA1024 one. The bitcoin P2P protocol has no support for the longer hidden service names that will come with ed25519 keys, until it does, we depend on the old hidden service type so make this explicit. See #9214. Github-Pull: #9234 Rebased-From:7d3b627395
* Bugfix: FRT: don't terminate when keypool is empty Github-Pull: #9295 Rebased-From:c24a4f5981
* add fundrawtransaction test on a locked wallet with empty keypool Github-Pull: #9295 Rebased-From:1a6eacbf3b
This commit is contained in:
parent
4595db0ce3
commit
ff30aed68f
@ -83,7 +83,7 @@ class BIP9SoftForksTest(ComparisonTestFramework):
|
||||
raise IndexError ('key:"%s" not found' % key)
|
||||
|
||||
|
||||
def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignature):
|
||||
def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignature, bitno):
|
||||
# generate some coins for later
|
||||
self.coinbase_blocks = self.nodes[0].generate(2)
|
||||
self.height = 3 # height of the next block to build
|
||||
@ -92,6 +92,11 @@ class BIP9SoftForksTest(ComparisonTestFramework):
|
||||
self.last_block_time = int(time.time())
|
||||
|
||||
assert_equal(self.get_bip9_status(bipName)['status'], 'defined')
|
||||
tmpl = self.nodes[0].getblocktemplate({})
|
||||
assert(bipName not in tmpl['rules'])
|
||||
assert(bipName not in tmpl['vbavailable'])
|
||||
assert_equal(tmpl['vbrequired'], 0)
|
||||
assert_equal(tmpl['version'], 0x20000000)
|
||||
|
||||
# Test 1
|
||||
# Advance from DEFINED to STARTED
|
||||
@ -99,6 +104,11 @@ class BIP9SoftForksTest(ComparisonTestFramework):
|
||||
yield TestInstance(test_blocks, sync_every_block=False)
|
||||
|
||||
assert_equal(self.get_bip9_status(bipName)['status'], 'started')
|
||||
tmpl = self.nodes[0].getblocktemplate({})
|
||||
assert(bipName not in tmpl['rules'])
|
||||
assert_equal(tmpl['vbavailable'][bipName], bitno)
|
||||
assert_equal(tmpl['vbrequired'], 0)
|
||||
assert(tmpl['version'] & activated_version)
|
||||
|
||||
# Test 2
|
||||
# Fail to achieve LOCKED_IN 100 out of 144 signal bit 1
|
||||
@ -110,6 +120,11 @@ class BIP9SoftForksTest(ComparisonTestFramework):
|
||||
yield TestInstance(test_blocks, sync_every_block=False)
|
||||
|
||||
assert_equal(self.get_bip9_status(bipName)['status'], 'started')
|
||||
tmpl = self.nodes[0].getblocktemplate({})
|
||||
assert(bipName not in tmpl['rules'])
|
||||
assert_equal(tmpl['vbavailable'][bipName], bitno)
|
||||
assert_equal(tmpl['vbrequired'], 0)
|
||||
assert(tmpl['version'] & activated_version)
|
||||
|
||||
# Test 3
|
||||
# 108 out of 144 signal bit 1 to achieve LOCKED_IN
|
||||
@ -121,6 +136,8 @@ class BIP9SoftForksTest(ComparisonTestFramework):
|
||||
yield TestInstance(test_blocks, sync_every_block=False)
|
||||
|
||||
assert_equal(self.get_bip9_status(bipName)['status'], 'locked_in')
|
||||
tmpl = self.nodes[0].getblocktemplate({})
|
||||
assert(bipName not in tmpl['rules'])
|
||||
|
||||
# Test 4
|
||||
# 143 more version 536870913 blocks (waiting period-1)
|
||||
@ -128,6 +145,8 @@ class BIP9SoftForksTest(ComparisonTestFramework):
|
||||
yield TestInstance(test_blocks, sync_every_block=False)
|
||||
|
||||
assert_equal(self.get_bip9_status(bipName)['status'], 'locked_in')
|
||||
tmpl = self.nodes[0].getblocktemplate({})
|
||||
assert(bipName not in tmpl['rules'])
|
||||
|
||||
# Test 5
|
||||
# Check that the new rule is enforced
|
||||
@ -151,6 +170,11 @@ class BIP9SoftForksTest(ComparisonTestFramework):
|
||||
yield TestInstance([[block, True]])
|
||||
|
||||
assert_equal(self.get_bip9_status(bipName)['status'], 'active')
|
||||
tmpl = self.nodes[0].getblocktemplate({})
|
||||
assert(bipName in tmpl['rules'])
|
||||
assert(bipName not in tmpl['vbavailable'])
|
||||
assert_equal(tmpl['vbrequired'], 0)
|
||||
assert(not (tmpl['version'] & (1 << bitno)))
|
||||
|
||||
# Test 6
|
||||
# Check that the new sequence lock rules are enforced
|
||||
@ -184,9 +208,9 @@ class BIP9SoftForksTest(ComparisonTestFramework):
|
||||
|
||||
def get_tests(self):
|
||||
for test in itertools.chain(
|
||||
self.test_BIP('csv', 536870913, self.sequence_lock_invalidate, self.donothing),
|
||||
self.test_BIP('csv', 536870913, self.mtp_invalidate, self.donothing),
|
||||
self.test_BIP('csv', 536870913, self.donothing, self.csv_invalidate)
|
||||
self.test_BIP('csv', 0x20000001, self.sequence_lock_invalidate, self.donothing, 0),
|
||||
self.test_BIP('csv', 0x20000001, self.mtp_invalidate, self.donothing, 0),
|
||||
self.test_BIP('csv', 0x20000001, self.donothing, self.csv_invalidate, 0)
|
||||
):
|
||||
yield test
|
||||
|
||||
|
@ -457,6 +457,23 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
self.is_network_split=False
|
||||
self.sync_all()
|
||||
|
||||
# drain the keypool
|
||||
self.nodes[1].getnewaddress()
|
||||
inputs = []
|
||||
outputs = {self.nodes[0].getnewaddress():1.1}
|
||||
rawTx = self.nodes[1].createrawtransaction(inputs, outputs)
|
||||
# fund a transaction that requires a new key for the change output
|
||||
# creating the key must be impossible because the wallet is locked
|
||||
try:
|
||||
fundedTx = self.nodes[1].fundrawtransaction(rawTx)
|
||||
raise AssertionError("Wallet unlocked without passphrase")
|
||||
except JSONRPCException as e:
|
||||
assert('Keypool ran out' in e.error['message'])
|
||||
|
||||
#refill the keypool
|
||||
self.nodes[1].walletpassphrase("test", 100)
|
||||
self.nodes[1].walletlock()
|
||||
|
||||
try:
|
||||
self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 12)
|
||||
raise AssertionError("Wallet unlocked without passphrase")
|
||||
|
@ -16,6 +16,7 @@ enum DeploymentPos
|
||||
{
|
||||
DEPLOYMENT_TESTDUMMY,
|
||||
DEPLOYMENT_CSV, // Deployment of BIP68, BIP112, and BIP113.
|
||||
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in versionbits.cpp
|
||||
MAX_VERSION_BITS_DEPLOYMENTS
|
||||
};
|
||||
|
||||
|
@ -2474,7 +2474,7 @@ void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const
|
||||
}
|
||||
|
||||
// Protected by cs_main
|
||||
static VersionBitsCache versionbitscache;
|
||||
VersionBitsCache versionbitscache;
|
||||
|
||||
int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params)
|
||||
{
|
||||
@ -3470,6 +3470,7 @@ bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensus
|
||||
|
||||
InvalidChainFound(pindex);
|
||||
mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS);
|
||||
uiInterface.NotifyBlockTip(IsInitialBlockDownload(), pindex->pprev);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -839,6 +839,8 @@ extern CBlockTreeDB *pblocktree;
|
||||
*/
|
||||
int GetSpendHeight(const CCoinsViewCache& inputs);
|
||||
|
||||
extern VersionBitsCache versionbitscache;
|
||||
|
||||
/**
|
||||
* Determine what nVersion a new block should use.
|
||||
*/
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "chain.h"
|
||||
#include "chainparams.h"
|
||||
#include "consensus/consensus.h"
|
||||
#include "consensus/params.h"
|
||||
#include "consensus/validation.h"
|
||||
#include "core_io.h"
|
||||
#include "init.h"
|
||||
@ -326,6 +327,15 @@ static UniValue BIP22ValidationResult(const CValidationState& state)
|
||||
return "valid?";
|
||||
}
|
||||
|
||||
std::string gbt_vb_name(const Consensus::DeploymentPos pos) {
|
||||
const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
|
||||
std::string s = vbinfo.name;
|
||||
if (!vbinfo.gbt_force) {
|
||||
s.insert(s.begin(), '!');
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
UniValue getblocktemplate(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() > 1)
|
||||
@ -333,7 +343,9 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
|
||||
"getblocktemplate ( \"jsonrequestobject\" )\n"
|
||||
"\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n"
|
||||
"It returns data needed to construct a block to work on.\n"
|
||||
"See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"
|
||||
"For full specification, see BIPs 22 and 9:\n"
|
||||
" https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki\n"
|
||||
" https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n"
|
||||
|
||||
"\nArguments:\n"
|
||||
"1. \"jsonrequestobject\" (string, optional) A json object in the following spec\n"
|
||||
@ -349,6 +361,12 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
|
||||
"\nResult:\n"
|
||||
"{\n"
|
||||
" \"version\" : n, (numeric) The block version\n"
|
||||
" \"rules\" : [ \"rulename\", ... ], (array of strings) specific block rules that are to be enforced\n"
|
||||
" \"vbavailable\" : { (json object) set of pending, supported versionbit (BIP 9) softfork deployments\n"
|
||||
" \"rulename\" : bitnumber (numeric) identifies the bit number as indicating acceptance and readiness for the named softfork rule\n"
|
||||
" ,...\n"
|
||||
" },\n"
|
||||
" \"vbrequired\" : n, (numeric) bit mask of versionbits the server requires set in submissions\n"
|
||||
" \"previousblockhash\" : \"xxxx\", (string) The hash of current highest block\n"
|
||||
" \"transactions\" : [ (array) contents of non-coinbase transactions that should be included in the next block\n"
|
||||
" {\n"
|
||||
@ -409,6 +427,8 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
|
||||
|
||||
std::string strMode = "template";
|
||||
UniValue lpval = NullUniValue;
|
||||
std::set<std::string> setClientRules;
|
||||
int64_t nMaxVersionPreVB = -1;
|
||||
if (params.size() > 0)
|
||||
{
|
||||
const UniValue& oparam = params[0].get_obj();
|
||||
@ -452,6 +472,20 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
|
||||
TestBlockValidity(state, Params(), block, pindexPrev, false, true);
|
||||
return BIP22ValidationResult(state);
|
||||
}
|
||||
|
||||
const UniValue& aClientRules = find_value(oparam, "rules");
|
||||
if (aClientRules.isArray()) {
|
||||
for (unsigned int i = 0; i < aClientRules.size(); ++i) {
|
||||
const UniValue& v = aClientRules[i];
|
||||
setClientRules.insert(v.get_str());
|
||||
}
|
||||
} else {
|
||||
// NOTE: It is important that this NOT be read if versionbits is supported
|
||||
const UniValue& uvMaxVersion = find_value(oparam, "maxversion");
|
||||
if (uvMaxVersion.isNum()) {
|
||||
nMaxVersionPreVB = uvMaxVersion.get_int64();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strMode != "template")
|
||||
@ -544,9 +578,10 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
|
||||
pindexPrev = pindexPrevNew;
|
||||
}
|
||||
CBlock* pblock = &pblocktemplate->block; // pointer for convenience
|
||||
const Consensus::Params& consensusParams = Params().GetConsensus();
|
||||
|
||||
// Update nTime
|
||||
UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
|
||||
UpdateTime(pblock, consensusParams, pindexPrev);
|
||||
pblock->nNonce = 0;
|
||||
|
||||
UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
|
||||
@ -587,17 +622,69 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
|
||||
|
||||
arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
|
||||
|
||||
static UniValue aMutable(UniValue::VARR);
|
||||
if (aMutable.empty())
|
||||
{
|
||||
aMutable.push_back("time");
|
||||
aMutable.push_back("transactions");
|
||||
aMutable.push_back("prevblock");
|
||||
}
|
||||
UniValue aMutable(UniValue::VARR);
|
||||
aMutable.push_back("time");
|
||||
aMutable.push_back("transactions");
|
||||
aMutable.push_back("prevblock");
|
||||
|
||||
UniValue result(UniValue::VOBJ);
|
||||
result.push_back(Pair("capabilities", aCaps));
|
||||
|
||||
UniValue aRules(UniValue::VARR);
|
||||
UniValue vbavailable(UniValue::VOBJ);
|
||||
for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++i) {
|
||||
Consensus::DeploymentPos pos = Consensus::DeploymentPos(i);
|
||||
ThresholdState state = VersionBitsState(pindexPrev, consensusParams, pos, versionbitscache);
|
||||
switch (state) {
|
||||
case THRESHOLD_DEFINED:
|
||||
case THRESHOLD_FAILED:
|
||||
// Not exposed to GBT at all
|
||||
break;
|
||||
case THRESHOLD_LOCKED_IN:
|
||||
// Ensure bit is set in block version
|
||||
pblock->nVersion |= VersionBitsMask(consensusParams, pos);
|
||||
// FALL THROUGH to get vbavailable set...
|
||||
case THRESHOLD_STARTED:
|
||||
{
|
||||
const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
|
||||
vbavailable.push_back(Pair(gbt_vb_name(pos), consensusParams.vDeployments[pos].bit));
|
||||
if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
|
||||
if (!vbinfo.gbt_force) {
|
||||
// If the client doesn't support this, don't indicate it in the [default] version
|
||||
pblock->nVersion &= ~VersionBitsMask(consensusParams, pos);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case THRESHOLD_ACTIVE:
|
||||
{
|
||||
// Add to rules only
|
||||
const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
|
||||
aRules.push_back(gbt_vb_name(pos));
|
||||
if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
|
||||
// Not supported by the client; make sure it's safe to proceed
|
||||
if (!vbinfo.gbt_force) {
|
||||
// If we do anything other than throw an exception here, be sure version/force isn't sent to old clients
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Support for '%s' rule requires explicit client support", vbinfo.name));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
result.push_back(Pair("version", pblock->nVersion));
|
||||
result.push_back(Pair("rules", aRules));
|
||||
result.push_back(Pair("vbavailable", vbavailable));
|
||||
result.push_back(Pair("vbrequired", int(0)));
|
||||
|
||||
if (nMaxVersionPreVB >= 2) {
|
||||
// If VB is supported by the client, nMaxVersionPreVB is -1, so we won't get here
|
||||
// Because BIP 34 changed how the generation transaction is serialised, we can only use version/force back to v2 blocks
|
||||
// This is safe to do [otherwise-]unconditionally only because we are throwing an exception above if a non-force deployment gets activated
|
||||
// Note that this can probably also be removed entirely after the first BIP9 non-force deployment (ie, probably segwit) gets activated
|
||||
aMutable.push_back("version/force");
|
||||
}
|
||||
|
||||
result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
|
||||
result.push_back(Pair("transactions", transactions));
|
||||
result.push_back(Pair("coinbaseaux", aux));
|
||||
|
@ -465,7 +465,7 @@ void TorController::auth_cb(TorControlConnection& conn, const TorControlReply& r
|
||||
|
||||
// Finally - now create the service
|
||||
if (private_key.empty()) // No private key, generate one
|
||||
private_key = "NEW:BEST";
|
||||
private_key = "NEW:RSA1024"; // Explicitly request RSA1024 - see issue #9214
|
||||
// Request hidden service, redirect port.
|
||||
// Note that the 'virtual' port doesn't have to be the same as our internal port, but this is just a convenient
|
||||
// choice. TODO; refactor the shutdown sequence some day.
|
||||
|
@ -4,6 +4,19 @@
|
||||
|
||||
#include "versionbits.h"
|
||||
|
||||
#include "consensus/params.h"
|
||||
|
||||
const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = {
|
||||
{
|
||||
/*.name =*/ "testdummy",
|
||||
/*.gbt_force =*/ true,
|
||||
},
|
||||
{
|
||||
/*.name =*/ "csv",
|
||||
/*.gbt_force =*/ true,
|
||||
}
|
||||
};
|
||||
|
||||
ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
|
||||
{
|
||||
int nPeriod = Period(params);
|
||||
|
@ -30,6 +30,15 @@ enum ThresholdState {
|
||||
// will either be NULL or a block with (height + 1) % Period() == 0.
|
||||
typedef std::map<const CBlockIndex*, ThresholdState> ThresholdConditionCache;
|
||||
|
||||
struct BIP9DeploymentInfo {
|
||||
/** Deployment name */
|
||||
const char *name;
|
||||
/** Whether GBT clients can safely ignore this rule in simplified usage */
|
||||
bool gbt_force;
|
||||
};
|
||||
|
||||
extern const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[];
|
||||
|
||||
/**
|
||||
* Abstract class that implements BIP9-style threshold logic, and caches results.
|
||||
*/
|
||||
|
@ -667,8 +667,8 @@ UniValue getreceivedbyaddress(const UniValue& params, bool fHelp)
|
||||
if (!address.IsValid())
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Dash address");
|
||||
CScript scriptPubKey = GetScriptForDestination(address.Get());
|
||||
if (!IsMine(*pwalletMain,scriptPubKey))
|
||||
return (double)0.0;
|
||||
if (!IsMine(*pwalletMain, scriptPubKey))
|
||||
return ValueFromAmount(0);
|
||||
|
||||
// Minimum confirmations
|
||||
int nMinDepth = 1;
|
||||
@ -746,7 +746,7 @@ UniValue getreceivedbyaccount(const UniValue& params, bool fHelp)
|
||||
}
|
||||
}
|
||||
|
||||
return (double)nAmount / (double)COIN;
|
||||
return ValueFromAmount(nAmount);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3070,10 +3070,11 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
||||
|
||||
// Reserve a new key pair from key pool
|
||||
CPubKey vchPubKey;
|
||||
bool ret;
|
||||
ret = reservekey.GetReservedKey(vchPubKey);
|
||||
assert(ret); // should never fail, as we just unlocked
|
||||
|
||||
if (!reservekey.GetReservedKey(vchPubKey))
|
||||
{
|
||||
strFailReason = _("Keypool ran out, please call keypoolrefill first");
|
||||
return false;
|
||||
}
|
||||
scriptChange = GetScriptForDestination(vchPubKey.GetID());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user