Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Broadcast validators signature and collect QC (BFT-414) #76

Merged
merged 88 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
23ef076
Create new message type for validators to broadcast signature
IAvecilla Mar 14, 2024
93732c4
Add new message to send to the gossip network
IAvecilla Mar 14, 2024
cbc7790
Add protobuf related functions for new message
IAvecilla Mar 14, 2024
a942623
Update batch signature message
IAvecilla Mar 19, 2024
73122a5
Add new rpc clients for validators to receive signatures
IAvecilla Mar 20, 2024
1538d0a
Add new input message for network actor
IAvecilla Mar 20, 2024
11680fd
Update L1Batch message variant
IAvecilla Apr 9, 2024
94f5b67
Add verification for L1 Batcj signatures
IAvecilla Apr 9, 2024
a532bbc
Merge branch 'main' into signature_broadcast
IAvecilla Apr 9, 2024
cec46c1
Update network struct for l1 batches rpc
IAvecilla Apr 9, 2024
5c2639b
introduced msg pool
pompon0 Apr 10, 2024
5926692
retransmission
pompon0 Apr 11, 2024
36be3da
typo
pompon0 Apr 11, 2024
1b28fd7
retransmission test
pompon0 Apr 11, 2024
c8d06ef
added tests
pompon0 Apr 11, 2024
96be90b
removed limiting from sync_blocks
pompon0 Apr 12, 2024
16693df
cargo fmt
pompon0 Apr 12, 2024
c9935c0
cargo fmt
pompon0 Apr 12, 2024
c670006
Merge branch 'main' into signature_broadcast
IAvecilla Apr 15, 2024
96a50de
Fix clippy lints
IAvecilla Apr 15, 2024
1dcda70
Added support for persisting blocks in parallel (#98)
pompon0 Apr 17, 2024
fb64951
Merge branch 'main' into signature_broadcast
IAvecilla Apr 18, 2024
d7069f7
New attester role for full nodes (#93)
IAvecilla Apr 19, 2024
8d76509
Rewritten sync_blocks actor to maximize utilization. (#101)
pompon0 Apr 25, 2024
26488ec
Weighted attesters (#102)
IAvecilla Apr 25, 2024
f729182
Merge branch 'main' into signature_broadcast
IAvecilla Apr 25, 2024
32fc525
Merge branch 'version0' into signature_broadcast
IAvecilla Apr 25, 2024
4d2675c
Merge branch 'main' into signature_broadcast
IAvecilla Apr 26, 2024
4e32fc0
l1 batch signature watcher for nodes in the gossip net
IAvecilla Apr 26, 2024
7c1ab8a
New push signature request for full nodes in the gossip network
IAvecilla Apr 30, 2024
dd912d1
Update gossip proto file
IAvecilla Apr 30, 2024
182adca
Add push signature watcher to the runner of the gossip network
IAvecilla Apr 30, 2024
d6a5f80
Fix lints
IAvecilla Apr 30, 2024
1359e54
Add attester key to the config
IAvecilla Apr 30, 2024
1e4e720
Identify node in gossip network adding the attester key
IAvecilla Apr 30, 2024
5f5cee1
Update watcher and signature broadcasting tasks
IAvecilla May 3, 2024
e9ad0fa
Add tests and update test setup to get batches
IAvecilla May 3, 2024
b53ec80
Merge branch 'main' into signature_broadcast
IAvecilla May 3, 2024
8365c9f
Fix genesis hash test
IAvecilla May 3, 2024
05f80e2
Fix encoding tests and hash back to previous version
IAvecilla May 6, 2024
df7b777
Fix deny
IAvecilla May 6, 2024
e77db65
Add test disclaimer
IAvecilla May 6, 2024
e86aa92
Update qc construction implementation
IAvecilla May 6, 2024
9511247
Delete committee prefix for validators and attesters in genesis
IAvecilla May 7, 2024
4f548d7
Fix some crate imports
IAvecilla May 7, 2024
5cf4fae
Update limit rate for rpc requests with batch signatures
IAvecilla May 7, 2024
03780cb
Update name for signed messages in proto file
IAvecilla May 7, 2024
5392a1c
Update attester field in genesis for proto struct
IAvecilla May 7, 2024
e0f16de
Leave TODO comment for hash of the L1 Batch
IAvecilla May 7, 2024
073c22d
Update proto genesis struct
IAvecilla May 7, 2024
93b59be
Delete unused code related to attesters an l1 batches
IAvecilla May 7, 2024
a9b5a5a
Use qualified names for attester imports
IAvecilla May 7, 2024
5c0e7b7
Renamed most of batch related structs for consistency
IAvecilla May 7, 2024
0271e43
Fix some function names
IAvecilla May 7, 2024
ecb3c99
Implement hash for every curve signature and derive it for each role
IAvecilla May 8, 2024
2201c54
Fix incorrect docs for attesters
IAvecilla May 8, 2024
99c9302
Update encoding tests for secret keys
IAvecilla May 8, 2024
e09b6f6
Make batch qc adding function return proper errors
IAvecilla May 8, 2024
76a0a9b
Remove timestamp for batch message
IAvecilla May 8, 2024
d4acad5
Update rpc method name for push batch votes
IAvecilla May 8, 2024
b50fb48
Calculate correctly the expected weight for tests
IAvecilla May 8, 2024
0aa2131
Fix format and clippy lints
IAvecilla May 8, 2024
8168af7
Add trait for the state keeper
IAvecilla May 10, 2024
f380e74
Use calculated QC by the node instead of taking it from signers
IAvecilla May 10, 2024
c9f6152
Add extra comments on QC updater
IAvecilla May 10, 2024
eabc7d7
Panic if overflow happens for batch number
IAvecilla May 13, 2024
e163378
Use validator function for max faulty weight
IAvecilla May 13, 2024
246d834
Use batch votes instead of batch signatures
IAvecilla May 13, 2024
2d331ef
Update some names referring to signatures changing it to votes
IAvecilla May 13, 2024
7eee7dc
Move trait to persist batches to the storage workspace
IAvecilla May 13, 2024
fab01d5
Implement deref for committees
IAvecilla May 13, 2024
c6fe4db
Use map instead of and_then
IAvecilla May 13, 2024
3cec7be
Fix clippy
IAvecilla May 13, 2024
b6721a8
Merge branch 'main' into signature_broadcast
IAvecilla May 14, 2024
55feb75
Fix some unused imports
IAvecilla May 14, 2024
70d8c91
Make attesters field in genesis optional
IAvecilla May 14, 2024
13b63d9
Optional build and read protobuff for attester committee
IAvecilla May 15, 2024
d521f10
Fix clippy lint
IAvecilla May 15, 2024
520e412
Delete attester key from the config
IAvecilla May 15, 2024
ef5c654
Generate valid genesis to verify in test
IAvecilla May 16, 2024
034f196
Fix clippy lints with latest rust version
IAvecilla May 16, 2024
77e45d6
Fix genesis raw encoding for empty attesters
IAvecilla May 16, 2024
834f0fb
Fix latest comments
IAvecilla May 16, 2024
5f35266
Get attester at the beginning of the tests
IAvecilla May 16, 2024
d2c8233
Fix some last comments
IAvecilla May 17, 2024
672046f
Fix CI protobuff job
IAvecilla May 17, 2024
d84421c
Fix last comment in gossip runner
IAvecilla May 20, 2024
06e1350
Merge branch 'main' into signature_broadcast
IAvecilla May 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions node/actors/network/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ pub struct RpcConfig {
pub get_block_rate: limiter::Rate,
/// Max rate of sending/receiving consensus messages.
pub consensus_rate: limiter::Rate,
/// Max rate of sending/receiving l1 batch signature messages.
pub l1_batch_signature_rate: limiter::Rate,
}

impl Default for RpcConfig {
Expand All @@ -39,6 +41,10 @@ impl Default for RpcConfig {
burst: 10,
refresh: time::Duration::ZERO,
},
l1_batch_signature_rate: limiter::Rate {
burst: 10,
pompon0 marked this conversation as resolved.
Show resolved Hide resolved
refresh: time::Duration::ZERO,
},
}
}
}
Expand Down
58 changes: 55 additions & 3 deletions node/actors/network/src/consensus/mod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
//! Consensus network is a full graph of connections between all validators.
//! BFT consensus messages are exchanged over this network.
use crate::{config, gossip, io, noise, pool::PoolWatch, preface, rpc};
use crate::{
config, gossip, io, noise,
pool::PoolWatch,
preface,
rpc::{self, signature::L1BatchSignatureServer},
};
use anyhow::Context as _;
use std::{
collections::{HashMap, HashSet},
sync::Arc,
};
use zksync_concurrency::{ctx, oneshot, scope, sync, time};
use zksync_consensus_roles::validator;
use zksync_consensus_roles::validator::{self, L1BatchQC};
use zksync_protobuf::kB;

mod handshake;
Expand All @@ -33,6 +38,9 @@ pub(crate) struct Network {
pub(crate) outbound: PoolWatch<validator::PublicKey>,
/// RPC clients for all validators.
pub(crate) clients: HashMap<validator::PublicKey, rpc::Client<rpc::consensus::Rpc>>,
/// RPC clients for l1 batch signature.
pub(crate) signature_clients: HashMap<validator::PublicKey, rpc::Client<rpc::signature::Rpc>>,
pub(crate) l1_batch_qc: L1BatchQC,
}

#[async_trait::async_trait]
Expand All @@ -59,13 +67,27 @@ impl rpc::Handler<rpc::consensus::Rpc> for &Network {
}
}

#[async_trait::async_trait]
impl rpc::Handler<rpc::signature::Rpc> for &L1BatchSignatureServer<'_> {
/// Here we bound the buffering of incoming consensus messages.
fn max_req_size(&self) -> usize {
self.0.gossip.cfg.max_block_size.saturating_add(kB)
IAvecilla marked this conversation as resolved.
Show resolved Hide resolved
}

async fn handle(&self, _ctx: &ctx::Ctx, req: rpc::signature::Req) -> anyhow::Result<()> {
self.0.l1_batch_qc.clone().add(req.0.sig);
IAvecilla marked this conversation as resolved.
Show resolved Hide resolved
Ok(())
}
}

