diff --git a/Cargo.toml b/Cargo.toml index d13a9f6..f5dc13b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tonic_lnd" -version = "0.5.0" +version = "0.25.0" authors = ["Martin Habovstiak <martin.habovstiak@gmail.com>"] edition = "2018" description = "An async library implementing LND RPC via tonic and prost" @@ -22,6 +22,7 @@ tokio = { version = "1.7.1", features = ["fs"] } tracing = { version = "0.1", features = ["log"], optional = true } rust_decimal = { version = "1.26.1", features = ["db-postgres"] } rust_decimal_macros = "1.26.1" +webpki-roots = "0.19.0" rand = "0.8.5" serde = { version = "1.0.145", features = ["derive"] } diff --git a/build.rs b/build.rs index 37fdb65..e0b913f 100644 --- a/build.rs +++ b/build.rs @@ -22,7 +22,8 @@ fn main() -> std::io::Result<()> { "faraday.proto", "looprpc/client.proto", "invoicesrpc/invoices.proto", - "walletunlocker.proto" + "walletunlocker.proto", + "stateservice.proto", ]; let proto_paths: Vec<_> = protos @@ -74,6 +75,19 @@ fn main() -> std::io::Result<()> { .type_attribute("ChannelBackup", "#[derive(serde::Deserialize, serde::Serialize)]") .type_attribute("ChannelPoint", "#[derive(serde::Deserialize, serde::Serialize)]") .type_attribute("funding_txid", "#[derive(serde::Deserialize, serde::Serialize)]") + //StateService fields + .type_attribute("GetState", "#[derive(serde::Deserialize, serde::Serialize)]") + .type_attribute("SubscribeState", "#[derive(serde::Deserialize, serde::Serialize)]") + //PendingChannels fields + .type_attribute("PendingChannelsResponse", "#[derive(serde::Deserialize, serde::Serialize)]") + .type_attribute("Commitments", "#[derive(serde::Deserialize, serde::Serialize)]") + .type_attribute("PendingOpenChannel", "#[derive(serde::Deserialize, serde::Serialize)]") + .type_attribute("PendingChannel", "#[derive(serde::Deserialize, serde::Serialize)]") + .type_attribute("ClosedChannel", "#[derive(serde::Deserialize, serde::Serialize)]") + .type_attribute("ForceClosedChannel", "#[derive(serde::Deserialize, serde::Serialize)]") + .type_attribute("PendingHTLC", "#[derive(serde::Deserialize, serde::Serialize)]") + .type_attribute("AnchorState", "#[derive(serde::Deserialize, serde::Serialize)]") + .type_attribute("WaitingCloseChannel", "#[derive(serde::Deserialize, serde::Serialize)]") .format(false) .compile(&proto_paths, &[dir])?; Ok(()) diff --git a/examples/send_via_route.rs b/examples/send_via_route.rs index ae395f7..dd3d37e 100644 --- a/examples/send_via_route.rs +++ b/examples/send_via_route.rs @@ -25,7 +25,7 @@ async fn main() { // All calls require at least empty parameter .send_to_route_v2(tonic_lnd::routerrpc::SendToRouteRequest { payment_hash: vec![], - route: Some(Route {}), + route: Some(Route { total_time_lock: 1000, total_fees: 100000, total_amt: 1000000, hops: todo!(), total_fees_msat: 100, total_amt_msat: 1000 }), skip_temp_err: true, }) .await diff --git a/examples/state_service.rs b/examples/state_service.rs new file mode 100644 index 0000000..20327be --- /dev/null +++ b/examples/state_service.rs @@ -0,0 +1,29 @@ +// This example unlocks a locked initialized node. +// +// This program accepts three arguments: address, cert file, macaroon file +// The address must start with `https://`! + +#[tokio::main] +async fn main() { + let mut args = std::env::args_os(); + args.next().expect("not even zeroth arg given"); + let address = args.next().expect("missing arguments: address, cert file, macaroon file"); + let cert_file = args.next().expect("missing arguments: cert file, macaroon file"); + let macaroon_file = args.next().expect("missing argument: macaroon file"); + let address = address.into_string().expect("address is not UTF-8"); + + // Connecting to LND requires only address, cert file, and macaroon file + let mut client = tonic_lnd::connect(address, cert_file, macaroon_file) + .await + .expect("failed to connect"); + + let unlock = client + .state() + .get_state(tonic_lnd::lnrpc::GetStateRequest { }) + .await + .expect("failed to get info"); + + // We only print it here, note that in real-life code you may want to call `.into_inner()` on + // the response to get the message. + println!("{:#?}", unlock); +} diff --git a/src/lib.rs b/src/lib.rs index 55edc94..10324fa 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -85,6 +85,7 @@ pub type LoopClient = looprpc::swap_client_client::SwapClientClient<InterceptedS pub type FaradayServerClient = frdrpc::faraday_server_client::FaradayServerClient<InterceptedService<Channel, MacaroonInterceptor>>; pub type InvoicesClient = invoicesrpc::invoices_client::InvoicesClient<InterceptedService<Channel, MacaroonInterceptor>>; pub type WalletUnlockerClient = lnrpc::wallet_unlocker_client::WalletUnlockerClient<InterceptedService<Channel, MacaroonInterceptor>>; +pub type StateClient = lnrpc::state_client::StateClient<InterceptedService<Channel, MacaroonInterceptor>>; /// The client returned by `connect` function /// @@ -93,10 +94,11 @@ pub struct Client { lightning: LightningClient, wallet: WalletKitClient, router: RouterClient, - loopclient: LoopClient, + loopclient: LoopClient, faraday: FaradayServerClient, invoices: InvoicesClient, wallet_unlocker: WalletUnlockerClient, + state: StateClient, } impl Client { @@ -129,6 +131,10 @@ impl Client { pub fn wallet_unlocker(&mut self) -> &mut WalletUnlockerClient { &mut self.wallet_unlocker } + + pub fn state(&mut self) -> &mut StateClient { + &mut self.state + } } /// [`tonic::Status`] is re-exported as `Error` for convenience. @@ -215,7 +221,7 @@ pub async fn connect<A, CP, MP>(address: A, cert_file: CP, macaroon_file: MP) -> let address_str = address.to_string(); let conn = try_map_err!(address .try_into(), |error| InternalConnectError::InvalidAddress { address: address_str.clone(), error: Box::new(error), }) - .tls_config(tls::config(cert_file).await?) + .tls_config(tls::config(Some(cert_file)).await?) .map_err(InternalConnectError::TlsConfig)? .connect() .await @@ -233,6 +239,7 @@ pub async fn connect<A, CP, MP>(address: A, cert_file: CP, macaroon_file: MP) -> faraday: frdrpc::faraday_server_client::FaradayServerClient::with_interceptor(conn.clone(), interceptor.clone()), invoices: invoicesrpc::invoices_client::InvoicesClient::with_interceptor(conn.clone(), interceptor.clone()), wallet_unlocker: lnrpc::wallet_unlocker_client::WalletUnlockerClient::with_interceptor(conn.clone(), interceptor.clone()), + state: lnrpc::state_client::StateClient::with_interceptor(conn.clone(), interceptor.clone()), }; Ok(client) } @@ -242,7 +249,7 @@ pub async fn in_mem_connect<A>(address: A, cert_file_as_hex: String, macaroon_as let address_str = address.to_string(); let conn = try_map_err!(address .try_into(), |error| InternalConnectError::InvalidAddress { address: address_str.clone(), error: Box::new(error), }) - .tls_config(tls::config_with_hex(cert_file_as_hex).await?) + .tls_config(tls::config_with_hex(Some(cert_file_as_hex)).await?) .map_err(InternalConnectError::TlsConfig)? .connect() .await @@ -260,6 +267,7 @@ pub async fn in_mem_connect<A>(address: A, cert_file_as_hex: String, macaroon_as faraday: frdrpc::faraday_server_client::FaradayServerClient::with_interceptor(conn.clone(), interceptor.clone()), invoices: invoicesrpc::invoices_client::InvoicesClient::with_interceptor(conn.clone(), interceptor.clone()), wallet_unlocker: lnrpc::wallet_unlocker_client::WalletUnlockerClient::with_interceptor(conn.clone(), interceptor.clone()), + state: lnrpc::state_client::StateClient::with_interceptor(conn.clone(), interceptor.clone()), }; Ok(client) } @@ -269,18 +277,43 @@ mod tls { use rustls::{RootCertStore, Certificate, TLSError, ServerCertVerified}; use webpki::DNSNameRef; use crate::error::{ConnectError, InternalConnectError}; + use webpki_roots; - pub(crate) async fn config(path: impl AsRef<Path> + Into<PathBuf>) -> Result<tonic::transport::ClientTlsConfig, ConnectError> { + pub(crate) async fn config(path: Option<impl AsRef<Path> + Into<PathBuf>>) -> Result<tonic::transport::ClientTlsConfig, ConnectError> { let mut tls_config = rustls::ClientConfig::new(); - tls_config.dangerous().set_certificate_verifier(std::sync::Arc::new(CertVerifier::load(path).await?)); + + match path { + Some(cert_path) if cert_path.as_ref().exists() => { + tls_config.dangerous().set_certificate_verifier(std::sync::Arc::new(CertVerifier::load(cert_path).await?)); + }, + _ => { + tls_config.root_store.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS); + #[cfg(feature = "tracing")] { + tracing::warn!("Certificate file not provided or does not exist. Using system trust anchors"); + } + } + } + tls_config.set_protocols(&["h2".into()]); Ok(tonic::transport::ClientTlsConfig::new() .rustls_client_config(tls_config)) } - pub(crate) async fn config_with_hex(file_as_hex: String) -> Result<tonic::transport::ClientTlsConfig, ConnectError> { + pub(crate) async fn config_with_hex(file_as_hex: Option<String>) -> Result<tonic::transport::ClientTlsConfig, ConnectError> { let mut tls_config = rustls::ClientConfig::new(); - tls_config.dangerous().set_certificate_verifier(std::sync::Arc::new(CertVerifier::load_as_hex(file_as_hex).await?)); + + match file_as_hex { + Some(hex_cert) if !hex_cert.is_empty() => { + tls_config.dangerous().set_certificate_verifier(std::sync::Arc::new(CertVerifier::load_as_hex(hex_cert).await?)); + }, + _ => { + tls_config.root_store.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS); + #[cfg(feature = "tracing")] { + tracing::warn!("Certificate hex not provided or empty. Using system trust anchors"); + } + } + } + tls_config.set_protocols(&["h2".into()]); Ok(tonic::transport::ClientTlsConfig::new() .rustls_client_config(tls_config)) @@ -326,11 +359,11 @@ mod tls { impl rustls::ServerCertVerifier for CertVerifier { fn verify_server_cert(&self, _roots: &RootCertStore, presented_certs: &[Certificate], _dns_name: DNSNameRef<'_>, _ocsp_response: &[u8]) -> Result<ServerCertVerified, TLSError> { - + if self.certs.len() != presented_certs.len() { return Err(TLSError::General(format!("Mismatched number of certificates (Expected: {}, Presented: {})", self.certs.len(), presented_certs.len()))); } - + for (c, p) in self.certs.iter().zip(presented_certs.iter()) { if *p.0 != **c { return Err(TLSError::General(format!("Server certificates do not match ours"))); @@ -344,4 +377,4 @@ mod tls { Ok(ServerCertVerified::assertion()) } } -} +} \ No newline at end of file diff --git a/vendor/lightning.proto b/vendor/lightning.proto index 89b298e..96fc36b 100644 --- a/vendor/lightning.proto +++ b/vendor/lightning.proto @@ -294,8 +294,7 @@ service Lightning { duplicated invoices are rejected, therefore all invoices *must* have a unique payment preimage. */ - rpc AddInvoice (InvoiceRequest) returns (AddInvoiceResponse); - // rpc AddInvoiceWithFixes (Invoice) returns (AddInvoiceResponse); + rpc AddInvoice (Invoice) returns (AddInvoiceResponse); /* lncli: `listinvoices` ListInvoices returns a list of all the invoices currently stored within the @@ -568,6 +567,10 @@ service Lightning { /* lncli: `subscribecustom` SubscribeCustomMessages subscribes to a stream of incoming custom peer messages. + + To include messages with type outside of the custom range (>= 32768) lnd + needs to be compiled with the `dev` build tag, and the message type to + override should be specified in lnd's experimental protocol configuration. */ rpc SubscribeCustomMessages (SubscribeCustomMessagesRequest) returns (stream CustomMessage); @@ -578,6 +581,28 @@ service Lightning { zero conf). */ rpc ListAliases (ListAliasesRequest) returns (ListAliasesResponse); + + /* + LookupHtlcResolution retrieves a final htlc resolution from the database. + If the htlc has no final resolution yet, a NotFound grpc status code is + returned. + */ + rpc LookupHtlcResolution (LookupHtlcResolutionRequest) + returns (LookupHtlcResolutionResponse); +} + +message LookupHtlcResolutionRequest { + uint64 chan_id = 1; + + uint64 htlc_index = 2; +} + +message LookupHtlcResolutionResponse { + // Settled is true is the htlc was settled. If false, the htlc was failed. + bool settled = 1; + + // Offchain indicates whether the htlc was resolved off-chain or on-chain. + bool offchain = 2; } message SubscribeCustomMessagesRequest { @@ -599,6 +624,9 @@ message SendCustomMessageRequest { bytes peer = 1; // Message type. This value needs to be in the custom range (>= 32768). + // To send a type < custom range, lnd needs to be compiled with the `dev` + // build tag, and the message type to override should be specified in lnd's + // experimental protocol configuration. uint32 type = 2; // Raw message data. @@ -638,6 +666,7 @@ enum OutputScriptType { SCRIPT_TYPE_NULLDATA = 6; SCRIPT_TYPE_NON_STANDARD = 7; SCRIPT_TYPE_WITNESS_UNKNOWN = 8; + SCRIPT_TYPE_WITNESS_V1_TAPROOT = 9; } message OutputDetail { @@ -684,7 +713,7 @@ message Transaction { // Addresses that received funds for this transaction. Deprecated as it is // now incorporated in the output_details field. - repeated string dest_addresses = 8 [deprecated = true]; + //repeated string dest_addresses = 8 [deprecated = true]; // Outputs that received funds for this transaction repeated OutputDetail output_details = 11; @@ -1130,12 +1159,14 @@ message SendCoinsRequest { // Deprecated, use sat_per_vbyte. // A manual fee rate set in sat/vbyte that should be used when crafting the // transaction. - int64 sat_per_byte = 5 [deprecated = true]; + //int64 sat_per_byte = 5 [deprecated = true]; /* If set, then the amount field will be ignored, and lnd will attempt to send all the coins under control of the internal wallet to the specified address. + send all the coins under control of the internal wallet or in the selected + utxos if specified to the address given in the command */ bool send_all = 6; @@ -1148,6 +1179,9 @@ message SendCoinsRequest { // Whether unconfirmed outputs should be used as inputs for the transaction. bool spend_unconfirmed = 9; + + // A list of selected outpoints for the transaction input in order. + repeated OutPoint outpoints = 10; } message SendCoinsResponse { // The transaction ID of the transaction @@ -1510,6 +1544,19 @@ message Channel { // This is the confirmed / on-chain zero-conf SCID. uint64 zero_conf_confirmed_scid = 33; + + // The configured alias name of our peer. + string peer_alias = 34; + + // This is the peer SCID alias. + uint64 peer_scid_alias = 35 [jstype = JS_STRING]; + + /* + An optional note-to-self to go along with the channel containing some + useful information. This is only ever stored locally and in no way impacts + the channel's operation. + */ + string memo = 36; } message ListChannelsRequest { @@ -1523,6 +1570,11 @@ message ListChannelsRequest { empty, all channels will be returned. */ bytes peer = 5; + + // Informs the server if the peer alias lookup per channel should be + // enabled. It is turned off by default in order to avoid degradation of + // performance for existing clients. + bool peer_alias_lookup = 6; } message ListChannelsResponse { // The list of active channels @@ -1871,7 +1923,7 @@ message GetInfoResponse { Whether the current node is connected to testnet. This field is deprecated and the network field should be used instead **/ - bool testnet = 10 [deprecated = true]; + //bool testnet = 10 [deprecated = true]; reserved 11; @@ -1891,6 +1943,9 @@ message GetInfoResponse { Indicates whether the HTLC interceptor API is in always-on mode. */ bool require_htlc_interceptor = 21; + + // Indicates whether final htlc resolutions are stored on disk. + bool store_final_htlc_resolutions = 22; } message GetRecoveryInfoRequest { @@ -1950,7 +2005,7 @@ message CloseChannelRequest { // Deprecated, use sat_per_vbyte. // A manual fee rate set in sat/vbyte that should be used when crafting the // closure transaction. - // int64 sat_per_byte = 4 [deprecated = true]; + //int64 sat_per_byte = 4 [deprecated = true]; /* An optional address to send funds to in the case of a cooperative close. @@ -2097,7 +2152,7 @@ message OpenChannelRequest { The hex encoded pubkey of the node to open a channel with. Deprecated now that the REST gateway supports base64 encoding of bytes fields. */ - string node_pubkey_string = 3 [deprecated = true]; + //string node_pubkey_string = 3 [deprecated = true]; // The number of satoshis the wallet should commit to the channel int64 local_funding_amount = 4; @@ -2113,7 +2168,7 @@ message OpenChannelRequest { // Deprecated, use sat_per_vbyte. // A manual fee rate set in sat/vbyte that should be used when crafting the // funding transaction. - int64 sat_per_byte = 7 [deprecated = true]; + //int64 sat_per_byte = 7 [deprecated = true]; // Whether this channel should be private, not announced to the greater // network. @@ -2190,6 +2245,54 @@ message OpenChannelRequest { attempted. */ bool scid_alias = 20; + + /* + The base fee charged regardless of the number of milli-satoshis sent. + */ + uint64 base_fee = 21; + + /* + The fee rate in ppm (parts per million) that will be charged in + proportion of the value of each forwarded HTLC. + */ + uint64 fee_rate = 22; + + /* + If use_base_fee is true the open channel announcement will update the + channel base fee with the value specified in base_fee. In the case of + a base_fee of 0 use_base_fee is needed downstream to distinguish whether + to use the default base fee value specified in the config or 0. + */ + bool use_base_fee = 23; + + /* + If use_fee_rate is true the open channel announcement will update the + channel fee rate with the value specified in fee_rate. In the case of + a fee_rate of 0 use_fee_rate is needed downstream to distinguish whether + to use the default fee rate value specified in the config or 0. + */ + bool use_fee_rate = 24; + + /* + The number of satoshis we require the remote peer to reserve. This value, + if specified, must be above the dust limit and below 20% of the channel + capacity. + */ + uint64 remote_chan_reserve_sat = 25; + + /* + If set, then lnd will attempt to commit all the coins under control of the + internal wallet to open the channel, and the LocalFundingAmount field must + be zero and is ignored. + */ + bool fund_max = 26; + + /* + An optional note-to-self to go along with the channel containing some + useful information. This is only ever stored locally and in no way impacts + the channel's operation. + */ + string memo = 27; } message OpenStatusUpdate { oneof update { @@ -2564,9 +2667,17 @@ message PendingChannelsResponse { repeated PendingHTLC pending_htlcs = 8; + /* + There are three resolution states for the anchor: + limbo, lost and recovered. Derive the current state + from the limbo and recovered balances. + */ enum AnchorState { + // The recovered_balance is zero and limbo_balance is non-zero. LIMBO = 0; + // The recovered_balance is non-zero. RECOVERED = 1; + // A state that is neither LIMBO nor RECOVERED. LOST = 2; } @@ -3012,6 +3123,9 @@ message LightningNode { repeated NodeAddress addresses = 4; string color = 5; map<uint32, Feature> features = 6; + + // Custom node announcement tlv records. + map<uint64, bytes> custom_records = 7; } message NodeAddress { @@ -3027,6 +3141,9 @@ message RoutingPolicy { bool disabled = 5; uint64 max_htlc_msat = 6; uint32 last_update = 7; + + // Custom channel update tlv records. + map<uint64, bytes> custom_records = 8; } /* @@ -3054,6 +3171,9 @@ message ChannelEdge { RoutingPolicy node1_policy = 7; RoutingPolicy node2_policy = 8; + + // Custom channel announcement tlv records. + map<uint64, bytes> custom_records = 9; } message ChannelGraphRequest { @@ -3246,198 +3366,6 @@ message AMPInvoiceState { int64 amt_paid_msat = 5; } -message InvoiceRequest { - /* - An optional memo to attach along with the invoice. Used for record keeping - purposes for the invoice's creator, and will also be set in the description - field of the encoded payment request if the description_hash field is not - being used. - */ - string memo = 1; - - // reserved 2; - - /* - The hex-encoded preimage (32 byte) which will allow settling an incoming - HTLC payable to this preimage. When using REST, this field must be encoded - as base64. - */ - // bytes r_preimage = 3; - - /* - The hash of the preimage. When using REST, this field must be encoded as - base64. - Note: Output only, don't specify for creating an invoice. - */ - // bytes r_hash = 4; - - /* - The value of this invoice in satoshis - - The fields value and value_msat are mutually exclusive. - */ - // int64 value = 5; - - /* - The value of this invoice in millisatoshis - - The fields value and value_msat are mutually exclusive. - */ - int64 value_msat = 23; - - /* - Whether this invoice has been fulfilled - - The field is deprecated. Use the state field instead (compare to SETTLED). - */ - // bool settled = 6 [deprecated = true]; - - /* - When this invoice was created. - Note: Output only, don't specify for creating an invoice. - */ - // int64 creation_date = 7; - - /* - When this invoice was settled. - Note: Output only, don't specify for creating an invoice. - */ - // int64 settle_date = 8; - - /* - A bare-bones invoice for a payment within the Lightning Network. With the - details of the invoice, the sender has all the data necessary to send a - payment to the recipient. - Note: Output only, don't specify for creating an invoice. - */ - // string payment_request = 9; - - /* - Hash (SHA-256) of a description of the payment. Used if the description of - payment (memo) is too long to naturally fit within the description field - of an encoded payment request. When using REST, this field must be encoded - as base64. - */ - // bytes description_hash = 10; - - // Payment request expiry time in seconds. Default is 3600 (1 hour). - // int64 expiry = 11; - - // Fallback on-chain address. - // string fallback_addr = 12; - - // Delta to use for the time-lock of the CLTV extended to the final hop. - // uint64 cltv_expiry = 13; - - /* - Route hints that can each be individually used to assist in reaching the - invoice's destination. - */ - // repeated RouteHint route_hints = 14; - - // Whether this invoice should include routing hints for private channels. - bool private = 15; - - /* - The "add" index of this invoice. Each newly created invoice will increment - this index making it monotonically increasing. Callers to the - SubscribeInvoices call can use this to instantly get notified of all added - invoices with an add_index greater than this one. - Note: Output only, don't specify for creating an invoice. - */ - // uint64 add_index = 16; - - /* - The "settle" index of this invoice. Each newly settled invoice will - increment this index making it monotonically increasing. Callers to the - SubscribeInvoices call can use this to instantly get notified of all - settled invoices with an settle_index greater than this one. - Note: Output only, don't specify for creating an invoice. - */ - // uint64 settle_index = 17; - - // Deprecated, use amt_paid_sat or amt_paid_msat. - // int64 amt_paid = 18 [deprecated = true]; - - /* - The amount that was accepted for this invoice, in satoshis. This will ONLY - be set if this invoice has been settled. We provide this field as if the - invoice was created with a zero value, then we need to record what amount - was ultimately accepted. Additionally, it's possible that the sender paid - MORE that was specified in the original invoice. So we'll record that here - as well. - Note: Output only, don't specify for creating an invoice. - */ - // int64 amt_paid_sat = 19; - - /* - The amount that was accepted for this invoice, in millisatoshis. This will - ONLY be set if this invoice has been settled. We provide this field as if - the invoice was created with a zero value, then we need to record what - amount was ultimately accepted. Additionally, it's possible that the sender - paid MORE that was specified in the original invoice. So we'll record that - here as well. - Note: Output only, don't specify for creating an invoice. - */ - // int64 amt_paid_msat = 20; - - enum InvoiceState { - OPEN = 0; - SETTLED = 1; - CANCELED = 2; - ACCEPTED = 3; - } - - /* - The state the invoice is in. - Note: Output only, don't specify for creating an invoice. - */ - // InvoiceState state = 21; - - /* - List of HTLCs paying to this invoice [EXPERIMENTAL]. - Note: Output only, don't specify for creating an invoice. - */ - // repeated InvoiceHTLC htlcs = 22; - - /* - List of features advertised on the invoice. - Note: Output only, don't specify for creating an invoice. - */ - // map<uint32, Feature> features = 24; - - /* - Indicates if this invoice was a spontaneous payment that arrived via keysend - [EXPERIMENTAL]. - Note: Output only, don't specify for creating an invoice. - */ - bool is_keysend = 25; - - /* - The payment address of this invoice. This value will be used in MPP - payments, and also for newer invoices that always require the MPP payload - for added end-to-end security. - Note: Output only, don't specify for creating an invoice. - */ - // bytes payment_addr = 26; - - /* - Signals whether or not this is an AMP invoice. - */ - bool is_amp = 27; - - /* - [EXPERIMENTAL]: - - Maps a 32-byte hex-encoded set ID to the sub-invoice AMP state for the - given set ID. This field is always populated for AMP invoices, and can be - used along side LookupInvoice to obtain the HTLC information related to a - given sub-invoice. - Note: Output only, don't specify for creating an invoice. - */ - // map<string, AMPInvoiceState> amp_invoice_state = 28; -} - message Invoice { /* An optional memo to attach along with the invoice. Used for record keeping @@ -3478,20 +3406,22 @@ message Invoice { int64 value_msat = 23; /* - Whether this invoice has been fulfilled + Whether this invoice has been fulfilled. The field is deprecated. Use the state field instead (compare to SETTLED). */ - bool settled = 6 [deprecated = true]; + //bool settled = 6 [deprecated = true]; /* When this invoice was created. + Measured in seconds since the unix epoch. Note: Output only, don't specify for creating an invoice. */ int64 creation_date = 7; /* When this invoice was settled. + Measured in seconds since the unix epoch. Note: Output only, don't specify for creating an invoice. */ int64 settle_date = 8; @@ -3512,7 +3442,7 @@ message Invoice { */ bytes description_hash = 10; - // Payment request expiry time in seconds. Default is 3600 (1 hour). + // Payment request expiry time in seconds. Default is 86400 (24 hours). int64 expiry = 11; // Fallback on-chain address. @@ -3528,6 +3458,8 @@ message Invoice { repeated RouteHint route_hints = 14; // Whether this invoice should include routing hints for private channels. + // Note: When enabled, if value and value_msat are zero, a large number of + // hints with these channels can be included, which might not be desirable. bool private = 15; /* @@ -3549,7 +3481,7 @@ message Invoice { uint64 settle_index = 17; // Deprecated, use amt_paid_sat or amt_paid_msat. - int64 amt_paid = 18 [deprecated = true]; + //int64 amt_paid = 18 [deprecated = true]; /* The amount that was accepted for this invoice, in satoshis. This will ONLY @@ -3726,7 +3658,7 @@ message PaymentHash { Deprecated now that the REST gateway supports base64 encoding of bytes fields. */ - // string r_hash_str = 1 [deprecated = true]; + //string r_hash_str = 1 [deprecated = true]; /* The payment hash of the invoice to be looked up. When using REST, this field @@ -3756,7 +3688,16 @@ message ListInvoiceRequest { specified index offset. This can be used to paginate backwards. */ bool reversed = 6; + + // If set, returns all invoices with a creation date greater than or equal + // to it. Measured in seconds since the unix epoch. + uint64 creation_date_start = 7; + + // If set, returns all invoices with a creation date less than or equal to + // it. Measured in seconds since the unix epoch. + uint64 creation_date_end = 8; } + message ListInvoiceResponse { /* A list of invoices from the time slice of the time series specified in the @@ -3955,6 +3896,14 @@ message ListPaymentsRequest { of payments, as all of them have to be iterated through to be counted. */ bool count_total_payments = 5; + + // If set, returns all invoices with a creation date greater than or equal + // to it. Measured in seconds since the unix epoch. + uint64 creation_date_start = 6; + + // If set, returns all invoices with a creation date less than or equal to + // it. Measured in seconds since the unix epoch. + uint64 creation_date_end = 7; } message ListPaymentsResponse { @@ -4199,6 +4148,10 @@ message ForwardingHistoryRequest { // The max number of events to return in the response to this query. uint32 num_max_events = 4; + + // Informs the server if the peer alias should be looked up for each + // forwarding event. + bool peer_alias_lookup = 5; } message ForwardingEvent { // Timestamp is the time (unix epoch offset) that this circuit was @@ -4238,6 +4191,12 @@ message ForwardingEvent { // circuit was completed. uint64 timestamp_ns = 11; + // The peer alias of the incoming channel. + string peer_alias_in = 12; + + // The peer alias of the outgoing channel. + string peer_alias_out = 13; + // TODO(roasbeef): add settlement latency? // * use FPE on the chan id? // * also list failures? diff --git a/vendor/looprpc/client.proto b/vendor/looprpc/client.proto index e4443bb..a7882d0 100644 --- a/vendor/looprpc/client.proto +++ b/vendor/looprpc/client.proto @@ -75,6 +75,11 @@ service SwapClient { */ rpc GetLsatTokens (TokensRequest) returns (TokensResponse); + /* loop: `getinfo` + GetInfo gets basic information about the loop daemon. + */ + rpc GetInfo (GetInfoRequest) returns (GetInfoResponse); + /* loop: `getparams` GetLiquidityParams gets the parameters that the daemon's liquidity manager is currently configured with. This may be nil if nothing is configured. @@ -162,7 +167,7 @@ message LoopOutRequest { to loop out is selected based on the lowest routing fee for the swap payment to the server. */ - uint64 loop_out_channel = 8 [deprecated = true]; + //uint64 loop_out_channel = 8 [deprecated = true]; /* A restriction on the channel set that may be used to loop out. The actual @@ -740,6 +745,78 @@ message LsatToken { string storage_name = 8; } +message LoopStats { + /* + Number of currently pending swaps. + */ + uint64 pending_count = 1; + + /* + Number of succeeded swaps. + */ + uint64 success_count = 2; + + /* + Number failed swaps. + */ + uint64 fail_count = 3; + + /* + The sum of all pending swap amounts. + */ + int64 sum_pending_amt = 4; + + /* + The sum of all succeeded swap amounts. + */ + int64 sum_succeeded_amt = 5; +} + +message GetInfoRequest { +} + +message GetInfoResponse { + /* + The current daemon version. + */ + string version = 1; + + /* + The network the daemon is running on. + */ + string network = 2; + + /* + Host and port of the loopd grpc server. + */ + string rpc_listen = 3; + + /* + Host and port of the loopd rest server. + */ + string rest_listen = 4; + + /* + Loop's macaroon path that clients use to talk to the daemon. + */ + string macaroon_path = 5; + + /* + Loop's tls cert path + */ + string tls_cert_path = 6; + + /* + Statistics about loop outs. + */ + LoopStats loop_out_stats = 7; + + /* + Statistics about loop ins. + */ + LoopStats loop_in_stats = 8; +} + message GetLiquidityParamsRequest { } @@ -873,6 +950,21 @@ message LiquidityParameters { UNIX timestamp in seconds. */ uint64 autoloop_budget_last_refresh = 20; + + /* + Set to true to enable easy autoloop. If set, all channel/peer rules will be + overridden and the client will automatically dispatch swaps in order to meet + the configured local balance target size. Currently only loop out is + supported, meaning that easy autoloop can only reduce the funds that are + held as balance in channels. + */ + bool easy_autoloop = 21; + + /* + The local balance target size, expressed in satoshis. This is used by easy + autoloop to determine how much liquidity should be maintained in channels. + */ + uint64 easy_autoloop_local_target_sat = 22; } enum LiquidityRuleType { diff --git a/vendor/routerrpc/router.proto b/vendor/routerrpc/router.proto index dd1e03f..82f6635 100644 --- a/vendor/routerrpc/router.proto +++ b/vendor/routerrpc/router.proto @@ -94,8 +94,10 @@ service Router { returns (SetMissionControlConfigResponse); /* - QueryProbability returns the current success probability estimate for a - given node pair and amount. + Deprecated. QueryProbability returns the current success probability + estimate for a given node pair and amount. The call returns a zero success + probability if no channel is available or if the amount violates min/max + HTLC constraints. */ rpc QueryProbability (QueryProbabilityRequest) returns (QueryProbabilityResponse); @@ -153,33 +155,33 @@ service Router { message SendPaymentRequest { // The identity pubkey of the payment recipient - // bytes dest = 1; + bytes dest = 1; /* Number of satoshis to send. The fields amt and amt_msat are mutually exclusive. */ - // int64 amt = 2; + int64 amt = 2; /* Number of millisatoshis to send. The fields amt and amt_msat are mutually exclusive. */ - // int64 amt_msat = 12; + int64 amt_msat = 12; // The hash to use within the payment's HTLC - // bytes payment_hash = 3; + bytes payment_hash = 3; /* The CLTV delta from the current height that should be used to set the timelock for the final hop. */ - // int32 final_cltv_delta = 4; + int32 final_cltv_delta = 4; // An optional payment addr to be included within the last hop of the route. - // bytes payment_addr = 20; + bytes payment_addr = 20; /* A bare-bones invoice for a payment within the Lightning Network. With the @@ -217,37 +219,37 @@ message SendPaymentRequest { The fields fee_limit_sat and fee_limit_msat are mutually exclusive. */ - // int64 fee_limit_msat = 13; + int64 fee_limit_msat = 13; /* Deprecated, use outgoing_chan_ids. The channel id of the channel that must be taken to the first hop. If zero, any channel may be used (unless outgoing_chan_ids are set). */ - // uint64 outgoing_chan_id = 8 [jstype = JS_STRING, deprecated = true]; + //uint64 outgoing_chan_id = 8 [jstype = JS_STRING, deprecated = true]; /* The channel ids of the channels are allowed for the first hop. If empty, any channel may be used. */ - // repeated uint64 outgoing_chan_ids = 19; + repeated uint64 outgoing_chan_ids = 19; /* The pubkey of the last hop of the route. If empty, any hop may be used. */ - // bytes last_hop_pubkey = 14; + bytes last_hop_pubkey = 14; /* An optional maximum total time lock for the route. This should not exceed lnd's `--max-cltv-expiry` setting. If zero, then the value of `--max-cltv-expiry` is enforced. */ - // int32 cltv_limit = 9; + int32 cltv_limit = 9; /* Optional route hints to reach the destination through private channels. */ - // repeated lnrpc.RouteHint route_hints = 10; + repeated lnrpc.RouteHint route_hints = 10; /* An optional field that can be used to pass an arbitrary set of TLV records @@ -256,7 +258,7 @@ message SendPaymentRequest { required to be in the custom range >= 65536. When using REST, the values must be encoded as base64. */ - // map<uint64, bytes> dest_custom_records = 11; + map<uint64, bytes> dest_custom_records = 11; // If set, circular payments to self are permitted. bool allow_self_payment = 15; @@ -268,19 +270,19 @@ message SendPaymentRequest { the router will try to load destination features from the graph as a fallback. */ - // repeated lnrpc.FeatureBit dest_features = 16; + repeated lnrpc.FeatureBit dest_features = 16; /* The maximum number of partial payments that may be use to complete the full amount. */ - // uint32 max_parts = 17; + uint32 max_parts = 17; /* If set, only the final payment update is streamed back. Intermediate updates that show which htlcs are still in flight are suppressed. */ - // bool no_inflight_updates = 18; + bool no_inflight_updates = 18; /* The largest payment split that should be attempted when making a payment if @@ -288,7 +290,7 @@ message SendPaymentRequest { split more aggressively, vs only when it thinks it needs to. Note that this value is in milli-satoshis. */ - // uint64 max_shard_size_msat = 21; + uint64 max_shard_size_msat = 21; /* If set, an AMP-payment will be attempted. @@ -299,7 +301,7 @@ message SendPaymentRequest { The time preference for this payment. Set to -1 to optimize for fees only, to 1 to optimize for reliability only or a value inbetween for a mix. */ - // double time_pref = 23; + double time_pref = 23; } message TrackPaymentRequest { @@ -465,6 +467,93 @@ message SetMissionControlConfigResponse { } message MissionControlConfig { + /* + Deprecated, use AprioriParameters. The amount of time mission control will + take to restore a penalized node or channel back to 50% success probability, + expressed in seconds. Setting this value to a higher value will penalize + failures for longer, making mission control less likely to route through + nodes and channels that we have previously recorded failures for. + */ + uint64 half_life_seconds = 1 [deprecated = true]; + + /* + Deprecated, use AprioriParameters. The probability of success mission + control should assign to hop in a route where it has no other information + available. Higher values will make mission control more willing to try hops + that we have no information about, lower values will discourage trying these + hops. + */ + float hop_probability = 2 [deprecated = true]; + + /* + Deprecated, use AprioriParameters. The importance that mission control + should place on historical results, expressed as a value in [0;1]. Setting + this value to 1 will ignore all historical payments and just use the hop + probability to assess the probability of success for each hop. A zero value + ignores hop probability completely and relies entirely on historical + results, unless none are available. + */ + float weight = 3 [deprecated = true]; + + /* + The maximum number of payment results that mission control will store. + */ + uint32 maximum_payment_results = 4; + + /* + The minimum time that must have passed since the previously recorded failure + before we raise the failure amount. + */ + uint64 minimum_failure_relax_interval = 5; + + enum ProbabilityModel { + APRIORI = 0; + BIMODAL = 1; + } + + /* + ProbabilityModel defines which probability estimator should be used in + pathfinding. Note that the bimodal estimator is experimental. + */ + ProbabilityModel model = 6; + + /* + EstimatorConfig is populated dependent on the estimator type. + */ + oneof EstimatorConfig { + AprioriParameters apriori = 7; + BimodalParameters bimodal = 8; + } +} + +message BimodalParameters { + /* + NodeWeight defines how strongly other previous forwardings on channels of a + router should be taken into account when computing a channel's probability + to route. The allowed values are in the range [0, 1], where a value of 0 + means that only direct information about a channel is taken into account. + */ + double node_weight = 1; + + /* + ScaleMsat describes the scale over which channels statistically have some + liquidity left. The value determines how quickly the bimodal distribution + drops off from the edges of a channel. A larger value (compared to typical + channel capacities) means that the drop off is slow and that channel + balances are distributed more uniformly. A small value leads to the + assumption of very unbalanced channels. + */ + uint64 scale_msat = 2; + + /* + DecayTime describes the information decay of knowledge about previous + successes and failures in channels. The smaller the decay time, the quicker + we forget about past forwardings. + */ + uint64 decay_time = 3; +} + +message AprioriParameters { /* The amount of time mission control will take to restore a penalized node or channel back to 50% success probability, expressed in seconds. Setting @@ -480,7 +569,7 @@ message MissionControlConfig { control more willing to try hops that we have no information about, lower values will discourage trying these hops. */ - float hop_probability = 2; + double hop_probability = 2; /* The importance that mission control should place on historical results, @@ -490,18 +579,15 @@ message MissionControlConfig { completely and relies entirely on historical results, unless none are available. */ - float weight = 3; - - /* - The maximum number of payment results that mission control will store. - */ - uint32 maximum_payment_results = 4; + double weight = 3; /* - The minimum time that must have passed since the previously recorded failure - before we raise the failure amount. + The fraction of a channel's capacity that we consider to have liquidity. For + amounts that come close to or exceed the fraction, an additional penalty is + applied. A value of 1.0 disables the capacity factor. Allowed values are in + [0.75, 1.0]. */ - uint64 minimum_failure_relax_interval = 5; + double capacity_fraction = 4; } message QueryProbabilityRequest { diff --git a/vendor/signrpc/signer.proto b/vendor/signrpc/signer.proto index 5ea85dd..6540252 100644 --- a/vendor/signrpc/signer.proto +++ b/vendor/signrpc/signer.proto @@ -444,12 +444,33 @@ message TaprootTweakDesc { bool key_spend_only = 2; } +enum MuSig2Version { + /* + The default value on the RPC is zero for enums so we need to represent an + invalid/undefined version by default to make sure clients upgrade their + software to set the version explicitly. + */ + MUSIG2_VERSION_UNDEFINED = 0; + + /* + The version of MuSig2 that lnd 0.15.x shipped with, which corresponds to the + version v0.4.0 of the MuSig2 BIP draft. + */ + MUSIG2_VERSION_V040 = 1; + + /* + The current version of MuSig2 which corresponds to the version v1.0.0rc2 of + the MuSig2 BIP draft. + */ + MUSIG2_VERSION_V100RC2 = 2; +} + message MuSig2CombineKeysRequest { /* - A list of all public keys (serialized in 32-byte x-only format!) - participating in the signing session. The list will always be sorted - lexicographically internally. This must include the local key which is - described by the above key_loc. + A list of all public keys (serialized in 32-byte x-only format for v0.4.0 + and 33-byte compressed format for v1.0.0rc2!) participating in the signing + session. The list will always be sorted lexicographically internally. This + must include the local key which is described by the above key_loc. */ repeated bytes all_signer_pubkeys = 1; @@ -465,6 +486,14 @@ message MuSig2CombineKeysRequest { on-chain. */ TaprootTweakDesc taproot_tweak = 3; + + /* + The mandatory version of the MuSig2 BIP draft to use. This is necessary to + differentiate between the changes that were made to the BIP while this + experimental RPC was already released. Some of those changes affect how the + combined key and nonces are created. + */ + MuSig2Version version = 4; } message MuSig2CombineKeysResponse { @@ -482,6 +511,11 @@ message MuSig2CombineKeysResponse { is used. */ bytes taproot_internal_key = 2; + + /* + The version of the MuSig2 BIP that was used to combine the keys. + */ + MuSig2Version version = 4; } message MuSig2SessionRequest { @@ -491,10 +525,10 @@ message MuSig2SessionRequest { KeyLocator key_loc = 1; /* - A list of all public keys (serialized in 32-byte x-only format!) - participating in the signing session. The list will always be sorted - lexicographically internally. This must include the local key which is - described by the above key_loc. + A list of all public keys (serialized in 32-byte x-only format for v0.4.0 + and 33-byte compressed format for v1.0.0rc2!) participating in the signing + session. The list will always be sorted lexicographically internally. This + must include the local key which is described by the above key_loc. */ repeated bytes all_signer_pubkeys = 2; @@ -516,6 +550,14 @@ message MuSig2SessionRequest { on-chain. */ TaprootTweakDesc taproot_tweak = 5; + + /* + The mandatory version of the MuSig2 BIP draft to use. This is necessary to + differentiate between the changes that were made to the BIP while this + experimental RPC was already released. Some of those changes affect how the + combined key and nonces are created. + */ + MuSig2Version version = 6; } message MuSig2SessionResponse { @@ -553,6 +595,11 @@ message MuSig2SessionResponse { now. */ bool have_all_nonces = 5; + + /* + The version of the MuSig2 BIP that was used to create the session. + */ + MuSig2Version version = 6; } message MuSig2RegisterNoncesRequest { diff --git a/vendor/stateservice.proto b/vendor/stateservice.proto new file mode 100644 index 0000000..97a78d3 --- /dev/null +++ b/vendor/stateservice.proto @@ -0,0 +1,73 @@ +syntax = "proto3"; + +package lnrpc; + +option go_package = "github.com/lightningnetwork/lnd/lnrpc"; + +/* + * Comments in this file will be directly parsed into the API + * Documentation as descriptions of the associated method, message, or field. + * These descriptions should go right above the definition of the object, and + * can be in either block or // comment format. + * + * An RPC method can be matched to an lncli command by placing a line in the + * beginning of the description in exactly the following format: + * lncli: `methodname` + * + * Failure to specify the exact name of the command will cause documentation + * generation to fail. + * + * More information on how exactly the gRPC documentation is generated from + * this proto file can be found here: + * https://github.com/lightninglabs/lightning-api + */ + +// State service is a always running service that exposes the current state of +// the wallet and RPC server. +service State { + // SubscribeState subscribes to the state of the wallet. The current wallet + // state will always be delivered immediately. + rpc SubscribeState (SubscribeStateRequest) + returns (stream SubscribeStateResponse); + + // GetState returns the current wallet state without streaming further + // changes. + rpc GetState (GetStateRequest) returns (GetStateResponse); +} + +enum WalletState { + // NON_EXISTING means that the wallet has not yet been initialized. + NON_EXISTING = 0; + + // LOCKED means that the wallet is locked and requires a password to unlock. + LOCKED = 1; + + // UNLOCKED means that the wallet was unlocked successfully, but RPC server + // isn't ready. + UNLOCKED = 2; + + // RPC_ACTIVE means that the lnd server is active but not fully ready for + // calls. + RPC_ACTIVE = 3; + + // SERVER_ACTIVE means that the lnd server is ready to accept calls. + SERVER_ACTIVE = 4; + + // WAITING_TO_START means that node is waiting to become the leader in a + // cluster and is not started yet. + WAITING_TO_START = 255; +} + +message SubscribeStateRequest { +} + +message SubscribeStateResponse { + WalletState state = 1; +} + +message GetStateRequest { +} + +message GetStateResponse { + WalletState state = 1; +} diff --git a/vendor/walletrpc/walletkit.proto b/vendor/walletrpc/walletkit.proto index 2e5f453..a9c7412 100644 --- a/vendor/walletrpc/walletkit.proto +++ b/vendor/walletrpc/walletkit.proto @@ -72,6 +72,54 @@ service WalletKit { rpc RequiredReserve (RequiredReserveRequest) returns (RequiredReserveResponse); + /* + ListAddresses retrieves all the addresses along with their balance. An + account name filter can be provided to filter through all of the + wallet accounts and return the addresses of only those matching. + */ + rpc ListAddresses (ListAddressesRequest) returns (ListAddressesResponse); + + /* + SignMessageWithAddr returns the compact signature (base64 encoded) created + with the private key of the provided address. This requires the address + to be solely based on a public key lock (no scripts). Obviously the internal + lnd wallet has to possess the private key of the address otherwise + an error is returned. + + This method aims to provide full compatibility with the bitcoin-core and + btcd implementation. Bitcoin-core's algorithm is not specified in a + BIP and only applicable for legacy addresses. This method enhances the + signing for additional address types: P2WKH, NP2WKH, P2TR. + For P2TR addresses this represents a special case. ECDSA is used to create + a compact signature which makes the public key of the signature recoverable. + */ + rpc SignMessageWithAddr (SignMessageWithAddrRequest) + returns (SignMessageWithAddrResponse); + + /* + VerifyMessageWithAddr returns the validity and the recovered public key of + the provided compact signature (base64 encoded). The verification is + twofold. First the validity of the signature itself is checked and then + it is verified that the recovered public key of the signature equals + the public key of the provided address. There is no dependence on the + private key of the address therefore also external addresses are allowed + to verify signatures. + Supported address types are P2PKH, P2WKH, NP2WKH, P2TR. + + This method is the counterpart of the related signing method + (SignMessageWithAddr) and aims to provide full compatibility to + bitcoin-core's implementation. Although bitcoin-core/btcd only provide + this functionality for legacy addresses this function enhances it to + the address types: P2PKH, P2WKH, NP2WKH, P2TR. + + The verification for P2TR addresses is a special case and requires the + ECDSA compact signature to compare the reovered public key to the internal + taproot key. The compact ECDSA signature format was used because there + are still no known compact signature schemes for schnorr signatures. + */ + rpc VerifyMessageWithAddr (VerifyMessageWithAddrRequest) + returns (VerifyMessageWithAddrResponse); + /* ImportAccount imports an account backed by an account extended public key. The master key fingerprint denotes the fingerprint of the root key @@ -100,7 +148,11 @@ service WalletKit { rpc ImportAccount (ImportAccountRequest) returns (ImportAccountResponse); /* - ImportPublicKey imports a public key as watch-only into the wallet. + ImportPublicKey imports a public key as watch-only into the wallet. The + public key is converted into a simple address of the given type and that + address script is watched on chain. For Taproot keys, this will only watch + the BIP-0086 style output script. Use ImportTapscript for more advanced key + spend or script spend outputs. NOTE: Events (deposits/spends) for a key will only be detected by lnd if they happen after the import. Rescans to detect past events will be @@ -109,6 +161,22 @@ service WalletKit { rpc ImportPublicKey (ImportPublicKeyRequest) returns (ImportPublicKeyResponse); + /* + ImportTapscript imports a Taproot script and internal key and adds the + resulting Taproot output key as a watch-only output script into the wallet. + For BIP-0086 style Taproot keys (no root hash commitment and no script spend + path) use ImportPublicKey. + + NOTE: Events (deposits/spends) for a key will only be detected by lnd if + they happen after the import. Rescans to detect past events will be + supported later on. + + NOTE: Taproot keys imported through this RPC currently _cannot_ be used for + funding PSBTs. Only tracking the balance and UTXOs is currently supported. + */ + rpc ImportTapscript (ImportTapscriptRequest) + returns (ImportTapscriptResponse); + /* PublishTransaction attempts to publish the passed transaction to the network. Once this returns without an error, the wallet will continually @@ -348,14 +416,7 @@ message Account { // The name used to identify the account. string name = 1; - /* - The type of addresses the account supports. - AddressType | External Branch | Internal Branch - --------------------------------------------------------------------- - WITNESS_PUBKEY_HASH | P2WPKH | P2WPKH - NESTED_WITNESS_PUBKEY_HASH | NP2WPKH | NP2WPKH - HYBRID_NESTED_WITNESS_PUBKEY_HASH | NP2WPKH | P2WPKH - */ + // The type of addresses the account supports. AddressType address_type = 2; /* @@ -397,6 +458,50 @@ message Account { // Whether the wallet stores private keys for the account. bool watch_only = 8; } + +message AddressProperty { + /* + The address encoded using the appropriate format depending on the + address type (base58, bech32, bech32m). + + Note that lnd's internal/custom keys for channels and other + functionality are derived from the same scope. Since they + aren't really used as addresses and will never have an + on-chain balance, we'll show the public key instead (only if + the show_custom_accounts flag is provided). + */ + string address = 1; + + // Denotes if the address is a change address. + bool is_internal = 2; + + // The balance of the address. + int64 balance = 3; +} + +message AccountWithAddresses { + // The name used to identify the account. + string name = 1; + + // The type of addresses the account supports. + AddressType address_type = 2; + + /* + The derivation path corresponding to the account public key. This will + always be empty for the default imported account in which single public keys + are imported into. + */ + string derivation_path = 3; + + /* + List of address, its type internal/external & balance. + Note that the order of addresses will be random and not according to the + derivation index, since that information is not stored by the underlying + wallet. + */ + repeated AddressProperty addresses = 4; +} + message ListAccountsRequest { // An optional filter to only return accounts matching this name. string name = 1; @@ -404,6 +509,7 @@ message ListAccountsRequest { // An optional filter to only return accounts matching this address type. AddressType address_type = 2; } + message ListAccountsResponse { repeated Account accounts = 1; } @@ -418,6 +524,57 @@ message RequiredReserveResponse { int64 required_reserve = 1; } +message ListAddressesRequest { + // An optional filter to only return addresses matching this account. + string account_name = 1; + + // An optional flag to return LND's custom accounts (Purpose=1017) + // public key along with other addresses. + bool show_custom_accounts = 2; +} + +message ListAddressesResponse { + // A list of all the accounts and their addresses. + repeated AccountWithAddresses account_with_addresses = 1; +} + +message SignMessageWithAddrRequest { + // The message to be signed. When using REST, this field must be encoded as + // base64. + bytes msg = 1; + + // The address which will be used to look up the private key and sign the + // corresponding message. + string addr = 2; +} + +message SignMessageWithAddrResponse { + // The compact ECDSA signature for the given message encoded in base64. + string signature = 1; +} + +message VerifyMessageWithAddrRequest { + // The message to be signed. When using REST, this field must be encoded as + // base64. + bytes msg = 1; + + // The compact ECDSA signature to be verified over the given message + // ecoded in base64. + string signature = 2; + + // The address which will be used to look up the public key and verify the + // the signature. + string addr = 3; +} + +message VerifyMessageWithAddrResponse { + // Whether the signature was valid over the given message. + bool valid = 1; + + // The pubkey recovered from the signature. + bytes pubkey = 2; +} + message ImportAccountRequest { // A name to identify the account with. string name = 1; @@ -482,6 +639,77 @@ message ImportPublicKeyRequest { message ImportPublicKeyResponse { } +message ImportTapscriptRequest { + /* + The internal public key, serialized as 32-byte x-only public key. + */ + bytes internal_public_key = 1; + + oneof script { + /* + The full script tree with all individual leaves is known and the root + hash can be constructed from the full tree directly. + */ + TapscriptFullTree full_tree = 2; + + /* + Only a single script leaf is known. To construct the root hash, the full + inclusion proof must also be provided. + */ + TapscriptPartialReveal partial_reveal = 3; + + /* + Only the root hash of the Taproot script tree (or other form of Taproot + commitment) is known. + */ + bytes root_hash_only = 4; + + /* + Only the final, tweaked Taproot key is known and no additional + information about the internal key or type of tweak that was used to + derive it. When this is set, the wallet treats the key in + internal_public_key as the Taproot key directly. This can be useful for + tracking arbitrary Taproot outputs without the goal of ever being able + to spend from them through the internal wallet. + */ + bool full_key_only = 5; + } +} + +message TapscriptFullTree { + /* + The complete, ordered list of all tap leaves of the tree. + */ + repeated TapLeaf all_leaves = 1; +} + +message TapLeaf { + // The leaf version. Should be 0xc0 (192) in case of a SegWit v1 script. + uint32 leaf_version = 1; + + // The script of the tap leaf. + bytes script = 2; +} + +message TapscriptPartialReveal { + // The tap leaf that is known and will be revealed. + TapLeaf revealed_leaf = 1; + + // The BIP-0341 serialized inclusion proof that is required to prove that + // the revealed leaf is part of the tree. This contains 0..n blocks of 32 + // bytes. If the tree only contained a single leaf (which is the revealed + // leaf), this can be empty. + bytes full_inclusion_proof = 2; +} + +message ImportTapscriptResponse { + /* + The resulting pay-to-Taproot address that represents the imported internal + key with the script committed to it. + */ + string p2tr_address = 1; +} + message Transaction { /* The raw serialized transaction. @@ -635,6 +863,76 @@ enum WitnessType { transaction. */ COMMITMENT_ANCHOR = 13; + + /* + A witness type that is similar to the COMMITMENT_NO_DELAY type, + but it omits the tweak that randomizes the key we need to + spend with a channel peer supplied set of randomness. + */ + COMMITMENT_NO_DELAY_TWEAKLESS = 14; + + /* + A witness type that allows us to spend our output on the counterparty's + commitment transaction after a confirmation. + */ + COMMITMENT_TO_REMOTE_CONFIRMED = 15; + + /* + A witness type that allows us to sweep an HTLC output that we extended + to a party, but was never fulfilled. This _is_ the HTLC output directly + on our commitment transaction, and the input to the second-level HTLC + timeout transaction. It can only be spent after CLTV expiry, and + commitment confirmation. + */ + HTLC_OFFERED_TIMEOUT_SECOND_LEVEL_INPUT_CONFIRMED = 16; + + /* + A witness type that allows us to sweep an HTLC output that was offered + to us, and for which we have a payment preimage. This _is_ the HTLC + output directly on our commitment transaction, and the input to the + second-level HTLC success transaction. It can only be spent after the + commitment has confirmed. + */ + HTLC_ACCEPTED_SUCCESS_SECOND_LEVEL_INPUT_CONFIRMED = 17; + + /* + A witness type that allows us to spend our output on our local + commitment transaction after a relative and absolute lock-time lockout as + part of the script enforced lease commitment type. + */ + LEASE_COMMITMENT_TIME_LOCK = 18; + + /* + A witness type that allows us to spend our output on the counterparty's + commitment transaction after a confirmation and absolute locktime as part + of the script enforced lease commitment type. + */ + LEASE_COMMITMENT_TO_REMOTE_CONFIRMED = 19; + + /* + A witness type that allows us to sweep an HTLC output that we extended + to a party, but was never fulfilled. This HTLC output isn't directly on + the commitment transaction, but is the result of a confirmed second-level + HTLC transaction. As a result, we can only spend this after a CSV delay + and CLTV locktime as part of the script enforced lease commitment type. + */ + LEASE_HTLC_OFFERED_TIMEOUT_SECOND_LEVEL = 20; + + /* + A witness type that allows us to sweep an HTLC output that was offered + to us, and for which we have a payment preimage. This HTLC output isn't + directly on our commitment transaction, but is the result of confirmed + second-level HTLC transaction. As a result, we can only spend this after + a CSV delay and CLTV locktime as part of the script enforced lease + commitment type. + */ + LEASE_HTLC_ACCEPTED_SUCCESS_SECOND_LEVEL = 21; + + /* + A witness type that allows us to spend a regular p2tr output that's sent + to an output which is under complete control of the backing wallet. + */ + TAPROOT_PUB_KEY_SPEND = 22; } message PendingSweep { @@ -754,7 +1052,8 @@ message ListSweepsResponse { } message LabelTransactionRequest { - // The txid of the transaction to label. + // The txid of the transaction to label. Note: When using gRPC, the bytes + // must be in little-endian (reverse) order. bytes txid = 1; // The label to add to the transaction, limited to 500 characters. @@ -767,6 +1066,23 @@ message LabelTransactionRequest { message LabelTransactionResponse { } +// The possible change address types for default accounts and single imported +// public keys. By default, P2WPKH will be used. We don't provide the +// possibility to choose P2PKH as it is a legacy key scope, nor NP2WPKH as +// no key scope permits to do so. For custom accounts, no change type should +// be provided as the coin selection key scope will always be used to generate +// the change address. +enum ChangeAddressType { + // CHANGE_ADDRESS_TYPE_UNSPECIFIED indicates that no change address type is + // provided. We will then use P2WPKH address type for change (BIP0084 key + // scope). + CHANGE_ADDRESS_TYPE_UNSPECIFIED = 0; + + // CHANGE_ADDRESS_TYPE_P2TR indicates to use P2TR address for change output + // (BIP0086 key scope). + CHANGE_ADDRESS_TYPE_P2TR = 1; +} + message FundPsbtRequest { oneof template { /* @@ -812,6 +1128,12 @@ message FundPsbtRequest { // Whether unconfirmed outputs should be used as inputs for the transaction. bool spend_unconfirmed = 7; + + // The address type for the change. If empty, P2WPKH addresses will be used + // for default accounts and single imported public keys. For custom + // accounts, no change type should be provided as the coin selection key + // scope will always be used to generate the change address. + ChangeAddressType change_type = 8; } message FundPsbtResponse { /* @@ -885,6 +1207,9 @@ message SignPsbtRequest { message SignPsbtResponse { // The signed transaction in PSBT format. bytes signed_psbt = 1; + + // The indices of signed inputs. + repeated uint32 signed_inputs = 2; } message FinalizePsbtRequest {