use crate::{state_transition, Adb};
use battleware_types::{
api::Summary,
execution::{Output, Progress, Seed, Transaction, Value},
Identity, NAMESPACE,
};
use commonware_consensus::{
aggregation::types::{Ack, Certificate, Item},
simplex::types::view_message,
threshold_simplex::types::seed_namespace,
};
use commonware_cryptography::{
bls12381::primitives::{
group::{Private, Share},
ops,
variant::{MinSig, Variant},
},
ed25519::{PrivateKey, PublicKey},
sha256::{Digest, Sha256},
Digestible, Hasher, PrivateKeyExt, Signer,
};
#[cfg(feature = "parallel")]
use commonware_runtime::ThreadPool;
use commonware_runtime::{buffer::PoolRef, Clock, Metrics, Spawner, Storage};
use commonware_storage::{
adb::{self, keyless},
translator::EightCap,
};
use commonware_utils::{NZUsize, NZU64};
use rand::{rngs::StdRng, SeedableRng};
pub fn create_network_keypair() -> (Private, <MinSig as Variant>::Public) {
let mut rng = StdRng::seed_from_u64(0);
ops::keypair::<_, MinSig>(&mut rng)
}
pub fn create_account_keypair(seed: u64) -> (PrivateKey, PublicKey) {
let mut rng = StdRng::seed_from_u64(seed);
let private = PrivateKey::from_rng(&mut rng);
let public = private.public_key();
(private, public)
}
pub fn create_seed(network_secret: &Private, view: u64) -> Seed {
let seed_namespace = seed_namespace(NAMESPACE);
let message = view_message(view);
Seed::new(
view,
ops::sign_message::<MinSig>(network_secret, Some(&seed_namespace), &message),
)
}
pub async fn create_adbs<E: Spawner + Metrics + Storage + Clock>(
context: &E,
) -> (Adb<E, EightCap>, keyless::Keyless<E, Output, Sha256>) {
let buffer_pool = PoolRef::new(NZUsize!(1024), NZUsize!(1024));
let state = Adb::init(
context.with_label("state"),
adb::any::variable::Config {
mmr_journal_partition: String::from("state-mmr-journal"),
mmr_metadata_partition: String::from("state-mmr-metadata"),
mmr_items_per_blob: NZU64!(1024),
mmr_write_buffer: NZUsize!(1024),
log_journal_partition: String::from("state-log-journal"),
log_items_per_section: NZU64!(1024),
log_write_buffer: NZUsize!(1024),
log_compression: None,
log_codec_config: (),
locations_journal_partition: String::from("state-locations-journal"),
locations_items_per_blob: NZU64!(1024),
translator: EightCap,
thread_pool: None,
buffer_pool: buffer_pool.clone(),
},
)
.await
.expect("Failed to initialize state ADB");
let events = keyless::Keyless::<_, Output, Sha256>::init(
context.with_label("events"),
keyless::Config {
mmr_journal_partition: String::from("events-mmr-journal"),
mmr_metadata_partition: String::from("events-mmr-metadata"),
mmr_items_per_blob: NZU64!(1024),
mmr_write_buffer: NZUsize!(1024),
log_journal_partition: String::from("events-log-journal"),
log_items_per_section: NZU64!(1024),
log_write_buffer: NZUsize!(1024),
log_compression: None,
log_codec_config: (),
locations_journal_partition: String::from("events-locations-journal"),
locations_items_per_blob: NZU64!(1024),
locations_write_buffer: NZUsize!(1024),
thread_pool: None,
buffer_pool,
},
)
.await
.expect("Failed to initialize events Keyless");
(state, events)
}
pub async fn execute_block<E: Spawner + Metrics + Storage + Clock>(
network_secret: &Private,
network_identity: Identity,
state: &mut Adb<E, EightCap>,
events: &mut keyless::Keyless<E, Output, Sha256>,
view: u64,
txs: Vec<Transaction>,
) -> (Seed, Summary) {
let current_height = state
.get_metadata()
.await
.unwrap()
.and_then(|(_, v)| match v {
Some(Value::Commit { height, start: _ }) => Some(height),
_ => None,
})
.unwrap_or(0);
let height = current_height + 1;
let seed = create_seed(network_secret, view);
#[cfg(feature = "parallel")]
let pool = ThreadPool::new(
rayon::ThreadPoolBuilder::new()
.num_threads(1)
.build()
.expect("failed to create execution pool"),
);
let result = state_transition::execute_state_transition(
state,
events,
network_identity,
height,
seed.clone(),
txs,
#[cfg(feature = "parallel")]
pool,
)
.await;
state.sync().await.unwrap();
events.sync().await.unwrap();
let state_proof_ops = result.state_end_op - result.state_start_op;
let (state_proof, state_proof_ops) = state
.historical_proof(result.state_end_op, result.state_start_op, state_proof_ops)
.await
.unwrap();
let events_proof_ops = result.events_end_op - result.events_start_op;
let (events_proof, events_proof_ops) = events
.historical_proof(
result.events_end_op,
result.events_start_op,
NZU64!(events_proof_ops),
)
.await
.unwrap();
let progress = Progress::new(
view,
height,
Sha256::hash(&height.to_be_bytes()),
result.state_root,
result.state_start_op,
result.state_end_op,
result.events_root,
result.events_start_op,
result.events_end_op,
);
let item = Item {
index: height,
digest: progress.digest(),
};
let ack = Ack::<MinSig, Digest>::sign(
NAMESPACE,
0,
&Share {
index: 0,
private: network_secret.clone(),
},
item.clone(),
);
let certificate = Certificate::<MinSig, Digest> {
item,
signature: ack.signature.value,
};
(
seed,
Summary {
progress,
certificate,
state_proof,
state_proof_ops,
events_proof,
events_proof_ops,
},
)
}