impl Network {
/// Constructs a new consensus network state.
pub(crate) fn new(ctx: &ctx::Ctx, gossip: Arc<gossip::Network>) -> Option<Arc<Self>> {
let key = gossip.cfg.validator_key.clone()?;
let validators: HashSet<_> = gossip.genesis().validators.iter().cloned().collect();
Some(Arc::new(Self {
key,
l1_batch_qc: L1BatchQC::default(),
inbound: PoolWatch::new(validators.clone(), 0),
outbound: PoolWatch::new(validators.clone(), 0),
clients: validators
Expand All @@ -77,12 +99,21 @@ impl Network {
)
})
.collect(),
signature_clients: validators
.iter()
.map(|peer| {
(
peer.clone(),
rpc::Client::new(ctx, gossip.cfg.rpc.l1_batch_signature_rate),
)
})
.collect(),
gossip,
}))
}

/// Sends a message to all validators.
pub(crate) async fn broadcast(
pub(crate) async fn broadcast_consensus_msg(
&self,
ctx: &ctx::Ctx,
msg: validator::Signed<validator::ConsensusMsg>,
Expand All @@ -102,6 +133,27 @@ impl Network {
.await
}

/// Broadcasts a signature to all validators.
pub(crate) async fn broadcast_signature(
&self,
ctx: &ctx::Ctx,
signature: validator::Signed<validator::L1BatchSignatureMsg>,
) -> anyhow::Result<()> {
let req = rpc::signature::Req(signature);
scope::run!(ctx, |ctx, s| async {
for (peer, client) in &self.signature_clients {
s.spawn(async {
if let Err(err) = client.call(ctx, &req, RESP_MAX_SIZE).await {
tracing::info!("send({:?},<L1BatchSignatureMsg>): {err:#}", &*peer);
}
Ok(())
});
}
Ok(())
})
.await
}

/// Sends a message to the given validator.
pub(crate) async fn send(
&self,
Expand Down
7 changes: 7 additions & 0 deletions node/actors/network/src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ pub enum InputMessage {
Consensus(ConsensusInputMessage),
/// Message types from the Sync Blocks actor.
SyncBlocks(SyncBlocksInputMessage),
/// Message of type L1BatchSignatureMsg from the validator.
L1BatchSignature(L1BatchSignatureInputMessage),
}

#[derive(Debug)]
pub struct L1BatchSignatureInputMessage {
pub message: validator::Signed<validator::L1BatchSignatureMsg>,
}

/// Message types from the Consensus actor.
Expand Down
11 changes: 10 additions & 1 deletion node/actors/network/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ impl Network {
io::Target::Validator(key) => {
consensus.send(ctx, &key, message.message).await?
}
io::Target::Broadcast => consensus.broadcast(ctx, message.message).await?,
io::Target::Broadcast => {
consensus
.broadcast_consensus_msg(ctx, message.message)
.await?
}
}
}
io::InputMessage::SyncBlocks(io::SyncBlocksInputMessage::GetBlock {
Expand All @@ -102,6 +106,11 @@ impl Network {
Err(err) => Err(io::GetBlockError::Internal(err)),
});
}
io::InputMessage::L1BatchSignature(message) => {
let consensus = self.consensus.as_ref().context("not a validator node")?;
let ctx = &ctx.with_timeout(CONSENSUS_MSG_TIMEOUT);
consensus.broadcast_signature(ctx, message.message).await?;
}
}
Ok(())
}
Expand Down
12 changes: 12 additions & 0 deletions node/actors/network/src/proto/signature.proto
pompon0 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
syntax = "proto3";

