X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=fuzz%2Fsrc%2Ffull_stack.rs;h=2af7009eb687d995641e40dadf5fd68f74f4f6fa;hb=5824e226cad67e32d5e8be71ebbb6f91a3fc2116;hp=eeb3728adf59dc789653a12e4c54835a5a1ea979;hpb=593d8c4610f082441563d4906d64175a354b1cfc;p=rust-lightning diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index eeb3728a..2af7009e 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -33,14 +33,14 @@ use lightning::chain::{BestBlock, ChannelMonitorUpdateStatus, Confirm, Listen}; use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator}; use lightning::chain::chainmonitor; use lightning::chain::transaction::OutPoint; -use lightning::chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial, KeysInterface}; +use lightning::chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial, EntropySource, NodeSigner, SignerProvider}; use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret}; -use lightning::ln::channelmanager::{ChainParameters, ChannelManager, PaymentId}; +use lightning::ln::channelmanager::{ChainParameters, ChannelDetails, ChannelManager, PaymentId}; use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor,IgnoringMessageHandler}; -use lightning::ln::msgs::DecodeError; +use lightning::ln::msgs::{self, DecodeError}; use lightning::ln::script::ShutdownScript; use lightning::routing::gossip::{P2PGossipSync, NetworkGraph}; -use lightning::routing::router::{find_route, PaymentParameters, RouteParameters}; +use lightning::routing::router::{find_route, InFlightHtlcs, PaymentParameters, Route, RouteHop, RouteParameters, Router}; use lightning::routing::scoring::FixedPenaltyScorer; use lightning::util::config::UserConfig; use lightning::util::errors::APIError; @@ -127,6 +127,24 @@ impl FeeEstimator for FuzzEstimator { } } +struct FuzzRouter {} + +impl Router for FuzzRouter { + fn find_route( + &self, _payer: &PublicKey, _params: &RouteParameters, _first_hops: Option<&[&ChannelDetails]>, + _inflight_htlcs: &InFlightHtlcs + ) -> Result { + Err(msgs::LightningError { + err: String::from("Not implemented"), + action: msgs::ErrorAction::IgnoreError + }) + } + fn notify_payment_path_failed(&self, _path: &[&RouteHop], _short_channel_id: u64) {} + fn notify_payment_path_successful(&self, _path: &[&RouteHop]) {} + fn notify_payment_probe_successful(&self, _path: &[&RouteHop]) {} + fn notify_payment_probe_failed(&self, _path: &[&RouteHop], _short_channel_id: u64) {} +} + struct TestBroadcaster { txn_broadcasted: Mutex>, } @@ -162,13 +180,13 @@ impl<'a> std::hash::Hash for Peer<'a> { } } -type ChannelMan = ChannelManager< +type ChannelMan<'a> = ChannelManager< Arc, Arc, Arc, Arc, Arc>>, - Arc, Arc, Arc, Arc>; -type PeerMan<'a> = PeerManager, Arc, Arc>>, Arc, Arc>>, IgnoringMessageHandler, Arc, IgnoringMessageHandler>; + Arc, Arc, Arc, &'a FuzzRouter, Arc>; +type PeerMan<'a> = PeerManager, Arc>, Arc>>, Arc, Arc>>, IgnoringMessageHandler, Arc, IgnoringMessageHandler>; struct MoneyLossDetector<'a> { - manager: Arc, + manager: Arc>, monitor: Arc, Arc, Arc, Arc, Arc>>, handler: PeerMan<'a>, @@ -182,7 +200,7 @@ struct MoneyLossDetector<'a> { } impl<'a> MoneyLossDetector<'a> { pub fn new(peers: &'a RefCell<[bool; 256]>, - manager: Arc, + manager: Arc>, monitor: Arc, Arc, Arc, Arc, Arc>>, handler: PeerMan<'a>) -> Self { MoneyLossDetector { @@ -263,14 +281,27 @@ struct KeyProvider { node_secret: SecretKey, inbound_payment_key: KeyMaterial, counter: AtomicU64, + signer_state: RefCell>)>> +} + +impl EntropySource for KeyProvider { + fn get_secure_random_bytes(&self) -> [u8; 32] { + let ctr = self.counter.fetch_add(1, Ordering::Relaxed); + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + (ctr >> 8*7) as u8, (ctr >> 8*6) as u8, (ctr >> 8*5) as u8, (ctr >> 8*4) as u8, (ctr >> 8*3) as u8, (ctr >> 8*2) as u8, (ctr >> 8*1) as u8, 14, (ctr >> 8*0) as u8] + } } -impl KeysInterface for KeyProvider { - type Signer = EnforcingSigner; +impl NodeSigner for KeyProvider { fn get_node_secret(&self, _recipient: Recipient) -> Result { Ok(self.node_secret.clone()) } + fn get_node_id(&self, recipient: Recipient) -> Result { + let secp_ctx = Secp256k1::signing_only(); + Ok(PublicKey::from_secret_key(&secp_ctx, &self.get_node_secret(recipient)?)) + } + fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result { let mut node_secret = self.get_node_secret(recipient)?; if let Some(tweak) = tweak { @@ -283,24 +314,25 @@ impl KeysInterface for KeyProvider { self.inbound_payment_key.clone() } - fn get_destination_script(&self) -> Script { - let secp_ctx = Secp256k1::signing_only(); - let channel_monitor_claim_key = SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(); - let our_channel_monitor_claim_key_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &channel_monitor_claim_key).serialize()); - Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script() + fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result { + unreachable!() } +} - fn get_shutdown_scriptpubkey(&self) -> ShutdownScript { - let secp_ctx = Secp256k1::signing_only(); - let secret_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, 0, 1]).unwrap(); - let pubkey_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &secret_key).serialize()); - ShutdownScript::new_p2wpkh(&pubkey_hash) - } +impl SignerProvider for KeyProvider { + type Signer = EnforcingSigner; - fn get_channel_signer(&self, inbound: bool, channel_value_satoshis: u64) -> EnforcingSigner { + fn generate_channel_keys_id(&self, inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] { let ctr = self.counter.fetch_add(1, Ordering::Relaxed) as u8; + self.signer_state.borrow_mut().insert(ctr, (inbound, Arc::new(Mutex::new(EnforcementState::new())))); + [ctr; 32] + } + + fn derive_channel_signer(&self, channel_value_satoshis: u64, channel_keys_id: [u8; 32]) -> Self::Signer { let secp_ctx = Secp256k1::signing_only(); - EnforcingSigner::new(if inbound { + let ctr = channel_keys_id[0]; + let (inbound, state) = self.signer_state.borrow().get(&ctr).unwrap().clone(); + EnforcingSigner::new_with_revoked(if inbound { InMemorySigner::new( &secp_ctx, self.node_secret.clone(), @@ -311,7 +343,7 @@ impl KeysInterface for KeyProvider { 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, ctr]).unwrap(), [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, 6, ctr], channel_value_satoshis, - [0; 32] + channel_keys_id, ) } else { InMemorySigner::new( @@ -324,15 +356,9 @@ impl KeysInterface for KeyProvider { 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, 11, ctr]).unwrap(), [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, 12, ctr], channel_value_satoshis, - [0; 32] + channel_keys_id, ) - }) - } - - fn get_secure_random_bytes(&self) -> [u8; 32] { - let ctr = self.counter.fetch_add(1, Ordering::Relaxed); - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - (ctr >> 8*7) as u8, (ctr >> 8*6) as u8, (ctr >> 8*5) as u8, (ctr >> 8*4) as u8, (ctr >> 8*3) as u8, (ctr >> 8*2) as u8, (ctr >> 8*1) as u8, 14, (ctr >> 8*0) as u8] + }, state, false) } fn read_chan_signer(&self, mut data: &[u8]) -> Result { @@ -346,8 +372,18 @@ impl KeysInterface for KeyProvider { )) } - fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result { - unreachable!() + fn get_destination_script(&self) -> Script { + let secp_ctx = Secp256k1::signing_only(); + let channel_monitor_claim_key = SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(); + let our_channel_monitor_claim_key_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &channel_monitor_claim_key).serialize()); + Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script() + } + + fn get_shutdown_scriptpubkey(&self) -> ShutdownScript { + let secp_ctx = Secp256k1::signing_only(); + let secret_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, 0, 1]).unwrap(); + let pubkey_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &secret_key).serialize()); + ShutdownScript::new_p2wpkh(&pubkey_hash) } } @@ -360,6 +396,7 @@ pub fn do_test(data: &[u8], logger: &Arc) { let fee_est = Arc::new(FuzzEstimator { input: input.clone(), }); + let router = FuzzRouter {}; macro_rules! get_slice { ($len: expr) => { @@ -390,7 +427,12 @@ pub fn do_test(data: &[u8], logger: &Arc) { let monitor = Arc::new(chainmonitor::ChainMonitor::new(None, broadcast.clone(), Arc::clone(&logger), fee_est.clone(), Arc::new(TestPersister { update_ret: Mutex::new(ChannelMonitorUpdateStatus::Completed) }))); - let keys_manager = Arc::new(KeyProvider { node_secret: our_network_key.clone(), inbound_payment_key: KeyMaterial(inbound_payment_key.try_into().unwrap()), counter: AtomicU64::new(0) }); + let keys_manager = Arc::new(KeyProvider { + node_secret: our_network_key.clone(), + inbound_payment_key: KeyMaterial(inbound_payment_key.try_into().unwrap()), + counter: AtomicU64::new(0), + signer_state: RefCell::new(HashMap::new()) + }); let mut config = UserConfig::default(); config.channel_config.forwarding_fee_proportional_millionths = slice_to_be32(get_slice!(4)); config.channel_handshake_config.announced_channel = get_slice!(1)[0] != 0; @@ -399,11 +441,11 @@ pub fn do_test(data: &[u8], logger: &Arc) { network, best_block: BestBlock::from_genesis(network), }; - let channelmanager = Arc::new(ChannelManager::new(fee_est.clone(), monitor.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, params)); - // Adding new calls to `KeysInterface::get_secure_random_bytes` during startup can change all the + let channelmanager = Arc::new(ChannelManager::new(fee_est.clone(), monitor.clone(), broadcast.clone(), &router, Arc::clone(&logger), keys_manager.clone(), config, params)); + // Adding new calls to `EntropySource::get_secure_random_bytes` during startup can change all the // keys subsequently generated in this test. Rather than regenerating all the messages manually, // it's easier to just increment the counter here so the keys don't change. - keys_manager.counter.fetch_sub(2, Ordering::AcqRel); + keys_manager.counter.fetch_sub(3, Ordering::AcqRel); let our_id = PublicKey::from_secret_key(&Secp256k1::signing_only(), &keys_manager.get_node_secret(Recipient::Node).unwrap()); let network_graph = Arc::new(NetworkGraph::new(genesis_block(network).block_hash(), Arc::clone(&logger))); let gossip_sync = Arc::new(P2PGossipSync::new(Arc::clone(&network_graph), None, Arc::clone(&logger))); @@ -646,7 +688,7 @@ pub fn do_test(data: &[u8], logger: &Arc) { Event::FundingGenerationReady { temporary_channel_id, counterparty_node_id, channel_value_satoshis, output_script, .. } => { pending_funding_generation.push((temporary_channel_id, counterparty_node_id, channel_value_satoshis, output_script)); }, - Event::PaymentReceived { payment_hash, .. } => { + Event::PaymentClaimable { payment_hash, .. } => { //TODO: enhance by fetching random amounts from fuzz input? payments_received.push(payment_hash); },