diff --git a/Cargo.lock b/Cargo.lock index 50ce03c38..fb02f768b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3657,6 +3657,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive-where" +version = "1.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "derive_more" version = "0.99.18" @@ -4838,6 +4849,16 @@ version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" +[[package]] +name = "informalsystems-malachitebft-core-types" +version = "0.0.1" +source = "git+https://github.com/informalsystems/malachite.git#1d50e2bdf92bf90c58dd39ee9ba2660255b8f6b8" +dependencies = [ + "bytes", + "derive-where", + "thiserror 2.0.3", +] + [[package]] name = "inout" version = "0.1.3" @@ -5418,6 +5439,15 @@ dependencies = [ "url", ] +[[package]] +name = "malachite" +version = "0.7.0" +dependencies = [ + "informalsystems-malachitebft-core-types", + "mp-block", + "starknet-types-core 0.1.7 (git+https://github.com/kasarlabs/types-rs.git?branch=feat-deserialize-v0.1.7)", +] + [[package]] name = "matchers" version = "0.1.0" @@ -6000,6 +6030,7 @@ name = "mp-block" version = "0.7.0" dependencies = [ "blockifier", + "informalsystems-malachitebft-core-types", "mp-chain-config", "mp-receipt", "mp-transactions", diff --git a/Cargo.toml b/Cargo.toml index 9a8c743ff..e87488bd8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ members = [ "crates/madara/tests", "crates/madara/cairo-test-contracts", "crates/madara/client/block_production", + "crates/madara/primitives/malachite", ] resolver = "2" # Everything except test-related packages, so that they are not compiled when doing `cargo build`. @@ -266,6 +267,12 @@ flate2 = "1.0" regex = "1.10.5" sha3 = "0.10" +# Starknet consensus + +[workspace.dependencies.malachite-core-types] +git = "https://github.com/informalsystems/malachite.git" +package = "informalsystems-malachitebft-core-types" + [patch.crates-io] rocksdb = { git = "https://github.com/madara-alliance/rust-rocksdb", branch = "read-options-set-raw-snapshot" } librocksdb-sys = { git = "https://github.com/madara-alliance/rust-rocksdb", branch = "read-options-set-raw-snapshot" } diff --git a/crates/madara/primitives/block/Cargo.toml b/crates/madara/primitives/block/Cargo.toml index df04f3807..4eb29a7a5 100644 --- a/crates/madara/primitives/block/Cargo.toml +++ b/crates/madara/primitives/block/Cargo.toml @@ -14,6 +14,10 @@ workspace = true [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] +[features] +default = [] +testing = [] + [dependencies] # Madara @@ -25,6 +29,7 @@ mp-transactions = { workspace = true } blockifier = { workspace = true } starknet-types-core = { workspace = true } starknet-types-rpc = { workspace = true } +malachite-core-types.workspace = true # Other primitive-types.workspace = true diff --git a/crates/madara/primitives/block/src/lib.rs b/crates/madara/primitives/block/src/lib.rs index 6e1c3fb58..8426307d9 100644 --- a/crates/madara/primitives/block/src/lib.rs +++ b/crates/madara/primitives/block/src/lib.rs @@ -202,6 +202,7 @@ impl MadaraMaybePendingBlock { } /// Starknet block definition. +#[cfg_attr(any(test, feature = "testing"), derive(PartialEq))] #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] pub struct MadaraBlock { pub info: MadaraBlockInfo, @@ -219,6 +220,37 @@ impl MadaraBlock { } } +/// For testing we use a more rigorous impl of [PartialEq] which doesn't just +/// check the block hash. +#[cfg(not(any(test, feature = "testing")))] +impl PartialEq for MadaraBlock { + fn eq(&self, other: &Self) -> bool { + self.info.block_hash == other.info.block_hash + } +} + +impl Eq for MadaraBlock {} + +impl Ord for MadaraBlock { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.info.header.block_number.cmp(&other.info.header.block_number) + } +} + +impl PartialOrd for MadaraBlock { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl malachite_core_types::Value for MadaraBlock { + type Id = Felt; + + fn id(&self) -> Self::Id { + self.info.block_hash + } +} + /// Starknet block definition. #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] pub struct MadaraPendingBlock { diff --git a/crates/madara/primitives/malachite/Cargo.toml b/crates/madara/primitives/malachite/Cargo.toml new file mode 100644 index 000000000..427e08677 --- /dev/null +++ b/crates/madara/primitives/malachite/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "malachite" +authors.workspace = true +homepage.workspace = true +edition.workspace = true +repository.workspace = true +version.workspace = true +license.workspace = true + +[dependencies] + +# Madara +mp-block.workspace = true + +# Starknet +malachite-core-types.workspace = true +starknet-types-core.workspace = true + +[lints] +workspace = true diff --git a/crates/madara/primitives/malachite/src/context.rs b/crates/madara/primitives/malachite/src/context.rs new file mode 100644 index 000000000..18e1ab20b --- /dev/null +++ b/crates/madara/primitives/malachite/src/context.rs @@ -0,0 +1,65 @@ +use mp_block::MadaraBlock; + +use crate::{ + proposal::{ProposalPartStub, ProposalStub}, + types::{Address, Height}, + validators::{ValidatorSet, ValidatorStub}, + vote::{SigningProviderStub, SigningSchemeStub, VoteStub}, +}; + +#[derive(Clone, Debug)] +pub struct MadaraContext; + +impl malachite_core_types::Context for MadaraContext { + type Address = Address; + type Height = Height; + type ProposalPart = ProposalPartStub; + type Proposal = ProposalStub; + type Validator = ValidatorStub; + type ValidatorSet = ValidatorSet; + type Value = MadaraBlock; + type Vote = VoteStub; + type SigningScheme = SigningSchemeStub; + type SigningProvider = SigningProviderStub; + + fn select_proposer<'a>( + &self, + validator_set: &'a Self::ValidatorSet, + height: Self::Height, + round: malachite_core_types::Round, + ) -> &'a Self::Validator { + todo!() + } + + fn signing_provider(&self) -> &Self::SigningProvider { + todo!() + } + + fn new_proposal( + height: Self::Height, + round: malachite_core_types::Round, + value: Self::Value, + pol_round: malachite_core_types::Round, + address: Self::Address, + ) -> Self::Proposal { + todo!() + } + + fn new_prevote( + height: Self::Height, + round: malachite_core_types::Round, + value_id: malachite_core_types::NilOrVal>, + address: Self::Address, + ) -> Self::Vote { + todo!() + } + + fn new_precommit( + height: Self::Height, + round: malachite_core_types::Round, + value_id: malachite_core_types::NilOrVal>, + address: Self::Address, + ) -> Self::Vote { + todo!() + } +} diff --git a/crates/madara/primitives/malachite/src/lib.rs b/crates/madara/primitives/malachite/src/lib.rs new file mode 100644 index 000000000..c5aae042c --- /dev/null +++ b/crates/madara/primitives/malachite/src/lib.rs @@ -0,0 +1,5 @@ +mod context; +mod proposal; +mod types; +mod validators; +mod vote; diff --git a/crates/madara/primitives/malachite/src/proposal.rs b/crates/madara/primitives/malachite/src/proposal.rs new file mode 100644 index 000000000..bb351cb9c --- /dev/null +++ b/crates/madara/primitives/malachite/src/proposal.rs @@ -0,0 +1,48 @@ +use mp_block::MadaraBlock; + +use crate::{ + context::MadaraContext, + types::{Address, Height}, +}; + +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct ProposalPartStub; + +impl malachite_core_types::ProposalPart for ProposalPartStub { + fn is_first(&self) -> bool { + unimplemented!() + } + + fn is_last(&self) -> bool { + unimplemented!() + } +} + +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct ProposalStub; + +impl malachite_core_types::Proposal for ProposalStub { + fn height(&self) -> Height { + todo!() + } + + fn round(&self) -> malachite_core_types::Round { + todo!() + } + + fn value(&self) -> &MadaraBlock { + todo!() + } + + fn take_value(self) -> MadaraBlock { + todo!() + } + + fn pol_round(&self) -> malachite_core_types::Round { + todo!() + } + + fn validator_address(&self) -> &Address { + todo!() + } +} diff --git a/crates/madara/primitives/malachite/src/types.rs b/crates/madara/primitives/malachite/src/types.rs new file mode 100644 index 000000000..a3c5292ac --- /dev/null +++ b/crates/madara/primitives/malachite/src/types.rs @@ -0,0 +1,37 @@ +use starknet_types_core::felt::Felt; + +#[repr(transparent)] +#[derive(Clone, Copy, Default, Debug, Eq, PartialEq, Ord, PartialOrd)] +pub struct Height(u64); + +impl std::fmt::Display for Height { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Height").field("at", &self.0).finish() + } +} + +impl malachite_core_types::Height for Height { + fn increment_by(&self, n: u64) -> Self { + Self(self.0.saturating_add(n)) + } + + fn decrement_by(&self, n: u64) -> Option { + self.0.checked_sub(n).map(Self) + } + + fn as_u64(&self) -> u64 { + self.0 + } +} + +#[repr(transparent)] +#[derive(Clone, Copy, Default, Debug, Eq, PartialEq, Ord, PartialOrd)] +pub struct Address(Felt); + +impl std::fmt::Display for Address { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Address").field("at", &self.0).finish() + } +} + +impl malachite_core_types::Address for Address {} diff --git a/crates/madara/primitives/malachite/src/validators.rs b/crates/madara/primitives/malachite/src/validators.rs new file mode 100644 index 000000000..f7307eb35 --- /dev/null +++ b/crates/madara/primitives/malachite/src/validators.rs @@ -0,0 +1,44 @@ +use malachite_core_types::Validator as _; +use std::collections::BTreeMap; + +use crate::{context::MadaraContext, types::Address}; + +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct ValidatorStub; + +impl malachite_core_types::Validator for ValidatorStub { + fn address(&self) -> &Address { + todo!() + } + + fn public_key(&self) -> &malachite_core_types::PublicKey { + todo!() + } + + fn voting_power(&self) -> malachite_core_types::VotingPower { + todo!() + } +} + +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct ValidatorSet { + validators: BTreeMap, +} + +impl malachite_core_types::ValidatorSet for ValidatorSet { + fn count(&self) -> usize { + self.validators.len() + } + + fn total_voting_power(&self) -> malachite_core_types::VotingPower { + self.validators.values().fold(0, |acc, v| acc + v.voting_power()) + } + + fn get_by_address(&self, address: &Address) -> Option<&ValidatorStub> { + self.validators.get(address) + } + + fn get_by_index(&self, index: usize) -> Option<&ValidatorStub> { + self.validators.values().take(index).last() + } +} diff --git a/crates/madara/primitives/malachite/src/vote.rs b/crates/madara/primitives/malachite/src/vote.rs new file mode 100644 index 000000000..ad8083cba --- /dev/null +++ b/crates/madara/primitives/malachite/src/vote.rs @@ -0,0 +1,127 @@ +//! These are temporary types while I wait to integrate @cchudant's p2p pr into +//! this one. + +use starknet_types_core::felt::Felt; + +use crate::{ + context::MadaraContext, + types::{Address, Height}, +}; + +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct VoteStub; + +impl malachite_core_types::Vote for VoteStub { + fn height(&self) -> Height { + unimplemented!() + } + + fn round(&self) -> malachite_core_types::Round { + unimplemented!() + } + + fn value(&self) -> &malachite_core_types::NilOrVal { + unimplemented!() + } + + fn take_value(self) -> malachite_core_types::NilOrVal { + unimplemented!() + } + + fn vote_type(&self) -> malachite_core_types::VoteType { + unimplemented!() + } + + fn validator_address(&self) -> &Address { + unimplemented!() + } + + fn extension(&self) -> Option<&malachite_core_types::SignedExtension> { + unimplemented!() + } + + fn extend(self, extension: malachite_core_types::SignedExtension) -> Self { + unimplemented!() + } +} + +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct SigningSchemeStub; + +impl malachite_core_types::SigningScheme for SigningSchemeStub { + type DecodingError = String; + type Signature = (); + type PublicKey = (); + type PrivateKey = (); + + fn decode_signature(bytes: &[u8]) -> Result { + unimplemented!() + } + + fn encode_signature(signature: &Self::Signature) -> Vec { + unimplemented!() + } +} + +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct SigningProviderStub; + +impl malachite_core_types::SigningProvider for SigningProviderStub { + fn sign_vote(&self, vote: VoteStub) -> malachite_core_types::SignedMessage { + todo!() + } + + fn verify_signed_vote( + &self, + vote: &VoteStub, + signature: &malachite_core_types::Signature, + public_key: &malachite_core_types::PublicKey, + ) -> bool { + todo!() + } + + fn sign_proposal( + &self, + proposal: ::Proposal, + ) -> malachite_core_types::SignedMessage::Proposal> + { + todo!() + } + + fn verify_signed_proposal( + &self, + proposal: &::Proposal, + signature: &malachite_core_types::Signature, + public_key: &malachite_core_types::PublicKey, + ) -> bool { + todo!() + } + + fn sign_proposal_part( + &self, + proposal_part: ::ProposalPart, + ) -> malachite_core_types::SignedMessage< + MadaraContext, + ::ProposalPart, + > { + todo!() + } + + fn verify_signed_proposal_part( + &self, + proposal_part: &::ProposalPart, + signature: &malachite_core_types::Signature, + public_key: &malachite_core_types::PublicKey, + ) -> bool { + todo!() + } + + fn verify_commit_signature( + &self, + certificate: &malachite_core_types::CommitCertificate, + commit_sig: &malachite_core_types::CommitSignature, + validator: &::Validator, + ) -> Result> { + todo!() + } +}