Skip to content

Latest commit

 

History

History
178 lines (140 loc) · 6.67 KB

File metadata and controls

178 lines (140 loc) · 6.67 KB

Changelog

0.5.0

Breaking — the library is now fully synchronous. Every method drops async and returns its value directly; remove .await from all call sites. tokio is no longer a dependency.

Changed

  • All ConsensusService, ConsensusStorage, and ConsensusEventBus methods, plus ConsensusSignatureScheme::sign and utils::build_vote, are now sync:
    // before
    let vote = service.cast_vote(&scope, id, choice).await?;
    // after
    let vote = service.cast_vote(&scope, id, choice)?;
  • ConsensusStorage::stream_scope_sessions returns impl Iterator<Item = ...> instead of a futures::Stream.
  • BroadcastEventBus now fans out over std::sync::mpsc. subscribe() returns a std::sync::mpsc::Receiver; consume it with recv() / try_recv() / recv_timeout() (was recv().await). Slow subscribers miss events rather than blocking the publisher.
  • InMemoryConsensusStorage uses parking_lot::RwLock internally.
  • The default EthereumConsensusSigner signs via alloy's SignerSync.

Added

  • Optional ethereum feature (enabled by default) gating the alloy-backed EthereumConsensusSigner and the DefaultConsensusService alias. Build with default-features = false to drop the alloy dependency and supply your own ConsensusSignatureScheme.

Migration

Remove .await from every consensus call, drop #[tokio::main]/#[tokio::test] (no async runtime needed), and switch event subscribers from recv().await to a blocking recv() / recv_timeout().

0.4.0

BreakingConsensusService now holds its peer's signer instead of taking one per call. cast_vote and friends drop the signer parameter.

Changed

  • ConsensusService<Scope, Storage, Event, Signer> now stores a Signer instance (previously PhantomData<fn() -> Signer>). The signer represents this peer's identity for the lifetime of the service; storage, event bus, and signer are all peer-scoped held state.
  • ConsensusSignatureScheme now requires Clone + Send + Sync + 'static, matching ConsensusStorage and ConsensusEventBus.
  • cast_vote and cast_vote_and_get_proposal drop the signer parameter and use the service's held signer:
    // before
    service.cast_vote(&scope, id, choice, signer).await?;
    // after
    service.cast_vote(&scope, id, choice).await?;
  • ConsensusService::new_with_components now takes the signer: new_with_components(storage, event_bus, signer, max_sessions_per_scope).
  • DefaultConsensusService::new(signer) and new_with_max_sessions(signer, max) require a signer. Default::default() is removed (no sensible identity to fabricate).
  • utils::build_vote now takes signer: &Signer (was by value).

Added

  • ConsensusService::signer(&self) -> &Signer accessor, mirroring storage() and event_bus().

Migration

// before
let service = DefaultConsensusService::default();
service.cast_vote(&scope, id, true, signer).await?;

// after
let signer = EthereumConsensusSigner::new(PrivateKeySigner::random());
let service = DefaultConsensusService::new(signer);
service.cast_vote(&scope, id, true).await?;

For multi-peer setups (one process simulating many identities), construct one ConsensusService per peer with shared storage and (optionally) a shared event bus — see the README "Service shape" section.

0.3.0

Breaking — the crate is no longer hard-coded to Ethereum signing.

Added

  • New signing module with a single ConsensusSignatureScheme trait. Each peer implements it for signing (identity, sign) and the same type's static verify method is used by the service to validate incoming votes. Embedders can plug in Ed25519, HSM-backed signers, libchat accounts, or any other scheme without forking the crate.
  • signing::ConsensusSchemeError — a thiserror-based enum with Sign and Verify variants, returned by both scheme operations. Implementors construct variants directly (e.g. ConsensusSchemeError::Sign(msg)).
  • signing::EthereumConsensusSigner provides the default ECDSA-secp256k1 implementation matching the historical behavior of the crate. It wraps an alloy::signers::local::PrivateKeySigner and verifies via recoverable signature recovery against 20-byte addresses.
  • New tests/custom_scheme_tests.rs exercises the generic path end-to-end with a non-Ethereum stub scheme.

Changed

  • ConsensusService now has a fourth generic parameter Signer: ConsensusSignatureScheme carried as PhantomData. The scheme is selected at construction (typically via the DefaultConsensusService alias for Ethereum, or by spelling out the type explicitly for custom schemes).
  • cast_vote / cast_vote_and_get_proposal now take signer: Signer instead of a bare alloy_signer::Signer — the signer must impl the scheme the service is parameterized over.
  • utils::build_vote, utils::validate_proposal, and utils::validate_vote are generic over the scheme; downstream callers pick a type at the call site (turbofish or inference).
  • ConsensusSession::from_proposal / initialize_with_votes accept the scheme as a generic parameter instead of receiving an explicit verifier.

Removed

  • The hard-coded SIGNATURE_LENGTH constant and 65-byte signature assumption in utils.rs. Length and format are now scheme-specific.
  • ConsensusError::MismatchedLength and ConsensusError::InvalidSignature variants. Scheme-specific length/encoding errors surface as ConsensusError::FailedToVerifyVote(ConsensusVerifyError).
  • From<alloy_signer::Error> for ConsensusError. Sign failures now go through ConsensusSignError (wrapping any concrete error type).

Migration

If you previously did:

use alloy::signers::local::PrivateKeySigner;
use hashgraph_like_consensus::service::DefaultConsensusService;

let service = DefaultConsensusService::default();
let signer = PrivateKeySigner::random();
service.cast_vote(&scope, proposal_id, true, signer).await?;

Wrap the signer in EthereumConsensusSigner:

use alloy::signers::local::PrivateKeySigner;
use hashgraph_like_consensus::{
    service::DefaultConsensusService,
    signing::EthereumConsensusSigner,
};

let service = DefaultConsensusService::default();
let signer = EthereumConsensusSigner::new(PrivateKeySigner::random());
service.cast_vote(&scope, proposal_id, true, signer).await?;

If you call validate_proposal directly, add a turbofish:

use hashgraph_like_consensus::{signing::EthereumConsensusSigner, utils::validate_proposal};

validate_proposal::<EthereumConsensusSigner>(&proposal)?;

0.2.0

  • Removed the ConsensusServiceAPI trait.
  • Timeout liveness fix.
  • Storage query defaults.
  • Visibility cleanup.