Skip to content

Commit

Permalink
feat<node>: add descriptor support in createmultisig rpc
Browse files Browse the repository at this point in the history
  • Loading branch information
Vasu-08 committed Aug 16, 2023
1 parent 6279a6d commit b2c2af0
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 13 deletions.
60 changes: 47 additions & 13 deletions lib/node/rpc.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,15 @@ const TX = require('../primitives/tx');
const consensus = require('../protocol/consensus');
const pkg = require('../pkg');
const {filters} = require('../blockstore/common');
const {createChecksum} = require('../descriptor/common');
const MultisigDescriptor = require('../descriptor/type/multisig');
const SHDescriptor = require('../descriptor/type/sh');
const WSHDescriptor = require('../descriptor/type/wsh');
const {parse} = require('../descriptor/parser');
const RPCBase = bweb.RPC;
const RPCError = bweb.RPCError;
const {
createChecksum, outputTypes, scriptContext
} = require('../descriptor/common');

/*
* Constants
Expand Down Expand Up @@ -2050,17 +2055,28 @@ class RPC extends RPCBase {
*/

async createMultisig(args, help) {
if (help || args.length < 2 || args.length > 2) {
if (help || args.length < 2 || args.length > 3) {
throw new RPCError(errs.MISC_ERROR,
'createmultisig nrequired ["key",...]');
'createmultisig nrequired ["key",...] (address_type)');
}

const valid = new Validator(args);
const keys = valid.array(1, []);
let outputType = valid.str(2);

if (outputType === null) {
outputType = outputTypes.LEGACY;

Check warning on line 2068 in lib/node/rpc.js

View check run for this annotation

Codecov / codecov/patch

lib/node/rpc.js#L2068

Added line #L2068 was not covered by tests
}

assert(
Object.values(outputTypes).includes(outputType),
`Unknown address type '${outputType}'.`
);

const m = valid.u32(0, 0);
const n = keys.length;

if (m < 1 || n < m || n > 16)
if (m < 1 || n < m || n > 20)
throw new RPCError(errs.INVALID_PARAMETER, 'Invalid m and n values.');

const items = new Validator(keys);
Expand All @@ -2074,21 +2090,39 @@ class RPC extends RPCBase {
if (!secp256k1.publicKeyVerify(key))
throw new RPCError(errs.INVALID_ADDRESS_OR_KEY, 'Invalid key.');

keys[i] = key;
keys[i] = items.str(i, '');
}

const script = Script.fromMultisig(m, n, keys, true, false);
const {P2SH, P2WSH} = scriptContext;
const context = outputType === outputType.LEGACY ? P2SH : P2WSH;

if (script.getSize() > consensus.MAX_SCRIPT_PUSH) {
throw new RPCError(errs.VERIFY_ERROR,
'Redeem script exceeds size limit.');
}
const subdesc = MultisigDescriptor.fromString(
`multi(${m},${keys.join(',')})`, this.network, context
);

const addr = script.getAddress();
let descriptor;

const options = {
subdescriptors: [subdesc], network: this.network
};

switch (outputType) {
case outputTypes.LEGACY:
descriptor = SHDescriptor.fromOptions(options);
break;

Check warning on line 2112 in lib/node/rpc.js

View check run for this annotation

Codecov / codecov/patch

lib/node/rpc.js#L2111-L2112

Added lines #L2111 - L2112 were not covered by tests
case outputTypes.BECH32:
descriptor = WSHDescriptor.fromOptions(options);
break;

Check warning on line 2115 in lib/node/rpc.js

View check run for this annotation

Codecov / codecov/patch

lib/node/rpc.js#L2114-L2115

Added lines #L2114 - L2115 were not covered by tests
case outputTypes.P2SH_SEGWIT: {
options.subdescriptors = [WSHDescriptor.fromOptions(options)];
descriptor = SHDescriptor.fromOptions(options);
}
}

return {
address: addr.toString(this.network),
redeemScript: script.toJSON()
address: descriptor.getAddresses(0)[0],
redeemScript: subdesc.generateScripts(0)[0].toJSON(),
descriptor: descriptor.toString()
};
}

Expand Down
35 changes: 35 additions & 0 deletions test/node-rpc-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,41 @@ describe('RPC', function() {
}
});

