BIP143: Verification logic
Includes simplifications by Eric Lombrozo.
This commit is contained in:
parent
8da543f279
commit
fff708d3a3
@ -160,7 +160,7 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
|
|||||||
{
|
{
|
||||||
std::vector<std::vector<unsigned char> > stack;
|
std::vector<std::vector<unsigned char> > stack;
|
||||||
// convert the scriptSig into a stack, so we can inspect the redeemScript
|
// convert the scriptSig into a stack, so we can inspect the redeemScript
|
||||||
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), 0))
|
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SIGVERSION_BASE))
|
||||||
return false;
|
return false;
|
||||||
if (stack.empty())
|
if (stack.empty())
|
||||||
return false;
|
return false;
|
||||||
|
@ -828,7 +828,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
|
|||||||
// ... and merge in other signatures:
|
// ... and merge in other signatures:
|
||||||
for (const CMutableTransaction& txv : txVariants) {
|
for (const CMutableTransaction& txv : txVariants) {
|
||||||
if (txv.vin.size() > i) {
|
if (txv.vin.size() > i) {
|
||||||
txin.scriptSig = CombineSignatures(prevPubKey, txConst, i, txin.scriptSig, txv.vin[i].scriptSig);
|
txin.scriptSig = CombineSignatures(prevPubKey, txConst, i, amount, txin.scriptSig, txv.vin[i].scriptSig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ScriptError serror = SCRIPT_ERR_OK;
|
ScriptError serror = SCRIPT_ERR_OK;
|
||||||
|
@ -227,7 +227,7 @@ bool static CheckMinimalPush(const valtype& data, opcodetype opcode) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
|
bool EvalScript(std::vector<std::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 bnZero(0);
|
||||||
static const CScriptNum bnOne(1);
|
static const CScriptNum bnOne(1);
|
||||||
@ -867,13 +867,15 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
|
|||||||
CScript scriptCode(pbegincodehash, pend);
|
CScript scriptCode(pbegincodehash, pend);
|
||||||
|
|
||||||
// Drop the signature, since there's no way for a signature to sign itself
|
// Drop the signature, since there's no way for a signature to sign itself
|
||||||
|
if (sigversion == SIGVERSION_BASE) {
|
||||||
scriptCode.FindAndDelete(CScript(vchSig));
|
scriptCode.FindAndDelete(CScript(vchSig));
|
||||||
|
}
|
||||||
|
|
||||||
if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, serror)) {
|
if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, serror)) {
|
||||||
//serror is set
|
//serror is set
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode);
|
bool fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode, sigversion);
|
||||||
|
|
||||||
if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && vchSig.size())
|
if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && vchSig.size())
|
||||||
return set_error(serror, SCRIPT_ERR_SIG_NULLFAIL);
|
return set_error(serror, SCRIPT_ERR_SIG_NULLFAIL);
|
||||||
@ -929,8 +931,10 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
|
|||||||
for (int k = 0; k < nSigsCount; k++)
|
for (int k = 0; k < nSigsCount; k++)
|
||||||
{
|
{
|
||||||
valtype& vchSig = stacktop(-isig-k);
|
valtype& vchSig = stacktop(-isig-k);
|
||||||
|
if (sigversion == SIGVERSION_BASE) {
|
||||||
scriptCode.FindAndDelete(CScript(vchSig));
|
scriptCode.FindAndDelete(CScript(vchSig));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool fSuccess = true;
|
bool fSuccess = true;
|
||||||
while (fSuccess && nSigsCount > 0)
|
while (fSuccess && nSigsCount > 0)
|
||||||
@ -947,7 +951,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check signature
|
// Check signature
|
||||||
bool fOk = checker.CheckSig(vchSig, vchPubKey, scriptCode);
|
bool fOk = checker.CheckSig(vchSig, vchPubKey, scriptCode, sigversion);
|
||||||
|
|
||||||
if (fOk) {
|
if (fOk) {
|
||||||
isig++;
|
isig++;
|
||||||
@ -1150,8 +1154,64 @@ PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo)
|
|||||||
hashOutputs = GetOutputsHash(txTo);
|
hashOutputs = GetOutputsHash(txTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const PrecomputedTransactionData* cache)
|
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache)
|
||||||
{
|
{
|
||||||
|
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 contain in hashSequence.
|
||||||
|
ss << txTo.vin[nIn].prevout;
|
||||||
|
ss << static_cast<const CScriptBase&>(scriptCode);
|
||||||
|
ss << amount;
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
|
static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
|
||||||
if (nIn >= txTo.vin.size()) {
|
if (nIn >= txTo.vin.size()) {
|
||||||
// nIn out of range
|
// nIn out of range
|
||||||
@ -1180,7 +1240,7 @@ bool TransactionSignatureChecker::VerifySignature(const std::vector<unsigned cha
|
|||||||
return pubkey.Verify(sighash, vchSig);
|
return pubkey.Verify(sighash, vchSig);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TransactionSignatureChecker::CheckSig(const std::vector<unsigned char>& vchSigIn, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const
|
bool TransactionSignatureChecker::CheckSig(const std::vector<unsigned char>& vchSigIn, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
|
||||||
{
|
{
|
||||||
CPubKey pubkey(vchPubKey);
|
CPubKey pubkey(vchPubKey);
|
||||||
if (!pubkey.IsValid())
|
if (!pubkey.IsValid())
|
||||||
@ -1193,7 +1253,7 @@ bool TransactionSignatureChecker::CheckSig(const std::vector<unsigned char>& vch
|
|||||||
int nHashType = vchSig.back();
|
int nHashType = vchSig.back();
|
||||||
vchSig.pop_back();
|
vchSig.pop_back();
|
||||||
|
|
||||||
uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, this->txdata);
|
uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion, this->txdata);
|
||||||
|
|
||||||
if (!VerifySignature(vchSig, pubkey, sighash))
|
if (!VerifySignature(vchSig, pubkey, sighash))
|
||||||
return false;
|
return false;
|
||||||
@ -1292,12 +1352,12 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::vector<unsigned char> > stack, stackCopy;
|
std::vector<std::vector<unsigned char> > stack, stackCopy;
|
||||||
if (!EvalScript(stack, scriptSig, flags, checker, serror))
|
if (!EvalScript(stack, scriptSig, flags, checker, SIGVERSION_BASE, serror))
|
||||||
// serror is set
|
// serror is set
|
||||||
return false;
|
return false;
|
||||||
if (flags & SCRIPT_VERIFY_P2SH)
|
if (flags & SCRIPT_VERIFY_P2SH)
|
||||||
stackCopy = stack;
|
stackCopy = stack;
|
||||||
if (!EvalScript(stack, scriptPubKey, flags, checker, serror))
|
if (!EvalScript(stack, scriptPubKey, flags, checker, SIGVERSION_BASE, serror))
|
||||||
// serror is set
|
// serror is set
|
||||||
return false;
|
return false;
|
||||||
if (stack.empty())
|
if (stack.empty())
|
||||||
@ -1324,7 +1384,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
|
|||||||
CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end());
|
CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end());
|
||||||
popstack(stack);
|
popstack(stack);
|
||||||
|
|
||||||
if (!EvalScript(stack, pubKey2, flags, checker, serror))
|
if (!EvalScript(stack, pubKey2, flags, checker, SIGVERSION_BASE, serror))
|
||||||
// serror is set
|
// serror is set
|
||||||
return false;
|
return false;
|
||||||
if (stack.empty())
|
if (stack.empty())
|
||||||
|
@ -101,12 +101,18 @@ struct PrecomputedTransactionData
|
|||||||
PrecomputedTransactionData(const CTransaction& tx);
|
PrecomputedTransactionData(const CTransaction& tx);
|
||||||
};
|
};
|
||||||
|
|
||||||
uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const PrecomputedTransactionData* cache = nullptr);
|
enum SigVersion
|
||||||
|
{
|
||||||
|
SIGVERSION_BASE = 0,
|
||||||
|
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 = nullptr);
|
||||||
|
|
||||||
class BaseSignatureChecker
|
class BaseSignatureChecker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const
|
virtual bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -129,15 +135,16 @@ class TransactionSignatureChecker : public BaseSignatureChecker
|
|||||||
private:
|
private:
|
||||||
const CTransaction* txTo;
|
const CTransaction* txTo;
|
||||||
unsigned int nIn;
|
unsigned int nIn;
|
||||||
|
const CAmount amount;
|
||||||
const PrecomputedTransactionData* txdata;
|
const PrecomputedTransactionData* txdata;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
|
virtual bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount) : txTo(txToIn), nIn(nInIn), txdata(nullptr) {}
|
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(nullptr) {}
|
||||||
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount, const PrecomputedTransactionData& txdataIn) : txTo(txToIn), nIn(nInIn), txdata(&txdataIn) {}
|
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& 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) const override;
|
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override;
|
||||||
bool CheckLockTime(const CScriptNum& nLockTime) const override;
|
bool CheckLockTime(const CScriptNum& nLockTime) const override;
|
||||||
bool CheckSequence(const CScriptNum& nSequence) const override;
|
bool CheckSequence(const CScriptNum& nSequence) const override;
|
||||||
};
|
};
|
||||||
@ -151,7 +158,7 @@ public:
|
|||||||
MutableTransactionSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amount) : TransactionSignatureChecker(&txTo, nInIn, amount), txTo(*txToIn) {}
|
MutableTransactionSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amount) : TransactionSignatureChecker(&txTo, nInIn, amount), txTo(*txToIn) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = nullptr);
|
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* error = nullptr);
|
||||||
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = nullptr);
|
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = nullptr);
|
||||||
|
|
||||||
#endif // BITCOIN_SCRIPT_INTERPRETER_H
|
#endif // BITCOIN_SCRIPT_INTERPRETER_H
|
||||||
|
@ -15,8 +15,7 @@
|
|||||||
|
|
||||||
typedef std::vector<unsigned char> valtype;
|
typedef std::vector<unsigned char> valtype;
|
||||||
|
|
||||||
static const CAmount amountZero = 0;
|
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, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), checker(txTo, nIn, amountZero) {}
|
|
||||||
|
|
||||||
bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode) const
|
bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode) const
|
||||||
{
|
{
|
||||||
@ -24,7 +23,7 @@ bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig,
|
|||||||
if (!keystore->GetKey(address, key))
|
if (!keystore->GetKey(address, key))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType);
|
uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, SIGVERSION_BASE);
|
||||||
if (!key.Sign(hash, vchSig))
|
if (!key.Sign(hash, vchSig))
|
||||||
return false;
|
return false;
|
||||||
vchSig.push_back((unsigned char)nHashType);
|
vchSig.push_back((unsigned char)nHashType);
|
||||||
@ -183,7 +182,7 @@ static CScript CombineMultisig(const CScript& scriptPubKey, const BaseSignatureC
|
|||||||
if (sigs.count(pubkey))
|
if (sigs.count(pubkey))
|
||||||
continue; // Already got a sig for this pubkey
|
continue; // Already got a sig for this pubkey
|
||||||
|
|
||||||
if (checker.CheckSig(sig, pubkey, scriptPubKey))
|
if (checker.CheckSig(sig, pubkey, scriptPubKey, SIGVERSION_BASE))
|
||||||
{
|
{
|
||||||
sigs[pubkey] = sig;
|
sigs[pubkey] = sig;
|
||||||
break;
|
break;
|
||||||
@ -253,10 +252,10 @@ static CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatur
|
|||||||
return CScript();
|
return CScript();
|
||||||
}
|
}
|
||||||
|
|
||||||
CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
|
CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CAmount& amount,
|
||||||
const CScript& scriptSig1, const CScript& scriptSig2)
|
const CScript& scriptSig1, const CScript& scriptSig2)
|
||||||
{
|
{
|
||||||
TransactionSignatureChecker checker(&txTo, nIn);
|
TransactionSignatureChecker checker(&txTo, nIn, amount);
|
||||||
return CombineSignatures(scriptPubKey, checker, scriptSig1, scriptSig2);
|
return CombineSignatures(scriptPubKey, checker, scriptSig1, scriptSig2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,9 +267,9 @@ CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecke
|
|||||||
Solver(scriptPubKey, txType, vSolutions);
|
Solver(scriptPubKey, txType, vSolutions);
|
||||||
|
|
||||||
std::vector<valtype> stack1;
|
std::vector<valtype> stack1;
|
||||||
EvalScript(stack1, scriptSig1, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker());
|
EvalScript(stack1, scriptSig1, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SIGVERSION_BASE);
|
||||||
std::vector<valtype> stack2;
|
std::vector<valtype> stack2;
|
||||||
EvalScript(stack2, scriptSig2, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker());
|
EvalScript(stack2, scriptSig2, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SIGVERSION_BASE);
|
||||||
|
|
||||||
return CombineSignatures(scriptPubKey, checker, txType, vSolutions, stack1, stack2);
|
return CombineSignatures(scriptPubKey, checker, txType, vSolutions, stack1, stack2);
|
||||||
}
|
}
|
||||||
@ -282,7 +281,7 @@ class DummySignatureChecker : public BaseSignatureChecker
|
|||||||
public:
|
public:
|
||||||
DummySignatureChecker() {}
|
DummySignatureChecker() {}
|
||||||
|
|
||||||
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const override
|
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -35,10 +35,11 @@ class TransactionSignatureCreator : public BaseSignatureCreator {
|
|||||||
const CTransaction* txTo;
|
const CTransaction* txTo;
|
||||||
unsigned int nIn;
|
unsigned int nIn;
|
||||||
int nHashType;
|
int nHashType;
|
||||||
|
CAmount amount;
|
||||||
const TransactionSignatureChecker checker;
|
const TransactionSignatureChecker checker;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, int nHashTypeIn=SIGHASH_ALL);
|
TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn=SIGHASH_ALL);
|
||||||
const BaseSignatureChecker& Checker() const override{ return checker; }
|
const BaseSignatureChecker& Checker() const override{ return checker; }
|
||||||
bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode) const override;
|
bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode) const override;
|
||||||
};
|
};
|
||||||
@ -62,6 +63,6 @@ bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutab
|
|||||||
CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, const CScript& scriptSig1, const CScript& scriptSig2);
|
CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, const CScript& scriptSig1, const CScript& scriptSig2);
|
||||||
|
|
||||||
/** Combine two script signatures on transactions. */
|
/** Combine two script signatures on transactions. */
|
||||||
CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CScript& scriptSig1, const CScript& scriptSig2);
|
CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CAmount& amount, const CScript& scriptSig1, const CScript& scriptSig2);
|
||||||
|
|
||||||
#endif // BITCOIN_SCRIPT_SIGN_H
|
#endif // BITCOIN_SCRIPT_SIGN_H
|
||||||
|
@ -23,7 +23,7 @@ BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup)
|
|||||||
CScript
|
CScript
|
||||||
sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transaction, int whichIn)
|
sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transaction, int whichIn)
|
||||||
{
|
{
|
||||||
uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL);
|
uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL, 0, SIGVERSION_BASE);
|
||||||
|
|
||||||
CScript result;
|
CScript result;
|
||||||
result << OP_0; // CHECKMULTISIG bug workaround
|
result << OP_0; // CHECKMULTISIG bug workaround
|
||||||
|
@ -308,7 +308,7 @@ public:
|
|||||||
|
|
||||||
TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32)
|
TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32)
|
||||||
{
|
{
|
||||||
uint256 hash = SignatureHash(scriptPubKey, spendTx, 0, nHashType);
|
uint256 hash = SignatureHash(scriptPubKey, spendTx, 0, nHashType, 0, SIGVERSION_BASE);
|
||||||
std::vector<unsigned char> vchSig, r, s;
|
std::vector<unsigned char> vchSig, r, s;
|
||||||
uint32_t iter = 0;
|
uint32_t iter = 0;
|
||||||
do {
|
do {
|
||||||
@ -735,21 +735,21 @@ BOOST_AUTO_TEST_CASE(script_PushData)
|
|||||||
|
|
||||||
ScriptError err;
|
ScriptError err;
|
||||||
std::vector<std::vector<unsigned char> > directStack;
|
std::vector<std::vector<unsigned char> > directStack;
|
||||||
BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err));
|
BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||||
|
|
||||||
std::vector<std::vector<unsigned char> > pushdata1Stack;
|
std::vector<std::vector<unsigned char> > pushdata1Stack;
|
||||||
BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err));
|
BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err));
|
||||||
BOOST_CHECK(pushdata1Stack == directStack);
|
BOOST_CHECK(pushdata1Stack == directStack);
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||||
|
|
||||||
std::vector<std::vector<unsigned char> > pushdata2Stack;
|
std::vector<std::vector<unsigned char> > pushdata2Stack;
|
||||||
BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err));
|
BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err));
|
||||||
BOOST_CHECK(pushdata2Stack == directStack);
|
BOOST_CHECK(pushdata2Stack == directStack);
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||||
|
|
||||||
std::vector<std::vector<unsigned char> > pushdata4Stack;
|
std::vector<std::vector<unsigned char> > pushdata4Stack;
|
||||||
BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err));
|
BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err));
|
||||||
BOOST_CHECK(pushdata4Stack == directStack);
|
BOOST_CHECK(pushdata4Stack == directStack);
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||||
}
|
}
|
||||||
@ -757,7 +757,7 @@ BOOST_AUTO_TEST_CASE(script_PushData)
|
|||||||
CScript
|
CScript
|
||||||
sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transaction)
|
sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transaction)
|
||||||
{
|
{
|
||||||
uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL);
|
uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL, 0, SIGVERSION_BASE);
|
||||||
|
|
||||||
CScript result;
|
CScript result;
|
||||||
//
|
//
|
||||||
@ -888,6 +888,7 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
|
|||||||
BOOST_AUTO_TEST_CASE(script_combineSigs)
|
BOOST_AUTO_TEST_CASE(script_combineSigs)
|
||||||
{
|
{
|
||||||
// Test the CombineSignatures function
|
// Test the CombineSignatures function
|
||||||
|
CAmount amount;
|
||||||
CBasicKeyStore keystore;
|
CBasicKeyStore keystore;
|
||||||
std::vector<CKey> keys;
|
std::vector<CKey> keys;
|
||||||
std::vector<CPubKey> pubkeys;
|
std::vector<CPubKey> pubkeys;
|
||||||
@ -906,19 +907,19 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
|
|||||||
CScript& scriptSig = txTo.vin[0].scriptSig;
|
CScript& scriptSig = txTo.vin[0].scriptSig;
|
||||||
|
|
||||||
CScript empty;
|
CScript empty;
|
||||||
CScript combined = CombineSignatures(scriptPubKey, txTo, 0, empty, empty);
|
CScript combined = CombineSignatures(scriptPubKey, txTo, 0, amount, empty, empty);
|
||||||
BOOST_CHECK(combined.empty());
|
BOOST_CHECK(combined.empty());
|
||||||
|
|
||||||
// Single signature case:
|
// Single signature case:
|
||||||
SignSignature(keystore, txFrom, txTo, 0); // changes scriptSig
|
SignSignature(keystore, txFrom, txTo, 0); // changes scriptSig
|
||||||
combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty);
|
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSig, empty);
|
||||||
BOOST_CHECK(combined == scriptSig);
|
BOOST_CHECK(combined == scriptSig);
|
||||||
combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig);
|
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, empty, scriptSig);
|
||||||
BOOST_CHECK(combined == scriptSig);
|
BOOST_CHECK(combined == scriptSig);
|
||||||
CScript scriptSigCopy = scriptSig;
|
CScript scriptSigCopy = scriptSig;
|
||||||
// Signing again will give a different, valid signature:
|
// Signing again will give a different, valid signature:
|
||||||
SignSignature(keystore, txFrom, txTo, 0);
|
SignSignature(keystore, txFrom, txTo, 0);
|
||||||
combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig);
|
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSigCopy, scriptSig);
|
||||||
BOOST_CHECK(combined == scriptSigCopy || combined == scriptSig);
|
BOOST_CHECK(combined == scriptSigCopy || combined == scriptSig);
|
||||||
|
|
||||||
// P2SH, single-signature case:
|
// P2SH, single-signature case:
|
||||||
@ -926,41 +927,41 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
|
|||||||
keystore.AddCScript(pkSingle);
|
keystore.AddCScript(pkSingle);
|
||||||
scriptPubKey = GetScriptForDestination(CScriptID(pkSingle));
|
scriptPubKey = GetScriptForDestination(CScriptID(pkSingle));
|
||||||
SignSignature(keystore, txFrom, txTo, 0);
|
SignSignature(keystore, txFrom, txTo, 0);
|
||||||
combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty);
|
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSig, empty);
|
||||||
BOOST_CHECK(combined == scriptSig);
|
BOOST_CHECK(combined == scriptSig);
|
||||||
combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig);
|
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, empty, scriptSig);
|
||||||
BOOST_CHECK(combined == scriptSig);
|
BOOST_CHECK(combined == scriptSig);
|
||||||
scriptSigCopy = scriptSig;
|
scriptSigCopy = scriptSig;
|
||||||
SignSignature(keystore, txFrom, txTo, 0);
|
SignSignature(keystore, txFrom, txTo, 0);
|
||||||
combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig);
|
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSigCopy, scriptSig);
|
||||||
BOOST_CHECK(combined == scriptSigCopy || combined == scriptSig);
|
BOOST_CHECK(combined == scriptSigCopy || combined == scriptSig);
|
||||||
// dummy scriptSigCopy with placeholder, should always choose non-placeholder:
|
// dummy scriptSigCopy with placeholder, should always choose non-placeholder:
|
||||||
scriptSigCopy = CScript() << OP_0 << std::vector<unsigned char>(pkSingle.begin(), pkSingle.end());
|
scriptSigCopy = CScript() << OP_0 << std::vector<unsigned char>(pkSingle.begin(), pkSingle.end());
|
||||||
combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig);
|
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSigCopy, scriptSig);
|
||||||
BOOST_CHECK(combined == scriptSig);
|
BOOST_CHECK(combined == scriptSig);
|
||||||
combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, scriptSigCopy);
|
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSig, scriptSigCopy);
|
||||||
BOOST_CHECK(combined == scriptSig);
|
BOOST_CHECK(combined == scriptSig);
|
||||||
|
|
||||||
// Hardest case: Multisig 2-of-3
|
// Hardest case: Multisig 2-of-3
|
||||||
scriptPubKey = GetScriptForMultisig(2, pubkeys);
|
scriptPubKey = GetScriptForMultisig(2, pubkeys);
|
||||||
keystore.AddCScript(scriptPubKey);
|
keystore.AddCScript(scriptPubKey);
|
||||||
SignSignature(keystore, txFrom, txTo, 0);
|
SignSignature(keystore, txFrom, txTo, 0);
|
||||||
combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty);
|
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSig, empty);
|
||||||
BOOST_CHECK(combined == scriptSig);
|
BOOST_CHECK(combined == scriptSig);
|
||||||
combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig);
|
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, empty, scriptSig);
|
||||||
BOOST_CHECK(combined == scriptSig);
|
BOOST_CHECK(combined == scriptSig);
|
||||||
|
|
||||||
// A couple of partially-signed versions:
|
// A couple of partially-signed versions:
|
||||||
std::vector<unsigned char> sig1;
|
std::vector<unsigned char> sig1;
|
||||||
uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL);
|
uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL, 0, SIGVERSION_BASE);
|
||||||
BOOST_CHECK(keys[0].Sign(hash1, sig1));
|
BOOST_CHECK(keys[0].Sign(hash1, sig1));
|
||||||
sig1.push_back(SIGHASH_ALL);
|
sig1.push_back(SIGHASH_ALL);
|
||||||
std::vector<unsigned char> sig2;
|
std::vector<unsigned char> sig2;
|
||||||
uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE);
|
uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE, 0, SIGVERSION_BASE);
|
||||||
BOOST_CHECK(keys[1].Sign(hash2, sig2));
|
BOOST_CHECK(keys[1].Sign(hash2, sig2));
|
||||||
sig2.push_back(SIGHASH_NONE);
|
sig2.push_back(SIGHASH_NONE);
|
||||||
std::vector<unsigned char> sig3;
|
std::vector<unsigned char> sig3;
|
||||||
uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE);
|
uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE, 0, SIGVERSION_BASE);
|
||||||
BOOST_CHECK(keys[2].Sign(hash3, sig3));
|
BOOST_CHECK(keys[2].Sign(hash3, sig3));
|
||||||
sig3.push_back(SIGHASH_SINGLE);
|
sig3.push_back(SIGHASH_SINGLE);
|
||||||
|
|
||||||
@ -976,21 +977,21 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
|
|||||||
CScript complete13 = CScript() << OP_0 << sig1 << sig3;
|
CScript complete13 = CScript() << OP_0 << sig1 << sig3;
|
||||||
CScript complete23 = CScript() << OP_0 << sig2 << sig3;
|
CScript complete23 = CScript() << OP_0 << sig2 << sig3;
|
||||||
|
|
||||||
combined = CombineSignatures(scriptPubKey, txTo, 0, partial1a, partial1b);
|
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial1a, partial1b);
|
||||||
BOOST_CHECK(combined == partial1a);
|
BOOST_CHECK(combined == partial1a);
|
||||||
combined = CombineSignatures(scriptPubKey, txTo, 0, partial1a, partial2a);
|
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial1a, partial2a);
|
||||||
BOOST_CHECK(combined == complete12);
|
BOOST_CHECK(combined == complete12);
|
||||||
combined = CombineSignatures(scriptPubKey, txTo, 0, partial2a, partial1a);
|
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial2a, partial1a);
|
||||||
BOOST_CHECK(combined == complete12);
|
BOOST_CHECK(combined == complete12);
|
||||||
combined = CombineSignatures(scriptPubKey, txTo, 0, partial1b, partial2b);
|
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial1b, partial2b);
|
||||||
BOOST_CHECK(combined == complete12);
|
BOOST_CHECK(combined == complete12);
|
||||||
combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial1b);
|
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial3b, partial1b);
|
||||||
BOOST_CHECK(combined == complete13);
|
BOOST_CHECK(combined == complete13);
|
||||||
combined = CombineSignatures(scriptPubKey, txTo, 0, partial2a, partial3a);
|
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial2a, partial3a);
|
||||||
BOOST_CHECK(combined == complete23);
|
BOOST_CHECK(combined == complete23);
|
||||||
combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial2b);
|
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial3b, partial2b);
|
||||||
BOOST_CHECK(combined == complete23);
|
BOOST_CHECK(combined == complete23);
|
||||||
combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial3a);
|
combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial3b, partial3a);
|
||||||
BOOST_CHECK(combined == partial3c);
|
BOOST_CHECK(combined == partial3c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ BOOST_AUTO_TEST_CASE(sighash_test)
|
|||||||
|
|
||||||
uint256 sh, sho;
|
uint256 sh, sho;
|
||||||
sho = SignatureHashOld(scriptCode, txTo, nIn, nHashType);
|
sho = SignatureHashOld(scriptCode, txTo, nIn, nHashType);
|
||||||
sh = SignatureHash(scriptCode, txTo, nIn, nHashType);
|
sh = SignatureHash(scriptCode, txTo, nIn, nHashType, 0, SIGVERSION_BASE);
|
||||||
#if defined(PRINT_SIGHASH_JSON)
|
#if defined(PRINT_SIGHASH_JSON)
|
||||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
ss << txTo;
|
ss << txTo;
|
||||||
@ -206,7 +206,7 @@ BOOST_AUTO_TEST_CASE(sighash_from_data)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
sh = SignatureHash(scriptCode, *tx, nIn, nHashType);
|
sh = SignatureHash(scriptCode, *tx, nIn, nHashType, 0, SIGVERSION_BASE);
|
||||||
BOOST_CHECK_MESSAGE(sh.GetHex() == sigHashHex, strTest);
|
BOOST_CHECK_MESSAGE(sh.GetHex() == sigHashHex, strTest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
|
|||||||
|
|
||||||
// Sign:
|
// Sign:
|
||||||
std::vector<unsigned char> vchSig;
|
std::vector<unsigned char> vchSig;
|
||||||
uint256 hash = SignatureHash(scriptPubKey, spends[i], 0, SIGHASH_ALL);
|
uint256 hash = SignatureHash(scriptPubKey, spends[i], 0, SIGHASH_ALL, 0, SIGVERSION_BASE);
|
||||||
BOOST_CHECK(coinbaseKey.Sign(hash, vchSig));
|
BOOST_CHECK(coinbaseKey.Sign(hash, vchSig));
|
||||||
vchSig.push_back((unsigned char)SIGHASH_ALL);
|
vchSig.push_back((unsigned char)SIGHASH_ALL);
|
||||||
spends[i].vin[0].scriptSig << vchSig;
|
spends[i].vin[0].scriptSig << vchSig;
|
||||||
|
Loading…
Reference in New Issue
Block a user