mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-17 13:07:54 +02:00
Refactors in anticipation of blinded values
This commit is contained in:
parent
743081a205
commit
b5f1b6dd38
34 changed files with 262 additions and 133 deletions
|
|
@ -292,10 +292,12 @@ libbitcoin_consensus_a_SOURCES = \
|
|||
script/script_error.cpp \
|
||||
script/script_error.h \
|
||||
support/events.cpp \
|
||||
script/sign.cpp \
|
||||
serialize.h \
|
||||
tinyformat.h \
|
||||
uint256.cpp \
|
||||
uint256.h \
|
||||
utilmoneystr.cpp \
|
||||
utilstrencodings.cpp \
|
||||
utilstrencodings.h \
|
||||
version.h
|
||||
|
|
|
|||
|
|
@ -89,11 +89,17 @@ static void VerifyScriptBench(benchmark::State& state)
|
|||
#if defined(HAVE_CONSENSUS_LIB)
|
||||
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
||||
stream << txSpend;
|
||||
CDataStream streamVal1(SER_NETWORK, PROTOCOL_VERSION);
|
||||
streamVal1 << txCredit.vout[0].nValue;
|
||||
CDataStream streamVal2(SER_NETWORK, PROTOCOL_VERSION);
|
||||
streamVal2 << CTxOutValue(0);
|
||||
int csuccess = bitcoinconsensus_verify_script_with_amount(
|
||||
txCredit.vout[0].scriptPubKey.data(),
|
||||
txCredit.vout[0].scriptPubKey.size(),
|
||||
txCredit.vout[0].nValue,
|
||||
-1,
|
||||
(const unsigned char*)&streamVal1[0],
|
||||
streamVal1.size(),
|
||||
(const unsigned char*)&streamVal2[0],
|
||||
streamVal2.size(),
|
||||
(const unsigned char*)stream.data(), stream.size(), 0, flags, nullptr);
|
||||
assert(csuccess == 1);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -617,7 +617,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
|
|||
continue;
|
||||
}
|
||||
const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey;
|
||||
const CAmount& amount = coins->vout[txin.prevout.n].nValue;
|
||||
const CTxOutValue& amount = coins->vout[txin.prevout.n].nValue;
|
||||
|
||||
SignatureData sigdata;
|
||||
// Only sign SIGHASH_SINGLE if there's a corresponding output:
|
||||
|
|
|
|||
|
|
@ -332,8 +332,11 @@ CAmount CCoinsViewCache::GetValueIn(const CTransaction& tx) const
|
|||
return 0;
|
||||
|
||||
CAmount nResult = 0;
|
||||
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
||||
nResult += GetOutputFor(tx.vin[i]).nValue;
|
||||
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;
|
||||
}
|
||||
|
|
@ -345,8 +348,9 @@ bool CCoinsViewCache::VerifyAmounts(const CTransaction& tx, const CAmount& exces
|
|||
CAmount nInAmount = GetValueIn(tx);
|
||||
for (std::vector<CTxOut>::const_iterator it(tx.vout.begin()); it != tx.vout.end(); ++it)
|
||||
{
|
||||
nInAmount -= it->nValue;
|
||||
if (!MoneyRange(it->nValue) || (!MoneyRange(nInAmount) && !MoneyRange(-nInAmount)))
|
||||
assert(it->nValue.IsAmount());
|
||||
nInAmount -= it->nValue.GetAmount();;
|
||||
if (!MoneyRange(it->nValue.GetAmount()) || (!MoneyRange(nInAmount) && !MoneyRange(-nInAmount)))
|
||||
return false;
|
||||
}
|
||||
return excess == nInAmount;
|
||||
|
|
@ -378,8 +382,12 @@ double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight, CAmount
|
|||
assert(coins);
|
||||
if (!coins->IsAvailable(txin.prevout.n)) continue;
|
||||
if (coins->nHeight <= nHeight) {
|
||||
dResult += (double)(coins->vout[txin.prevout.n].nValue) * (nHeight-coins->nHeight);
|
||||
inChainInputValue += coins->vout[txin.prevout.n].nValue;
|
||||
const CTxOutValue& val = coins->vout[txin.prevout.n].nValue;
|
||||
CAmount nAmount = COIN;
|
||||
if (val.IsAmount())
|
||||
nAmount = val.GetAmount();
|
||||
dResult += nAmount * (nHeight-coins->nHeight);
|
||||
inChainInputValue += nAmount;
|
||||
}
|
||||
}
|
||||
return tx.ComputePriority(dResult);
|
||||
|
|
|
|||
|
|
@ -106,7 +106,8 @@ public:
|
|||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
if (!ser_action.ForRead()) {
|
||||
uint64_t nVal = CompressAmount(txout.nValue);
|
||||
assert(txout.nValue.IsAmount());
|
||||
uint64_t nVal = CompressAmount(txout.nValue.GetAmount());
|
||||
READWRITE(VARINT(nVal));
|
||||
} else {
|
||||
uint64_t nVal = 0;
|
||||
|
|
|
|||
|
|
@ -192,8 +192,10 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry)
|
|||
|
||||
UniValue out(UniValue::VOBJ);
|
||||
|
||||
UniValue outValue(UniValue::VNUM, FormatMoney(txout.nValue));
|
||||
out.pushKV("value", outValue);
|
||||
if (txout.nValue.IsAmount()) {
|
||||
UniValue outValue(UniValue::VNUM, FormatMoney(txout.nValue.GetAmount()));
|
||||
out.pushKV("value", outValue);
|
||||
}
|
||||
out.pushKV("n", (int64_t)i);
|
||||
|
||||
UniValue o(UniValue::VOBJ);
|
||||
|
|
|
|||
|
|
@ -43,7 +43,48 @@ std::string CTxIn::ToString() const
|
|||
return str;
|
||||
}
|
||||
|
||||
CTxOut::CTxOut(const CAmount& nValueIn, CScript scriptPubKeyIn)
|
||||
|
||||
CTxOutValue::CTxOutValue()
|
||||
: nAmount(-1)
|
||||
{
|
||||
}
|
||||
|
||||
CTxOutValue::CTxOutValue(CAmount nAmountIn)
|
||||
: nAmount(nAmountIn)
|
||||
{
|
||||
}
|
||||
|
||||
bool CTxOutValue::IsValid() const
|
||||
{
|
||||
return MoneyRange(nAmount);
|
||||
}
|
||||
|
||||
bool CTxOutValue::IsNull() const
|
||||
{
|
||||
return nAmount == -1;
|
||||
}
|
||||
|
||||
bool CTxOutValue::IsAmount() const
|
||||
{
|
||||
return nAmount != -1;
|
||||
}
|
||||
|
||||
CAmount CTxOutValue::GetAmount() const
|
||||
{
|
||||
assert(IsAmount());
|
||||
return nAmount;
|
||||
}
|
||||
|
||||
bool operator==(const CTxOutValue& a, const CTxOutValue& b)
|
||||
{
|
||||
return a.nAmount == b.nAmount;
|
||||
}
|
||||
|
||||
bool operator!=(const CTxOutValue& a, const CTxOutValue& b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
CTxOut::CTxOut(const CTxOutValue& nValueIn, CScript scriptPubKeyIn)
|
||||
{
|
||||
nValue = nValueIn;
|
||||
scriptPubKey = scriptPubKeyIn;
|
||||
|
|
@ -51,7 +92,7 @@ CTxOut::CTxOut(const CAmount& nValueIn, CScript scriptPubKeyIn)
|
|||
|
||||
std::string CTxOut::ToString() const
|
||||
{
|
||||
return strprintf("CTxOut(nValue=%d.%08d, scriptPubKey=%s)", nValue / COIN, nValue % COIN, HexStr(scriptPubKey).substr(0, 30));
|
||||
return strprintf("CTxOut(nValue=%s, scriptPubKey=%s)", (nValue.IsAmount() ? strprintf("%d.%08d", nValue.GetAmount() / COIN, nValue.GetAmount() % COIN) : std::string("UNKNOWN")), HexStr(scriptPubKey).substr(0, 30));
|
||||
}
|
||||
|
||||
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nTxFee(0), vin(), vout(), nLockTime(0) {}
|
||||
|
|
|
|||
|
|
@ -127,13 +127,38 @@ public:
|
|||
std::string ToString() const;
|
||||
};
|
||||
|
||||
|
||||
class CTxOutValue
|
||||
{
|
||||
CAmount nAmount;
|
||||
public:
|
||||
CTxOutValue();
|
||||
CTxOutValue(CAmount);
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(nAmount);
|
||||
}
|
||||
|
||||
bool IsValid() const;
|
||||
bool IsNull() const;
|
||||
bool IsAmount() const;
|
||||
|
||||
CAmount GetAmount() const;
|
||||
|
||||
friend bool operator==(const CTxOutValue& a, const CTxOutValue& b);
|
||||
friend bool operator!=(const CTxOutValue& a, const CTxOutValue& b);
|
||||
};
|
||||
|
||||
/** An output of a transaction. It contains the public key that the next input
|
||||
* must be able to sign with to claim it.
|
||||
*/
|
||||
class CTxOut
|
||||
{
|
||||
public:
|
||||
CAmount nValue;
|
||||
CTxOutValue nValue;
|
||||
CScript scriptPubKey;
|
||||
|
||||
CTxOut()
|
||||
|
|
@ -141,7 +166,7 @@ public:
|
|||
SetNull();
|
||||
}
|
||||
|
||||
CTxOut(const CAmount& nValueIn, CScript scriptPubKeyIn);
|
||||
CTxOut(const CTxOutValue& nValueIn, CScript scriptPubKeyIn);
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
|
|
@ -196,7 +221,9 @@ public:
|
|||
|
||||
bool IsDust(const CFeeRate &minRelayTxFee) const
|
||||
{
|
||||
return (nValue < GetDustThreshold(minRelayTxFee));
|
||||
if (!nValue.IsAmount())
|
||||
return false; // FIXME
|
||||
return (nValue.GetAmount() < GetDustThreshold(minRelayTxFee));
|
||||
}
|
||||
|
||||
friend bool operator==(const CTxOut& a, const CTxOut& b)
|
||||
|
|
|
|||
|
|
@ -471,10 +471,10 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
|
|||
nQuantity++;
|
||||
|
||||
// Amount
|
||||
nAmount += out.tx->tx->vout[out.i].nValue;
|
||||
nAmount += out.tx->tx->vout[out.i].nValue.GetAmount();
|
||||
|
||||
// Priority
|
||||
dPriorityInputs += (double)out.tx->tx->vout[out.i].nValue * (out.nDepth+1);
|
||||
dPriorityInputs += (double)out.tx->tx->vout[out.i].nValue.GetAmount() * (out.nDepth+1);
|
||||
|
||||
// Bytes
|
||||
CTxDestination address;
|
||||
|
|
@ -676,7 +676,7 @@ void CoinControlDialog::updateView()
|
|||
CAmount nSum = 0;
|
||||
int nChildren = 0;
|
||||
BOOST_FOREACH(const COutput& out, coins.second) {
|
||||
nSum += out.tx->tx->vout[out.i].nValue;
|
||||
nSum += out.tx->tx->vout[out.i].nValue.GetAmount();
|
||||
nChildren++;
|
||||
|
||||
CCoinControlWidgetItem *itemOutput;
|
||||
|
|
@ -713,8 +713,8 @@ void CoinControlDialog::updateView()
|
|||
}
|
||||
|
||||
// amount
|
||||
itemOutput->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, out.tx->tx->vout[out.i].nValue));
|
||||
itemOutput->setData(COLUMN_AMOUNT, Qt::UserRole, QVariant((qlonglong)out.tx->tx->vout[out.i].nValue)); // padding so that sorting works correctly
|
||||
itemOutput->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, out.tx->tx->vout[out.i].nValue.GetAmount()));
|
||||
itemOutput->setData(COLUMN_AMOUNT, Qt::UserRole, QVariant((qlonglong)out.tx->tx->vout[out.i].nValue.GetAmount())); // padding so that sorting works correctly
|
||||
|
||||
// date
|
||||
itemOutput->setText(COLUMN_DATE, GUIUtil::dateTimeStr(out.tx->GetTxTime()));
|
||||
|
|
|
|||
|
|
@ -198,9 +198,9 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
|
|||
}
|
||||
}
|
||||
|
||||
strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -txout.nValue) + "<br>";
|
||||
strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -txout.nValue.GetAmount()) + "<br>";
|
||||
if(toSelf)
|
||||
strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, txout.nValue) + "<br>";
|
||||
strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, txout.nValue.GetAmount()) + "<br>";
|
||||
}
|
||||
|
||||
if (fAllToMe)
|
||||
|
|
@ -307,7 +307,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
|
|||
strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
|
||||
strHTML += QString::fromStdString(CBitcoinAddress(address).ToString());
|
||||
}
|
||||
strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatHtmlWithUnit(unit, vout.nValue);
|
||||
strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatHtmlWithUnit(unit, vout.nValue.GetAmount());
|
||||
strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) & ISMINE_SPENDABLE ? tr("true") : tr("false")) + "</li>";
|
||||
strHTML = strHTML + " IsWatchOnly=" + (wallet->IsMine(vout) & ISMINE_WATCH_ONLY ? tr("true") : tr("false")) + "</li>";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
|
|||
TransactionRecord sub(hash, nTime);
|
||||
CTxDestination address;
|
||||
sub.idx = i; // vout index
|
||||
sub.credit = txout.nValue;
|
||||
sub.credit = txout.nValue.GetAmount();
|
||||
sub.involvesWatchAddress = mine & ISMINE_WATCH_ONLY;
|
||||
if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
|
||||
{
|
||||
|
|
@ -143,7 +143,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
|
|||
sub.address = mapValue["to"];
|
||||
}
|
||||
|
||||
CAmount nValue = txout.nValue;
|
||||
CAmount nValue = txout.nValue.GetAmount();
|
||||
/* Add fee to first output */
|
||||
if (nTxFee > 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ CAmount WalletModel::getBalance(const CCoinControl *coinControl) const
|
|||
wallet->AvailableCoins(vCoins, true, coinControl);
|
||||
BOOST_FOREACH(const COutput& out, vCoins)
|
||||
if(out.fSpendable)
|
||||
nBalance += out.tx->tx->vout[out.i].nValue;
|
||||
nBalance = out.tx->tx->vout[out.i].nValue.GetAmount();
|
||||
|
||||
return nBalance;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ void WalletModelTransaction::reassignAmounts(int nChangePosRet)
|
|||
if (out.amount() <= 0) continue;
|
||||
if (i == nChangePosRet)
|
||||
i++;
|
||||
subtotal += walletTransaction->tx->vout[i].nValue;
|
||||
subtotal += walletTransaction->tx->vout[i].nValue.GetAmount();
|
||||
i++;
|
||||
}
|
||||
rcp.amount = subtotal;
|
||||
|
|
@ -73,7 +73,7 @@ void WalletModelTransaction::reassignAmounts(int nChangePosRet)
|
|||
{
|
||||
if (i == nChangePosRet)
|
||||
i++;
|
||||
rcp.amount = walletTransaction->tx->vout[i].nValue;
|
||||
rcp.amount = walletTransaction->tx->vout[i].nValue.GetAmount();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -575,7 +575,8 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
|
|||
UniValue utxo(UniValue::VOBJ);
|
||||
utxo.push_back(Pair("txvers", (int32_t)coin.nTxVer));
|
||||
utxo.push_back(Pair("height", (int32_t)coin.nHeight));
|
||||
utxo.push_back(Pair("value", ValueFromAmount(coin.out.nValue)));
|
||||
if (coin.out.nValue.IsAmount())
|
||||
utxo.push_back(Pair("value", ValueFromAmount(coin.out.nValue.GetAmount())));
|
||||
|
||||
// include the script in a json output
|
||||
UniValue o(UniValue::VOBJ);
|
||||
|
|
|
|||
|
|
@ -783,7 +783,8 @@ static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats)
|
|||
stats.nTransactionOutputs++;
|
||||
ss << VARINT(i+1);
|
||||
ss << out;
|
||||
nTotalAmount += out.nValue;
|
||||
if (out.nValue.IsAmount())
|
||||
nTotalAmount += out.nValue.GetAmount();
|
||||
}
|
||||
}
|
||||
stats.nSerializedSize += 32 + pcursor->GetValueSize();
|
||||
|
|
@ -862,7 +863,6 @@ UniValue gettxoutsetinfo(const JSONRPCRequest& request)
|
|||
" \"txouts\": n, (numeric) The number of output transactions\n"
|
||||
" \"bytes_serialized\": n, (numeric) The serialized size\n"
|
||||
" \"hash_serialized\": \"hash\", (string) The serialized hash\n"
|
||||
" \"total_amount\": x.xxx (numeric) The total amount\n"
|
||||
"}\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("gettxoutsetinfo", "")
|
||||
|
|
@ -880,7 +880,6 @@ UniValue gettxoutsetinfo(const JSONRPCRequest& request)
|
|||
ret.push_back(Pair("txouts", (int64_t)stats.nTransactionOutputs));
|
||||
ret.push_back(Pair("bytes_serialized", (int64_t)stats.nSerializedSize));
|
||||
ret.push_back(Pair("hash_serialized", stats.hashSerialized.GetHex()));
|
||||
ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount)));
|
||||
} else {
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set");
|
||||
}
|
||||
|
|
@ -957,7 +956,8 @@ UniValue gettxout(const JSONRPCRequest& request)
|
|||
ret.push_back(Pair("confirmations", 0));
|
||||
else
|
||||
ret.push_back(Pair("confirmations", pindex->nHeight - coins.nHeight + 1));
|
||||
ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue)));
|
||||
if (coins.vout[n].nValue.IsAmount())
|
||||
ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue.GetAmount())));
|
||||
UniValue o(UniValue::VOBJ);
|
||||
ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true);
|
||||
ret.push_back(Pair("scriptPubKey", o));
|
||||
|
|
|
|||
|
|
@ -632,7 +632,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
|
|||
result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
|
||||
result.push_back(Pair("transactions", transactions));
|
||||
result.push_back(Pair("coinbaseaux", aux));
|
||||
result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue));
|
||||
result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue.GetAmount()));
|
||||
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));
|
||||
|
|
|
|||
|
|
@ -99,7 +99,8 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
|
|||
for (unsigned int i = 0; i < tx.vout.size(); i++) {
|
||||
const CTxOut& txout = tx.vout[i];
|
||||
UniValue out(UniValue::VOBJ);
|
||||
out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
|
||||
if (txout.nValue.IsAmount())
|
||||
out.push_back(Pair("value", ValueFromAmount(txout.nValue.GetAmount())));
|
||||
out.push_back(Pair("n", (int64_t)i));
|
||||
UniValue o(UniValue::VOBJ);
|
||||
ScriptPubKeyToJSON(txout.scriptPubKey, o, true);
|
||||
|
|
@ -839,7 +840,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
|
|||
continue;
|
||||
}
|
||||
const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey;
|
||||
const CAmount& amount = coins->vout[txin.prevout.n].nValue;
|
||||
const CTxOutValue& amount = coins->vout[txin.prevout.n].nValue;
|
||||
|
||||
SignatureData sigdata;
|
||||
// Only sign SIGHASH_SINGLE if there's a corresponding output:
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ static bool verify_flags(unsigned int flags)
|
|||
return (flags & ~(bitcoinconsensus_SCRIPT_FLAGS_VERIFY_ALL)) == 0;
|
||||
}
|
||||
|
||||
static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, CAmount amount,
|
||||
CAmount amountPreviousInput,
|
||||
static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, CTxOutValue amount,
|
||||
CTxOutValue amountPreviousInput,
|
||||
const unsigned char *txTo , unsigned int txToLen,
|
||||
unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err)
|
||||
{
|
||||
|
|
@ -96,7 +96,7 @@ static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptP
|
|||
set_error(err, bitcoinconsensus_ERR_OK);
|
||||
|
||||
PrecomputedTransactionData txdata(tx);
|
||||
if (amountPreviousInput < -1 || (nIn != 0 && !MoneyRange(amountPreviousInput)))
|
||||
if (amountPreviousInput.IsAmount() && (amountPreviousInput.GetAmount() < -1 || (nIn != 0 && !MoneyRange(amountPreviousInput.GetAmount()))))
|
||||
return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), &tx.vin[nIn].scriptWitness, flags, TransactionNoWithdrawsSignatureChecker(&tx, nIn, amount, txdata), NULL);
|
||||
else
|
||||
return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), &tx.vin[nIn].scriptWitness, flags, TransactionSignatureChecker(&tx, nIn, amount, amountPreviousInput, txdata), NULL);
|
||||
|
|
@ -105,14 +105,25 @@ static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptP
|
|||
}
|
||||
}
|
||||
|
||||
int bitcoinconsensus_verify_script_with_amount(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, int64_t amount,
|
||||
int64_t amountPreviousInput,
|
||||
int bitcoinconsensus_verify_script_with_amount(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen,
|
||||
const unsigned char* amount, unsigned int amountLen,
|
||||
const unsigned char* amountPreviousInput, unsigned int amountPreviousInputLen,
|
||||
const unsigned char *txTo , unsigned int txToLen,
|
||||
unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err)
|
||||
{
|
||||
CAmount am(amount);
|
||||
CAmount prevInAm(amountPreviousInput);
|
||||
return ::verify_script(scriptPubKey, scriptPubKeyLen, am, prevInAm, txTo, txToLen, nIn, flags, err);
|
||||
try {
|
||||
TxInputStream stream(SER_NETWORK, PROTOCOL_VERSION, amount, amountLen);
|
||||
CTxOutValue am;
|
||||
stream >> am;
|
||||
|
||||
TxInputStream stream2(SER_NETWORK, PROTOCOL_VERSION, amountPreviousInput, amountPreviousInputLen);
|
||||
CTxOutValue prevInAm;
|
||||
stream >> prevInAm;
|
||||
|
||||
return ::verify_script(scriptPubKey, scriptPubKeyLen, am, prevInAm, txTo, txToLen, nIn, flags, err);
|
||||
} catch (const std::exception&) {
|
||||
return set_error(err, bitcoinconsensus_ERR_TX_DESERIALIZE); // Error deserializing
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -124,8 +135,8 @@ int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned i
|
|||
return set_error(err, bitcoinconsensus_ERR_AMOUNT_REQUIRED);
|
||||
}
|
||||
|
||||
CAmount am(0);
|
||||
CAmount prevInAm(-2);
|
||||
CTxOutValue am(0);
|
||||
CTxOutValue prevInAm(-2);
|
||||
return ::verify_script(scriptPubKey, scriptPubKeyLen, am, prevInAm, txTo, txToLen, nIn, flags, err);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,8 +72,9 @@ EXPORT_SYMBOL int bitcoinconsensus_verify_script(const unsigned char *scriptPubK
|
|||
unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err);
|
||||
|
||||
// Use -1 for amountPreviousInput if there is no previous input (ie nIn == 0)
|
||||
EXPORT_SYMBOL int bitcoinconsensus_verify_script_with_amount(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, int64_t amount,
|
||||
int64_t amountPreviousInput,
|
||||
EXPORT_SYMBOL int bitcoinconsensus_verify_script_with_amount(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen,
|
||||
const unsigned char* amount, unsigned int amountLen,
|
||||
const unsigned char* amountPreviousInput, unsigned int amountPreviousInputLen,
|
||||
const unsigned char *txTo , unsigned int txToLen,
|
||||
unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err);
|
||||
|
||||
|
|
|
|||
|
|
@ -1097,13 +1097,19 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
|
|||
CScript relockScript = CScript() << vgenesisHash << OP_WITHDRAWPROOFVERIFY;
|
||||
|
||||
if (stack.size() == 1) { // increasing value of locked coins
|
||||
CAmount minValue = checker.GetValueIn();
|
||||
if (!checker.GetValueIn().IsAmount())
|
||||
return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_BLINDED_AMOUNTS);
|
||||
CAmount minValue = checker.GetValueIn().GetAmount();
|
||||
CTxOut newOutput = checker.GetOutputOffsetFromCurrent(0);
|
||||
if (newOutput.IsNull()) {
|
||||
newOutput = checker.GetOutputOffsetFromCurrent(-1);
|
||||
minValue += checker.GetValueInPrevIn();
|
||||
if (!checker.GetValueInPrevIn().IsAmount())
|
||||
return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_BLINDED_AMOUNTS);
|
||||
minValue += checker.GetValueInPrevIn().GetAmount();
|
||||
}
|
||||
if (newOutput.scriptPubKey != relockScript || newOutput.nValue < minValue)
|
||||
if (!newOutput.nValue.IsAmount())
|
||||
return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_BLINDED_AMOUNTS);
|
||||
if (newOutput.scriptPubKey != relockScript || newOutput.nValue.GetAmount() < minValue)
|
||||
return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_OUTPUT);
|
||||
} else { // stack.size() >= 7...ie regular withdraw
|
||||
int stackReadPos = -2;
|
||||
|
|
@ -1193,16 +1199,24 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
|
|||
// We check values by doing the following:
|
||||
// * Tx must relock at least <unlocked coins> - <locked-on-bitcoin coins>
|
||||
// * Tx must send at least the withdraw value to its P2SH withdraw, but may send more
|
||||
CAmount withdrawVal = locktx->vout[nlocktxOut].nValue;
|
||||
CAmount lockValueRequired = checker.GetValueIn() - withdrawVal;
|
||||
assert(locktx->vout[nlocktxOut].nValue.IsAmount()); // Its a SERIALIZE_BITCOIN_BLOCK_OR_TX
|
||||
CAmount withdrawVal = locktx->vout[nlocktxOut].nValue.GetAmount();
|
||||
if (!checker.GetValueIn().IsAmount()) // Heh, you just destroyed coins
|
||||
return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_BLINDED_AMOUNTS);
|
||||
|
||||
CAmount lockValueRequired = checker.GetValueIn().GetAmount() - withdrawVal;
|
||||
if (lockValueRequired > 0) {
|
||||
const CTxOut newLockOutput = checker.GetOutputOffsetFromCurrent(1);
|
||||
if (newLockOutput.IsNull() || newLockOutput.scriptPubKey != relockScript || newLockOutput.nValue < lockValueRequired)
|
||||
if (!newLockOutput.nValue.IsAmount())
|
||||
return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_BLINDED_AMOUNTS);
|
||||
if (newLockOutput.IsNull() || newLockOutput.scriptPubKey != relockScript || newLockOutput.nValue.GetAmount() < lockValueRequired)
|
||||
return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_OUTPUT);
|
||||
}
|
||||
|
||||
const CTxOut withdrawOutput = checker.GetOutputOffsetFromCurrent(0);
|
||||
if (withdrawOutput.nValue < withdrawVal)
|
||||
if (!withdrawOutput.nValue.IsAmount())
|
||||
return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_BLINDED_AMOUNTS);
|
||||
if (withdrawOutput.nValue.GetAmount() < withdrawVal)
|
||||
return set_error(serror, SCRIPT_ERR_WITHDRAW_VERIFY_OUTPUT);
|
||||
|
||||
CScript expectedWithdrawScriptPubKey;
|
||||
|
|
@ -1379,7 +1393,7 @@ PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo)
|
|||
hashOutputs = GetOutputsHash(txTo);
|
||||
}
|
||||
|
||||
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache)
|
||||
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CTxOutValue& amount, SigVersion sigversion, const PrecomputedTransactionData* cache)
|
||||
{
|
||||
if (sigversion == SIGVERSION_WITNESS_V0) {
|
||||
uint256 hashPrevouts;
|
||||
|
|
@ -1580,12 +1594,12 @@ COutPoint TransactionSignatureChecker::GetPrevOut() const
|
|||
return txTo->vin[nIn].prevout;
|
||||
}
|
||||
|
||||
CAmount TransactionSignatureChecker::GetValueIn() const
|
||||
CTxOutValue TransactionSignatureChecker::GetValueIn() const
|
||||
{
|
||||
return amount;
|
||||
}
|
||||
|
||||
CAmount TransactionSignatureChecker::GetValueInPrevIn() const
|
||||
CTxOutValue TransactionSignatureChecker::GetValueInPrevIn() const
|
||||
{
|
||||
return amountPreviousInput;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ enum SigVersion
|
|||
SIGVERSION_WITNESS_V0 = 1,
|
||||
};
|
||||
|
||||
uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache = NULL);
|
||||
uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CTxOutValue& amount, SigVersion sigversion, const PrecomputedTransactionData* cache = NULL);
|
||||
|
||||
class BaseSignatureChecker
|
||||
{
|
||||
|
|
@ -150,7 +150,7 @@ public:
|
|||
virtual CTxOut GetOutputOffsetFromCurrent(const int offset) const;
|
||||
virtual COutPoint GetPrevOut() const;
|
||||
|
||||
virtual CAmount GetValueIn() const
|
||||
virtual CTxOutValue GetValueIn() const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -160,7 +160,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
virtual CAmount GetValueInPrevIn() const
|
||||
virtual CTxOutValue GetValueInPrevIn() const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -178,14 +178,14 @@ class TransactionNoWithdrawsSignatureChecker : public BaseSignatureChecker
|
|||
protected:
|
||||
const CTransaction* txTo;
|
||||
const unsigned int nIn;
|
||||
const CAmount amount;
|
||||
const CTxOutValue amount;
|
||||
const PrecomputedTransactionData* txdata;
|
||||
|
||||
virtual bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
|
||||
|
||||
public:
|
||||
TransactionNoWithdrawsSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(NULL) {}
|
||||
TransactionNoWithdrawsSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, const PrecomputedTransactionData& txdataIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(&txdataIn) {}
|
||||
TransactionNoWithdrawsSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CTxOutValue& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(NULL) {}
|
||||
TransactionNoWithdrawsSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CTxOutValue& amountIn, const PrecomputedTransactionData& txdataIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(&txdataIn) {}
|
||||
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const;
|
||||
bool CheckLockTime(const CScriptNum& nLockTime) const;
|
||||
bool CheckSequence(const CScriptNum& nSequence) const;
|
||||
|
|
@ -197,21 +197,21 @@ private:
|
|||
const CTransaction txTo;
|
||||
|
||||
public:
|
||||
MutableTransactionNoWithdrawsSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amount) : TransactionNoWithdrawsSignatureChecker(&txTo, nInIn, amount), txTo(*txToIn) {}
|
||||
MutableTransactionNoWithdrawsSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn, const CTxOutValue& amount) : TransactionNoWithdrawsSignatureChecker(&txTo, nInIn, amount), txTo(*txToIn) {}
|
||||
};
|
||||
|
||||
class TransactionSignatureChecker : public TransactionNoWithdrawsSignatureChecker
|
||||
{
|
||||
private:
|
||||
const CAmount amountPreviousInput;
|
||||
const CTxOutValue amountPreviousInput;
|
||||
|
||||
public:
|
||||
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, const CAmount& amountPreviousInputIn) : TransactionNoWithdrawsSignatureChecker(txToIn, nInIn, amountIn), amountPreviousInput(amountPreviousInputIn) {}
|
||||
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, const CAmount& amountPreviousInputIn, const PrecomputedTransactionData& txdataIn) : TransactionNoWithdrawsSignatureChecker(txToIn, nInIn, amountIn, txdataIn), amountPreviousInput(amountPreviousInputIn) {}
|
||||
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CTxOutValue& amountIn, const CTxOutValue& amountPreviousInputIn) : TransactionNoWithdrawsSignatureChecker(txToIn, nInIn, amountIn), amountPreviousInput(amountPreviousInputIn) {}
|
||||
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CTxOutValue& amountIn, const CTxOutValue& amountPreviousInputIn, const PrecomputedTransactionData& txdataIn) : TransactionNoWithdrawsSignatureChecker(txToIn, nInIn, amountIn, txdataIn), amountPreviousInput(amountPreviousInputIn) {}
|
||||
CTxOut GetOutputOffsetFromCurrent(const int offset) const;
|
||||
COutPoint GetPrevOut() const;
|
||||
CAmount GetValueIn() const;
|
||||
CAmount GetValueInPrevIn() const;
|
||||
CTxOutValue GetValueIn() const;
|
||||
CTxOutValue GetValueInPrevIn() const;
|
||||
bool IsConfirmedBitcoinBlock(const uint256& genesishash, const uint256& hash, bool fConservativeConfirmationRequirements) const;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -97,6 +97,8 @@ const char* ScriptErrorString(const ScriptError serror)
|
|||
return "Withdraw proof validation failed - output does not match expected";
|
||||
case SCRIPT_ERR_WITHDRAW_VERIFY_BLOCKCONFIRMED:
|
||||
return "Withdraw proof validation failed - lock block was not sufficiently confirmed on sending chain";
|
||||
case SCRIPT_ERR_WITHDRAW_VERIFY_BLINDED_AMOUNTS:
|
||||
return "Withdraw proof validation failed - amounts in outputs were blinded";
|
||||
case SCRIPT_ERR_UNKNOWN_ERROR:
|
||||
case SCRIPT_ERR_ERROR_COUNT:
|
||||
default: break;
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ typedef enum ScriptError_t
|
|||
SCRIPT_ERR_WITHDRAW_VERIFY_LOCKTX,
|
||||
SCRIPT_ERR_WITHDRAW_VERIFY_OUTPUT,
|
||||
SCRIPT_ERR_WITHDRAW_VERIFY_BLOCKCONFIRMED,
|
||||
SCRIPT_ERR_WITHDRAW_VERIFY_BLINDED_AMOUNTS,
|
||||
|
||||
SCRIPT_ERR_ERROR_COUNT
|
||||
} ScriptError;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ private:
|
|||
bool store;
|
||||
|
||||
public:
|
||||
CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount, const CAmount& amountPreviousInput, bool storeIn, PrecomputedTransactionData& txdataIn) : TransactionSignatureChecker(txToIn, nInIn, amount, amountPreviousInput), store(storeIn) {}
|
||||
CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CTxOutValue& amount, const CTxOutValue& amountPreviousInput, bool storeIn, PrecomputedTransactionData& txdataIn) : TransactionSignatureChecker(txToIn, nInIn, amount, amountPreviousInput), store(storeIn) {}
|
||||
|
||||
bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ using namespace std;
|
|||
|
||||
typedef std::vector<unsigned char> valtype;
|
||||
|
||||
TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {}
|
||||
TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CTxOutValue& amountIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {}
|
||||
|
||||
bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, SigVersion sigversion) const
|
||||
{
|
||||
|
|
@ -206,7 +206,7 @@ void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const Signatur
|
|||
tx.vin[nIn].scriptWitness = data.scriptWitness;
|
||||
}
|
||||
|
||||
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType)
|
||||
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CTxOutValue& amount, int nHashType)
|
||||
{
|
||||
assert(nIn < txTo.vin.size());
|
||||
|
||||
|
|
|
|||
|
|
@ -35,11 +35,11 @@ class TransactionSignatureCreator : public BaseSignatureCreator {
|
|||
const CTransaction* txTo;
|
||||
unsigned int nIn;
|
||||
int nHashType;
|
||||
CAmount amount;
|
||||
CTxOutValue amount;
|
||||
const TransactionNoWithdrawsSignatureChecker checker;
|
||||
|
||||
public:
|
||||
TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn=SIGHASH_ALL);
|
||||
TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CTxOutValue& amountIn, int nHashTypeIn=SIGHASH_ALL);
|
||||
const BaseSignatureChecker& Checker() const { return checker; }
|
||||
bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const;
|
||||
};
|
||||
|
|
@ -48,7 +48,7 @@ class MutableTransactionSignatureCreator : public TransactionSignatureCreator {
|
|||
CTransaction tx;
|
||||
|
||||
public:
|
||||
MutableTransactionSignatureCreator(const CKeyStore* keystoreIn, const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amount, int nHashTypeIn) : TransactionSignatureCreator(keystoreIn, &tx, nInIn, amount, nHashTypeIn), tx(*txToIn) {}
|
||||
MutableTransactionSignatureCreator(const CKeyStore* keystoreIn, const CMutableTransaction* txToIn, unsigned int nInIn, const CTxOutValue& amount, int nHashTypeIn) : TransactionSignatureCreator(keystoreIn, &tx, nInIn, amount, nHashTypeIn), tx(*txToIn) {}
|
||||
};
|
||||
|
||||
/** A signature creator that just produces 72-byte empty signatures. */
|
||||
|
|
@ -71,7 +71,7 @@ struct SignatureData {
|
|||
bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& scriptPubKey, SignatureData& sigdata);
|
||||
|
||||
/** Produce a script signature for a transaction. */
|
||||
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType);
|
||||
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CTxOutValue& amount, int nHashType);
|
||||
bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType);
|
||||
|
||||
/** Combine two script signatures using a generic signature checker, intelligently, possibly with OP_0 placeholders. */
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey,
|
|||
// of the transactions is below the min relay fee
|
||||
// Remove the low fee transaction and replace with a higher fee transaction
|
||||
mempool.removeRecursive(tx);
|
||||
tx.vout[0].nValue -= 2; // Now we should be just over the min relay fee
|
||||
tx.vout[0].nValue = CTxOutValue(tx.vout[0].nValue.GetAmount()- 2); // Now we should be just over the min relay fee
|
||||
hashLowFeeTx = tx.GetHash();
|
||||
mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse+2).FromTx(tx));
|
||||
pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey);
|
||||
|
|
@ -252,7 +252,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||
tx.vout[0].nValue = BLOCKSUBSIDY;
|
||||
for (unsigned int i = 0; i < 1001; ++i)
|
||||
{
|
||||
tx.vout[0].nValue -= LOWFEE;
|
||||
tx.vout[0].nValue = CTxOutValue(tx.vout[0].nValue.GetAmount() - LOWFEE);
|
||||
hash = tx.GetHash();
|
||||
bool spendsCoinbase = (i == 0) ? true : false; // only first tx spends coinbase
|
||||
// If we don't set the # of sig ops in the CTxMemPoolEntry, template creation fails
|
||||
|
|
@ -266,7 +266,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||
tx.vout[0].nValue = BLOCKSUBSIDY;
|
||||
for (unsigned int i = 0; i < 1001; ++i)
|
||||
{
|
||||
tx.vout[0].nValue -= LOWFEE;
|
||||
tx.vout[0].nValue = CTxOutValue(tx.vout[0].nValue.GetAmount() - LOWFEE);
|
||||
hash = tx.GetHash();
|
||||
bool spendsCoinbase = (i == 0) ? true : false; // only first tx spends coinbase
|
||||
// If we do set the # of sig ops in the CTxMemPoolEntry, template creation passes
|
||||
|
|
@ -287,7 +287,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||
tx.vout[0].nValue = BLOCKSUBSIDY;
|
||||
for (unsigned int i = 0; i < 128; ++i)
|
||||
{
|
||||
tx.vout[0].nValue -= LOWFEE;
|
||||
tx.vout[0].nValue = CTxOutValue(tx.vout[0].nValue.GetAmount() - LOWFEE);
|
||||
hash = tx.GetHash();
|
||||
bool spendsCoinbase = (i == 0) ? true : false; // only first tx spends coinbase
|
||||
mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
|
||||
|
|
@ -313,7 +313,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||
tx.vin[1].scriptSig = CScript() << OP_1;
|
||||
tx.vin[1].prevout.hash = txFirst[0]->GetHash();
|
||||
tx.vin[1].prevout.n = 0;
|
||||
tx.vout[0].nValue = tx.vout[0].nValue+BLOCKSUBSIDY-HIGHERFEE; //First txn output + fresh coinbase - new txn fee
|
||||
tx.vout[0].nValue = CTxOutValue(tx.vout[0].nValue.GetAmount()+BLOCKSUBSIDY-HIGHERFEE); //First txn output + fresh coinbase - new txn fee
|
||||
hash = tx.GetHash();
|
||||
mempool.addUnchecked(hash, entry.Fee(HIGHERFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
|
||||
BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey));
|
||||
|
|
@ -341,7 +341,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||
mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
|
||||
tx.vin[0].prevout.hash = hash;
|
||||
tx.vin[0].scriptSig = CScript() << std::vector<unsigned char>(script.begin(), script.end());
|
||||
tx.vout[0].nValue -= LOWFEE;
|
||||
tx.vout[0].nValue = CTxOutValue(tx.vout[0].nValue.GetAmount() - LOWFEE);
|
||||
hash = tx.GetHash();
|
||||
mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
|
||||
BOOST_CHECK_THROW(BlockAssembler(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error);
|
||||
|
|
|
|||
|
|
@ -171,12 +171,16 @@ return;
|
|||
#if defined(HAVE_CONSENSUS_LIB)
|
||||
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
||||
stream << tx2;
|
||||
CDataStream streamVal1(SER_NETWORK, PROTOCOL_VERSION);
|
||||
streamVal1 << txCredit.vout[0].nValue;
|
||||
CDataStream streamVal2(SER_NETWORK, PROTOCOL_VERSION);
|
||||
streamVal2 << CTxOutValue();
|
||||
int libconsensus_flags = flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_ALL;
|
||||
if (libconsensus_flags == flags) {
|
||||
if (flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS) {
|
||||
BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(scriptPubKey.data(), scriptPubKey.size(), txCredit.vout[0].nValue, -1, (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, NULL) == expect, message);
|
||||
BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&streamVal1[0], streamVal1.size(), (const unsigned char*)&streamVal2[0], streamVal2.size(), (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, NULL) == expect, message);
|
||||
} else {
|
||||
BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(scriptPubKey.data(), scriptPubKey.size(), 0, -1, (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, NULL) == expect, message);
|
||||
BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&streamVal2[0], streamVal2.size(), (const unsigned char*)&streamVal2[0], streamVal2.size(), (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, NULL) == expect, message);
|
||||
BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, NULL) == expect,message);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ TestChain100Setup::~TestChain100Setup()
|
|||
CAmount TotalValueOut(const CMutableTransaction& tx) {
|
||||
CAmount nTotal = 0;
|
||||
BOOST_FOREACH(const CTxOut& txo, tx.vout)
|
||||
nTotal += txo.nValue;
|
||||
nTotal += txo.nValue.GetAmount();
|
||||
return nTotal;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
|
|||
spends[i].vout.resize(1);
|
||||
spends[i].vout[0].nValue = 11*CENT;
|
||||
spends[i].vout[0].scriptPubKey = scriptPubKey;
|
||||
spends[i].nTxFee = coinbaseTxns[0].vout[0].nValue - 11*CENT;
|
||||
spends[i].nTxFee = coinbaseTxns[0].vout[0].nValue.GetAmount() - 11*CENT;
|
||||
|
||||
// Sign:
|
||||
std::vector<unsigned char> vchSig;
|
||||
|
|
|
|||
|
|
@ -504,11 +504,11 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fChe
|
|||
CAmount nValueOut = 0;
|
||||
for (const auto& txout : tx.vout)
|
||||
{
|
||||
if (txout.nValue < 0)
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-negative");
|
||||
if (txout.nValue > MAX_MONEY)
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-toolarge");
|
||||
nValueOut += txout.nValue;
|
||||
if (!txout.nValue.IsValid())
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-amount-invalid");
|
||||
if (!txout.nValue.IsAmount())
|
||||
continue;
|
||||
nValueOut += txout.nValue.GetAmount();
|
||||
if (!MoneyRange(nValueOut))
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge");
|
||||
}
|
||||
|
|
@ -1432,9 +1432,12 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins
|
|||
}
|
||||
|
||||
// Check for negative or overflow input values
|
||||
nValueIn += coins->vout[prevout.n].nValue;
|
||||
if (!MoneyRange(coins->vout[prevout.n].nValue) || !MoneyRange(nValueIn))
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputvalues-outofrange");
|
||||
const CTxOutValue& value = coins->vout[prevout.n].nValue;
|
||||
if (value.IsAmount()) {
|
||||
nValueIn += value.GetAmount();
|
||||
if (!MoneyRange(value.GetAmount()) || !MoneyRange(nValueIn))
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputvalues-outofrange");
|
||||
}
|
||||
|
||||
if (coins->vout[prevout.n].scriptPubKey.IsWithdrawLock() && tx.vin[i].scriptSig.IsWithdrawProof()) {
|
||||
uint256 genesisHash(coins->vout[prevout.n].scriptPubKey.GetWithdrawLockGenesisHash());
|
||||
|
|
@ -1518,7 +1521,11 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
|
|||
// super-majority signaling has occurred.
|
||||
return state.DoS(100,false, REJECT_INVALID, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(check.GetScriptError())));
|
||||
}
|
||||
prevValueIn = coins->vout[tx.vin[i].prevout.n].nValue;
|
||||
const CTxOutValue& value = coins->vout[tx.vin[i].prevout.n].nValue;
|
||||
if (value.IsAmount())
|
||||
prevValueIn = value.GetAmount();
|
||||
else
|
||||
prevValueIn = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -449,8 +449,8 @@ class CScriptCheck
|
|||
{
|
||||
private:
|
||||
CScript scriptPubKey;
|
||||
CAmount amount;
|
||||
CAmount amountPreviousInput;
|
||||
CTxOutValue amount;
|
||||
CTxOutValue amountPreviousInput;
|
||||
const CTransaction *ptxTo;
|
||||
unsigned int nIn;
|
||||
unsigned int nFlags;
|
||||
|
|
@ -460,7 +460,7 @@ private:
|
|||
|
||||
public:
|
||||
CScriptCheck(): amount(0), amountPreviousInput(-1), ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
|
||||
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, CAmount amountPreviousInputIn, unsigned int nFlagsIn, bool cacheIn, PrecomputedTransactionData* txdataIn) :
|
||||
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, const CTxOutValue& amountPreviousInputIn, unsigned int nFlagsIn, bool cacheIn, PrecomputedTransactionData* txdataIn) :
|
||||
scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey), amount(txFromIn.vout[txToIn.vin[nInIn].prevout.n].nValue),
|
||||
amountPreviousInput(amountPreviousInputIn),
|
||||
ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR), txdata(txdataIn) { }
|
||||
|
|
|
|||
|
|
@ -592,7 +592,7 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request)
|
|||
BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
|
||||
if (txout.scriptPubKey == scriptPubKey)
|
||||
if (wtx.GetDepthInMainChain() >= nMinDepth)
|
||||
nAmount += txout.nValue;
|
||||
nAmount += txout.nValue.GetAmount();
|
||||
}
|
||||
|
||||
return ValueFromAmount(nAmount);
|
||||
|
|
@ -648,7 +648,7 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request)
|
|||
CTxDestination address;
|
||||
if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address))
|
||||
if (wtx.GetDepthInMainChain() >= nMinDepth)
|
||||
nAmount += txout.nValue;
|
||||
nAmount += txout.nValue.GetAmount();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1187,7 +1187,7 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
|
|||
continue;
|
||||
|
||||
tallyitem& item = mapTally[address];
|
||||
item.nAmount += txout.nValue;
|
||||
item.nAmount += txout.nValue.GetAmount();
|
||||
item.nConf = min(item.nConf, nDepth);
|
||||
item.txids.push_back(wtx.GetHash());
|
||||
if (mine & ISMINE_WATCH_ONLY)
|
||||
|
|
@ -2503,7 +2503,7 @@ UniValue listunspent(const JSONRPCRequest& request)
|
|||
}
|
||||
|
||||
entry.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
|
||||
entry.push_back(Pair("amount", ValueFromAmount(out.tx->tx->vout[out.i].nValue)));
|
||||
entry.push_back(Pair("amount", ValueFromAmount(out.tx->tx->vout[out.i].nValue.GetAmount())));
|
||||
entry.push_back(Pair("confirmations", out.nDepth));
|
||||
entry.push_back(Pair("spendable", out.fSpendable));
|
||||
entry.push_back(Pair("solvable", out.fSolvable));
|
||||
|
|
@ -2910,15 +2910,15 @@ UniValue bumpfee(const JSONRPCRequest& request)
|
|||
assert(nDelta > 0);
|
||||
CMutableTransaction tx(*(wtx.tx));
|
||||
CTxOut* poutput = &(tx.vout[nOutput]);
|
||||
if (poutput->nValue < nDelta) {
|
||||
if (poutput->nValue.GetAmount() < nDelta) {
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "Change output is too small to bump the fee");
|
||||
}
|
||||
|
||||
// If the output would become dust, discard it (converting the dust to fee)
|
||||
poutput->nValue -= nDelta;
|
||||
if (poutput->nValue <= poutput->GetDustThreshold(::dustRelayFee)) {
|
||||
poutput->nValue = CTxOutValue(poutput->nValue.GetAmount() - nDelta);
|
||||
if (poutput->nValue.GetAmount() <= poutput->GetDustThreshold(::dustRelayFee)) {
|
||||
LogPrint("rpc", "Bumping fee and discarding dust output\n");
|
||||
nNewFee += poutput->nValue;
|
||||
nNewFee += poutput->nValue.GetAmount();
|
||||
tx.vout.erase(tx.vout.begin() + nOutput);
|
||||
}
|
||||
|
||||
|
|
@ -2936,7 +2936,7 @@ UniValue bumpfee(const JSONRPCRequest& request)
|
|||
std::map<uint256, CWalletTx>::const_iterator mi = pwalletMain->mapWallet.find(input.prevout.hash);
|
||||
assert(mi != pwalletMain->mapWallet.end() && input.prevout.n < mi->second.tx->vout.size());
|
||||
const CScript& scriptPubKey = mi->second.tx->vout[input.prevout.n].scriptPubKey;
|
||||
const CAmount& amount = mi->second.tx->vout[input.prevout.n].nValue;
|
||||
const CAmount& amount = mi->second.tx->vout[input.prevout.n].nValue.GetAmount();
|
||||
SignatureData sigdata;
|
||||
if (!ProduceSignature(TransactionSignatureCreator(pwalletMain, &txNewConst, nIn, amount, SIGHASH_ALL), scriptPubKey, sigdata)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Can't sign transaction.");
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ struct CompareValueOnly
|
|||
|
||||
std::string COutput::ToString() const
|
||||
{
|
||||
return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->tx->vout[i].nValue));
|
||||
return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->tx->vout[i].nValue.GetAmount()));
|
||||
}
|
||||
|
||||
const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
|
||||
|
|
@ -1226,7 +1226,7 @@ CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
|
|||
const CWalletTx& prev = (*mi).second;
|
||||
if (txin.prevout.n < prev.tx->vout.size())
|
||||
if (IsMine(prev.tx->vout[txin.prevout.n]) & filter)
|
||||
return prev.tx->vout[txin.prevout.n].nValue;
|
||||
return prev.tx->vout[txin.prevout.n].nValue.GetAmount();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -1239,9 +1239,9 @@ isminetype CWallet::IsMine(const CTxOut& txout) const
|
|||
|
||||
CAmount CWallet::GetCredit(const CTxOut& txout, const isminefilter& filter) const
|
||||
{
|
||||
if (!MoneyRange(txout.nValue))
|
||||
if (!MoneyRange(txout.nValue.GetAmount()))
|
||||
throw std::runtime_error(std::string(__func__) + ": value out of range");
|
||||
return ((IsMine(txout) & filter) ? txout.nValue : 0);
|
||||
return ((IsMine(txout) & filter) ? txout.nValue.GetAmount() : 0);
|
||||
}
|
||||
|
||||
bool CWallet::IsChange(const CTxOut& txout) const
|
||||
|
|
@ -1268,9 +1268,9 @@ bool CWallet::IsChange(const CTxOut& txout) const
|
|||
|
||||
CAmount CWallet::GetChange(const CTxOut& txout) const
|
||||
{
|
||||
if (!MoneyRange(txout.nValue))
|
||||
if (!MoneyRange(txout.nValue.GetAmount()))
|
||||
throw std::runtime_error(std::string(__func__) + ": value out of range");
|
||||
return (IsChange(txout) ? txout.nValue : 0);
|
||||
return (IsChange(txout) ? txout.nValue.GetAmount() : 0);
|
||||
}
|
||||
|
||||
bool CWallet::IsMine(const CTransaction& tx) const
|
||||
|
|
@ -1492,7 +1492,7 @@ void CWalletTx::GetAmounts(list<COutputEntry>& listReceived,
|
|||
address = CNoDestination();
|
||||
}
|
||||
|
||||
COutputEntry output = {address, txout.nValue, (int)i};
|
||||
COutputEntry output = {address, txout.nValue.GetAmount(), (int)i};
|
||||
|
||||
// If we are debited by the transaction, add the output as a "sent" entry
|
||||
if (nDebit > 0)
|
||||
|
|
@ -2081,7 +2081,7 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const
|
|||
for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++) {
|
||||
isminetype mine = IsMine(pcoin->tx->vout[i]);
|
||||
if (!(IsSpent(wtxid, i)) && mine != ISMINE_NO &&
|
||||
!IsLockedCoin((*it).first, i) && (pcoin->tx->vout[i].nValue > 0 || fIncludeZeroValue) &&
|
||||
!IsLockedCoin((*it).first, i) && (pcoin->tx->vout[i].nValue.GetAmount() > 0 || fIncludeZeroValue) &&
|
||||
(!coinControl || !coinControl->HasSelected() || coinControl->fAllowOtherInputs || coinControl->IsSelected(COutPoint((*it).first, i))))
|
||||
vCoins.push_back(COutput(pcoin, i, nDepth,
|
||||
((mine & ISMINE_SPENDABLE) != ISMINE_NO) ||
|
||||
|
|
@ -2167,7 +2167,7 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin
|
|||
continue;
|
||||
|
||||
int i = output.i;
|
||||
CAmount n = pcoin->tx->vout[i].nValue;
|
||||
CAmount n = pcoin->tx->vout[i].nValue.GetAmount();
|
||||
|
||||
pair<CAmount,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i));
|
||||
|
||||
|
|
@ -2254,7 +2254,7 @@ bool CWallet::SelectCoins(const vector<COutput>& vAvailableCoins, const CAmount&
|
|||
{
|
||||
if (!out.fSpendable)
|
||||
continue;
|
||||
nValueRet += out.tx->tx->vout[out.i].nValue;
|
||||
nValueRet += out.tx->tx->vout[out.i].nValue.GetAmount();
|
||||
setCoinsRet.insert(make_pair(out.tx, out.i));
|
||||
}
|
||||
return (nValueRet >= nTargetValue);
|
||||
|
|
@ -2276,7 +2276,7 @@ bool CWallet::SelectCoins(const vector<COutput>& vAvailableCoins, const CAmount&
|
|||
// Clearly invalid input, fail
|
||||
if (pcoin->tx->vout.size() <= outpoint.n)
|
||||
return false;
|
||||
nValueFromPresetInputs += pcoin->tx->vout[outpoint.n].nValue;
|
||||
nValueFromPresetInputs += pcoin->tx->vout[outpoint.n].nValue.GetAmount();
|
||||
setPresetCoins.insert(make_pair(pcoin, outpoint.n));
|
||||
} else
|
||||
return false; // TODO: Allow non-wallet inputs
|
||||
|
|
@ -2320,7 +2320,7 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool ov
|
|||
for (size_t idx = 0; idx < tx.vout.size(); idx++)
|
||||
{
|
||||
const CTxOut& txOut = tx.vout[idx];
|
||||
CRecipient recipient = {txOut.scriptPubKey, txOut.nValue, setSubtractFeeFromOutputs.count(idx) == 1};
|
||||
CRecipient recipient = {txOut.scriptPubKey, txOut.nValue.GetAmount(), setSubtractFeeFromOutputs.count(idx) == 1};
|
||||
vecSend.push_back(recipient);
|
||||
}
|
||||
|
||||
|
|
@ -2456,12 +2456,12 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
|||
|
||||
if (recipient.fSubtractFeeFromAmount)
|
||||
{
|
||||
txout.nValue -= nFeeRet / nSubtractFeeFromAmount; // Subtract fee equally from each selected recipient
|
||||
txout.nValue = CTxOutValue(txout.nValue.GetAmount() - (nFeeRet / nSubtractFeeFromAmount)); // Subtract fee equally from each selected recipient
|
||||
|
||||
if (fFirst) // first receiver pays the remainder not divisible by output count
|
||||
{
|
||||
fFirst = false;
|
||||
txout.nValue -= nFeeRet % nSubtractFeeFromAmount;
|
||||
txout.nValue = CTxOutValue(txout.nValue.GetAmount() - (nFeeRet % nSubtractFeeFromAmount));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2469,7 +2469,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
|||
{
|
||||
if (recipient.fSubtractFeeFromAmount && nFeeRet > 0)
|
||||
{
|
||||
if (txout.nValue < 0)
|
||||
if (txout.nValue.GetAmount() < 0)
|
||||
strFailReason = _("The transaction amount is too small to pay the fee");
|
||||
else
|
||||
strFailReason = _("The transaction amount is too small to send after the fee has been deducted");
|
||||
|
|
@ -2491,7 +2491,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
|||
}
|
||||
for (const auto& pcoin : setCoins)
|
||||
{
|
||||
CAmount nCredit = pcoin.first->tx->vout[pcoin.second].nValue;
|
||||
CAmount nCredit = pcoin.first->tx->vout[pcoin.second].nValue.GetAmount();
|
||||
//The coin age after the next block (depth+1) is used instead of the current,
|
||||
//reflecting an assumption the user would accept a bit more delay for
|
||||
//a chance at a free transaction.
|
||||
|
|
@ -2545,13 +2545,13 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
|||
// So instead we raise the change and deduct from the recipient.
|
||||
if (nSubtractFeeFromAmount > 0 && newTxOut.IsDust(dustRelayFee))
|
||||
{
|
||||
CAmount nDust = newTxOut.GetDustThreshold(dustRelayFee) - newTxOut.nValue;
|
||||
newTxOut.nValue += nDust; // raise change until no more dust
|
||||
CAmount nDust = newTxOut.GetDustThreshold(dustRelayFee) - newTxOut.nValue.GetAmount();
|
||||
newTxOut.nValue = CTxOutValue(newTxOut.nValue.GetAmount() + nDust); // raise change until no more dust
|
||||
for (unsigned int i = 0; i < vecSend.size(); i++) // subtract from first recipient
|
||||
{
|
||||
if (vecSend[i].fSubtractFeeFromAmount)
|
||||
{
|
||||
txNew.vout[i].nValue -= nDust;
|
||||
txNew.vout[i].nValue = CTxOutValue(txNew.vout[i].nValue.GetAmount() - nDust);
|
||||
if (txNew.vout[i].IsDust(dustRelayFee))
|
||||
{
|
||||
strFailReason = _("The transaction amount is too small to send after the fee has been deducted");
|
||||
|
|
@ -2667,7 +2667,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
|||
if (nFeeRet > nFeeNeeded && nChangePosInOut != -1 && nSubtractFeeFromAmount == 0) {
|
||||
CAmount extraFeePaid = nFeeRet - nFeeNeeded;
|
||||
vector<CTxOut>::iterator change_position = txNew.vout.begin()+nChangePosInOut;
|
||||
change_position->nValue += extraFeePaid;
|
||||
change_position->nValue = CTxOutValue(change_position->nValue.GetAmount() + extraFeePaid);
|
||||
nFeeRet -= extraFeePaid;
|
||||
}
|
||||
break; // Done, enough fee included.
|
||||
|
|
@ -2678,8 +2678,8 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
|||
CAmount additionalFeeNeeded = nFeeNeeded - nFeeRet;
|
||||
vector<CTxOut>::iterator change_position = txNew.vout.begin()+nChangePosInOut;
|
||||
// Only reduce change if remaining amount is still a large enough output.
|
||||
if (change_position->nValue >= MIN_FINAL_CHANGE + additionalFeeNeeded) {
|
||||
change_position->nValue -= additionalFeeNeeded;
|
||||
if (change_position->nValue.GetAmount() >= MIN_FINAL_CHANGE + additionalFeeNeeded) {
|
||||
change_position->nValue = CTxOutValue(change_position->nValue.GetAmount() - additionalFeeNeeded);
|
||||
nFeeRet += additionalFeeNeeded;
|
||||
break; // Done, able to increase fee from change
|
||||
}
|
||||
|
|
@ -3146,7 +3146,7 @@ std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
|
|||
if(!ExtractDestination(pcoin->tx->vout[i].scriptPubKey, addr))
|
||||
continue;
|
||||
|
||||
CAmount n = IsSpent(walletEntry.first, i) ? 0 : pcoin->tx->vout[i].nValue;
|
||||
CAmount n = IsSpent(walletEntry.first, i) ? 0 : pcoin->tx->vout[i].nValue.GetAmount();
|
||||
|
||||
if (!balances.count(addr))
|
||||
balances[addr] = 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue