Skip to content

Commit f322eaa

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

39 files changed

Lines changed: 1987 additions & 413 deletions

Cargo.lock

Lines changed: 404 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: 6 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,17 +29,20 @@ 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"
3741
assert_matches = "1.5.0"
3842
bincode = { version = "2.0.0", features = ["derive"] }
3943
bit-set = { version = "0.8" }
4044
bon = "3.6.1"
45+
clap = "4.5.37"
4146
blake3 = "1.8.2"
4247
bytes = "1.0"
4348
convi = { version = "0.1.1", features = ["min_target_pointer_width_32"] }
@@ -53,6 +58,7 @@ num-bigint = "0.4.6"
5358
serde_bytes = "0.11.17"
5459
serde = { version = "1.0", features = ["derive"] }
5560
snafu = { version = "0.8.5", features = ["rust_1_81"] }
61+
test-log = { version = "0.2.16", features = ["trace"] }
5662
tokio-test = "0.4.4"
5763
tokio = { version = "1.0", features = ["full"] }
5864
tracing = "0.1.41"

crates/bfte/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ version.workspace = true
88

99
[dependencies]
1010
bon = { workspace = true }
11+
clap = { workspace = true, features = ["derive", "env"] }
1112
bfte-util-array-type = { workspace = true }
1213
bfte-consensus-core = { workspace = true }
1314
bincode = { workspace = true }

crates/bfte/src/lib.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,35 @@
1+
use std::path::PathBuf;
2+
3+
use clap::{Parser, Subcommand};
4+
15
pub struct Bfte {}
26

7+
#[derive(Parser, Debug)]
8+
pub struct Opts {
9+
#[arg(long, env = "BFTE_DATA_DIR")]
10+
data_dir: Option<PathBuf>,
11+
12+
#[arg(long, env = "BFTE_SECRET_PATH")]
13+
secret_path: Option<PathBuf>,
14+
15+
#[command(subcommand)]
16+
command: Commands,
17+
}
18+
19+
#[derive(Debug, Subcommand)]
20+
enum Commands {
21+
Create,
22+
Join {
23+
#[arg(long)]
24+
invite: String,
25+
},
26+
Run,
27+
}
28+
329
#[bon::bon]
430
impl Bfte {
531
#[builder(finish_fn = run)]
6-
pub fn build() {}
32+
pub fn build() {
33+
let _opts = Opts::parse();
34+
}
735
}

crates/consensus-core/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ blake3 = { workspace = true }
1111
convi = { workspace = true }
1212
data-encoding = { workspace = true }
1313
derive_more = { workspace = true }
14-
ed25519-dalek = { workspace = true }
14+
ed25519-dalek = { workspace = true, features = ["rand_core", "digest"] }
1515
num-bigint = { workspace = true }
16+
rand = { workspace = true }
1617
serde_bytes = { workspace = true }
1718
serde = { workspace = true, features = ["derive"] }
19+
snafu = { workspace = true }

crates/consensus-core/src/block.rs

Lines changed: 97 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@ 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;
1114
use crate::num_peers::NumPeers;
1215
use crate::peer::PeerIdx;
13-
use crate::ver::ConsensusVersionMinor;
1416

