lightning_signer/signer/
multi_signer.rs

1#[cfg(feature = "std")]
2use bitcoin::secp256k1::rand::{rngs::OsRng, RngCore};
3use bitcoin::secp256k1::PublicKey;
4use bitcoin::OutPoint;
5
6use crate::channel::{Channel, ChannelBase, ChannelId, ChannelSlot};
7use crate::node::{Node, NodeConfig, NodeServices};
8use crate::persist::{Persist, SeedPersist};
9use crate::prelude::*;
10use crate::util::status::{invalid_argument, Status};
11use vls_common::HexEncode;
12
13/// A signer for multiple nodes.
14///
15/// If you need just one node, use [Node] directly.
16pub struct MultiSigner {
17    pub(crate) nodes: Mutex<Map<PublicKey, Arc<Node>>>,
18    pub(crate) persister: Arc<dyn Persist>,
19    pub(crate) test_mode: bool,
20    pub(crate) initial_allowlist: Vec<String>,
21    services: NodeServices,
22}
23
24impl MultiSigner {
25    /// Construct
26    pub fn new_with_test_mode(
27        test_mode: bool,
28        initial_allowlist: Vec<String>,
29        services: NodeServices,
30    ) -> MultiSigner {
31        if !services.persister.get_nodes().expect("get_nodes").is_empty() {
32            panic!("Cannot create new MultiSigner with existing nodes - use MultiSigner::restore instead");
33        }
34        MultiSigner {
35            nodes: Mutex::new(Default::default()),
36            persister: services.persister.clone(),
37            test_mode,
38            initial_allowlist,
39            services,
40        }
41    }
42
43    /// Construct and restore nodes from the persister.
44    pub fn restore_with_test_mode(
45        test_mode: bool,
46        initial_allowlist: Vec<String>,
47        services: NodeServices,
48        seed_persister: Arc<dyn SeedPersist>,
49    ) -> Result<MultiSigner, Status> {
50        let nodes = Node::restore_nodes(services.clone(), seed_persister)?;
51        Ok(MultiSigner {
52            nodes: Mutex::new(nodes),
53            persister: services.persister.clone(),
54            test_mode,
55            initial_allowlist,
56            services,
57        })
58    }
59
60    /// Construct
61    ///
62    /// Will panic if there are nodes already persisted.
63    pub fn new(services: NodeServices) -> MultiSigner {
64        if !services.persister.get_nodes().expect("get_nodes").is_empty() {
65            panic!("Cannot create new MultiSigner with existing nodes - use MultiSigner::restore instead");
66        }
67        MultiSigner {
68            nodes: Mutex::new(Default::default()),
69            persister: services.persister.clone(),
70            test_mode: false,
71            initial_allowlist: vec![],
72            services,
73        }
74    }
75
76    /// Construct and restore nodes from the persister.
77    pub fn restore(
78        services: NodeServices,
79        seed_persister: Arc<dyn SeedPersist>,
80    ) -> Result<MultiSigner, Status> {
81        let nodes = Node::restore_nodes(services.clone(), seed_persister)?;
82        Ok(MultiSigner {
83            nodes: Mutex::new(nodes),
84            persister: services.persister.clone(),
85            test_mode: false,
86            initial_allowlist: vec![],
87            services,
88        })
89    }
90
91    /// Create a node with a random seed
92    #[cfg(feature = "std")]
93    pub fn new_node(
94        &self,
95        node_config: NodeConfig,
96        seed_persister: Arc<dyn SeedPersist>,
97    ) -> Result<(PublicKey, [u8; 32]), Status> {
98        let mut rng = OsRng;
99
100        let mut seed = [0; 32];
101        rng.fill_bytes(&mut seed);
102        self.new_node_with_seed(node_config, &seed, seed_persister).map(|id| (id, seed))
103    }
104
105    /// New node with externally supplied cryptographic seed
106    pub fn new_node_with_seed(
107        &self,
108        node_config: NodeConfig,
109        seed: &[u8],
110        seed_persister: Arc<dyn SeedPersist>,
111    ) -> Result<PublicKey, Status> {
112        let node = Node::new(node_config, &seed, vec![], self.services.clone());
113        let node_id = node.get_id();
114        let mut nodes = self.nodes.lock().unwrap();
115        if self.test_mode {
116            // In test mode we allow overwriting the node (thereby resetting all of its channels)
117            self.persister.delete_node(&node_id).expect("delete_node");
118        } else {
119            // In production, the node must not have existed
120
121            if nodes.contains_key(&node_id) {
122                return Err(invalid_argument("node_exists"));
123            }
124        }
125        node.add_allowlist(&self.initial_allowlist).expect("valid initialallowlist");
126        seed_persister.put(&node_id.serialize().to_hex(), seed);
127        self.persister.new_node(&node_id, &node_config, &*node.get_state()).expect("new node");
128        self.persister.new_tracker(&node_id, &node.get_tracker()).expect("new_chain_tracker");
129        nodes.insert(node_id, Arc::new(node));
130        Ok(node_id)
131    }
132
133    /// Get all node IDs
134    pub fn get_node_ids(&self) -> Vec<PublicKey> {
135        let nodes = self.nodes.lock().unwrap();
136        nodes.keys().map(|k| k.clone()).collect()
137    }
138
139    /// Ensure that a node exists given its seed
140    pub fn warmstart_with_seed(
141        &self,
142        node_config: NodeConfig,
143        seed: &[u8],
144    ) -> Result<PublicKey, Status> {
145        let node = Node::new(node_config, &seed, vec![], self.services.clone());
146        let node_id = node.get_id();
147        let nodes = self.nodes.lock().unwrap();
148        nodes.get(&node_id).ok_or_else(|| {
149            invalid_argument(format!("warmstart failed: no such node: {}", node_id))
150        })?;
151        Ok(node_id)
152    }
153
154    /// Temporary, until phase 2 is fully implemented
155    pub fn additional_setup(
156        &self,
157        node_id: &PublicKey,
158        channel_id: &ChannelId,
159        outpoint: OutPoint,
160    ) -> Result<(), Status> {
161        self.with_channel(node_id, channel_id, |chan| {
162            if chan.setup.funding_outpoint.is_null() {
163                chan.setup.funding_outpoint = outpoint;
164            } else if chan.setup.funding_outpoint != outpoint {
165                panic!("funding outpoint changed");
166            }
167            self.persist_channel(node_id, chan);
168            Ok(())
169        })
170    }
171
172    /// See [`Node::with_channel_base`]
173    pub fn with_channel_base<F: Sized, T>(
174        &self,
175        node_id: &PublicKey,
176        channel_id: &ChannelId,
177        f: F,
178    ) -> Result<T, Status>
179    where
180        F: Fn(&mut dyn ChannelBase) -> Result<T, Status>,
181    {
182        let slot_arc = self.get_channel(&node_id, &channel_id)?;
183        let mut slot = slot_arc.lock().unwrap();
184        let base = match &mut *slot {
185            ChannelSlot::Stub(stub) => stub as &mut dyn ChannelBase,
186            ChannelSlot::Ready(chan) => chan as &mut dyn ChannelBase,
187        };
188        f(base)
189    }
190
191    fn get_channel(
192        &self,
193        node_id: &PublicKey,
194        channel_id: &ChannelId,
195    ) -> Result<Arc<Mutex<ChannelSlot>>, Status> {
196        self.get_node(node_id)?.get_channel(channel_id)
197    }
198
199    /// Get a node
200    pub fn get_node(&self, node_id: &PublicKey) -> Result<Arc<Node>, Status> {
201        // Grab a reference to the node and release the nodes mutex
202        let nodes = self.nodes.lock().unwrap();
203        let node = nodes.get(node_id).ok_or_else(|| invalid_argument("no such node"))?;
204        Ok(Arc::clone(node))
205    }
206
207    /// See [`Node::with_channel`]
208    pub fn with_channel<F: Sized, T>(
209        &self,
210        node_id: &PublicKey,
211        channel_id: &ChannelId,
212        f: F,
213    ) -> Result<T, Status>
214    where
215        F: FnOnce(&mut Channel) -> Result<T, Status>,
216    {
217        let slot_arc = self.get_channel(&node_id, &channel_id)?;
218        let mut slot = slot_arc.lock().unwrap();
219        match &mut *slot {
220            ChannelSlot::Stub(_) =>
221                Err(invalid_argument(format!("channel not ready: {}", &channel_id))),
222            ChannelSlot::Ready(chan) => f(chan),
223        }
224    }
225
226    fn persist_channel(&self, node_id: &PublicKey, chan: &Channel) {
227        self.persister
228            .update_channel(&node_id, &chan)
229            .expect("channel was in storage but not in memory");
230    }
231
232    /// Get the node services
233    pub fn node_services(&self) -> NodeServices {
234        self.services.clone()
235    }
236}
237
238#[cfg(test)]
239mod tests {
240    use crate::persist::{DummyPersister, DummySeedPersister};
241    use crate::policy::simple_validator::SimpleValidatorFactory;
242    use crate::util::clock::StandardClock;
243    use crate::util::status::Code;
244    use crate::util::test_utils::hex_decode;
245    use crate::util::test_utils::*;
246    use bitcoin::secp256k1::Secp256k1;
247
248    use super::*;
249
250    fn make_test_services() -> NodeServices {
251        let validator_factory = Arc::new(SimpleValidatorFactory::new());
252        let persister = Arc::new(DummyPersister {});
253        let clock = Arc::new(StandardClock());
254        let starting_time_factory = make_genesis_starting_time_factory(TEST_NODE_CONFIG.network);
255        NodeServices {
256            validator_factory,
257            starting_time_factory,
258            persister,
259            clock,
260            trusted_oracle_pubkeys: vec![],
261        }
262    }
263
264    #[test]
265    fn warmstart_with_seed_test() {
266        let signer = MultiSigner::new(make_test_services());
267        let mut seed = [0; 32];
268        seed.copy_from_slice(hex_decode(TEST_SEED[1]).unwrap().as_slice());
269        let seed_persister = Arc::new(DummySeedPersister {});
270
271        // First try a warmstart w/ no existing node.
272        let result = signer.warmstart_with_seed(TEST_NODE_CONFIG, &seed);
273        assert!(result.is_err());
274        let err = result.unwrap_err();
275        assert_eq!(err.code(), Code::InvalidArgument);
276        assert_eq!(err.message(), "warmstart failed: no such node: 022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59");
277
278        // Then a "coldstart" from seed should succeed.
279        let node_id = signer.new_node_with_seed(TEST_NODE_CONFIG, &seed, seed_persister).unwrap();
280
281        // Now a warmstart will work, should get the same node_id.
282        let result = signer.warmstart_with_seed(TEST_NODE_CONFIG, &seed);
283        assert!(!result.is_err());
284        assert_eq!(result.unwrap(), node_id);
285    }
286
287    #[test]
288    fn bad_node_lookup_test() -> Result<(), ()> {
289        let secp_ctx = Secp256k1::signing_only();
290        let signer = MultiSigner::new(make_test_services());
291        let node_id = pubkey_from_secret_hex(
292            "0101010101010101010101010101010101010101010101010101010101010101",
293            &secp_ctx,
294        );
295
296        let channel_id = ChannelId::new(&hex_decode(TEST_CHANNEL_ID[0]).unwrap());
297        assert!(signer.get_channel(&node_id, &channel_id).is_err());
298        assert!(signer.get_node(&node_id).is_err());
299
300        Ok(())
301    }
302}