PIVX Core  5.6.99
P2P Digital Currency
sapling_operation.cpp
Go to the documentation of this file.
1 // Copyright (c) 2021 The PIVX Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or https://www.opensource.org/licenses/mit-license.php.
4 
6 
7 #include "coincontrol.h"
8 #include "net.h" // for g_connman
9 #include "policy/policy.h" // for GetDustThreshold
10 #include "sapling/key_io_sapling.h"
11 #include "script/standard.h"
12 #include "utilmoneystr.h" // for FormatMoney
13 
14 struct TxValues
15 {
21 };
22 
24  wallet(_wallet),
25  txBuilder(consensusParams, _wallet)
26 {
27  assert (wallet != nullptr);
28 };
29 
31 {
32  delete tkeyChange;
33 }
34 
35 OperationResult SaplingOperation::checkTxValues(TxValues& txValues, bool isFromtAddress, bool isFromShielded)
36 {
37  assert(!isFromtAddress || txValues.shieldedInTotal == 0);
38  assert(!isFromShielded || txValues.transInTotal == 0);
39 
40  if (isFromtAddress && (txValues.transInTotal < txValues.target)) {
41  return errorOut(strprintf("Insufficient transparent funds, have %s, need %s",
42  FormatMoney(txValues.transInTotal), FormatMoney(txValues.target)));
43  }
44 
45  if (isFromShielded && (txValues.shieldedInTotal < txValues.target)) {
46  return errorOut(strprintf("Insufficient shielded funds, have %s, need %s",
47  FormatMoney(txValues.shieldedInTotal), FormatMoney(txValues.target)));
48  }
49  return OperationResult(true);
50 }
51 
55  uint256& ovkOut)
56 {
57  // Get spending key for address
59  if (!pwallet->GetSaplingExtendedSpendingKey(addr, sk)) {
60  return errorOut("Spending key not in the wallet");
61  }
62  expskOut = sk.expsk;
63  ovkOut = expskOut.full_viewing_key().ovk;
64  return OperationResult(true);
65 }
66 
67 TxValues calculateTarget(const std::vector<SendManyRecipient>& recipients, const CAmount& fee)
68 {
69  TxValues txValues;
70  for (const SendManyRecipient &t : recipients) {
71  if (t.IsTransparent()) {
72  txValues.transOutTotal += t.getAmount();
73  } else {
74  txValues.shieldedOutTotal += t.getAmount();
75  }
76  }
77  txValues.target = txValues.shieldedOutTotal + txValues.transOutTotal + fee;
78  return txValues;
79 }
80 
82 {
83  bool isFromtAddress = false;
84  bool isFromShielded = false;
85 
87  // if coin control was selected it overrides any other defined configuration
88  std::vector<OutPointWrapper> coins;
89  coinControl->ListSelected(coins);
90  // first check that every selected input is from the same type, cannot be mixed for clear privacy reasons.
91  // error is thrown below if it happens, not here.
92  for (const auto& coin : coins) {
93  if (coin.outPoint.isTransparent) {
94  isFromtAddress = true;
95  } else {
96  isFromShielded = true;
97  }
98  }
99  } else {
100  // Regular flow
101  isFromtAddress = fromAddress.isFromTAddress();
102  isFromShielded = fromAddress.isFromSapAddress();
103 
104  if (!isFromtAddress && !isFromShielded) {
105  isFromtAddress = selectFromtaddrs;
106  isFromShielded = selectFromShield;
107  }
108  }
109 
110  // It needs to have a from.
111  if (!isFromtAddress && !isFromShielded) {
112  return errorOut("From address parameter missing");
113  }
114 
115  // Cannot be from both
116  if (isFromtAddress && isFromShielded) {
117  return errorOut("From address type cannot be shielded and transparent");
118  }
119 
120  if (recipients.empty()) {
121  return errorOut("No recipients");
122  }
123 
124  if (isFromShielded && mindepth == 0) {
125  return errorOut("Minconf cannot be zero when sending from shielded address");
126  }
127 
128  // Check outputs to subtract fee from
129  unsigned int nSubtractFeeFromAmount = 0;
130  for (const SendManyRecipient& rec : recipients) {
131  if (rec.IsSubtractFee()) nSubtractFeeFromAmount++;
132  }
133 
134  CAmount nFeeRet = (fee > 0 ? fee : minRelayTxFee.GetFeePerK());
135  int tries = 0;
136  while (true) {
137  // First calculate target values
138  TxValues txValues = calculateTarget(recipients, nSubtractFeeFromAmount == 0 ? nFeeRet : 0);
139  OperationResult result(false);
140  uint256 ovk;
141  if (isFromShielded) {
142  // Load and select notes to spend, then return the ovk of the first note input of the transaction
143  if (!(result = loadUnspentNotes(txValues, ovk))) {
144  return result;
145  }
146  } else {
147  // Get the common OVK for recovering t->shield outputs.
148  // If not already databased, a new one will be generated from the HD seed.
149  // It is safe to do it here, as the wallet is unlocked.
151  }
152 
153  // Add outputs
154  bool fFirst = true;
155  for (const SendManyRecipient &t : recipients) {
156  CAmount amount = t.getAmount();
157  // Subtract from fee calculation
158  if (t.IsSubtractFee()) {
159  // Subtract fee equally from each selected recipient
160  amount -= nFeeRet / nSubtractFeeFromAmount;
161  if (fFirst) {
162  // first receiver pays the remainder not divisible by output count
163  fFirst = false;
164  amount -= nFeeRet % nSubtractFeeFromAmount;
165  }
166  }
167  // Append output
168  if (t.IsTransparent()) {
169  txBuilder.AddTransparentOutput(CTxOut(amount, t.getScript()));
170  } else {
171  const auto& address = t.getSapPaymentAddr();
172  assert(IsValidPaymentAddress(address));
173  std::array<unsigned char, ZC_MEMO_SIZE> vMemo = {};
174  if (!(result = GetMemoFromString(t.getMemo(), vMemo)))
175  return result;
176  txBuilder.AddSaplingOutput(ovk, address, amount, vMemo);
177  }
178  }
179 
180  // If from address is a taddr, select UTXOs to spend
181  // note: when spending coinbase utxos, you can only specify a single shielded addr as the change must go somewhere
182  // and if there are multiple shielded addrs, we don't know where to send it.
183  if (isFromtAddress && !(result = loadUtxos(txValues))) {
184  return result;
185  }
186 
187  const auto& retCalc = checkTxValues(txValues, isFromtAddress, isFromShielded);
188  if (!retCalc) return retCalc;
189 
190  // By default look for a shield change address
193 
194  // If not found, and the transaction is transparent, set transparent change address
195  } else if (isFromtAddress) {
196  // Try to use coin control first
199  // No Coin control! Then we can just use a random key from the keypool
200  } else {
201  if (!tkeyChange) {
203  }
204  CPubKey vchPubKey;
205  if (!tkeyChange->GetReservedKey(vchPubKey, true)) {
206  return errorOut("Could not generate a taddr to use as a change address");
207  }
208  CTxDestination changeAddr = vchPubKey.GetID();
209  txBuilder.SendChangeTo(changeAddr);
210  }
211  }
212 
213  // Build the transaction
214  txBuilder.SetFee(nFeeRet);
215  TransactionBuilderResult txResult = txBuilder.Build(true);
216  auto opTx = txResult.GetTx();
217 
218  // Check existent tx
219  if (!opTx) {
220  return errorOut("Failed to build transaction: " + txResult.GetError());
221  }
222 
223  // Now check fee
224  bool isShielded = opTx->IsShieldedTx();
225  const CAmount& nFeeNeeded = isShielded ? GetShieldedTxMinFee(*opTx) :
226  GetMinRelayFee(opTx->GetTotalSize());
227  if (nFeeNeeded <= nFeeRet) {
228  // Check that the fee is not too high.
229  CAmount nMaxFee = nFeeNeeded * (isShielded ? 100 : 10000);
230  if (nFeeRet > nMaxFee) {
231  return errorOut(strprintf("The transaction fee is too high: %s > %s", FormatMoney(nFeeRet), FormatMoney(100 * nFeeNeeded)));
232  }
233  // Done, enough fee included
234  LogPrint(BCLog::SAPLING, "%s: spending %s to send %s with fee %s (min required %s)\n", __func__ , FormatMoney(txValues.target),
235  FormatMoney(txValues.shieldedOutTotal + txValues.transOutTotal), FormatMoney(nFeeRet), FormatMoney(nFeeNeeded));
236  LogPrint(BCLog::SAPLING, "%s: transparent input: %s (to choose from)\n", __func__ , FormatMoney(txValues.transInTotal));
237  LogPrint(BCLog::SAPLING, "%s: private input: %s (to choose from)\n", __func__ , FormatMoney(txValues.shieldedInTotal));
238  LogPrint(BCLog::SAPLING, "%s: transparent output: %s\n", __func__ , FormatMoney(txValues.transOutTotal));
239  LogPrint(BCLog::SAPLING, "%s: private output: %s\n", __func__ , FormatMoney(txValues.shieldedOutTotal));
240  break;
241  }
242  if (fee > 0 && nFeeNeeded > fee) {
243  // User selected fee is not enough
244  return errorOut(strprintf("Fee set (%s) too low. Must be at least %s", FormatMoney(fee), FormatMoney(nFeeNeeded)));
245  }
246  // If we can't get the optimal fee after 100 tries, give up.
247  if (++tries > 100) {
248  return errorOut("Unable to compute optimal fee. Set manually.");
249  }
250  // include more fee and try again
251  LogPrint(BCLog::SAPLING, "%s: incrementing fee: %s --> %s\n", __func__ , FormatMoney(nFeeRet), FormatMoney(nFeeNeeded));
252  clearTx();
253  nFeeRet = nFeeNeeded;
254  }
255  // Done
256  fee = nFeeRet;
257 
258  // Clear dummy signatures/proofs and add real ones
261  auto opTx = txResult.GetTx();
262  // Check existent tx
263  if (!opTx) {
264  return errorOut("Failed to build transaction: " + txResult.GetError());
265  }
266  finalTx = MakeTransactionRef(*opTx);
267  return OperationResult(true);
268 }
269 
271 {
273  if (res.status != CWallet::CommitStatus::OK) {
274  return errorOut(res.ToString());
275  }
276 
277  retTxHash = finalTx->GetHash().ToString();
278  return OperationResult(true);
279 }
280 
282 {
283  OperationResult res = build();
284  return (res) ? send(retTxHash) : res;
285 }
286 
288 {
289  fromAddress = FromAddress(_dest);
290 }
291 
293 {
294  fromAddress = FromAddress(_payment);
295 }
296 
297 SaplingOperation* SaplingOperation::setSelectTransparentCoins(const bool select, const bool _fIncludeDelegated)
298 {
299  selectFromtaddrs = select;
300  if (selectFromtaddrs) fIncludeDelegated = _fIncludeDelegated;
301  return this;
302 };
303 
305 {
306  // If the user has selected coins to spend then, directly load them.
307  // The spendability, depth and other checks should have been done on the user selection side,
308  // no need to do them again.
309  if (coinControl && coinControl->HasSelected()) {
310  std::vector<OutPointWrapper> vCoins;
311  coinControl->ListSelected(vCoins);
312 
313  std::vector<COutput> selectedUTXOInputs;
314  CAmount nSelectedValue = 0;
315  for (const auto& outpoint : vCoins) {
316  const auto* tx = wallet->GetWalletTx(outpoint.outPoint.hash);
317  if (!tx) continue;
318  nSelectedValue += tx->tx->vout[outpoint.outPoint.n].nValue;
319  selectedUTXOInputs.emplace_back(tx, outpoint.outPoint.n, 0, true, true, true);
320  }
321  return loadUtxos(txValues, selectedUTXOInputs, nSelectedValue);
322  }
323 
324  // No coin control selected, let's find the utxo by our own.
325  std::set<CTxDestination> destinations;
326  if (fromAddress.isFromTAddress()) destinations.insert(fromAddress.fromTaddr);
328  false,
329  true,
330  true,
331  &destinations,
332  mindepth);
333  if (!wallet->AvailableCoins(&transInputs, nullptr, coinsFilter)) {
334  return errorOut("Insufficient funds, no available UTXO to spend");
335  }
336 
337  // sort in descending order, so higher utxos appear first
338  std::sort(transInputs.begin(), transInputs.end(), [](const COutput& i, const COutput& j) -> bool {
339  return i.Value() > j.Value();
340  });
341 
342  // Final step, append utxo to the transaction
343 
344  // Get dust threshold
345  CAmount dustThreshold = GetDustThreshold(dustRelayFee);
346  CAmount dustChange = -1;
347 
348  CAmount selectedUTXOAmount = 0;
349  std::vector<COutput> selectedTInputs;
350  for (const COutput& t : transInputs) {
351  const auto& outPoint = t.tx->tx->vout[t.i];
352  selectedUTXOAmount += outPoint.nValue;
353  selectedTInputs.emplace_back(t);
354  if (selectedUTXOAmount >= txValues.target) {
355  // Select another utxo if there is change less than the dust threshold.
356  dustChange = selectedUTXOAmount - txValues.target;
357  if (dustChange == 0 || dustChange >= dustThreshold) {
358  break;
359  }
360  }
361  }
362 
363  // Not enough funds
364  if (selectedUTXOAmount < txValues.target) {
365  return errorOut(strprintf("Insufficient transparent funds, have %s, need %s",
366  FormatMoney(selectedUTXOAmount), FormatMoney(txValues.target)));
367  }
368 
369  // If there is transparent change, is it valid or is it dust?
370  if (dustChange < dustThreshold && dustChange != 0) {
371  return errorOut(strprintf("Insufficient transparent funds, have %s, need %s more to avoid creating invalid change output %s (dust threshold is %s)",
372  FormatMoney(selectedUTXOAmount), FormatMoney(dustThreshold - dustChange), FormatMoney(dustChange), FormatMoney(dustThreshold)));
373  }
374 
375  return loadUtxos(txValues, selectedTInputs, selectedUTXOAmount);
376 }
377 
378 OperationResult SaplingOperation::loadUtxos(TxValues& txValues, const std::vector<COutput>& selectedUTXO, const CAmount selectedUTXOAmount)
379 {
380  transInputs = selectedUTXO;
381  txValues.transInTotal = selectedUTXOAmount;
382 
383  // update the transaction with these inputs
384  for (const auto& t : transInputs) {
385  const auto& outPoint = t.tx->tx->vout[t.i];
386  txBuilder.AddTransparentInput(COutPoint(t.tx->GetHash(), t.i), outPoint.scriptPubKey, outPoint.nValue);
387  }
388  return OperationResult(true);
389 }
390 
391 /*
392  * Check that the witness and nullifier of a sapling note (about to be spent) have been
393  * correctly cached. If the witness is missing, return an error. If the nullifier is missing,
394  * recover it from the note (now that we have the spending key).
395  */
397 static CacheCheckResult CheckCachedNote(CWallet* pwallet,
398  const SaplingNoteEntry& t,
400 {
401  auto sspkm = pwallet->GetSaplingScriptPubKeyMan();
402  CWalletTx& prevTx = pwallet->mapWallet.at(t.op.hash);
403  SaplingNoteData& nd = prevTx.mapSaplingNoteData.at(t.op);
404  if (nd.witnesses.empty()) {
406  }
407  if (nd.nullifier == nullopt) {
408  const std::string& noteStr = t.op.ToString();
409  LogPrintf("WARNING: nullifier not cached for note %s. Updating...\n", noteStr);
410  // get the nullifier from the note and update the cache
411  const auto& witness = nd.witnesses.front();
412  const Optional<uint256> nf = t.note.nullifier(expsk.full_viewing_key(), witness.position());
413  // check that it's valid
414  if (nf == nullopt) {
415  LogPrintf("ERROR: Unable to recover nullifier for note %s.\n", noteStr);
417  }
418  WITH_LOCK(pwallet->cs_wallet, sspkm->UpdateSaplingNullifierNoteMap(nd, t.op, nf));
419  // re-check the spent status
420  if (sspkm->IsSaplingSpent(*(nd.nullifier))) {
421  LogPrintf("Removed note %s as it appears to be already spent.\n", noteStr);
422  prevTx.MarkDirty();
423  WalletBatch(pwallet->GetDBHandle(), "r+").WriteTx(prevTx);
424  pwallet->NotifyTransactionChanged(pwallet, t.op.hash, CT_UPDATED);
426  }
427  }
428  return CacheCheckResult::OK;
429 }
430 
432 {
433  shieldedInputs.clear();
434  auto sspkm = wallet->GetSaplingScriptPubKeyMan();
435  // if we already have selected the notes, let's directly set them.
436  bool hasCoinControl = coinControl && coinControl->HasSelected();
437  if (hasCoinControl) {
438  std::vector<OutPointWrapper> vCoins;
439  coinControl->ListSelected(vCoins);
440 
441  // Converting outpoint wrapper to sapling outpoints
442  std::vector<SaplingOutPoint> vSaplingOutpoints;
443  vSaplingOutpoints.reserve(vCoins.size());
444  for (const auto& outpoint : vCoins) {
445  vSaplingOutpoints.emplace_back(outpoint.outPoint.hash, outpoint.outPoint.n);
446  }
447 
448  sspkm->GetNotes(vSaplingOutpoints, shieldedInputs);
449 
450  if (shieldedInputs.empty()) {
451  return errorOut("Insufficient funds, no available notes to spend");
452  }
453  } else {
454  // If we don't have coinControl then let's find the notes
455  sspkm->GetFilteredNotes(shieldedInputs, fromAddress.fromSapAddr, mindepth);
456  if (shieldedInputs.empty()) {
457  // Just to notify the user properly, check if the wallet has notes with less than the min depth
458  std::vector<SaplingNoteEntry> _shieldedInputs;
459  sspkm->GetFilteredNotes(_shieldedInputs, fromAddress.fromSapAddr, 0);
460  return errorOut(_shieldedInputs.empty() ?
461  "Insufficient funds, no available notes to spend" :
462  "Insufficient funds, shielded PIV need at least 5 confirmations");
463  }
464  }
465 
466  // sort in descending order, so big notes appear first
467  std::sort(shieldedInputs.begin(), shieldedInputs.end(),
468  [](const SaplingNoteEntry& i, const SaplingNoteEntry& j) -> bool {
469  return i.note.value() > j.note.value();
470  });
471 
472  // Now select the notes that we are going to use.
473  std::vector<SaplingOutPoint> ops;
474  std::vector<libzcash::SaplingNote> notes;
475  std::vector<libzcash::SaplingExpandedSpendingKey> spendingKeys;
476  txValues.shieldedInTotal = 0;
478  CAmount dustChange = -1;
479  for (const auto& t : shieldedInputs) {
480  // Get the spending key for the address.
482  uint256 ovkIn;
483  auto resLoadKeys = loadKeysFromShieldedFrom(wallet, t.address, expsk, ovkIn);
484  if (!resLoadKeys) return resLoadKeys;
485 
486  // If the noteData is not properly cached, for whatever reason,
487  // try to update it here, now that we have the spending key.
488  CacheCheckResult res = CheckCachedNote(wallet, t, expsk);
489  if (res == CacheCheckResult::INVALID) {
490  // This should never happen. User would be forced to zap.
491  LogPrintf("ERROR: Witness/Nullifier invalid for note %s. Restart with --zapwallettxes\n", t.op.ToString());
492  return errorOut("Note cache corrupt. Try \"Recover transactions\" (Settings-->Debug-->\"wallet repair\")");
493  } else if (res == CacheCheckResult::SPENT) {
494  // note was already spent, don't include it in the inputs
495  continue;
496  }
497 
498  // Return ovk to be used in the outputs
499  if (ovk.IsNull()) {
500  ovk = ovkIn;
501  }
502 
503  // Load data
504  spendingKeys.emplace_back(expsk);
505  ops.emplace_back(t.op);
506  notes.emplace_back(t.note);
507  txValues.shieldedInTotal += t.note.value();
508  if (!hasCoinControl && txValues.shieldedInTotal >= txValues.target) {
509  // coin control selection by pass this check, uses all the selected notes.
510  // Select another note if there is change less than the dust threshold.
511  dustChange = txValues.shieldedInTotal - txValues.target;
512  if (dustChange == 0 || dustChange >= dustThreshold) {
513  break;
514  }
515  }
516  }
517 
518  // Not enough funds
519  if (txValues.shieldedInTotal < txValues.target) {
520  return errorOut(strprintf("Insufficient shielded funds, have %s, need %s",
521  FormatMoney(txValues.shieldedInTotal), FormatMoney(txValues.target)));
522  }
523 
524  // Fetch Sapling anchor and witnesses
525  uint256 anchor;
526  std::vector<Optional<SaplingWitness>> witnesses;
527  wallet->GetSaplingScriptPubKeyMan()->GetSaplingNoteWitnesses(ops, witnesses, anchor);
528 
529  // Add Sapling spends
530  for (size_t i = 0; i < notes.size(); i++) {
531  if (!witnesses[i]) {
532  return errorOut("Missing witness for Sapling note");
533  }
534  txBuilder.AddSaplingSpend(spendingKeys[i], notes[i], anchor, witnesses[i].get());
535  }
536 
537  return OperationResult(true);
538 }
539 
540 OperationResult GetMemoFromString(const std::string& s, std::array<unsigned char, ZC_MEMO_SIZE>& memoRet)
541 {
542  memoRet.fill(0x00);
543  // default memo (no_memo), see section 5.5 of the protocol spec
544  if (s.empty()) {
545  memoRet[0] = 0xF6;
546  return OperationResult(true);
547  }
548  // non-empty memo
549  std::vector<unsigned char> rawMemo(s.begin(), s.end());
550  const size_t sizeMemo = rawMemo.size();
551  if (sizeMemo > ZC_MEMO_SIZE) {
552  return errorOut(strprintf("Memo size of %d is too big, maximum allowed is %d", sizeMemo, ZC_MEMO_SIZE));
553  }
554  // copy vector into array
555  for (unsigned int i = 0; i < sizeMemo; i++) {
556  memoRet[i] = rawMemo[i];
557  }
558  return OperationResult(true);
559 }
560 
561 OperationResult CheckTransactionSize(std::vector<SendManyRecipient>& recipients, bool fromTaddr)
562 {
565  unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING;
566 
567  // As a sanity check, estimate and verify that the size of the transaction will be valid.
568  // Depending on the input notes, the actual tx size may turn out to be larger and perhaps invalid.
569  size_t nTransparentOuts = 0;
570  for (const auto& t : recipients) {
571  if (t.IsTransparent()) {
572  nTransparentOuts++;
573  continue;
574  }
575  if (IsValidPaymentAddress(t.getSapPaymentAddr())) {
576  mtx.sapData->vShieldedOutput.emplace_back();
577  } else {
578  return errorOut(strprintf("invalid recipient shielded address %s",
579  KeyIO::EncodePaymentAddress(t.getSapPaymentAddr())));
580  }
581  }
582  CTransaction tx(mtx);
583  size_t txsize = tx.GetTotalSize() + CTXOUT_REGULAR_SIZE * nTransparentOuts;
584  if (fromTaddr) {
585  txsize += CTXIN_SPEND_DUST_SIZE;
586  txsize += CTXOUT_REGULAR_SIZE; // There will probably be taddr change
587  }
588  if (txsize > max_tx_size) {
589  return errorOut(strprintf("Too many outputs, size of raw transaction would be larger than limit of %d bytes", max_tx_size));
590  }
591  return OperationResult(true);
592 }
bool IsValidPaymentAddress(const libzcash::PaymentAddress &zaddr)
Check whether a PaymentAddress is not an InvalidEncoding.
Definition: address.cpp:92
int64_t CAmount
Amount in PIV (Can be negative)
Definition: amount.h:13
uint256 hash
Definition: transaction.h:35
bool GetSaplingExtendedSpendingKey(const libzcash::SaplingPaymentAddress &addr, libzcash::SaplingExtendedSpendingKey &extskOut) const
Definition: keystore.cpp:240
bool HasSelected() const
Definition: coincontrol.h:66
void ListSelected(std::vector< OutPointWrapper > &vOutpoints) const
Definition: coincontrol.h:91
CTxDestination destChange
Definition: coincontrol.h:38
Optional< libzcash::SaplingPaymentAddress > destShieldChange
Definition: coincontrol.h:37
CAmount GetFeePerK() const
Definition: feerate.h:29
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:72
An encapsulated public key.
Definition: pubkey.h:44
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:167
A key allocated from the key pool.
Definition: wallet.h:1256
The basic transaction that is broadcasted on the network and contained in blocks.
Definition: transaction.h:244
unsigned int GetTotalSize() const
An output of a transaction.
Definition: transaction.h:137
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,...
Definition: wallet.h:577
std::map< uint256, CWalletTx > mapWallet
Definition: wallet.h:766
RecursiveMutex cs_wallet
Definition: wallet.h:720
boost::signals2::signal< void(CWallet *wallet, const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged
Wallet transaction added, removed or updated.
Definition: wallet.h:1239
SaplingScriptPubKeyMan * GetSaplingScriptPubKeyMan() const
Definition: wallet.h:712
WalletDatabase & GetDBHandle() const
Definition: wallet.h:752
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:325
CTransactionRef tx
Definition: wallet.h:364
mapSaplingNoteData_t mapSaplingNoteData
Definition: wallet.h:336
void MarkDirty()
make sure balances are recalculated
Definition: wallet.cpp:4833
CTxDestination fromTaddr
bool isFromTAddress() const
bool isFromSapAddress() const
Optional< libzcash::SaplingPaymentAddress > fromSapAddr
Optional< uint256 > nullifier
Cached note nullifier.
std::list< SaplingWitness > witnesses
std::vector< SaplingNoteEntry > shieldedInputs
FromAddress fromAddress
CTransactionRef finalTx
const CCoinControl * coinControl
SaplingOperation(const Consensus::Params &consensusParams, CWallet *_wallet)
TransactionBuilder txBuilder
OperationResult loadUnspentNotes(TxValues &txValues, uint256 &ovk)
CReserveKey * tkeyChange
OperationResult loadUtxos(TxValues &values)
OperationResult checkTxValues(TxValues &txValues, bool isFromtAddress, bool isFromShielded)
void setFromAddress(const CTxDestination &)
std::vector< COutput > transInputs
OperationResult send(std::string &retTxHash)
OperationResult build()
std::vector< SendManyRecipient > recipients
OperationResult buildAndSend(std::string &retTxHash)
SaplingOperation * setSelectTransparentCoins(const bool select, const bool _fIncludeDelegated=false)
std::string ToString() const
Definition: transaction.cpp:23
void GetSaplingNoteWitnesses(const std::vector< SaplingOutPoint > &notes, std::vector< Optional< SaplingWitness >> &witnesses, uint256 &final_anchor) const
Return all of the witnesses for the input notes.
void AddTransparentOutput(const CTxOut &out)
void SetFee(CAmount _fee)
void AddSaplingSpend(const libzcash::SaplingExpandedSpendingKey &expsk, const libzcash::SaplingNote &note, const uint256 &anchor, const SaplingWitness &witness)
TransactionBuilderResult Build(bool fDummySig=false)
void AddSaplingOutput(const uint256 &ovk, const libzcash::SaplingPaymentAddress &to, CAmount value, const std::array< unsigned char, ZC_MEMO_SIZE > &memo)
TransactionBuilderResult ProveAndSign()
void AddTransparentInput(const COutPoint &utxo, const CScript &scriptPubKey, CAmount value)
void SendChangeTo(const libzcash::SaplingPaymentAddress &changeAddr, const uint256 &ovk)
Optional< CTransaction > GetTx()
Access to the wallet database.
Definition: walletdb.h:112
bool WriteTx(const CWalletTx &wtx)
Definition: walletdb.cpp:92
bool IsNull() const
Definition: uint256.h:36
uint64_t value() const
Definition: note.h:30
SaplingFullViewingKey full_viewing_key() const
Definition: address.cpp:29
Optional< uint256 > nullifier(const SaplingFullViewingKey &vk, const uint64_t position) const
Definition: note.cpp:47
Sapling functions.
Definition: address.h:30
256-bit opaque blob.
Definition: uint256.h:138
CWallet::CommitResult CommitTransaction(CTransactionRef tx, CReserveKey &opReservekey, CConnman *connman)
Definition: wallet.cpp:3510
bool AvailableCoins(std::vector< COutput > *pCoins, const CCoinControl *coinControl=nullptr, AvailableCoinsFilter coinsFilter=AvailableCoinsFilter()) const
populate vCoins with vector of available COutputs.
Definition: wallet.cpp:2555
bool GetReservedKey(CPubKey &pubkey, bool internal=false)
Definition: wallet.cpp:3901
std::string ToString() const
Definition: wallet.cpp:3489
const CWalletTx * GetWalletTx(const uint256 &hash) const
Definition: wallet.cpp:166
@ CT_UPDATED
Definition: guiinterface.h:26
std::unique_ptr< CConnman > g_connman
Definition: init.cpp:90
#define LogPrint(category,...)
Definition: logging.h:163
@ SAPLING
Definition: logging.h:63
std::string EncodePaymentAddress(const libzcash::PaymentAddress &zaddr)
bool IsValidDestination(const CWDestination &address)
OperationResult errorOut(const std::string &errorStr)
boost::optional< T > Optional
Substitute for C++17 std::optional.
Definition: optional.h:12
CAmount GetDustThreshold(const CTxOut &txout, const CFeeRate &dustRelayFeeIn)
Definition: policy.cpp:21
CAmount GetShieldedDustThreshold(const CFeeRate &dustRelayFeeIn)
Definition: policy.cpp:50
CFeeRate dustRelayFee
Definition: policy.cpp:19
#define ZC_MEMO_SIZE
Definition: sapling.h:24
OperationResult loadKeysFromShieldedFrom(const CWallet *pwallet, const libzcash::SaplingPaymentAddress &addr, libzcash::SaplingExpandedSpendingKey &expskOut, uint256 &ovkOut)
TxValues calculateTarget(const std::vector< SendManyRecipient > &recipients, const CAmount &fee)
OperationResult GetMemoFromString(const std::string &s, std::array< unsigned char, ZC_MEMO_SIZE > &memoRet)
CacheCheckResult
OperationResult CheckTransactionSize(std::vector< SendManyRecipient > &recipients, bool fromTaddr)
#define CTXIN_SPEND_DUST_SIZE
#define CTXOUT_REGULAR_SIZE
boost::variant< CNoDestination, CKeyID, CScriptID, CExchangeKeyID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:72
A mutable version of CTransaction.
Definition: transaction.h:409
Optional< SaplingTxData > sapData
Definition: transaction.h:415
CWallet::CommitStatus status
Definition: wallet.h:1106
Parameters that influence chain consensus.
Definition: params.h:171
Sapling note, its location in a transaction, and number of confirmations.
SaplingOutPoint op
libzcash::SaplingPaymentAddress address
libzcash::SaplingNote note
CAmount shieldedInTotal
CAmount shieldedOutTotal
CAmount transInTotal
CAmount transOutTotal
libzcash::SaplingExpandedSpendingKey expsk
Definition: zip32.h:92
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:247
#define strprintf
Definition: tinyformat.h:1056
std::string FormatMoney(const CAmount &n, bool fPlus)
Money parsing/formatting utilities.
CAmount GetShieldedTxMinFee(const CTransaction &tx)
Return the minimum fee for a shielded tx.
Definition: validation.cpp:288
CFeeRate minRelayTxFee
Fees smaller than this (in upiv) are considered zero fee (for relaying, mining and transaction creati...
Definition: validation.cpp:108
CAmount GetMinRelayFee(const CTransaction &tx, const CTxMemPool &pool, unsigned int nBytes)
Definition: validation.cpp:265