mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-16 13:01:19 +02:00
Add SIGHASH_RANGEPROOF support
This commit is contained in:
parent
236f0b1762
commit
691040a63d
11 changed files with 144 additions and 54 deletions
|
|
@ -17,7 +17,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))
|
||||
|
|
@ -27,7 +27,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);
|
||||
|
|
@ -68,7 +68,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);
|
||||
|
|
@ -80,7 +80,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;
|
||||
|
|
@ -97,8 +97,9 @@ 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, txnouttype& whichTypeRet, SigVersion sigversion, SignatureData& sigdata)
|
||||
{
|
||||
std::vector<valtype>& ret, txnouttype& whichTypeRet, SigVersion sigversion,
|
||||
SignatureData& sigdata, unsigned int flags
|
||||
) {
|
||||
CScript scriptRet;
|
||||
uint160 h160;
|
||||
ret.clear();
|
||||
|
|
@ -114,7 +115,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
|
|||
case TX_WITNESS_UNKNOWN:
|
||||
return false;
|
||||
case TX_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 TX_PUBKEYHASH: {
|
||||
|
|
@ -125,7 +126,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;
|
||||
|
|
@ -145,7 +146,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
|
|||
ret.push_back(valtype()); // workaround CHECKMULTISIG bug
|
||||
for (size_t i = 1; i < vSolutions.size() - 1; ++i) {
|
||||
CPubKey pubkey = CPubKey(vSolutions[i]);
|
||||
if (ret.size() < required + 1 && CreateSig(creator, sigdata, provider, sig, pubkey, scriptPubKey, sigversion)) {
|
||||
if (ret.size() < required + 1 && CreateSig(creator, sigdata, provider, sig, pubkey, scriptPubKey, sigversion, flags)) {
|
||||
ret.push_back(std::move(sig));
|
||||
}
|
||||
}
|
||||
|
|
@ -196,9 +197,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;
|
||||
txnouttype 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();
|
||||
|
|
@ -210,7 +216,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 != TX_SCRIPTHASH;
|
||||
solved = solved && SignStep(provider, creator, subscript, result, whichType, SigVersion::BASE, sigdata, signFlags) && whichType != TX_SCRIPTHASH;
|
||||
P2SH = true;
|
||||
}
|
||||
|
||||
|
|
@ -219,7 +225,7 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
|
|||
CScript witnessscript;
|
||||
witnessscript << OP_DUP << OP_HASH160 << ToByteVector(result[0]) << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||
txnouttype 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();
|
||||
|
|
@ -229,7 +235,7 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
|
|||
CScript witnessscript(result[0].begin(), result[0].end());
|
||||
sigdata.witness_script = witnessscript;
|
||||
txnouttype subType;
|
||||
solved = solved && SignStep(provider, creator, witnessscript, result, subType, SigVersion::WITNESS_V0, sigdata) && subType != TX_SCRIPTHASH && subType != TX_WITNESS_V0_SCRIPTHASH && subType != TX_WITNESS_V0_KEYHASH;
|
||||
solved = solved && SignStep(provider, creator, witnessscript, result, subType, SigVersion::WITNESS_V0, sigdata, signFlags) && subType != TX_SCRIPTHASH && subType != TX_WITNESS_V0_SCRIPTHASH && subType != TX_WITNESS_V0_KEYHASH;
|
||||
result.push_back(std::vector<unsigned char>(witnessscript.begin(), witnessscript.end()));
|
||||
sigdata.scriptWitness.stack = result;
|
||||
sigdata.witness = true;
|
||||
|
|
@ -244,7 +250,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;
|
||||
}
|
||||
|
||||
|
|
@ -256,12 +262,12 @@ private:
|
|||
|
||||
public:
|
||||
SignatureExtractorChecker(SignatureData& sigdata, BaseSignatureChecker& checker) : sigdata(sigdata), checker(checker) {}
|
||||
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override;
|
||||
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion, unsigned int flags) const override;
|
||||
};
|
||||
|
||||
bool SignatureExtractorChecker::CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
|
||||
bool SignatureExtractorChecker::CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion, unsigned int flags) const
|
||||
{
|
||||
if (checker.CheckSig(scriptSig, vchPubKey, scriptCode, sigversion)) {
|
||||
if (checker.CheckSig(scriptSig, vchPubKey, scriptCode, sigversion, flags)) {
|
||||
CPubKey pubkey(vchPubKey);
|
||||
sigdata.signatures.emplace(pubkey.GetID(), SigPair(pubkey, scriptSig));
|
||||
return true;
|
||||
|
|
@ -330,6 +336,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 == TX_MULTISIG && !stack.script.empty()) {
|
||||
// Build a map of pubkey -> signature by matching sigs to pubkeys:
|
||||
assert(solutions.size() > 1);
|
||||
|
|
@ -339,7 +347,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.CheckSig(sig, pubkey, next_script, sigversion)) {
|
||||
if (data.signatures.count(CPubKey(pubkey).GetID()) || extractor_checker.CheckSig(sig, pubkey, next_script, sigversion, flags)) {
|
||||
last_success_key = i + 1;
|
||||
break;
|
||||
}
|
||||
|
|
@ -404,7 +412,7 @@ class DummySignatureChecker final : public BaseSignatureChecker
|
|||
{
|
||||
public:
|
||||
DummySignatureChecker() {}
|
||||
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override { return true; }
|
||||
bool CheckSig(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;
|
||||
|
||||
|
|
@ -415,7 +423,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