BIP143: Verification logic
Includes simplifications by Eric Lombrozo. Edited for Zcash merge by Ariel Gabizon.
This commit is contained in:
committed by
Jack Grigg
parent
2d42e1a993
commit
c86a1cb86e
@@ -232,7 +232,7 @@ bool static CheckMinimalPush(const valtype& data, opcodetype opcode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
|
||||
bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror)
|
||||
{
|
||||
static const CScriptNum bnZero(0);
|
||||
static const CScriptNum bnOne(1);
|
||||
@@ -828,7 +828,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
|
||||
//serror is set
|
||||
return false;
|
||||
}
|
||||
bool fSuccess = checker.CheckSig(vchSig, vchPubKey, script);
|
||||
bool fSuccess = checker.CheckSig(vchSig, vchPubKey, script, sigversion);
|
||||
|
||||
popstack(stack);
|
||||
popstack(stack);
|
||||
@@ -886,7 +886,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
|
||||
}
|
||||
|
||||
// Check signature
|
||||
bool fOk = checker.CheckSig(vchSig, vchPubKey, script);
|
||||
bool fOk = checker.CheckSig(vchSig, vchPubKey, script, sigversion);
|
||||
|
||||
if (fOk) {
|
||||
isig++;
|
||||
@@ -1052,13 +1052,71 @@ public:
|
||||
|
||||
} // anon namespace
|
||||
|
||||
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
|
||||
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion)
|
||||
{
|
||||
if (nIn >= txTo.vin.size() && nIn != NOT_AN_INPUT) {
|
||||
// nIn out of range
|
||||
throw logic_error("input index is out of range");
|
||||
}
|
||||
|
||||
if (sigversion == SIGVERSION_WITNESS_V0) {
|
||||
uint256 hashPrevouts;
|
||||
uint256 hashSequence;
|
||||
uint256 hashOutputs;
|
||||
|
||||
if (!(nHashType & SIGHASH_ANYONECANPAY)) {
|
||||
CHashWriter ss(SER_GETHASH, 0);
|
||||
for (unsigned int n = 0; n < txTo.vin.size(); n++) {
|
||||
ss << txTo.vin[n].prevout;
|
||||
}
|
||||
hashPrevouts = ss.GetHash(); // TODO: cache this value for all signatures in a transaction
|
||||
}
|
||||
|
||||
if (!(nHashType & SIGHASH_ANYONECANPAY) && (nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
|
||||
CHashWriter ss(SER_GETHASH, 0);
|
||||
for (unsigned int n = 0; n < txTo.vin.size(); n++) {
|
||||
ss << txTo.vin[n].nSequence;
|
||||
}
|
||||
hashSequence = ss.GetHash(); // TODO: cache this value for all signatures in a transaction
|
||||
}
|
||||
|
||||
if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
|
||||
CHashWriter ss(SER_GETHASH, 0);
|
||||
for (unsigned int n = 0; n < txTo.vout.size(); n++) {
|
||||
ss << txTo.vout[n];
|
||||
}
|
||||
hashOutputs = ss.GetHash(); // TODO: cache this value for all signatures in a transaction
|
||||
} else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) {
|
||||
CHashWriter ss(SER_GETHASH, 0);
|
||||
ss << txTo.vout[nIn];
|
||||
hashOutputs = ss.GetHash();
|
||||
}
|
||||
|
||||
CHashWriter ss(SER_GETHASH, 0);
|
||||
// Version
|
||||
ss << txTo.nVersion;
|
||||
// Input prevouts/nSequence (none/all, depending on flags)
|
||||
ss << hashPrevouts;
|
||||
ss << hashSequence;
|
||||
// The input being signed (replacing the scriptSig with scriptCode + amount)
|
||||
// The prevout may already be contained in hashPrevout, and the nSequence
|
||||
// may already be contained in hashSequence.
|
||||
if (nIn != NOT_AN_INPUT)
|
||||
ss << txTo.vin[nIn].prevout;
|
||||
ss << scriptCode;
|
||||
ss << amount;
|
||||
if (nIn != NOT_AN_INPUT)
|
||||
ss << txTo.vin[nIn].nSequence;
|
||||
// Outputs (none/one/all, depending on flags)
|
||||
ss << hashOutputs;
|
||||
// Locktime
|
||||
ss << txTo.nLockTime;
|
||||
// Sighash type
|
||||
ss << nHashType;
|
||||
|
||||
return ss.GetHash();
|
||||
}
|
||||
|
||||
// Check for invalid use of SIGHASH_SINGLE
|
||||
if ((nHashType & 0x1f) == SIGHASH_SINGLE) {
|
||||
if (nIn >= txTo.vout.size()) {
|
||||
@@ -1081,7 +1139,7 @@ bool TransactionSignatureChecker::VerifySignature(const std::vector<unsigned cha
|
||||
return pubkey.Verify(sighash, vchSig);
|
||||
}
|
||||
|
||||
bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vector<unsigned char>& vchPubKey, const CScript& scriptCode) const
|
||||
bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
|
||||
{
|
||||
CPubKey pubkey(vchPubKey);
|
||||
if (!pubkey.IsValid())
|
||||
@@ -1096,7 +1154,7 @@ bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn
|
||||
|
||||
uint256 sighash;
|
||||
try {
|
||||
sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType);
|
||||
sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion);
|
||||
} catch (logic_error ex) {
|
||||
return false;
|
||||
}
|
||||
@@ -1153,12 +1211,12 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
|
||||
}
|
||||
|
||||
vector<vector<unsigned char> > stack, stackCopy;
|
||||
if (!EvalScript(stack, scriptSig, flags, checker, serror))
|
||||
if (!EvalScript(stack, scriptSig, flags, checker, SIGVERSION_BASE, serror))
|
||||
// serror is set
|
||||
return false;
|
||||
if (flags & SCRIPT_VERIFY_P2SH)
|
||||
stackCopy = stack;
|
||||
if (!EvalScript(stack, scriptPubKey, flags, checker, serror))
|
||||
if (!EvalScript(stack, scriptPubKey, flags, checker, SIGVERSION_BASE, serror))
|
||||
// serror is set
|
||||
return false;
|
||||
if (stack.empty())
|
||||
@@ -1185,7 +1243,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
|
||||
CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end());
|
||||
popstack(stack);
|
||||
|
||||
if (!EvalScript(stack, pubKey2, flags, checker, serror))
|
||||
if (!EvalScript(stack, pubKey2, flags, checker, SIGVERSION_BASE, serror))
|
||||
// serror is set
|
||||
return false;
|
||||
if (stack.empty())
|
||||
|
||||
Reference in New Issue
Block a user