Skip to content

Commit

Permalink
Remove in-band error signalling from SignatureHash, fixing the SIGHAS…
Browse files Browse the repository at this point in the history
…H_SINGLE bug.
  • Loading branch information
defuse committed Jul 19, 2016
1 parent 85cc6f5 commit 67f0243
Show file tree
Hide file tree
Showing 6 changed files with 19 additions and 20 deletions.
8 changes: 4 additions & 4 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -999,12 +999,12 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio
REJECT_INVALID, "bad-txns-prevout-null");

if (tx.vjoinsplit.size() > 0) {
// TODO: #966.
static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
// Empty output script.
CScript scriptCode;
uint256 dataToBeSigned = SignatureHash(scriptCode, tx, NOT_AN_INPUT, SIGHASH_ALL);
if (dataToBeSigned == one) {
uint256 dataToBeSigned;
try {
dataToBeSigned = SignatureHash(scriptCode, tx, NOT_AN_INPUT, SIGHASH_ALL);
} catch (std::logic_error ex) {
return state.DoS(100, error("CheckTransaction(): error computing signature hash"),
REJECT_INVALID, "error-computing-signature-hash");
}
Expand Down
12 changes: 8 additions & 4 deletions src/script/interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1095,17 +1095,16 @@ class CTransactionSignatureSerializer {

uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
{
static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
if (nIn >= txTo.vin.size() && nIn != NOT_AN_INPUT) {
// nIn out of range
return one;
throw logic_error("input index is out of range");
}

// Check for invalid use of SIGHASH_SINGLE
if ((nHashType & 0x1f) == SIGHASH_SINGLE) {
if (nIn >= txTo.vout.size()) {
// nOut out of range
return one;
throw logic_error("no matching output for SIGHASH_SINGLE");
}
}

Expand Down Expand Up @@ -1136,7 +1135,12 @@ bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn
int nHashType = vchSig.back();
vchSig.pop_back();

uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType);
uint256 sighash;
try {
sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType);
} catch (logic_error ex) {
return false;
}

if (!VerifySignature(vchSig, pubkey, sighash))
return false;
Expand Down
8 changes: 7 additions & 1 deletion src/script/sign.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,13 @@ bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig,
if (!keystore->GetKey(address, key))
return false;

uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType);
uint256 hash;
try {
hash = SignatureHash(scriptCode, *txTo, nIn, nHashType);
} catch (logic_error ex) {
return false;
}

if (!key.Sign(hash, vchSig))
return false;
vchSig.push_back((unsigned char)nHashType);
Expand Down
3 changes: 0 additions & 3 deletions src/test/sighash_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,10 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle) {
unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
crypto_sign_keypair(tx.joinSplitPubKey.begin(), joinSplitPrivKey);

// TODO: #966.
static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
// Empty output script.
CScript scriptCode;
CTransaction signTx(tx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);
BOOST_CHECK(dataToBeSigned != one);

assert(crypto_sign_detached(&tx.joinSplitSig[0], NULL,
dataToBeSigned.begin(), 32,
Expand Down
3 changes: 0 additions & 3 deletions src/test/transaction_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,13 +402,10 @@ BOOST_AUTO_TEST_CASE(test_simple_joinsplit_invalidity)
BOOST_CHECK(!CheckTransactionWithoutProofVerification(newTx, state));
BOOST_CHECK(state.GetRejectReason() == "bad-txns-invalid-joinsplit-signature");

// TODO: #966.
static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
// Empty output script.
CScript scriptCode;
CTransaction signTx(newTx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);
BOOST_CHECK(dataToBeSigned != one);

assert(crypto_sign_detached(&newTx.joinSplitSig[0], NULL,
dataToBeSigned.begin(), 32,
Expand Down
5 changes: 0 additions & 5 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2656,15 +2656,10 @@ Value zc_raw_joinsplit(const json_spirit::Array& params, bool fHelp)

mtx.vjoinsplit.push_back(jsdesc);

// TODO: #966.
static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
// Empty output script.
CScript scriptCode;
CTransaction signTx(mtx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);
if (dataToBeSigned == one) {
throw runtime_error("SignatureHash failed");
}

// Add the signature
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
Expand Down

0 comments on commit 67f0243

Please sign in to comment.