diff --git a/src/blind.cpp b/src/blind.cpp index 197a80f211..0c603f968e 100644 --- a/src/blind.cpp +++ b/src/blind.cpp @@ -161,7 +161,7 @@ int BlindOutputs(std::vector& input_blinding_factors, const std::vecto CTxOutValue& value = out.nValue; CTxOutAsset& asset = out.nAsset; CAmount amount = value.GetAmount(); - out.nAsset.GetAsset(assetID); + assetID = out.nAsset.GetAsset(); blindedAmounts.push_back(value.GetAmount()); GetRandBytes(&blind[nBlinded][0], 32); diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index f087d3c70b..3754535db5 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -16,14 +16,6 @@ void CTxOutAsset::SetNull() vchSurjectionproof.clear(); } -bool CTxOutAsset::GetAsset(CAsset& asset) const -{ - if (!IsAsset()) - return false; - std::copy(vchAssetTag.begin() + 1, vchAssetTag.end(), asset.begin()); - return true; -} - void CTxOutAsset::SetToAsset(const CAsset& asset) { vchAssetTag.reserve(nAssetTagSize); @@ -86,10 +78,9 @@ CTxOut::CTxOut(const CTxOutAsset& nAssetIn, const CTxOutValue& nValueIn, CScript std::string CTxOut::ToString() const { - CAsset asset; std::string strAsset; - if (nAsset.IsAsset() && nAsset.GetAsset(asset)) - strAsset = strprintf("nAsset=%s, ", asset.ToString()); + if (nAsset.IsAsset()) + strAsset = strprintf("nAsset=%s, ", nAsset.GetAsset().ToString()); if (nAsset.IsAssetCommitment()) strAsset = std::string("nAsset=UNKNOWN, "); return strprintf("CTxOut(%snValue=%s, scriptPubKey=%s)", strAsset, (nValue.IsAmount() ? strprintf("%d.%08d", nValue.GetAmount() / COIN, nValue.GetAmount() % COIN) : std::string("UNKNOWN")), HexStr(scriptPubKey).substr(0, 30)); @@ -175,9 +166,7 @@ bool CTransaction::HasValidFee() const fee = vout[i].nValue.GetAmount(); if (fee == 0 || !MoneyRange(fee)) return false; - CAsset asset; - vout[i].nAsset.GetAsset(asset); - totalFee[asset] += fee; + totalFee[vout[i].nAsset.GetAsset()] += fee; } } return MoneyRange(totalFee); @@ -188,9 +177,7 @@ CAmountMap CTransaction::GetFee() const CAmountMap fee; for (unsigned int i = 0; i < vout.size(); i++) if (vout[i].IsFee()) { - CAsset asset; - vout[i].nAsset.GetAsset(asset); - fee[asset] += vout[i].nValue.GetAmount(); + fee[vout[i].nAsset.GetAsset()] += vout[i].nValue.GetAmount(); } return fee; } diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 0ef4a48a23..69bf8e6f23 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -56,7 +56,11 @@ public: { return vchAssetTag.size()==nAssetTagSize && vchAssetTag[0]==1; } - bool GetAsset(CAsset& asset) const; + const CAsset& GetAsset() const + { + assert(IsAsset()); + return *reinterpret_cast(&vchAssetTag[1]); + } bool IsAssetCommitment() const { @@ -222,8 +226,7 @@ public: { if (!nValue.IsAmount()) return false; // FIXME - CAsset asset; - if (!nAsset.GetAsset(asset) || asset != BITCOINID) + if (!nAsset.IsAsset() || nAsset.GetAsset() != BITCOINID) return false; //Withdrawlocks are evaluated at a higher, static feerate //to ensure peg-outs are IsStandard on mainchain diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 4aea1c05a2..7791eec8cf 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -145,9 +145,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) } const CTxOutAsset& asset = txout.nAsset; if (asset.IsAsset()) { - CAsset assetID; - asset.GetAsset(assetID); - out.push_back(Pair("asset", assetID.GetHex())); + out.push_back(Pair("asset", asset.GetAsset().GetHex())); } else if (asset.IsAssetCommitment()) { out.push_back(Pair("assettag", HexStr(asset.vchAssetTag))); @@ -777,9 +775,7 @@ UniValue blindrawtransaction(const JSONRPCRequest& request) input_blinds.push_back(it->second.GetBlindingFactor(tx.vin[nIn].prevout.n)); input_asset_blinds.push_back(it->second.GetAssetBlindingFactor(tx.vin[nIn].prevout.n)); if (it->second.tx->vout[tx.vin[nIn].prevout.n].nAsset.IsAsset()) { - CAsset asset; - it->second.tx->vout[tx.vin[nIn].prevout.n].nAsset.GetAsset(asset); - input_assets.push_back(asset); + input_assets.push_back(it->second.tx->vout[tx.vin[nIn].prevout.n].nAsset.GetAsset()); } else { input_assets.push_back(it->second.GetAsset(tx.vin[nIn].prevout.n)); diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp index 70d83a2e54..40647f711a 100644 --- a/src/test/uint256_tests.cpp +++ b/src/test/uint256_tests.cpp @@ -266,4 +266,17 @@ BOOST_AUTO_TEST_CASE( conversion ) BOOST_CHECK(R2L.GetHex() == UintToArith256(R2L).GetHex()); } +BOOST_AUTO_TEST_CASE( reinterpret_bytes ) +{ + // This test checks that any sequence of bytes inside of a + // std::vector can be safely interpreted as a + // uint256. This allows various fast non-allocating (const) + // conversions. + std::vector bytes; + bytes.resize(33); + for (size_t i = 0; i < bytes.size(); ++i) + bytes[i] = static_cast(i); + BOOST_CHECK_MESSAGE(*reinterpret_cast(&bytes[1]) == uint256S("0x201f1e1d1c1b1a191817161514131211100f0e0d0c0b0a090807060504030201"), reinterpret_cast(&bytes[1])->ToString()); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/validation.cpp b/src/validation.cpp index 4bdf360d35..906d197b93 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -684,9 +684,7 @@ bool VerifyAmounts(const CCoinsViewCache& cache, const CTransaction& tx, std::ve return false; if (asset.IsAsset()) { - CAsset fixedAsset; - asset.GetAsset(fixedAsset); - ret = secp256k1_generator_generate(secp256k1_ctx_verify_amounts, &gen, fixedAsset.begin()); + ret = secp256k1_generator_generate(secp256k1_ctx_verify_amounts, &gen, asset.GetAsset().begin()); assert(ret != 0); } else if (asset.IsAssetCommitment()) { @@ -729,9 +727,7 @@ bool VerifyAmounts(const CCoinsViewCache& cache, const CTransaction& tx, std::ve return false; if (asset.IsAsset()) { - CAsset fixedAsset; - asset.GetAsset(fixedAsset); - ret = secp256k1_generator_generate(secp256k1_ctx_verify_amounts, &gen, fixedAsset.begin()); + ret = secp256k1_generator_generate(secp256k1_ctx_verify_amounts, &gen, asset.GetAsset().begin()); assert(ret != 0); } else if (asset.IsAssetCommitment()) { @@ -788,9 +784,7 @@ bool VerifyAmounts(const CCoinsViewCache& cache, const CTransaction& tx, std::ve { const CTxOutAsset& asset = cache.GetOutputFor(tx.vin[i]).nAsset; if (asset.IsAsset()) { - CAsset fixedAsset; - asset.GetAsset(fixedAsset); - ret = secp256k1_generator_generate(secp256k1_ctx_verify_amounts, &ephemeral_input_tags[i], fixedAsset.begin()); + ret = secp256k1_generator_generate(secp256k1_ctx_verify_amounts, &ephemeral_input_tags[i], asset.GetAsset().begin()); assert(ret != 0); } else { @@ -834,9 +828,7 @@ bool VerifyCoinbaseAmount(const CTransaction& tx, const CAmountMap& mapFees) for (unsigned int i = 0; i < tx.vout.size(); i++) { if (!tx.vout[i].nValue.IsAmount() || !tx.vout[i].nAsset.IsAsset()) return false; - CAsset asset; - tx.vout[i].nAsset.GetAsset(asset); - remaining[asset] -= tx.vout[i].nValue.GetAmount(); + remaining[tx.vout[i].nAsset.GetAsset()] -= tx.vout[i].nValue.GetAmount(); } return MoneyRange(remaining); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 7877e1bb99..0d7c56e0a4 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2558,15 +2558,13 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool ov strFailReason = _("Pre-funded amounts must be non-blinded"); return false; } - CAsset asset; - txOut.nAsset.GetAsset(asset); - CRecipient recipient = {txOut.scriptPubKey, txOut.nValue.GetAmount(), asset, CPubKey(txOut.nValue.vchNonceCommitment), false}; + CRecipient recipient = {txOut.scriptPubKey, txOut.nValue.GetAmount(), txOut.nAsset.GetAsset(), CPubKey(txOut.nValue.vchNonceCommitment), false}; vecSend.push_back(recipient); - if (setAssets.count(asset) == 0) { + if (setAssets.count(txOut.nAsset.GetAsset()) == 0) { vChangeKey.push_back(CReserveKey(this)); vpChangeKey.push_back(&vChangeKey[vChangeKey.size()-1]); - setAssets.insert(asset); + setAssets.insert(txOut.nAsset.GetAsset()); } } // Always add bitcoin, as fees via bitcoin may create change @@ -2908,9 +2906,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt if (outAmounts) outAmounts->push_back(txNew.vout[nOut].nValue.GetAmount()); vAmounts.push_back(txNew.vout[nOut].nValue.GetAmount()); - CAsset asset; - txNew.vout[nOut].nAsset.GetAsset(asset); - output_assets.push_back(asset); + output_assets.push_back(txNew.vout[nOut].nAsset.GetAsset()); } if (BlindOutputs(input_blinds, input_asset_blinds, input_assets, input_amounts, output_blinds, output_asset_blinds, output_pubkeys, txNew) != numBlindingKeys) { @@ -4423,7 +4419,7 @@ void CWallet::ComputeBlindingData(const CTxOut& output, CAmount& amount, CPubKey { if (output.nValue.IsAmount() && output.nAsset.IsAsset()) { amount = output.nValue.GetAmount(); - output.nAsset.GetAsset(asset); + asset = output.nAsset.GetAsset(); pubkey = CPubKey(); blindingfactor.SetNull(); assetBlindingFactor.SetNull();