Skip to content

Commit

Permalink
Lightning Node Connect: LSP support
Browse files Browse the repository at this point in the history
  • Loading branch information
kaloudis committed Jan 20, 2024
1 parent eaf9d57 commit de25bb2
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 28 deletions.
2 changes: 1 addition & 1 deletion backends/LightningNodeConnect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ export default class LightningNodeConnect {
supportsAddressTypeSelection = () => true;
supportsTaproot = () => this.supports('v0.15.0');
supportsBumpFee = () => true;
supportsLSPs = () => false;
supportsLSPs = () => true;
supportsNetworkInfo = () => false;
supportsSimpleTaprootChannels = () => this.supports('v0.17.0');
supportsCustomPreimages = () => true;
Expand Down
4 changes: 2 additions & 2 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ PODS:
- RNVectorIcons (7.1.0):
- React
- SocketRocket (0.6.1)
- SwiftProtobuf (1.23.0)
- SwiftProtobuf (1.25.2)
- TcpSockets (4.0.0):
- React
- Yoga (1.14.0)
Expand Down Expand Up @@ -830,7 +830,7 @@ SPEC CHECKSUMS:
RNSVG: d00c8f91c3cbf6d476451313a18f04d220d4f396
RNVectorIcons: bc69e6a278b14842063605de32bec61f0b251a59
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
SwiftProtobuf: b70d65f419fbfe61a2d58003456ca5da58e337d6
SwiftProtobuf: 407a385e97fd206c4fbe880cc84123989167e0d1
TcpSockets: 4ef55305239923b343ed0a378b1fac188b1373b0
Yoga: 86fed2e4d425ee4c6eab3813ba1791101ee153c6

Expand Down
2 changes: 2 additions & 0 deletions ios/zeus.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2134,6 +2134,7 @@
"-ld_classic",
"-Wl",
"-ld_classic",
"-Wl -ld_classic ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
Expand Down Expand Up @@ -2211,6 +2212,7 @@
"-ld_classic",
"-Wl",
"-ld_classic",
"-Wl -ld_classic ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
Expand Down
7 changes: 7 additions & 0 deletions lndmobile/LndMobileInjection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
listPayments,
listInvoices,
subscribeChannelGraph,
channelAcceptorAnswer,
sendKeysendPaymentV2
} from './index';
import {
Expand Down Expand Up @@ -196,6 +197,11 @@ export interface ILndMobileInjections {
) => Promise<lnrpc.QueryRoutesResponse>;
listPayments: () => Promise<lnrpc.ListPaymentsResponse>;
subscribeChannelGraph: () => Promise<string>;
channelAcceptorAnswer: (
pending_chan_id: Uint8Array,
zero_conf: boolean,
accept: boolean
) => void;
sendKeysendPaymentV2: ({
amt,
max_shard_size_msat,
Expand Down Expand Up @@ -382,6 +388,7 @@ export default {
listPayments,
listInvoices,
subscribeChannelGraph,
channelAcceptorAnswer,
sendKeysendPaymentV2
},
channel: {
Expand Down
22 changes: 22 additions & 0 deletions lndmobile/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,28 @@ export const subscribeChannelGraph = async (): Promise<string> => {
return response;
};

/**
* @throws
*/
export const channelAcceptorAnswer = async (
pending_chan_id: Uint8Array,
zero_conf: boolean,
accept: boolean
) => {
await sendStreamCommand<
lnrpc.IChannelAcceptResponse,
lnrpc.ChannelAcceptResponse
>({
request: lnrpc.ChannelAcceptResponse,
method: 'ChannelAcceptor',
options: {
pending_chan_id,
zero_conf,
accept
}
});
};

export type IReadLndLogResponse = string[];
/**
* @throws
Expand Down
78 changes: 53 additions & 25 deletions stores/LSPStore.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { action, observable } from 'mobx';
import ReactNativeBlobUtil from 'react-native-blob-util';
import { NativeEventEmitter, NativeModules } from 'react-native';

import SettingsStore from './SettingsStore';
import ChannelsStore from './ChannelsStore';
import stores from './Stores';

import lndMobile from '../lndmobile/LndMobileInjection';
const { channel } = lndMobile;
const { channel, index } = lndMobile;

import Base64Utils from '../utils/Base64Utils';
import { LndMobileEventEmitter } from '../utils/LndMobileUtils';
import { localeString } from '../utils/LocaleUtils';

Expand Down Expand Up @@ -146,17 +146,9 @@ export default class LSPStore {

handleChannelAcceptorEvent = async (channelAcceptRequest: any) => {
try {
const requestPubkey = Base64Utils.bytesToHex(
channelAcceptRequest.node_pubkey
);

// Only allow 0-conf chans from LSP or whitelisted peers
// only allow zero conf chans from the LSP
const isZeroConfAllowed =
this.info?.pubkey === requestPubkey ||
(this.settingsStore?.settings?.zeroConfPeers &&
this.settingsStore?.settings?.zeroConfPeers.includes(
requestPubkey
));
channelAcceptRequest.node_pubkey === this.info.pub_key;

await channel.channelAcceptorResponse(
channelAcceptRequest.pending_chan_id,
Expand All @@ -170,22 +162,58 @@ export default class LSPStore {

@action
public initChannelAcceptor = async () => {
const { implementation } = this.settingsStore;
if (this.channelAcceptor) return;
this.channelAcceptor = LndMobileEventEmitter.addListener(
'ChannelAcceptor',
async (event: any) => {
try {
const channelAcceptRequest =
channel.decodeChannelAcceptRequest(event.data);

await this.handleChannelAcceptorEvent(channelAcceptRequest);
} catch (error: any) {
console.error('channel acceptance error: ' + error.message);

if (implementation === 'embedded-lnd') {
this.channelAcceptor = LndMobileEventEmitter.addListener(
'ChannelAcceptor',
async (event: any) => {
try {
const result = channel.decodeChannelAcceptRequest(
event.data
);
await this.handleChannelAcceptorEvent(result);
} catch (error: any) {
console.error(
'channelAcceptorEvent embedded-lnd error:',
error.message
);
}
}
}
);
);

await channel.channelAcceptor();
}

await channel.channelAcceptor();
if (implementation === 'lightning-node-connect') {
const { LncModule } = NativeModules;
const eventEmitter = new NativeEventEmitter(LncModule);
this.channelAcceptor = eventEmitter.addListener(
'lnrpc.Lightning.ChannelAcceptor',
async (event: any) => {
if (event.result) {
try {
const result = JSON.parse(event.result);
// only allow zero conf chans from the LSP
const isZeroConfAllowed =
result.node_pubkey === this.info.pub_key;

index.channelAcceptorAnswer(
result.pending_chan_id,
!result.wants_zero_conf || isZeroConfAllowed,
isZeroConfAllowed
);
} catch (error: any) {
console.error(
'channelAcceptorEvent lightning-node-connect error:',
error.message
);
}
}
}
);
}
};

@action
Expand Down

0 comments on commit de25bb2

Please sign in to comment.