From 9b79c4dc0ce965b787c25332039e95d06da0b083 Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Sun, 30 Jul 2023 07:00:54 -0400 Subject: [PATCH] Test Eventuality completion via CoordinatorMessage::Completed --- tests/processor/src/lib.rs | 43 ++++++++++++++++++++++++-- tests/processor/src/tests/send.rs | 51 ++++++++++++++++++++++++++----- 2 files changed, 84 insertions(+), 10 deletions(-) diff --git a/tests/processor/src/lib.rs b/tests/processor/src/lib.rs index 070ea2fb..67941dce 100644 --- a/tests/processor/src/lib.rs +++ b/tests/processor/src/lib.rs @@ -324,12 +324,14 @@ impl Coordinator { let rpc_url = network_rpc(self.network, ops, &self.network_handle); match self.network { NetworkId::Bitcoin => { - use bitcoin_serai::rpc::Rpc; + use bitcoin_serai::{ + bitcoin::{consensus::Decodable, Transaction}, + rpc::Rpc, + }; let rpc = Rpc::new(rpc_url).await.expect("couldn't connect to the coordinator's Bitcoin RPC"); - let _: String = - rpc.rpc_call("sendrawtransaction", serde_json::json!([hex::encode(tx)])).await.unwrap(); + rpc.send_raw_transaction(&Transaction::consensus_decode(&mut &*tx).unwrap()).await.unwrap(); } NetworkId::Ethereum => todo!(), NetworkId::Monero => { @@ -341,4 +343,39 @@ impl Coordinator { NetworkId::Serai => panic!("processor tests broadcasting block to Serai"), } } + + pub async fn get_transaction(&self, ops: &DockerOperations, tx: &[u8]) -> Option> { + let rpc_url = network_rpc(self.network, ops, &self.network_handle); + match self.network { + NetworkId::Bitcoin => { + use bitcoin_serai::{bitcoin::consensus::Encodable, rpc::Rpc}; + + let rpc = + Rpc::new(rpc_url).await.expect("couldn't connect to the coordinator's Bitcoin RPC"); + let mut hash = [0; 32]; + hash.copy_from_slice(tx); + if let Ok(tx) = rpc.get_transaction(&hash).await { + let mut buf = vec![]; + tx.consensus_encode(&mut buf).unwrap(); + Some(buf) + } else { + None + } + } + NetworkId::Ethereum => todo!(), + NetworkId::Monero => { + use monero_serai::rpc::HttpRpc; + + let rpc = HttpRpc::new(rpc_url).expect("couldn't connect to the coordinator's Monero RPC"); + let mut hash = [0; 32]; + hash.copy_from_slice(tx); + if let Ok(tx) = rpc.get_transaction(hash).await { + Some(tx.serialize()) + } else { + None + } + } + NetworkId::Serai => panic!("processor tests broadcasting block to Serai"), + } + } } diff --git a/tests/processor/src/tests/send.rs b/tests/processor/src/tests/send.rs index 136713d4..bc2a4325 100644 --- a/tests/processor/src/tests/send.rs +++ b/tests/processor/src/tests/send.rs @@ -1,5 +1,5 @@ use std::{ - collections::HashMap, + collections::{HashSet, HashMap}, time::{SystemTime, Duration}, }; @@ -250,15 +250,52 @@ fn send_test() { (id, preprocesses) = recv_sign_preprocesses(&mut coordinators, key_pair.1.to_vec(), attempt).await; } + let participating = preprocesses.keys().cloned().collect::>(); - let tx_id = sign_tx(&mut coordinators, id, preprocesses).await; + let tx_id = sign_tx(&mut coordinators, id.clone(), preprocesses).await; + + // Make sure all participating nodes published the TX + let participating = + participating.iter().map(|p| usize::from(u16::from(*p) - 1)).collect::>(); + for participant in &participating { + assert!(coordinators[*participant].get_transaction(&ops, &tx_id).await.is_some()); + } + + // Publish this transaction to the left out nodes + let tx = coordinators[*participating.iter().next().unwrap()] + .get_transaction(&ops, &tx_id) + .await + .unwrap(); + for (i, coordinator) in coordinators.iter_mut().enumerate() { + if !participating.contains(&i) { + coordinator.publish_transacton(&ops, &tx).await; + // Tell them of it as a completion of the relevant signing nodess + coordinator + .send_message(messages::sign::CoordinatorMessage::Completed { + key: key_pair.1.to_vec(), + id: id.id, + tx: tx_id.clone(), + }) + .await; + // Verify they send Completed back + match coordinator.recv_message().await { + messages::ProcessorMessage::Sign(messages::sign::ProcessorMessage::Completed { + key, + id: this_id, + tx: this_tx, + }) => { + assert_eq!(&key, &id.key); + assert_eq!(&this_id, &id.id); + assert_eq!(this_tx, tx_id); + } + _ => panic!("processor didn't send Completed"), + } + } + } - // TODO: Test callimg Sign again yields tx_id again - // TODO: Make sure all participating nodes published the TX - // TODO: Send this TX to the left out node and make sure they can complete the Eventuality // TODO: Test the Eventuality from the blockchain, instead of from the coordinator - - let _ = tx_id; + // TODO: Test what happenns when Completed is sent with a non-existent TX ID + // TODO: Test what happenns when Completed is sent with a non-completing TX ID }); } }