diff --git a/config/ValidatorConfigOutput b/config/ValidatorConfigOutput index 79d47d567e..65aa85fbd7 100644 --- a/config/ValidatorConfigOutput +++ b/config/ValidatorConfigOutput @@ -1 +1 @@ -ValidatorConfig { public_key: BLSPubKey { pub_key: VerKey((QuadExtField(2264797523581107490935262917175769123227923636811928330606075281145117212394 + 15807017392833049888165434456991157794698032464874424842715555348468160607934 * u), QuadExtField(7996517616082121122160563552650547601395271017260499735456299700133762512689 + 7504045709281061282278228438613345070383424761478787301859187055302953740948 * u), QuadExtField(1515973040548822760825076242090160370742046237881440422068330135941139244581 + 20251846261653098602911417004145145971080304248810966341160788194007704966108 * u))) }, private_key: BLSPrivKey { priv_key: SignKey(BigInt([3505488234151006356, 6655477166151225138, 3291219027844407676, 2153641080015542578])) }, stake_value: 1, state_key_pair: StateKeyPair(KeyPair { sk: SignKey(BigInt([2822822805887490846, 6664316196088353173, 4926510007447087464, 116097479308258694])), vk: VerKey(Projective { x: BigInt([11315198235793138814, 4744451806709910489, 6921831025042192557, 1125393823825936625]), y: BigInt([13035879815613524256, 18225673961538637854, 12006860967936477969, 1516668567229692859]), t: BigInt([13450777528397789701, 12242009376162249168, 12596256366242272750, 3368076418495976469]), z: BigInt([10465708325245823445, 13967918689717629445, 14943426723808572731, 621075342718756551]) }) }) } \ No newline at end of file +ValidatorConfig { public_key: BLSPubKey { pub_key: VerKey((QuadExtField(2264797523581107490935262917175769123227923636811928330606075281145117212394 + 15807017392833049888165434456991157794698032464874424842715555348468160607934 * u), QuadExtField(7996517616082121122160563552650547601395271017260499735456299700133762512689 + 7504045709281061282278228438613345070383424761478787301859187055302953740948 * u), QuadExtField(1515973040548822760825076242090160370742046237881440422068330135941139244581 + 20251846261653098602911417004145145971080304248810966341160788194007704966108 * u))) }, private_key: BLSPrivKey { priv_key: SignKey(BigInt([3505488234151006356, 6655477166151225138, 3291219027844407676, 2153641080015542578])) }, stake_value: 1 } \ No newline at end of file diff --git a/crates/hotshot/Cargo.toml b/crates/hotshot/Cargo.toml index 612872f976..49af631ee4 100644 --- a/crates/hotshot/Cargo.toml +++ b/crates/hotshot/Cargo.toml @@ -21,74 +21,60 @@ hotshot-testing = [] # libp2p [[example]] name = "validator-libp2p" -required-features = ["libp2p/rsa"] path = "examples/libp2p/validator.rs" [[example]] name = "multi-validator-libp2p" -required-features = ["libp2p/rsa"] path = "examples/libp2p/multi-validator.rs" [[example]] name = "orchestrator-libp2p" -required-features = ["libp2p/rsa"] path = "examples/libp2p/orchestrator.rs" [[example]] name = "all-libp2p" -required-features = ["libp2p/rsa"] path = "examples/libp2p/all.rs" # webserver [[example]] name = "webserver" -required-features = ["libp2p/rsa"] path = "examples/webserver/webserver.rs" [[example]] name = "orchestrator-webserver" -required-features = ["libp2p/rsa"] path = "examples/webserver/orchestrator.rs" [[example]] name = "validator-webserver" -required-features = ["libp2p/rsa"] path = "examples/webserver/validator.rs" [[example]] name = "multi-validator-webserver" -required-features = ["libp2p/rsa"] path = "examples/webserver/multi-validator.rs" [[example]] name = "multi-webserver" -required-features = ["libp2p/rsa"] path = "examples/webserver/multi-webserver.rs" [[example]] name = "all-webserver" -required-features = ["libp2p/rsa"] path = "examples/webserver/all.rs" # combined [[example]] name = "all-combined" -required-features = ["libp2p/rsa"] path = "examples/combined/all.rs" [[example]] name = "multi-validator-combined" -required-features = ["libp2p/rsa"] path = "examples/combined/multi-validator.rs" [[example]] name = "validator-combined" -required-features = ["libp2p/rsa"] path = "examples/combined/validator.rs" [[example]] name = "orchestrator-combined" -required-features = ["libp2p/rsa"] path = "examples/combined/orchestrator.rs" [dependencies] diff --git a/crates/hotshot/examples/combined/multi-validator.rs b/crates/hotshot/examples/combined/multi-validator.rs index 9ef67056f5..5b550caf22 100644 --- a/crates/hotshot/examples/combined/multi-validator.rs +++ b/crates/hotshot/examples/combined/multi-validator.rs @@ -41,7 +41,7 @@ async fn main() { tracing::error!("connecting to orchestrator at {:?}", args.url); let mut nodes = Vec::new(); for _ in 0..args.num_nodes { - let url: String = args.url.clone(); + let url = args.url.clone(); let node = async_spawn(async move { infra::main_entry_point::< diff --git a/crates/hotshot/examples/infra/mod.rs b/crates/hotshot/examples/infra/mod.rs index 26d919fc0c..9243eb9cef 100644 --- a/crates/hotshot/examples/infra/mod.rs +++ b/crates/hotshot/examples/infra/mod.rs @@ -153,9 +153,9 @@ async fn webserver_network_from_config( let WebServerConfig { url, wait_between_polls, - }: WebServerConfig = config.clone().web_server_config.unwrap(); + }: WebServerConfig = config.web_server_config.unwrap(); - WebServerNetwork::create(url, wait_between_polls, pub_key.clone(), false) + WebServerNetwork::create(url, wait_between_polls, pub_key, false) } async fn libp2p_network_from_config( diff --git a/crates/hotshot/examples/libp2p/multi-validator.rs b/crates/hotshot/examples/libp2p/multi-validator.rs index bf0fbe95a8..9fb1199b88 100644 --- a/crates/hotshot/examples/libp2p/multi-validator.rs +++ b/crates/hotshot/examples/libp2p/multi-validator.rs @@ -41,7 +41,7 @@ async fn main() { tracing::error!("connecting to orchestrator at {:?}", args.url); let mut nodes = Vec::new(); for _ in 0..args.num_nodes { - let url: String = args.url.clone(); + let url = args.url.clone(); let node = async_spawn(async move { infra::main_entry_point::< diff --git a/crates/hotshot/src/tasks/mod.rs b/crates/hotshot/src/tasks/mod.rs index 50cd306e86..95679ab3d5 100644 --- a/crates/hotshot/src/tasks/mod.rs +++ b/crates/hotshot/src/tasks/mod.rs @@ -23,6 +23,7 @@ use hotshot_task_impls::{ vid::{VIDTaskState, VIDTaskTypes}, view_sync::{ViewSyncTaskState, ViewSyncTaskStateTypes}, }; +use hotshot_types::traits::election::Membership; use hotshot_types::{ event::Event, message::Messages, @@ -206,7 +207,15 @@ pub async fn add_consensus_task>( let registry = task_runner.registry.clone(); let (payload, metadata) = ::genesis(); // Impossible for `unwrap` to fail on the genesis payload. - let payload_commitment = vid_commitment(&payload.encode().unwrap().collect()); + let payload_commitment = vid_commitment( + &payload.encode().unwrap().collect(), + handle + .hotshot + .inner + .memberships + .quorum_membership + .total_nodes(), + ); // build the consensus task let consensus_state = ConsensusTaskState { registry: registry.clone(), @@ -353,6 +362,7 @@ pub async fn add_da_task>( consensus: handle.hotshot.get_consensus(), da_membership: c_api.inner.memberships.da_membership.clone().into(), da_network: c_api.inner.networks.da_network.clone().into(), + quorum_membership: c_api.inner.memberships.quorum_membership.clone().into(), cur_view: TYPES::Time::new(0), vote_collector: None, event_stream: event_stream.clone(), diff --git a/crates/hotshot/src/traits/storage/memory_storage.rs b/crates/hotshot/src/traits/storage/memory_storage.rs index 5b7ddfd25e..94ffdef83d 100644 --- a/crates/hotshot/src/traits/storage/memory_storage.rs +++ b/crates/hotshot/src/traits/storage/memory_storage.rs @@ -117,7 +117,10 @@ mod test { use hotshot_types::{ data::{fake_commitment, genesis_proposer_id, Leaf}, simple_certificate::QuorumCertificate, - traits::{node_implementation::NodeType, state::ConsensusTime}, + traits::{ + block_contents::genesis_vid_commitment, node_implementation::NodeType, + state::ConsensusTime, + }, }; use std::marker::PhantomData; use tracing::instrument; @@ -126,7 +129,7 @@ mod test { let payload = TestBlockPayload::genesis(); let header = TestBlockHeader { block_number: 0, - payload_commitment: payload.payload_commitment, + payload_commitment: genesis_vid_commitment(), }; let dummy_leaf_commit = fake_commitment::>(); let data = hotshot_types::simple_vote::QuorumData { diff --git a/crates/task-impls/src/consensus.rs b/crates/task-impls/src/consensus.rs index e90ffac24f..04e13f9c65 100644 --- a/crates/task-impls/src/consensus.rs +++ b/crates/task-impls/src/consensus.rs @@ -618,12 +618,8 @@ impl, A: ConsensusApi + encoded_txns.clone().into_iter(), leaf.get_block_header().metadata(), ); - if let Err(e) = leaf.fill_block_payload(payload) { - error!( - "Saved block payload and commitment don't match: {:?}", - e - ); - } + + leaf.fill_block_payload_unchecked(payload); } leaf_views.push(leaf.clone()); diff --git a/crates/task-impls/src/da.rs b/crates/task-impls/src/da.rs index dce9a470c2..cbf438484b 100644 --- a/crates/task-impls/src/da.rs +++ b/crates/task-impls/src/da.rs @@ -57,6 +57,11 @@ pub struct DATaskState< /// Membership for the DA committee pub da_membership: Arc, + /// Membership for the quorum committee + /// We need this only for calculating the proper VID scheme + /// from the number of nodes in the quorum. + pub quorum_membership: Arc, + /// Network for DA pub da_network: Arc, @@ -113,7 +118,10 @@ impl, A: ConsensusApi + return None; } - let payload_commitment = vid_commitment(&proposal.data.encoded_transactions); + let payload_commitment = vid_commitment( + &proposal.data.encoded_transactions, + self.quorum_membership.total_nodes(), + ); let encoded_transactions_hash = Sha256::digest(&proposal.data.encoded_transactions); // ED Is this the right leader? diff --git a/crates/task-impls/src/events.rs b/crates/task-impls/src/events.rs index 08d61bbe76..9409b34067 100644 --- a/crates/task-impls/src/events.rs +++ b/crates/task-impls/src/events.rs @@ -92,7 +92,7 @@ pub enum HotShotEvent { VidCommitment, ::Metadata, ), - /// Event when the transactions task has sequenced transactions. Contains the encoded transactions + /// Event when the transactions task has sequenced transactions. Contains the encoded transactions, the metadata, and the view number TransactionsSequenced( Vec, ::Metadata, diff --git a/crates/task-impls/src/network.rs b/crates/task-impls/src/network.rs index a88da8b3ac..cdef8af4d2 100644 --- a/crates/task-impls/src/network.rs +++ b/crates/task-impls/src/network.rs @@ -56,7 +56,7 @@ impl NetworkMessageTaskState { let event = match consensus_message.0 { Either::Left(general_message) => match general_message { GeneralConsensusMessage::Proposal(proposal) => { - HotShotEvent::QuorumProposalRecv(proposal.clone(), sender) + HotShotEvent::QuorumProposalRecv(proposal, sender) } GeneralConsensusMessage::Vote(vote) => { HotShotEvent::QuorumVoteRecv(vote.clone()) @@ -92,7 +92,7 @@ impl NetworkMessageTaskState { }, Either::Right(committee_message) => match committee_message { CommitteeConsensusMessage::DAProposal(proposal) => { - HotShotEvent::DAProposalRecv(proposal.clone(), sender) + HotShotEvent::DAProposalRecv(proposal, sender) } CommitteeConsensusMessage::DAVote(vote) => { HotShotEvent::DAVoteRecv(vote.clone()) @@ -236,7 +236,7 @@ impl> HotShotEvent::ViewSyncPreCommitCertificate2Send(certificate, sender) => ( sender, MessageKind::::from_consensus_message(SequencingMessage(Left( - GeneralConsensusMessage::ViewSyncPreCommitCertificate(certificate.clone()), + GeneralConsensusMessage::ViewSyncPreCommitCertificate(certificate), ))), TransmitType::Broadcast, None, diff --git a/crates/task-impls/src/vid.rs b/crates/task-impls/src/vid.rs index 9118c9082a..8e72414743 100644 --- a/crates/task-impls/src/vid.rs +++ b/crates/task-impls/src/vid.rs @@ -20,10 +20,7 @@ use hotshot_types::{ }; use hotshot_types::{ data::{test_srs, VidScheme, VidSchemeTrait}, - traits::{ - block_contents::{NUM_CHUNKS, NUM_STORAGE_NODES}, - network::ConsensusIntentEvent, - }, + traits::network::ConsensusIntentEvent, }; use hotshot_task::event_stream::EventStream; @@ -54,7 +51,7 @@ pub struct VIDTaskState< pub consensus: Arc>>, /// Network for all nodes pub network: Arc, - /// Membership for teh quorum + /// Membership for the quorum pub membership: Arc, /// This Nodes Public Key pub public_key: TYPES::SignatureKey, @@ -81,12 +78,19 @@ impl, A: ConsensusApi + ) -> Option { match event { HotShotEvent::TransactionsSequenced(encoded_transactions, metadata, view_number) => { + // get the number of quorum committee members to be used for VID calculation + let num_quorum_committee = self.membership.total_nodes(); + // TODO - let srs = test_srs(NUM_STORAGE_NODES); - // TODO We are using constant numbers for now, but they will change as the quorum size - // changes. - // TODO - let vid = VidScheme::new(NUM_CHUNKS, NUM_STORAGE_NODES, &srs).unwrap(); + let srs = test_srs(num_quorum_committee); + + // calculate the last power of two + // TODO change after https://github.com/EspressoSystems/jellyfish/issues/339 + // issue: https://github.com/EspressoSystems/HotShot/issues/2152 + let chunk_size = 1 << num_quorum_committee.ilog2(); + + // calculate vid shares + let vid = VidScheme::new(chunk_size, num_quorum_committee, &srs).unwrap(); let vid_disperse = vid.disperse(encoded_transactions.clone()).unwrap(); // send the commitment and metadata to consensus for block building @@ -100,12 +104,7 @@ impl, A: ConsensusApi + // send the block to the VID dispersal function self.event_stream .publish(HotShotEvent::BlockReady( - VidDisperse { - view_number, - payload_commitment: vid_disperse.commit, - shares: vid_disperse.shares, - common: vid_disperse.common, - }, + VidDisperse::from_membership(view_number, vid_disperse, &self.membership), view_number, )) .await; diff --git a/crates/testing/src/block_types.rs b/crates/testing/src/block_types.rs index a49e93c5ed..39fa591795 100644 --- a/crates/testing/src/block_types.rs +++ b/crates/testing/src/block_types.rs @@ -5,9 +5,9 @@ use std::{ use commit::{Commitment, Committable, RawCommitmentBuilder}; use hotshot_types::{ - data::{BlockError, VidCommitment, VidScheme, VidSchemeTrait}, + data::{BlockError, VidCommitment}, traits::{ - block_contents::{vid_commitment, BlockHeader, Transaction}, + block_contents::{genesis_vid_commitment, BlockHeader, Transaction}, state::TestableBlock, BlockPayload, }, @@ -67,8 +67,6 @@ impl Transaction for TestTransaction {} pub struct TestBlockPayload { /// List of transactions. pub transactions: Vec, - /// VID commitment to the block payload. - pub payload_commitment: ::Commit, } impl TestBlockPayload { @@ -80,10 +78,8 @@ impl TestBlockPayload { pub fn genesis() -> Self { let txns: Vec = vec![0]; // It's impossible for `encode` to fail because the transaciton length is very small. - let encoded = TestTransaction::encode(vec![TestTransaction(txns.clone())]).unwrap(); TestBlockPayload { transactions: vec![TestTransaction(txns)], - payload_commitment: vid_commitment(&encoded), } } } @@ -114,11 +110,9 @@ impl BlockPayload for TestBlockPayload { transactions: impl IntoIterator, ) -> Result<(Self, Self::Metadata), Self::Error> { let txns_vec: Vec = transactions.into_iter().collect(); - let encoded = TestTransaction::encode(txns_vec.clone())?; Ok(( Self { transactions: txns_vec, - payload_commitment: vid_commitment(&encoded), }, (), )) @@ -146,10 +140,7 @@ impl BlockPayload for TestBlockPayload { current_index = next_index; } - Self { - transactions, - payload_commitment: vid_commitment(&encoded_vec), - } + Self { transactions } } fn genesis() -> (Self, Self::Metadata) { @@ -200,7 +191,7 @@ impl BlockHeader for TestBlockHeader { ( Self { block_number: 0, - payload_commitment: payload.payload_commitment, + payload_commitment: genesis_vid_commitment(), }, payload, metadata, diff --git a/crates/testing/src/task_helpers.rs b/crates/testing/src/task_helpers.rs index e4a66fdcc1..dc7a3b43d0 100644 --- a/crates/testing/src/task_helpers.rs +++ b/crates/testing/src/task_helpers.rs @@ -18,8 +18,8 @@ use hotshot_types::{ message::Proposal, simple_certificate::QuorumCertificate, traits::{ + block_contents::vid_commitment, block_contents::BlockHeader, - block_contents::{vid_commitment, NUM_CHUNKS, NUM_STORAGE_NODES}, consensus_api::ConsensusSharedApi, election::Membership, node_implementation::NodeType, @@ -126,7 +126,15 @@ async fn build_quorum_proposal_and_signature( // every event input is seen on the event stream in the output. let block = ::genesis(); - let payload_commitment = vid_commitment(&block.encode().unwrap().collect()); + let payload_commitment = vid_commitment( + &block.encode().unwrap().collect(), + handle + .hotshot + .inner + .memberships + .quorum_membership + .total_nodes(), + ); let block_header = TestBlockHeader::new(payload_commitment, (), &parent_leaf.block_header); let leaf = Leaf { view_number: ViewNumber::new(view), @@ -171,7 +179,19 @@ pub fn key_pair_for_id(node_id: u64) -> (::PrivateKey (private_key, public_key) } -pub fn vid_init() -> VidScheme { - let srs = hotshot_types::data::test_srs(NUM_STORAGE_NODES); - VidScheme::new(NUM_CHUNKS, NUM_STORAGE_NODES, srs).unwrap() +pub fn vid_init( + membership: TYPES::Membership, + view_number: TYPES::Time, +) -> VidScheme { + let num_committee = membership.get_committee(view_number).len(); + + // calculate the last power of two + // TODO change after https://github.com/EspressoSystems/jellyfish/issues/339 + // issue: https://github.com/EspressoSystems/HotShot/issues/2152 + let chunk_size = 1 << num_committee.ilog2(); + + // TODO + let srs = hotshot_types::data::test_srs(num_committee); + + VidScheme::new(chunk_size, num_committee, srs).unwrap() } diff --git a/crates/testing/src/test_builder.rs b/crates/testing/src/test_builder.rs index d3734bfcb3..4e59dc75d1 100644 --- a/crates/testing/src/test_builder.rs +++ b/crates/testing/src/test_builder.rs @@ -137,7 +137,7 @@ impl TestMetadata { completion_task_description: CompletionTaskDescription::TimeBasedCompletionTaskBuilder( TimeBasedCompletionTaskDescription { // Increase the duration to get the expected number of successful views. - duration: Duration::new(300, 0), + duration: Duration::new(340, 0), }, ), overall_safety_properties: OverallSafetyPropertiesDescription { diff --git a/crates/testing/tests/da_task.rs b/crates/testing/tests/da_task.rs index 81e01425eb..4e786713fd 100644 --- a/crates/testing/tests/da_task.rs +++ b/crates/testing/tests/da_task.rs @@ -8,7 +8,7 @@ use hotshot_types::{ data::{DAProposal, ViewNumber}, simple_vote::{DAData, DAVote}, traits::{ - block_contents::vid_commitment, consensus_api::ConsensusSharedApi, + block_contents::vid_commitment, consensus_api::ConsensusSharedApi, election::Membership, node_implementation::NodeType, state::ConsensusTime, }, }; @@ -37,7 +37,15 @@ async fn test_da_task() { let pub_key = *api.public_key(); let transactions = vec![TestTransaction(vec![0])]; let encoded_transactions = TestTransaction::encode(transactions.clone()).unwrap(); - let payload_commitment = vid_commitment(&encoded_transactions); + let payload_commitment = vid_commitment( + &encoded_transactions, + handle + .hotshot + .inner + .memberships + .quorum_membership + .total_nodes(), + ); let encoded_transactions_hash = Sha256::digest(&encoded_transactions); let signature = diff --git a/crates/testing/tests/network_task.rs b/crates/testing/tests/network_task.rs index 02188d0bea..4252ffb770 100644 --- a/crates/testing/tests/network_task.rs +++ b/crates/testing/tests/network_task.rs @@ -32,7 +32,10 @@ async fn test_network_task() { }; let pub_key = *api.public_key(); let priv_key = api.private_key(); - let vid = vid_init(); + // quorum membership for VID share distribution + let quorum_membership = handle.hotshot.inner.memberships.quorum_membership.clone(); + + let vid = vid_init::(quorum_membership.clone(), ViewNumber::new(0)); let transactions = vec![TestTransaction(vec![0])]; let encoded_transactions = TestTransaction::encode(transactions.clone()).unwrap(); let vid_disperse = vid.disperse(&encoded_transactions).unwrap(); @@ -53,12 +56,12 @@ async fn test_network_task() { }; let quorum_proposal = build_quorum_proposal(&handle, priv_key, 2).await; - let da_vid_disperse_inner = VidDisperse { - view_number: da_proposal.data.view_number, - payload_commitment, - shares: vid_disperse.shares, - common: vid_disperse.common, - }; + let da_vid_disperse_inner = VidDisperse::from_membership( + da_proposal.data.view_number, + vid_disperse, + &quorum_membership.clone().into(), + ); + // TODO for now reuse the same block payload commitment and signature as DA committee // https://github.com/EspressoSystems/jellyfish/issues/369 let da_vid_disperse = Proposal { diff --git a/crates/testing/tests/vid_task.rs b/crates/testing/tests/vid_task.rs index 1c224db08d..8757a3d414 100644 --- a/crates/testing/tests/vid_task.rs +++ b/crates/testing/tests/vid_task.rs @@ -33,7 +33,10 @@ async fn test_vid_task() { }; let pub_key = *api.public_key(); - let vid = vid_init(); + // quorum membership for VID share distribution + let quorum_membership = handle.hotshot.inner.memberships.quorum_membership.clone(); + + let vid = vid_init::(quorum_membership.clone(), ViewNumber::new(0)); let transactions = vec![TestTransaction(vec![0])]; let encoded_transactions = TestTransaction::encode(transactions.clone()).unwrap(); let vid_disperse = vid.disperse(&encoded_transactions).unwrap(); @@ -51,12 +54,13 @@ async fn test_vid_task() { signature, _pd: PhantomData, }; - let vid_disperse = VidDisperse { - view_number: message.data.view_number, - payload_commitment, - shares: vid_disperse.shares, - common: vid_disperse.common, - }; + + let vid_disperse = VidDisperse::from_membership( + message.data.view_number, + vid_disperse, + &quorum_membership.clone().into(), + ); + let vid_proposal = Proposal { data: vid_disperse.clone(), signature: message.signature.clone(), diff --git a/crates/types/src/data.rs b/crates/types/src/data.rs index 71a6170df8..fc8797f0db 100644 --- a/crates/types/src/data.rs +++ b/crates/types/src/data.rs @@ -8,6 +8,7 @@ use crate::{ traits::{ block_contents::vid_commitment, block_contents::BlockHeader, + election::Membership, node_implementation::NodeType, signature_key::{EncodedPublicKey, SignatureKey}, state::{ConsensusTime, TestableBlock, TestableState}, @@ -23,14 +24,18 @@ use commit::{Commitment, Committable, RawCommitmentBuilder}; use derivative::Derivative; use hotshot_constants::GENESIS_PROPOSER_ID; use hotshot_utils::bincode::bincode_opts; -// use jf_primitives::pcs::prelude::Commitment; -use jf_primitives::pcs::{checked_fft_size, prelude::UnivariateKzgPCS, PolynomialCommitmentScheme}; +use jf_primitives::{ + pcs::{checked_fft_size, prelude::UnivariateKzgPCS, PolynomialCommitmentScheme}, + vid::VidDisperse as JfVidDisperse, +}; use rand::Rng; use serde::{Deserialize, Serialize}; use snafu::Snafu; use std::{ + collections::BTreeMap, fmt::{Debug, Display}, hash::Hash, + sync::Arc, }; /// Type-safe wrapper around `u64` so we know the thing we're talking about is a view number. @@ -138,12 +143,36 @@ pub struct VidDisperse { pub view_number: TYPES::Time, /// Block payload commitment pub payload_commitment: VidCommitment, - /// VID shares dispersed among storage nodes - pub shares: Vec<::Share>, + /// A storage node's key and its corresponding VID share + pub shares: BTreeMap::Share>, /// VID common data sent to all storage nodes pub common: ::Common, } +impl VidDisperse { + /// Create VID dispersal from a specified membership + /// Uses the specified function to calculate share dispersal + /// Allows for more complex stake table functionality + pub fn from_membership( + view_number: TYPES::Time, + mut vid_disperse: JfVidDisperse, + membership: &Arc, + ) -> Self { + let shares = membership + .get_committee(view_number) + .iter() + .map(|node| (node.clone(), vid_disperse.shares.remove(0))) + .collect(); + + Self { + view_number, + shares, + common: vid_disperse.common, + payload_commitment: vid_disperse.commit, + } + } +} + /// Trusted KZG setup for VID. /// /// TESTING ONLY: don't use this in production @@ -370,10 +399,12 @@ impl Leaf { /// /// # Errors /// - /// Fails if the payload commitment doesn't match `self.block_header.payload_commitment()`. + /// Fails if the payload commitment doesn't match `self.block_header.payload_commitment()` + /// or if the transactions are of invalid length pub fn fill_block_payload( &mut self, block_payload: TYPES::BlockPayload, + num_storage_nodes: usize, ) -> Result<(), BlockError> { let encoded_txns = match block_payload.encode() { // TODO (Keyao) [VALIDATED_STATE] - Avoid collect/copy on the encoded transaction bytes. @@ -381,13 +412,20 @@ impl Leaf { Ok(encoded) => encoded.into_iter().collect(), Err(_) => return Err(BlockError::InvalidTransactionLength), }; - let commitment = vid_commitment(&encoded_txns); + let commitment = vid_commitment(&encoded_txns, num_storage_nodes); if commitment != self.block_header.payload_commitment() { return Err(BlockError::InconsistentPayloadCommitment); } self.block_payload = Some(block_payload); Ok(()) } + + /// Fill this leaf with the block payload, without checking + /// header and payload consistency + pub fn fill_block_payload_unchecked(&mut self, block_payload: TYPES::BlockPayload) { + self.block_payload = Some(block_payload); + } + /// Optional block payload. pub fn get_block_payload(&self) -> Option { self.block_payload.clone() diff --git a/crates/types/src/traits/block_contents.rs b/crates/types/src/traits/block_contents.rs index 859bf3e173..c75315fe58 100644 --- a/crates/types/src/traits/block_contents.rs +++ b/crates/types/src/traits/block_contents.rs @@ -59,7 +59,8 @@ pub trait BlockPayload: transactions: impl IntoIterator, ) -> Result<(Self, Self::Metadata), Self::Error>; - /// Build a payload with the encoded transaction bytes and metadata. + /// Build a payload with the encoded transaction bytes, metadata, + /// and the associated number of VID storage nodes /// /// `I` may be, but not necessarily is, the `Encode` type directly from `fn encode`. fn from_bytes(encoded_transactions: I, metadata: Self::Metadata) -> Self @@ -83,16 +84,25 @@ pub trait BlockPayload: /// # Panics /// If the VID computation fails. #[must_use] -pub fn vid_commitment(encoded_transactions: &Vec) -> ::Commit { +pub fn vid_commitment( + encoded_transactions: &Vec, + num_storage_nodes: usize, +) -> ::Commit { + let num_chunks = 1 << num_storage_nodes.ilog2(); + // TODO - let srs = test_srs(NUM_STORAGE_NODES); - // TODO We are using constant numbers for now, but they will change as the quorum size - // changes. - // TODO - let vid = VidScheme::new(NUM_CHUNKS, NUM_STORAGE_NODES, srs).unwrap(); + let srs = test_srs(num_storage_nodes); + + let vid = VidScheme::new(num_chunks, num_storage_nodes, srs).unwrap(); vid.commit_only(encoded_transactions).unwrap() } +/// Computes the (empty) genesis VID commitment +#[must_use] +pub fn genesis_vid_commitment() -> ::Commit { + vid_commitment(&vec![], 8) +} + /// Header of a block, which commits to a [`BlockPayload`]. pub trait BlockHeader: Serialize + Clone + Debug + Hash + PartialEq + Eq + Send + Sync + DeserializeOwned + Committable diff --git a/justfile b/justfile index 69a1d5b3e9..2d706e01a3 100644 --- a/justfile +++ b/justfile @@ -2,8 +2,8 @@ default: run_ci set export -original_rustflags := env_var_or_default('RUSTFLAGS', '') -original_rustdocflags := env_var_or_default('RUSTDOCFLAGS', '') +original_rustflags := env_var_or_default('RUSTFLAGS', '--cfg hotshot_example') +original_rustdocflags := env_var_or_default('RUSTDOCFLAGS', '--cfg hotshot_example') run_ci: lint build test @@ -19,7 +19,7 @@ build: cargo build --workspace --examples --bins --tests --lib --benches example *ARGS: - RUSTFLAGS='--cfg hotshot_example {{original_rustflags}}' cargo run --profile=release-lto --example {{ARGS}} + cargo run --profile=release-lto --example {{ARGS}} test: echo Testing