use bitcoin::blockdata::constants::genesis_block;
use bitcoin::blockdata::transaction::{Transaction, TxOut};
-use bitcoin::blockdata::script::{Builder, Script};
+use bitcoin::blockdata::script::{Builder, ScriptBuf};
use bitcoin::blockdata::opcodes;
-use bitcoin::blockdata::locktime::PackedLockTime;
+use bitcoin::blockdata::locktime::absolute::LockTime;
use bitcoin::network::constants::Network;
use bitcoin::hashes::Hash as TraitImport;
use bitcoin::hashes::sha256d::Hash as Sha256dHash;
use bitcoin::hash_types::{BlockHash, WPubkeyHash};
+use lightning::blinded_path::BlindedPath;
+use lightning::blinded_path::payment::ReceiveTlvs;
use lightning::chain;
use lightning::chain::{BestBlock, ChannelMonitorUpdateStatus, chainmonitor, channelmonitor, Confirm, Watch};
use lightning::chain::channelmonitor::{ChannelMonitor, MonitorEvent};
use lightning::sign::{KeyMaterial, InMemorySigner, Recipient, EntropySource, NodeSigner, SignerProvider};
use lightning::events;
use lightning::events::MessageSendEventsProvider;
-use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
+use lightning::ln::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret};
use lightning::ln::channelmanager::{ChainParameters, ChannelDetails, ChannelManager, PaymentSendFailure, ChannelManagerReadArgs, PaymentId, RecipientOnionFields};
use lightning::ln::channel::FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
use lightning::ln::msgs::{self, CommitmentUpdate, ChannelMessageHandler, DecodeError, UpdateAddHTLC, Init};
use lightning::ln::script::ShutdownScript;
use lightning::ln::functional_test_utils::*;
-use lightning::util::enforcing_trait_impls::{EnforcingSigner, EnforcementState};
+use lightning::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice};
+use lightning::offers::invoice_request::UnsignedInvoiceRequest;
+use lightning::onion_message::messenger::{Destination, MessageRouter, OnionMessagePath};
+use lightning::util::test_channel_signer::{TestChannelSigner, EnforcementState};
use lightning::util::errors::APIError;
use lightning::util::logger::Logger;
use lightning::util::config::UserConfig;
use crate::utils::test_logger::{self, Output};
use crate::utils::test_persister::TestPersister;
-use bitcoin::secp256k1::{Message, PublicKey, SecretKey, Scalar, Secp256k1};
+use bitcoin::secp256k1::{Message, PublicKey, SecretKey, Scalar, Secp256k1, self};
use bitcoin::secp256k1::ecdh::SharedSecret;
use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
+use bitcoin::secp256k1::schnorr;
use std::mem;
use std::cmp::{self, Ordering};
// always return a HighPriority feerate here which is >= the maximum Normal feerate and a
// Background feerate which is <= the minimum Normal feerate.
match conf_target {
- ConfirmationTarget::HighPriority => MAX_FEE,
- ConfirmationTarget::Background|ConfirmationTarget::MempoolMinimum => 253,
- ConfirmationTarget::Normal => cmp::min(self.ret_val.load(atomic::Ordering::Acquire), MAX_FEE),
+ ConfirmationTarget::OnChainSweep => MAX_FEE,
+ ConfirmationTarget::ChannelCloseMinimum|ConfirmationTarget::AnchorChannelFee|ConfirmationTarget::MinAllowedAnchorChannelRemoteFee|ConfirmationTarget::MinAllowedNonAnchorChannelRemoteFee => 253,
+ ConfirmationTarget::NonAnchorChannelFee => cmp::min(self.ret_val.load(atomic::Ordering::Acquire), MAX_FEE),
}
}
}
impl Router for FuzzRouter {
fn find_route(
&self, _payer: &PublicKey, _params: &RouteParameters, _first_hops: Option<&[&ChannelDetails]>,
- _inflight_htlcs: &InFlightHtlcs
+ _inflight_htlcs: InFlightHtlcs
) -> Result<Route, msgs::LightningError> {
Err(msgs::LightningError {
err: String::from("Not implemented"),
action: msgs::ErrorAction::IgnoreError
})
}
+
+ fn create_blinded_payment_paths<
+ ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification
+ >(
+ &self, _recipient: PublicKey, _first_hops: Vec<ChannelDetails>, _tlvs: ReceiveTlvs,
+ _amount_msats: u64, _entropy_source: &ES, _secp_ctx: &Secp256k1<T>
+ ) -> Result<Vec<(BlindedPayInfo, BlindedPath)>, ()> {
+ unreachable!()
+ }
+}
+
+impl MessageRouter for FuzzRouter {
+ fn find_path(
+ &self, _sender: PublicKey, _peers: Vec<PublicKey>, _destination: Destination
+ ) -> Result<OnionMessagePath, ()> {
+ unreachable!()
+ }
+
+ fn create_blinded_paths<
+ ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification
+ >(
+ &self, _recipient: PublicKey, _peers: Vec<PublicKey>, _entropy_source: &ES,
+ _secp_ctx: &Secp256k1<T>
+ ) -> Result<Vec<BlindedPath>, ()> {
+ unreachable!()
+ }
}
pub struct TestBroadcaster {}
pub logger: Arc<dyn Logger>,
pub keys: Arc<KeyProvider>,
pub persister: Arc<TestPersister>,
- pub chain_monitor: Arc<chainmonitor::ChainMonitor<EnforcingSigner, Arc<dyn chain::Filter>, Arc<TestBroadcaster>, Arc<FuzzEstimator>, Arc<dyn Logger>, Arc<TestPersister>>>,
+ pub chain_monitor: Arc<chainmonitor::ChainMonitor<TestChannelSigner, Arc<dyn chain::Filter>, Arc<TestBroadcaster>, Arc<FuzzEstimator>, Arc<dyn Logger>, Arc<TestPersister>>>,
// If we reload a node with an old copy of ChannelMonitors, the ChannelManager deserialization
// logic will automatically force-close our channels for us (as we don't have an up-to-date
// monitor implying we are not able to punish misbehaving counterparties). Because this test
// "fails" if we ever force-close a channel, we avoid doing so, always saving the latest
// fully-serialized monitor state here, as well as the corresponding update_id.
pub latest_monitors: Mutex<HashMap<OutPoint, (u64, Vec<u8>)>>,
- pub should_update_manager: atomic::AtomicBool,
}
impl TestChainMonitor {
pub fn new(broadcaster: Arc<TestBroadcaster>, logger: Arc<dyn Logger>, feeest: Arc<FuzzEstimator>, persister: Arc<TestPersister>, keys: Arc<KeyProvider>) -> Self {
keys,
persister,
latest_monitors: Mutex::new(HashMap::new()),
- should_update_manager: atomic::AtomicBool::new(false),
}
}
}
-impl chain::Watch<EnforcingSigner> for TestChainMonitor {
- fn watch_channel(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor<EnforcingSigner>) -> chain::ChannelMonitorUpdateStatus {
+impl chain::Watch<TestChannelSigner> for TestChainMonitor {
+ fn watch_channel(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor<TestChannelSigner>) -> Result<chain::ChannelMonitorUpdateStatus, ()> {
let mut ser = VecWriter(Vec::new());
monitor.write(&mut ser).unwrap();
if let Some(_) = self.latest_monitors.lock().unwrap().insert(funding_txo, (monitor.get_latest_update_id(), ser.0)) {
panic!("Already had monitor pre-watch_channel");
}
- self.should_update_manager.store(true, atomic::Ordering::Relaxed);
self.chain_monitor.watch_channel(funding_txo, monitor)
}
hash_map::Entry::Occupied(entry) => entry,
hash_map::Entry::Vacant(_) => panic!("Didn't have monitor on update call"),
};
- let deserialized_monitor = <(BlockHash, channelmonitor::ChannelMonitor<EnforcingSigner>)>::
+ let deserialized_monitor = <(BlockHash, channelmonitor::ChannelMonitor<TestChannelSigner>)>::
read(&mut Cursor::new(&map_entry.get().1), (&*self.keys, &*self.keys)).unwrap().1;
- deserialized_monitor.update_monitor(update, &&TestBroadcaster{}, &FuzzEstimator { ret_val: atomic::AtomicU32::new(253) }, &self.logger).unwrap();
+ deserialized_monitor.update_monitor(update, &&TestBroadcaster{}, &&FuzzEstimator { ret_val: atomic::AtomicU32::new(253) }, &self.logger).unwrap();
let mut ser = VecWriter(Vec::new());
deserialized_monitor.write(&mut ser).unwrap();
map_entry.insert((update.update_id, ser.0));
- self.should_update_manager.store(true, atomic::Ordering::Relaxed);
self.chain_monitor.update_channel(funding_txo, update)
}
- fn release_pending_monitor_events(&self) -> Vec<(OutPoint, Vec<MonitorEvent>, Option<PublicKey>)> {
+ fn release_pending_monitor_events(&self) -> Vec<(OutPoint, ChannelId, Vec<MonitorEvent>, Option<PublicKey>)> {
return self.chain_monitor.release_pending_monitor_events();
}
}
unreachable!()
}
+ fn sign_bolt12_invoice_request(
+ &self, _invoice_request: &UnsignedInvoiceRequest
+ ) -> Result<schnorr::Signature, ()> {
+ unreachable!()
+ }
+
+ fn sign_bolt12_invoice(
+ &self, _invoice: &UnsignedBolt12Invoice,
+ ) -> Result<schnorr::Signature, ()> {
+ unreachable!()
+ }
+
fn sign_gossip_message(&self, msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result<Signature, ()> {
let msg_hash = Message::from_slice(&Sha256dHash::hash(&msg.encode()[..])[..]).map_err(|_| ())?;
let secp_ctx = Secp256k1::signing_only();
}
impl SignerProvider for KeyProvider {
- type Signer = EnforcingSigner;
+ type EcdsaSigner = TestChannelSigner;
+ #[cfg(taproot)]
+ type TaprootSigner = TestChannelSigner;
fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] {
let id = self.rand_bytes_id.fetch_add(1, atomic::Ordering::Relaxed) as u8;
[id; 32]
}
- fn derive_channel_signer(&self, channel_value_satoshis: u64, channel_keys_id: [u8; 32]) -> Self::Signer {
+ fn derive_channel_signer(&self, channel_value_satoshis: u64, channel_keys_id: [u8; 32]) -> Self::EcdsaSigner {
let secp_ctx = Secp256k1::signing_only();
let id = channel_keys_id[0];
let keys = InMemorySigner::new(
channel_keys_id,
);
let revoked_commitment = self.make_enforcement_state_cell(keys.commitment_seed);
- EnforcingSigner::new_with_revoked(keys, revoked_commitment, false)
+ TestChannelSigner::new_with_revoked(keys, revoked_commitment, false)
}
- fn read_chan_signer(&self, buffer: &[u8]) -> Result<Self::Signer, DecodeError> {
+ fn read_chan_signer(&self, buffer: &[u8]) -> Result<Self::EcdsaSigner, DecodeError> {
let mut reader = std::io::Cursor::new(buffer);
let inner: InMemorySigner = ReadableArgs::read(&mut reader, self)?;
let state = self.make_enforcement_state_cell(inner.commitment_seed);
- Ok(EnforcingSigner {
+ Ok(TestChannelSigner {
inner,
state,
disable_revocation_policy_check: false,
+ available: Arc::new(Mutex::new(true)),
})
}
- fn get_destination_script(&self) -> Result<Script, ()> {
+ fn get_destination_script(&self, _channel_keys_id: [u8; 32]) -> Result<ScriptBuf, ()> {
let secp_ctx = Secp256k1::signing_only();
let channel_monitor_claim_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, 2, self.node_secret[31]]).unwrap();
let our_channel_monitor_claim_key_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &channel_monitor_claim_key).serialize());
- Ok(Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script())
+ Ok(Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(our_channel_monitor_claim_key_hash).into_script())
}
fn get_shutdown_scriptpubkey(&self) -> Result<ShutdownScript, ()> {
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());
+ payment_hash = PaymentHash(Sha256::hash(&[*payment_id; 1]).to_byte_array());
if let Ok(payment_secret) = dest.create_inbound_payment_for_hash(payment_hash, None, 3600, None) {
return Some((payment_secret, payment_hash));
}
channel_features: dest.channel_features(),
fee_msat: amt,
cltv_expiry_delta: 200,
+ maybe_announced_channel: true,
}], blinded_tail: None }],
- payment_params: None,
+ route_params: None,
}, payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_id)) {
check_payment_err(err, amt > max_value_sendable || amt < min_value_sendable);
false
channel_features: middle.channel_features(),
fee_msat: first_hop_fee,
cltv_expiry_delta: 100,
- },RouteHop {
+ maybe_announced_channel: true,
+ }, RouteHop {
pubkey: dest.get_our_node_id(),
node_features: dest.node_features(),
short_channel_id: dest_chan_id,
channel_features: dest.channel_features(),
fee_msat: amt,
cltv_expiry_delta: 200,
+ maybe_announced_channel: true,
}], blinded_tail: None }],
- payment_params: None,
+ route_params: None,
}, payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_id)) {
let sent_amt = amt + first_hop_fee;
check_payment_err(err, sent_amt < min_value_sendable || sent_amt > max_value_sendable);
}
#[inline]
-pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out) {
+pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
let out = SearchingOutput::new(underlying_out);
let broadcast = Arc::new(TestBroadcaster{});
let router = FuzzRouter {};
let mut config = UserConfig::default();
config.channel_config.forwarding_fee_proportional_millionths = 0;
config.channel_handshake_config.announced_channel = true;
+ if anchors {
+ config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
+ config.manually_accept_inbound_channels = true;
+ }
let network = Network::Bitcoin;
let best_block_timestamp = genesis_block(network).header.time;
let params = ChainParameters {
let mut config = UserConfig::default();
config.channel_config.forwarding_fee_proportional_millionths = 0;
config.channel_handshake_config.announced_channel = true;
+ if anchors {
+ config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
+ config.manually_accept_inbound_channels = true;
+ }
let mut monitors = HashMap::new();
let mut old_monitors = $old_monitors.latest_monitors.lock().unwrap();
for (outpoint, (update_id, monitor_ser)) in old_monitors.drain() {
- monitors.insert(outpoint, <(BlockHash, ChannelMonitor<EnforcingSigner>)>::read(&mut Cursor::new(&monitor_ser), (&*$keys_manager, &*$keys_manager)).expect("Failed to read monitor").1);
+ monitors.insert(outpoint, <(BlockHash, ChannelMonitor<TestChannelSigner>)>::read(&mut Cursor::new(&monitor_ser), (&*$keys_manager, &*$keys_manager)).expect("Failed to read monitor").1);
chain_monitor.latest_monitors.lock().unwrap().insert(outpoint, (update_id, monitor_ser));
}
let mut monitor_refs = HashMap::new();
let res = (<(BlockHash, ChanMan)>::read(&mut Cursor::new(&$ser.0), read_args).expect("Failed to read manager").1, chain_monitor.clone());
for (funding_txo, mon) in monitors.drain() {
assert_eq!(chain_monitor.chain_monitor.watch_channel(funding_txo, mon),
- ChannelMonitorUpdateStatus::Completed);
+ Ok(ChannelMonitorUpdateStatus::Completed));
}
res
} }
let mut channel_txn = Vec::new();
macro_rules! make_channel {
- ($source: expr, $dest: expr, $chan_id: expr) => { {
+ ($source: expr, $dest: expr, $dest_keys_manager: expr, $chan_id: expr) => { {
$source.peer_connected(&$dest.get_our_node_id(), &Init {
features: $dest.init_features(), networks: None, remote_network_address: None
}, true).unwrap();
features: $source.init_features(), networks: None, remote_network_address: None
}, false).unwrap();
- $source.create_channel($dest.get_our_node_id(), 100_000, 42, 0, None).unwrap();
+ $source.create_channel($dest.get_our_node_id(), 100_000, 42, 0, None, None).unwrap();
let open_channel = {
let events = $source.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
$dest.handle_open_channel(&$source.get_our_node_id(), &open_channel);
let accept_channel = {
+ if anchors {
+ let events = $dest.get_and_clear_pending_events();
+ assert_eq!(events.len(), 1);
+ if let events::Event::OpenChannelRequest {
+ ref temporary_channel_id, ref counterparty_node_id, ..
+ } = events[0] {
+ let mut random_bytes = [0u8; 16];
+ random_bytes.copy_from_slice(&$dest_keys_manager.get_secure_random_bytes()[..16]);
+ let user_channel_id = u128::from_be_bytes(random_bytes);
+ $dest.accept_inbound_channel(
+ temporary_channel_id,
+ counterparty_node_id,
+ user_channel_id,
+ ).unwrap();
+ } else { panic!("Wrong event type"); }
+ }
let events = $dest.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
if let events::MessageSendEvent::SendAcceptChannel { ref msg, .. } = events[0] {
let events = $source.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
if let events::Event::FundingGenerationReady { ref temporary_channel_id, ref channel_value_satoshis, ref output_script, .. } = events[0] {
- let tx = Transaction { version: $chan_id, lock_time: PackedLockTime::ZERO, input: Vec::new(), output: vec![TxOut {
+ let tx = Transaction { version: $chan_id, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
value: *channel_value_satoshis, script_pubkey: output_script.clone(),
}]};
funding_output = OutPoint { txid: tx.txid(), index: 0 };
let mut nodes = [node_a, node_b, node_c];
- let chan_1_funding = make_channel!(nodes[0], nodes[1], 0);
- let chan_2_funding = make_channel!(nodes[1], nodes[2], 1);
+ let chan_1_funding = make_channel!(nodes[0], nodes[1], keys_manager_b, 0);
+ let chan_2_funding = make_channel!(nodes[1], nodes[2], keys_manager_c, 1);
for node in nodes.iter() {
confirm_txn!(node);
if !chan_a_disconnected {
nodes[1].peer_disconnected(&nodes[0].get_our_node_id());
chan_a_disconnected = true;
- drain_msg_events_on_disconnect!(0);
- }
- if monitor_a.should_update_manager.load(atomic::Ordering::Relaxed) {
- node_a_ser.0.clear();
- nodes[0].write(&mut node_a_ser).unwrap();
+ push_excess_b_events!(nodes[1].get_and_clear_pending_msg_events().drain(..), Some(0));
+ ab_events.clear();
+ ba_events.clear();
}
let (new_node_a, new_monitor_a) = reload_node!(node_a_ser, 0, monitor_a, keys_manager_a, fee_est_a);
nodes[0] = new_node_a;
if !chan_b_disconnected {
nodes[1].peer_disconnected(&nodes[2].get_our_node_id());
chan_b_disconnected = true;
- drain_msg_events_on_disconnect!(2);
- }
- if monitor_c.should_update_manager.load(atomic::Ordering::Relaxed) {
- node_c_ser.0.clear();
- nodes[2].write(&mut node_c_ser).unwrap();
+ push_excess_b_events!(nodes[1].get_and_clear_pending_msg_events().drain(..), Some(2));
+ bc_events.clear();
+ cb_events.clear();
}
let (new_node_c, new_monitor_c) = reload_node!(node_c_ser, 2, monitor_c, keys_manager_c, fee_est_c);
nodes[2] = new_node_c;
0x6d => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 1, &mut payment_id, &mut payment_idx); },
0x80 => {
- let max_feerate = last_htlc_clear_fee_a * FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE as u32;
+ let mut max_feerate = last_htlc_clear_fee_a;
+ if !anchors {
+ max_feerate *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE as u32;
+ }
if fee_est_a.ret_val.fetch_add(250, atomic::Ordering::AcqRel) + 250 > max_feerate {
fee_est_a.ret_val.store(max_feerate, atomic::Ordering::Release);
}
0x81 => { fee_est_a.ret_val.store(253, atomic::Ordering::Release); nodes[0].maybe_update_chan_fees(); },
0x84 => {
- let max_feerate = last_htlc_clear_fee_b * FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE as u32;
+ let mut max_feerate = last_htlc_clear_fee_b;
+ if !anchors {
+ max_feerate *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE as u32;
+ }
if fee_est_b.ret_val.fetch_add(250, atomic::Ordering::AcqRel) + 250 > max_feerate {
fee_est_b.ret_val.store(max_feerate, atomic::Ordering::Release);
}
0x85 => { fee_est_b.ret_val.store(253, atomic::Ordering::Release); nodes[1].maybe_update_chan_fees(); },
0x88 => {
- let max_feerate = last_htlc_clear_fee_c * FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE as u32;
+ let mut max_feerate = last_htlc_clear_fee_c;
+ if !anchors {
+ max_feerate *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE as u32;
+ }
if fee_est_c.ret_val.fetch_add(250, atomic::Ordering::AcqRel) + 250 > max_feerate {
fee_est_c.ret_val.store(max_feerate, atomic::Ordering::Release);
}
},
0x89 => { fee_est_c.ret_val.store(253, atomic::Ordering::Release); nodes[2].maybe_update_chan_fees(); },
+ 0xf0 => {
+ let pending_updates = monitor_a.chain_monitor.list_pending_monitor_updates().remove(&chan_1_funding).unwrap();
+ if let Some(id) = pending_updates.get(0) {
+ monitor_a.chain_monitor.channel_monitor_updated(chan_1_funding, *id).unwrap();
+ }
+ nodes[0].process_monitor_events();
+ }
+ 0xf1 => {
+ let pending_updates = monitor_a.chain_monitor.list_pending_monitor_updates().remove(&chan_1_funding).unwrap();
+ if let Some(id) = pending_updates.get(1) {
+ monitor_a.chain_monitor.channel_monitor_updated(chan_1_funding, *id).unwrap();
+ }
+ nodes[0].process_monitor_events();
+ }
+ 0xf2 => {
+ let pending_updates = monitor_a.chain_monitor.list_pending_monitor_updates().remove(&chan_1_funding).unwrap();
+ if let Some(id) = pending_updates.last() {
+ monitor_a.chain_monitor.channel_monitor_updated(chan_1_funding, *id).unwrap();
+ }
+ nodes[0].process_monitor_events();
+ }
+
+ 0xf4 => {
+ let pending_updates = monitor_b.chain_monitor.list_pending_monitor_updates().remove(&chan_1_funding).unwrap();
+ if let Some(id) = pending_updates.get(0) {
+ monitor_b.chain_monitor.channel_monitor_updated(chan_1_funding, *id).unwrap();
+ }
+ nodes[1].process_monitor_events();
+ }
+ 0xf5 => {
+ let pending_updates = monitor_b.chain_monitor.list_pending_monitor_updates().remove(&chan_1_funding).unwrap();
+ if let Some(id) = pending_updates.get(1) {
+ monitor_b.chain_monitor.channel_monitor_updated(chan_1_funding, *id).unwrap();
+ }
+ nodes[1].process_monitor_events();
+ }
+ 0xf6 => {
+ let pending_updates = monitor_b.chain_monitor.list_pending_monitor_updates().remove(&chan_1_funding).unwrap();
+ if let Some(id) = pending_updates.last() {
+ monitor_b.chain_monitor.channel_monitor_updated(chan_1_funding, *id).unwrap();
+ }
+ nodes[1].process_monitor_events();
+ }
+
+ 0xf8 => {
+ let pending_updates = monitor_b.chain_monitor.list_pending_monitor_updates().remove(&chan_2_funding).unwrap();
+ if let Some(id) = pending_updates.get(0) {
+ monitor_b.chain_monitor.channel_monitor_updated(chan_2_funding, *id).unwrap();
+ }
+ nodes[1].process_monitor_events();
+ }
+ 0xf9 => {
+ let pending_updates = monitor_b.chain_monitor.list_pending_monitor_updates().remove(&chan_2_funding).unwrap();
+ if let Some(id) = pending_updates.get(1) {
+ monitor_b.chain_monitor.channel_monitor_updated(chan_2_funding, *id).unwrap();
+ }
+ nodes[1].process_monitor_events();
+ }
+ 0xfa => {
+ let pending_updates = monitor_b.chain_monitor.list_pending_monitor_updates().remove(&chan_2_funding).unwrap();
+ if let Some(id) = pending_updates.last() {
+ monitor_b.chain_monitor.channel_monitor_updated(chan_2_funding, *id).unwrap();
+ }
+ nodes[1].process_monitor_events();
+ }
+
+ 0xfc => {
+ let pending_updates = monitor_c.chain_monitor.list_pending_monitor_updates().remove(&chan_2_funding).unwrap();
+ if let Some(id) = pending_updates.get(0) {
+ monitor_c.chain_monitor.channel_monitor_updated(chan_2_funding, *id).unwrap();
+ }
+ nodes[2].process_monitor_events();
+ }
+ 0xfd => {
+ let pending_updates = monitor_c.chain_monitor.list_pending_monitor_updates().remove(&chan_2_funding).unwrap();
+ if let Some(id) = pending_updates.get(1) {
+ monitor_c.chain_monitor.channel_monitor_updated(chan_2_funding, *id).unwrap();
+ }
+ nodes[2].process_monitor_events();
+ }
+ 0xfe => {
+ let pending_updates = monitor_c.chain_monitor.list_pending_monitor_updates().remove(&chan_2_funding).unwrap();
+ if let Some(id) = pending_updates.last() {
+ monitor_c.chain_monitor.channel_monitor_updated(chan_2_funding, *id).unwrap();
+ }
+ nodes[2].process_monitor_events();
+ }
+
0xff => {
// Test that no channel is in a stuck state where neither party can send funds even
// after we resolve all pending events.
_ => test_return!(),
}
- node_a_ser.0.clear();
- nodes[0].write(&mut node_a_ser).unwrap();
- monitor_a.should_update_manager.store(false, atomic::Ordering::Relaxed);
- node_b_ser.0.clear();
- nodes[1].write(&mut node_b_ser).unwrap();
- monitor_b.should_update_manager.store(false, atomic::Ordering::Relaxed);
- node_c_ser.0.clear();
- nodes[2].write(&mut node_c_ser).unwrap();
- monitor_c.should_update_manager.store(false, atomic::Ordering::Relaxed);
+ if nodes[0].get_and_clear_needs_persistence() == true {
+ node_a_ser.0.clear();
+ nodes[0].write(&mut node_a_ser).unwrap();
+ }
+ if nodes[1].get_and_clear_needs_persistence() == true {
+ node_b_ser.0.clear();
+ nodes[1].write(&mut node_b_ser).unwrap();
+ }
+ if nodes[2].get_and_clear_needs_persistence() == true {
+ node_c_ser.0.clear();
+ nodes[2].write(&mut node_c_ser).unwrap();
+ }
}
}
}
pub fn chanmon_consistency_test<Out: Output>(data: &[u8], out: Out) {
- do_test(data, out);
+ do_test(data, out.clone(), false);
+ do_test(data, out, true);
}
#[no_mangle]
pub extern "C" fn chanmon_consistency_run(data: *const u8, datalen: usize) {
- do_test(unsafe { std::slice::from_raw_parts(data, datalen) }, test_logger::DevNull{});
+ do_test(unsafe { std::slice::from_raw_parts(data, datalen) }, test_logger::DevNull{}, false);
+ do_test(unsafe { std::slice::from_raw_parts(data, datalen) }, test_logger::DevNull{}, true);
}