it('should rpc createmultisig', async () => {
const data = [
{
'm': 4,
'keys': [
'02f293c4d026a536a082453f8327f305ae0a0c59350b396205e15fbec2af67390b',
'03d7b6a7e972f6e1a532f9f49a7cc35055a0ffd7cec5f81728f6a3fdf4dad93672',
'021f360d51b8eb43422fe942c837ad16e36bab87c5f7567609de9a38e205fb51ed',
'03a778eaee9cc18a4e5e02a78f403082d4e6f3a9c0d9edaea20b9ad86089de7fc9',
'02a3c95e41e8272c6842df8c9da492ef5e03bbc4ca17c22ce1f88570e716e187db',
'032e1d465bc5cdea674337934fb861d097dd7ab20289e4d41de14a6cafcd61d30a',
'0370fd35da88778a805ce9acc88c0020e3b14cacaa30f99d829207e1896d782ea1',
'03878a4b831af4fee069964448ccca999071633fcc751d296e8c5325167274febf',
'0248f8621596029568070dda40bc1e3ace78df320b5ebf0d6a431536e9af3ec894',
'03f757260835b7e439b244a9b10f5645966d7dcff9d2648c400a0d6827f4a64ac4',
'023b3972554e123985b6c3d8575e6fd3384f59a58ef91e0d39ba5905dad49e7372',
'02e32652928f21764e02822d39ffd1075c428e372a06fe7247023d5b60f1d01596',
'020e002818c48b1d1766f6196e09db90f51e155bbd49be0ad743d1fa6b7e8efcae',
'03725d482f0c77f4feb1ecbea28f036b30889f462222002e88aa8f8346dce94474'
],
'address_type': 'p2sh-segwit',
'result': {
'address': '2N5YHZJYNqXqCwiX2FTQ9ZgwCoW4qksY2CE',
'redeemScript': '542102f293c4d026a536a082453f8327f305ae0a0c59350b396205e15fbec2af67390b2103d7b6a7e972f6e1a532f9f49a7cc35055a0ffd7cec5f81728f6a3fdf4dad9367221021f360d51b8eb43422fe942c837ad16e36bab87c5f7567609de9a38e205fb51ed2103a778eaee9cc18a4e5e02a78f403082d4e6f3a9c0d9edaea20b9ad86089de7fc92102a3c95e41e8272c6842df8c9da492ef5e03bbc4ca17c22ce1f88570e716e187db21032e1d465bc5cdea674337934fb861d097dd7ab20289e4d41de14a6cafcd61d30a210370fd35da88778a805ce9acc88c0020e3b14cacaa30f99d829207e1896d782ea12103878a4b831af4fee069964448ccca999071633fcc751d296e8c5325167274febf210248f8621596029568070dda40bc1e3ace78df320b5ebf0d6a431536e9af3ec8942103f757260835b7e439b244a9b10f5645966d7dcff9d2648c400a0d6827f4a64ac421023b3972554e123985b6c3d8575e6fd3384f59a58ef91e0d39ba5905dad49e73722102e32652928f21764e02822d39ffd1075c428e372a06fe7247023d5b60f1d0159621020e002818c48b1d1766f6196e09db90f51e155bbd49be0ad743d1fa6b7e8efcae2103725d482f0c77f4feb1ecbea28f036b30889f462222002e88aa8f8346dce944745eae',
'descriptor': 'sh(wsh(multi(4,02f293c4d026a536a082453f8327f305ae0a0c59350b396205e15fbec2af67390b,03d7b6a7e972f6e1a532f9f49a7cc35055a0ffd7cec5f81728f6a3fdf4dad93672,021f360d51b8eb43422fe942c837ad16e36bab87c5f7567609de9a38e205fb51ed,03a778eaee9cc18a4e5e02a78f403082d4e6f3a9c0d9edaea20b9ad86089de7fc9,02a3c95e41e8272c6842df8c9da492ef5e03bbc4ca17c22ce1f88570e716e187db,032e1d465bc5cdea674337934fb861d097dd7ab20289e4d41de14a6cafcd61d30a,0370fd35da88778a805ce9acc88c0020e3b14cacaa30f99d829207e1896d782ea1,03878a4b831af4fee069964448ccca999071633fcc751d296e8c5325167274febf,0248f8621596029568070dda40bc1e3ace78df320b5ebf0d6a431536e9af3ec894,03f757260835b7e439b244a9b10f5645966d7dcff9d2648c400a0d6827f4a64ac4,023b3972554e123985b6c3d8575e6fd3384f59a58ef91e0d39ba5905dad49e7372,02e32652928f21764e02822d39ffd1075c428e372a06fe7247023d5b60f1d01596,020e002818c48b1d1766f6196e09db90f51e155bbd49be0ad743d1fa6b7e8efcae,03725d482f0c77f4feb1ecbea28f036b30889f462222002e88aa8f8346dce94474)))#a880m646'
}
}
];

for (const test of data) {
const result = test.address_type ? await nclient.execute('createmultisig', [test.m, test.keys, test.address_type]) : await nclient.execute('createmultisig', [test.m, test.keys, test.address_type]);
assert.deepStrictEqual(result, test.result);
}
});

it('should rpc getblockhash', async () => {
const info = await nclient.execute('getblockhash', [node.chain.tip.height]);
assert.strictEqual(util.revHex(node.chain.tip.hash), info);
Expand Down

0 comments on commit b2c2af0

Please sign in to comment.