mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-14 12:43:40 +02:00
Merge a993a7c675 into merged_master (Elements PR #960)
Several conflicts in the C++ code related to the new `flags` parameter to `CheckSignature` and the corresponding function being renamed upstream to `CheckSignatureECDSA`. Several conflicts in the test harness as Steven sorta pulled the new upstream ECKey module into the Python code, and the actual upstream code was slightly different. Also needed to update the feature_taproot code to always use the non-RANGEPROOF sighash since dynafed is not enabled in the Taproot test. Also had to pull the `set_wif` method out of `ECKey` and inline it because otherwise it triggers a "circular inclusion" error between script.py (which would pull in `base58_to_bytes` from address.py) and address.py (which now pulls in some taproot EC related stuff from script.py). Noticed that #960 does not test the "sighash rangeproof flag set but no witnesses" case.
This commit is contained in:
commit
22cf380984
18 changed files with 410 additions and 65 deletions
|
|
@ -20,7 +20,7 @@ typedef std::vector<unsigned char> valtype;
|
|||
|
||||
MutableTransactionSignatureCreator::MutableTransactionSignatureCreator(const CMutableTransaction* txToIn, unsigned int nInIn, const CConfidentialValue& amountIn, int nHashTypeIn) : txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {}
|
||||
|
||||
bool MutableTransactionSignatureCreator::CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, SigVersion sigversion) const
|
||||
bool MutableTransactionSignatureCreator::CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, SigVersion sigversion, unsigned int flags) const
|
||||
{
|
||||
CKey key;
|
||||
if (!provider.GetKey(address, key))
|
||||
|
|
@ -30,7 +30,7 @@ bool MutableTransactionSignatureCreator::CreateSig(const SigningProvider& provid
|
|||
if (sigversion == SigVersion::WITNESS_V0 && !key.IsCompressed())
|
||||
return false;
|
||||
|
||||
uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion);
|
||||
uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion, flags);
|
||||
if (!key.Sign(hash, vchSig))
|
||||
return false;
|
||||
vchSig.push_back((unsigned char)nHashType);
|
||||
|
|
@ -71,7 +71,7 @@ static bool GetPubKey(const SigningProvider& provider, const SignatureData& sigd
|
|||
return provider.GetPubKey(address, pubkey);
|
||||
}
|
||||
|
||||
static bool CreateSig(const BaseSignatureCreator& creator, SignatureData& sigdata, const SigningProvider& provider, std::vector<unsigned char>& sig_out, const CPubKey& pubkey, const CScript& scriptcode, SigVersion sigversion)
|
||||
static bool CreateSig(const BaseSignatureCreator& creator, SignatureData& sigdata, const SigningProvider& provider, std::vector<unsigned char>& sig_out, const CPubKey& pubkey, const CScript& scriptcode, SigVersion sigversion, unsigned int flags)
|
||||
{
|
||||
CKeyID keyid = pubkey.GetID();
|
||||
const auto it = sigdata.signatures.find(keyid);
|
||||
|
|
@ -83,7 +83,7 @@ static bool CreateSig(const BaseSignatureCreator& creator, SignatureData& sigdat
|
|||
if (provider.GetKeyOrigin(keyid, info)) {
|
||||
sigdata.misc_pubkeys.emplace(keyid, std::make_pair(pubkey, std::move(info)));
|
||||
}
|
||||
if (creator.CreateSig(provider, sig_out, keyid, scriptcode, sigversion)) {
|
||||
if (creator.CreateSig(provider, sig_out, keyid, scriptcode, sigversion, flags)) {
|
||||
auto i = sigdata.signatures.emplace(keyid, SigPair(pubkey, sig_out));
|
||||
assert(i.second);
|
||||
return true;
|
||||
|
|
@ -100,7 +100,8 @@ static bool CreateSig(const BaseSignatureCreator& creator, SignatureData& sigdat
|
|||
* Returns false if scriptPubKey could not be completely satisfied.
|
||||
*/
|
||||
static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator& creator, const CScript& scriptPubKey,
|
||||
std::vector<valtype>& ret, TxoutType& whichTypeRet, SigVersion sigversion, SignatureData& sigdata)
|
||||
std::vector<valtype>& ret, TxoutType& whichTypeRet, SigVersion sigversion, SignatureData& sigdata,
|
||||
unsigned int flags)
|
||||
{
|
||||
CScript scriptRet;
|
||||
uint160 h160;
|
||||
|
|
@ -118,7 +119,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
|
|||
case TxoutType::WITNESS_V1_TAPROOT:
|
||||
return false;
|
||||
case TxoutType::PUBKEY:
|
||||
if (!CreateSig(creator, sigdata, provider, sig, CPubKey(vSolutions[0]), scriptPubKey, sigversion)) return false;
|
||||
if (!CreateSig(creator, sigdata, provider, sig, CPubKey(vSolutions[0]), scriptPubKey, sigversion, flags)) return false;
|
||||
ret.push_back(std::move(sig));
|
||||
return true;
|
||||
case TxoutType::PUBKEYHASH: {
|
||||
|
|
@ -129,7 +130,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
|
|||
sigdata.missing_pubkeys.push_back(keyID);
|
||||
return false;
|
||||
}
|
||||
if (!CreateSig(creator, sigdata, provider, sig, pubkey, scriptPubKey, sigversion)) return false;
|
||||
if (!CreateSig(creator, sigdata, provider, sig, pubkey, scriptPubKey, sigversion, flags)) return false;
|
||||
ret.push_back(std::move(sig));
|
||||
ret.push_back(ToByteVector(pubkey));
|
||||
return true;
|
||||
|
|
@ -152,7 +153,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
|
|||
// We need to always call CreateSig in order to fill sigdata with all
|
||||
// possible signatures that we can create. This will allow further PSBT
|
||||
// processing to work as it needs all possible signature and pubkey pairs
|
||||
if (CreateSig(creator, sigdata, provider, sig, pubkey, scriptPubKey, sigversion)) {
|
||||
if (CreateSig(creator, sigdata, provider, sig, pubkey, scriptPubKey, sigversion, flags)) {
|
||||
if (ret.size() < required + 1) {
|
||||
ret.push_back(std::move(sig));
|
||||
}
|
||||
|
|
@ -207,9 +208,14 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
|
|||
{
|
||||
if (sigdata.complete) return true;
|
||||
|
||||
// We will already activate SIGHASH_RANGEPROOF for signing. This means that
|
||||
// users using the flag before it activates will produce invalid signatures.
|
||||
unsigned int signFlags = SCRIPT_SIGHASH_RANGEPROOF;
|
||||
unsigned int verifyFlags = STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_SIGHASH_RANGEPROOF | additional_flags;
|
||||
|
||||
std::vector<valtype> result;
|
||||
TxoutType whichType;
|
||||
bool solved = SignStep(provider, creator, fromPubKey, result, whichType, SigVersion::BASE, sigdata);
|
||||
bool solved = SignStep(provider, creator, fromPubKey, result, whichType, SigVersion::BASE, sigdata, signFlags);
|
||||
bool P2SH = false;
|
||||
CScript subscript;
|
||||
sigdata.scriptWitness.stack.clear();
|
||||
|
|
@ -221,7 +227,7 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
|
|||
// and then the serialized subscript:
|
||||
subscript = CScript(result[0].begin(), result[0].end());
|
||||
sigdata.redeem_script = subscript;
|
||||
solved = solved && SignStep(provider, creator, subscript, result, whichType, SigVersion::BASE, sigdata) && whichType != TxoutType::SCRIPTHASH;
|
||||
solved = solved && SignStep(provider, creator, subscript, result, whichType, SigVersion::BASE, sigdata, signFlags) && whichType != TxoutType::SCRIPTHASH;
|
||||
P2SH = true;
|
||||
}
|
||||
|
||||
|
|
@ -230,7 +236,7 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
|
|||
CScript witnessscript;
|
||||
witnessscript << OP_DUP << OP_HASH160 << ToByteVector(result[0]) << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||
TxoutType subType;
|
||||
solved = solved && SignStep(provider, creator, witnessscript, result, subType, SigVersion::WITNESS_V0, sigdata);
|
||||
solved = solved && SignStep(provider, creator, witnessscript, result, subType, SigVersion::WITNESS_V0, sigdata, signFlags);
|
||||
sigdata.scriptWitness.stack = result;
|
||||
sigdata.witness = true;
|
||||
result.clear();
|
||||
|
|
@ -240,7 +246,7 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
|
|||
CScript witnessscript(result[0].begin(), result[0].end());
|
||||
sigdata.witness_script = witnessscript;
|
||||
TxoutType subType;
|
||||
solved = solved && SignStep(provider, creator, witnessscript, result, subType, SigVersion::WITNESS_V0, sigdata) && subType != TxoutType::SCRIPTHASH && subType != TxoutType::WITNESS_V0_SCRIPTHASH && subType != TxoutType::WITNESS_V0_KEYHASH;
|
||||
solved = solved && SignStep(provider, creator, witnessscript, result, subType, SigVersion::WITNESS_V0, sigdata, signFlags) && subType != TxoutType::SCRIPTHASH && subType != TxoutType::WITNESS_V0_SCRIPTHASH && subType != TxoutType::WITNESS_V0_KEYHASH;
|
||||
result.push_back(std::vector<unsigned char>(witnessscript.begin(), witnessscript.end()));
|
||||
sigdata.scriptWitness.stack = result;
|
||||
sigdata.witness = true;
|
||||
|
|
@ -255,7 +261,7 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
|
|||
sigdata.scriptSig = PushAll(result);
|
||||
|
||||
// Test solution
|
||||
sigdata.complete = solved && VerifyScript(sigdata.scriptSig, fromPubKey, &sigdata.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS|additional_flags, creator.Checker());
|
||||
sigdata.complete = solved && VerifyScript(sigdata.scriptSig, fromPubKey, &sigdata.scriptWitness, verifyFlags, creator.Checker());
|
||||
return sigdata.complete;
|
||||
}
|
||||
|
||||
|
|
@ -268,9 +274,9 @@ private:
|
|||
|
||||
public:
|
||||
SignatureExtractorChecker(SignatureData& sigdata, BaseSignatureChecker& checker) : sigdata(sigdata), checker(checker) {}
|
||||
bool CheckECDSASignature(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override
|
||||
bool CheckECDSASignature(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion, unsigned int flags) const override
|
||||
{
|
||||
if (checker.CheckECDSASignature(scriptSig, vchPubKey, scriptCode, sigversion)) {
|
||||
if (checker.CheckECDSASignature(scriptSig, vchPubKey, scriptCode, sigversion, flags)) {
|
||||
CPubKey pubkey(vchPubKey);
|
||||
sigdata.signatures.emplace(pubkey.GetID(), SigPair(pubkey, scriptSig));
|
||||
return true;
|
||||
|
|
@ -338,6 +344,8 @@ SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nI
|
|||
stack.witness.clear();
|
||||
sigversion = SigVersion::WITNESS_V0;
|
||||
}
|
||||
// We enable SIGHASH_RANGEPROOF for signing.
|
||||
unsigned int flags = SCRIPT_SIGHASH_RANGEPROOF;
|
||||
if (script_type == TxoutType::MULTISIG && !stack.script.empty()) {
|
||||
// Build a map of pubkey -> signature by matching sigs to pubkeys:
|
||||
assert(solutions.size() > 1);
|
||||
|
|
@ -347,7 +355,7 @@ SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nI
|
|||
for (unsigned int i = last_success_key; i < num_pubkeys; ++i) {
|
||||
const valtype& pubkey = solutions[i+1];
|
||||
// We either have a signature for this pubkey, or we have found a signature and it is valid
|
||||
if (data.signatures.count(CPubKey(pubkey).GetID()) || extractor_checker.CheckECDSASignature(sig, pubkey, next_script, sigversion)) {
|
||||
if (data.signatures.count(CPubKey(pubkey).GetID()) || extractor_checker.CheckECDSASignature(sig, pubkey, next_script, sigversion, flags)) {
|
||||
last_success_key = i + 1;
|
||||
break;
|
||||
}
|
||||
|
|
@ -412,7 +420,7 @@ class DummySignatureChecker final : public BaseSignatureChecker
|
|||
{
|
||||
public:
|
||||
DummySignatureChecker() {}
|
||||
bool CheckECDSASignature(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override { return true; }
|
||||
bool CheckECDSASignature(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion, unsigned int flags) const override { return true; }
|
||||
};
|
||||
const DummySignatureChecker DUMMY_CHECKER;
|
||||
|
||||
|
|
@ -423,7 +431,7 @@ private:
|
|||
public:
|
||||
DummySignatureCreator(char r_len, char s_len) : m_r_len(r_len), m_s_len(s_len) {}
|
||||
const BaseSignatureChecker& Checker() const override { return DUMMY_CHECKER; }
|
||||
bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override
|
||||
bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion, unsigned int flags) const override
|
||||
{
|
||||
// Create a dummy signature that is a valid DER-encoding
|
||||
vchSig.assign(m_r_len + m_s_len + 7, '\000');
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue