Skip to content

silent payments: file-based key import/export - #56

Merged
rustaceanrob merged 2 commits into
kernel-node:masterfrom
pzafonte:sp-keys-file
May 24, 2026
Merged

silent payments: file-based key import/export#56
rustaceanrob merged 2 commits into
kernel-node:masterfrom
pzafonte:sp-keys-file

Conversation

@pzafonte

Copy link
Copy Markdown
Contributor

Implements file imports from #55:

  • wallet::io::FileExt trait that carries save/load so file-backed types can reuse the path handling.
  • wallet generate-keys --out <path> writes a binary keys file (mode 0o600 on Unix, refuses to overwrite).
  • wallet import-keys-file <path> reads it back.
  • --sp-keys-file <path> (node option) auto-imports on startup; load errors warn and continue.

Comment thread crates/wallet/src/silentpayments/keys_file.rs Outdated
Comment thread crates/wallet/src/silentpayments/keys_file.rs
Comment thread src/bin/cli.rs Outdated
Comment thread src/bin/node.rs Outdated
Comment thread src/bin/node.rs Outdated
@rustaceanrob

Copy link
Copy Markdown
Contributor

High level comment, we should allow the spend key to be passed by either private scalar or x-only public key in the file. This would allow us to use hardware signers and still use this import format. I suggest changing the file format to have an enum either 0 for private key or 1 for x-only key, followed by the bytes. Our default for generate-keys will be to write the private key.

Comment thread crates/wallet/src/silentpayments/keys_file.rs Outdated
pzafonte added 2 commits May 23, 2026 13:33
Extend `wallet generate-keys` with `--out <path>`. The file refuses
to overwrite an existing path.

Format: 4-byte magic `SPKF`, 32-byte scan secret, 1-byte spend tag,
32-byte spend material. Tag 0 stores the spend secret (software
wallet); tag 1 stores the x-only spend public key (hardware-signer /
watch-only setup). Incompatible revisions bump the magic.

A new `wallet::io::FileExt` trait carries `save`/`load` so other
file-backed types can reuse the path handling.
Add `--sp-keys-file <path>`. When set, the node loads the binary keys
file before block scanning and imports it. Failures (missing file,
bad magic, invalid key) abort startup so a misconfigured keys-file
path surfaces clearly rather than as a silently-unimported wallet.

The IPC handler's inline import logic moves to a new
`Wallet::import_keys(scan_key, spend_xonly)` shared with the startup
path.
@pzafonte

Copy link
Copy Markdown
Contributor Author

High level comment, we should allow the spend key to be passed by either private scalar or x-only public key in the file. This would allow us to use hardware signers and still use this import format. I suggest changing the file format to have an enum either 0 for private key or 1 for x-only key, followed by the bytes. Our default for generate-keys will be to write the private key.

keys_file.rs now has a SpendKey { Secret(SecretKey), XOnlyPublic(XOnlyPublicKey) } enum and a 1-byte tag.

@rustaceanrob

Copy link
Copy Markdown
Contributor

I'm going to pull and test locally but looking good to me

scan_key: SecretKey,
spend_xonly: XOnlyPublicKey,
) -> Result<(), ::silentpayments::Error> {
let spend_pub = PublicKey::from_x_only_public_key(spend_xonly, Parity::Even);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know much about the semantics of taproot, but I assume it's defined all x-only keys are even parity? I only ask because it seems strange the from_x_only_public_key function would need a parity argument at all if it's just going to be passed as Even every time

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe from_x_only_public_key is just the secp256k1 primitive and not taproot-specific.

@rustaceanrob
rustaceanrob marked this pull request as ready for review May 23, 2026 18:56
@rustaceanrob

Copy link
Copy Markdown
Contributor

Tested locally and received a payment. Nice job let's keep it rollin

ACK 6981b69

@rustaceanrob
rustaceanrob merged commit a457a7e into kernel-node:master May 24, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants