From ebde772adad957eb24dd3f2a0548961f41f85d9d Mon Sep 17 00:00:00 2001 From: Duke Date: Tue, 14 Oct 2025 11:52:05 -0400 Subject: [PATCH] WIP donation test --- qa/rpc-tests/shieldcoinbase_donation.py | 6 +++--- .../asyncrpcoperation_shieldcoinbase.cpp | 19 +++++++++++-------- src/wallet/asyncrpcoperation_shieldcoinbase.h | 7 +++++-- src/wallet/rpcwallet.cpp | 5 ++++- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/qa/rpc-tests/shieldcoinbase_donation.py b/qa/rpc-tests/shieldcoinbase_donation.py index e50c1ea3c..010ed3548 100755 --- a/qa/rpc-tests/shieldcoinbase_donation.py +++ b/qa/rpc-tests/shieldcoinbase_donation.py @@ -46,9 +46,9 @@ class ShieldCoinbaseDonationTest (BitcoinTestFramework): '-regtest', '--daemon', #'-debug', - #'-zrpc', - #'-zdebug', - ##'-zrpcunsafe' + '-zrpc', + '-zdebug', + '-zrpcunsafe' ]] ) self.is_network_split = False diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp index adb8c748e..a11908230 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp @@ -54,9 +54,9 @@ AsyncRPCOperation_shieldcoinbase::AsyncRPCOperation_shieldcoinbase( std::vector inputs, std::string toAddress, CAmount fee, - CAmount donation, + uint8_t donation, UniValue contextInfo) : - builder_(builder), tx_(contextualTx), inputs_(inputs), fee_(fee), contextinfo_(contextInfo) + builder_(builder), tx_(contextualTx), inputs_(inputs), fee_(fee), donation_(donation), contextinfo_(contextInfo) { assert(contextualTx.nVersion >= 2); // transaction format version must support vjoinsplit @@ -68,6 +68,10 @@ AsyncRPCOperation_shieldcoinbase::AsyncRPCOperation_shieldcoinbase( throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Empty inputs"); } + if (donation < 0 || donation > 10 ) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid donation percentage, must be an integer between 0 and 10"); + } + // Check the destination address is valid for this network i.e. not testnet being used on mainnet auto address = DecodePaymentAddress(toAddress); if (IsValidPaymentAddress(address)) { @@ -177,11 +181,9 @@ bool AsyncRPCOperation_shieldcoinbase::main_impl() { CAmount sendAmount = targetAmount - minersFee; LogPrint("zrpc", "%s: spending %s to shield %s with fee %s, donation=%d\n", - getId(), FormatMoney(targetAmount), FormatMoney(sendAmount), FormatMoney(minersFee)); + getId(), FormatMoney(targetAmount), FormatMoney(sendAmount), FormatMoney(minersFee), donation_); - //TODO: pass this in from RPC - CAmount donation = 2; - return boost::apply_visitor(ShieldToAddress(this, sendAmount, donation), tozaddr_); + return boost::apply_visitor(ShieldToAddress(this, sendAmount, donation_), tozaddr_); } extern UniValue signrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); @@ -225,8 +227,9 @@ bool ShieldToAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) c //TODO: if donation>0, send X% of value to zaddr and Y% of of value to donatezaddr // where X+Y=100% if(donation) { - //TODO: calculate exact values of sendAmount and donationAmount - CAmount donationAmount = (donation/100)*sendAmount; + // calculate donation as a double then convert to CAmount + CAmount donationAmount = (CAmount) ( ((double)donation/100)*sendAmount ); + // add original recipient as first output, with sendAmount less the donation m_op->builder_.AddSaplingOutput(ovk, zaddr, sendAmount - donationAmount); diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.h b/src/wallet/asyncrpcoperation_shieldcoinbase.h index 312c9111f..8ef85bdc0 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.h +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.h @@ -49,7 +49,7 @@ public: std::vector inputs, std::string toAddress, CAmount fee = SHIELD_COINBASE_DEFAULT_MINERS_FEE, - CAmount donation = 0, //TODO: uint8_t + uint8_t donation = 0, UniValue contextInfo = NullUniValue); virtual ~AsyncRPCOperation_shieldcoinbase(); @@ -76,6 +76,9 @@ private: std::vector inputs_; + // this is a donation % between 0 and 10, not a CAmount + uint8_t donation_; + TransactionBuilder builder_; CTransaction tx_; @@ -92,7 +95,7 @@ class ShieldToAddress : public boost::static_visitor private: AsyncRPCOperation_shieldcoinbase *m_op; CAmount sendAmount; - CAmount donation = 0; + uint8_t donation = 0; public: ShieldToAddress(AsyncRPCOperation_shieldcoinbase *op, CAmount sendAmount, bool donation) : m_op(op), sendAmount(sendAmount), donation(donation) {} diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 734cdd15c..7d816491b 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5563,10 +5563,12 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& myp if (params.size() > 4) { donation = params[4].get_int(); if (donation < 0 || donation > 10 ) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid donation percentage, must be an integer between 1 and 10"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid donation percentage, must be an integer between 0 and 10"); } } + LogPrintf("%s: donation=%d\n", __func__, donation); + int nextBlockHeight = chainActive.Height() + 1; bool overwinterActive = nextBlockHeight>=1 ? true : false; // NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER); unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING; @@ -5694,6 +5696,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& myp o.push_back(Pair("remainingValue", ValueFromAmount(remainingValue))); o.push_back(Pair("shieldingUTXOs", static_cast(numUtxos))); o.push_back(Pair("shieldingValue", ValueFromAmount(shieldedValue))); + o.push_back(Pair("donation", donation)); o.push_back(Pair("opid", operationId)); return o; }