mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-17 13:07:54 +02:00
CreateTransaction stores destination blinding keys,factors, and amounts
This commit is contained in:
parent
7acb86cf8b
commit
e30340a8d6
4 changed files with 49 additions and 7 deletions
|
|
@ -60,7 +60,7 @@ bool UnblindOutput(const CKey &key, const CTxOut& txout, CAmount& amount_out, ui
|
|||
}
|
||||
}
|
||||
|
||||
bool BlindOutputs(const std::vector<uint256 >& input_blinding_factors, const std::vector<uint256 >& output_blinding_factors, const std::vector<CPubKey>& output_pubkeys, CMutableTransaction& tx)
|
||||
bool BlindOutputs(const std::vector<uint256 >& input_blinding_factors, std::vector<uint256 >& output_blinding_factors, const std::vector<CPubKey>& 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<uint256 >& 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<uint256 >& input_blinding_factors, const std
|
|||
GetRandBytes(&blind[nBlinded][0], 32);
|
||||
blindptrs.push_back(&blind[nBlinded++][0]);
|
||||
}
|
||||
output_blinding_factors[nOut] = uint256(std::vector<unsigned char>(blindptrs[blindptrs.size()-1], blindptrs[blindptrs.size()-1]+32));
|
||||
nBlindsOut++;
|
||||
// Create blinded value
|
||||
CTxOutValue& value = tx.vout[nOut].nValue;
|
||||
|
|
|
|||
|
|
@ -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<uint256>& input_blinding_factors, const std::vector<uint256>& output_blinding_factors, const std::vector<CPubKey>& output_pubkeys, CMutableTransaction& tx);
|
||||
bool BlindOutputs(const std::vector<uint256>& input_blinding_factors, std::vector<uint256>& output_blinding_factors, const std::vector<CPubKey>& output_pubkeys, CMutableTransaction& tx);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1512,6 +1512,7 @@ void CWalletTx::GetAmounts(list<COutputEntry>& 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<CRecipient>& vecSend, CWalletTx& wt
|
|||
txNew.nTxFee = nFeeRet;
|
||||
LogPrintf("Created transaction (before blinding): %s", CTransaction(txNew).ToString());
|
||||
|
||||
// Store amounts for storage in mapValue
|
||||
std::vector<CAmount> vAmounts;
|
||||
|
||||
// Create blinded outputs
|
||||
std::vector<uint256> input_blinds;
|
||||
std::vector<uint256> output_blinds;
|
||||
|
|
@ -2731,6 +2755,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& 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<CRecipient>& 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<CRecipient>& 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();
|
||||
|
|
|
|||
|
|
@ -439,12 +439,15 @@ public:
|
|||
|
||||
std::set<uint256> 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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue