feat(network): implement chain sync server side (#277)
This commit is contained in:
parent
367e76872b
commit
f223b0fde9
6 changed files with 524 additions and 9 deletions
|
|
@ -3,6 +3,7 @@ use std::time::Duration;
|
|||
|
||||
use pallas_network::facades::PeerClient;
|
||||
use pallas_network::miniprotocols::blockfetch::BlockRequest;
|
||||
use pallas_network::miniprotocols::chainsync::{ClientRequest, HeaderContent, Tip};
|
||||
use pallas_network::miniprotocols::handshake;
|
||||
use pallas_network::miniprotocols::handshake::n2n::VersionData;
|
||||
use pallas_network::miniprotocols::{
|
||||
|
|
@ -261,4 +262,203 @@ pub async fn blockfetch_server_and_client_happy_path() {
|
|||
_ = tokio::join!(client, server);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
pub async fn chainsync_server_and_client_happy_path_n2n() {
|
||||
let point1 = Point::Specific(1, vec![0x01]);
|
||||
let point2 = Point::Specific(2, vec![0x02]);
|
||||
|
||||
let server = tokio::spawn({
|
||||
let point1 = point1.clone();
|
||||
let point2 = point2.clone();
|
||||
async move {
|
||||
// server setup
|
||||
|
||||
let server_listener = TcpListener::bind(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 30001))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let (bearer, _) = Bearer::accept_tcp(server_listener).await.unwrap();
|
||||
|
||||
let mut server_plexer = Plexer::new(bearer);
|
||||
|
||||
let mut server_hs: handshake::Server<VersionData> =
|
||||
handshake::Server::new(server_plexer.subscribe_server(0));
|
||||
let mut server_cs = chainsync::N2NServer::new(server_plexer.subscribe_server(2));
|
||||
|
||||
tokio::spawn(async move { server_plexer.run().await });
|
||||
|
||||
server_hs.receive_proposed_versions().await.unwrap();
|
||||
server_hs
|
||||
.accept_version(10, VersionData::new(0, false))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// server receives find intersect from client, sends intersect point
|
||||
|
||||
assert_eq!(*server_cs.state(), chainsync::State::Idle);
|
||||
|
||||
let intersect_points = match server_cs.recv_while_idle().await.unwrap().unwrap() {
|
||||
ClientRequest::Intersect(points) => points,
|
||||
ClientRequest::RequestNext => panic!("unexpected message"),
|
||||
};
|
||||
|
||||
assert_eq!(*server_cs.state(), chainsync::State::Intersect);
|
||||
assert_eq!(intersect_points, vec![point2.clone(), point1.clone()]);
|
||||
|
||||
server_cs
|
||||
.send_intersect_found(point2.clone(), Tip(point2.clone(), 1337))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(*server_cs.state(), chainsync::State::Idle);
|
||||
|
||||
// server receives request next from client, sends rollbackwards
|
||||
|
||||
match server_cs.recv_while_idle().await.unwrap().unwrap() {
|
||||
ClientRequest::RequestNext => (),
|
||||
ClientRequest::Intersect(_) => panic!("unexpected message"),
|
||||
};
|
||||
|
||||
assert_eq!(*server_cs.state(), chainsync::State::CanAwait);
|
||||
|
||||
server_cs
|
||||
.send_roll_backward(point2.clone(), Tip(point2.clone(), 1337))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(*server_cs.state(), chainsync::State::Idle);
|
||||
|
||||
// server receives request next from client, sends rollforwards
|
||||
|
||||
match server_cs.recv_while_idle().await.unwrap().unwrap() {
|
||||
ClientRequest::RequestNext => (),
|
||||
ClientRequest::Intersect(_) => panic!("unexpected message"),
|
||||
};
|
||||
|
||||
assert_eq!(*server_cs.state(), chainsync::State::CanAwait);
|
||||
|
||||
let header2 = HeaderContent {
|
||||
variant: 1,
|
||||
byron_prefix: None,
|
||||
cbor: hex::decode("c0ffeec0ffeec0ffee").unwrap(),
|
||||
};
|
||||
|
||||
server_cs
|
||||
.send_roll_forward(header2, Tip(point2.clone(), 1337))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(*server_cs.state(), chainsync::State::Idle);
|
||||
|
||||
// server receives request next from client, sends await reply
|
||||
// then rollforwards
|
||||
|
||||
match server_cs.recv_while_idle().await.unwrap().unwrap() {
|
||||
ClientRequest::RequestNext => (),
|
||||
ClientRequest::Intersect(_) => panic!("unexpected message"),
|
||||
};
|
||||
|
||||
assert_eq!(*server_cs.state(), chainsync::State::CanAwait);
|
||||
|
||||
server_cs.send_await_reply().await.unwrap();
|
||||
|
||||
assert_eq!(*server_cs.state(), chainsync::State::MustReply);
|
||||
|
||||
let header1 = HeaderContent {
|
||||
variant: 1,
|
||||
byron_prefix: None,
|
||||
cbor: hex::decode("deadbeefdeadbeef").unwrap(),
|
||||
};
|
||||
|
||||
server_cs
|
||||
.send_roll_forward(header1, Tip(point1.clone(), 123))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(*server_cs.state(), chainsync::State::Idle);
|
||||
|
||||
// server receives client done
|
||||
|
||||
assert!(server_cs.recv_while_idle().await.unwrap().is_none());
|
||||
assert_eq!(*server_cs.state(), chainsync::State::Done);
|
||||
}
|
||||
});
|
||||
|
||||
let client = tokio::spawn(async move {
|
||||
tokio::time::sleep(Duration::from_secs(2)).await;
|
||||
|
||||
// client setup
|
||||
|
||||
let mut client_to_server_conn = PeerClient::connect("localhost:30001", 0).await.unwrap();
|
||||
|
||||
let client_cs = client_to_server_conn.chainsync();
|
||||
|
||||
// client sends find intersect
|
||||
|
||||
let intersect_response = client_cs
|
||||
.find_intersect(vec![point2.clone(), point1.clone()])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(intersect_response.0, Some(point2.clone()));
|
||||
assert_eq!(intersect_response.1 .0, point2.clone());
|
||||
assert_eq!(intersect_response.1 .1, 1337);
|
||||
|
||||
// client sends msg request next
|
||||
|
||||
client_cs.send_request_next().await.unwrap();
|
||||
|
||||
// client receives rollback
|
||||
|
||||
match client_cs.recv_while_can_await().await.unwrap() {
|
||||
NextResponse::RollBackward(point, tip) => {
|
||||
assert_eq!(point, point2.clone());
|
||||
assert_eq!(tip.0, point2.clone());
|
||||
assert_eq!(tip.1, 1337);
|
||||
}
|
||||
_ => panic!("unexpected response"),
|
||||
}
|
||||
|
||||
client_cs.send_request_next().await.unwrap();
|
||||
|
||||
// client receives roll forward
|
||||
|
||||
match client_cs.recv_while_can_await().await.unwrap() {
|
||||
NextResponse::RollForward(content, tip) => {
|
||||
assert_eq!(content.cbor, hex::decode("c0ffeec0ffeec0ffee").unwrap());
|
||||
assert_eq!(tip.0, point2.clone());
|
||||
assert_eq!(tip.1, 1337);
|
||||
}
|
||||
_ => panic!("unexpected response"),
|
||||
}
|
||||
|
||||
// client sends msg request next
|
||||
|
||||
client_cs.send_request_next().await.unwrap();
|
||||
|
||||
// client receives await
|
||||
|
||||
match client_cs.recv_while_can_await().await.unwrap() {
|
||||
NextResponse::Await => (),
|
||||
_ => panic!("unexpected response"),
|
||||
}
|
||||
|
||||
match client_cs.recv_while_must_reply().await.unwrap() {
|
||||
NextResponse::RollForward(content, tip) => {
|
||||
assert_eq!(content.cbor, hex::decode("deadbeefdeadbeef").unwrap());
|
||||
assert_eq!(tip.0, point1.clone());
|
||||
assert_eq!(tip.1, 123);
|
||||
}
|
||||
_ => panic!("unexpected response"),
|
||||
}
|
||||
|
||||
// client sends done
|
||||
|
||||
client_cs.send_done().await.unwrap();
|
||||
});
|
||||
|
||||
_ = tokio::join!(client, server);
|
||||
}
|
||||
|
||||
// TODO: redo txsubmission client test
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue