Skip to content

Commit

Permalink
test marketplace upgrade (#1927)
Browse files Browse the repository at this point in the history
Add a unit tests for marketplace view and time based upgrade. Also refactors test_upgrade_helper to support upgrades between any versions.

---------

Co-authored-by: tbro <[email protected]>
  • Loading branch information
tbro and tbro authored Sep 11, 2024
1 parent e0399c8 commit 180b99c
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 47 deletions.
158 changes: 122 additions & 36 deletions sequencer/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1069,16 +1069,16 @@ mod api_tests {

#[cfg(test)]
mod test {
use std::time::Duration;
use std::{collections::BTreeMap, time::Duration};

use async_std::task::sleep;
use committable::{Commitment, Committable};

use espresso_types::{
mock::MockStateCatchup,
v0_1::{UpgradeMode, ViewBasedUpgrade},
FeeAccount, FeeAmount, Header, MockSequencerVersions, TimeBasedUpgrade, Timestamp, Upgrade,
UpgradeType, ValidatedState,
FeeAccount, FeeAmount, Header, MockSequencerVersions, SequencerVersions, TimeBasedUpgrade,
Timestamp, Upgrade, UpgradeType, ValidatedState,
};
use ethers::utils::Anvil;
use futures::{
Expand All @@ -1105,7 +1105,7 @@ mod test {
};
use tide_disco::{app::AppHealth, error::ServerError, healthcheck::HealthStatus};
use time::OffsetDateTime;
use vbs::version::{StaticVersion, StaticVersionType};
use vbs::version::{StaticVersion, StaticVersionType, Version};

use self::{
data_source::{testing::TestableSequencerDataSource, PublicHotShotConfig},
Expand Down Expand Up @@ -1465,50 +1465,137 @@ mod test {
async fn test_fee_upgrade_view_based() {
setup_test();

test_fee_upgrade_helper(UpgradeMode::View(ViewBasedUpgrade {
let mut upgrades = std::collections::BTreeMap::new();
type MySequencerVersions = SequencerVersions<StaticVersion<0, 1>, StaticVersion<0, 2>>;

let mode = UpgradeMode::View(ViewBasedUpgrade {
start_voting_view: None,
stop_voting_view: None,
start_proposing_view: 1,
stop_proposing_view: 10,
}))
.await;
});

let upgrade_type = UpgradeType::Fee {
chain_config: ChainConfig {
max_block_size: 300.into(),
base_fee: 1.into(),
..Default::default()
},
};

upgrades.insert(
<MySequencerVersions as Versions>::Upgrade::VERSION,
Upgrade { mode, upgrade_type },
);
test_upgrade_helper::<MySequencerVersions>(upgrades, MySequencerVersions::new()).await;
}

#[async_std::test]
async fn test_fee_upgrade_time_based() {
setup_test();

let now = OffsetDateTime::now_utc().unix_timestamp() as u64;
test_fee_upgrade_helper(UpgradeMode::Time(TimeBasedUpgrade {

let mut upgrades = std::collections::BTreeMap::new();
type MySequencerVersions = SequencerVersions<StaticVersion<0, 1>, StaticVersion<0, 2>>;

let mode = UpgradeMode::Time(TimeBasedUpgrade {
start_proposing_time: Timestamp::from_integer(now).unwrap(),
stop_proposing_time: Timestamp::from_integer(now + 500).unwrap(),
start_voting_time: None,
stop_voting_time: None,
}))
.await;
});

let upgrade_type = UpgradeType::Fee {
chain_config: ChainConfig {
max_block_size: 300.into(),
base_fee: 1.into(),
..Default::default()
},
};

upgrades.insert(
<MySequencerVersions as Versions>::Upgrade::VERSION,
Upgrade { mode, upgrade_type },
);
test_upgrade_helper::<MySequencerVersions>(upgrades, MySequencerVersions::new()).await;
}

async fn test_fee_upgrade_helper(mode: UpgradeMode) {
let port = pick_unused_port().expect("No ports free");
let anvil = Anvil::new().spawn();
let l1 = anvil.endpoint().parse().unwrap();
#[async_std::test]
async fn test_marketplace_upgrade_view_based() {
setup_test();

let chain_config_upgrade = ChainConfig {
max_block_size: 300.into(),
base_fee: 1.into(),
..Default::default()
};
let mut upgrades = std::collections::BTreeMap::new();
type MySequencerVersions = SequencerVersions<StaticVersion<0, 2>, StaticVersion<0, 3>>;

let mode = UpgradeMode::View(ViewBasedUpgrade {
start_voting_view: None,
stop_voting_view: None,
start_proposing_view: 1,
stop_proposing_view: 10,
});

let upgrade_type = UpgradeType::Marketplace {
chain_config: ChainConfig {
max_block_size: 400.into(),
base_fee: 2.into(),
bid_recipient: Some(Default::default()),
..Default::default()
},
};

upgrades.insert(
StaticVersion::<0, 2>::version(),
Upgrade {
mode,
upgrade_type: UpgradeType::Fee {
chain_config: chain_config_upgrade,
},
<MySequencerVersions as Versions>::Upgrade::VERSION,
Upgrade { mode, upgrade_type },
);
test_upgrade_helper::<MySequencerVersions>(upgrades, MySequencerVersions::new()).await;
}

#[async_std::test]
async fn test_marketplace_upgrade_time_based() {
setup_test();

let now = OffsetDateTime::now_utc().unix_timestamp() as u64;

let mut upgrades = std::collections::BTreeMap::new();
type MySequencerVersions = SequencerVersions<StaticVersion<0, 2>, StaticVersion<0, 3>>;

let mode = UpgradeMode::Time(TimeBasedUpgrade {
start_proposing_time: Timestamp::from_integer(now).unwrap(),
stop_proposing_time: Timestamp::from_integer(now + 500).unwrap(),
start_voting_time: None,
stop_voting_time: None,
});

let upgrade_type = UpgradeType::Fee {
chain_config: ChainConfig {
max_block_size: 400.into(),
base_fee: 2.into(),
bid_recipient: Some(Default::default()),
..Default::default()
},
};

upgrades.insert(
<MySequencerVersions as Versions>::Upgrade::VERSION,
Upgrade { mode, upgrade_type },
);
test_upgrade_helper::<MySequencerVersions>(upgrades, MySequencerVersions::new()).await;
}

async fn test_upgrade_helper<MockSeqVersions: Versions>(
upgrades: BTreeMap<Version, Upgrade>,
bind_version: MockSeqVersions,
) {
let port = pick_unused_port().expect("No ports free");
let anvil = Anvil::new().spawn();
let l1 = anvil.endpoint().parse().unwrap();

let chain_config_upgrade = upgrades
.get(&<MockSeqVersions as Versions>::Upgrade::VERSION)
.unwrap()
.upgrade_type
.data();

const NUM_NODES: usize = 5;
let config = TestNetworkConfigBuilder::<NUM_NODES, _, _>::with_num_nodes()
Expand All @@ -1529,12 +1616,12 @@ mod test {
.network_config(
TestConfigBuilder::default()
.l1_url(l1)
.upgrades(upgrades)
.upgrades::<MockSeqVersions>(upgrades)
.build(),
)
.build();

let mut network = TestNetwork::new(config, MockSequencerVersions::new()).await;
let mut network = TestNetwork::new(config, bind_version).await;

let mut events = network.server.event_stream().await;

Expand All @@ -1543,15 +1630,12 @@ mod test {
// voting and finally the actual upgrade.
let new_version_first_view = loop {
let event = events.next().await.unwrap();

match event.event {
EventType::UpgradeProposal { proposal, .. } => {
let upgrade = proposal.data.upgrade_proposal;
let new_version = upgrade.new_version;
assert_eq!(
new_version,
<MockSequencerVersions as Versions>::Upgrade::VERSION
);
dbg!(&new_version);
assert_eq!(new_version, <MockSeqVersions as Versions>::Upgrade::VERSION);
break upgrade.new_version_first_view;
}
_ => continue,
Expand All @@ -1566,9 +1650,10 @@ mod test {
// Loop to wait on the upgrade itself.
loop {
// Get height as a proxy for view number. Height is always
// >= to view, especially using anvil. As a possible
// alternative we might loop on hotshot events here again
// and pull the view number off the event.
// >= to view. Especially when using Anvil, there should be little
// difference. As a possible alternative we might loop on
// hotshot events here again and pull the view number off
// the event.
let height = client
.get::<ViewNumber>("status/block-height")
.send()
Expand All @@ -1589,7 +1674,8 @@ mod test {

// ChainConfigs will eventually be resolved
if let Some(configs) = configs {
if height >= new_version_first_view {
dbg!(height, new_version_first_view);
if height > new_version_first_view {
for config in configs {
assert_eq!(config, chain_config_upgrade);
}
Expand Down
17 changes: 6 additions & 11 deletions sequencer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,8 +434,8 @@ pub mod testing {
eth_signature_key::EthKeyPair,
mock::MockStateCatchup,
v0::traits::{PersistenceOptions, StateCatchup},
Event, FeeAccount, Leaf, MarketplaceVersion, MockSequencerVersions, Payload, PubKey,
SeqTypes, Transaction, Upgrade,
Event, FeeAccount, Leaf, MarketplaceVersion, Payload, PubKey, SeqTypes, Transaction,
Upgrade,
};
use futures::{
future::join_all,
Expand Down Expand Up @@ -640,19 +640,14 @@ pub mod testing {
self
}

pub fn upgrades(mut self, upgrades: BTreeMap<Version, Upgrade>) -> Self {
pub fn upgrades<V: Versions>(mut self, upgrades: BTreeMap<Version, Upgrade>) -> Self {
let upgrade = upgrades.get(&<V as Versions>::Upgrade::VERSION).unwrap();
upgrade.set_hotshot_config_parameters(&mut self.config);
self.upgrades = upgrades;
self
}

pub fn build(mut self) -> TestConfig<NUM_NODES> {
if let Some(upgrade) = self
.upgrades
.get(&<MockSequencerVersions as Versions>::Upgrade::VERSION)
{
upgrade.set_hotshot_config_parameters(&mut self.config)
}

pub fn build(self) -> TestConfig<NUM_NODES> {
TestConfig {
config: self.config,
priv_keys: self.priv_keys,
Expand Down
11 changes: 11 additions & 0 deletions types/src/v0/v0_1/instance_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ pub enum UpgradeType {
Marketplace { chain_config: ChainConfig },
}

impl UpgradeType {
/// Get the upgrade data from `UpgradeType`. As of this writing,
/// we are only concerned w/ `ChainConfig`.
pub fn data(&self) -> ChainConfig {
match self {
UpgradeType::Fee { chain_config } => *chain_config,
UpgradeType::Marketplace { chain_config } => *chain_config,
}
}
}

/// Represents an upgrade based on time (unix timestamp).
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct TimeBasedUpgrade {
Expand Down

0 comments on commit 180b99c

Please sign in to comment.