Skip to content

Commit

Permalink
[Refactoring] SendManyRecipient: use CRecipient for taddr + add sffa
Browse files Browse the repository at this point in the history
  • Loading branch information
random-zebra committed Jun 9, 2021
1 parent 6fff9f5 commit cba898b
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 25 deletions.
5 changes: 3 additions & 2 deletions src/qt/walletmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -598,16 +598,17 @@ OperationResult WalletModel::PrepareShieldedTransaction(WalletModelTransaction*
const CCoinControl* coinControl)
{
// Load shieldedAddrRecipients.
bool fSubtractFeeFromAmount{false};
std::vector<SendManyRecipient> recipients;
for (const auto& recipient : modelTransaction->getRecipients()) {
if (recipient.isShieldedAddr) {
auto pa = KeyIO::DecodeSaplingPaymentAddress(recipient.address.toStdString());
if (!pa) return errorOut("Error, invalid shielded address");
recipients.emplace_back(*pa, recipient.amount, recipient.message.toStdString());
recipients.emplace_back(*pa, recipient.amount, recipient.message.toStdString(), fSubtractFeeFromAmount);
} else {
auto dest = DecodeDestination(recipient.address.toStdString());
if (!IsValidDestination(dest)) return errorOut("Error, invalid transparent address");
recipients.emplace_back(dest, recipient.amount);
recipients.emplace_back(dest, recipient.amount, fSubtractFeeFromAmount);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/sapling/sapling_operation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ TxValues calculateTarget(const std::vector<SendManyRecipient>& recipients, const
TxValues txValues;
for (const SendManyRecipient &t : recipients) {
if (t.IsTransparent())
txValues.transOutTotal += t.transparentRecipient->nValue;
txValues.transOutTotal += t.transparentRecipient->nAmount;
else
txValues.shieldedOutTotal += t.shieldedRecipient->amount;
}
Expand Down Expand Up @@ -145,7 +145,7 @@ OperationResult SaplingOperation::build()
// Add outputs
for (const SendManyRecipient &t : recipients) {
if (t.IsTransparent()) {
txBuilder.AddTransparentOutput(*t.transparentRecipient);
txBuilder.AddTransparentOutput(CTxOut(t.transparentRecipient->nAmount, t.transparentRecipient->scriptPubKey));
} else {
const auto& address = t.shieldedRecipient->address;
const CAmount& amount = t.shieldedRecipient->amount;
Expand Down
24 changes: 13 additions & 11 deletions src/sapling/sapling_operation.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,47 +23,49 @@ struct ShieldedRecipient
const libzcash::SaplingPaymentAddress address;
const CAmount amount;
const std::string memo;
ShieldedRecipient(const libzcash::SaplingPaymentAddress& _address, const CAmount& _amount, const std::string& _memo) :
bool fSubtractFeeFromAmount;
ShieldedRecipient(const libzcash::SaplingPaymentAddress& _address, const CAmount& _amount, const std::string& _memo, bool _fSubtractFeeFromAmount) :
address(_address),
amount(_amount),
memo(_memo)
memo(_memo),
fSubtractFeeFromAmount(_fSubtractFeeFromAmount)
{}
};

struct SendManyRecipient
{
const Optional<ShieldedRecipient> shieldedRecipient{nullopt};
const Optional<CTxOut> transparentRecipient{nullopt};
const Optional<CRecipient> transparentRecipient{nullopt};

bool IsTransparent() const { return transparentRecipient != nullopt; }

// Prevent default empty initialization
SendManyRecipient() = delete;

// Shielded recipient
SendManyRecipient(const libzcash::SaplingPaymentAddress& address, const CAmount& amount, const std::string& memo):
shieldedRecipient(ShieldedRecipient(address, amount, memo))
SendManyRecipient(const libzcash::SaplingPaymentAddress& address, const CAmount& amount, const std::string& memo, bool fSubtractFeeFromAmount):
shieldedRecipient(ShieldedRecipient(address, amount, memo, fSubtractFeeFromAmount))
{}

// Transparent recipient: P2PKH
SendManyRecipient(const CTxDestination& dest, const CAmount& amount):
transparentRecipient(CTxOut(amount, GetScriptForDestination(dest)))
SendManyRecipient(const CTxDestination& dest, const CAmount& amount, bool fSubtractFeeFromAmount):
transparentRecipient(CRecipient(GetScriptForDestination(dest), amount, fSubtractFeeFromAmount))
{}

// Transparent recipient: P2CS
SendManyRecipient(const CKeyID& ownerKey, const CKeyID& stakerKey, const CAmount& amount, bool fV6Enforced):
transparentRecipient(CTxOut(amount, fV6Enforced ? GetScriptForStakeDelegation(stakerKey, ownerKey)
: GetScriptForStakeDelegationLOF(stakerKey, ownerKey)))
transparentRecipient(CRecipient(fV6Enforced ? GetScriptForStakeDelegation(stakerKey, ownerKey)
: GetScriptForStakeDelegationLOF(stakerKey, ownerKey), amount, false))
{}

// Transparent recipient: multisig
SendManyRecipient(int nRequired, const std::vector<CPubKey>& keys, const CAmount& amount):
transparentRecipient(CTxOut(amount, GetScriptForMultisig(nRequired, keys)))
transparentRecipient(CRecipient(GetScriptForMultisig(nRequired, keys), amount, false))
{}

// Transparent recipient: OP_RETURN
SendManyRecipient(const uint256& message):
transparentRecipient(CTxOut(0, GetScriptForOpReturn(message)))
transparentRecipient(CRecipient(GetScriptForOpReturn(message), 0, false))
{}
};

Expand Down
10 changes: 5 additions & 5 deletions src/test/librust/sapling_rpc_wallet_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ BOOST_AUTO_TEST_CASE(saplingOperationTests)

// there are no utxos to spend
{
std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1, COIN, "DEADBEEF") };
std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1, COIN, "DEADBEEF", false) };
SaplingOperation operation(consensusParams, 1, pwalletMain.get());
operation.setFromAddress(taddr1);
auto res = operation.setRecipients(recipients)->buildAndSend(ret);
Expand All @@ -359,7 +359,7 @@ BOOST_AUTO_TEST_CASE(saplingOperationTests)

// minconf cannot be zero when sending from zaddr
{
std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1, COIN, "DEADBEEF") };
std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1, COIN, "DEADBEEF", false) };
SaplingOperation operation(consensusParams, 1, pwalletMain.get());
operation.setFromAddress(zaddr1);
auto res = operation.setRecipients(recipients)->setMinDepth(0)->buildAndSend(ret);
Expand All @@ -369,7 +369,7 @@ BOOST_AUTO_TEST_CASE(saplingOperationTests)

