diff --git a/src/blind.cpp b/src/blind.cpp index 3e8f39f10f..cfc6f065bb 100644 --- a/src/blind.cpp +++ b/src/blind.cpp @@ -126,7 +126,7 @@ int BlindOutputs(std::vector& input_blinding_factors, const std::vecto // Wallet only understands all-blinded or all-unblinded assert((output_blinding_factors[nOut] != uint256()) == !out.nValue.IsExplicit()); assert(out.nValue.IsExplicit() == out.nAsset.IsExplicit()); - assert(out.nAsset.IsCommitment() == !out.nAsset.vchSurjectionproof.empty()); + assert(out.nAsset.IsCommitment() == !out.vchSurjectionproof.empty()); if (output_blinding_factors[nOut] != uint256()) { assert(output_asset_blinding_factors[nOut] != uint256()); blindptrs.push_back(output_blinding_factors[nOut].begin()); @@ -138,7 +138,7 @@ int BlindOutputs(std::vector& input_blinding_factors, const std::vecto secp256k1_generator gen; secp256k1_surjectionproof proof; assert(secp256k1_generator_parse(secp256k1_blind_context, &gen, &out.nAsset.vchCommitment[0]) == 1); - assert(secp256k1_surjectionproof_parse(secp256k1_blind_context, &proof, &out.nAsset.vchSurjectionproof[0], out.nAsset.vchSurjectionproof.size()) == 1); + assert(secp256k1_surjectionproof_parse(secp256k1_blind_context, &proof, &out.vchSurjectionproof[0], out.vchSurjectionproof.size()) == 1); assert(secp256k1_surjectionproof_verify(secp256k1_blind_context, &proof, &inputAssetGenerators[0], inputAssetGenerators.size(), &gen) == 1); } else { if (output_pubkeys[nOut].IsFullyValid()) { @@ -257,8 +257,8 @@ int BlindOutputs(std::vector& input_blinding_factors, const std::vecto assert(ret != 0); size_t output_len = secp256k1_surjectionproof_serialized_size(secp256k1_blind_context, &proof); - tx.vout[nOut].nAsset.vchSurjectionproof.resize(output_len); - secp256k1_surjectionproof_serialize(secp256k1_blind_context, &asset.vchSurjectionproof[0], &output_len, &proof); + out.vchSurjectionproof.resize(output_len); + secp256k1_surjectionproof_serialize(secp256k1_blind_context, &out.vchSurjectionproof[0], &output_len, &proof); } } diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index 8be12afcaa..7202795847 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -12,7 +12,6 @@ void CTxOutAsset::SetNull() { vchCommitment.clear(); - vchSurjectionproof.clear(); } void CTxOutAsset::SetToAsset(const CAsset& asset) @@ -20,7 +19,6 @@ void CTxOutAsset::SetToAsset(const CAsset& asset) vchCommitment.reserve(nCommittedSize); vchCommitment.push_back(1); vchCommitment.insert(vchCommitment.end(), asset.begin(), asset.end()); - vchSurjectionproof.clear(); } CTxOutValue::CTxOutValue(CAmount nAmountIn) diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 68ac6e637b..7dff5a78dc 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -23,7 +23,6 @@ public: static const size_t nCommittedSize = 33; std::vector vchCommitment; - std::vector vchSurjectionproof; CTxOutAsset() { @@ -64,7 +63,6 @@ public: } if (vchCommitment.size() > 1) READWRITE(REF(CFlatData(&vchCommitment[1], &vchCommitment[vchCommitment.size()]))); - // The surjection proof is serialized as part of the witness data } bool IsNull() const @@ -91,8 +89,7 @@ public: friend bool operator==(const CTxOutAsset& a, const CTxOutAsset& b) { - return (a.vchCommitment == b.vchCommitment && - a.vchSurjectionproof == b.vchSurjectionproof); + return a.vchCommitment == b.vchCommitment; } friend bool operator!=(const CTxOutAsset& a, const CTxOutAsset& b) @@ -180,6 +177,7 @@ class CTxOut { public: CTxOutAsset nAsset; + std::vector vchSurjectionproof; CTxOutValue nValue; CScript scriptPubKey; @@ -200,6 +198,7 @@ public: template inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(nAsset); + // The surjection proof is serialized as part of the witness data READWRITE(nValue); READWRITE(*(CScriptBase*)(&scriptPubKey)); } @@ -207,13 +206,14 @@ public: void SetNull() { nAsset = CTxOutAsset(); + vchSurjectionproof.clear(); nValue = CTxOutValue(); scriptPubKey.clear(); } bool IsNull() const { - return nAsset.IsNull() && nValue.IsNull() && scriptPubKey.empty(); + return nAsset.IsNull() && vchSurjectionproof.empty() && nValue.IsNull() && scriptPubKey.empty(); } CAmount GetDustThreshold(const CFeeRate &minRelayTxFee) const @@ -271,8 +271,9 @@ public: friend bool operator==(const CTxOut& a, const CTxOut& b) { - return (a.nValue == b.nValue && - a.nValue == b.nValue && + return (a.nAsset == b.nAsset && + a.vchSurjectionproof == b.vchSurjectionproof && + a.nValue == b.nValue && a.scriptPubKey == b.scriptPubKey); } @@ -536,18 +537,18 @@ public: ADD_SERIALIZE_METHODS; bool IsNull() const { - return ref.nAsset.vchSurjectionproof.empty() && ref.nValue.vchRangeproof.empty() && ref.nValue.vchNonceCommitment.empty(); + return ref.vchSurjectionproof.empty() && ref.nValue.vchRangeproof.empty() && ref.nValue.vchNonceCommitment.empty(); } template inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(ref.nAsset.vchSurjectionproof); + READWRITE(ref.vchSurjectionproof); READWRITE(ref.nValue.vchRangeproof); READWRITE(ref.nValue.vchNonceCommitment); } void SetNull() { - std::vector().swap(ref.nAsset.vchSurjectionproof); + std::vector().swap(ref.vchSurjectionproof); std::vector().swap(ref.nValue.vchRangeproof); std::vector().swap(ref.nValue.vchNonceCommitment); } diff --git a/src/validation.cpp b/src/validation.cpp index 8b8472d4d2..a0379f2462 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -800,14 +800,14 @@ bool VerifyAmounts(const CCoinsViewCache& cache, const CTransaction& tx, std::ve const CTxOutAsset& asset = tx.vout[i].nAsset; //No need for surjective proof if (asset.IsExplicit()) { - assert(asset.vchSurjectionproof.size() == 0); + assert(tx.vout[i].vchSurjectionproof.size() == 0); continue; } if (secp256k1_generator_parse(secp256k1_ctx_verify_amounts, &gen, &asset.vchCommitment[0]) != 1) return false; secp256k1_surjectionproof proof; - if (secp256k1_surjectionproof_parse(secp256k1_ctx_verify_amounts, &proof, &asset.vchSurjectionproof[0], asset.vchSurjectionproof.size()) != 1) + if (secp256k1_surjectionproof_parse(secp256k1_ctx_verify_amounts, &proof, &tx.vout[i].vchSurjectionproof[0], tx.vout[i].vchSurjectionproof.size()) != 1) return false; if (!QueueCheck(pvChecks, new CSurjectionCheck(proof, ephemeral_input_tags, gen, cacheStore))) {