Skip to content

Commit

Permalink
Listener/spammer for remote benchmark. Genesis certificates for kernel
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Zaikin committed Jan 10, 2024
1 parent 0d38b95 commit 18dec75
Show file tree
Hide file tree
Showing 18 changed files with 344 additions and 95 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ bin/
.tezos-client

# Jupyter checkpoints
.ipynb_checkpoints
.ipynb_checkpoints

dsn.env
6 changes: 6 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 11 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ run-operator:
$(MAKE) build-operator
$(MAKE) image-operator OCTEZ_TAG=$(OCTEZ_TAG) OCTEZ_PROTO=$(OCTEZ_PROTO)
docker stop dsn-operator || true
docker volume rm dsn-operator
docker run --rm -it \
--name dsn-operator \
--entrypoint=/bin/sh \
Expand All @@ -70,6 +71,7 @@ run-sequencer:
RUST_LOG=info ./target/debug/sequencer

run-dsn:
rm -rf ./db
./target/debug/launcher --id 1 --log-level 2 &
./target/debug/launcher --id 2 --log-level 0 &
./target/debug/launcher --id 3 --log-level 0 &
Expand All @@ -90,4 +92,12 @@ stop-dsn-min:
cd docker/setup/dsn-min-4-1 && docker-compose down -v

broadcast:
curl -d '{"data":"deadbeef"}' -H "Content-Type: application/json" -X POST http://localhost:8080/broadcast
curl -d '{"data":"deadbeef"}' -H "Content-Type: application/json" -X POST http://localhost:8080/broadcast

run-listener:
cargo build --bin simple-listener
RUST_LOG=info ./target/debug/simple-listener --endpoint $(ENDPOINT) --from-id $(FROM_ID)

