Skip to content

Commit

Permalink
Merge pull request #731 from tynes/validateaddress-upgrade
Browse files Browse the repository at this point in the history
validateaddress and getaddressinfo RPC Update
  • Loading branch information
braydonf committed Mar 26, 2019
2 parents 2b2e53d + 6850a32 commit 01a7156
Show file tree
Hide file tree
Showing 6 changed files with 431 additions and 7 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@
#### RPC

- Bug fix addresses for the `getnewaddress` command with various networks.
- Deprecate the `ismine` and `iswatchonly` fields from the `validateaddress`
command and add `isscript`, `iswitness`, `ischange`, `witness_version`
and `witness_program` to partially match the v0.18.0 Bitcoin Core release
(26a2000b0177fd2668b7d82e5aa52829cf2bfdf6)
- Add wallet RPC `getaddressinfo` to return `ismine` and `iswatchonly`
with the correct values instead of their previous values which were
hardcoded to false. Also returns `address`, `scriptPubKey`, `isscript`,
`iswitness`, `witness_version` and `witness_program`.
(a28ffa272a3c4d90d0273d9aa223a23becc08e0e)

### Network changes

Expand Down
15 changes: 12 additions & 3 deletions lib/node/rpc.js
Original file line number Diff line number Diff line change
Expand Up @@ -2073,14 +2073,23 @@ class RPC extends RPCBase {
}

const script = Script.fromAddress(addr);
const isWitness = addr.isProgram();
const isScript = script.isScripthash() || script.isWitnessScripthash();

return {
const result = {
isvalid: true,
address: addr.toString(this.network),
scriptPubKey: script.toJSON(),
ismine: false,
iswatchonly: false
isscript: isScript,
iswitness: isWitness
};

if (isWitness) {
result.witness_version = addr.version;
result.witness_program = addr.hash.toString('hex');
}

return result;
}

async verifyMessage(args, help) {
Expand Down
35 changes: 35 additions & 0 deletions lib/wallet/rpc.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ class RPC extends RPCBase {
this.add('dumpprivkey', this.dumpPrivKey);
this.add('dumpwallet', this.dumpWallet);
this.add('encryptwallet', this.encryptWallet);
this.add('getaddressinfo', this.getAddressInfo);
this.add('getaccountaddress', this.getAccountAddress);
this.add('getaccount', this.getAccount);
this.add('getaddressesbyaccount', this.getAddressesByAccount);
Expand Down Expand Up @@ -443,6 +444,40 @@ class RPC extends RPCBase {
return addrs;
}

async getAddressInfo(args, help) {
if (help || args.length !== 1)
throw new RPCError(errs.MISC_ERROR, 'getaddressinfo "address"');

const valid = new Validator(args);
const addr = valid.str(0, '');

const address = parseAddress(addr, this.network);
const script = Script.fromAddress(address);
const wallet = this.wallet.toJSON();

const path = await this.wallet.getPath(address);

const isScript = script.isScripthash() || script.isWitnessScripthash();
const isWitness = address.isProgram();

const result = {
address: address.toString(this.network),
scriptPubKey: script ? script.toJSON() : undefined,
ismine: path != null,
ischange: path ? path.branch === 1 : false,
iswatchonly: wallet.watchOnly,
isscript: isScript,
iswitness: isWitness
};

if (isWitness) {
result.witness_version = address.version;
result.witness_program = address.hash.toString('hex');
}

return result;
}

async getBalance(args, help) {
if (help || args.length > 3) {
throw new RPCError(errs.MISC_ERROR,
Expand Down
100 changes: 98 additions & 2 deletions test/http-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ let hash = null;
describe('HTTP', function() {
this.timeout(15000);

// m/44'/1'/0'/0/{0,1}
const pubkeys = [
Buffer.from('02a7451395735369f2ecdfc829c0f'
+ '774e88ef1303dfe5b2f04dbaab30a535dfdd6', 'hex'),
Buffer.from('03589ae7c835ce76e23cf8feb32f1a'
+ 'df4a7f2ba0ed2ad70801802b0bcd70e99c1c', 'hex')
];

it('should open node', async () => {
consensus.COINBASE_MATURITY = 0;
await node.open();
Expand Down Expand Up @@ -267,8 +275,96 @@ describe('HTTP', function() {
isvalid: true,
address: addr.toString(node.network),
scriptPubKey: Script.fromAddress(addr).toRaw().toString('hex'),
ismine: false,
iswatchonly: false
iswitness: false,
isscript: false
});
});

it('should not validate invalid address', async () => {
// Valid Mainnet P2WPKH from
// https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
const json = await nclient.execute('validateaddress', [
'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'
]);

// Sending an address from the incorrect network
// should result in an invalid address
assert.deepStrictEqual(json, {
isvalid: false
});
});

it('should validate a p2wpkh address', async () => {
const address = 'bcrt1q8gk5z3dy7zv9ywe7synlrk58elz4hrnegvpv6m';
const addr = Address.fromString(address);
const script = Script.fromAddress(addr);

const json = await nclient.execute('validateaddress', [
address
]);

assert.deepStrictEqual(json, {
isvalid: true,
iswitness: true,
address: address,
isscript: addr.isScripthash(),
scriptPubKey: script.toJSON(),
witness_version: addr.version,
witness_program: addr.hash.toString('hex')
});
});

it('should validate a p2sh address', async () => {
const script = Script.fromMultisig(2, 2, pubkeys);
const address = Address.fromScript(script);

// Test the valid case - render the address to the
// correct network
{
const json = await nclient.execute('validateaddress', [
address.toString(node.network)
]);

assert.deepEqual(json, {
isvalid: true,
address: address.toString(node.network),
scriptPubKey: Script.fromAddress(address).toJSON(),
isscript: true,
iswitness: false
});
}

// Test the invalid case - render the address to the
// incorrect network, making it an invalid address
{
const json = await nclient.execute('validateaddress', [
address.toString('main')
]);

assert.deepEqual(json, {
isvalid: false
});
}
});

it('should validate a p2wsh address', async () => {
const script = Script.fromMultisig(2, 2, pubkeys);
const scriptPubKey = script.forWitness();
const program = script.sha256();
const address = Address.fromProgram(0, program);

const json = await nclient.execute('validateaddress', [
address.toString(node.network)
]);

assert.deepEqual(json, {
isvalid: true,
address: address.toString(node.network),
scriptPubKey: scriptPubKey.toJSON(),
isscript: true,
iswitness: true,
witness_version: 0,
witness_program: program.toString('hex')
});
});

Expand Down
4 changes: 2 additions & 2 deletions test/node-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -591,8 +591,8 @@ describe('Node', function() {
isvalid: true,
address: addr.toString(node.network),
scriptPubKey: Script.fromAddress(addr, node.network).toJSON(),
ismine: false,
iswatchonly: false
isscript: false,
iswitness: false
});
});

Expand Down
Loading

0 comments on commit 01a7156

Please sign in to comment.