From 1bcfc9656297d1a401ef60536924dc6bbf46d106 Mon Sep 17 00:00:00 2001 From: quake Date: Tue, 11 Jun 2024 13:27:13 +0900 Subject: [PATCH] fix: tweak e2e test --- src/ckb/channel.rs | 8 ++- src/ckb/network.rs | 2 +- src/ckb/test_utils.rs | 23 ++++++- src/rpc/channel.rs | 61 +++++++++++++++++-- src/rpc/mod.rs | 8 +-- src/store.rs | 22 ++++++- .../03-node1-node2-open-channel.bru | 7 +-- ...=> 04-node2-get-auto-accepted-channel.bru} | 14 ++--- .../07-node2-node3-open-channel.bru | 7 +-- ...=> 08-node3-get-auto-accepted-channel.bru} | 16 ++--- .../02-open-channel.bru | 5 +- ...l.bru => 03-get-auto-accepted-channel.bru} | 12 ++-- 12 files changed, 138 insertions(+), 47 deletions(-) rename tests/bruno/e2e/3-nodes-transfer/{08-node2-accept-channel.bru => 04-node2-get-auto-accepted-channel.bru} (61%) rename tests/bruno/e2e/3-nodes-transfer/{04-node1-accept-channel.bru => 08-node3-get-auto-accepted-channel.bru} (58%) rename tests/bruno/e2e/open-use-close-a-channel/{03-accept-channel.bru => 03-get-auto-accepted-channel.bru} (64%) diff --git a/src/ckb/channel.rs b/src/ckb/channel.rs index 523064eb..a1bbcc12 100644 --- a/src/ckb/channel.rs +++ b/src/ckb/channel.rs @@ -1061,6 +1061,11 @@ enum CommitmentSignedFlags { } #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde( + rename_all = "SCREAMING_SNAKE_CASE", + tag = "state_name", + content = "state_flags" +)] pub enum ChannelState { /// We are negotiating the parameters required for the channel prior to funding it. NegotiatingFunding(NegotiatingFundingFlags), @@ -2825,7 +2830,8 @@ pub trait ChannelActorStateStore { fn get_channel_actor_state(&self, id: &Hash256) -> Option; fn insert_channel_actor_state(&self, state: ChannelActorState); fn delete_channel_actor_state(&self, id: &Hash256); - fn get_channels(&self, peer_id: &PeerId) -> Vec; + fn get_channel_ids_by_peer(&self, peer_id: &PeerId) -> Vec; + fn get_channel_states(&self, peer_id: Option) -> Vec<(PeerId, Hash256, ChannelState)>; } /// A wrapper on CommitmentTransaction that has a partial signature along with diff --git a/src/ckb/network.rs b/src/ckb/network.rs index 0e2e9e5f..9a46e519 100644 --- a/src/ckb/network.rs +++ b/src/ckb/network.rs @@ -660,7 +660,7 @@ impl NetworkActorState { debug!("Peer connected: {:?}, session id: {}", &peer_id, session.id); self.peer_session_map.insert(peer_id.clone(), session.id); - for channel_id in store.get_channels(&peer_id) { + for channel_id in store.get_channel_ids_by_peer(&peer_id) { debug!("Reestablishing channel {:?}", &channel_id); if let Ok((channel, _)) = Actor::spawn_linked( None, diff --git a/src/ckb/test_utils.rs b/src/ckb/test_utils.rs index 5656b636..7c8af040 100644 --- a/src/ckb/test_utils.rs +++ b/src/ckb/test_utils.rs @@ -28,7 +28,7 @@ use crate::{ }; use super::{ - channel::{ChannelActorState, ChannelActorStateStore}, + channel::{ChannelActorState, ChannelActorStateStore, ChannelState}, types::Hash256, NetworkActor, NetworkActorCommand, NetworkActorMessage, }; @@ -246,7 +246,7 @@ impl ChannelActorStateStore for MemoryStore { self.channel_actor_state_map.write().unwrap().remove(id); } - fn get_channels(&self, peer_id: &PeerId) -> Vec { + fn get_channel_ids_by_peer(&self, peer_id: &PeerId) -> Vec { self.channel_actor_state_map .read() .unwrap() @@ -260,6 +260,25 @@ impl ChannelActorStateStore for MemoryStore { }) .collect() } + + fn get_channel_states(&self, peer_id: Option) -> Vec<(PeerId, Hash256, ChannelState)> { + let map = self.channel_actor_state_map.read().unwrap(); + let values = map.values(); + match peer_id { + Some(peer_id) => values + .filter_map(|state| { + if peer_id == state.peer_id { + Some((state.peer_id.clone(), state.id.clone(), state.state.clone())) + } else { + None + } + }) + .collect(), + None => values + .map(|state| (state.peer_id.clone(), state.id.clone(), state.state.clone())) + .collect(), + } + } } #[cfg(test)] diff --git a/src/rpc/channel.rs b/src/rpc/channel.rs index f28263d3..03d183da 100644 --- a/src/rpc/channel.rs +++ b/src/rpc/channel.rs @@ -1,6 +1,7 @@ use crate::ckb::{ channel::{ - AddTlcCommand, ChannelCommand, ChannelCommandWithId, RemoveTlcCommand, ShutdownCommand, + AddTlcCommand, ChannelActorStateStore, ChannelCommand, ChannelCommandWithId, ChannelState, + RemoveTlcCommand, ShutdownCommand, }, network::{AcceptChannelCommand, OpenChannelCommand}, serde_utils::{U128Hex, U32Hex, U64Hex}, @@ -51,6 +52,27 @@ pub struct CommitmentSignedParams { pub channel_id: Hash256, } +#[serde_as] +#[derive(Serialize, Deserialize)] +pub struct ListChannelsParams { + #[serde_as(as = "Option")] + pub peer_id: Option, +} + +#[derive(Clone, Serialize)] +pub struct ListChannelsResult { + pub channels: Vec, +} + +#[serde_as] +#[derive(Clone, Serialize)] +pub struct Channel { + pub channel_id: Hash256, + #[serde_as(as = "DisplayFromStr")] + pub peer_id: PeerId, + pub state: ChannelState, +} + #[serde_as] #[derive(Serialize, Deserialize)] pub struct AddTlcParams { @@ -113,6 +135,12 @@ pub trait ChannelRpc { params: AcceptChannelParams, ) -> Result; + #[method(name = "list_channels")] + async fn list_channels( + &self, + params: ListChannelsParams, + ) -> Result; + #[method(name = "commitment_signed")] async fn commitment_signed( &self, @@ -130,18 +158,22 @@ pub trait ChannelRpc { -> Result<(), ErrorObjectOwned>; } -pub struct ChannelRpcServerImpl { +pub struct ChannelRpcServerImpl { actor: ActorRef, + store: S, } -impl ChannelRpcServerImpl { - pub fn new(actor: ActorRef) -> Self { - ChannelRpcServerImpl { actor } +impl ChannelRpcServerImpl { + pub fn new(actor: ActorRef, store: S) -> Self { + ChannelRpcServerImpl { actor, store } } } #[async_trait] -impl ChannelRpcServer for ChannelRpcServerImpl { +impl ChannelRpcServer for ChannelRpcServerImpl +where + S: ChannelActorStateStore + Send + Sync + 'static, +{ async fn open_channel( &self, params: OpenChannelParams, @@ -192,6 +224,23 @@ impl ChannelRpcServer for ChannelRpcServerImpl { } } + async fn list_channels( + &self, + params: ListChannelsParams, + ) -> Result { + let channels = self.store.get_channel_states(params.peer_id); + Ok(ListChannelsResult { + channels: channels + .into_iter() + .map(|(peer_id, channel_id, state)| Channel { + channel_id, + peer_id, + state, + }) + .collect(), + }) + } + async fn commitment_signed( &self, params: CommitmentSignedParams, diff --git a/src/rpc/mod.rs b/src/rpc/mod.rs index 603d3187..6086c0bc 100644 --- a/src/rpc/mod.rs +++ b/src/rpc/mod.rs @@ -6,7 +6,7 @@ mod peer; use crate::{ cch::CchCommand, - ckb::NetworkActorMessage, + ckb::{channel::ChannelActorStateStore, NetworkActorMessage}, invoice::{InvoiceCommand, InvoiceStore}, }; use cch::{CchRpcServer, CchRpcServerImpl}; @@ -20,7 +20,7 @@ use tokio::sync::mpsc::Sender; pub type InvoiceCommandWithReply = (InvoiceCommand, Sender>); -pub async fn start_rpc( +pub async fn start_rpc( config: RpcConfig, ckb_network_actor: Option>, cch_command_sender: Option>, @@ -28,10 +28,10 @@ pub async fn start_rpc( ) -> ServerHandle { let listening_addr = config.listening_addr.as_deref().unwrap_or("[::]:0"); let server = Server::builder().build(listening_addr).await.unwrap(); - let mut methods = InvoiceRpcServerImpl::new(store).into_rpc(); + let mut methods = InvoiceRpcServerImpl::new(store.clone()).into_rpc(); if let Some(ckb_network_actor) = ckb_network_actor { let peer = PeerRpcServerImpl::new(ckb_network_actor.clone()); - let channel = ChannelRpcServerImpl::new(ckb_network_actor.clone()); + let channel = ChannelRpcServerImpl::new(ckb_network_actor.clone(), store); methods.merge(peer.into_rpc()).unwrap(); methods.merge(channel.into_rpc()).unwrap(); } diff --git a/src/store.rs b/src/store.rs index 5ffa87ca..3759aef5 100644 --- a/src/store.rs +++ b/src/store.rs @@ -130,7 +130,7 @@ impl ChannelActorStateStore for Store { } } - fn get_channels(&self, peer_id: &tentacle::secio::PeerId) -> Vec { + fn get_channel_ids_by_peer(&self, peer_id: &tentacle::secio::PeerId) -> Vec { let prefix = [&[64], peer_id.as_bytes()].concat(); let iter = self.db.prefix_iterator(prefix.as_ref()); iter.map(|(key, _)| { @@ -141,6 +141,26 @@ impl ChannelActorStateStore for Store { }) .collect() } + + fn get_channel_states(&self, peer_id: Option) -> Vec<(PeerId, Hash256, ChannelState)> { + let prefix = match peer_id { + Some(peer_id) => [&[64], peer_id.as_bytes()].concat(), + None => vec![64], + }; + let iter = self.db.prefix_iterator(prefix.as_ref()); + iter.map(|(key, value)| { + let key_len = key.len(); + let peer_id = PeerId::from_bytes(key[1..key_len - 32].into()) + .expect("deserialize peer id should be OK"); + let channel_id: [u8; 32] = key[key_len - 32..] + .try_into() + .expect("channel id should be 32 bytes"); + let state = serde_json::from_slice(value.as_ref()) + .expect("deserialize ChannelState should be OK"); + (peer_id, channel_id.into(), state) + }) + .collect() + } } impl InvoiceStore for Store { diff --git a/tests/bruno/e2e/3-nodes-transfer/03-node1-node2-open-channel.bru b/tests/bruno/e2e/3-nodes-transfer/03-node1-node2-open-channel.bru index 6a2b55b9..b632602b 100644 --- a/tests/bruno/e2e/3-nodes-transfer/03-node1-node2-open-channel.bru +++ b/tests/bruno/e2e/3-nodes-transfer/03-node1-node2-open-channel.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{NODE2_RPC_URL}} + url: {{NODE1_RPC_URL}} body: json auth: none } @@ -22,7 +22,7 @@ body:json { "method": "open_channel", "params": [ { - "peer_id": "{{NODE1_PEERID}}", + "peer_id": "{{NODE2_PEERID}}", "funding_amount": "0x377aab54d000" } ] @@ -35,6 +35,5 @@ assert { } script:post-response { - await new Promise(r => setTimeout(r, 1000)); - bru.setVar("N1N2_TEMP_CHANNEL_ID", res.body.result.temporary_channel_id); + await new Promise(r => setTimeout(r, 2000)); } diff --git a/tests/bruno/e2e/3-nodes-transfer/08-node2-accept-channel.bru b/tests/bruno/e2e/3-nodes-transfer/04-node2-get-auto-accepted-channel.bru similarity index 61% rename from tests/bruno/e2e/3-nodes-transfer/08-node2-accept-channel.bru rename to tests/bruno/e2e/3-nodes-transfer/04-node2-get-auto-accepted-channel.bru index 3c8903da..2678f9fa 100644 --- a/tests/bruno/e2e/3-nodes-transfer/08-node2-accept-channel.bru +++ b/tests/bruno/e2e/3-nodes-transfer/04-node2-get-auto-accepted-channel.bru @@ -1,7 +1,7 @@ meta { - name: Node2 accept a channel from a peer + name: get auto accepted channel id from Node2 type: http - seq: 8 + seq: 4 } post { @@ -19,11 +19,10 @@ body:json { { "id": "42", "jsonrpc": "2.0", - "method": "accept_channel", + "method": "list_channels", "params": [ { - "temporary_channel_id": "{{N2N3_TEMP_CHANNEL_ID}}", - "funding_amount": "0x377aab54d000" + "peer_id": "{{NODE1_PEERID}}" } ] } @@ -31,11 +30,12 @@ body:json { assert { res.body.error: isUndefined - res.body.result.channel_id: isDefined + res.body.result.channels: isDefined } script:post-response { + console.log(res.body.result); // Sleep for sometime to make sure current operation finishes before next request starts. await new Promise(r => setTimeout(r, 2000)); - bru.setVar("N2N3_CHANNEL_ID", res.body.result.channel_id); + bru.setVar("N1N2_CHANNEL_ID", res.body.result.channels[0].channel_id); } diff --git a/tests/bruno/e2e/3-nodes-transfer/07-node2-node3-open-channel.bru b/tests/bruno/e2e/3-nodes-transfer/07-node2-node3-open-channel.bru index a54a88d4..f5298386 100644 --- a/tests/bruno/e2e/3-nodes-transfer/07-node2-node3-open-channel.bru +++ b/tests/bruno/e2e/3-nodes-transfer/07-node2-node3-open-channel.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{NODE3_RPC_URL}} + url: {{NODE2_RPC_URL}} body: json auth: none } @@ -22,7 +22,7 @@ body:json { "method": "open_channel", "params": [ { - "peer_id": "{{NODE2_PEERID}}", + "peer_id": "{{NODE3_PEERID}}", "funding_amount": "0x377aab54d000" } ] @@ -35,6 +35,5 @@ assert { } script:post-response { - await new Promise(r => setTimeout(r, 1000)); - bru.setVar("N2N3_TEMP_CHANNEL_ID", res.body.result.temporary_channel_id); + await new Promise(r => setTimeout(r, 2000)); } diff --git a/tests/bruno/e2e/3-nodes-transfer/04-node1-accept-channel.bru b/tests/bruno/e2e/3-nodes-transfer/08-node3-get-auto-accepted-channel.bru similarity index 58% rename from tests/bruno/e2e/3-nodes-transfer/04-node1-accept-channel.bru rename to tests/bruno/e2e/3-nodes-transfer/08-node3-get-auto-accepted-channel.bru index cd996254..f02d9ac8 100644 --- a/tests/bruno/e2e/3-nodes-transfer/04-node1-accept-channel.bru +++ b/tests/bruno/e2e/3-nodes-transfer/08-node3-get-auto-accepted-channel.bru @@ -1,11 +1,11 @@ meta { - name: accept a channel from a peer + name: get auto accepted channel id from Node3 type: http - seq: 4 + seq: 8 } post { - url: {{NODE1_RPC_URL}} + url: {{NODE3_RPC_URL}} body: json auth: none } @@ -19,11 +19,10 @@ body:json { { "id": "42", "jsonrpc": "2.0", - "method": "accept_channel", + "method": "list_channels", "params": [ { - "temporary_channel_id": "{{N1N2_TEMP_CHANNEL_ID}}", - "funding_amount": "0x377aab54d000" + "peer_id": "{{NODE2_PEERID}}" } ] } @@ -31,11 +30,12 @@ body:json { assert { res.body.error: isUndefined - res.body.result.channel_id: isDefined + res.body.result.channels: isDefined } script:post-response { + console.log(res.body.result); // Sleep for sometime to make sure current operation finishes before next request starts. await new Promise(r => setTimeout(r, 2000)); - bru.setVar("N1N2_CHANNEL_ID", res.body.result.channel_id); + bru.setVar("N2N3_CHANNEL_ID", res.body.result.channels[0].channel_id); } diff --git a/tests/bruno/e2e/open-use-close-a-channel/02-open-channel.bru b/tests/bruno/e2e/open-use-close-a-channel/02-open-channel.bru index 7f219957..9ddbbe7d 100644 --- a/tests/bruno/e2e/open-use-close-a-channel/02-open-channel.bru +++ b/tests/bruno/e2e/open-use-close-a-channel/02-open-channel.bru @@ -1,5 +1,5 @@ meta { - name: open a channel to a peer + name: Node3 open a channel to Node1 type: http seq: 2 } @@ -35,6 +35,5 @@ assert { } script:post-response { - await new Promise(r => setTimeout(r, 1000)); - bru.setVar("TEMP_CHANNEL_ID", res.body.result.temporary_channel_id); + await new Promise(r => setTimeout(r, 2000)); } diff --git a/tests/bruno/e2e/open-use-close-a-channel/03-accept-channel.bru b/tests/bruno/e2e/open-use-close-a-channel/03-get-auto-accepted-channel.bru similarity index 64% rename from tests/bruno/e2e/open-use-close-a-channel/03-accept-channel.bru rename to tests/bruno/e2e/open-use-close-a-channel/03-get-auto-accepted-channel.bru index f0b66202..eaf76c57 100644 --- a/tests/bruno/e2e/open-use-close-a-channel/03-accept-channel.bru +++ b/tests/bruno/e2e/open-use-close-a-channel/03-get-auto-accepted-channel.bru @@ -1,5 +1,5 @@ meta { - name: accept a channel from a peer + name: get auto accepted channel id from Node1 type: http seq: 3 } @@ -19,11 +19,10 @@ body:json { { "id": "42", "jsonrpc": "2.0", - "method": "accept_channel", + "method": "list_channels", "params": [ { - "temporary_channel_id": "{{TEMP_CHANNEL_ID}}", - "funding_amount": "0x174876e800" + "peer_id": "{{NODE3_PEERID}}" } ] } @@ -31,11 +30,12 @@ body:json { assert { res.body.error: isUndefined - res.body.result.channel_id: isDefined + res.body.result.channels: isDefined } script:post-response { + console.log(res.body.result); // Sleep for sometime to make sure current operation finishes before next request starts. await new Promise(r => setTimeout(r, 2000)); - bru.setVar("CHANNEL_ID", res.body.result.channel_id); + bru.setVar("CHANNEL_ID", res.body.result.channels[0].channel_id); }