Skip to content

Commit 271e45e

Browse files
committed
Observe input amounts: verification
1 parent 6a8021f commit 271e45e

File tree

13 files changed

+48
-36
lines changed

13 files changed

+48
-36
lines changed

src/bitcoin-tx.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
457457
continue;
458458
}
459459
const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey;
460+
const CAmount& amount = coins->vout[txin.prevout.n].nValue;
460461

461462
txin.scriptSig.clear();
462463
// Only sign SIGHASH_SINGLE if there's a corresponding output:
@@ -467,7 +468,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
467468
BOOST_FOREACH(const CTransaction& txv, txVariants) {
468469
txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
469470
}
470-
if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i)))
471+
if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount)))
471472
fComplete = false;
472473
}
473474

src/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1796,7 +1796,7 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
17961796
bool CScriptCheck::operator()() {
17971797
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
17981798
const CScriptWitness *witness = (nIn < ptxTo->wit.vtxinwit.size()) ? &ptxTo->wit.vtxinwit[nIn].scriptWitness : NULL;
1799-
if (!VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, cacheStore), &error)) {
1799+
if (!VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore), &error)) {
18001800
return false;
18011801
}
18021802
return true;

src/main.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,23 +411,25 @@ class CScriptCheck
411411
{
412412
private:
413413
CScript scriptPubKey;
414+
CAmount amount;
414415
const CTransaction *ptxTo;
415416
unsigned int nIn;
416417
unsigned int nFlags;
417418
bool cacheStore;
418419
ScriptError error;
419420

420421
public:
421-
CScriptCheck(): ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
422+
CScriptCheck(): amount(0), ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
422423
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn) :
423-
scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey),
424+
scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey), amount(txFromIn.vout[txToIn.vin[nInIn].prevout.n].nValue),
424425
ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR) { }
425426

426427
bool operator()();
427428

428429
void swap(CScriptCheck &check) {
429430
scriptPubKey.swap(check.scriptPubKey);
430431
std::swap(ptxTo, check.ptxTo);
432+
std::swap(amount, check.amount);
431433
std::swap(nIn, check.nIn);
432434
std::swap(nFlags, check.nFlags);
433435
std::swap(cacheStore, check.cacheStore);

src/rpc/rawtransaction.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,7 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp)
752752
continue;
753753
}
754754
const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey;
755+
const CAmount& amount = coins->vout[txin.prevout.n].nValue;
755756

756757
txin.scriptSig.clear();
757758
// Only sign SIGHASH_SINGLE if there's a corresponding output:
@@ -763,7 +764,7 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp)
763764
txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
764765
}
765766
ScriptError serror = SCRIPT_ERR_OK;
766-
if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i), &serror)) {
767+
if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount), &serror)) {
767768
TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
768769
}
769770
}

src/script/bitcoinconsensus.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned i
8585
// Regardless of the verification result, the tx did not error.
8686
set_error(err, bitcoinconsensus_ERR_OK);
8787

88-
return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), nIn < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[nIn].scriptWitness : NULL, flags, TransactionSignatureChecker(&tx, nIn), NULL);
88+
CAmount am(0);
89+
return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), nIn < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[nIn].scriptWitness : NULL, flags, TransactionSignatureChecker(&tx, nIn, am), NULL);
8990
} catch (const std::exception&) {
9091
return set_error(err, bitcoinconsensus_ERR_TX_DESERIALIZE); // Error deserializing
9192
}

src/script/bitcoinconsensus.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#ifndef BITCOIN_BITCOINCONSENSUS_H
77
#define BITCOIN_BITCOINCONSENSUS_H
88

9+
#include <stdint.h>
10+
911
#if defined(BUILD_BITCOIN_INTERNAL) && defined(HAVE_CONFIG_H)
1012
#include "config/bitcoin-config.h"
1113
#if defined(_WIN32)

src/script/interpreter.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ class TransactionSignatureChecker : public BaseSignatureChecker
131131
virtual bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
132132

