From f387869598dbd2009efd84fd804232bc7ce50fba Mon Sep 17 00:00:00 2001 From: Evan Kaloudis Date: Thu, 26 Mar 2026 11:46:23 -0400 Subject: [PATCH] feat: add verify message support for LDK Node backend --- backends/CLNRest.ts | 1 + backends/EmbeddedLND.ts | 1 + backends/EmbeddedLdkNode.ts | 13 +++--- backends/LND.ts | 1 + backends/LightningNodeConnect.ts | 1 + locales/en.json | 2 + stores/MessageSignStore.ts | 4 +- utils/BackendUtils.ts | 1 + views/Tools/SignVerifyMessage.tsx | 68 ++++++++++++++++++++++++++++--- 9 files changed, 80 insertions(+), 12 deletions(-) diff --git a/backends/CLNRest.ts b/backends/CLNRest.ts index c24603bac..b816dd040 100644 --- a/backends/CLNRest.ts +++ b/backends/CLNRest.ts @@ -591,6 +591,7 @@ export default class CLNRest { supportsPeers = () => true; supportsMessageSigning = () => true; supportsMessageVerification = () => true; + requiresVerifyPubkey = () => false; supportsAddressMessageSigning = () => false; supportsLnurlAuth = () => true; supportsOnchainBalance = () => true; diff --git a/backends/EmbeddedLND.ts b/backends/EmbeddedLND.ts index 8918021e3..dff16caa6 100644 --- a/backends/EmbeddedLND.ts +++ b/backends/EmbeddedLND.ts @@ -421,6 +421,7 @@ export default class EmbeddedLND extends LND { supportsPeers = () => true; supportsMessageSigning = () => true; supportsMessageVerification = () => true; + requiresVerifyPubkey = () => false; supportsAddressMessageSigning = () => true; supportsLnurlAuth = () => true; supportsOnchainBalance = () => true; diff --git a/backends/EmbeddedLdkNode.ts b/backends/EmbeddedLdkNode.ts index f4deb7080..575e06baf 100644 --- a/backends/EmbeddedLdkNode.ts +++ b/backends/EmbeddedLdkNode.ts @@ -1702,10 +1702,12 @@ export default class EmbeddedLdkNode { return { signature }; }; - verifyMessage = async (data: { msg: string; signature: string }) => { - const { msg, signature } = data; - // Get the node's public key to verify against - const pubkey = await LdkNode.node.nodeId(); + verifyMessage = async (data: { + msg: string; + signature: string; + pubkey: string; + }) => { + const { msg, signature, pubkey } = data; const valid = await LdkNode.signing.verifySignature({ message: msg, signature, @@ -1948,7 +1950,8 @@ export default class EmbeddedLdkNode { // ======================================================================== supportsMessageSigning = () => true; - supportsMessageVerification = () => false; + supportsMessageVerification = () => true; + requiresVerifyPubkey = () => true; supportsLnurlAuth = () => true; supportsOnchainBalance = () => true; supportsOnchainSends = () => true; diff --git a/backends/LND.ts b/backends/LND.ts index bb3f9239e..923d7f1fc 100644 --- a/backends/LND.ts +++ b/backends/LND.ts @@ -872,6 +872,7 @@ export default class LND { supportsPeers = () => true; supportsMessageSigning = () => true; supportsMessageVerification = () => true; + requiresVerifyPubkey = () => false; supportsLnurlAuth = () => true; supportsOnchainBalance = () => true; supportsOnchainSends = () => true; diff --git a/backends/LightningNodeConnect.ts b/backends/LightningNodeConnect.ts index 49e4a5028..64cefdd05 100644 --- a/backends/LightningNodeConnect.ts +++ b/backends/LightningNodeConnect.ts @@ -709,6 +709,7 @@ export default class LightningNodeConnect { supportsPeers = () => true; supportsMessageSigning = () => this.permSignMessage; supportsMessageVerification = () => true; + requiresVerifyPubkey = () => false; supportsAddressMessageSigning = () => true; supportsLnurlAuth = () => true; supportsOnchainBalance = () => true; diff --git a/locales/en.json b/locales/en.json index 25d30614a..ba9f392e6 100644 --- a/locales/en.json +++ b/locales/en.json @@ -1026,6 +1026,8 @@ "views.Settings.SignMessage.noAddressForVerification": "No address provided for on-chain verification", "views.Settings.SignMessage.noDataReceived": "No data received from sign operation", "views.Settings.SignMessage.signOperationFailed": "Sign operation not supported", + "views.Settings.SignMessage.pubkeyToVerify": "Pubkey of signer", + "views.Settings.SignMessage.pleaseEnterPubkey": "Please enter the pubkey of the signer", "views.Settings.SignMessage.verificationOperationFailed": "Verification operation not supported", "views.Settings.Language.title": "Language", "views.Settings.Currency.title": "Currency", diff --git a/stores/MessageSignStore.ts b/stores/MessageSignStore.ts index f9831421d..4f497727e 100644 --- a/stores/MessageSignStore.ts +++ b/stores/MessageSignStore.ts @@ -7,6 +7,7 @@ interface VerificationRequest { msg: string; signature: string; addr?: string; + pubkey?: string; } export default class MessageSignStore { @@ -233,7 +234,8 @@ export default class MessageSignStore { this.signingMode === 'lightning' ? BackendUtils.verifyMessage({ msg: data.msg, - signature: data.signature + signature: data.signature, + pubkey: data.pubkey }) : BackendUtils.verifyMessageWithAddr( data.msg, diff --git a/utils/BackendUtils.ts b/utils/BackendUtils.ts index c697e6f1c..5b856c3a7 100644 --- a/utils/BackendUtils.ts +++ b/utils/BackendUtils.ts @@ -191,6 +191,7 @@ class BackendUtils { supportsMessageSigning = () => this.call('supportsMessageSigning'); supportsMessageVerification = () => this.call('supportsMessageVerification'); + requiresVerifyPubkey = () => this.call('requiresVerifyPubkey'); supportsLnurlAuth = () => this.call('supportsLnurlAuth'); supportsOnchainBalance = () => this.call('supportsOnchainBalance'); supportsOnchainSends = () => this.call('supportsOnchainSends'); diff --git a/views/Tools/SignVerifyMessage.tsx b/views/Tools/SignVerifyMessage.tsx index 4a909dde7..d4481c092 100644 --- a/views/Tools/SignVerifyMessage.tsx +++ b/views/Tools/SignVerifyMessage.tsx @@ -40,12 +40,14 @@ interface SignVerifyMessageState { messageToSign: string; messageToVerify: string; signatureToVerify: string; + pubkeyToVerify: string; selectedIndex: number; signingMethodIndex: number; selectedAddress: string; signingMode: string; supportsAddressMessageSigning: boolean; supportsMessageVerification: boolean; + requiresVerifyPubkey: boolean; loading: boolean; } @@ -61,12 +63,14 @@ export default class SignVerifyMessage extends React.Component< messageToSign: '', messageToVerify: '', signatureToVerify: '', + pubkeyToVerify: '', selectedIndex: 0, signingMethodIndex: 0, selectedAddress: '', signingMode: 'lightning', supportsAddressMessageSigning: false, supportsMessageVerification: true, + requiresVerifyPubkey: false, loading: false }; @@ -93,6 +97,10 @@ export default class SignVerifyMessage extends React.Component< this.setState({ supportsMessageVerification: false }); } + if (BackendUtils.requiresVerifyPubkey()) { + this.setState({ requiresVerifyPubkey: true }); + } + this.handleRouteParams(route?.params || {}); }; @@ -225,6 +233,7 @@ export default class SignVerifyMessage extends React.Component< messageToSign: '', messageToVerify: '', signatureToVerify: '', + pubkeyToVerify: '', selectedAddress: '' }); @@ -609,7 +618,7 @@ export default class SignVerifyMessage extends React.Component< 'views.Settings.SignMessage.success' )} /> - {pubkey && ( + {pubkey && !this.state.requiresVerifyPubkey && ( { if (this.validateSigningInput()) { - signMessage(messageToSign); + signMessage(messageToSign.trim()); } }} /> @@ -938,6 +961,8 @@ export default class SignVerifyMessage extends React.Component< ); }} locked={loading} + autoCorrect={false} + autoCapitalize="none" multiline style={{ height: 100 @@ -964,6 +989,8 @@ export default class SignVerifyMessage extends React.Component< text ); }} + autoCorrect={false} + autoCapitalize="none" multiline style={{ height: 100 @@ -972,6 +999,33 @@ export default class SignVerifyMessage extends React.Component< /> + {this.state.requiresVerifyPubkey && ( + + + {localeString( + 'views.Settings.SignMessage.pubkeyToVerify' + )} + + { + this.handleTextInputChange( + 'pubkeyToVerify', + text + ); + }} + autoCorrect={false} + autoCapitalize="none" + locked={loading} + /> + + )} + {this.renderVerificationResult()} @@ -1010,6 +1064,7 @@ export default class SignVerifyMessage extends React.Component< const { messageToVerify, signatureToVerify, + pubkeyToVerify, selectedAddress, signingMode } = this.state; @@ -1021,8 +1076,9 @@ export default class SignVerifyMessage extends React.Component< const { supportsAddressMessageSigning } = this.state; const verifyRequest = { - msg: messageToVerify, - signature: signatureToVerify, + msg: messageToVerify.trim(), + signature: signatureToVerify.trim(), + pubkey: pubkeyToVerify.trim() || undefined, addr: supportsAddressMessageSigning && signingMode === 'onchain' ? selectedAddress