feat: Node::export_channel_attestation (RFC staging)#1
Draft
rsafier wants to merge 3 commits into
Draft
Conversation
Adds a read-only accessor on `Node` that returns a cryptographically verifiable snapshot of the current state of a channel, shaped for use by external custodial-attestation tooling (see `lightning-attestor` / the upstream RFC "expose channel attestation data"). The bundle contains, per channel: - The unsigned commitment transaction we would broadcast on force-close - The counterparty's ECDSA signature over it (BIP-143, SIGHASH_ALL) - Both funding pubkeys, DISTINGUISHABLY (holder vs counterparty) - Balances, pending HTLCs, capacity, is_outbound Exposes no secret material — the counterparty's signature is cryptographically attributable to them regardless of who holds it. Implementation: - Reaches the `ChannelMonitor` via `chain_monitor.get_monitor()`. - Calls `unsafe_get_latest_holder_commitment_txn()` to get the signed holder commit tx (requires the `unsafe_revoked_tx_signing` feature on the `lightning` dep, enabled here; despite the name the method is a pure read with no broadcast side-effect). - Parses the funding-input witness to extract both funding pubkeys and both signatures. - Uses `ChannelMonitor::channel_keys_id` (exposed in the paired rust-lightning fork) + `SignerProvider::derive_channel_signer` to rederive the holder signer and obtain the holder funding pubkey, disambiguating the lex-sorted pair returned by the witness. - Strips the witness to produce the unsigned commit tx. Cargo.toml: adds a `[patch]` section pointing lightning-* git deps at the rsafier/rust-lightning fork branch `rfc/channel-keys-id-accessor`, and adds the `unsafe_revoked_tx_signing` feature to the `lightning` dep. Consumers: - `lightningdevkit/ldk-server` gains a `GetChannelAttestations` RPC wrapping this call (RFC: "include commitment-bundle data on channel-state events"). - Downstream attestor binaries (Go / Rust) consume the bundle and emit operator-signed artifacts verifiable by any party holding the operator's Ed25519 public key.
OP_2 lives at byte 69 and OP_CHECKMULTISIG at byte 70 in the 71-byte BOLT-3 funding redeem script. Previous offsets were off by one (and the operator-precedence goof compared a 2-byte slice to a 1-byte array).
a3dc7f6 to
20e0faa
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Status: review-staging draft on the rsafier fork. See rsafier/rust-lightning#1 for the one-accessor PR this depends on.
Summary
Adds a new public read-only API on `Node`:
```rust
pub fn export_channel_attestation(
&self, channel_id: &ChannelId,
) -> Result<attestation::ChannelAttestation, Error>;
pub fn list_channel_attestations(&self) -> Vecattestation::ChannelAttestation;
```
Returns, for the current state of each channel:
No secret material exposed. The counterparty's signature is cryptographically attributable to them regardless of who holds it.
Implementation (new module `src/attestation.rs`, ~180 LOC)
Proof
Regtest end-to-end in the lightning-attestor harness: two `ldk-server` nodes built from this branch, six channel scenarios (initial / outbound-pay / bidirectional / htlc-inflight / htlc-settled / multi-channel). Each snapshot's extracted bundle passes an independent BIP-143 counterparty-sig verification against the counterparty's funding pubkey.
Non-goals
Ask
Feedback on the method signature, the module placement, and whether `ChannelAttestation` should live in `ldk-node` or move up into rust-lightning (we went with ldk-node since the witness-parsing + signer-rederivation is LDK-node-level plumbing, not a rust-lightning primitive).