From e30340a8d656540ed2ff44078fd0a2ecc1770cca Mon Sep 17 00:00:00 2001 From: instagibbs Date: Tue, 7 Jun 2016 14:51:47 -0400 Subject: [PATCH] CreateTransaction stores destination blinding keys,factors, and amounts --- src/blind.cpp | 11 ++++++----- src/blind.h | 7 ++++++- src/wallet/wallet.cpp | 33 +++++++++++++++++++++++++++++++++ src/wallet/wallet.h | 5 ++++- 4 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/blind.cpp b/src/blind.cpp index d300608820..357a137620 100644 --- a/src/blind.cpp +++ b/src/blind.cpp @@ -60,7 +60,7 @@ bool UnblindOutput(const CKey &key, const CTxOut& txout, CAmount& amount_out, ui } } -bool BlindOutputs(const std::vector& input_blinding_factors, const std::vector& output_blinding_factors, const std::vector& output_pubkeys, CMutableTransaction& tx) +bool BlindOutputs(const std::vector& input_blinding_factors, std::vector& output_blinding_factors, const std::vector& output_pubkeys, CMutableTransaction& tx) { assert(tx.vout.size() == output_blinding_factors.size()); assert(tx.vout.size() == output_pubkeys.size()); @@ -84,10 +84,10 @@ bool BlindOutputs(const std::vector& input_blinding_factors, const std //Number of outputs to newly blind int nToBlind = 0; for (size_t nOut = 0; nOut < tx.vout.size(); nOut++) { - assert((output_blinding_factors[nOut] != uint256()) == !tx.vout[nOut].nValue.IsAmount()); - if (output_blinding_factors[nOut] != uint256()) { - blindptrs.push_back(output_blinding_factors[nOut].begin()); - nBlindsOut++; + assert((output_blinding_factors[nOut] != uint256()) == !tx.vout[nOut].nValue.IsAmount()); + if (output_blinding_factors[nOut] != uint256()) { + blindptrs.push_back(output_blinding_factors[nOut].begin()); + nBlindsOut++; } else { if (output_pubkeys[nOut].IsValid()) { nToBlind++; @@ -125,6 +125,7 @@ bool BlindOutputs(const std::vector& input_blinding_factors, const std GetRandBytes(&blind[nBlinded][0], 32); blindptrs.push_back(&blind[nBlinded++][0]); } + output_blinding_factors[nOut] = uint256(std::vector(blindptrs[blindptrs.size()-1], blindptrs[blindptrs.size()-1]+32)); nBlindsOut++; // Create blinded value CTxOutValue& value = tx.vout[nOut].nValue; diff --git a/src/blind.h b/src/blind.h index af550e7328..22e5114f04 100644 --- a/src/blind.h +++ b/src/blind.h @@ -9,7 +9,12 @@ bool UnblindOutput(const CKey& blinding_key, const CTxOut& txout, CAmount& amoun /* Returns false if there is no output to create where the non-zero resultant (inputs - outputs) factor can be put. * The caller should retry with an extra blinded output, in that case. + * @param[in] input_blinding_factors - A vector of input blinding factors that will be used to create the balanced output blinding factors + * @param[in/out] output_blinding_factors - A vector of blinding factors. Null uint256 values are used to signal to the callee that a new blinding is needed. New blinds then replace the blank values. + * @param[in] blinding factor must be created for the commitments and range proof creation. Non-null is used to signal that the given value should be used. + * @param[in] output_pubkeys - If non-null, these pubkeys will be used in conjunction with the non-null passed in output blinding factors. + * @param[in/out] tx - The transaction to be modified. */ -bool BlindOutputs(const std::vector& input_blinding_factors, const std::vector& output_blinding_factors, const std::vector& output_pubkeys, CMutableTransaction& tx); +bool BlindOutputs(const std::vector& input_blinding_factors, std::vector& output_blinding_factors, const std::vector& output_pubkeys, CMutableTransaction& tx); #endif diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a74c8b73ea..695720bca2 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1512,6 +1512,7 @@ void CWalletTx::GetAmounts(list& listReceived, listReceived.push_back(output); } + // This should not happen if transaction was created via CreateTransaction if (nValueUnaccounted != 0 && nDebit > 0) { if (nValueUnaccounted > 0 && nUnaccountedOutputs == 1) { // There is exactly one sent output with unknown value. Reconstruct it. @@ -1911,6 +1912,26 @@ bool CWalletTx::IsEquivalentTo(const CWalletTx& _tx) const return CTransaction(tx1) == CTransaction(tx2); } +void CWalletTx::SetBlindingData(unsigned int nOut, CAmount amountIn, CPubKey pubkeyIn, uint256 blindingfactorIn) const +{ + assert(nOut < tx->vout.size()); + if (mapValue["blindingdata"].size() < (nOut + 1) * 74) { + mapValue["blindingdata"].resize(tx->vout.size() * 74); + } + + unsigned char* it = (unsigned char*)(&mapValue["blindingdata"][0]) + 74 * nOut; + + *it = 1; + memcpy(&*(it + 1), &amountIn, 8); + memcpy(&*(it + 9), blindingfactorIn.begin(), 32); + if (pubkeyIn.IsValid() && pubkeyIn.size() == 33) { + memcpy(&*(it + 41), pubkeyIn.begin(), 33); + } else { + memset(&*(it + 41), 0, 33); + } + +} + void CWalletTx::GetBlindingData(unsigned int nOut, CAmount* pamountOut, CPubKey* ppubkeyOut, uint256* pblindingfactorOut) const { // Blinding data is cached in a serialized record mapWallet["blindingdata"]. @@ -2718,6 +2739,9 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt txNew.nTxFee = nFeeRet; LogPrintf("Created transaction (before blinding): %s", CTransaction(txNew).ToString()); + // Store amounts for storage in mapValue + std::vector vAmounts; + // Create blinded outputs std::vector input_blinds; std::vector output_blinds; @@ -2731,6 +2755,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt output_blinds.push_back(uint256()); if (outAmounts) outAmounts->push_back(txNew.vout[nOut].nValue.GetAmount()); + vAmounts.push_back(txNew.vout[nOut].nValue.GetAmount()); } if (!BlindOutputs(input_blinds, output_blinds, output_pubkeys, txNew)) { // We need a dummy output to put a non-zero blinding factor. @@ -2740,6 +2765,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt txNew.vout.push_back(newTxOut); output_pubkeys.push_back(GetBlindingPubKey(newTxOut.scriptPubKey)); output_blinds.push_back(uint256()); + vAmounts.push_back(0); // Now it has to succeed bool ret = BlindOutputs(input_blinds, output_blinds, output_pubkeys, txNew); assert(ret); @@ -2756,6 +2782,13 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt CTransaction txNewConst(txNew); dPriority = txNewConst.ComputePriority(dPriority, nBytes); + assert(vAmounts.size() == output_pubkeys.size()); + assert(output_pubkeys.size() == output_blinds.size()); + + for (unsigned int i = 0; i< vAmounts.size(); i++) { + wtxNew.SetBlindingData(i, vAmounts[i], output_pubkeys[i], output_blinds[i]); + } + // Remove scriptSigs to eliminate the fee calculation dummy signatures for (auto& vin : txNew.vin) { vin.scriptSig = CScript(); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 3374497eec..8ecf3b7387 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -439,12 +439,15 @@ public: std::set GetConflicts() const; + // For use in wallet transaction creation to remember 3rd party values + void SetBlindingData(unsigned int nOut, CAmount amountIn, CPubKey pubkeyIn, uint256 blindingfactorIn) const; + private: void GetBlindingData(unsigned int nOut, CAmount* pamountOut, CPubKey* ppubkeyOut, uint256* pblindingfactorOut) const; void WipeUnknownBlindingData() const; public: - //! Returns either the value out (if it is to us) or -1 + //! Returns either the value out (if it is known) or -1 CAmount GetValueOut(unsigned int nOut) const; //! Returns either the blinding factor (if it is to us) or 0