2014-08-27 11:22:33 -04:00
// Copyright (c) 2009-2010 Satoshi Nakamoto
2018-01-02 14:12:05 -03:00
// Copyright (c) 2009-2017 The Bitcoin Core developers
2014-09-09 05:00:42 -03:00
// Distributed under the MIT software license, see the accompanying
2014-08-27 11:22:33 -04:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2017-11-09 21:57:53 -03:00
# include <script/sign.h>
2014-08-27 11:22:33 -04:00
2017-11-09 21:57:53 -03:00
# include <key.h>
# include <keystore.h>
# include <policy/policy.h>
# include <primitives/transaction.h>
# include <script/standard.h>
# include <uint256.h>
2014-08-27 11:22:33 -04:00
2015-10-29 03:11:24 -03:00
typedef std : : vector < unsigned char > valtype ;
2014-08-27 11:22:33 -04:00
2015-12-27 15:49:08 -03:00
TransactionSignatureCreator : : TransactionSignatureCreator ( const CKeyStore * keystoreIn , const CTransaction * txToIn , unsigned int nInIn , const CAmount & amountIn , int nHashTypeIn ) : BaseSignatureCreator ( keystoreIn ) , txTo ( txToIn ) , nIn ( nInIn ) , nHashType ( nHashTypeIn ) , amount ( amountIn ) , checker ( txTo , nIn , amountIn ) { }
2014-11-04 15:06:20 -03:00
2016-03-31 09:54:58 -03:00
bool TransactionSignatureCreator : : CreateSig ( std : : vector < unsigned char > & vchSig , const CKeyID & address , const CScript & scriptCode , SigVersion sigversion ) const
2014-08-27 11:22:33 -04:00
{
CKey key ;
2014-11-04 15:06:20 -03:00
if ( ! keystore - > GetKey ( address , key ) )
2014-08-27 11:22:33 -04:00
return false ;
2016-10-01 14:19:33 -03:00
// Signing with uncompressed keys is disabled in witness scripts
if ( sigversion = = SIGVERSION_WITNESS_V0 & & ! key . IsCompressed ( ) )
return false ;
2016-03-31 09:54:58 -03:00
uint256 hash = SignatureHash ( scriptCode , * txTo , nIn , nHashType , amount , sigversion ) ;
2014-08-27 11:22:33 -04:00
if ( ! key . Sign ( hash , vchSig ) )
return false ;
vchSig . push_back ( ( unsigned char ) nHashType ) ;
2014-11-04 15:06:20 -03:00
return true ;
}
2014-08-27 11:22:33 -04:00
2016-03-31 09:54:58 -03:00
static bool Sign1 ( const CKeyID & address , const BaseSignatureCreator & creator , const CScript & scriptCode , std : : vector < valtype > & ret , SigVersion sigversion )
2014-11-04 15:06:20 -03:00
{
2017-01-04 02:42:14 -03:00
std : : vector < unsigned char > vchSig ;
2016-03-31 09:54:58 -03:00
if ( ! creator . CreateSig ( vchSig , address , scriptCode , sigversion ) )
2014-11-04 15:06:20 -03:00
return false ;
2016-03-31 09:54:58 -03:00
ret . push_back ( vchSig ) ;
2014-08-27 11:22:33 -04:00
return true ;
}
2017-01-04 02:42:14 -03:00
static bool SignN ( const std : : vector < valtype > & multisigdata , const BaseSignatureCreator & creator , const CScript & scriptCode , std : : vector < valtype > & ret , SigVersion sigversion )
2014-08-27 11:22:33 -04:00
{
int nSigned = 0 ;
int nRequired = multisigdata . front ( ) [ 0 ] ;
for ( unsigned int i = 1 ; i < multisigdata . size ( ) - 1 & & nSigned < nRequired ; i + + )
{
const valtype & pubkey = multisigdata [ i ] ;
CKeyID keyID = CPubKey ( pubkey ) . GetID ( ) ;
2016-03-31 09:54:58 -03:00
if ( Sign1 ( keyID , creator , scriptCode , ret , sigversion ) )
2014-08-27 11:22:33 -04:00
+ + nSigned ;
}
return nSigned = = nRequired ;
}
2014-11-10 03:40:01 -03:00
/**
2014-11-04 15:06:20 -03:00
* Sign scriptPubKey using signature made with creator .
2014-11-10 03:40:01 -03:00
* 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 .
* Returns false if scriptPubKey could not be completely satisfied .
*/
2014-11-04 15:06:20 -03:00
static bool SignStep ( const BaseSignatureCreator & creator , const CScript & scriptPubKey ,
2016-03-31 09:54:58 -03:00
std : : vector < valtype > & ret , txnouttype & whichTypeRet , SigVersion sigversion )
2014-08-27 11:22:33 -04:00
{
2016-03-31 09:54:58 -03:00
CScript scriptRet ;
uint160 h160 ;
ret . clear ( ) ;
2014-08-27 11:22:33 -04:00
2017-01-04 02:42:14 -03:00
std : : vector < valtype > vSolutions ;
2014-08-27 11:22:33 -04:00
if ( ! Solver ( scriptPubKey , whichTypeRet , vSolutions ) )
return false ;
CKeyID keyID ;
switch ( whichTypeRet )
{
case TX_NONSTANDARD :
case TX_NULL_DATA :
2017-08-25 23:55:52 -03:00
case TX_WITNESS_UNKNOWN :
2014-08-27 11:22:33 -04:00
return false ;
case TX_PUBKEY :
keyID = CPubKey ( vSolutions [ 0 ] ) . GetID ( ) ;
2016-03-31 09:54:58 -03:00
return Sign1 ( keyID , creator , scriptPubKey , ret , sigversion ) ;
2014-08-27 11:22:33 -04:00
case TX_PUBKEYHASH :
keyID = CKeyID ( uint160 ( vSolutions [ 0 ] ) ) ;
2016-03-31 09:54:58 -03:00
if ( ! Sign1 ( keyID , creator , scriptPubKey , ret , sigversion ) )
2014-08-27 11:22:33 -04:00
return false ;
else
{
CPubKey vch ;
2014-11-04 15:06:20 -03:00
creator . KeyStore ( ) . GetPubKey ( keyID , vch ) ;
2016-03-31 09:54:58 -03:00
ret . push_back ( ToByteVector ( vch ) ) ;
2014-08-27 11:22:33 -04:00
}
return true ;
case TX_SCRIPTHASH :
2016-03-31 09:54:58 -03:00
if ( creator . KeyStore ( ) . GetCScript ( uint160 ( vSolutions [ 0 ] ) , scriptRet ) ) {
ret . push_back ( std : : vector < unsigned char > ( scriptRet . begin ( ) , scriptRet . end ( ) ) ) ;
return true ;
}
return false ;
2014-08-27 11:22:33 -04:00
case TX_MULTISIG :
2016-03-31 09:54:58 -03:00
ret . push_back ( valtype ( ) ) ; // workaround CHECKMULTISIG bug
return ( SignN ( vSolutions , creator , scriptPubKey , ret , sigversion ) ) ;
case TX_WITNESS_V0_KEYHASH :
ret . push_back ( vSolutions [ 0 ] ) ;
return true ;
case TX_WITNESS_V0_SCRIPTHASH :
CRIPEMD160 ( ) . Write ( & vSolutions [ 0 ] [ 0 ] , vSolutions [ 0 ] . size ( ) ) . Finalize ( h160 . begin ( ) ) ;
if ( creator . KeyStore ( ) . GetCScript ( h160 , scriptRet ) ) {
ret . push_back ( std : : vector < unsigned char > ( scriptRet . begin ( ) , scriptRet . end ( ) ) ) ;
return true ;
}
return false ;
default :
return false ;
2014-08-27 11:22:33 -04:00
}
}
2017-01-04 02:42:14 -03:00
static CScript PushAll ( const std : : vector < valtype > & values )
2014-08-27 11:22:33 -04:00
{
2016-03-31 09:54:58 -03:00
CScript result ;
2017-06-01 21:18:57 -04:00
for ( const valtype & v : values ) {
2016-03-31 09:54:58 -03:00
if ( v . size ( ) = = 0 ) {
result < < OP_0 ;
} else if ( v . size ( ) = = 1 & & v [ 0 ] > = 1 & & v [ 0 ] < = 16 ) {
result < < CScript : : EncodeOP_N ( v [ 0 ] ) ;
} else {
result < < v ;
}
}
return result ;
}
bool ProduceSignature ( const BaseSignatureCreator & creator , const CScript & fromPubKey , SignatureData & sigdata )
{
std : : vector < valtype > result ;
2014-08-27 11:22:33 -04:00
txnouttype whichType ;
2017-12-13 17:16:23 -03:00
bool solved = SignStep ( creator , fromPubKey , result , whichType , SIGVERSION_BASE ) ;
2016-03-31 09:54:58 -03:00
bool P2SH = false ;
CScript subscript ;
sigdata . scriptWitness . stack . clear ( ) ;
2014-08-27 11:22:33 -04:00
2016-03-31 09:54:58 -03:00
if ( solved & & whichType = = TX_SCRIPTHASH )
2014-08-27 11:22:33 -04:00
{
2016-03-31 09:54:58 -03:00
// Solver returns the subscript that needs to be evaluated;
2014-08-27 11:22:33 -04:00
// the final scriptSig is the signatures from that
// and then the serialized subscript:
2017-12-13 17:16:23 -03:00
subscript = CScript ( result [ 0 ] . begin ( ) , result [ 0 ] . end ( ) ) ;
solved = solved & & SignStep ( creator , subscript , result , whichType , SIGVERSION_BASE ) & & whichType ! = TX_SCRIPTHASH ;
2016-03-31 09:54:58 -03:00
P2SH = true ;
}
2014-08-27 11:22:33 -04:00
2016-03-31 09:54:58 -03:00
if ( solved & & whichType = = TX_WITNESS_V0_KEYHASH )
{
CScript witnessscript ;
witnessscript < < OP_DUP < < OP_HASH160 < < ToByteVector ( result [ 0 ] ) < < OP_EQUALVERIFY < < OP_CHECKSIG ;
2014-08-27 11:22:33 -04:00
txnouttype subType ;
2016-03-31 09:54:58 -03:00
solved = solved & & SignStep ( creator , witnessscript , result , subType , SIGVERSION_WITNESS_V0 ) ;
sigdata . scriptWitness . stack = result ;
result . clear ( ) ;
}
else if ( solved & & whichType = = TX_WITNESS_V0_SCRIPTHASH )
{
CScript witnessscript ( result [ 0 ] . begin ( ) , result [ 0 ] . end ( ) ) ;
txnouttype subType ;
solved = solved & & SignStep ( creator , witnessscript , result , subType , SIGVERSION_WITNESS_V0 ) & & 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 ;
result . clear ( ) ;
2014-08-27 11:22:33 -04:00
}
2016-03-31 09:54:58 -03:00
if ( P2SH ) {
result . push_back ( std : : vector < unsigned char > ( subscript . begin ( ) , subscript . end ( ) ) ) ;
}
sigdata . scriptSig = PushAll ( result ) ;
2014-08-27 11:22:33 -04:00
// Test solution
2016-03-31 09:54:58 -03:00
return solved & & VerifyScript ( sigdata . scriptSig , fromPubKey , & sigdata . scriptWitness , STANDARD_SCRIPT_VERIFY_FLAGS , creator . Checker ( ) ) ;
}
SignatureData DataFromTransaction ( const CMutableTransaction & tx , unsigned int nIn )
{
SignatureData data ;
assert ( tx . vin . size ( ) > nIn ) ;
data . scriptSig = tx . vin [ nIn ] . scriptSig ;
2016-08-03 20:49:16 -04:00
data . scriptWitness = tx . vin [ nIn ] . scriptWitness ;
2016-03-31 09:54:58 -03:00
return data ;
}
void UpdateTransaction ( CMutableTransaction & tx , unsigned int nIn , const SignatureData & data )
{
assert ( tx . vin . size ( ) > nIn ) ;
tx . vin [ nIn ] . scriptSig = data . scriptSig ;
2016-08-03 20:49:16 -04:00
tx . vin [ nIn ] . scriptWitness = data . scriptWitness ;
2014-11-04 15:06:20 -03:00
}
2016-03-31 09:54:58 -03:00
bool SignSignature ( const CKeyStore & keystore , const CScript & fromPubKey , CMutableTransaction & txTo , unsigned int nIn , const CAmount & amount , int nHashType )
2014-11-04 15:06:20 -03:00
{
assert ( nIn < txTo . vin . size ( ) ) ;
CTransaction txToConst ( txTo ) ;
2016-03-31 09:54:58 -03:00
TransactionSignatureCreator creator ( & keystore , & txToConst , nIn , amount , nHashType ) ;
2014-11-04 15:06:20 -03:00
2016-03-31 09:54:58 -03:00
SignatureData sigdata ;
bool ret = ProduceSignature ( creator , fromPubKey , sigdata ) ;
UpdateTransaction ( txTo , nIn , sigdata ) ;
return ret ;
2014-08-27 11:22:33 -04:00
}
bool SignSignature ( const CKeyStore & keystore , const CTransaction & txFrom , CMutableTransaction & txTo , unsigned int nIn , int nHashType )
{
assert ( nIn < txTo . vin . size ( ) ) ;
CTxIn & txin = txTo . vin [ nIn ] ;
assert ( txin . prevout . n < txFrom . vout . size ( ) ) ;
const CTxOut & txout = txFrom . vout [ txin . prevout . n ] ;
2016-03-31 09:54:58 -03:00
return SignSignature ( keystore , txout . scriptPubKey , txTo , nIn , txout . nValue , nHashType ) ;
2014-08-27 11:22:33 -04:00
}
2017-01-04 02:42:14 -03:00
static std : : vector < valtype > CombineMultisig ( const CScript & scriptPubKey , const BaseSignatureChecker & checker ,
const std : : vector < valtype > & vSolutions ,
const std : : vector < valtype > & sigs1 , const std : : vector < valtype > & sigs2 , SigVersion sigversion )
2014-08-27 11:22:33 -04:00
{
// Combine all the signatures we've got:
2017-01-04 02:42:14 -03:00
std : : set < valtype > allsigs ;
2017-06-01 21:18:57 -04:00
for ( const valtype & v : sigs1 )
2014-08-27 11:22:33 -04:00
{
if ( ! v . empty ( ) )
allsigs . insert ( v ) ;
}
2017-06-01 21:18:57 -04:00
for ( const valtype & v : sigs2 )
2014-08-27 11:22:33 -04:00
{
if ( ! v . empty ( ) )
allsigs . insert ( v ) ;
}
// Build a map of pubkey -> signature by matching sigs to pubkeys:
assert ( vSolutions . size ( ) > 1 ) ;
unsigned int nSigsRequired = vSolutions . front ( ) [ 0 ] ;
unsigned int nPubKeys = vSolutions . size ( ) - 2 ;
2017-01-04 02:42:14 -03:00
std : : map < valtype , valtype > sigs ;
2017-06-01 21:18:57 -04:00
for ( const valtype & sig : allsigs )
2014-08-27 11:22:33 -04:00
{
for ( unsigned int i = 0 ; i < nPubKeys ; i + + )
{
const valtype & pubkey = vSolutions [ i + 1 ] ;
if ( sigs . count ( pubkey ) )
continue ; // Already got a sig for this pubkey
2016-03-31 09:54:58 -03:00
if ( checker . CheckSig ( sig , pubkey , scriptPubKey , sigversion ) )
2014-08-27 11:22:33 -04:00
{
sigs [ pubkey ] = sig ;
break ;
}
}
}
// Now build a merged CScript:
unsigned int nSigsHave = 0 ;
2016-03-31 09:54:58 -03:00
std : : vector < valtype > result ; result . push_back ( valtype ( ) ) ; // pop-one-too-many workaround
2014-08-27 11:22:33 -04:00
for ( unsigned int i = 0 ; i < nPubKeys & & nSigsHave < nSigsRequired ; i + + )
{
if ( sigs . count ( vSolutions [ i + 1 ] ) )
{
2016-03-31 09:54:58 -03:00
result . push_back ( sigs [ vSolutions [ i + 1 ] ] ) ;
2014-08-27 11:22:33 -04:00
+ + nSigsHave ;
}
}
// Fill any missing with OP_0:
for ( unsigned int i = nSigsHave ; i < nSigsRequired ; i + + )
2016-03-31 09:54:58 -03:00
result . push_back ( valtype ( ) ) ;
2014-08-27 11:22:33 -04:00
return result ;
}
2016-03-31 09:54:58 -03:00
namespace
{
struct Stacks
{
std : : vector < valtype > script ;
std : : vector < valtype > witness ;
Stacks ( ) { }
explicit Stacks ( const std : : vector < valtype > & scriptSigStack_ ) : script ( scriptSigStack_ ) , witness ( ) { }
explicit Stacks ( const SignatureData & data ) : witness ( data . scriptWitness . stack ) {
EvalScript ( script , data . scriptSig , SCRIPT_VERIFY_STRICTENC , BaseSignatureChecker ( ) , SIGVERSION_BASE ) ;
}
SignatureData Output ( ) const {
SignatureData result ;
result . scriptSig = PushAll ( script ) ;
result . scriptWitness . stack = witness ;
return result ;
}
} ;
}
static Stacks CombineSignatures ( const CScript & scriptPubKey , const BaseSignatureChecker & checker ,
2017-01-04 02:42:14 -03:00
const txnouttype txType , const std : : vector < valtype > & vSolutions ,
2016-03-31 09:54:58 -03:00
Stacks sigs1 , Stacks sigs2 , SigVersion sigversion )
2014-08-27 11:22:33 -04:00
{
switch ( txType )
{
case TX_NONSTANDARD :
case TX_NULL_DATA :
2017-08-25 23:55:52 -03:00
case TX_WITNESS_UNKNOWN :
2014-08-27 11:22:33 -04:00
// Don't know anything about this, assume bigger one is correct:
2016-03-31 09:54:58 -03:00
if ( sigs1 . script . size ( ) > = sigs2 . script . size ( ) )
return sigs1 ;
return sigs2 ;
2014-08-27 11:22:33 -04:00
case TX_PUBKEY :
case TX_PUBKEYHASH :
// Signatures are bigger than placeholders or empty scripts:
2016-03-31 09:54:58 -03:00
if ( sigs1 . script . empty ( ) | | sigs1 . script [ 0 ] . empty ( ) )
return sigs2 ;
return sigs1 ;
case TX_WITNESS_V0_KEYHASH :
// Signatures are bigger than placeholders or empty scripts:
if ( sigs1 . witness . empty ( ) | | sigs1 . witness [ 0 ] . empty ( ) )
return sigs2 ;
return sigs1 ;
2014-08-27 11:22:33 -04:00
case TX_SCRIPTHASH :
2016-03-31 09:54:58 -03:00
if ( sigs1 . script . empty ( ) | | sigs1 . script . back ( ) . empty ( ) )
return sigs2 ;
else if ( sigs2 . script . empty ( ) | | sigs2 . script . back ( ) . empty ( ) )
return sigs1 ;
2014-08-27 11:22:33 -04:00
else
{
// Recur to combine:
2016-03-31 09:54:58 -03:00
valtype spk = sigs1 . script . back ( ) ;
2014-08-27 11:22:33 -04:00
CScript pubKey2 ( spk . begin ( ) , spk . end ( ) ) ;
txnouttype txType2 ;
2017-01-04 02:42:14 -03:00
std : : vector < std : : vector < unsigned char > > vSolutions2 ;
2014-08-27 11:22:33 -04:00
Solver ( pubKey2 , txType2 , vSolutions2 ) ;
2016-03-31 09:54:58 -03:00
sigs1 . script . pop_back ( ) ;
sigs2 . script . pop_back ( ) ;
Stacks result = CombineSignatures ( pubKey2 , checker , txType2 , vSolutions2 , sigs1 , sigs2 , sigversion ) ;
result . script . push_back ( spk ) ;
2014-08-27 11:22:33 -04:00
return result ;
}
case TX_MULTISIG :
2016-03-31 09:54:58 -03:00
return Stacks ( CombineMultisig ( scriptPubKey , checker , vSolutions , sigs1 . script , sigs2 . script , sigversion ) ) ;
case TX_WITNESS_V0_SCRIPTHASH :
if ( sigs1 . witness . empty ( ) | | sigs1 . witness . back ( ) . empty ( ) )
return sigs2 ;
else if ( sigs2 . witness . empty ( ) | | sigs2 . witness . back ( ) . empty ( ) )
return sigs1 ;
else
{
// Recur to combine:
CScript pubKey2 ( sigs1 . witness . back ( ) . begin ( ) , sigs1 . witness . back ( ) . end ( ) ) ;
txnouttype txType2 ;
2017-01-04 02:42:14 -03:00
std : : vector < valtype > vSolutions2 ;
2016-03-31 09:54:58 -03:00
Solver ( pubKey2 , txType2 , vSolutions2 ) ;
sigs1 . witness . pop_back ( ) ;
sigs1 . script = sigs1 . witness ;
sigs1 . witness . clear ( ) ;
sigs2 . witness . pop_back ( ) ;
sigs2 . script = sigs2 . witness ;
sigs2 . witness . clear ( ) ;
Stacks result = CombineSignatures ( pubKey2 , checker , txType2 , vSolutions2 , sigs1 , sigs2 , SIGVERSION_WITNESS_V0 ) ;
result . witness = result . script ;
result . script . clear ( ) ;
result . witness . push_back ( valtype ( pubKey2 . begin ( ) , pubKey2 . end ( ) ) ) ;
return result ;
}
default :
return Stacks ( ) ;
2014-08-27 11:22:33 -04:00
}
}
2016-03-31 09:54:58 -03:00
SignatureData CombineSignatures ( const CScript & scriptPubKey , const BaseSignatureChecker & checker ,
const SignatureData & scriptSig1 , const SignatureData & scriptSig2 )
2014-08-27 11:22:33 -04:00
{
txnouttype txType ;
2017-01-04 02:42:14 -03:00
std : : vector < std : : vector < unsigned char > > vSolutions ;
2014-08-27 11:22:33 -04:00
Solver ( scriptPubKey , txType , vSolutions ) ;
2016-03-31 09:54:58 -03:00
return CombineSignatures ( scriptPubKey , checker , txType , vSolutions , Stacks ( scriptSig1 ) , Stacks ( scriptSig2 ) , SIGVERSION_BASE ) . Output ( ) ;
2014-08-27 11:22:33 -04:00
}
2015-05-01 10:21:06 -03:00
namespace {
/** Dummy signature checker which accepts all signatures. */
class DummySignatureChecker : public BaseSignatureChecker
{
public :
DummySignatureChecker ( ) { }
2017-06-20 15:58:56 -04:00
bool CheckSig ( const std : : vector < unsigned char > & scriptSig , const std : : vector < unsigned char > & vchPubKey , const CScript & scriptCode , SigVersion sigversion ) const override
2015-05-01 10:21:06 -03:00
{
return true ;
}
} ;
const DummySignatureChecker dummyChecker ;
2017-05-31 16:21:25 -04:00
} // namespace
2015-05-01 10:21:06 -03:00
const BaseSignatureChecker & DummySignatureCreator : : Checker ( ) const
{
return dummyChecker ;
}
2016-03-31 09:54:58 -03:00
bool DummySignatureCreator : : CreateSig ( std : : vector < unsigned char > & vchSig , const CKeyID & keyid , const CScript & scriptCode , SigVersion sigversion ) const
2015-05-01 10:21:06 -03:00
{
// Create a dummy signature that is a valid DER-encoding
vchSig . assign ( 72 , ' \000 ' ) ;
vchSig [ 0 ] = 0x30 ;
vchSig [ 1 ] = 69 ;
vchSig [ 2 ] = 0x02 ;
vchSig [ 3 ] = 33 ;
vchSig [ 4 ] = 0x01 ;
vchSig [ 4 + 33 ] = 0x02 ;
vchSig [ 5 + 33 ] = 32 ;
vchSig [ 6 + 33 ] = 0x01 ;
vchSig [ 6 + 33 + 32 ] = SIGHASH_ALL ;
return true ;
}
2017-11-30 21:48:31 -03:00
bool IsSolvable ( const CKeyStore & store , const CScript & script )
{
// This check is to make sure that the script we created can actually be solved for and signed by us
// if we were to have the private keys. This is just to make sure that the script is valid and that,
// if found in a transaction, we would still accept and relay that transaction. In particular,
// it will reject witness outputs that require signing with an uncompressed public key.
DummySignatureCreator creator ( & store ) ;
SignatureData sigs ;
// Make sure that STANDARD_SCRIPT_VERIFY_FLAGS includes SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, the most
// important property this function is designed to test for.
static_assert ( STANDARD_SCRIPT_VERIFY_FLAGS & SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , " IsSolvable requires standard script flags to include WITNESS_PUBKEYTYPE " ) ;
if ( ProduceSignature ( creator , script , sigs ) ) {
// VerifyScript check is just defensive, and should never fail.
assert ( VerifyScript ( sigs . scriptSig , script , & sigs . scriptWitness , STANDARD_SCRIPT_VERIFY_FLAGS , creator . Checker ( ) ) ) ;
return true ;
}
return false ;
}