mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-12-03 17:30:25 +01:00
script/sign: signing support for Miniscripts with hash preimage challenges
Preimages must be externally provided (typically, via a PSBT).
This commit is contained in:
@@ -382,6 +382,17 @@ static CScript PushAll(const std::vector<valtype>& values)
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename M, typename K, typename V>
|
||||
miniscript::Availability MsLookupHelper(const M& map, const K& key, V& value)
|
||||
{
|
||||
auto it = map.find(key);
|
||||
if (it != map.end()) {
|
||||
value = it->second;
|
||||
return miniscript::Availability::YES;
|
||||
}
|
||||
return miniscript::Availability::NO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Context for solving a Miniscript.
|
||||
* If enough material (access to keys, hash preimages, ..) is given, produces a valid satisfaction.
|
||||
@@ -443,11 +454,18 @@ struct Satisfier {
|
||||
|
||||
|
||||
//! Hash preimage satisfactions.
|
||||
// TODO
|
||||
miniscript::Availability SatSHA256(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const { return miniscript::Availability::NO; }
|
||||
miniscript::Availability SatRIPEMD160(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const { return miniscript::Availability::NO; }
|
||||
miniscript::Availability SatHASH256(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const { return miniscript::Availability::NO; }
|
||||
miniscript::Availability SatHASH160(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const { return miniscript::Availability::NO; }
|
||||
miniscript::Availability SatSHA256(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
|
||||
return MsLookupHelper(m_sig_data.sha256_preimages, hash, preimage);
|
||||
}
|
||||
miniscript::Availability SatRIPEMD160(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
|
||||
return MsLookupHelper(m_sig_data.ripemd160_preimages, hash, preimage);
|
||||
}
|
||||
miniscript::Availability SatHASH256(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
|
||||
return MsLookupHelper(m_sig_data.hash256_preimages, hash, preimage);
|
||||
}
|
||||
miniscript::Availability SatHASH160(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
|
||||
return MsLookupHelper(m_sig_data.hash160_preimages, hash, preimage);
|
||||
}
|
||||
};
|
||||
|
||||
bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreator& creator, const CScript& fromPubKey, SignatureData& sigdata)
|
||||
@@ -645,26 +663,25 @@ void SignatureData::MergeSignatureData(SignatureData sigdata)
|
||||
signatures.insert(std::make_move_iterator(sigdata.signatures.begin()), std::make_move_iterator(sigdata.signatures.end()));
|
||||
}
|
||||
|
||||
bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType)
|
||||
bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType, SignatureData& sig_data)
|
||||
{
|
||||
assert(nIn < txTo.vin.size());
|
||||
|
||||
MutableTransactionSignatureCreator creator(txTo, nIn, amount, nHashType);
|
||||
|
||||
SignatureData sigdata;
|
||||
bool ret = ProduceSignature(provider, creator, fromPubKey, sigdata);
|
||||
UpdateInput(txTo.vin.at(nIn), sigdata);
|
||||
bool ret = ProduceSignature(provider, creator, fromPubKey, sig_data);
|
||||
UpdateInput(txTo.vin.at(nIn), sig_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
|
||||
bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType, SignatureData& sig_data)
|
||||
{
|
||||
assert(nIn < txTo.vin.size());
|
||||
const CTxIn& txin = txTo.vin[nIn];
|
||||
assert(txin.prevout.n < txFrom.vout.size());
|
||||
const CTxOut& txout = txFrom.vout[txin.prevout.n];
|
||||
|
||||
return SignSignature(provider, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType);
|
||||
return SignSignature(provider, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType, sig_data);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -82,6 +82,10 @@ struct SignatureData {
|
||||
std::vector<CKeyID> missing_sigs; ///< KeyIDs of pubkeys for signatures which could not be found
|
||||
uint160 missing_redeem_script; ///< ScriptID of the missing redeemScript (if any)
|
||||
uint256 missing_witness_script; ///< SHA256 of the missing witnessScript (if any)
|
||||
std::map<std::vector<uint8_t>, std::vector<uint8_t>> sha256_preimages; ///< Mapping from a SHA256 hash to its preimage provided to solve a Script
|
||||
std::map<std::vector<uint8_t>, std::vector<uint8_t>> hash256_preimages; ///< Mapping from a HASH256 hash to its preimage provided to solve a Script
|
||||
std::map<std::vector<uint8_t>, std::vector<uint8_t>> ripemd160_preimages; ///< Mapping from a RIPEMD160 hash to its preimage provided to solve a Script
|
||||
std::map<std::vector<uint8_t>, std::vector<uint8_t>> hash160_preimages; ///< Mapping from a HASH160 hash to its preimage provided to solve a Script
|
||||
|
||||
SignatureData() {}
|
||||
explicit SignatureData(const CScript& script) : scriptSig(script) {}
|
||||
@@ -91,9 +95,24 @@ struct SignatureData {
|
||||
/** Produce a script signature using a generic signature creator. */
|
||||
bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreator& creator, const CScript& scriptPubKey, SignatureData& sigdata);
|
||||
|
||||
/** Produce a script signature for a transaction. */
|
||||
bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType);
|
||||
bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType);
|
||||
/**
|
||||
* Produce a satisfying script (scriptSig or witness).
|
||||
*
|
||||
* @param provider Utility containing the information necessary to solve a script.
|
||||
* @param fromPubKey The script to produce a satisfaction for.
|
||||
* @param txTo The spending transaction.
|
||||
* @param nIn The index of the input in `txTo` refering the output being spent.
|
||||
* @param amount The value of the output being spent.
|
||||
* @param nHashType Signature hash type.
|
||||
* @param sig_data Additional data provided to solve a script. Filled with the resulting satisfying
|
||||
* script and whether the satisfaction is complete.
|
||||
*
|
||||
* @return True if the produced script is entirely satisfying `fromPubKey`.
|
||||
**/
|
||||
bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo,
|
||||
unsigned int nIn, const CAmount& amount, int nHashType, SignatureData& sig_data);
|
||||
bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo,
|
||||
unsigned int nIn, int nHashType, SignatureData& sig_data);
|
||||
|
||||
/** Extract signature data from a transaction input, and insert it. */
|
||||
SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn, const CTxOut& txout);
|
||||
|
||||
Reference in New Issue
Block a user