diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2016-01-03 18:54:50 +0100 |
---|---|---|
committer | Pieter Wuille <pieter.wuille@gmail.com> | 2016-06-22 15:43:00 +0200 |
commit | 2b1f6f9ccf36f1e0a2c9d99154e1642f796d7c2b (patch) | |
tree | 30b17fa55ea6c9ae0055c0c16d2e271a0c799d16 /src/primitives | |
parent | 7c4bf779e8b74e474551982a24f5acc265293abd (diff) |
BIP141: Other consensus critical limits, and BIP145
Includes changes by Suhas Daftuar, Luke-jr, and mruddy.
Diffstat (limited to 'src/primitives')
-rw-r--r-- | src/primitives/block.cpp | 9 | ||||
-rw-r--r-- | src/primitives/block.h | 3 | ||||
-rw-r--r-- | src/primitives/transaction.cpp | 7 | ||||
-rw-r--r-- | src/primitives/transaction.h | 28 |
4 files changed, 42 insertions, 5 deletions
diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index 6fb33230a5..df900388f2 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -31,3 +31,12 @@ std::string CBlock::ToString() const } return s.str(); } + +int64_t GetBlockCost(const CBlock& block) +{ + // This implements the cost = (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. + 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 29307aed5b..e2a309e63d 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -154,4 +154,7 @@ struct CBlockLocator } }; +/** Compute the consensus-critical block cost (see BIP 141). */ +int64_t GetBlockCost(const CBlock& tx); + #endif // BITCOIN_PRIMITIVES_BLOCK_H diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index b0230530e8..7f10409c05 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 = ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION); + nTxSize = (GetTransactionCost(*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()); @@ -148,3 +148,8 @@ std::string CTransaction::ToString() const str += " " + vout[i].ToString() + "\n"; return str; } + +int64_t GetTransactionCost(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 5a58241347..e87ad90f0d 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -13,6 +13,8 @@ static const int SERIALIZE_TRANSACTION_NO_WITNESS = 0x40000000; +static const int WITNESS_SCALE_FACTOR = 4; + /** An outpoint - a combination of a transaction hash and an index n into its vout */ class COutPoint { @@ -166,15 +168,30 @@ public: // which has units satoshis-per-kilobyte. // If you'd pay more than 1/3 in fees // to spend something, then we consider it dust. - // A typical spendable txout is 34 bytes big, and will + // A typical spendable non-segwit txout is 34 bytes big, and will // need a CTxIn of at least 148 bytes to spend: // so dust is a spendable txout less than - // 546*minRelayTxFee/1000 (in satoshis) + // 546*minRelayTxFee/1000 (in satoshis). + // A typical spendable segwit txout is 31 bytes big, and will + // need a CTxIn of at least 67 bytes to spend: + // so dust is a spendable txout less than + // 294*minRelayTxFee/1000 (in satoshis). if (scriptPubKey.IsUnspendable()) return 0; - size_t nSize = GetSerializeSize(SER_DISK,0)+148u; - return 3*minRelayTxFee.GetFee(nSize); + size_t nSize = GetSerializeSize(SER_DISK, 0); + int witnessversion = 0; + std::vector<unsigned char> witnessprogram; + + if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) { + // sum the sizes of the parts of a transaction input + // with 75% segwit discount applied to the script size. + nSize += (32 + 4 + 1 + (107 / WITNESS_SCALE_FACTOR) + 4); + } else { + nSize += (32 + 4 + 1 + 107 + 4); // the 148 mentioned above + } + + return 3 * minRelayTxFee.GetFee(nSize); } bool IsDust(const CFeeRate &minRelayTxFee) const @@ -442,4 +459,7 @@ struct CMutableTransaction uint256 GetHash() const; }; +/** Compute the cost of a transaction, as defined by BIP 141 */ +int64_t GetTransactionCost(const CTransaction &tx); + #endif // BITCOIN_PRIMITIVES_TRANSACTION_H |