Skip to content

Commit

Permalink
Merge PR #696 from 'pinheadmz/ports-getinfo'
Browse files Browse the repository at this point in the history
  • Loading branch information
pinheadmz committed Aug 15, 2022
2 parents bf614e0 + 69e0759 commit 3fd74e0
Show file tree
Hide file tree
Showing 5 changed files with 525 additions and 70 deletions.
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

## unreleased

### Node changes
### Node API changes

- HTTP API endpoint `/` (`hsd-cli getinfo`) now includes "public" networking settings.

- RPCs `getnameinfo` `getnameresource` `verifymessagewithname` and `getnamebyhash`
now accept an additional boolean parameter `safe` which will resolve the name from the Urkel
Expand All @@ -14,11 +16,12 @@ to these calls.
- `decoderesource` like `decodescript` accepts hex string as input and returns
JSON formatted DNS records resource.

### Wallet changes
### Wallet API changes

- New RPC methods:
- `createbatch` and `sendbatch` create batch transactions with any number
of outputs with any combination of covenants.

## v4.0.0

**When upgrading to this version of hsd you must pass
Expand Down
6 changes: 6 additions & 0 deletions lib/net/hostlist.js
Original file line number Diff line number Diff line change
Expand Up @@ -1033,6 +1033,12 @@ class HostList {

if (!src) {
for (const dest of this.local.values()) {
if (this.network.type === 'main') {
// Disable everything else for now.
if (dest.type < HostList.scores.UPNP)
continue;
}

if (dest.addr.hasKey())
continue;

Expand Down
28 changes: 19 additions & 9 deletions lib/node/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,20 @@ class HTTP extends Server {
const orphans = this.mempool ? this.mempool.orphans.size : 0;
const brontide = this.pool.hosts.brontide;

let addr = this.pool.hosts.getLocal();

if (!addr)
addr = this.pool.hosts.address;
const pub = {
listen: this.pool.options.listen,
host: null,
port: null,
brontidePort: null
};

const addr = this.pool.hosts.getLocal();

if (addr && pub.listen) {
pub.host = addr.host;
pub.port = addr.port;
pub.brontidePort = brontide.port;
}

res.json(200, {
version: pkg.version,
Expand All @@ -138,15 +148,15 @@ class HTTP extends Server {
}
},
pool: {
host: addr.host,
port: addr.port,
brontideHost: brontide.host,
brontidePort: brontide.port,
host: this.pool.options.host,
port: this.pool.options.port,
brontidePort: this.pool.options.brontidePort,
identitykey: brontide.getKey('base32'),
agent: this.pool.options.agent,
services: this.pool.options.services.toString(2),
outbound: this.pool.peers.outbound,
inbound: this.pool.peers.inbound
inbound: this.pool.peers.inbound,
public: pub
},
mempool: {
tx: totalTX,
Expand Down
273 changes: 214 additions & 59 deletions test/node-http-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,73 +19,239 @@ const mnemonics = require('./data/mnemonic-english.json');
// Commonly used test mnemonic
const phrase = mnemonics[0][1];

const network = Network.get('regtest');
const {types} = rules;

const node = new FullNode({
network: 'regtest',
apiKey: 'foo',
walletAuth: true,
memory: true,
indexTx: true,
indexAddress: true,
rejectAbsurdFees: false
});
describe('Node HTTP', function() {
describe('Networking info', function() {
it('should not have public address: regtest', async () => {
const network = Network.get('regtest');

const nclient = new NodeClient({
port: network.rpcPort,
apiKey: 'foo'
});
const node = new FullNode({
network: network.type
});

let cbAddress, privkey, pubkey;
let socketData, mempoolData;
const nclient = new NodeClient({
port: network.rpcPort
});

const {treeInterval} = network.names;
await node.open();
await node.connect();
const {pool} = await nclient.getInfo();
await node.close();

describe('Node HTTP', function() {
this.timeout(15000);
assert.strictEqual(pool.host, '0.0.0.0');
assert.strictEqual(pool.port, network.port);
assert.strictEqual(pool.brontidePort, network.brontidePort);

const {public: pub} = pool;

before(async () => {
await node.open();
await nclient.open();
await nclient.call('watch chain');
assert.strictEqual(pub.listen, false);
assert.strictEqual(pub.host, null);
assert.strictEqual(pub.port, null);
assert.strictEqual(pub.brontidePort, null);
});

it('should not have public address: regtest, listen', async () => {
const network = Network.get('regtest');

const mnemonic = Mnemonic.fromPhrase(phrase);
const priv = HDPrivateKey.fromMnemonic(mnemonic);
const type = network.keyPrefix.coinType;
const key = priv.derive(44, true).derive(type, true).derive(0, true);
const xkey = key.derive(0).derive(0);
const node = new FullNode({
network: network.type,
listen: true
});

pubkey = xkey.publicKey;
privkey = xkey.privateKey;
const nclient = new NodeClient({
port: network.rpcPort
});

cbAddress = Address.fromPubkey(pubkey).toString(network.type);
await node.open();
await node.connect();
const {pool} = await nclient.getInfo();
await node.close();

nclient.bind('tree commit', (root, entry, block) => {
assert.ok(root);
assert.ok(block);
assert.ok(entry);
assert.strictEqual(pool.host, '0.0.0.0');
assert.strictEqual(pool.port, network.port);
assert.strictEqual(pool.brontidePort, network.brontidePort);

socketData.push({root, entry, block});
const {public: pub} = pool;

assert.strictEqual(pub.listen, true);
assert.strictEqual(pub.host, null); // we don't discover from external
assert.strictEqual(pub.port, null);
assert.strictEqual(pub.brontidePort, null);
});

node.mempool.on('tx', (tx) => {
mempoolData[tx.txid()] = true;
it('should not have public address: main', async () => {
const network = Network.get('main');

const node = new FullNode({
network: network.type
});

const nclient = new NodeClient({
port: network.rpcPort
});

await node.open();
await node.connect();
const {pool} = await nclient.getInfo();
await node.close();

assert.strictEqual(pool.host, '0.0.0.0');
assert.strictEqual(pool.port, network.port);
assert.strictEqual(pool.brontidePort, network.brontidePort);

const {public: pub} = pool;

assert.strictEqual(pub.listen, false);
assert.strictEqual(pub.host, null);
assert.strictEqual(pub.port, null);
assert.strictEqual(pub.brontidePort, null);
});
});

beforeEach(() => {
socketData = [];
mempoolData = {};
});
it('should not have public address: main, listen', async () => {
const network = Network.get('main');

const node = new FullNode({
network: network.type,
listen: true
});

const nclient = new NodeClient({
port: network.rpcPort
});

await node.open();
await node.connect();
const {pool} = await nclient.getInfo();
await node.close();

after(async () => {
await nclient.close();
await node.close();
assert.strictEqual(pool.host, '0.0.0.0');
assert.strictEqual(pool.port, network.port);
assert.strictEqual(pool.brontidePort, network.brontidePort);

const {public: pub} = pool;

assert.strictEqual(pub.listen, true);
assert.strictEqual(pub.host, null);
assert.strictEqual(pub.port, null);
assert.strictEqual(pub.brontidePort, null);
});

it('should have public address: main, listen, publicHost', async () => {
const network = Network.get('main');
const publicHost = '100.200.11.22';
const publicPort = 11111;
const publicBrontidePort = 22222;

const node = new FullNode({
network: network.type,
listen: true,
publicHost,
publicPort,
publicBrontidePort
});

const nclient = new NodeClient({
port: network.rpcPort
});

await node.open();
await node.connect();
const {pool} = await nclient.getInfo();
await node.close();

assert.strictEqual(pool.host, '0.0.0.0');
assert.strictEqual(pool.port, network.port);
assert.strictEqual(pool.brontidePort, network.brontidePort);

const {public: pub} = pool;

assert.strictEqual(pub.listen, true);
assert.strictEqual(pub.host, publicHost);
assert.strictEqual(pub.port, publicPort);
assert.strictEqual(pub.brontidePort, publicBrontidePort);
});
});

describe('Websockets', function () {
this.timeout(15000);

describe('tree commit', () => {
const network = Network.get('regtest');
const {types} = rules;

const node = new FullNode({
network: 'regtest',
apiKey: 'foo',
walletAuth: true,
memory: true,
indexTx: true,
indexAddress: true,
rejectAbsurdFees: false
});

const nclient = new NodeClient({
port: network.rpcPort,
apiKey: 'foo'
});

const {treeInterval} = network.names;

let privkey, pubkey;
let socketData, mempoolData;
let cbAddress;

// take into account race conditions
async function mineBlocks(count, address) {
for (let i = 0; i < count; i++) {
const obj = { complete: false };
node.once('block', () => {
obj.complete = true;
});
await nclient.execute('generatetoaddress', [1, address]);
await common.forValue(obj, 'complete', true);
}
}

before(async () => {
await node.open();
await nclient.open();
await nclient.call('watch chain');

const mnemonic = Mnemonic.fromPhrase(phrase);
const priv = HDPrivateKey.fromMnemonic(mnemonic);
const type = network.keyPrefix.coinType;
const key = priv.derive(44, true).derive(type, true).derive(0, true);
const xkey = key.derive(0).derive(0);

socketData = [];
mempoolData = {};
pubkey = xkey.publicKey;
privkey = xkey.privateKey;

cbAddress = Address.fromPubkey(pubkey).toString(network.type);

nclient.bind('tree commit', (root, entry, block) => {
assert.ok(root);
assert.ok(block);
assert.ok(entry);

socketData.push({root, entry, block});
});

node.mempool.on('tx', (tx) => {
mempoolData[tx.txid()] = true;
});
});

after(async () => {
await nclient.close();
await node.close();
});

beforeEach(() => {
socketData = [];
mempoolData = {};
});

it('should mine 1 tree interval', async () => {
await mineBlocks(treeInterval, cbAddress);
assert.equal(socketData.length, 1);
Expand Down Expand Up @@ -153,14 +319,3 @@ describe('Node HTTP', function() {
});
});

// take into account race conditions
async function mineBlocks(count, address) {
for (let i = 0; i < count; i++) {
const obj = { complete: false };
node.once('block', () => {
obj.complete = true;
});
await nclient.execute('generatetoaddress', [1, address]);
await common.forValue(obj, 'complete', true);
}
}
Loading

0 comments on commit 3fd74e0

Please sign in to comment.