Skip to content

Commit c7e7f04

Browse files
committed
chore: more progress
1 parent dfc6d17 commit c7e7f04

33 files changed

Lines changed: 1620 additions & 255 deletions

Cargo.lock

Lines changed: 307 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ members = [
44
"crates/bfte-node",
55
"crates/consensus",
66
"crates/consensus-core",
7+
"crates/consensus-tests",
78
"crates/util-array-type",
89
"crates/util-db",
10+
"crates/util-fmt-opt",
911
"crates/util-error",
1012
]
1113
resolver = "2"
@@ -27,10 +29,12 @@ collapsible_else_if = "allow"
2729
[workspace.dependencies]
2830
bfte = { path = "./crates/bfte" }
2931
bfte-consensus-core = { path = "./crates/consensus-core" }
32+
bfte-consensus-tests = { path = "./crates/consensus-tests" }
3033
bfte-consensus = { path = "./crates/consensus" }
3134
bfte-node = { path = "./crates/bfte-node" }
3235
bfte-util-array-type = { path = "./crates/util-array-type" }
3336
bfte-util-db = { path = "./crates/util-db" }
37+
bfte-util-fmt-opt = { path = "./crates/util-fmt-opt" }
3438
bfte-util-error = { path = "./crates/util-error" }
3539

3640
anyhow = "1.0"
@@ -53,6 +57,7 @@ num-bigint = "0.4.6"
5357
serde_bytes = "0.11.17"
5458
serde = { version = "1.0", features = ["derive"] }
5559
snafu = { version = "0.8.5", features = ["rust_1_81"] }
60+
test-log = { version = "0.2.16", features = ["trace"] }
5661
tokio-test = "0.4.4"
5762
tokio = { version = "1.0", features = ["full"] }
5863
tracing = "0.1.41"

crates/consensus-core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ ed25519-dalek = { workspace = true }
1515
num-bigint = { workspace = true }
1616
serde_bytes = { workspace = true }
1717
serde = { workspace = true, features = ["derive"] }
18+
snafu = { workspace = true }

crates/consensus-core/src/block.rs

Lines changed: 94 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@ use std::sync::Arc;
33

44
use bfte_util_array_type::{
55
array_type_define, array_type_define_fixed_size, array_type_impl_base32_str,
6-
array_type_impl_serde, array_type_impl_zero_default,
6+
array_type_impl_debug_as_display, array_type_impl_serde, array_type_impl_zero_default,
77
};
88
use bincode::{Decode, Encode};
99
use num_bigint::BigUint;
10+
use snafu::Snafu;
1011

12+
use crate::bincode::STD_BINCODE_CONFIG;
13+
use crate::consensus_params::ConsensusParamsHash;
14+
use crate::federation_id::FederationId;
1115
use crate::num_peers::NumPeers;
1216
use crate::peer::PeerIdx;
1317
use crate::ver::ConsensusVersionMinor;
@@ -28,15 +32,6 @@ array_type_define_fixed_size! {
2832
pub struct BlockRound(u64);
2933
}
3034

