|
|
@ -17,22 +17,31 @@ using namespace std; |
|
|
|
|
|
|
|
|
|
|
|
typedef vector<unsigned char> valtype; |
|
|
|
typedef vector<unsigned char> valtype; |
|
|
|
|
|
|
|
|
|
|
|
bool Sign1(const CKeyID& address, const CKeyStore& keystore, uint256 hash, int nHashType, CScript& scriptSigRet) |
|
|
|
TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), checker(txTo, nIn) {} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode) const |
|
|
|
{ |
|
|
|
{ |
|
|
|
CKey key; |
|
|
|
CKey key; |
|
|
|
if (!keystore.GetKey(address, key)) |
|
|
|
if (!keystore->GetKey(address, key)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
vector<unsigned char> vchSig; |
|
|
|
uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType); |
|
|
|
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); |
|
|
|
scriptSigRet << vchSig; |
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bool Sign1(const CKeyID& address, const BaseSignatureCreator& creator, const CScript& scriptCode, CScript& scriptSigRet) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
vector<unsigned char> vchSig; |
|
|
|
|
|
|
|
if (!creator.CreateSig(vchSig, address, scriptCode)) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
scriptSigRet << vchSig; |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool SignN(const vector<valtype>& multisigdata, const CKeyStore& keystore, uint256 hash, int nHashType, CScript& scriptSigRet) |
|
|
|
static bool SignN(const vector<valtype>& multisigdata, const BaseSignatureCreator& creator, const CScript& scriptCode, CScript& scriptSigRet) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int nSigned = 0; |
|
|
|
int nSigned = 0; |
|
|
|
int nRequired = multisigdata.front()[0]; |
|
|
|
int nRequired = multisigdata.front()[0]; |
|
|
@ -40,19 +49,19 @@ bool SignN(const vector<valtype>& multisigdata, const CKeyStore& keystore, uint2 |
|
|
|
{ |
|
|
|
{ |
|
|
|
const valtype& pubkey = multisigdata[i]; |
|
|
|
const valtype& pubkey = multisigdata[i]; |
|
|
|
CKeyID keyID = CPubKey(pubkey).GetID(); |
|
|
|
CKeyID keyID = CPubKey(pubkey).GetID(); |
|
|
|
if (Sign1(keyID, keystore, hash, nHashType, scriptSigRet)) |
|
|
|
if (Sign1(keyID, creator, scriptCode, scriptSigRet)) |
|
|
|
++nSigned; |
|
|
|
++nSigned; |
|
|
|
} |
|
|
|
} |
|
|
|
return nSigned==nRequired; |
|
|
|
return nSigned==nRequired; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Sign scriptPubKey with private keys stored in keystore, given transaction hash and hash type. |
|
|
|
* Sign scriptPubKey using signature made with creator. |
|
|
|
* Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed), |
|
|
|
* Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed), |
|
|
|
* unless whichTypeRet is TX_SCRIPTHASH, in which case scriptSigRet is the redemption script. |
|
|
|
* unless whichTypeRet is TX_SCRIPTHASH, in which case scriptSigRet is the redemption script. |
|
|
|
* Returns false if scriptPubKey could not be completely satisfied. |
|
|
|
* Returns false if scriptPubKey could not be completely satisfied. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash, int nHashType, |
|
|
|
static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptPubKey, |
|
|
|
CScript& scriptSigRet, txnouttype& whichTypeRet) |
|
|
|
CScript& scriptSigRet, txnouttype& whichTypeRet) |
|
|
|
{ |
|
|
|
{ |
|
|
|
scriptSigRet.clear(); |
|
|
|
scriptSigRet.clear(); |
|
|
@ -69,39 +78,32 @@ bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
case TX_PUBKEY: |
|
|
|
case TX_PUBKEY: |
|
|
|
keyID = CPubKey(vSolutions[0]).GetID(); |
|
|
|
keyID = CPubKey(vSolutions[0]).GetID(); |
|
|
|
return Sign1(keyID, keystore, hash, nHashType, scriptSigRet); |
|
|
|
return Sign1(keyID, creator, scriptPubKey, scriptSigRet); |
|
|
|
case TX_PUBKEYHASH: |
|
|
|
case TX_PUBKEYHASH: |
|
|
|
keyID = CKeyID(uint160(vSolutions[0])); |
|
|
|
keyID = CKeyID(uint160(vSolutions[0])); |
|
|
|
if (!Sign1(keyID, keystore, hash, nHashType, scriptSigRet)) |
|
|
|
if (!Sign1(keyID, creator, scriptPubKey, scriptSigRet)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
CPubKey vch; |
|
|
|
CPubKey vch; |
|
|
|
keystore.GetPubKey(keyID, vch); |
|
|
|
creator.KeyStore().GetPubKey(keyID, vch); |
|
|
|
scriptSigRet << ToByteVector(vch); |
|
|
|
scriptSigRet << ToByteVector(vch); |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
case TX_SCRIPTHASH: |
|
|
|
case TX_SCRIPTHASH: |
|
|
|
return keystore.GetCScript(uint160(vSolutions[0]), scriptSigRet); |
|
|
|
return creator.KeyStore().GetCScript(uint160(vSolutions[0]), scriptSigRet); |
|
|
|
|
|
|
|
|
|
|
|
case TX_MULTISIG: |
|
|
|
case TX_MULTISIG: |
|
|
|
scriptSigRet << OP_0; // workaround CHECKMULTISIG bug
|
|
|
|
scriptSigRet << OP_0; // workaround CHECKMULTISIG bug
|
|
|
|
return (SignN(vSolutions, keystore, hash, nHashType, scriptSigRet)); |
|
|
|
return (SignN(vSolutions, creator, scriptPubKey, scriptSigRet)); |
|
|
|
} |
|
|
|
} |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType) |
|
|
|
bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPubKey, CScript& scriptSig) |
|
|
|
{ |
|
|
|
{ |
|
|
|
assert(nIn < txTo.vin.size()); |
|
|
|
|
|
|
|
CTxIn& txin = txTo.vin[nIn]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Leave out the signature from the hash, since a signature can't sign itself.
|
|
|
|
|
|
|
|
// The checksig op will also drop the signatures from its hash.
|
|
|
|
|
|
|
|
uint256 hash = SignatureHash(fromPubKey, txTo, nIn, nHashType); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
txnouttype whichType; |
|
|
|
txnouttype whichType; |
|
|
|
if (!Solver(keystore, fromPubKey, hash, nHashType, txin.scriptSig, whichType)) |
|
|
|
if (!SignStep(creator, fromPubKey, scriptSig, whichType)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
if (whichType == TX_SCRIPTHASH) |
|
|
|
if (whichType == TX_SCRIPTHASH) |
|
|
@ -109,21 +111,29 @@ bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutabl |
|
|
|
// Solver returns the subscript that need to be evaluated;
|
|
|
|
// Solver returns the subscript that need to be evaluated;
|
|
|
|
// the final scriptSig is the signatures from that
|
|
|
|
// the final scriptSig is the signatures from that
|
|
|
|
// and then the serialized subscript:
|
|
|
|
// and then the serialized subscript:
|
|
|
|
CScript subscript = txin.scriptSig; |
|
|
|
CScript subscript = scriptSig; |
|
|
|
|
|
|
|
|
|
|
|
// Recompute txn hash using subscript in place of scriptPubKey:
|
|
|
|
|
|
|
|
uint256 hash2 = SignatureHash(subscript, txTo, nIn, nHashType); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
txnouttype subType; |
|
|
|
txnouttype subType; |
|
|
|
bool fSolved = |
|
|
|
bool fSolved = |
|
|
|
Solver(keystore, subscript, hash2, nHashType, txin.scriptSig, subType) && subType != TX_SCRIPTHASH; |
|
|
|
SignStep(creator, subscript, scriptSig, subType) && subType != TX_SCRIPTHASH; |
|
|
|
// Append serialized subscript whether or not it is completely signed:
|
|
|
|
// Append serialized subscript whether or not it is completely signed:
|
|
|
|
txin.scriptSig << static_cast<valtype>(subscript); |
|
|
|
scriptSig << static_cast<valtype>(subscript); |
|
|
|
if (!fSolved) return false; |
|
|
|
if (!fSolved) return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Test solution
|
|
|
|
// Test solution
|
|
|
|
return VerifyScript(txin.scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&txTo, nIn)); |
|
|
|
return VerifyScript(scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
assert(nIn < txTo.vin.size()); |
|
|
|
|
|
|
|
CTxIn& txin = txTo.vin[nIn]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CTransaction txToConst(txTo); |
|
|
|
|
|
|
|
TransactionSignatureCreator creator(&keystore, &txToConst, nIn, nHashType); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ProduceSignature(creator, fromPubKey, txin.scriptSig); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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) |
|
|
@ -144,7 +154,7 @@ static CScript PushAll(const vector<valtype>& values) |
|
|
|
return result; |
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static CScript CombineMultisig(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, |
|
|
|
static CScript CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker, |
|
|
|
const vector<valtype>& vSolutions, |
|
|
|
const vector<valtype>& vSolutions, |
|
|
|
const vector<valtype>& sigs1, const vector<valtype>& sigs2) |
|
|
|
const vector<valtype>& sigs1, const vector<valtype>& sigs2) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -174,7 +184,7 @@ static CScript CombineMultisig(const CScript& scriptPubKey, const CTransaction& |
|
|
|
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 (TransactionSignatureChecker(&txTo, nIn).CheckSig(sig, pubkey, scriptPubKey)) |
|
|
|
if (checker.CheckSig(sig, pubkey, scriptPubKey)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
sigs[pubkey] = sig; |
|
|
|
sigs[pubkey] = sig; |
|
|
|
break; |
|
|
|
break; |
|
|
@ -199,7 +209,7 @@ static CScript CombineMultisig(const CScript& scriptPubKey, const CTransaction& |
|
|
|
return result; |
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, |
|
|
|
static CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, |
|
|
|
const txnouttype txType, const vector<valtype>& vSolutions, |
|
|
|
const txnouttype txType, const vector<valtype>& vSolutions, |
|
|
|
vector<valtype>& sigs1, vector<valtype>& sigs2) |
|
|
|
vector<valtype>& sigs1, vector<valtype>& sigs2) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -233,12 +243,12 @@ static CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction |
|
|
|
Solver(pubKey2, txType2, vSolutions2); |
|
|
|
Solver(pubKey2, txType2, vSolutions2); |
|
|
|
sigs1.pop_back(); |
|
|
|
sigs1.pop_back(); |
|
|
|
sigs2.pop_back(); |
|
|
|
sigs2.pop_back(); |
|
|
|
CScript result = CombineSignatures(pubKey2, txTo, nIn, txType2, vSolutions2, sigs1, sigs2); |
|
|
|
CScript result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2); |
|
|
|
result << spk; |
|
|
|
result << spk; |
|
|
|
return result; |
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
case TX_MULTISIG: |
|
|
|
case TX_MULTISIG: |
|
|
|
return CombineMultisig(scriptPubKey, txTo, nIn, vSolutions, sigs1, sigs2); |
|
|
|
return CombineMultisig(scriptPubKey, checker, vSolutions, sigs1, sigs2); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return CScript(); |
|
|
|
return CScript(); |
|
|
@ -246,6 +256,13 @@ static CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction |
|
|
|
|
|
|
|
|
|
|
|
CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, |
|
|
|
CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, |
|
|
|
const CScript& scriptSig1, const CScript& scriptSig2) |
|
|
|
const CScript& scriptSig1, const CScript& scriptSig2) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
TransactionSignatureChecker checker(&txTo, nIn); |
|
|
|
|
|
|
|
return CombineSignatures(scriptPubKey, checker, scriptSig1, scriptSig2); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, |
|
|
|
|
|
|
|
const CScript& scriptSig1, const CScript& scriptSig2) |
|
|
|
{ |
|
|
|
{ |
|
|
|
txnouttype txType; |
|
|
|
txnouttype txType; |
|
|
|
vector<vector<unsigned char> > vSolutions; |
|
|
|
vector<vector<unsigned char> > vSolutions; |
|
|
@ -256,5 +273,5 @@ CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, |
|
|
|
vector<valtype> stack2; |
|
|
|
vector<valtype> stack2; |
|
|
|
EvalScript(stack2, scriptSig2, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker()); |
|
|
|
EvalScript(stack2, scriptSig2, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker()); |
|
|
|
|
|
|
|
|
|
|
|
return CombineSignatures(scriptPubKey, txTo, nIn, txType, vSolutions, stack1, stack2); |
|
|
|
return CombineSignatures(scriptPubKey, checker, txType, vSolutions, stack1, stack2); |
|
|
|
} |
|
|
|
} |
|
|
|