package zksync.network.consensus;

import "zksync/roles/validator.proto";
import "zksync/std.proto";

message SignatureReq {
optional roles.validator.Signed msg = 1;
}

message SignatureResp {}
1 change: 1 addition & 0 deletions node/actors/network/src/rpc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ mod metrics;
pub(crate) mod ping;
pub(crate) mod push_block_store_state;
pub(crate) mod push_validator_addrs;
pub(crate) mod signature;
#[cfg(test)]
pub(crate) mod testonly;
#[cfg(test)]
Expand Down
49 changes: 49 additions & 0 deletions node/actors/network/src/rpc/signature.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//! Defines RPC for passing consensus messages.
use crate::{consensus::Network, mux, proto::consensus as proto};
use zksync_consensus_roles::validator;
use zksync_protobuf::{read_required, ProtoFmt};

/// Signature RPC.
pub(crate) struct Rpc;

impl super::Rpc for Rpc {
const CAPABILITY_ID: mux::CapabilityId = 5;
const INFLIGHT: u32 = 1;
const METHOD: &'static str = "signature";
type Req = Req;
type Resp = ();
}
pub(crate) struct L1BatchSignatureServer<'a>(pub(crate) &'a Network);
/// Signed consensus message that the receiving peer should process.
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct Req(pub(crate) validator::Signed<validator::L1BatchSignatureMsg>);

