platform: [ ubuntu-latest ]
toolchain: [ stable,
beta,
- # 1.30.0 is MSRV for Rust-Lightning
- 1.30.0,
- # 1.34.2 is Debian stable
- 1.34.2,
+ # 1.36.0 is MSRV for Rust-Lightning, lightning-invoice, and lightning-persister
+ 1.36.0,
+ # 1.41.0 is Debian stable
+ 1.41.0,
# 1.45.2 is MSRV for lightning-net-tokio, lightning-block-sync, and coverage generation
1.45.2]
include:
run: RUSTFLAGS="-C link-dead-code" cargo build --verbose --color always
- name: Build on Rust ${{ matrix.toolchain }}
if: "! matrix.build-net-tokio"
- run: cargo build --verbose --color always -p lightning && cargo build --verbose --color always -p lightning-invoice
+ run: cargo build --verbose --color always -p lightning && cargo build --verbose --color always -p lightning-invoice && cargo build --verbose --color always -p lightning-persister
- name: Build Block Sync Clients on Rust ${{ matrix.toolchain }} with features
if: "matrix.build-net-tokio && !matrix.coverage"
run: |
run: RUSTFLAGS="-C link-dead-code" cargo test --verbose --color always
- name: Test on Rust ${{ matrix.toolchain }}
if: "! matrix.build-net-tokio"
- run: cargo test --verbose --color always -p lightning && cargo test --verbose --color always -p lightning-invoice
+ run: cargo test --verbose --color always -p lightning && cargo test --verbose --color always -p lightning-invoice && cargo build --verbose --color always -p lightning-persister
- name: Test Block Sync Clients on Rust ${{ matrix.toolchain }} with features
if: "matrix.build-net-tokio && !matrix.coverage"
run: |
When refactoring, structure your PR to make it easy to review and don't
hestitate to split it into multiple small, focused PRs.
-The Minimal Supported Rust Version is 1.30.0 (enforced by our Travis and
-GitHub Actions).
+The Minimal Supported Rust Version is 1.36.0 (enforced by our GitHub Actions).
Commits should cover both the issue fixed and the solution's rationale.
These [guidelines](https://chris.beams.io/posts/git-commit/) should be kept in mind.
[patch.crates-io]
# Rust-Secp256k1 PR 282. This patch should be dropped once that is merged.
-secp256k1 = { git = 'https://github.com/TheBlueMatt/rust-secp256k1', rev = '32767e0e21e8861701ff7d5957613169d67ff1f8' }
+secp256k1 = { git = 'https://github.com/TheBlueMatt/rust-secp256k1', rev = 'c8615128097e0205dcf69e515e56fb57e5c97138' }
# bitcoin_hashes PR 111 (without the top commit). This patch should be dropped once that is merged.
bitcoin_hashes = { git = 'https://github.com/TheBlueMatt/bitcoin_hashes', rev = 'c90d26339a3e34fd2f942aa80298f410cc41b743' }
use lightning::chain::transaction::OutPoint;
use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
use lightning::chain::keysinterface::{KeysInterface, InMemorySigner};
-use lightning::ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret, PaymentSendFailure, ChannelManagerReadArgs};
+use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
+use lightning::ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, PaymentSendFailure, ChannelManagerReadArgs};
use lightning::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
use lightning::ln::msgs::{CommitmentUpdate, ChannelMessageHandler, DecodeError, ErrorAction, UpdateAddHTLC, Init};
use lightning::util::enforcing_trait_impls::{EnforcingSigner, INITIAL_REVOKED_COMMITMENT_NUMBER};
use utils::test_persister::TestPersister;
use bitcoin::secp256k1::key::{PublicKey,SecretKey};
+use bitcoin::secp256k1::recovery::RecoverableSignature;
use bitcoin::secp256k1::Secp256k1;
use std::mem;
disable_revocation_policy_check: false,
})
}
+
+ fn sign_invoice(&self, _invoice_preimage: Vec<u8>) -> Result<RecoverableSignature, ()> {
+ unreachable!()
+ }
}
impl KeyProvider {
type ChanMan = ChannelManager<EnforcingSigner, Arc<TestChainMonitor>, Arc<TestBroadcaster>, Arc<KeyProvider>, Arc<FuzzEstimator>, Arc<dyn Logger>>;
+#[inline]
+fn get_payment_secret_hash(dest: &ChanMan, payment_id: &mut u8) -> Option<(PaymentSecret, PaymentHash)> {
+ let mut payment_hash;
+ for _ in 0..256 {
+ payment_hash = PaymentHash(Sha256::hash(&[*payment_id; 1]).into_inner());
+ if let Ok(payment_secret) = dest.create_inbound_payment_for_hash(payment_hash, None, 7200, 0) {
+ return Some((payment_secret, payment_hash));
+ }
+ *payment_id = payment_id.wrapping_add(1);
+ }
+ None
+}
+
#[inline]
fn send_payment(source: &ChanMan, dest: &ChanMan, dest_chan_id: u64, amt: u64, payment_id: &mut u8) -> bool {
- let payment_hash = Sha256::hash(&[*payment_id; 1]);
- *payment_id = payment_id.wrapping_add(1);
+ let (payment_secret, payment_hash) =
+ if let Some((secret, hash)) = get_payment_secret_hash(dest, payment_id) { (secret, hash) } else { return true; };
if let Err(err) = source.send_payment(&Route {
paths: vec![vec![RouteHop {
pubkey: dest.get_our_node_id(),
- node_features: NodeFeatures::empty(),
+ node_features: NodeFeatures::known(),
short_channel_id: dest_chan_id,
- channel_features: ChannelFeatures::empty(),
+ channel_features: ChannelFeatures::known(),
fee_msat: amt,
cltv_expiry_delta: 200,
}]],
- }, PaymentHash(payment_hash.into_inner()), &None) {
+ }, payment_hash, &Some(payment_secret)) {
check_payment_err(err);
false
} else { true }
}
#[inline]
fn send_hop_payment(source: &ChanMan, middle: &ChanMan, middle_chan_id: u64, dest: &ChanMan, dest_chan_id: u64, amt: u64, payment_id: &mut u8) -> bool {
- let payment_hash = Sha256::hash(&[*payment_id; 1]);
- *payment_id = payment_id.wrapping_add(1);
+ let (payment_secret, payment_hash) =
+ if let Some((secret, hash)) = get_payment_secret_hash(dest, payment_id) { (secret, hash) } else { return true; };
if let Err(err) = source.send_payment(&Route {
paths: vec![vec![RouteHop {
pubkey: middle.get_our_node_id(),
- node_features: NodeFeatures::empty(),
+ node_features: NodeFeatures::known(),
short_channel_id: middle_chan_id,
- channel_features: ChannelFeatures::empty(),
+ channel_features: ChannelFeatures::known(),
fee_msat: 50000,
cltv_expiry_delta: 100,
},RouteHop {
pubkey: dest.get_our_node_id(),
- node_features: NodeFeatures::empty(),
+ node_features: NodeFeatures::known(),
short_channel_id: dest_chan_id,
- channel_features: ChannelFeatures::empty(),
+ channel_features: ChannelFeatures::known(),
fee_msat: amt,
cltv_expiry_delta: 200,
}]],
- }, PaymentHash(payment_hash.into_inner()), &None) {
+ }, payment_hash, &Some(payment_secret)) {
check_payment_err(err);
false
} else { true }
}
loop {
- macro_rules! send_payment_with_secret {
- ($source: expr, $middle: expr, $dest: expr) => { {
- let payment_hash = Sha256::hash(&[payment_id; 1]);
- payment_id = payment_id.wrapping_add(1);
- let payment_secret = Sha256::hash(&[payment_id; 1]);
- payment_id = payment_id.wrapping_add(1);
- if let Err(err) = $source.send_payment(&Route {
- paths: vec![vec![RouteHop {
- pubkey: $middle.0.get_our_node_id(),
- node_features: NodeFeatures::empty(),
- short_channel_id: $middle.1,
- channel_features: ChannelFeatures::empty(),
- fee_msat: 50_000,
- cltv_expiry_delta: 100,
- },RouteHop {
- pubkey: $dest.0.get_our_node_id(),
- node_features: NodeFeatures::empty(),
- short_channel_id: $dest.1,
- channel_features: ChannelFeatures::empty(),
- fee_msat: 10_000_000,
- cltv_expiry_delta: 200,
- }],vec![RouteHop {
- pubkey: $middle.0.get_our_node_id(),
- node_features: NodeFeatures::empty(),
- short_channel_id: $middle.1,
- channel_features: ChannelFeatures::empty(),
- fee_msat: 50_000,
- cltv_expiry_delta: 100,
- },RouteHop {
- pubkey: $dest.0.get_our_node_id(),
- node_features: NodeFeatures::empty(),
- short_channel_id: $dest.1,
- channel_features: ChannelFeatures::empty(),
- fee_msat: 10_000_000,
- cltv_expiry_delta: 200,
- }]],
- }, PaymentHash(payment_hash.into_inner()), &Some(PaymentSecret(payment_secret.into_inner()))) {
- check_payment_err(err);
- }
- } }
- }
-
macro_rules! process_msg_events {
($node: expr, $corrupt_forward: expr) => { {
let events = if $node == 1 {
let had_events = !events.is_empty();
for event in events.drain(..) {
match event {
- events::Event::PaymentReceived { payment_hash, payment_secret, amt } => {
+ events::Event::PaymentReceived { payment_hash, .. } => {
if claim_set.insert(payment_hash.0) {
if $fail {
- assert!(nodes[$node].fail_htlc_backwards(&payment_hash, &payment_secret));
+ assert!(nodes[$node].fail_htlc_backwards(&payment_hash));
} else {
- assert!(nodes[$node].claim_funds(PaymentPreimage(payment_hash.0), &payment_secret, amt));
+ assert!(nodes[$node].claim_funds(PaymentPreimage(payment_hash.0)));
}
}
},
},
0x0e => {
if chan_a_disconnected {
- nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::empty() });
- nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: InitFeatures::empty() });
+ nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::known() });
+ nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: InitFeatures::known() });
chan_a_disconnected = false;
}
},
0x0f => {
if chan_b_disconnected {
- nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: InitFeatures::empty() });
- nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::empty() });
+ nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: InitFeatures::known() });
+ nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::known() });
chan_b_disconnected = false;
}
},
0x24 => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 10_000_000, &mut payment_id); },
0x25 => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 10_000_000, &mut payment_id); },
- 0x26 => { send_payment_with_secret!(nodes[0], (&nodes[1], chan_a), (&nodes[2], chan_b)); },
- 0x27 => { send_payment_with_secret!(nodes[2], (&nodes[1], chan_b), (&nodes[0], chan_a)); },
-
0x28 => { send_payment(&nodes[0], &nodes[1], chan_a, 1_000_000, &mut payment_id); },
0x29 => { send_payment(&nodes[1], &nodes[0], chan_a, 1_000_000, &mut payment_id); },
0x2a => { send_payment(&nodes[1], &nodes[2], chan_b, 1_000_000, &mut payment_id); },
// Next, make sure peers are all connected to each other
if chan_a_disconnected {
- nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::empty() });
- nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: InitFeatures::empty() });
+ nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::known() });
+ nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: InitFeatures::known() });
chan_a_disconnected = false;
}
if chan_b_disconnected {
- nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: InitFeatures::empty() });
- nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::empty() });
+ nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: InitFeatures::known() });
+ nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::known() });
chan_b_disconnected = false;
}
use lightning::chain::chainmonitor;
use lightning::chain::transaction::OutPoint;
use lightning::chain::keysinterface::{InMemorySigner, KeysInterface};
-use lightning::ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret};
+use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
+use lightning::ln::channelmanager::{BestBlock, ChainParameters, ChannelManager};
use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor};
use lightning::ln::msgs::DecodeError;
use lightning::routing::router::get_route;
use utils::test_persister::TestPersister;
use bitcoin::secp256k1::key::{PublicKey,SecretKey};
+use bitcoin::secp256k1::recovery::RecoverableSignature;
use bitcoin::secp256k1::Secp256k1;
use std::cell::RefCell;
fn read_chan_signer(&self, data: &[u8]) -> Result<EnforcingSigner, DecodeError> {
EnforcingSigner::read(&mut std::io::Cursor::new(data))
}
+
+ fn sign_invoice(&self, _invoice_preimage: Vec<u8>) -> Result<RecoverableSignature, ()> {
+ unreachable!()
+ }
}
#[inline]
}, our_network_key, &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0], Arc::clone(&logger)));
let mut should_forward = false;
- let mut payments_received: Vec<(PaymentHash, Option<PaymentSecret>, u64)> = Vec::new();
+ let mut payments_received: Vec<PaymentHash> = Vec::new();
let mut payments_sent = 0;
let mut pending_funding_generation: Vec<([u8; 32], u64, Script)> = Vec::new();
let mut pending_funding_signatures = HashMap::new();
}
},
8 => {
- for (payment, payment_secret, amt) in payments_received.drain(..) {
+ for payment in payments_received.drain(..) {
// SHA256 is defined as XOR of all input bytes placed in the first byte, and 0s
// for the remaining bytes. Thus, if not all remaining bytes are 0s we cannot
// fulfill this HTLC, but if they are, we can just take the first byte and
// place that anywhere in our preimage.
if &payment.0[1..] != &[0; 31] {
- channelmanager.fail_htlc_backwards(&payment, &payment_secret);
+ channelmanager.fail_htlc_backwards(&payment);
} else {
let mut payment_preimage = PaymentPreimage([0; 32]);
payment_preimage.0[0] = payment.0[0];
- channelmanager.claim_funds(payment_preimage, &payment_secret, amt);
+ channelmanager.claim_funds(payment_preimage);
}
}
},
+ 16 => {
+ let payment_preimage = PaymentPreimage(keys_manager.get_secure_random_bytes());
+ let mut sha = Sha256::engine();
+ sha.input(&payment_preimage.0[..]);
+ let payment_hash = PaymentHash(Sha256::from_engine(sha).into_inner());
+ // Note that this may fail - our hashes may collide and we'll end up trying to
+ // double-register the same payment_hash.
+ let _ = channelmanager.create_inbound_payment_for_hash(payment_hash, None, 1, 0);
+ },
9 => {
- for (payment, payment_secret, _) in payments_received.drain(..) {
- channelmanager.fail_htlc_backwards(&payment, &payment_secret);
+ for payment in payments_received.drain(..) {
+ channelmanager.fail_htlc_backwards(&payment);
}
},
10 => {
Event::FundingGenerationReady { temporary_channel_id, channel_value_satoshis, output_script, .. } => {
pending_funding_generation.push((temporary_channel_id, channel_value_satoshis, output_script));
},
- Event::PaymentReceived { payment_hash, payment_secret, amt } => {
+ Event::PaymentReceived { payment_hash, .. } => {
//TODO: enhance by fetching random amounts from fuzz input?
- payments_received.push((payment_hash, payment_secret, amt));
+ payments_received.push(payment_hash);
},
Event::PaymentSent {..} => {},
Event::PaymentFailed {..} => {},
use std::sync::{Arc, Mutex};
use std::io::Write;
-pub trait Output : Clone + Sync + Send + 'static {
+pub trait Output : Clone + 'static {
fn locked_write(&self, data: &[u8]);
}
[dev-dependencies]
lightning = { version = "0.0.13", path = "../lightning", features = ["_test_utils"] }
-[dev-dependencies.bitcoin]
-version = "0.26"
-features = ["bitcoinconsensus"]
///
/// Other `Poll` implementations must be built using `ChainPoller` as it provides the only means of
/// validating chain data.
-pub struct ChainPoller<B: DerefMut<Target=T> + Sized + Sync + Send, T: BlockSource> {
+pub struct ChainPoller<B: DerefMut<Target=T> + Sized , T: BlockSource> {
block_source: B,
network: Network,
}
-impl<B: DerefMut<Target=T> + Sized + Sync + Send, T: BlockSource> ChainPoller<B, T> {
+impl<B: DerefMut<Target=T> + Sized , T: BlockSource> ChainPoller<B, T> {
/// Creates a new poller for the given block source.
///
/// If the `network` parameter is mainnet, then the difficulty between blocks is checked for
}
}
-impl<B: DerefMut<Target=T> + Sized + Sync + Send, T: BlockSource> Poll for ChainPoller<B, T> {
+impl<B: DerefMut<Target=T> + Sized + Send + Sync, T: BlockSource> Poll for ChainPoller<B, T> {
fn poll_chain_tip<'a>(&'a mut self, best_known_chain_tip: ValidatedBlockHeader) ->
AsyncBlockSourceResult<'a, ChainTip>
{
num-traits = "0.2.8"
bitcoin_hashes = "0.9.4"
+[dev-dependencies]
+lightning = { version = "0.0.13", path = "../lightning", features = ["_test_utils"] }
+
[lib]
crate-type = ["cdylib", "rlib"]
use bitcoin_hashes::Hash;
use bitcoin_hashes::sha256;
+use lightning::ln::PaymentSecret;
use lightning::routing::network_graph::RoutingFees;
use lightning::routing::router::RouteHintHop;
use secp256k1::recovery::{RecoveryId, RecoverableSignature};
use secp256k1::key::PublicKey;
-use super::*;
+use super::{Invoice, Sha256, TaggedField, ExpiryTime, MinFinalCltvExpiry, Fallback, PayeePubKey, InvoiceSignature, PositiveTimestamp,
+ SemanticError, RouteHint, Description, RawTaggedField, Currency, RawHrp, SiPrefix, RawInvoice, constants, SignedRawInvoice,
+ RawDataPart, CreationError, InvoiceFeatures};
use self::hrp_sm::parse_hrp;
hrp.as_bytes(),
&data[..data.len()-104]
),
- signature: Signature::from_base32(&data[data.len()-104..])?,
+ signature: InvoiceSignature::from_base32(&data[data.len()-104..])?,
})
}
}
}
}
-impl FromBase32 for Signature {
+impl FromBase32 for InvoiceSignature {
type Err = ParseError;
fn from_base32(signature: &[u5]) -> Result<Self, Self::Err> {
if signature.len() != 104 {
- return Err(ParseError::InvalidSliceLength("Signature::from_base32()".into()));
+ return Err(ParseError::InvalidSliceLength("InvoiceSignature::from_base32()".into()));
}
let recoverable_signature_bytes = Vec::<u8>::from_base32(signature)?;
let signature = &recoverable_signature_bytes[0..64];
let recovery_id = RecoveryId::from_i32(recoverable_signature_bytes[64] as i32)?;
- Ok(Signature(RecoverableSignature::from_compact(
+ Ok(InvoiceSignature(RecoverableSignature::from_compact(
signature,
recovery_id
)?))
Ok(TaggedField::Route(RouteHint::from_base32(field_data)?)),
constants::TAG_PAYMENT_SECRET =>
Ok(TaggedField::PaymentSecret(PaymentSecret::from_base32(field_data)?)),
+ constants::TAG_FEATURES =>
+ Ok(TaggedField::Features(InvoiceFeatures::from_base32(field_data)?)),
_ => {
// "A reader MUST skip over unknown fields"
Err(ParseError::Skip)
}
}
-impl FromBase32 for PaymentSecret {
- type Err = ParseError;
-
- fn from_base32(field_data: &[u5]) -> Result<PaymentSecret, ParseError> {
- if field_data.len() != 52 {
- Err(ParseError::Skip)
- } else {
- let data_bytes = Vec::<u8>::from_base32(field_data)?;
- let mut payment_secret = [0; 32];
- payment_secret.copy_from_slice(&data_bytes);
- Ok(PaymentSecret(payment_secret))
- }
- }
-}
-
impl FromBase32 for ExpiryTime {
type Err = ParseError;
}
#[test]
- fn test_payment_secret_deserialization() {
- use bech32::CheckBase32;
+ fn test_payment_secret_and_features_de_and_ser() {
+ use lightning::ln::features::InvoiceFeatures;
use secp256k1::recovery::{RecoveryId, RecoverableSignature};
use TaggedField::*;
- use {SiPrefix, SignedRawInvoice, Signature, RawInvoice, RawTaggedField, RawHrp, RawDataPart,
+ use {SiPrefix, SignedRawInvoice, InvoiceSignature, RawInvoice, RawHrp, RawDataPart,
Currency, Sha256, PositiveTimestamp};
- assert_eq!( // BOLT 11 payment secret invoice. The unknown fields are invoice features.
- "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q5sqqqqqqqqqqqqqqqpqsq67gye39hfg3zd8rgc80k32tvy9xk2xunwm5lzexnvpx6fd77en8qaq424dxgt56cag2dpt359k3ssyhetktkpqh24jqnjyw6uqd08sgptq44qu".parse(),
- Ok(SignedRawInvoice {
+ // Feature bits 9, 15, and 99 are set.
+ let expected_features = InvoiceFeatures::from_le_bytes(vec![0, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8]);
+ let invoice_str = "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q5sqqqqqqqqqqqqqqqpqsq67gye39hfg3zd8rgc80k32tvy9xk2xunwm5lzexnvpx6fd77en8qaq424dxgt56cag2dpt359k3ssyhetktkpqh24jqnjyw6uqd08sgptq44qu";
+ let invoice = SignedRawInvoice {
raw_invoice: RawInvoice {
hrp: RawHrp {
currency: Currency::Bitcoin,
).unwrap())).into(),
Description(::Description::new("coffee beans".to_owned()).unwrap()).into(),
PaymentSecret(::PaymentSecret([17; 32])).into(),
- RawTaggedField::UnknownSemantics(vec![5, 0, 20, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 1, 0, 16,
- 0].check_base32().unwrap())],
- }
+ Features(expected_features).into()]}
},
hash: [0xb1, 0x96, 0x46, 0xc3, 0xbc, 0x56, 0x76, 0x1d, 0x20, 0x65, 0x6e, 0x0e, 0x32,
0xec, 0xd2, 0x69, 0x27, 0xb7, 0x62, 0x6e, 0x2a, 0x8b, 0xe6, 0x97, 0x71, 0x9f,
0xf8, 0x7e, 0x44, 0x54, 0x55, 0xb9],
- signature: Signature(RecoverableSignature::from_compact(
+ signature: InvoiceSignature(RecoverableSignature::from_compact(
&[0xd7, 0x90, 0x4c, 0xc4, 0xb7, 0x4a, 0x22, 0x26, 0x9c, 0x68, 0xc1, 0xdf, 0x68,
0xa9, 0x6c, 0x21, 0x4d, 0x65, 0x1b, 0x93, 0x76, 0xe9, 0xf1, 0x64, 0xd3, 0x60,
0x4d, 0xa4, 0xb7, 0xde, 0xcc, 0xce, 0x0e, 0x82, 0xaa, 0xab, 0x4c, 0x85, 0xd3,
0x60, 0x82, 0xea, 0xac, 0x81, 0x39, 0x11, 0xda, 0xe0, 0x1a, 0xf3, 0xc1],
RecoveryId::from_i32(1).unwrap()
).unwrap()),
- })
- )
+ };
+ assert_eq!(invoice_str, invoice.to_string());
+ assert_eq!(
+ invoice_str.parse(),
+ Ok(invoice)
+ );
}
#[test]
fn test_raw_signed_invoice_deserialization() {
use TaggedField::*;
use secp256k1::recovery::{RecoveryId, RecoverableSignature};
- use {SignedRawInvoice, Signature, RawInvoice, RawHrp, RawDataPart, Currency, Sha256,
+ use {SignedRawInvoice, InvoiceSignature, RawInvoice, RawHrp, RawDataPart, Currency, Sha256,
PositiveTimestamp};
assert_eq!(
0x7b, 0x1d, 0x85, 0x8d, 0xb1, 0xd1, 0xf7, 0xab, 0x71, 0x37, 0xdc, 0xb7,
0x83, 0x5d, 0xb2, 0xec, 0xd5, 0x18, 0xe1, 0xc9
],
- signature: Signature(RecoverableSignature::from_compact(
+ signature: InvoiceSignature(RecoverableSignature::from_compact(
& [
0x38u8, 0xec, 0x68, 0x91, 0x34, 0x5e, 0x20, 0x41, 0x45, 0xbe, 0x8a,
0x3a, 0x99, 0xde, 0x38, 0xe9, 0x8a, 0x39, 0xd6, 0xa5, 0x69, 0x43,
#![deny(non_camel_case_types)]
#![deny(non_snake_case)]
#![deny(unused_mut)]
+#![deny(broken_intra_doc_links)]
#![cfg_attr(feature = "strict", deny(warnings))]
//! * For parsing use `str::parse::<Invoice>(&self)` (see the docs of `impl FromStr for Invoice`)
//! * For constructing invoices use the `InvoiceBuilder`
//! * For serializing invoices use the `Display`/`ToString` traits
+pub mod utils;
extern crate bech32;
extern crate bitcoin_hashes;
use bech32::u5;
use bitcoin_hashes::Hash;
use bitcoin_hashes::sha256;
+use lightning::ln::PaymentSecret;
+use lightning::ln::features::InvoiceFeatures;
#[cfg(any(doc, test))]
use lightning::routing::network_graph::RoutingFees;
use lightning::routing::router::RouteHintHop;
use secp256k1::key::PublicKey;
use secp256k1::{Message, Secp256k1};
use secp256k1::recovery::RecoverableSignature;
-use std::ops::Deref;
+use std::fmt::{Display, Formatter, self};
use std::iter::FilterMap;
+use std::ops::Deref;
use std::slice::Iter;
use std::time::{SystemTime, Duration, UNIX_EPOCH};
-use std::fmt::{Display, Formatter, self};
mod de;
mod ser;
/// it should be rather low as long as we still have to support 32bit time representations
const MAX_EXPIRY_TIME: u64 = 60 * 60 * 24 * 356;
+/// Default expiry time as defined by [BOLT 11].
+///
+/// [BOLT 11]: https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md
+const DEFAULT_EXPIRY_TIME: u64 = 3600;
+
+/// Default minimum final CLTV expiry as defined by [BOLT 11].
+///
+/// [BOLT 11]: https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md
+const DEFAULT_MIN_FINAL_CLTV_EXPIRY: u64 = 18;
+
/// This function is used as a static assert for the size of `SystemTime`. If the crate fails to
/// compile due to it this indicates that your system uses unexpected bounds for `SystemTime`. You
/// can remove this functions and run the test `test_system_time_bounds_assumptions`. In any case,
/// .description("Coins pls!".into())
/// .payment_hash(payment_hash)
/// .current_timestamp()
+/// .min_final_cltv_expiry(144)
/// .build_signed(|hash| {
/// Secp256k1::new().sign_recoverable(hash, &private_key)
/// })
/// * `D`: exactly one `Description` or `DescriptionHash`
/// * `H`: exactly one `PaymentHash`
/// * `T`: the timestamp is set
+///
+/// (C-not exported) as we likely need to manually select one set of boolean type parameters.
#[derive(Eq, PartialEq, Debug, Clone)]
-pub struct InvoiceBuilder<D: tb::Bool, H: tb::Bool, T: tb::Bool> {
+pub struct InvoiceBuilder<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool> {
currency: Currency,
amount: Option<u64>,
si_prefix: Option<SiPrefix>,
phantom_d: std::marker::PhantomData<D>,
phantom_h: std::marker::PhantomData<H>,
phantom_t: std::marker::PhantomData<T>,
+ phantom_c: std::marker::PhantomData<C>,
}
/// Represents a syntactically and semantically correct lightning BOLT11 invoice.
/// Represents the description of an invoice which has to be either a directly included string or
/// a hash of a description provided out of band.
+///
+/// (C-not exported) As we don't have a good way to map the reference lifetimes making this
+/// practically impossible to use safely in languages like C.
#[derive(Eq, PartialEq, Debug, Clone)]
pub enum InvoiceDescription<'f> {
/// Reference to the directly supplied description in the invoice
hash: [u8; 32],
/// signature of the payment request
- signature: Signature,
+ signature: InvoiceSignature,
}
/// Represents an syntactically correct Invoice for a payment on the lightning network,
}
/// Data of the `RawInvoice` that is encoded in the human readable part
+///
+/// (C-not exported) As we don't yet support Option<Enum>
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct RawHrp {
/// The currency deferred from the 3rd and 4th character of the bech32 transaction
/// Returns all enum variants of `SiPrefix` sorted in descending order of their associated
/// multiplier.
+ ///
+ /// (C-not exported) As we don't yet support a slice of enums, and also because this function
+ /// isn't the most critical to expose.
pub fn values_desc() -> &'static [SiPrefix] {
use SiPrefix::*;
static VALUES: [SiPrefix; 4] = [Milli, Micro, Nano, Pico];
}
/// Tagged field which may have an unknown tag
+///
+/// (C-not exported) as we don't currently support TaggedField
#[derive(Eq, PartialEq, Debug, Clone)]
pub enum RawTaggedField {
/// Parsed tagged field with known tag
/// Tagged field with known tag
///
/// For descriptions of the enum values please refer to the enclosed type's docs.
+///
+/// (C-not exported) As we don't yet support enum variants with the same name the struct contained
+/// in the variant.
#[allow(missing_docs)]
#[derive(Eq, PartialEq, Debug, Clone)]
pub enum TaggedField {
Fallback(Fallback),
Route(RouteHint),
PaymentSecret(PaymentSecret),
+ Features(InvoiceFeatures),
}
/// SHA-256 hash
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct PayeePubKey(pub PublicKey);
-/// 256-bit payment secret
-#[derive(Eq, PartialEq, Debug, Clone)]
-pub struct PaymentSecret(pub [u8; 32]);
-
/// Positive duration that defines when (relatively to the timestamp) in the future the invoice
/// expires
///
/// Recoverable signature
#[derive(Eq, PartialEq, Debug, Clone)]
-pub struct Signature(pub RecoverableSignature);
+pub struct InvoiceSignature(pub RecoverableSignature);
/// Private routing information
///
pub const TAG_FALLBACK: u8 = 9;
pub const TAG_ROUTE: u8 = 3;
pub const TAG_PAYMENT_SECRET: u8 = 16;
+ pub const TAG_FEATURES: u8 = 5;
}
-impl InvoiceBuilder<tb::False, tb::False, tb::False> {
+impl InvoiceBuilder<tb::False, tb::False, tb::False, tb::False> {
/// Construct new, empty `InvoiceBuilder`. All necessary fields have to be filled first before
/// `InvoiceBuilder::build(self)` becomes available.
pub fn new(currrency: Currency) -> Self {
phantom_d: std::marker::PhantomData,
phantom_h: std::marker::PhantomData,
phantom_t: std::marker::PhantomData,
+ phantom_c: std::marker::PhantomData,
}
}
}
-impl<D: tb::Bool, H: tb::Bool, T: tb::Bool> InvoiceBuilder<D, H, T> {
+impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool> InvoiceBuilder<D, H, T, C> {
/// Helper function to set the completeness flags.
- fn set_flags<DN: tb::Bool, HN: tb::Bool, TN: tb::Bool>(self) -> InvoiceBuilder<DN, HN, TN> {
- InvoiceBuilder::<DN, HN, TN> {
+ fn set_flags<DN: tb::Bool, HN: tb::Bool, TN: tb::Bool, CN: tb::Bool>(self) -> InvoiceBuilder<DN, HN, TN, CN> {
+ InvoiceBuilder::<DN, HN, TN, CN> {
currency: self.currency,
amount: self.amount,
si_prefix: self.si_prefix,
phantom_d: std::marker::PhantomData,
phantom_h: std::marker::PhantomData,
phantom_t: std::marker::PhantomData,
+ phantom_c: std::marker::PhantomData,
}
}
self
}
- /// Sets `min_final_cltv_expiry`.
- pub fn min_final_cltv_expiry(mut self, min_final_cltv_expiry: u64) -> Self {
- self.tagged_fields.push(TaggedField::MinFinalCltvExpiry(MinFinalCltvExpiry(min_final_cltv_expiry)));
- self
- }
-
/// Adds a fallback address.
pub fn fallback(mut self, fallback: Fallback) -> Self {
self.tagged_fields.push(TaggedField::Fallback(fallback));
}
self
}
+
+ /// Adds a features field which indicates the set of supported protocol extensions which the
+ /// origin node supports.
+ pub fn features(mut self, features: InvoiceFeatures) -> Self {
+ self.tagged_fields.push(TaggedField::Features(features));
+ self
+ }
}
-impl<D: tb::Bool, H: tb::Bool> InvoiceBuilder<D, H, tb::True> {
+impl<D: tb::Bool, H: tb::Bool, C: tb::Bool> InvoiceBuilder<D, H, tb::True, C> {
/// Builds a `RawInvoice` if no `CreationError` occurred while construction any of the fields.
pub fn build_raw(self) -> Result<RawInvoice, CreationError> {
}
}
-impl<H: tb::Bool, T: tb::Bool> InvoiceBuilder<tb::False, H, T> {
+impl<H: tb::Bool, T: tb::Bool, C: tb::Bool> InvoiceBuilder<tb::False, H, T, C> {
/// Set the description. This function is only available if no description (hash) was set.
- pub fn description(mut self, description: String) -> InvoiceBuilder<tb::True, H, T> {
+ pub fn description(mut self, description: String) -> InvoiceBuilder<tb::True, H, T, C> {
match Description::new(description) {
Ok(d) => self.tagged_fields.push(TaggedField::Description(d)),
Err(e) => self.error = Some(e),
}
/// Set the description hash. This function is only available if no description (hash) was set.
- pub fn description_hash(mut self, description_hash: sha256::Hash) -> InvoiceBuilder<tb::True, H, T> {
+ pub fn description_hash(mut self, description_hash: sha256::Hash) -> InvoiceBuilder<tb::True, H, T, C> {
self.tagged_fields.push(TaggedField::DescriptionHash(Sha256(description_hash)));
self.set_flags()
}
}
-impl<D: tb::Bool, T: tb::Bool> InvoiceBuilder<D, tb::False, T> {
+impl<D: tb::Bool, T: tb::Bool, C: tb::Bool> InvoiceBuilder<D, tb::False, T, C> {
/// Set the payment hash. This function is only available if no payment hash was set.
- pub fn payment_hash(mut self, hash: sha256::Hash) -> InvoiceBuilder<D, tb::True, T> {
+ pub fn payment_hash(mut self, hash: sha256::Hash) -> InvoiceBuilder<D, tb::True, T, C> {
self.tagged_fields.push(TaggedField::PaymentHash(Sha256(hash)));
self.set_flags()
}
}
-impl<D: tb::Bool, H: tb::Bool> InvoiceBuilder<D, H, tb::False> {
+impl<D: tb::Bool, H: tb::Bool, C: tb::Bool> InvoiceBuilder<D, H, tb::False, C> {
/// Sets the timestamp.
- pub fn timestamp(mut self, time: SystemTime) -> InvoiceBuilder<D, H, tb::True> {
+ pub fn timestamp(mut self, time: SystemTime) -> InvoiceBuilder<D, H, tb::True, C> {
match PositiveTimestamp::from_system_time(time) {
Ok(t) => self.timestamp = Some(t),
Err(e) => self.error = Some(e),
}
/// Sets the timestamp to the current UNIX timestamp.
- pub fn current_timestamp(mut self) -> InvoiceBuilder<D, H, tb::True> {
+ pub fn current_timestamp(mut self) -> InvoiceBuilder<D, H, tb::True, C> {
let now = PositiveTimestamp::from_system_time(SystemTime::now());
self.timestamp = Some(now.expect("for the foreseeable future this shouldn't happen"));
self.set_flags()
}
}
-impl InvoiceBuilder<tb::True, tb::True, tb::True> {
+impl<D: tb::Bool, H: tb::Bool, T: tb::Bool> InvoiceBuilder<D, H, T, tb::False> {
+ /// Sets `min_final_cltv_expiry`.
+ pub fn min_final_cltv_expiry(mut self, min_final_cltv_expiry: u64) -> InvoiceBuilder<D, H, T, tb::True> {
+ self.tagged_fields.push(TaggedField::MinFinalCltvExpiry(MinFinalCltvExpiry(min_final_cltv_expiry)));
+ self.set_flags()
+ }
+}
+
+impl InvoiceBuilder<tb::True, tb::True, tb::True, tb::True> {
/// Builds and signs an invoice using the supplied `sign_function`. This function MAY NOT fail
/// and MUST produce a recoverable signature valid for the given hash and if applicable also for
/// the included payee public key.
/// 1. raw invoice
/// 2. hash of the raw invoice
/// 3. signature
- pub fn into_parts(self) -> (RawInvoice, [u8; 32], Signature) {
+ pub fn into_parts(self) -> (RawInvoice, [u8; 32], InvoiceSignature) {
(self.raw_invoice, self.hash, self.signature)
}
&self.hash
}
- /// Signature for the invoice.
- pub fn signature(&self) -> &Signature {
+ /// InvoiceSignature for the invoice.
+ pub fn signature(&self) -> &InvoiceSignature {
&self.signature
}
#[allow(missing_docs)]
impl RawInvoice {
- /// Hash the HRP as bytes and signatureless data part.
- fn hash_from_parts(hrp_bytes: &[u8], data_without_signature: &[u5]) -> [u8; 32] {
+ /// Construct the invoice's HRP and signatureless data into a preimage to be hashed.
+ pub(crate) fn construct_invoice_preimage(hrp_bytes: &[u8], data_without_signature: &[u5]) -> Vec<u8> {
use bech32::FromBase32;
let mut preimage = Vec::<u8>::from(hrp_bytes);
preimage.extend_from_slice(&Vec::<u8>::from_base32(&data_part)
.expect("No padding error may occur due to appended zero above."));
+ preimage
+ }
+ /// Hash the HRP as bytes and signatureless data part.
+ fn hash_from_parts(hrp_bytes: &[u8], data_without_signature: &[u5]) -> [u8; 32] {
+ let preimage = RawInvoice::construct_invoice_preimage(hrp_bytes, data_without_signature);
let mut hash: [u8; 32] = Default::default();
hash.copy_from_slice(&sha256::Hash::hash(&preimage)[..]);
hash
/// Signs the invoice using the supplied `sign_function`. This function MAY fail with an error
/// of type `E`. Since the signature of a `SignedRawInvoice` is not required to be valid there
/// are no constraints regarding the validity of the produced signature.
+ ///
+ /// (C-not exported) As we don't currently support passing function pointers into methods
+ /// explicitly.
pub fn sign<F, E>(self, sign_method: F) -> Result<SignedRawInvoice, E>
where F: FnOnce(&Message) -> Result<RecoverableSignature, E>
{
Ok(SignedRawInvoice {
raw_invoice: self,
hash: raw_hash,
- signature: Signature(signature),
+ signature: InvoiceSignature(signature),
})
}
/// Returns an iterator over all tagged fields with known semantics.
+ ///
+ /// (C-not exported) As there is not yet a manual mapping for a FilterMap
pub fn known_tagged_fields(&self)
-> FilterMap<Iter<RawTaggedField>, fn(&RawTaggedField) -> Option<&TaggedField>>
{
find_extract!(self.known_tagged_fields(), TaggedField::PaymentSecret(ref x), x)
}
+ pub fn features(&self) -> Option<&InvoiceFeatures> {
+ find_extract!(self.known_tagged_fields(), TaggedField::Features(ref x), x)
+ }
+
+ /// (C-not exported) as we don't support Vec<&NonOpaqueType>
pub fn fallbacks(&self) -> Vec<&Fallback> {
self.known_tagged_fields().filter_map(|tf| match tf {
&TaggedField::Fallback(ref f) => Some(f),
}
/// Returns an iterator over all tagged fields of this Invoice.
+ ///
+ /// (C-not exported) As there is not yet a manual mapping for a FilterMap
pub fn tagged_fields(&self)
-> FilterMap<Iter<RawTaggedField>, fn(&RawTaggedField) -> Option<&TaggedField>> {
self.signed_invoice.raw_invoice().known_tagged_fields()
}
/// Return the description or a hash of it for longer ones
+ ///
+ /// (C-not exported) because we don't yet export InvoiceDescription
pub fn description(&self) -> InvoiceDescription {
if let Some(ref direct) = self.signed_invoice.description() {
return InvoiceDescription::Direct(direct);
self.signed_invoice.payee_pub_key().map(|x| &x.0)
}
- /// Get the payment secret if one was included in the invoice
- pub fn payment_secret(&self) -> Option<&PaymentSecret> {
- self.signed_invoice.payment_secret()
- }
+ /// Get the payment secret if one was included in the invoice
+ pub fn payment_secret(&self) -> Option<&PaymentSecret> {
+ self.signed_invoice.payment_secret()
+ }
+
+ /// Get the invoice features if they were included in the invoice
+ pub fn features(&self) -> Option<&InvoiceFeatures> {
+ self.signed_invoice.features()
+ }
/// Recover the payee's public key (only to be used if none was included in the invoice)
pub fn recover_payee_pub_key(&self) -> PublicKey {
self.signed_invoice.recover_payee_pub_key().expect("was checked by constructor").0
}
- /// Returns the invoice's expiry time if present
+ /// Returns the invoice's expiry time, if present, otherwise [`DEFAULT_EXPIRY_TIME`].
pub fn expiry_time(&self) -> Duration {
self.signed_invoice.expiry_time()
.map(|x| x.0)
- .unwrap_or(Duration::from_secs(3600))
+ .unwrap_or(Duration::from_secs(DEFAULT_EXPIRY_TIME))
}
- /// Returns the invoice's `min_cltv_expiry` time if present
- pub fn min_final_cltv_expiry(&self) -> Option<&u64> {
- self.signed_invoice.min_final_cltv_expiry().map(|x| &x.0)
+ /// Returns the invoice's `min_final_cltv_expiry` time, if present, otherwise
+ /// [`DEFAULT_MIN_FINAL_CLTV_EXPIRY`].
+ pub fn min_final_cltv_expiry(&self) -> u64 {
+ self.signed_invoice.min_final_cltv_expiry()
+ .map(|x| x.0)
+ .unwrap_or(DEFAULT_MIN_FINAL_CLTV_EXPIRY)
}
/// Returns a list of all fallback addresses
+ ///
+ /// (C-not exported) as we don't support Vec<&NonOpaqueType>
pub fn fallbacks(&self) -> Vec<&Fallback> {
self.signed_invoice.fallbacks()
}
TaggedField::Fallback(_) => constants::TAG_FALLBACK,
TaggedField::Route(_) => constants::TAG_ROUTE,
TaggedField::PaymentSecret(_) => constants::TAG_PAYMENT_SECRET,
+ TaggedField::Features(_) => constants::TAG_FEATURES,
};
u5::try_from_u8(tag).expect("all tags defined are <32")
}
}
-impl Deref for Signature {
+impl Deref for InvoiceSignature {
type Target = RecoverableSignature;
fn deref(&self) -> &RecoverableSignature {
/// When signing using a fallible method either an user-supplied `SignError` or a `CreationError`
/// may occur.
#[derive(Eq, PartialEq, Debug, Clone)]
-pub enum SignOrCreationError<S> {
+pub enum SignOrCreationError<S = ()> {
/// An error occurred during signing
SignError(S),
use secp256k1::Secp256k1;
use secp256k1::recovery::{RecoveryId, RecoverableSignature};
use secp256k1::key::{SecretKey, PublicKey};
- use {SignedRawInvoice, Signature, RawInvoice, RawHrp, RawDataPart, Currency, Sha256,
+ use {SignedRawInvoice, InvoiceSignature, RawInvoice, RawHrp, RawDataPart, Currency, Sha256,
PositiveTimestamp};
let invoice = SignedRawInvoice {
0x7b, 0x1d, 0x85, 0x8d, 0xb1, 0xd1, 0xf7, 0xab, 0x71, 0x37, 0xdc, 0xb7,
0x83, 0x5d, 0xb2, 0xec, 0xd5, 0x18, 0xe1, 0xc9
],
- signature: Signature(RecoverableSignature::from_compact(
+ signature: InvoiceSignature(RecoverableSignature::from_compact(
& [
0x38u8, 0xec, 0x68, 0x91, 0x34, 0x5e, 0x20, 0x41, 0x45, 0xbe, 0x8a,
0x3a, 0x99, 0xde, 0x38, 0xe9, 0x8a, 0x39, 0xd6, 0xa5, 0x69, 0x43,
let builder = InvoiceBuilder::new(Currency::Bitcoin)
.payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap())
- .current_timestamp();
+ .current_timestamp()
+ .min_final_cltv_expiry(144);
let too_long_string = String::from_iter(
(0..1024).map(|_| '?')
.payee_pub_key(public_key.clone())
.expiry_time(Duration::from_secs(54321))
.min_final_cltv_expiry(144)
- .min_final_cltv_expiry(143)
.fallback(Fallback::PubKeyHash([0;20]))
.route(route_1.clone())
.route(route_2.clone())
}).unwrap();
assert!(invoice.check_signature().is_ok());
- assert_eq!(invoice.tagged_fields().count(), 9);
+ assert_eq!(invoice.tagged_fields().count(), 8);
assert_eq!(invoice.amount_pico_btc(), Some(123));
assert_eq!(invoice.currency(), Currency::BitcoinTestnet);
);
assert_eq!(invoice.payee_pub_key(), Some(&public_key));
assert_eq!(invoice.expiry_time(), Duration::from_secs(54321));
- assert_eq!(invoice.min_final_cltv_expiry(), Some(&144));
+ assert_eq!(invoice.min_final_cltv_expiry(), 144);
assert_eq!(invoice.fallbacks(), vec![&Fallback::PubKeyHash([0;20])]);
assert_eq!(invoice.routes(), vec![&RouteHint(route_1), &RouteHint(route_2)]);
assert_eq!(
let raw_invoice = builder.build_raw().unwrap();
assert_eq!(raw_invoice, *invoice.into_signed_raw().raw_invoice())
}
+
+ #[test]
+ fn test_default_values() {
+ use ::*;
+ use secp256k1::Secp256k1;
+ use secp256k1::key::SecretKey;
+
+ let signed_invoice = InvoiceBuilder::new(Currency::Bitcoin)
+ .description("Test".into())
+ .payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap())
+ .current_timestamp()
+ .build_raw()
+ .unwrap()
+ .sign::<_, ()>(|hash| {
+ let privkey = SecretKey::from_slice(&[41; 32]).unwrap();
+ let secp_ctx = Secp256k1::new();
+ Ok(secp_ctx.sign_recoverable(hash, &privkey))
+ })
+ .unwrap();
+ let invoice = Invoice::from_signed(signed_invoice).unwrap();
+
+ assert_eq!(invoice.min_final_cltv_expiry(), DEFAULT_MIN_FINAL_CLTV_EXPIRY);
+ assert_eq!(invoice.expiry_time(), Duration::from_secs(DEFAULT_EXPIRY_TIME));
+ }
}
use std::fmt::{Display, Formatter};
use bech32::{ToBase32, u5, WriteBase32, Base32Len};
-use ::*;
+use super::{Invoice, Sha256, TaggedField, ExpiryTime, MinFinalCltvExpiry, Fallback, PayeePubKey, InvoiceSignature, PositiveTimestamp,
+ RouteHint, Description, RawTaggedField, Currency, RawHrp, SiPrefix, constants, SignedRawInvoice, RawDataPart};
/// Converts a stream of bytes written to it to base32. On finalization the according padding will
/// be applied. That means the results of writing two data blocks with one or two `BytesToBase32`
}
}
+/// (C-not exported)
impl Display for RawHrp {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
let amount = match self.raw_amount {
}
}
-impl ToBase32 for PaymentSecret {
- fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
- (&self.0[..]).write_base32(writer)
- }
-}
-
-impl Base32Len for PaymentSecret {
- fn base32_len(&self) -> usize {
- bytes_size_to_base32_size(32)
- }
-}
-
impl ToBase32 for ExpiryTime {
fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
writer.write(&encode_int_be_base32(self.as_seconds()))
TaggedField::PaymentSecret(ref payment_secret) => {
write_tagged_field(writer, constants::TAG_PAYMENT_SECRET, payment_secret)
},
-
+ TaggedField::Features(ref features) => {
+ write_tagged_field(writer, constants::TAG_FEATURES, features)
+ },
}
}
}
-impl ToBase32 for Signature {
+impl ToBase32 for InvoiceSignature {
fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
let mut converter = BytesToBase32::new(writer);
let (recovery_id, signature) = self.0.serialize_compact();
--- /dev/null
+//! Convenient utilities to create an invoice.
+use {Currency, Invoice, InvoiceBuilder, SignOrCreationError, RawInvoice};
+use bech32::ToBase32;
+use bitcoin_hashes::Hash;
+use lightning::chain;
+use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
+use lightning::chain::keysinterface::{Sign, KeysInterface};
+use lightning::ln::channelmanager::{ChannelManager, MIN_FINAL_CLTV_EXPIRY};
+use lightning::ln::features::InvoiceFeatures;
+use lightning::routing::network_graph::RoutingFees;
+use lightning::routing::router::RouteHintHop;
+use lightning::util::logger::Logger;
+use std::ops::Deref;
+
+/// Utility to construct an invoice. Generally, unless you want to do something like a custom
+/// cltv_expiry, this is what you should be using to create an invoice. The reason being, this
+/// method stores the invoice's payment secret and preimage in `ChannelManager`, so (a) the user
+/// doesn't have to store preimage/payment secret information and (b) `ChannelManager` can verify
+/// that the payment secret is valid when the invoice is paid.
+pub fn create_invoice_from_channelmanager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>(
+ channelmanager: &ChannelManager<Signer, M, T, K, F, L>, keys_manager: K, network: Currency,
+ amt_msat: Option<u64>, description: String
+) -> Result<Invoice, SignOrCreationError<()>>
+where
+ M::Target: chain::Watch<Signer>,
+ T::Target: BroadcasterInterface,
+ K::Target: KeysInterface<Signer = Signer>,
+ F::Target: FeeEstimator,
+ L::Target: Logger,
+{
+ // Marshall route hints.
+ let our_channels = channelmanager.list_usable_channels();
+ let mut route_hints = vec![];
+ for channel in our_channels {
+ let short_channel_id = match channel.short_channel_id {
+ Some(id) => id,
+ None => continue,
+ };
+ let forwarding_info = match channel.counterparty_forwarding_info {
+ Some(info) => info,
+ None => continue,
+ };
+ route_hints.push(vec![RouteHintHop {
+ src_node_id: channel.remote_network_id,
+ short_channel_id,
+ fees: RoutingFees {
+ base_msat: forwarding_info.fee_base_msat,
+ proportional_millionths: forwarding_info.fee_proportional_millionths,
+ },
+ cltv_expiry_delta: forwarding_info.cltv_expiry_delta,
+ htlc_minimum_msat: None,
+ htlc_maximum_msat: None,
+ }]);
+ }
+
+ let (payment_hash, payment_secret) = channelmanager.create_inbound_payment(
+ amt_msat,
+ 7200, // default invoice expiry is 2 hours
+ 0,
+ );
+ let our_node_pubkey = channelmanager.get_our_node_id();
+ let mut invoice = InvoiceBuilder::new(network)
+ .description(description)
+ .current_timestamp()
+ .payee_pub_key(our_node_pubkey)
+ .payment_hash(Hash::from_slice(&payment_hash.0).unwrap())
+ .payment_secret(payment_secret)
+ .features(InvoiceFeatures::known())
+ .min_final_cltv_expiry(MIN_FINAL_CLTV_EXPIRY.into());
+ if let Some(amt) = amt_msat {
+ invoice = invoice.amount_pico_btc(amt * 10);
+ }
+ for hint in route_hints.drain(..) {
+ invoice = invoice.route(hint);
+ }
+
+ let raw_invoice = match invoice.build_raw() {
+ Ok(inv) => inv,
+ Err(e) => return Err(SignOrCreationError::CreationError(e))
+ };
+ let hrp_str = raw_invoice.hrp.to_string();
+ let hrp_bytes = hrp_str.as_bytes();
+ let data_without_signature = raw_invoice.data.to_base32();
+ let invoice_preimage = RawInvoice::construct_invoice_preimage(hrp_bytes, &data_without_signature);
+ let signed_raw_invoice = raw_invoice.sign(|_| keys_manager.sign_invoice(invoice_preimage));
+ match signed_raw_invoice {
+ Ok(inv) => Ok(Invoice::from_signed(inv).unwrap()),
+ Err(e) => Err(SignOrCreationError::SignError(e))
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use {Currency, Description, InvoiceDescription};
+ use lightning::ln::PaymentHash;
+ use lightning::ln::functional_test_utils::*;
+ use lightning::ln::features::InitFeatures;
+ use lightning::ln::msgs::ChannelMessageHandler;
+ use lightning::routing::router;
+ use lightning::util::events::MessageSendEventsProvider;
+ use lightning::util::test_utils;
+ #[test]
+ fn test_from_channelmanager() {
+ let chanmon_cfgs = create_chanmon_cfgs(2);
+ let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+ let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+ let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+ let _chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+ let invoice = ::utils::create_invoice_from_channelmanager(&nodes[1].node, nodes[1].keys_manager, Currency::BitcoinTestnet, Some(10_000), "test".to_string()).unwrap();
+ assert_eq!(invoice.amount_pico_btc(), Some(100_000));
+ assert_eq!(invoice.min_final_cltv_expiry(), 9);
+ assert_eq!(invoice.description(), InvoiceDescription::Direct(&Description("test".to_string())));
+
+ let mut route_hints = invoice.routes().clone();
+ let mut last_hops = Vec::new();
+ for hint in route_hints.drain(..) {
+ last_hops.push(hint[hint.len() - 1].clone());
+ }
+ let amt_msat = invoice.amount_pico_btc().unwrap() / 10;
+
+ let first_hops = nodes[0].node.list_usable_channels();
+ let network_graph = nodes[0].net_graph_msg_handler.network_graph.read().unwrap();
+ let logger = test_utils::TestLogger::new();
+ let route = router::get_route(
+ &nodes[0].node.get_our_node_id(),
+ &network_graph,
+ &invoice.recover_payee_pub_key(),
+ Some(invoice.features().unwrap().clone()),
+ Some(&first_hops.iter().collect::<Vec<_>>()),
+ &last_hops.iter().collect::<Vec<_>>(),
+ amt_msat,
+ invoice.min_final_cltv_expiry() as u32,
+ &logger,
+ ).unwrap();
+
+ let payment_event = {
+ let mut payment_hash = PaymentHash([0; 32]);
+ payment_hash.0.copy_from_slice(&invoice.payment_hash().as_ref()[0..32]);
+ nodes[0].node.send_payment(&route, payment_hash, &Some(invoice.payment_secret().unwrap().clone())).unwrap();
+ let mut added_monitors = nodes[0].chain_monitor.added_monitors.lock().unwrap();
+ assert_eq!(added_monitors.len(), 1);
+ added_monitors.clear();
+
+ let mut events = nodes[0].node.get_and_clear_pending_msg_events();
+ assert_eq!(events.len(), 1);
+ SendEvent::from_event(events.remove(0))
+
+ };
+ nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
+ nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &payment_event.commitment_msg);
+ let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap();
+ assert_eq!(added_monitors.len(), 1);
+ added_monitors.clear();
+ let events = nodes[1].node.get_and_clear_pending_msg_events();
+ assert_eq!(events.len(), 2);
+ }
+}
extern crate bitcoin_hashes;
+extern crate lightning;
extern crate lightning_invoice;
extern crate secp256k1;
use bitcoin_hashes::hex::FromHex;
use bitcoin_hashes::sha256;
+use lightning::ln::PaymentSecret;
use lightning_invoice::*;
use secp256k1::Secp256k1;
use secp256k1::key::SecretKey;
.amount_pico_btc(20000000000)
.timestamp(UNIX_EPOCH + Duration::from_secs(1496314658))
.payment_secret(PaymentSecret([42; 32]))
- .build_signed(|msg_hash| {
+ .build_raw()
+ .unwrap()
+ .sign::<_, ()>(|msg_hash| {
let privkey = SecretKey::from_slice(&[41; 32]).unwrap();
let secp_ctx = Secp256k1::new();
- secp_ctx.sign_recoverable(msg_hash, &privkey)
+ Ok(secp_ctx.sign_recoverable(msg_hash, &privkey))
})
- .unwrap()
- .into_signed_raw(),
+ .unwrap(),
None
)
]
//! use std::sync::Arc;
//!
//! // Define concrete types for our high-level objects:
-//! type TxBroadcaster = dyn lightning::chain::chaininterface::BroadcasterInterface;
-//! type FeeEstimator = dyn lightning::chain::chaininterface::FeeEstimator;
-//! type Logger = dyn lightning::util::logger::Logger;
-//! type ChainAccess = dyn lightning::chain::Access;
-//! type ChainFilter = dyn lightning::chain::Filter;
-//! type DataPersister = dyn lightning::chain::channelmonitor::Persist<lightning::chain::keysinterface::InMemorySigner>;
+//! type TxBroadcaster = dyn lightning::chain::chaininterface::BroadcasterInterface + Send + Sync;
+//! type FeeEstimator = dyn lightning::chain::chaininterface::FeeEstimator + Send + Sync;
+//! type Logger = dyn lightning::util::logger::Logger + Send + Sync;
+//! type ChainAccess = dyn lightning::chain::Access + Send + Sync;
+//! type ChainFilter = dyn lightning::chain::Filter + Send + Sync;
+//! type DataPersister = dyn lightning::chain::channelmonitor::Persist<lightning::chain::keysinterface::InMemorySigner> + Send + Sync;
//! type ChainMonitor = lightning::chain::chainmonitor::ChainMonitor<lightning::chain::keysinterface::InMemorySigner, Arc<ChainFilter>, Arc<TxBroadcaster>, Arc<FeeEstimator>, Arc<Logger>, Arc<DataPersister>>;
//! type ChannelManager = Arc<lightning::ln::channelmanager::SimpleArcChannelManager<ChainMonitor, TxBroadcaster, FeeEstimator, Logger>>;
//! type PeerManager = Arc<lightning::ln::peer_handler::SimpleArcPeerManager<lightning_net_tokio::SocketDescriptor, ChainMonitor, TxBroadcaster, FeeEstimator, ChainAccess, Logger>>;
///
/// See the module-level documentation for how to handle the event_notify mpsc::Sender.
pub fn setup_inbound<CMH, RMH, L>(peer_manager: Arc<peer_handler::PeerManager<SocketDescriptor, Arc<CMH>, Arc<RMH>, Arc<L>>>, event_notify: mpsc::Sender<()>, stream: StdTcpStream) -> impl std::future::Future<Output=()> where
- CMH: ChannelMessageHandler + 'static,
- RMH: RoutingMessageHandler + 'static,
- L: Logger + 'static + ?Sized {
+ CMH: ChannelMessageHandler + 'static + Send + Sync,
+ RMH: RoutingMessageHandler + 'static + Send + Sync,
+ L: Logger + 'static + ?Sized + Send + Sync {
let (reader, write_receiver, read_receiver, us) = Connection::new(event_notify, stream);
#[cfg(debug_assertions)]
let last_us = Arc::clone(&us);
///
/// See the module-level documentation for how to handle the event_notify mpsc::Sender.
pub fn setup_outbound<CMH, RMH, L>(peer_manager: Arc<peer_handler::PeerManager<SocketDescriptor, Arc<CMH>, Arc<RMH>, Arc<L>>>, event_notify: mpsc::Sender<()>, their_node_id: PublicKey, stream: StdTcpStream) -> impl std::future::Future<Output=()> where
- CMH: ChannelMessageHandler + 'static,
- RMH: RoutingMessageHandler + 'static,
- L: Logger + 'static + ?Sized {
+ CMH: ChannelMessageHandler + 'static + Send + Sync,
+ RMH: RoutingMessageHandler + 'static + Send + Sync,
+ L: Logger + 'static + ?Sized + Send + Sync {
let (reader, mut write_receiver, read_receiver, us) = Connection::new(event_notify, stream);
#[cfg(debug_assertions)]
let last_us = Arc::clone(&us);
///
/// See the module-level documentation for how to handle the event_notify mpsc::Sender.
pub async fn connect_outbound<CMH, RMH, L>(peer_manager: Arc<peer_handler::PeerManager<SocketDescriptor, Arc<CMH>, Arc<RMH>, Arc<L>>>, event_notify: mpsc::Sender<()>, their_node_id: PublicKey, addr: SocketAddr) -> Option<impl std::future::Future<Output=()>> where
- CMH: ChannelMessageHandler + 'static,
- RMH: RoutingMessageHandler + 'static,
- L: Logger + 'static + ?Sized {
+ CMH: ChannelMessageHandler + 'static + Send + Sync,
+ RMH: RoutingMessageHandler + 'static + Send + Sync,
+ L: Logger + 'static + ?Sized + Send + Sync {
if let Ok(Ok(stream)) = time::timeout(Duration::from_secs(10), async { TcpStream::connect(&addr).await.map(|s| s.into_std().unwrap()) }).await {
Some(setup_outbound(peer_manager, event_notify, their_node_id, stream))
} else { None }
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["winbase"] }
-[dev-dependencies.bitcoin]
-version = "0.26"
-features = ["bitcoinconsensus"]
-
[dev-dependencies]
lightning = { version = "0.0.13", path = "../lightning", features = ["_test_utils"] }
check_persisted_data!(0);
// Send a few payments and make sure the monitors are updated to the latest.
- send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000, 8_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
check_persisted_data!(5);
- send_payment(&nodes[1], &vec!(&nodes[0])[..], 4000000, 4_000_000);
+ send_payment(&nodes[1], &vec!(&nodes[0])[..], 4000000);
check_persisted_data!(10);
// Force close because cooperative close doesn't result in any persisted
allow_wallclock_use = []
fuzztarget = ["bitcoin/fuzztarget", "regex"]
# Internal test utilities exposed to other repo crates
-_test_utils = ["hex", "regex"]
+_test_utils = ["hex", "regex", "bitcoin/bitcoinconsensus"]
# Unlog messages superior at targeted level.
max_level_off = []
max_level_error = []
hex = { version = "0.3", optional = true }
regex = { version = "0.1.80", optional = true }
-[dev-dependencies.bitcoin]
-version = "0.26"
-features = ["bitcoinconsensus"]
-
[dev-dependencies]
hex = "0.3"
regex = "0.1.80"
+[dev-dependencies.bitcoin]
+version = "0.26"
+features = ["bitcoinconsensus"]
+
[package.metadata.docs.rs]
features = ["allow_wallclock_use"] # When https://github.com/rust-lang/rust/issues/43781 complies with our MSVR, we can add nice banners in the docs for the methods behind this feature-gate.
use bitcoin::blockdata::transaction::Transaction;
/// An interface to send a transaction to the Bitcoin network.
-pub trait BroadcasterInterface: Sync + Send {
+pub trait BroadcasterInterface {
/// Sends a transaction out to (hopefully) be mined.
fn broadcast_transaction(&self, tx: &Transaction);
}
///
/// Note that all of the functions implemented here *must* be reentrant-safe (obviously - they're
/// called from inside the library in response to chain events, P2P events, or timer events).
-pub trait FeeEstimator: Sync + Send {
+pub trait FeeEstimator {
/// Gets estimated satoshis of fee required per 1000 Weight-Units.
///
/// Must be no smaller than 253 (ie 1 satoshi-per-byte rounded up to ensure later round-downs
impl<ChannelSigner: Sign, C: Deref, T: Deref, F: Deref, L: Deref, P: Deref>
chain::Listen for ChainMonitor<ChannelSigner, C, T, F, L, P>
where
- ChannelSigner: Sign,
C::Target: chain::Filter,
T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
impl<ChannelSigner: Sign, C: Deref, T: Deref, F: Deref, L: Deref, P: Deref>
chain::Confirm for ChainMonitor<ChannelSigner, C, T, F, L, P>
where
- ChannelSigner: Sign,
C::Target: chain::Filter,
T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
}
}
-impl<ChannelSigner: Sign, C: Deref + Sync + Send, T: Deref + Sync + Send, F: Deref + Sync + Send, L: Deref + Sync + Send, P: Deref + Sync + Send>
+impl<ChannelSigner: Sign, C: Deref , T: Deref , F: Deref , L: Deref , P: Deref >
chain::Watch<ChannelSigner> for ChainMonitor<ChannelSigner, C, T, F, L, P>
where C::Target: chain::Filter,
T::Target: BroadcasterInterface,
let (commitment_tx, htlc_tx) = {
let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 5_000_000).0;
let mut txn = get_local_commitment_txn!(nodes[0], channel.2);
- claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage, 5_000_000);
+ claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage);
assert_eq!(txn.len(), 2);
(txn.remove(0), txn.remove(0))
use bitcoin::secp256k1::key::{SecretKey,PublicKey};
use bitcoin::secp256k1;
+use ln::{PaymentHash, PaymentPreimage};
use ln::msgs::DecodeError;
use ln::chan_utils;
use ln::chan_utils::{CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLCType, ChannelTransactionParameters, HolderCommitmentTransaction};
-use ln::channelmanager::{BestBlock, HTLCSource, PaymentPreimage, PaymentHash};
+use ln::channelmanager::{BestBlock, HTLCSource};
use ln::onchaintx::{OnchainTxHandler, InputDescriptors};
use chain;
use chain::WatchedOutput;
/// transaction and losing money. This is a risk because previous channel states
/// are toxic, so it's important that whatever channel state is persisted is
/// kept up-to-date.
-pub trait Persist<ChannelSigner: Sign>: Send + Sync {
+pub trait Persist<ChannelSigner: Sign> {
/// Persist a new channel's data. The data can be stored any way you want, but
/// the identifier provided by Rust-Lightning is the channel's outpoint (and
/// it is up to you to maintain a correct mapping between the outpoint and the
use hex;
use chain::channelmonitor::ChannelMonitor;
use chain::transaction::OutPoint;
- use ln::channelmanager::{BestBlock, PaymentPreimage, PaymentHash};
+ use ln::{PaymentPreimage, PaymentHash};
+ use ln::channelmanager::BestBlock;
use ln::onchaintx::{OnchainTxHandler, InputDescriptors};
use ln::chan_utils;
use ln::chan_utils::{HTLCOutputInCommitment, ChannelPublicKeys, ChannelTransactionParameters, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters};
use bitcoin::secp256k1::key::{SecretKey, PublicKey};
use bitcoin::secp256k1::{Secp256k1, Signature, Signing};
+use bitcoin::secp256k1::recovery::RecoverableSignature;
use bitcoin::secp256k1;
use util::{byte_utils, transaction_utils};
/// of LN security model, orthogonal of key management issues.
// TODO: We should remove Clone by instead requesting a new Sign copy when we create
// ChannelMonitors instead of expecting to clone the one out of the Channel into the monitors.
-pub trait BaseSign : Send {
+pub trait BaseSign {
/// Gets the per-commitment point for a specific commitment number
///
/// Note that the commitment number starts at (1 << 48) - 1 and counts backwards.
}
/// A trait to describe an object which can get user secrets and key material.
-pub trait KeysInterface: Send + Sync {
+pub trait KeysInterface {
/// A type which implements Sign which will be returned by get_channel_signer.
type Signer : Sign;
/// contain no versioning scheme. You may wish to include your own version prefix and ensure
/// you've read all of the provided bytes to ensure no corruption occurred.
fn read_chan_signer(&self, reader: &[u8]) -> Result<Self::Signer, DecodeError>;
+
+ /// Sign an invoice's preimage (note that this is the preimage of the invoice, not the HTLC's
+ /// preimage). By parameterizing by the preimage instead of the hash, we allow implementors of
+ /// this trait to parse the invoice and make sure they're signing what they expect, rather than
+ /// blindly signing the hash.
+ fn sign_invoice(&self, invoice_preimage: Vec<u8>) -> Result<RecoverableSignature, ()>;
}
#[derive(Clone)]
fn read_chan_signer(&self, reader: &[u8]) -> Result<Self::Signer, DecodeError> {
InMemorySigner::read(&mut std::io::Cursor::new(reader))
}
+
+ fn sign_invoice(&self, invoice_preimage: Vec<u8>) -> Result<RecoverableSignature, ()> {
+ Ok(self.secp_ctx.sign_recoverable(&hash_to_message!(&Sha256::hash(&invoice_preimage)), &self.get_node_secret()))
+ }
}
// Ensure that BaseSign can have a vtable
/// The `Access` trait defines behavior for accessing chain data and state, such as blocks and
/// UTXOs.
-pub trait Access: Send + Sync {
+pub trait Access {
/// Returns the transaction output of a funding transaction encoded by [`short_channel_id`].
/// Returns an error if `genesis_hash` is for a different chain or if such a transaction output
/// is unknown.
/// in the event of a chain reorganization, it must not be called with a `header` that is no
/// longer in the chain as of the last call to [`best_block_updated`].
///
- /// [chain order]: Self#order
+ /// [chain order]: Confirm#Order
/// [`best_block_updated`]: Self::best_block_updated
fn transactions_confirmed(&self, header: &BlockHeader, txdata: &TransactionData, height: u32);
/// [`ChannelMonitor`]: channelmonitor::ChannelMonitor
/// [`ChannelMonitorUpdateErr`]: channelmonitor::ChannelMonitorUpdateErr
/// [`PermanentFailure`]: channelmonitor::ChannelMonitorUpdateErr::PermanentFailure
-pub trait Watch<ChannelSigner: Sign>: Send + Sync {
+pub trait Watch<ChannelSigner: Sign> {
/// Watches a channel identified by `funding_txo` using `monitor`.
///
/// Implementations are responsible for watching the chain for the funding transaction along
/// [`TemporaryFailure`]: channelmonitor::ChannelMonitorUpdateErr::TemporaryFailure
/// [BIP 157]: https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki
/// [BIP 158]: https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki
-pub trait Filter: Send + Sync {
+pub trait Filter {
/// Registers interest in a transaction with `txid` and having an output with `script_pubkey` as
/// a spending condition.
fn register_tx(&self, txid: &Txid, script_pubkey: &Script);
use bitcoin::hashes::ripemd160::Hash as Ripemd160;
use bitcoin::hash_types::{Txid, PubkeyHash};
-use ln::channelmanager::{PaymentHash, PaymentPreimage};
+use ln::{PaymentHash, PaymentPreimage};
use ln::msgs::DecodeError;
use util::ser::{Readable, Writeable, Writer, MAX_BUF_SIZE};
use util::byte_utils;
use std::ops::Deref;
use chain;
+// Maximum size of a serialized HTLCOutputInCommitment
const HTLC_OUTPUT_IN_COMMITMENT_SIZE: usize = 1 + 8 + 4 + 32 + 5;
pub(crate) const MAX_HTLCS: u16 = 483;
/// Broadcaster's Payment Key (which isn't allowed to be spent from for some delay)
pub broadcaster_delayed_payment_key: PublicKey,
}
-impl_writeable!(TxCreationKeys, 33*6,
+
+impl_writeable!(TxCreationKeys, 33*5,
{ per_commitment_point, revocation_key, broadcaster_htlc_key, countersignatory_htlc_key, broadcaster_delayed_payment_key });
/// One counterparty's public keys which do not change over the life of a channel.
pub transaction_output_index: Option<u32>,
}
-impl_writeable!(HTLCOutputInCommitment, HTLC_OUTPUT_IN_COMMITMENT_SIZE, {
+impl_writeable_len_match!(HTLCOutputInCommitment, {
+ { HTLCOutputInCommitment { transaction_output_index: None, .. }, HTLC_OUTPUT_IN_COMMITMENT_SIZE - 4 },
+ { _, HTLC_OUTPUT_IN_COMMITMENT_SIZE }
+ }, {
offered,
amount_msat,
cltv_expiry,
use chain::transaction::OutPoint;
use chain::Listen;
use chain::Watch;
-use ln::channelmanager::{RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSecret, PaymentSendFailure};
-use ln::features::InitFeatures;
+use ln::{PaymentPreimage, PaymentHash};
+use ln::channelmanager::{RAACommitmentOrder, PaymentSendFailure};
+use ln::features::{InitFeatures, InvoiceFeatures};
use ln::msgs;
use ln::msgs::{ChannelMessageHandler, ErrorAction, RoutingMessageHandler};
use routing::router::get_route;
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
let logger = test_utils::TestLogger::new();
- let (_, payment_hash_1) = get_payment_preimage_hash!(&nodes[0]);
+ let (_, payment_hash_1, payment_secret_1) = get_payment_preimage_hash!(&nodes[1]);
match persister_fail {
true => chanmon_cfgs[0].persister.set_update_ret(Err(ChannelMonitorUpdateErr::PermanentFailure)),
false => *nodes[0].chain_monitor.update_ret.lock().unwrap() = Some(Err(ChannelMonitorUpdateErr::PermanentFailure))
}
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- unwrap_send_err!(nodes[0].node.send_payment(&route, payment_hash_1, &None), true, APIError::ChannelUnavailable {..}, {});
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ unwrap_send_err!(nodes[0].node.send_payment(&route, payment_hash_1, &Some(payment_secret_1)), true, APIError::ChannelUnavailable {..}, {});
check_added_monitors!(nodes[0], 2);
let events_1 = nodes[0].node.get_and_clear_pending_msg_events();
let outpoint = OutPoint { txid: chan.3.txid(), index: 0 };
// Rebalance the network to generate htlc in the two directions
- send_payment(&nodes[0], &vec!(&nodes[1])[..], 10_000_000, 10_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1])[..], 10_000_000);
// Route an HTLC from node 0 to node 1 (but don't settle)
let preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9_000_000).0;
persister.set_update_ret(Err(ChannelMonitorUpdateErr::TemporaryFailure));
// Try to update ChannelMonitor
- assert!(nodes[1].node.claim_funds(preimage, &None, 9_000_000));
+ assert!(nodes[1].node.claim_funds(preimage));
check_added_monitors!(nodes[1], 1);
let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
assert_eq!(updates.update_fulfill_htlcs.len(), 1);
let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
let logger = test_utils::TestLogger::new();
- let (payment_preimage_1, payment_hash_1) = get_payment_preimage_hash!(&nodes[0]);
+ let (payment_preimage_1, payment_hash_1, payment_secret_1) = get_payment_preimage_hash!(&nodes[1]);
match persister_fail {
true => chanmon_cfgs[0].persister.set_update_ret(Err(ChannelMonitorUpdateErr::TemporaryFailure)),
{
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- unwrap_send_err!(nodes[0].node.send_payment(&route, payment_hash_1, &None), false, APIError::MonitorUpdateFailed, {});
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ unwrap_send_err!(nodes[0].node.send_payment(&route, payment_hash_1, &Some(payment_secret_1)), false, APIError::MonitorUpdateFailed, {});
check_added_monitors!(nodes[0], 1);
}
let events_3 = nodes[1].node.get_and_clear_pending_events();
assert_eq!(events_3.len(), 1);
match events_3[0] {
- Event::PaymentReceived { ref payment_hash, ref payment_secret, amt } => {
+ Event::PaymentReceived { ref payment_hash, ref payment_preimage, ref payment_secret, amt, user_payment_id: _ } => {
assert_eq!(payment_hash_1, *payment_hash);
- assert_eq!(*payment_secret, None);
+ assert!(payment_preimage.is_none());
+ assert_eq!(payment_secret_1, *payment_secret);
assert_eq!(amt, 1000000);
},
_ => panic!("Unexpected event"),
}
- claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_1, 1_000_000);
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_1);
// Now set it to failed again...
- let (_, payment_hash_2) = get_payment_preimage_hash!(&nodes[0]);
+ let (_, payment_hash_2, payment_secret_2) = get_payment_preimage_hash!(&nodes[1]);
{
match persister_fail {
true => chanmon_cfgs[0].persister.set_update_ret(Err(ChannelMonitorUpdateErr::TemporaryFailure)),
false => *nodes[0].chain_monitor.update_ret.lock().unwrap() = Some(Err(ChannelMonitorUpdateErr::TemporaryFailure))
}
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- unwrap_send_err!(nodes[0].node.send_payment(&route, payment_hash_2, &None), false, APIError::MonitorUpdateFailed, {});
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ unwrap_send_err!(nodes[0].node.send_payment(&route, payment_hash_2, &Some(payment_secret_2)), false, APIError::MonitorUpdateFailed, {});
check_added_monitors!(nodes[0], 1);
}
let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
let logger = test_utils::TestLogger::new();
- let (payment_preimage_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
+ let (payment_preimage_1, _, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
// Now try to send a second payment which will fail to send
- let (payment_preimage_2, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
+ let (payment_preimage_2, payment_hash_2, payment_secret_2) = get_payment_preimage_hash!(nodes[1]);
{
*nodes[0].chain_monitor.update_ret.lock().unwrap() = Some(Err(ChannelMonitorUpdateErr::TemporaryFailure));
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- unwrap_send_err!(nodes[0].node.send_payment(&route, payment_hash_2, &None), false, APIError::MonitorUpdateFailed, {});
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ unwrap_send_err!(nodes[0].node.send_payment(&route, payment_hash_2, &Some(payment_secret_2)), false, APIError::MonitorUpdateFailed, {});
check_added_monitors!(nodes[0], 1);
}
// Claim the previous payment, which will result in a update_fulfill_htlc/CS from nodes[1]
// but nodes[0] won't respond since it is frozen.
- assert!(nodes[1].node.claim_funds(payment_preimage_1, &None, 1_000_000));
+ assert!(nodes[1].node.claim_funds(payment_preimage_1));
check_added_monitors!(nodes[1], 1);
let events_2 = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(events_2.len(), 1);
let events_5 = nodes[1].node.get_and_clear_pending_events();
assert_eq!(events_5.len(), 1);
match events_5[0] {
- Event::PaymentReceived { ref payment_hash, ref payment_secret, amt } => {
+ Event::PaymentReceived { ref payment_hash, ref payment_preimage, ref payment_secret, amt, user_payment_id: _ } => {
assert_eq!(payment_hash_2, *payment_hash);
- assert_eq!(*payment_secret, None);
+ assert!(payment_preimage.is_none());
+ assert_eq!(payment_secret_2, *payment_secret);
assert_eq!(amt, 1000000);
},
_ => panic!("Unexpected event"),
}
- claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_2, 1_000_000);
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_2);
}
#[test]
let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
let logger = test_utils::TestLogger::new();
- let (payment_preimage, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (payment_preimage, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[1]);
{
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
}
let events = nodes[1].node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
match events[0] {
- Event::PaymentReceived { payment_hash, payment_secret, amt } => {
+ Event::PaymentReceived { payment_hash, payment_preimage, payment_secret, amt, user_payment_id: _ } => {
assert_eq!(payment_hash, our_payment_hash);
- assert_eq!(payment_secret, None);
+ assert!(payment_preimage.is_none());
+ assert_eq!(our_payment_secret, payment_secret);
assert_eq!(amt, 1000000);
},
_ => panic!("Unexpected event"),
};
- claim_payment(&nodes[0], &[&nodes[1]], payment_preimage, 1_000_000);
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage);
}
#[test]
let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
let logger = test_utils::TestLogger::new();
- let (payment_preimage_1, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (payment_preimage_1, our_payment_hash, payment_secret_1) = get_payment_preimage_hash!(nodes[1]);
{
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(payment_secret_1)).unwrap();
check_added_monitors!(nodes[0], 1);
}
_ => panic!("Unexpected event"),
}
- claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_1, 1_000_000);
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_1);
}
#[test]
let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
let logger = test_utils::TestLogger::new();
- send_payment(&nodes[0], &[&nodes[1]], 5000000, 5_000_000);
- let (payment_preimage_1, our_payment_hash_1) = get_payment_preimage_hash!(nodes[0]);
+ send_payment(&nodes[0], &[&nodes[1]], 5000000);
+ let (payment_preimage_1, our_payment_hash_1, our_payment_secret_1) = get_payment_preimage_hash!(nodes[1]);
{
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, our_payment_hash_1, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash_1, &Some(our_payment_secret_1)).unwrap();
check_added_monitors!(nodes[0], 1);
}
let send_event_1 = SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0));
- let (payment_preimage_2, our_payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
+ let (payment_preimage_2, our_payment_hash_2, our_payment_secret_2) = get_payment_preimage_hash!(nodes[0]);
{
let net_graph_msg_handler = &nodes[1].net_graph_msg_handler;
- let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[1].node.send_payment(&route, our_payment_hash_2, &None).unwrap();
+ let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[1].node.send_payment(&route, our_payment_hash_2, &Some(our_payment_secret_2)).unwrap();
check_added_monitors!(nodes[1], 1);
}
let send_event_2 = SendEvent::from_event(nodes[1].node.get_and_clear_pending_msg_events().remove(0));
nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_second_raa);
check_added_monitors!(nodes[0], 1);
expect_pending_htlcs_forwardable!(nodes[0]);
- expect_payment_received!(nodes[0], our_payment_hash_2, 1000000);
+ expect_payment_received!(nodes[0], our_payment_hash_2, our_payment_secret_2, 1000000);
nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_second_raa);
check_added_monitors!(nodes[1], 1);
expect_pending_htlcs_forwardable!(nodes[1]);
- expect_payment_received!(nodes[1], our_payment_hash_1, 1000000);
+ expect_payment_received!(nodes[1], our_payment_hash_1, our_payment_secret_1, 1000000);
- claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_1, 1_000_000);
- claim_payment(&nodes[1], &[&nodes[0]], payment_preimage_2, 1_000_000);
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_1);
+ claim_payment(&nodes[1], &[&nodes[0]], payment_preimage_2);
}
fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) {
let logger = test_utils::TestLogger::new();
// Rebalance a bit so that we can send backwards from 2 to 1.
- send_payment(&nodes[0], &[&nodes[1], &nodes[2]], 5000000, 5_000_000);
+ send_payment(&nodes[0], &[&nodes[1], &nodes[2]], 5000000);
// Route a first payment that we'll fail backwards
- let (_, payment_hash_1) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1000000);
+ let (_, payment_hash_1, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1000000);
// Fail the payment backwards, failing the monitor update on nodes[1]'s receipt of the RAA
- assert!(nodes[2].node.fail_htlc_backwards(&payment_hash_1, &None));
+ assert!(nodes[2].node.fail_htlc_backwards(&payment_hash_1));
expect_pending_htlcs_forwardable!(nodes[2]);
check_added_monitors!(nodes[2], 1);
// While the second channel is AwaitingRAA, forward a second payment to get it into the
// holding cell.
- let (payment_preimage_2, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
+ let (payment_preimage_2, payment_hash_2, payment_secret_2) = get_payment_preimage_hash!(nodes[2]);
{
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, payment_hash_2, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash_2, &Some(payment_secret_2)).unwrap();
check_added_monitors!(nodes[0], 1);
}
// Attempt to forward a third payment but fail due to the second channel being unavailable
// for forwarding.
- let (_, payment_hash_3) = get_payment_preimage_hash!(nodes[0]);
+ let (_, payment_hash_3, payment_secret_3) = get_payment_preimage_hash!(nodes[2]);
{
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, payment_hash_3, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash_3, &Some(payment_secret_3)).unwrap();
check_added_monitors!(nodes[0], 1);
}
let (payment_preimage_4, payment_hash_4) = if test_ignore_second_cs {
// Try to route another payment backwards from 2 to make sure 1 holds off on responding
- let (payment_preimage_4, payment_hash_4) = get_payment_preimage_hash!(nodes[0]);
+ let (payment_preimage_4, payment_hash_4, payment_secret_4) = get_payment_preimage_hash!(nodes[0]);
let net_graph_msg_handler = &nodes[2].net_graph_msg_handler;
- let route = get_route(&nodes[2].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[2].node.send_payment(&route, payment_hash_4, &None).unwrap();
+ let route = get_route(&nodes[2].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[2].node.send_payment(&route, payment_hash_4, &Some(payment_secret_4)).unwrap();
check_added_monitors!(nodes[2], 1);
send_event = SendEvent::from_event(nodes[2].node.get_and_clear_pending_msg_events().remove(0));
Event::PaymentReceived { payment_hash, .. } => assert_eq!(payment_hash, payment_hash_4.unwrap()),
_ => panic!("Unexpected event"),
};
- claim_payment(&nodes[2], &[&nodes[1], &nodes[0]], payment_preimage_4.unwrap(), 1_000_000);
+ claim_payment(&nodes[2], &[&nodes[1], &nodes[0]], payment_preimage_4.unwrap());
}
- claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage_2, 1_000_000);
+ claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage_2);
}
#[test]
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
- let (our_payment_preimage, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1000000);
+ let (our_payment_preimage, _, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1000000);
nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
- assert!(nodes[2].node.claim_funds(our_payment_preimage, &None, 1_000_000));
+ assert!(nodes[2].node.claim_funds(our_payment_preimage));
check_added_monitors!(nodes[2], 1);
let mut updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
assert!(updates.update_add_htlcs.is_empty());
let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;
let logger = test_utils::TestLogger::new();
- let (payment_preimage_1, payment_hash_1) = get_payment_preimage_hash!(nodes[0]);
- let (payment_preimage_2, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
- let (payment_preimage_3, payment_hash_3) = get_payment_preimage_hash!(nodes[0]);
+ let (payment_preimage_1, payment_hash_1, payment_secret_1) = get_payment_preimage_hash!(nodes[1]);
+ let (payment_preimage_2, payment_hash_2, payment_secret_2) = get_payment_preimage_hash!(nodes[1]);
+ let (payment_preimage_3, payment_hash_3, payment_secret_3) = get_payment_preimage_hash!(nodes[1]);
// Queue up two payments - one will be delivered right away, one immediately goes into the
// holding cell as nodes[0] is AwaitingRAA. Ultimately this allows us to deliver an RAA
// generation during RAA while in monitor-update-failed state.
{
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, payment_hash_1, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash_1, &Some(payment_secret_1)).unwrap();
check_added_monitors!(nodes[0], 1);
- nodes[0].node.send_payment(&route, payment_hash_2, &None).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash_2, &Some(payment_secret_2)).unwrap();
check_added_monitors!(nodes[0], 0);
}
check_added_monitors!(nodes[1], 0);
let bs_responses = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id());
expect_pending_htlcs_forwardable!(nodes[1]);
- expect_payment_received!(nodes[1], payment_hash_1, 1000000);
+ expect_payment_received!(nodes[1], payment_hash_1, payment_secret_1, 1000000);
// We send a third payment here, which is somewhat of a redundant test, but the
// chanmon_fail_consistency test required it to actually find the bug (by seeing out-of-sync
// commitment transaction states) whereas here we can explicitly check for it.
{
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, payment_hash_3, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash_3, &Some(payment_secret_3)).unwrap();
check_added_monitors!(nodes[0], 0);
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
}
nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_raa);
check_added_monitors!(nodes[1], 1);
expect_pending_htlcs_forwardable!(nodes[1]);
- expect_payment_received!(nodes[1], payment_hash_2, 1000000);
+ expect_payment_received!(nodes[1], payment_hash_2, payment_secret_2, 1000000);
let bs_update = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_raa);
nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_raa);
check_added_monitors!(nodes[1], 1);
expect_pending_htlcs_forwardable!(nodes[1]);
- expect_payment_received!(nodes[1], payment_hash_3, 1000000);
+ expect_payment_received!(nodes[1], payment_hash_3, payment_secret_3, 1000000);
- claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_1, 1_000_000);
- claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_2, 1_000_000);
- claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_3, 1_000_000);
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_1);
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_2);
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_3);
}
#[test]
let logger = test_utils::TestLogger::new();
// Forward a payment for B to claim
- let (payment_preimage_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
+ let (payment_preimage_1, _, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
- assert!(nodes[1].node.claim_funds(payment_preimage_1, &None, 1_000_000));
+ assert!(nodes[1].node.claim_funds(payment_preimage_1));
check_added_monitors!(nodes[1], 1);
nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
// Send a second payment from A to B, resulting in a commitment update that gets swallowed with
// the monitor still failed
- let (payment_preimage_2, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
+ let (payment_preimage_2, payment_hash_2, payment_secret_2) = get_payment_preimage_hash!(nodes[1]);
{
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, payment_hash_2, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash_2, &Some(payment_secret_2)).unwrap();
check_added_monitors!(nodes[0], 1);
}
check_added_monitors!(nodes[1], 1);
expect_pending_htlcs_forwardable!(nodes[1]);
- expect_payment_received!(nodes[1], payment_hash_2, 1000000);
+ expect_payment_received!(nodes[1], payment_hash_2, payment_secret_2, 1000000);
nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_raa);
check_added_monitors!(nodes[0], 1);
_ => panic!("Unexpected event"),
}
- claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_2, 1_000_000);
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_2);
}
#[test]
// Route the payment and deliver the initial commitment_signed (with a monitor update failure
// on receipt).
- let (payment_preimage_1, payment_hash_1) = get_payment_preimage_hash!(nodes[0]);
+ let (payment_preimage_1, payment_hash_1, payment_secret_1) = get_payment_preimage_hash!(nodes[1]);
{
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, payment_hash_1, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash_1, &Some(payment_secret_1)).unwrap();
check_added_monitors!(nodes[0], 1);
}
check_added_monitors!(nodes[1], 1);
expect_pending_htlcs_forwardable!(nodes[1]);
- expect_payment_received!(nodes[1], payment_hash_1, 1000000);
+ expect_payment_received!(nodes[1], payment_hash_1, payment_secret_1, 1000000);
- claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_1, 1_000_000);
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_1);
}
#[test]
// Route the first payment outbound, holding the last RAA for B until we are set up so that we
// can deliver it and fail the monitor update.
- let (payment_preimage_1, payment_hash_1) = get_payment_preimage_hash!(nodes[0]);
+ let (payment_preimage_1, payment_hash_1, payment_secret_1) = get_payment_preimage_hash!(nodes[1]);
{
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, payment_hash_1, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash_1, &Some(payment_secret_1)).unwrap();
check_added_monitors!(nodes[0], 1);
}
let as_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id());
// Route the second payment, generating an update_add_htlc/commitment_signed
- let (payment_preimage_2, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
+ let (payment_preimage_2, payment_hash_2, payment_secret_2) = get_payment_preimage_hash!(nodes[1]);
{
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, payment_hash_2, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash_2, &Some(payment_secret_2)).unwrap();
check_added_monitors!(nodes[0], 1);
}
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
check_added_monitors!(nodes[1], 0);
expect_pending_htlcs_forwardable!(nodes[1]);
- expect_payment_received!(nodes[1], payment_hash_1, 1000000);
+ expect_payment_received!(nodes[1], payment_hash_1, payment_secret_1, 1000000);
let bs_responses = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id());
nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_responses.0);
check_added_monitors!(nodes[1], 1);
expect_pending_htlcs_forwardable!(nodes[1]);
- expect_payment_received!(nodes[1], payment_hash_2, 1000000);
+ expect_payment_received!(nodes[1], payment_hash_2, payment_secret_2, 1000000);
- claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_1, 1_000_000);
- claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_2, 1_000_000);
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_1);
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_2);
}
#[test]
let logger = test_utils::TestLogger::new();
// Rebalance a bit so that we can send backwards from 3 to 2.
- send_payment(&nodes[0], &[&nodes[1], &nodes[2]], 5000000, 5_000_000);
+ send_payment(&nodes[0], &[&nodes[1], &nodes[2]], 5000000);
- let (payment_preimage_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
+ let (payment_preimage_1, _, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Some(Err(ChannelMonitorUpdateErr::TemporaryFailure));
- assert!(nodes[1].node.claim_funds(payment_preimage_1, &None, 1_000_000));
+ assert!(nodes[1].node.claim_funds(payment_preimage_1));
check_added_monitors!(nodes[1], 1);
- let (_, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
+ let (_, payment_hash_2, payment_secret_2) = get_payment_preimage_hash!(nodes[0]);
{
let net_graph_msg_handler = &nodes[2].net_graph_msg_handler;
- let route = get_route(&nodes[2].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[2].node.send_payment(&route, payment_hash_2, &None).unwrap();
+ let route = get_route(&nodes[2].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[2].node.send_payment(&route, payment_hash_2, &Some(payment_secret_2)).unwrap();
check_added_monitors!(nodes[2], 1);
}
let logger = test_utils::TestLogger::new();
// Rebalance a bit so that we can send backwards from 3 to 1.
- send_payment(&nodes[0], &[&nodes[1], &nodes[2]], 5000000, 5_000_000);
+ send_payment(&nodes[0], &[&nodes[1], &nodes[2]], 5000000);
- let (_, payment_hash_1) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1000000);
- assert!(nodes[2].node.fail_htlc_backwards(&payment_hash_1, &None));
+ let (_, payment_hash_1, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1000000);
+ assert!(nodes[2].node.fail_htlc_backwards(&payment_hash_1));
expect_pending_htlcs_forwardable!(nodes[2]);
check_added_monitors!(nodes[2], 1);
commitment_signed_dance!(nodes[1], nodes[2], cs_fail_update.commitment_signed, true, true);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
- let (payment_preimage_2, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
+ let (payment_preimage_2, payment_hash_2, payment_secret_2) = get_payment_preimage_hash!(nodes[0]);
{
let net_graph_msg_handler = &nodes[2].net_graph_msg_handler;
- let route = get_route(&nodes[2].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[2].node.send_payment(&route, payment_hash_2, &None).unwrap();
+ let route = get_route(&nodes[2].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[2].node.send_payment(&route, payment_hash_2, &Some(payment_secret_2)).unwrap();
check_added_monitors!(nodes[2], 1);
}
_ => panic!("Unexpected event"),
};
nodes[0].node.process_pending_htlc_forwards();
- expect_payment_received!(nodes[0], payment_hash_2, 1000000);
+ expect_payment_received!(nodes[0], payment_hash_2, payment_secret_2, 1000000);
- claim_payment(&nodes[2], &[&nodes[1], &nodes[0]], payment_preimage_2, 1_000_000);
+ claim_payment(&nodes[2], &[&nodes[1], &nodes[0]], payment_preimage_2);
}
#[test]
let logger = test_utils::TestLogger::new();
// Forward a payment for B to claim
- let (payment_preimage_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
+ let (payment_preimage_1, _, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
// Now start forwarding a second payment, skipping the last RAA so B is in AwaitingRAA
- let (payment_preimage_2, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
+ let (payment_preimage_2, payment_hash_2, payment_secret_2) = get_payment_preimage_hash!(nodes[1]);
{
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, payment_hash_2, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash_2, &Some(payment_secret_2)).unwrap();
check_added_monitors!(nodes[0], 1);
}
let as_raa = commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false, true, false, true);
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Some(Err(ChannelMonitorUpdateErr::TemporaryFailure));
- assert!(nodes[1].node.claim_funds(payment_preimage_1, &None, 1_000_000));
+ assert!(nodes[1].node.claim_funds(payment_preimage_1));
check_added_monitors!(nodes[1], 1);
let events = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 0);
nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_raa);
check_added_monitors!(nodes[1], 1);
expect_pending_htlcs_forwardable!(nodes[1]);
- expect_payment_received!(nodes[1], payment_hash_2, 1000000);
+ expect_payment_received!(nodes[1], payment_hash_2, payment_secret_2, 1000000);
let bs_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &bs_updates.update_fulfill_htlcs[0]);
_ => panic!("Unexpected event"),
}
- claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_2, 1_000_000);
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_2);
}
// confirm_a_first and restore_b_before_conf are wholly unrelated to earlier bools and
node.net_graph_msg_handler.handle_channel_update(&bs_update).unwrap();
}
- send_payment(&nodes[0], &[&nodes[1]], 8000000, 8_000_000);
+ send_payment(&nodes[0], &[&nodes[1]], 8000000);
close_channel(&nodes[0], &nodes[1], &channel_id, funding_tx, true);
}
let chan_4_id = create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
let logger = test_utils::TestLogger::new();
- let (payment_preimage, payment_hash) = get_payment_preimage_hash!(&nodes[0]);
- let payment_secret = PaymentSecret([0xdb; 32]);
- let mut route = get_route(&nodes[0].node.get_our_node_id(), &nodes[0].net_graph_msg_handler.network_graph.read().unwrap(), &nodes[3].node.get_our_node_id(), None, None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
+ let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!(&nodes[3]);
+ let mut route = get_route(&nodes[0].node.get_our_node_id(), &nodes[0].net_graph_msg_handler.network_graph.read().unwrap(), &nodes[3].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
// Set us up to take multiple routes, one 0 -> 1 -> 3 and one 0 -> 2 -> 3:
let path = route.paths[0].clone();
// Pass the first HTLC of the payment along to nodes[3].
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
- pass_along_path(&nodes[0], &[&nodes[1], &nodes[3]], 0, payment_hash.clone(), Some(payment_secret), events.pop().unwrap(), false);
+ pass_along_path(&nodes[0], &[&nodes[1], &nodes[3]], 0, payment_hash.clone(), payment_secret, events.pop().unwrap(), false);
// And check that, after we successfully update the monitor for chan_2 we can pass the second
// HTLC along to nodes[3] and claim the whole payment back to nodes[0].
nodes[0].node.channel_monitor_updated(&outpoint, latest_update);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
- pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], 200_000, payment_hash.clone(), Some(payment_secret), events.pop().unwrap(), true);
+ pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], 200_000, payment_hash.clone(), payment_secret, events.pop().unwrap(), true);
- claim_payment_along_route_with_secret(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage, Some(payment_secret), 200_000);
+ claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage);
}
use bitcoin::secp256k1::{Secp256k1,Signature};
use bitcoin::secp256k1;
+use ln::{PaymentPreimage, PaymentHash};
use ln::features::{ChannelFeatures, InitFeatures};
use ln::msgs;
use ln::msgs::{DecodeError, OptionalField, DataLossProtect};
-use ln::channelmanager::{BestBlock, PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT};
+use ln::channelmanager::{BestBlock, PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT};
use ln::chan_utils::{CounterpartyCommitmentSecrets, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys, CommitmentTransaction, HolderCommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, MAX_HTLCS, get_commitment_transaction_number_obscure_factor};
use ln::chan_utils;
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
use bitcoin::network::constants::Network;
use bitcoin::hashes::hex::FromHex;
use hex;
- use ln::channelmanager::{BestBlock, HTLCSource, PaymentPreimage, PaymentHash};
+ use ln::{PaymentPreimage, PaymentHash};
+ use ln::channelmanager::{BestBlock, HTLCSource};
use ln::channel::{Channel,InboundHTLCOutput,OutboundHTLCOutput,InboundHTLCState,OutboundHTLCState,HTLCOutputInCommitment,HTLCCandidate,HTLCInitiator,TxCreationKeys};
use ln::channel::MAX_FUNDING_SATOSHIS;
use ln::features::InitFeatures;
use bitcoin::secp256k1::{Secp256k1, Message, Signature, All};
use bitcoin::secp256k1::ffi::Signature as FFISignature;
use bitcoin::secp256k1::key::{SecretKey,PublicKey};
+ use bitcoin::secp256k1::recovery::RecoverableSignature;
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::hashes::Hash;
use bitcoin::hash_types::{Txid, WPubkeyHash};
}
fn get_secure_random_bytes(&self) -> [u8; 32] { [0; 32] }
fn read_chan_signer(&self, _data: &[u8]) -> Result<Self::Signer, DecodeError> { panic!(); }
+ fn sign_invoice(&self, _invoice_preimage: Vec<u8>) -> Result<RecoverableSignature, ()> { panic!(); }
}
fn public_from_secret_hex(secp_ctx: &Secp256k1<All>, hex: &str) -> PublicKey {
use chain::transaction::{OutPoint, TransactionData};
// Since this struct is returned in `list_channels` methods, expose it here in case users want to
// construct one themselves.
+use ln::{PaymentHash, PaymentPreimage, PaymentSecret};
pub use ln::channel::CounterpartyForwardingInfo;
use ln::channel::{Channel, ChannelError};
use ln::features::{InitFeatures, NodeFeatures};
use std::time::Duration;
#[cfg(any(test, feature = "allow_wallclock_use"))]
use std::time::Instant;
-use std::marker::{Sync, Send};
use std::ops::Deref;
use bitcoin::hashes::hex::ToHex;
short_channel_id: u64, // This should be NonZero<u64> eventually when we bump MSRV
},
Receive {
- payment_data: Option<msgs::FinalOnionHopData>,
+ payment_data: msgs::FinalOnionHopData,
incoming_cltv_expiry: u32, // Used to track when we should expire pending HTLCs that go unclaimed
},
}
struct ClaimableHTLC {
prev_hop: HTLCPreviousHopData,
value: u64,
- /// Filled in when the HTLC was received with a payment_secret packet, which contains a
- /// total_msat (which may differ from value if this is a Multi-Path Payment) and a
+ /// Contains a total_msat (which may differ from value if this is a Multi-Path Payment) and a
/// payment_secret which prevents path-probing attacks and can associate different HTLCs which
/// are part of the same payment.
- payment_data: Option<msgs::FinalOnionHopData>,
+ payment_data: msgs::FinalOnionHopData,
cltv_expiry: u32,
}
}
}
-/// payment_hash type, use to cross-lock hop
-/// (C-not exported) as we just use [u8; 32] directly
-#[derive(Hash, Copy, Clone, PartialEq, Eq, Debug)]
-pub struct PaymentHash(pub [u8;32]);
-/// payment_preimage type, use to route payment between hop
-/// (C-not exported) as we just use [u8; 32] directly
-#[derive(Hash, Copy, Clone, PartialEq, Eq, Debug)]
-pub struct PaymentPreimage(pub [u8;32]);
-/// payment_secret type, use to authenticate sender to the receiver and tie MPP HTLCs together
-/// (C-not exported) as we just use [u8; 32] directly
-#[derive(Hash, Copy, Clone, PartialEq, Eq, Debug)]
-pub struct PaymentSecret(pub [u8;32]);
-
type ShutdownResult = (Option<(OutPoint, ChannelMonitorUpdate)>, Vec<(HTLCSource, PaymentHash)>);
/// Error type returned across the channel_state mutex boundary. When an Err is generated for a
/// guarantees are made about the existence of a channel with the short id here, nor the short
/// ids in the PendingHTLCInfo!
pub(super) forward_htlcs: HashMap<u64, Vec<HTLCForwardInfo>>,
- /// (payment_hash, payment_secret) -> Vec<HTLCs> for tracking HTLCs that
- /// were to us and can be failed/claimed by the user
+ /// Map from payment hash to any HTLCs which are to us and can be failed/claimed by the user.
/// Note that while this is held in the same mutex as the channels themselves, no consistency
/// guarantees are made about the channels given here actually existing anymore by the time you
/// go to read them!
- claimable_htlcs: HashMap<(PaymentHash, Option<PaymentSecret>), Vec<ClaimableHTLC>>,
+ claimable_htlcs: HashMap<PaymentHash, Vec<ClaimableHTLC>>,
/// Messages to send to peers - pushed to in the same lock that they are generated in (except
/// for broadcast messages, where ordering isn't as strict).
pub(super) pending_msg_events: Vec<MessageSendEvent>,
latest_features: InitFeatures,
}
+/// Stores a PaymentSecret and any other data we may need to validate an inbound payment is
+/// actually ours and not some duplicate HTLC sent to us by a node along the route.
+///
+/// For users who don't want to bother doing their own payment preimage storage, we also store that
+/// here.
+struct PendingInboundPayment {
+ /// The payment secret that the sender must use for us to accept this payment
+ payment_secret: PaymentSecret,
+ /// Time at which this HTLC expires - blocks with a header time above this value will result in
+ /// this payment being removed.
+ expiry_time: u64,
+ /// Arbitrary identifier the user specifies (or not)
+ user_payment_id: u64,
+ // Other required attributes of the payment, optionally enforced:
+ payment_preimage: Option<PaymentPreimage>,
+ min_value_msat: Option<u64>,
+}
+
/// SimpleArcChannelManager is useful when you need a ChannelManager with a static lifetime, e.g.
/// when you're using lightning-net-tokio (since tokio::spawn requires parameters with static
/// lifetimes). Other times you can afford a reference, which is more efficient, in which case
pub(super) channel_state: Mutex<ChannelHolder<Signer>>,
#[cfg(not(any(test, feature = "_test_utils")))]
channel_state: Mutex<ChannelHolder<Signer>>,
+
+ /// Storage for PaymentSecrets and any requirements on future inbound payments before we will
+ /// expose them to users via a PaymentReceived event. HTLCs which do not meet the requirements
+ /// here are failed when we process them as pending-forwardable-HTLCs, and entries are removed
+ /// after we generate a PaymentReceived upon receipt of all MPP parts or when they time out.
+ /// Locked *after* channel_state.
+ pending_inbound_payments: Mutex<HashMap<PaymentHash, PendingInboundPayment>>,
+
our_network_key: SecretKey,
our_network_pubkey: PublicKey,
/// value increases strictly since we don't assume access to a time source.
last_node_announcement_serial: AtomicUsize,
+ /// The highest block timestamp we've seen, which is usually a good guess at the current time.
+ /// Assuming most miners are generating blocks with reasonable timestamps, this shouldn't be
+ /// very far in the past, and can only ever be up to two hours in the future.
+ highest_seen_timestamp: AtomicUsize,
+
/// The bulk of our storage will eventually be here (channels and message queues and the like).
/// If we are connected to a peer we always at least have an entry here, even if no channels
/// are currently open with that peer.
pub const MIN_CLTV_EXPIRY_DELTA: u16 = 6 * 6;
pub(super) const CLTV_FAR_FAR_AWAY: u32 = 6 * 24 * 7; //TODO?
+/// Minimum CLTV difference between the current block height and received inbound payments.
+/// Invoices generated for payment to us must set their `min_final_cltv_expiry` field to at least
+/// this value.
+pub const MIN_FINAL_CLTV_EXPIRY: u32 = HTLC_FAIL_BACK_BUFFER;
+
// Check that our CLTV_EXPIRY is at least CLTV_CLAIM_BUFFER + ANTI_REORG_DELAY + LATENCY_GRACE_PERIOD_BLOCKS,
// ie that if the next-hop peer fails the HTLC within
// LATENCY_GRACE_PERIOD_BLOCKS then we'll still have CLTV_CLAIM_BUFFER left to timeout it onchain,
claimable_htlcs: HashMap::new(),
pending_msg_events: Vec::new(),
}),
+ pending_inbound_payments: Mutex::new(HashMap::new()),
+
our_network_key: keys_manager.get_node_secret(),
our_network_pubkey: PublicKey::from_secret_key(&secp_ctx, &keys_manager.get_node_secret()),
secp_ctx,
last_node_announcement_serial: AtomicUsize::new(0),
+ highest_seen_timestamp: AtomicUsize::new(0),
per_peer_state: RwLock::new(HashMap::new()),
msgs::OnionHopDataFormat::FinalNode { payment_data } => payment_data,
};
+ if payment_data.is_none() {
+ return_err!("We require payment_secrets", 0x4000|0x2000|3, &[0;0]);
+ }
+
// Note that we could obviously respond immediately with an update_fulfill_htlc
// message, however that would leak that we are the recipient of this payment, so
// instead we stay symmetric with the forwarding case, only responding (after a
PendingHTLCStatus::Forward(PendingHTLCInfo {
routing: PendingHTLCRouting::Receive {
- payment_data,
+ payment_data: payment_data.unwrap(),
incoming_cltv_expiry: msg.cltv_expiry,
},
payment_hash: msg.payment_hash.clone(),
routing: PendingHTLCRouting::Receive { payment_data, incoming_cltv_expiry },
incoming_shared_secret, payment_hash, amt_to_forward, .. },
prev_funding_outpoint } => {
- let prev_hop = HTLCPreviousHopData {
- short_channel_id: prev_short_channel_id,
- outpoint: prev_funding_outpoint,
- htlc_id: prev_htlc_id,
- incoming_packet_shared_secret: incoming_shared_secret,
- };
-
- let mut total_value = 0;
- let payment_secret_opt =
- if let &Some(ref data) = &payment_data { Some(data.payment_secret.clone()) } else { None };
- let htlcs = channel_state.claimable_htlcs.entry((payment_hash, payment_secret_opt))
- .or_insert(Vec::new());
- htlcs.push(ClaimableHTLC {
- prev_hop,
+ let claimable_htlc = ClaimableHTLC {
+ prev_hop: HTLCPreviousHopData {
+ short_channel_id: prev_short_channel_id,
+ outpoint: prev_funding_outpoint,
+ htlc_id: prev_htlc_id,
+ incoming_packet_shared_secret: incoming_shared_secret,
+ },
value: amt_to_forward,
payment_data: payment_data.clone(),
cltv_expiry: incoming_cltv_expiry,
- });
- if let &Some(ref data) = &payment_data {
- for htlc in htlcs.iter() {
- total_value += htlc.value;
- if htlc.payment_data.as_ref().unwrap().total_msat != data.total_msat {
- total_value = msgs::MAX_VALUE_MSAT;
- }
- if total_value >= msgs::MAX_VALUE_MSAT { break; }
- }
- if total_value >= msgs::MAX_VALUE_MSAT || total_value > data.total_msat {
- for htlc in htlcs.iter() {
- let mut htlc_msat_height_data = byte_utils::be64_to_array(htlc.value).to_vec();
- htlc_msat_height_data.extend_from_slice(
- &byte_utils::be32_to_array(self.best_block.read().unwrap().height()),
- );
- failed_forwards.push((HTLCSource::PreviousHopData(HTLCPreviousHopData {
- short_channel_id: htlc.prev_hop.short_channel_id,
- outpoint: prev_funding_outpoint,
- htlc_id: htlc.prev_hop.htlc_id,
- incoming_packet_shared_secret: htlc.prev_hop.incoming_packet_shared_secret,
- }), payment_hash,
- HTLCFailReason::Reason { failure_code: 0x4000 | 15, data: htlc_msat_height_data }
- ));
- }
- } else if total_value == data.total_msat {
- new_events.push(events::Event::PaymentReceived {
- payment_hash,
- payment_secret: Some(data.payment_secret),
- amt: total_value,
- });
+ };
+
+ macro_rules! fail_htlc {
+ ($htlc: expr) => {
+ let mut htlc_msat_height_data = byte_utils::be64_to_array($htlc.value).to_vec();
+ htlc_msat_height_data.extend_from_slice(
+ &byte_utils::be32_to_array(self.best_block.read().unwrap().height()),
+ );
+ failed_forwards.push((HTLCSource::PreviousHopData(HTLCPreviousHopData {
+ short_channel_id: $htlc.prev_hop.short_channel_id,
+ outpoint: prev_funding_outpoint,
+ htlc_id: $htlc.prev_hop.htlc_id,
+ incoming_packet_shared_secret: $htlc.prev_hop.incoming_packet_shared_secret,
+ }), payment_hash,
+ HTLCFailReason::Reason { failure_code: 0x4000 | 15, data: htlc_msat_height_data }
+ ));
}
- } else {
- new_events.push(events::Event::PaymentReceived {
- payment_hash,
- payment_secret: None,
- amt: amt_to_forward,
- });
}
+
+ // Check that the payment hash and secret are known. Note that we
+ // MUST take care to handle the "unknown payment hash" and
+ // "incorrect payment secret" cases here identically or we'd expose
+ // that we are the ultimate recipient of the given payment hash.
+ // Further, we must not expose whether we have any other HTLCs
+ // associated with the same payment_hash pending or not.
+ let mut payment_secrets = self.pending_inbound_payments.lock().unwrap();
+ match payment_secrets.entry(payment_hash) {
+ hash_map::Entry::Vacant(_) => {
+ log_trace!(self.logger, "Failing new HTLC with payment_hash {} as we didn't have a corresponding inbound payment.", log_bytes!(payment_hash.0));
+ fail_htlc!(claimable_htlc);
+ },
+ hash_map::Entry::Occupied(inbound_payment) => {
+ if inbound_payment.get().payment_secret != payment_data.payment_secret {
+ log_trace!(self.logger, "Failing new HTLC with payment_hash {} as it didn't match our expected payment secret.", log_bytes!(payment_hash.0));
+ fail_htlc!(claimable_htlc);
+ } else if inbound_payment.get().min_value_msat.is_some() && payment_data.total_msat < inbound_payment.get().min_value_msat.unwrap() {
+ log_trace!(self.logger, "Failing new HTLC with payment_hash {} as it didn't match our minimum value (had {}, needed {}).",
+ log_bytes!(payment_hash.0), payment_data.total_msat, inbound_payment.get().min_value_msat.unwrap());
+ fail_htlc!(claimable_htlc);
+ } else {
+ let mut total_value = 0;
+ let htlcs = channel_state.claimable_htlcs.entry(payment_hash)
+ .or_insert(Vec::new());
+ htlcs.push(claimable_htlc);
+ for htlc in htlcs.iter() {
+ total_value += htlc.value;
+ if htlc.payment_data.total_msat != payment_data.total_msat {
+ log_trace!(self.logger, "Failing HTLCs with payment_hash {} as the HTLCs had inconsistent total values (eg {} and {})",
+ log_bytes!(payment_hash.0), payment_data.total_msat, htlc.payment_data.total_msat);
+ total_value = msgs::MAX_VALUE_MSAT;
+ }
+ if total_value >= msgs::MAX_VALUE_MSAT { break; }
+ }
+ if total_value >= msgs::MAX_VALUE_MSAT || total_value > payment_data.total_msat {
+ log_trace!(self.logger, "Failing HTLCs with payment_hash {} as the total value {} ran over expected value {} (or HTLCs were inconsistent)",
+ log_bytes!(payment_hash.0), total_value, payment_data.total_msat);
+ for htlc in htlcs.iter() {
+ fail_htlc!(htlc);
+ }
+ } else if total_value == payment_data.total_msat {
+ new_events.push(events::Event::PaymentReceived {
+ payment_hash,
+ payment_preimage: inbound_payment.get().payment_preimage,
+ payment_secret: payment_data.payment_secret,
+ amt: total_value,
+ user_payment_id: inbound_payment.get().user_payment_id,
+ });
+ // Only ever generate at most one PaymentReceived
+ // per registered payment_hash, even if it isn't
+ // claimed.
+ inbound_payment.remove_entry();
+ } else {
+ // Nothing to do - we haven't reached the total
+ // payment value yet, wait until we receive more
+ // MPP parts.
+ }
+ }
+ },
+ };
},
HTLCForwardInfo::AddHTLC { .. } => {
panic!("short_channel_id == 0 should imply any pending_forward entries are of type Receive");
/// along the path (including in our own channel on which we received it).
/// Returns false if no payment was found to fail backwards, true if the process of failing the
/// HTLC backwards has been started.
- pub fn fail_htlc_backwards(&self, payment_hash: &PaymentHash, payment_secret: &Option<PaymentSecret>) -> bool {
+ pub fn fail_htlc_backwards(&self, payment_hash: &PaymentHash) -> bool {
let _persistence_guard = PersistenceNotifierGuard::new(&self.total_consistency_lock, &self.persistence_notifier);
let mut channel_state = Some(self.channel_state.lock().unwrap());
- let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(&(*payment_hash, *payment_secret));
+ let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(payment_hash);
if let Some(mut sources) = removed_source {
for htlc in sources.drain(..) {
if channel_state.is_none() { channel_state = Some(self.channel_state.lock().unwrap()); }
/// generating message events for the net layer to claim the payment, if possible. Thus, you
/// should probably kick the net layer to go send messages if this returns true!
///
- /// You must specify the expected amounts for this HTLC, and we will only claim HTLCs
- /// available within a few percent of the expected amount. This is critical for several
- /// reasons : a) it avoids providing senders with `proof-of-payment` (in the form of the
- /// payment_preimage without having provided the full value and b) it avoids certain
- /// privacy-breaking recipient-probing attacks which may reveal payment activity to
- /// motivated attackers.
- ///
- /// Note that the privacy concerns in (b) are not relevant in payments with a payment_secret
- /// set. Thus, for such payments we will claim any payments which do not under-pay.
+ /// Note that if you did not set an `amount_msat` when calling [`create_inbound_payment`] or
+ /// [`create_inbound_payment_for_hash`] you must check that the amount in the `PaymentReceived`
+ /// event matches your expectation. If you fail to do so and call this method, you may provide
+ /// the sender "proof-of-payment" when they did not fulfill the full expected payment.
///
/// May panic if called except in response to a PaymentReceived event.
- pub fn claim_funds(&self, payment_preimage: PaymentPreimage, payment_secret: &Option<PaymentSecret>, expected_amount: u64) -> bool {
+ ///
+ /// [`create_inbound_payment`]: Self::create_inbound_payment
+ /// [`create_inbound_payment_for_hash`]: Self::create_inbound_payment_for_hash
+ pub fn claim_funds(&self, payment_preimage: PaymentPreimage) -> bool {
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
let _persistence_guard = PersistenceNotifierGuard::new(&self.total_consistency_lock, &self.persistence_notifier);
let mut channel_state = Some(self.channel_state.lock().unwrap());
- let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(&(payment_hash, *payment_secret));
+ let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(&payment_hash);
if let Some(mut sources) = removed_source {
assert!(!sources.is_empty());
// we got all the HTLCs and then a channel closed while we were waiting for the user to
// provide the preimage, so worrying too much about the optimal handling isn't worth
// it.
-
- let (is_mpp, mut valid_mpp) = if let &Some(ref data) = &sources[0].payment_data {
- assert!(payment_secret.is_some());
- (true, data.total_msat >= expected_amount)
- } else {
- assert!(payment_secret.is_none());
- (false, false)
- };
-
+ let mut valid_mpp = true;
for htlc in sources.iter() {
- if !is_mpp || !valid_mpp { break; }
if let None = channel_state.as_ref().unwrap().short_to_id.get(&htlc.prev_hop.short_channel_id) {
valid_mpp = false;
+ break;
}
}
let mut errs = Vec::new();
let mut claimed_any_htlcs = false;
for htlc in sources.drain(..) {
- if channel_state.is_none() { channel_state = Some(self.channel_state.lock().unwrap()); }
- if (is_mpp && !valid_mpp) || (!is_mpp && (htlc.value < expected_amount || htlc.value > expected_amount * 2)) {
+ if !valid_mpp {
+ if channel_state.is_none() { channel_state = Some(self.channel_state.lock().unwrap()); }
let mut htlc_msat_height_data = byte_utils::be64_to_array(htlc.value).to_vec();
htlc_msat_height_data.extend_from_slice(&byte_utils::be32_to_array(
self.best_block.read().unwrap().height()));
claimed_any_htlcs = true;
} else { errs.push(e); }
},
- Err(None) if is_mpp => unreachable!("We already checked for channel existence, we can't fail here!"),
- Err(None) => {
- log_warn!(self.logger, "Channel we expected to claim an HTLC from was closed.");
- },
+ Err(None) => unreachable!("We already checked for channel existence, we can't fail here!"),
Ok(()) => claimed_any_htlcs = true,
}
}
self.finish_force_close_channel(failure);
}
}
+
+ fn set_payment_hash_secret_map(&self, payment_hash: PaymentHash, payment_preimage: Option<PaymentPreimage>, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32, user_payment_id: u64) -> Result<PaymentSecret, APIError> {
+ assert!(invoice_expiry_delta_secs <= 60*60*24*365); // Sadly bitcoin timestamps are u32s, so panic before 2106
+
+ let payment_secret = PaymentSecret(self.keys_manager.get_secure_random_bytes());
+
+ let _persistence_guard = PersistenceNotifierGuard::new(&self.total_consistency_lock, &self.persistence_notifier);
+ let mut payment_secrets = self.pending_inbound_payments.lock().unwrap();
+ match payment_secrets.entry(payment_hash) {
+ hash_map::Entry::Vacant(e) => {
+ e.insert(PendingInboundPayment {
+ payment_secret, min_value_msat, user_payment_id, payment_preimage,
+ // We assume that highest_seen_timestamp is pretty close to the current time -
+ // its updated when we receive a new block with the maximum time we've seen in
+ // a header. It should never be more than two hours in the future.
+ // Thus, we add two hours here as a buffer to ensure we absolutely
+ // never fail a payment too early.
+ // Note that we assume that received blocks have reasonably up-to-date
+ // timestamps.
+ expiry_time: self.highest_seen_timestamp.load(Ordering::Acquire) as u64 + invoice_expiry_delta_secs as u64 + 7200,
+ });
+ },
+ hash_map::Entry::Occupied(_) => return Err(APIError::APIMisuseError { err: "Duplicate payment hash".to_owned() }),
+ }
+ Ok(payment_secret)
+ }
+
+ /// Gets a payment secret and payment hash for use in an invoice given to a third party wishing
+ /// to pay us.
+ ///
+ /// This differs from [`create_inbound_payment_for_hash`] only in that it generates the
+ /// [`PaymentHash`] and [`PaymentPreimage`] for you, returning the first and storing the second.
+ ///
+ /// The [`PaymentPreimage`] will ultimately be returned to you in the [`PaymentReceived`], which
+ /// will have the [`PaymentReceived::payment_preimage`] field filled in. That should then be
+ /// passed directly to [`claim_funds`].
+ ///
+ /// See [`create_inbound_payment_for_hash`] for detailed documentation on behavior and requirements.
+ ///
+ /// [`claim_funds`]: Self::claim_funds
+ /// [`PaymentReceived`]: events::Event::PaymentReceived
+ /// [`PaymentReceived::payment_preimage`]: events::Event::PaymentReceived::payment_preimage
+ /// [`create_inbound_payment_for_hash`]: Self::create_inbound_payment_for_hash
+ pub fn create_inbound_payment(&self, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32, user_payment_id: u64) -> (PaymentHash, PaymentSecret) {
+ let payment_preimage = PaymentPreimage(self.keys_manager.get_secure_random_bytes());
+ let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
+
+ (payment_hash,
+ self.set_payment_hash_secret_map(payment_hash, Some(payment_preimage), min_value_msat, invoice_expiry_delta_secs, user_payment_id)
+ .expect("RNG Generated Duplicate PaymentHash"))
+ }
+
+ /// Gets a [`PaymentSecret`] for a given [`PaymentHash`], for which the payment preimage is
+ /// stored external to LDK.
+ ///
+ /// A [`PaymentReceived`] event will only be generated if the [`PaymentSecret`] matches a
+ /// payment secret fetched via this method or [`create_inbound_payment`], and which is at least
+ /// the `min_value_msat` provided here, if one is provided.
+ ///
+ /// The [`PaymentHash`] (and corresponding [`PaymentPreimage`]) must be globally unique. This
+ /// method may return an Err if another payment with the same payment_hash is still pending.
+ ///
+ /// `user_payment_id` will be provided back in [`PaymentReceived::user_payment_id`] events to
+ /// allow tracking of which events correspond with which calls to this and
+ /// [`create_inbound_payment`]. `user_payment_id` has no meaning inside of LDK, it is simply
+ /// copied to events and otherwise ignored. It may be used to correlate PaymentReceived events
+ /// with invoice metadata stored elsewhere.
+ ///
+ /// `min_value_msat` should be set if the invoice being generated contains a value. Any payment
+ /// received for the returned [`PaymentHash`] will be required to be at least `min_value_msat`
+ /// before a [`PaymentReceived`] event will be generated, ensuring that we do not provide the
+ /// sender "proof-of-payment" unless they have paid the required amount.
+ ///
+ /// `invoice_expiry_delta_secs` describes the number of seconds that the invoice is valid for
+ /// in excess of the current time. This should roughly match the expiry time set in the invoice.
+ /// After this many seconds, we will remove the inbound payment, resulting in any attempts to
+ /// pay the invoice failing. The BOLT spec suggests 7,200 secs as a default validity time for
+ /// invoices when no timeout is set.
+ ///
+ /// Note that we use block header time to time-out pending inbound payments (with some margin
+ /// to compensate for the inaccuracy of block header timestamps). Thus, in practice we will
+ /// accept a payment and generate a [`PaymentReceived`] event for some time after the expiry.
+ /// If you need exact expiry semantics, you should enforce them upon receipt of
+ /// [`PaymentReceived`].
+ ///
+ /// Pending inbound payments are stored in memory and in serialized versions of this
+ /// [`ChannelManager`]. If potentially unbounded numbers of inbound payments may exist and
+ /// space is limited, you may wish to rate-limit inbound payment creation.
+ ///
+ /// May panic if `invoice_expiry_delta_secs` is greater than one year.
+ ///
+ /// Note that invoices generated for inbound payments should have their `min_final_cltv_expiry`
+ /// set to at least [`MIN_FINAL_CLTV_EXPIRY`].
+ ///
+ /// [`create_inbound_payment`]: Self::create_inbound_payment
+ /// [`PaymentReceived`]: events::Event::PaymentReceived
+ /// [`PaymentReceived::user_payment_id`]: events::Event::PaymentReceived::user_payment_id
+ pub fn create_inbound_payment_for_hash(&self, payment_hash: PaymentHash, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32, user_payment_id: u64) -> Result<PaymentSecret, APIError> {
+ self.set_payment_hash_secret_map(payment_hash, None, min_value_msat, invoice_expiry_delta_secs, user_payment_id)
+ }
}
impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> MessageSendEventsProvider for ChannelManager<Signer, M, T, K, F, L>
self.do_chain_event(Some(height), |channel| channel.best_block_updated(height, header.time));
- loop {
- // Update last_node_announcement_serial to be the max of its current value and the
- // block timestamp. This should keep us close to the current time without relying on
- // having an explicit local time source.
- // Just in case we end up in a race, we loop until we either successfully update
- // last_node_announcement_serial or decide we don't need to.
- let old_serial = self.last_node_announcement_serial.load(Ordering::Acquire);
- if old_serial >= header.time as usize { break; }
- if self.last_node_announcement_serial.compare_exchange(old_serial, header.time as usize, Ordering::AcqRel, Ordering::Relaxed).is_ok() {
- break;
+ macro_rules! max_time {
+ ($timestamp: expr) => {
+ loop {
+ // Update $timestamp to be the max of its current value and the block
+ // timestamp. This should keep us close to the current time without relying on
+ // having an explicit local time source.
+ // Just in case we end up in a race, we loop until we either successfully
+ // update $timestamp or decide we don't need to.
+ let old_serial = $timestamp.load(Ordering::Acquire);
+ if old_serial >= header.time as usize { break; }
+ if $timestamp.compare_exchange(old_serial, header.time as usize, Ordering::AcqRel, Ordering::Relaxed).is_ok() {
+ break;
+ }
+ }
}
}
+ max_time!(self.last_node_announcement_serial);
+ max_time!(self.highest_seen_timestamp);
+ let mut payment_secrets = self.pending_inbound_payments.lock().unwrap();
+ payment_secrets.retain(|_, inbound_payment| {
+ inbound_payment.expiry_time > header.time as u64
+ });
}
fn get_relevant_txids(&self) -> Vec<Txid> {
});
if let Some(height) = height_opt {
- channel_state.claimable_htlcs.retain(|&(ref payment_hash, _), htlcs| {
+ channel_state.claimable_htlcs.retain(|payment_hash, htlcs| {
htlcs.retain(|htlc| {
// If height is approaching the number of blocks we think it takes us to get
// our commitment transaction confirmed before the HTLC expires, plus the
}
}
-impl<Signer: Sign, M: Deref + Sync + Send, T: Deref + Sync + Send, K: Deref + Sync + Send, F: Deref + Sync + Send, L: Deref + Sync + Send>
+impl<Signer: Sign, M: Deref , T: Deref , K: Deref , F: Deref , L: Deref >
ChannelMessageHandler for ChannelManager<Signer, M, T, K, F, L>
where M::Target: chain::Watch<Signer>,
T::Target: BroadcasterInterface,
},
&PendingHTLCRouting::Receive { ref payment_data, ref incoming_cltv_expiry } => {
1u8.write(writer)?;
- payment_data.write(writer)?;
+ payment_data.payment_secret.write(writer)?;
+ payment_data.total_msat.write(writer)?;
incoming_cltv_expiry.write(writer)?;
},
}
short_channel_id: Readable::read(reader)?,
},
1u8 => PendingHTLCRouting::Receive {
- payment_data: Readable::read(reader)?,
+ payment_data: msgs::FinalOnionHopData {
+ payment_secret: Readable::read(reader)?,
+ total_msat: Readable::read(reader)?,
+ },
incoming_cltv_expiry: Readable::read(reader)?,
},
_ => return Err(DecodeError::InvalidValue),
incoming_packet_shared_secret
});
-impl_writeable!(ClaimableHTLC, 0, {
- prev_hop,
- value,
- payment_data,
- cltv_expiry
-});
+impl Writeable for ClaimableHTLC {
+ fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
+ self.prev_hop.write(writer)?;
+ self.value.write(writer)?;
+ self.payment_data.payment_secret.write(writer)?;
+ self.payment_data.total_msat.write(writer)?;
+ self.cltv_expiry.write(writer)
+ }
+}
+
+impl Readable for ClaimableHTLC {
+ fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+ Ok(ClaimableHTLC {
+ prev_hop: Readable::read(reader)?,
+ value: Readable::read(reader)?,
+ payment_data: msgs::FinalOnionHopData {
+ payment_secret: Readable::read(reader)?,
+ total_msat: Readable::read(reader)?,
+ },
+ cltv_expiry: Readable::read(reader)?,
+ })
+ }
+}
impl Writeable for HTLCSource {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
}
}
+impl_writeable!(PendingInboundPayment, 0, {
+ payment_secret,
+ expiry_time,
+ user_payment_id,
+ payment_preimage,
+ min_value_msat
+});
+
impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable for ChannelManager<Signer, M, T, K, F, L>
where M::Target: chain::Watch<Signer>,
T::Target: BroadcasterInterface,
}
(self.last_node_announcement_serial.load(Ordering::Acquire) as u32).write(writer)?;
+ (self.highest_seen_timestamp.load(Ordering::Acquire) as u32).write(writer)?;
+
+ let pending_inbound_payments = self.pending_inbound_payments.lock().unwrap();
+ (pending_inbound_payments.len() as u64).write(writer)?;
+ for (hash, pending_payment) in pending_inbound_payments.iter() {
+ hash.write(writer)?;
+ pending_payment.write(writer)?;
+ }
Ok(())
}
}
let last_node_announcement_serial: u32 = Readable::read(reader)?;
+ let highest_seen_timestamp: u32 = Readable::read(reader)?;
+
+ let pending_inbound_payment_count: u64 = Readable::read(reader)?;
+ let mut pending_inbound_payments: HashMap<PaymentHash, PendingInboundPayment> = HashMap::with_capacity(cmp::min(pending_inbound_payment_count as usize, MAX_ALLOC_SIZE/(3*32)));
+ for _ in 0..pending_inbound_payment_count {
+ if pending_inbound_payments.insert(Readable::read(reader)?, Readable::read(reader)?).is_some() {
+ return Err(DecodeError::InvalidValue);
+ }
+ }
let mut secp_ctx = Secp256k1::new();
secp_ctx.seeded_randomize(&args.keys_manager.get_secure_random_bytes());
claimable_htlcs,
pending_msg_events: Vec::new(),
}),
+ pending_inbound_payments: Mutex::new(pending_inbound_payments),
+
our_network_key: args.keys_manager.get_node_secret(),
our_network_pubkey: PublicKey::from_secret_key(&secp_ctx, &args.keys_manager.get_node_secret()),
secp_ctx,
last_node_announcement_serial: AtomicUsize::new(last_node_announcement_serial as usize),
+ highest_seen_timestamp: AtomicUsize::new(highest_seen_timestamp as usize),
per_peer_state: RwLock::new(per_peer_state),
use chain::channelmonitor::Persist;
use chain::keysinterface::{KeysManager, InMemorySigner};
use ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, PaymentHash, PaymentPreimage};
- use ln::features::InitFeatures;
+ use ln::features::{InitFeatures, InvoiceFeatures};
use ln::functional_test_utils::*;
use ln::msgs::ChannelMessageHandler;
use routing::network_graph::NetworkGraph;
let dummy_graph = NetworkGraph::new(genesis_hash);
+ let mut payment_count: u64 = 0;
macro_rules! send_payment {
($node_a: expr, $node_b: expr) => {
let usable_channels = $node_a.list_usable_channels();
- let route = get_route(&$node_a.get_our_node_id(), &dummy_graph, &$node_b.get_our_node_id(), None, Some(&usable_channels.iter().map(|r| r).collect::<Vec<_>>()), &[], 10_000, TEST_FINAL_CLTV, &logger_a).unwrap();
+ let route = get_route(&$node_a.get_our_node_id(), &dummy_graph, &$node_b.get_our_node_id(), Some(InvoiceFeatures::known()),
+ Some(&usable_channels.iter().map(|r| r).collect::<Vec<_>>()), &[], 10_000, TEST_FINAL_CLTV, &logger_a).unwrap();
- let payment_preimage = PaymentPreimage([0; 32]);
+ let mut payment_preimage = PaymentPreimage([0; 32]);
+ payment_preimage.0[0..8].copy_from_slice(&payment_count.to_le_bytes());
+ payment_count += 1;
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner());
+ let payment_secret = $node_b.create_inbound_payment_for_hash(payment_hash, None, 7200, 0).unwrap();
- $node_a.send_payment(&route, payment_hash, &None).unwrap();
+ $node_a.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap();
let payment_event = SendEvent::from_event($node_a.get_and_clear_pending_msg_events().pop().unwrap());
$node_b.handle_update_add_htlc(&$node_a.get_our_node_id(), &payment_event.msgs[0]);
$node_b.handle_commitment_signed(&$node_a.get_our_node_id(), &payment_event.commitment_msg);
$node_b.handle_revoke_and_ack(&$node_a.get_our_node_id(), &get_event_msg!(NodeHolder { node: &$node_a }, MessageSendEvent::SendRevokeAndACK, $node_b.get_our_node_id()));
expect_pending_htlcs_forwardable!(NodeHolder { node: &$node_b });
- expect_payment_received!(NodeHolder { node: &$node_b }, payment_hash, 10_000);
- assert!($node_b.claim_funds(payment_preimage, &None, 10_000));
+ expect_payment_received!(NodeHolder { node: &$node_b }, payment_hash, payment_secret, 10_000);
+ assert!($node_b.claim_funds(payment_preimage));
match $node_b.get_and_clear_pending_msg_events().pop().unwrap() {
MessageSendEvent::UpdateHTLCs { node_id, updates } => {
use std::{cmp, fmt};
use std::marker::PhantomData;
+use bitcoin::bech32;
+use bitcoin::bech32::{Base32Len, FromBase32, ToBase32, u5, WriteBase32};
use ln::msgs::DecodeError;
use util::ser::{Readable, Writeable, Writer};
required_features: [$( $( $required_feature: ident )|*, )*],
optional_features: [$( $( $optional_feature: ident )|*, )*],
}) => {
+ #[derive(Eq, PartialEq)]
pub struct $context {}
impl Context for $context {
// Byte 0
,
// Byte 1
- StaticRemoteKey,
+ StaticRemoteKey | PaymentSecret,
// Byte 2
,
// Byte 3
// Byte 0
DataLossProtect | InitialRoutingSync | UpfrontShutdownScript | GossipQueries,
// Byte 1
- VariableLengthOnion | PaymentSecret,
+ VariableLengthOnion,
// Byte 2
BasicMPP,
// Byte 3
// Byte 0
,
// Byte 1
- StaticRemoteKey,
+ StaticRemoteKey | PaymentSecret,
// Byte 2
,
// Byte 3
// Byte 0
DataLossProtect | UpfrontShutdownScript | GossipQueries,
// Byte 1
- VariableLengthOnion | PaymentSecret,
+ VariableLengthOnion,
// Byte 2
BasicMPP,
// Byte 3
optional_features: [],
});
define_context!(InvoiceContext {
- required_features: [,,,],
+ required_features: [
+ // Byte 0
+ ,
+ // Byte 1
+ PaymentSecret,
+ // Byte 2
+ ,
+ ],
optional_features: [
// Byte 0
,
// Byte 1
- VariableLengthOnion | PaymentSecret,
+ VariableLengthOnion,
// Byte 2
BasicMPP,
],
/// appears.
///
/// (C-not exported) as we map the concrete feature types below directly instead
+#[derive(Eq)]
pub struct Features<T: sealed::Context> {
/// Note that, for convenience, flags is LITTLE endian (despite being big-endian on the wire)
flags: Vec<u8>,
}
}
+impl ToBase32 for InvoiceFeatures {
+ fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
+ // Explanation for the "4": the normal way to round up when dividing is to add the divisor
+ // minus one before dividing
+ let length_u5s = (self.flags.len() * 8 + 4) / 5 as usize;
+ let mut res_u5s: Vec<u5> = vec![u5::try_from_u8(0).unwrap(); length_u5s];
+ for (byte_idx, byte) in self.flags.iter().enumerate() {
+ let bit_pos_from_left_0_indexed = byte_idx * 8;
+ let new_u5_idx = length_u5s - (bit_pos_from_left_0_indexed / 5) as usize - 1;
+ let new_bit_pos = bit_pos_from_left_0_indexed % 5;
+ let shifted_chunk_u16 = (*byte as u16) << new_bit_pos;
+ let curr_u5_as_u8 = res_u5s[new_u5_idx].to_u8();
+ res_u5s[new_u5_idx] = u5::try_from_u8(curr_u5_as_u8 | ((shifted_chunk_u16 & 0x001f) as u8)).unwrap();
+ if new_u5_idx > 0 {
+ let curr_u5_as_u8 = res_u5s[new_u5_idx - 1].to_u8();
+ res_u5s[new_u5_idx - 1] = u5::try_from_u8(curr_u5_as_u8 | (((shifted_chunk_u16 >> 5) & 0x001f) as u8)).unwrap();
+ }
+ if new_u5_idx > 1 {
+ let curr_u5_as_u8 = res_u5s[new_u5_idx - 2].to_u8();
+ res_u5s[new_u5_idx - 2] = u5::try_from_u8(curr_u5_as_u8 | (((shifted_chunk_u16 >> 10) & 0x001f) as u8)).unwrap();
+ }
+ }
+ // Trim the highest feature bits.
+ while !res_u5s.is_empty() && res_u5s[0] == u5::try_from_u8(0).unwrap() {
+ res_u5s.remove(0);
+ }
+ writer.write(&res_u5s)
+ }
+}
+
+impl Base32Len for InvoiceFeatures {
+ fn base32_len(&self) -> usize {
+ self.to_base32().len()
+ }
+}
+
+impl FromBase32 for InvoiceFeatures {
+ type Err = bech32::Error;
+
+ fn from_base32(field_data: &[u5]) -> Result<InvoiceFeatures, bech32::Error> {
+ // Explanation for the "7": the normal way to round up when dividing is to add the divisor
+ // minus one before dividing
+ let length_bytes = (field_data.len() * 5 + 7) / 8 as usize;
+ let mut res_bytes: Vec<u8> = vec![0; length_bytes];
+ for (u5_idx, chunk) in field_data.iter().enumerate() {
+ let bit_pos_from_right_0_indexed = (field_data.len() - u5_idx - 1) * 5;
+ let new_byte_idx = (bit_pos_from_right_0_indexed / 8) as usize;
+ let new_bit_pos = bit_pos_from_right_0_indexed % 8;
+ let chunk_u16 = chunk.to_u8() as u16;
+ res_bytes[new_byte_idx] |= ((chunk_u16 << new_bit_pos) & 0xff) as u8;
+ if new_byte_idx != length_bytes - 1 {
+ res_bytes[new_byte_idx + 1] |= ((chunk_u16 >> (8-new_bit_pos)) & 0xff) as u8;
+ }
+ }
+ // Trim the highest feature bits.
+ while !res_bytes.is_empty() && res_bytes[res_bytes.len() - 1] == 0 {
+ res_bytes.pop();
+ }
+ Ok(InvoiceFeatures::from_le_bytes(res_bytes))
+ }
+}
+
impl<T: sealed::Context> Features<T> {
/// Create a blank Features with no features set
pub fn empty() -> Self {
Features::<C> { flags, mark: PhantomData, }
}
- #[cfg(test)]
- /// Create a Features given a set of flags, in LE.
+ /// Create a Features given a set of flags, in little-endian. This is in reverse byte order from
+ /// most on-the-wire encodings.
+ /// (C-not exported) as we don't support export across multiple T
pub fn from_le_bytes(flags: Vec<u8>) -> Features<T> {
Features {
flags,
#[cfg(test)]
mod tests {
use super::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
+ use bitcoin::bech32::{Base32Len, FromBase32, ToBase32, u5};
#[test]
fn sanity_test_known_features() {
assert!(InitFeatures::known().supports_payment_secret());
assert!(NodeFeatures::known().supports_payment_secret());
- assert!(!InitFeatures::known().requires_payment_secret());
- assert!(!NodeFeatures::known().requires_payment_secret());
+ assert!(InitFeatures::known().requires_payment_secret());
+ assert!(NodeFeatures::known().requires_payment_secret());
assert!(InitFeatures::known().supports_basic_mpp());
assert!(NodeFeatures::known().supports_basic_mpp());
{
// Check that the flags are as expected:
// - option_data_loss_protect
- // - var_onion_optin | static_remote_key (req) | payment_secret
+ // - var_onion_optin | static_remote_key (req) | payment_secret(req)
// - basic_mpp
// - opt_shutdown_anysegwit
assert_eq!(node_features.flags.len(), 4);
assert_eq!(node_features.flags[0], 0b00000010);
- assert_eq!(node_features.flags[1], 0b10010010);
+ assert_eq!(node_features.flags[1], 0b01010010);
assert_eq!(node_features.flags[2], 0b00000010);
assert_eq!(node_features.flags[3], 0b00001000);
}
assert!(features.requires_payment_secret());
assert!(features.supports_payment_secret());
}
+
+ #[test]
+ fn invoice_features_encoding() {
+ let features_as_u5s = vec![
+ u5::try_from_u8(6).unwrap(),
+ u5::try_from_u8(10).unwrap(),
+ u5::try_from_u8(25).unwrap(),
+ u5::try_from_u8(1).unwrap(),
+ u5::try_from_u8(10).unwrap(),
+ u5::try_from_u8(0).unwrap(),
+ u5::try_from_u8(20).unwrap(),
+ u5::try_from_u8(2).unwrap(),
+ u5::try_from_u8(0).unwrap(),
+ u5::try_from_u8(6).unwrap(),
+ u5::try_from_u8(0).unwrap(),
+ u5::try_from_u8(16).unwrap(),
+ u5::try_from_u8(1).unwrap(),
+ ];
+ let features = InvoiceFeatures::from_le_bytes(vec![1, 2, 3, 4, 5, 42, 100, 101]);
+
+ // Test length calculation.
+ assert_eq!(features.base32_len(), 13);
+
+ // Test serialization.
+ let features_serialized = features.to_base32();
+ assert_eq!(features_as_u5s, features_serialized);
+
+ // Test deserialization.
+ let features_deserialized = InvoiceFeatures::from_base32(&features_as_u5s).unwrap();
+ assert_eq!(features, features_deserialized);
+ }
}
use chain::{Confirm, Listen, Watch};
use chain::channelmonitor::ChannelMonitor;
use chain::transaction::OutPoint;
-use ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSecret, PaymentSendFailure};
+use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
+use ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentSendFailure};
use routing::router::{Route, get_route};
use routing::network_graph::{NetGraphMsgHandler, NetworkGraph};
-use ln::features::InitFeatures;
+use ln::features::{InitFeatures, InvoiceFeatures};
use ln::msgs;
use ln::msgs::{ChannelMessageHandler,RoutingMessageHandler};
use util::enforcing_trait_impls::EnforcingSigner;
connect_blocks(node, conf_height - first_connect_height);
}
let mut block = Block {
- header: BlockHeader { version: 0x20000000, prev_blockhash: node.best_block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
+ header: BlockHeader { version: 0x20000000, prev_blockhash: node.best_block_hash(), merkle_root: Default::default(), time: conf_height, bits: 42, nonce: 42 },
txdata: Vec::new(),
};
for _ in 0..*node.network_chan_count.borrow() { // Make sure we don't end up with channels at the same short id by offsetting by chan_count
_ => false,
};
+ let height = node.best_block_info().1 + 1;
let mut block = Block {
- header: BlockHeader { version: 0x2000000, prev_blockhash: node.best_block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
+ header: BlockHeader { version: 0x2000000, prev_blockhash: node.best_block_hash(), merkle_root: Default::default(), time: height, bits: 42, nonce: 42 },
txdata: vec![],
};
assert!(depth >= 1);
- for _ in 0..depth - 1 {
+ for i in 1..depth {
do_connect_block(node, &block, skip_intermediaries);
block = Block {
- header: BlockHeader { version: 0x20000000, prev_blockhash: block.header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
+ header: BlockHeader { version: 0x20000000, prev_blockhash: block.header.block_hash(), merkle_root: Default::default(), time: height + i, bits: 42, nonce: 42 },
txdata: vec![],
};
}
/// Get a payment preimage and hash.
#[macro_export]
macro_rules! get_payment_preimage_hash {
- ($node: expr) => {
+ ($dest_node: expr) => {
{
- let payment_preimage = PaymentPreimage([*$node.network_payment_count.borrow(); 32]);
- *$node.network_payment_count.borrow_mut() += 1;
+ let payment_preimage = PaymentPreimage([*$dest_node.network_payment_count.borrow(); 32]);
+ *$dest_node.network_payment_count.borrow_mut() += 1;
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner());
- (payment_preimage, payment_hash)
+ let payment_secret = $dest_node.node.create_inbound_payment_for_hash(payment_hash, None, 7200, 0).unwrap();
+ (payment_preimage, payment_hash, payment_secret)
}
}
}
+#[cfg(test)]
+macro_rules! get_route_and_payment_hash {
+ ($send_node: expr, $recv_node: expr, $recv_value: expr) => {{
+ let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!($recv_node);
+ let net_graph_msg_handler = &$send_node.net_graph_msg_handler;
+ let route = get_route(&$send_node.node.get_our_node_id(),
+ &net_graph_msg_handler.network_graph.read().unwrap(),
+ &$recv_node.node.get_our_node_id(), None, None, &Vec::new(), $recv_value, TEST_FINAL_CLTV, $send_node.logger).unwrap();
+ (route, payment_hash, payment_preimage, payment_secret)
+ }}
+}
+
macro_rules! expect_pending_htlcs_forwardable_ignore {
($node: expr) => {{
let events = $node.node.get_and_clear_pending_events();
#[cfg(any(test, feature = "unstable"))]
macro_rules! expect_payment_received {
- ($node: expr, $expected_payment_hash: expr, $expected_recv_value: expr) => {
+ ($node: expr, $expected_payment_hash: expr, $expected_payment_secret: expr, $expected_recv_value: expr) => {
let events = $node.node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
match events[0] {
- Event::PaymentReceived { ref payment_hash, ref payment_secret, amt } => {
+ Event::PaymentReceived { ref payment_hash, ref payment_preimage, ref payment_secret, amt, user_payment_id: _ } => {
assert_eq!($expected_payment_hash, *payment_hash);
- assert_eq!(None, *payment_secret);
+ assert!(payment_preimage.is_none());
+ assert_eq!($expected_payment_secret, *payment_secret);
assert_eq!($expected_recv_value, amt);
},
_ => panic!("Unexpected event"),
}
}
-pub fn send_along_route_with_secret<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route, expected_paths: &[&[&Node<'a, 'b, 'c>]], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: Option<PaymentSecret>) {
- origin_node.node.send_payment(&route, our_payment_hash, &our_payment_secret).unwrap();
+pub fn send_along_route_with_secret<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route, expected_paths: &[&[&Node<'a, 'b, 'c>]], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: PaymentSecret) {
+ origin_node.node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(origin_node, expected_paths.len());
pass_along_route(origin_node, expected_paths, recv_value, our_payment_hash, our_payment_secret);
}
-pub fn pass_along_path<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_path: &[&Node<'a, 'b, 'c>], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: Option<PaymentSecret>, ev: MessageSendEvent, payment_received_expected: bool) {
+pub fn pass_along_path<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_path: &[&Node<'a, 'b, 'c>], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: PaymentSecret, ev: MessageSendEvent, payment_received_expected: bool) {
let mut payment_event = SendEvent::from_event(ev);
let mut prev_node = origin_node;
if payment_received_expected {
assert_eq!(events_2.len(), 1);
match events_2[0] {
- Event::PaymentReceived { ref payment_hash, ref payment_secret, amt } => {
+ Event::PaymentReceived { ref payment_hash, ref payment_preimage, ref payment_secret, amt, user_payment_id: _ } => {
assert_eq!(our_payment_hash, *payment_hash);
+ assert!(payment_preimage.is_none());
assert_eq!(our_payment_secret, *payment_secret);
assert_eq!(amt, recv_value);
},
}
}
-pub fn pass_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&[&Node<'a, 'b, 'c>]], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: Option<PaymentSecret>) {
+pub fn pass_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&[&Node<'a, 'b, 'c>]], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: PaymentSecret) {
let mut events = origin_node.node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), expected_route.len());
for (path_idx, (ev, expected_path)) in events.drain(..).zip(expected_route.iter()).enumerate() {
}
}
-pub fn send_along_route_with_hash<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64, our_payment_hash: PaymentHash) {
- send_along_route_with_secret(origin_node, route, &[expected_route], recv_value, our_payment_hash, None);
+pub fn send_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) -> (PaymentPreimage, PaymentHash, PaymentSecret) {
+ let (our_payment_preimage, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(expected_route.last().unwrap());
+ send_along_route_with_secret(origin_node, route, &[expected_route], recv_value, our_payment_hash, our_payment_secret);
+ (our_payment_preimage, our_payment_hash, our_payment_secret)
}
-pub fn send_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) -> (PaymentPreimage, PaymentHash) {
- let (our_payment_preimage, our_payment_hash) = get_payment_preimage_hash!(origin_node);
- send_along_route_with_hash(origin_node, route, expected_route, recv_value, our_payment_hash);
- (our_payment_preimage, our_payment_hash)
-}
-
-pub fn claim_payment_along_route_with_secret<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], skip_last: bool, our_payment_preimage: PaymentPreimage, our_payment_secret: Option<PaymentSecret>, expected_amount: u64) {
+pub fn claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], skip_last: bool, our_payment_preimage: PaymentPreimage) {
for path in expected_paths.iter() {
assert_eq!(path.last().unwrap().node.get_our_node_id(), expected_paths[0].last().unwrap().node.get_our_node_id());
}
- assert!(expected_paths[0].last().unwrap().node.claim_funds(our_payment_preimage, &our_payment_secret, expected_amount));
+ assert!(expected_paths[0].last().unwrap().node.claim_funds(our_payment_preimage));
check_added_monitors!(expected_paths[0].last().unwrap(), expected_paths.len());
macro_rules! msgs_from_ev {
}
}
-pub fn claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], skip_last: bool, our_payment_preimage: PaymentPreimage, expected_amount: u64) {
- claim_payment_along_route_with_secret(origin_node, &[expected_route], skip_last, our_payment_preimage, None, expected_amount);
-}
-
-pub fn claim_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], our_payment_preimage: PaymentPreimage, expected_amount: u64) {
- claim_payment_along_route(origin_node, expected_route, false, our_payment_preimage, expected_amount);
+pub fn claim_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], our_payment_preimage: PaymentPreimage) {
+ claim_payment_along_route(origin_node, &[expected_route], false, our_payment_preimage);
}
pub const TEST_FINAL_CLTV: u32 = 50;
-pub fn route_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) -> (PaymentPreimage, PaymentHash) {
+pub fn route_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) -> (PaymentPreimage, PaymentHash, PaymentSecret) {
let net_graph_msg_handler = &origin_node.net_graph_msg_handler;
let logger = test_utils::TestLogger::new();
- let route = get_route(&origin_node.node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &expected_route.last().unwrap().node.get_our_node_id(), None, None, &Vec::new(), recv_value, TEST_FINAL_CLTV, &logger).unwrap();
+ let route = get_route(&origin_node.node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &expected_route.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), recv_value, TEST_FINAL_CLTV, &logger).unwrap();
assert_eq!(route.paths.len(), 1);
assert_eq!(route.paths[0].len(), expected_route.len());
for (node, hop) in expected_route.iter().zip(route.paths[0].iter()) {
pub fn route_over_limit<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) {
let logger = test_utils::TestLogger::new();
let net_graph_msg_handler = &origin_node.net_graph_msg_handler;
- let route = get_route(&origin_node.node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &expected_route.last().unwrap().node.get_our_node_id(), None, None, &Vec::new(), recv_value, TEST_FINAL_CLTV, &logger).unwrap();
+ let route = get_route(&origin_node.node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &expected_route.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), recv_value, TEST_FINAL_CLTV, &logger).unwrap();
assert_eq!(route.paths.len(), 1);
assert_eq!(route.paths[0].len(), expected_route.len());
for (node, hop) in expected_route.iter().zip(route.paths[0].iter()) {
assert_eq!(hop.pubkey, node.node.get_our_node_id());
}
- let (_, our_payment_hash) = get_payment_preimage_hash!(origin_node);
- unwrap_send_err!(origin_node.node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { ref err },
+ let (_, our_payment_hash, our_payment_preimage) = get_payment_preimage_hash!(expected_route.last().unwrap());
+ unwrap_send_err!(origin_node.node.send_payment(&route, our_payment_hash, &Some(our_payment_preimage)), true, APIError::ChannelUnavailable { ref err },
assert!(err.contains("Cannot send value that would put us over the max HTLC value in flight our peer will accept")));
}
-pub fn send_payment<'a, 'b, 'c>(origin: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64, expected_value: u64) {
+pub fn send_payment<'a, 'b, 'c>(origin: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) {
let our_payment_preimage = route_payment(&origin, expected_route, recv_value).0;
- claim_payment(&origin, expected_route, our_payment_preimage, expected_value);
+ claim_payment(&origin, expected_route, our_payment_preimage);
}
pub fn fail_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], skip_last: bool, our_payment_hash: PaymentHash) {
- assert!(expected_route.last().unwrap().node.fail_htlc_backwards(&our_payment_hash, &None));
+ assert!(expected_route.last().unwrap().node.fail_htlc_backwards(&our_payment_hash));
expect_pending_htlcs_forwardable!(expected_route.last().unwrap());
check_added_monitors!(expected_route.last().unwrap(), 1);
use chain::channelmonitor::{ChannelMonitor, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY};
use chain::transaction::OutPoint;
use chain::keysinterface::{KeysInterface, BaseSign};
+use ln::{PaymentPreimage, PaymentSecret, PaymentHash};
use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC};
-use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSecret, PaymentSendFailure, BREAKDOWN_TIMEOUT};
+use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentSendFailure, BREAKDOWN_TIMEOUT};
use ln::channel::{Channel, ChannelError};
use ln::{chan_utils, onion_utils};
use routing::router::{Route, RouteHop, get_route};
-use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
+use ln::features::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
use ln::msgs;
use ln::msgs::{ChannelMessageHandler,RoutingMessageHandler,HTLCFailChannelUpdate, ErrorAction};
use util::enforcing_trait_impls::EnforcingSigner;
let channel_id = chan.2;
// balancing
- send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000, 8_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
// A B
// update_fee ->
nodes[1].node.handle_update_fee(&nodes[0].node.get_our_node_id(), update_msg.unwrap());
// ...but before it's delivered, nodes[1] starts to send a payment back to nodes[0]...
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[0]);
let net_graph_msg_handler = &nodes[1].net_graph_msg_handler;
- nodes[1].node.send_payment(&get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), None, None, &Vec::new(), 40000, TEST_FINAL_CLTV, &logger).unwrap(), our_payment_hash, &None).unwrap();
+ nodes[1].node.send_payment(&get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 40000, TEST_FINAL_CLTV, &logger).unwrap(), our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(nodes[1], 1);
let payment_event = {
let logger = test_utils::TestLogger::new();
// balancing
- send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000, 8_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
// First nodes[0] generates an update_fee
nodes[0].node.update_fee(channel_id, get_feerate!(nodes[0], channel_id) + 20).unwrap();
nodes[1].node.handle_update_fee(&nodes[0].node.get_our_node_id(), update_msg.unwrap());
// ...but before it's delivered, nodes[1] starts to send a payment back to nodes[0]...
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[0]);
let net_graph_msg_handler = &nodes[1].net_graph_msg_handler;
- nodes[1].node.send_payment(&get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), None, None, &Vec::new(), 40000, TEST_FINAL_CLTV, &logger).unwrap(), our_payment_hash, &None).unwrap();
+ nodes[1].node.send_payment(&get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 40000, TEST_FINAL_CLTV, &logger).unwrap(), our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(nodes[1], 1);
let payment_event = {
let logger = test_utils::TestLogger::new();
// balancing
- send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000, 8_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
let feerate = get_feerate!(nodes[0], channel_id);
nodes[0].node.update_fee(channel_id, feerate+20).unwrap();
let (revoke_msg, commitment_signed) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id());
check_added_monitors!(nodes[1], 1);
- let (our_payment_preimage, our_payment_hash) = get_payment_preimage_hash!(nodes[1]);
+ let (our_payment_preimage, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[0]);
let net_graph_msg_handler = &nodes[1].net_graph_msg_handler;
- let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), None, None, &Vec::new(), 800000, TEST_FINAL_CLTV, &logger).unwrap();
+ let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 800000, TEST_FINAL_CLTV, &logger).unwrap();
// nothing happens since node[1] is in AwaitingRemoteRevoke
- nodes[1].node.send_payment(&route, our_payment_hash, &None).unwrap();
+ nodes[1].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
{
let mut added_monitors = nodes[0].chain_monitor.added_monitors.lock().unwrap();
assert_eq!(added_monitors.len(), 0);
_ => panic!("Unexpected event"),
};
- claim_payment(&nodes[1], &vec!(&nodes[0])[..], our_payment_preimage, 800_000);
+ claim_payment(&nodes[1], &vec!(&nodes[0])[..], our_payment_preimage);
- send_payment(&nodes[1], &vec!(&nodes[0])[..], 800000, 800_000);
- send_payment(&nodes[0], &vec!(&nodes[1])[..], 800000, 800_000);
+ send_payment(&nodes[1], &vec!(&nodes[0])[..], 800000);
+ send_payment(&nodes[0], &vec!(&nodes[1])[..], 800000);
close_channel(&nodes[0], &nodes[1], &chan.2, chan.3, true);
}
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
let logger = test_utils::TestLogger::new();
- let (our_payment_preimage, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 100000);
+ let (our_payment_preimage, _, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 100000);
nodes[0].node.close_channel(&chan_1.2).unwrap();
let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
- let (_, payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[0]);
let net_graph_msg_handler0 = &nodes[0].net_graph_msg_handler;
let net_graph_msg_handler1 = &nodes[1].net_graph_msg_handler;
- let route_1 = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler0.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
- let route_2 = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler1.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), None, None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
- unwrap_send_err!(nodes[0].node.send_payment(&route_1, payment_hash, &None), true, APIError::ChannelUnavailable {..}, {});
- unwrap_send_err!(nodes[1].node.send_payment(&route_2, payment_hash, &None), true, APIError::ChannelUnavailable {..}, {});
+ let route_1 = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler0.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
+ let route_2 = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler1.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
+ unwrap_send_err!(nodes[0].node.send_payment(&route_1, payment_hash, &Some(payment_secret)), true, APIError::ChannelUnavailable {..}, {});
+ unwrap_send_err!(nodes[1].node.send_payment(&route_2, payment_hash, &Some(payment_secret)), true, APIError::ChannelUnavailable {..}, {});
- assert!(nodes[2].node.claim_funds(our_payment_preimage, &None, 100_000));
+ assert!(nodes[2].node.claim_funds(our_payment_preimage));
check_added_monitors!(nodes[2], 1);
let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
assert!(updates.update_add_htlcs.is_empty());
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
let logger = test_utils::TestLogger::new();
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[2]);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), None, None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
assert_eq!(updates.update_add_htlcs.len(), 1);
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
- let (our_payment_preimage, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 100000);
+ let (our_payment_preimage, _, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 100000);
nodes[1].node.close_channel(&chan_1.2).unwrap();
let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
- assert!(nodes[2].node.claim_funds(our_payment_preimage, &None, 100_000));
+ assert!(nodes[2].node.claim_funds(our_payment_preimage));
check_added_monitors!(nodes[2], 1);
let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
assert!(updates.update_add_htlcs.is_empty());
let chan_3 = create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known());
// Rebalance the network a bit by relaying one payment through all the channels...
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000, 8_000_000);
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000, 8_000_000);
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000, 8_000_000);
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000, 8_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000);
+ send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000);
+ send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000);
+ send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000);
// Send some more payments
- send_payment(&nodes[1], &vec!(&nodes[2], &nodes[3])[..], 1000000, 1_000_000);
- send_payment(&nodes[3], &vec!(&nodes[2], &nodes[1], &nodes[0])[..], 1000000, 1_000_000);
- send_payment(&nodes[3], &vec!(&nodes[2], &nodes[1])[..], 1000000, 1_000_000);
+ send_payment(&nodes[1], &vec!(&nodes[2], &nodes[3])[..], 1000000);
+ send_payment(&nodes[3], &vec!(&nodes[2], &nodes[1], &nodes[0])[..], 1000000);
+ send_payment(&nodes[3], &vec!(&nodes[2], &nodes[1])[..], 1000000);
// Test failure packets
let payment_hash_1 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 1000000).1;
// Add a new channel that skips 3
let chan_4 = create_announced_chan_between_nodes(&nodes, 1, 3, InitFeatures::known(), InitFeatures::known());
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[3])[..], 1000000, 1_000_000);
- send_payment(&nodes[2], &vec!(&nodes[3])[..], 1000000, 1_000_000);
- send_payment(&nodes[1], &vec!(&nodes[3])[..], 8000000, 8_000_000);
- send_payment(&nodes[1], &vec!(&nodes[3])[..], 8000000, 8_000_000);
- send_payment(&nodes[1], &vec!(&nodes[3])[..], 8000000, 8_000_000);
- send_payment(&nodes[1], &vec!(&nodes[3])[..], 8000000, 8_000_000);
- send_payment(&nodes[1], &vec!(&nodes[3])[..], 8000000, 8_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1], &nodes[3])[..], 1000000);
+ send_payment(&nodes[2], &vec!(&nodes[3])[..], 1000000);
+ send_payment(&nodes[1], &vec!(&nodes[3])[..], 8000000);
+ send_payment(&nodes[1], &vec!(&nodes[3])[..], 8000000);
+ send_payment(&nodes[1], &vec!(&nodes[3])[..], 8000000);
+ send_payment(&nodes[1], &vec!(&nodes[3])[..], 8000000);
+ send_payment(&nodes[1], &vec!(&nodes[3])[..], 8000000);
// Do some rebalance loop payments, simultaneously
let mut hops = Vec::with_capacity(3);
});
hops.push(RouteHop {
pubkey: nodes[1].node.get_our_node_id(),
- node_features: NodeFeatures::empty(),
+ node_features: NodeFeatures::known(),
short_channel_id: chan_4.0.contents.short_channel_id,
- channel_features: ChannelFeatures::empty(),
+ channel_features: ChannelFeatures::known(),
fee_msat: 1000000,
cltv_expiry_delta: TEST_FINAL_CLTV,
});
});
hops.push(RouteHop {
pubkey: nodes[1].node.get_our_node_id(),
- node_features: NodeFeatures::empty(),
+ node_features: NodeFeatures::known(),
short_channel_id: chan_2.0.contents.short_channel_id,
- channel_features: ChannelFeatures::empty(),
+ channel_features: ChannelFeatures::known(),
fee_msat: 1000000,
cltv_expiry_delta: TEST_FINAL_CLTV,
});
// Claim the rebalances...
fail_payment(&nodes[1], &vec!(&nodes[3], &nodes[2], &nodes[1])[..], payment_hash_2);
- claim_payment(&nodes[1], &vec!(&nodes[2], &nodes[3], &nodes[1])[..], payment_preimage_1, 1_000_000);
+ claim_payment(&nodes[1], &vec!(&nodes[2], &nodes[3], &nodes[1])[..], payment_preimage_1);
// Add a duplicate new channel from 2 to 4
let chan_5 = create_announced_chan_between_nodes(&nodes, 1, 3, InitFeatures::known(), InitFeatures::known());
//TODO: Test that routes work again here as we've been notified that the channel is full
- claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[3])[..], payment_preimage_3, 3_000_000);
- claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[3])[..], payment_preimage_4, 3_000_000);
- claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[3])[..], payment_preimage_5, 3_000_000);
+ claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[3])[..], payment_preimage_3);
+ claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[3])[..], payment_preimage_4);
+ claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[3])[..], payment_preimage_5);
// Close down the channels...
close_channel(&nodes[0], &nodes[1], &chan_1.2, chan_1.3, true);
let mut payments = Vec::new();
for _ in 0..::ln::channel::OUR_MAX_HTLCS {
- let (payment_preimage, payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[2]);
let net_graph_msg_handler = &nodes[1].net_graph_msg_handler;
- let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), None, None, &Vec::new(), 100000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[1].node.send_payment(&route, payment_hash, &None).unwrap();
+ let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 100000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[1].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap();
payments.push((payment_preimage, payment_hash));
}
check_added_monitors!(nodes[1], 1);
// There is now one HTLC in an outbound commitment transaction and (OUR_MAX_HTLCS - 1) HTLCs in
// the holding cell waiting on B's RAA to send. At this point we should not be able to add
// another HTLC.
- let (_, payment_hash_1) = get_payment_preimage_hash!(nodes[0]);
+ let (_, payment_hash_1, payment_secret_1) = get_payment_preimage_hash!(nodes[2]);
{
let net_graph_msg_handler = &nodes[1].net_graph_msg_handler;
- let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), None, None, &Vec::new(), 100000, TEST_FINAL_CLTV, &logger).unwrap();
- unwrap_send_err!(nodes[1].node.send_payment(&route, payment_hash_1, &None), true, APIError::ChannelUnavailable { ref err },
+ let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 100000, TEST_FINAL_CLTV, &logger).unwrap();
+ unwrap_send_err!(nodes[1].node.send_payment(&route, payment_hash_1, &Some(payment_secret_1)), true, APIError::ChannelUnavailable { ref err },
assert!(regex::Regex::new(r"Cannot push more than their max accepted HTLCs \(\d+\)").unwrap().is_match(err)));
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
nodes[1].logger.assert_log_contains("lightning::ln::channelmanager".to_string(), "Cannot push more than their max accepted HTLCs".to_string(), 1);
}
// This should also be true if we try to forward a payment.
- let (_, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
+ let (_, payment_hash_2, payment_secret_2) = get_payment_preimage_hash!(nodes[2]);
{
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), None, None, &Vec::new(), 100000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, payment_hash_2, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 100000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash_2, &Some(payment_secret_2)).unwrap();
check_added_monitors!(nodes[0], 1);
}
}
for (preimage, _) in payments.drain(..) {
- claim_payment(&nodes[1], &[&nodes[2]], preimage, 100_000);
+ claim_payment(&nodes[1], &[&nodes[2]], preimage);
}
- send_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1000000, 1_000_000);
+ send_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1000000);
}
#[test]
create_announced_chan_between_nodes(&nodes, 3, 4, InitFeatures::known(), InitFeatures::known());
create_announced_chan_between_nodes(&nodes, 3, 5, InitFeatures::known(), InitFeatures::known());
- let (payment_preimage, payment_hash) = route_payment(&nodes[0], &vec!(&nodes[3], &nodes[4])[..], 1000000);
+ let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &vec!(&nodes[3], &nodes[4])[..], 1000000);
*nodes[0].network_payment_count.borrow_mut() -= 1;
assert_eq!(route_payment(&nodes[1], &vec!(&nodes[3])[..], 1000000).0, payment_preimage);
*nodes[0].network_payment_count.borrow_mut() -= 1;
assert_eq!(route_payment(&nodes[2], &vec!(&nodes[3], &nodes[5])[..], 1000000).0, payment_preimage);
- claim_payment(&nodes[0], &vec!(&nodes[3], &nodes[4])[..], payment_preimage, 1_000_000);
+ claim_payment(&nodes[0], &vec!(&nodes[3], &nodes[4])[..], payment_preimage);
fail_payment(&nodes[2], &vec!(&nodes[3], &nodes[5])[..], payment_hash);
- claim_payment(&nodes[1], &vec!(&nodes[3])[..], payment_preimage, 1_000_000);
+ claim_payment(&nodes[1], &vec!(&nodes[3])[..], payment_preimage);
}
#[test]
fn test_duplicate_htlc_different_direction_onchain() {
// Test that ChannelMonitor doesn't generate 2 preimage txn
// when we have 2 HTLCs with same preimage that go across a node
- // in opposite directions.
+ // in opposite directions, even with the same payment secret.
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let logger = test_utils::TestLogger::new();
// balancing
- send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000, 8_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
- let (payment_preimage, payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1])[..], 900_000);
+ let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &vec!(&nodes[1])[..], 900_000);
let net_graph_msg_handler = &nodes[1].net_graph_msg_handler;
- let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), None, None, &Vec::new(), 800_000, TEST_FINAL_CLTV, &logger).unwrap();
- send_along_route_with_hash(&nodes[1], route, &vec!(&nodes[0])[..], 800_000, payment_hash);
+ let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 800_000, TEST_FINAL_CLTV, &logger).unwrap();
+ let node_a_payment_secret = nodes[0].node.create_inbound_payment_for_hash(payment_hash, None, 7200, 0).unwrap();
+ send_along_route_with_secret(&nodes[1], route, &[&[&nodes[0]]], 800_000, payment_hash, node_a_payment_secret);
// Provide preimage to node 0 by claiming payment
- nodes[0].node.claim_funds(payment_preimage, &None, 800_000);
+ nodes[0].node.claim_funds(payment_preimage);
check_added_monitors!(nodes[0], 1);
// Broadcast node 1 commitment txn
let channel_reserve = chan_stat.channel_reserve_msat;
// The 2* and +1 are for the fee spike reserve.
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[1]);
let commit_tx_fee = 2 * commit_tx_fee_msat(get_feerate!(nodes[0], chan.2), 1 + 1);
let max_can_send = 5000000 - channel_reserve - commit_tx_fee;
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes.last().unwrap().node.get_our_node_id(), None, None, &Vec::new(), max_can_send + 1, TEST_FINAL_CLTV, &logger).unwrap();
- let err = nodes[0].node.send_payment(&route, our_payment_hash, &None).err().unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), max_can_send + 1, TEST_FINAL_CLTV, &logger).unwrap();
+ let err = nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).err().unwrap();
match err {
PaymentSendFailure::AllFailedRetrySafe(ref fails) => {
match &fails[0] {
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
nodes[0].logger.assert_log_contains("lightning::ln::channelmanager".to_string(), "Cannot send value that would put our balance under counterparty-announced channel reserve value".to_string(), 1);
- send_payment(&nodes[0], &vec![&nodes[1]], max_can_send, max_can_send);
+ send_payment(&nodes[0], &vec![&nodes[1]], max_can_send);
}
#[test]
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
- let logger = test_utils::TestLogger::new();
- macro_rules! get_route_and_payment_hash {
- ($recv_value: expr) => {{
- let (payment_preimage, payment_hash) = get_payment_preimage_hash!(nodes[1]);
- let net_graph_msg_handler = &nodes[0].net_graph_msg_handler.network_graph.read().unwrap();
- let route = get_route(&nodes[0].node.get_our_node_id(), net_graph_msg_handler, &nodes.last().unwrap().node.get_our_node_id(), None, None, &Vec::new(), $recv_value, TEST_FINAL_CLTV, &logger).unwrap();
- (route, payment_hash, payment_preimage)
- }}
- }
-
- let (route, payment_hash, _) = get_route_and_payment_hash!(3460001);
+ let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 3460001);
// Need to manually create the update_add_htlc message to go around the channel reserve check in send_htlc()
let secp_ctx = Secp256k1::new();
let session_priv = SecretKey::from_slice(&[42; 32]).expect("RNG is bad!");
let cur_height = nodes[1].node.best_block.read().unwrap().height() + 1;
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap();
- let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 3460001, &None, cur_height).unwrap();
+ let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 3460001, &Some(payment_secret), cur_height).unwrap();
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash);
let msg = msgs::UpdateAddHTLC {
channel_id: chan.2,
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let _ = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
- let logger = test_utils::TestLogger::new();
- macro_rules! get_route_and_payment_hash {
- ($recv_value: expr) => {{
- let (payment_preimage, payment_hash) = get_payment_preimage_hash!(nodes[1]);
- let net_graph_msg_handler = &nodes[1].net_graph_msg_handler;
- let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes.first().unwrap().node.get_our_node_id(), None, None, &Vec::new(), $recv_value, TEST_FINAL_CLTV, &logger).unwrap();
- (route, payment_hash, payment_preimage)
- }}
- }
-
- let (route, our_payment_hash, _) = get_route_and_payment_hash!(4843000);
- unwrap_send_err!(nodes[1].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { ref err },
+ let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], 4843000);
+ unwrap_send_err!(nodes[1].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)), true, APIError::ChannelUnavailable { ref err },
assert_eq!(err, "Cannot send value that would put counterparty balance under holder-announced channel reserve value"));
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
nodes[1].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot send value that would put counterparty balance under holder-announced channel reserve value".to_string(), 1);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
- let logger = test_utils::TestLogger::new();
- macro_rules! get_route_and_payment_hash {
- ($recv_value: expr) => {{
- let (payment_preimage, payment_hash) = get_payment_preimage_hash!(nodes[1]);
- let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes.first().unwrap().node.get_our_node_id(), None, None, &Vec::new(), $recv_value, TEST_FINAL_CLTV, &logger).unwrap();
- (route, payment_hash, payment_preimage)
- }}
- }
-
- let (route, payment_hash, _) = get_route_and_payment_hash!(1000);
+ let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], 1000);
// Need to manually create the update_add_htlc message to go around the channel reserve check in send_htlc()
let secp_ctx = Secp256k1::new();
let session_priv = SecretKey::from_slice(&[42; 32]).unwrap();
let cur_height = nodes[1].node.best_block.read().unwrap().height() + 1;
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap();
- let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 1000, &None, cur_height).unwrap();
+ let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 1000, &Some(payment_secret), cur_height).unwrap();
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash);
let msg = msgs::UpdateAddHTLC {
channel_id: chan.2,
// In the previous code, routing this dust payment would cause nodes[0] to perceive a channel
// reserve violation even though it's a dust HTLC and therefore shouldn't count towards the
// commitment transaction fee.
- let (_, _) = route_payment(&nodes[1], &[&nodes[0]], dust_amt);
+ let (_, _, _) = route_payment(&nodes[1], &[&nodes[0]], dust_amt);
}
#[test]
let payment_amt = 46000; // Dust amount
// In the previous code, these first four payments would succeed.
- let (_, _) = route_payment(&nodes[0], &[&nodes[1]], payment_amt);
- let (_, _) = route_payment(&nodes[0], &[&nodes[1]], payment_amt);
- let (_, _) = route_payment(&nodes[0], &[&nodes[1]], payment_amt);
- let (_, _) = route_payment(&nodes[0], &[&nodes[1]], payment_amt);
+ let (_, _, _) = route_payment(&nodes[0], &[&nodes[1]], payment_amt);
+ let (_, _, _) = route_payment(&nodes[0], &[&nodes[1]], payment_amt);
+ let (_, _, _) = route_payment(&nodes[0], &[&nodes[1]], payment_amt);
+ let (_, _, _) = route_payment(&nodes[0], &[&nodes[1]], payment_amt);
// Then these next 5 would be interpreted by nodes[1] as violating the fee spike buffer.
- let (_, _) = route_payment(&nodes[0], &[&nodes[1]], payment_amt);
- let (_, _) = route_payment(&nodes[0], &[&nodes[1]], payment_amt);
- let (_, _) = route_payment(&nodes[0], &[&nodes[1]], payment_amt);
- let (_, _) = route_payment(&nodes[0], &[&nodes[1]], payment_amt);
- let (_, _) = route_payment(&nodes[0], &[&nodes[1]], payment_amt);
+ let (_, _, _) = route_payment(&nodes[0], &[&nodes[1]], payment_amt);
+ let (_, _, _) = route_payment(&nodes[0], &[&nodes[1]], payment_amt);
+ let (_, _, _) = route_payment(&nodes[0], &[&nodes[1]], payment_amt);
+ let (_, _, _) = route_payment(&nodes[0], &[&nodes[1]], payment_amt);
+ let (_, _, _) = route_payment(&nodes[0], &[&nodes[1]], payment_amt);
// And this last payment previously resulted in nodes[1] closing on its inbound-channel
// counterparty, because it counted all the previous dust HTLCs against nodes[0]'s commitment
// transaction fee and therefore perceived this next payment as a channel reserve violation.
- let (_, _) = route_payment(&nodes[0], &[&nodes[1]], payment_amt);
+ let (_, _, _) = route_payment(&nodes[0], &[&nodes[1]], payment_amt);
}
#[test]
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
let _ = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
- let logger = test_utils::TestLogger::new();
-
- macro_rules! get_route_and_payment_hash {
- ($recv_value: expr) => {{
- let (payment_preimage, payment_hash) = get_payment_preimage_hash!(nodes[0]);
- let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes.last().unwrap().node.get_our_node_id(), None, None, &Vec::new(), $recv_value, TEST_FINAL_CLTV, &logger).unwrap();
- (route, payment_hash, payment_preimage)
- }}
- }
let feemsat = 239;
let total_routing_fee_msat = (nodes.len() - 2) as u64 * feemsat;
let amt_msat_1 = recv_value_1 + total_routing_fee_msat;
// Add a pending HTLC.
- let (route_1, our_payment_hash_1, _) = get_route_and_payment_hash!(amt_msat_1);
+ let (route_1, our_payment_hash_1, _, our_payment_secret_1) = get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat_1);
let payment_event_1 = {
- nodes[0].node.send_payment(&route_1, our_payment_hash_1, &None).unwrap();
+ nodes[0].node.send_payment(&route_1, our_payment_hash_1, &Some(our_payment_secret_1)).unwrap();
check_added_monitors!(nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
let commit_tx_fee_2_htlcs = commit_tx_fee_msat(feerate, 2);
let recv_value_2 = chan_stat.value_to_self_msat - amt_msat_1 - chan_stat.channel_reserve_msat - total_routing_fee_msat - commit_tx_fee_2_htlcs + 1;
let amt_msat_2 = recv_value_2 + total_routing_fee_msat;
- let (route_2, _, _) = get_route_and_payment_hash!(amt_msat_2);
+ let (route_2, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat_2);
// Need to manually create the update_add_htlc message to go around the channel reserve check in send_htlc()
let secp_ctx = Secp256k1::new();
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
let chan_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 190000, 1001, InitFeatures::known(), InitFeatures::known());
let chan_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 190000, 1001, InitFeatures::known(), InitFeatures::known());
- let logger = test_utils::TestLogger::new();
let mut stat01 = get_channel_value_stat!(nodes[0], chan_1.2);
let mut stat11 = get_channel_value_stat!(nodes[1], chan_1.2);
let mut stat12 = get_channel_value_stat!(nodes[1], chan_2.2);
let mut stat22 = get_channel_value_stat!(nodes[2], chan_2.2);
- macro_rules! get_route_and_payment_hash {
- ($recv_value: expr) => {{
- let (payment_preimage, payment_hash) = get_payment_preimage_hash!(nodes[0]);
- let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes.last().unwrap().node.get_our_node_id(), None, None, &Vec::new(), $recv_value, TEST_FINAL_CLTV, &logger).unwrap();
- (route, payment_hash, payment_preimage)
- }}
- }
-
macro_rules! expect_forward {
($node: expr) => {{
let mut events = $node.node.get_and_clear_pending_msg_events();
// attempt to send amt_msat > their_max_htlc_value_in_flight_msat
{
- let (mut route, our_payment_hash, _) = get_route_and_payment_hash!(recv_value_0);
+ let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_0);
route.paths[0].last_mut().unwrap().fee_msat += 1;
assert!(route.paths[0].iter().rev().skip(1).all(|h| h.fee_msat == feemsat));
- unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { ref err },
+ unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)), true, APIError::ChannelUnavailable { ref err },
assert!(regex::Regex::new(r"Cannot send value that would put us over the max HTLC value in flight our peer will accept \(\d+\)").unwrap().is_match(err)));
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
nodes[0].logger.assert_log_contains("lightning::ln::channelmanager".to_string(), "Cannot send value that would put us over the max HTLC value in flight our peer will accept".to_string(), 1);
if stat01.value_to_self_msat < stat01.channel_reserve_msat + commit_tx_fee_all_htlcs + ensure_htlc_amounts_above_dust_buffer + amt_msat {
break;
}
- send_payment(&nodes[0], &vec![&nodes[1], &nodes[2]][..], recv_value_0, recv_value_0);
+ send_payment(&nodes[0], &vec![&nodes[1], &nodes[2]][..], recv_value_0);
let (stat01_, stat11_, stat12_, stat22_) = (
get_channel_value_stat!(nodes[0], chan_1.2),
let recv_value_1 = (stat01.value_to_self_msat - stat01.channel_reserve_msat - total_fee_msat - commit_tx_fee_2_htlcs)/2;
let amt_msat_1 = recv_value_1 + total_fee_msat;
- let (route_1, our_payment_hash_1, our_payment_preimage_1) = get_route_and_payment_hash!(recv_value_1);
+ let (route_1, our_payment_hash_1, our_payment_preimage_1, our_payment_secret_1) = get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_1);
let payment_event_1 = {
- nodes[0].node.send_payment(&route_1, our_payment_hash_1, &None).unwrap();
+ nodes[0].node.send_payment(&route_1, our_payment_hash_1, &Some(our_payment_secret_1)).unwrap();
check_added_monitors!(nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
// channel reserve test with htlc pending output > 0
let recv_value_2 = stat01.value_to_self_msat - amt_msat_1 - stat01.channel_reserve_msat - total_fee_msat - commit_tx_fee_2_htlcs;
{
- let (route, our_payment_hash, _) = get_route_and_payment_hash!(recv_value_2 + 1);
- unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { ref err },
+ let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_2 + 1);
+ unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)), true, APIError::ChannelUnavailable { ref err },
assert!(regex::Regex::new(r"Cannot send value that would put our balance under counterparty-announced channel reserve value \(\d+\)").unwrap().is_match(err)));
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
}
}
// now see if they go through on both sides
- let (route_21, our_payment_hash_21, our_payment_preimage_21) = get_route_and_payment_hash!(recv_value_21);
+ let (route_21, our_payment_hash_21, our_payment_preimage_21, our_payment_secret_21) = get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_21);
// but this will stuck in the holding cell
- nodes[0].node.send_payment(&route_21, our_payment_hash_21, &None).unwrap();
+ nodes[0].node.send_payment(&route_21, our_payment_hash_21, &Some(our_payment_secret_21)).unwrap();
check_added_monitors!(nodes[0], 0);
let events = nodes[0].node.get_and_clear_pending_events();
assert_eq!(events.len(), 0);
// test with outbound holding cell amount > 0
{
- let (route, our_payment_hash, _) = get_route_and_payment_hash!(recv_value_22+1);
- unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { ref err },
+ let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_22+1);
+ unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)), true, APIError::ChannelUnavailable { ref err },
assert!(regex::Regex::new(r"Cannot send value that would put our balance under counterparty-announced channel reserve value \(\d+\)").unwrap().is_match(err)));
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
nodes[0].logger.assert_log_contains("lightning::ln::channelmanager".to_string(), "Cannot send value that would put our balance under counterparty-announced channel reserve value".to_string(), 2);
}
- let (route_22, our_payment_hash_22, our_payment_preimage_22) = get_route_and_payment_hash!(recv_value_22);
+ let (route_22, our_payment_hash_22, our_payment_preimage_22, our_payment_secret_22) = get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_22);
// this will also stuck in the holding cell
- nodes[0].node.send_payment(&route_22, our_payment_hash_22, &None).unwrap();
+ nodes[0].node.send_payment(&route_22, our_payment_hash_22, &Some(our_payment_secret_22)).unwrap();
check_added_monitors!(nodes[0], 0);
assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
commitment_signed_dance!(nodes[2], nodes[1], payment_event_11.commitment_msg, false);
expect_pending_htlcs_forwardable!(nodes[2]);
- expect_payment_received!(nodes[2], our_payment_hash_1, recv_value_1);
+ expect_payment_received!(nodes[2], our_payment_hash_1, our_payment_secret_1, recv_value_1);
// flush the htlcs in the holding cell
assert_eq!(commitment_update_2.update_add_htlcs.len(), 2);
let events = nodes[2].node.get_and_clear_pending_events();
assert_eq!(events.len(), 2);
match events[0] {
- Event::PaymentReceived { ref payment_hash, ref payment_secret, amt } => {
+ Event::PaymentReceived { ref payment_hash, ref payment_preimage, ref payment_secret, amt, user_payment_id: _ } => {
assert_eq!(our_payment_hash_21, *payment_hash);
- assert_eq!(*payment_secret, None);
+ assert!(payment_preimage.is_none());
+ assert_eq!(our_payment_secret_21, *payment_secret);
assert_eq!(recv_value_21, amt);
},
_ => panic!("Unexpected event"),
}
match events[1] {
- Event::PaymentReceived { ref payment_hash, ref payment_secret, amt } => {
+ Event::PaymentReceived { ref payment_hash, ref payment_preimage, ref payment_secret, amt, user_payment_id: _ } => {
assert_eq!(our_payment_hash_22, *payment_hash);
- assert_eq!(None, *payment_secret);
+ assert!(payment_preimage.is_none());
+ assert_eq!(our_payment_secret_22, *payment_secret);
assert_eq!(recv_value_22, amt);
},
_ => panic!("Unexpected event"),
}
- claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), our_payment_preimage_1, recv_value_1);
- claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), our_payment_preimage_21, recv_value_21);
- claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), our_payment_preimage_22, recv_value_22);
+ claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), our_payment_preimage_1);
+ claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), our_payment_preimage_21);
+ claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), our_payment_preimage_22);
let commit_tx_fee_0_htlcs = 2*commit_tx_fee_msat(feerate, 1);
let recv_value_3 = commit_tx_fee_2_htlcs - commit_tx_fee_0_htlcs - total_fee_msat;
- send_payment(&nodes[0], &vec![&nodes[1], &nodes[2]][..], recv_value_3, recv_value_3);
+ send_payment(&nodes[0], &vec![&nodes[1], &nodes[2]][..], recv_value_3);
let commit_tx_fee_1_htlc = 2*commit_tx_fee_msat(feerate, 1 + 1);
let expected_value_to_self = stat01.value_to_self_msat - (recv_value_1 + total_fee_msat) - (recv_value_21 + total_fee_msat) - (recv_value_22 + total_fee_msat) - (recv_value_3 + total_fee_msat);
let b_chan_values = get_channel_value_stat!(nodes[1], chan_1.2);
// Route the first two HTLCs.
- let (payment_preimage_1, _) = route_payment(&nodes[0], &[&nodes[1]], b_chan_values.channel_reserve_msat - b_chan_values.value_to_self_msat - 10000);
- let (payment_preimage_2, _) = route_payment(&nodes[0], &[&nodes[1]], 20000);
+ let (payment_preimage_1, _, _) = route_payment(&nodes[0], &[&nodes[1]], b_chan_values.channel_reserve_msat - b_chan_values.value_to_self_msat - 10000);
+ let (payment_preimage_2, _, _) = route_payment(&nodes[0], &[&nodes[1]], 20000);
// Start routing the third HTLC (this is just used to get everyone in the right state).
- let (payment_preimage_3, payment_hash_3) = get_payment_preimage_hash!(nodes[0]);
+ let (payment_preimage_3, payment_hash_3, payment_secret_3) = get_payment_preimage_hash!(nodes[1]);
let send_1 = {
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, payment_hash_3, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash_3, &Some(payment_secret_3)).unwrap();
check_added_monitors!(nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
// Now claim both of the first two HTLCs on B's end, putting B in AwaitingRAA and generating an
// initial fulfill/CS.
- assert!(nodes[1].node.claim_funds(payment_preimage_1, &None, b_chan_values.channel_reserve_msat - b_chan_values.value_to_self_msat - 10000));
+ assert!(nodes[1].node.claim_funds(payment_preimage_1));
check_added_monitors!(nodes[1], 1);
let bs_removes = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
// This claim goes in B's holding cell, allowing us to have a pending B->A RAA which does not
// remove the second HTLC when we send the HTLC back from B to A.
- assert!(nodes[1].node.claim_funds(payment_preimage_2, &None, 20000));
+ assert!(nodes[1].node.claim_funds(payment_preimage_2));
check_added_monitors!(nodes[1], 1);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
expect_pending_htlcs_forwardable!(nodes[1]);
- expect_payment_received!(nodes[1], payment_hash_3, 100000);
+ expect_payment_received!(nodes[1], payment_hash_3, payment_secret_3, 100000);
// Note that as this RAA was generated before the delivery of the update_fulfill it shouldn't
// resolve the second HTLC from A's point of view.
// Now that B doesn't have the second RAA anymore, but A still does, send a payment from B back
// to A to ensure that A doesn't count the almost-removed HTLC in update_add processing.
- let (payment_preimage_4, payment_hash_4) = get_payment_preimage_hash!(nodes[1]);
+ let (payment_preimage_4, payment_hash_4, payment_secret_4) = get_payment_preimage_hash!(nodes[0]);
let send_2 = {
let net_graph_msg_handler = &nodes[1].net_graph_msg_handler;
- let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), None, None, &[], 10000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[1].node.send_payment(&route, payment_hash_4, &None).unwrap();
+ let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 10000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[1].node.send_payment(&route, payment_hash_4, &Some(payment_secret_4)).unwrap();
check_added_monitors!(nodes[1], 1);
let mut events = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
check_added_monitors!(nodes[0], 1);
expect_pending_htlcs_forwardable!(nodes[0]);
- expect_payment_received!(nodes[0], payment_hash_4, 10000);
+ expect_payment_received!(nodes[0], payment_hash_4, payment_secret_4, 10000);
- claim_payment(&nodes[1], &[&nodes[0]], payment_preimage_4, 10_000);
- claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_3, 100_000);
+ claim_payment(&nodes[1], &[&nodes[0]], payment_preimage_4);
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_3);
}
#[test]
connect_blocks(&nodes[4], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[4].best_block_info().1);
// Rebalance the network a bit by relaying one payment through all the channels...
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000, 8_000_000);
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000, 8_000_000);
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000, 8_000_000);
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000, 8_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000);
+ send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000);
+ send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000);
+ send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000);
// Simple case with no pending HTLCs:
nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), true);
assert_eq!(nodes[2].node.list_channels().len(), 1);
macro_rules! claim_funds {
- ($node: expr, $prev_node: expr, $preimage: expr, $amount: expr) => {
+ ($node: expr, $prev_node: expr, $preimage: expr) => {
{
- assert!($node.node.claim_funds($preimage, &None, $amount));
+ assert!($node.node.claim_funds($preimage));
check_added_monitors!($node, 1);
let events = $node.node.get_and_clear_pending_msg_events();
node2_commitment_txid = node_txn[0].txid();
// Claim the payment on nodes[3], giving it knowledge of the preimage
- claim_funds!(nodes[3], nodes[2], payment_preimage_1, 3_000_000);
+ claim_funds!(nodes[3], nodes[2], payment_preimage_1);
mine_transaction(&nodes[3], &node_txn[0]);
check_added_monitors!(nodes[3], 1);
check_preimage_claim(&nodes[3], &node_txn);
let node_txn = test_txn_broadcast(&nodes[3], &chan_4, None, HTLCType::TIMEOUT);
// Claim the payment on nodes[4], giving it knowledge of the preimage
- claim_funds!(nodes[4], nodes[3], payment_preimage_2, 3_000_000);
+ claim_funds!(nodes[4], nodes[3], payment_preimage_2);
connect_blocks(&nodes[4], TEST_FINAL_CLTV - CLTV_CLAIM_BUFFER + 2);
let events = nodes[4].node.get_and_clear_pending_msg_events();
assert_eq!(revoked_local_txn[1].input[0].previous_output.txid, revoked_local_txn[0].txid());
assert_eq!(revoked_local_txn[1].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); // HTLC-Timeout
// Revoke the old state
- claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_3, 3_000_000);
+ claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_3);
{
mine_transaction(&nodes[1], &revoked_local_txn[0]);
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_6.3.txid());
assert_eq!(revoked_local_txn[0].output.len(), 2); // Only HTLC and output back to A are present
// Revoke the old state
- claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_4, 3_000_000);
+ claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_4);
{
mine_transaction(&nodes[0], &revoked_local_txn[0]);
{
// Only output is the full channel value back to nodes[0]:
assert_eq!(revoked_local_txn[0].output.len(), 1);
// Send a payment through, updating everyone's latest commitment txn
- send_payment(&nodes[0], &vec!(&nodes[1])[..], 5000000, 5_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1])[..], 5000000);
// Inform nodes[1] that nodes[0] broadcast a stale tx
mine_transaction(&nodes[1], &revoked_local_txn[0]);
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
// Rebalance the network to generate htlc in the two directions
- send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000, 8_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
// node[0] is gonna to revoke an old state thus node[1] should be able to claim both offered/received HTLC outputs on top of commitment tx
let payment_preimage_1 = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
- let (_payment_preimage_2, payment_hash_2) = route_payment(&nodes[1], &vec!(&nodes[0])[..], 3000000);
+ let (_payment_preimage_2, payment_hash_2, _) = route_payment(&nodes[1], &vec!(&nodes[0])[..], 3000000);
// Get the will-be-revoked local txn from node[0]
let revoked_local_txn = get_local_commitment_txn!(nodes[0], chan_1.2);
check_spends!(revoked_local_txn[1], revoked_local_txn[0]);
//Revoke the old state
- claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_1, 3_000_000);
+ claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_1);
{
mine_transaction(&nodes[0], &revoked_local_txn[0]);
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
// Rebalance the network to generate htlc in the two directions
- send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000, 8_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
// node[0] is gonna to revoke an old state thus node[1] should be able to claim both offered/received HTLC outputs on top of commitment tx, but this
// time as two different claim transactions as we're gonna to timeout htlc with given a high current height
let payment_preimage_1 = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
- let (_payment_preimage_2, payment_hash_2) = route_payment(&nodes[1], &vec!(&nodes[0])[..], 3000000);
+ let (_payment_preimage_2, payment_hash_2, _payment_secret_2) = route_payment(&nodes[1], &vec!(&nodes[0])[..], 3000000);
// Get the will-be-revoked local txn from node[0]
let revoked_local_txn = get_local_commitment_txn!(nodes[0], chan_1.2);
//Revoke the old state
- claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_1, 3_000_000);
+ claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_1);
{
confirm_transaction_at(&nodes[0], &revoked_local_txn[0], 100);
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
// Rebalance the network a bit by relaying one payment through all the channels...
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000, 8_000_000);
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000, 8_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000);
+ send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000);
- let (our_payment_preimage, _payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), 3000000);
- let (our_payment_preimage_2, _payment_hash_2) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), 3000000);
+ let (our_payment_preimage, _payment_hash, _payment_secret) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), 3000000);
+ let (our_payment_preimage_2, _payment_hash_2, _payment_secret_2) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), 3000000);
// Broadcast legit commitment tx from C on B's chain
// Broadcast HTLC Success transaction by C on received output from C's commitment tx on B's chain
let commitment_tx = get_local_commitment_txn!(nodes[2], chan_2.2);
assert_eq!(commitment_tx.len(), 1);
check_spends!(commitment_tx[0], chan_2.3);
- nodes[2].node.claim_funds(our_payment_preimage, &None, 3_000_000);
- nodes[2].node.claim_funds(our_payment_preimage_2, &None, 3_000_000);
+ nodes[2].node.claim_funds(our_payment_preimage);
+ nodes[2].node.claim_funds(our_payment_preimage_2);
check_added_monitors!(nodes[2], 2);
let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
assert!(updates.update_add_htlcs.is_empty());
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
// Rebalance the network a bit by relaying one payment thorugh all the channels...
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000, 8_000_000);
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000, 8_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000);
+ send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000);
- let (_payment_preimage, payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), 3000000);
+ let (_payment_preimage, payment_hash, _payment_secret) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), 3000000);
// Broadcast legit commitment tx from C on B's chain
let commitment_tx = get_local_commitment_txn!(nodes[2], chan_2.2);
check_spends!(commitment_tx[0], chan_2.3);
- nodes[2].node.fail_htlc_backwards(&payment_hash, &None);
+ nodes[2].node.fail_htlc_backwards(&payment_hash);
check_added_monitors!(nodes[2], 0);
expect_pending_htlcs_forwardable!(nodes[2]);
check_added_monitors!(nodes[2], 1);
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
- let (payment_preimage, _payment_hash) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3000000);
+ let (payment_preimage, _payment_hash, _payment_secret) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3000000);
// Get the will-be-revoked local txn from nodes[2]
let revoked_local_txn = get_local_commitment_txn!(nodes[2], chan_2.2);
// Revoke the old state
- claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage, 3_000_000);
+ claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);
- let (_, payment_hash) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3000000);
+ let (_, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3000000);
mine_transaction(&nodes[1], &revoked_local_txn[0]);
connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1);
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
- let (payment_preimage, _payment_hash) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], if no_to_remote { 10_000 } else { 3_000_000 });
+ let (payment_preimage, _payment_hash, _payment_secret) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], if no_to_remote { 10_000 } else { 3_000_000 });
// Get the will-be-revoked local txn from nodes[2]
let revoked_local_txn = get_local_commitment_txn!(nodes[2], chan_2.2);
assert_eq!(revoked_local_txn[0].output.len(), if no_to_remote { 1 } else { 2 });
// Revoke the old state
- claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage, if no_to_remote { 10_000 } else { 3_000_000});
+ claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);
let value = if use_dust {
// The dust limit applied to HTLC outputs considers the fee of the HTLC transaction as
nodes[2].node.channel_state.lock().unwrap().by_id.get(&chan_2.2).unwrap().holder_dust_limit_satoshis * 1000
} else { 3000000 };
- let (_, first_payment_hash) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], value);
- let (_, second_payment_hash) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], value);
- let (_, third_payment_hash) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], value);
+ let (_, first_payment_hash, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], value);
+ let (_, second_payment_hash, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], value);
+ let (_, third_payment_hash, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], value);
- assert!(nodes[2].node.fail_htlc_backwards(&first_payment_hash, &None));
+ assert!(nodes[2].node.fail_htlc_backwards(&first_payment_hash));
expect_pending_htlcs_forwardable!(nodes[2]);
check_added_monitors!(nodes[2], 1);
let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
let bs_raa = commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false, true, false, true);
// Drop the last RAA from 3 -> 2
- assert!(nodes[2].node.fail_htlc_backwards(&second_payment_hash, &None));
+ assert!(nodes[2].node.fail_htlc_backwards(&second_payment_hash));
expect_pending_htlcs_forwardable!(nodes[2]);
check_added_monitors!(nodes[2], 1);
let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
nodes[2].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &as_raa);
check_added_monitors!(nodes[2], 1);
- assert!(nodes[2].node.fail_htlc_backwards(&third_payment_hash, &None));
+ assert!(nodes[2].node.fail_htlc_backwards(&third_payment_hash));
expect_pending_htlcs_forwardable!(nodes[2]);
check_added_monitors!(nodes[2], 1);
let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
// Add a fourth HTLC, this one will get sequestered away in nodes[1]'s holding cell waiting
// on nodes[2]'s RAA.
- let (_, fourth_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, fourth_payment_hash, fourth_payment_secret) = get_payment_preimage_hash!(nodes[2]);
let net_graph_msg_handler = &nodes[1].net_graph_msg_handler;
let logger = test_utils::TestLogger::new();
- let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[1].node.send_payment(&route, fourth_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[1].node.send_payment(&route, fourth_payment_hash, &Some(fourth_payment_secret)).unwrap();
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
check_added_monitors!(nodes[1], 0);
// Alice -> Bob: Route a payment but without Bob sending revoke_and_ack.
{
- let (_, payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[1]);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &Vec::new(), 50_000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 50_000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
let payment_event = {
}
// Alice -> Bob: Route another payment but now Alice waits for Bob's earlier revoke_and_ack.
- let (_, failed_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, failed_payment_hash, failed_payment_secret) = get_payment_preimage_hash!(nodes[1]);
{
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &Vec::new(), 50_000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, failed_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 50_000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, failed_payment_hash, &Some(failed_payment_secret)).unwrap();
check_added_monitors!(nodes[0], 0);
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
// Alice <- Bob: Send a malformed update_add_htlc so Alice fails the channel.
{
- let (_, payment_hash) = get_payment_preimage_hash!(nodes[1]);
+ let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[0]);
let secp_ctx = Secp256k1::new();
let session_priv = SecretKey::from_slice(&[42; 32]).unwrap();
let current_height = nodes[1].node.best_block.read().unwrap().height() + 1;
let net_graph_msg_handler = &nodes[1].net_graph_msg_handler;
- let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), None, None, &Vec::new(), 50_000, TEST_FINAL_CLTV, &logger).unwrap();
- let (onion_payloads, _amount_msat, cltv_expiry) = onion_utils::build_onion_payloads(&route.paths[0], 50_000, &None, current_height).unwrap();
+ let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 50_000, TEST_FINAL_CLTV, &logger).unwrap();
+ let (onion_payloads, _amount_msat, cltv_expiry) = onion_utils::build_onion_payloads(&route.paths[0], 50_000, &Some(payment_secret), current_height).unwrap();
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap();
let onion_routing_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash);
create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
let logger = test_utils::TestLogger::new();
- let (our_payment_preimage, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (our_payment_preimage, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[2]);
let mut payment_event = {
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), None, None, &Vec::new(), 1000000, 42, &logger).unwrap();
- nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, 42, &logger).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
let payment_preimage_1 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).0;
let payment_hash_2 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).1;
fail_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_hash_2);
- claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_preimage_1, 1_000_000);
+ claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_preimage_1);
nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
- claim_payment_along_route(&nodes[0], &vec!(&nodes[1], &nodes[2]), true, payment_preimage_3, 1_000_000);
+ claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], true, payment_preimage_3);
fail_payment_along_route(&nodes[0], &[&nodes[1], &nodes[2]], true, payment_hash_5);
reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (1, 0), (1, 0), (false, false));
}
}
- claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_preimage_4, 1_000_000);
+ claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_preimage_4);
fail_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_hash_6);
}
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
}
- let (payment_preimage_1, payment_hash_1) = get_payment_preimage_hash!(nodes[0]);
+ let (payment_preimage_1, payment_hash_1, payment_secret_1) = get_payment_preimage_hash!(nodes[1]);
let logger = test_utils::TestLogger::new();
let payment_event = {
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(),
- &nodes[1].node.get_our_node_id(), None, Some(&nodes[0].node.list_usable_channels().iter().collect::<Vec<_>>()),
+ &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), Some(&nodes[0].node.list_usable_channels().iter().collect::<Vec<_>>()),
&Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, payment_hash_1, &None).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash_1, &Some(payment_secret_1)).unwrap();
check_added_monitors!(nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
let events_2 = nodes[1].node.get_and_clear_pending_events();
assert_eq!(events_2.len(), 1);
match events_2[0] {
- Event::PaymentReceived { ref payment_hash, ref payment_secret, amt } => {
+ Event::PaymentReceived { ref payment_hash, ref payment_preimage, ref payment_secret, amt, user_payment_id: _ } => {
assert_eq!(payment_hash_1, *payment_hash);
- assert_eq!(*payment_secret, None);
+ assert!(payment_preimage.is_none());
+ assert_eq!(payment_secret_1, *payment_secret);
assert_eq!(amt, 1000000);
},
_ => panic!("Unexpected event"),
}
- nodes[1].node.claim_funds(payment_preimage_1, &None, 1_000_000);
+ nodes[1].node.claim_funds(payment_preimage_1);
check_added_monitors!(nodes[1], 1);
let events_3 = nodes[1].node.get_and_clear_pending_msg_events();
// Channel should still work fine...
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(),
- &nodes[1].node.get_our_node_id(), None, Some(&nodes[0].node.list_usable_channels().iter().collect::<Vec<_>>()),
+ &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), Some(&nodes[0].node.list_usable_channels().iter().collect::<Vec<_>>()),
&Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
let payment_preimage_2 = send_along_route(&nodes[0], route, &[&nodes[1]], 1000000).0;
- claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_2, 1_000_000);
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_2);
}
#[test]
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
let logger = test_utils::TestLogger::new();
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- let (payment_preimage, _) = send_along_route(&nodes[0], route, &[&nodes[1]], 1000000);
- claim_payment(&nodes[0], &[&nodes[1]], payment_preimage, 1_000_000);
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ let (payment_preimage, _, _) = send_along_route(&nodes[0], route, &[&nodes[1]], 1000000);
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage);
}
#[test]
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
let logger = test_utils::TestLogger::new();
- let (payment_preimage_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
+ let (payment_preimage_1, _, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
// Now try to send a second payment which will fail to send
- let (payment_preimage_2, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
+ let (payment_preimage_2, payment_hash_2, payment_secret_2) = get_payment_preimage_hash!(nodes[1]);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, payment_hash_2, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash_2, &Some(payment_secret_2)).unwrap();
check_added_monitors!(nodes[0], 1);
let events_1 = nodes[0].node.get_and_clear_pending_msg_events();
_ => panic!("Unexpected event"),
}
- assert!(nodes[1].node.claim_funds(payment_preimage_1, &None, 1_000_000));
+ assert!(nodes[1].node.claim_funds(payment_preimage_1));
check_added_monitors!(nodes[1], 1);
let events_2 = nodes[1].node.get_and_clear_pending_msg_events();
let events_5 = nodes[1].node.get_and_clear_pending_events();
assert_eq!(events_5.len(), 1);
match events_5[0] {
- Event::PaymentReceived { ref payment_hash, ref payment_secret, amt: _ } => {
+ Event::PaymentReceived { ref payment_hash, ref payment_preimage, ref payment_secret, amt: _, user_payment_id: _ } => {
assert_eq!(payment_hash_2, *payment_hash);
- assert_eq!(*payment_secret, None);
+ assert!(payment_preimage.is_none());
+ assert_eq!(payment_secret_2, *payment_secret);
},
_ => panic!("Unexpected event"),
}
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
check_added_monitors!(nodes[0], 1);
- claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_2, 1_000_000);
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_2);
}
fn do_test_htlc_timeout(send_partial_mpp: bool) {
let our_payment_hash = if send_partial_mpp {
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &Vec::new(), 100000, TEST_FINAL_CLTV, &logger).unwrap();
- let (_, our_payment_hash) = get_payment_preimage_hash!(&nodes[0]);
- let payment_secret = PaymentSecret([0xdb; 32]);
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 100000, TEST_FINAL_CLTV, &logger).unwrap();
+ let (_, our_payment_hash, payment_secret) = get_payment_preimage_hash!(&nodes[1]);
// Use the utility function send_payment_along_path to send the payment with MPP data which
// indicates there are more HTLCs coming.
let cur_height = CHAN_CONFIRM_DEPTH + 1; // route_payment calls send_payment, which adds 1 to the current height. So we do the same here to match.
assert_eq!(events.len(), 1);
// Now do the relevant commitment_signed/RAA dances along the path, noting that the final
// hop should *not* yet generate any PaymentReceived event(s).
- pass_along_path(&nodes[0], &[&nodes[1]], 100000, our_payment_hash, Some(payment_secret), events.drain(..).next().unwrap(), false);
+ pass_along_path(&nodes[0], &[&nodes[1]], 100000, our_payment_hash, payment_secret, events.drain(..).next().unwrap(), false);
our_payment_hash
} else {
route_payment(&nodes[0], &[&nodes[1]], 100000).1
let logger = test_utils::TestLogger::new();
// Route a first payment to get the 1 -> 2 channel in awaiting_raa...
- let (_, first_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, first_payment_hash, first_payment_secret) = get_payment_preimage_hash!(nodes[2]);
{
let net_graph_msg_handler = &nodes[1].net_graph_msg_handler;
- let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), None, None, &Vec::new(), 100000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[1].node.send_payment(&route, first_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 100000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[1].node.send_payment(&route, first_payment_hash, &Some(first_payment_secret)).unwrap();
}
assert_eq!(nodes[1].node.get_and_clear_pending_msg_events().len(), 1);
check_added_monitors!(nodes[1], 1);
// Now attempt to route a second payment, which should be placed in the holding cell
- let (_, second_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, second_payment_hash, second_payment_secret) = get_payment_preimage_hash!(nodes[2]);
if forwarded_htlc {
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), None, None, &Vec::new(), 100000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, second_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 100000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, second_payment_hash, &Some(first_payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
let payment_event = SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0));
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
check_added_monitors!(nodes[1], 0);
} else {
let net_graph_msg_handler = &nodes[1].net_graph_msg_handler;
- let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), None, None, &Vec::new(), 100000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[1].node.send_payment(&route, second_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 100000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[1].node.send_payment(&route, second_payment_hash, &Some(second_payment_secret)).unwrap();
check_added_monitors!(nodes[1], 0);
}
node.net_graph_msg_handler.handle_channel_update(&bs_update).unwrap();
}
- send_payment(&nodes[0], &[&nodes[1]], 1000000, 1_000_000);
+ send_payment(&nodes[0], &[&nodes[1]], 1000000);
}
#[test]
node.net_graph_msg_handler.handle_channel_update(&bs_update).unwrap();
}
- send_payment(&nodes[0], &[&nodes[1]], 1000000, 1_000_000);
+ send_payment(&nodes[0], &[&nodes[1]], 1000000);
}
#[test]
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let (our_payment_preimage, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
- let (_, our_payment_hash) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
+ let (our_payment_preimage, _, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
+ let (_, our_payment_hash, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
fail_payment(&nodes[0], &[&nodes[1]], our_payment_hash);
- claim_payment(&nodes[0], &[&nodes[1]], our_payment_preimage, 1_000_000);
+ claim_payment(&nodes[0], &[&nodes[1]], our_payment_preimage);
}
#[test]
node_0_stale_monitors_serialized.push(writer.0);
}
- let (our_payment_preimage, _) = route_payment(&nodes[2], &[&nodes[0], &nodes[1]], 1000000);
+ let (our_payment_preimage, _, _) = route_payment(&nodes[2], &[&nodes[0], &nodes[1]], 1000000);
// Serialize the ChannelManager here, but the monitor we keep up-to-date
let nodes_0_serialized = nodes[0].node.encode();
reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
reconnect_nodes(&nodes[0], &nodes[2], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
//... and we can even still claim the payment!
- claim_payment(&nodes[2], &[&nodes[0], &nodes[1]], our_payment_preimage, 1_000_000);
+ claim_payment(&nodes[2], &[&nodes[0], &nodes[1]], our_payment_preimage);
nodes[3].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
let reestablish = get_event_msg!(nodes[3], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
assert_eq!(revoked_local_txn[0].input.len(), 1);
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan.3.txid());
- claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage, 3_000_000);
+ claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage);
mine_transaction(&nodes[1], &revoked_local_txn[0]);
check_closed_broadcast!(nodes[1], true);
check_added_monitors!(nodes[1], 1);
assert_eq!(commitment_tx[0].input[0].previous_output.txid, chan_1.3.txid());
// Settle A's commitment tx on B's chain
- assert!(nodes[1].node.claim_funds(payment_preimage, &None, 3_000_000));
+ assert!(nodes[1].node.claim_funds(payment_preimage));
check_added_monitors!(nodes[1], 1);
mine_transaction(&nodes[1], &commitment_tx[0]);
check_added_monitors!(nodes[1], 1);
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
// Rebalance the network a bit by relaying one payment through all the channels ...
- send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000, 8_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
- let (_, our_payment_hash) = route_payment(&nodes[1], &vec!(&nodes[0])[..], 3_000_000);
+ let (_, our_payment_hash, _) = route_payment(&nodes[1], &vec!(&nodes[0])[..], 3_000_000);
let commitment_tx = get_local_commitment_txn!(nodes[0], chan_1.2);
assert_eq!(commitment_tx[0].input.len(), 1);
assert_eq!(revoked_local_txn[0].input.len(), 1);
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid());
- claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage, 3_000_000);
+ claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage);
mine_transaction(&nodes[1], &revoked_local_txn[0]);
check_closed_broadcast!(nodes[1], true);
assert_eq!(revoked_local_txn[0].input.len(), 1);
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid());
- claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage, 3_000_000);
+ claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage);
// A will generate HTLC-Timeout from revoked commitment tx
mine_transaction(&nodes[0], &revoked_local_txn[0]);
// The to-be-revoked commitment tx should have one HTLC and one to_remote output
assert_eq!(revoked_local_txn[0].output.len(), 2);
- claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage, 3_000_000);
+ claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage);
// B will generate HTLC-Success from revoked commitment tx
mine_transaction(&nodes[1], &revoked_local_txn[0]);
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
// Rebalance the network a bit by relaying one payment through all the channels ...
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000, 8_000_000);
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000, 8_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000);
+ send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000);
- let (payment_preimage, _payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), 3000000);
+ let (payment_preimage, _payment_hash, _payment_secret) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), 3000000);
let commitment_tx = get_local_commitment_txn!(nodes[2], chan_2.2);
check_spends!(commitment_tx[0], chan_2.3);
- nodes[2].node.claim_funds(payment_preimage, &None, 3_000_000);
+ nodes[2].node.claim_funds(payment_preimage);
check_added_monitors!(nodes[2], 1);
let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
assert!(updates.update_add_htlcs.is_empty());
#[test]
fn test_duplicate_payment_hash_one_failure_one_success() {
- // Topology : A --> B --> C
+ // Topology : A --> B --> C --> D
// We route 2 payments with same hash between B and C, one will be timeout, the other successfully claim
- let chanmon_cfgs = create_chanmon_cfgs(3);
- let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
- let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
- let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+ // Note that because C will refuse to generate two payment secrets for the same payment hash,
+ // we forward one of the payments onwards to D.
+ let chanmon_cfgs = create_chanmon_cfgs(4);
+ let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
+ let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
+ let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs);
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+ create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known());
- let (our_payment_preimage, duplicate_payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 900000);
- *nodes[0].network_payment_count.borrow_mut() -= 1;
- assert_eq!(route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 900000).1, duplicate_payment_hash);
+ let (our_payment_preimage, duplicate_payment_hash, _) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 900000);
+
+ let payment_secret = nodes[3].node.create_inbound_payment_for_hash(duplicate_payment_hash, None, 7200, 0).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &nodes[0].net_graph_msg_handler.network_graph.read().unwrap(),
+ &nodes[3].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 900000, TEST_FINAL_CLTV, nodes[0].logger).unwrap();
+ send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[2], &nodes[3]]], 900000, duplicate_payment_hash, payment_secret);
let commitment_txn = get_local_commitment_txn!(nodes[2], chan_2.2);
assert_eq!(commitment_txn[0].input.len(), 1);
htlc_timeout_tx = node_txn[1].clone();
}
- nodes[2].node.claim_funds(our_payment_preimage, &None, 900_000);
+ nodes[2].node.claim_funds(our_payment_preimage);
mine_transaction(&nodes[2], &commitment_txn[0]);
- check_added_monitors!(nodes[2], 3);
+ check_added_monitors!(nodes[2], 2);
let events = nodes[2].node.get_and_clear_pending_msg_events();
match events[0] {
MessageSendEvent::UpdateHTLCs { .. } => {},
check_spends!(local_txn[0], chan_1.3);
// Give B knowledge of preimage to be able to generate a local HTLC-Success Tx
- nodes[1].node.claim_funds(payment_preimage, &None, 9_000_000);
+ nodes[1].node.claim_funds(payment_preimage);
check_added_monitors!(nodes[1], 1);
mine_transaction(&nodes[1], &local_txn[0]);
check_added_monitors!(nodes[1], 1);
create_announced_chan_between_nodes(&nodes, 3, 5, InitFeatures::known(), InitFeatures::known());
// Rebalance and check output sanity...
- send_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 500000, 500_000);
- send_payment(&nodes[1], &[&nodes[2], &nodes[3], &nodes[5]], 500000, 500_000);
+ send_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 500000);
+ send_payment(&nodes[1], &[&nodes[2], &nodes[3], &nodes[5]], 500000);
assert_eq!(get_local_commitment_txn!(nodes[3], chan.2)[0].output.len(), 2);
let ds_dust_limit = nodes[3].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().holder_dust_limit_satoshis;
// 0th HTLC:
- let (_, payment_hash_1) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], ds_dust_limit*1000); // not added < dust limit + HTLC tx fee
+ let (_, payment_hash_1, _) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], ds_dust_limit*1000); // not added < dust limit + HTLC tx fee
// 1st HTLC:
- let (_, payment_hash_2) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], ds_dust_limit*1000); // not added < dust limit + HTLC tx fee
+ let (_, payment_hash_2, _) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], ds_dust_limit*1000); // not added < dust limit + HTLC tx fee
let net_graph_msg_handler = &nodes[1].net_graph_msg_handler;
let our_node_id = &nodes[1].node.get_our_node_id();
- let route = get_route(our_node_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[5].node.get_our_node_id(), None, None, &Vec::new(), ds_dust_limit*1000, TEST_FINAL_CLTV, &logger).unwrap();
+ let route = get_route(our_node_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[5].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), ds_dust_limit*1000, TEST_FINAL_CLTV, &logger).unwrap();
// 2nd HTLC:
- send_along_route_with_hash(&nodes[1], route.clone(), &[&nodes[2], &nodes[3], &nodes[5]], ds_dust_limit*1000, payment_hash_1); // not added < dust limit + HTLC tx fee
+ send_along_route_with_secret(&nodes[1], route.clone(), &[&[&nodes[2], &nodes[3], &nodes[5]]], ds_dust_limit*1000, payment_hash_1, nodes[5].node.create_inbound_payment_for_hash(payment_hash_1, None, 7200, 0).unwrap()); // not added < dust limit + HTLC tx fee
// 3rd HTLC:
- send_along_route_with_hash(&nodes[1], route, &[&nodes[2], &nodes[3], &nodes[5]], ds_dust_limit*1000, payment_hash_2); // not added < dust limit + HTLC tx fee
+ send_along_route_with_secret(&nodes[1], route, &[&[&nodes[2], &nodes[3], &nodes[5]]], ds_dust_limit*1000, payment_hash_2, nodes[5].node.create_inbound_payment_for_hash(payment_hash_2, None, 7200, 0).unwrap()); // not added < dust limit + HTLC tx fee
// 4th HTLC:
- let (_, payment_hash_3) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 1000000);
+ let (_, payment_hash_3, _) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 1000000);
// 5th HTLC:
- let (_, payment_hash_4) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 1000000);
- let route = get_route(our_node_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[5].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ let (_, payment_hash_4, _) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 1000000);
+ let route = get_route(our_node_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[5].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
// 6th HTLC:
- send_along_route_with_hash(&nodes[1], route.clone(), &[&nodes[2], &nodes[3], &nodes[5]], 1000000, payment_hash_3);
+ send_along_route_with_secret(&nodes[1], route.clone(), &[&[&nodes[2], &nodes[3], &nodes[5]]], 1000000, payment_hash_3, nodes[5].node.create_inbound_payment_for_hash(payment_hash_3, None, 7200, 0).unwrap());
// 7th HTLC:
- send_along_route_with_hash(&nodes[1], route, &[&nodes[2], &nodes[3], &nodes[5]], 1000000, payment_hash_4);
+ send_along_route_with_secret(&nodes[1], route, &[&[&nodes[2], &nodes[3], &nodes[5]]], 1000000, payment_hash_4, nodes[5].node.create_inbound_payment_for_hash(payment_hash_4, None, 7200, 0).unwrap());
// 8th HTLC:
- let (_, payment_hash_5) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 1000000);
+ let (_, payment_hash_5, _) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 1000000);
// 9th HTLC:
- let route = get_route(our_node_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[5].node.get_our_node_id(), None, None, &Vec::new(), ds_dust_limit*1000, TEST_FINAL_CLTV, &logger).unwrap();
- send_along_route_with_hash(&nodes[1], route, &[&nodes[2], &nodes[3], &nodes[5]], ds_dust_limit*1000, payment_hash_5); // not added < dust limit + HTLC tx fee
+ let route = get_route(our_node_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[5].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), ds_dust_limit*1000, TEST_FINAL_CLTV, &logger).unwrap();
+ send_along_route_with_secret(&nodes[1], route, &[&[&nodes[2], &nodes[3], &nodes[5]]], ds_dust_limit*1000, payment_hash_5, nodes[5].node.create_inbound_payment_for_hash(payment_hash_5, None, 7200, 0).unwrap()); // not added < dust limit + HTLC tx fee
// 10th HTLC:
- let (_, payment_hash_6) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], ds_dust_limit*1000); // not added < dust limit + HTLC tx fee
+ let (_, payment_hash_6, _) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], ds_dust_limit*1000); // not added < dust limit + HTLC tx fee
// 11th HTLC:
- let route = get_route(our_node_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[5].node.get_our_node_id(), None, None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- send_along_route_with_hash(&nodes[1], route, &[&nodes[2], &nodes[3], &nodes[5]], 1000000, payment_hash_6);
+ let route = get_route(our_node_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[5].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ send_along_route_with_secret(&nodes[1], route, &[&[&nodes[2], &nodes[3], &nodes[5]]], 1000000, payment_hash_6, nodes[5].node.create_inbound_payment_for_hash(payment_hash_6, None, 7200, 0).unwrap());
// Double-check that six of the new HTLC were added
// We now have six HTLCs pending over the dust limit and six HTLCs under the dust limit (ie,
// Now fail back three of the over-dust-limit and three of the under-dust-limit payments in one go.
// Fail 0th below-dust, 4th above-dust, 8th above-dust, 10th below-dust HTLCs
- assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_1, &None));
- assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_3, &None));
- assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_5, &None));
- assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_6, &None));
+ assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_1));
+ assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_3));
+ assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_5));
+ assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_6));
check_added_monitors!(nodes[4], 0);
expect_pending_htlcs_forwardable!(nodes[4]);
check_added_monitors!(nodes[4], 1);
commitment_signed_dance!(nodes[3], nodes[4], four_removes.commitment_signed, false);
// Fail 3rd below-dust and 7th above-dust HTLCs
- assert!(nodes[5].node.fail_htlc_backwards(&payment_hash_2, &None));
- assert!(nodes[5].node.fail_htlc_backwards(&payment_hash_4, &None));
+ assert!(nodes[5].node.fail_htlc_backwards(&payment_hash_2));
+ assert!(nodes[5].node.fail_htlc_backwards(&payment_hash_4));
check_added_monitors!(nodes[5], 0);
expect_pending_htlcs_forwardable!(nodes[5]);
check_added_monitors!(nodes[5], 1);
// Create some initial channels
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let (_, our_payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9000000);
+ let (_, our_payment_hash, _) = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9000000);
let local_txn = get_local_commitment_txn!(nodes[0], chan_1.2);
assert_eq!(local_txn[0].input.len(), 1);
check_spends!(local_txn[0], chan_1.3);
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
assert_ne!(chan_0.3.output[0].script_pubkey, chan_1.3.output[0].script_pubkey);
- let (_, our_payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9000000);
+ let (_, our_payment_hash, _) = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9000000);
let local_txn_0 = get_local_commitment_txn!(nodes[0], chan_0.2);
let local_txn_1 = get_local_commitment_txn!(nodes[0], chan_1.2);
assert_eq!(local_txn_1[0].input.len(), 1);
let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000, 8_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
let closing_tx = close_channel(&nodes[0], &nodes[1], &chan.2, chan.3, true).2;
mine_transaction(&nodes[0], &closing_tx);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let (our_payment_preimage, _) = route_payment(&nodes[0], &[&nodes[1]], if use_dust { 50000 } else { 3000000 });
+ let (our_payment_preimage, _, _) = route_payment(&nodes[0], &[&nodes[1]], if use_dust { 50000 } else { 3000000 });
// Claim the payment, but don't deliver A's commitment_signed, resulting in the HTLC only being
// present in B's local commitment transaction, but none of A's commitment transactions.
- assert!(nodes[1].node.claim_funds(our_payment_preimage, &None, if use_dust { 50_000 } else { 3_000_000 }));
+ assert!(nodes[1].node.claim_funds(our_payment_preimage));
check_added_monitors!(nodes[1], 1);
let bs_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
let logger = test_utils::TestLogger::new();
- let (_, payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[1]);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &Vec::new(), if use_dust { 50000 } else { 3000000 }, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), if use_dust { 50000 } else { 3000000 }, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
let _as_update = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
// Also optionally test that we *don't* fail the channel in case the commitment transaction was
// actually revoked.
let htlc_value = if use_dust { 50000 } else { 3000000 };
- let (_, our_payment_hash) = route_payment(&nodes[0], &[&nodes[1]], htlc_value);
- assert!(nodes[1].node.fail_htlc_backwards(&our_payment_hash, &None));
+ let (_, our_payment_hash, _) = route_payment(&nodes[0], &[&nodes[1]], htlc_value);
+ assert!(nodes[1].node.fail_htlc_backwards(&our_payment_hash));
expect_pending_htlcs_forwardable!(nodes[1]);
check_added_monitors!(nodes[1], 1);
let feerate = get_feerate!(nodes[0], chan.2);
// 2* and +1 HTLCs on the commit tx fee calculation for the fee spike reserve.
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[1]);
let max_can_send = 5000000 - channel_reserve - 2*commit_tx_fee_msat(feerate, 1 + 1);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], max_can_send, TEST_FINAL_CLTV, &logger).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], max_can_send, TEST_FINAL_CLTV, &logger).unwrap();
// Send a payment which passes reserve checks but gets stuck in the holding cell.
- nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
chan_stat = get_channel_value_stat!(nodes[0], chan.2);
assert_eq!(chan_stat.holding_cell_outbound_amount_msat, max_can_send);
let feerate = get_feerate!(nodes[0], chan.2);
// 2* and +1 HTLCs on the commit tx fee calculation for the fee spike reserve.
- let (payment_preimage_1, payment_hash_1) = get_payment_preimage_hash!(nodes[0]);
+ let (payment_preimage_1, payment_hash_1, payment_secret_1) = get_payment_preimage_hash!(nodes[1]);
let amt_1 = 20000;
- let (_, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
+ let (_, payment_hash_2, payment_secret_2) = get_payment_preimage_hash!(nodes[1]);
let amt_2 = 5000000 - channel_reserve - 2*commit_tx_fee_msat(feerate, 2 + 1) - amt_1;
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route_1 = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], amt_1, TEST_FINAL_CLTV, &logger).unwrap();
- let route_2 = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], amt_2, TEST_FINAL_CLTV, &logger).unwrap();
+ let route_1 = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], amt_1, TEST_FINAL_CLTV, &logger).unwrap();
+ let route_2 = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], amt_2, TEST_FINAL_CLTV, &logger).unwrap();
// Send 2 payments which pass reserve checks but get stuck in the holding cell.
- nodes[0].node.send_payment(&route_1, payment_hash_1, &None).unwrap();
+ nodes[0].node.send_payment(&route_1, payment_hash_1, &Some(payment_secret_1)).unwrap();
chan_stat = get_channel_value_stat!(nodes[0], chan.2);
assert_eq!(chan_stat.holding_cell_outbound_amount_msat, amt_1);
- nodes[0].node.send_payment(&route_2, payment_hash_2, &None).unwrap();
+ nodes[0].node.send_payment(&route_2, payment_hash_2, &Some(payment_secret_2)).unwrap();
chan_stat = get_channel_value_stat!(nodes[0], chan.2);
assert_eq!(chan_stat.holding_cell_outbound_amount_msat, amt_1 + amt_2);
Event::PaymentReceived { .. } => {},
_ => panic!("Unexpected event"),
}
- nodes[1].node.claim_funds(payment_preimage_1, &None, amt_1);
+ nodes[1].node.claim_funds(payment_preimage_1);
check_added_monitors!(nodes[1], 1);
let update_msgs = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &update_msgs.update_fulfill_htlcs[0]);
// Send a payment which passes reserve checks but gets stuck in the holding cell.
let feemsat = 239;
let total_routing_fee_msat = (nodes.len() - 2) as u64 * feemsat;
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[2]);
let max_can_send = 5000000 - channel_reserve - 2*commit_tx_fee_msat(feerate, 1 + 1) - total_routing_fee_msat;
let payment_event = {
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), None, None, &[], max_can_send, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], max_can_send, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[1]);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
let logger = test_utils::TestLogger::new();
- let mut route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
+ let mut route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
route.paths[0][0].fee_msat = 100;
- unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { ref err },
+ unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)), true, APIError::ChannelUnavailable { ref err },
assert!(regex::Regex::new(r"Cannot send less than their minimum HTLC value \(\d+\)").unwrap().is_match(err)));
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
nodes[0].logger.assert_log_contains("lightning::ln::channelmanager".to_string(), "Cannot send less than their minimum HTLC value".to_string(), 1);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[1]);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
let logger = test_utils::TestLogger::new();
- let mut route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
+ let mut route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
route.paths[0][0].fee_msat = 0;
- unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { ref err },
+ unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)), true, APIError::ChannelUnavailable { ref err },
assert_eq!(err, "Cannot send 0-msat HTLC"));
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[1]);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
let logger = test_utils::TestLogger::new();
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
updates.update_add_htlcs[0].amount_msat = 0;
let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 0, InitFeatures::known(), InitFeatures::known());
let logger = test_utils::TestLogger::new();
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[1]);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], 100000000, 500000001, &logger).unwrap();
- unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::RouteError { ref err },
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 100000000, 500000001, &logger).unwrap();
+ unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)), true, APIError::RouteError { ref err },
assert_eq!(err, &"Channel CLTV overflowed?"));
}
let logger = test_utils::TestLogger::new();
for i in 0..max_accepted_htlcs {
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[1]);
let payment_event = {
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false);
expect_pending_htlcs_forwardable!(nodes[1]);
- expect_payment_received!(nodes[1], our_payment_hash, 100000);
+ expect_payment_received!(nodes[1], our_payment_hash, our_payment_secret, 100000);
}
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[1]);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
- unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { ref err },
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
+ unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)), true, APIError::ChannelUnavailable { ref err },
assert!(regex::Regex::new(r"Cannot push more than their max accepted HTLCs \(\d+\)").unwrap().is_match(err)));
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, channel_value, 0, InitFeatures::known(), InitFeatures::known());
let max_in_flight = get_channel_value_stat!(nodes[0], chan.2).counterparty_max_htlc_value_in_flight_msat;
- send_payment(&nodes[0], &vec!(&nodes[1])[..], max_in_flight, max_in_flight);
+ send_payment(&nodes[0], &vec!(&nodes[1])[..], max_in_flight);
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[1]);
// Manually create a route over our max in flight (which our router normally automatically
// limits us to.
let route = Route { paths: vec![vec![RouteHop {
short_channel_id: nodes[1].node.list_usable_channels()[0].short_channel_id.unwrap(),
fee_msat: max_in_flight + 1, cltv_expiry_delta: TEST_FINAL_CLTV
}]] };
- unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { ref err },
+ unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)), true, APIError::ChannelUnavailable { ref err },
assert!(regex::Regex::new(r"Cannot send value that would put us over the max HTLC value in flight our peer will accept \(\d+\)").unwrap().is_match(err)));
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
nodes[0].logger.assert_log_contains("lightning::ln::channelmanager".to_string(), "Cannot send value that would put us over the max HTLC value in flight our peer will accept".to_string(), 1);
- send_payment(&nodes[0], &[&nodes[1]], max_in_flight, max_in_flight);
+ send_payment(&nodes[0], &[&nodes[1]], max_in_flight);
}
// BOLT 2 Requirements for the Receiver when handling an update_add_htlc message.
htlc_minimum_msat = channel.get_holder_htlc_minimum_msat();
}
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[1]);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
let logger = test_utils::TestLogger::new();
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], htlc_minimum_msat, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], htlc_minimum_msat, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
updates.update_add_htlcs[0].amount_msat = htlc_minimum_msat-1;
let commit_tx_fee_outbound = 2 * commit_tx_fee_msat(feerate, 1 + 1);
let max_can_send = 5000000 - channel_reserve - commit_tx_fee_outbound;
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[1]);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], max_can_send, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], max_can_send, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
let logger = test_utils::TestLogger::new();
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[1]);
let session_priv = SecretKey::from_slice(&[42; 32]).unwrap();
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], 3999999, TEST_FINAL_CLTV, &logger).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 3999999, TEST_FINAL_CLTV, &logger).unwrap();
let cur_height = nodes[0].node.best_block.read().unwrap().height() + 1;
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::signing_only(), &route.paths[0], &session_priv).unwrap();
- let (onion_payloads, _htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 3999999, &None, cur_height).unwrap();
+ let (onion_payloads, _htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 3999999, &Some(our_payment_secret), cur_height).unwrap();
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash);
let mut msg = msgs::UpdateAddHTLC {
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000, InitFeatures::known(), InitFeatures::known());
let logger = test_utils::TestLogger::new();
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[1]);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
updates.update_add_htlcs[0].amount_msat = get_channel_value_stat!(nodes[1], chan.2).counterparty_max_htlc_value_in_flight_msat + 1;
let logger = test_utils::TestLogger::new();
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[1]);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
updates.update_add_htlcs[0].cltv_expiry = 500000000;
let logger = test_utils::TestLogger::new();
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[1]);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let logger = test_utils::TestLogger::new();
let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let (our_payment_preimage, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (our_payment_preimage, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[1]);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
let logger = test_utils::TestLogger::new();
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[1]);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
let logger = test_utils::TestLogger::new();
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[1]);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
let our_payment_preimage = route_payment(&nodes[0], &[&nodes[1]], 100000).0;
- nodes[1].node.claim_funds(our_payment_preimage, &None, 100_000);
+ nodes[1].node.claim_funds(our_payment_preimage);
check_added_monitors!(nodes[1], 1);
let events = nodes[1].node.get_and_clear_pending_msg_events();
let our_payment_preimage = route_payment(&nodes[0], &[&nodes[1]], 100000).0;
- nodes[1].node.claim_funds(our_payment_preimage, &None, 100_000);
+ nodes[1].node.claim_funds(our_payment_preimage);
check_added_monitors!(nodes[1], 1);
let events = nodes[1].node.get_and_clear_pending_msg_events();
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000, InitFeatures::known(), InitFeatures::known());
let logger = test_utils::TestLogger::new();
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[1]);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, None, &[], 1000000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 1000000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1000000, 1000000, InitFeatures::known(), InitFeatures::known());
let logger = test_utils::TestLogger::new();
- let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[2]);
//First hop
let mut payment_event = {
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), None, None, &Vec::new(), 100000, TEST_FINAL_CLTV, &logger).unwrap();
- nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 100000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
let bs_dust_limit = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().holder_dust_limit_satoshis;
// We route 2 dust-HTLCs between A and B
- let (_, payment_hash_1) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000);
- let (_, payment_hash_2) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000);
+ let (_, payment_hash_1, _) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000);
+ let (_, payment_hash_2, _) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000);
route_payment(&nodes[0], &[&nodes[1]], 1000000);
// Cache one local commitment tx as previous
let as_prev_commitment_tx = get_local_commitment_txn!(nodes[0], chan.2);
// Fail one HTLC to prune it in the will-be-latest-local commitment tx
- assert!(nodes[1].node.fail_htlc_backwards(&payment_hash_2, &None));
+ assert!(nodes[1].node.fail_htlc_backwards(&payment_hash_2));
check_added_monitors!(nodes[1], 0);
expect_pending_htlcs_forwardable!(nodes[1]);
check_added_monitors!(nodes[1], 1);
let bs_dust_limit = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().holder_dust_limit_satoshis;
- let (_payment_preimage_1, dust_hash) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000);
- let (_payment_preimage_2, non_dust_hash) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
+ let (_payment_preimage_1, dust_hash, _payment_secret_1) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000);
+ let (_payment_preimage_2, non_dust_hash, _payment_secret_2) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
let as_commitment_tx = get_local_commitment_txn!(nodes[0], chan.2);
let bs_commitment_tx = get_local_commitment_txn!(nodes[1], chan.2);
// We revoked bs_commitment_tx
if revoked {
- let (payment_preimage_3, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
- claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_3, 1_000_000);
+ let (payment_preimage_3, _, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
+ claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_3);
}
let mut timeout_tx = Vec::new();
let mut previous_chain_monitor_state = test_utils::TestVecWriter(Vec::new());
nodes[0].chain_monitor.chain_monitor.monitors.read().unwrap().iter().next().unwrap().1.write(&mut previous_chain_monitor_state).unwrap();
- send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000, 8_000_000);
- send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000, 8_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
+ send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
- let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+ let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
// Create some initial channels
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- let (payment_preimage, payment_hash) = route_payment(&nodes[0], &[&nodes[1]], 10_000);
+ let route = get_route(&nodes[0].node.get_our_node_id(), &nodes[0].net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 10_000, TEST_FINAL_CLTV, nodes[0].logger).unwrap();
+ let (_, our_payment_hash, _) = get_payment_preimage_hash!(nodes[0]);
+ let our_payment_secret = nodes[1].node.create_inbound_payment_for_hash(our_payment_hash, Some(100_000), 7200, 0).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
+ check_added_monitors!(nodes[0], 1);
+
+ let mut events = nodes[0].node.get_and_clear_pending_msg_events();
+ assert_eq!(events.len(), 1);
+ let mut payment_event = SendEvent::from_event(events.pop().unwrap());
+ nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
+ commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false);
- // Node 3 is expecting payment of 100_000 but receive 10_000,
- // fail htlc like we didn't know the preimage.
- nodes[1].node.claim_funds(payment_preimage, &None, 100_000);
+ // Note that we first have to wait a random delay before processing the receipt of the HTLC,
+ // and then will wait a second random delay before failing the HTLC back:
+ expect_pending_htlcs_forwardable!(nodes[1]);
+ expect_pending_htlcs_forwardable!(nodes[1]);
+
+ // Node 3 is expecting payment of 100_000 but received 10_000,
+ // it should fail htlc like we didn't know the preimage.
nodes[1].node.process_pending_htlc_forwards();
let events = nodes[1].node.get_and_clear_pending_msg_events();
// 10_000 msat as u64, followed by a height of CHAN_CONFIRM_DEPTH as u32
let mut expected_failure_data = byte_utils::be64_to_array(10_000).to_vec();
expected_failure_data.extend_from_slice(&byte_utils::be32_to_array(CHAN_CONFIRM_DEPTH));
- expect_payment_failed!(nodes[0], payment_hash, true, 0x4000|15, &expected_failure_data[..]);
- nodes[1].node.get_and_clear_pending_events();
+ expect_payment_failed!(nodes[0], our_payment_hash, true, 0x4000|15, &expected_failure_data[..]);
}
#[test]
let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
let net_graph_msg_handler = &nodes[1].net_graph_msg_handler;
- let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), None, None, &Vec::new(), 3000000, 30, &logger).unwrap();
+ let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 3000000, 30, &logger).unwrap();
send_along_route(&nodes[1], route, &vec!(&nodes[0])[..], 3000000);
let revoked_txn = get_local_commitment_txn!(nodes[0], chan.2);
let header_114 = connect_blocks(&nodes[1], 14);
// Actually revoke tx by claiming a HTLC
- claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage, 3_000_000);
+ claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage);
let header = BlockHeader { version: 0x20000000, prev_blockhash: header_114, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
connect_block(&nodes[1], &Block { header, txdata: vec![revoked_txn[0].clone()] });
check_added_monitors!(nodes[1], 1);
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan.3.txid());
// Revoke local commitment tx
- claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage, 3_000_000);
+ claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage);
let header = BlockHeader { version: 0x20000000, prev_blockhash: nodes[1].best_block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
// B will generate both revoked HTLC-timeout/HTLC-preimage txn from revoked commitment tx
assert_eq!(remote_txn[0].input[0].previous_output.txid, chan.3.txid());
// Claim a HTLC without revocation (provide B monitor with preimage)
- nodes[1].node.claim_funds(payment_preimage, &None, 3_000_000);
+ nodes[1].node.claim_funds(payment_preimage);
mine_transaction(&nodes[1], &remote_txn[0]);
check_added_monitors!(nodes[1], 2);
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan.3.txid());
// Revoke local commitment tx
- claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage, 9_000_000);
+ claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage);
// Broadcast set of revoked txn on A
connect_blocks(&nodes[0], 52 - CHAN_CONFIRM_DEPTH);
assert_eq!(res.htlc_minimum_msat, 1);
}
-#[test]
-fn test_simple_payment_secret() {
- // Simple test of sending a payment with a payment_secret present. This does not use any AMP
- // features, however.
- let chanmon_cfgs = create_chanmon_cfgs(3);
- let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
- let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
- let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
-
- create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
- let logger = test_utils::TestLogger::new();
-
- let (payment_preimage, payment_hash) = get_payment_preimage_hash!(&nodes[0]);
- let payment_secret = PaymentSecret([0xdb; 32]);
- let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), None, None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
- send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[2]]], 100000, payment_hash, Some(payment_secret.clone()));
- // Claiming with all the correct values but the wrong secret should result in nothing...
- assert_eq!(nodes[2].node.claim_funds(payment_preimage, &None, 100_000), false);
- assert_eq!(nodes[2].node.claim_funds(payment_preimage, &Some(PaymentSecret([42; 32])), 100_000), false);
- // ...but with the right secret we should be able to claim all the way back
- claim_payment_along_route_with_secret(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage, Some(payment_secret.clone()), 100_000);
-}
-
#[test]
fn test_simple_mpp() {
// Simple test of sending a multi-path payment.
let chan_4_id = create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
let logger = test_utils::TestLogger::new();
- let (payment_preimage, payment_hash) = get_payment_preimage_hash!(&nodes[0]);
- let payment_secret = PaymentSecret([0xdb; 32]);
+ let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!(&nodes[3]);
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
- let mut route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[3].node.get_our_node_id(), None, None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
+ let mut route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[3].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 100000, TEST_FINAL_CLTV, &logger).unwrap();
let path = route.paths[0].clone();
route.paths.push(path);
route.paths[0][0].pubkey = nodes[1].node.get_our_node_id();
route.paths[1][0].pubkey = nodes[2].node.get_our_node_id();
route.paths[1][0].short_channel_id = chan_2_id;
route.paths[1][1].short_channel_id = chan_4_id;
- send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], 200_000, payment_hash, Some(payment_secret.clone()));
- // Claiming with all the correct values but the wrong secret should result in nothing...
- assert_eq!(nodes[3].node.claim_funds(payment_preimage, &None, 200_000), false);
- assert_eq!(nodes[3].node.claim_funds(payment_preimage, &Some(PaymentSecret([42; 32])), 200_000), false);
- // ...but with the right secret we should be able to claim all the way back
- claim_payment_along_route_with_secret(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage, Some(payment_secret), 200_000);
+ send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], 200_000, payment_hash, payment_secret);
+ claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage);
+}
+
+#[test]
+fn test_preimage_storage() {
+ // Simple test of payment preimage storage allowing no client-side storage to claim payments
+ let chanmon_cfgs = create_chanmon_cfgs(2);
+ let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+ let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+ let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+ create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
+
+ {
+ let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(100_000), 7200, 42);
+
+ let logger = test_utils::TestLogger::new();
+ let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 100_000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap();
+ check_added_monitors!(nodes[0], 1);
+ let mut events = nodes[0].node.get_and_clear_pending_msg_events();
+ let mut payment_event = SendEvent::from_event(events.pop().unwrap());
+ nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
+ commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false);
+ }
+ // Note that after leaving the above scope we have no knowledge of any arguments or return
+ // values from previous calls.
+ expect_pending_htlcs_forwardable!(nodes[1]);
+ let events = nodes[1].node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 1);
+ match events[0] {
+ Event::PaymentReceived { payment_preimage, user_payment_id, .. } => {
+ assert_eq!(user_payment_id, 42);
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage.unwrap());
+ },
+ _ => panic!("Unexpected event"),
+ }
+}
+
+#[test]
+fn test_secret_timeout() {
+ // Simple test of payment secret storage time outs
+ let chanmon_cfgs = create_chanmon_cfgs(2);
+ let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+ let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+ let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+ create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
+
+ let (payment_hash, payment_secret_1) = nodes[1].node.create_inbound_payment(Some(100_000), 2, 0);
+
+ // We should fail to register the same payment hash twice, at least until we've connected a
+ // block with time 7200 + CHAN_CONFIRM_DEPTH + 1.
+ if let Err(APIError::APIMisuseError { err }) = nodes[1].node.create_inbound_payment_for_hash(payment_hash, Some(100_000), 2, 0) {
+ assert_eq!(err, "Duplicate payment hash");
+ } else { panic!(); }
+ let mut block = Block {
+ header: BlockHeader {
+ version: 0x2000000,
+ prev_blockhash: nodes[1].blocks.borrow().last().unwrap().0.block_hash(),
+ merkle_root: Default::default(),
+ time: nodes[1].blocks.borrow().len() as u32 + 7200, bits: 42, nonce: 42 },
+ txdata: vec![],
+ };
+ connect_block(&nodes[1], &block);
+ if let Err(APIError::APIMisuseError { err }) = nodes[1].node.create_inbound_payment_for_hash(payment_hash, Some(100_000), 2, 0) {
+ assert_eq!(err, "Duplicate payment hash");
+ } else { panic!(); }
+
+ // If we then connect the second block, we should be able to register the same payment hash
+ // again with a different user_payment_id (this time getting a new payment secret).
+ block.header.prev_blockhash = block.header.block_hash();
+ block.header.time += 1;
+ connect_block(&nodes[1], &block);
+ let our_payment_secret = nodes[1].node.create_inbound_payment_for_hash(payment_hash, Some(100_000), 2, 42).unwrap();
+ assert_ne!(payment_secret_1, our_payment_secret);
+
+ {
+ let logger = test_utils::TestLogger::new();
+ let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 100_000, TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash, &Some(our_payment_secret)).unwrap();
+ check_added_monitors!(nodes[0], 1);
+ let mut events = nodes[0].node.get_and_clear_pending_msg_events();
+ let mut payment_event = SendEvent::from_event(events.pop().unwrap());
+ nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
+ commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false);
+ }
+ // Note that after leaving the above scope we have no knowledge of any arguments or return
+ // values from previous calls.
+ expect_pending_htlcs_forwardable!(nodes[1]);
+ let events = nodes[1].node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 1);
+ match events[0] {
+ Event::PaymentReceived { payment_preimage, payment_secret, user_payment_id, .. } => {
+ assert!(payment_preimage.is_none());
+ assert_eq!(user_payment_id, 42);
+ assert_eq!(payment_secret, our_payment_secret);
+ // We don't actually have the payment preimage with which to claim this payment!
+ },
+ _ => panic!("Unexpected event"),
+ }
+}
+
+#[test]
+fn test_bad_secret_hash() {
+ // Simple test of unregistered payment hash/invalid payment secret handling
+ let chanmon_cfgs = create_chanmon_cfgs(2);
+ let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+ let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+ let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+ create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
+
+ let random_payment_hash = PaymentHash([42; 32]);
+ let random_payment_secret = PaymentSecret([43; 32]);
+ let (our_payment_hash, our_payment_secret) = nodes[1].node.create_inbound_payment(Some(100_000), 2, 0);
+
+ let logger = test_utils::TestLogger::new();
+ let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 100_000, TEST_FINAL_CLTV, &logger).unwrap();
+
+ // All the below cases should end up being handled exactly identically, so we macro the
+ // resulting events.
+ macro_rules! handle_unknown_invalid_payment_data {
+ () => {
+ check_added_monitors!(nodes[0], 1);
+ let mut events = nodes[0].node.get_and_clear_pending_msg_events();
+ let payment_event = SendEvent::from_event(events.pop().unwrap());
+ nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
+ commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false);
+
+ // We have to forward pending HTLCs once to process the receipt of the HTLC and then
+ // again to process the pending backwards-failure of the HTLC
+ expect_pending_htlcs_forwardable!(nodes[1]);
+ expect_pending_htlcs_forwardable!(nodes[1]);
+ check_added_monitors!(nodes[1], 1);
+
+ // We should fail the payment back
+ let mut events = nodes[1].node.get_and_clear_pending_msg_events();
+ match events.pop().unwrap() {
+ MessageSendEvent::UpdateHTLCs { node_id: _, updates: msgs::CommitmentUpdate { update_fail_htlcs, commitment_signed, .. } } => {
+ nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &update_fail_htlcs[0]);
+ commitment_signed_dance!(nodes[0], nodes[1], commitment_signed, false);
+ },
+ _ => panic!("Unexpected event"),
+ }
+ }
+ }
+
+ let expected_error_code = 0x4000|15; // incorrect_or_unknown_payment_details
+ // Error data is the HTLC value (100,000) and current block height
+ let expected_error_data = [0, 0, 0, 0, 0, 1, 0x86, 0xa0, 0, 0, 0, CHAN_CONFIRM_DEPTH as u8];
+
+ // Send a payment with the right payment hash but the wrong payment secret
+ nodes[0].node.send_payment(&route, our_payment_hash, &Some(random_payment_secret)).unwrap();
+ handle_unknown_invalid_payment_data!();
+ expect_payment_failed!(nodes[0], our_payment_hash, true, expected_error_code, expected_error_data);
+
+ // Send a payment with a random payment hash, but the right payment secret
+ nodes[0].node.send_payment(&route, random_payment_hash, &Some(our_payment_secret)).unwrap();
+ handle_unknown_invalid_payment_data!();
+ expect_payment_failed!(nodes[0], random_payment_hash, true, expected_error_code, expected_error_data);
+
+ // Send a payment with a random payment hash and random payment secret
+ nodes[0].node.send_payment(&route, random_payment_hash, &Some(random_payment_secret)).unwrap();
+ handle_unknown_invalid_payment_data!();
+ expect_payment_failed!(nodes[0], random_payment_hash, true, expected_error_code, expected_error_data);
}
#[test]
let outpoint = OutPoint { txid: chan_1.3.txid(), index: 0 };
// Rebalance the network to generate htlc in the two directions
- send_payment(&nodes[0], &vec!(&nodes[1])[..], 10_000_000, 10_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1])[..], 10_000_000);
// Route a HTLC from node 0 to node 1 (but don't settle)
let preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9_000_000).0;
watchtower.chain_monitor.block_connected(&Block { header, txdata: vec![] }, 200);
// Try to update ChannelMonitor
- assert!(nodes[1].node.claim_funds(preimage, &None, 9_000_000));
+ assert!(nodes[1].node.claim_funds(preimage));
check_added_monitors!(nodes[1], 1);
let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
assert_eq!(updates.update_fulfill_htlcs.len(), 1);
let outpoint = OutPoint { txid: chan_1.3.txid(), index: 0 };
// Rebalance the network to generate htlc in the two directions
- send_payment(&nodes[0], &vec!(&nodes[1])[..], 10_000_000, 10_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1])[..], 10_000_000);
// Route a HTLC from node 0 to node 1 (but don't settle)
route_payment(&nodes[0], &vec!(&nodes[1])[..], 9_000_000).0;
watchtower_bob.chain_monitor.block_connected(&Block { header, txdata: vec![] }, CHAN_CONFIRM_DEPTH + TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS);
// Route another payment to generate another update with still previous HTLC pending
- let (_, payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[0]);
{
let net_graph_msg_handler = &nodes[1].net_graph_msg_handler;
- let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), None, None, &Vec::new(), 3000000 , TEST_FINAL_CLTV, &logger).unwrap();
- nodes[1].node.send_payment(&route, payment_hash, &None).unwrap();
+ let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[0].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 3000000 , TEST_FINAL_CLTV, &logger).unwrap();
+ nodes[1].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap();
}
check_added_monitors!(nodes[1], 1);
// Create some initial channels
let chan_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
- send_payment(&nodes[0], &vec!(&nodes[1])[..], 1_000_000, 1_000_000);
- let (_, our_payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1])[..], 2_000_000);
+ send_payment(&nodes[0], &vec!(&nodes[1])[..], 1_000_000);
+ let (_, our_payment_hash, _) = route_payment(&nodes[0], &vec!(&nodes[1])[..], 2_000_000);
let local_txn = get_local_commitment_txn!(nodes[0], chan_1.2);
assert_eq!(local_txn[0].input.len(), 1);
assert_eq!(local_txn[0].output.len(), 3);
// Steps (1) and (2):
// Send an HTLC Alice --> Bob --> Carol, but Carol doesn't settle the HTLC back.
- let (payment_preimage, _payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), 3_000_000);
+ let (payment_preimage, _payment_hash, _payment_secret) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), 3_000_000);
// Check that Alice's commitment transaction now contains an output for this HTLC.
let alice_txn = get_local_commitment_txn!(nodes[0], chan_ab.2);
// Step (5):
// Carol then claims the funds and sends an update_fulfill message to Bob, and they go through the
// process of removing the HTLC from their commitment transactions.
- assert!(nodes[2].node.claim_funds(payment_preimage, &None, 3_000_000));
+ assert!(nodes[2].node.claim_funds(payment_preimage));
check_added_monitors!(nodes[2], 1);
let carol_updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
assert!(carol_updates.update_add_htlcs.is_empty());
let (funding_locked, _) = create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx);
let (announcement, as_update, bs_update) = create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &funding_locked);
update_nodes_with_chan_announce(&nodes, 0, 1, &announcement, &as_update, &bs_update);
- send_payment(&nodes[0], &[&nodes[1]], 8000000, 8_000_000);
+ send_payment(&nodes[0], &[&nodes[1]], 8000000);
}
#[test]
mod onion_route_tests;
pub use self::peer_channel_encryptor::LN_MAX_MSG_LEN;
+
+/// payment_hash type, use to cross-lock hop
+/// (C-not exported) as we just use [u8; 32] directly
+#[derive(Hash, Copy, Clone, PartialEq, Eq, Debug)]
+pub struct PaymentHash(pub [u8;32]);
+/// payment_preimage type, use to route payment between hop
+/// (C-not exported) as we just use [u8; 32] directly
+#[derive(Hash, Copy, Clone, PartialEq, Eq, Debug)]
+pub struct PaymentPreimage(pub [u8;32]);
+/// payment_secret type, use to authenticate sender to the receiver and tie MPP HTLCs together
+/// (C-not exported) as we just use [u8; 32] directly
+#[derive(Hash, Copy, Clone, PartialEq, Eq, Debug)]
+pub struct PaymentSecret(pub [u8;32]);
+
+use bitcoin::bech32;
+use bitcoin::bech32::{Base32Len, FromBase32, ToBase32, WriteBase32, u5};
+
+impl FromBase32 for PaymentSecret {
+ type Err = bech32::Error;
+
+ fn from_base32(field_data: &[u5]) -> Result<PaymentSecret, bech32::Error> {
+ if field_data.len() != 52 {
+ return Err(bech32::Error::InvalidLength)
+ } else {
+ let data_bytes = Vec::<u8>::from_base32(field_data)?;
+ let mut payment_secret = [0; 32];
+ payment_secret.copy_from_slice(&data_bytes);
+ Ok(PaymentSecret(payment_secret))
+ }
+ }
+}
+
+impl ToBase32 for PaymentSecret {
+ fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
+ (&self.0[..]).write_base32(writer)
+ }
+}
+
+impl Base32Len for PaymentSecret {
+ fn base32_len(&self) -> usize {
+ 52
+ }
+}
use util::events::MessageSendEventsProvider;
use util::ser::{Readable, Writeable, Writer, FixedLengthReader, HighZeroBytesDroppedVarInt};
-use ln::channelmanager::{PaymentPreimage, PaymentHash, PaymentSecret};
+use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
/// 21 million * 10^8 * 1000
pub(crate) const MAX_VALUE_MSAT: u64 = 21_000_000_0000_0000_000;
///
/// Messages MAY be called in parallel when they originate from different their_node_ids, however
/// they MUST NOT be called in parallel when the two calls have the same their_node_id.
-pub trait ChannelMessageHandler : MessageSendEventsProvider + Send + Sync {
+pub trait ChannelMessageHandler : MessageSendEventsProvider {
//Channel init:
/// Handle an incoming open_channel message from the given peer.
fn handle_open_channel(&self, their_node_id: &PublicKey, their_features: InitFeatures, msg: &OpenChannel);
/// For `gossip_queries` messages there are potential DoS vectors when handling
/// inbound queries. Implementors using an on-disk network graph should be aware of
/// repeated disk I/O for queries accessing different parts of the network graph.
-pub trait RoutingMessageHandler : Send + Sync + MessageSendEventsProvider {
+pub trait RoutingMessageHandler : MessageSendEventsProvider {
/// Handle an incoming node_announcement message, returning true if it should be forwarded on,
/// false or returning an Err otherwise.
fn handle_node_announcement(&self, msg: &NodeAnnouncement) -> Result<bool, LightningError>;
}
mod fuzzy_internal_msgs {
- use ln::channelmanager::PaymentSecret;
+ use ln::PaymentSecret;
// These types aren't intended to be pub, but are exposed for direct fuzzing (as we deserialize
// them from untrusted input):
impl Writeable for UnsignedChannelAnnouncement {
fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
- w.size_hint(2 + 2*32 + 4*33 + self.features.byte_count() + self.excess_data.len());
+ w.size_hint(2 + 32 + 8 + 4*33 + self.features.byte_count() + self.excess_data.len());
self.features.write(w)?;
self.chain_hash.write(w)?;
self.short_channel_id.write(w)?;
impl_writeable_len_match!(ChannelAnnouncement, {
{ ChannelAnnouncement { contents: UnsignedChannelAnnouncement {ref features, ref excess_data, ..}, .. },
- 2 + 2*32 + 4*33 + features.byte_count() + excess_data.len() + 4*64 }
+ 2 + 32 + 8 + 4*33 + features.byte_count() + excess_data.len() + 4*64 }
}, {
node_signature_1,
node_signature_2,
}
impl_writeable_len_match!(ChannelUpdate, {
- { ChannelUpdate { contents: UnsignedChannelUpdate {ref excess_data, ..}, .. },
- 64 + excess_data.len() + 64 }
+ { ChannelUpdate { contents: UnsignedChannelUpdate {ref excess_data, ref htlc_maximum_msat, ..}, .. },
+ 64 + 64 + excess_data.len() + if let OptionalField::Present(_) = htlc_maximum_msat { 8 } else { 0 } }
}, {
signature,
contents
impl Writeable for UnsignedNodeAnnouncement {
fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
- w.size_hint(64 + 76 + self.features.byte_count() + self.addresses.len()*38 + self.excess_address_data.len() + self.excess_data.len());
+ w.size_hint(76 + self.features.byte_count() + self.addresses.len()*38 + self.excess_address_data.len() + self.excess_data.len());
self.features.write(w)?;
self.timestamp.write(w)?;
self.node_id.write(w)?;
}
}
-impl_writeable_len_match!(NodeAnnouncement, {
+impl_writeable_len_match!(NodeAnnouncement, <=, {
{ NodeAnnouncement { contents: UnsignedNodeAnnouncement { ref features, ref addresses, ref excess_address_data, ref excess_data, ..}, .. },
64 + 76 + features.byte_count() + addresses.len()*(NetAddress::MAX_LEN as usize + 1) + excess_address_data.len() + excess_data.len() }
}, {
#[cfg(test)]
mod tests {
use hex;
+ use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
use ln::msgs;
use ln::msgs::{ChannelFeatures, FinalOnionHopData, InitFeatures, NodeFeatures, OptionalField, OnionErrorPacket, OnionHopDataFormat};
- use ln::channelmanager::{PaymentPreimage, PaymentHash, PaymentSecret};
use util::ser::{Writeable, Readable};
use bitcoin::hashes::hex::FromHex;
use bitcoin::secp256k1;
use ln::msgs::DecodeError;
-use ln::channelmanager::PaymentPreimage;
+use ln::PaymentPreimage;
use ln::chan_utils;
use ln::chan_utils::{TxCreationKeys, ChannelTransactionParameters, HolderCommitmentTransaction};
use chain::chaininterface::{FeeEstimator, BroadcasterInterface, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT};
//! returned errors decode to the correct thing.
use chain::channelmonitor::{CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS};
-use ln::channelmanager::{HTLCForwardInfo, PaymentPreimage, PaymentHash};
+use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
+use ln::channelmanager::HTLCForwardInfo;
use ln::onion_utils;
use routing::router::{Route, get_route};
-use ln::features::InitFeatures;
+use ln::features::{InitFeatures, InvoiceFeatures};
use ln::msgs;
use ln::msgs::{ChannelMessageHandler, HTLCFailChannelUpdate, OptionalField};
use util::test_utils;
use ln::functional_test_utils::*;
-fn run_onion_failure_test<F1,F2>(_name: &str, test_case: u8, nodes: &Vec<Node>, route: &Route, payment_hash: &PaymentHash, callback_msg: F1, callback_node: F2, expected_retryable: bool, expected_error_code: Option<u16>, expected_channel_update: Option<HTLCFailChannelUpdate>)
+fn run_onion_failure_test<F1,F2>(_name: &str, test_case: u8, nodes: &Vec<Node>, route: &Route, payment_hash: &PaymentHash, payment_secret: &PaymentSecret, callback_msg: F1, callback_node: F2, expected_retryable: bool, expected_error_code: Option<u16>, expected_channel_update: Option<HTLCFailChannelUpdate>)
where F1: for <'a> FnMut(&'a mut msgs::UpdateAddHTLC),
F2: FnMut(),
{
- run_onion_failure_test_with_fail_intercept(_name, test_case, nodes, route, payment_hash, callback_msg, |_|{}, callback_node, expected_retryable, expected_error_code, expected_channel_update);
+ run_onion_failure_test_with_fail_intercept(_name, test_case, nodes, route, payment_hash, payment_secret, callback_msg, |_|{}, callback_node, expected_retryable, expected_error_code, expected_channel_update);
}
// test_case
// 3: final node fails backward (but tamper onion payloads from node0)
// 100: trigger error in the intermediate node and tamper returning fail_htlc
// 200: trigger error in the final node and tamper returning fail_htlc
-fn run_onion_failure_test_with_fail_intercept<F1,F2,F3>(_name: &str, test_case: u8, nodes: &Vec<Node>, route: &Route, payment_hash: &PaymentHash, mut callback_msg: F1, mut callback_fail: F2, mut callback_node: F3, expected_retryable: bool, expected_error_code: Option<u16>, expected_channel_update: Option<HTLCFailChannelUpdate>)
+fn run_onion_failure_test_with_fail_intercept<F1,F2,F3>(_name: &str, test_case: u8, nodes: &Vec<Node>, route: &Route, payment_hash: &PaymentHash, payment_secret: &PaymentSecret, mut callback_msg: F1, mut callback_fail: F2, mut callback_node: F3, expected_retryable: bool, expected_error_code: Option<u16>, expected_channel_update: Option<HTLCFailChannelUpdate>)
where F1: for <'a> FnMut(&'a mut msgs::UpdateAddHTLC),
F2: for <'a> FnMut(&'a mut msgs::UpdateFailHTLC),
F3: FnMut(),
}
// 0 ~~> 2 send payment
- nodes[0].node.send_payment(&route, payment_hash.clone(), &None).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash.clone(), &Some(*payment_secret)).unwrap();
check_added_monitors!(nodes[0], 1);
let update_0 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
// temper update_add (0 => 1)
*node.keys_manager.override_session_priv.lock().unwrap() = Some([3; 32]);
}
let channels = [create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()), create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known())];
- let (_, payment_hash) = get_payment_preimage_hash!(nodes[0]);
- let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
+ let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[2]);
let logger = test_utils::TestLogger::new();
- let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), None, None, &Vec::new(), 40000, TEST_FINAL_CLTV, &logger).unwrap();
+ let route = get_route(&nodes[0].node.get_our_node_id(), &nodes[0].net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 40000, TEST_FINAL_CLTV, &logger).unwrap();
// positve case
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 40000, 40_000);
+ send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 40000);
// intermediate node failure
- run_onion_failure_test("invalid_realm", 0, &nodes, &route, &payment_hash, |msg| {
+ run_onion_failure_test("invalid_realm", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
let cur_height = nodes[0].best_block_info().1 + 1;
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
}, ||{}, true, Some(PERM|22), Some(msgs::HTLCFailChannelUpdate::ChannelClosed{short_channel_id: channels[1].0.contents.short_channel_id, is_permanent: true}));//XXX incremented channels idx here
// final node failure
- run_onion_failure_test("invalid_realm", 3, &nodes, &route, &payment_hash, |msg| {
+ run_onion_failure_test("invalid_realm", 3, &nodes, &route, &payment_hash, &payment_secret, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
let cur_height = nodes[0].best_block_info().1 + 1;
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
// the following three with run_onion_failure_test_with_fail_intercept() test only the origin node
// receiving simulated fail messages
// intermediate node failure
- run_onion_failure_test_with_fail_intercept("temporary_node_failure", 100, &nodes, &route, &payment_hash, |msg| {
+ run_onion_failure_test_with_fail_intercept("temporary_node_failure", 100, &nodes, &route, &payment_hash, &payment_secret, |msg| {
// trigger error
msg.amount_msat -= 1;
}, |msg| {
}, ||{}, true, Some(NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.paths[0][0].pubkey, is_permanent: false}));
// final node failure
- run_onion_failure_test_with_fail_intercept("temporary_node_failure", 200, &nodes, &route, &payment_hash, |_msg| {}, |msg| {
+ run_onion_failure_test_with_fail_intercept("temporary_node_failure", 200, &nodes, &route, &payment_hash, &payment_secret, |_msg| {}, |msg| {
// and tamper returning error message
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[1].shared_secret[..], NODE|2, &[0;0]);
}, ||{
- nodes[2].node.fail_htlc_backwards(&payment_hash, &None);
+ nodes[2].node.fail_htlc_backwards(&payment_hash);
}, true, Some(NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.paths[0][1].pubkey, is_permanent: false}));
+ let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[2]);
// intermediate node failure
- run_onion_failure_test_with_fail_intercept("permanent_node_failure", 100, &nodes, &route, &payment_hash, |msg| {
+ run_onion_failure_test_with_fail_intercept("permanent_node_failure", 100, &nodes, &route, &payment_hash, &payment_secret, |msg| {
msg.amount_msat -= 1;
}, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
}, ||{}, true, Some(PERM|NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.paths[0][0].pubkey, is_permanent: true}));
// final node failure
- run_onion_failure_test_with_fail_intercept("permanent_node_failure", 200, &nodes, &route, &payment_hash, |_msg| {}, |msg| {
+ run_onion_failure_test_with_fail_intercept("permanent_node_failure", 200, &nodes, &route, &payment_hash, &payment_secret, |_msg| {}, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[1].shared_secret[..], PERM|NODE|2, &[0;0]);
}, ||{
- nodes[2].node.fail_htlc_backwards(&payment_hash, &None);
+ nodes[2].node.fail_htlc_backwards(&payment_hash);
}, false, Some(PERM|NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.paths[0][1].pubkey, is_permanent: true}));
+ let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[2]);
// intermediate node failure
- run_onion_failure_test_with_fail_intercept("required_node_feature_missing", 100, &nodes, &route, &payment_hash, |msg| {
+ run_onion_failure_test_with_fail_intercept("required_node_feature_missing", 100, &nodes, &route, &payment_hash, &payment_secret, |msg| {
msg.amount_msat -= 1;
}, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[0].shared_secret[..], PERM|NODE|3, &[0;0]);
}, ||{
- nodes[2].node.fail_htlc_backwards(&payment_hash, &None);
+ nodes[2].node.fail_htlc_backwards(&payment_hash);
}, true, Some(PERM|NODE|3), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.paths[0][0].pubkey, is_permanent: true}));
// final node failure
- run_onion_failure_test_with_fail_intercept("required_node_feature_missing", 200, &nodes, &route, &payment_hash, |_msg| {}, |msg| {
+ run_onion_failure_test_with_fail_intercept("required_node_feature_missing", 200, &nodes, &route, &payment_hash, &payment_secret, |_msg| {}, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[1].shared_secret[..], PERM|NODE|3, &[0;0]);
}, ||{
- nodes[2].node.fail_htlc_backwards(&payment_hash, &None);
+ nodes[2].node.fail_htlc_backwards(&payment_hash);
}, false, Some(PERM|NODE|3), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.paths[0][1].pubkey, is_permanent: true}));
+ let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[2]);
- run_onion_failure_test("invalid_onion_version", 0, &nodes, &route, &payment_hash, |msg| { msg.onion_routing_packet.version = 1; }, ||{}, true,
+ run_onion_failure_test("invalid_onion_version", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| { msg.onion_routing_packet.version = 1; }, ||{}, true,
Some(BADONION|PERM|4), None);
- run_onion_failure_test("invalid_onion_hmac", 0, &nodes, &route, &payment_hash, |msg| { msg.onion_routing_packet.hmac = [3; 32]; }, ||{}, true,
+ run_onion_failure_test("invalid_onion_hmac", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| { msg.onion_routing_packet.hmac = [3; 32]; }, ||{}, true,
Some(BADONION|PERM|5), None);
- run_onion_failure_test("invalid_onion_key", 0, &nodes, &route, &payment_hash, |msg| { msg.onion_routing_packet.public_key = Err(secp256k1::Error::InvalidPublicKey);}, ||{}, true,
+ run_onion_failure_test("invalid_onion_key", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| { msg.onion_routing_packet.public_key = Err(secp256k1::Error::InvalidPublicKey);}, ||{}, true,
Some(BADONION|PERM|6), None);
- run_onion_failure_test_with_fail_intercept("temporary_channel_failure", 100, &nodes, &route, &payment_hash, |msg| {
+ run_onion_failure_test_with_fail_intercept("temporary_channel_failure", 100, &nodes, &route, &payment_hash, &payment_secret, |msg| {
msg.amount_msat -= 1;
}, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[0].shared_secret[..], UPDATE|7, &ChannelUpdate::dummy().encode_with_len()[..]);
}, ||{}, true, Some(UPDATE|7), Some(msgs::HTLCFailChannelUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy()}));
- run_onion_failure_test_with_fail_intercept("permanent_channel_failure", 100, &nodes, &route, &payment_hash, |msg| {
+ run_onion_failure_test_with_fail_intercept("permanent_channel_failure", 100, &nodes, &route, &payment_hash, &payment_secret, |msg| {
msg.amount_msat -= 1;
}, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
// short_channel_id from the processing node
}, ||{}, true, Some(PERM|8), Some(msgs::HTLCFailChannelUpdate::ChannelClosed{short_channel_id: channels[1].0.contents.short_channel_id, is_permanent: true}));
- run_onion_failure_test_with_fail_intercept("required_channel_feature_missing", 100, &nodes, &route, &payment_hash, |msg| {
+ run_onion_failure_test_with_fail_intercept("required_channel_feature_missing", 100, &nodes, &route, &payment_hash, &payment_secret, |msg| {
msg.amount_msat -= 1;
}, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
let mut bogus_route = route.clone();
bogus_route.paths[0][1].short_channel_id -= 1;
- run_onion_failure_test("unknown_next_peer", 0, &nodes, &bogus_route, &payment_hash, |_| {}, ||{}, true, Some(PERM|10),
+ run_onion_failure_test("unknown_next_peer", 0, &nodes, &bogus_route, &payment_hash, &payment_secret, |_| {}, ||{}, true, Some(PERM|10),
Some(msgs::HTLCFailChannelUpdate::ChannelClosed{short_channel_id: bogus_route.paths[0][1].short_channel_id, is_permanent:true}));
let amt_to_forward = nodes[1].node.channel_state.lock().unwrap().by_id.get(&channels[1].2).unwrap().get_counterparty_htlc_minimum_msat() - 1;
let mut bogus_route = route.clone();
let route_len = bogus_route.paths[0].len();
bogus_route.paths[0][route_len-1].fee_msat = amt_to_forward;
- run_onion_failure_test("amount_below_minimum", 0, &nodes, &bogus_route, &payment_hash, |_| {}, ||{}, true, Some(UPDATE|11), Some(msgs::HTLCFailChannelUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy()}));
+ run_onion_failure_test("amount_below_minimum", 0, &nodes, &bogus_route, &payment_hash, &payment_secret, |_| {}, ||{}, true, Some(UPDATE|11), Some(msgs::HTLCFailChannelUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy()}));
// Test a positive test-case with one extra msat, meeting the minimum.
bogus_route.paths[0][route_len-1].fee_msat = amt_to_forward + 1;
- let (preimage, _) = send_along_route(&nodes[0], bogus_route, &[&nodes[1], &nodes[2]], amt_to_forward+1);
- claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], preimage, amt_to_forward+1);
+ let (preimage, _, _) = send_along_route(&nodes[0], bogus_route, &[&nodes[1], &nodes[2]], amt_to_forward+1);
+ claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], preimage);
//TODO: with new config API, we will be able to generate both valid and
//invalid channel_update cases.
- run_onion_failure_test("fee_insufficient", 0, &nodes, &route, &payment_hash, |msg| {
+ run_onion_failure_test("fee_insufficient", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| {
msg.amount_msat -= 1;
}, || {}, true, Some(UPDATE|12), Some(msgs::HTLCFailChannelUpdate::ChannelClosed { short_channel_id: channels[0].0.contents.short_channel_id, is_permanent: true}));
- run_onion_failure_test("incorrect_cltv_expiry", 0, &nodes, &route, &payment_hash, |msg| {
+ run_onion_failure_test("incorrect_cltv_expiry", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| {
// need to violate: cltv_expiry - cltv_expiry_delta >= outgoing_cltv_value
msg.cltv_expiry -= 1;
}, || {}, true, Some(UPDATE|13), Some(msgs::HTLCFailChannelUpdate::ChannelClosed { short_channel_id: channels[0].0.contents.short_channel_id, is_permanent: true}));
- run_onion_failure_test("expiry_too_soon", 0, &nodes, &route, &payment_hash, |msg| {
+ run_onion_failure_test("expiry_too_soon", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| {
let height = msg.cltv_expiry - CLTV_CLAIM_BUFFER - LATENCY_GRACE_PERIOD_BLOCKS + 1;
connect_blocks(&nodes[0], height - nodes[0].best_block_info().1);
connect_blocks(&nodes[1], height - nodes[1].best_block_info().1);
connect_blocks(&nodes[2], height - nodes[2].best_block_info().1);
}, ||{}, true, Some(UPDATE|14), Some(msgs::HTLCFailChannelUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy()}));
- run_onion_failure_test("unknown_payment_hash", 2, &nodes, &route, &payment_hash, |_| {}, || {
- nodes[2].node.fail_htlc_backwards(&payment_hash, &None);
+ run_onion_failure_test("unknown_payment_hash", 2, &nodes, &route, &payment_hash, &payment_secret, |_| {}, || {
+ nodes[2].node.fail_htlc_backwards(&payment_hash);
}, false, Some(PERM|15), None);
+ let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[2]);
- run_onion_failure_test("final_expiry_too_soon", 1, &nodes, &route, &payment_hash, |msg| {
+ run_onion_failure_test("final_expiry_too_soon", 1, &nodes, &route, &payment_hash, &payment_secret, |msg| {
let height = msg.cltv_expiry - CLTV_CLAIM_BUFFER - LATENCY_GRACE_PERIOD_BLOCKS + 1;
connect_blocks(&nodes[0], height - nodes[0].best_block_info().1);
connect_blocks(&nodes[1], height - nodes[1].best_block_info().1);
connect_blocks(&nodes[2], height - nodes[2].best_block_info().1);
}, || {}, true, Some(17), None);
- run_onion_failure_test("final_incorrect_cltv_expiry", 1, &nodes, &route, &payment_hash, |_| {}, || {
+ run_onion_failure_test("final_incorrect_cltv_expiry", 1, &nodes, &route, &payment_hash, &payment_secret, |_| {}, || {
for (_, pending_forwards) in nodes[1].node.channel_state.lock().unwrap().forward_htlcs.iter_mut() {
for f in pending_forwards.iter_mut() {
match f {
}
}, true, Some(18), None);
- run_onion_failure_test("final_incorrect_htlc_amount", 1, &nodes, &route, &payment_hash, |_| {}, || {
+ run_onion_failure_test("final_incorrect_htlc_amount", 1, &nodes, &route, &payment_hash, &payment_secret, |_| {}, || {
// violate amt_to_forward > msg.amount_msat
for (_, pending_forwards) in nodes[1].node.channel_state.lock().unwrap().forward_htlcs.iter_mut() {
for f in pending_forwards.iter_mut() {
}
}, true, Some(19), None);
- run_onion_failure_test("channel_disabled", 0, &nodes, &route, &payment_hash, |_| {}, || {
+ run_onion_failure_test("channel_disabled", 0, &nodes, &route, &payment_hash, &payment_secret, |_| {}, || {
// disconnect event to the channel between nodes[1] ~ nodes[2]
nodes[1].node.peer_disconnected(&nodes[2].node.get_our_node_id(), false);
nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
}, true, Some(UPDATE|20), Some(msgs::HTLCFailChannelUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy()}));
reconnect_nodes(&nodes[1], &nodes[2], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
- run_onion_failure_test("expiry_too_far", 0, &nodes, &route, &payment_hash, |msg| {
+ run_onion_failure_test("expiry_too_far", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
let mut route = route.clone();
let height = nodes[2].best_block_info().1;
// You may not use this file except in accordance with one or both of these
// licenses.
-use ln::channelmanager::{PaymentHash, PaymentSecret, HTLCSource};
+use ln::{PaymentHash, PaymentSecret};
+use ln::channelmanager::HTLCSource;
use ln::msgs;
use routing::router::RouteHop;
use util::byte_utils;
#[cfg(test)]
mod tests {
- use ln::channelmanager::PaymentHash;
+ use ln::PaymentHash;
use ln::features::{ChannelFeatures, NodeFeatures};
use routing::router::{Route, RouteHop};
use ln::msgs;
struct Peer {
channel_encryptor: PeerChannelEncryptor,
- outbound: bool,
their_node_id: Option<PublicKey>,
their_features: Option<InitFeatures>,
let mut peers = self.peers.lock().unwrap();
if peers.peers.insert(descriptor, Peer {
channel_encryptor: peer_encryptor,
- outbound: true,
their_node_id: None,
their_features: None,
let mut peers = self.peers.lock().unwrap();
if peers.peers.insert(descriptor, Peer {
channel_encryptor: peer_encryptor,
- outbound: false,
their_node_id: None,
their_features: None,
peer.pending_read_is_header = true;
peer.their_node_id = Some(their_node_id);
insert_node_id!();
+ let features = InitFeatures::known();
+ let resp = msgs::Init { features };
+ self.enqueue_message(&mut peers.peers_needing_send, peer, peer_descriptor.clone(), &resp);
},
NextNoiseStep::NoiseComplete => {
if peer.pending_read_is_header {
return Err(PeerHandleError{ no_connection_possible: true }.into());
}
- if !peer.outbound {
- let features = InitFeatures::known();
- let resp = msgs::Init { features };
- self.enqueue_message(peers_needing_send, peer, peer_descriptor.clone(), &resp);
- }
-
self.message_handler.route_handler.sync_routing_table(&peer.their_node_id.unwrap(), &msg);
self.message_handler.chan_handler.peer_connected(&peer.their_node_id.unwrap(), &msg);
connect_blocks(&nodes[1], 2*CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1);
connect_blocks(&nodes[2], 2*CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1);
- let (our_payment_preimage, our_payment_hash) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1000000);
+ let (our_payment_preimage, our_payment_hash, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1000000);
// Provide preimage to node 2 by claiming payment
- nodes[2].node.claim_funds(our_payment_preimage, &None, 1000000);
+ nodes[2].node.claim_funds(our_payment_preimage);
check_added_monitors!(nodes[2], 1);
get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
// Now check that we can create a new channel
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
- send_payment(&nodes[0], &[&nodes[1]], 8000000, 8_000_000);
+ send_payment(&nodes[0], &[&nodes[1]], 8000000);
}
#[test]
// Connect blocks on node A to advance height towards TEST_FINAL_CLTV
// Provide node A with both preimage
- nodes[0].node.claim_funds(payment_preimage_1, &None, 3_000_000);
- nodes[0].node.claim_funds(payment_preimage_2, &None, 3_000_000);
+ nodes[0].node.claim_funds(payment_preimage_1);
+ nodes[0].node.claim_funds(payment_preimage_2);
check_added_monitors!(nodes[0], 2);
nodes[0].node.get_and_clear_pending_events();
nodes[0].node.get_and_clear_pending_msg_events();
};
}
-impl<C: Deref + Sync + Send, L: Deref + Sync + Send> RoutingMessageHandler for NetGraphMsgHandler<C, L> where C::Target: chain::Access, L::Target: Logger {
+impl<C: Deref , L: Deref > RoutingMessageHandler for NetGraphMsgHandler<C, L> where C::Target: chain::Access, L::Target: Logger {
fn handle_node_announcement(&self, msg: &msgs::NodeAnnouncement) -> Result<bool, LightningError> {
self.network_graph.write().unwrap().update_node_from_announcement(msg, &self.secp_ctx)?;
Ok(msg.contents.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY &&
}
//Add write and readable traits to channelconfig
-impl_writeable!(ChannelConfig, 8+2+1+1, {
+impl_writeable!(ChannelConfig, 4+2+1+1, {
fee_proportional_millionths,
cltv_expiry_delta,
announced_channel,
//! few other things.
use ln::msgs;
-use ln::channelmanager::{PaymentPreimage, PaymentHash, PaymentSecret};
+use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
use chain::keysinterface::SpendableOutputDescriptor;
use util::ser::{Writeable, Writer, MaybeReadable, Readable};
PaymentReceived {
/// The hash for which the preimage should be handed to the ChannelManager.
payment_hash: PaymentHash,
+ /// The preimage to the payment_hash, if the payment hash (and secret) were fetched via
+ /// [`ChannelManager::create_inbound_payment`]. If provided, this can be handed directly to
+ /// [`ChannelManager::claim_funds`].
+ ///
+ /// [`ChannelManager::create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
+ /// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds
+ payment_preimage: Option<PaymentPreimage>,
/// The "payment secret". This authenticates the sender to the recipient, preventing a
/// number of deanonymization attacks during the routing process.
- /// As nodes upgrade, the invoices you provide should likely migrate to setting the
- /// payment_secret feature to required, at which point you should fail_backwards any HTLCs
- /// which have a None here.
- /// Until then, however, values of None should be ignored, and only incorrect Some values
- /// should result in an HTLC fail_backwards.
- /// Note that, in any case, this value must be passed as-is to any fail or claim calls as
- /// the HTLC index includes this value.
- payment_secret: Option<PaymentSecret>,
+ /// It is provided here for your reference, however its accuracy is enforced directly by
+ /// [`ChannelManager`] using the values you previously provided to
+ /// [`ChannelManager::create_inbound_payment`] or
+ /// [`ChannelManager::create_inbound_payment_for_hash`].
+ ///
+ /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
+ /// [`ChannelManager::create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
+ /// [`ChannelManager::create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
+ payment_secret: PaymentSecret,
/// The value, in thousandths of a satoshi, that this payment is for. Note that you must
/// compare this to the expected value before accepting the payment (as otherwise you are
/// providing proof-of-payment for less than the value you expected!).
amt: u64,
+ /// This is the `user_payment_id` which was provided to
+ /// [`ChannelManager::create_inbound_payment_for_hash`] or
+ /// [`ChannelManager::create_inbound_payment`]. It has no meaning inside of LDK and is
+ /// simply copied here. It may be used to correlate PaymentReceived events with invoice
+ /// metadata stored elsewhere.
+ ///
+ /// [`ChannelManager::create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
+ /// [`ChannelManager::create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
+ user_payment_id: u64,
},
/// Indicates an outbound payment we made succeeded (ie it made it all the way to its target
/// and we got back the payment preimage for it).
// We never write out FundingGenerationReady events as, upon disconnection, peers
// drop any channels which have not yet exchanged funding_signed.
},
- &Event::PaymentReceived { ref payment_hash, ref payment_secret, ref amt } => {
+ &Event::PaymentReceived { ref payment_hash, ref payment_preimage, ref payment_secret, ref amt, ref user_payment_id } => {
1u8.write(writer)?;
payment_hash.write(writer)?;
+ payment_preimage.write(writer)?;
payment_secret.write(writer)?;
amt.write(writer)?;
+ user_payment_id.write(writer)?;
},
&Event::PaymentSent { ref payment_preimage } => {
2u8.write(writer)?;
0u8 => Ok(None),
1u8 => Ok(Some(Event::PaymentReceived {
payment_hash: Readable::read(reader)?,
+ payment_preimage: Readable::read(reader)?,
payment_secret: Readable::read(reader)?,
amt: Readable::read(reader)?,
+ user_payment_id: Readable::read(reader)?,
})),
2u8 => Ok(Some(Event::PaymentSent {
payment_preimage: Readable::read(reader)?,
}
/// A trait encapsulating the operations required of a logger
-pub trait Logger: Sync + Send {
+pub trait Logger {
/// Logs the `Record`
fn log(&self, record: &Record);
}
use bitcoin::hash_types::{Txid, BlockHash};
use std::marker::Sized;
use ln::msgs::DecodeError;
-use ln::channelmanager::{PaymentPreimage, PaymentHash, PaymentSecret};
+use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
use util::byte_utils;
use util::byte_utils::{be64_to_array, be48_to_array, be32_to_array, be16_to_array, slice_to_be16, slice_to_be32, slice_to_be48, slice_to_be64};
if $len != 0 {
w.size_hint($len);
}
+ #[cfg(any(test, feature = "fuzztarget"))]
+ {
+ // In tests, assert that the hard-coded length matches the actual one
+ if $len != 0 {
+ use util::ser::LengthCalculatingWriter;
+ let mut len_calc = LengthCalculatingWriter(0);
+ $( self.$field.write(&mut len_calc)?; )*
+ assert_eq!(len_calc.0, $len);
+ }
+ }
$( self.$field.write(w)?; )*
Ok(())
}
}
}
macro_rules! impl_writeable_len_match {
- ($st:ident, {$({$m: pat, $l: expr}),*}, {$($field:ident),*}) => {
- impl Writeable for $st {
+ ($struct: ident, $cmp: tt, {$({$match: pat, $length: expr}),*}, {$($field:ident),*}) => {
+ impl Writeable for $struct {
fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
- w.size_hint(match *self {
- $($m => $l,)*
- });
+ let len = match *self {
+ $($match => $length,)*
+ };
+ w.size_hint(len);
+ #[cfg(any(test, feature = "fuzztarget"))]
+ {
+ // In tests, assert that the hard-coded length matches the actual one
+ use util::ser::LengthCalculatingWriter;
+ let mut len_calc = LengthCalculatingWriter(0);
+ $( self.$field.write(&mut len_calc)?; )*
+ assert!(len_calc.0 $cmp len);
+ }
$( self.$field.write(w)?; )*
Ok(())
}
}
- impl ::util::ser::Readable for $st {
+ impl ::util::ser::Readable for $struct {
fn read<R: ::std::io::Read>(r: &mut R) -> Result<Self, DecodeError> {
Ok(Self {
$($field: Readable::read(r)?),*
})
}
}
+ };
+ ($struct: ident, {$({$match: pat, $length: expr}),*}, {$($field:ident),*}) => {
+ impl_writeable_len_match!($struct, ==, { $({ $match, $length }),* }, { $($field),* });
}
}
use bitcoin::hash_types::{BlockHash, Txid};
use bitcoin::secp256k1::{SecretKey, PublicKey, Secp256k1, Signature};
+use bitcoin::secp256k1::recovery::RecoverableSignature;
use regex;
fn read_chan_signer(&self, reader: &[u8]) -> Result<Self::Signer, msgs::DecodeError> {
EnforcingSigner::read(&mut std::io::Cursor::new(reader))
}
+ fn sign_invoice(&self, _invoice_preimage: Vec<u8>) -> Result<RecoverableSignature, ()> { unreachable!(); }
}
pub struct TestChainMonitor<'a> {
disable_revocation_policy_check: self.disable_revocation_policy_check,
})
}
+
+ fn sign_invoice(&self, invoice_preimage: Vec<u8>) -> Result<RecoverableSignature, ()> {
+ self.backing.sign_invoice(invoice_preimage)
+ }
}