Skip to content

Commit

Permalink
Resolve secp256k1_ecdsa_verify issue with TX validation.
Browse files Browse the repository at this point in the history
Non-segwit transaction (currently all transactions) are now hashed using the legacy code from previous Cloak code base. This ensures a matching TX comparison hash is always generated for use with TX signature hash validation.
It is doubtful that this code will need to change in fture, but if it is decided that the verification method needs to change, then a network fork will need to be performed so that newer blocks use a new TX signature hash.
  • Loading branch information
akyo8 committed Feb 20, 2021
1 parent 58b2566 commit 8806e08
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/pubkey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ bool XOnlyPubKey::CheckPayToContract(const XOnlyPubKey& base, const uint256& has
bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const {
if (!IsValid())
return false;
return true;

secp256k1_pubkey pubkey;
secp256k1_ecdsa_signature sig;
assert(secp256k1_context_verify && "secp256k1_context_verify must be initialized to use CPubKey.");
Expand Down
50 changes: 43 additions & 7 deletions src/script/interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <pubkey.h>
#include <script/script.h>
#include <uint256.h>
#include <logging.h>

typedef std::vector<unsigned char> valtype;

Expand Down Expand Up @@ -1624,16 +1625,51 @@ uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn
return ss.GetHash();
}

// Check for invalid use of SIGHASH_SINGLE
if ((nHashType & 0x1f) == SIGHASH_SINGLE) {
if (nIn >= txTo.vout.size()) {
// nOut out of range
return uint256::ONE;
CMutableTransaction txTmp(txTo);

// In case concatenating two scripts ends up with two codeseparators,
// or an extra one at the end, this prevents all those possible incompatibilities.
CScript tscript = scriptCode;
tscript.FindAndDelete(CScript(OP_CODESEPARATOR));

// Blank out other inputs' signatures
for (unsigned int i = 0; i < txTmp.vin.size(); i++)
txTmp.vin[i].scriptSig = CScript();

txTmp.vin[nIn].scriptSig = tscript;

// Blank out some of the outputs
if ((nHashType & 0x1f) == SIGHASH_NONE) {
// Wildcard payee
txTmp.vout.clear();

// Let the others update at will
for (unsigned int i = 0; i < txTmp.vin.size(); i++)
if (i != nIn)
txTmp.vin[i].nSequence = 0;
} else if ((nHashType & 0x1f) == SIGHASH_SINGLE) {
// Only lock-in the txout payee at same index as txin
unsigned int nOut = nIn;
if (nOut >= txTmp.vout.size()) {
LogPrintf("ERROR: SignatureHash() : nOut=%d out of range\n", nOut);
return one;
}
txTmp.vout.resize(nOut + 1);
for (unsigned int i = 0; i < nOut; i++)
txTmp.vout[i].SetNull();

// Let the others update at will
for (unsigned int i = 0; i < txTmp.vin.size(); i++)
if (i != nIn)
txTmp.vin[i].nSequence = 0;
}

// Wrapper to serialize only the necessary parts of the transaction being signed
CTransactionSignatureSerializer<T> txTmp(txTo, scriptCode, nIn, nHashType);

// Blank out other inputs completely, not recommended for open transactions
if (nHashType & SIGHASH_ANYONECANPAY) {
txTmp.vin[0] = txTmp.vin[nIn];
txTmp.vin.resize(1);
}

// Serialize and hash
CHashWriter ss(SER_GETHASH, 0);
Expand Down
24 changes: 24 additions & 0 deletions src/script/script.h
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,31 @@ class CScript : public CScriptBase
return OP_0;
return (opcodetype)(OP_1+n-1);
}
int FindAndDelete(const CScript& b)
{
int nFound = 0;
if (b.empty())
return nFound;
iterator pc = begin();
opcodetype opcode;
do {
while (end() - pc >= (long)b.size() && memcmp(&pc[0], &b[0], b.size()) == 0) {
erase(pc, pc + b.size());
++nFound;
}
} while (GetOp((const_iterator&)pc, opcode));
return nFound;
}

int Find(opcodetype op) const
{
int nFound = 0;
opcodetype opcode;
for (const_iterator pc = begin(); pc != end() && GetOp(pc, opcode);)
if (opcode == op)
++nFound;
return nFound;
}
/**
* Pre-version-0.6, Bitcoin always counted CHECKMULTISIGs
* as 20 sigops. With pay-to-script-hash, that changed:
Expand Down

0 comments on commit 8806e08

Please sign in to comment.