aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/clientversion.h2
-rw-r--r--src/consensus/consensus.h4
-rw-r--r--src/indirectmap.h4
-rw-r--r--src/init.cpp8
-rw-r--r--src/key.h3
-rw-r--r--src/main.cpp86
-rw-r--r--src/main.h11
-rw-r--r--src/miner.cpp145
-rw-r--r--src/miner.h17
-rw-r--r--src/policy/policy.cpp23
-rw-r--r--src/policy/policy.h25
-rw-r--r--src/primitives/block.cpp6
-rw-r--r--src/primitives/block.h4
-rw-r--r--src/primitives/transaction.cpp4
-rw-r--r--src/primitives/transaction.h4
-rw-r--r--src/qt/bitcoinstrings.cpp3
-rw-r--r--src/qt/locale/bitcoin_de.ts4
-rw-r--r--src/qt/locale/bitcoin_en.ts43
-rw-r--r--src/qt/locale/bitcoin_es_MX.ts12
-rw-r--r--src/qt/locale/bitcoin_es_UY.ts2
-rw-r--r--src/qt/locale/bitcoin_fa.ts74
-rw-r--r--src/qt/locale/bitcoin_pl.ts2
-rw-r--r--src/qt/locale/bitcoin_pt_BR.ts4
-rw-r--r--src/qt/locale/bitcoin_pt_PT.ts8
-rw-r--r--src/qt/locale/bitcoin_tr.ts32
-rw-r--r--src/rpc/blockchain.cpp4
-rw-r--r--src/rpc/mining.cpp12
-rw-r--r--src/rpc/misc.cpp8
-rw-r--r--src/txmempool.cpp4
-rw-r--r--src/txmempool.h4
-rw-r--r--src/wallet/rpcdump.cpp29
-rw-r--r--src/wallet/rpcwallet.cpp22
-rw-r--r--src/wallet/wallet.cpp7
-rw-r--r--src/wallet/wallet.h10
-rw-r--r--src/wallet/walletdb.h17
35 files changed, 408 insertions, 239 deletions
diff --git a/src/clientversion.h b/src/clientversion.h
index 47263d5344..53ad460346 100644
--- a/src/clientversion.h
+++ b/src/clientversion.h
@@ -15,7 +15,7 @@
//! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it
#define CLIENT_VERSION_MAJOR 0
-#define CLIENT_VERSION_MINOR 12
+#define CLIENT_VERSION_MINOR 13
#define CLIENT_VERSION_REVISION 99
#define CLIENT_VERSION_BUILD 0
diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h
index 81f40593b2..6908565866 100644
--- a/src/consensus/consensus.h
+++ b/src/consensus/consensus.h
@@ -10,8 +10,8 @@
/** The maximum allowed size for a serialized block, in bytes (only for buffer size limits) */
static const unsigned int MAX_BLOCK_SERIALIZED_SIZE = 4000000;
-/** The maximum allowed cost for a block, see BIP 141 (network rule) */
-static const unsigned int MAX_BLOCK_COST = 4000000;
+/** The maximum allowed weight for a block, see BIP 141 (network rule) */
+static const unsigned int MAX_BLOCK_WEIGHT = 4000000;
/** The maximum allowed size for a block excluding witness data, in bytes (network rule) */
static const unsigned int MAX_BLOCK_BASE_SIZE = 1000000;
/** The maximum allowed number of signature check operations in a block (network rule) */
diff --git a/src/indirectmap.h b/src/indirectmap.h
index 28e1e8dedd..76da4a6bd5 100644
--- a/src/indirectmap.h
+++ b/src/indirectmap.h
@@ -1,3 +1,7 @@
+// Copyright (c) 2016 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
#ifndef BITCOIN_INDIRECTMAP_H
#define BITCOIN_INDIRECTMAP_H
diff --git a/src/init.cpp b/src/init.cpp
index 7e91e0ba8b..8d4a2cafbf 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -446,14 +446,13 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageGroup(_("Node relay options:"));
if (showDebug)
strUsage += HelpMessageOpt("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)", "testnet/regtest only; ", !Params(CBaseChainParams::TESTNET).RequireStandard()));
- strUsage += HelpMessageOpt("-bytespersigop", strprintf(_("Minimum bytes per sigop in transactions we relay and mine (default: %u)"), DEFAULT_BYTES_PER_SIGOP));
+ strUsage += HelpMessageOpt("-bytespersigop", strprintf(_("Equivalent bytes per sigop in transactions for relay and mining (default: %u)"), DEFAULT_BYTES_PER_SIGOP));
strUsage += HelpMessageOpt("-datacarrier", strprintf(_("Relay and mine data carrier transactions (default: %u)"), DEFAULT_ACCEPT_DATACARRIER));
strUsage += HelpMessageOpt("-datacarriersize", strprintf(_("Maximum size of data in data carrier transactions we relay and mine (default: %u)"), MAX_OP_RETURN_RELAY));
strUsage += HelpMessageOpt("-mempoolreplacement", strprintf(_("Enable transaction replacement in the memory pool (default: %u)"), DEFAULT_ENABLE_REPLACEMENT));
strUsage += HelpMessageGroup(_("Block creation options:"));
- strUsage += HelpMessageOpt("-blockmaxcost=<n>", strprintf(_("Set maximum block cost (default: %d)"), DEFAULT_BLOCK_MAX_COST));
- strUsage += HelpMessageOpt("-blockminsize=<n>", strprintf(_("Set minimum block size in bytes (default: %u)"), DEFAULT_BLOCK_MIN_SIZE));
+ strUsage += HelpMessageOpt("-blockmaxweight=<n>", strprintf(_("Set maximum BIP141 block weight (default: %d)"), DEFAULT_BLOCK_MAX_WEIGHT));
strUsage += HelpMessageOpt("-blockmaxsize=<n>", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE));
strUsage += HelpMessageOpt("-blockprioritysize=<n>", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE));
if (showDebug)
@@ -877,6 +876,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (GetBoolArg("-whitelistalwaysrelay", false))
InitWarning(_("Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay."));
+ if (mapArgs.count("-blockminsize"))
+ InitWarning("Unsupported argument -blockminsize ignored.");
+
// Checkmempool and checkblockindex default to true in regtest mode
int ratio = std::min<int>(std::max<int>(GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000);
if (ratio != 0) {
diff --git a/src/key.h b/src/key.h
index b4f48d59f5..4e5e208928 100644
--- a/src/key.h
+++ b/src/key.h
@@ -146,9 +146,6 @@ public:
//! Load private key and check that public key matches.
bool Load(CPrivKey& privkey, CPubKey& vchPubKey, bool fSkipCheck);
-
- //! Check whether an element of a signature (r or s) is valid.
- static bool CheckSignatureElement(const unsigned char* vch, int len, bool half);
};
struct CExtKey {
diff --git a/src/main.cpp b/src/main.cpp
index 21092ca2db..8dd703b687 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -74,7 +74,6 @@ bool fHavePruned = false;
bool fPruneMode = false;
bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
bool fRequireStandard = true;
-unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
bool fCheckBlockIndex = false;
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
size_t nCoinCacheUsage = 5000 * 300;
@@ -276,6 +275,8 @@ struct CNodeState {
CBlockIndex *pindexLastCommonBlock;
//! The best header we have sent our peer.
CBlockIndex *pindexBestHeaderSent;
+ //! Length of current-streak of unconnecting headers announcements
+ int nUnconnectingHeaders;
//! Whether we've started headers synchronization with this peer.
bool fSyncStarted;
//! Since when we're stalling block download progress (in microseconds), or 0.
@@ -304,6 +305,7 @@ struct CNodeState {
hashLastUnknownBlock.SetNull();
pindexLastCommonBlock = NULL;
pindexBestHeaderSent = NULL;
+ nUnconnectingHeaders = 0;
fSyncStarted = false;
nStallingSince = 0;
nDownloadingSince = 0;
@@ -691,8 +693,8 @@ bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(c
// have been mined or received.
// 100 orphans, each of which is at most 99,999 bytes big is
// at most 10 megabytes of orphans and somewhat more byprev index (in the worst case):
- unsigned int sz = GetTransactionCost(tx);
- if (sz >= MAX_STANDARD_TX_COST)
+ unsigned int sz = GetTransactionWeight(tx);
+ if (sz >= MAX_STANDARD_TX_WEIGHT)
{
LogPrint("mempool", "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString());
return false;
@@ -785,7 +787,7 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
return true;
if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
return true;
- BOOST_FOREACH(const CTxIn& txin, tx.vin) {
+ for (const auto& txin : tx.vin) {
if (!(txin.nSequence == CTxIn::SEQUENCE_FINAL))
return false;
}
@@ -999,11 +1001,11 @@ bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool
unsigned int GetLegacySigOpCount(const CTransaction& tx)
{
unsigned int nSigOps = 0;
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
+ for (const auto& txin : tx.vin)
{
nSigOps += txin.scriptSig.GetSigOpCount(false);
}
- BOOST_FOREACH(const CTxOut& txout, tx.vout)
+ for (const auto& txout : tx.vout)
{
nSigOps += txout.scriptPubKey.GetSigOpCount(false);
}
@@ -1061,7 +1063,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
// Check for negative or overflow output values
CAmount nValueOut = 0;
- BOOST_FOREACH(const CTxOut& txout, tx.vout)
+ for (const auto& txout : tx.vout)
{
if (txout.nValue < 0)
return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-negative");
@@ -1074,7 +1076,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
// Check for duplicate inputs
set<COutPoint> vInOutPoints;
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
+ for (const auto& txin : tx.vin)
{
if (vInOutPoints.count(txin.prevout))
return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate");
@@ -1088,7 +1090,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
}
else
{
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
+ for (const auto& txin : tx.vin)
if (txin.prevout.IsNull())
return state.DoS(10, false, REJECT_INVALID, "bad-txns-prevout-null");
}
@@ -1141,13 +1143,14 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
}
// Reject transactions with witness before segregated witness activates (override with -prematurewitness)
- if (!GetBoolArg("-prematurewitness",false) && !tx.wit.IsNull() && !IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus())) {
+ bool witnessEnabled = IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus());
+ if (!GetBoolArg("-prematurewitness",false) && !tx.wit.IsNull() && !witnessEnabled) {
return state.DoS(0, false, REJECT_NONSTANDARD, "no-witness-yet", true);
}
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
string reason;
- if (fRequireStandard && !IsStandardTx(tx, reason))
+ if (fRequireStandard && !IsStandardTx(tx, reason, witnessEnabled))
return state.DoS(0, false, REJECT_NONSTANDARD, reason);
// Only accept nLockTime-using transactions that can be mined in the next
@@ -1293,7 +1296,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
// itself can contain sigops MAX_STANDARD_TX_SIGOPS is less than
// MAX_BLOCK_SIGOPS; we still consider this an invalid rather than
// merely non-standard transaction.
- if ((nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST) || (nBytesPerSigOp && nSigOpsCost > nSize * WITNESS_SCALE_FACTOR / nBytesPerSigOp))
+ if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST)
return state.DoS(0, false, REJECT_NONSTANDARD, "bad-txns-too-many-sigops", false,
strprintf("%d", nSigOpsCost));
@@ -3401,13 +3404,13 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
return state.DoS(100, false, REJECT_INVALID, "bad-cb-multiple", false, "more than one coinbase");
// Check transactions
- BOOST_FOREACH(const CTransaction& tx, block.vtx)
+ for (const auto& tx : block.vtx)
if (!CheckTransaction(tx, state))
return state.Invalid(false, state.GetRejectCode(), state.GetRejectReason(),
strprintf("Transaction check failed (tx hash %s) %s", tx.GetHash().ToString(), state.GetDebugMessage()));
unsigned int nSigOps = 0;
- BOOST_FOREACH(const CTransaction& tx, block.vtx)
+ for (const auto& tx : block.vtx)
{
nSigOps += GetLegacySigOpCount(tx);
}
@@ -3499,7 +3502,7 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
return commitment;
}
-bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex * const pindexPrev, int64_t nAdjustedTime)
+bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev, int64_t nAdjustedTime)
{
// Check proof of work
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams))
@@ -3522,7 +3525,7 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
return true;
}
-bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex * const pindexPrev)
+bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const CBlockIndex* pindexPrev)
{
const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1;
const Consensus::Params& consensusParams = Params().GetConsensus();
@@ -3538,7 +3541,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
: block.GetBlockTime();
// Check that all transactions are finalized
- BOOST_FOREACH(const CTransaction& tx, block.vtx) {
+ for (const auto& tx : block.vtx) {
if (!IsFinalTx(tx, nHeight, nLockTimeCutoff)) {
return state.DoS(10, false, REJECT_INVALID, "bad-txns-nonfinal", false, "non-final transaction");
}
@@ -3573,11 +3576,11 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
// already does not permit it, it is impossible to trigger in the
// witness tree.
if (block.vtx[0].wit.vtxinwit.size() != 1 || block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.size() != 1 || block.vtx[0].wit.vtxinwit[0].scriptWitness.stack[0].size() != 32) {
- return state.DoS(100, error("%s : invalid witness nonce size", __func__), REJECT_INVALID, "bad-witness-nonce-size", true);
+ return state.DoS(100, false, REJECT_INVALID, "bad-witness-nonce-size", true, strprintf("%s : invalid witness nonce size", __func__));
}
CHash256().Write(hashWitness.begin(), 32).Write(&block.vtx[0].wit.vtxinwit[0].scriptWitness.stack[0][0], 32).Finalize(hashWitness.begin());
if (memcmp(hashWitness.begin(), &block.vtx[0].vout[commitpos].scriptPubKey[6], 32)) {
- return state.DoS(100, error("%s : witness merkle commitment mismatch", __func__), REJECT_INVALID, "bad-witness-merkle-match", true);
+ return state.DoS(100, false, REJECT_INVALID, "bad-witness-merkle-match", true, strprintf("%s : witness merkle commitment mismatch", __func__));
}
fHaveWitness = true;
}
@@ -3587,19 +3590,19 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
if (!fHaveWitness) {
for (size_t i = 0; i < block.vtx.size(); i++) {
if (!block.vtx[i].wit.IsNull()) {
- return state.DoS(100, error("%s : unexpected witness data found", __func__), REJECT_INVALID, "unexpected-witness", true);
+ return state.DoS(100, false, REJECT_INVALID, "unexpected-witness", true, strprintf("%s : unexpected witness data found", __func__));
}
}
}
// After the coinbase witness nonce and commitment are verified,
- // we can check if the block cost passes (before we've checked the
- // coinbase witness, it would be possible for the cost to be too
+ // we can check if the block weight passes (before we've checked the
+ // coinbase witness, it would be possible for the weight to be too
// large by filling up the coinbase witness, which doesn't change
// the block hash, so we couldn't mark the block as permanently
// failed).
- if (GetBlockCost(block) > MAX_BLOCK_COST) {
- return state.DoS(100, error("ContextualCheckBlock(): cost limit failed"), REJECT_INVALID, "bad-blk-cost");
+ if (GetBlockWeight(block) > MAX_BLOCK_WEIGHT) {
+ return state.DoS(100, false, REJECT_INVALID, "bad-blk-weight", false, strprintf("%s : weight limit failed", __func__));
}
return true;
@@ -5773,6 +5776,35 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
return true;
}
+ CNodeState *nodestate = State(pfrom->GetId());
+
+ // If this looks like it could be a block announcement (nCount <
+ // MAX_BLOCKS_TO_ANNOUNCE), use special logic for handling headers that
+ // don't connect:
+ // - Send a getheaders message in response to try to connect the chain.
+ // - The peer can send up to MAX_UNCONNECTING_HEADERS in a row that
+ // don't connect before giving DoS points
+ // - Once a headers message is received that is valid and does connect,
+ // nUnconnectingHeaders gets reset back to 0.
+ if (mapBlockIndex.find(headers[0].hashPrevBlock) == mapBlockIndex.end() && nCount < MAX_BLOCKS_TO_ANNOUNCE) {
+ nodestate->nUnconnectingHeaders++;
+ pfrom->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256());
+ LogPrint("net", "received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n",
+ headers[0].GetHash().ToString(),
+ headers[0].hashPrevBlock.ToString(),
+ pindexBestHeader->nHeight,
+ pfrom->id, nodestate->nUnconnectingHeaders);
+ // Set hashLastUnknownBlock for this peer, so that if we
+ // eventually get the headers - even from a different peer -
+ // we can use this peer to download.
+ UpdateBlockAvailability(pfrom->GetId(), headers.back().GetHash());
+
+ if (nodestate->nUnconnectingHeaders % MAX_UNCONNECTING_HEADERS == 0) {
+ Misbehaving(pfrom->GetId(), 20);
+ }
+ return true;
+ }
+
CBlockIndex *pindexLast = NULL;
BOOST_FOREACH(const CBlockHeader& header, headers) {
CValidationState state;
@@ -5790,6 +5822,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
}
+ if (nodestate->nUnconnectingHeaders > 0) {
+ LogPrint("net", "peer=%d: resetting nUnconnectingHeaders (%d -> 0)\n", pfrom->id, nodestate->nUnconnectingHeaders);
+ }
+ nodestate->nUnconnectingHeaders = 0;
+
assert(pindexLast);
UpdateBlockAvailability(pfrom->GetId(), pindexLast->GetBlockHash());
@@ -5802,7 +5839,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
bool fCanDirectFetch = CanDirectFetch(chainparams.GetConsensus());
- CNodeState *nodestate = State(pfrom->GetId());
// If this set of headers is valid and ends in a block with at least as
// much work as our tip, download as much as possible.
if (fCanDirectFetch && pindexLast->IsValid(BLOCK_VALID_TREE) && chainActive.Tip()->nChainWork <= pindexLast->nChainWork) {
diff --git a/src/main.h b/src/main.h
index 7ea570d859..26ea6adc6b 100644
--- a/src/main.h
+++ b/src/main.h
@@ -124,7 +124,6 @@ static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60;
/** Default for -permitbaremultisig */
static const bool DEFAULT_PERMIT_BAREMULTISIG = true;
-static const unsigned int DEFAULT_BYTES_PER_SIGOP = 20;
static const bool DEFAULT_CHECKPOINTS_ENABLED = true;
static const bool DEFAULT_TXINDEX = false;
static const unsigned int DEFAULT_BANSCORE_THRESHOLD = 100;
@@ -138,6 +137,9 @@ static const bool DEFAULT_FEEFILTER = true;
/** Maximum number of headers to announce when relaying blocks with headers message.*/
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE = 8;
+/** Maximum number of unconnecting headers announcements before DoS score */
+static const int MAX_UNCONNECTING_HEADERS = 10;
+
static const bool DEFAULT_PEERBLOOMFILTERS = true;
struct BlockHasher
@@ -152,7 +154,7 @@ typedef boost::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
extern BlockMap mapBlockIndex;
extern uint64_t nLastBlockTx;
extern uint64_t nLastBlockSize;
-extern uint64_t nLastBlockCost;
+extern uint64_t nLastBlockWeight;
extern const std::string strMessageMagic;
extern CWaitableCriticalSection csBestBlock;
extern CConditionVariable cvBlockChange;
@@ -162,7 +164,6 @@ extern int nScriptCheckThreads;
extern bool fTxIndex;
extern bool fIsBareMultisigStd;
extern bool fRequireStandard;
-extern unsigned int nBytesPerSigOp;
extern bool fCheckBlockIndex;
extern bool fCheckpointsEnabled;
extern size_t nCoinCacheUsage;
@@ -444,8 +445,8 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
/** Context-dependent validity checks.
* By "context", we mean only the previous block headers, but not the UTXO
* set; UTXO-related validity checks are done in ConnectBlock(). */
-bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex* pindexPrev, int64_t nAdjustedTime);
-bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex *pindexPrev);
+bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev, int64_t nAdjustedTime);
+bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const CBlockIndex* pindexPrev);
/** Apply the effects of this block (with given index) on the UTXO set represented by coins.
* Validity checks that depend on the UTXO set are also done; ConnectBlock()
diff --git a/src/miner.cpp b/src/miner.cpp
index cfc2dae56e..9575858840 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -45,7 +45,7 @@ using namespace std;
uint64_t nLastBlockTx = 0;
uint64_t nLastBlockSize = 0;
-uint64_t nLastBlockCost = 0;
+uint64_t nLastBlockWeight = 0;
class ScoreCompare
{
@@ -77,35 +77,31 @@ BlockAssembler::BlockAssembler(const CChainParams& _chainparams)
: chainparams(_chainparams)
{
// Block resource limits
- // If neither -blockmaxsize or -blockmaxcost is given, limit to DEFAULT_BLOCK_MAX_*
+ // If neither -blockmaxsize or -blockmaxweight is given, limit to DEFAULT_BLOCK_MAX_*
// If only one is given, only restrict the specified resource.
// If both are given, restrict both.
- nBlockMaxCost = DEFAULT_BLOCK_MAX_COST;
+ nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT;
nBlockMaxSize = DEFAULT_BLOCK_MAX_SIZE;
- bool fCostSet = false;
- if (mapArgs.count("-blockmaxcost")) {
- nBlockMaxCost = GetArg("-blockmaxcost", DEFAULT_BLOCK_MAX_COST);
+ bool fWeightSet = false;
+ if (mapArgs.count("-blockmaxweight")) {
+ nBlockMaxWeight = GetArg("-blockmaxweight", DEFAULT_BLOCK_MAX_WEIGHT);
nBlockMaxSize = MAX_BLOCK_SERIALIZED_SIZE;
- fCostSet = true;
+ fWeightSet = true;
}
if (mapArgs.count("-blockmaxsize")) {
nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
- if (!fCostSet) {
- nBlockMaxCost = nBlockMaxSize * WITNESS_SCALE_FACTOR;
+ if (!fWeightSet) {
+ nBlockMaxWeight = nBlockMaxSize * WITNESS_SCALE_FACTOR;
}
}
- // Limit cost to between 4K and MAX_BLOCK_COST-4K for sanity:
- nBlockMaxCost = std::max((unsigned int)4000, std::min((unsigned int)(MAX_BLOCK_COST-4000), nBlockMaxCost));
+
+ // Limit weight to between 4K and MAX_BLOCK_WEIGHT-4K for sanity:
+ nBlockMaxWeight = std::max((unsigned int)4000, std::min((unsigned int)(MAX_BLOCK_WEIGHT-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));
- // Minimum block size you want to create; block will be filled with free transactions
- // until there are no more or the block reaches this size:
- nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE);
- nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize);
-
- // Whether we need to account for byte usage (in addition to cost usage)
- fNeedSizeAccounting = (nBlockMaxSize < MAX_BLOCK_SERIALIZED_SIZE-1000) || (nBlockMinSize > 0);
+ // Whether we need to account for byte usage (in addition to weight usage)
+ fNeedSizeAccounting = (nBlockMaxSize < MAX_BLOCK_SERIALIZED_SIZE-1000);
}
void BlockAssembler::resetBlock()
@@ -114,7 +110,7 @@ void BlockAssembler::resetBlock()
// Reserve space for coinbase tx
nBlockSize = 1000;
- nBlockCost = 4000;
+ nBlockWeight = 4000;
nBlockSigOpsCost = 400;
fIncludeWitness = false;
@@ -167,17 +163,11 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn)
fIncludeWitness = IsWitnessEnabled(pindexPrev, chainparams.GetConsensus());
addPriorityTxs();
- if (fNeedSizeAccounting) {
- // addPackageTxs (the CPFP-based algorithm) cannot deal with size based
- // accounting, so fall back to the old algorithm.
- addScoreTxs();
- } else {
- addPackageTxs();
- }
+ addPackageTxs();
nLastBlockTx = nBlockTx;
nLastBlockSize = nBlockSize;
- nLastBlockCost = nBlockCost;
+ nLastBlockWeight = nBlockWeight;
LogPrintf("CreateNewBlock(): total size %u txs: %u fees: %ld sigops %d\n", nBlockSize, nBlockTx, nFees, nBlockSigOpsCost);
// Create coinbase transaction.
@@ -197,7 +187,7 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn)
UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus());
pblock->nNonce = 0;
- pblocktemplate->vTxSigOpsCost[0] = GetLegacySigOpCount(pblock->vtx[0]);
+ pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(pblock->vtx[0]);
CValidationState state;
if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) {
@@ -233,38 +223,51 @@ void BlockAssembler::onlyUnconfirmed(CTxMemPool::setEntries& testSet)
bool BlockAssembler::TestPackage(uint64_t packageSize, int64_t packageSigOpsCost)
{
- // TODO: switch to cost-based accounting for packages instead of vsize-based accounting.
- if (nBlockCost + WITNESS_SCALE_FACTOR * packageSize >= nBlockMaxCost)
+ // 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 >= MAX_BLOCK_SIGOPS_COST)
return false;
return true;
}
-// Block size and sigops have already been tested. Check that all transactions
-// are final.
-bool BlockAssembler::TestPackageFinality(const CTxMemPool::setEntries& package)
+// Perform transaction-level checks before adding to block:
+// - transaction finality (locktime)
+// - premature witness (in case segwit transactions are added to mempool before
+// segwit activation)
+// - serialized size (in case -blockmaxsize is in use)
+bool BlockAssembler::TestPackageTransactions(const CTxMemPool::setEntries& package)
{
+ uint64_t nPotentialBlockSize = nBlockSize; // only used with fNeedSizeAccounting
BOOST_FOREACH (const CTxMemPool::txiter it, package) {
if (!IsFinalTx(it->GetTx(), nHeight, nLockTimeCutoff))
return false;
+ if (!fIncludeWitness && !it->GetTx().wit.IsNull())
+ return false;
+ if (fNeedSizeAccounting) {
+ uint64_t nTxSize = ::GetSerializeSize(it->GetTx(), SER_NETWORK, PROTOCOL_VERSION);
+ if (nPotentialBlockSize + nTxSize >= nBlockMaxSize) {
+ return false;
+ }
+ nPotentialBlockSize += nTxSize;
+ }
}
return true;
}
bool BlockAssembler::TestForBlock(CTxMemPool::txiter iter)
{
- if (nBlockCost + iter->GetTxCost() >= nBlockMaxCost) {
+ if (nBlockWeight + iter->GetTxWeight() >= nBlockMaxWeight) {
// If the block is so close to full that no more txs will fit
// or if we've tried more than 50 times to fill remaining space
// then flag that the block is finished
- if (nBlockCost > nBlockMaxCost - 400 || lastFewTxs > 50) {
+ if (nBlockWeight > nBlockMaxWeight - 400 || lastFewTxs > 50) {
blockFinished = true;
return false;
}
- // Once we're within 4000 cost of a full block, only look at 50 more txs
+ // Once we're within 4000 weight of a full block, only look at 50 more txs
// to try to fill the remaining space.
- if (nBlockCost > nBlockMaxCost - 4000) {
+ if (nBlockWeight > nBlockMaxWeight - 4000) {
lastFewTxs++;
}
return false;
@@ -312,7 +315,7 @@ void BlockAssembler::AddToBlock(CTxMemPool::txiter iter)
if (fNeedSizeAccounting) {
nBlockSize += ::GetSerializeSize(iter->GetTx(), SER_NETWORK, PROTOCOL_VERSION);
}
- nBlockCost += iter->GetTxCost();
+ nBlockWeight += iter->GetTxWeight();
++nBlockTx;
nBlockSigOpsCost += iter->GetSigOpCost();
nFees += iter->GetFee();
@@ -330,66 +333,6 @@ void BlockAssembler::AddToBlock(CTxMemPool::txiter iter)
}
}
-void BlockAssembler::addScoreTxs()
-{
- std::priority_queue<CTxMemPool::txiter, std::vector<CTxMemPool::txiter>, ScoreCompare> clearedTxs;
- CTxMemPool::setEntries waitSet;
- CTxMemPool::indexed_transaction_set::index<mining_score>::type::iterator mi = mempool.mapTx.get<mining_score>().begin();
- CTxMemPool::txiter iter;
- while (!blockFinished && (mi != mempool.mapTx.get<mining_score>().end() || !clearedTxs.empty()))
- {
- // If no txs that were previously postponed are available to try
- // again, then try the next highest score tx
- if (clearedTxs.empty()) {
- iter = mempool.mapTx.project<0>(mi);
- mi++;
- }
- // If a previously postponed tx is available to try again, then it
- // has higher score than all untried so far txs
- else {
- iter = clearedTxs.top();
- clearedTxs.pop();
- }
-
- // If tx already in block, skip (added by addPriorityTxs)
- if (inBlock.count(iter)) {
- continue;
- }
-
- // cannot accept witness transactions into a non-witness block
- if (!fIncludeWitness && !iter->GetTx().wit.IsNull())
- continue;
-
- // If tx is dependent on other mempool txs which haven't yet been included
- // then put it in the waitSet
- if (isStillDependent(iter)) {
- waitSet.insert(iter);
- continue;
- }
-
- // If the fee rate is below the min fee rate for mining, then we're done
- // adding txs based on score (fee rate)
- if (iter->GetModifiedFee() < ::minRelayTxFee.GetFee(iter->GetTxSize()) && nBlockSize >= nBlockMinSize) {
- return;
- }
-
- // If this tx fits in the block add it, otherwise keep looping
- if (TestForBlock(iter)) {
- AddToBlock(iter);
-
- // This tx was successfully added, so
- // add transactions that depend on this one to the priority queue to try again
- BOOST_FOREACH(CTxMemPool::txiter child, mempool.GetMemPoolChildren(iter))
- {
- if (waitSet.count(child)) {
- clearedTxs.push(child);
- waitSet.erase(child);
- }
- }
- }
- }
-}
-
void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded,
indexed_modified_transaction_set &mapModifiedTx)
{
@@ -539,7 +482,7 @@ void BlockAssembler::addPackageTxs()
ancestors.insert(iter);
// Test if all tx's are Final
- if (!TestPackageFinality(ancestors)) {
+ if (!TestPackageTransactions(ancestors)) {
if (fUsingModified) {
mapModifiedTx.get<ancestor_score>().erase(modit);
failedTx.insert(iter);
@@ -573,6 +516,7 @@ void BlockAssembler::addPriorityTxs()
return;
}
+ bool fSizeAccounting = fNeedSizeAccounting;
fNeedSizeAccounting = true;
// This vector will be sorted into a priority queue:
@@ -624,7 +568,7 @@ void BlockAssembler::addPriorityTxs()
// If now that this txs is added we've surpassed our desired priority size
// or have dropped below the AllowFreeThreshold, then we're done adding priority txs
if (nBlockSize >= nBlockPrioritySize || !AllowFree(actualPriority)) {
- return;
+ break;
}
// This tx was successfully added, so
@@ -640,6 +584,7 @@ void BlockAssembler::addPriorityTxs()
}
}
}
+ fNeedSizeAccounting = fSizeAccounting;
}
void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
diff --git a/src/miner.h b/src/miner.h
index b303a8fa3c..11753f5e43 100644
--- a/src/miner.h
+++ b/src/miner.h
@@ -141,11 +141,11 @@ private:
// Configuration parameters for the block size
bool fIncludeWitness;
- unsigned int nBlockMaxCost, nBlockMaxSize, nBlockMinSize;
+ unsigned int nBlockMaxWeight, nBlockMaxSize;
bool fNeedSizeAccounting;
// Information on the current status of the block
- uint64_t nBlockCost;
+ uint64_t nBlockWeight;
uint64_t nBlockSize;
uint64_t nBlockTx;
uint64_t nBlockSigOpsCost;
@@ -157,7 +157,7 @@ private:
int64_t nLockTimeCutoff;
const CChainParams& chainparams;
- // Variables used for addScoreTxs and addPriorityTxs
+ // Variables used for addPriorityTxs
int lastFewTxs;
bool blockFinished;
@@ -174,14 +174,12 @@ private:
void AddToBlock(CTxMemPool::txiter iter);
// Methods for how to add transactions to a block.
- /** Add transactions based on modified feerate */
- void addScoreTxs();
/** Add transactions based on tx "priority" */
void addPriorityTxs();
/** Add transactions based on feerate including unconfirmed ancestors */
void addPackageTxs();
- // helper function for addScoreTxs and addPriorityTxs
+ // helper function for addPriorityTxs
/** Test if tx will still "fit" in the block */
bool TestForBlock(CTxMemPool::txiter iter);
/** Test if tx still has unconfirmed parents not yet in block */
@@ -192,8 +190,11 @@ private:
void onlyUnconfirmed(CTxMemPool::setEntries& testSet);
/** Test if a new package would "fit" in the block */
bool TestPackage(uint64_t packageSize, int64_t packageSigOpsCost);
- /** Test if a set of transactions are all final */
- bool TestPackageFinality(const CTxMemPool::setEntries& package);
+ /** Perform checks on each transaction in a package:
+ * locktime, premature-witness, serialized size (if necessary)
+ * These checks should always succeed, and they're here
+ * only as an extra check in case of suboptimal node configuration */
+ bool TestPackageTransactions(const CTxMemPool::setEntries& package);
/** Return true if given transaction from mapTx has already been evaluated,
* or if the transaction's cached data in mapTx is incorrect. */
bool SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx);
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index f2148bfe10..48080abc77 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -31,7 +31,7 @@
* DUP CHECKSIG DROP ... repeated 100 times... OP_1
*/
-bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
+bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType, const bool witnessEnabled)
{
std::vector<std::vector<unsigned char> > vSolutions;
if (!Solver(scriptPubKey, whichType, vSolutions))
@@ -50,10 +50,13 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
(!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes))
return false;
+ else if (!witnessEnabled && (whichType == TX_WITNESS_V0_KEYHASH || whichType == TX_WITNESS_V0_SCRIPTHASH))
+ return false;
+
return whichType != TX_NONSTANDARD;
}
-bool IsStandardTx(const CTransaction& tx, std::string& reason)
+bool IsStandardTx(const CTransaction& tx, std::string& reason, const bool witnessEnabled)
{
if (tx.nVersion > CTransaction::MAX_STANDARD_VERSION || tx.nVersion < 1) {
reason = "version";
@@ -64,8 +67,8 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason)
// almost as much to process as they cost the sender in fees, because
// computing signature hashes is O(ninputs*txsize). Limiting transactions
// to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks.
- unsigned int sz = GetTransactionCost(tx);
- if (sz >= MAX_STANDARD_TX_COST) {
+ unsigned int sz = GetTransactionWeight(tx);
+ if (sz >= MAX_STANDARD_TX_WEIGHT) {
reason = "tx-size";
return false;
}
@@ -92,7 +95,7 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason)
unsigned int nDataOut = 0;
txnouttype whichType;
BOOST_FOREACH(const CTxOut& txout, tx.vout) {
- if (!::IsStandard(txout.scriptPubKey, whichType)) {
+ if (!::IsStandard(txout.scriptPubKey, whichType, witnessEnabled)) {
reason = "scriptpubkey";
return false;
}
@@ -151,12 +154,14 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
return true;
}
-int64_t GetVirtualTransactionSize(int64_t nCost)
+unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
+
+int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost)
{
- return (nCost + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
+ return (std::max(nWeight, nSigOpCost * nBytesPerSigOp) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
}
-int64_t GetVirtualTransactionSize(const CTransaction& tx)
+int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost)
{
- return GetVirtualTransactionSize(GetTransactionCost(tx));
+ return GetVirtualTransactionSize(GetTransactionWeight(tx), nSigOpCost);
}
diff --git a/src/policy/policy.h b/src/policy/policy.h
index fefb562ff9..6bf5ca0ee5 100644
--- a/src/policy/policy.h
+++ b/src/policy/policy.h
@@ -14,21 +14,22 @@
class CCoinsViewCache;
-/** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/
+/** Default for -blockmaxsize, which controls the maximum size of block the mining code will create **/
static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000;
-static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0;
/** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/
static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 0;
-/** Default for -blockmaxcost, which control the range of block costs the mining code will create **/
-static const unsigned int DEFAULT_BLOCK_MAX_COST = 3000000;
-/** The maximum size for transactions we're willing to relay/mine */
-static const unsigned int MAX_STANDARD_TX_COST = 400000;
+/** Default for -blockmaxweight, which controls the range of block weights the mining code will create **/
+static const unsigned int DEFAULT_BLOCK_MAX_WEIGHT = 3000000;
+/** The maximum weight for transactions we're willing to relay/mine */
+static const unsigned int MAX_STANDARD_TX_WEIGHT = 400000;
/** Maximum number of signature check operations in an IsStandard() P2SH script */
static const unsigned int MAX_P2SH_SIGOPS = 15;
/** The maximum number of sigops we're willing to relay/mine in a single tx */
static const unsigned int MAX_STANDARD_TX_SIGOPS_COST = MAX_BLOCK_SIGOPS_COST/5;
/** Default for -maxmempool, maximum megabytes of mempool memory usage */
static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300;
+/** Default for -bytespersigop */
+static const unsigned int DEFAULT_BYTES_PER_SIGOP = 20;
/**
* Standard script verification flags that standard transactions will comply
* with. However scripts violating these flags may still be present in valid
@@ -54,12 +55,12 @@ static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_
static const unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS = LOCKTIME_VERIFY_SEQUENCE |
LOCKTIME_MEDIAN_TIME_PAST;
-bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType);
+bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType, const bool witnessEnabled = false);
/**
* Check for standard transaction types
* @return True if all outputs (scriptPubKeys) use only standard transaction forms
*/
-bool IsStandardTx(const CTransaction& tx, std::string& reason);
+bool IsStandardTx(const CTransaction& tx, std::string& reason, const bool witnessEnabled = false);
/**
* Check for standard transaction types
* @param[in] mapInputs Map of previous transactions that have outputs we're spending
@@ -67,8 +68,10 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason);
*/
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
-/** Compute the virtual transaction size (cost reinterpreted as bytes). */
-int64_t GetVirtualTransactionSize(int64_t nCost);
-int64_t GetVirtualTransactionSize(const CTransaction& tx);
+extern unsigned int nBytesPerSigOp;
+
+/** Compute the virtual transaction size (weight reinterpreted as bytes). */
+int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost);
+int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost = 0);
#endif // BITCOIN_POLICY_POLICY_H
diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp
index df900388f2..0e6ab4dd71 100644
--- a/src/primitives/block.cpp
+++ b/src/primitives/block.cpp
@@ -32,11 +32,11 @@ std::string CBlock::ToString() const
return s.str();
}
-int64_t GetBlockCost(const CBlock& block)
+int64_t GetBlockWeight(const CBlock& block)
{
- // This implements the cost = (stripped_size * 4) + witness_size formula,
+ // This implements the weight = (stripped_size * 4) + witness_size formula,
// using only serialization with and without witness data. As witness_size
// is equal to total_size - stripped_size, this formula is identical to:
- // cost = (stripped_size * 3) + total_size.
+ // weight = (stripped_size * 3) + total_size.
return ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION);
}
diff --git a/src/primitives/block.h b/src/primitives/block.h
index e2a309e63d..72dfed985a 100644
--- a/src/primitives/block.h
+++ b/src/primitives/block.h
@@ -154,7 +154,7 @@ struct CBlockLocator
}
};
-/** Compute the consensus-critical block cost (see BIP 141). */
-int64_t GetBlockCost(const CBlock& tx);
+/** Compute the consensus-critical block weight (see BIP 141). */
+int64_t GetBlockWeight(const CBlock& tx);
#endif // BITCOIN_PRIMITIVES_BLOCK_H
diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp
index 7f10409c05..8d63805643 100644
--- a/src/primitives/transaction.cpp
+++ b/src/primitives/transaction.cpp
@@ -121,7 +121,7 @@ unsigned int CTransaction::CalculateModifiedSize(unsigned int nTxSize) const
// Providing any more cleanup incentive than making additional inputs free would
// risk encouraging people to create junk outputs to redeem later.
if (nTxSize == 0)
- nTxSize = (GetTransactionCost(*this) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
+ nTxSize = (GetTransactionWeight(*this) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
for (std::vector<CTxIn>::const_iterator it(vin.begin()); it != vin.end(); ++it)
{
unsigned int offset = 41U + std::min(110U, (unsigned int)it->scriptSig.size());
@@ -149,7 +149,7 @@ std::string CTransaction::ToString() const
return str;
}
-int64_t GetTransactionCost(const CTransaction& tx)
+int64_t GetTransactionWeight(const CTransaction& tx)
{
return ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR -1) + ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
}
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index 8a2d5dd22c..d37890667f 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -459,7 +459,7 @@ struct CMutableTransaction
uint256 GetHash() const;
};
-/** Compute the cost of a transaction, as defined by BIP 141 */
-int64_t GetTransactionCost(const CTransaction &tx);
+/** Compute the weight of a transaction, as defined by BIP 141 */
+int64_t GetTransactionWeight(const CTransaction &tx);
#endif // BITCOIN_PRIMITIVES_TRANSACTION_H
diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp
index 9c5b1e09d4..bca5b72827 100644
--- a/src/qt/bitcoinstrings.cpp
+++ b/src/qt/bitcoinstrings.cpp
@@ -311,9 +311,8 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Send trace/debug info to console instead of d
QT_TRANSLATE_NOOP("bitcoin-core", "Send transactions as zero-fee transactions if possible (default: %u)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Set database cache size in megabytes (%d to %d, default: %d)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Set key pool size to <n> (default: %u)"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Set maximum block cost (default: %d)"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Set maximum BIP141 block cost (default: %d)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Set maximum block size in bytes (default: %d)"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Set minimum block size in bytes (default: %u)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Set the number of threads to service RPC calls (default: %d)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Show all debugging options (usage: --help -help-debug)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Shrink debug.log file on client startup (default: 1 when no -debug)"),
diff --git a/src/qt/locale/bitcoin_de.ts b/src/qt/locale/bitcoin_de.ts
index f38f4c10f7..2708324d17 100644
--- a/src/qt/locale/bitcoin_de.ts
+++ b/src/qt/locale/bitcoin_de.ts
@@ -2007,6 +2007,10 @@
<translation>Nur zu Knoten des Netzwerktyps &lt;net&gt; verbinden (ipv4, ipv6 oder onion)</translation>
</message>
<message>
+ <source>Print this help message and exit</source>
+ <translation>Drucke diese Hilfemeldung und beende</translation>
+ </message>
+ <message>
<source>Print version and exit</source>
<translation>Gibt die Versionsnummer aus und beendet das Programm</translation>
</message>
diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts
index c6f3a4013c..79c3e87b2b 100644
--- a/src/qt/locale/bitcoin_en.ts
+++ b/src/qt/locale/bitcoin_en.ts
@@ -1218,12 +1218,12 @@
<translation type="unfinished">Amount</translation>
</message>
<message>
- <location filename="../guiutil.cpp" line="+118"/>
+ <location filename="../guiutil.cpp" line="+135"/>
<source>Enter a Bitcoin address (e.g. %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+763"/>
+ <location line="+764"/>
<source>%1 d</source>
<translation type="unfinished"></translation>
</message>
@@ -2231,22 +2231,22 @@
<translation>Options:</translation>
</message>
<message>
- <location line="+31"/>
+ <location line="+30"/>
<source>Specify data directory</source>
<translation>Specify data directory</translation>
</message>
<message>
- <location line="-90"/>
+ <location line="-89"/>
<source>Connect to a node to retrieve peer addresses, and disconnect</source>
<translation>Connect to a node to retrieve peer addresses, and disconnect</translation>
</message>
<message>
- <location line="+93"/>
+ <location line="+92"/>
<source>Specify your own public address</source>
<translation>Specify your own public address</translation>
</message>
<message>
- <location line="-109"/>
+ <location line="-108"/>
<source>Accept command line and JSON-RPC commands</source>
<translation>Accept command line and JSON-RPC commands</translation>
</message>
@@ -2296,12 +2296,12 @@
<translation>Run in the background as a daemon and accept commands</translation>
</message>
<message>
- <location line="+31"/>
+ <location line="+30"/>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-122"/>
+ <location line="-121"/>
<source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
<translation>Accept connections from outside (default: 1 if no -proxy or -connect)</translation>
</message>
@@ -2686,17 +2686,12 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
- <source>Set maximum block cost (default: %d)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
+ <location line="+3"/>
<source>Set maximum block size in bytes (default: %d)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+10"/>
+ <location line="+9"/>
<source>Specify wallet file (within data directory)</source>
<translation>Specify wallet file (within data directory)</translation>
</message>
@@ -2766,7 +2761,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-322"/>
+ <location line="-321"/>
<source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times</source>
<translation type="unfinished"></translation>
</message>
@@ -2946,7 +2941,12 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+7"/>
+ <location line="+3"/>
+ <source>Set maximum BIP141 block cost (default: %d)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
<source>Show all debugging options (usage: --help -help-debug)</source>
<translation type="unfinished"></translation>
</message>
@@ -3041,7 +3041,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-66"/>
+ <location line="-65"/>
<source>Password for JSON-RPC connections</source>
<translation>Password for JSON-RPC connections</translation>
</message>
@@ -3227,11 +3227,6 @@
</message>
<message>
<location line="+3"/>
- <source>Set minimum block size in bytes (default: %u)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
<source>Set the number of threads to service RPC calls (default: %d)</source>
<translation type="unfinished"></translation>
</message>
@@ -3266,7 +3261,7 @@
<translation>Unknown network specified in -onlynet: &apos;%s&apos;</translation>
</message>
<message>
- <location line="-74"/>
+ <location line="-73"/>
<source>Insufficient funds</source>
<translation>Insufficient funds</translation>
</message>
diff --git a/src/qt/locale/bitcoin_es_MX.ts b/src/qt/locale/bitcoin_es_MX.ts
index 26432190a2..0a6ea1e1dd 100644
--- a/src/qt/locale/bitcoin_es_MX.ts
+++ b/src/qt/locale/bitcoin_es_MX.ts
@@ -45,6 +45,10 @@
<context>
<name>AskPassphraseDialog</name>
<message>
+ <source>Passphrase Dialog</source>
+ <translation>Dialogo de contraseña</translation>
+ </message>
+ <message>
<source>Enter passphrase</source>
<translation>Ingrese la contraseña</translation>
</message>
@@ -59,6 +63,10 @@
</context>
<context>
<name>BanTableModel</name>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>IP/Máscara de red</translation>
+ </message>
</context>
<context>
<name>BitcoinGUI</name>
@@ -179,6 +187,10 @@
<translation>&amp;Recibir</translation>
</message>
<message>
+ <source>&amp;Show / Hide</source>
+ <translation>&amp;Mostrar / Ocultar</translation>
+ </message>
+ <message>
<source>&amp;File</source>
<translation>&amp;Archivo</translation>
</message>
diff --git a/src/qt/locale/bitcoin_es_UY.ts b/src/qt/locale/bitcoin_es_UY.ts
index 8d361620de..c565a63cd8 100644
--- a/src/qt/locale/bitcoin_es_UY.ts
+++ b/src/qt/locale/bitcoin_es_UY.ts
@@ -108,7 +108,7 @@
</message>
<message>
<source>Send coins to a Bitcoin address</source>
- <translation>Enviar monedas a una dirección BItCoin</translation>
+ <translation>Enviar monedas a una dirección Bitcoin</translation>
</message>
<message>
<source>Change the passphrase used for wallet encryption</source>
diff --git a/src/qt/locale/bitcoin_fa.ts b/src/qt/locale/bitcoin_fa.ts
index 8bf727a0cd..98543ded46 100644
--- a/src/qt/locale/bitcoin_fa.ts
+++ b/src/qt/locale/bitcoin_fa.ts
@@ -67,7 +67,11 @@
<source>IP/Netmask</source>
<translation>آی‌پی/نت‌ماسک</translation>
</message>
- </context>
+ <message>
+ <source>Banned Until</source>
+ <translation>مسدود شده تا</translation>
+ </message>
+</context>
<context>
<name>BitcoinGUI</name>
<message>
@@ -111,6 +115,10 @@
<translation>&amp;حدود%1</translation>
</message>
<message>
+ <source>Show information about %1</source>
+ <translation>نمایش اطلاعات دربارهٔ %1</translation>
+ </message>
+ <message>
<source>About &amp;Qt</source>
<translation>دربارهٔ &amp;کیوت</translation>
</message>
@@ -510,6 +518,10 @@
</context>
<context>
<name>OpenURIDialog</name>
+ <message>
+ <source>Open URI</source>
+ <translation>بازکردن آدرس</translation>
+ </message>
</context>
<context>
<name>OptionsDialog</name>
@@ -526,6 +538,10 @@
<translation>پذیرش اتصالات از بیرون</translation>
</message>
<message>
+ <source>Allow incoming connections</source>
+ <translation>اجازه دادن به اتصالات دریافتی</translation>
+ </message>
+ <message>
<source>Reset all client options to default.</source>
<translation>بازنشانی تمام تنظیمات به پیش‌فرض.</translation>
</message>
@@ -691,7 +707,11 @@
</context>
<context>
<name>PeerTableModel</name>
- </context>
+ <message>
+ <source>Ping Time</source>
+ <translation>زمان پینگ</translation>
+ </message>
+</context>
<context>
<name>QObject</name>
<message>
@@ -798,6 +818,14 @@
<translation>آخرین دریافتی</translation>
</message>
<message>
+ <source>Ping Time</source>
+ <translation>زمان پینگ</translation>
+ </message>
+ <message>
+ <source>Ping Wait</source>
+ <translation>انتظار پینگ</translation>
+ </message>
+ <message>
<source>Last block time</source>
<translation>زمان آخرین بلوک</translation>
</message>
@@ -834,6 +862,22 @@
<translation>برای نمایش یک مرور کلی از دستورات ممکن، عبارت &lt;b&gt;help&lt;/b&gt; را بنویسید.</translation>
</message>
<message>
+ <source>%1 B</source>
+ <translation>%1 بایت</translation>
+ </message>
+ <message>
+ <source>%1 KB</source>
+ <translation>%1 کیلوبایت</translation>
+ </message>
+ <message>
+ <source>%1 MB</source>
+ <translation>%1 مگابایت</translation>
+ </message>
+ <message>
+ <source>%1 GB</source>
+ <translation>%1 گیگابایت</translation>
+ </message>
+ <message>
<source>never</source>
<translation>هرگز</translation>
</message>
@@ -887,7 +931,11 @@
<source>Copy &amp;Address</source>
<translation>&amp;کپی نشانی</translation>
</message>
- </context>
+ <message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;ذخیره عکس...</translation>
+ </message>
+</context>
<context>
<name>SendCoinsDialog</name>
<message>
@@ -935,6 +983,18 @@
<translation>پنهان کردن</translation>
</message>
<message>
+ <source>Recommended:</source>
+ <translation>توصیه شده:</translation>
+ </message>
+ <message>
+ <source>Custom:</source>
+ <translation>سفارشی:</translation>
+ </message>
+ <message>
+ <source>Confirmation time:</source>
+ <translation>روز تایید:</translation>
+ </message>
+ <message>
<source>normal</source>
<translation>نرمال</translation>
</message>
@@ -1024,6 +1084,10 @@
</context>
<context>
<name>ShutdownWindow</name>
+ <message>
+ <source>%1 is shutting down...</source>
+ <translation>%1 در حال خاموش شدن است...</translation>
+ </message>
</context>
<context>
<name>SignVerifyMessageDialog</name>
@@ -1251,6 +1315,10 @@
<translation>گزینه‌های کیف پول:</translation>
</message>
<message>
+ <source>(default: %u)</source>
+ <translation>(پیش‌فرض %u)</translation>
+ </message>
+ <message>
<source>Information</source>
<translation>اطلاعات</translation>
</message>
diff --git a/src/qt/locale/bitcoin_pl.ts b/src/qt/locale/bitcoin_pl.ts
index a88e505b39..09f748b83c 100644
--- a/src/qt/locale/bitcoin_pl.ts
+++ b/src/qt/locale/bitcoin_pl.ts
@@ -300,7 +300,7 @@
</message>
<message>
<source>%1 behind</source>
- <translation>%1 wstecz</translation>
+ <translation>%1 za</translation>
</message>
<message>
<source>Last received block was generated %1 ago.</source>
diff --git a/src/qt/locale/bitcoin_pt_BR.ts b/src/qt/locale/bitcoin_pt_BR.ts
index 2941430392..ee48c67341 100644
--- a/src/qt/locale/bitcoin_pt_BR.ts
+++ b/src/qt/locale/bitcoin_pt_BR.ts
@@ -1895,6 +1895,10 @@
<translation>Adiciona comentário ao user-agent do navegador</translation>
</message>
<message>
+ <source>Attempt to recover private keys from a corrupt wallet on startup</source>
+ <translation>Tentando recuperar a chape privada da carteira corrompida ao inicializar</translation>
+ </message>
+ <message>
<source>Block creation options:</source>
<translation>Opções de criação de blocos:</translation>
</message>
diff --git a/src/qt/locale/bitcoin_pt_PT.ts b/src/qt/locale/bitcoin_pt_PT.ts
index f63bfece69..eed262e010 100644
--- a/src/qt/locale/bitcoin_pt_PT.ts
+++ b/src/qt/locale/bitcoin_pt_PT.ts
@@ -618,6 +618,10 @@
<translation>&amp;Principal</translation>
</message>
<message>
+ <source>Automatically start %1 after logging in to the system.</source>
+ <translation>Começar o %1 automaticamente ao iniciar a sessão no sistema.</translation>
+ </message>
+ <message>
<source>&amp;Start %1 on system login</source>
<translation>&amp;Iniciar o %1 no início de sessão do sistema</translation>
</message>
@@ -1832,6 +1836,10 @@
<translation>Anexar um comentário para a entrada de agente do utilizador</translation>
</message>
<message>
+ <source>Attempt to recover private keys from a corrupt wallet on startup</source>
+ <translation>Tentar reuperar as chaves privadas de um "wallet" ao iniciar</translation>
+ </message>
+ <message>
<source>Block creation options:</source>
<translation>Opções da criação de bloco:</translation>
</message>
diff --git a/src/qt/locale/bitcoin_tr.ts b/src/qt/locale/bitcoin_tr.ts
index bbd0117404..e3a811b504 100644
--- a/src/qt/locale/bitcoin_tr.ts
+++ b/src/qt/locale/bitcoin_tr.ts
@@ -1831,6 +1831,10 @@
<translation>MIT yazılım lisansı kapsamında yayınlanmıştır, ekteki COPYING dosyasına ya da &lt;http://www.opensource.org/licenses/mit-license.php&gt; adresine bakınız.</translation>
</message>
<message>
+ <source>Error loading %s: You can't enable HD on a already existing non-HD wallet</source>
+ <translation>%s yüklenmesinde hata: zaten var olan ve HD olmayan bir cüzdanda HD etkinleştirilemez.</translation>
+ </message>
+ <message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>%s dosyasının okunması sırasında bir hata meydana geldi! Tüm anahtarlar doğru bir şekilde okundu, ancak muamele verileri ya da adres defteri unsurları hatalı veya eksik olabilir.</translation>
</message>
@@ -1855,6 +1859,10 @@
<translation>Lütfen bilgisayarınızın saat ve tarihinin doğru olduğunu kontrol ediniz! Saatinizde gecikme varsa %s doğru şekilde çalışamaz.</translation>
</message>
<message>
+ <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
+ <translation>%s programını faydalı buluyorsanız lütfen katkıda bulununuz. Yazılım hakkında daha fazla bilgi için %s adresini ziyaret ediniz.</translation>
+ </message>
+ <message>
<source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
<translation>Betik kontrolü iş parçacıklarının sayısını belirler (%u ilâ %d, 0 = otomatik, &lt;0 = bu sayıda çekirdeği kullanma, varsayılan: %d)</translation>
</message>
@@ -1867,6 +1875,10 @@
<translation>Bu yayın öncesi bir deneme sürümüdür - tüm riski siz üstlenmiş olursunuz - bitcoin oluşturmak ya da ticari uygulamalar için kullanmayınız</translation>
</message>
<message>
+ <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
+ <translation>Veritabanını çatallama öncesi duruma geri sarmak mümkün değil. Blok zincirini tekrar indirmeniz gerekmektedir</translation>
+ </message>
+ <message>
<source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
<translation>Dinlenecek portu haritalamak için UPnP kullan (varsayılan: dinlenildiğinde ve -proxy olmadığında 1)</translation>
</message>
@@ -1987,6 +1999,10 @@
<translation>%s unsurunun yüklenmesinde hata oluştu: cüzdan %s programının yeni bir sürümüne ihtiyaç duyuyor</translation>
</message>
<message>
+ <source>Error loading %s: You can't disable HD on a already existing HD wallet</source>
+ <translation>%s yüklenmesinde hata: zaten var olan HD bir cüzdanda HD devre dışı bırakılamaz.</translation>
+ </message>
+ <message>
<source>Error loading block database</source>
<translation>Blok veritabanının yüklenmesinde hata</translation>
</message>
@@ -2075,10 +2091,18 @@
<translation>Zincir durumunu güncel olarak endekslenen bloklardan yeniden derle</translation>
</message>
<message>
+ <source>Rewinding blocks...</source>
+ <translation>Bloklar geri sarılıyor...</translation>
+ </message>
+ <message>
<source>Set database cache size in megabytes (%d to %d, default: %d)</source>
<translation>Veritabanı önbellek boyutunu megabayt olarak belirt (%d ilâ %d, varsayılan: %d)</translation>
</message>
<message>
+ <source>Set maximum block cost (default: %d)</source>
+ <translation>Azami blok maliyetini ayarla (varsayılan: %d)</translation>
+ </message>
+ <message>
<source>Set maximum block size in bytes (default: %d)</source>
<translation>Azami blok boyutunu bayt olarak ayarla (varsayılan: %d)</translation>
</message>
@@ -2087,6 +2111,10 @@
<translation>Cüzdan dosyası belirtiniz (veri klasörünün içinde)</translation>
</message>
<message>
+ <source>The source code is available from %s.</source>
+ <translation>Kaynak kod şuradan elde edilebilir: %s.</translation>
+ </message>
+ <message>
<source>Unable to bind to %s on this computer. %s is probably already running.</source>
<translation>Bu bilgisayarda %s unsuruna bağlanılamadı. %s muhtemelen hâlihazırda çalışmaktadır.</translation>
</message>
@@ -2199,6 +2227,10 @@
<translation>Bu ürün OpenSSL projesi tarafından OpenSSL araç takımı (http://www.openssl.org/) için geliştirilen yazılımlar, Eric Young (eay@cryptsoft.com) tarafından hazırlanmış şifreleme yazılımları ve Thomas Bernard tarafından programlanmış UPnP yazılımı içerir.</translation>
</message>
<message>
+ <source>Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start</source>
+ <translation>BIP32'den sonra hiyerarşik determinist (HD) anahtar üretimini kullan. Sadece cüzdan oluşturulmasında/ilk başlamada etkiye sahiptir.</translation>
+ </message>
+ <message>
<source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
<translation>Beyaz listeye alınan eşler DoS yasaklamasına uğramazlar ve muameleleri zaten mempool'da olsalar da daima aktarılır, bu mesela bir geçit için kullanışlıdır</translation>
</message>
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 20eefa1c57..9dc896b7af 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -101,7 +101,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
result.push_back(Pair("confirmations", confirmations));
result.push_back(Pair("strippedsize", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS)));
result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
- result.push_back(Pair("cost", (int)::GetBlockCost(block)));
+ result.push_back(Pair("weight", (int)::GetBlockWeight(block)));
result.push_back(Pair("height", blockindex->nHeight));
result.push_back(Pair("version", block.nVersion));
result.push_back(Pair("versionHex", strprintf("%08x", block.nVersion)));
@@ -559,7 +559,7 @@ UniValue getblock(const UniValue& params, bool fHelp)
" \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
" \"size\" : n, (numeric) The block size\n"
" \"strippedsize\" : n, (numeric) The block size excluding witness data\n"
- " \"cost\" : n (numeric) The block cost\n"
+ " \"weight\" : n (numeric) The block weight (BIP 141)\n"
" \"height\" : n, (numeric) The block height or index\n"
" \"version\" : n, (numeric) The block version\n"
" \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n"
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 4c4e599781..92ca4bab6b 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -224,7 +224,7 @@ UniValue getmininginfo(const UniValue& params, bool fHelp)
"{\n"
" \"blocks\": nnn, (numeric) The current block\n"
" \"currentblocksize\": nnn, (numeric) The last block size\n"
- " \"currentblockcost\": nnn, (numeric) The last block cost\n"
+ " \"currentblockweight\": nnn, (numeric) The last block weight\n"
" \"currentblocktx\": nnn, (numeric) The last block transaction\n"
" \"difficulty\": xxx.xxxxx (numeric) The current difficulty\n"
" \"errors\": \"...\" (string) Current errors\n"
@@ -243,7 +243,7 @@ UniValue getmininginfo(const UniValue& params, bool fHelp)
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("blocks", (int)chainActive.Height()));
obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize));
- obj.push_back(Pair("currentblockcost", (uint64_t)nLastBlockCost));
+ obj.push_back(Pair("currentblockweight", (uint64_t)nLastBlockWeight));
obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx));
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
obj.push_back(Pair("errors", GetWarnings("statusbar")));
@@ -358,7 +358,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
" ],\n"
" \"fee\": n, (numeric) difference in value between transaction inputs and outputs (in Satoshis); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n"
" \"sigops\" : n, (numeric) total SigOps cost, as counted for purposes of block limits; if key is not present, sigop cost is unknown and clients MUST NOT assume it is zero\n"
- " \"cost\" : n, (numeric) total transaction size cost, as counted for purposes of block limits\n"
+ " \"weight\" : n, (numeric) total transaction weight, as counted for purposes of block limits\n"
" \"required\" : true|false (boolean) if provided and true, this transaction must be in the final block\n"
" }\n"
" ,...\n"
@@ -377,7 +377,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
" \"noncerange\" : \"00000000ffffffff\", (string) A range of valid nonces\n"
" \"sigoplimit\" : n, (numeric) cost limit of sigops in blocks\n"
" \"sizelimit\" : n, (numeric) limit of block size\n"
- " \"costlimit\" : n, (numeric) limit of block cost\n"
+ " \"weightlimit\" : n, (numeric) limit of block weight\n"
" \"curtime\" : ttt, (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
" \"bits\" : \"xxx\", (string) compressed target of next block\n"
" \"height\" : n (numeric) The height of the next block\n"
@@ -575,7 +575,7 @@ 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]));
- entry.push_back(Pair("cost", GetTransactionCost(tx)));
+ entry.push_back(Pair("weight", GetTransactionWeight(tx)));
transactions.push_back(entry);
}
@@ -659,7 +659,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
result.push_back(Pair("noncerange", "00000000ffffffff"));
result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS_COST));
result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SERIALIZED_SIZE));
- result.push_back(Pair("costlimit", (int64_t)MAX_BLOCK_COST));
+ result.push_back(Pair("weightlimit", (int64_t)MAX_BLOCK_WEIGHT));
result.push_back(Pair("curtime", pblock->GetBlockTime()));
result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1)));
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index f2a29416e6..a8c5bcd177 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -166,6 +166,8 @@ UniValue validateaddress(const UniValue& params, bool fHelp)
" \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n"
" \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
" \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n"
+ " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n"
+ " \"hdmasterkeyid\" : \"<hash160>\" (string, optional) The Hash160 of the HD master pubkey\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
@@ -200,6 +202,12 @@ UniValue validateaddress(const UniValue& params, bool fHelp)
ret.pushKVs(detail);
if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
+ CKeyID keyID;
+ if (pwalletMain && address.GetKeyID(keyID) && pwalletMain->mapKeyMetadata.count(keyID) && !pwalletMain->mapKeyMetadata[keyID].hdKeypath.empty())
+ {
+ ret.push_back(Pair("hdkeypath", pwalletMain->mapKeyMetadata[keyID].hdKeypath));
+ ret.push_back(Pair("hdmasterkeyid", pwalletMain->mapKeyMetadata[keyID].hdMasterKeyID.GetHex()));
+ }
#endif
}
return ret;
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index a48a6d9465..82827b8e4f 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -28,7 +28,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
hadNoDependencies(poolHasNoInputsOf), inChainInputValue(_inChainInputValue),
spendsCoinbase(_spendsCoinbase), sigOpCost(_sigOpsCost), lockPoints(lp)
{
- nTxCost = GetTransactionCost(_tx);
+ nTxWeight = GetTransactionWeight(_tx);
nModSize = _tx.CalculateModifiedSize(GetTxSize());
nUsageSize = RecursiveDynamicUsage(*tx) + memusage::DynamicUsage(tx);
@@ -75,7 +75,7 @@ void CTxMemPoolEntry::UpdateLockPoints(const LockPoints& lp)
size_t CTxMemPoolEntry::GetTxSize() const
{
- return GetVirtualTransactionSize(nTxCost);
+ return GetVirtualTransactionSize(nTxWeight, sigOpCost);
}
// Update the given tx for any in-mempool descendants.
diff --git a/src/txmempool.h b/src/txmempool.h
index e5a500e19d..2c2127f326 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -78,7 +78,7 @@ class CTxMemPoolEntry
private:
std::shared_ptr<const CTransaction> tx;
CAmount nFee; //!< Cached to avoid expensive parent-transaction lookups
- size_t nTxCost; //!< ... and avoid recomputing tx cost (also used for GetTxSize())
+ size_t nTxWeight; //!< ... and avoid recomputing tx weight (also used for GetTxSize())
size_t nModSize; //!< ... and modified size for priority
size_t nUsageSize; //!< ... and total memory usage
int64_t nTime; //!< Local time when entering the mempool
@@ -122,7 +122,7 @@ public:
double GetPriority(unsigned int currentHeight) const;
const CAmount& GetFee() const { return nFee; }
size_t GetTxSize() const;
- size_t GetTxCost() const { return nTxCost; }
+ size_t GetTxWeight() const { return nTxWeight; }
int64_t GetTime() const { return nTime; }
unsigned int GetHeight() const { return entryHeight; }
bool WasClearAtEntry() const { return hadNoDependencies; }
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index d55cc68dc0..6647d3297f 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -602,19 +602,42 @@ UniValue dumpwallet(const UniValue& params, bool fHelp)
file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString());
file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.Tip()->GetBlockTime()));
file << "\n";
+
+ // add the base58check encoded extended master if the wallet uses HD
+ CKeyID masterKeyID = pwalletMain->GetHDChain().masterKeyID;
+ if (!masterKeyID.IsNull())
+ {
+ CKey key;
+ if (pwalletMain->GetKey(masterKeyID, key))
+ {
+ CExtKey masterKey;
+ masterKey.SetMaster(key.begin(), key.size());
+
+ CBitcoinExtKey b58extkey;
+ b58extkey.SetKey(masterKey);
+
+ file << "# extended private masterkey: " << b58extkey.ToString() << "\n\n";
+ }
+ }
for (std::vector<std::pair<int64_t, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
const CKeyID &keyid = it->second;
std::string strTime = EncodeDumpTime(it->first);
std::string strAddr = CBitcoinAddress(keyid).ToString();
CKey key;
if (pwalletMain->GetKey(keyid, key)) {
+ file << strprintf("%s %s ", CBitcoinSecret(key).ToString(), strTime);
if (pwalletMain->mapAddressBook.count(keyid)) {
- file << strprintf("%s %s label=%s # addr=%s\n", CBitcoinSecret(key).ToString(), strTime, EncodeDumpString(pwalletMain->mapAddressBook[keyid].name), strAddr);
+ file << strprintf("label=%s", EncodeDumpString(pwalletMain->mapAddressBook[keyid].name));
+ } else if (keyid == masterKeyID) {
+ file << "hdmaster=1";
} else if (setKeyPool.count(keyid)) {
- file << strprintf("%s %s reserve=1 # addr=%s\n", CBitcoinSecret(key).ToString(), strTime, strAddr);
+ file << "reserve=1";
+ } else if (pwalletMain->mapKeyMetadata[keyid].hdKeypath == "m") {
+ file << "inactivehdmaster=1";
} else {
- file << strprintf("%s %s change=1 # addr=%s\n", CBitcoinSecret(key).ToString(), strTime, strAddr);
+ file << "change=1";
}
+ file << strprintf(" # addr=%s%s\n", strAddr, (pwalletMain->mapKeyMetadata[keyid].hdKeypath.size() > 0 ? " hdkeypath="+pwalletMain->mapKeyMetadata[keyid].hdKeypath : ""));
}
}
file << "\n";
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 2747477fd9..4087b8e77b 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -2260,15 +2260,16 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp)
"Returns an object containing various wallet state info.\n"
"\nResult:\n"
"{\n"
- " \"walletversion\": xxxxx, (numeric) the wallet version\n"
- " \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
- " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
- " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + CURRENCY_UNIT + "\n"
- " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n"
- " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
- " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
- " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
- " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n"
+ " \"walletversion\": xxxxx, (numeric) the wallet version\n"
+ " \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
+ " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
+ " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + CURRENCY_UNIT + "\n"
+ " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n"
+ " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
+ " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
+ " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
+ " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n"
+ " \"hdmasterkeyid\": \"<hash160>\", (string) the Hash160 of the HD master pubkey\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("getwalletinfo", "")
@@ -2288,6 +2289,9 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp)
if (pwalletMain->IsCrypted())
obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
+ CKeyID masterKeyID = pwalletMain->GetHDChain().masterKeyID;
+ if (!masterKeyID.IsNull())
+ obj.push_back(Pair("hdmasterkeyid", masterKeyID.GetHex()));
return obj;
}
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 7cb294bec1..5908dfeace 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -126,6 +126,8 @@ CPubKey CWallet::GenerateNewKey()
// childIndex | BIP32_HARDENED_KEY_LIMIT = derive childIndex in hardened child-index-range
// example: 1 | BIP32_HARDENED_KEY_LIMIT == 0x80000001 == 2147483649
externalChainChildKey.Derive(childKey, hdChain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
+ metadata.hdKeypath = "m/0'/0'/"+std::to_string(hdChain.nExternalChainCounter)+"'";
+ metadata.hdMasterKeyID = hdChain.masterKeyID;
// increment childkey index
hdChain.nExternalChainCounter++;
} while(HaveKey(childKey.key.GetPubKey().GetID()));
@@ -1168,6 +1170,9 @@ bool CWallet::SetHDMasterKey(const CKey& key)
{
LOCK(cs_wallet);
+ // ensure this wallet.dat can only be opened by clients supporting HD
+ SetMinVersion(FEATURE_HD);
+
// store the key as normal "key"/"ckey" object
// in the database
// key metadata is not required
@@ -2354,7 +2359,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
*static_cast<CTransaction*>(&wtxNew) = CTransaction(txNew);
// Limit size
- if (GetTransactionCost(txNew) >= MAX_STANDARD_TX_COST)
+ if (GetTransactionWeight(txNew) >= MAX_STANDARD_TX_WEIGHT)
{
strFailReason = _("Transaction too large");
return false;
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 7fc6ce5de5..efed2ba11d 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -78,7 +78,8 @@ enum WalletFeature
FEATURE_WALLETCRYPT = 40000, // wallet encryption
FEATURE_COMPRPUBKEY = 60000, // compressed public keys
- FEATURE_LATEST = 60000
+ FEATURE_HD = 130000, // Hierarchical key derivation after BIP32 (HD Wallet)
+ FEATURE_LATEST = FEATURE_COMPRPUBKEY // HD is optional, use FEATURE_COMPRPUBKEY as latest version
};
@@ -577,7 +578,7 @@ private:
void SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator>);
- /* the hd chain data model (external chain counters) */
+ /* the HD chain data model (external chain counters) */
CHDChain hdChain;
public:
@@ -896,10 +897,11 @@ public:
bool BackupWallet(const std::string& strDest);
- /* Set the hd chain model (chain child index counters) */
+ /* Set the HD chain model (chain child index counters) */
bool SetHDChain(const CHDChain& chain, bool memonly);
+ const CHDChain& GetHDChain() { return hdChain; }
- /* Set the current hd master key (will reset the chain child index counters) */
+ /* Set the current HD master key (will reset the chain child index counters) */
bool SetHDMasterKey(const CKey& key);
};
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index d083722dd2..5addd5c5c0 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -41,7 +41,7 @@ enum DBErrors
DB_NEED_REWRITE
};
-/* simple hd chain data model */
+/* simple HD chain data model */
class CHDChain
{
public:
@@ -73,9 +73,13 @@ public:
class CKeyMetadata
{
public:
- static const int CURRENT_VERSION=1;
+ static const int VERSION_BASIC=1;
+ static const int VERSION_WITH_HDDATA=10;
+ static const int CURRENT_VERSION=VERSION_WITH_HDDATA;
int nVersion;
int64_t nCreateTime; // 0 means unknown
+ std::string hdKeypath; //optional HD/bip32 keypath
+ CKeyID hdMasterKeyID; //id of the HD masterkey used to derive this key
CKeyMetadata()
{
@@ -83,7 +87,7 @@ public:
}
CKeyMetadata(int64_t nCreateTime_)
{
- nVersion = CKeyMetadata::CURRENT_VERSION;
+ SetNull();
nCreateTime = nCreateTime_;
}
@@ -94,12 +98,19 @@ public:
READWRITE(this->nVersion);
nVersion = this->nVersion;
READWRITE(nCreateTime);
+ if (this->nVersion >= VERSION_WITH_HDDATA)
+ {
+ READWRITE(hdKeypath);
+ READWRITE(hdMasterKeyID);
+ }
}
void SetNull()
{
nVersion = CKeyMetadata::CURRENT_VERSION;
nCreateTime = 0;
+ hdKeypath.clear();
+ hdMasterKeyID.SetNull();
}
};