@ -821,9 +821,10 @@ public:
////////////////////////////////////////////////////////////////////////////
enum class ParseScriptContext {
TOP ,
P2SH ,
P2WSH ,
TOP , //!< Top-level context (script goes directly in scriptPubKey)
P2SH , //!< Inside sh() (script becomes P2SH redeemScript)
P2WPKH , //!< Inside wpkh() (no script, pubkey only)
P2WSH , //!< Inside wsh() (script becomes v0 witness script)
} ;
/** Parse a key path, being passed a split list of elements (the first element is ignored). */
@ -850,10 +851,11 @@ enum class ParseScriptContext {
}
/** Parse a public key that excludes origin information. */
std : : unique_ptr < PubkeyProvider > ParsePubkeyInner ( uint32_t key_exp_index , const Span < const char > & sp , bool permit_uncompressed , FlatSigningProvider & out , std : : string & error )
std : : unique_ptr < PubkeyProvider > ParsePubkeyInner ( uint32_t key_exp_index , const Span < const char > & sp , ParseScriptContext ctx , FlatSigningProvider & out , std : : string & error )
{
using namespace spanparsing ;
bool permit_uncompressed = ctx = = ParseScriptContext : : TOP | | ctx = = ParseScriptContext : : P2SH ;
auto split = Split ( sp , ' / ' ) ;
std : : string str ( split [ 0 ] . begin ( ) , split [ 0 ] . end ( ) ) ;
if ( str . size ( ) = = 0 ) {
@ -911,7 +913,7 @@ std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index, const S
}
/** Parse a public key including origin information (if enabled). */
std : : unique_ptr < PubkeyProvider > ParsePubkey ( uint32_t key_exp_index , const Span < const char > & sp , bool permit_uncompressed , FlatSigningProvider & out , std : : string & error )
std : : unique_ptr < PubkeyProvider > ParsePubkey ( uint32_t key_exp_index , const Span < const char > & sp , ParseScriptContext ctx , FlatSigningProvider & out , std : : string & error )
{
using namespace spanparsing ;
@ -920,7 +922,7 @@ std::unique_ptr<PubkeyProvider> ParsePubkey(uint32_t key_exp_index, const Span<c
error = " Multiple ']' characters found for a single pubkey " ;
return nullptr ;
}
if ( origin_split . size ( ) = = 1 ) return ParsePubkeyInner ( key_exp_index , origin_split [ 0 ] , permit_uncompressed , out , error ) ;
if ( origin_split . size ( ) = = 1 ) return ParsePubkeyInner ( key_exp_index , origin_split [ 0 ] , ctx , out , error ) ;
if ( origin_split [ 0 ] . empty ( ) | | origin_split [ 0 ] [ 0 ] ! = ' [ ' ) {
error = strprintf ( " Key origin start '[ character expected but not found, got '%c' instead " ,
origin_split [ 0 ] . empty ( ) ? /** empty, implies split char */ ' ] ' : origin_split [ 0 ] [ 0 ] ) ;
@ -942,7 +944,7 @@ std::unique_ptr<PubkeyProvider> ParsePubkey(uint32_t key_exp_index, const Span<c
assert ( fpr_bytes . size ( ) = = 4 ) ;
std : : copy ( fpr_bytes . begin ( ) , fpr_bytes . end ( ) , info . fingerprint ) ;
if ( ! ParseKeyPath ( slash_split , info . path , error ) ) return nullptr ;
auto provider = ParsePubkeyInner ( key_exp_index , origin_split [ 1 ] , permit_uncompressed , out , error ) ;
auto provider = ParsePubkeyInner ( key_exp_index , origin_split [ 1 ] , ctx , out , error ) ;
if ( ! provider ) return nullptr ;
return std : : make_unique < OriginPubkeyProvider > ( key_exp_index , std : : move ( info ) , std : : move ( provider ) ) ;
}
@ -955,19 +957,19 @@ std::unique_ptr<DescriptorImpl> ParseScript(uint32_t& key_exp_index, Span<const
auto expr = Expr ( sp ) ;
bool sorted_multi = false ;
if ( Func ( " pk " , expr ) ) {
auto pubkey = ParsePubkey ( key_exp_index , expr , ctx ! = ParseScriptContext : : P2WSH , out , error ) ;
auto pubkey = ParsePubkey ( key_exp_index , expr , ctx , out , error ) ;
if ( ! pubkey ) return nullptr ;
+ + key_exp_index ;
return std : : make_unique < PKDescriptor > ( std : : move ( pubkey ) ) ;
}
if ( Func ( " pkh " , expr ) ) {
auto pubkey = ParsePubkey ( key_exp_index , expr , ctx ! = ParseScriptContext : : P2WSH , out , error ) ;
auto pubkey = ParsePubkey ( key_exp_index , expr , ctx , out , error ) ;
if ( ! pubkey ) return nullptr ;
+ + key_exp_index ;
return std : : make_unique < PKHDescriptor > ( std : : move ( pubkey ) ) ;
}
if ( ctx = = ParseScriptContext : : TOP & & Func ( " combo " , expr ) ) {
auto pubkey = ParsePubkey ( key_exp_index , expr , true , out , error ) ;
auto pubkey = ParsePubkey ( key_exp_index , expr , ctx , out , error ) ;
if ( ! pubkey ) return nullptr ;
+ + key_exp_index ;
return std : : make_unique < ComboDescriptor > ( std : : move ( pubkey ) ) ;
@ -990,7 +992,7 @@ std::unique_ptr<DescriptorImpl> ParseScript(uint32_t& key_exp_index, Span<const
return nullptr ;
}
auto arg = Expr ( expr ) ;
auto pk = ParsePubkey ( key_exp_index , arg , ctx ! = ParseScriptContext : : P2WSH , out , error ) ;
auto pk = ParsePubkey ( key_exp_index , arg , ctx , out , error ) ;
if ( ! pk ) return nullptr ;
script_size + = pk - > GetSize ( ) + 1 ;
providers . emplace_back ( std : : move ( pk ) ) ;
@ -1021,7 +1023,7 @@ std::unique_ptr<DescriptorImpl> ParseScript(uint32_t& key_exp_index, Span<const
return std : : make_unique < MultisigDescriptor > ( thres , std : : move ( providers ) , sorted_multi ) ;
}
if ( ctx ! = ParseScriptContext : : P2WSH & & Func ( " wpkh " , expr ) ) {
auto pubkey = ParsePubkey ( key_exp_index , expr , false , out , error ) ;
auto pubkey = ParsePubkey ( key_exp_index , expr , ParseScriptContext : : P2WPKH , out , error ) ;
if ( ! pubkey ) return nullptr ;
key_exp_index + + ;
return std : : make_unique < WPKHDescriptor > ( std : : move ( pubkey ) ) ;