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

fix: save addresses only when used for closing a channel #252

Merged
merged 4 commits into from
Jun 28, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/e2e-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:

jobs:
e2e-android:
runs-on: macos-12
runs-on: macos-13
timeout-minutes: 120

steps:
Expand Down
4 changes: 2 additions & 2 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ PODS:
- React-jsinspector (0.72.4)
- React-logger (0.72.4):
- glog
- react-native-ldk (0.0.143):
- react-native-ldk (0.0.145):
- React
- react-native-randombytes (3.6.1):
- React-Core
Expand Down Expand Up @@ -621,7 +621,7 @@ SPEC CHECKSUMS:
React-jsiexecutor: c7f826e40fa9cab5d37cab6130b1af237332b594
React-jsinspector: aaed4cf551c4a1c98092436518c2d267b13a673f
React-logger: da1ebe05ae06eb6db4b162202faeafac4b435e77
react-native-ldk: 12d78fe1141ad4343a2842340f7ebf8539dcc3b0
react-native-ldk: 496216796eafbd77c43cd5228342460a242cf7ed
react-native-randombytes: 421f1c7d48c0af8dbcd471b0324393ebf8fe7846
react-native-tcp-socket: c1b7297619616b4c9caae6889bcb0aba78086989
React-NativeModulesApple: edb5ace14f73f4969df6e7b1f3e41bef0012740f
Expand Down
2 changes: 2 additions & 0 deletions example/ios/exmpl.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,7 @@
baseConfigurationReference = 5B7EB9410499542E8C5724F5 /* Pods-exmpl-exmplTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
DEVELOPMENT_TEAM = KYH47R284B;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
Expand Down Expand Up @@ -516,6 +517,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = KYH47R284B;
INFOPLIST_FILE = exmpl/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13;
LD_RUNPATH_SEARCH_PATHS = (
Expand Down
7 changes: 4 additions & 3 deletions lib/android/src/main/java/com/reactnativeldk/LdkModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ enum class EventTypes {
network_graph_updated,
channel_manager_restarted,
backup_state_update,
lsp_log
lsp_log,
used_close_address
}
//*****************************************************************

Expand Down Expand Up @@ -242,7 +243,7 @@ class LdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod
}

@ReactMethod
fun initKeysManager(seed: String, destinationScriptPublicKey: String, witnessProgram: String, witnessProgramVersion: Double, promise: Promise) {
fun initKeysManager(seed: String, address: String, destinationScriptPublicKey: String, witnessProgram: String, witnessProgramVersion: Double, promise: Promise) {
if (keysManager != null) {
return handleResolve(promise, LdkCallbackResponses.keys_manager_init_success)
}
Expand All @@ -259,11 +260,11 @@ class LdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod
seedBytes,
seconds,
nanoSeconds.toInt(),
address,
destinationScriptPublicKey.hexa(),
witnessProgram.hexa(),
witnessProgramVersion.toInt().toByte()
)
//keysManager = KeysManager.of(seedBytes, seconds, nanoSeconds.toInt())

handleResolve(promise, LdkCallbackResponses.keys_manager_init_success)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class CustomKeysManager(
seed: ByteArray,
startingTimeSecs: Long,
startingTimeNanos: Int,
val address: String,
val destinationScriptPublicKey: ByteArray,
val witnessProgram: ByteArray,
val witnessProgramVersion: Byte
Expand Down Expand Up @@ -68,6 +69,7 @@ class CustomSignerProvider : SignerProviderInterface {
val res = ShutdownScript.new_witness_program(witness)

return if (res.is_ok) {
LdkEventEmitter.send(EventTypes.used_close_address, customKeysManager.address)
Result_ShutdownScriptNoneZ.ok((res as Result_ShutdownScriptInvalidShutdownScriptZ.Result_ShutdownScriptInvalidShutdownScriptZ_OK).res)
} else {
Result_ShutdownScriptNoneZ.err()
Expand Down
6 changes: 5 additions & 1 deletion lib/ios/Classes/CustomKeysManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ import LightningDevKit
class CustomKeysManager {
let inner: KeysManager
let signerProvider: CustomSignerProvider
let address: String
let destinationScriptPublicKey: [UInt8]
let witnessProgram: [UInt8]
let witnessProgramVersion: UInt8

init(seed: [UInt8], startingTimeSecs: UInt64, startingTimeNanos: UInt32, destinationScriptPublicKey: [UInt8], witnessProgram: [UInt8], witnessProgramVersion: UInt8) {
init(seed: [UInt8], startingTimeSecs: UInt64, startingTimeNanos: UInt32, address: String, destinationScriptPublicKey: [UInt8], witnessProgram: [UInt8], witnessProgramVersion: UInt8) {
self.inner = KeysManager(seed: seed, startingTimeSecs: startingTimeSecs, startingTimeNanos: startingTimeNanos)
self.address = address
self.destinationScriptPublicKey = destinationScriptPublicKey
self.witnessProgram = witnessProgram
self.witnessProgramVersion = witnessProgramVersion
Expand Down Expand Up @@ -61,6 +63,8 @@ class CustomSignerProvider: SignerProvider {
override func getShutdownScriptpubkey() -> Bindings.Result_ShutdownScriptNoneZ {
let res = ShutdownScript.newWitnessProgram(witnessProgram: .init(version: customKeysManager!.witnessProgramVersion, program: customKeysManager!.witnessProgram))
if res.isOk() {
//To record which addresses should be watched for close channel funds
LdkEventEmitter.shared.send(withEvent: .used_close_address, body: customKeysManager!.address)
return Bindings.Result_ShutdownScriptNoneZ.initWithOk(o: res.getValue()!)
}

Expand Down
1 change: 1 addition & 0 deletions lib/ios/Ldk.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ @interface RCT_EXTERN_MODULE(Ldk, NSObject)
RCT_EXTERN_METHOD(initChainMonitor:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
RCT_EXTERN_METHOD(initKeysManager:(NSString *)seed
address:(NSString *)address
destinationScriptPublicKey:(NSString *)destinationScriptPublicKey
witnessProgram:(NSString *)witnessProgram
witnessProgramVersion:(NSInteger *)witnessProgramVersion
Expand Down
6 changes: 4 additions & 2 deletions lib/ios/Ldk.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ enum EventTypes: String, CaseIterable {
case channel_manager_restarted = "channel_manager_restarted"
case backup_state_update = "backup_state_update"
case lsp_log = "lsp_log"
case used_close_address = "used_close_address"
}
//*****************************************************************

Expand Down Expand Up @@ -210,7 +211,7 @@ class Ldk: NSObject {
}

@objc
func initKeysManager(_ seed: NSString, destinationScriptPublicKey: NSString, witnessProgram: NSString, witnessProgramVersion: NSInteger, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
func initKeysManager(_ seed: NSString, address: NSString, destinationScriptPublicKey: NSString, witnessProgram: NSString, witnessProgramVersion: NSInteger, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
if keysManager != nil {
//If previously started with the same key (by backup client) return success.
return handleResolve(resolve, .keys_manager_init_success)
Expand All @@ -228,6 +229,7 @@ class Ldk: NSObject {
seed: String(seed).hexaBytes,
startingTimeSecs: seconds,
startingTimeNanos: nanoSeconds,
address: String(address),
destinationScriptPublicKey: String(destinationScriptPublicKey).hexaBytes,
witnessProgram: String(witnessProgram).hexaBytes,
witnessProgramVersion: UInt8(witnessProgramVersion)
Expand Down Expand Up @@ -661,7 +663,7 @@ class Ldk: NSObject {
droppedPeerTimer = Timer.scheduledTimer(
timeInterval: 5.0,
target: self,
selector: #selector(handleDroppedPeers),
selector: #selector(self.handleDroppedPeers),
userInfo: nil,
repeats: true
)
Expand Down
2 changes: 1 addition & 1 deletion lib/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@synonymdev/react-native-ldk",
"title": "React Native LDK",
"version": "0.0.143",
"version": "0.0.145",
"description": "React Native wrapper for LDK",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
Expand Down
2 changes: 2 additions & 0 deletions lib/src/ldk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,15 @@ class LDK {
*/
async initKeysManager({
seed,
address,
channelCloseDestinationScriptPublicKey,
channelCloseWitnessProgram,
channelCloseWitnessProgramVersion,
}: TInitKeysManager): Promise<Result<string>> {
try {
const res = await NativeLDK.initKeysManager(
seed,
address,
channelCloseDestinationScriptPublicKey,
channelCloseWitnessProgram,
channelCloseWitnessProgramVersion,
Expand Down
50 changes: 42 additions & 8 deletions lib/src/lightning-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
TCreatePaymentReq,
TBackupServerDetails,
IAddress,
TLspLogPayload,

Check warning on line 58 in lib/src/lightning-manager.ts

View workflow job for this annotation

GitHub Actions / mocha-ios

'TLspLogPayload' is defined but never used

Check warning on line 58 in lib/src/lightning-manager.ts

View workflow job for this annotation

GitHub Actions / Run lint check

'TLspLogPayload' is defined but never used
TLspLogEvent,
TChannelMonitor,
} from './utils/types';
Expand Down Expand Up @@ -232,6 +232,9 @@
this.onChannelManagerRestarted.bind(this),
);
ldk.onEvent(EEventTypes.lsp_log, this.onLspLogEvent.bind(this));
ldk.onEvent(EEventTypes.used_close_address, (address: string) => {
this.saveAddressToFile(address).catch(console.error);
});
}

