mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-18 13:17:55 +02:00
HF Assets: coins.cpp: Adapt CCoinsViewCache::VerifyAmounts and CCoins::FromTx()
Assets: Adapt CCoins::FromTx() to Asset definition transactions jerzy Assets: coins.cpp fix for txs spending genesis tx
This commit is contained in:
parent
f406c03568
commit
ba04aed9d9
2 changed files with 62 additions and 19 deletions
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "coins.h"
|
||||
|
||||
#include "chainparams.h"
|
||||
#include "random.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
|
@ -255,11 +256,11 @@ const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input) const
|
|||
|
||||
extern secp256k1_context* secp256k1_bitcoin_verify_context;
|
||||
|
||||
bool CCoinsViewCache::VerifyAmounts(const CTransaction& tx, const CAmount& excess) const
|
||||
bool CCoinsViewCache::VerifyAmounts(const CTransaction& tx, const CAmountMap& mTxReward) const
|
||||
{
|
||||
CAmount nPlainAmount = excess;
|
||||
CAmountMap nPlainAmounts = mTxReward;
|
||||
std::vector<unsigned char> vchData;
|
||||
std::vector<unsigned char *> vpchCommitsIn, vpchCommitsOut;
|
||||
std::map<CAssetID, std::vector<unsigned char *> > vpchCommitsInMap, vpchCommitsOutMap;
|
||||
bool fNullRangeproof = false;
|
||||
vchData.resize(CTxOutValue::nCommitmentSize * (tx.vin.size() + tx.vout.size()));
|
||||
unsigned char *p = vchData.data();
|
||||
|
|
@ -270,29 +271,45 @@ bool CCoinsViewCache::VerifyAmounts(const CTransaction& tx, const CAmount& exces
|
|||
{
|
||||
const CTxOut& txOut = GetOutputFor(txin);
|
||||
const CTxOutValue& val = txOut.nValue;
|
||||
CAssetID assetID;
|
||||
if (txOut.assetID.IsNull()) {
|
||||
bool isPrevGenesis = false;
|
||||
for (unsigned int j = 0; j < Params().GenesisBlock().vtx.size(); ++j) {
|
||||
if (Params().GenesisBlock().vtx[j].GetHash() == txin.prevout.hash)
|
||||
isPrevGenesis = true;
|
||||
}
|
||||
assetID = isPrevGenesis ? Params().HashGenesisBlock() : CAssetID(txin.prevout.hash);
|
||||
}
|
||||
else
|
||||
assetID = txOut.assetID;
|
||||
if (val.IsAmount())
|
||||
nPlainAmount -= val.GetAmount();
|
||||
nPlainAmounts[assetID] -= val.GetAmount();
|
||||
else
|
||||
{
|
||||
// Touch the asset ID in the map to later iterate
|
||||
nPlainAmounts[assetID] += 0;
|
||||
assert(val.vchCommitment.size() == CTxOutValue::nCommitmentSize);
|
||||
memcpy(p, &val.vchCommitment[0], CTxOutValue::nCommitmentSize);
|
||||
vpchCommitsIn.push_back(p);
|
||||
vpchCommitsInMap[assetID].push_back(p);
|
||||
p += CTxOutValue::nCommitmentSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < tx.vout.size(); ++i)
|
||||
{
|
||||
const CTxOutValue& val = tx.vout[i].nValue;
|
||||
const CTxOut& txOut = tx.vout[i];
|
||||
const CTxOutValue& val = txOut.nValue;
|
||||
assert(val.vchCommitment.size() == CTxOutValue::nCommitmentSize);
|
||||
if (val.vchNonceCommitment.size() > CTxOutValue::nCommitmentSize || val.vchRangeproof.size() > 5000)
|
||||
return false;
|
||||
if (val.IsAmount())
|
||||
nPlainAmount += val.GetAmount();
|
||||
nPlainAmounts[txOut.assetID] += val.GetAmount();
|
||||
else
|
||||
{
|
||||
// Touch the asset ID in the map to later iterate
|
||||
nPlainAmounts[txOut.assetID] += 0;
|
||||
memcpy(p, &val.vchCommitment[0], CTxOutValue::nCommitmentSize);
|
||||
vpchCommitsOut.push_back(p);
|
||||
vpchCommitsOutMap[txOut.assetID].push_back(p);
|
||||
p += CTxOutValue::nCommitmentSize;
|
||||
|
||||
if (val.vchRangeproof.empty())
|
||||
|
|
@ -300,17 +317,33 @@ bool CCoinsViewCache::VerifyAmounts(const CTransaction& tx, const CAmount& exces
|
|||
}
|
||||
}
|
||||
|
||||
for(std::map<CAssetID, CAmount>::const_iterator it = nPlainAmounts.begin(); it != nPlainAmounts.end(); ++it) {
|
||||
const CAssetID& assetID = it->first;
|
||||
const CAmount& nPlainAmount = nPlainAmounts[assetID];
|
||||
std::vector<unsigned char *>& vpchCommitsIn = vpchCommitsInMap[assetID];
|
||||
std::vector<unsigned char *>& vpchCommitsOut = vpchCommitsOutMap[assetID];
|
||||
// If there are no encrypted input or output values, we can do simple math
|
||||
if (vpchCommitsIn.size() + vpchCommitsOut.size() == 0)
|
||||
return (nPlainAmount == 0);
|
||||
if (vpchCommitsIn.size() + vpchCommitsOut.size() == 0) {
|
||||
// Within an asset definition transaction, the asset being defined is identified with a 0
|
||||
if (assetID.IsNull()) {
|
||||
// Only asset definitions can have null asset IDs in outputs
|
||||
if (!tx.IsAssetDefinition())
|
||||
return false;
|
||||
// Cannot issue negative amounts
|
||||
if (nPlainAmount < 0)
|
||||
return false;
|
||||
} else if (nPlainAmount != 0)
|
||||
return false;
|
||||
} else {
|
||||
// Newly issued assets cannot be confidential
|
||||
if (assetID.IsNull())
|
||||
return false;
|
||||
|
||||
if (!secp256k1_pedersen_verify_tally(secp256k1_bitcoin_verify_context, vpchCommitsIn.data(), vpchCommitsIn.size(), vpchCommitsOut.data(), vpchCommitsOut.size(), nPlainAmount))
|
||||
return false;
|
||||
|
||||
// Rangeproof is optional in this case
|
||||
if ((!vpchCommitsIn.empty()) && vpchCommitsOut.size() == 1 && nPlainAmount <= 0 && fNullRangeproof)
|
||||
return true;
|
||||
|
||||
// Rangeproof is optional in case none of the conditions are satisfied
|
||||
if (!fNullRangeproof || vpchCommitsIn.empty() || vpchCommitsOut.size() != 1 || nPlainAmount > 0) {
|
||||
uint64_t min_value, max_value;
|
||||
for (size_t i = 0; i < tx.vout.size(); ++i)
|
||||
{
|
||||
|
|
@ -320,14 +353,16 @@ bool CCoinsViewCache::VerifyAmounts(const CTransaction& tx, const CAmount& exces
|
|||
if (!secp256k1_rangeproof_verify(secp256k1_bitcoin_verify_context, &min_value, &max_value, &val.vchCommitment[0], val.vchRangeproof.data(), val.vchRangeproof.size()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCoinsViewCache::VerifyAmounts(const CTransaction& tx) const
|
||||
{
|
||||
const CAmount& excess = tx.nTxFee;
|
||||
return VerifyAmounts(tx, excess);
|
||||
return VerifyAmounts(tx, tx.GetTxRewardMap());
|
||||
}
|
||||
|
||||
bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const
|
||||
|
|
|
|||
14
src/coins.h
14
src/coins.h
|
|
@ -88,6 +88,14 @@ public:
|
|||
void FromTx(const CTransaction &tx, int nHeightIn) {
|
||||
fCoinBase = tx.IsCoinBase();
|
||||
vout = tx.vout;
|
||||
// Within an asset definition transaction, the asset being defined is identified with a 0.
|
||||
if (tx.IsAssetDefinition()) {
|
||||
const CAssetID assetID = CAssetID(tx.GetHash());
|
||||
BOOST_FOREACH(CTxOut& txout, vout)
|
||||
if (txout.assetID.IsNull())
|
||||
txout.assetID = assetID;
|
||||
}
|
||||
|
||||
nHeight = nHeightIn;
|
||||
nVersion = tx.nVersion;
|
||||
ClearUnspendable();
|
||||
|
|
@ -430,13 +438,13 @@ public:
|
|||
unsigned int GetCacheSize() const;
|
||||
|
||||
/**
|
||||
* Verify the transaction's outputs spend exactly what its inputs provide, plus some excess amount.
|
||||
* Verify the transaction's outputs spend exactly what its inputs provide, plus some excess amounts as transaction reward.
|
||||
*
|
||||
* @param[in] tx transaction for which we are checking totals
|
||||
* @param[in] excess additional amount to consider (eg, fees)
|
||||
* @param[in] txReward additional amounts to consider (eg, fees and subsidy)
|
||||
* @return True if totals are identical
|
||||
*/
|
||||
bool VerifyAmounts(const CTransaction& tx, const CAmount& excess) const;
|
||||
bool VerifyAmounts(const CTransaction& tx, const CAmountMap& mTxReward) const;
|
||||
bool VerifyAmounts(const CTransaction& tx) const;
|
||||
|
||||
//! Check whether all prevouts of the transaction are present in the UTXO set represented by this view
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue