diff --git a/crates/example-types/src/auction_results_provider_types.rs b/crates/example-types/src/auction_results_provider_types.rs index 87dbdb9374..d363446655 100644 --- a/crates/example-types/src/auction_results_provider_types.rs +++ b/crates/example-types/src/auction_results_provider_types.rs @@ -1,14 +1,14 @@ use anyhow::{bail, Result}; use async_trait::async_trait; use hotshot_types::traits::{ - auction_results_provider::{AuctionResultsProvider, HasUrls}, - node_implementation::NodeType, + auction_results_provider::AuctionResultsProvider, + node_implementation::{HasUrls, NodeType}, }; use serde::{Deserialize, Serialize}; use url::Url; /// A mock result for the auction solver. This type is just a pointer to a URL. -#[derive(Debug, Clone, Serialize, Deserialize, Default)] +#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize, Default)] pub struct TestAuctionResult { /// The URL of the builder to reach out to. pub urls: Vec, @@ -22,10 +22,10 @@ impl HasUrls for TestAuctionResult { /// The test auction results type is used to mimic the results from the Solver. #[derive(Clone, Debug, Default)] -pub struct TestAuctionResultsProvider { +pub struct TestAuctionResultsProvider { /// We intentionally allow for the results to be pre-cooked for the unit test to gurantee a /// particular outcome is met. - pub solver_results: TestAuctionResult, + pub solver_results: TYPES::AuctionResult, /// A canned type to ensure that an error is thrown in absence of a true fault-injectible /// system for logical tests. This will guarantee that `fetch_auction_result` always throws an @@ -39,17 +39,15 @@ pub struct TestAuctionResultsProvider { } #[async_trait] -impl AuctionResultsProvider for TestAuctionResultsProvider { - type AuctionResult = TestAuctionResult; - +impl AuctionResultsProvider for TestAuctionResultsProvider { /// Mock fetching the auction results, with optional error injection to simulate failure cases /// in the solver. - async fn fetch_auction_result(&self, view_number: TYPES::Time) -> Result { + async fn fetch_auction_result(&self, view_number: TYPES::Time) -> Result { if let Some(url) = &self.broadcast_url { let resp = reqwest::get(url.join(&format!("/v0/api/auction_results/{}", *view_number))?) .await? - .json::() + .json::() .await?; Ok(resp) diff --git a/crates/example-types/src/block_types.rs b/crates/example-types/src/block_types.rs index 2820bd0898..0768d956bb 100644 --- a/crates/example-types/src/block_types.rs +++ b/crates/example-types/src/block_types.rs @@ -23,7 +23,6 @@ use time::OffsetDateTime; use vbs::version::Version; use crate::{ - auction_results_provider_types::TestAuctionResult, node_types::TestTypes, state_types::{TestInstanceState, TestValidatedState}, }; @@ -244,7 +243,6 @@ impl> Block for TestBlockHeader { type Error = std::convert::Infallible; - type AuctionResult = TestAuctionResult; async fn new_legacy( _parent_state: &TYPES::ValidatedState, @@ -281,7 +279,7 @@ impl> Block _metadata: >::Metadata, _builder_fee: Vec>, _vid_common: VidCommon, - _auction_results: Option, + _auction_results: Option, _version: Version, ) -> Result { unimplemented!() @@ -317,7 +315,7 @@ impl> Block self.builder_commitment.clone() } - fn get_auction_results(&self) -> Option { + fn get_auction_results(&self) -> Option { unimplemented!() } } diff --git a/crates/example-types/src/node_types.rs b/crates/example-types/src/node_types.rs index 57b031e0ff..13ba83a383 100644 --- a/crates/example-types/src/node_types.rs +++ b/crates/example-types/src/node_types.rs @@ -15,7 +15,7 @@ use serde::{Deserialize, Serialize}; use vbs::version::StaticVersion; use crate::{ - auction_results_provider_types::TestAuctionResultsProvider, + auction_results_provider_types::{TestAuctionResult, TestAuctionResultsProvider}, block_types::{TestBlockHeader, TestBlockPayload, TestTransaction}, state_types::{TestInstanceState, TestValidatedState}, storage_types::TestStorage, @@ -38,6 +38,7 @@ use crate::{ /// to select our traits pub struct TestTypes; impl NodeType for TestTypes { + type AuctionResult = TestAuctionResult; type Base = StaticVersion<0, 1>; type Upgrade = StaticVersion<0, 2>; const UPGRADE_HASH: [u8; 32] = [ @@ -72,6 +73,7 @@ impl NodeType for TestTypes { /// to select our traits pub struct TestConsecutiveLeaderTypes; impl NodeType for TestConsecutiveLeaderTypes { + type AuctionResult = TestAuctionResult; type Base = StaticVersion<0, 1>; type Upgrade = StaticVersion<0, 2>; const UPGRADE_HASH: [u8; 32] = [ @@ -116,23 +118,23 @@ pub type StaticMembership = StaticCommittee; impl NodeImplementation for PushCdnImpl { type Network = PushCdnNetwork; type Storage = TestStorage; - type AuctionResultsProvider = TestAuctionResultsProvider; + type AuctionResultsProvider = TestAuctionResultsProvider; } impl NodeImplementation for MemoryImpl { type Network = MemoryNetwork; type Storage = TestStorage; - type AuctionResultsProvider = TestAuctionResultsProvider; + type AuctionResultsProvider = TestAuctionResultsProvider; } impl NodeImplementation for CombinedImpl { type Network = CombinedNetworks; type Storage = TestStorage; - type AuctionResultsProvider = TestAuctionResultsProvider; + type AuctionResultsProvider = TestAuctionResultsProvider; } impl NodeImplementation for Libp2pImpl { type Network = Libp2pNetwork; type Storage = TestStorage; - type AuctionResultsProvider = TestAuctionResultsProvider; + type AuctionResultsProvider = TestAuctionResultsProvider; } diff --git a/crates/examples/combined/types.rs b/crates/examples/combined/types.rs index f15f4d8891..caf0218621 100644 --- a/crates/examples/combined/types.rs +++ b/crates/examples/combined/types.rs @@ -20,7 +20,7 @@ pub type Network = CombinedNetworks; impl NodeImplementation for NodeImpl { type Network = Network; type Storage = TestStorage; - type AuctionResultsProvider = TestAuctionResultsProvider; + type AuctionResultsProvider = TestAuctionResultsProvider; } /// convenience type alias pub type ThisRun = CombinedDaRun; diff --git a/crates/examples/infra/mod.rs b/crates/examples/infra/mod.rs index 23350e43bf..00c5c320e2 100755 --- a/crates/examples/infra/mod.rs +++ b/crates/examples/infra/mod.rs @@ -339,7 +339,7 @@ pub trait RunDa< TYPES, Network = NETWORK, Storage = TestStorage, - AuctionResultsProvider = TestAuctionResultsProvider, + AuctionResultsProvider = TestAuctionResultsProvider, >, > where ::ValidatedState: TestableState, @@ -406,7 +406,7 @@ pub trait RunDa< initializer, ConsensusMetricsValue::default(), TestStorage::::default(), - TestAuctionResultsProvider::default(), + TestAuctionResultsProvider::::default(), ) .await .expect("Could not init hotshot") @@ -604,7 +604,7 @@ impl< TYPES, Network = PushCdnNetwork, Storage = TestStorage, - AuctionResultsProvider = TestAuctionResultsProvider, + AuctionResultsProvider = TestAuctionResultsProvider, >, > RunDa, NODE> for PushCdnDaRun where @@ -681,7 +681,7 @@ impl< TYPES, Network = Libp2pNetwork, Storage = TestStorage, - AuctionResultsProvider = TestAuctionResultsProvider, + AuctionResultsProvider = TestAuctionResultsProvider, >, > RunDa, NODE> for Libp2pDaRun where @@ -767,7 +767,7 @@ impl< TYPES, Network = CombinedNetworks, Storage = TestStorage, - AuctionResultsProvider = TestAuctionResultsProvider, + AuctionResultsProvider = TestAuctionResultsProvider, >, > RunDa, NODE> for CombinedDaRun where @@ -837,7 +837,7 @@ pub async fn main_entry_point< TYPES, Network = NETWORK, Storage = TestStorage, - AuctionResultsProvider = TestAuctionResultsProvider, + AuctionResultsProvider = TestAuctionResultsProvider, >, RUNDA: RunDa, >( diff --git a/crates/examples/libp2p/types.rs b/crates/examples/libp2p/types.rs index af73237d0b..c3f2c59d2d 100644 --- a/crates/examples/libp2p/types.rs +++ b/crates/examples/libp2p/types.rs @@ -20,7 +20,7 @@ pub type Network = Libp2pNetwork<::SignatureKey>; impl NodeImplementation for NodeImpl { type Network = Network; type Storage = TestStorage; - type AuctionResultsProvider = TestAuctionResultsProvider; + type AuctionResultsProvider = TestAuctionResultsProvider; } /// convenience type alias pub type ThisRun = Libp2pDaRun; diff --git a/crates/examples/push-cdn/types.rs b/crates/examples/push-cdn/types.rs index c9721af3cb..17852a99af 100644 --- a/crates/examples/push-cdn/types.rs +++ b/crates/examples/push-cdn/types.rs @@ -17,7 +17,7 @@ pub type Network = PushCdnNetwork; impl NodeImplementation for NodeImpl { type Network = Network; type Storage = TestStorage; - type AuctionResultsProvider = TestAuctionResultsProvider; + type AuctionResultsProvider = TestAuctionResultsProvider; } /// Convenience type alias diff --git a/crates/hotshot/src/traits/election/static_committee.rs b/crates/hotshot/src/traits/election/static_committee.rs index 3163d3b532..255c446401 100644 --- a/crates/hotshot/src/traits/election/static_committee.rs +++ b/crates/hotshot/src/traits/election/static_committee.rs @@ -1,12 +1,14 @@ use std::{marker::PhantomData, num::NonZeroU64}; use ethereum_types::U256; -use hotshot_types::traits::network::Topic; // use ark_bls12_381::Parameters as Param381; use hotshot_types::traits::signature_key::StakeTableEntryType; use hotshot_types::{ signature_key::BLSPubKey, - traits::{election::Membership, node_implementation::NodeType, signature_key::SignatureKey}, + traits::{ + election::Membership, network::Topic, node_implementation::NodeType, + signature_key::SignatureKey, + }, PeerConfig, }; #[cfg(feature = "randomized-leader-election")] diff --git a/crates/hotshot/src/traits/election/static_committee_leader_two_views.rs b/crates/hotshot/src/traits/election/static_committee_leader_two_views.rs index 882b7565c1..d114a5d904 100644 --- a/crates/hotshot/src/traits/election/static_committee_leader_two_views.rs +++ b/crates/hotshot/src/traits/election/static_committee_leader_two_views.rs @@ -1,12 +1,14 @@ use std::{marker::PhantomData, num::NonZeroU64}; use ethereum_types::U256; -use hotshot_types::traits::network::Topic; // use ark_bls12_381::Parameters as Param381; use hotshot_types::traits::signature_key::StakeTableEntryType; use hotshot_types::{ signature_key::BLSPubKey, - traits::{election::Membership, node_implementation::NodeType, signature_key::SignatureKey}, + traits::{ + election::Membership, network::Topic, node_implementation::NodeType, + signature_key::SignatureKey, + }, PeerConfig, }; use tracing::debug; diff --git a/crates/task-impls/src/consensus/handlers.rs b/crates/task-impls/src/consensus/handlers.rs index c8efa8c84f..c025be9d13 100644 --- a/crates/task-impls/src/consensus/handlers.rs +++ b/crates/task-impls/src/consensus/handlers.rs @@ -14,6 +14,7 @@ use committable::Committable; use futures::FutureExt; use hotshot_types::{ consensus::{CommitmentAndMetadata, OuterConsensus, View}, + constants::MarketplaceVersion, data::{null_block, Leaf, QuorumProposal, ViewChangeEvidence}, event::{Event, EventType}, message::{GeneralConsensusMessage, Proposal}, @@ -33,7 +34,7 @@ use hotshot_types::{ #[cfg(async_executor_impl = "tokio")] use tokio::task::JoinHandle; use tracing::{debug, error, info, instrument, warn}; -use vbs::version::Version; +use vbs::version::{StaticVersionType, Version}; use super::ConsensusTaskState; use crate::{ @@ -64,37 +65,46 @@ pub async fn create_and_send_proposal( instance_state: Arc, version: Version, id: u64, -) { +) -> Result<()> { let consensus_read = consensus.read().await; - let Some(Some(vid_share)) = consensus_read + let vid_share = consensus_read .vid_shares() .get(&view) .map(|shares| shares.get(&public_key).cloned()) - else { - error!("Cannot propopse without our VID share, view {:?}", view); - return; - }; - // TODO ED: This will need to be version-gated to use the appropriate `BlockHeader::new` function. - // Pre-marketplace versions will use `new_legacy` and post-marketplace versions will use `new_marketplace` + .context(format!( + "Cannot propopse without our VID share, view {view:?}" + ))? + .context("Failed to get vid share")?; drop(consensus_read); - let block_header = match TYPES::BlockHeader::new_legacy( - state.as_ref(), - instance_state.as_ref(), - &parent_leaf, - commitment_and_metadata.commitment, - commitment_and_metadata.builder_commitment, - commitment_and_metadata.metadata, - commitment_and_metadata.fee, - vid_share.data.common, - version, - ) - .await - { - Ok(header) => header, - Err(err) => { - error!(%err, "Failed to construct block header"); - return; - } + + let block_header = if version < MarketplaceVersion::VERSION { + TYPES::BlockHeader::new_legacy( + state.as_ref(), + instance_state.as_ref(), + &parent_leaf, + commitment_and_metadata.commitment, + commitment_and_metadata.builder_commitment, + commitment_and_metadata.metadata, + commitment_and_metadata.fees.first().clone(), + vid_share.data.common, + version, + ) + .await + .context("Failed to construct legacy block header")? + } else { + TYPES::BlockHeader::new_marketplace( + state.as_ref(), + instance_state.as_ref(), + &parent_leaf, + commitment_and_metadata.commitment, + commitment_and_metadata.metadata, + commitment_and_metadata.fees.to_vec(), + vid_share.data.common, + commitment_and_metadata.auction_result, + version, + ) + .await + .context("Failed to construct marketplace block header")? }; let proposal = QuorumProposal { @@ -106,35 +116,29 @@ pub async fn create_and_send_proposal( }; let proposed_leaf = Leaf::from_quorum_proposal(&proposal); - if proposed_leaf.parent_commitment() != parent_leaf.commit() { - return; - } - let Ok(signature) = TYPES::SignatureKey::sign(&private_key, proposed_leaf.commit().as_ref()) - else { - // This should never happen. - error!("Failed to sign proposed_leaf.commit()!"); - return; - }; + ensure!(proposed_leaf.parent_commitment() == parent_leaf.commit()); + + let signature = TYPES::SignatureKey::sign(&private_key, proposed_leaf.commit().as_ref())?; let message = Proposal { data: proposal, signature, _pd: PhantomData, }; + debug!( - "Sending null proposal for view {:?}", + "Sending proposal for view {:?}", proposed_leaf.view_number(), ); - if let Err(e) = consensus + + consensus .write() .await - .update_last_proposed_view(message.clone()) - { - tracing::trace!("{e:?}"); - return; - } + .update_last_proposed_view(message.clone())?; + async_sleep(Duration::from_millis(round_start_delay)).await; + broadcast_event( Arc::new(HotShotEvent::QuorumProposalSend( message.clone(), @@ -143,6 +147,8 @@ pub async fn create_and_send_proposal( &event_stream, ) .await; + + Ok(()) } /// Send a proposal for the view `view` from the latest high_qc given an upgrade cert. This is the @@ -213,7 +219,7 @@ pub async fn publish_proposal_from_commitment_and_metadata( let version = version(view, &decided_upgrade_certificate.read().await.clone())?; let create_and_send_proposal_handle = async_spawn(async move { - create_and_send_proposal( + match create_and_send_proposal( public_key, private_key, OuterConsensus::new(Arc::clone(&consensus.inner_consensus)), @@ -229,7 +235,13 @@ pub async fn publish_proposal_from_commitment_and_metadata( version, id, ) - .await; + .await + { + Ok(()) => {} + Err(e) => { + tracing::error!("Failed to send proposal: {}", e); + } + }; }); Ok(create_and_send_proposal_handle) diff --git a/crates/task-impls/src/consensus/mod.rs b/crates/task-impls/src/consensus/mod.rs index 352363e380..2d73af5da9 100644 --- a/crates/task-impls/src/consensus/mod.rs +++ b/crates/task-impls/src/consensus/mod.rs @@ -576,7 +576,8 @@ impl> ConsensusTaskState builder_commitment, metadata, view, - fee, + fees, + auction_result, ) => { let view = *view; debug!( @@ -587,8 +588,9 @@ impl> ConsensusTaskState commitment: *payload_commitment, builder_commitment: builder_commitment.clone(), metadata: metadata.clone(), - fee: fee.clone(), + fees: fees.clone(), block_view: view, + auction_result: auction_result.clone(), }); if self.quorum_membership.leader(view) == self.public_key && self.consensus.read().await.high_qc().view_number() + 1 == view diff --git a/crates/task-impls/src/events.rs b/crates/task-impls/src/events.rs index f12fe1bd23..9eac42273d 100644 --- a/crates/task-impls/src/events.rs +++ b/crates/task-impls/src/events.rs @@ -22,6 +22,7 @@ use hotshot_types::{ vid::VidCommitment, vote::{HasViewNumber, VoteDependencyData}, }; +use vec1::Vec1; use crate::view_sync::ViewSyncPhase; @@ -142,7 +143,8 @@ pub enum HotShotEvent { BuilderCommitment, >::Metadata, TYPES::Time, - BuilderFee, + Vec1>, + Option, ), /// Event when the transactions task has sequenced transactions. Contains the encoded transactions, the metadata, and the view number BlockRecv(PackedBundle), @@ -351,7 +353,7 @@ impl Display for HotShotEvent { HotShotEvent::Timeout(view_number) => write!(f, "Timeout(view_number={view_number:?})"), HotShotEvent::TransactionsRecv(_) => write!(f, "TransactionsRecv"), HotShotEvent::TransactionSend(_, _) => write!(f, "TransactionSend"), - HotShotEvent::SendPayloadCommitmentAndMetadata(_, _, _, view_number, _) => { + HotShotEvent::SendPayloadCommitmentAndMetadata(_, _, _, view_number, _, _) => { write!( f, "SendPayloadCommitmentAndMetadata(view_number={view_number:?})" diff --git a/crates/task-impls/src/quorum_proposal/handlers.rs b/crates/task-impls/src/quorum_proposal/handlers.rs index 20f8dbbacd..04161fbf34 100644 --- a/crates/task-impls/src/quorum_proposal/handlers.rs +++ b/crates/task-impls/src/quorum_proposal/handlers.rs @@ -16,6 +16,7 @@ use hotshot_task::{ }; use hotshot_types::{ consensus::{CommitmentAndMetadata, OuterConsensus}, + constants::MarketplaceVersion, data::{Leaf, QuorumProposal, VidDisperse, ViewChangeEvidence}, message::Proposal, simple_certificate::{version, UpgradeCertificate}, @@ -24,6 +25,7 @@ use hotshot_types::{ }, }; use tracing::{debug, error, instrument}; +use vbs::version::StaticVersionType; use crate::{ events::HotShotEvent, @@ -163,19 +165,35 @@ impl ProposalDependencyHandle { &self.decided_upgrade_certificate.read().await.clone(), )?; - let block_header = TYPES::BlockHeader::new_legacy( - state.as_ref(), - self.instance_state.as_ref(), - &parent_leaf, - commitment_and_metadata.commitment, - commitment_and_metadata.builder_commitment, - commitment_and_metadata.metadata, - commitment_and_metadata.fee, - vid_share.data.common.clone(), - version, - ) - .await - .context("Failed to construct block header")?; + let block_header = if version < MarketplaceVersion::VERSION { + TYPES::BlockHeader::new_legacy( + state.as_ref(), + self.instance_state.as_ref(), + &parent_leaf, + commitment_and_metadata.commitment, + commitment_and_metadata.builder_commitment, + commitment_and_metadata.metadata, + commitment_and_metadata.fees.first().clone(), + vid_share.data.common.clone(), + version, + ) + .await + .context("Failed to construct legacy block header")? + } else { + TYPES::BlockHeader::new_marketplace( + state.as_ref(), + self.instance_state.as_ref(), + &parent_leaf, + commitment_and_metadata.commitment, + commitment_and_metadata.metadata, + commitment_and_metadata.fees.to_vec(), + vid_share.data.common.clone(), + commitment_and_metadata.auction_result, + version, + ) + .await + .context("Failed to construct marketplace block header")? + }; let proposal = QuorumProposal { block_header, @@ -269,14 +287,16 @@ impl HandleDepOutput for ProposalDependencyHandle { builder_commitment, metadata, view, - fee, + fees, + auction_result, ) => { commit_and_metadata = Some(CommitmentAndMetadata { commitment: *payload_commitment, builder_commitment: builder_commitment.clone(), metadata: metadata.clone(), - fee: fee.clone(), + fees: fees.clone(), block_view: *view, + auction_result: auction_result.clone(), }); } HotShotEvent::QcFormed(cert) => match cert { diff --git a/crates/task-impls/src/quorum_proposal/mod.rs b/crates/task-impls/src/quorum_proposal/mod.rs index ea0059b230..8caa42caa7 100644 --- a/crates/task-impls/src/quorum_proposal/mod.rs +++ b/crates/task-impls/src/quorum_proposal/mod.rs @@ -148,6 +148,7 @@ impl> QuorumProposalTaskState> QuorumProposalTaskState { let view_number = *view_number; diff --git a/crates/task-impls/src/transactions.rs b/crates/task-impls/src/transactions.rs index 621ff66077..eece7205c5 100644 --- a/crates/task-impls/src/transactions.rs +++ b/crates/task-impls/src/transactions.rs @@ -18,10 +18,10 @@ use hotshot_types::{ event::{Event, EventType}, simple_certificate::{version, UpgradeCertificate}, traits::{ - auction_results_provider::{AuctionResultsProvider, HasUrls}, + auction_results_provider::AuctionResultsProvider, block_contents::{precompute_vid_commitment, BuilderFee, EncodeBytes}, election::Membership, - node_implementation::{ConsensusTime, NodeImplementation, NodeType}, + node_implementation::{ConsensusTime, HasUrls, NodeImplementation, NodeType}, signature_key::{BuilderSignatureKey, SignatureKey}, BlockPayload, }, @@ -187,6 +187,7 @@ impl> TransactionTaskState> TransactionTaskState> TransactionTaskState> TransactionTaskState> TransactionTaskState> VidTaskState { view_number, sequencing_fees, vid_precompute, + auction_result, .. } = packed_bundle; let payload = @@ -87,7 +88,8 @@ impl> VidTaskState { builder_commitment, metadata.clone(), *view_number, - sequencing_fees.first().clone(), + sequencing_fees.clone(), + auction_result.clone(), )), &event_stream, ) diff --git a/crates/testing/src/helpers.rs b/crates/testing/src/helpers.rs index ac6730b93a..67480905ff 100644 --- a/crates/testing/src/helpers.rs +++ b/crates/testing/src/helpers.rs @@ -48,7 +48,7 @@ pub async fn build_system_handle< I: NodeImplementation< TYPES, Storage = TestStorage, - AuctionResultsProvider = TestAuctionResultsProvider, + AuctionResultsProvider = TestAuctionResultsProvider, > + TestableNodeImplementation, >( node_id: u64, diff --git a/crates/testing/src/spinning_task.rs b/crates/testing/src/spinning_task.rs index 73c27193c5..65dffac329 100644 --- a/crates/testing/src/spinning_task.rs +++ b/crates/testing/src/spinning_task.rs @@ -65,7 +65,7 @@ where TYPES, Network = N, Storage = TestStorage, - AuctionResultsProvider = TestAuctionResultsProvider, + AuctionResultsProvider = TestAuctionResultsProvider, >, { type Event = Event; diff --git a/crates/testing/src/test_builder.rs b/crates/testing/src/test_builder.rs index 909ccaa898..d2726aa25f 100644 --- a/crates/testing/src/test_builder.rs +++ b/crates/testing/src/test_builder.rs @@ -478,7 +478,9 @@ impl, I: TestableNodeImplemen ), storage: Box::new(|_| TestStorage::::default()), config, - auction_results_provider: Box::new(|_| TestAuctionResultsProvider::default()), + auction_results_provider: Box::new(|_| { + TestAuctionResultsProvider::::default() + }), }, metadata: self, } diff --git a/crates/testing/src/test_launcher.rs b/crates/testing/src/test_launcher.rs index 0ed2907fe5..077194fad7 100644 --- a/crates/testing/src/test_launcher.rs +++ b/crates/testing/src/test_launcher.rs @@ -29,7 +29,7 @@ pub struct ResourceGenerators, /// generate a new auction results connector for each node - pub auction_results_provider: Generator, + pub auction_results_provider: Generator>, } /// test launcher diff --git a/crates/testing/src/test_runner.rs b/crates/testing/src/test_runner.rs index 76ccbc8625..e11a343676 100644 --- a/crates/testing/src/test_runner.rs +++ b/crates/testing/src/test_runner.rs @@ -70,7 +70,7 @@ where TYPES, Network = N, Storage = TestStorage, - AuctionResultsProvider = TestAuctionResultsProvider, + AuctionResultsProvider = TestAuctionResultsProvider, >, { /// execute test diff --git a/crates/testing/tests/tests_1/consensus_task.rs b/crates/testing/tests/tests_1/consensus_task.rs index 4a7314ced5..c3abf8c2ff 100644 --- a/crates/testing/tests/tests_1/consensus_task.rs +++ b/crates/testing/tests/tests_1/consensus_task.rs @@ -37,6 +37,7 @@ use hotshot_types::{ }; use jf_vid::VidScheme; use sha2::Digest; +use vec1::vec1; const TIMEOUT: Duration = Duration::from_millis(35); @@ -97,8 +98,12 @@ async fn test_consensus_task() { builder_commitment, TestMetadata, ViewNumber::new(2), - null_block::builder_fee(quorum_membership.total_nodes(), BaseVersion::version()) - .unwrap(), + vec1![null_block::builder_fee( + quorum_membership.total_nodes(), + BaseVersion::version() + ) + .unwrap()], + None, ), ], ]; @@ -285,7 +290,8 @@ async fn test_view_sync_finalize_propose() { builder_commitment, TestMetadata, ViewNumber::new(4), - null_block::builder_fee(4, BaseVersion::version()).unwrap(), + vec1![null_block::builder_fee(4, BaseVersion::version()).unwrap()], + None, ), ], ]; diff --git a/crates/testing/tests/tests_1/da_task.rs b/crates/testing/tests/tests_1/da_task.rs index e98711d5ed..ac550f6a1e 100644 --- a/crates/testing/tests/tests_1/da_task.rs +++ b/crates/testing/tests/tests_1/da_task.rs @@ -85,6 +85,7 @@ async fn test_da_task() { ) .unwrap()], Some(precompute), + None, )), ], serial![DaProposalRecv(proposals[1].clone(), leaders[1])], @@ -171,6 +172,7 @@ async fn test_da_task_storage_failure() { ) .unwrap()], Some(precompute), + None, ),) ], serial![DaProposalRecv(proposals[1].clone(), leaders[1])], diff --git a/crates/testing/tests/tests_1/quorum_proposal_task.rs b/crates/testing/tests/tests_1/quorum_proposal_task.rs index 96c11122f9..5783498acd 100644 --- a/crates/testing/tests/tests_1/quorum_proposal_task.rs +++ b/crates/testing/tests/tests_1/quorum_proposal_task.rs @@ -28,6 +28,7 @@ use hotshot_types::{ vote::HasViewNumber, }; use sha2::Digest; +use vec1::vec1; const TIMEOUT: Duration = Duration::from_millis(35); @@ -43,7 +44,9 @@ async fn test_quorum_proposal_task_quorum_proposal_view_1() { async_compatibility_layer::logging::setup_backtrace(); let node_id = 1; - let handle = build_system_handle::(node_id).await.0; + let handle = build_system_handle::(node_id) + .await + .0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); let da_membership = handle.hotshot.memberships.da_membership.clone(); @@ -90,7 +93,8 @@ async fn test_quorum_proposal_task_quorum_proposal_view_1() { builder_commitment, TestMetadata, ViewNumber::new(1), - builder_fee.clone(), + vec1![builder_fee.clone()], + None, ), ValidatedStateUpdated( proposals[0].data.view_number(), @@ -130,7 +134,9 @@ async fn test_quorum_proposal_task_quorum_proposal_view_gt_1() { async_compatibility_layer::logging::setup_backtrace(); let node_id = 3; - let handle = build_system_handle::(node_id).await.0; + let handle = build_system_handle::(node_id) + .await + .0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); let da_membership = handle.hotshot.memberships.da_membership.clone(); @@ -186,7 +192,8 @@ async fn test_quorum_proposal_task_quorum_proposal_view_gt_1() { builder_commitment.clone(), TestMetadata, ViewNumber::new(1), - builder_fee.clone(), + vec1![builder_fee.clone()], + None, ), VidDisperseSend(vid_dispersals[0].clone(), handle.public_key()), ValidatedStateUpdated( @@ -202,7 +209,8 @@ async fn test_quorum_proposal_task_quorum_proposal_view_gt_1() { builder_commitment.clone(), TestMetadata, ViewNumber::new(2), - builder_fee.clone(), + vec1![builder_fee.clone()], + None, ), VidDisperseSend(vid_dispersals[1].clone(), handle.public_key()), ValidatedStateUpdated( @@ -218,7 +226,8 @@ async fn test_quorum_proposal_task_quorum_proposal_view_gt_1() { builder_commitment.clone(), TestMetadata, ViewNumber::new(3), - builder_fee.clone(), + vec1![builder_fee.clone()], + None, ), VidDisperseSend(vid_dispersals[2].clone(), handle.public_key()), ValidatedStateUpdated( @@ -234,7 +243,8 @@ async fn test_quorum_proposal_task_quorum_proposal_view_gt_1() { builder_commitment.clone(), TestMetadata, ViewNumber::new(4), - builder_fee.clone(), + vec1![builder_fee.clone()], + None, ), VidDisperseSend(vid_dispersals[3].clone(), handle.public_key()), ValidatedStateUpdated( @@ -250,7 +260,8 @@ async fn test_quorum_proposal_task_quorum_proposal_view_gt_1() { builder_commitment, TestMetadata, ViewNumber::new(5), - builder_fee.clone(), + vec1![builder_fee.clone()], + None, ), VidDisperseSend(vid_dispersals[4].clone(), handle.public_key()), ValidatedStateUpdated( @@ -307,7 +318,9 @@ async fn test_quorum_proposal_task_qc_timeout() { async_compatibility_layer::logging::setup_backtrace(); let node_id = 3; - let handle = build_system_handle::(node_id).await.0; + let handle = build_system_handle::(node_id) + .await + .0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); let da_membership = handle.hotshot.memberships.da_membership.clone(); @@ -353,8 +366,11 @@ async fn test_quorum_proposal_task_qc_timeout() { builder_commitment, TestMetadata, ViewNumber::new(3), - null_block::builder_fee(quorum_membership.total_nodes(), BaseVersion::version()) - .unwrap(), + vec1![ + null_block::builder_fee(quorum_membership.total_nodes(), BaseVersion::version()) + .unwrap() + ], + None, ), VidDisperseSend(vid_dispersals[2].clone(), handle.public_key()), ValidatedStateUpdated( @@ -388,7 +404,9 @@ async fn test_quorum_proposal_task_view_sync() { async_compatibility_layer::logging::setup_backtrace(); let node_id = 2; - let handle = build_system_handle::(node_id).await.0; + let handle = build_system_handle::(node_id) + .await + .0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); let da_membership = handle.hotshot.memberships.da_membership.clone(); @@ -436,8 +454,11 @@ async fn test_quorum_proposal_task_view_sync() { builder_commitment, TestMetadata, ViewNumber::new(2), - null_block::builder_fee(quorum_membership.total_nodes(), BaseVersion::version()) - .unwrap(), + vec1![ + null_block::builder_fee(quorum_membership.total_nodes(), BaseVersion::version()) + .unwrap() + ], + None, ), VidDisperseSend(vid_dispersals[1].clone(), handle.public_key()), ValidatedStateUpdated( @@ -470,7 +491,9 @@ async fn test_quorum_proposal_task_liveness_check() { async_compatibility_layer::logging::setup_backtrace(); let node_id = 3; - let handle = build_system_handle::(node_id).await.0; + let handle = build_system_handle::(node_id) + .await + .0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); let da_membership = handle.hotshot.memberships.da_membership.clone(); @@ -524,7 +547,8 @@ async fn test_quorum_proposal_task_liveness_check() { builder_commitment.clone(), TestMetadata, ViewNumber::new(1), - builder_fee.clone(), + vec1![builder_fee.clone()], + None, ), VidDisperseSend(vid_dispersals[0].clone(), handle.public_key()), ValidatedStateUpdated( @@ -540,7 +564,8 @@ async fn test_quorum_proposal_task_liveness_check() { builder_commitment.clone(), TestMetadata, ViewNumber::new(2), - builder_fee.clone(), + vec1![builder_fee.clone()], + None, ), VidDisperseSend(vid_dispersals[1].clone(), handle.public_key()), ValidatedStateUpdated( @@ -556,7 +581,8 @@ async fn test_quorum_proposal_task_liveness_check() { builder_commitment.clone(), TestMetadata, ViewNumber::new(3), - builder_fee.clone(), + vec1![builder_fee.clone()], + None, ), VidDisperseSend(vid_dispersals[2].clone(), handle.public_key()), ValidatedStateUpdated( @@ -572,7 +598,8 @@ async fn test_quorum_proposal_task_liveness_check() { builder_commitment.clone(), TestMetadata, ViewNumber::new(4), - builder_fee.clone(), + vec1![builder_fee.clone()], + None, ), VidDisperseSend(vid_dispersals[3].clone(), handle.public_key()), ValidatedStateUpdated( @@ -588,7 +615,8 @@ async fn test_quorum_proposal_task_liveness_check() { builder_commitment, TestMetadata, ViewNumber::new(5), - builder_fee.clone(), + vec1![builder_fee.clone()], + None, ), VidDisperseSend(vid_dispersals[4].clone(), handle.public_key()), ValidatedStateUpdated( diff --git a/crates/testing/tests/tests_1/transaction_task.rs b/crates/testing/tests/tests_1/transaction_task.rs index 25b2f53942..dc3386162f 100644 --- a/crates/testing/tests/tests_1/transaction_task.rs +++ b/crates/testing/tests/tests_1/transaction_task.rs @@ -47,6 +47,7 @@ async fn test_transaction_task_leader_two_views_in_a_row() { ) .unwrap()], Some(precompute_data.clone()), + None, ); output.push(HotShotEvent::BlockRecv(exp_packed_bundle.clone())); @@ -56,4 +57,4 @@ async fn test_transaction_task_leader_two_views_in_a_row() { let transaction_state = TransactionTaskState::::create_from(&handle).await; run_harness(input, output, transaction_state, false).await; -} \ No newline at end of file +} diff --git a/crates/testing/tests/tests_1/upgrade_task_with_consensus.rs b/crates/testing/tests/tests_1/upgrade_task_with_consensus.rs index 958ccad63a..28b0b5b6a5 100644 --- a/crates/testing/tests/tests_1/upgrade_task_with_consensus.rs +++ b/crates/testing/tests/tests_1/upgrade_task_with_consensus.rs @@ -30,6 +30,7 @@ use hotshot_types::{ vote::HasViewNumber, }; use vbs::version::{StaticVersionType, Version}; +use vec1::vec1; #[cfg_attr(async_executor_impl = "tokio", tokio::test(flavor = "multi_thread"))] #[cfg_attr(async_executor_impl = "async-std", async_std::test)] @@ -272,8 +273,12 @@ async fn test_upgrade_task_propose() { proposals[2].data.block_header.builder_commitment.clone(), TestMetadata, ViewNumber::new(3), - null_block::builder_fee(quorum_membership.total_nodes(), BaseVersion::version()) - .unwrap(), + vec1![null_block::builder_fee( + quorum_membership.total_nodes(), + BaseVersion::version() + ) + .unwrap()], + None, ), QcFormed(either::Either::Left(proposals[2].data.justify_qc.clone())), ], @@ -459,7 +464,8 @@ async fn test_upgrade_task_blank_blocks() { proposals[1].data.block_header.builder_commitment.clone(), TestMetadata, ViewNumber::new(2), - builder_fee.clone(), + vec1![builder_fee.clone()], + None, ), ], vec![ @@ -470,7 +476,8 @@ async fn test_upgrade_task_blank_blocks() { proposals[2].data.block_header.builder_commitment.clone(), TestMetadata, ViewNumber::new(3), - builder_fee.clone(), + vec1![builder_fee.clone()], + None, ), QuorumProposalRecv(proposals[2].clone(), leaders[2]), ], @@ -482,7 +489,8 @@ async fn test_upgrade_task_blank_blocks() { proposals[3].data.block_header.builder_commitment.clone(), TestMetadata, ViewNumber::new(4), - builder_fee.clone(), + vec1![builder_fee.clone()], + None, ), QuorumProposalRecv(proposals[3].clone(), leaders[3]), ], @@ -494,7 +502,8 @@ async fn test_upgrade_task_blank_blocks() { proposals[4].data.block_header.builder_commitment.clone(), TestMetadata, ViewNumber::new(5), - builder_fee.clone(), + vec1![builder_fee.clone()], + None, ), QuorumProposalRecv(proposals[4].clone(), leaders[4]), ], @@ -506,7 +515,8 @@ async fn test_upgrade_task_blank_blocks() { proposals[5].data.block_header.builder_commitment.clone(), TestMetadata, ViewNumber::new(6), - builder_fee.clone(), + vec1![builder_fee.clone()], + None, ), QuorumProposalRecv(proposals[5].clone(), leaders[5]), QcFormed(either::Either::Left(proposals[5].data.justify_qc.clone())), @@ -519,7 +529,8 @@ async fn test_upgrade_task_blank_blocks() { proposals[6].data.block_header.builder_commitment.clone(), TestMetadata, ViewNumber::new(7), - builder_fee, + vec1![builder_fee], + None, ), QuorumProposalRecv(proposals[6].clone(), leaders[6]), ], diff --git a/crates/testing/tests/tests_1/upgrade_task_with_proposal.rs b/crates/testing/tests/tests_1/upgrade_task_with_proposal.rs index 3095c4ef25..40f766b273 100644 --- a/crates/testing/tests/tests_1/upgrade_task_with_proposal.rs +++ b/crates/testing/tests/tests_1/upgrade_task_with_proposal.rs @@ -35,6 +35,7 @@ use hotshot_types::{ }; use sha2::Digest; use vbs::version::{StaticVersionType, Version}; +use vec1::vec1; const TIMEOUT: Duration = Duration::from_millis(35); @@ -146,7 +147,8 @@ async fn test_upgrade_task_with_proposal() { builder_commitment.clone(), TestMetadata, ViewNumber::new(1), - builder_fee.clone(), + vec1![builder_fee.clone()], + None, ), VidDisperseSend(vid_dispersals[0].clone(), handle.public_key()), ValidatedStateUpdated( @@ -162,7 +164,8 @@ async fn test_upgrade_task_with_proposal() { builder_commitment.clone(), TestMetadata, ViewNumber::new(2), - builder_fee.clone(), + vec1![builder_fee.clone()], + None, ), VidDisperseSend(vid_dispersals[1].clone(), handle.public_key()), ValidatedStateUpdated( @@ -179,7 +182,8 @@ async fn test_upgrade_task_with_proposal() { builder_commitment.clone(), TestMetadata, ViewNumber::new(3), - builder_fee.clone(), + vec1![builder_fee.clone()], + None, ), VidDisperseSend(vid_dispersals[2].clone(), handle.public_key()), ValidatedStateUpdated( diff --git a/crates/testing/tests/tests_1/vid_task.rs b/crates/testing/tests/tests_1/vid_task.rs index 7d6ad7bc08..3087293ccc 100644 --- a/crates/testing/tests/tests_1/vid_task.rs +++ b/crates/testing/tests/tests_1/vid_task.rs @@ -26,6 +26,7 @@ use hotshot_types::{ }; use jf_vid::{precomputable::Precomputable, VidScheme}; use vbs::version::StaticVersionType; +use vec1::vec1; #[cfg_attr(async_executor_impl = "tokio", tokio::test(flavor = "multi_thread"))] #[cfg_attr(async_executor_impl = "async-std", async_std::test)] @@ -97,6 +98,7 @@ async fn test_vid_task() { ) .unwrap()], Some(vid_precompute), + None, )), ], ]; @@ -109,8 +111,12 @@ async fn test_vid_task() { builder_commitment, TestMetadata, ViewNumber::new(2), - null_block::builder_fee(quorum_membership.total_nodes(), BaseVersion::version()) - .unwrap(), + vec1![null_block::builder_fee( + quorum_membership.total_nodes(), + BaseVersion::version() + ) + .unwrap()], + None, )), exact(BlockReady(vid_disperse, ViewNumber::new(2))), exact(VidDisperseSend(vid_proposal.clone(), pub_key)), diff --git a/crates/testing/tests/tests_3/memory_network.rs b/crates/testing/tests/tests_3/memory_network.rs index 591f7a5147..e4869e383c 100644 --- a/crates/testing/tests/tests_3/memory_network.rs +++ b/crates/testing/tests/tests_3/memory_network.rs @@ -11,7 +11,7 @@ use hotshot::{ types::SignatureKey, }; use hotshot_example_types::{ - auction_results_provider_types::TestAuctionResultsProvider, + auction_results_provider_types::{TestAuctionResult, TestAuctionResultsProvider}, block_types::{TestBlockHeader, TestBlockPayload, TestTransaction}, state_types::{TestInstanceState, TestValidatedState}, storage_types::TestStorage, @@ -46,6 +46,7 @@ use vbs::version::StaticVersion; pub struct Test; impl NodeType for Test { + type AuctionResult = TestAuctionResult; type Base = StaticVersion<0, 1>; type Upgrade = StaticVersion<0, 2>; const UPGRADE_HASH: [u8; 32] = [ @@ -69,7 +70,7 @@ pub struct TestImpl {} impl NodeImplementation for TestImpl { type Network = MemoryNetwork<::SignatureKey>; type Storage = TestStorage; - type AuctionResultsProvider = TestAuctionResultsProvider; + type AuctionResultsProvider = TestAuctionResultsProvider; } /// fake Eq diff --git a/crates/types/src/consensus.rs b/crates/types/src/consensus.rs index 9ef89601f6..33b91cd147 100644 --- a/crates/types/src/consensus.rs +++ b/crates/types/src/consensus.rs @@ -11,6 +11,7 @@ use anyhow::{bail, ensure, Result}; use async_lock::{RwLock, RwLockReadGuard, RwLockUpgradableReadGuard, RwLockWriteGuard}; use committable::{Commitment, Committable}; use tracing::{debug, error, instrument, trace}; +use vec1::Vec1; pub use crate::utils::{View, ViewInner}; use crate::{ @@ -732,7 +733,9 @@ pub struct CommitmentAndMetadata { /// Metadata for the block payload pub metadata: >::Metadata, /// Builder fee data - pub fee: BuilderFee, + pub fees: Vec1>, /// View number this block is for pub block_view: TYPES::Time, + /// auction result that the block was produced from, if any + pub auction_result: Option, } diff --git a/crates/types/src/data.rs b/crates/types/src/data.rs index c963cb5648..d2356e1df9 100644 --- a/crates/types/src/data.rs +++ b/crates/types/src/data.rs @@ -881,6 +881,9 @@ pub struct PackedBundle { /// The Vid precompute for the block. pub vid_precompute: Option, + + /// The auction results for the block, if it was produced as the result of an auction + pub auction_result: Option, } impl PackedBundle { @@ -891,6 +894,7 @@ impl PackedBundle { view_number: TYPES::Time, sequencing_fees: Vec1>, vid_precompute: Option, + auction_result: Option, ) -> Self { Self { encoded_transactions, @@ -898,6 +902,7 @@ impl PackedBundle { view_number, sequencing_fees, vid_precompute, + auction_result, } } } diff --git a/crates/types/src/traits/auction_results_provider.rs b/crates/types/src/traits/auction_results_provider.rs index 1d373e2af2..e9154151ce 100644 --- a/crates/types/src/traits/auction_results_provider.rs +++ b/crates/types/src/traits/auction_results_provider.rs @@ -3,29 +3,16 @@ use anyhow::Result; use async_trait::async_trait; -use url::Url; use super::node_implementation::NodeType; -/// This trait guarantees that a particular type has urls that can be extracted from it. This trait -/// essentially ensures that the results returned by the [`AuctionResultsProvider`] trait includes a -/// list of urls for the builders that HotShot must request from. -pub trait HasUrls { - /// Returns the builer url associated with the datatype - fn urls(&self) -> Vec; -} - /// The AuctionResultsProvider trait is the sole source of Solver-originated state and interaction, /// and returns the results of the Solver's allocation via the associated type. The associated type, -/// `AuctionResult`, also implements the [`HasUrls`] trait, which requires that the output +/// `AuctionResult`, also implements the `HasUrls` trait, which requires that the output /// type has the requisite fields available. #[async_trait] pub trait AuctionResultsProvider: Send + Sync + Clone { - /// The AuctionSolverResult is a type that holds the data associated with a particular solver - /// run, for a particular view. - type AuctionResult: HasUrls + Send; - /// Fetches the auction result for a view. Does not cache the result, /// subsequent calls will invoke additional wasted calls. - async fn fetch_auction_result(&self, view_number: TYPES::Time) -> Result; + async fn fetch_auction_result(&self, view_number: TYPES::Time) -> Result; } diff --git a/crates/types/src/traits/block_contents.rs b/crates/types/src/traits/block_contents.rs index 253554650f..6c1bb1704f 100644 --- a/crates/types/src/traits/block_contents.rs +++ b/crates/types/src/traits/block_contents.rs @@ -17,7 +17,7 @@ use jf_vid::{precomputable::Precomputable, VidScheme}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use vbs::version::Version; -use super::{auction_results_provider::HasUrls, signature_key::BuilderSignatureKey}; +use super::signature_key::BuilderSignatureKey; use crate::{ data::Leaf, traits::{node_implementation::NodeType, states::InstanceState, ValidatedState}, @@ -181,8 +181,6 @@ pub trait BlockHeader: { /// Error type for this type of block header type Error: Error + Debug + Send + Sync; - /// Type of Auction Results - type AuctionResult: HasUrls + Send; /// Build a header with the parent validate state, instance-level state, parent leaf, payload /// commitment, and metadata. This is only used in pre-marketplace versions @@ -210,7 +208,7 @@ pub trait BlockHeader: metadata: >::Metadata, builder_fee: Vec>, vid_common: VidCommon, - auction_results: Option, + auction_results: Option, version: Version, ) -> impl Future> + Send; @@ -235,5 +233,5 @@ pub trait BlockHeader: fn builder_commitment(&self) -> BuilderCommitment; /// Get the results of the auction for this Header. Only used in post-marketplace versions - fn get_auction_results(&self) -> Option; + fn get_auction_results(&self) -> Option; } diff --git a/crates/types/src/traits/node_implementation.rs b/crates/types/src/traits/node_implementation.rs index 4dba2104c1..49a93de123 100644 --- a/crates/types/src/traits/node_implementation.rs +++ b/crates/types/src/traits/node_implementation.rs @@ -13,7 +13,8 @@ use std::{ use async_trait::async_trait; use committable::Committable; -use serde::{Deserialize, Serialize}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use url::Url; use vbs::version::StaticVersionType; use super::{ @@ -34,6 +35,14 @@ use crate::{ }, }; +/// This trait guarantees that a particular type has urls that can be extracted from it. This trait +/// essentially ensures that the results returned by the [`AuctionResultsProvider`] trait includes a +/// list of urls for the builders that HotShot must request from. +pub trait HasUrls { + /// Returns the builer url associated with the datatype + fn urls(&self) -> Vec; +} + /// Node implementation aggregate trait /// /// This trait exists to collect multiple behavior implementations into one type, to allow @@ -205,6 +214,17 @@ pub trait NodeType: /// /// This should be the same `Time` that `ValidatedState::Time` is using. type Time: ConsensusTime; + /// The AuctionSolverResult is a type that holds the data associated with a particular solver + /// run, for a particular view. + type AuctionResult: Debug + + HasUrls + + DeserializeOwned + + Default + + PartialEq + + Eq + + Clone + + Send + + Sync; /// The block header type that this hotshot setup is using. type BlockHeader: BlockHeader; /// The block type that this hotshot setup is using.