Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions packages/dashmate/templates/core/dash.conf.dot
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,9 @@ externalip={{=it.externalIp}}
# Tor. The sidecar shares this container's network namespace, so its SOCKS and
# control ports are on loopback. Only onion destinations use the proxy: clearnet
# peers (including quorum traffic) stay direct, so `proxy=` is deliberately not
# set. Core registers an onion service through the control port and binds the
# default onion target (127.0.0.1:<network onion port>) for its inbound side.
# set. An explicit bind disables Core's automatic onion target, and listenonion=1
# requires a dedicated non-wildcard onion bind. Since bind is network-only, the
# onion bind is rendered beside the network bind in the # network block below.
{{? it.core.tor.enabled }}
onion=127.0.0.1:9050
listenonion=1
Expand Down Expand Up @@ -148,5 +149,8 @@ addnode={{=seed.host}}:{{=seed.port}}{{~}}
# network
port={{=it.core.p2p.port}}
bind=0.0.0.0
{{? it.core.tor.enabled }}
bind=127.0.0.1=onion
{{?}}
rpcbind=0.0.0.0
rpcport={{=it.core.rpc.port}}
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,40 @@ describe('migrateConfigFileFactory', () => {
});
});

it('should render a migrated legacy config before and after enabling Tor', async () => {
const { version } = JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT_DIR, 'package.json'), 'utf8'));
const baseConfig = container.resolve('defaultConfigs').get('base');
const renderServiceTemplates = container.resolve('renderServiceTemplates');

for (const fromVersion of ['4.1.0', '4.1.1', '4.2.0-dev.1']) {
const configFileData = createConfigFile().toObject();
configFileData.configFormatVersion = fromVersion;
const devnetConfig = new Config('devnet', baseConfig.getStoredOptions());
devnetConfig.set('network', 'devnet');
configFileData.configs.devnet = devnetConfig.getStoredOptions();
for (const options of Object.values(configFileData.configs)) {
delete options.core.tor;
}

const migrated = migrateConfigFile(configFileData, fromVersion, version);

for (const [name, options] of Object.entries(migrated.configs)) {
const config = new Config(name, options);
const disabledConf = renderServiceTemplates(config)['core/dash.conf'];
expect(disabledConf).to.match(/^listenonion=0$/m);
expect(disabledConf.match(/^bind=.*$/gm)).to.deep.equal(['bind=0.0.0.0']);

config.set('core.tor.enabled', true);
const enabledConf = renderServiceTemplates(config)['core/dash.conf'];
expect(enabledConf).to.match(/^listenonion=1$/m);
expect(enabledConf.match(/^bind=.*$/gm)).to.deep.equal([
'bind=0.0.0.0',
'bind=127.0.0.1=onion',
]);
}
}
});

it('should add the quorum list reload interval to a 5.0.0-beta.3 config, short only on local networks', async () => {
// Loading is what fails without it: the schema requires the option.
const fromVersion = '5.0.0-beta.3';
Expand Down
44 changes: 37 additions & 7 deletions packages/dashmate/test/unit/templates/torTemplates.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,45 @@ describe('Tor templates', () => {
renderServiceTemplates = renderServiceTemplatesFactory(renderTemplateFactory());
});

it('should leave onion listening off and set no proxy when Tor is disabled', () => {
config.set('core.tor.enabled', false);
[
['mainnet', null],
['testnet', '[test]'],
['devnet', '[devnet]'],
['local', '[regtest]'],
].forEach(([network, section]) => {
it(`should provide the dedicated onion bind required by Core 24 on ${network}`, () => {
config.set('network', network);
config.set('core.tor.enabled', true);
// The onion target is independent of an operator's clearnet P2P port.
config.set('core.p2p.port', 21000);

const dashConf = renderServiceTemplates(config)['core/dash.conf'];
const dashConf = renderServiceTemplates(config)['core/dash.conf'];
// -bind is network-only, so non-mainnet binds must be in their network section.
const networkConf = section ? dashConf.split(section)[1] : dashConf;

expect(dashConf).to.match(/^listenonion=0$/m);
expect(dashConf).to.not.match(/^onion=/m);
expect(dashConf).to.not.match(/^torcontrol=/m);
expect(dashConf).to.not.match(/^proxy=/m);
expect(dashConf).to.match(/^listenonion=1$/m);
expect(networkConf.match(/^bind=.*$/gm)).to.deep.equal([
'bind=0.0.0.0',
'bind=127.0.0.1=onion',
]);
if (network === 'mainnet') {
const beforeOnionBind = dashConf.slice(0, dashConf.indexOf('bind=127.0.0.1=onion'));
expect(beforeOnionBind).to.not.match(/^\s*\[.*\]\s*$/m);
}
});

it(`should leave onion listening off and set no proxy when Tor is disabled on ${network}`, () => {
config.set('network', network);
config.set('core.tor.enabled', false);

const dashConf = renderServiceTemplates(config)['core/dash.conf'];

expect(dashConf).to.match(/^listenonion=0$/m);
expect(dashConf.match(/^bind=.*$/gm)).to.deep.equal(['bind=0.0.0.0']);
expect(dashConf).to.not.match(/^onion=/m);
expect(dashConf).to.not.match(/^torcontrol=/m);
expect(dashConf).to.not.match(/^proxy=/m);
});
});

it('should point Core at the sidecar on loopback by default', () => {
Expand Down
Loading