/// Confirmation that the signature message has been processed.
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct Resp;

impl ProtoFmt for Req {
type Proto = proto::SignatureReq;

fn read(r: &Self::Proto) -> anyhow::Result<Self> {
read_required(&r.msg).map(Self)
}

fn build(&self) -> Self::Proto {
Self::Proto {
msg: Some(self.0.build()),
}
}
}

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

fn read(_r: &Self::Proto) -> anyhow::Result<Self> {
Ok(Self)
}

fn build(&self) -> Self::Proto {
Self::Proto {}
}
}
5 changes: 5 additions & 0 deletions node/libs/roles/src/proto/validator.proto
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,16 @@ message NetAddress {
optional std.Timestamp timestamp = 3; // required
}

message L1BatchSignatureMsg {
optional bytes signature = 1; // required
}

message Msg {
oneof t { // required
ConsensusMsg consensus = 1;
bytes session_id = 2;
NetAddress net_address = 3;
L1BatchSignatureMsg l1_batch_signature = 4;
}
}

Expand Down
25 changes: 22 additions & 3 deletions node/libs/roles/src/validator/conv.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use super::{
AggregateSignature, BlockHeader, BlockHeaderHash, BlockNumber, CommitQC, ConsensusMsg,
FinalBlock, Fork, ForkNumber, Genesis, GenesisHash, LeaderCommit, LeaderPrepare, Msg, MsgHash,
NetAddress, Payload, PayloadHash, Phase, PrepareQC, ProtocolVersion, PublicKey, ReplicaCommit,
ReplicaPrepare, Signature, Signed, Signers, ValidatorSet, View, ViewNumber,
FinalBlock, Fork, ForkNumber, Genesis, GenesisHash, L1BatchSignatureMsg, LeaderCommit,
LeaderPrepare, Msg, MsgHash, NetAddress, Payload, PayloadHash, Phase, PrepareQC,
ProtocolVersion, PublicKey, ReplicaCommit, ReplicaPrepare, Signature, Signed, Signers,
ValidatorSet, View, ViewNumber,
};
use crate::{node::SessionId, proto::validator as proto};
use anyhow::Context as _;
Expand Down Expand Up @@ -355,6 +356,20 @@ impl ProtoFmt for NetAddress {
}
}

