Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: remove mpay for xpay #758

Merged
merged 2 commits into from
Jan 3, 2025
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
30 changes: 0 additions & 30 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ jobs:
matrix:
platform: [ubuntu-latest]
node-version: [20]
python-version: ['3.10']
rust-version: [stable]

runs-on: ${{ matrix.platform }}
Expand All @@ -25,14 +24,6 @@ jobs:
node-version: ${{ matrix.node-version }}
cache: 'npm'

- name: Use Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Use Poetry
uses: abatilo/actions-poetry@v2

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

Expand All @@ -48,18 +39,12 @@ jobs:
- name: Start PostgreSQL
run: npm run db:start

- name: Install Python dependencies
run: npm run python:install

- name: Start containers
run: npm run docker:regtest && npm run docker:solidity

- name: Deploy Ethereum contracts
run: npm run docker:solidity:deploy

- name: Install Python dependencies in regtest container
run: docker exec regtest bash /root/poetry-install.sh

- name: Compile
run: npm run compile

Expand All @@ -69,30 +54,15 @@ jobs:
- name: Lint
run: npm run lint

- name: Python lint
run: npm run python:lint

- name: Start hold invoice plugin
run: npm run docker:cln:hold

- name: Start mpay plugin
run: docker exec regtest lightning-cli plugin start /root/mpay.sh

- name: Unit tests
run: npm run test:unit

- name: Integration tests
run: node run-int.js

- name: Stop hold invoice plugin
run: docker exec regtest lightning-cli plugin stop /root/.lightning/plugins/hold

- name: Stop mpay plugin
run: docker exec regtest lightning-cli plugin stop /root/mpay.sh

- name: Python plugin tests
run: npm run python:test

build-rust:
strategy:
matrix:
Expand Down
5 changes: 5 additions & 0 deletions docker/c-lightning/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ WORKDIR /lightning
RUN git checkout v${VERSION}
RUN git submodule init && git submodule update

RUN git remote add fork https://github.com/michael1011/lightning.git && git fetch fork
RUN git config user.name buildkit && \
git config user.email root@buildkitsandbox && \
git cherry-pick b302d3b4a0230cc7774bc3a9c80784d96e54af42

RUN ./configure
RUN make install

Expand Down
14 changes: 0 additions & 14 deletions lib/Boltz.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import GrpcService from './grpc/GrpcService';
import { LightningClient } from './lightning/LightningClient';
import LndClient from './lightning/LndClient';
import ClnClient from './lightning/cln/ClnClient';
import MpayClient from './lightning/cln/MpayClient';
import NotificationClient from './notifications/NotificationClient';
import NotificationProvider from './notifications/NotificationProvider';
import Blocks from './service/Blocks';
Expand Down Expand Up @@ -411,19 +410,6 @@ class Boltz {
client.symbol,
holdInfo.version,
);

if (client.useMpay()) {
const mpayInfo = await client.mpay!.getInfo();
this.logger.verbose(
`${client.symbol} ${MpayClient.serviceName} version: ${mpayInfo.version}`,
);

VersionCheck.checkLightningVersion(
MpayClient.serviceName,
client.symbol,
mpayInfo.version,
);
}
}

this.logStatus(service, info);
Expand Down
11 changes: 1 addition & 10 deletions lib/VersionCheck.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import ChainClient from './chain/ChainClient';
import LndClient from './lightning/LndClient';
import ClnClient from './lightning/cln/ClnClient';
import MpayClient from './lightning/cln/MpayClient';

type Version = string | number;

Expand Down Expand Up @@ -82,17 +81,13 @@ class VersionCheck {
maximal: 280000,
},
[ClnClient.serviceName]: {
minimal: '24.08',
minimal: '24.11',
maximal: '24.11.1',
},
[ClnClient.serviceNameHold]: {
minimal: '0.2.0',
maximal: '0.2.0',
},
[MpayClient.serviceName]: {
minimal: '0.1.3',
maximal: '0.1.3',
},
[LndClient.serviceName]: {
minimal: '0.18.0',
maximal: '0.18.4',
Expand Down Expand Up @@ -149,10 +144,6 @@ class VersionCheck {
limits = VersionCheck.versionLimits[ClnClient.serviceNameHold];
break;

case MpayClient.serviceName:
limits = VersionCheck.versionLimits[MpayClient.serviceName];
break;

default:
throw `unsupported lightning client ${serviceName}`;
}
Expand Down
123 changes: 42 additions & 81 deletions lib/lightning/cln/ClnClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,10 @@ import { ClientStatus } from '../../consts/Enums';
import { NodeType } from '../../db/models/ReverseSwap';
import { NodeClient } from '../../proto/cln/node_grpc_pb';
import * as noderpc from '../../proto/cln/node_pb';
import {
DecodeResponse,
ListfundsOutputs,
ListpaysPays,
} from '../../proto/cln/node_pb';
import { ListfundsOutputs, ListpaysPays } from '../../proto/cln/node_pb';
import * as primitivesrpc from '../../proto/cln/primitives_pb';
import { HoldClient } from '../../proto/hold/hold_grpc_pb';
import * as holdrpc from '../../proto/hold/hold_pb';
import * as mpayrpc from '../../proto/mpay/mpay_pb';
import { WalletBalance } from '../../wallet/providers/WalletProviderInterface';
import { msatToSat, satToMsat, scidClnToLnd } from '../ChannelUtils';
import Errors from '../Errors';
Expand All @@ -40,12 +35,10 @@ import {
RoutingHintsProvider,
calculatePaymentFee,
} from '../LightningClient';
import Mpay from './MpayClient';
import { getRoute } from './Router';
import { ClnConfig, createSsl } from './Types';

import ListpaysPaysStatus = ListpaysPays.ListpaysPaysStatus;
import DecodeType = DecodeResponse.DecodeType;

class ClnClient
extends BaseClient<EventTypes>
Expand All @@ -57,8 +50,6 @@ class ClnClient

public static readonly paymentPendingError = 'payment already pending';

public readonly mpay?: Mpay;

private static readonly paymentMinFee = 121;
private static readonly paymentTimeout = 300;

Expand Down Expand Up @@ -93,17 +84,6 @@ class ClnClient

this.nodeUri = `${config.host}:${config.port}`;
this.holdUri = `${config.hold.host}:${config.hold.port}`;

if (config.mpay) {
this.logger.verbose(
`Using mpay for ${ClnClient.serviceName} ${this.symbol}`,
);
this.mpay = new Mpay(logger, this.symbol, config.mpay);
} else {
this.logger.warn(
`Mpay not configured for ${ClnClient.serviceName} ${this.symbol}; using pay`,
);
}
}

