mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-17 13:07:54 +02:00
Merge pull request #1366 from delta1/discountweight
discount: fix weight calculation
This commit is contained in:
commit
fbc01d56d7
4 changed files with 43 additions and 22 deletions
|
|
@ -237,11 +237,12 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
|
||||||
entry.pushKV("version", static_cast<int64_t>(static_cast<uint32_t>(tx.nVersion)));
|
entry.pushKV("version", static_cast<int64_t>(static_cast<uint32_t>(tx.nVersion)));
|
||||||
entry.pushKV("size", (int)::GetSerializeSize(tx, PROTOCOL_VERSION));
|
entry.pushKV("size", (int)::GetSerializeSize(tx, PROTOCOL_VERSION));
|
||||||
entry.pushKV("vsize", (GetTransactionWeight(tx) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR);
|
entry.pushKV("vsize", (GetTransactionWeight(tx) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR);
|
||||||
|
entry.pushKV("weight", GetTransactionWeight(tx));
|
||||||
// ELEMENTS: add discountvsize
|
// ELEMENTS: add discountvsize
|
||||||
if (Params().GetAcceptDiscountCT()) {
|
if (Params().GetAcceptDiscountCT()) {
|
||||||
entry.pushKV("discountvsize", GetDiscountVirtualTransactionSize(tx));
|
entry.pushKV("discountvsize", GetDiscountVirtualTransactionSize(tx));
|
||||||
|
entry.pushKV("discountweight", GetDiscountTransactionWeight(tx));
|
||||||
}
|
}
|
||||||
entry.pushKV("weight", GetTransactionWeight(tx));
|
|
||||||
entry.pushKV("locktime", (int64_t)tx.nLockTime);
|
entry.pushKV("locktime", (int64_t)tx.nLockTime);
|
||||||
|
|
||||||
UniValue vin{UniValue::VARR};
|
UniValue vin{UniValue::VARR};
|
||||||
|
|
|
||||||
|
|
@ -12,16 +12,15 @@
|
||||||
#include <version.h>
|
#include <version.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate a smaller virtual size for discounted Confidential Transactions.
|
* Calculate a smaller weight for discounted Confidential Transactions.
|
||||||
*/
|
*/
|
||||||
static inline int64_t GetDiscountVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost = 0, unsigned int bytes_per_sig_op = 0)
|
static inline int64_t GetDiscountTransactionWeight(const CTransaction& tx, int64_t nSigOpCost = 0, unsigned int bytes_per_sig_op = 0)
|
||||||
{
|
{
|
||||||
int64_t size_bytes = ::GetSerializeSize(tx, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(tx, PROTOCOL_VERSION);
|
int64_t size_bytes = ::GetSerializeSize(tx, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(tx, PROTOCOL_VERSION);
|
||||||
int64_t sigop_bytes = nSigOpCost * bytes_per_sig_op;
|
int64_t sigop_bytes = nSigOpCost * bytes_per_sig_op;
|
||||||
|
|
||||||
int64_t weight = std::max(size_bytes, sigop_bytes);
|
int64_t weight = std::max(size_bytes, sigop_bytes);
|
||||||
|
|
||||||
// for each confidential output
|
|
||||||
for (size_t i = 0; i < tx.vout.size(); ++i) {
|
for (size_t i = 0; i < tx.vout.size(); ++i) {
|
||||||
const CTxOut& output = tx.vout[i];
|
const CTxOut& output = tx.vout[i];
|
||||||
if (i < tx.witness.vtxoutwit.size()) {
|
if (i < tx.witness.vtxoutwit.size()) {
|
||||||
|
|
@ -32,16 +31,25 @@ static inline int64_t GetDiscountVirtualTransactionSize(const CTransaction& tx,
|
||||||
}
|
}
|
||||||
if (output.nValue.IsCommitment()) {
|
if (output.nValue.IsCommitment()) {
|
||||||
// subtract the weight difference of amount commitment (33) vs explicit amount (9)
|
// subtract the weight difference of amount commitment (33) vs explicit amount (9)
|
||||||
weight -= (33 - 9);
|
// weighted as part of the base transaction
|
||||||
|
weight -= (33 - 9) * WITNESS_SCALE_FACTOR;
|
||||||
}
|
}
|
||||||
if (output.nNonce.IsCommitment()) {
|
if (output.nNonce.IsCommitment()) {
|
||||||
// subtract the weight difference of nonce commitment (33) vs no nonce (1)
|
// subtract the weight difference of nonce commitment (33) vs no nonce (1)
|
||||||
weight -= 32;
|
// weighted as part of the base transaction
|
||||||
|
weight -= 32 * WITNESS_SCALE_FACTOR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(weight > 0);
|
assert(weight > 0);
|
||||||
|
return weight;
|
||||||
|
}
|
||||||
|
|
||||||
size_t discountvsize = (weight + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
|
/**
|
||||||
|
* Calculate a smaller virtual size for discounted Confidential Transactions.
|
||||||
|
*/
|
||||||
|
static inline int64_t GetDiscountVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost = 0, unsigned int bytes_per_sig_op = 0)
|
||||||
|
{
|
||||||
|
size_t discountvsize = (GetDiscountTransactionWeight(tx, nSigOpCost, bytes_per_sig_op) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
|
||||||
|
|
||||||
assert(discountvsize > 0);
|
assert(discountvsize > 0);
|
||||||
return discountvsize;
|
return discountvsize;
|
||||||
|
|
|
||||||
|
|
@ -79,8 +79,10 @@ class CTTest(BitcoinTestFramework):
|
||||||
assert_equal(len(vout), 3)
|
assert_equal(len(vout), 3)
|
||||||
assert_equal(tx['fee']['bitcoin'], Decimal('-0.00000326'))
|
assert_equal(tx['fee']['bitcoin'], Decimal('-0.00000326'))
|
||||||
assert_equal(decoded['vsize'], 326)
|
assert_equal(decoded['vsize'], 326)
|
||||||
|
assert_equal(decoded['weight'], 1302)
|
||||||
self.generate(node0, 1)
|
self.generate(node0, 1)
|
||||||
tx = node1.getrawtransaction(txid, True)
|
tx = node1.getrawtransaction(txid, True)
|
||||||
|
assert_equal(tx['discountweight'], 1302)
|
||||||
assert_equal(tx['discountvsize'], 326)
|
assert_equal(tx['discountvsize'], 326)
|
||||||
|
|
||||||
self.log.info("Send confidential tx to node 0")
|
self.log.info("Send confidential tx to node 0")
|
||||||
|
|
@ -95,9 +97,11 @@ class CTTest(BitcoinTestFramework):
|
||||||
assert_equal(len(vout), 3)
|
assert_equal(len(vout), 3)
|
||||||
assert_equal(tx['fee']['bitcoin'], Decimal('-0.00002575'))
|
assert_equal(tx['fee']['bitcoin'], Decimal('-0.00002575'))
|
||||||
assert_equal(decoded['vsize'], 2575)
|
assert_equal(decoded['vsize'], 2575)
|
||||||
|
assert_equal(decoded['weight'], 10300)
|
||||||
self.generate(node0, 1)
|
self.generate(node0, 1)
|
||||||
tx = node1.getrawtransaction(txid, True)
|
tx = node1.getrawtransaction(txid, True)
|
||||||
assert_equal(tx['discountvsize'], 410) # node1 has discountvsize
|
assert_equal(tx['discountweight'], 1302)
|
||||||
|
assert_equal(tx['discountvsize'], 326) # node1 has discountvsize
|
||||||
|
|
||||||
self.log.info("Send explicit tx to node 1")
|
self.log.info("Send explicit tx to node 1")
|
||||||
addr = node1.getnewaddress()
|
addr = node1.getnewaddress()
|
||||||
|
|
@ -111,8 +115,10 @@ class CTTest(BitcoinTestFramework):
|
||||||
assert_equal(len(vout), 3)
|
assert_equal(len(vout), 3)
|
||||||
assert_equal(tx['fee']['bitcoin'], Decimal('-0.00000326'))
|
assert_equal(tx['fee']['bitcoin'], Decimal('-0.00000326'))
|
||||||
assert_equal(decoded['vsize'], 326)
|
assert_equal(decoded['vsize'], 326)
|
||||||
|
assert_equal(decoded['weight'], 1302)
|
||||||
self.generate(node0, 1)
|
self.generate(node0, 1)
|
||||||
tx = node1.getrawtransaction(txid, True)
|
tx = node1.getrawtransaction(txid, True)
|
||||||
|
assert_equal(tx['discountweight'], 1302)
|
||||||
assert_equal(tx['discountvsize'], 326)
|
assert_equal(tx['discountvsize'], 326)
|
||||||
|
|
||||||
self.log.info("Send confidential (undiscounted) tx to node 1")
|
self.log.info("Send confidential (undiscounted) tx to node 1")
|
||||||
|
|
@ -127,9 +133,11 @@ class CTTest(BitcoinTestFramework):
|
||||||
assert_equal(len(vout), 3)
|
assert_equal(len(vout), 3)
|
||||||
assert_equal(tx['fee']['bitcoin'], Decimal('-0.00002575'))
|
assert_equal(tx['fee']['bitcoin'], Decimal('-0.00002575'))
|
||||||
assert_equal(decoded['vsize'], 2575)
|
assert_equal(decoded['vsize'], 2575)
|
||||||
|
assert_equal(decoded['weight'], 10300)
|
||||||
self.generate(node0, 1)
|
self.generate(node0, 1)
|
||||||
tx = node1.getrawtransaction(txid, True)
|
tx = node1.getrawtransaction(txid, True)
|
||||||
assert_equal(tx['discountvsize'], 410) # node1 has discountvsize
|
assert_equal(tx['discountweight'], 1302)
|
||||||
|
assert_equal(tx['discountvsize'], 326) # node1 has discountvsize
|
||||||
|
|
||||||
self.log.info("Send confidential (discounted) tx to node 1")
|
self.log.info("Send confidential (discounted) tx to node 1")
|
||||||
bitcoin = 'b2e15d0d7a0c94e4e2ce0fe6e8691b9e451377f6e46e8045a86f7c4b5d4f0f23'
|
bitcoin = 'b2e15d0d7a0c94e4e2ce0fe6e8691b9e451377f6e46e8045a86f7c4b5d4f0f23'
|
||||||
|
|
@ -148,11 +156,13 @@ class CTTest(BitcoinTestFramework):
|
||||||
assert_equal(len(vin), 2)
|
assert_equal(len(vin), 2)
|
||||||
assert_equal(len(vout), 3)
|
assert_equal(len(vout), 3)
|
||||||
if 'bitcoin' in decoded['fee']:
|
if 'bitcoin' in decoded['fee']:
|
||||||
assert_equal(decoded['fee']['bitcoin'], Decimal('-0.00000410'))
|
assert_equal(decoded['fee']['bitcoin'], Decimal('-0.00000326'))
|
||||||
else:
|
else:
|
||||||
assert_equal(decoded['fee'][bitcoin], Decimal('0.00000410'))
|
assert_equal(decoded['fee'][bitcoin], Decimal('0.00000326'))
|
||||||
assert_equal(decoded['vsize'], 2575)
|
assert_equal(decoded['vsize'], 2575)
|
||||||
assert_equal(decoded['discountvsize'], 410)
|
assert_equal(decoded['weight'], 10300)
|
||||||
|
assert_equal(decoded['discountweight'], 1302)
|
||||||
|
assert_equal(decoded['discountvsize'], 326)
|
||||||
|
|
||||||
# node0 only has vsize
|
# node0 only has vsize
|
||||||
tx = node0.getrawtransaction(txid, True)
|
tx = node0.getrawtransaction(txid, True)
|
||||||
|
|
@ -176,11 +186,13 @@ class CTTest(BitcoinTestFramework):
|
||||||
assert_equal(len(vin), 2)
|
assert_equal(len(vin), 2)
|
||||||
assert_equal(len(vout), 3)
|
assert_equal(len(vout), 3)
|
||||||
if 'bitcoin' in decoded['fee']:
|
if 'bitcoin' in decoded['fee']:
|
||||||
assert_equal(decoded['fee']['bitcoin'], Decimal('-0.00000041'))
|
assert_equal(decoded['fee']['bitcoin'], Decimal('-0.00000033'))
|
||||||
else:
|
else:
|
||||||
assert_equal(decoded['fee'][bitcoin], Decimal('0.00000041'))
|
assert_equal(decoded['fee'][bitcoin], Decimal('0.00000033'))
|
||||||
assert_equal(decoded['vsize'], 2575)
|
assert_equal(decoded['vsize'], 2575)
|
||||||
assert_equal(decoded['discountvsize'], 410)
|
assert_equal(decoded['weight'], 10300)
|
||||||
|
assert_equal(decoded['discountweight'], 1302)
|
||||||
|
assert_equal(decoded['discountvsize'], 326)
|
||||||
# node0 only has vsize
|
# node0 only has vsize
|
||||||
tx = node0.getrawtransaction(txid, True)
|
tx = node0.getrawtransaction(txid, True)
|
||||||
assert_equal(tx['vsize'], 2575)
|
assert_equal(tx['vsize'], 2575)
|
||||||
|
|
@ -207,7 +219,7 @@ class CTTest(BitcoinTestFramework):
|
||||||
assert_equal(test[0]["allowed"], True)
|
assert_equal(test[0]["allowed"], True)
|
||||||
txid = node1.sendrawtransaction(signed['hex'])
|
txid = node1.sendrawtransaction(signed['hex'])
|
||||||
tx = node1.gettransaction(txid, True, True)
|
tx = node1.gettransaction(txid, True, True)
|
||||||
assert_equal(tx['decoded']['discountvsize'], 341)
|
assert_equal(tx['decoded']['discountvsize'], 257)
|
||||||
|
|
||||||
for i in range(24):
|
for i in range(24):
|
||||||
self.log.info(f"Add package descendant {i+1}")
|
self.log.info(f"Add package descendant {i+1}")
|
||||||
|
|
@ -231,7 +243,7 @@ class CTTest(BitcoinTestFramework):
|
||||||
assert_equal(test[0]["allowed"], True)
|
assert_equal(test[0]["allowed"], True)
|
||||||
txid = node1.sendrawtransaction(hex)
|
txid = node1.sendrawtransaction(hex)
|
||||||
tx = node1.gettransaction(txid, True, True)
|
tx = node1.gettransaction(txid, True, True)
|
||||||
assert_equal(tx['decoded']['discountvsize'], 341)
|
assert_equal(tx['decoded']['discountvsize'], 257)
|
||||||
assert_equal(len(node1.getrawmempool()), i + 2)
|
assert_equal(len(node1.getrawmempool()), i + 2)
|
||||||
|
|
||||||
assert_equal(len(node1.getrawmempool()), 25)
|
assert_equal(len(node1.getrawmempool()), 25)
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ class CTTest(BitcoinTestFramework):
|
||||||
assert_equal(decoded['vsize'], 2575)
|
assert_equal(decoded['vsize'], 2575)
|
||||||
self.sync_mempools([node0, node1])
|
self.sync_mempools([node0, node1])
|
||||||
tx = node1.getrawtransaction(txid, True)
|
tx = node1.getrawtransaction(txid, True)
|
||||||
assert_equal(tx['discountvsize'], 410)
|
assert_equal(tx['discountvsize'], 326)
|
||||||
|
|
||||||
feerate = 1.0
|
feerate = 1.0
|
||||||
self.log.info(f"Send confidential (discounted) tx to node 1 at {feerate} sat/vb")
|
self.log.info(f"Send confidential (discounted) tx to node 1 at {feerate} sat/vb")
|
||||||
|
|
@ -131,11 +131,11 @@ class CTTest(BitcoinTestFramework):
|
||||||
assert_equal(len(vin), 2)
|
assert_equal(len(vin), 2)
|
||||||
assert_equal(len(vout), 3)
|
assert_equal(len(vout), 3)
|
||||||
if 'bitcoin' in decoded['fee']:
|
if 'bitcoin' in decoded['fee']:
|
||||||
assert_equal(decoded['fee']['bitcoin'], Decimal('-0.00000410'))
|
assert_equal(decoded['fee']['bitcoin'], Decimal('-0.00000326'))
|
||||||
else:
|
else:
|
||||||
assert_equal(decoded['fee'][bitcoin], Decimal('0.00000410'))
|
assert_equal(decoded['fee'][bitcoin], Decimal('0.00000326'))
|
||||||
assert_equal(decoded['vsize'], 2575)
|
assert_equal(decoded['vsize'], 2575)
|
||||||
assert_equal(decoded['discountvsize'], 410)
|
assert_equal(decoded['discountvsize'], 326)
|
||||||
|
|
||||||
feerate = 2.0
|
feerate = 2.0
|
||||||
self.log.info(f"Send confidential (discounted) tx to node 1 at {feerate} sat/vb")
|
self.log.info(f"Send confidential (discounted) tx to node 1 at {feerate} sat/vb")
|
||||||
|
|
@ -145,7 +145,7 @@ class CTTest(BitcoinTestFramework):
|
||||||
self.sync_mempools([node1, node2])
|
self.sync_mempools([node1, node2])
|
||||||
tx = node1.gettransaction(txid, True, True)
|
tx = node1.gettransaction(txid, True, True)
|
||||||
decoded = tx['decoded']
|
decoded = tx['decoded']
|
||||||
assert_equal(decoded['fee'][bitcoin], Decimal('0.00000820'))
|
assert_equal(decoded['fee'][bitcoin], Decimal('0.00000652'))
|
||||||
|
|
||||||
# check that txs in the block template are in decreasing feerate according to their discount size
|
# check that txs in the block template are in decreasing feerate according to their discount size
|
||||||
self.log.info("Check tx ordering in block template")
|
self.log.info("Check tx ordering in block template")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue