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

feat: node signing #169

Merged
merged 1 commit into from
Sep 19, 2023
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
15 changes: 15 additions & 0 deletions example/Dev.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,21 @@ const Dev = (): ReactElement => {
setMessage('Node Restarted');
}}
/>
<Button
title={'Sign message'}
onPress={async (): Promise<void> => {
setMessage('Signing...');
const res = await ldk.nodeSign({
message: 'Hello Bitcoin',
});
if (res.isErr()) {
setMessage(res.error.message);
return;
}

setMessage(res.value);
}}
/>
</View>
</ScrollView>

Expand Down
4 changes: 2 additions & 2 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ PODS:
- React-jsinspector (0.70.6)
- React-logger (0.70.6):
- glog
- react-native-ldk (0.0.106):
- react-native-ldk (0.0.109):
- React
- react-native-randombytes (3.6.1):
- React-Core
Expand Down Expand Up @@ -593,7 +593,7 @@ SPEC CHECKSUMS:
React-jsiexecutor: b4a65947391c658450151275aa406f2b8263178f
React-jsinspector: 60769e5a0a6d4b32294a2456077f59d0266f9a8b
React-logger: 1623c216abaa88974afce404dc8f479406bbc3a0
react-native-ldk: 9cbe6586e65697322126c6475547a55e2c12bf1c
react-native-ldk: 3c1cd457a2372ef3eda9fbe144f4cdf6bc1fd6c3
react-native-randombytes: 421f1c7d48c0af8dbcd471b0324393ebf8fe7846
react-native-tcp-socket: c1b7297619616b4c9caae6889bcb0aba78086989
React-perflogger: 8c79399b0500a30ee8152d0f9f11beae7fc36595
Expand Down
1 change: 1 addition & 0 deletions example/ldk/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export const setupLdk = async (
highPriority: 10,
normal: 5,
background: 1,
mempoolMinimum: 1,
}),
getTransactionData,
getTransactionPosition,
Expand Down
16 changes: 16 additions & 0 deletions lib/android/src/main/java/com/reactnativeldk/LdkModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import org.ldk.structs.*
import org.ldk.structs.Result_Bolt11InvoiceParseOrSemanticErrorZ.Result_Bolt11InvoiceParseOrSemanticErrorZ_OK
import org.ldk.structs.Result_Bolt11InvoiceSignOrCreationErrorZ.Result_Bolt11InvoiceSignOrCreationErrorZ_OK
import org.ldk.structs.Result_PaymentIdPaymentErrorZ.Result_PaymentIdPaymentErrorZ_OK
import org.ldk.structs.Result_StringErrorZ.Result_StringErrorZ_OK
import org.ldk.util.UInt128
import java.io.File
import java.net.InetSocketAddress
Expand Down Expand Up @@ -81,6 +82,7 @@ enum class LdkErrors {
channel_close_fail,
channel_accept_fail,
spend_outputs_fail,
failed_signing_request,
write_fail,
read_fail,
file_does_not_exist,
Expand Down Expand Up @@ -1088,6 +1090,20 @@ class LdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod

promise.resolve((res as Result_TransactionNoneZ.Result_TransactionNoneZ_OK).res.hexEncodedString())
}


@ReactMethod
fun nodeSign(message: String, promise: Promise) {
keysManager ?: return handleReject(promise, LdkErrors.init_keys_manager)

val res = UtilMethods.sign(message.toByteArray(Charsets.UTF_8), keysManager!!._node_secret_key)

if (!res.is_ok) {
return handleReject(promise, LdkErrors.failed_signing_request)
}

promise.resolve((res as Result_StringErrorZ_OK).res)
}
}

object LdkEventEmitter {
Expand Down
3 changes: 3 additions & 0 deletions lib/ios/Ldk.m
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ @interface RCT_EXTERN_MODULE(Ldk, NSObject)
changeDestinationScript:(NSString *)changeDestinationScript
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
RCT_EXTERN_METHOD(nodeSign:(NSString *)message
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
@end

//MARK: Events
Expand Down
15 changes: 15 additions & 0 deletions lib/ios/Ldk.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ enum LdkErrors: String {
case channel_close_fail = "channel_close_fail"
case channel_accept_fail = "channel_accept_fail"
case spend_outputs_fail = "spend_outputs_fail"
case failed_signing_request = "failed_signing_request"
case write_fail = "write_fail"
case read_fail = "read_fail"
case file_does_not_exist = "file_does_not_exist"
Expand Down Expand Up @@ -1177,6 +1178,20 @@ class Ldk: NSObject {

return resolve(Data(res.getValue()!).hexEncodedString())
}

@objc
func nodeSign(_ message: NSString, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
guard let keysManager = keysManager else {
return handleReject(reject, .init_keys_manager)
}

let signed = Bindings.swiftSign(msg: Array(String(message).utf8), sk: keysManager.getNodeSecretKey())
if let _ = signed.getError() {
handleReject(reject, .failed_signing_request)
}

return resolve(signed.getValue()!)
}
}

//MARK: Singleton react native event emitter
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.106",
"version": "0.0.109",
"description": "React Native wrapper for LDK",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
Expand Down
22 changes: 22 additions & 0 deletions lib/src/ldk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
TReconstructAndSpendOutputsReq,
THeader,
TAcceptChannelReq,
TNodeSignReq,
} from './utils/types';
import { extractPaymentRequest } from './utils/helpers';

Expand Down Expand Up @@ -1163,6 +1164,27 @@ class LDK {
return err(e);
}
}

/**
* Creates a digital signature of a message the node's secret key.
* A receiver knowing the PublicKey (e.g. the node's id) and the message can be sure that the signature was generated by the caller.
* Signatures are EC recoverable, meaning that given the message and the signature the PublicKey of the signer can be extracted.
* @param message
* @param messagePrefix
*/
async nodeSign({
message,
messagePrefix = 'Lightning Signed Message:',
}: TNodeSignReq): Promise<Result<string>> {
try {
const res = await NativeLDK.nodeSign(`${messagePrefix}${message}`);
this.writeDebugToLog('nodeSign', res);
return ok(res);
} catch (e) {
this.writeErrorToLog('nodeSign', e);
return err(e);
}
}
}

export default new LDK();
5 changes: 5 additions & 0 deletions lib/src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -574,3 +574,8 @@ export type TReconstructAndSpendOutputsReq = {
feeRate: number;
changeDestinationScript: string;
};

export type TNodeSignReq = {
message: string;
messagePrefix?: string;
};