public get type() {
Expand All @@ -130,15 +110,16 @@ class ClnClient
};

public static errIsIncorrectPaymentDetails = (err: string): boolean => {
return err.includes('WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS');
return (
err.includes('WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS') ||
err.includes('incorrect_or_unknown_payment_details')
);
};

public serviceName = (): string => {
return ClnClient.serviceName;
};

public useMpay = () => this.mpay !== undefined && this.mpay.isConnected();

public connect = async (): Promise<boolean> => {
if (!this.isConnected()) {
this.nodeClient = new NodeClient(this.nodeUri, this.nodeCreds, {
Expand All @@ -151,8 +132,6 @@ class ClnClient
'grpc.ssl_target_name_override': 'hold',
});

this.mpay?.connect();

try {
await this.getInfo();
this.setClientStatus(ClientStatus.Connected);
Expand Down Expand Up @@ -191,8 +170,6 @@ class ClnClient
this.holdClient = undefined;
}

this.mpay?.disconnect();

this.removeAllListeners();

this.setClientStatus(ClientStatus.Disconnected);
Expand Down Expand Up @@ -572,25 +549,9 @@ class ClnClient
),
);

// TODO: mpay support for bolt12
const useMpay =
this.useMpay() && decoded.type !== DecodeType.BOLT12_INVOICE;
this.logger.verbose(
`Using ${useMpay ? 'mpay' : 'pay'} for ${ClnClient.serviceName} ${this.symbol} invoice payment`,
);

if (useMpay) {
return this.mpay!.sendPayment(
invoice,
maxFee,
ClnClient.paymentTimeout,
cltvDelta,
);
}
const req = new noderpc.XpayRequest();

const req = new noderpc.PayRequest();

req.setBolt11(invoice);
req.setInvstring(invoice);
req.setRetryFor(ClnClient.paymentTimeout);

const feeAmount = new primitivesrpc.Amount();
Expand All @@ -601,23 +562,22 @@ class ClnClient
req.setMaxdelay(cltvDelta);
}

const res = await this.unaryNodeCall<
noderpc.PayRequest,
noderpc.PayResponse
>('pay', req, false);

if (res.getStatus() !== noderpc.PayResponse.PayStatus.COMPLETE) {
// TODO: error message?
throw 'payment failed';
}
try {
const res = await this.unaryNodeCall<
noderpc.XpayRequest,
noderpc.XpayResponse
>('xpay', req, false);

const fee =
BigInt(res.getAmountSentMsat()!.getMsat()) - BigInt(decoded.valueMsat);
const fee =
BigInt(res.getAmountSentMsat()!.getMsat()) - BigInt(decoded.valueMsat);

return {
feeMsat: Number(fee),
preimage: Buffer.from(res.getPaymentPreimage_asU8()),
};
return {
feeMsat: Number(fee),
preimage: Buffer.from(res.getPaymentPreimage_asU8()),
};
} catch (e) {
throw this.parseError(e);
}
};

public subscribeSingleInvoice = (preimageHash: Buffer): void => {
Expand Down Expand Up @@ -720,26 +680,6 @@ class ClnClient
};
}

// ... has failed...
if (this.mpay !== undefined) {
for (const payStatus of (await this.mpay.payStatus(invoice)).statusList) {
for (const attempt of payStatus.attemptsList) {
if (
attempt.state ===
mpayrpc.PayStatusResponse.PayStatus.Attempt.AttemptState
.ATTEMPT_PENDING ||
attempt.failure === undefined
) {
continue;
}

if (ClnClient.errIsIncorrectPaymentDetails(attempt.failure.message)) {
throw attempt.failure.message;
}
}
}
}

// ... or is still pending
const hasPendingPayments = pays.some(
(pay) => pay.getStatus() === ListpaysPaysStatus.PENDING,
Expand Down Expand Up @@ -847,6 +787,27 @@ class ClnClient
setTimeout(() => this.reconnect(), this.RECONNECT_INTERVAL);
}
};

private parseError = (error: unknown) => {
if (
typeof error === 'object' &&
'message' in error! &&
typeof error.message === 'string'
) {
const msg = error.message as string;
const messagePrefix = 'message: "';
const messageSuffix = '", data:';

if (msg.includes(messagePrefix)) {
return msg.slice(
msg.indexOf(messagePrefix) + messagePrefix.length,
msg.indexOf(messageSuffix),
);
}
}

return formatError(error);
};
}

export default ClnClient;
Expand Down
Loading
Loading