Skip to content

Commit

Permalink
backward compatibility test
Browse files Browse the repository at this point in the history
  • Loading branch information
pompon0 committed Oct 1, 2024
1 parent cee8d59 commit 1537c34
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 24 deletions.
1 change: 1 addition & 0 deletions node/actors/executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ impl Executor {
refresh: time::Duration::milliseconds(100),
},
rpc: self.config.rpc.clone(),
enable_pregenesis: true,
}
}

Expand Down
4 changes: 3 additions & 1 deletion node/actors/network/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@ pub struct Config {
/// Rate limiting config for RPCs.
pub rpc: RpcConfig,
/// Enables syncing blocks before genesis.
pub enable_pre_genesis_support: bool,
/// In production, it should be set to `true`.
/// Set it to `false` in tests to simulate node behavior before pre-genesis support.
pub enable_pregenesis: bool,
/// Maximum number of not-yet-persisted blocks fetched from the network.
/// If reached, network actor will wait for more blocks to get persisted
/// before fetching the next ones. It is useful for limiting memory consumption
Expand Down
27 changes: 14 additions & 13 deletions node/actors/network/src/gossip/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rand::seq::SliceRandom;
use std::sync::atomic::Ordering;
use zksync_concurrency::{ctx, net, scope, sync};
use zksync_consensus_roles::node;
use zksync_consensus_storage::{BlockStore, BlockStoreState};
use zksync_consensus_storage::BlockStoreState;
use zksync_protobuf::kB;

/// Receiver of push messages from the peers.
Expand Down Expand Up @@ -92,8 +92,8 @@ impl rpc::Handler<rpc::push_block_store_state::Rpc> for &PushServer<'_> {
_ctx: &ctx::Ctx,
mut req: rpc::push_block_store_state::Req,
) -> anyhow::Result<()> {
if !self.net.cfg.enable_pre_genesis_support {
req.clear_pre_genesis_info();
if !self.net.cfg.enable_pregenesis {
req.clear_pregenesis_data();
}
let state = req.state();
state.verify(self.net.genesis())?;
Expand All @@ -103,7 +103,7 @@ impl rpc::Handler<rpc::push_block_store_state::Rpc> for &PushServer<'_> {
}

#[async_trait]
impl rpc::Handler<rpc::get_block::Rpc> for &BlockStore {
impl rpc::Handler<rpc::get_block::Rpc> for &Network {
fn max_req_size(&self) -> usize {
kB
}
Expand All @@ -112,9 +112,9 @@ impl rpc::Handler<rpc::get_block::Rpc> for &BlockStore {
ctx: &ctx::Ctx,
req: rpc::get_block::Req,
) -> anyhow::Result<rpc::get_block::Resp> {
let mut resp = rpc::get_block::Resp(self.block(ctx, req.0).await?;
if !self.cfg.enable_pre_genesis_support {
resp.clear_pre_genesis_info();
let mut resp = rpc::get_block::Resp(self.block_store.block(ctx, req.0).await?);
if !self.cfg.enable_pregenesis {
resp.clear_pregenesis_data();
}
Ok(resp)
}
Expand Down Expand Up @@ -152,7 +152,7 @@ impl Network {
self.cfg.rpc.push_block_store_state_rate,
)
.add_client(&get_block_client)
.add_server(ctx, &*self.block_store, self.cfg.rpc.get_block_rate)
.add_server::<rpc::get_block::Rpc>(ctx, self, self.cfg.rpc.get_block_rate)
.add_server(ctx, rpc::ping::Server, rpc::ping::RATE)
.add_client(&push_batch_votes_client)
.add_server::<rpc::push_batch_votes::Rpc>(
Expand Down Expand Up @@ -212,9 +212,10 @@ impl Network {
s.spawn::<()>(async {
let mut state = self.block_store.queued();
loop {
let mut req = rpc::push_block_store_state::Req::new(state.clone(), self.genesis());
if !self.cfg.enable_pre_genesis_support {
req.clear_pre_genesis_info();
let mut req =
rpc::push_block_store_state::Req::new(state.clone(), self.genesis());
if !self.cfg.enable_pregenesis {
req.clear_pregenesis_data();
}
push_block_store_state_client.call(ctx, &req, kB).await?;
state = self.block_store.wait_for_queued_change(ctx, &state).await?;
Expand Down Expand Up @@ -264,8 +265,8 @@ impl Network {
let mut resp = call
.call(ctx, &req, self.cfg.max_block_size.saturating_add(kB))
.await?;
if self.cfg.enable_pre_genesis_support {
resp.0.clear_pre_genesis_info();
if !self.cfg.enable_pregenesis {
resp.clear_pregenesis_data();
}
let block = resp.0.context("empty response")?;
anyhow::ensure!(block.number() == req.0, "received wrong block");
Expand Down
65 changes: 65 additions & 0 deletions node/actors/network/src/gossip/tests/syncing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,3 +397,68 @@ async fn test_sidechannel_sync() {
.await
.unwrap();
}

/// Test checking that nodes with/without pregenesis support can sync with each other.
/// This is a backward compatibility test.
#[tokio::test(flavor = "multi_thread")]
async fn test_syncing_without_pregenesis_support() {
let ctx = &ctx::test_root(&ctx::RealClock);
let rng = &mut ctx.rng();
let mut spec = validator::testonly::SetupSpec::new(rng, 2);
spec.first_block = spec.first_pregenesis_block + 2;
let mut setup = validator::testonly::Setup::from_spec(rng, spec);
setup.push_blocks(rng, 6);
let mut cfgs = testonly::new_configs(rng, &setup, 1);
cfgs[1].enable_pregenesis = false;
for cfg in &mut cfgs {
cfg.rpc.push_block_store_state_rate = limiter::Rate::INF;
cfg.rpc.get_block_rate = limiter::Rate::INF;
cfg.rpc.get_block_timeout = None;
cfg.validator_key = None;
}

scope::run!(ctx, |ctx, s| async {
let stores = [in_memory::BlockStore::new(&setup, setup.blocks[0].number()),
// Node 1 doesn't have pregenesis support.
in_memory::BlockStore::new(&setup, setup.genesis.first_block)];
let mut nodes = vec![];
for i in 0..cfgs.len() {
let (block_store, runner) = BlockStore::new(ctx, Box::new(stores[i].clone())).await?;
s.spawn_bg(runner.run(ctx));
let (node, runner) = testonly::Instance::new(cfgs[i].clone(), block_store);
s.spawn_bg(runner.run(ctx).instrument(tracing::info_span!("node", i)));
nodes.push(node);
}

// Insert blocks in order, alternating between nodes.
// The other node should sync the block.
for i in 0..setup.blocks.len() {
// Select the node which will have block `i`.
// Pregenesis blocks are only for the node that supports them.
let x = if let validator::Block::PreGenesis(_) = &setup.blocks[i] {
0
} else {
i % 2
};
nodes[x]
.net
.gossip
.block_store
.queue_block(ctx, setup.blocks[i].clone())
.await?;
}

// Wait for all nodes to fetch all the blocks.
for n in &nodes {
n.net
.gossip
.block_store
.wait_until_persisted(ctx, setup.blocks.last().unwrap().number())
.await?;
}

Ok(())
})
.await
.unwrap();
}
12 changes: 11 additions & 1 deletion node/actors/network/src/rpc/get_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ impl ProtoFmt for Req {
#[derive(Debug, PartialEq)]
pub(crate) struct Resp(pub(crate) Option<validator::Block>);

impl Resp {
/// Clears pregenesis data from the response.
/// Use to simulate node behavior before pre-genesis support.
pub(crate) fn clear_pregenesis_data(&mut self) {
if let Some(validator::Block::PreGenesis(_)) = &self.0 {
self.0 = None;
}
}
}

impl ProtoFmt for Resp {
type Proto = proto::GetBlockResponse;

Expand All @@ -52,7 +62,7 @@ impl ProtoFmt for Resp {
None => None,
Some(T::Block(b)) => Some(B::Final(ProtoFmt::read(b).context("block")?)),
Some(T::PreGenesis(b)) => Some(B::PreGenesis(
ProtoFmt::read(b).context("pre_genesis_block")?,
ProtoFmt::read(b).context("pregenesis_block")?,
)),
}))
}
Expand Down
2 changes: 1 addition & 1 deletion node/actors/network/src/rpc/push_block_store_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ impl Req {

/// Clears pre-genesis info from the request.
/// Use to simulate node behavior before pre-genesis support.
pub(crate) fn clear_pre_genesis_info(&mut self) {
pub(crate) fn clear_pregenesis_data(&mut self) {
self.state = None;
}
}
Expand Down
2 changes: 2 additions & 0 deletions node/actors/network/src/testonly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ pub(crate) fn make_config(key: node::SecretKey) -> Config {
tcp_accept_rate: limiter::Rate::INF,
rpc: RpcConfig::default(),
max_block_queue_size: 10,
enable_pregenesis: true,
}
}

Expand Down Expand Up @@ -162,6 +163,7 @@ pub fn new_fullnode(rng: &mut impl Rng, peer: &Config) -> Config {
tcp_accept_rate: limiter::Rate::INF,
rpc: RpcConfig::default(),
max_block_queue_size: 10,
enable_pregenesis: true,
}
}

Expand Down
25 changes: 17 additions & 8 deletions node/libs/storage/src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use super::*;
use crate::{testonly::TestMemoryStorage, ReplicaState};
use zksync_concurrency::{ctx, scope, sync, testonly::abort_on_panic};
use zksync_consensus_roles::{validator,validator::testonly::{SetupSpec,Setup}};
use rand::Rng as _;
use zksync_concurrency::{ctx, scope, sync, testonly::abort_on_panic};
use zksync_consensus_roles::{
validator,
validator::testonly::{Setup, SetupSpec},
};

#[tokio::test]
async fn test_inmemory_block_store() {
Expand Down Expand Up @@ -35,23 +38,29 @@ async fn test_invalid_justification() {
let ctx = &ctx::test_root(&ctx::RealClock);
let rng = &mut ctx.rng();
let mut spec = SetupSpec::new(rng, 1);
spec.first_block = spec.first_pregenesis_block+2;
spec.first_block = spec.first_pregenesis_block + 2;
let setup = Setup::from_spec(rng, spec);
scope::run!(ctx, |ctx,s| async {
scope::run!(ctx, |ctx, s| async {
let store = TestMemoryStorage::new(ctx, &setup).await;
s.spawn_bg(store.runner.run(ctx));
let store = store.blocks;
// Insert a correct block first.
store.queue_block(ctx, setup.blocks[0].clone()).await.unwrap();
store
.queue_block(ctx, setup.blocks[0].clone())
.await
.unwrap();
// Insert an incorrect second block.
let validator::Block::PreGenesis(mut b) = setup.blocks[1].clone() else { panic!() };
let validator::Block::PreGenesis(mut b) = setup.blocks[1].clone() else {
panic!()
};
b.justification = rng.gen();
store.queue_block(ctx, b.into()).await.unwrap_err();
Ok(())
}).await.unwrap();
})
.await
.unwrap();
}


#[test]
fn test_schema_encode_decode() {
let ctx = ctx::test_root(&ctx::RealClock);
Expand Down

0 comments on commit 1537c34

Please sign in to comment.