Consensus support for blinded amounts

This commit is contained in:
Luke Dashjr 2015-05-20 10:24:16 +00:00 committed by Matt Corallo
parent b05e98bc9c
commit bf009e4ba1
16 changed files with 177 additions and 98 deletions

View file

@ -8,6 +8,8 @@
#include <assert.h>
#include <secp256k1.h>
/**
* calculate number of bytes for the bitmask, and its number of non-zero bytes
* each bit in the bitmask represents the availability of one output, but the
@ -250,41 +252,78 @@ const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input) const
return coins->vout[input.prevout.n];
}
CAmount CCoinsViewCache::GetValueIn(const CTransaction& tx) const
{
if (tx.IsCoinBase())
return 0;
CAmount nResult = 0;
for (unsigned int i = 0; i < tx.vin.size(); i++)
{
const CTxOutValue& val = GetOutputFor(tx.vin[i]).nValue;
assert(val.IsAmount());
nResult += val.GetAmount();
}
return nResult;
}
CAmount CCoinsViewCache::GetValueInExcess(const CTransaction& tx) const
{
const CAmount nValueIn = GetValueIn(tx);
const CAmount nValueOut = tx.GetValueOut();
return nValueIn - nValueOut;
}
extern secp256k1_context_t* secp256k1_bitcoin_verify_context;
bool CCoinsViewCache::VerifyAmounts(const CTransaction& tx, const CAmount& excess) const
{
CAmount nInAmount = GetValueIn(tx);
if (nInAmount < excess)
CAmount nPlainAmount = excess;
std::vector<unsigned char> vchData;
std::vector<unsigned char *> vpchCommitsIn, vpchCommitsOut;
bool fNullRangeproof = false;
vchData.resize(CTxOutValue::nCommitmentSize * (tx.vin.size() + tx.vout.size()));
unsigned char *p = vchData.data();
if (!tx.IsCoinBase())
{
for (size_t i = 0; i < tx.vin.size(); ++i)
{
const CTxOutValue& val = GetOutputFor(tx.vin[i]).nValue;
if (val.IsAmount())
nPlainAmount -= val.GetAmount();
else
{
assert(val.vchCommitment.size() == CTxOutValue::nCommitmentSize);
memcpy(p, &val.vchCommitment[0], CTxOutValue::nCommitmentSize);
vpchCommitsIn.push_back(p);
p += CTxOutValue::nCommitmentSize;
}
}
}
for (size_t i = 0; i < tx.vout.size(); ++i)
{
const CTxOutValue& val = tx.vout[i].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();
else
{
memcpy(p, &val.vchCommitment[0], CTxOutValue::nCommitmentSize);
vpchCommitsOut.push_back(p);
p += CTxOutValue::nCommitmentSize;
if (val.vchRangeproof.empty())
fNullRangeproof = true;
}
}
// If there are no encrypted input or output values, we can do simple math
if (vpchCommitsIn.size() + vpchCommitsOut.size() == 0)
return (nPlainAmount == 0);
if (!secp256k1_pedersen_verify_tally(secp256k1_bitcoin_verify_context, vpchCommitsIn.data(), vpchCommitsIn.size(), vpchCommitsOut.data(), vpchCommitsOut.size(), nPlainAmount))
return false;
nInAmount -= excess;
return nInAmount == tx.GetValueOut();
// Rangeproof is optional in this case
if ((!vpchCommitsIn.empty()) && vpchCommitsOut.size() == 1 && nPlainAmount <= 0 && fNullRangeproof)
return true;
uint64_t min_value, max_value;
for (size_t i = 0; i < tx.vout.size(); ++i)
{
const CTxOutValue& val = tx.vout[i].nValue;
if (val.IsAmount())
continue;
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 = GetValueInExcess(tx);
const CAmount& excess = tx.nTxFee;
return VerifyAmounts(tx, excess);
}
@ -322,6 +361,7 @@ double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight) const
int nCoinsHeight = coins->nHeight == 0x7fffffff ? nHeight + 1 : coins->nHeight;
if (nCoinsHeight < nHeight + nOffset) {
const CTxOutValue& val = coins->vout[txin.prevout.n].nValue;
// FIXME: This assumes all blinded values are COIN
CAmount nAmount = COIN;
if (val.IsAmount())
nAmount = val.GetAmount();

View file

@ -429,18 +429,6 @@ public:
//! Calculate the size of the cache (in number of transactions)
unsigned int GetCacheSize() const;
/**
* Amount of bitcoins coming in to a transaction
* Note that lightweight clients may not know anything besides the hash of previous transactions,
* so may not be able to calculate this.
*
* @param[in] tx transaction for which we are checking input total
* @return Sum of value of all inputs (scriptSigs)
*/
CAmount GetValueIn(const CTransaction& tx) const;
CAmount GetValueInExcess(const CTransaction& tx) const;
/**
* Verify the transaction's outputs spend exactly what its inputs provide, plus some excess amount.
*

View file

@ -107,6 +107,7 @@ public:
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
#if 0 // TODO: Actually compress numeric values at least
if (!ser_action.ForRead()) {
assert(txout.nValue.IsAmount()); // FIXME
uint64_t nVal = CompressAmount(txout.nValue.GetAmount());
@ -116,6 +117,9 @@ public:
READWRITE(VARINT(nVal));
txout.nValue = DecompressAmount(nVal);
}
#else
READWRITE(txout.nValue);
#endif
CScriptCompressor cscript(REF(txout.scriptPubKey));
READWRITE(cscript);
}

View file

@ -128,6 +128,7 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry)
UniValue outValue(UniValue::VNUM, FormatMoney(txout.nValue.GetAmount()));
out.pushKV("value", outValue);
}
// TODO: Non-Amount values
out.pushKV("n", (int64_t)i);
UniValue o(UniValue::VOBJ);

View file

@ -1096,7 +1096,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// Bring the best block into scope
view.GetBestBlock();
nFees = view.GetValueInExcess(tx);
nFees = tx.nTxFee;
if (!view.VerifyAmounts(tx, nFees))
return state.DoS(0,
error("AcceptToMemoryPool : input amounts do not match output amounts %s",
@ -1576,7 +1576,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
}
}
const CAmount nTxFee = inputs.GetValueInExcess(tx);
const CAmount& nTxFee = tx.nTxFee;
if (nTxFee < 0)
return state.DoS(100, error("CheckInputs() : %s nTxFee < 0", tx.GetHash().ToString()),
REJECT_INVALID, "bad-txns-fee-negative");
@ -1598,7 +1598,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
// before the last block chain checkpoint. This is safe because block merkle hashes are
// still computed and checked, and any change will be caught at the next checkpoint.
if (fScriptChecks) {
CAmount prevValueIn = -1;
CTxOutValue prevValueIn = -1;
for (unsigned int i = 0; i < tx.vin.size(); i++) {
const COutPoint &prevout = tx.vin[i].prevout;
const CCoins* coins = inputs.AccessCoins(prevout.hash);
@ -1880,7 +1880,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
REJECT_INVALID, "bad-blk-sigops");
}
nFees += view.GetValueInExcess(tx);
nFees += tx.nTxFee;
std::vector<CScriptCheck> vChecks;
if (!CheckInputs(tx, state, view, fScriptChecks, flags, false, nScriptCheckThreads ? &vChecks : NULL))

View file

@ -354,8 +354,8 @@ private:
CScript scriptPubKey;
const CTransaction *ptxTo;
unsigned int nIn;
CAmount nValueIn;
CAmount nValueInPreviousIn;
CTxOutValue nValueIn;
CTxOutValue nValueInPreviousIn;
CAmount nTxFee;
int nSpendHeight;
unsigned int nFlags;
@ -364,7 +364,7 @@ private:
public:
CScriptCheck(): ptxTo(0), nIn(0), nValueIn(-1), nValueInPreviousIn(-1), nTxFee(-1), nSpendHeight(-1), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, CAmount nValueInPreviousInIn, CAmount nTxFeeIn, int nSpendHeightIn, unsigned int nFlagsIn, bool cacheIn) :
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, CTxOutValue nValueInPreviousInIn, CAmount nTxFeeIn, int nSpendHeightIn, unsigned int nFlagsIn, bool cacheIn) :
scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey),
ptxTo(&txToIn), nIn(nInIn), nValueIn(txFromIn.vout[txToIn.vin[nInIn].prevout.n].nValue),
nValueInPreviousIn(nValueInPreviousInIn), nTxFee(nTxFeeIn), nSpendHeight(nSpendHeightIn),

View file

@ -96,7 +96,7 @@ int64_t UpdateTime(CBlockHeader* pblock, const CBlockIndex* pindexPrev)
static CFeeRate CalculateSubjectiveFeeRateAndPriority(const CCoinsViewCache& view, const CTransaction& tx, const unsigned int& nTxSize, double& dPriority) {
const uint256& hash = tx.GetHash();
CAmount nTxFees = view.GetValueInExcess(tx);
CAmount nTxFees = tx.nTxFee;
mempool.ApplyDeltas(hash, dPriority, nTxFees);
return CFeeRate(nTxFees, nTxSize);
@ -281,7 +281,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
if (!view.HaveInputs(tx))
continue;
CAmount nTxFees = view.GetValueInExcess(tx);
const CAmount& nTxFees = tx.nTxFee;
nTxSigOps += GetP2SHSigOpCount(tx, view);
if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)

View file

@ -10,39 +10,72 @@
#include "utilstrencodings.h"
CTxOutValue::CTxOutValue()
: nAmount(-1)
{
vchCommitment.resize(nCommitmentSize);
memset(&vchCommitment[0], 0xff, nCommitmentSize);
}
CTxOutValue::CTxOutValue(CAmount nAmountIn)
: nAmount(nAmountIn)
{
vchCommitment.resize(nCommitmentSize);
assert(vchCommitment.size() > sizeof(nAmountIn) + 1);
memset(&vchCommitment[0], 0, vchCommitment.size() - sizeof(nAmountIn));
for (size_t i = 0; i < sizeof(nAmountIn); ++i)
vchCommitment[vchCommitment.size() - (i + 1)] = ((nAmountIn >> (i * 8)) & 0xff);
}
CTxOutValue::CTxOutValue(const std::vector<unsigned char>& vchValueCommitmentIn, const std::vector<unsigned char>& vchRangeproofIn)
: vchCommitment(vchValueCommitmentIn), vchRangeproof(vchRangeproofIn)
{
assert(vchCommitment.size() == nCommitmentSize);
assert(vchCommitment[0] == 2 || vchCommitment[0] == 3);
}
bool CTxOutValue::IsValid() const
{
return nAmount >= 0;
switch (vchCommitment[0])
{
case 0:
{
// Ensure all but the last sizeof(CAmount) bytes are zero
for (size_t i = vchCommitment.size() - sizeof(CAmount); --i > 0; )
if (vchCommitment[i])
return false;
return true;
}
case 2:
case 3:
// FIXME: Additional checks?
return true;
default:
return false;
}
}
bool CTxOutValue::IsNull() const
{
return nAmount == -1;
return vchCommitment[0] == 0xff;
}
bool CTxOutValue::IsAmount() const
{
return nAmount != -1;
return !vchCommitment[0];
}
CAmount CTxOutValue::GetAmount() const
{
assert(IsAmount());
CAmount nAmount = 0;
for (size_t i = 0; i < sizeof(nAmount); ++i)
nAmount |= CAmount(vchCommitment[vchCommitment.size() - (i + 1)]) << (i * 8);
return nAmount;
}
bool operator==(const CTxOutValue& a, const CTxOutValue& b)
{
return a.nAmount == b.nAmount;
return a.vchRangeproof == b.vchRangeproof &&
a.vchCommitment == b.vchCommitment &&
a.vchNonceCommitment == b.vchNonceCommitment;
}
bool operator!=(const CTxOutValue& a, const CTxOutValue& b) {
@ -94,8 +127,8 @@ std::string CTxOut::ToString() const
return strprintf("CTxOut(nValue=%s, scriptPubKey=%s)", (nValue.IsAmount() ? strprintf("%d.%08d", nValue.GetAmount() / COIN, nValue.GetAmount() % COIN) : std::string("UNKNOWN")), scriptPubKey.ToString().substr(0,30));
}
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nLockTime(0) {}
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {}
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nTxFee(0), nLockTime(0) {}
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), nTxFee(tx.nTxFee), vout(tx.vout), nLockTime(tx.nLockTime) {}
uint256 CMutableTransaction::GetHash() const
{
@ -107,14 +140,15 @@ void CTransaction::UpdateHash() const
*const_cast<uint256*>(&hash) = SerializeHash(*this);
}
CTransaction::CTransaction() : hash(0), nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0) { }
CTransaction::CTransaction() : hash(0), nVersion(CTransaction::CURRENT_VERSION), vin(), nTxFee(0), vout(), nLockTime(0) { }
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), nTxFee(tx.nTxFee), vout(tx.vout), nLockTime(tx.nLockTime) {
UpdateHash();
}
CTransaction& CTransaction::operator=(const CTransaction &tx) {
*const_cast<int*>(&nVersion) = tx.nVersion;
*const_cast<CAmount*>(&nTxFee) = tx.nTxFee;
*const_cast<std::vector<CTxIn>*>(&vin) = tx.vin;
*const_cast<std::vector<CTxOut>*>(&vout) = tx.vout;
*const_cast<unsigned int*>(&nLockTime) = tx.nLockTime;
@ -122,20 +156,6 @@ CTransaction& CTransaction::operator=(const CTransaction &tx) {
return *this;
}
CAmount CTransaction::GetValueOut() const
{
CAmount nValueOut = 0;
for (std::vector<CTxOut>::const_iterator it(vout.begin()); it != vout.end(); ++it)
{
assert(it->nValue.IsAmount());
const CAmount nAmount = it->nValue.GetAmount();
nValueOut += nAmount;
if (!MoneyRange(nAmount) || !MoneyRange(nValueOut))
throw std::runtime_error("CTransaction::GetValueOut() : value out of range");
}
return nValueOut;
}
double CTransaction::ComputePriority(double dPriorityInputs, unsigned int nTxSize) const
{
nTxSize = CalculateModifiedSize(nTxSize);

View file

@ -13,16 +13,25 @@
class CTxOutValue
{
CAmount nAmount;
public:
static const size_t nCommitmentSize = 33;
std::vector<unsigned char> vchCommitment;
std::vector<unsigned char> vchRangeproof;
std::vector<unsigned char> vchNonceCommitment;
CTxOutValue();
CTxOutValue(CAmount);
CTxOutValue(const std::vector<unsigned char>& vchValueCommitment, const std::vector<unsigned char>& vchRangeproofIn);
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(nAmount);
template<typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion)
{
READWRITE(REF(CFlatData(&vchCommitment[0], &vchCommitment[nCommitmentSize])));
READWRITE(vchRangeproof);
READWRITE(vchNonceCommitment);
}
bool IsValid() const;
@ -130,7 +139,7 @@ public:
SetNull();
}
CTxOut(const CTxOutValue& nValueIn, CScript scriptPubKeyIn);
CTxOut(const CTxOutValue& valueIn, CScript scriptPubKeyIn);
ADD_SERIALIZE_METHODS;
@ -142,13 +151,13 @@ public:
void SetNull()
{
nValue = -1;
nValue = CTxOutValue();
scriptPubKey.clear();
}
bool IsNull() const
{
return (nValue == -1);
return nValue.IsNull() && scriptPubKey.empty();
}
bool IsDust(CFeeRate minRelayTxFee) const
@ -204,6 +213,7 @@ public:
// structure, including the hash.
const int32_t nVersion;
const std::vector<CTxIn> vin;
const CAmount nTxFee;
const std::vector<CTxOut> vout;
const uint32_t nLockTime;
@ -222,6 +232,7 @@ public:
READWRITE(*const_cast<int32_t*>(&this->nVersion));
nVersion = this->nVersion;
READWRITE(*const_cast<std::vector<CTxIn>*>(&vin));
READWRITE(*const_cast<CAmount*>(&nTxFee));
READWRITE(*const_cast<std::vector<CTxOut>*>(&vout));
READWRITE(*const_cast<uint32_t*>(&nLockTime));
if (ser_action.ForRead())
@ -236,11 +247,6 @@ public:
return hash;
}
// Return sum of txouts.
CAmount GetValueOut() const;
// GetValueIn() is a method on CCoinsViewCache, because
// inputs must be known to compute value in.
// Compute priority, given priority of inputs and (optionally) tx size
double ComputePriority(double dPriorityInputs, unsigned int nTxSize=0) const;
@ -270,6 +276,7 @@ struct CMutableTransaction
{
int32_t nVersion;
std::vector<CTxIn> vin;
CAmount nTxFee;
std::vector<CTxOut> vout;
uint32_t nLockTime;
@ -283,6 +290,7 @@ struct CMutableTransaction
READWRITE(this->nVersion);
nVersion = this->nVersion;
READWRITE(vin);
READWRITE(nTxFee);
READWRITE(vout);
READWRITE(nLockTime);
}

View file

@ -6,7 +6,8 @@
#include <secp256k1.h>
static secp256k1_context_t* secp256k1_context = NULL;
secp256k1_context_t* secp256k1_bitcoin_verify_context = NULL;
static secp256k1_context_t*& secp256k1_context = secp256k1_bitcoin_verify_context;
bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const {
if (!IsValid())
@ -87,7 +88,7 @@ bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const {
void ECC_Verify_Start() {
assert(secp256k1_context == NULL);
secp256k1_context_t *ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
secp256k1_context_t *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_COMMIT | SECP256K1_CONTEXT_RANGEPROOF);
assert(ctx != NULL);
secp256k1_context = ctx;

View file

@ -395,6 +395,7 @@ Value gettxout(const Array& params, bool fHelp)
ret.push_back(Pair("confirmations", pindex->nHeight - coins.nHeight + 1));
if (coins.vout[n].nValue.IsAmount())
ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue.GetAmount())));
// TODO: Non-Amount values
Object o;
ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true);
ret.push_back(Pair("scriptPubKey", o));

View file

@ -661,7 +661,9 @@ Value getblocktemplate(const Array& params, bool fHelp)
result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
result.push_back(Pair("transactions", transactions));
result.push_back(Pair("coinbaseaux", aux));
#if 0 // FIXME: GBT won't work with non-Bitcoin transaction formats! at the very least, we'll need to change to coinbasetxn
result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue.GetAmount()));
#endif
result.push_back(Pair("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
result.push_back(Pair("target", GetChallengeStrHex(*pblock)));
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));

View file

@ -83,6 +83,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
Object out;
if (txout.nValue.IsAmount())
out.push_back(Pair("value", ValueFromAmount(txout.nValue.GetAmount())));
// TODO: Non-Amount values
out.push_back(Pair("n", (int64_t)i));
Object o;
ScriptPubKeyToJSON(txout.scriptPubKey, o, true);

View file

@ -35,13 +35,26 @@ typedef vector<unsigned char> valtype;
//! anonymous namespace
namespace {
static secp256k1_context_t* secp256k1_context = NULL;
class CSecp256k1Init {
public:
CSecp256k1Init() {
secp256k1_start(SECP256K1_START_VERIFY);
assert(secp256k1_context == NULL);
secp256k1_context_t *ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
assert(ctx != NULL);
secp256k1_context = ctx;
}
~CSecp256k1Init() {
secp256k1_stop();
secp256k1_context_t *ctx = secp256k1_context;
secp256k1_context = NULL;
if (ctx) {
secp256k1_context_destroy(ctx);
}
}
};
static CSecp256k1Init instance_of_csecp256k1;
@ -1703,7 +1716,7 @@ COutPoint TransactionSignatureChecker::GetPrevOut() const
return txTo->vin[nIn].prevout;
}
CAmount TransactionSignatureChecker::GetValueIn() const
CTxOutValue TransactionSignatureChecker::GetValueIn() const
{
return nInValue;
}
@ -1713,7 +1726,7 @@ CAmount TransactionSignatureChecker::GetTransactionFee() const
return nTransactionFee;
}
CAmount TransactionSignatureChecker::GetValueInPrevIn() const
CTxOutValue TransactionSignatureChecker::GetValueInPrevIn() const
{
return nInMinusOneValue;
}

View file

@ -105,12 +105,12 @@ public:
virtual CTxOut GetOutputOffsetFromCurrent(const int offset) const;
virtual COutPoint GetPrevOut() const;
virtual CAmount GetValueIn() const
virtual CTxOutValue GetValueIn() const
{
return -1;
}
virtual CAmount GetValueInPrevIn() const
virtual CTxOutValue GetValueInPrevIn() const
{
return -1;
}
@ -156,17 +156,17 @@ public:
class TransactionSignatureChecker : public TransactionNoWithdrawsSignatureChecker
{
private:
const CAmount nInValue;
const CAmount nInMinusOneValue;
const CTxOutValue nInValue;
const CTxOutValue nInMinusOneValue;
const CAmount nTransactionFee;
const int nSpendHeight;
public:
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, CAmount nInValueIn, CAmount nInMinusOneValueIn, CAmount nTransactionFeeIn, int nSpendHeightIn) : TransactionNoWithdrawsSignatureChecker(txToIn, nInIn), nInValue(nInValueIn), nInMinusOneValue(nInMinusOneValueIn), nTransactionFee(nTransactionFeeIn), nSpendHeight(nSpendHeightIn) {}
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, CTxOutValue nInValueIn, CTxOutValue nInMinusOneValueIn, CAmount nTransactionFeeIn, int nSpendHeightIn) : TransactionNoWithdrawsSignatureChecker(txToIn, nInIn), nInValue(nInValueIn), nInMinusOneValue(nInMinusOneValueIn), nTransactionFee(nTransactionFeeIn), nSpendHeight(nSpendHeightIn) {}
CTxOut GetOutputOffsetFromCurrent(const int offset) const;
COutPoint GetPrevOut() const;
CAmount GetValueIn() const;
CAmount GetValueInPrevIn() const;
CTxOutValue GetValueIn() const;
CTxOutValue GetValueInPrevIn() const;
CAmount GetTransactionFee() const;
#ifdef FEDERATED_PEG_SIDECHAIN_ONLY
bool IsConfirmedBitcoinBlock(const uint256& hash, bool fConservativeConfirmationRequirements) const;

View file

@ -18,7 +18,7 @@ private:
bool store;
public:
CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, CAmount nInValueIn, CAmount nInMinusOneValueIn, CAmount nTransactionFeeIn, int nSpendHeightIn, bool storeIn=true) : TransactionSignatureChecker(txToIn, nInIn, nInValueIn, nInMinusOneValueIn, nTransactionFeeIn, nSpendHeightIn), store(storeIn) {}
CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, CTxOutValue nInValueIn, CTxOutValue nInMinusOneValueIn, CAmount nTransactionFeeIn, int nSpendHeightIn, bool storeIn=true) : TransactionSignatureChecker(txToIn, nInIn, nInValueIn, nInMinusOneValueIn, nTransactionFeeIn, nSpendHeightIn), store(storeIn) {}
bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
};