Add consensus branch ID parameter to SignatureHash, remove SigVersion parameter
We do not need to be able to calculate multiple SignatureHash versions for a single transaction format; instead, we use the transaction format to determine the SigVersion. The consensus branch ID *does* need to be passed in from the outside, as only the caller knows the context in which the SignatureHash is being calculated (ie. mempool acceptance vs. block validation). JoinSplit signature verification has been moved into ContextualCheckTransaction, where the consensus branch ID can be obtained. The argument to the sign command for zcash-tx has been modified to take a height in addition to the optional sigtype flags.
This commit is contained in:
@@ -19,7 +19,7 @@ typedef vector<unsigned char> valtype;
|
||||
|
||||
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) {}
|
||||
|
||||
bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, SigVersion sigversion) const
|
||||
bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, uint32_t consensusBranchId) const
|
||||
{
|
||||
CKey key;
|
||||
if (!keystore->GetKey(address, key))
|
||||
@@ -27,7 +27,7 @@ bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig,
|
||||
|
||||
uint256 hash;
|
||||
try {
|
||||
hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion);
|
||||
hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, consensusBranchId);
|
||||
} catch (logic_error ex) {
|
||||
return false;
|
||||
}
|
||||
@@ -38,16 +38,16 @@ bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool Sign1(const CKeyID& address, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector<valtype>& ret, SigVersion sigversion)
|
||||
static bool Sign1(const CKeyID& address, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector<valtype>& ret, uint32_t consensusBranchId)
|
||||
{
|
||||
vector<unsigned char> vchSig;
|
||||
if (!creator.CreateSig(vchSig, address, scriptCode, sigversion))
|
||||
if (!creator.CreateSig(vchSig, address, scriptCode, consensusBranchId))
|
||||
return false;
|
||||
ret.push_back(vchSig);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool SignN(const vector<valtype>& multisigdata, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector<valtype>& ret, SigVersion sigversion)
|
||||
static bool SignN(const vector<valtype>& multisigdata, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector<valtype>& ret, uint32_t consensusBranchId)
|
||||
{
|
||||
int nSigned = 0;
|
||||
int nRequired = multisigdata.front()[0];
|
||||
@@ -55,7 +55,7 @@ static bool SignN(const vector<valtype>& multisigdata, const BaseSignatureCreato
|
||||
{
|
||||
const valtype& pubkey = multisigdata[i];
|
||||
CKeyID keyID = CPubKey(pubkey).GetID();
|
||||
if (Sign1(keyID, creator, scriptCode, ret, sigversion))
|
||||
if (Sign1(keyID, creator, scriptCode, ret, consensusBranchId))
|
||||
++nSigned;
|
||||
}
|
||||
return nSigned==nRequired;
|
||||
@@ -68,7 +68,7 @@ static bool SignN(const vector<valtype>& multisigdata, const BaseSignatureCreato
|
||||
* Returns false if scriptPubKey could not be completely satisfied.
|
||||
*/
|
||||
static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptPubKey,
|
||||
std::vector<valtype>& ret, txnouttype& whichTypeRet, SigVersion sigversion)
|
||||
std::vector<valtype>& ret, txnouttype& whichTypeRet, uint32_t consensusBranchId)
|
||||
{
|
||||
CScript scriptRet;
|
||||
uint160 h160;
|
||||
@@ -86,10 +86,10 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP
|
||||
return false;
|
||||
case TX_PUBKEY:
|
||||
keyID = CPubKey(vSolutions[0]).GetID();
|
||||
return Sign1(keyID, creator, scriptPubKey, ret, sigversion);
|
||||
return Sign1(keyID, creator, scriptPubKey, ret, consensusBranchId);
|
||||
case TX_PUBKEYHASH:
|
||||
keyID = CKeyID(uint160(vSolutions[0]));
|
||||
if (!Sign1(keyID, creator, scriptPubKey, ret, sigversion))
|
||||
if (!Sign1(keyID, creator, scriptPubKey, ret, consensusBranchId))
|
||||
return false;
|
||||
else
|
||||
{
|
||||
@@ -107,7 +107,7 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP
|
||||
|
||||
case TX_MULTISIG:
|
||||
ret.push_back(valtype()); // workaround CHECKMULTISIG bug
|
||||
return (SignN(vSolutions, creator, scriptPubKey, ret, sigversion));
|
||||
return (SignN(vSolutions, creator, scriptPubKey, ret, consensusBranchId));
|
||||
|
||||
default:
|
||||
return false;
|
||||
@@ -129,13 +129,13 @@ static CScript PushAll(const vector<valtype>& values)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPubKey, SignatureData& sigdata)
|
||||
bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPubKey, SignatureData& sigdata, uint32_t consensusBranchId)
|
||||
{
|
||||
CScript script = fromPubKey;
|
||||
bool solved = true;
|
||||
std::vector<valtype> result;
|
||||
txnouttype whichType;
|
||||
solved = SignStep(creator, script, result, whichType, SIGVERSION_BASE);
|
||||
solved = SignStep(creator, script, result, whichType, consensusBranchId);
|
||||
CScript subscript;
|
||||
|
||||
if (solved && whichType == TX_SCRIPTHASH)
|
||||
@@ -144,14 +144,14 @@ bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPu
|
||||
// the final scriptSig is the signatures from that
|
||||
// and then the serialized subscript:
|
||||
script = subscript = CScript(result[0].begin(), result[0].end());
|
||||
solved = solved && SignStep(creator, script, result, whichType, SIGVERSION_BASE) && whichType != TX_SCRIPTHASH;
|
||||
solved = solved && SignStep(creator, script, result, whichType, consensusBranchId) && whichType != TX_SCRIPTHASH;
|
||||
result.push_back(std::vector<unsigned char>(subscript.begin(), subscript.end()));
|
||||
}
|
||||
|
||||
sigdata.scriptSig = PushAll(result);
|
||||
|
||||
// Test solution
|
||||
return solved && VerifyScript(sigdata.scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker());
|
||||
return solved && VerifyScript(sigdata.scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker(), consensusBranchId);
|
||||
}
|
||||
|
||||
SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn)
|
||||
@@ -168,7 +168,7 @@ void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const Signatur
|
||||
tx.vin[nIn].scriptSig = data.scriptSig;
|
||||
}
|
||||
|
||||
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType)
|
||||
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType, uint32_t consensusBranchId)
|
||||
{
|
||||
assert(nIn < txTo.vin.size());
|
||||
|
||||
@@ -176,24 +176,24 @@ bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutabl
|
||||
TransactionSignatureCreator creator(&keystore, &txToConst, nIn, amount, nHashType);
|
||||
|
||||
SignatureData sigdata;
|
||||
bool ret = ProduceSignature(creator, fromPubKey, sigdata);
|
||||
bool ret = ProduceSignature(creator, fromPubKey, sigdata, consensusBranchId);
|
||||
UpdateTransaction(txTo, nIn, sigdata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
|
||||
bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType, uint32_t consensusBranchId)
|
||||
{
|
||||
assert(nIn < txTo.vin.size());
|
||||
CTxIn& txin = txTo.vin[nIn];
|
||||
assert(txin.prevout.n < txFrom.vout.size());
|
||||
const CTxOut& txout = txFrom.vout[txin.prevout.n];
|
||||
|
||||
return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType);
|
||||
return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType, consensusBranchId);
|
||||
}
|
||||
|
||||
static vector<valtype> CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
|
||||
const vector<valtype>& vSolutions,
|
||||
const vector<valtype>& sigs1, const vector<valtype>& sigs2, SigVersion sigversion)
|
||||
const vector<valtype>& sigs1, const vector<valtype>& sigs2, uint32_t consensusBranchId)
|
||||
{
|
||||
// Combine all the signatures we've got:
|
||||
set<valtype> allsigs;
|
||||
@@ -221,7 +221,7 @@ static vector<valtype> CombineMultisig(const CScript& scriptPubKey, const BaseSi
|
||||
if (sigs.count(pubkey))
|
||||
continue; // Already got a sig for this pubkey
|
||||
|
||||
if (checker.CheckSig(sig, pubkey, scriptPubKey, sigversion))
|
||||
if (checker.CheckSig(sig, pubkey, scriptPubKey, consensusBranchId))
|
||||
{
|
||||
sigs[pubkey] = sig;
|
||||
break;
|
||||
@@ -254,8 +254,8 @@ struct Stacks
|
||||
|
||||
Stacks() {}
|
||||
explicit Stacks(const std::vector<valtype>& scriptSigStack_) : script(scriptSigStack_) {}
|
||||
explicit Stacks(const SignatureData& data) {
|
||||
EvalScript(script, data.scriptSig, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SIGVERSION_BASE);
|
||||
explicit Stacks(const SignatureData& data, uint32_t consensusBranchId) {
|
||||
EvalScript(script, data.scriptSig, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), consensusBranchId);
|
||||
}
|
||||
|
||||
SignatureData Output() const {
|
||||
@@ -268,7 +268,7 @@ struct Stacks
|
||||
|
||||
static Stacks CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
|
||||
const txnouttype txType, const vector<valtype>& vSolutions,
|
||||
Stacks sigs1, Stacks sigs2, SigVersion sigversion)
|
||||
Stacks sigs1, Stacks sigs2, uint32_t consensusBranchId)
|
||||
{
|
||||
switch (txType)
|
||||
{
|
||||
@@ -300,25 +300,26 @@ static Stacks CombineSignatures(const CScript& scriptPubKey, const BaseSignature
|
||||
Solver(pubKey2, txType2, vSolutions2);
|
||||
sigs1.script.pop_back();
|
||||
sigs2.script.pop_back();
|
||||
Stacks result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2, sigversion);
|
||||
Stacks result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2, consensusBranchId);
|
||||
result.script.push_back(spk);
|
||||
return result;
|
||||
}
|
||||
case TX_MULTISIG:
|
||||
return Stacks(CombineMultisig(scriptPubKey, checker, vSolutions, sigs1.script, sigs2.script, sigversion));
|
||||
return Stacks(CombineMultisig(scriptPubKey, checker, vSolutions, sigs1.script, sigs2.script, consensusBranchId));
|
||||
default:
|
||||
return Stacks();
|
||||
}
|
||||
}
|
||||
|
||||
SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
|
||||
const SignatureData& scriptSig1, const SignatureData& scriptSig2)
|
||||
const SignatureData& scriptSig1, const SignatureData& scriptSig2,
|
||||
uint32_t consensusBranchId)
|
||||
{
|
||||
txnouttype txType;
|
||||
vector<vector<unsigned char> > vSolutions;
|
||||
Solver(scriptPubKey, txType, vSolutions);
|
||||
|
||||
return CombineSignatures(scriptPubKey, checker, txType, vSolutions, Stacks(scriptSig1), Stacks(scriptSig2), SIGVERSION_BASE).Output();
|
||||
return CombineSignatures(scriptPubKey, checker, txType, vSolutions, Stacks(scriptSig1, consensusBranchId), Stacks(scriptSig2, consensusBranchId), consensusBranchId).Output();
|
||||
}
|
||||
|
||||
namespace {
|
||||
@@ -328,7 +329,7 @@ class DummySignatureChecker : public BaseSignatureChecker
|
||||
public:
|
||||
DummySignatureChecker() {}
|
||||
|
||||
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
|
||||
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, uint32_t consensusBranchId) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -341,7 +342,7 @@ const BaseSignatureChecker& DummySignatureCreator::Checker() const
|
||||
return dummyChecker;
|
||||
}
|
||||
|
||||
bool DummySignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const
|
||||
bool DummySignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, uint32_t consensusBranchId) const
|
||||
{
|
||||
// Create a dummy signature that is a valid DER-encoding
|
||||
vchSig.assign(72, '\000');
|
||||
|
||||
Reference in New Issue
Block a user