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 <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
2018-05-20 16:47:14 -04:00
MutableTransactionSignatureCreator : : MutableTransactionSignatureCreator ( const CMutableTransaction * txToIn , unsigned int nInIn , const CAmount & amountIn , int nHashTypeIn ) : txTo ( txToIn ) , nIn ( nInIn ) , nHashType ( nHashTypeIn ) , amount ( amountIn ) , checker ( txTo , nIn , amountIn ) { }
2014-11-04 15:06:20 -03:00
2018-05-20 16:47:14 -04:00
bool MutableTransactionSignatureCreator : : CreateSig ( const SigningProvider & provider , std : : vector < unsigned char > & vchSig , const CKeyID & address , const CScript & scriptCode , SigVersion sigversion ) const
2014-08-27 11:22:33 -04:00
{
CKey key ;
2018-03-27 17:15:10 -03:00
if ( ! provider . 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
2018-03-09 11:03:40 -03:00
if ( sigversion = = SigVersion : : WITNESS_V0 & & ! key . IsCompressed ( ) )
2016-10-01 14:19:33 -03:00
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
2018-06-08 00:12:25 -04:00
static bool GetCScript ( const SigningProvider & provider , const SignatureData & sigdata , const CScriptID & scriptid , CScript & script )
{
if ( provider . GetCScript ( scriptid , script ) ) {
return true ;
}
// Look for scripts in SignatureData
if ( CScriptID ( sigdata . redeem_script ) = = scriptid ) {
script = sigdata . redeem_script ;
return true ;
} else if ( CScriptID ( sigdata . witness_script ) = = scriptid ) {
script = sigdata . witness_script ;
return true ;
}
return false ;
}
2018-06-27 19:56:30 -04:00
static bool GetPubKey ( const SigningProvider & provider , SignatureData & sigdata , const CKeyID & address , CPubKey & pubkey )
2018-06-08 00:12:25 -04:00
{
if ( provider . GetPubKey ( address , pubkey ) ) {
2018-06-27 19:56:30 -04:00
sigdata . misc_pubkeys . emplace ( pubkey . GetID ( ) , pubkey ) ;
2018-06-08 00:12:25 -04:00
return true ;
}
// Look for pubkey in all partial sigs
const auto it = sigdata . signatures . find ( address ) ;
if ( it ! = sigdata . signatures . end ( ) ) {
pubkey = it - > second . first ;
return true ;
}
2018-06-27 19:56:30 -04:00
// Look for pubkey in pubkey list
const auto & pk_it = sigdata . misc_pubkeys . find ( address ) ;
if ( pk_it ! = sigdata . misc_pubkeys . end ( ) ) {
pubkey = pk_it - > second ;
return true ;
}
2018-06-08 00:12:25 -04:00
return false ;
}
static bool CreateSig ( const BaseSignatureCreator & creator , SignatureData & sigdata , const SigningProvider & provider , std : : vector < unsigned char > & sig_out , const CKeyID & keyid , const CScript & scriptcode , SigVersion sigversion )
{
const auto it = sigdata . signatures . find ( keyid ) ;
if ( it ! = sigdata . signatures . end ( ) ) {
sig_out = it - > second . second ;
return true ;
}
2018-06-27 19:56:30 -04:00
CPubKey pubkey ;
GetPubKey ( provider , sigdata , keyid , pubkey ) ;
2018-06-08 00:12:25 -04:00
if ( creator . CreateSig ( provider , sig_out , keyid , scriptcode , sigversion ) ) {
auto i = sigdata . signatures . emplace ( keyid , SigPair ( pubkey , sig_out ) ) ;
assert ( i . second ) ;
return true ;
}
return false ;
}
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 .
*/
2018-03-27 17:15:10 -03:00
static bool SignStep ( const SigningProvider & provider , const BaseSignatureCreator & creator , const CScript & scriptPubKey ,
2018-06-08 00:12:25 -04:00
std : : vector < valtype > & ret , txnouttype & whichTypeRet , SigVersion sigversion , SignatureData & sigdata )
2014-08-27 11:22:33 -04:00
{
2016-03-31 09:54:58 -03:00
CScript scriptRet ;
uint160 h160 ;
ret . clear ( ) ;
2018-06-09 15:06:25 -04:00
std : : vector < unsigned char > sig ;
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 ;
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 :
2018-06-08 00:12:25 -04:00
if ( ! CreateSig ( creator , sigdata , provider , sig , CPubKey ( vSolutions [ 0 ] ) . GetID ( ) , scriptPubKey , sigversion ) ) return false ;
2018-06-09 15:06:25 -04:00
ret . push_back ( std : : move ( sig ) ) ;
2014-08-27 11:22:33 -04:00
return true ;
2018-06-09 15:06:25 -04:00
case TX_PUBKEYHASH : {
CKeyID keyID = CKeyID ( uint160 ( vSolutions [ 0 ] ) ) ;
2018-06-08 00:12:25 -04:00
if ( ! CreateSig ( creator , sigdata , provider , sig , keyID , scriptPubKey , sigversion ) ) return false ;
2018-06-09 15:06:25 -04:00
ret . push_back ( std : : move ( sig ) ) ;
CPubKey pubkey ;
2018-06-08 00:12:25 -04:00
GetPubKey ( provider , sigdata , keyID , pubkey ) ;
2018-06-09 15:06:25 -04:00
ret . push_back ( ToByteVector ( pubkey ) ) ;
return true ;
}
2014-08-27 11:22:33 -04:00
case TX_SCRIPTHASH :
2018-06-08 00:12:25 -04:00
if ( GetCScript ( provider , sigdata , uint160 ( vSolutions [ 0 ] ) , scriptRet ) ) {
2016-03-31 09:54:58 -03:00
ret . push_back ( std : : vector < unsigned char > ( scriptRet . begin ( ) , scriptRet . end ( ) ) ) ;
return true ;
}
return false ;
2014-08-27 11:22:33 -04:00
2018-06-09 15:06:25 -04:00
case TX_MULTISIG : {
size_t required = vSolutions . front ( ) [ 0 ] ;
2016-03-31 09:54:58 -03:00
ret . push_back ( valtype ( ) ) ; // workaround CHECKMULTISIG bug
2018-06-09 15:06:25 -04:00
for ( size_t i = 1 ; i < vSolutions . size ( ) - 1 ; + + i ) {
CPubKey pubkey = CPubKey ( vSolutions [ i ] ) ;
2018-06-08 00:12:25 -04:00
if ( ret . size ( ) < required + 1 & & CreateSig ( creator , sigdata , provider , sig , pubkey . GetID ( ) , scriptPubKey , sigversion ) ) {
2018-06-09 15:06:25 -04:00
ret . push_back ( std : : move ( sig ) ) ;
}
}
bool ok = ret . size ( ) = = required + 1 ;
for ( size_t i = 0 ; i + ret . size ( ) < required + 1 ; + + i ) {
ret . push_back ( valtype ( ) ) ;
}
return ok ;
}
2016-03-31 09:54:58 -03:00
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 ( ) ) ;
2018-06-08 00:12:25 -04:00
if ( GetCScript ( provider , sigdata , h160 , scriptRet ) ) {
2016-03-31 09:54:58 -03:00
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 ;
}
2018-03-27 17:15:10 -03:00
bool ProduceSignature ( const SigningProvider & provider , const BaseSignatureCreator & creator , const CScript & fromPubKey , SignatureData & sigdata )
2016-03-31 09:54:58 -03:00
{
2018-07-03 20:18:52 -04:00
if ( sigdata . complete ) return true ;
2016-03-31 09:54:58 -03:00
std : : vector < valtype > result ;
2014-08-27 11:22:33 -04:00
txnouttype whichType ;
2018-06-08 00:12:25 -04:00
bool solved = SignStep ( provider , creator , fromPubKey , result , whichType , SigVersion : : BASE , sigdata ) ;
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 ( ) ) ;
2018-06-08 00:12:25 -04:00
sigdata . redeem_script = subscript ;
solved = solved & & SignStep ( provider , creator , subscript , result , whichType , SigVersion : : BASE , sigdata ) & & 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 ;
2018-06-08 00:12:25 -04:00
solved = solved & & SignStep ( provider , creator , witnessscript , result , subType , SigVersion : : WITNESS_V0 , sigdata ) ;
2016-03-31 09:54:58 -03:00
sigdata . scriptWitness . stack = result ;
2018-06-27 19:56:30 -04:00
sigdata . witness = true ;
2016-03-31 09:54:58 -03:00
result . clear ( ) ;
}
else if ( solved & & whichType = = TX_WITNESS_V0_SCRIPTHASH )
{
CScript witnessscript ( result [ 0 ] . begin ( ) , result [ 0 ] . end ( ) ) ;
2018-06-08 00:12:25 -04:00
sigdata . witness_script = witnessscript ;
2016-03-31 09:54:58 -03:00
txnouttype subType ;
2018-06-08 00:12:25 -04:00
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 ;
2016-03-31 09:54:58 -03:00
result . push_back ( std : : vector < unsigned char > ( witnessscript . begin ( ) , witnessscript . end ( ) ) ) ;
sigdata . scriptWitness . stack = result ;
2018-06-27 19:56:30 -04:00
sigdata . witness = true ;
2016-03-31 09:54:58 -03:00
result . clear ( ) ;
2018-06-27 19:56:30 -04:00
} else if ( solved & & whichType = = TX_WITNESS_UNKNOWN ) {
sigdata . witness = true ;
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
2018-07-03 20:18:52 -04:00
sigdata . complete = solved & & VerifyScript ( sigdata . scriptSig , fromPubKey , & sigdata . scriptWitness , STANDARD_SCRIPT_VERIFY_FLAGS , creator . Checker ( ) ) ;
return sigdata . complete ;
}
2018-06-28 21:56:34 -04:00
bool SignPSBTInput ( const SigningProvider & provider , const CMutableTransaction & tx , PSBTInput & input , SignatureData & sigdata , int index , int sighash )
{
// if this input has a final scriptsig or scriptwitness, don't do anything with it
if ( ! input . final_script_sig . empty ( ) | | ! input . final_script_witness . IsNull ( ) ) {
return true ;
}
// Fill SignatureData with input info
input . FillSignatureData ( sigdata ) ;
// Get UTXO
CTxOut utxo ;
if ( input . non_witness_utxo ) {
utxo = input . non_witness_utxo - > vout [ tx . vin [ index ] . prevout . n ] ;
} else if ( ! input . witness_utxo . IsNull ( ) ) {
utxo = input . witness_utxo ;
} else {
return false ;
}
MutableTransactionSignatureCreator creator ( & tx , index , utxo . nValue , sighash ) ;
bool sig_complete = ProduceSignature ( provider , creator , utxo . scriptPubKey , sigdata ) ;
input . FromSignatureData ( sigdata ) ;
return sig_complete ;
}
2018-07-03 20:18:52 -04:00
class SignatureExtractorChecker final : public BaseSignatureChecker
{
private :
SignatureData & sigdata ;
BaseSignatureChecker & checker ;
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 SignatureExtractorChecker : : CheckSig ( const std : : vector < unsigned char > & scriptSig , const std : : vector < unsigned char > & vchPubKey , const CScript & scriptCode , SigVersion sigversion ) const
{
if ( checker . CheckSig ( scriptSig , vchPubKey , scriptCode , sigversion ) ) {
CPubKey pubkey ( vchPubKey ) ;
sigdata . signatures . emplace ( pubkey . GetID ( ) , SigPair ( pubkey , scriptSig ) ) ;
return true ;
}
return false ;
}
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 ;
}
} ;
2016-03-31 09:54:58 -03:00
}
2018-07-03 20:18:52 -04:00
// Extracts signatures and scripts from incomplete scriptSigs. Please do not extend this, use PSBT instead
SignatureData DataFromTransaction ( const CMutableTransaction & tx , unsigned int nIn , const CTxOut & txout )
2016-03-31 09:54:58 -03:00
{
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 ;
2018-07-03 20:18:52 -04:00
Stacks stack ( data ) ;
// Get signatures
MutableTransactionSignatureChecker tx_checker ( & tx , nIn , txout . nValue ) ;
SignatureExtractorChecker extractor_checker ( data , tx_checker ) ;
if ( VerifyScript ( data . scriptSig , txout . scriptPubKey , & data . scriptWitness , STANDARD_SCRIPT_VERIFY_FLAGS , extractor_checker ) ) {
data . complete = true ;
return data ;
}
// Get scripts
txnouttype script_type ;
std : : vector < std : : vector < unsigned char > > solutions ;
Solver ( txout . scriptPubKey , script_type , solutions ) ;
SigVersion sigversion = SigVersion : : BASE ;
CScript next_script = txout . scriptPubKey ;
if ( script_type = = TX_SCRIPTHASH & & ! stack . script . empty ( ) & & ! stack . script . back ( ) . empty ( ) ) {
// Get the redeemScript
CScript redeem_script ( stack . script . back ( ) . begin ( ) , stack . script . back ( ) . end ( ) ) ;
data . redeem_script = redeem_script ;
next_script = std : : move ( redeem_script ) ;
// Get redeemScript type
Solver ( next_script , script_type , solutions ) ;
stack . script . pop_back ( ) ;
}
if ( script_type = = TX_WITNESS_V0_SCRIPTHASH & & ! stack . witness . empty ( ) & & ! stack . witness . back ( ) . empty ( ) ) {
// Get the witnessScript
CScript witness_script ( stack . witness . back ( ) . begin ( ) , stack . witness . back ( ) . end ( ) ) ;
data . witness_script = witness_script ;
next_script = std : : move ( witness_script ) ;
// Get witnessScript type
Solver ( next_script , script_type , solutions ) ;
stack . witness . pop_back ( ) ;
stack . script = std : : move ( stack . witness ) ;
stack . witness . clear ( ) ;
sigversion = SigVersion : : WITNESS_V0 ;
}
if ( script_type = = TX_MULTISIG & & ! stack . script . empty ( ) ) {
// Build a map of pubkey -> signature by matching sigs to pubkeys:
assert ( solutions . size ( ) > 1 ) ;
unsigned int num_pubkeys = solutions . size ( ) - 2 ;
unsigned int last_success_key = 0 ;
for ( const valtype & sig : stack . script ) {
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 ) ) {
last_success_key = i + 1 ;
break ;
}
}
}
}
2016-03-31 09:54:58 -03:00
return data ;
}
2018-03-05 18:37:24 -03:00
void UpdateInput ( CTxIn & input , const SignatureData & data )
{
input . scriptSig = data . scriptSig ;
input . scriptWitness = data . scriptWitness ;
}
2018-06-08 00:12:25 -04:00
void SignatureData : : MergeSignatureData ( SignatureData sigdata )
{
if ( complete ) return ;
if ( sigdata . complete ) {
* this = std : : move ( sigdata ) ;
return ;
}
if ( redeem_script . empty ( ) & & ! sigdata . redeem_script . empty ( ) ) {
redeem_script = sigdata . redeem_script ;
}
if ( witness_script . empty ( ) & & ! sigdata . witness_script . empty ( ) ) {
witness_script = sigdata . witness_script ;
}
signatures . insert ( std : : make_move_iterator ( sigdata . signatures . begin ( ) ) , std : : make_move_iterator ( sigdata . signatures . end ( ) ) ) ;
}
2018-03-17 23:19:09 -03:00
bool SignSignature ( const SigningProvider & provider , 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 ( ) ) ;
2018-05-20 16:47:14 -04:00
MutableTransactionSignatureCreator creator ( & txTo , nIn , amount , nHashType ) ;
2014-11-04 15:06:20 -03:00
2016-03-31 09:54:58 -03:00
SignatureData sigdata ;
2018-03-27 17:15:10 -03:00
bool ret = ProduceSignature ( provider , creator , fromPubKey , sigdata ) ;
2018-05-17 20:54:18 -04:00
UpdateInput ( txTo . vin . at ( nIn ) , sigdata ) ;
2016-03-31 09:54:58 -03:00
return ret ;
2014-08-27 11:22:33 -04:00
}
2018-03-17 23:19:09 -03:00
bool SignSignature ( const SigningProvider & provider , const CTransaction & txFrom , CMutableTransaction & txTo , unsigned int nIn , int nHashType )
2014-08-27 11:22:33 -04:00
{
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 ] ;
2018-03-17 23:19:09 -03:00
return SignSignature ( provider , txout . scriptPubKey , txTo , nIn , txout . nValue , nHashType ) ;
2014-08-27 11:22:33 -04:00
}
2015-05-01 10:21:06 -03:00
namespace {
/** Dummy signature checker which accepts all signatures. */
2018-03-27 17:34:39 -03:00
class DummySignatureChecker final : public BaseSignatureChecker
2015-05-01 10:21:06 -03:00
{
public :
DummySignatureChecker ( ) { }
2018-03-27 17:34:39 -03:00
bool CheckSig ( const std : : vector < unsigned char > & scriptSig , const std : : vector < unsigned char > & vchPubKey , const CScript & scriptCode , SigVersion sigversion ) const override { return true ; }
} ;
const DummySignatureChecker DUMMY_CHECKER ;
2015-05-01 10:21:06 -03:00
2018-03-27 17:34:39 -03:00
class DummySignatureCreator final : public BaseSignatureCreator {
public :
DummySignatureCreator ( ) { }
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
2015-05-01 10:21:06 -03:00
{
2018-03-27 17:34:39 -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 ;
2015-05-01 10:21:06 -03:00
return true ;
}
} ;
}
2018-03-27 17:34:39 -03:00
const BaseSignatureCreator & DUMMY_SIGNATURE_CREATOR = DummySignatureCreator ( ) ;
2018-06-08 00:12:25 -04:00
const SigningProvider & DUMMY_SIGNING_PROVIDER = SigningProvider ( ) ;
2017-11-30 21:48:31 -03:00
2018-03-17 23:19:09 -03:00
bool IsSolvable ( const SigningProvider & provider , const CScript & script )
2017-11-30 21:48:31 -03:00
{
// 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.
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 " ) ;
2018-03-27 17:34:39 -03:00
if ( ProduceSignature ( provider , DUMMY_SIGNATURE_CREATOR , script , sigs ) ) {
2017-11-30 21:48:31 -03:00
// VerifyScript check is just defensive, and should never fail.
2018-03-27 17:34:39 -03:00
assert ( VerifyScript ( sigs . scriptSig , script , & sigs . scriptWitness , STANDARD_SCRIPT_VERIFY_FLAGS , DUMMY_CHECKER ) ) ;
2017-11-30 21:48:31 -03:00
return true ;
}
return false ;
}
2018-06-27 19:53:48 -04:00
bool PartiallySignedTransaction : : IsNull ( ) const
{
return ! tx & & inputs . empty ( ) & & outputs . empty ( ) & & unknown . empty ( ) ;
}
2018-06-27 19:58:01 -04:00
void PartiallySignedTransaction : : Merge ( const PartiallySignedTransaction & psbt )
{
for ( unsigned int i = 0 ; i < inputs . size ( ) ; + + i ) {
inputs [ i ] . Merge ( psbt . inputs [ i ] ) ;
}
for ( unsigned int i = 0 ; i < outputs . size ( ) ; + + i ) {
outputs [ i ] . Merge ( psbt . outputs [ i ] ) ;
}
}
bool PartiallySignedTransaction : : IsSane ( ) const
{
for ( PSBTInput input : inputs ) {
if ( ! input . IsSane ( ) ) return false ;
}
return true ;
}
2018-06-27 19:53:48 -04:00
bool PSBTInput : : IsNull ( ) const
{
return ! non_witness_utxo & & witness_utxo . IsNull ( ) & & partial_sigs . empty ( ) & & unknown . empty ( ) & & hd_keypaths . empty ( ) & & redeem_script . empty ( ) & & witness_script . empty ( ) ;
}
2018-06-27 19:58:01 -04:00
void PSBTInput : : FillSignatureData ( SignatureData & sigdata ) const
{
if ( ! final_script_sig . empty ( ) ) {
sigdata . scriptSig = final_script_sig ;
sigdata . complete = true ;
}
if ( ! final_script_witness . IsNull ( ) ) {
sigdata . scriptWitness = final_script_witness ;
sigdata . complete = true ;
}
if ( sigdata . complete ) {
return ;
}
sigdata . signatures . insert ( partial_sigs . begin ( ) , partial_sigs . end ( ) ) ;
if ( ! redeem_script . empty ( ) ) {
sigdata . redeem_script = redeem_script ;
}
if ( ! witness_script . empty ( ) ) {
sigdata . witness_script = witness_script ;
}
for ( const auto & key_pair : hd_keypaths ) {
sigdata . misc_pubkeys . emplace ( key_pair . first . GetID ( ) , key_pair . first ) ;
}
}
void PSBTInput : : FromSignatureData ( const SignatureData & sigdata )
{
if ( sigdata . complete ) {
partial_sigs . clear ( ) ;
hd_keypaths . clear ( ) ;
redeem_script . clear ( ) ;
witness_script . clear ( ) ;
if ( ! sigdata . scriptSig . empty ( ) ) {
final_script_sig = sigdata . scriptSig ;
}
if ( ! sigdata . scriptWitness . IsNull ( ) ) {
final_script_witness = sigdata . scriptWitness ;
}
return ;
}
partial_sigs . insert ( sigdata . signatures . begin ( ) , sigdata . signatures . end ( ) ) ;
if ( redeem_script . empty ( ) & & ! sigdata . redeem_script . empty ( ) ) {
redeem_script = sigdata . redeem_script ;
}
if ( witness_script . empty ( ) & & ! sigdata . witness_script . empty ( ) ) {
witness_script = sigdata . witness_script ;
}
}
void PSBTInput : : Merge ( const PSBTInput & input )
{
if ( ! non_witness_utxo & & input . non_witness_utxo ) non_witness_utxo = input . non_witness_utxo ;
if ( witness_utxo . IsNull ( ) & & ! input . witness_utxo . IsNull ( ) ) {
witness_utxo = input . witness_utxo ;
non_witness_utxo = nullptr ; // Clear out any non-witness utxo when we set a witness one.
}
partial_sigs . insert ( input . partial_sigs . begin ( ) , input . partial_sigs . end ( ) ) ;
hd_keypaths . insert ( input . hd_keypaths . begin ( ) , input . hd_keypaths . end ( ) ) ;
unknown . insert ( input . unknown . begin ( ) , input . unknown . end ( ) ) ;
if ( redeem_script . empty ( ) & & ! input . redeem_script . empty ( ) ) redeem_script = input . redeem_script ;
if ( witness_script . empty ( ) & & ! input . witness_script . empty ( ) ) witness_script = input . witness_script ;
if ( final_script_sig . empty ( ) & & ! input . final_script_sig . empty ( ) ) final_script_sig = input . final_script_sig ;
if ( final_script_witness . IsNull ( ) & & ! input . final_script_witness . IsNull ( ) ) final_script_witness = input . final_script_witness ;
}
bool PSBTInput : : IsSane ( ) const
{
// Cannot have both witness and non-witness utxos
if ( ! witness_utxo . IsNull ( ) & & non_witness_utxo ) return false ;
// If we have a witness_script or a scriptWitness, we must also have a witness utxo
if ( ! witness_script . empty ( ) & & witness_utxo . IsNull ( ) ) return false ;
if ( ! final_script_witness . IsNull ( ) & & witness_utxo . IsNull ( ) ) return false ;
return true ;
}
void PSBTOutput : : FillSignatureData ( SignatureData & sigdata ) const
{
if ( ! redeem_script . empty ( ) ) {
sigdata . redeem_script = redeem_script ;
}
if ( ! witness_script . empty ( ) ) {
sigdata . witness_script = witness_script ;
}
for ( const auto & key_pair : hd_keypaths ) {
sigdata . misc_pubkeys . emplace ( key_pair . first . GetID ( ) , key_pair . first ) ;
}
}
void PSBTOutput : : FromSignatureData ( const SignatureData & sigdata )
{
if ( redeem_script . empty ( ) & & ! sigdata . redeem_script . empty ( ) ) {
redeem_script = sigdata . redeem_script ;
}
if ( witness_script . empty ( ) & & ! sigdata . witness_script . empty ( ) ) {
witness_script = sigdata . witness_script ;
}
}
2018-06-27 19:53:48 -04:00
bool PSBTOutput : : IsNull ( ) const
{
return redeem_script . empty ( ) & & witness_script . empty ( ) & & hd_keypaths . empty ( ) & & unknown . empty ( ) ;
}
2018-06-27 19:58:01 -04:00
void PSBTOutput : : Merge ( const PSBTOutput & output )
{
hd_keypaths . insert ( output . hd_keypaths . begin ( ) , output . hd_keypaths . end ( ) ) ;
unknown . insert ( output . unknown . begin ( ) , output . unknown . end ( ) ) ;
if ( redeem_script . empty ( ) & & ! output . redeem_script . empty ( ) ) redeem_script = output . redeem_script ;
if ( witness_script . empty ( ) & & ! output . witness_script . empty ( ) ) witness_script = output . witness_script ;
}
2018-06-28 22:05:05 -04:00
bool PublicOnlySigningProvider : : GetCScript ( const CScriptID & scriptid , CScript & script ) const
{
return m_provider - > GetCScript ( scriptid , script ) ;
}
bool PublicOnlySigningProvider : : GetPubKey ( const CKeyID & address , CPubKey & pubkey ) const
{
return m_provider - > GetPubKey ( address , pubkey ) ;
}