use lightning::ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdateErr, HTLCUpdate};
use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage, ChannelManagerReadArgs};
use lightning::ln::router::{Route, RouteHop};
-use lightning::ln::msgs::{CommitmentUpdate, ChannelMessageHandler, ErrorAction, LightningError, UpdateAddHTLC, LocalFeatures};
+use lightning::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
+use lightning::ln::msgs::{CommitmentUpdate, ChannelMessageHandler, ErrorAction, UpdateAddHTLC, Init};
use lightning::util::enforcing_trait_impls::EnforcingChannelKeys;
use lightning::util::events;
use lightning::util::logger::Logger;
impl TestChannelMonitor {
pub fn new(chain_monitor: Arc<dyn chaininterface::ChainWatchInterface>, broadcaster: Arc<dyn chaininterface::BroadcasterInterface>, logger: Arc<dyn Logger>, feeest: Arc<dyn chaininterface::FeeEstimator>) -> Self {
Self {
- simple_monitor: channelmonitor::SimpleManyChannelMonitor::new(chain_monitor, broadcaster, logger, feeest),
+ simple_monitor: Arc::new(channelmonitor::SimpleManyChannelMonitor::new(chain_monitor, broadcaster, logger, feeest)),
update_ret: Mutex::new(Ok(())),
latest_good_update: Mutex::new(HashMap::new()),
latest_update_good: Mutex::new(HashMap::new()),
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[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, 3, self.node_id]).unwrap())
}
- fn get_channel_keys(&self, _inbound: bool) -> EnforcingChannelKeys {
+ fn get_channel_keys(&self, _inbound: bool, channel_value_satoshis: u64) -> EnforcingChannelKeys {
EnforcingChannelKeys::new(InMemoryChannelKeys {
funding_key: SecretKey::from_slice(&[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, 4, self.node_id]).unwrap(),
revocation_base_key: SecretKey::from_slice(&[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, 5, self.node_id]).unwrap(),
delayed_payment_base_key: SecretKey::from_slice(&[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, 7, self.node_id]).unwrap(),
htlc_base_key: SecretKey::from_slice(&[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, 8, self.node_id]).unwrap(),
commitment_seed: [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, 9, self.node_id],
+ remote_channel_pubkeys: None,
+ channel_value_satoshis,
})
}
config.channel_options.fee_proportional_millionths = 0;
config.channel_options.announced_channel = true;
config.peer_channel_config_limits.min_dust_limit_satoshis = 0;
- (ChannelManager::new(Network::Bitcoin, fee_est.clone(), monitor.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, 0).unwrap(),
+ (Arc::new(ChannelManager::new(Network::Bitcoin, fee_est.clone(), monitor.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, 0).unwrap()),
monitor)
} }
}
channel_monitors: &mut monitor_refs,
};
- let res = (<(Sha256d, ChannelManager<EnforcingChannelKeys>)>::read(&mut Cursor::new(&$ser.0), read_args).expect("Failed to read manager").1, monitor);
+ let res = (<(Sha256d, ChannelManager<EnforcingChannelKeys, Arc<TestChannelMonitor>>)>::read(&mut Cursor::new(&$ser.0), read_args).expect("Failed to read manager").1, monitor);
for (_, was_good) in $old_monitors.latest_updates_good_at_last_ser.lock().unwrap().iter() {
if !was_good {
// If the last time we updated a monitor we didn't successfully update (and we
} else { panic!("Wrong event type"); }
};
- $dest.handle_open_channel(&$source.get_our_node_id(), LocalFeatures::new(), &open_channel).unwrap();
+ $dest.handle_open_channel(&$source.get_our_node_id(), InitFeatures::supported(), &open_channel);
let accept_channel = {
let events = $dest.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
} else { panic!("Wrong event type"); }
};
- $source.handle_accept_channel(&$dest.get_our_node_id(), LocalFeatures::new(), &accept_channel).unwrap();
+ $source.handle_accept_channel(&$dest.get_our_node_id(), InitFeatures::supported(), &accept_channel);
{
let events = $source.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
msg.clone()
} else { panic!("Wrong event type"); }
};
- $dest.handle_funding_created(&$source.get_our_node_id(), &funding_created).unwrap();
+ $dest.handle_funding_created(&$source.get_our_node_id(), &funding_created);
let funding_signed = {
let events = $dest.get_and_clear_pending_msg_events();
msg.clone()
} else { panic!("Wrong event type"); }
};
- $source.handle_funding_signed(&$dest.get_our_node_id(), &funding_signed).unwrap();
+ $source.handle_funding_signed(&$dest.get_our_node_id(), &funding_signed);
{
let events = $source.get_and_clear_pending_events();
if let events::MessageSendEvent::SendFundingLocked { ref node_id, ref msg } = event {
for node in $nodes.iter() {
if node.get_our_node_id() == *node_id {
- node.handle_funding_locked(&$nodes[idx].get_our_node_id(), msg).unwrap();
+ node.handle_funding_locked(&$nodes[idx].get_our_node_id(), msg);
}
}
} else { panic!("Wrong event type"); }
let mut node_c_ser = VecWriter(Vec::new());
nodes[2].write(&mut node_c_ser).unwrap();
- macro_rules! test_err {
- ($res: expr) => {
- match $res {
- Ok(()) => {},
- Err(LightningError { action: ErrorAction::IgnoreError, .. }) => { },
- _ => { $res.unwrap() },
- }
- }
- }
-
macro_rules! test_return {
() => { {
assert_eq!(nodes[0].list_channels().len(), 1);
let payment_hash = Sha256::hash(&[payment_id; 1]);
payment_id = payment_id.wrapping_add(1);
if let Err(_) = $source.send_payment(Route {
- hops: vec![RouteHop {
+ paths: vec![vec![RouteHop {
pubkey: $dest.0.get_our_node_id(),
+ node_features: NodeFeatures::empty(),
short_channel_id: $dest.1,
+ channel_features: ChannelFeatures::empty(),
fee_msat: 5000000,
cltv_expiry_delta: 200,
- }],
- }, PaymentHash(payment_hash.into_inner())) {
+ }]],
+ }, PaymentHash(payment_hash.into_inner()), None) {
// Probably ran out of funds
test_return!();
}
} };
- ($source: expr, $middle: expr, $dest: expr) => { {
+ ($source: expr, $middle: expr, $dest: expr, false) => { {
let payment_hash = Sha256::hash(&[payment_id; 1]);
payment_id = payment_id.wrapping_add(1);
if let Err(_) = $source.send_payment(Route {
- hops: vec![RouteHop {
+ 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: 50000,
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: 5000000,
cltv_expiry_delta: 200,
- }],
- }, PaymentHash(payment_hash.into_inner())) {
+ }]],
+ }, PaymentHash(payment_hash.into_inner()), None) {
+ // Probably ran out of funds
+ test_return!();
+ }
+ } };
+ ($source: expr, $middle: expr, $dest: expr, true) => { {
+ 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(_) = $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: 50000,
+ 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: 5000000,
+ 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: 50000,
+ 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: 5000000,
+ cltv_expiry_delta: 200,
+ }]],
+ }, PaymentHash(payment_hash.into_inner()), Some(&payment_secret.into_inner())) {
// Probably ran out of funds
test_return!();
}
bc_events.clear();
new_events
} else { Vec::new() };
- for event in events.iter().chain(nodes[$node].get_and_clear_pending_msg_events().iter()) {
+ let ev = nodes[$node].get_and_clear_pending_msg_events();
+ for event in events.iter().chain(ev.iter()) {
+ match event {
+ events::MessageSendEvent::UpdateHTLCs { updates: CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, ref update_fulfill_htlcs, ref update_fail_malformed_htlcs, .. }, .. } => {
+ println!("UPDATEHTLCs {} {} {} {}", update_add_htlcs.len(), update_fail_htlcs.len(), update_fulfill_htlcs.len(), update_fail_malformed_htlcs.len());
+ },
+ events::MessageSendEvent::SendRevokeAndACK { .. } => {
+ println!("RAA");
+ },
+ events::MessageSendEvent::SendChannelReestablish { .. } => {
+ println!("Chan REE");
+ },
+ events::MessageSendEvent::SendFundingLocked { .. } => {
+ println!("FL");
+ },
+ events::MessageSendEvent::PaymentFailureNetworkUpdate { .. } => {
+ println!("Fail net update");
+ },
+ _ => panic!("Unhandled message event"),
+ }
+ }
+ for event in events.iter().chain(ev.iter()) {
match event {
events::MessageSendEvent::UpdateHTLCs { ref node_id, updates: CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, ref update_fulfill_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => {
for dest in nodes.iter() {
assert!(update_fee.is_none());
for update_add in update_add_htlcs {
if !$corrupt_forward {
- test_err!(dest.handle_update_add_htlc(&nodes[$node].get_our_node_id(), &update_add));
+ dest.handle_update_add_htlc(&nodes[$node].get_our_node_id(), &update_add);
} else {
// Corrupt the update_add_htlc message so that its HMAC
// check will fail and we generate a
let mut msg_ser = update_add.encode();
msg_ser[1000] ^= 0xff;
let new_msg = UpdateAddHTLC::read(&mut Cursor::new(&msg_ser)).unwrap();
- test_err!(dest.handle_update_add_htlc(&nodes[$node].get_our_node_id(), &new_msg));
+ dest.handle_update_add_htlc(&nodes[$node].get_our_node_id(), &new_msg);
}
}
for update_fulfill in update_fulfill_htlcs {
- test_err!(dest.handle_update_fulfill_htlc(&nodes[$node].get_our_node_id(), &update_fulfill));
+ dest.handle_update_fulfill_htlc(&nodes[$node].get_our_node_id(), &update_fulfill);
}
for update_fail in update_fail_htlcs {
- test_err!(dest.handle_update_fail_htlc(&nodes[$node].get_our_node_id(), &update_fail));
+ dest.handle_update_fail_htlc(&nodes[$node].get_our_node_id(), &update_fail);
}
for update_fail_malformed in update_fail_malformed_htlcs {
- test_err!(dest.handle_update_fail_malformed_htlc(&nodes[$node].get_our_node_id(), &update_fail_malformed));
+ dest.handle_update_fail_malformed_htlc(&nodes[$node].get_our_node_id(), &update_fail_malformed);
}
- test_err!(dest.handle_commitment_signed(&nodes[$node].get_our_node_id(), &commitment_signed));
+ dest.handle_commitment_signed(&nodes[$node].get_our_node_id(), &commitment_signed);
}
}
},
events::MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => {
for dest in nodes.iter() {
if dest.get_our_node_id() == *node_id {
- test_err!(dest.handle_revoke_and_ack(&nodes[$node].get_our_node_id(), msg));
+ dest.handle_revoke_and_ack(&nodes[$node].get_our_node_id(), msg);
}
}
},
events::MessageSendEvent::SendChannelReestablish { ref node_id, ref msg } => {
for dest in nodes.iter() {
if dest.get_our_node_id() == *node_id {
- test_err!(dest.handle_channel_reestablish(&nodes[$node].get_our_node_id(), msg));
+ dest.handle_channel_reestablish(&nodes[$node].get_our_node_id(), msg);
}
}
},
// Can be generated due to a payment forward being rejected due to a
// channel having previously failed a monitor update
},
+ events::MessageSendEvent::HandleError { action: ErrorAction::IgnoreError, .. } => {
+ // Can be generated at any processing step to send back an error, disconnect
+ // peer or just ignore
+ },
_ => panic!("Unhandled message event"),
}
}
events::MessageSendEvent::SendChannelReestablish { .. } => {},
events::MessageSendEvent::SendFundingLocked { .. } => {},
events::MessageSendEvent::PaymentFailureNetworkUpdate { .. } => {},
+ events::MessageSendEvent::HandleError { action: ErrorAction::IgnoreError, .. } => {},
_ => panic!("Unhandled message event"),
}
}
events::MessageSendEvent::SendChannelReestablish { .. } => {},
events::MessageSendEvent::SendFundingLocked { .. } => {},
events::MessageSendEvent::PaymentFailureNetworkUpdate { .. } => {},
+ events::MessageSendEvent::HandleError { action: ErrorAction::IgnoreError, .. } => {},
_ => panic!("Unhandled message event"),
}
}
},
events::MessageSendEvent::SendFundingLocked { .. } => false,
events::MessageSendEvent::PaymentFailureNetworkUpdate { .. } => false,
+ events::MessageSendEvent::HandleError { action: ErrorAction::IgnoreError, .. } => false,
_ => panic!("Unhandled message event"),
};
if push { msg_sink.push(event); }
});
for event in events.drain(..) {
match event {
- events::Event::PaymentReceived { payment_hash, .. } => {
+ events::Event::PaymentReceived { payment_hash, payment_secret, .. } => {
if claim_set.insert(payment_hash.0) {
if $fail {
- assert!(nodes[$node].fail_htlc_backwards(&payment_hash));
+ assert!(nodes[$node].fail_htlc_backwards(&payment_hash, &payment_secret));
} else {
- assert!(nodes[$node].claim_funds(PaymentPreimage(payment_hash.0), 5_000_000));
+ assert!(nodes[$node].claim_funds(PaymentPreimage(payment_hash.0), &payment_secret, 5_000_000));
}
}
},
} }
}
- match get_slice!(1)[0] {
+ let a = get_slice!(1)[0];
+ println!("PROCESSING {:x}", a);
+ match a {
0x00 => *monitor_a.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure),
0x01 => *monitor_b.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure),
0x02 => *monitor_c.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure),
0x0a => send_payment!(nodes[1], (&nodes[0], chan_a)),
0x0b => send_payment!(nodes[1], (&nodes[2], chan_b)),
0x0c => send_payment!(nodes[2], (&nodes[1], chan_b)),
- 0x0d => send_payment!(nodes[0], (&nodes[1], chan_a), (&nodes[2], chan_b)),
- 0x0e => send_payment!(nodes[2], (&nodes[1], chan_b), (&nodes[0], chan_a)),
+ 0x0d => send_payment!(nodes[0], (&nodes[1], chan_a), (&nodes[2], chan_b), false),
+ 0x0e => send_payment!(nodes[2], (&nodes[1], chan_b), (&nodes[0], chan_a), false),
0x0f => {
if !chan_a_disconnected {
nodes[0].peer_disconnected(&nodes[1].get_our_node_id(), false);
},
0x11 => {
if chan_a_disconnected {
- nodes[0].peer_connected(&nodes[1].get_our_node_id());
- nodes[1].peer_connected(&nodes[0].get_our_node_id());
+ 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() });
chan_a_disconnected = false;
}
},
0x12 => {
if chan_b_disconnected {
- nodes[1].peer_connected(&nodes[2].get_our_node_id());
- nodes[2].peer_connected(&nodes[1].get_our_node_id());
+ 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() });
chan_b_disconnected = false;
}
},
nodes[2] = node_c.clone();
monitor_c = new_monitor_c;
},
+ 0x22 => send_payment!(nodes[0], (&nodes[1], chan_a), (&nodes[2], chan_b), true),
+ 0x23 => send_payment!(nodes[2], (&nodes[1], chan_b), (&nodes[0], chan_a), true),
_ => test_return!(),
}
pub extern "C" fn chanmon_consistency_run(data: *const u8, datalen: usize) {
do_test(unsafe { std::slice::from_raw_parts(data, datalen) });
}
-
-#[cfg(test)]
-mod tests {
- #[test]
- fn duplicate_crash() {
- super::do_test(&::hex::decode("00").unwrap());
- }
-}