// there are no unspent notes to spend
{
std::vector<SendManyRecipient> recipients = { SendManyRecipient(taddr1, COIN) };
std::vector<SendManyRecipient> recipients = { SendManyRecipient(taddr1, COIN, false) };
SaplingOperation operation(consensusParams, 1, pwalletMain.get());
operation.setFromAddress(zaddr1);
auto res = operation.setRecipients(recipients)->buildAndSend(ret);
Expand Down Expand Up @@ -455,15 +455,15 @@ BOOST_AUTO_TEST_CASE(rpc_shieldsendmany_taddr_to_sapling)
pwalletMain->BlockConnected(std::make_shared<CBlock>(block), mi->second);
BOOST_CHECK_MESSAGE(pwalletMain->GetAvailableBalance() > 0, "tx not confirmed");

std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1, 1 * COIN, "ABCD") };
std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1, 1 * COIN, "ABCD", false) };
SaplingOperation operation(consensusParams, nextBlockHeight, pwalletMain.get());
operation.setFromAddress(taddr);
BOOST_CHECK(operation.setRecipients(recipients)
->setMinDepth(0)
->build());

// try from auto-selected transparent address
std::vector<SendManyRecipient> recipients2 = { SendManyRecipient(zaddr1, 1 * COIN, "ABCD") };
std::vector<SendManyRecipient> recipients2 = { SendManyRecipient(zaddr1, 1 * COIN, "ABCD", false) };
SaplingOperation operation2(consensusParams, nextBlockHeight, pwalletMain.get());
BOOST_CHECK(operation2.setSelectTransparentCoins(true)
->setRecipients(recipients2)
Expand Down
5 changes: 3 additions & 2 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1720,10 +1720,11 @@ static SaplingOperation CreateShieldedTransaction(CWallet* const pwallet, const
if (nAmount < 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, amount must be positive");

bool fSubtractFeeFromAmount = false; // !TODO
if (saddr) {
recipients.emplace_back(*saddr, nAmount, memo);
recipients.emplace_back(*saddr, nAmount, memo, fSubtractFeeFromAmount);
} else {
recipients.emplace_back(taddr, nAmount);
recipients.emplace_back(taddr, nAmount, fSubtractFeeFromAmount);
}

nTotalOut += nAmount;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ BOOST_AUTO_TEST_CASE(test_in_block_and_mempool_notes_double_spend)
// single recipient
std::vector<SendManyRecipient> recipients;
libzcash::SaplingPaymentAddress pa = pwalletMain->GenerateNewSaplingZKey("sapling1");
recipients.emplace_back(pa, CAmount(100 * COIN), "");
recipients.emplace_back(pa, CAmount(100 * COIN), "", false);

// Create the operation and build the transaction
SaplingOperation operation = createOperationAndBuildTx(pwalletMain, recipients, tipHeight + 1, true);
Expand All @@ -135,14 +135,14 @@ BOOST_AUTO_TEST_CASE(test_in_block_and_mempool_notes_double_spend)
CTxDestination tDest2;
pwalletMain->getNewAddress(tDest2, "receiveValid");
std::vector<SendManyRecipient> recipients2;
recipients2.emplace_back(tDest2, CAmount(90 * COIN));
recipients2.emplace_back(tDest2, CAmount(90 * COIN), false);
SaplingOperation operation2 = createOperationAndBuildTx(pwalletMain, recipients2, tipHeight + 1, false);

// Create a second transaction that spends the same note with a different output now
CTxDestination tDest3;
pwalletMain->getNewAddress(tDest3, "receiveInvalid");
std::vector<SendManyRecipient> recipients3;
recipients3.emplace_back(tDest3, CAmount(5 * COIN));
recipients3.emplace_back(tDest3, CAmount(5 * COIN), false);
SaplingOperation operation3 = createOperationAndBuildTx(pwalletMain, recipients3, tipHeight + 1, false);

// Now that both transactions were created, broadcast the first one
Expand Down

0 comments on commit cba898b

Please sign in to comment.