impl ProtoFmt for L1BatchSignatureMsg {
type Proto = proto::L1BatchSignatureMsg;

fn read(r: &Self::Proto) -> anyhow::Result<Self> {
Ok(Self(ByteFmt::decode(required(&r.signature)?)?))
}

fn build(&self) -> Self::Proto {
Self::Proto {
signature: Some(self.0.encode()),
}
}
}

impl ProtoFmt for Msg {
type Proto = proto::Msg;

Expand All @@ -364,6 +379,9 @@ impl ProtoFmt for Msg {
T::Consensus(r) => Self::Consensus(ProtoFmt::read(r).context("Consensus")?),
T::SessionId(r) => Self::SessionId(SessionId(r.clone())),
T::NetAddress(r) => Self::NetAddress(ProtoFmt::read(r).context("NetAddress")?),
T::L1BatchSignature(r) => {
Self::L1BatchSignature(ProtoFmt::read(r).context("L1BatchSignature")?)
}
})
}

Expand All @@ -374,6 +392,7 @@ impl ProtoFmt for Msg {
Self::Consensus(x) => T::Consensus(x.build()),
Self::SessionId(x) => T::SessionId(x.0.clone()),
Self::NetAddress(x) => T::NetAddress(x.build()),
Self::L1BatchSignature(x) => T::L1BatchSignature(x.build()),
};

Self::Proto { t: Some(t) }
Expand Down
20 changes: 20 additions & 0 deletions node/libs/roles/src/validator/messages/l1_batch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use crate::validator::{self, Signature};

/// A message to send by validators to the gossip network.
/// It contains the validators signature to sign the block batches to be sent to L1.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct L1BatchSignatureMsg(pub Signature);

/// A certificate for a batch of L2 blocks to be sent to L1.
/// It contains the signatures of the validators that signed the batch.
#[derive(Debug, Clone, Default, Eq, PartialEq)]
pub struct L1BatchQC {
/// The aggregate signature of the signed L1 batches.
pub signatures: validator::AggregateSignature,
}

impl L1BatchQC {
pub fn add(&mut self, signature: Signature) {
self.signatures.add(&signature);
}
}
2 changes: 2 additions & 0 deletions node/libs/roles/src/validator/messages/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
mod block;
mod consensus;
mod discovery;
mod l1_batch;
mod leader_commit;
mod leader_prepare;
mod msg;
Expand All @@ -12,6 +13,7 @@ mod replica_prepare;
pub use block::*;
pub use consensus::*;
pub use discovery::*;
pub use l1_batch::*;
pub use leader_commit::*;
pub use leader_prepare::*;
pub use msg::*;
Expand Down
21 changes: 19 additions & 2 deletions node/libs/roles/src/validator/messages/msg.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
//! Generic message types.
use super::{ConsensusMsg, NetAddress};
use crate::{node::SessionId, validator, validator::Error};
use super::{ConsensusMsg, L1BatchSignatureMsg, NetAddress};
use crate::{
node::SessionId,
validator::{self, Error},
};
use std::fmt;
use zksync_consensus_crypto::{keccak256, ByteFmt, Text, TextFmt};
use zksync_consensus_utils::enum_util::{BadVariantError, Variant};
Expand All @@ -14,6 +17,8 @@ pub enum Msg {
SessionId(SessionId),
/// validator discovery
NetAddress(NetAddress),
/// l1 batch signature
L1BatchSignature(L1BatchSignatureMsg),
IAvecilla marked this conversation as resolved.
Show resolved Hide resolved
}

impl Msg {
Expand Down Expand Up @@ -59,6 +64,18 @@ impl Variant<Msg> for NetAddress {
}
}

impl Variant<Msg> for L1BatchSignatureMsg {
fn insert(self) -> Msg {
Msg::L1BatchSignature(self)
}
fn extract(msg: Msg) -> Result<Self, BadVariantError> {
let Msg::L1BatchSignature(this) = msg else {
return Err(BadVariantError);
};
Ok(this)
}
}

/// Hash of a message.
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct MsgHash(pub(crate) keccak256::Keccak256);
Expand Down