From 03791e36fc4ccbb6346abed5db2e5da935014583 Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Mon, 17 Apr 2017 15:01:12 -0400 Subject: [PATCH] FundTransaction needs to give back all the outputs in an unblinded state, including the change outputs. For this we now use the "sign" boolean to back out of the blinding, much like "!sign" means the signatures should be stripped after fee estimation. --- src/wallet/wallet.cpp | 44 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index b251e9b2f9..29c74bb83a 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2404,18 +2404,15 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool ov if (!CreateTransaction(vecSend, wtx, vpChangeKey, nFeeRet, nChangePosInOut, strFailReason, &coinControl, false)) return false; - // Append fee output if any - // This assumes fee is appended to end, and only one fee added by the CreateTransaction call - if (wtx.vout.back().IsFee()) { - tx.vout.push_back(wtx.vout.back()); - } - - if (nChangePosInOut != -1) { - tx.vout.insert(tx.vout.begin() + nChangePosInOut, wtx.vout[nChangePosInOut]); - - // Insert change witness - tx.wit.vtxoutwit.resize(tx.vout.size()-1); - tx.wit.vtxoutwit.insert(tx.wit.vtxoutwit.begin() + nChangePosInOut, wtx.wit.vtxoutwit[nChangePosInOut]); + // Wipe outputs and output witness and re-add one by one + wtx.wit.vtxoutwit.resize(wtx.vout.size()); + tx.vout.clear(); + tx.wit.vtxoutwit.clear(); + for (unsigned int i = 0; i < wtx.vout.size(); i++) { + const CTxOut& out = wtx.vout[i]; + const CTxOutWitness& outwit = wtx.wit.vtxoutwit[i]; + tx.vout.push_back(out); + tx.wit.vtxoutwit.push_back(outwit); } // Add new txins (keeping original txin scriptSig/order) @@ -2536,6 +2533,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt BOOST_FOREACH (const CRecipient& recipient, vecSend) { CTxOut txout(recipient.asset, recipient.nAmount, recipient.scriptPubKey); + txout.nNonce.vchCommitment = std::vector(recipient.confidentiality_key.begin(), recipient.confidentiality_key.end()); if (recipient.fSubtractFeeFromAmount) { @@ -2674,8 +2672,9 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt } vector::iterator position = txNew.vout.begin()+nChangePosInOut; - txNew.vout.insert(position, newTxOut); CPubKey pubkey = GetBlindingPubKey(scriptChange); + newTxOut.nNonce.vchCommitment = std::vector(pubkey.begin(), pubkey.end()); + txNew.vout.insert(position, newTxOut); output_pubkeys.insert(output_pubkeys.begin() + nChangePosInOut, pubkey); if (pubkey != CPubKey()) { numToBlind++; @@ -2826,6 +2825,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt } // Keep a backup of transaction in case re-blinding necessary + CMutableTransaction txUnblindedAndUnsigned(txNew); CMutableTransaction txBackup(txNew); int ret = BlindTransaction(input_blinds, input_asset_blinds, input_assets, input_amounts, output_blinds, output_asset_blinds, output_pubkeys, vassetKeys, vtokenKeys, txNew); // TODO remove? @@ -2878,11 +2878,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt // Remove scriptSigs if we used dummy signatures for fee calculation if (!sign) { - BOOST_FOREACH (CTxIn& vin, txNew.vin) - vin.scriptSig = CScript(); - // Only clear our script witness - BOOST_FOREACH (CTxInWitness& txinwit, txNew.wit.vtxinwit) - txinwit.scriptWitness.stack.clear(); + txNew = txUnblindedAndUnsigned; } // Embed the constructed transaction data in wtxNew. @@ -2893,11 +2889,13 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt assert(output_blinds.size() == output_asset_blinds.size()); assert(output_asset_blinds.size() == output_assets.size()); - for (unsigned int i = 0; i< vAmounts.size(); i++) { - assert((output_pubkeys[i] == CPubKey())==(output_blinds[i] == uint256())); - assert((output_pubkeys[i] == CPubKey())==(output_asset_blinds[i] == uint256())); - assert(!output_assets[i].IsNull()); - wtxNew.SetBlindingData(i, vAmounts[i], output_pubkeys[i], output_blinds[i], output_assets[i], output_asset_blinds[i]); + if (sign) { + for (unsigned int i = 0; i< vAmounts.size(); i++) { + assert((output_pubkeys[i] == CPubKey())==(output_blinds[i] == uint256())); + assert((output_pubkeys[i] == CPubKey())==(output_asset_blinds[i] == uint256())); + assert(!output_assets[i].IsNull()); + wtxNew.SetBlindingData(i, vAmounts[i], output_pubkeys[i], output_blinds[i], output_assets[i], output_asset_blinds[i]); + } } // Limit size