/**
Expand Down Expand Up @@ -364,14 +367,7 @@
this.account = account;
this.network = network;
this.addresses = await this.readAddressesFromFile();
this.getAddress = async () => {
const addressObj = await getAddress();
const address = addressObj?.address;
if (address) {
this.saveAddressToFile(address).then();
}
return addressObj;
};
this.getAddress = getAddress;
this.getScriptPubKeyHistory = getScriptPubKeyHistory;
this.getFees = getFees;
this.broadcastTransaction = broadcastTransaction;
Expand Down Expand Up @@ -452,6 +448,7 @@
// ldk.setLogLevel(ELdkLogLevels.trace, true),
ldk.initKeysManager({
seed: this.account.seed,
address: closeAddress.address,
channelCloseDestinationScriptPublicKey: closeAddress.publicKey,
channelCloseWitnessProgram: witnessProgram,
channelCloseWitnessProgramVersion: witnessProgramVersion,
Expand Down Expand Up @@ -513,6 +510,7 @@
ldk.nodeStateDump().catch(console.error);

this.cleanupBroadcastedTxs().catch(console.error);
this.resetAddressFileIfUnused().catch(console.error);

this.isStarting = false;
const result = ok('Node started');
Expand Down Expand Up @@ -769,6 +767,37 @@
return ok('Watch transactions checked');
};

/*
* Previously we were writing all addresses to file even
* if they may not have been used in a channel shutdown script or
* force close sweeping. So reset the file if there is no evidence of prior channels.
* */
resetAddressFileIfUnused = async (): Promise<void> => {
//If no channel files found and no addresses are being used, reset the address file.
const channelFilesRes = await ldk.listChannelFiles();
if (channelFilesRes.isErr()) {
return;
}

if (channelFilesRes.value.length > 0) {
return;
}

const accountPath = appendPath(this.baseStoragePath, this.account.name);
const writeRes = await ldk.writeToFile({
fileName: ELdkFiles.addresses,
path: accountPath,
content: JSON.stringify([]),
remotePersist: false,
});

this.addresses = [];

if (writeRes.isErr()) {
console.error(writeRes.error);
}
};

