@@ -35,10 +35,15 @@ const TX = require('../primitives/tx');
3535const consensus = require ( '../protocol/consensus' ) ;
3636const pkg = require ( '../pkg' ) ;
3737const { filters} = require ( '../blockstore/common' ) ;
38- const { createChecksum} = require ( '../descriptor/common' ) ;
38+ const MultisigDescriptor = require ( '../descriptor/type/multisig' ) ;
39+ const SHDescriptor = require ( '../descriptor/type/sh' ) ;
40+ const WSHDescriptor = require ( '../descriptor/type/wsh' ) ;
3941const { parse} = require ( '../descriptor/parser' ) ;
4042const RPCBase = bweb . RPC ;
4143const RPCError = bweb . RPCError ;
44+ const {
45+ createChecksum, outputTypes, scriptContext
46+ } = require ( '../descriptor/common' ) ;
4247
4348/*
4449 * Constants
@@ -2050,17 +2055,28 @@ class RPC extends RPCBase {
20502055 */
20512056
20522057 async createMultisig ( args , help ) {
2053- if ( help || args . length < 2 || args . length > 2 ) {
2058+ if ( help || args . length < 2 || args . length > 3 ) {
20542059 throw new RPCError ( errs . MISC_ERROR ,
2055- 'createmultisig nrequired ["key",...]' ) ;
2060+ 'createmultisig nrequired ["key",...] (address_type) ' ) ;
20562061 }
20572062
20582063 const valid = new Validator ( args ) ;
20592064 const keys = valid . array ( 1 , [ ] ) ;
2065+ let outputType = valid . str ( 2 ) ;
2066+
2067+ if ( outputType === null ) {
2068+ outputType = outputTypes . LEGACY ;
2069+ }
2070+
2071+ assert (
2072+ Object . values ( outputTypes ) . includes ( outputType ) ,
2073+ `Unknown address type '${ outputType } '.`
2074+ ) ;
2075+
20602076 const m = valid . u32 ( 0 , 0 ) ;
20612077 const n = keys . length ;
20622078
2063- if ( m < 1 || n < m || n > 16 )
2079+ if ( m < 1 || n < m || n > 20 )
20642080 throw new RPCError ( errs . INVALID_PARAMETER , 'Invalid m and n values.' ) ;
20652081
20662082 const items = new Validator ( keys ) ;
@@ -2074,21 +2090,39 @@ class RPC extends RPCBase {
20742090 if ( ! secp256k1 . publicKeyVerify ( key ) )
20752091 throw new RPCError ( errs . INVALID_ADDRESS_OR_KEY , 'Invalid key.' ) ;
20762092
2077- keys [ i ] = key ;
2093+ keys [ i ] = items . str ( i , '' ) ;
20782094 }
20792095
2080- const script = Script . fromMultisig ( m , n , keys , true , false ) ;
2096+ const { P2SH , P2WSH } = scriptContext ;
2097+ const context = outputType === outputTypes . LEGACY ? P2SH : P2WSH ;
20812098
2082- if ( script . getSize ( ) > consensus . MAX_SCRIPT_PUSH ) {
2083- throw new RPCError ( errs . VERIFY_ERROR ,
2084- 'Redeem script exceeds size limit.' ) ;
2085- }
2099+ const subdesc = MultisigDescriptor . fromString (
2100+ `multi(${ m } ,${ keys . join ( ',' ) } )` , this . network , context
2101+ ) ;
20862102
2087- const addr = script . getAddress ( ) ;
2103+ let descriptor ;
2104+
2105+ const options = {
2106+ subdescriptors : [ subdesc ] , network : this . network
2107+ } ;
2108+
2109+ switch ( outputType ) {
2110+ case outputTypes . LEGACY :
2111+ descriptor = SHDescriptor . fromOptions ( options ) ;
2112+ break ;
2113+ case outputTypes . BECH32 :
2114+ descriptor = WSHDescriptor . fromOptions ( options ) ;
2115+ break ;
2116+ case outputTypes . P2SH_SEGWIT : {
2117+ options . subdescriptors = [ WSHDescriptor . fromOptions ( options ) ] ;
2118+ descriptor = SHDescriptor . fromOptions ( options ) ;
2119+ }
2120+ }
20882121
20892122 return {
2090- address : addr . toString ( this . network ) ,
2091- redeemScript : script . toJSON ( )
2123+ address : descriptor . getAddresses ( ) [ 0 ] ,
2124+ redeemScript : subdesc . generateScripts ( ) [ 0 ] . toJSON ( ) ,
2125+ descriptor : descriptor . toString ( )
20922126 } ;
20932127 }
20942128
0 commit comments