Use alloc for no_std builds
[rust-lightning] / lightning / src / util / test_utils.rs
index ea110023823242c0e3ae5999e353db8c7c61f1b1..43bb1ef930391d7966af82308d74aef1ad3e6073 100644 (file)
@@ -8,6 +8,7 @@
 // licenses.
 
 use chain;
+use chain::WatchedOutput;
 use chain::chaininterface;
 use chain::chaininterface::ConfirmationTarget;
 use chain::chainmonitor;
@@ -31,14 +32,16 @@ use bitcoin::network::constants::Network;
 use bitcoin::hash_types::{BlockHash, Txid};
 
 use bitcoin::secp256k1::{SecretKey, PublicKey, Secp256k1, Signature};
+use bitcoin::secp256k1::recovery::RecoverableSignature;
 
 use regex;
 
-use std::time::Duration;
+use prelude::*;
+use core::time::Duration;
 use std::sync::{Mutex, Arc};
-use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
-use std::{cmp, mem};
-use std::collections::{HashMap, HashSet};
+use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
+use core::{cmp, mem};
+use std::collections::{HashMap, HashSet, VecDeque};
 use chain::keysinterface::InMemorySigner;
 
 pub struct TestVecWriter(pub Vec<u8>);
@@ -74,6 +77,7 @@ impl keysinterface::KeysInterface for OnlyReadsKeysInterface {
        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> {
@@ -185,12 +189,12 @@ impl TestPersister {
                *self.update_ret.lock().unwrap() = ret;
        }
 }
-impl channelmonitor::Persist<EnforcingSigner> for TestPersister {
-       fn persist_new_channel(&self, _funding_txo: OutPoint, _data: &channelmonitor::ChannelMonitor<EnforcingSigner>) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> {
+impl<Signer: keysinterface::Sign> channelmonitor::Persist<Signer> for TestPersister {
+       fn persist_new_channel(&self, _funding_txo: OutPoint, _data: &channelmonitor::ChannelMonitor<Signer>) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> {
                self.update_ret.lock().unwrap().clone()
        }
 
-       fn update_persisted_channel(&self, _funding_txo: OutPoint, _update: &channelmonitor::ChannelMonitorUpdate, _data: &channelmonitor::ChannelMonitor<EnforcingSigner>) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> {
+       fn update_persisted_channel(&self, _funding_txo: OutPoint, _update: &channelmonitor::ChannelMonitorUpdate, _data: &channelmonitor::ChannelMonitor<Signer>) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> {
                self.update_ret.lock().unwrap().clone()
        }
 }
@@ -231,6 +235,7 @@ impl msgs::ChannelMessageHandler for TestChannelMessageHandler {
        fn handle_commitment_signed(&self, _their_node_id: &PublicKey, _msg: &msgs::CommitmentSigned) {}
        fn handle_revoke_and_ack(&self, _their_node_id: &PublicKey, _msg: &msgs::RevokeAndACK) {}
        fn handle_update_fee(&self, _their_node_id: &PublicKey, _msg: &msgs::UpdateFee) {}
+       fn handle_channel_update(&self, _their_node_id: &PublicKey, _msg: &msgs::ChannelUpdate) {}
        fn handle_announcement_signatures(&self, _their_node_id: &PublicKey, _msg: &msgs::AnnouncementSignatures) {}
        fn handle_channel_reestablish(&self, _their_node_id: &PublicKey, _msg: &msgs::ChannelReestablish) {}
        fn peer_disconnected(&self, _their_node_id: &PublicKey, _no_connection_possible: bool) {}
@@ -481,6 +486,10 @@ impl keysinterface::KeysInterface for TestKeysInterface {
                        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)
+       }
 }
 
 
@@ -516,6 +525,7 @@ pub struct TestChainSource {
        pub utxo_ret: Mutex<Result<TxOut, chain::AccessError>>,
        pub watched_txn: Mutex<HashSet<(Txid, Script)>>,
        pub watched_outputs: Mutex<HashSet<(OutPoint, Script)>>,
+       expectations: Mutex<Option<VecDeque<OnRegisterOutput>>>,
 }
 
 impl TestChainSource {
@@ -526,8 +536,17 @@ impl TestChainSource {
                        utxo_ret: Mutex::new(Ok(TxOut { value: u64::max_value(), script_pubkey })),
                        watched_txn: Mutex::new(HashSet::new()),
                        watched_outputs: Mutex::new(HashSet::new()),
+                       expectations: Mutex::new(None),
                }
        }
+
+       /// Sets an expectation that [`chain::Filter::register_output`] is called.
+       pub fn expect(&self, expectation: OnRegisterOutput) -> &Self {
+               self.expectations.lock().unwrap()
+                       .get_or_insert_with(|| VecDeque::new())
+                       .push_back(expectation);
+               self
+       }
 }
 
 impl chain::Access for TestChainSource {
@@ -545,7 +564,72 @@ impl chain::Filter for TestChainSource {
                self.watched_txn.lock().unwrap().insert((*txid, script_pubkey.clone()));
        }
 
-       fn register_output(&self, outpoint: &OutPoint, script_pubkey: &Script) {
-               self.watched_outputs.lock().unwrap().insert((*outpoint, script_pubkey.clone()));
+       fn register_output(&self, output: WatchedOutput) -> Option<(usize, Transaction)> {
+               let dependent_tx = match &mut *self.expectations.lock().unwrap() {
+                       None => None,
+                       Some(expectations) => match expectations.pop_front() {
+                               None => {
+                                       panic!("Unexpected register_output: {:?}",
+                                               (output.outpoint, output.script_pubkey));
+                               },
+                               Some(expectation) => {
+                                       assert_eq!(output.outpoint, expectation.outpoint());
+                                       assert_eq!(&output.script_pubkey, expectation.script_pubkey());
+                                       expectation.returns
+                               },
+                       },
+               };
+
+               self.watched_outputs.lock().unwrap().insert((output.outpoint, output.script_pubkey));
+               dependent_tx
+       }
+}
+
+impl Drop for TestChainSource {
+       fn drop(&mut self) {
+               if std::thread::panicking() {
+                       return;
+               }
+
+               if let Some(expectations) = &*self.expectations.lock().unwrap() {
+                       if !expectations.is_empty() {
+                               panic!("Unsatisfied expectations: {:?}", expectations);
+                       }
+               }
+       }
+}
+
+/// An expectation that [`chain::Filter::register_output`] was called with a transaction output and
+/// returns an optional dependent transaction that spends the output in the same block.
+pub struct OnRegisterOutput {
+       /// The transaction output to register.
+       pub with: TxOutReference,
+
+       /// A dependent transaction spending the output along with its position in the block.
+       pub returns: Option<(usize, Transaction)>,
+}
+
+/// A transaction output as identified by an index into a transaction's output list.
+pub struct TxOutReference(pub Transaction, pub usize);
+
+impl OnRegisterOutput {
+       fn outpoint(&self) -> OutPoint {
+               let txid = self.with.0.txid();
+               let index = self.with.1 as u16;
+               OutPoint { txid, index }
+       }
+
+       fn script_pubkey(&self) -> &Script {
+               let index = self.with.1;
+               &self.with.0.output[index].script_pubkey
+       }
+}
+
+impl core::fmt::Debug for OnRegisterOutput {
+       fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+               f.debug_struct("OnRegisterOutput")
+                       .field("outpoint", &self.outpoint())
+                       .field("script_pubkey", self.script_pubkey())
+                       .finish()
        }
 }