133133
public:
134-
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn) : txTo(txToIn), nIn(nInIn) {}
134+
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount) : txTo(txToIn), nIn(nInIn) {}
135135
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const;
136136
bool CheckLockTime(const CScriptNum& nLockTime) const;
137137
bool CheckSequence(const CScriptNum& nSequence) const;
@@ -143,7 +143,7 @@ class MutableTransactionSignatureChecker : public TransactionSignatureChecker
143143
const CTransaction txTo;
144144

145145
public:
146-
MutableTransactionSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn) : TransactionSignatureChecker(&txTo, nInIn), txTo(*txToIn) {}
146+
MutableTransactionSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amount) : TransactionSignatureChecker(&txTo, nInIn, amount), txTo(*txToIn) {}
147147
};
148148

149149
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL);

src/script/sigcache.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class CachingTransactionSignatureChecker : public TransactionSignatureChecker
2222
bool store;
2323

2424
public:
25-
CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, bool storeIn=true) : TransactionSignatureChecker(txToIn, nInIn), store(storeIn) {}
25+
CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount, bool storeIn) : TransactionSignatureChecker(txToIn, nInIn, amount), store(storeIn) {}
2626

2727
bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
2828
};

src/script/sign.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ using namespace std;
1818

1919
typedef std::vector<unsigned char> valtype;
2020

21-
TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), checker(txTo, nIn) {}
21+
static const CAmount amountZero = 0;
22+
TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), checker(txTo, nIn, amountZero) {}
2223

2324
bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode) const
2425
{
@@ -258,7 +259,7 @@ static CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatur
258259
CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
259260
const CScript& scriptSig1, const CScript& scriptSig2)
260261
{
261-
TransactionSignatureChecker checker(&txTo, nIn);
262+
TransactionSignatureChecker checker(&txTo, nIn, amountZero);
262263
return CombineSignatures(scriptPubKey, checker, scriptSig1, scriptSig2);
263264
}
264265

src/test/multisig_tests.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
4646

4747
ScriptError err;
4848
CKey key[4];
49+
CAmount amount = 0;
4950
for (int i = 0; i < 4; i++)
5051
key[i].MakeNewKey(true);
5152

@@ -81,20 +82,20 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
8182
keys.assign(1,key[0]);
8283
keys.push_back(key[1]);
8384
s = sign_multisig(a_and_b, keys, txTo[0], 0);
84-
BOOST_CHECK(VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err));
85+
BOOST_CHECK(VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err));
8586
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
8687

8788
for (int i = 0; i < 4; i++)
8889
{
8990
keys.assign(1,key[i]);
9091
s = sign_multisig(a_and_b, keys, txTo[0], 0);
91-
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err), strprintf("a&b 1: %d", i));
92+
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 1: %d", i));
9293
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
9394

9495
keys.assign(1,key[1]);
9596
keys.push_back(key[i]);
9697
s = sign_multisig(a_and_b, keys, txTo[0], 0);
97-
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err), strprintf("a&b 2: %d", i));
98+
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 2: %d", i));
9899
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
99100
}
100101

@@ -105,18 +106,18 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
105106
s = sign_multisig(a_or_b, keys, txTo[1], 0);
106107
if (i == 0 || i == 1)
107108
{
108-
BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err), strprintf("a|b: %d", i));
109+
BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i));
109110
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
110111
}
111112
else
112113
{
113-
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err), strprintf("a|b: %d", i));
114+
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i));
114115
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
115116
}
116117
}
117118
s.clear();
118119
s << OP_0 << OP_1;
119-
BOOST_CHECK(!VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err));
120+
BOOST_CHECK(!VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err));
120121
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));
121122

122123

@@ -128,12 +129,12 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
128129
s = sign_multisig(escrow, keys, txTo[2], 0);
129130
if (i < j && i < 3 && j < 3)
130131
{
131-
BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, NULL, flags, MutableTransactionSignatureChecker(&txTo[2], 0), &err), strprintf("escrow 1: %d %d", i, j));
132+
BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, NULL, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 1: %d %d", i, j));
132133
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
133134
}
134135
else
135136
{
136-
BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, NULL, flags, MutableTransactionSignatureChecker(&txTo[2], 0), &err), strprintf("escrow 2: %d %d", i, j));
137+
BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, NULL, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 2: %d %d", i, j));
137138
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
138139
}
139140
}

0 commit comments

Comments
 (0)