saveAddressToFile = async (address: string): Promise<Result<boolean>> => {
if (!address) {
return err('No address provided');
Expand Down Expand Up @@ -1822,6 +1851,7 @@
changeDestinationScript: changeDestinationScript,
};
const res = await ldk.reconstructAndSpendOutputs(req);
await this.saveAddressToFile(address.address);

if (res.isOk()) {
reconstructedTxs++;
Expand Down Expand Up @@ -2099,7 +2129,7 @@
}

private onChannelManagerPendingHtlcsForwardable(
res: TChannelManagerPendingHtlcsForwardable,

Check warning on line 2132 in lib/src/lightning-manager.ts

View workflow job for this annotation

GitHub Actions / mocha-ios

'res' is defined but never used. Allowed unused args must match /^_/u

Check warning on line 2132 in lib/src/lightning-manager.ts

View workflow job for this annotation

GitHub Actions / Run lint check

'res' is defined but never used. Allowed unused args must match /^_/u
): void {
ldk.processPendingHtlcForwards().catch(console.error);
}
Expand Down Expand Up @@ -2127,6 +2157,7 @@
res: TChannelManagerSpendableOutputs,
): Promise<void> {
const spendableOutputs = await this.getLdkSpendableOutputs();

res.outputsSerialized.forEach((o) => {
if (!spendableOutputs.includes(o)) {
spendableOutputs.push(o);
Expand Down Expand Up @@ -2172,6 +2203,9 @@
return;
}

//Address was used to sweep to so wallet needs to watch it
await this.saveAddressToFile(address.address);

await ldk.writeToLogFile(
'info',
`Created tx spending outputs: ${spendRes.value}`,
Expand Down
2 changes: 2 additions & 0 deletions lib/src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export enum EEventTypes {
channel_manager_restarted = 'channel_manager_restarted',
backup_state_update = 'backup_state_update',
lsp_log = 'lsp_log',
used_close_address = 'used_close_address',
}

//LDK event responses
Expand Down Expand Up @@ -326,6 +327,7 @@ export type TDownloadScorer = {

export type TInitKeysManager = {
seed: string;
address: string;
channelCloseDestinationScriptPublicKey: string;
channelCloseWitnessProgram: string;
channelCloseWitnessProgramVersion: number;
Expand Down
Loading