Skip to content

Commit f3d59d8

Browse files
committed
feat: add simln support to CLN
1 parent 180eb21 commit f3d59d8

File tree

5 files changed

+65
-5
lines changed

5 files changed

+65
-5
lines changed

src/components/designer/default/AddSimulationModal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ const AddSimulationModal: React.FC<Props> = ({ network }) => {
113113
name="source"
114114
label={l('source')}
115115
nodeStatus={Status.Started}
116-
implementation={['LND', 'eclair']}
116+
implementation={['LND', 'eclair', 'c-lightning']}
117117
nodes={nodes}
118118
/>
119119
</Col>
@@ -123,7 +123,7 @@ const AddSimulationModal: React.FC<Props> = ({ network }) => {
123123
name="destination"
124124
label={l('destination')}
125125
nodeStatus={Status.Started}
126-
implementation={['LND', 'eclair']}
126+
implementation={['LND', 'eclair', 'c-lightning']}
127127
nodes={nodes}
128128
/>
129129
</Col>

src/lib/docker/dockerService.spec.ts

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,7 @@ describe('DockerService', () => {
885885
name: 'my network',
886886
description: 'network description',
887887
lndNodes: 1,
888-
clightningNodes: 0,
888+
clightningNodes: 1,
889889
eclairNodes: 1,
890890
bitcoindNodes: 1,
891891
tapdNodes: 0,
@@ -899,6 +899,9 @@ describe('DockerService', () => {
899899
const eclairNodes = network.nodes.lightning.filter(
900900
n => n.implementation === 'eclair',
901901
);
902+
const clightningNodes = network.nodes.lightning.filter(
903+
n => n.implementation === 'c-lightning',
904+
);
902905
beforeEach(() => {
903906
// Add simulation config to the test network
904907
network.simulation = {
@@ -964,9 +967,9 @@ describe('DockerService', () => {
964967
});
965968

966969
it('should handle errors when using unsupported node types', async () => {
967-
network.nodes.lightning[0].implementation = 'c-lightning';
970+
network.nodes.lightning[0].implementation = 'litd';
968971
await expect(dockerService.startSimulation(network)).rejects.toThrow(
969-
'unsupported node implementation: c-lightning',
972+
'unsupported node implementation: litd',
970973
);
971974
});
972975

@@ -995,5 +998,44 @@ describe('DockerService', () => {
995998
expect.stringContaining(`container_name: polar-n1-simln`),
996999
);
9971000
});
1001+
1002+
// Now we should be able to use c-lightning in the simulation
1003+
it('should add c-lightning to the docker-compose.yml file', async () => {
1004+
network.simulation = {
1005+
activity: [
1006+
{
1007+
id: 0,
1008+
source: clightningNodes[0].name,
1009+
destination: eclairNodes[0].name,
1010+
intervalSecs: 60,
1011+
amountMsat: 1000,
1012+
},
1013+
],
1014+
status: Status.Stopped,
1015+
};
1016+
dockerService.saveComposeFile(network);
1017+
expect(filesMock.write).toHaveBeenCalledWith(
1018+
expect.stringContaining('docker-compose.yml'),
1019+
expect.stringContaining(`container_name: polar-n1-simln`),
1020+
);
1021+
1022+
composeMock.upOne.mockResolvedValue(mockResult);
1023+
await dockerService.startSimulation(network);
1024+
1025+
// Verify directories were created
1026+
expect(fsMock.ensureDir).toHaveBeenCalled();
1027+
1028+
// Verify sim.json was written with correct config
1029+
expect(filesMock.write).toHaveBeenCalledWith(
1030+
expect.stringContaining('sim.json'),
1031+
expect.stringContaining(clightningNodes[0].name),
1032+
);
1033+
1034+
// Verify docker compose command was called
1035+
expect(composeMock.upOne).toHaveBeenCalledWith(
1036+
'simln',
1037+
expect.objectContaining({ cwd: network.path }),
1038+
);
1039+
});
9981040
});
9991041
});

src/lib/docker/dockerService.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,21 @@ class DockerService implements DockerLibrary {
455455
};
456456
break;
457457

458+
case 'c-lightning':
459+
const cln = node as CLightningNode;
460+
simNode = {
461+
id: cln.name,
462+
address: `host.docker.internal:${cln.ports.grpc}`,
463+
ca_cert: `/home/simln/.${cln.paths.tlsCert?.split('volumes/').pop()}`,
464+
client_cert: `/home/simln/.${cln.paths.tlsClientCert
465+
?.split('volumes/')
466+
.pop()}`,
467+
client_key: `/home/simln/.${cln.paths.tlsClientKey
468+
?.split('volumes/')
469+
.pop()}`,
470+
};
471+
break;
472+
458473
default:
459474
throw new Error(`unsupported node implementation: ${node.implementation}`);
460475
}

src/lib/docker/nodeTemplates.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ export const simln = (
198198
volumes: [
199199
`./volumes/${name}:/home/simln/.simln`,
200200
`./volumes/${dockerConfigs.LND.volumeDirName}:/home/simln/.lnd`,
201+
`./volumes/${dockerConfigs['c-lightning'].volumeDirName}:/home/simln/.c-lightning`,
201202
],
202203
expose: [],
203204
ports: [],

src/utils/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,8 @@ export const dockerConfigs: Record<NodeImplementationWithSimln, DockerConfig> =
193193
'--channel.max-htlc-value-in-flight-percent=100',
194194
'--channel.max-htlc-value-in-flight-msat=5000000000000', // 50 BTC in msats
195195
'--features.keysend=optional',
196+
'--channel.min-final-expiry-delta-blocks=22', // Default is 30 for eclair, however it is 22 for CLN (the lowest).
197+
'--channel.fulfill-safety-before-timeout-blocks=20', // When `channel.min-final-expiry-delta-blocks` is set, this is required and most be less than it. Default is 24.
196198
].join('\n '),
197199
// if vars are modified, also update composeFile.ts & the i18n strings for cmps.nodes.CommandVariables
198200
variables: ['name', 'eclairPass', 'backendName', 'rpcUser', 'rpcPass'],

0 commit comments

Comments
 (0)