Merge pull request #5580 from steven-ecc/update-transaction-size-estimation

Update transaction size estimation to include V5 transactions
This commit is contained in:
Steven 2022-02-23 20:16:58 -08:00 committed by GitHub
commit 82c33596b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 40 deletions

View File

@ -27,6 +27,7 @@
#include "primitives/transaction.h"
#include "zcbenchmarks.h"
#include "script/interpreter.h"
#include "zcash/Zcash.h"
#include "zcash/Address.hpp"
#include "zcash/address/zip32.h"
@ -4352,43 +4353,16 @@ size_t EstimateTxSize(
int nextBlockHeight) {
CMutableTransaction mtx;
mtx.fOverwintered = true;
mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID;
mtx.nVersion = SAPLING_TX_VERSION;
mtx.nConsensusBranchId = CurrentEpochBranchId(nextBlockHeight, Params().GetConsensus());
bool fromTaddr = std::visit(match {
[&](const AccountZTXOPattern& acct) {
return
acct.GetReceiverTypes().empty() ||
acct.GetReceiverTypes().count(ReceiverType::P2PKH) > 0 ||
acct.GetReceiverTypes().count(ReceiverType::P2SH) > 0;
},
[&](const CKeyID& keyId) {
return true;
},
[&](const CScriptID& scriptId) {
return true;
},
[&](const libzcash::UnifiedFullViewingKey& ufvk) {
return ufvk.GetTransparentKey().has_value();
},
[&](const libzcash::SproutPaymentAddress& addr) {
return false;
},
[&](const libzcash::SproutViewingKey& addr) {
return false;
},
[&](const libzcash::SaplingPaymentAddress& addr) {
return false;
},
[&](const libzcash::SaplingExtendedFullViewingKey& addr) {
return false;
}
}, ztxoSelector.GetPattern());
bool fromSprout = ztxoSelector.SelectsSprout();
bool fromTaddr = ztxoSelector.SelectsTransparent();
// As a sanity check, estimate and verify that the size of the transaction will be valid.
// Depending on the input notes, the actual tx size may turn out to be larger and perhaps invalid.
size_t txsize = 0;
size_t taddrRecipientCount = 0;
size_t orchardRecipientCount = 0;
for (const SendManyRecipient& recipient : recipients) {
std::visit(match {
[&](const CKeyID&) {
@ -4405,13 +4379,27 @@ size_t EstimateTxSize(
jsdesc.proof = GrothProof();
mtx.vJoinSplit.push_back(jsdesc);
},
[&](const libzcash::UnifiedAddress& ua) {
// FIXME
throw JSONRPCError(RPC_INVALID_PARAMETER, "Unified addresses not yet supported.");
[&](const libzcash::OrchardRawAddress& addr) {
if (fromSprout) {
throw JSONRPCError(
RPC_INVALID_PARAMETER,
"Sending funds from a Sprout address to a Unified Address is not supported by z_sendmany");
}
orchardRecipientCount += 1;
}
}, recipient.address);
}
bool nu5Active = Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_NU5);
if (fromSprout || !nu5Active) {
mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID;
mtx.nVersion = SAPLING_TX_VERSION;
} else {
mtx.nVersionGroupId = ZIP225_VERSION_GROUP_ID;
mtx.nVersion = ZIP225_TX_VERSION;
}
CTransaction tx(mtx);
txsize += GetSerializeSize(tx, SER_NETWORK, tx.nVersion);
if (fromTaddr) {
@ -4420,6 +4408,12 @@ size_t EstimateTxSize(
}
txsize += CTXOUT_REGULAR_SIZE * taddrRecipientCount;
if (orchardRecipientCount > 0) {
// - The Orchard transaction builder pads to a minimum of 2 actions.
// - We subtract 1 because `GetSerializeSize(tx, ...)` already counts
// `ZC_ZIP225_ORCHARD_NUM_ACTIONS_BASE_SIZE`.
txsize += ZC_ZIP225_ORCHARD_BASE_SIZE - 1 + ZC_ZIP225_ORCHARD_MARGINAL_SIZE * std::max(2, (int) orchardRecipientCount);
}
return txsize;
}

View File

@ -6554,7 +6554,7 @@ std::optional<libzcash::UnifiedAddress> UnifiedAddressForReceiver::operator()(co
return std::nullopt;
}
bool ZTXOSelector::SelectsTransparent() {
bool ZTXOSelector::SelectsTransparent() const {
return std::visit(match {
[](const CKeyID& keyId) { return true; },
[](const CScriptID& scriptId) { return true; },
@ -6566,14 +6566,14 @@ bool ZTXOSelector::SelectsTransparent() {
[](const AccountZTXOPattern& acct) { return acct.IncludesP2PKH() || acct.IncludesP2SH(); }
}, this->pattern);
}
bool ZTXOSelector::SelectsSprout() {
bool ZTXOSelector::SelectsSprout() const {
return std::visit(match {
[](const libzcash::SproutViewingKey& addr) { return true; },
[](const libzcash::SproutPaymentAddress& extfvk) { return true; },
[](const auto& addr) { return false; }
}, this->pattern);
}
bool ZTXOSelector::SelectsSapling() {
bool ZTXOSelector::SelectsSapling() const {
return std::visit(match {
[](const libzcash::SaplingPaymentAddress& addr) { return true; },
[](const libzcash::SaplingExtendedSpendingKey& extfvk) { return true; },

View File

@ -771,9 +771,9 @@ public:
return requireSpendingKeys;
}
bool SelectsTransparent();
bool SelectsSprout();
bool SelectsSapling();
bool SelectsTransparent() const;
bool SelectsSprout() const;
bool SelectsSapling() const;
};
class SpendableInputs {

View File

@ -28,4 +28,20 @@
#define ZC_SAPLING_ENCCIPHERTEXT_SIZE (ZC_SAPLING_ENCPLAINTEXT_SIZE + NOTEENCRYPTION_AUTH_BYTES)
#define ZC_SAPLING_OUTCIPHERTEXT_SIZE (ZC_SAPLING_OUTPLAINTEXT_SIZE + NOTEENCRYPTION_AUTH_BYTES)
// - CompactSize is at least 1 byte
#define ZC_ZIP225_ORCHARD_NUM_ACTIONS_SIZE 1
#define ZC_ZIP225_ORCHARD_FLAGS_SIZE 1
#define ZC_ZIP225_ORCHARD_VALUE_BALANCE_SIZE 8
#define ZC_ZIP225_ORCHARD_ANCHOR_SIZE 32
// - CompactSize is at least 2 bytes because sizeProofsOrchard >= 253
#define ZC_ZIP225_ORCHARD_SIZE_PROOFS_BASE_SIZE 2
#define ZC_ZIP225_ORCHARD_PROOF_BASE_SIZE 2720
#define ZC_ZIP225_ORCHARD_BINDING_SIG_SIZE 64
#define ZC_ZIP225_ORCHARD_BASE_SIZE (ZC_ZIP225_ORCHARD_NUM_ACTIONS_SIZE + ZC_ZIP225_ORCHARD_FLAGS_SIZE + ZC_ZIP225_ORCHARD_VALUE_BALANCE_SIZE + ZC_ZIP225_ORCHARD_ANCHOR_SIZE + ZC_ZIP225_ORCHARD_SIZE_PROOFS_BASE_SIZE + ZC_ZIP225_ORCHARD_PROOF_BASE_SIZE + ZC_ZIP225_ORCHARD_BINDING_SIG_SIZE)
// Marginal transaction size per Orchard Action
#define ZC_ZIP225_ORCHARD_ACTION_SIZE 820
#define ZC_ZIP225_ORCHARD_SPEND_AUTH_SIG_SIZE 64
#define ZC_ZIP225_ORCHARD_PROOF_MARGINAL_SIZE 2272
#define ZC_ZIP225_ORCHARD_MARGINAL_SIZE (ZC_ZIP225_ORCHARD_ACTION_SIZE + ZC_ZIP225_ORCHARD_SPEND_AUTH_SIG_SIZE + ZC_ZIP225_ORCHARD_PROOF_MARGINAL_SIZE)
#endif // ZCASH_ZCASH_ZCASH_H