Interface IRemoteSignerTransport
- Namespace
- NArk.Abstractions.Wallets
- Assembly
- NArk.Abstractions.dll
Transport abstraction over a remote signer. Mirrors IArkadeWalletSigner but
adds a walletId argument to every call so a single transport instance can serve
multiple wallets (e.g. a multi-user server-side signing service, an HWI bridge, or a
browser-extension wallet shared across tabs).
public interface IRemoteSignerTransport
Remarks
Register an implementation in DI alongside any wallet whose Secret
is null/empty (i.e. no local signing material). The default IWalletProvider
implementation probes KnowsWalletAsync(string, CancellationToken) to decide whether such a wallet is
remote-signed (signer is a IArkadeWalletSigner proxy over this transport) or
watch-only (GetSignerAsync(string, CancellationToken) returns null). Capability is
answered by this interface, not by a flag on the wallet record.
The MuSig2 nonce flow keeps the secret half on the transport side:
GenerateNoncesAsync(string, OutputDescriptor, MusigContext, string, CancellationToken) returns only the public nonce, the implementation retains
the secret half indexed by walletId + sessionId, and SignMusigAsync(string, OutputDescriptor, MusigContext, string, CancellationToken)
consumes it on use. Implementations need an eviction policy for abandoned nonces (TTL or
bounded count) so the store does not grow without bound — the SDK-side
IArkadeWalletSigner contract requires SignMusig to throw if no matching nonce
is found.
Methods
GenerateNoncesAsync(string, OutputDescriptor, MusigContext, string, CancellationToken)
Generates a fresh MuSig2 nonce pair for the supplied context, retains the secret
half on the transport side indexed by walletId +
sessionId, and returns the public half so the caller can complete
nonce aggregation with cosigners. The secret half never crosses the transport
boundary — that is the cryptographic claim of remote signing.
Task<MusigPubNonce> GenerateNoncesAsync(string walletId, OutputDescriptor descriptor, MusigContext context, string sessionId, CancellationToken cancellationToken = default)
Parameters
walletIdstringThe wallet whose key contributes the nonce.
descriptorOutputDescriptorThe descriptor identifying the signing key.
contextMusigContextThe MuSig2 context the nonce is generated for.
sessionIdstringA caller-supplied identifier unique to this signing operation, used to correlate this nonce with the matching SignMusigAsync(string, OutputDescriptor, MusigContext, string, CancellationToken) call. Typically a transaction identifier (txid).
cancellationTokenCancellationTokenCancellation token.
Returns
- Task<MusigPubNonce>
GetPubKeyAsync(string, OutputDescriptor, CancellationToken)
Gets the compressed public key for the given descriptor, preserving parity.
Task<ECPubKey> GetPubKeyAsync(string walletId, OutputDescriptor descriptor, CancellationToken cancellationToken = default)
Parameters
walletIdstringThe wallet whose key is being requested.
descriptorOutputDescriptorThe descriptor identifying the key to return.
cancellationTokenCancellationTokenCancellation token.
Returns
- Task<ECPubKey>
KnowsWalletAsync(string, CancellationToken)
Indicates whether this transport can sign for the given wallet. Used by the wallet
provider to distinguish remote-signed wallets from watch-only ones when the wallet has
no local Secret: true → produce a remote-signer proxy;
false → fall through to watch-only (signer = null).
Task<bool> KnowsWalletAsync(string walletId, CancellationToken cancellationToken = default)
Parameters
walletIdstringcancellationTokenCancellationToken
Returns
SignAsync(string, OutputDescriptor, uint256, CancellationToken)
Produces a BIP-340 Schnorr signature over hash using
the descriptor's private key, returning the x-only pubkey alongside the
signature.
Task<(ECXOnlyPubKey, SecpSchnorrSignature)> SignAsync(string walletId, OutputDescriptor descriptor, uint256 hash, CancellationToken cancellationToken = default)
Parameters
walletIdstringThe wallet whose key signs.
descriptorOutputDescriptorThe descriptor identifying the signing key.
hashuint256The 32-byte hash to sign.
cancellationTokenCancellationTokenCancellation token.
Returns
- Task<(ECXOnlyPubKey, SecpSchnorrSignature)>
Remarks
Implementations MUST sign with aux_rand set to 32 zero bytes so the
signature is deterministic per (key, hash).
The requirement is about what a signature may be used FOR, not only about signing. Anything that derives a secret from one — a swap preimage being the case this SDK has shipped — needs the same descriptor and the same wallet to reproduce it exactly, or a restored wallet re-derives a different secret and cannot spend what the old one committed to. The in-box signing sources honour this; a transport that does not is not interchangeable with them, however valid its signatures are on their own terms.
In NBitcoin.Secp256k1, use ECPrivKey.SignBIP340(msg, new byte[32]) — the
no-auxData overload SignBIP340(msg) draws from the system RNG on every call
and is therefore non-deterministic.
Implementations that randomise aux_rand (e.g. for side-channel resistance on a
hardware signer) break that contract, and a wallet on such a transport cannot rebuild
from its seed any secret that was derived from a signature.
SignMusigAsync(string, OutputDescriptor, MusigContext, string, CancellationToken)
Produces a MuSig2 partial signature for the given context using the descriptor's
private key and the secret nonce the transport retained when GenerateNoncesAsync(string, OutputDescriptor, MusigContext, string, CancellationToken)
was called for the same sessionId. The secret nonce is consumed on
this call.
Task<MusigPartialSignature> SignMusigAsync(string walletId, OutputDescriptor descriptor, MusigContext context, string sessionId, CancellationToken cancellationToken = default)
Parameters
walletIdstringThe wallet whose key signs.
descriptorOutputDescriptorThe descriptor identifying the signing key.
contextMusigContextThe MuSig2 context (cosigner set + sighash) the nonce was generated for.
sessionIdstringThe same session identifier that was passed to GenerateNoncesAsync(string, OutputDescriptor, MusigContext, string, CancellationToken).
cancellationTokenCancellationTokenCancellation token.
Returns
- Task<MusigPartialSignature>
Exceptions
- InvalidOperationException
No secret nonce is stored for
walletId+sessionId(it was never generated, was already consumed, or has been evicted by the transport's eviction policy).