1517
array_type_define_fixed_size! {
1618
/// Non-dumy block sequence number
@@ -28,15 +30,6 @@ array_type_define_fixed_size! {
2830
pub struct BlockRound(u64);
2931
}
3032

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-
4033
impl BlockRound {
4134
pub fn hash(self) -> blake3::Hash {
4235
blake3::hash(&self.0)
@@ -75,57 +68,127 @@ fn block_round_leader_test() {
7568
}
7669
}
7770
array_type_define! {
78-
#[derive(Encode, Decode)]
71+
#[derive(Encode, Decode, Copy, Clone)]
7972
pub struct BlockHash[32];
8073
}
8174
array_type_impl_zero_default!(BlockHash);
8275
array_type_impl_base32_str!(BlockHash);
8376
array_type_impl_serde!(BlockHash);
77+
array_type_impl_debug_as_display!(BlockHash);
8478

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

114+
#[derive(Debug, Snafu)]
115+
pub struct PayloadHashMismatchError;
116+
117+
pub type PayloadHashMismatchResult<T> = std::result::Result<T, PayloadHashMismatchError>;
118+
94119
impl BlockHeader {
95-
pub fn dummy(round: BlockRound, consensus_minor_version: ConsensusVersionMinor) -> Self {
120+
pub fn hash(&self) -> BlockHash {
121+
// TODO: use static array for encoding output
122+
blake3::hash(&bincode::encode_to_vec(self, STD_BINCODE_CONFIG).expect("Can't fail")).into()
123+
}
124+
125+
pub fn verify_payload(&self, payload: &BlockPayload) -> PayloadHashMismatchResult<()> {
126+
if payload.hash() != self.payload_hash {
127+
return Err(PayloadHashMismatchError);
128+
}
129+
130+
Ok(())
131+
}
132+
pub fn dummy(round: BlockRound, consensus_params_hash: ConsensusParamsHash) -> Self {
96133
Self {
97134
seq: BlockSeq::default(),
98135
round,
99-
prev_block_id: BlockHash::ZERO,
136+
prev_block_hash: BlockHash::ZERO,
137+
consensus_params_hash,
100138
payload_hash: BlockPayloadHash::ZERO,
101-
consensus_minor_version,
102139
}
103140
}
104141

105142
pub fn is_dummy(&self) -> bool {
106143
self.seq == BlockSeq::ZERO
107-
&& self.prev_block_id == BlockHash::ZERO
144+
&& self.prev_block_hash == BlockHash::ZERO
108145
&& self.payload_hash == BlockPayloadHash::ZERO
109146
}
110147

111148
pub fn sign_by(&self, _secret_key: ed25519_dalek::SecretKey) {
112149
todo!()
113150
}
151+
152+
pub fn does_extend(
153+
&self,
154+
prev_block: Option<BlockHeader>,
155+
consensus_params_hash: ConsensusParamsHash,
156+
) -> bool {
157+
if self.consensus_params_hash.to_bytes() != consensus_params_hash.to_bytes() {
158+
return false;
159+
}
160+
161+
if let Some(prev_block) = prev_block {
162+
prev_block.seq.next() == Some(self.seq)
163+
&& prev_block.round < self.round
164+
&& prev_block.hash() == self.prev_block_hash
165+
} else {
166+
// Note: 0 round block could be a dummy, so we can't require round to be 0
167+
self.seq == BlockSeq::ZERO && self.prev_block_hash == BlockHash::ZERO
168+
}
169+
}
114170
}
171+
115172
#[derive(Encode, Decode)]
116173
pub struct SignedBlock {
117174
block: BlockHeader,
118175
signatures: BTreeMap<PeerIdx, BlockSignature>,
119176
}
120177

121178
array_type_define! {
122-
#[derive(Encode, Decode)]
179+
#[derive(Encode, Decode, Copy, Clone)]
123180
pub struct BlockPayloadHash[32];
124181
}
125182
array_type_impl_zero_default!(BlockPayloadHash);
126183
array_type_impl_base32_str!(BlockPayloadHash);
127184
array_type_impl_serde!(BlockPayloadHash);
185+
array_type_impl_debug_as_display!(BlockPayloadHash);
128186

187+
impl From<blake3::Hash> for BlockPayloadHash {
188+
fn from(value: blake3::Hash) -> Self {
189+
Self(*value.as_bytes())
190+
}
191+
}
129192
array_type_define! {
130193
#[derive(Encode, Decode)]
131194
pub struct BlockSignature[32];
@@ -135,4 +198,14 @@ array_type_impl_base32_str!(BlockSignature);
135198
array_type_impl_serde!(BlockSignature);
136199

137200
#[derive(Encode, Decode, Clone)]
138-
pub struct BlockPayload(Arc<u8>);
201+
pub struct BlockPayload(Arc<[u8]>);
202+
203+
impl BlockPayload {
204+
pub fn empty() -> Self {
205+
Self(Default::default())
206+
}
207+
208+
pub fn hash(&self) -> BlockPayloadHash {
209+
blake3::hash(&self.0).into()
210+
}
211+
}
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+
}

0 commit comments

Comments
 (0)