Skip to content

abcperf/minbft

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MinBFT

MinBFT is a Rust implementation based on the equally named Byzantine fault-tolerant consensus algorithm presented in the paper Efficient Byzantine Fault-Tolerance.

MinBFT requires a Unique Sequential Identifier Generator (USIG) implementation. A USIG implementation compatible with this MinBFT implementation can be found here. Note that this implementation does not use Trusted Execution Environments and, thus, should not be used in untrusted environments.

This implementation was created as part of the ABCperf project. An integration in ABCperf also exists.

MinBFT in Action

use anyhow::Result;
use std::{num::NonZeroU64, time::Duration};
use serde::{Deserialize, Serialize};
use shared_ids::{ReplicaId, ClientId, RequestId};
use usig::{Usig, noop::UsigNoOp};
use minbft::{MinBft, Config, Output, RequestPayload, PeerMessage, timeout::{TimeoutType}};

// The payload of a client request must be implemented by the user.
#[derive(Deserialize, Serialize, Clone, Debug, Eq, PartialEq)]
struct SamplePayload {}
impl RequestPayload for SamplePayload {
    fn id(&self) -> RequestId {
        todo!()
    }
    fn verify(&self, id: ClientId) -> Result<()> {
        todo!()
    }
}

// The output should be handled by the user.
fn handle_output<U: Usig>(output: Output<SamplePayload, U>) {
    let Output { broadcasts, responses, timeout_requests, .. } = output;
    for broadcast in broadcasts.iter() {
        // broadcast message to all peers, i.e., send messages contained
        // in `broadcasts` of struct Output over the network to other
        // replicas.
        todo!();
    }
    for response in responses.iter() {
        todo!();
    }
    for timeout_request in timeout_requests.iter() {
        todo!();
    }
}

fn main() {
    // define the amount of replicas that form the atomic broadcast
    let n = NonZeroU64::new(10).unwrap();
    // define the maximum amount of faulty replicas (`n >= t / 2 + 1`)
    let t = n.get() / 2;
    // define the ID of one of the replicas
    let replica_id = ReplicaId::from_u64(0);

    let config = Config {
                n: n.try_into().unwrap(),
                t,
                id: replica_id,
                max_batch_size: Some(1.try_into().expect("> 0")),
                batch_timeout: Duration::from_secs(1),
                initial_timeout_duration: Duration::from_secs(1),
                checkpoint_period: NonZeroU64::new(2).unwrap(),
            };
    
    // can be exchanged with a different USIG implementation
    let usig = UsigNoOp::default();

    let (mut minbft, output) = MinBft::<SamplePayload, _>::new(
            usig,
            config,
        )
        .unwrap();

    // handle output to setup connection with peers
    handle_output(output);

    // all peers are now ready for client requests as they have
    // successfully communicated with each replica for the first time.

    // create and send client message to be handled by replicas.
    let some_client_message: SamplePayload = todo!();
    let output = minbft.handle_client_message(ClientId::from_u64(0), some_client_message);
    handle_output(output);
    // after the atomic broadcast achieves consensus,
    // a response to the client request can be seen in the output struct.
}

Contact

Feel free to reach out via GitHub, matrix, or mail.

License

Licensed under MIT license.

About

Efficient Byzantine Fault-Tolerance in the partially synchronous timing model

Resources

License

Stars

Watchers

Forks

Languages