31-
// array_type_fixed_size_u64!(BlockSeq);
32-
// array_type_define! {
33-
// /// Round the block was produced in
34-
// #[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
35-
// pub struct BlockRound[8];
36-
// }
37-
38-
// array_type_fixed_size_u64!(BlockRound);
39-
4035
impl BlockRound {
4136
pub fn hash(self) -> blake3::Hash {
4237
blake3::hash(&self.0)
@@ -75,57 +70,127 @@ fn block_round_leader_test() {
7570
}
7671
}
7772
array_type_define! {
78-
#[derive(Encode, Decode)]
73+
#[derive(Encode, Decode, Copy, Clone)]
7974
pub struct BlockHash[32];
8075
}
8176
array_type_impl_zero_default!(BlockHash);
8277
array_type_impl_base32_str!(BlockHash);
8378
array_type_impl_serde!(BlockHash);
79+
array_type_impl_debug_as_display!(BlockHash);
8480

85-
#[derive(Encode, Decode)]
81+
impl From<blake3::Hash> for BlockHash {
82+
fn from(value: blake3::Hash) -> Self {
83+
Self(*value.as_bytes())
84+
}
85+
}
86+
87+
impl From<BlockHash> for blake3::Hash {
88+
fn from(value: BlockHash) -> Self {
89+
blake3::Hash::from_bytes(value.0)
90+
}
91+
}
92+
93+
#[derive(Debug, Encode, Decode, Copy, Clone, PartialEq, Eq)]
8694
pub struct BlockHeader {
87-
pub consensus_minor_version: ConsensusVersionMinor,
88-
pub seq: BlockSeq,
89-
pub round: BlockRound,
90-
pub prev_block_id: BlockHash,
91-
pub payload_hash: BlockPayloadHash,
95+
pub seq: BlockSeq, // 8B
96+
pub round: BlockRound, // 8B
97+
/// Commits to previous non-dummy `BlockHeader`
98+
pub prev_block_hash: BlockHash, // 32B
99+
/// Commits to [`ConsensusParams`] used for this block
100+
pub consensus_params_hash: ConsensusParamsHash, // 32B
101+
/// Commits to [`BlockPayload`]
102+
pub payload_hash: BlockPayloadHash, // 32B
103+
}
104+
105+
#[test]
106+
fn block_header_size_sanity() {
107+
let block = BlockHeader::dummy(0.into(), 0.into());
108+
assert_eq!(
109+
bincode::encode_to_vec(block, STD_BINCODE_CONFIG)
110+
.expect("Can't fail")
111+
.len(),
112+
112
113+
)
92114
}
93115

116+
#[derive(Debug, Snafu)]
117+
pub struct PayloadHashMismatchError;
118+
119+
pub type PayloadHashMismatchResult<T> = std::result::Result<T, PayloadHashMismatchError>;
120+
94121
impl BlockHeader {
95-
pub fn dummy(round: BlockRound, consensus_minor_version: ConsensusVersionMinor) -> Self {
122+
pub fn hash(&self) -> BlockHash {
123+
// TODO: use static array for encoding output
124+
blake3::hash(&bincode::encode_to_vec(self, STD_BINCODE_CONFIG).expect("Can't fail")).into()
125+
}
126+
127+
pub fn verify_payload(&self, payload: &BlockPayload) -> PayloadHashMismatchResult<()> {
128+
if payload.hash() != self.payload_hash {
129+
return Err(PayloadHashMismatchError);
130+
}
131+
132+
Ok(())
133+
}
134+
pub fn dummy(round: BlockRound, consensus_params_hash: ConsensusParamsHash) -> Self {
96135
Self {
97136
seq: BlockSeq::default(),
98137
round,
99-
prev_block_id: BlockHash::ZERO,
138+
prev_block_hash: BlockHash::ZERO,
139+
consensus_params_hash,
100140
payload_hash: BlockPayloadHash::ZERO,
101-
consensus_minor_version,
102141
}
103142
}
104143

105144
pub fn is_dummy(&self) -> bool {
106145
self.seq == BlockSeq::ZERO
107-
&& self.prev_block_id == BlockHash::ZERO
146+
&& self.prev_block_hash == BlockHash::ZERO
108147
&& self.payload_hash == BlockPayloadHash::ZERO
109148
}
110149

111150
pub fn sign_by(&self, _secret_key: ed25519_dalek::SecretKey) {
112151
todo!()
113152
}
153+
154+
pub fn does_extend(
155+
&self,
156+
prev_block: Option<BlockHeader>,
157+
consensus_params_hash: ConsensusParamsHash,
158+
) -> bool {
159+
if self.consensus_params_hash.to_bytes() != consensus_params_hash.to_bytes() {
160+
return false;
161+
}
162+
163+
if let Some(prev_block) = prev_block {
164+
prev_block.seq.next() == Some(self.seq)
165+
&& prev_block.round < self.round
166+
&& prev_block.hash() == self.prev_block_hash
167+
} else {
168+
// Note: 0 round block could be a dummy, so we can't require round to be 0
169+
self.seq == BlockSeq::ZERO && self.prev_block_hash == BlockHash::ZERO
170+
}
171+
}
114172
}
173+
115174
#[derive(Encode, Decode)]
116175
pub struct SignedBlock {
117176
block: BlockHeader,
118177
signatures: BTreeMap<PeerIdx, BlockSignature>,
119178
}
120179

121180
array_type_define! {
122-
#[derive(Encode, Decode)]
181+
#[derive(Encode, Decode, Copy, Clone)]
123182
pub struct BlockPayloadHash[32];
124183
}
125184
array_type_impl_zero_default!(BlockPayloadHash);
126185
array_type_impl_base32_str!(BlockPayloadHash);
127186
array_type_impl_serde!(BlockPayloadHash);
187+
array_type_impl_debug_as_display!(BlockPayloadHash);
128188

189+
impl From<blake3::Hash> for BlockPayloadHash {
190+
fn from(value: blake3::Hash) -> Self {
191+
Self(*value.as_bytes())
192+
}
193+
}
129194
array_type_define! {
130195
#[derive(Encode, Decode)]
131196
pub struct BlockSignature[32];
@@ -135,4 +200,10 @@ array_type_impl_base32_str!(BlockSignature);
135200
array_type_impl_serde!(BlockSignature);
136201

137202
#[derive(Encode, Decode, Clone)]
138-
pub struct BlockPayload(Arc<u8>);
203+
pub struct BlockPayload(Arc<[u8]>);
204+
205+
impl BlockPayload {
206+
pub fn hash(&self) -> BlockPayloadHash {
207+
blake3::hash(&self.0).into()
208+
}
209+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use bfte_util_array_type::{
2+
array_type_define, array_type_impl_base32_str, array_type_impl_debug_as_display,
3+
array_type_impl_serde, array_type_impl_zero_default,
4+
};
5+
use bincode::{Decode, Encode};
6+
7+
use crate::bincode::STD_BINCODE_CONFIG;
8+
use crate::block::BlockRound;
9+
use crate::num_peers::{NumPeers, ToNumPeers as _};
10+
use crate::peer::{PeerIdx, PeerPubkey};
11+
use crate::ver::ConsensusVersion;
12+
13+
/// Global consensus parameters
14+
#[derive(Decode, Encode, Clone, PartialEq, Eq)]
15+
pub struct ConsensusParams {
16+
pub version: ConsensusVersion,
17+
pub peers: Vec<PeerPubkey>,
18+
}
19+
20+
impl ConsensusParams {
21+
pub fn num_peers(&self) -> NumPeers {
22+
self.peers.to_num_peers()
23+
}
24+
25+
pub fn leader_idx(&self, round: BlockRound) -> PeerIdx {
26+
round.leader_idx(self.num_peers())
27+
}
28+
29+
pub fn hash(&self) -> ConsensusParamsHash {
30+
blake3::hash(&bincode::encode_to_vec(self, STD_BINCODE_CONFIG).expect("Can't fail")).into()
31+
}
32+
}
33+
34+
array_type_define! {
35+
#[derive(Encode, Decode, Copy, Clone)]
36+
pub struct ConsensusParamsHash[32];
37+
}
38+
39+
array_type_impl_zero_default!(ConsensusParamsHash);
40+
array_type_impl_base32_str!(ConsensusParamsHash);
41+
array_type_impl_serde!(ConsensusParamsHash);
42+
array_type_impl_debug_as_display!(ConsensusParamsHash);
43+
44+
impl From<blake3::Hash> for ConsensusParamsHash {
45+
fn from(value: blake3::Hash) -> Self {
46+
Self(*value.as_bytes())
47+
}
48+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use bfte_util_array_type::{
2+
array_type_define, array_type_impl_base32_str, array_type_impl_debug_as_display,
3+
array_type_impl_serde, array_type_impl_zero_default,
4+
};
5+
use bincode::{Decode, Encode};
6+
7+
array_type_define! {
8+
#[derive(Encode, Decode, Copy, Clone)]
9+
pub struct FederationId[32];
10+
}
11+
array_type_impl_zero_default!(FederationId);
12+
array_type_impl_base32_str!(FederationId);
13+
array_type_impl_serde!(FederationId);
14+
array_type_impl_debug_as_display!(FederationId);
15+
16+
impl From<blake3::Hash> for FederationId {
17+
fn from(value: blake3::Hash) -> Self {
18+
Self(*value.as_bytes())
19+
}
20+
}
21+
22+
impl From<FederationId> for blake3::Hash {
23+
fn from(value: FederationId) -> Self {
24+
blake3::Hash::from_bytes(value.0)
25+
}
26+
}

crates/consensus-core/src/lib.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,33 @@
22

33
use ::bincode::{Decode, Encode};
44
use bfte_util_array_type::{
5-
array_type_define, array_type_impl_base32_str, array_type_impl_serde,
6-
array_type_impl_zero_default,
5+
array_type_define, array_type_impl_base32_str, array_type_impl_debug_as_display,
6+
array_type_impl_serde, array_type_impl_zero_default,
77
};
8-
use peer::PeerIdx;
98

109
pub mod bincode;
1110
pub mod block;
1211
pub mod citem;
12+
pub mod consensus_params;
13+
pub mod federation_id;
14+
pub mod msg;
1315
pub mod num_peers;
1416
pub mod peer;
17+
pub mod signed;
1518
pub mod ver;
19+
pub mod vote;
1620

1721
array_type_define! {
18-
#[derive(Encode, Decode)]
19-
pub struct Signature[32];
22+
#[derive(Encode, Decode, Copy, Clone)]
23+
pub struct Signature[64];
2024
}
2125
array_type_impl_zero_default!(Signature);
2226
array_type_impl_base32_str!(Signature);
2327
array_type_impl_serde!(Signature);
28+
array_type_impl_debug_as_display!(Signature);
2429

25-
pub struct PeerSignature {
26-
pub peer_idx: PeerIdx,
27-
pub signature: Signature,
30+
impl From<Signature> for ed25519_dalek::Signature {
31+
fn from(value: Signature) -> Self {
32+
ed25519_dalek::Signature::from_bytes(&value.0)
33+
}
2834
}

0 commit comments

Comments
 (0)