run-spammer:
cargo build --bin simple-spammer
RUST_LOG=info ./target/debug/simple-spammer --endpoint $(ENDPOINT) --sleep $(SLEEP)
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,44 @@ The consensus part is based on the Narwhal codebase from [Sui](https://github.co
4. No transaction validation, as we assume a closed network;

![image](https://github.com/baking-bad/sequencer/assets/44951260/7f7604c9-af1b-4c57-8daa-c2d330979b7f)

## Installation

Install Rust toolchain:
```
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

Add Wasm32 target:
```
rustup target add wasm32-unknown-unknown
```

Install kernel build dependencies:
```
make install
```

Install `protobuf` and `clang` system packages:
```
sudo apt install protobuf-compiler clang
```

## How to run

### Local consensus benchmark

Check out the [instructions](./benchmark/README.md)

### Remote consensus benchmark


### Local DSN setup



#### Operator

#### DSN

#### Sequencer
8 changes: 1 addition & 7 deletions crates/exporter/src/proto.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use roaring::RoaringBitmap;
use std::collections::HashMap;
use types::{BatchAPI, CertificateAPI, HeaderAPI};

Expand Down Expand Up @@ -58,7 +57,7 @@ impl Certificate {
| types::SignatureVerificationState::Unsigned(bytes) => Vec::from(bytes.0),
types::SignatureVerificationState::Genesis => Vec::new(),
},
signers: rb_to_bytes(&c.signed_authorities),
signers: c.signed_authorities.iter().map(|x| x as u8).collect(),
},
_ => panic!("CertificateV1 is not expected"),
}
Expand Down Expand Up @@ -113,8 +112,3 @@ impl Header {
}
}

fn rb_to_bytes(rb: &RoaringBitmap) -> Vec<u8> {
let mut bytes = Vec::with_capacity(rb.serialized_size());
rb.serialize_into(&mut bytes).unwrap();
bytes
}
4 changes: 2 additions & 2 deletions crates/pre-block/src/fixture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ impl Default for NarwhalFixture {

#[derive(Debug, Default)]
pub struct SimpleStore {
latest_index: Option<u64>,
certificate_indexes: HashMap<Digest, u64>,
pub latest_index: Option<u64>,
pub certificate_indexes: HashMap<Digest, u64>,
}

impl PreBlockStore for SimpleStore {
Expand Down
57 changes: 53 additions & 4 deletions crates/pre-block/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: MIT

use std::collections::BTreeSet;
use std::collections::{BTreeSet, BTreeMap};

use digest::Blake2b256;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -77,20 +77,25 @@ impl PreBlock {
// NOTE that index is not enforced by any signature, so technically one can craft a
// pre-block with a mismatched (sub dag) index.
// The validation would fail either way, because of the parents check.
anyhow::bail!("Non-sequential index");
anyhow::bail!("Non-sequential index: expected {}", self.index + 1);
}

// TODO: check that leader is actually leader — or is it implied by consensus?
validate_certificate_signature(&self.leader, config)?;

let digests: BTreeSet<Digest> =
self.certificates.iter().map(|cert| cert.digest()).collect();
let mut missing: BTreeMap<Digest, usize> = BTreeMap::new();

validate_certificate_chain(&self.leader, self.index, store, &digests)?;
validate_certificate_chain(&self.leader, config, self.index, store, &digests, &mut missing)?;

for (idx, cert) in self.certificates.iter().enumerate() {
validate_certificate_chain(cert, self.index, store, &digests)?;
validate_certificate_chain(cert, config, self.index, store, &digests, &mut missing)?;
validate_certificate_batches(cert, self.batches.get(idx).unwrap())?;

if cert.header.round == 165 {
println!("{:?}", cert.header);
}
}

Ok(())
Expand Down Expand Up @@ -119,6 +124,18 @@ impl DsnConfig {
pub fn quorum_threshold(&self) -> usize {
self.authorities.len() * 2 / 3 + 1
}

pub fn genesis(&self) -> Vec<Digest> {
self.authorities
.iter()
.enumerate()
.map(|(i, _)| CertificateHeader {
epoch: self.epoch,
author: i as u16,
..Default::default()
}.digest())
.collect()
}
}

pub trait PreBlockStore {
Expand All @@ -127,3 +144,35 @@ pub trait PreBlockStore {
fn get_latest_index(&self) -> Option<u64>;
fn set_latest_index(&mut self, index: u64);
}

#[cfg(test)]
mod tests {
use narwhal_crypto::traits::ToFromBytes;
use narwhal_test_utils::CommitteeFixture;
use narwhal_types::CertificateV2;

use crate::DsnConfig;

#[test]
fn test_genesis_certificate_digests() {
let fixture = CommitteeFixture::builder().build();
let committee = fixture.committee();

let genesis_digests: Vec<[u8; 32]> = CertificateV2::genesis(&committee, true)
.iter()
.map(|cert| cert.header.digest().0)
.collect();

let config = DsnConfig::new(
0,
fixture
.authorities()
.map(|auth| auth.public_key().as_bytes().to_vec())
.collect(),
);

let digests = config.genesis();

pretty_assertions::assert_eq!(genesis_digests, digests);
}
}
39 changes: 25 additions & 14 deletions crates/pre-block/src/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: MIT

use std::collections::BTreeSet;
use std::collections::{BTreeSet, BTreeMap};

use crate::{
bls_min_sig::aggregate_verify, digest::Blake2b256, Batch, Certificate, Digest, DsnConfig,
Expand All @@ -26,7 +26,7 @@ pub fn validate_certificate_signature(
}

if cert.signers.len() < config.quorum_threshold() {
anyhow::bail!("Quorum is not met");
anyhow::bail!("Quorum is not met (round #{})", cert.header.round);
}

let digest = cert.digest();
Expand All @@ -41,9 +41,11 @@ pub fn validate_certificate_signature(

pub fn validate_certificate_chain(
cert: &Certificate,
config: &DsnConfig,
index: u64,
store: &impl PreBlockStore,
neighbors: &BTreeSet<Digest>,
missing: &mut BTreeMap<Digest, usize>,
) -> anyhow::Result<()> {
// We need to ensure the sub dag is:
// 1) Not overlapping with the previous one
Expand All @@ -53,23 +55,31 @@ pub fn validate_certificate_chain(
// that every parent certificate is either:
// 1) From this sub dag
// 2) From a known sub dag (previous one)
// 3) Missing, but is not referenced by the majority
for parent in cert.header.parents.iter() {
if neighbors.contains(parent) {
continue;
}

match store.get_certificate_index(parent) {
Some(prev_index) if prev_index + 1 != index => {
anyhow::bail!(
"Parent certificate is not from a preceding sub dag {}",
hex::encode(parent)
)
}
// TODO: this does not hold for second sub-DAG (references genesis cert)
// Some(prev_index) if prev_index + 1 != index => {
// anyhow::bail!(
// "Parent certificate is not from a preceding sub dag {} (round #{})",
// hex::encode(parent),
// cert.header.round,
// )
// }
None => {
anyhow::bail!(
"Parent certificate cannot be not found {}",
hex::encode(parent)
);
let num_misses = missing.get(parent).unwrap_or(&0usize) + 1;
if num_misses >= config.quorum_threshold() {
anyhow::bail!(
"Parent certificate cannot be not found {} (round #{}, num misses {})",
hex::encode(parent),
cert.header.round,
num_misses,
);
}
}
_ => (),
}
Expand All @@ -85,9 +95,10 @@ pub fn validate_certificate_batches(cert: &Certificate, batches: &[Batch]) -> an
let digest = batch.digest();
if !digests.contains(&digest) {
anyhow::bail!(
"Invalid batch content (digest mismatch), idx = {}, digest = {}",
"Invalid batch content (digest mismatch), idx = {}, digest = {}, round = {}",
i,
hex::encode(&digest)
hex::encode(&digest),
cert.header.round,
);
}
}
Expand Down
21 changes: 18 additions & 3 deletions kernel/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT

use narwhal_config::{Committee, Import};
use pre_block::{fixture::NarwhalFixture, PublicKey};
use pre_block::{fixture::NarwhalFixture, PublicKey, DsnConfig};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;

Expand Down Expand Up @@ -48,9 +48,9 @@ fn real_setup() -> std::result::Result<KernelSetup, Box<dyn std::error::Error>>
.authorities()
.map(|auth| auth.protocol_key_bytes().0.to_vec())
.collect();
let value = bcs::to_bytes(&authorities)?;
let authorities_value = bcs::to_bytes(&authorities)?;

let setup = KernelSetup {
let mut setup = KernelSetup {
instructions: vec![
// Instruction {
// set: Set {
Expand All @@ -66,6 +66,21 @@ fn real_setup() -> std::result::Result<KernelSetup, Box<dyn std::error::Error>>
},
],
};

let config = DsnConfig {
epoch: 0,
authorities
};

for digest in config.genesis() {
setup.instructions.push(Instruction {
set: Set {
value: hex::encode(&(0u64.to_be_bytes())),
to: format!("/certificates/{}", hex::encode(&digest)),
},
});
}

Ok(setup)
}

Expand Down
Loading

0 comments on commit 18dec75

Please sign in to comment.