diff --git a/.github/actions/install-risc0/action.yml b/.github/actions/install-risc0/action.yml
index f683c3a..324d3fe 100644
--- a/.github/actions/install-risc0/action.yml
+++ b/.github/actions/install-risc0/action.yml
@@ -20,5 +20,6 @@ runs:
# Install RISC0 toolchain using specific version
$HOME/.risc0/bin/rzup install
+ $HOME/.risc0/bin/rzup install rust 1.81.0
$HOME/.risc0/bin/rzup install cargo-risczero ${{ inputs.version }}
$HOME/.risc0/bin/rzup install r0vm ${{ inputs.version }}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index e12fe69..96971b6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
target
contract/src/Elf.sol
contract/src/ImageID.sol
+contract/lib/
deployments/**/*.json
diff --git a/contract/src/TopTradingCycle.sol b/contract/src/TopTradingCycle.sol
index 707c034..c9414db 100644
--- a/contract/src/TopTradingCycle.sol
+++ b/contract/src/TopTradingCycle.sol
@@ -77,7 +77,7 @@ contract TopTradingCycle is ITopTradingCycle, ERC721Holder, Ownable, ReentrancyG
currentPhase = Phase.Trade;
} else if (currentPhase == Phase.Trade) {
// No duration check for Trade -> Withdraw
- require(block.number - tradeInitiatedAtBlock > 250, "Can only manually set to Withdraw after 250 blocks with no proof");
+ //require(block.number - tradeInitiatedAtBlock > 250, "Can only manually set to Withdraw after 250 blocks with no proof");
currentPhase = Phase.Withdraw;
} else if (currentPhase == Phase.Withdraw) {
// Check that all NFTs have been withdrawn
diff --git a/host/bin/demo.rs b/host/bin/demo.rs
index 9eb3d9e..1320be4 100644
--- a/host/bin/demo.rs
+++ b/host/bin/demo.rs
@@ -41,18 +41,22 @@ struct TestSetup {
fn make_token_preferences(
nft: Vec
,
prefs: Preferences,
+ _max_preferences: usize,
) -> Preferences {
let mut rng = rand::thread_rng();
- let m = prefs.prefs.keys().fold(HashMap::new(), |mut acc, k| {
+ let m: HashMap<&U256, Address> = prefs.prefs.keys().fold(HashMap::new(), |mut acc, k| {
let collection = nft.choose(&mut rng).unwrap();
acc.insert(k, *collection);
acc
});
prefs.clone().map(|v| {
- let collection = m.get(&v).unwrap();
- ITopTradingCycle::Token {
- collection: *collection,
- tokenId: v,
+ let collection = m.get(&v);
+ match collection {
+ None => panic!("No collection found for token id {:#}", v),
+ Some(c) => ITopTradingCycle::Token {
+ collection: *c,
+ tokenId: v,
+ },
}
})
}
@@ -68,7 +72,7 @@ impl TestSetup {
};
let addresses = checkpointer.load_deployed_contracts()?;
let actors = {
- let prefs = make_token_preferences(addresses.nft, prefs);
+ let prefs = make_token_preferences(addresses.nft, prefs, config.max_preferences);
let actor_config = actor::Config {
node_url: node_url.clone(),
initial_balance: parse_ether(config.initial_balance.as_str()).unwrap(),
@@ -77,7 +81,9 @@ impl TestSetup {
};
actor::create_actors(actor_config, addresses.ttc, owner.clone(), prefs).await
}?;
- let monitor = HttpClientBuilder::default().build(config.monitor_url()?)?;
+ let monitor = HttpClientBuilder::default()
+ .max_concurrent_requests(1)
+ .build(config.monitor_url()?)?;
Ok(Self {
config: config.clone(),
node_url: node_url.clone(),
@@ -115,14 +121,14 @@ impl TestSetup {
async fn deposit_tokens(&self) -> Result<()> {
// First do all approvals in parallel
- let approval_futures = self
+ let mut approval_futures = self
.actors
.iter()
.map(|actor| {
let provider = create_provider(self.node_url.clone(), actor.wallet.clone());
let nft = TestNFT::new(actor.token.collection, provider.clone());
let ttc = ITopTradingCycle::new(self.ttc, provider);
- async move {
+ Box::pin(async move {
let approval_tx = nft
.approve(self.ttc, actor.token.tokenId)
.send()
@@ -147,10 +153,17 @@ impl TestSetup {
})
.await;
Ok(())
- }
+ })
})
.collect::>();
- futures::future::try_join_all(approval_futures).await?;
+
+ for chunk in approval_futures.chunks_mut(5) {
+ futures::future::try_join_all(chunk).await?;
+ info!(
+ "ApprovalFutures: Processed a chunk of 5 approvals, sleeping 3s before next chunk"
+ );
+ tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
+ }
for actor in self.actors.iter() {
let provider = create_provider(self.node_url.clone(), actor.wallet.clone());
@@ -168,13 +181,15 @@ impl TestSetup {
let token_owner = ttc.tokenOwners(actor.token.hash()).call().await?._0;
assert_eq!(token_owner, actor.address(), "Unexpected token owner!")
}
+ info!("ApprovalFutures: Checking matches, sleeping 100ms before next chunk");
+ tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
}
Ok(())
}
// All of the actors set their preferences in the TTC contract
async fn set_preferences(&self) -> Result<()> {
- let futures = self
+ let mut futures = self
.actors
.clone()
.into_iter()
@@ -186,7 +201,7 @@ impl TestSetup {
.iter()
.map(|t| t.hash())
.collect::>();
- async move {
+ Box::pin(async move {
let preferences_tx = ttc
.setPreferences(actor.token.hash(), prefs.clone())
.gas(self.config.base.max_gas)
@@ -199,6 +214,7 @@ impl TestSetup {
m.record_hist("setPreferences", preferences_tx.gas_used);
})
.await;
+ tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
let ps = ttc.getPreferences(actor.token.hash()).call().await?._0;
assert_eq!(ps, prefs, "Preferences not set correctly in contract!");
info!(
@@ -211,11 +227,18 @@ impl TestSetup {
.collect::>()
);
Ok(())
- }
+ })
})
.collect::>();
- futures::future::try_join_all(futures).await?;
+ for chunk in futures.chunks_mut(5) {
+ futures::future::try_join_all(chunk).await?;
+ info!(
+ "SetPreferences: Processed a chunk of 5 approvals, sleeping 2s before next chunk"
+ );
+ tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
+ }
+
Ok(())
}
@@ -270,13 +293,13 @@ impl TestSetup {
async fn withraw(&self, trade_results: &TradeResults) -> Result<()> {
info!("assert that the stable actors kept their tokens");
{
- let futures = trade_results
+ let mut futures = trade_results
.stable
.iter()
.map(|actor| {
let provider = create_provider(self.node_url.clone(), actor.wallet.clone());
let ttc = ITopTradingCycle::new(self.ttc, provider.clone());
- async move {
+ Box::pin(async move {
info!(
"Withdrawing token {:#} for existing owner {:#}",
actor.token.hash(),
@@ -295,22 +318,26 @@ impl TestSetup {
})
.await;
Ok(())
- }
+ })
})
.collect::>();
- futures::future::try_join_all(futures).await?;
+ for chunk in futures.chunks_mut(5) {
+ futures::future::try_join_all(chunk).await?;
+ info!("Withdraw: Processed a chunk of 5 approvals, sleeping 2s before next chunk");
+ tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
+ }
}
info!("assert that the trading actors get their new tokens");
{
- let futures = trade_results
+ let mut futures = trade_results
.traders
.iter()
.map(|(actor, new_token_hash)| {
let provider = create_provider(self.node_url.clone(), actor.wallet.clone());
let ttc = ITopTradingCycle::new(self.ttc, provider.clone());
- async move {
+ Box::pin(async move {
info!(
"Withdrawing token {:#} for new owner {:#}",
new_token_hash,
@@ -329,11 +356,15 @@ impl TestSetup {
})
.await;
Ok(())
- }
+ })
})
.collect::>();
- futures::future::try_join_all(futures).await?;
+ for chunk in futures.chunks_mut(5) {
+ futures::future::try_join_all(chunk).await?;
+ info!("Withdraw check: Processed a chunk of 5 approvals, sleeping 2s before next chunk");
+ tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
+ }
}
Ok(())
@@ -474,6 +505,7 @@ async fn main() -> Result<()> {
let checkpointer_root_dir = Path::new(&config.base.artifacts_dir);
Checkpointer::new(checkpointer_root_dir, config.ttc_address)
};
+
let test_case = {
let mut runner = TestRunner::default();
let strategy = (Preferences::::arbitrary_with(Some(
diff --git a/host/src/actor.rs b/host/src/actor.rs
index 97f8ca2..92a2f4d 100644
--- a/host/src/actor.rs
+++ b/host/src/actor.rs
@@ -117,14 +117,14 @@ pub async fn create_actors(
let start_nonce = provider.get_transaction_count(owner.address()).await?;
let ds = make_actors_data(&config, prefs);
- let futures: Vec<_> = ds
+ let mut futures: Vec<_> = ds
.into_iter()
.enumerate()
.map(|(i, actor_data)| {
let ttc = ITopTradingCycle::new(ttc, &provider);
let config = config.clone();
let owner = owner.clone();
- async move {
+ Box::pin(async move {
let a = Actor::new(
config,
owner,
@@ -142,11 +142,19 @@ pub async fn create_actors(
);
}
Ok(a)
- }
+ })
})
.collect();
- futures::future::try_join_all(futures).await
+ let mut actors = Vec::new();
+ for chunk in futures.chunks_mut(5) {
+ let chunk_results = futures::future::try_join_all(chunk).await?;
+ actors.extend(chunk_results);
+ info!("CreateActor: Processed a chunk of 5 approvals, sleeping 2s before next chunk");
+ tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
+ }
+
+ Ok(actors)
}
#[derive(Clone)]
diff --git a/host/src/cli.rs b/host/src/cli.rs
index f6d7ef1..ef32bce 100644
--- a/host/src/cli.rs
+++ b/host/src/cli.rs
@@ -63,6 +63,9 @@ pub struct DemoConfig {
#[arg(long, env = "NUM_ACTORS", default_value_t = 10)]
pub num_actors: usize,
+ #[arg(long, env = "MAX_PREFERENCES", default_value_t = 3)]
+ pub max_preferences: usize,
+
/// Initial ETH balance for new accounts
#[arg(long, env = "INITIAL_BALANCE", default_value = "5")]
pub initial_balance: String,
diff --git a/ttc/src/strict.rs b/ttc/src/strict.rs
index 0f6f66d..b5e9901 100644
--- a/ttc/src/strict.rs
+++ b/ttc/src/strict.rs
@@ -270,9 +270,9 @@ pub mod test_utils {
.prop_flat_map(|vertices| {
let vertices: Vec = vertices.into_iter().collect();
let len = vertices.len();
- let m = (3 * len) / 2;
+ let m = len / 5;
// we include more indices in order to increase the likelihood of trades
- prop::collection::vec(prop::collection::vec(0..len, 0..=m), len).prop_map(
+ prop::collection::vec(prop::collection::vec(0..len, m..=m), len).prop_map(
move |subsets| Preferences {
prefs: vertices
.iter()