Skip to content

Commit 560e62b

Browse files
committed
script/sign: signing support for Miniscripts with hash preimage challenges
Preimages must be externally provided (typically, via a PSBT).
1 parent a2f81b6 commit 560e62b

File tree

9 files changed

+109
-37
lines changed

9 files changed

+109
-37
lines changed

src/script/sign.cpp

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,17 @@ static CScript PushAll(const std::vector<valtype>& values)
382382
return result;
383383
}
384384

385+
template<typename M, typename K, typename V>
386+
miniscript::Availability MsLookupHelper(const M& map, const K& key, V& value)
387+
{
388+
auto it = map.find(key);
389+
if (it != map.end()) {
390+
value = it->second;
391+
return miniscript::Availability::YES;
392+
}
393+
return miniscript::Availability::NO;
394+
}
395+
385396
/**
386397
* Context for solving a Miniscript.
387398
* If enough material (access to keys, hash preimages, ..) is given, produces a valid satisfaction.
@@ -443,11 +454,18 @@ struct Satisfier {
443454

444455

445456
//! Hash preimage satisfactions.
446-
// TODO
447-
miniscript::Availability SatSHA256(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const { return miniscript::Availability::NO; }
448-
miniscript::Availability SatRIPEMD160(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const { return miniscript::Availability::NO; }
449-
miniscript::Availability SatHASH256(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const { return miniscript::Availability::NO; }
450-
miniscript::Availability SatHASH160(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const { return miniscript::Availability::NO; }
457+
miniscript::Availability SatSHA256(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
458+
return MsLookupHelper(m_sig_data.sha256_preimages, hash, preimage);
459+
}
460+
miniscript::Availability SatRIPEMD160(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
461+
return MsLookupHelper(m_sig_data.ripemd160_preimages, hash, preimage);
462+
}
463+
miniscript::Availability SatHASH256(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
464+
return MsLookupHelper(m_sig_data.hash256_preimages, hash, preimage);
465+
}
466+
miniscript::Availability SatHASH160(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
467+
return MsLookupHelper(m_sig_data.hash160_preimages, hash, preimage);
468+
}
451469
};
452470

453471
bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreator& creator, const CScript& fromPubKey, SignatureData& sigdata)
@@ -645,26 +663,25 @@ void SignatureData::MergeSignatureData(SignatureData sigdata)
645663
signatures.insert(std::make_move_iterator(sigdata.signatures.begin()), std::make_move_iterator(sigdata.signatures.end()));
646664
}
647665

648-
bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType)
666+
bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType, SignatureData& sig_data)
649667
{
650668
assert(nIn < txTo.vin.size());
651669

652670
MutableTransactionSignatureCreator creator(txTo, nIn, amount, nHashType);
653671

654-
SignatureData sigdata;
655-
bool ret = ProduceSignature(provider, creator, fromPubKey, sigdata);
656-
UpdateInput(txTo.vin.at(nIn), sigdata);
672+
bool ret = ProduceSignature(provider, creator, fromPubKey, sig_data);
673+
UpdateInput(txTo.vin.at(nIn), sig_data);
657674
return ret;
658675
}
659676

660-
bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
677+
bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType, SignatureData& sig_data)
661678
{
662679
assert(nIn < txTo.vin.size());
663680
const CTxIn& txin = txTo.vin[nIn];
664681
assert(txin.prevout.n < txFrom.vout.size());
665682
const CTxOut& txout = txFrom.vout[txin.prevout.n];
666683

667-
return SignSignature(provider, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType);
684+
return SignSignature(provider, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType, sig_data);
668685
}
669686

670687
namespace {

src/script/sign.h

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ struct SignatureData {
8282
std::vector<CKeyID> missing_sigs; ///< KeyIDs of pubkeys for signatures which could not be found
8383
uint160 missing_redeem_script; ///< ScriptID of the missing redeemScript (if any)
8484
uint256 missing_witness_script; ///< SHA256 of the missing witnessScript (if any)
85+
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
86+
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
87+
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
88+
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
8589

8690
SignatureData() {}
8791
explicit SignatureData(const CScript& script) : scriptSig(script) {}
@@ -91,9 +95,24 @@ struct SignatureData {
9195
/** Produce a script signature using a generic signature creator. */
9296
bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreator& creator, const CScript& scriptPubKey, SignatureData& sigdata);
9397

94-
/** Produce a script signature for a transaction. */
95-
bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType);
96-
bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType);
98+
/**
99+
* Produce a satisfying script (scriptSig or witness).
100+
*
101+
* @param provider Utility containing the information necessary to solve a script.
102+
* @param fromPubKey The script to produce a satisfaction for.
103+
* @param txTo The spending transaction.
104+
* @param nIn The index of the input in `txTo` refering the output being spent.
105+
* @param amount The value of the output being spent.
106+
* @param nHashType Signature hash type.
107+
* @param sig_data Additional data provided to solve a script. Filled with the resulting satisfying
108+
* script and whether the satisfaction is complete.
109+
*
110+
* @return True if the produced script is entirely satisfying `fromPubKey`.
111+
**/
112+
bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo,
113+
unsigned int nIn, const CAmount& amount, int nHashType, SignatureData& sig_data);
114+
bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo,
115+
unsigned int nIn, int nHashType, SignatureData& sig_data);
97116

98117
/** Extract signature data from a transaction input, and insert it. */
99118
SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn, const CTxOut& txout);

0 commit comments

Comments
 (0)