From 6db4684713254d809d57db84b67b8ca199a71eb2 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Thu, 11 Jan 2024 11:12:13 -0700 Subject: [PATCH 01/20] feat: stream into process --- arbiter-core/src/data_collection.rs | 42 ++++++++++---------- arbiter-engine/src/agent.rs | 35 ++++++++++++++-- arbiter-engine/src/examples/timed_message.rs | 34 ++++++++-------- 3 files changed, 69 insertions(+), 42 deletions(-) diff --git a/arbiter-core/src/data_collection.rs b/arbiter-core/src/data_collection.rs index e17fd1dd..c22fff07 100644 --- a/arbiter-core/src/data_collection.rs +++ b/arbiter-core/src/data_collection.rs @@ -365,32 +365,34 @@ impl EventLogger { } /// Returns a stream of the serialized events. - pub fn stream(self) -> Pin + Send + 'static>> { - let receiver = self.receiver.clone().unwrap(); - - let stream = async_stream::stream! { - while let Ok(broadcast) = receiver.recv() { - match broadcast { - Broadcast::StopSignal => { - trace!("`EventLogger` has seen a stop signal"); - break; - } - Broadcast::Event(event) => { - trace!("`EventLogger` received an event"); - let ethers_logs = revm_logs_to_ethers_logs(event); - for log in ethers_logs { - for (_id, (filter, decoder)) in self.decoder.iter() { - if filter.filter_address(&log) && filter.filter_topics(&log) { - yield decoder(&log.clone().into()); + pub fn stream(self) -> Option + Send + 'static>>> { + if let Some(receiver) = self.receiver.clone() { + let stream = async_stream::stream! { + while let Ok(broadcast) = receiver.recv() { + match broadcast { + Broadcast::StopSignal => { + trace!("`EventLogger` has seen a stop signal"); + break; + } + Broadcast::Event(event) => { + trace!("`EventLogger` received an event"); + let ethers_logs = revm_logs_to_ethers_logs(event); + for log in ethers_logs { + for (_id, (filter, decoder)) in self.decoder.iter() { + if filter.filter_address(&log) && filter.filter_topics(&log) { + yield decoder(&log.clone().into()); + } } } } } } - } - }; + }; - Box::pin(stream) + Some(Box::pin(stream)) + } else { + None + } } } diff --git a/arbiter-engine/src/agent.rs b/arbiter-engine/src/agent.rs index 19c81f58..e12d42ba 100644 --- a/arbiter-engine/src/agent.rs +++ b/arbiter-engine/src/agent.rs @@ -16,7 +16,7 @@ //! The agent module contains the core agent abstraction for the Arbiter Engine. -use std::{fmt::Debug, pin::Pin, sync::Arc}; +use std::{clone, fmt::Debug, pin::Pin, sync::Arc}; use arbiter_core::{data_collection::EventLogger, middleware::RevmMiddleware}; use ethers::contract::{EthLogDecode, Event}; @@ -94,6 +94,8 @@ pub struct Agent { async_broadcast::Sender, async_broadcast::Receiver, ), + + broadcast_task: Option + Send>>>>, } impl Agent { @@ -111,6 +113,7 @@ impl Agent { behavior_engines: None, distributor, behavior_tasks: None, + broadcast_task: None, } } @@ -141,13 +144,15 @@ impl Agent { // pipelining. #[allow(unused)] pub(crate) fn start_event_stream(&mut self) -> Pin + Send + '_>> { - let event_stream = self.event_streamer.take().unwrap().stream(); let message_stream = self .messager .stream() .map(|msg| serde_json::to_string(&msg).unwrap_or_else(|e| e.to_string())); - - Box::pin(futures::stream::select(event_stream, message_stream)) + if let Some(event_stream) = self.event_streamer.take().unwrap().stream() { + Box::pin(futures::stream::select(event_stream, message_stream)) + } else { + Box::pin(message_stream) + } } } @@ -191,6 +196,27 @@ impl StateMachine for Agent { State::Processing => { trace!("Agent is processing."); self.state = state; + let messager = Box::leak(Box::new(self.messager.clone())); // TODO: We shouldn't have to do box leak + let message_stream = messager + .stream() + .map(|msg| serde_json::to_string(&msg).unwrap_or_else(|e| e.to_string())); + + let eth_event_stream = self.event_streamer.take().unwrap().stream(); + + let mut event_stream: Pin + Send + '_>> = + if let Some(event_stream) = eth_event_stream { + Box::pin(futures::stream::select(event_stream, message_stream)) + } else { + Box::pin(message_stream) + }; + + let sender = self.distributor.0.clone(); + self.broadcast_task = Some(tokio::spawn(async move { + while let Some(event) = event_stream.next().await { + sender.broadcast(event).await.unwrap(); + } + event_stream + })); let mut behavior_engines = self.behavior_engines.take().unwrap(); for engine in behavior_engines.iter_mut() { engine.run_state(state); @@ -210,6 +236,7 @@ impl StateMachine for Agent { } async fn transition(&mut self) { + // TODO: Might need to handle the broadcast_task here now. self.behavior_engines = Some( self.behavior_tasks .take() diff --git a/arbiter-engine/src/examples/timed_message.rs b/arbiter-engine/src/examples/timed_message.rs index 919ad041..ce11455a 100644 --- a/arbiter-engine/src/examples/timed_message.rs +++ b/arbiter-engine/src/examples/timed_message.rs @@ -18,11 +18,12 @@ struct TimedMessage { impl Behavior for TimedMessage { async fn process(&mut self, event: Message) { trace!("Processing event."); - let message = Message { - from: "agent".to_owned(), - to: To::Agent("agent".to_owned()), - data: "Hello, world!".to_owned(), - }; + if event.data != self.message.data { + return; + } else { + trace!("Event matches message."); + trace!("We received: {:?}\n inside the behavior itself", event); + } tokio::time::sleep(std::time::Duration::from_secs(self.delay)).await; // TODO: send a message @@ -57,13 +58,15 @@ async fn echoer() { let agent = world.create_agent(AGENT_ID); + let message = Message { + from: "agent".to_owned(), + to: To::Agent("agent".to_owned()), + data: "Hello, world!".to_owned(), + }; + let behavior = TimedMessage { - delay: 2, - message: Message { - from: "agent".to_owned(), - to: To::Agent("agent".to_owned()), - data: "Hello, world!".to_owned(), - }, + delay: 1, + message: message.clone(), }; agent.add_behavior(behavior); @@ -77,13 +80,8 @@ async fn echoer() { world.run_state(State::Processing); - let message = Message { - from: "agent".to_owned(), - to: To::Agent("agent".to_owned()), - data: "Start".to_owned(), - }; - let send_result = messager.send(message).await; - tracing::debug!("Start message sent {:?}", send_result); + messager.send(message).await; + tracing::debug!("Start message sent from main thread."); tokio::time::sleep(std::time::Duration::from_secs(1)).await; From e54b275899c1a527edac1891022321e53e1e3c4b Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Thu, 11 Jan 2024 11:32:39 -0700 Subject: [PATCH 02/20] example: timed message --- arbiter-engine/src/examples/timed_message.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arbiter-engine/src/examples/timed_message.rs b/arbiter-engine/src/examples/timed_message.rs index ce11455a..f916a2a7 100644 --- a/arbiter-engine/src/examples/timed_message.rs +++ b/arbiter-engine/src/examples/timed_message.rs @@ -12,6 +12,7 @@ use crate::{ struct TimedMessage { delay: u64, message: Message, + messager: Messager, } #[async_trait::async_trait] @@ -21,8 +22,8 @@ impl Behavior for TimedMessage { if event.data != self.message.data { return; } else { - trace!("Event matches message."); - trace!("We received: {:?}\n inside the behavior itself", event); + trace!("Event matches message. Sending a new message."); + self.messager.send(self.message.clone()).await; } tokio::time::sleep(std::time::Duration::from_secs(self.delay)).await; @@ -56,6 +57,8 @@ async fn echoer() { let mut world = World::new("world"); + let messager = world.messager.clone(); + let agent = world.create_agent(AGENT_ID); let message = Message { @@ -67,6 +70,7 @@ async fn echoer() { let behavior = TimedMessage { delay: 1, message: message.clone(), + messager, }; agent.add_behavior(behavior); From c34a3cd47490a1b0a6a9dde8e17899e1d16ef48c Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Thu, 11 Jan 2024 11:41:47 -0700 Subject: [PATCH 03/20] example ping pong --- arbiter-engine/src/examples/timed_message.rs | 71 ++++++++++++++++++-- 1 file changed, 67 insertions(+), 4 deletions(-) diff --git a/arbiter-engine/src/examples/timed_message.rs b/arbiter-engine/src/examples/timed_message.rs index f916a2a7..410af109 100644 --- a/arbiter-engine/src/examples/timed_message.rs +++ b/arbiter-engine/src/examples/timed_message.rs @@ -11,7 +11,8 @@ use crate::{ struct TimedMessage { delay: u64, - message: Message, + receive_data: String, + send_data: String, messager: Messager, } @@ -19,11 +20,16 @@ struct TimedMessage { impl Behavior for TimedMessage { async fn process(&mut self, event: Message) { trace!("Processing event."); - if event.data != self.message.data { + if event.data != self.receive_data { return; } else { trace!("Event matches message. Sending a new message."); - self.messager.send(self.message.clone()).await; + let message = Message { + from: "agent".to_owned(), + to: To::Agent("agent".to_owned()), + data: self.send_data.clone(), + }; + self.messager.send(message).await; } tokio::time::sleep(std::time::Duration::from_secs(self.delay)).await; @@ -69,7 +75,8 @@ async fn echoer() { let behavior = TimedMessage { delay: 1, - message: message.clone(), + receive_data: "Hello, world!".to_owned(), + send_data: "Hello, world!".to_owned(), messager, }; agent.add_behavior(behavior); @@ -91,3 +98,59 @@ async fn echoer() { world.transition().await; } + +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn ping_pong() { + std::env::set_var("RUST_LOG", "trace"); + tracing_subscriber::fmt::init(); + + let mut world = World::new("world"); + + let messager = world.messager.clone(); + + let agent = world.create_agent(AGENT_ID); + + let behavior_ping = TimedMessage { + delay: 1, + receive_data: "pong".to_owned(), + send_data: "ping".to_owned(), + messager: messager.clone(), + }; + agent.add_behavior(behavior_ping); + + let message_pong = Message { + from: "agent".to_owned(), + to: To::Agent("agent".to_owned()), + data: "pong".to_owned(), + }; + let behavior_pong = TimedMessage { + delay: 1, + receive_data: "ping".to_owned(), + send_data: "pong".to_owned(), + messager, + }; + agent.add_behavior(behavior_pong); + + tracing::debug!("Starting world."); + let messager = world.messager.clone(); + world.run_state(State::Syncing); + world.transition().await; + + world.run_state(State::Startup); + world.transition().await; + + world.run_state(State::Processing); + + let init_message = Message { + from: "agent".to_owned(), + to: To::Agent("agent".to_owned()), + data: "ping".to_owned(), + }; + + messager.send(init_message).await; + tracing::debug!("Start message sent from main thread."); + + tokio::time::sleep(std::time::Duration::from_secs(1)).await; + + world.transition().await; +} From d41c9c500c9ad087a46e86a84c7d60c515e6017d Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Thu, 11 Jan 2024 14:06:15 -0700 Subject: [PATCH 04/20] feat: double agent test --- arbiter-engine/src/agent.rs | 109 ++++++++++--------- arbiter-engine/src/examples/timed_message.rs | 96 +++++++++++----- arbiter-engine/src/world.rs | 5 +- 3 files changed, 127 insertions(+), 83 deletions(-) diff --git a/arbiter-engine/src/agent.rs b/arbiter-engine/src/agent.rs index e12d42ba..c708ae49 100644 --- a/arbiter-engine/src/agent.rs +++ b/arbiter-engine/src/agent.rs @@ -100,7 +100,7 @@ pub struct Agent { impl Agent { /// Produces a new agent with the given identifier. - pub(crate) fn connect(id: &str, world: &World) -> Self { + pub fn new(id: &str, world: &World) -> Self { let messager = world.messager.for_agent(id); let client = RevmMiddleware::new(&world.environment, Some(id)).unwrap(); let distributor = async_broadcast::broadcast(512); @@ -118,18 +118,19 @@ impl Agent { } /// Adds an Ethereum event to the agent's event streamer. - pub fn add_event( - &mut self, + pub fn with_event( + mut self, event: Event, RevmMiddleware, D>, - ) { + ) -> Self { self.event_streamer = Some(self.event_streamer.take().unwrap().add_stream(event)); + self } /// Adds a behavior to the agent that it will run. - pub fn add_behavior( - &mut self, + pub fn with_behavior( + mut self, behavior: impl Behavior + 'static, - ) { + ) -> Self { let event_receiver = self.distributor.0.new_receiver(); let engine = Engine::new(behavior, event_receiver); @@ -137,7 +138,8 @@ impl Agent { engines.push(Box::new(engine)); } else { self.behavior_engines = Some(vec![Box::new(engine)]); - } + }; + self } // TODO: This is unused for now, but we will use it in the future for the event @@ -249,6 +251,7 @@ impl StateMachine for Agent { } } +#[ignore = "This test should be adjusted or possibly removed as it isn't really testing anything now"] #[cfg(test)] mod tests { use arbiter_bindings::bindings::arbiter_token::ArbiterToken; @@ -259,49 +262,51 @@ mod tests { #[ignore] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn streaming() { - std::env::set_var("RUST_LOG", "trace"); - tracing_subscriber::fmt::init(); - - let mut world = World::new("world"); - let messager = world.messager.clone(); - println!( - "Receiver count: {:?}", - messager.broadcast_sender.receiver_count() - ); - - let agent = world.create_agent("agent"); - - let arb = ArbiterToken::deploy( - agent.client.clone(), - ("ArbiterToken".to_string(), "ARB".to_string(), 18u8), - ) - .unwrap() - .send() - .await - .unwrap(); - - agent.add_event(arb.events()); - let address = agent.client.address(); - let mut streamer = agent.start_event_stream(); - - for _ in 0..5 { - messager - .send(Message { - from: "me".to_string(), - to: messager::To::All, - data: "hello".to_string(), - }) - .await; - arb.approve(address, U256::from(1)) - .send() - .await - .unwrap() - .await - .unwrap(); - } - - while let Some(msg) = streamer.next().await { - println!("Printing message in test: {:?}", msg); - } + todo!() + // std::env::set_var("RUST_LOG", "trace"); + // tracing_subscriber::fmt::init(); + + // let mut world = World::new("world"); + // let messager = world.messager.clone(); + // println!( + // "Receiver count: {:?}", + // messager.broadcast_sender.receiver_count() + // ); + + // let agent = Agent::new("agent", &world); + // // world.add_agent(agent); // DON'T NEED TO DO THIS IN THIS EXAMPLE? + + // let arb = ArbiterToken::deploy( + // agent.client.clone(), + // ("ArbiterToken".to_string(), "ARB".to_string(), 18u8), + // ) + // .unwrap() + // .send() + // .await + // .unwrap(); + + // let agent = agent.with_event(arb.events()); + // let address = agent.client.address(); + // let mut streamer = agent.start_event_stream(); + + // for _ in 0..5 { + // messager + // .send(Message { + // from: "me".to_string(), + // to: messager::To::All, + // data: "hello".to_string(), + // }) + // .await; + // arb.approve(address, U256::from(1)) + // .send() + // .await + // .unwrap() + // .await + // .unwrap(); + // } + + // while let Some(msg) = streamer.next().await { + // println!("Printing message in test: {:?}", msg); + // } } } diff --git a/arbiter-engine/src/examples/timed_message.rs b/arbiter-engine/src/examples/timed_message.rs index 410af109..f7c31d4f 100644 --- a/arbiter-engine/src/examples/timed_message.rs +++ b/arbiter-engine/src/examples/timed_message.rs @@ -4,6 +4,7 @@ const AGENT_ID: &str = "agent"; use super::*; use crate::{ + agent::Agent, machine::{Behavior, Engine, State, StateMachine}, messager::To, world::World, @@ -25,8 +26,8 @@ impl Behavior for TimedMessage { } else { trace!("Event matches message. Sending a new message."); let message = Message { - from: "agent".to_owned(), - to: To::Agent("agent".to_owned()), + from: self.messager.id.clone().unwrap(), + to: To::All, data: self.send_data.clone(), }; self.messager.send(message).await; @@ -63,26 +64,66 @@ async fn echoer() { let mut world = World::new("world"); + let agent = Agent::new(AGENT_ID, &world); + let behavior = TimedMessage { + delay: 1, + receive_data: "Hello, world!".to_owned(), + send_data: "Hello, world!".to_owned(), + messager: agent.messager.clone(), + }; + world.add_agent(agent.with_behavior(behavior)); + + tracing::debug!("Starting world."); let messager = world.messager.clone(); + world.run_state(State::Syncing); + world.transition().await; + + world.run_state(State::Startup); + world.transition().await; - let agent = world.create_agent(AGENT_ID); + world.run_state(State::Processing); let message = Message { - from: "agent".to_owned(), + from: "god".to_owned(), to: To::Agent("agent".to_owned()), data: "Hello, world!".to_owned(), }; + world.messager.send(message).await; + tracing::debug!("Start message sent from main thread."); - let behavior = TimedMessage { + tokio::time::sleep(std::time::Duration::from_secs(1)).await; + + world.transition().await; +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn ping_pong() { + std::env::set_var("RUST_LOG", "trace"); + tracing_subscriber::fmt::init(); + + let mut world = World::new("world"); + + let agent = Agent::new(AGENT_ID, &world); + let behavior_ping = TimedMessage { delay: 1, - receive_data: "Hello, world!".to_owned(), - send_data: "Hello, world!".to_owned(), - messager, + receive_data: "pong".to_owned(), + send_data: "ping".to_owned(), + messager: agent.messager.clone(), }; - agent.add_behavior(behavior); + let behavior_pong = TimedMessage { + delay: 1, + receive_data: "ping".to_owned(), + send_data: "pong".to_owned(), + messager: agent.messager.clone(), + }; + + world.add_agent( + agent + .with_behavior(behavior_ping) + .with_behavior(behavior_pong), + ); tracing::debug!("Starting world."); - let messager = world.messager.clone(); world.run_state(State::Syncing); world.transition().await; @@ -91,7 +132,12 @@ async fn echoer() { world.run_state(State::Processing); - messager.send(message).await; + let init_message = Message { + from: "god".to_owned(), + to: To::Agent("agent".to_owned()), + data: "ping".to_owned(), + }; + world.messager.send(init_message).await; tracing::debug!("Start message sent from main thread."); tokio::time::sleep(std::time::Duration::from_secs(1)).await; @@ -100,36 +146,30 @@ async fn echoer() { } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn ping_pong() { +async fn ping_pong_two_agent() { std::env::set_var("RUST_LOG", "trace"); tracing_subscriber::fmt::init(); let mut world = World::new("world"); - let messager = world.messager.clone(); - - let agent = world.create_agent(AGENT_ID); - + let agent_ping = Agent::new("agent_ping", &world); let behavior_ping = TimedMessage { delay: 1, receive_data: "pong".to_owned(), send_data: "ping".to_owned(), - messager: messager.clone(), + messager: agent_ping.messager.clone(), }; - agent.add_behavior(behavior_ping); - let message_pong = Message { - from: "agent".to_owned(), - to: To::Agent("agent".to_owned()), - data: "pong".to_owned(), - }; + let agent_pong = Agent::new("agent_pong", &world); let behavior_pong = TimedMessage { delay: 1, receive_data: "ping".to_owned(), send_data: "pong".to_owned(), - messager, + messager: agent_pong.messager.clone(), }; - agent.add_behavior(behavior_pong); + + world.add_agent(agent_ping.with_behavior(behavior_ping)); + world.add_agent(agent_pong.with_behavior(behavior_pong)); tracing::debug!("Starting world."); let messager = world.messager.clone(); @@ -142,12 +182,12 @@ async fn ping_pong() { world.run_state(State::Processing); let init_message = Message { - from: "agent".to_owned(), - to: To::Agent("agent".to_owned()), + from: "god".to_owned(), + to: To::All, data: "ping".to_owned(), }; - messager.send(init_message).await; + world.messager.send(init_message).await; tracing::debug!("Start message sent from main thread."); tokio::time::sleep(std::time::Duration::from_secs(1)).await; diff --git a/arbiter-engine/src/world.rs b/arbiter-engine/src/world.rs index 9396f133..26d990ab 100644 --- a/arbiter-engine/src/world.rs +++ b/arbiter-engine/src/world.rs @@ -82,11 +82,10 @@ impl World { } /// Adds an agent to the world. - pub fn create_agent(&mut self, id: &str) -> &mut Agent { - let agent = Agent::connect(id, self); + pub fn add_agent(&mut self, agent: Agent) { + let id = agent.id.clone(); let agents = self.agents.as_mut().unwrap(); agents.insert(id.to_owned(), agent); - agents.get_mut(id).unwrap() } } From 08a86865809e2228523b22422770ef319bac0c67 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Thu, 11 Jan 2024 16:08:47 -0700 Subject: [PATCH 05/20] test gets stuck But this is cleaned up quite a bit and is almost there. --- arbiter-engine/src/agent.rs | 28 +- arbiter-engine/src/examples/timed_message.rs | 55 +- arbiter-engine/src/examples/token_minter.rs | 611 +++++++++---------- arbiter-engine/src/machine.rs | 12 +- arbiter-engine/src/world.rs | 20 +- 5 files changed, 318 insertions(+), 408 deletions(-) diff --git a/arbiter-engine/src/agent.rs b/arbiter-engine/src/agent.rs index c708ae49..ec00f27b 100644 --- a/arbiter-engine/src/agent.rs +++ b/arbiter-engine/src/agent.rs @@ -141,25 +141,11 @@ impl Agent { }; self } - - // TODO: This is unused for now, but we will use it in the future for the event - // pipelining. - #[allow(unused)] - pub(crate) fn start_event_stream(&mut self) -> Pin + Send + '_>> { - let message_stream = self - .messager - .stream() - .map(|msg| serde_json::to_string(&msg).unwrap_or_else(|e| e.to_string())); - if let Some(event_stream) = self.event_streamer.take().unwrap().stream() { - Box::pin(futures::stream::select(event_stream, message_stream)) - } else { - Box::pin(message_stream) - } - } } #[async_trait::async_trait] impl StateMachine for Agent { + #[tracing::instrument(skip(self), fields(id = self.id))] fn run_state(&mut self, state: State) { match state { State::Uninitialized => { @@ -167,7 +153,7 @@ impl StateMachine for Agent { } State::Syncing => { self.state = state; - trace!("Agent is syncing."); + debug!("Agent is syncing."); let mut behavior_engines = self.behavior_engines.take().unwrap(); for engine in behavior_engines.iter_mut() { engine.run_state(state); @@ -181,7 +167,7 @@ impl StateMachine for Agent { }))); } State::Startup => { - trace!("Agent is starting up."); + debug!("Agent is starting up."); self.state = state; let mut behavior_engines = self.behavior_engines.take().unwrap(); for engine in behavior_engines.iter_mut() { @@ -196,7 +182,7 @@ impl StateMachine for Agent { }))); } State::Processing => { - trace!("Agent is processing."); + debug!("Agent is processing."); self.state = state; let messager = Box::leak(Box::new(self.messager.clone())); // TODO: We shouldn't have to do box leak let message_stream = messager @@ -207,14 +193,17 @@ impl StateMachine for Agent { let mut event_stream: Pin + Send + '_>> = if let Some(event_stream) = eth_event_stream { + trace!("Merging event streams."); Box::pin(futures::stream::select(event_stream, message_stream)) } else { + trace!("Agent only sees message stream."); Box::pin(message_stream) }; let sender = self.distributor.0.clone(); self.broadcast_task = Some(tokio::spawn(async move { while let Some(event) = event_stream.next().await { + println!("Broadcasting event through agent comms: {:?}", event); sender.broadcast(event).await.unwrap(); } event_stream @@ -238,7 +227,8 @@ impl StateMachine for Agent { } async fn transition(&mut self) { - // TODO: Might need to handle the broadcast_task here now. + // TODO: Might need to handle the broadcast_task here now especially if we need + // to stop. self.behavior_engines = Some( self.behavior_tasks .take() diff --git a/arbiter-engine/src/examples/timed_message.rs b/arbiter-engine/src/examples/timed_message.rs index f7c31d4f..cfcea9d4 100644 --- a/arbiter-engine/src/examples/timed_message.rs +++ b/arbiter-engine/src/examples/timed_message.rs @@ -34,7 +34,6 @@ impl Behavior for TimedMessage { } tokio::time::sleep(std::time::Duration::from_secs(self.delay)).await; - // TODO: send a message trace!("Processed event."); } @@ -51,11 +50,6 @@ impl Behavior for TimedMessage { } } -// // TODO: Can we combine the `world.run().await` through the `for task in -// tasks // {task.await}` step to make this DEVX super easy TODO: Having -// something like // an automatic impl of Start and Stop for all behaviors -// would be nice or load // that in as a default behavior of agents or -// something. #[ignore = "This is a work in progress and does not work and does not ever terminate."] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn echoer() { @@ -73,27 +67,17 @@ async fn echoer() { }; world.add_agent(agent.with_behavior(behavior)); - tracing::debug!("Starting world."); let messager = world.messager.clone(); - world.run_state(State::Syncing); - world.transition().await; - - world.run_state(State::Startup); - world.transition().await; - - world.run_state(State::Processing); + let task = world.run(); let message = Message { from: "god".to_owned(), to: To::Agent("agent".to_owned()), data: "Hello, world!".to_owned(), }; - world.messager.send(message).await; - tracing::debug!("Start message sent from main thread."); - - tokio::time::sleep(std::time::Duration::from_secs(1)).await; + messager.send(message).await; - world.transition().await; + task.await; } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] @@ -123,26 +107,17 @@ async fn ping_pong() { .with_behavior(behavior_pong), ); - tracing::debug!("Starting world."); - world.run_state(State::Syncing); - world.transition().await; - - world.run_state(State::Startup); - world.transition().await; - - world.run_state(State::Processing); + let messager = world.messager.clone(); + let task = world.run(); let init_message = Message { from: "god".to_owned(), to: To::Agent("agent".to_owned()), data: "ping".to_owned(), }; - world.messager.send(init_message).await; - tracing::debug!("Start message sent from main thread."); - - tokio::time::sleep(std::time::Duration::from_secs(1)).await; + messager.send(init_message).await; - world.transition().await; + task.await; } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] @@ -171,15 +146,8 @@ async fn ping_pong_two_agent() { world.add_agent(agent_ping.with_behavior(behavior_ping)); world.add_agent(agent_pong.with_behavior(behavior_pong)); - tracing::debug!("Starting world."); let messager = world.messager.clone(); - world.run_state(State::Syncing); - world.transition().await; - - world.run_state(State::Startup); - world.transition().await; - - world.run_state(State::Processing); + let task = world.run(); let init_message = Message { from: "god".to_owned(), @@ -187,10 +155,7 @@ async fn ping_pong_two_agent() { data: "ping".to_owned(), }; - world.messager.send(init_message).await; - tracing::debug!("Start message sent from main thread."); - - tokio::time::sleep(std::time::Duration::from_secs(1)).await; + messager.send(init_message).await; - world.transition().await; + task.await; } diff --git a/arbiter-engine/src/examples/token_minter.rs b/arbiter-engine/src/examples/token_minter.rs index 65886fe9..8a1abd00 100644 --- a/arbiter-engine/src/examples/token_minter.rs +++ b/arbiter-engine/src/examples/token_minter.rs @@ -1,335 +1,276 @@ -// use artemis_core::executors::mempool_executor::MempoolExecutor; -// use ethers::types::{transaction::request, Filter}; -// use tracing::error; - -// use super::*; -// use crate::{agent::BehaviorBuilder, messager::To}; - -// const TOKEN_ADMIN_ID: &str = "token_admin"; -// const REQUESTER_ID: &str = "requester"; -// const TOKEN_NAME: &str = "Arbiter Token"; -// const TOKEN_SYMBOL: &str = "ARB"; -// const TOKEN_DECIMALS: u8 = 18; - -// /// The token admin is responsible for handling token minting requests. -// #[derive(Clone, Debug)] -// pub struct TokenAdmin { -// /// The identifier of the token admin. -// pub id: String, // TODO: The strategies should not really need an ID. - -// pub token_data: HashMap, - -// /// The tokens that the token admin has control over. -// /// These will be deployed when we call `sync_state()` -// pub tokens: Option>>, - -// pub client: Arc, -// } - -// impl TokenAdmin { -// // TODO: I don't think we should pass in a client like this, probably, -// doing it // for testing purposes. Also using RevmMiddleware for testing -// purposes, // although this strategy should never be deployed -// /// Creates a new token admin with the given identifier. -// pub fn new(client: Arc) -> Self { -// Self { -// id: TOKEN_ADMIN_ID.to_owned(), -// token_data: HashMap::new(), -// tokens: None, -// client, -// } -// } - -// /// Adds a token to the token admin. -// pub fn add_token(&mut self, token_data: TokenData) { -// self.token_data.insert(token_data.name.clone(), token_data); -// } -// } - -// #[derive(Clone, Debug, Deserialize, Serialize)] -// pub struct TokenData { -// pub name: String, -// pub symbol: String, -// pub decimals: u8, -// pub address: Option
, -// } - -// /// Used as an action to ask what tokens are available. -// #[derive(Clone, Debug, Deserialize, Serialize)] -// pub enum TokenAdminQuery { -// /// Get the address of the token. -// AddressOf(String), - -// /// Mint tokens. -// MintRequest(MintRequest), -// } - -// /// Used as an action to mint tokens. -// #[derive(Clone, Debug, Deserialize, Serialize)] -// pub struct MintRequest { -// /// The token to mint. -// pub token: String, - -// /// The address to mint to. -// pub mint_to: Address, - -// /// The amount to mint. -// pub mint_amount: u64, -// } - -// #[async_trait::async_trait] -// impl Strategy for TokenAdmin { -// #[tracing::instrument(skip(self), fields(id = %self.id))] -// async fn sync_state(&mut self) -> Result<()> { -// debug!("Syncing state for `TokenAdmin`."); -// for token_data in self.token_data.values_mut() { -// let token = ArbiterToken::deploy( -// self.client.clone(), -// ( -// token_data.name.clone(), -// token_data.symbol.clone(), -// token_data.decimals, -// ), -// ) -// .unwrap() -// .send() -// .await -// .unwrap(); -// token_data.address = Some(token.address()); -// self.tokens -// .get_or_insert_with(HashMap::new) -// .insert(token_data.name.clone(), token.clone()); -// trace!("Deployed token: {:?}", token); -// } -// Ok(()) -// } - -// #[tracing::instrument(skip(self, event), fields(id = %self.id))] -// async fn process_event(&mut self, event: Message) -> Vec { -// trace!("Processing event for `TokenAdmin` {:?}.", event); -// if self.tokens.is_none() { -// error!("There were no tokens to deploy! You must add tokens to -// the token admin before running the simulation."); } - -// let query: TokenAdminQuery = -// serde_json::from_str(&event.data).unwrap(); trace!("Got query: {:?}", -// query); match query { -// TokenAdminQuery::AddressOf(token_name) => { -// trace!( -// "Getting address of token with name: {:?}", -// token_name.clone() -// ); -// let token_data = self.token_data.get(&token_name).unwrap(); -// let message = Message { -// from: self.id.to_owned(), -// to: To::Agent(event.from.clone()), // Reply back to -// sender data: serde_json::to_string(token_data).unwrap(), -// }; -// vec![MessageOrTx::Message(message)] -// } -// TokenAdminQuery::MintRequest(mint_request) => { -// trace!("Minting tokens: {:?}", mint_request); -// let token = self -// .tokens -// .as_ref() -// .unwrap() -// .get(&mint_request.token) -// .unwrap(); -// let tx = token -// .mint(mint_request.mint_to, -// U256::from(mint_request.mint_amount)) .tx; - -// vec![MessageOrTx::Tx(tx)] -// } -// } -// } -// } - -// /// The token requester is responsible for requesting tokens from the token -// /// admin. This agents is purely for testing purposes as far as I can tell. -// #[derive(Clone, Debug)] -// pub struct TokenRequester { -// /// The identifier of the token requester. -// pub id: String, - -// /// The tokens that the token requester has requested. -// pub token_data: TokenData, - -// /// The agent ID to request tokens to. -// pub request_to: String, - -// /// Client to have an address to receive token mint to and check balance -// pub client: Arc, -// } - -// impl TokenRequester { -// pub fn new(id: &str, client: Arc) -> Self { -// Self { -// id: id.to_owned(), -// token_data: TokenData { -// name: TOKEN_NAME.to_owned(), -// symbol: TOKEN_SYMBOL.to_owned(), -// decimals: TOKEN_DECIMALS, -// address: None, -// }, -// request_to: TOKEN_ADMIN_ID.to_owned(), -// client, -// } -// } -// } - -// #[async_trait::async_trait] -// impl Strategy for TokenRequester { -// #[tracing::instrument(skip(self), fields(id = %self.id))] -// async fn sync_state(&mut self) -> Result<()> { -// trace!("Syncing state for `TokenRequester` startup."); -// Ok(()) -// } - -// #[tracing::instrument(skip(self, event), fields(id = %self.id))] -// async fn process_event(&mut self, event: Message) -> Vec { -// trace!("Processing event for `TokenRequester` startup {:?}.", event); - -// if event.data == "Start" { -// trace!("Requesting address of token: {:?}", -// self.token_data.name); let message = Message { -// from: self.id.to_owned(), -// to: To::Agent(self.request_to.clone()), -// data: serde_json::to_string(&TokenAdminQuery::AddressOf( -// self.token_data.name.clone(), -// )) -// .unwrap(), -// }; -// vec![message] -// } else if event.data == "Mint" { -// trace!("Requesting mint of token: {:?}", self.token_data.name); -// let message = Message { -// from: self.id.to_owned(), -// to: To::Agent(self.request_to.clone()), -// data: -// serde_json::to_string(&TokenAdminQuery::MintRequest(MintRequest { -// token: self.token_data.name.clone(), mint_to: -// self.client.address(), mint_amount: 1, -// })) -// .unwrap(), -// }; -// vec![message] -// } else { -// vec![] -// } -// } -// } - -// #[async_trait::async_trait] -// impl Strategy for TokenRequester { -// #[tracing::instrument(skip(self), fields(id = %self.id))] -// async fn sync_state(&mut self) -> Result<()> { -// trace!("Syncing state for `TokenRequester` logger."); -// Ok(()) -// } - -// #[tracing::instrument(skip(self, event), fields(id = %self.id))] -// async fn process_event(&mut self, event: Log) -> Vec { -// trace!("Got event for `TokenRequester` logger: {:?}", event); -// std::thread::sleep(std::time::Duration::from_secs(1)); -// let message = Message { -// from: self.id.clone(), -// to: To::Agent(self.request_to.clone()), -// data: -// serde_json::to_string(&TokenAdminQuery::MintRequest(MintRequest { -// token: self.token_data.name.clone(), mint_to: -// self.client.address(), mint_amount: 1, -// })) -// .unwrap(), -// }; -// vec![message] -// } -// } - -// #[ignore] -// #[tokio::test(flavor = "multi_thread", worker_threads = 4)] -// async fn token_minter_simulation() { -// // TODO: Test outline, requester requests 1, 2, 3 tokens, and the test -// stops // when the balance is checked to be 6. -// std::env::set_var("RUST_LOG", "trace"); -// tracing_subscriber::fmt::init(); - -// let environment = EnvironmentBuilder::new().build(); -// let connection = Connection::from(&environment); -// let provider = Provider::new(connection); -// let mut world = World::new("test_world", provider); - -// // Create the token admin agent -// let token_admin_agent = world.create_agent(TOKEN_ADMIN_ID); -// let token_admin_client = RevmMiddleware::new(&environment, -// Some(TOKEN_ADMIN_ID)).unwrap(); let mut token_admin_strategy = -// TokenAdmin::new(token_admin_client.clone()); token_admin_strategy. -// add_token(TokenData { name: TOKEN_NAME.to_owned(), -// symbol: TOKEN_SYMBOL.to_owned(), -// decimals: TOKEN_DECIMALS, -// address: None, -// }); - -// let message_and_mempool_executor = MessageAndTransactionExecutor { -// messager: token_admin_agent.messager.clone(), -// transactor: Transactor { -// client: token_admin_client.clone(), -// }, -// }; - -// let token_admin_behavior = BehaviorBuilder::new() -// .add_collector(token_admin_agent.messager.clone()) -// .add_executor(message_and_mempool_executor) -// .add_strategy(token_admin_strategy.clone()) -// .build(); -// token_admin_agent.add_behavior(token_admin_behavior); - -// // Create the token requester agent -// let requester_agent = world.create_agent(REQUESTER_ID); -// let requester_client = RevmMiddleware::new(&environment, -// Some(REQUESTER_ID)).unwrap(); let token_requester = -// TokenRequester::new(REQUESTER_ID, requester_client.clone()); -// let query_behavior = BehaviorBuilder::new() -// .add_collector(requester_agent.messager.clone()) -// .add_executor(requester_agent.messager.clone()) -// .add_strategy(token_requester.clone()) -// .build(); -// requester_agent.add_behavior(query_behavior); -// let mint_behavior = BehaviorBuilder::new() -// .add_collector(LogCollector::new( -// requester_client.clone(), -// Filter::default(), -// // token_admin_strategy -// // .tokens -// // .as_ref() -// // .unwrap() -// // .get(&TOKEN_NAME.to_owned()) -// // .unwrap() -// // .transfer_filter() -// // .filter, -// )) -// .add_executor(requester_agent.messager.clone()) -// .add_strategy(token_requester) -// .build(); -// requester_agent.add_behavior(mint_behavior); - -// // Run the world and send the start message - -// let message = Message { -// from: "host".to_owned(), -// to: To::Agent(REQUESTER_ID.to_owned()), -// data: "Start".to_owned(), -// }; -// // TODO: Messages like this could probably be put in the `world.run()` -// world.messager.execute(message).await; - -// let message = Message { -// from: "host".to_owned(), -// to: To::Agent(REQUESTER_ID.to_owned()), -// data: "Mint".to_owned(), -// }; -// world.messager.execute(message).await; - -// let tasks = world.run().await; -// world.join().await; -// } +use std::str::FromStr; + +use anyhow::Context; +use arbiter_bindings::bindings::arbiter_token; +use ethers::{ + abi::token, + types::{transaction::request, Filter}, +}; +use tracing::error; + +use super::*; +use crate::{agent::Agent, machine::Behavior, messager::To, world::World}; + +const TOKEN_ADMIN_ID: &str = "token_admin"; +const REQUESTER_ID: &str = "requester"; +const TOKEN_NAME: &str = "Arbiter Token"; +const TOKEN_SYMBOL: &str = "ARB"; +const TOKEN_DECIMALS: u8 = 18; + +/// The token admin is responsible for handling token minting requests. +#[derive(Clone, Debug)] +pub struct TokenAdmin { + /// The identifier of the token admin. + pub token_data: HashMap, + + pub tokens: Option>>, + + // TODO: We should not have to have a client or a messager put here explicitly, they should + // come from the Agent the behavior is given to. + pub client: Arc, + pub messager: Messager, +} + +impl TokenAdmin { + pub fn new(client: Arc, messager: Messager) -> Self { + Self { + token_data: HashMap::new(), + tokens: None, + client, + messager, + } + } + + /// Adds a token to the token admin. + pub fn add_token(&mut self, token_data: TokenData) { + self.token_data.insert(token_data.name.clone(), token_data); + } +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct TokenData { + pub name: String, + pub symbol: String, + pub decimals: u8, + pub address: Option
, +} + +/// Used as an action to ask what tokens are available. +#[derive(Clone, Debug, Deserialize, Serialize)] +pub enum TokenAdminQuery { + /// Get the address of the token. + AddressOf(String), + + /// Mint tokens. + MintRequest(MintRequest), +} + +/// Used as an action to mint tokens. +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct MintRequest { + /// The token to mint. + pub token: String, + + /// The address to mint to. + pub mint_to: Address, + + /// The amount to mint. + pub mint_amount: u64, +} + +#[async_trait::async_trait] +impl Behavior for TokenAdmin { + #[tracing::instrument(skip(self), fields(id = self.messager.id.as_deref()))] + async fn sync(&mut self) { + for token_data in self.token_data.values_mut() { + let token = ArbiterToken::deploy( + self.client.clone(), + ( + token_data.name.clone(), + token_data.symbol.clone(), + token_data.decimals, + ), + ) + .unwrap() + .send() + .await + .unwrap(); + token_data.address = Some(token.address()); + self.tokens + .get_or_insert_with(HashMap::new) + .insert(token_data.name.clone(), token.clone()); + debug!("Deployed token: {:?}", token); + } + } + + #[tracing::instrument(skip(self), fields(id = self.messager.id.as_deref()))] + async fn process(&mut self, event: Message) { + if self.tokens.is_none() { + error!( + "There were no tokens to deploy! You must add tokens to +the token admin before running the simulation." + ); + } + + let query: TokenAdminQuery = serde_json::from_str(&event.data).unwrap(); + trace!("Got query: {:?}", query); + match query { + TokenAdminQuery::AddressOf(token_name) => { + trace!( + "Getting address of token with name: {:?}", + token_name.clone() + ); + let token_data = self.token_data.get(&token_name).unwrap(); + let message = Message { + from: self.messager.id.clone().unwrap(), + to: To::Agent(event.from.clone()), // Reply back to sender + data: serde_json::to_string(token_data).unwrap(), + }; + self.messager.send(message).await; + } + TokenAdminQuery::MintRequest(mint_request) => { + trace!("Minting tokens: {:?}", mint_request); + let token = self + .tokens + .as_ref() + .unwrap() + .get(&mint_request.token) + .unwrap(); + token + .mint(mint_request.mint_to, U256::from(mint_request.mint_amount)) + .send() + .await + .unwrap() + .await + .unwrap(); + } + } + } +} + +/// The token requester is responsible for requesting tokens from the token +/// admin. This agents is purely for testing purposes as far as I can tell. +#[derive(Clone, Debug)] +pub struct TokenRequester { + /// The tokens that the token requester has requested. + pub token_data: TokenData, + + /// The agent ID to request tokens to. + pub request_to: String, + + /// Client to have an address to receive token mint to and check balance + pub client: Arc, + + /// The messaging layer for the token requester. + pub messager: Messager, +} + +impl TokenRequester { + pub fn new(client: Arc, messager: Messager) -> Self { + Self { + token_data: TokenData { + name: TOKEN_NAME.to_owned(), + symbol: TOKEN_SYMBOL.to_owned(), + decimals: TOKEN_DECIMALS, + address: None, + }, + request_to: TOKEN_ADMIN_ID.to_owned(), + client, + messager, + } + } +} + +#[async_trait::async_trait] +impl Behavior for TokenRequester { + #[tracing::instrument(skip(self), fields(id = self.messager.id.as_deref()))] + async fn startup(&mut self) { + trace!("Requesting address of token: {:?}", self.token_data.name); + let message = Message { + from: self.messager.clone().id.unwrap(), + to: To::Agent(self.request_to.clone()), + data: serde_json::to_string(&TokenAdminQuery::AddressOf(self.token_data.name.clone())) + .unwrap(), + }; + self.messager.send(message).await; + } + + #[tracing::instrument(skip(self), fields(id = self.messager.id.as_deref()))] + async fn process(&mut self, event: Message) { + if let Ok(token_data) = serde_json::from_str::(&event.data) { + trace!("Got token data: {:?}", token_data); + trace!("Requesting first mint of token: {:?}", self.token_data.name); + let message = Message { + from: self.messager.clone().id.unwrap(), + to: To::Agent(self.request_to.clone()), + data: serde_json::to_string(&TokenAdminQuery::MintRequest(MintRequest { + token: self.token_data.name.clone(), + mint_to: self.client.address(), + mint_amount: 1, + })) + .unwrap(), + }; + self.messager.send(message).await; + } + } +} + +#[async_trait::async_trait] +impl Behavior for TokenRequester { + #[tracing::instrument(skip(self), fields(id = self.messager.id.as_deref()))] + async fn process(&mut self, event: arbiter_token::TransferFilter) { + trace!("Got event for `TokenRequester` logger: {:?}", event); + std::thread::sleep(std::time::Duration::from_secs(1)); + let message = Message { + from: self.messager.clone().id.unwrap(), + to: To::Agent(self.request_to.clone()), + data: serde_json::to_string(&TokenAdminQuery::MintRequest(MintRequest { + token: self.token_data.name.clone(), + mint_to: self.client.address(), + mint_amount: 1, + })) + .unwrap(), + }; + } +} + +#[ignore] +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] +async fn token_minter_simulation() { + std::env::set_var("RUST_LOG", "trace"); + tracing_subscriber::fmt::init(); + + let mut world = World::new("test_world"); + + // Create the token admin agent + let token_admin = Agent::new(TOKEN_ADMIN_ID, &world); + let mut token_admin_behavior = + TokenAdmin::new(token_admin.client.clone(), token_admin.messager.clone()); + token_admin_behavior.add_token(TokenData { + name: TOKEN_NAME.to_owned(), + symbol: TOKEN_SYMBOL.to_owned(), + decimals: TOKEN_DECIMALS, + address: None, + }); + world.add_agent(token_admin.with_behavior(token_admin_behavior)); + + // Create the token requester agent + let token_requester = Agent::new(REQUESTER_ID, &world); + let token_requester_behavior = TokenRequester::new( + token_requester.client.clone(), + token_requester.messager.clone(), + ); + let transfer_event = ArbiterToken::new( + Address::from_str("0x240a76d4c8a7dafc6286db5fa6b589e8b21fc00f").unwrap(), + token_requester.client.clone(), + ) + .transfer_filter(); + world.add_agent( + token_requester + .with_behavior::(token_requester_behavior.clone()) + .with_behavior::(token_requester_behavior) + .with_event(transfer_event), + ); + + world.run().await; +} diff --git a/arbiter-engine/src/machine.rs b/arbiter-engine/src/machine.rs index 6a9cb750..4e77808b 100644 --- a/arbiter-engine/src/machine.rs +++ b/arbiter-engine/src/machine.rs @@ -47,12 +47,12 @@ pub enum State { pub trait Behavior: Send + Sync + 'static { /// Used to bring the agent back up to date with the latest state of the /// world. This could be used if the world was stopped and later restarted. - async fn sync(&mut self); + async fn sync(&mut self) {} /// Used to start the agent. /// This is where the agent can engage in its specific start up activities /// that it can do given the current state of the world. - async fn startup(&mut self); + async fn startup(&mut self) {} /// Used to process events. /// This is where the agent can engage in its specific processing @@ -142,12 +142,14 @@ where let mut receiver = self.event_receiver.clone(); // TODO Could use Option::take() if we don't want to clone. self.behavior_task = Some(tokio::spawn(async move { while let Ok(event) = receiver.recv().await { - trace!("Behavior has gotten event: {:?}", event); + println!("Event received: {:?}", event); let decoding_result = serde_json::from_str::(&event); match decoding_result { Ok(event) => behavior.process(event).await, - Err(e) => { - tracing::error!("Error decoding event: {:?}", e); + Err(_e) => { + trace!( + "Event received by behavior that could not be deserialized." + ); continue; } } diff --git a/arbiter-engine/src/world.rs b/arbiter-engine/src/world.rs index 26d990ab..7ae969b7 100644 --- a/arbiter-engine/src/world.rs +++ b/arbiter-engine/src/world.rs @@ -17,6 +17,7 @@ use arbiter_core::environment::{builder::EnvironmentBuilder, Environment}; use futures_util::future::{join_all, JoinAll}; use tokio::task::JoinHandle; +use tracing::info; use super::*; use crate::{ @@ -87,6 +88,17 @@ impl World { let agents = self.agents.as_mut().unwrap(); agents.insert(id.to_owned(), agent); } + + pub async fn run(&mut self) { + self.run_state(State::Syncing); + self.transition().await; + + self.run_state(State::Startup); + self.transition().await; + + self.run_state(State::Processing); + self.transition().await; + } } #[async_trait::async_trait] @@ -97,7 +109,7 @@ impl StateMachine for World { unimplemented!("This never gets called.") } State::Syncing => { - trace!("World is syncing."); + info!("World is syncing."); let mut agents = self.agents.take().unwrap(); for agent in agents.values_mut() { agent.run_state(state); @@ -110,7 +122,7 @@ impl StateMachine for World { }))); } State::Startup => { - trace!("World is starting up."); + info!("World is starting up."); let mut agents = self.agents.take().unwrap(); for agent in agents.values_mut() { agent.run_state(state); @@ -123,7 +135,7 @@ impl StateMachine for World { }))); } State::Processing => { - trace!("World is starting up."); + info!("World is processing."); let mut agents = self.agents.take().unwrap(); for agent in agents.values_mut() { agent.run_state(state); @@ -136,7 +148,7 @@ impl StateMachine for World { }))); } State::Stopped => { - trace!("World is starting up."); + info!("World is starting up."); let mut agents = self.agents.take().unwrap(); for agent in agents.values_mut() { agent.run_state(state); From 3a444cec4b52853f327152ad68a22f919a32edc4 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Thu, 11 Jan 2024 16:51:23 -0700 Subject: [PATCH 06/20] removing eth event leads to different behavior --- arbiter-engine/src/examples/token_minter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbiter-engine/src/examples/token_minter.rs b/arbiter-engine/src/examples/token_minter.rs index 8a1abd00..2f5e3f6d 100644 --- a/arbiter-engine/src/examples/token_minter.rs +++ b/arbiter-engine/src/examples/token_minter.rs @@ -269,7 +269,7 @@ async fn token_minter_simulation() { token_requester .with_behavior::(token_requester_behavior.clone()) .with_behavior::(token_requester_behavior) - .with_event(transfer_event), + // .with_event(transfer_event), ); world.run().await; From 933606ec0464d7e5514f9dae2df82224cfe4a79d Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Tue, 16 Jan 2024 16:33:52 -0700 Subject: [PATCH 07/20] test: agent::streaming() passes --- arbiter-engine/src/agent.rs | 118 ++++++++++++-------- arbiter-engine/src/examples/token_minter.rs | 2 +- arbiter-engine/src/messager.rs | 2 +- arbiter-engine/src/world.rs | 1 + 4 files changed, 76 insertions(+), 47 deletions(-) diff --git a/arbiter-engine/src/agent.rs b/arbiter-engine/src/agent.rs index ec00f27b..d15860c5 100644 --- a/arbiter-engine/src/agent.rs +++ b/arbiter-engine/src/agent.rs @@ -16,7 +16,7 @@ //! The agent module contains the core agent abstraction for the Arbiter Engine. -use std::{clone, fmt::Debug, pin::Pin, sync::Arc}; +use std::{fmt::Debug, pin::Pin, sync::Arc}; use arbiter_core::{data_collection::EventLogger, middleware::RevmMiddleware}; use ethers::contract::{EthLogDecode, Event}; @@ -184,7 +184,7 @@ impl StateMachine for Agent { State::Processing => { debug!("Agent is processing."); self.state = state; - let messager = Box::leak(Box::new(self.messager.clone())); // TODO: We shouldn't have to do box leak + let messager = self.messager.clone(); let message_stream = messager .stream() .map(|msg| serde_json::to_string(&msg).unwrap_or_else(|e| e.to_string())); @@ -241,7 +241,6 @@ impl StateMachine for Agent { } } -#[ignore = "This test should be adjusted or possibly removed as it isn't really testing anything now"] #[cfg(test)] mod tests { use arbiter_bindings::bindings::arbiter_token::ArbiterToken; @@ -249,54 +248,83 @@ mod tests { use super::*; use crate::messager::Message; - #[ignore] - #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn streaming() { - todo!() - // std::env::set_var("RUST_LOG", "trace"); - // tracing_subscriber::fmt::init(); + std::env::set_var("RUST_LOG", "trace"); + tracing_subscriber::fmt::init(); - // let mut world = World::new("world"); - // let messager = world.messager.clone(); - // println!( - // "Receiver count: {:?}", - // messager.broadcast_sender.receiver_count() - // ); + let world = World::new("world"); + let agent = Agent::new("agent", &world); - // let agent = Agent::new("agent", &world); - // // world.add_agent(agent); // DON'T NEED TO DO THIS IN THIS EXAMPLE? + let arb = ArbiterToken::deploy( + agent.client.clone(), + ("ArbiterToken".to_string(), "ARB".to_string(), 18u8), + ) + .unwrap() + .send() + .await + .unwrap(); - // let arb = ArbiterToken::deploy( - // agent.client.clone(), - // ("ArbiterToken".to_string(), "ARB".to_string(), 18u8), - // ) - // .unwrap() - // .send() - // .await - // .unwrap(); + let mut agent = agent.with_event(arb.events()); + let address = agent.client.address(); - // let agent = agent.with_event(arb.events()); - // let address = agent.client.address(); - // let mut streamer = agent.start_event_stream(); + // THIS COUYLD BE A SINGLE FUNCTION AS IT IS IN THE AGENT::PROCESS, but it is + // annoyikng to do so. + let messager = agent.messager.clone(); + let message_stream = messager + .clone() + .stream() + .map(|msg| serde_json::to_string(&msg).unwrap_or_else(|e| e.to_string())); + let eth_event_stream = agent.event_streamer.take().unwrap().stream(); - // for _ in 0..5 { - // messager - // .send(Message { - // from: "me".to_string(), - // to: messager::To::All, - // data: "hello".to_string(), - // }) - // .await; - // arb.approve(address, U256::from(1)) - // .send() - // .await - // .unwrap() - // .await - // .unwrap(); - // } + let mut event_stream: Pin + Send + '_>> = + if let Some(event_stream) = eth_event_stream { + trace!("Merging event streams."); + Box::pin(futures::stream::select(event_stream, message_stream)) + } else { + trace!("Agent only sees message stream."); + Box::pin(message_stream) + }; + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // while let Some(msg) = streamer.next().await { - // println!("Printing message in test: {:?}", msg); - // } + for _ in 0..5 { + messager + .send(Message { + from: "god".to_string(), + to: messager::To::All, + data: "hello".to_string(), + }) + .await; + arb.approve(address, U256::from(1)) + .send() + .await + .unwrap() + .await + .unwrap(); + } + let mut idx = 0; + while let Some(msg) = event_stream.next().await { + println!("Printing message in test: {:?}", msg); + if idx % 2 == 1 { + assert_eq!( + msg, + serde_json::to_string(&Message { + from: "god".to_string(), + to: messager::To::All, + data: "hello".to_string(), + }) + .unwrap() + ); + } else { + assert_eq!( + msg, + "{\"ApprovalFilter\":{\"owner\":\"0xe7a46f3d9f0e9b9c02f58f95e3bcee2db54050b0\",\"spender\":\"0xe7a46f3d9f0e9b9c02f58f95e3bcee2db54050b0\",\"amount\":\"0x1\"}}".to_string(), + ); + } + idx += 1; + if idx == 10 { + break; + } + } } } diff --git a/arbiter-engine/src/examples/token_minter.rs b/arbiter-engine/src/examples/token_minter.rs index 2f5e3f6d..8a1abd00 100644 --- a/arbiter-engine/src/examples/token_minter.rs +++ b/arbiter-engine/src/examples/token_minter.rs @@ -269,7 +269,7 @@ async fn token_minter_simulation() { token_requester .with_behavior::(token_requester_behavior.clone()) .with_behavior::(token_requester_behavior) - // .with_event(transfer_event), + .with_event(transfer_event), ); world.run().await; diff --git a/arbiter-engine/src/messager.rs b/arbiter-engine/src/messager.rs index c2973c8e..94ea7fa5 100644 --- a/arbiter-engine/src/messager.rs +++ b/arbiter-engine/src/messager.rs @@ -69,7 +69,7 @@ impl Messager { /// Returns a stream of messages that are either sent to [`To::All`] or to /// the agent via [`To::Agent(id)`]. - pub fn stream(&self) -> Pin + Send + '_>> { + pub fn stream(self) -> Pin + Send + 'static>> { let mut receiver = self.broadcast_receiver.clone(); let stream = async_stream::stream! { while let Ok(message) = receiver.recv().await { diff --git a/arbiter-engine/src/world.rs b/arbiter-engine/src/world.rs index 7ae969b7..f29c23b2 100644 --- a/arbiter-engine/src/world.rs +++ b/arbiter-engine/src/world.rs @@ -10,6 +10,7 @@ // it owns a clone of the same messager. // * The worlds now are just going to be revm worlds. We can generalize this // later. +// * Can we give the world an address book?? // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //! The world module contains the core world abstraction for the Arbiter Engine. From 448142c08afa18ddf7bed7c92d6fa1b68aa05d00 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Wed, 17 Jan 2024 12:28:27 -0700 Subject: [PATCH 08/20] refactor: `StateMachine` trait --- arbiter-engine/src/agent.rs | 173 ++++++++++++------- arbiter-engine/src/examples/timed_message.rs | 2 +- arbiter-engine/src/examples/token_minter.rs | 2 +- arbiter-engine/src/machine.rs | 33 ++-- arbiter-engine/src/world.rs | 109 +++++++----- 5 files changed, 190 insertions(+), 129 deletions(-) diff --git a/arbiter-engine/src/agent.rs b/arbiter-engine/src/agent.rs index d15860c5..3cfaf517 100644 --- a/arbiter-engine/src/agent.rs +++ b/arbiter-engine/src/agent.rs @@ -1,5 +1,7 @@ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // TODO: Notes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// * Maybe we just use tokio for everything (like `select`) so that we don't mix +// futures and tokio together in ways that may be weird. // When we start running an agent, we should have their messager start producing // events that can be used by any and all behaviors the agent has that takes in // messages as an event. Similarly, we should have agents start up any streams @@ -146,7 +148,7 @@ impl Agent { #[async_trait::async_trait] impl StateMachine for Agent { #[tracing::instrument(skip(self), fields(id = self.id))] - fn run_state(&mut self, state: State) { + async fn run_state(&mut self, state: State) { match state { State::Uninitialized => { unimplemented!("This never gets called.") @@ -154,32 +156,44 @@ impl StateMachine for Agent { State::Syncing => { self.state = state; debug!("Agent is syncing."); - let mut behavior_engines = self.behavior_engines.take().unwrap(); - for engine in behavior_engines.iter_mut() { - engine.run_state(state); - } + let behavior_engines = self.behavior_engines.take().unwrap(); self.behavior_tasks = Some(join_all(behavior_engines.into_iter().map(|mut engine| { tokio::spawn(async move { - engine.transition().await; + engine.run_state(state).await; engine }) }))); + self.behavior_engines = Some( + self.behavior_tasks + .take() + .unwrap() + .await + .into_iter() + .map(|res| res.unwrap()) + .collect::>(), + ); } State::Startup => { debug!("Agent is starting up."); self.state = state; - let mut behavior_engines = self.behavior_engines.take().unwrap(); - for engine in behavior_engines.iter_mut() { - engine.run_state(state); - } + let behavior_engines = self.behavior_engines.take().unwrap(); self.behavior_tasks = Some(join_all(behavior_engines.into_iter().map(|mut engine| { tokio::spawn(async move { - engine.transition().await; + engine.run_state(state).await; engine }) }))); + self.behavior_engines = Some( + self.behavior_tasks + .take() + .unwrap() + .await + .into_iter() + .map(|res| res.unwrap()) + .collect::>(), + ); } State::Processing => { debug!("Agent is processing."); @@ -208,37 +222,29 @@ impl StateMachine for Agent { } event_stream })); - let mut behavior_engines = self.behavior_engines.take().unwrap(); - for engine in behavior_engines.iter_mut() { - engine.run_state(state); - } + let behavior_engines = self.behavior_engines.take().unwrap(); self.behavior_tasks = Some(join_all(behavior_engines.into_iter().map(|mut engine| { tokio::spawn(async move { - engine.transition().await; + engine.run_state(state).await; engine }) }))); + self.behavior_engines = Some( + self.behavior_tasks + .take() + .unwrap() + .await + .into_iter() + .map(|res| res.unwrap()) + .collect::>(), + ); } State::Stopped => { todo!() } } } - - async fn transition(&mut self) { - // TODO: Might need to handle the broadcast_task here now especially if we need - // to stop. - self.behavior_engines = Some( - self.behavior_tasks - .take() - .unwrap() - .await - .into_iter() - .map(|res| res.unwrap()) - .collect::>(), - ); - } } #[cfg(test)] @@ -248,6 +254,7 @@ mod tests { use super::*; use crate::messager::Message; + #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn streaming() { std::env::set_var("RUST_LOG", "trace"); @@ -280,51 +287,91 @@ mod tests { let mut event_stream: Pin + Send + '_>> = if let Some(event_stream) = eth_event_stream { trace!("Merging event streams."); - Box::pin(futures::stream::select(event_stream, message_stream)) + Box::pin(futures::stream::select(message_stream, event_stream)) } else { trace!("Agent only sees message stream."); Box::pin(message_stream) }; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - for _ in 0..5 { - messager - .send(Message { - from: "god".to_string(), - to: messager::To::All, - data: "hello".to_string(), - }) - .await; - arb.approve(address, U256::from(1)) - .send() - .await - .unwrap() - .await - .unwrap(); - } - let mut idx = 0; - while let Some(msg) = event_stream.next().await { - println!("Printing message in test: {:?}", msg); - if idx % 2 == 1 { - assert_eq!( - msg, - serde_json::to_string(&Message { + // for _ in 0..5 { + // messager + // .send(Message { + // from: "god".to_string(), + // to: messager::To::All, + // data: "hello".to_string(), + // }) + // .await; + // std::thread::sleep(std::time::Duration::from_secs(1)); + // arb.approve(address, U256::from(1)) + // .send() + // .await + // .unwrap() + // .await + // .unwrap(); + // } + + let message_task = tokio::spawn(async move { + for _ in 0..5 { + messager + .send(Message { from: "god".to_string(), to: messager::To::All, data: "hello".to_string(), }) + .await; + // tokio::time::sleep(std::time::Duration::from_secs(1)).await; + } + }); + + let eth_event_task = tokio::spawn(async move { + for _ in 0..5 { + arb.approve(address, U256::from(1)) + .send() + .await .unwrap() - ); - } else { - assert_eq!( - msg, - "{\"ApprovalFilter\":{\"owner\":\"0xe7a46f3d9f0e9b9c02f58f95e3bcee2db54050b0\",\"spender\":\"0xe7a46f3d9f0e9b9c02f58f95e3bcee2db54050b0\",\"amount\":\"0x1\"}}".to_string(), - ); + .await + .unwrap(); } - idx += 1; - if idx == 10 { - break; + }); + + // let mut idx = 0; + let mut event_idx = 0; + let mut message_idx = 0; + let print_task = tokio::spawn(async move { + while let Some(msg) = event_stream.next().await { + println!("Printing message in test: {:?}", msg); + if msg == "{\"ApprovalFilter\":{\"owner\":\"0xe7a46f3d9f0e9b9c02f58f95e3bcee2db54050b0\",\"spender\":\"0xe7a46f3d9f0e9b9c02f58f95e3bcee2db54050b0\",\"amount\":\"0x1\"}}" { + event_idx += 1; + println!("Event idx: {}", event_idx); + } else { + message_idx += 1; + println!("Message idx: {}", message_idx); + } + // if idx % 2 == 1 { + // assert_eq!( + // msg, + // serde_json::to_string(&Message { + // from: "god".to_string(), + // to: messager::To::All, + // data: "hello".to_string(), + // }) + // .unwrap() + // ); + // } else { + // assert_eq!( + // msg, + // "{\"ApprovalFilter\":{\"owner\":\" + // 0xe7a46f3d9f0e9b9c02f58f95e3bcee2db54050b0\",\"spender\":\" + // 0xe7a46f3d9f0e9b9c02f58f95e3bcee2db54050b0\",\"amount\":\" + // 0x1\" }}".to_string(), ); + // } + // idx += 1; + // if idx == 10 { + // break; + // } } - } + }); + join_all(vec![message_task, eth_event_task, print_task]).await; } } diff --git a/arbiter-engine/src/examples/timed_message.rs b/arbiter-engine/src/examples/timed_message.rs index cfcea9d4..c5029ab3 100644 --- a/arbiter-engine/src/examples/timed_message.rs +++ b/arbiter-engine/src/examples/timed_message.rs @@ -51,7 +51,7 @@ impl Behavior for TimedMessage { } #[ignore = "This is a work in progress and does not work and does not ever terminate."] -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn echoer() { std::env::set_var("RUST_LOG", "trace"); tracing_subscriber::fmt::init(); diff --git a/arbiter-engine/src/examples/token_minter.rs b/arbiter-engine/src/examples/token_minter.rs index 8a1abd00..2f5e3f6d 100644 --- a/arbiter-engine/src/examples/token_minter.rs +++ b/arbiter-engine/src/examples/token_minter.rs @@ -269,7 +269,7 @@ async fn token_minter_simulation() { token_requester .with_behavior::(token_requester_behavior.clone()) .with_behavior::(token_requester_behavior) - .with_event(transfer_event), + // .with_event(transfer_event), ); world.run().await; diff --git a/arbiter-engine/src/machine.rs b/arbiter-engine/src/machine.rs index 4e77808b..ff5df048 100644 --- a/arbiter-engine/src/machine.rs +++ b/arbiter-engine/src/machine.rs @@ -62,8 +62,7 @@ pub trait Behavior: Send + Sync + 'static { #[async_trait::async_trait] pub(crate) trait StateMachine: Send + Sync + 'static { - fn run_state(&mut self, state: State); - async fn transition(&mut self); + async fn run_state(&mut self, state: State); } /// The idea of the [`Engine`] is that it drives the [`Behavior`] of a @@ -81,10 +80,6 @@ where /// The behavior the [`Engine`] runs. pub behavior: Option, - /// When the state of the [`Engine`] is modified, the tasks will be run (and - /// therefore `move`d) concurrently and stored here. - behavior_task: Option>, - /// The receiver of events that the [`Engine`] will process. /// The [`State::Processing`] stage will attempt a decode of the [`String`]s /// into the event type ``. @@ -102,7 +97,6 @@ where pub(crate) fn new(behavior: B, event_receiver: Receiver) -> Self { Self { behavior: Some(behavior), - behavior_task: None, event_receiver, phantom: std::marker::PhantomData, } @@ -115,7 +109,7 @@ where B: Behavior, E: DeserializeOwned + Send + Sync + Debug + 'static, { - fn run_state(&mut self, state: State) { + async fn run_state(&mut self, state: State) { match state { State::Uninitialized => { unimplemented!("This never gets called.") @@ -123,24 +117,26 @@ where State::Syncing => { trace!("Behavior is syncing."); let mut behavior = self.behavior.take().unwrap(); - self.behavior_task = Some(tokio::spawn(async move { + let behavior_task = tokio::spawn(async move { behavior.sync().await; behavior - })); + }); + self.behavior = Some(behavior_task.await.unwrap()); } State::Startup => { trace!("Behavior is starting up."); let mut behavior = self.behavior.take().unwrap(); - self.behavior_task = Some(tokio::spawn(async move { + let behavior_task = tokio::spawn(async move { behavior.startup().await; behavior - })); + }); + self.behavior = Some(behavior_task.await.unwrap()); } State::Processing => { trace!("Behavior is processing."); let mut behavior = self.behavior.take().unwrap(); let mut receiver = self.event_receiver.clone(); // TODO Could use Option::take() if we don't want to clone. - self.behavior_task = Some(tokio::spawn(async move { + let behavior_task = tokio::spawn(async move { while let Ok(event) = receiver.recv().await { println!("Event received: {:?}", event); let decoding_result = serde_json::from_str::(&event); @@ -155,19 +151,12 @@ where } } behavior - })); + }); + self.behavior = Some(behavior_task.await.unwrap()); } State::Stopped => { todo!() } } } - - /// Take the task and wait for it to finish. Then take the [`Behavior`] and - /// put it back into the engine. - async fn transition(&mut self) { - let behavior_task = self.behavior_task.take().unwrap(); - let behavior = behavior_task.await.unwrap(); - self.behavior = Some(behavior); - } } diff --git a/arbiter-engine/src/world.rs b/arbiter-engine/src/world.rs index f29c23b2..fc320537 100644 --- a/arbiter-engine/src/world.rs +++ b/arbiter-engine/src/world.rs @@ -57,6 +57,8 @@ pub struct World { /// The identifier of the world. pub id: String, + pub state: State, + /// The agents in the world. pub agents: Option>, @@ -76,6 +78,7 @@ impl World { pub fn new(id: &str) -> Self { Self { id: id.to_owned(), + state: State::Uninitialized, agents: Some(HashMap::new()), agent_tasks: None, environment: EnvironmentBuilder::new().build(), @@ -91,93 +94,115 @@ impl World { } pub async fn run(&mut self) { - self.run_state(State::Syncing); - self.transition().await; + self.run_state(State::Syncing).await; - self.run_state(State::Startup); - self.transition().await; + self.run_state(State::Startup).await; - self.run_state(State::Processing); - self.transition().await; + self.run_state(State::Processing).await; } } #[async_trait::async_trait] impl StateMachine for World { - fn run_state(&mut self, state: State) { + async fn run_state(&mut self, state: State) { match state { State::Uninitialized => { unimplemented!("This never gets called.") } State::Syncing => { info!("World is syncing."); - let mut agents = self.agents.take().unwrap(); - for agent in agents.values_mut() { - agent.run_state(state); - } + self.state = state; + let agents = self.agents.take().unwrap(); self.agent_tasks = Some(join_all(agents.into_values().map(|mut agent| { tokio::spawn(async move { - agent.transition().await; + agent.run_state(state).await; agent }) }))); + self.agents = Some( + self.agent_tasks + .take() + .unwrap() + .await + .into_iter() + .map(|res| { + let agent = res.unwrap(); + (agent.id.clone(), agent) + }) + .collect::>(), + ); } State::Startup => { info!("World is starting up."); - let mut agents = self.agents.take().unwrap(); - for agent in agents.values_mut() { - agent.run_state(state); - } + self.state = state; + let agents = self.agents.take().unwrap(); self.agent_tasks = Some(join_all(agents.into_values().map(|mut agent| { tokio::spawn(async move { - agent.transition().await; + agent.run_state(state).await; agent }) }))); + self.agents = Some( + self.agent_tasks + .take() + .unwrap() + .await + .into_iter() + .map(|res| { + let agent = res.unwrap(); + (agent.id.clone(), agent) + }) + .collect::>(), + ); } State::Processing => { info!("World is processing."); - let mut agents = self.agents.take().unwrap(); - for agent in agents.values_mut() { - agent.run_state(state); - } + self.state = state; + let agents = self.agents.take().unwrap(); self.agent_tasks = Some(join_all(agents.into_values().map(|mut agent| { tokio::spawn(async move { - agent.transition().await; + agent.run_state(state).await; agent }) }))); + self.agents = Some( + self.agent_tasks + .take() + .unwrap() + .await + .into_iter() + .map(|res| { + let agent = res.unwrap(); + (agent.id.clone(), agent) + }) + .collect::>(), + ); } State::Stopped => { info!("World is starting up."); - let mut agents = self.agents.take().unwrap(); - for agent in agents.values_mut() { - agent.run_state(state); - } + self.state = state; + let agents = self.agents.take().unwrap(); self.agent_tasks = Some(join_all(agents.into_values().map(|mut agent| { tokio::spawn(async move { - agent.transition().await; + agent.run_state(state).await; agent }) }))); + self.agents = Some( + self.agent_tasks + .take() + .unwrap() + .await + .into_iter() + .map(|res| { + let agent = res.unwrap(); + (agent.id.clone(), agent) + }) + .collect::>(), + ); } } } - - async fn transition(&mut self) { - self.agents = Some( - self.agent_tasks - .take() - .unwrap() - .await - .into_iter() - .map(|res| { - let agent = res.unwrap(); - (agent.id.clone(), agent) - }) - .collect::>(), - ); - } } #[cfg(test)] From 453aad9bf6f29484cd2f5e6fe1e3a7742aa91e8f Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Wed, 17 Jan 2024 12:33:28 -0700 Subject: [PATCH 09/20] refactor: helper functions for `StateMachine`s --- arbiter-engine/src/agent.rs | 78 ++++++++++------------------------- arbiter-engine/src/machine.rs | 27 ++++++------ 2 files changed, 36 insertions(+), 69 deletions(-) diff --git a/arbiter-engine/src/agent.rs b/arbiter-engine/src/agent.rs index 3cfaf517..8a421dbd 100644 --- a/arbiter-engine/src/agent.rs +++ b/arbiter-engine/src/agent.rs @@ -87,9 +87,6 @@ pub struct Agent { /// events. behavior_engines: Option>>, - /// The tasks that represent the agent running a specific state transition. - behavior_tasks: Option>>>, - /// The pipeline for yielding events from the centralized event streamer /// (for both messages and Ethereum events) to agents. distributor: ( @@ -114,7 +111,6 @@ impl Agent { event_streamer: Some(EventLogger::builder()), behavior_engines: None, distributor, - behavior_tasks: None, broadcast_task: None, } } @@ -143,6 +139,24 @@ impl Agent { }; self } + + pub(crate) async fn run(&mut self, state: State) { + self.state = state; + let behavior_engines = self.behavior_engines.take().unwrap(); + let behavior_tasks = join_all(behavior_engines.into_iter().map(|mut engine| { + tokio::spawn(async move { + engine.run_state(state).await; + engine + }) + })); + self.behavior_engines = Some( + behavior_tasks + .await + .into_iter() + .map(|res| res.unwrap()) + .collect::>(), + ); + } } #[async_trait::async_trait] @@ -154,46 +168,12 @@ impl StateMachine for Agent { unimplemented!("This never gets called.") } State::Syncing => { - self.state = state; debug!("Agent is syncing."); - let behavior_engines = self.behavior_engines.take().unwrap(); - self.behavior_tasks = - Some(join_all(behavior_engines.into_iter().map(|mut engine| { - tokio::spawn(async move { - engine.run_state(state).await; - engine - }) - }))); - self.behavior_engines = Some( - self.behavior_tasks - .take() - .unwrap() - .await - .into_iter() - .map(|res| res.unwrap()) - .collect::>(), - ); + self.run(state).await; } State::Startup => { debug!("Agent is starting up."); - self.state = state; - let behavior_engines = self.behavior_engines.take().unwrap(); - self.behavior_tasks = - Some(join_all(behavior_engines.into_iter().map(|mut engine| { - tokio::spawn(async move { - engine.run_state(state).await; - engine - }) - }))); - self.behavior_engines = Some( - self.behavior_tasks - .take() - .unwrap() - .await - .into_iter() - .map(|res| res.unwrap()) - .collect::>(), - ); + self.run(state).await; } State::Processing => { debug!("Agent is processing."); @@ -222,23 +202,7 @@ impl StateMachine for Agent { } event_stream })); - let behavior_engines = self.behavior_engines.take().unwrap(); - self.behavior_tasks = - Some(join_all(behavior_engines.into_iter().map(|mut engine| { - tokio::spawn(async move { - engine.run_state(state).await; - engine - }) - }))); - self.behavior_engines = Some( - self.behavior_tasks - .take() - .unwrap() - .await - .into_iter() - .map(|res| res.unwrap()) - .collect::>(), - ); + self.run(state).await; } State::Stopped => { todo!() diff --git a/arbiter-engine/src/machine.rs b/arbiter-engine/src/machine.rs index ff5df048..2b3a6c9b 100644 --- a/arbiter-engine/src/machine.rs +++ b/arbiter-engine/src/machine.rs @@ -80,6 +80,8 @@ where /// The behavior the [`Engine`] runs. pub behavior: Option, + pub state: State, + /// The receiver of events that the [`Engine`] will process. /// The [`State::Processing`] stage will attempt a decode of the [`String`]s /// into the event type ``. @@ -97,10 +99,21 @@ where pub(crate) fn new(behavior: B, event_receiver: Receiver) -> Self { Self { behavior: Some(behavior), + state: State::Uninitialized, event_receiver, phantom: std::marker::PhantomData, } } + + pub(crate) async fn run(&mut self, state: State) { + self.state = state; + let mut behavior = self.behavior.take().unwrap(); + let behavior_task = tokio::spawn(async move { + behavior.sync().await; + behavior + }); + self.behavior = Some(behavior_task.await.unwrap()); + } } #[async_trait::async_trait] @@ -116,21 +129,11 @@ where } State::Syncing => { trace!("Behavior is syncing."); - let mut behavior = self.behavior.take().unwrap(); - let behavior_task = tokio::spawn(async move { - behavior.sync().await; - behavior - }); - self.behavior = Some(behavior_task.await.unwrap()); + self.run(state).await; } State::Startup => { trace!("Behavior is starting up."); - let mut behavior = self.behavior.take().unwrap(); - let behavior_task = tokio::spawn(async move { - behavior.startup().await; - behavior - }); - self.behavior = Some(behavior_task.await.unwrap()); + self.run(state).await; } State::Processing => { trace!("Behavior is processing."); From 3c6c11395b41c1f453c68660988c9d0899cb8ba7 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Wed, 17 Jan 2024 12:54:58 -0700 Subject: [PATCH 10/20] save --- arbiter-core/src/data_collection.rs | 4 ++-- arbiter-engine/src/agent.rs | 9 +++++++-- arbiter-engine/src/machine.rs | 1 - arbiter-engine/src/messager.rs | 4 ++-- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/arbiter-core/src/data_collection.rs b/arbiter-core/src/data_collection.rs index c22fff07..00d37810 100644 --- a/arbiter-core/src/data_collection.rs +++ b/arbiter-core/src/data_collection.rs @@ -365,7 +365,7 @@ impl EventLogger { } /// Returns a stream of the serialized events. - pub fn stream(self) -> Option + Send + 'static>>> { + pub fn stream(self) -> Option + Send> { if let Some(receiver) = self.receiver.clone() { let stream = async_stream::stream! { while let Ok(broadcast) = receiver.recv() { @@ -389,7 +389,7 @@ impl EventLogger { } }; - Some(Box::pin(stream)) + Some(stream) } else { None } diff --git a/arbiter-engine/src/agent.rs b/arbiter-engine/src/agent.rs index 8a421dbd..5abab28c 100644 --- a/arbiter-engine/src/agent.rs +++ b/arbiter-engine/src/agent.rs @@ -217,7 +217,7 @@ mod tests { use ethers::types::U256; use super::*; - use crate::messager::Message; + use crate::messager::Message; // Add this import statement #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn streaming() { @@ -248,10 +248,15 @@ mod tests { .map(|msg| serde_json::to_string(&msg).unwrap_or_else(|e| e.to_string())); let eth_event_stream = agent.event_streamer.take().unwrap().stream(); + // ... + let mut event_stream: Pin + Send + '_>> = if let Some(event_stream) = eth_event_stream { trace!("Merging event streams."); - Box::pin(futures::stream::select(message_stream, event_stream)) + Box::pin(futures::stream::select_all(vec![ + message_stream, + event_stream, + ])) } else { trace!("Agent only sees message stream."); Box::pin(message_stream) diff --git a/arbiter-engine/src/machine.rs b/arbiter-engine/src/machine.rs index 2b3a6c9b..2acfa6a0 100644 --- a/arbiter-engine/src/machine.rs +++ b/arbiter-engine/src/machine.rs @@ -5,7 +5,6 @@ use std::fmt::Debug; use async_broadcast::Receiver; use serde::de::DeserializeOwned; -use tokio::task::JoinHandle; use super::*; diff --git a/arbiter-engine/src/messager.rs b/arbiter-engine/src/messager.rs index 94ea7fa5..ee35ce50 100644 --- a/arbiter-engine/src/messager.rs +++ b/arbiter-engine/src/messager.rs @@ -69,7 +69,7 @@ impl Messager { /// Returns a stream of messages that are either sent to [`To::All`] or to /// the agent via [`To::Agent(id)`]. - pub fn stream(self) -> Pin + Send + 'static>> { + pub fn stream(self) -> impl Stream + Send { let mut receiver = self.broadcast_receiver.clone(); let stream = async_stream::stream! { while let Ok(message) = receiver.recv().await { @@ -87,7 +87,7 @@ impl Messager { } } }; - Box::pin(stream) + stream } /// Sends a message to the messager. From 79458123b785f234a74359d05f22cc20a41402d0 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Wed, 17 Jan 2024 13:03:45 -0700 Subject: [PATCH 11/20] push up --- arbiter-engine/src/agent.rs | 64 ++++++++----------------------------- 1 file changed, 14 insertions(+), 50 deletions(-) diff --git a/arbiter-engine/src/agent.rs b/arbiter-engine/src/agent.rs index 5abab28c..2d175d8b 100644 --- a/arbiter-engine/src/agent.rs +++ b/arbiter-engine/src/agent.rs @@ -23,7 +23,7 @@ use std::{fmt::Debug, pin::Pin, sync::Arc}; use arbiter_core::{data_collection::EventLogger, middleware::RevmMiddleware}; use ethers::contract::{EthLogDecode, Event}; use futures::stream::{Stream, StreamExt}; -use futures_util::future::{join_all, JoinAll}; +use futures_util::future::join_all; use serde::de::DeserializeOwned; use tokio::task::JoinHandle; @@ -188,7 +188,13 @@ impl StateMachine for Agent { let mut event_stream: Pin + Send + '_>> = if let Some(event_stream) = eth_event_stream { trace!("Merging event streams."); - Box::pin(futures::stream::select(event_stream, message_stream)) + // Convert the individual streams into a Vec + let all_streams = vec![ + Box::pin(message_stream) as Pin + Send>>, + Box::pin(event_stream), + ]; + // Use select_all to combine them + Box::pin(futures::stream::select_all(all_streams)) } else { trace!("Agent only sees message stream."); Box::pin(message_stream) @@ -217,7 +223,7 @@ mod tests { use ethers::types::U256; use super::*; - use crate::messager::Message; // Add this import statement + use crate::messager::Message; #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn streaming() { @@ -248,37 +254,18 @@ mod tests { .map(|msg| serde_json::to_string(&msg).unwrap_or_else(|e| e.to_string())); let eth_event_stream = agent.event_streamer.take().unwrap().stream(); - // ... - let mut event_stream: Pin + Send + '_>> = if let Some(event_stream) = eth_event_stream { trace!("Merging event streams."); - Box::pin(futures::stream::select_all(vec![ - message_stream, - event_stream, - ])) + let all_streams = vec![ + Box::pin(message_stream) as Pin + Send>>, + Box::pin(event_stream), + ]; + Box::pin(futures::stream::select_all(all_streams)) } else { trace!("Agent only sees message stream."); Box::pin(message_stream) }; - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - // for _ in 0..5 { - // messager - // .send(Message { - // from: "god".to_string(), - // to: messager::To::All, - // data: "hello".to_string(), - // }) - // .await; - // std::thread::sleep(std::time::Duration::from_secs(1)); - // arb.approve(address, U256::from(1)) - // .send() - // .await - // .unwrap() - // .await - // .unwrap(); - // } let message_task = tokio::spawn(async move { for _ in 0..5 { @@ -304,7 +291,6 @@ mod tests { } }); - // let mut idx = 0; let mut event_idx = 0; let mut message_idx = 0; let print_task = tokio::spawn(async move { @@ -317,28 +303,6 @@ mod tests { message_idx += 1; println!("Message idx: {}", message_idx); } - // if idx % 2 == 1 { - // assert_eq!( - // msg, - // serde_json::to_string(&Message { - // from: "god".to_string(), - // to: messager::To::All, - // data: "hello".to_string(), - // }) - // .unwrap() - // ); - // } else { - // assert_eq!( - // msg, - // "{\"ApprovalFilter\":{\"owner\":\" - // 0xe7a46f3d9f0e9b9c02f58f95e3bcee2db54050b0\",\"spender\":\" - // 0xe7a46f3d9f0e9b9c02f58f95e3bcee2db54050b0\",\"amount\":\" - // 0x1\" }}".to_string(), ); - // } - // idx += 1; - // if idx == 10 { - // break; - // } } }); join_all(vec![message_task, eth_event_task, print_task]).await; From 6de3d7a53723c01f5cf71c6ec9311cbfec3c191e Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Wed, 17 Jan 2024 14:20:05 -0700 Subject: [PATCH 12/20] fix: `Engine::run_state` --- arbiter-engine/src/examples/token_minter.rs | 4 ++-- arbiter-engine/src/machine.rs | 26 +++++++++++---------- arbiter-engine/src/messager.rs | 8 +++---- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/arbiter-engine/src/examples/token_minter.rs b/arbiter-engine/src/examples/token_minter.rs index 2f5e3f6d..fd293077 100644 --- a/arbiter-engine/src/examples/token_minter.rs +++ b/arbiter-engine/src/examples/token_minter.rs @@ -237,7 +237,7 @@ impl Behavior for TokenRequester { #[ignore] #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn token_minter_simulation() { - std::env::set_var("RUST_LOG", "trace"); + std::env::set_var("RUST_LOG", "arbiter_engine=trace"); tracing_subscriber::fmt::init(); let mut world = World::new("test_world"); @@ -269,7 +269,7 @@ async fn token_minter_simulation() { token_requester .with_behavior::(token_requester_behavior.clone()) .with_behavior::(token_requester_behavior) - // .with_event(transfer_event), + .with_event(transfer_event), ); world.run().await; diff --git a/arbiter-engine/src/machine.rs b/arbiter-engine/src/machine.rs index 2acfa6a0..0818201b 100644 --- a/arbiter-engine/src/machine.rs +++ b/arbiter-engine/src/machine.rs @@ -103,16 +103,6 @@ where phantom: std::marker::PhantomData, } } - - pub(crate) async fn run(&mut self, state: State) { - self.state = state; - let mut behavior = self.behavior.take().unwrap(); - let behavior_task = tokio::spawn(async move { - behavior.sync().await; - behavior - }); - self.behavior = Some(behavior_task.await.unwrap()); - } } #[async_trait::async_trait] @@ -128,11 +118,23 @@ where } State::Syncing => { trace!("Behavior is syncing."); - self.run(state).await; + self.state = state; + let mut behavior = self.behavior.take().unwrap(); + let behavior_task = tokio::spawn(async move { + behavior.sync().await; + behavior + }); + self.behavior = Some(behavior_task.await.unwrap()); } State::Startup => { trace!("Behavior is starting up."); - self.run(state).await; + self.state = state; + let mut behavior = self.behavior.take().unwrap(); + let behavior_task = tokio::spawn(async move { + behavior.startup().await; + behavior + }); + self.behavior = Some(behavior_task.await.unwrap()); } State::Processing => { trace!("Behavior is processing."); diff --git a/arbiter-engine/src/messager.rs b/arbiter-engine/src/messager.rs index ee35ce50..ece378df 100644 --- a/arbiter-engine/src/messager.rs +++ b/arbiter-engine/src/messager.rs @@ -39,7 +39,7 @@ pub struct Messager { pub(crate) broadcast_sender: BroadcastSender, - broadcast_receiver: BroadcastReceiver, + broadcast_receiver: Option>, } impl Messager { @@ -52,7 +52,7 @@ impl Messager { let (broadcast_sender, broadcast_receiver) = broadcast(512); Self { broadcast_sender, - broadcast_receiver, + broadcast_receiver: Some(broadcast_receiver), id: None, } } @@ -69,8 +69,8 @@ impl Messager { /// Returns a stream of messages that are either sent to [`To::All`] or to /// the agent via [`To::Agent(id)`]. - pub fn stream(self) -> impl Stream + Send { - let mut receiver = self.broadcast_receiver.clone(); + pub fn stream(mut self) -> impl Stream + Send { + let mut receiver = self.broadcast_receiver.take().unwrap(); let stream = async_stream::stream! { while let Ok(message) = receiver.recv().await { match &message.to { From 239e2147f682e5ba94ff6a999023f2370d84133b Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Wed, 17 Jan 2024 16:07:13 -0700 Subject: [PATCH 13/20] last push Revert "last push" This reverts commit d4be6c46cb5789de45369aece39babfb7105dbd8. progess on change to tokio::broadcast almost passing works now wow it does work lol all tests run --- Cargo.lock | 48 -------- arbiter-core/src/data_collection.rs | 41 +++---- arbiter-core/src/environment/mod.rs | 76 ++----------- arbiter-core/src/middleware/connection.rs | 104 +++++++++--------- arbiter-core/src/middleware/mod.rs | 19 +--- .../src/tests/data_collection_integration.rs | 37 +++++-- arbiter-engine/Cargo.toml | 3 +- arbiter-engine/src/agent.rs | 30 ++--- arbiter-engine/src/examples/timed_message.rs | 41 +++++-- arbiter-engine/src/examples/token_minter.rs | 79 +++++++++---- arbiter-engine/src/machine.rs | 8 +- arbiter-engine/src/messager.rs | 24 ++-- 12 files changed, 232 insertions(+), 278 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 96ec26b2..cc0ec144 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -316,7 +316,6 @@ dependencies = [ "anyhow", "arbiter-bindings", "arbiter-core", - "async-broadcast", "async-stream", "async-trait", "crossbeam-channel", @@ -517,17 +516,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" -[[package]] -name = "async-broadcast" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "334d75cf09b33bede6cbc20e52515853ae7bee3d4eadd9540e13ce92af983d34" -dependencies = [ - "event-listener", - "event-listener-strategy", - "futures-core", -] - [[package]] name = "async-stream" version = "0.3.5" @@ -1088,15 +1076,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "concurrent-queue" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "config" version = "0.13.4" @@ -1891,27 +1870,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" -[[package]] -name = "event-listener" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c97b4e30ea7e4b7e7b429d6e2d8510433ba8cee4e70dfb3243794e539d29fd" -dependencies = [ - "event-listener", - "pin-project-lite", -] - [[package]] name = "eyre" version = "0.6.8" @@ -3246,12 +3204,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "parking" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" - [[package]] name = "parking_lot" version = "0.12.1" diff --git a/arbiter-core/src/data_collection.rs b/arbiter-core/src/data_collection.rs index 00d37810..55a5852e 100644 --- a/arbiter-core/src/data_collection.rs +++ b/arbiter-core/src/data_collection.rs @@ -20,7 +20,7 @@ use std::{ collections::BTreeMap, fmt::Debug, io::BufWriter, marker::PhantomData, mem::transmute, - pin::Pin, sync::Arc, + sync::Arc, }; use ethers::{ @@ -38,6 +38,10 @@ use polars::{ }; use serde::Serialize; use serde_json::Value; +use tokio::{ + sync::broadcast::{Receiver as BroadcastReceiver, Sender as BroadcastSender}, + task::JoinHandle, +}; use super::*; use crate::{ @@ -63,8 +67,8 @@ pub(crate) type FilterDecoder = /// traits, and has a static lifetime. pub struct EventLogger { decoder: FilterDecoder, - receiver: Option>, - shutdown_sender: Option>, + receiver: Option>, + // shutdown_sender: Option>, output_file_type: Option, directory: Option, file_name: Option, @@ -103,7 +107,7 @@ impl EventLogger { file_name: None, decoder: BTreeMap::new(), receiver: None, - shutdown_sender: None, + // shutdown_sender: None, output_file_type: None, metadata: None, } @@ -138,15 +142,7 @@ impl EventLogger { ); let connection = middleware.provider().as_ref(); if self.receiver.is_none() { - let (event_sender, event_receiver) = crossbeam_channel::unbounded::(); - let (shutdown_sender, shutdown_receiver) = crossbeam_channel::bounded::<()>(1); - connection - .event_broadcaster - .lock() - .unwrap() - .add_sender(event_sender, Some(shutdown_receiver)); - self.receiver = Some(event_receiver); - self.shutdown_sender = Some(shutdown_sender); + self.receiver = Some(connection.event_sender.subscribe()); } debug!("`EventLogger` now provided with event labeled: {:?}", name); self @@ -253,15 +249,15 @@ impl EventLogger { /// /// This function will return an error if there is a problem creating the /// directories or files, or writing to the files. - pub fn run(self) -> Result<(), RevmMiddlewareError> { - let receiver = self.receiver.unwrap(); + pub fn run(self) -> Result, RevmMiddlewareError> { + let mut receiver = self.receiver.unwrap(); let dir = self.directory.unwrap_or("./data".into()); let file_name = self.file_name.unwrap_or("output".into()); let file_type = self.output_file_type.unwrap_or(OutputFileType::JSON); let metadata = self.metadata.clone(); - std::thread::spawn(move || { + let task = tokio::spawn(async move { let mut events: BTreeMap>> = BTreeMap::new(); - while let Ok(broadcast) = receiver.recv() { + while let Ok(broadcast) = receiver.recv().await { match broadcast { Broadcast::StopSignal => { debug!("`EventLogger` has seen a stop signal"); @@ -288,7 +284,6 @@ impl EventLogger { } let data = OutputData { events, metadata }; serde_json::to_writer(writer, &data).expect("Unable to write data"); - self.shutdown_sender.unwrap().send(()).unwrap(); } OutputFileType::CSV => { // Write the DataFrame to a CSV file @@ -301,7 +296,6 @@ impl EventLogger { writer.finish(&mut df).unwrap_or_else(|_| { panic!("Error writing to csv file"); }); - self.shutdown_sender.unwrap().send(()).unwrap(); } OutputFileType::Parquet => { // Write the DataFrame to a parquet file @@ -314,7 +308,6 @@ impl EventLogger { writer.finish(&mut df).unwrap_or_else(|_| { panic!("Error writing to parquet file"); }); - self.shutdown_sender.unwrap().send(()).unwrap(); } } break; @@ -361,14 +354,14 @@ impl EventLogger { } } }); - Ok(()) + Ok(task) } /// Returns a stream of the serialized events. - pub fn stream(self) -> Option + Send> { - if let Some(receiver) = self.receiver.clone() { + pub fn stream(mut self) -> Option + Send> { + if let Some(mut receiver) = self.receiver.take() { let stream = async_stream::stream! { - while let Ok(broadcast) = receiver.recv() { + while let Ok(broadcast) = receiver.recv().await { match broadcast { Broadcast::StopSignal => { trace!("`EventLogger` has seen a stop signal"); diff --git a/arbiter-core/src/environment/mod.rs b/arbiter-core/src/environment/mod.rs index 3f91f7e7..a53e65cd 100644 --- a/arbiter-core/src/environment/mod.rs +++ b/arbiter-core/src/environment/mod.rs @@ -45,7 +45,12 @@ use revm::{ }; use serde::{Deserialize, Serialize}; use thiserror::Error; +use tokio::sync::{ + broadcast::{channel, Sender as BroadcastSender}, + oneshot, +}; +use self::data_collection::EventLogger; use super::*; #[cfg_attr(doc, doc(hidden))] #[cfg_attr(doc, allow(unused_imports))] @@ -84,10 +89,6 @@ pub(crate) type OutcomeSender = Sender>; /// emitted from transactions. pub(crate) type OutcomeReceiver = Receiver>; -/// Alias for the sender used in the [`EventBroadcaster`] that transmits -/// contract events via [`Log`]. -pub(crate) type EventSender = Sender; - /// Alias for the receiver used in the [`EventBroadcaster`] that accepts /// shutdown signals from child processes. pub(crate) type ShutDownReceiver = Receiver<()>; @@ -162,10 +163,11 @@ impl Environment { db: Option>, ) -> Self { let (instruction_sender, instruction_receiver) = unbounded(); + let (event_broadcaster, _) = channel(512); let socket = Socket { instruction_sender: Arc::new(instruction_sender), instruction_receiver, - event_broadcaster: Arc::new(Mutex::new(EventBroadcaster::new())), + event_broadcaster, }; let db = db.map(|db| ArbiterDB(Arc::new(RwLock::new(db)))); @@ -540,15 +542,13 @@ impl Environment { // update transaction count for sender - let event_broadcaster = event_broadcaster - .lock() - .map_err(|e| EnvironmentError::Communication(e.to_string()))?; let receipt_data = ReceiptData { block_number, transaction_index: transaction_index.into(), cumulative_gas_per_block, }; - event_broadcaster.broadcast(Some(execution_result.logs()), false)?; + let res = event_broadcaster.send(Broadcast::Event(execution_result.logs())); + println!("Result: {:?}", res); outcome_sender .send(Ok(Outcome::TransactionCompleted( execution_result, @@ -649,10 +649,10 @@ impl Environment { .map_err(|e| EnvironmentError::Communication(e.to_string()))?; } Instruction::Stop(outcome_sender) => { + event_broadcaster.send(Broadcast::StopSignal).unwrap(); outcome_sender .send(Ok(Outcome::StopCompleted(evm.db.unwrap()))) .map_err(|e| EnvironmentError::Communication(e.to_string()))?; - event_broadcaster.lock().unwrap().broadcast(None, true)?; break; } } @@ -718,7 +718,7 @@ impl Environment { pub(crate) struct Socket { pub(crate) instruction_sender: Arc, pub(crate) instruction_receiver: InstructionReceiver, - pub(crate) event_broadcaster: Arc>, + pub(crate) event_broadcaster: BroadcastSender, } /// Enum representing the types of broadcasts that can be sent. @@ -729,7 +729,7 @@ pub(crate) struct Socket { /// Variants: /// * `StopSignal`: Represents a signal to stop the event logger process. /// * `Event(Vec)`: Represents a broadcast of a vector of Ethereum logs. -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug)] pub enum Broadcast { /// Represents a signal to stop the event logger process. StopSignal, @@ -737,58 +737,6 @@ pub enum Broadcast { Event(Vec), } -/// Responsible for broadcasting Ethereum logs to subscribers. -/// -/// Maintains a list of senders to which logs are sent whenever they are -/// produced by the EVM. -#[derive(Clone, Debug)] -pub(crate) struct EventBroadcaster(Vec<(EventSender, Option)>); - -impl EventBroadcaster { - /// Called only when creating a new [`Environment`] - fn new() -> Self { - Self(vec![]) - } - - /// Called from [`RevmMiddleware`] implementation when setting up a new - /// `FilterWatcher` as each watcher will need their own sender - pub(crate) fn add_sender( - &mut self, - sender: EventSender, - shutdown_receiver: Option, - ) { - debug!("Sender added for `EventBroadcaster`"); - self.0.push((sender, shutdown_receiver)); - } - - /// Loop through each sender and send `Vec` emitted from a transaction - /// downstream to any and all receivers - fn broadcast(&self, logs: Option>, stop_signal: bool) -> Result<(), EnvironmentError> { - if stop_signal { - for (sender, receiver) in &self.0 { - sender.send(Broadcast::StopSignal)?; - debug!("Broadcasted stop signal to listener"); - if let Some(receiver) = receiver { - receiver - .recv() - .map_err(|_| EnvironmentError::ShutDownReceiverError)?; - debug!("Blocked on shutdown receiver signal"); - } - } - return Ok(()); - } else { - if logs.is_none() { - unreachable!(); - } - for (sender, _) in &self.0 { - sender.send(Broadcast::Event(logs.clone().unwrap()))?; - trace!("Broadcasting event to all listeners") - } - } - Ok(()) - } -} - /// Convert a U256 to a U64, discarding the higher bits if the number is larger /// than 2^64 # Arguments /// * `input` - The U256 to convert. diff --git a/arbiter-core/src/middleware/connection.rs b/arbiter-core/src/middleware/connection.rs index 670c5d43..37f414c9 100644 --- a/arbiter-core/src/middleware/connection.rs +++ b/arbiter-core/src/middleware/connection.rs @@ -3,20 +3,22 @@ use std::{ collections::HashMap, fmt::Debug, pin::Pin, - sync::{Arc, Mutex, Weak}, + sync::{Arc, Weak}, task::Poll, }; -use crossbeam_channel::TryRecvError; use futures_util::{stream, Stream}; use serde_json::value::RawValue; +use tokio::sync::broadcast::{ + error::TryRecvError, Receiver as BroadcastReceiver, Sender as BroadcastSender, +}; use super::{cast::revm_logs_to_ethers_logs, *}; -use crate::environment::{EventBroadcaster, InstructionSender, OutcomeReceiver, OutcomeSender}; +use crate::environment::{InstructionSender, OutcomeReceiver, OutcomeSender}; /// Represents a connection to the EVM contained in the corresponding /// [`Environment`]. -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct Connection { /// Used to send calls and transactions to the [`Environment`] to be /// executed by `revm`. @@ -32,9 +34,7 @@ pub struct Connection { /// call/transact. pub(crate) outcome_receiver: OutcomeReceiver, - /// A reference to the [`EventBroadcaster`] so that more receivers of the - /// broadcast can be taken from it. - pub(crate) event_broadcaster: Arc>, + pub(crate) event_sender: BroadcastSender, /// A collection of `FilterReceiver`s that will receive outgoing logs /// generated by `revm` and output by the [`Environment`]. @@ -49,7 +49,7 @@ impl From<&Environment> for Connection { instruction_sender: Arc::downgrade(instruction_sender), outcome_sender, outcome_receiver, - event_broadcaster: Arc::clone(&environment.socket.event_broadcaster), + event_sender: environment.socket.event_broadcaster.clone(), filter_receivers: Arc::new(Mutex::new(HashMap::new())), } } @@ -103,22 +103,24 @@ impl JsonRpcClient for Connection { ))?; let mut logs = vec![]; let filtered_params = FilteredParams::new(Some(filter_receiver.filter.clone())); - if let Ok(broadcast) = filter_receiver.receiver.try_recv() { - match broadcast { - Broadcast::Event(received_logs) => { - let ethers_logs = revm_logs_to_ethers_logs(received_logs); - for log in ethers_logs { - if filtered_params.filter_address(&log) - && filtered_params.filter_topics(&log) - { - logs.push(log); + if let Some(receiver) = filter_receiver.receiver.as_mut() { + if let Ok(broadcast) = receiver.try_recv() { + match broadcast { + Broadcast::Event(received_logs) => { + let ethers_logs = revm_logs_to_ethers_logs(received_logs); + for log in ethers_logs { + if filtered_params.filter_address(&log) + && filtered_params.filter_topics(&log) + { + logs.push(log); + } } } - } - Broadcast::StopSignal => { - return Err(ProviderError::CustomError( - "The `EventBroadcaster` has stopped!".to_string(), - )) + Broadcast::StopSignal => { + return Err(ProviderError::CustomError( + "The `EventBroadcaster` has stopped!".to_string(), + )); + } } } } @@ -145,12 +147,22 @@ impl PubsubClient for Connection { let id = id.into(); debug!("Subscribing to filter with ID: {:?}", id); - let filter_receiver = self.filter_receivers.lock().unwrap().get(&id).cloned(); - match filter_receiver { - Some(filter_receiver) => { - let stream = stream::poll_fn(move |cx| { - match filter_receiver.receiver.try_recv() { - Ok(Broadcast::Event(logs)) => { + let mut filter_receiver = self + .filter_receivers + .lock() + .unwrap() + .remove(&id) + .take() + .unwrap(); + + let mut receiver = filter_receiver.receiver.take().unwrap(); + let stream = async_stream::stream! { + while let Ok(broadcast) = receiver.recv().await { + match broadcast { + Broadcast::StopSignal => { + break; + } + Broadcast::Event(logs) => { let filtered_params = FilteredParams::new(Some(filter_receiver.filter.clone())); let ethers_logs = revm_logs_to_ethers_logs(logs); @@ -173,39 +185,23 @@ impl PubsubClient for Connection { continue; } }; - return Poll::Ready(Some(raw_log)); + yield raw_log; } } - Poll::Ready(None) - } - Ok(Broadcast::StopSignal) => { - eprintln!("The `EventBroadcaster` has stopped!"); - Poll::Ready(None) - } - Err(TryRecvError::Empty) => { - // No logs available yet, so we'll try again later - cx.waker().wake_by_ref(); - Poll::Pending - } - Err(TryRecvError::Disconnected) => { - eprintln!("The `EventBroadcaster` has been disconnected!"); - Poll::Ready(None) + } - } - }); - Ok(Box::pin(stream)) + } } - None => Err(ProviderError::CustomError( - "The filter ID does not seem to match any that this client owns!".to_string(), - )), - } + }; + + Ok(Box::pin(stream)) } + // TODO: At the moment, this won't actually drop the stream. fn unsubscribe>(&self, id: T) -> Result<(), Self::Error> { let id = id.into(); debug!("Unsubscribing from filter with ID: {:?}", id); - let mut filter_receivers = self.filter_receivers.lock().unwrap(); - if filter_receivers.remove(&id).is_some() { + if self.filter_receivers.lock().unwrap().remove(&id).is_some() { Ok(()) } else { Err(ProviderError::CustomError( @@ -218,7 +214,7 @@ impl PubsubClient for Connection { /// Packages together a [`crossbeam_channel::Receiver>`] along with a /// [`Filter`] for events. Allows the client to have a stream of filtered /// events. -#[derive(Clone, Debug)] +#[derive(Debug)] pub(crate) struct FilterReceiver { /// The filter definition used for this receiver. /// Comes from the `ethers-rs` crate. @@ -226,5 +222,5 @@ pub(crate) struct FilterReceiver { /// The receiver for the channel that receives logs from the broadcaster. /// These are filtered upon reception. - pub(crate) receiver: crossbeam_channel::Receiver, + pub(crate) receiver: Option>, } diff --git a/arbiter-core/src/middleware/mod.rs b/arbiter-core/src/middleware/mod.rs index 8d8130f9..19b7ddc2 100644 --- a/arbiter-core/src/middleware/mod.rs +++ b/arbiter-core/src/middleware/mod.rs @@ -94,7 +94,7 @@ pub mod nonce_middleware; /// Use a seed like `Some("test_label")` for maintaining a /// consistent address across simulations and client labeling. Seeding is be /// useful for debugging and post-processing. -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct RevmMiddleware { provider: Provider, wallet: EOA, @@ -222,7 +222,7 @@ impl RevmMiddleware { instruction_sender: Arc::downgrade(instruction_sender), outcome_sender, outcome_receiver: outcome_receiver.clone(), - event_broadcaster: Arc::clone(&environment.socket.event_broadcaster), + event_sender: environment.socket.event_broadcaster.clone(), filter_receivers: Arc::new(Mutex::new(HashMap::new())), }; let provider = Provider::new(connection); @@ -687,22 +687,11 @@ impl Middleware for RevmMiddleware { hasher.update(serde_json::to_string(&args).map_err(RevmMiddlewareError::Json)?); let hash = hasher.finalize(); let id = ethers::types::U256::from(ethers::types::H256::from_slice(&hash).as_bytes()); - let (event_sender, event_receiver) = crossbeam_channel::unbounded::(); + let event_receiver = self.provider().as_ref().event_sender.subscribe(); let filter_receiver = FilterReceiver { filter, - receiver: event_receiver, + receiver: Some(event_receiver), }; - self.provider() - .as_ref() - .event_broadcaster - .lock() - .map_err(|e| { - RevmMiddlewareError::EventBroadcaster(format!( - "Failed to gain lock on the `Connection`'s `event_broadcaster` due to {:?} ", - e - )) - })? - .add_sender(event_sender, None); self.provider() .as_ref() .filter_receivers diff --git a/arbiter-core/src/tests/data_collection_integration.rs b/arbiter-core/src/tests/data_collection_integration.rs index de895e05..245b1e04 100644 --- a/arbiter-core/src/tests/data_collection_integration.rs +++ b/arbiter-core/src/tests/data_collection_integration.rs @@ -19,7 +19,7 @@ async fn generate_events( lex: LiquidExchange, client: Arc, ) -> Result<(), RevmMiddlewareError> { - for _ in 0..5 { + for _ in 0..2 { arbx.approve(client.address(), U256::from(1)) .send() .await @@ -41,12 +41,14 @@ async fn generate_events( #[tokio::test] async fn data_capture() { + std::env::set_var("RUST_LOG", "trace"); + tracing_subscriber::fmt::init(); let (env, client) = startup_user_controlled().unwrap(); let (arbx, arby, lex) = deploy_liquid_exchange(client.clone()).await.unwrap(); println!("Deployed contracts"); // default_listener - EventLogger::builder() + let logger_task = EventLogger::builder() .add(arbx.events(), "arbx") .add(arby.events(), "arby") .add(lex.events(), "lex") @@ -90,6 +92,8 @@ async fn data_capture() { let _ = env.stop(); + logger_task.await.unwrap(); + std::thread::sleep(std::time::Duration::from_secs(1)); assert!(Path::new("./data/output.csv").exists()); assert!(Path::new("./data/output.parquet").exists()); assert!(Path::new("./data/output.json").exists()); @@ -102,22 +106,33 @@ async fn data_stream() { tracing_subscriber::fmt::init(); let (env, client) = startup_user_controlled().unwrap(); let (arbx, arby, lex) = deploy_liquid_exchange(client.clone()).await.unwrap(); - println!("Deployed contracts"); + println!( + "Deployed +contracts" + ); // default_listener - let streamer = EventLogger::builder() - .add_stream(arbx.events()) - .add_stream(arby.events()) - .add_stream(lex.events()) - .stream(); + let mut streamer = Box::pin( + EventLogger::builder() + .add_stream(arbx.events()) + .add_stream(lex.events()) + .stream() + .unwrap(), + ); generate_events(arbx, arby, lex, client.clone()) .await .unwrap_or_else(|e| { panic!("Error generating events: {}", e); }); - panic!("This test is not complete"); - let stream_buffer = streamer.enumerate().collect::>().await; - println!("Buffer: {:?}", stream_buffer); + let mut idx = 0; + while let Some(item) = streamer.next().await { + println!("item: {}", item); + idx += 1; + if idx == 4 { + break; + } + } let _ = env.stop(); + assert_eq!(idx, 4); } diff --git a/arbiter-engine/Cargo.toml b/arbiter-engine/Cargo.toml index 06799070..9df67c7d 100644 --- a/arbiter-engine/Cargo.toml +++ b/arbiter-engine/Cargo.toml @@ -18,8 +18,7 @@ tokio.workspace = true async-stream.workspace = true anyhow = { version = "=1.0.79" } tracing.workspace = true -tokio-stream = "0.1.14" -async-broadcast = "0.6.0" +tokio-stream = "0.1.14" futures = "0.3.30" crossbeam-channel.workspace = true arbiter-core.workspace = true diff --git a/arbiter-engine/src/agent.rs b/arbiter-engine/src/agent.rs index 2d175d8b..f2b4aee7 100644 --- a/arbiter-engine/src/agent.rs +++ b/arbiter-engine/src/agent.rs @@ -25,7 +25,10 @@ use ethers::contract::{EthLogDecode, Event}; use futures::stream::{Stream, StreamExt}; use futures_util::future::join_all; use serde::de::DeserializeOwned; -use tokio::task::JoinHandle; +use tokio::{ + sync::broadcast::{channel, Receiver, Sender}, + task::JoinHandle, +}; use super::*; use crate::{ @@ -74,7 +77,7 @@ pub struct Agent { /// The messager the agent uses to send and receive messages from other /// agents. - pub messager: Messager, + pub messager: Option, /// The client the agent uses to interact with the blockchain. pub client: Arc, @@ -89,10 +92,7 @@ pub struct Agent { /// The pipeline for yielding events from the centralized event streamer /// (for both messages and Ethereum events) to agents. - distributor: ( - async_broadcast::Sender, - async_broadcast::Receiver, - ), + distributor: (Sender, Receiver), broadcast_task: Option + Send>>>>, } @@ -102,11 +102,11 @@ impl Agent { pub fn new(id: &str, world: &World) -> Self { let messager = world.messager.for_agent(id); let client = RevmMiddleware::new(&world.environment, Some(id)).unwrap(); - let distributor = async_broadcast::broadcast(512); + let distributor = channel(512); Self { id: id.to_owned(), state: State::Uninitialized, - messager, + messager: Some(messager), client, event_streamer: Some(EventLogger::builder()), behavior_engines: None, @@ -129,7 +129,7 @@ impl Agent { mut self, behavior: impl Behavior + 'static, ) -> Self { - let event_receiver = self.distributor.0.new_receiver(); + let event_receiver = self.distributor.0.subscribe(); let engine = Engine::new(behavior, event_receiver); if let Some(engines) = &mut self.behavior_engines { @@ -178,7 +178,7 @@ impl StateMachine for Agent { State::Processing => { debug!("Agent is processing."); self.state = state; - let messager = self.messager.clone(); + let messager = self.messager.take().unwrap(); let message_stream = messager .stream() .map(|msg| serde_json::to_string(&msg).unwrap_or_else(|e| e.to_string())); @@ -204,7 +204,7 @@ impl StateMachine for Agent { self.broadcast_task = Some(tokio::spawn(async move { while let Some(event) = event_stream.next().await { println!("Broadcasting event through agent comms: {:?}", event); - sender.broadcast(event).await.unwrap(); + sender.send(event).unwrap(); } event_stream })); @@ -230,7 +230,7 @@ mod tests { std::env::set_var("RUST_LOG", "trace"); tracing_subscriber::fmt::init(); - let world = World::new("world"); + let mut world = World::new("world"); let agent = Agent::new("agent", &world); let arb = ArbiterToken::deploy( @@ -247,9 +247,8 @@ mod tests { // THIS COUYLD BE A SINGLE FUNCTION AS IT IS IN THE AGENT::PROCESS, but it is // annoyikng to do so. - let messager = agent.messager.clone(); + let messager = agent.messager.take().unwrap(); let message_stream = messager - .clone() .stream() .map(|msg| serde_json::to_string(&msg).unwrap_or_else(|e| e.to_string())); let eth_event_stream = agent.event_streamer.take().unwrap().stream(); @@ -267,9 +266,10 @@ mod tests { Box::pin(message_stream) }; + let outside_messager = world.messager.join_with_id(None); let message_task = tokio::spawn(async move { for _ in 0..5 { - messager + outside_messager .send(Message { from: "god".to_string(), to: messager::To::All, diff --git a/arbiter-engine/src/examples/timed_message.rs b/arbiter-engine/src/examples/timed_message.rs index c5029ab3..22ab2f43 100644 --- a/arbiter-engine/src/examples/timed_message.rs +++ b/arbiter-engine/src/examples/timed_message.rs @@ -50,7 +50,6 @@ impl Behavior for TimedMessage { } } -#[ignore = "This is a work in progress and does not work and does not ever terminate."] #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn echoer() { std::env::set_var("RUST_LOG", "trace"); @@ -63,11 +62,15 @@ async fn echoer() { delay: 1, receive_data: "Hello, world!".to_owned(), send_data: "Hello, world!".to_owned(), - messager: agent.messager.clone(), + messager: agent + .messager + .as_ref() + .unwrap() + .join_with_id(Some(AGENT_ID.to_owned())), }; world.add_agent(agent.with_behavior(behavior)); - let messager = world.messager.clone(); + let messager = world.messager.join_with_id(None); let task = world.run(); let message = Message { @@ -80,7 +83,7 @@ async fn echoer() { task.await; } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn ping_pong() { std::env::set_var("RUST_LOG", "trace"); tracing_subscriber::fmt::init(); @@ -92,13 +95,21 @@ async fn ping_pong() { delay: 1, receive_data: "pong".to_owned(), send_data: "ping".to_owned(), - messager: agent.messager.clone(), + messager: agent + .messager + .as_ref() + .unwrap() + .join_with_id(Some(AGENT_ID.to_owned())), }; let behavior_pong = TimedMessage { delay: 1, receive_data: "ping".to_owned(), send_data: "pong".to_owned(), - messager: agent.messager.clone(), + messager: agent + .messager + .as_ref() + .unwrap() + .join_with_id(Some(AGENT_ID.to_owned())), }; world.add_agent( @@ -107,7 +118,7 @@ async fn ping_pong() { .with_behavior(behavior_pong), ); - let messager = world.messager.clone(); + let messager = world.messager.join_with_id(None); let task = world.run(); let init_message = Message { @@ -120,7 +131,7 @@ async fn ping_pong() { task.await; } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn ping_pong_two_agent() { std::env::set_var("RUST_LOG", "trace"); tracing_subscriber::fmt::init(); @@ -132,7 +143,11 @@ async fn ping_pong_two_agent() { delay: 1, receive_data: "pong".to_owned(), send_data: "ping".to_owned(), - messager: agent_ping.messager.clone(), + messager: agent_ping + .messager + .as_ref() + .unwrap() + .join_with_id(Some("agent_ping".to_owned())), }; let agent_pong = Agent::new("agent_pong", &world); @@ -140,13 +155,17 @@ async fn ping_pong_two_agent() { delay: 1, receive_data: "ping".to_owned(), send_data: "pong".to_owned(), - messager: agent_pong.messager.clone(), + messager: agent_pong + .messager + .as_ref() + .unwrap() + .join_with_id(Some("agent_pong".to_owned())), }; world.add_agent(agent_ping.with_behavior(behavior_ping)); world.add_agent(agent_pong.with_behavior(behavior_pong)); - let messager = world.messager.clone(); + let messager = world.messager.join_with_id(None); let task = world.run(); let init_message = Message { diff --git a/arbiter-engine/src/examples/token_minter.rs b/arbiter-engine/src/examples/token_minter.rs index fd293077..cfaba89e 100644 --- a/arbiter-engine/src/examples/token_minter.rs +++ b/arbiter-engine/src/examples/token_minter.rs @@ -18,15 +18,15 @@ const TOKEN_SYMBOL: &str = "ARB"; const TOKEN_DECIMALS: u8 = 18; /// The token admin is responsible for handling token minting requests. -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct TokenAdmin { /// The identifier of the token admin. pub token_data: HashMap, pub tokens: Option>>, - // TODO: We should not have to have a client or a messager put here explicitly, they should - // come from the Agent the behavior is given to. + // TODO: We should not have to have a client or a messager put here + // explicitly, they should come from the Agent the behavior is given to. pub client: Arc, pub messager: Messager, } @@ -80,7 +80,8 @@ pub struct MintRequest { #[async_trait::async_trait] impl Behavior for TokenAdmin { - #[tracing::instrument(skip(self), fields(id = self.messager.id.as_deref()))] + #[tracing::instrument(skip(self), fields(id = +self.messager.id.as_deref()))] async fn sync(&mut self) { for token_data in self.token_data.values_mut() { let token = ArbiterToken::deploy( @@ -103,7 +104,8 @@ impl Behavior for TokenAdmin { } } - #[tracing::instrument(skip(self), fields(id = self.messager.id.as_deref()))] + #[tracing::instrument(skip(self), fields(id = +self.messager.id.as_deref()))] async fn process(&mut self, event: Message) { if self.tokens.is_none() { error!( @@ -150,7 +152,7 @@ the token admin before running the simulation." /// The token requester is responsible for requesting tokens from the token /// admin. This agents is purely for testing purposes as far as I can tell. -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct TokenRequester { /// The tokens that the token requester has requested. pub token_data: TokenData, @@ -183,11 +185,12 @@ impl TokenRequester { #[async_trait::async_trait] impl Behavior for TokenRequester { - #[tracing::instrument(skip(self), fields(id = self.messager.id.as_deref()))] + #[tracing::instrument(skip(self), fields(id = +self.messager.id.as_deref()))] async fn startup(&mut self) { trace!("Requesting address of token: {:?}", self.token_data.name); let message = Message { - from: self.messager.clone().id.unwrap(), + from: self.messager.id.clone().unwrap(), to: To::Agent(self.request_to.clone()), data: serde_json::to_string(&TokenAdminQuery::AddressOf(self.token_data.name.clone())) .unwrap(), @@ -195,13 +198,22 @@ impl Behavior for TokenRequester { self.messager.send(message).await; } - #[tracing::instrument(skip(self), fields(id = self.messager.id.as_deref()))] + #[tracing::instrument(skip(self), fields(id = +self.messager.id.as_deref()))] async fn process(&mut self, event: Message) { if let Ok(token_data) = serde_json::from_str::(&event.data) { - trace!("Got token data: {:?}", token_data); - trace!("Requesting first mint of token: {:?}", self.token_data.name); + trace!( + "Got +token data: {:?}", + token_data + ); + trace!( + "Requesting first mint of +token: {:?}", + self.token_data.name + ); let message = Message { - from: self.messager.clone().id.unwrap(), + from: self.messager.id.clone().unwrap(), to: To::Agent(self.request_to.clone()), data: serde_json::to_string(&TokenAdminQuery::MintRequest(MintRequest { token: self.token_data.name.clone(), @@ -217,12 +229,17 @@ impl Behavior for TokenRequester { #[async_trait::async_trait] impl Behavior for TokenRequester { - #[tracing::instrument(skip(self), fields(id = self.messager.id.as_deref()))] + #[tracing::instrument(skip(self), fields(id = +self.messager.id.as_deref()))] async fn process(&mut self, event: arbiter_token::TransferFilter) { - trace!("Got event for `TokenRequester` logger: {:?}", event); + trace!( + "Got event for +`TokenRequester` logger: {:?}", + event + ); std::thread::sleep(std::time::Duration::from_secs(1)); let message = Message { - from: self.messager.clone().id.unwrap(), + from: self.messager.id.clone().unwrap(), to: To::Agent(self.request_to.clone()), data: serde_json::to_string(&TokenAdminQuery::MintRequest(MintRequest { token: self.token_data.name.clone(), @@ -231,21 +248,28 @@ impl Behavior for TokenRequester { })) .unwrap(), }; + self.messager.send(message).await; } } #[ignore] #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn token_minter_simulation() { - std::env::set_var("RUST_LOG", "arbiter_engine=trace"); + std::env::set_var("RUST_LOG", "trace"); tracing_subscriber::fmt::init(); let mut world = World::new("test_world"); // Create the token admin agent let token_admin = Agent::new(TOKEN_ADMIN_ID, &world); - let mut token_admin_behavior = - TokenAdmin::new(token_admin.client.clone(), token_admin.messager.clone()); + let mut token_admin_behavior = TokenAdmin::new( + token_admin.client.clone(), + token_admin + .messager + .as_ref() + .unwrap() + .join_with_id(Some(TOKEN_ADMIN_ID.to_owned())), + ); token_admin_behavior.add_token(TokenData { name: TOKEN_NAME.to_owned(), symbol: TOKEN_SYMBOL.to_owned(), @@ -258,17 +282,30 @@ async fn token_minter_simulation() { let token_requester = Agent::new(REQUESTER_ID, &world); let token_requester_behavior = TokenRequester::new( token_requester.client.clone(), - token_requester.messager.clone(), + token_requester + .messager + .as_ref() + .unwrap() + .join_with_id(Some(REQUESTER_ID.to_owned())), ); let transfer_event = ArbiterToken::new( Address::from_str("0x240a76d4c8a7dafc6286db5fa6b589e8b21fc00f").unwrap(), token_requester.client.clone(), ) .transfer_filter(); + + let token_requester_behavior_again = TokenRequester::new( + token_requester.client.clone(), + token_requester + .messager + .as_ref() + .unwrap() + .join_with_id(Some(REQUESTER_ID.to_owned())), + ); world.add_agent( token_requester - .with_behavior::(token_requester_behavior.clone()) - .with_behavior::(token_requester_behavior) + .with_behavior::(token_requester_behavior) + .with_behavior::(token_requester_behavior_again) .with_event(transfer_event), ); diff --git a/arbiter-engine/src/machine.rs b/arbiter-engine/src/machine.rs index 0818201b..34a2b468 100644 --- a/arbiter-engine/src/machine.rs +++ b/arbiter-engine/src/machine.rs @@ -3,8 +3,8 @@ use std::fmt::Debug; -use async_broadcast::Receiver; use serde::de::DeserializeOwned; +use tokio::sync::broadcast::Receiver; use super::*; @@ -84,7 +84,7 @@ where /// The receiver of events that the [`Engine`] will process. /// The [`State::Processing`] stage will attempt a decode of the [`String`]s /// into the event type ``. - event_receiver: Receiver, + event_receiver: Option>, phantom: std::marker::PhantomData, } @@ -99,7 +99,7 @@ where Self { behavior: Some(behavior), state: State::Uninitialized, - event_receiver, + event_receiver: Some(event_receiver), phantom: std::marker::PhantomData, } } @@ -139,7 +139,7 @@ where State::Processing => { trace!("Behavior is processing."); let mut behavior = self.behavior.take().unwrap(); - let mut receiver = self.event_receiver.clone(); // TODO Could use Option::take() if we don't want to clone. + let mut receiver = self.event_receiver.take().unwrap(); let behavior_task = tokio::spawn(async move { while let Ok(event) = receiver.recv().await { println!("Event received: {:?}", event); diff --git a/arbiter-engine/src/messager.rs b/arbiter-engine/src/messager.rs index ece378df..ea6fefff 100644 --- a/arbiter-engine/src/messager.rs +++ b/arbiter-engine/src/messager.rs @@ -1,9 +1,7 @@ //! The messager module contains the core messager layer for the Arbiter Engine. -use std::pin::Pin; - -use async_broadcast::{broadcast, Receiver as BroadcastReceiver, Sender as BroadcastSender}; use futures_util::Stream; +use tokio::sync::broadcast::{channel, Receiver, Sender}; use super::*; @@ -32,14 +30,14 @@ pub enum To { } /// A messager that can be used to send messages between agents. -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct Messager { /// The identifier of the entity that is using the messager. pub id: Option, - pub(crate) broadcast_sender: BroadcastSender, + pub(crate) broadcast_sender: Sender, - broadcast_receiver: Option>, + broadcast_receiver: Option>, } impl Messager { @@ -49,7 +47,7 @@ impl Messager { /// Creates a new messager with the given capacity. #[allow(clippy::new_without_default)] pub fn new() -> Self { - let (broadcast_sender, broadcast_receiver) = broadcast(512); + let (broadcast_sender, broadcast_receiver) = channel(512); Self { broadcast_sender, broadcast_receiver: Some(broadcast_receiver), @@ -62,7 +60,7 @@ impl Messager { pub(crate) fn for_agent(&self, id: &str) -> Self { Self { broadcast_sender: self.broadcast_sender.clone(), - broadcast_receiver: self.broadcast_receiver.clone(), + broadcast_receiver: Some(self.broadcast_sender.subscribe()), id: Some(id.to_owned()), } } @@ -90,9 +88,17 @@ impl Messager { stream } + pub fn join_with_id(&self, id: Option) -> Messager { + Messager { + broadcast_sender: self.broadcast_sender.clone(), + broadcast_receiver: Some(self.broadcast_sender.subscribe()), + id, + } + } + /// Sends a message to the messager. pub async fn send(&self, message: Message) { trace!("Sending message via messager."); - self.broadcast_sender.broadcast(message).await.unwrap(); + self.broadcast_sender.send(message).unwrap(); } } From b58e50b1cd84b3796730371b8d164d4dd80211ab Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Fri, 19 Jan 2024 11:57:57 -0700 Subject: [PATCH 14/20] fix: `arbiter-core` tests --- arbiter-core/src/environment/mod.rs | 15 ++++++++++++--- .../src/tests/data_collection_integration.rs | 7 +++---- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/arbiter-core/src/environment/mod.rs b/arbiter-core/src/environment/mod.rs index a53e65cd..24ccea67 100644 --- a/arbiter-core/src/environment/mod.rs +++ b/arbiter-core/src/environment/mod.rs @@ -547,8 +547,12 @@ impl Environment { transaction_index: transaction_index.into(), cumulative_gas_per_block, }; - let res = event_broadcaster.send(Broadcast::Event(execution_result.logs())); - println!("Result: {:?}", res); + match event_broadcaster.send(Broadcast::Event(execution_result.logs())) { + Ok(_) => {} + Err(_) => { + warn!("Stop signal was not sent to any listeners. Are there any listeners?") + } + } outcome_sender .send(Ok(Outcome::TransactionCompleted( execution_result, @@ -649,7 +653,12 @@ impl Environment { .map_err(|e| EnvironmentError::Communication(e.to_string()))?; } Instruction::Stop(outcome_sender) => { - event_broadcaster.send(Broadcast::StopSignal).unwrap(); + match event_broadcaster.send(Broadcast::StopSignal) { + Ok(_) => {} + Err(_) => { + warn!("Stop signal was not sent to any listeners. Are there any listeners?") + } + } outcome_sender .send(Ok(Outcome::StopCompleted(evm.db.unwrap()))) .map_err(|e| EnvironmentError::Communication(e.to_string()))?; diff --git a/arbiter-core/src/tests/data_collection_integration.rs b/arbiter-core/src/tests/data_collection_integration.rs index 245b1e04..619a58c1 100644 --- a/arbiter-core/src/tests/data_collection_integration.rs +++ b/arbiter-core/src/tests/data_collection_integration.rs @@ -41,8 +41,7 @@ async fn generate_events( #[tokio::test] async fn data_capture() { - std::env::set_var("RUST_LOG", "trace"); - tracing_subscriber::fmt::init(); + // let (env, client) = startup_user_controlled().unwrap(); let (arbx, arby, lex) = deploy_liquid_exchange(client.clone()).await.unwrap(); println!("Deployed contracts"); @@ -102,8 +101,8 @@ async fn data_capture() { #[tokio::test] async fn data_stream() { - std::env::set_var("RUST_LOG", "trace"); - tracing_subscriber::fmt::init(); + // std::env::set_var("RUST_LOG", "trace"); + // tracing_subscriber::fmt::init(); let (env, client) = startup_user_controlled().unwrap(); let (arbx, arby, lex) = deploy_liquid_exchange(client.clone()).await.unwrap(); println!( From a5d9af8aee32201456fcd789ea37a5efa5394ea4 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Fri, 19 Jan 2024 12:35:28 -0700 Subject: [PATCH 15/20] make clippy happy --- arbiter-core/src/data_collection.rs | 5 +---- arbiter-core/src/environment/mod.rs | 14 ++++---------- arbiter-core/src/middleware/connection.rs | 7 ++----- arbiter-engine/src/machine.rs | 1 + arbiter-engine/src/messager.rs | 2 ++ arbiter-engine/src/world.rs | 2 ++ 6 files changed, 12 insertions(+), 19 deletions(-) diff --git a/arbiter-core/src/data_collection.rs b/arbiter-core/src/data_collection.rs index 55a5852e..e659b3b9 100644 --- a/arbiter-core/src/data_collection.rs +++ b/arbiter-core/src/data_collection.rs @@ -38,10 +38,7 @@ use polars::{ }; use serde::Serialize; use serde_json::Value; -use tokio::{ - sync::broadcast::{Receiver as BroadcastReceiver, Sender as BroadcastSender}, - task::JoinHandle, -}; +use tokio::{sync::broadcast::Receiver as BroadcastReceiver, task::JoinHandle}; use super::*; use crate::{ diff --git a/arbiter-core/src/environment/mod.rs b/arbiter-core/src/environment/mod.rs index 24ccea67..fc9b8e31 100644 --- a/arbiter-core/src/environment/mod.rs +++ b/arbiter-core/src/environment/mod.rs @@ -45,12 +45,8 @@ use revm::{ }; use serde::{Deserialize, Serialize}; use thiserror::Error; -use tokio::sync::{ - broadcast::{channel, Sender as BroadcastSender}, - oneshot, -}; +use tokio::sync::broadcast::{channel, Sender as BroadcastSender}; -use self::data_collection::EventLogger; use super::*; #[cfg_attr(doc, doc(hidden))] #[cfg_attr(doc, allow(unused_imports))] @@ -89,10 +85,6 @@ pub(crate) type OutcomeSender = Sender>; /// emitted from transactions. pub(crate) type OutcomeReceiver = Receiver>; -/// Alias for the receiver used in the [`EventBroadcaster`] that accepts -/// shutdown signals from child processes. -pub(crate) type ShutDownReceiver = Receiver<()>; - /// Represents a sandboxed EVM environment. /// /// ## Communication @@ -550,7 +542,9 @@ impl Environment { match event_broadcaster.send(Broadcast::Event(execution_result.logs())) { Ok(_) => {} Err(_) => { - warn!("Stop signal was not sent to any listeners. Are there any listeners?") + warn!( + "Event was not sent to any listeners. Are there any listeners?" + ) } } outcome_sender diff --git a/arbiter-core/src/middleware/connection.rs b/arbiter-core/src/middleware/connection.rs index 37f414c9..f4c11e95 100644 --- a/arbiter-core/src/middleware/connection.rs +++ b/arbiter-core/src/middleware/connection.rs @@ -4,14 +4,11 @@ use std::{ fmt::Debug, pin::Pin, sync::{Arc, Weak}, - task::Poll, }; -use futures_util::{stream, Stream}; +use futures_util::Stream; use serde_json::value::RawValue; -use tokio::sync::broadcast::{ - error::TryRecvError, Receiver as BroadcastReceiver, Sender as BroadcastSender, -}; +use tokio::sync::broadcast::{Receiver as BroadcastReceiver, Sender as BroadcastSender}; use super::{cast::revm_logs_to_ethers_logs, *}; use crate::environment::{InstructionSender, OutcomeReceiver, OutcomeSender}; diff --git a/arbiter-engine/src/machine.rs b/arbiter-engine/src/machine.rs index 34a2b468..1ee7742c 100644 --- a/arbiter-engine/src/machine.rs +++ b/arbiter-engine/src/machine.rs @@ -79,6 +79,7 @@ where /// The behavior the [`Engine`] runs. pub behavior: Option, + /// The current state of the [`Engine`]. pub state: State, /// The receiver of events that the [`Engine`] will process. diff --git a/arbiter-engine/src/messager.rs b/arbiter-engine/src/messager.rs index ea6fefff..494ea656 100644 --- a/arbiter-engine/src/messager.rs +++ b/arbiter-engine/src/messager.rs @@ -88,6 +88,8 @@ impl Messager { stream } + /// Returns a [`Messager`] interface connected to the same instance but with + /// the `id` provided. pub fn join_with_id(&self, id: Option) -> Messager { Messager { broadcast_sender: self.broadcast_sender.clone(), diff --git a/arbiter-engine/src/world.rs b/arbiter-engine/src/world.rs index fc320537..e2ec9329 100644 --- a/arbiter-engine/src/world.rs +++ b/arbiter-engine/src/world.rs @@ -57,6 +57,7 @@ pub struct World { /// The identifier of the world. pub id: String, + /// The state of the [`World`]. pub state: State, /// The agents in the world. @@ -93,6 +94,7 @@ impl World { agents.insert(id.to_owned(), agent); } + /// Runs the world through up to the [`State::Processing`] stage. pub async fn run(&mut self) { self.run_state(State::Syncing).await; From 982a5b2596670ea4ff8571861e41d0b2be36e220 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Fri, 19 Jan 2024 12:49:13 -0700 Subject: [PATCH 16/20] feat: `World::stop()` method This commit broke stuff! --- arbiter-engine/src/agent.rs | 68 +++++----- arbiter-engine/src/examples/timed_message.rs | 20 ++- arbiter-engine/src/examples/token_minter.rs | 10 +- arbiter-engine/src/machine.rs | 68 ++++++---- arbiter-engine/src/messager.rs | 5 +- arbiter-engine/src/world.rs | 126 +++++++++---------- 6 files changed, 167 insertions(+), 130 deletions(-) diff --git a/arbiter-engine/src/agent.rs b/arbiter-engine/src/agent.rs index f2b4aee7..b545f313 100644 --- a/arbiter-engine/src/agent.rs +++ b/arbiter-engine/src/agent.rs @@ -26,10 +26,11 @@ use futures::stream::{Stream, StreamExt}; use futures_util::future::join_all; use serde::de::DeserializeOwned; use tokio::{ - sync::broadcast::{channel, Receiver, Sender}, + sync::broadcast::{channel, Receiver as BroadcastReceiver, Sender as BroadcastSender}, task::JoinHandle, }; +use self::machine::MachineInstruction; use super::*; use crate::{ machine::{Behavior, Engine, State, StateMachine}, @@ -92,7 +93,7 @@ pub struct Agent { /// The pipeline for yielding events from the centralized event streamer /// (for both messages and Ethereum events) to agents. - distributor: (Sender, Receiver), + pub(crate) distributor: (BroadcastSender, BroadcastReceiver), broadcast_task: Option + Send>>>>, } @@ -140,12 +141,11 @@ impl Agent { self } - pub(crate) async fn run(&mut self, state: State) { - self.state = state; + pub(crate) async fn run(&mut self, instruction: MachineInstruction) { let behavior_engines = self.behavior_engines.take().unwrap(); let behavior_tasks = join_all(behavior_engines.into_iter().map(|mut engine| { tokio::spawn(async move { - engine.run_state(state).await; + engine.execute(instruction).await; engine }) })); @@ -162,22 +162,20 @@ impl Agent { #[async_trait::async_trait] impl StateMachine for Agent { #[tracing::instrument(skip(self), fields(id = self.id))] - async fn run_state(&mut self, state: State) { - match state { - State::Uninitialized => { - unimplemented!("This never gets called.") - } - State::Syncing => { + async fn execute(&mut self, instruction: MachineInstruction) { + match instruction { + MachineInstruction::Sync => { debug!("Agent is syncing."); - self.run(state).await; + self.state = State::Syncing; + self.run(instruction).await; } - State::Startup => { + MachineInstruction::Start => { debug!("Agent is starting up."); - self.run(state).await; + self.run(instruction).await; } - State::Processing => { + MachineInstruction::Process => { debug!("Agent is processing."); - self.state = state; + self.state = State::Processing; let messager = self.messager.take().unwrap(); let message_stream = messager .stream() @@ -204,14 +202,16 @@ impl StateMachine for Agent { self.broadcast_task = Some(tokio::spawn(async move { while let Some(event) = event_stream.next().await { println!("Broadcasting event through agent comms: {:?}", event); - sender.send(event).unwrap(); + sender.send(event).unwrap(); // TODO: If this errors + // out, we can exit the + // task } event_stream })); - self.run(state).await; + self.run(instruction).await; } - State::Stopped => { - todo!() + MachineInstruction::Stop => { + unreachable!("This is never explicitly called on an agent.") } } } @@ -230,7 +230,7 @@ mod tests { std::env::set_var("RUST_LOG", "trace"); tracing_subscriber::fmt::init(); - let mut world = World::new("world"); + let world = World::new("world"); let agent = Agent::new("agent", &world); let arb = ArbiterToken::deploy( @@ -245,8 +245,8 @@ mod tests { let mut agent = agent.with_event(arb.events()); let address = agent.client.address(); - // THIS COUYLD BE A SINGLE FUNCTION AS IT IS IN THE AGENT::PROCESS, but it is - // annoyikng to do so. + // TODO: (START BLOCK) It would be nice to get this block to be a single + // function that isn't copy and pasted from above. let messager = agent.messager.take().unwrap(); let message_stream = messager .stream() @@ -265,6 +265,7 @@ mod tests { trace!("Agent only sees message stream."); Box::pin(message_stream) }; + // TODO: (END BLOCK) let outside_messager = world.messager.join_with_id(None); let message_task = tokio::spawn(async move { @@ -276,12 +277,14 @@ mod tests { data: "hello".to_string(), }) .await; - // tokio::time::sleep(std::time::Duration::from_secs(1)).await; } }); let eth_event_task = tokio::spawn(async move { - for _ in 0..5 { + for i in 0..5 { + if i == 0 { + tokio::time::sleep(std::time::Duration::from_secs(1)).await; + } arb.approve(address, U256::from(1)) .send() .await @@ -291,17 +294,18 @@ mod tests { } }); - let mut event_idx = 0; - let mut message_idx = 0; + let mut idx = 0; let print_task = tokio::spawn(async move { while let Some(msg) = event_stream.next().await { println!("Printing message in test: {:?}", msg); - if msg == "{\"ApprovalFilter\":{\"owner\":\"0xe7a46f3d9f0e9b9c02f58f95e3bcee2db54050b0\",\"spender\":\"0xe7a46f3d9f0e9b9c02f58f95e3bcee2db54050b0\",\"amount\":\"0x1\"}}" { - event_idx += 1; - println!("Event idx: {}", event_idx); + if idx < 5 { + assert_eq!(msg, "{\"from\":\"god\",\"to\":\"All\",\"data\":\"hello\"}"); } else { - message_idx += 1; - println!("Message idx: {}", message_idx); + assert_eq!(msg, "{\"ApprovalFilter\":{\"owner\":\"0xe7a46f3d9f0e9b9c02f58f95e3bcee2db54050b0\",\"spender\":\"0xe7a46f3d9f0e9b9c02f58f95e3bcee2db54050b0\",\"amount\":\"0x1\"}}"); + } + idx += 1; + if idx == 10 { + break; } } }); diff --git a/arbiter-engine/src/examples/timed_message.rs b/arbiter-engine/src/examples/timed_message.rs index 22ab2f43..881d3e8f 100644 --- a/arbiter-engine/src/examples/timed_message.rs +++ b/arbiter-engine/src/examples/timed_message.rs @@ -15,12 +15,15 @@ struct TimedMessage { receive_data: String, send_data: String, messager: Messager, + count: u64, + max_count: Option, } #[async_trait::async_trait] impl Behavior for TimedMessage { async fn process(&mut self, event: Message) { trace!("Processing event."); + if self.count == self.max_count.unwrap_or(u64::MAX) {} if event.data != self.receive_data { return; } else { @@ -67,10 +70,12 @@ async fn echoer() { .as_ref() .unwrap() .join_with_id(Some(AGENT_ID.to_owned())), + count: 0, + max_count: Some(5), }; world.add_agent(agent.with_behavior(behavior)); - let messager = world.messager.join_with_id(None); + let messager = world.messager.join_with_id(Some("god".to_owned())); let task = world.run(); let message = Message { @@ -79,7 +84,6 @@ async fn echoer() { data: "Hello, world!".to_owned(), }; messager.send(message).await; - task.await; } @@ -100,6 +104,8 @@ async fn ping_pong() { .as_ref() .unwrap() .join_with_id(Some(AGENT_ID.to_owned())), + count: 0, + max_count: Some(5), }; let behavior_pong = TimedMessage { delay: 1, @@ -110,6 +116,8 @@ async fn ping_pong() { .as_ref() .unwrap() .join_with_id(Some(AGENT_ID.to_owned())), + count: 0, + max_count: Some(5), }; world.add_agent( @@ -118,7 +126,7 @@ async fn ping_pong() { .with_behavior(behavior_pong), ); - let messager = world.messager.join_with_id(None); + let messager = world.messager.join_with_id(Some("god".to_owned())); let task = world.run(); let init_message = Message { @@ -148,6 +156,8 @@ async fn ping_pong_two_agent() { .as_ref() .unwrap() .join_with_id(Some("agent_ping".to_owned())), + count: 0, + max_count: Some(5), }; let agent_pong = Agent::new("agent_pong", &world); @@ -160,12 +170,14 @@ async fn ping_pong_two_agent() { .as_ref() .unwrap() .join_with_id(Some("agent_pong".to_owned())), + count: 0, + max_count: Some(5), }; world.add_agent(agent_ping.with_behavior(behavior_ping)); world.add_agent(agent_pong.with_behavior(behavior_pong)); - let messager = world.messager.join_with_id(None); + let messager = world.messager.join_with_id(Some("god".to_owned())); let task = world.run(); let init_message = Message { diff --git a/arbiter-engine/src/examples/token_minter.rs b/arbiter-engine/src/examples/token_minter.rs index cfaba89e..35036fa2 100644 --- a/arbiter-engine/src/examples/token_minter.rs +++ b/arbiter-engine/src/examples/token_minter.rs @@ -9,7 +9,12 @@ use ethers::{ use tracing::error; use super::*; -use crate::{agent::Agent, machine::Behavior, messager::To, world::World}; +use crate::{ + agent::Agent, + machine::{Behavior, MachineInstruction, StateMachine}, + messager::To, + world::World, +}; const TOKEN_ADMIN_ID: &str = "token_admin"; const REQUESTER_ID: &str = "requester"; @@ -310,4 +315,7 @@ async fn token_minter_simulation() { ); world.run().await; + + std::thread::sleep(std::time::Duration::from_secs(1)); + world.stop().await; } diff --git a/arbiter-engine/src/machine.rs b/arbiter-engine/src/machine.rs index 1ee7742c..50f9ec70 100644 --- a/arbiter-engine/src/machine.rs +++ b/arbiter-engine/src/machine.rs @@ -8,8 +8,31 @@ use tokio::sync::broadcast::Receiver; use super::*; +/// The instructions that can be sent to a [`StateMachine`]. +#[derive(Clone, Copy, Debug)] +pub enum MachineInstruction { + /// Used to make a [`StateMachine`] sync with the world. + Sync, + + /// Used to make a [`StateMachine`] start up. + Start, + + /// Used to make a [`StateMachine`] process events. + /// This will offload the process into a task that can be halted by sending + /// a [`MachineHalt`] message from the [`Messager`]. For our purposes, the + /// [`crate::world::World`] will handle this. + Process, + + /// Used to make a [`StateMachine`] stop. Only applicable for the + /// [`crate::world::World`] currently. + Stop, +} + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub(crate) struct MachineHalt; + /// The state used by any entity implementing [`StateMachine`]. -#[derive(Debug, Copy, Clone)] +#[derive(Clone, Copy, Debug)] pub enum State { /// The entity is not yet running any process. /// This is the state adopted by the entity when it is first created. @@ -25,7 +48,7 @@ pub enum State { /// This is where the entity can engage in its specific start up activities /// that it can do given the current state of the world. /// These are usually quick one-shot activities that are not repeated. - Startup, + Starting, /// The entity is processing. /// This is where the entity can engage in its specific processing @@ -61,7 +84,7 @@ pub trait Behavior: Send + Sync + 'static { #[async_trait::async_trait] pub(crate) trait StateMachine: Send + Sync + 'static { - async fn run_state(&mut self, state: State); + async fn execute(&mut self, instruction: MachineInstruction); } /// The idea of the [`Engine`] is that it drives the [`Behavior`] of a @@ -112,14 +135,11 @@ where B: Behavior, E: DeserializeOwned + Send + Sync + Debug + 'static, { - async fn run_state(&mut self, state: State) { - match state { - State::Uninitialized => { - unimplemented!("This never gets called.") - } - State::Syncing => { + async fn execute(&mut self, instruction: MachineInstruction) { + match instruction { + MachineInstruction::Sync => { trace!("Behavior is syncing."); - self.state = state; + self.state = State::Syncing; let mut behavior = self.behavior.take().unwrap(); let behavior_task = tokio::spawn(async move { behavior.sync().await; @@ -127,9 +147,9 @@ where }); self.behavior = Some(behavior_task.await.unwrap()); } - State::Startup => { + MachineInstruction::Start => { trace!("Behavior is starting up."); - self.state = state; + self.state = State::Starting; let mut behavior = self.behavior.take().unwrap(); let behavior_task = tokio::spawn(async move { behavior.startup().await; @@ -137,7 +157,7 @@ where }); self.behavior = Some(behavior_task.await.unwrap()); } - State::Processing => { + MachineInstruction::Process => { trace!("Behavior is processing."); let mut behavior = self.behavior.take().unwrap(); let mut receiver = self.event_receiver.take().unwrap(); @@ -147,20 +167,26 @@ where let decoding_result = serde_json::from_str::(&event); match decoding_result { Ok(event) => behavior.process(event).await, - Err(_e) => { - trace!( - "Event received by behavior that could not be deserialized." - ); - continue; - } + Err(_) => match serde_json::from_str::(&event) { + Ok(_) => { + warn!("Behavior received `MachineHalt` message. Breaking!"); + break; + } + Err(_) => { + trace!( + "Event received by behavior that could not be deserialized." + ); + continue; + } + }, } } behavior }); self.behavior = Some(behavior_task.await.unwrap()); } - State::Stopped => { - todo!() + MachineInstruction::Stop => { + unreachable!("This is never explicitly called on an engine.") } } } diff --git a/arbiter-engine/src/messager.rs b/arbiter-engine/src/messager.rs index 494ea656..290fd6f3 100644 --- a/arbiter-engine/src/messager.rs +++ b/arbiter-engine/src/messager.rs @@ -69,7 +69,7 @@ impl Messager { /// the agent via [`To::Agent(id)`]. pub fn stream(mut self) -> impl Stream + Send { let mut receiver = self.broadcast_receiver.take().unwrap(); - let stream = async_stream::stream! { + async_stream::stream! { while let Ok(message) = receiver.recv().await { match &message.to { To::All => { @@ -84,8 +84,7 @@ impl Messager { } } } - }; - stream + } } /// Returns a [`Messager`] interface connected to the same instance but with diff --git a/arbiter-engine/src/world.rs b/arbiter-engine/src/world.rs index e2ec9329..c993b9f5 100644 --- a/arbiter-engine/src/world.rs +++ b/arbiter-engine/src/world.rs @@ -17,9 +17,10 @@ use arbiter_core::environment::{builder::EnvironmentBuilder, Environment}; use futures_util::future::{join_all, JoinAll}; -use tokio::task::JoinHandle; +use tokio::{sync::broadcast::Sender as BroadcastSender, task::JoinHandle}; use tracing::info; +use self::machine::{MachineHalt, MachineInstruction}; use super::*; use crate::{ agent::Agent, @@ -63,15 +64,15 @@ pub struct World { /// The agents in the world. pub agents: Option>, + agent_processors: Option>>, + + agent_distributors: Option>>, + /// The environment for the world. pub environment: Environment, /// The messaging layer for the world. pub messager: Messager, - - /// Holds onto the tasks that represent the agent running a specific state - /// transition. - agent_tasks: Option>>, } impl World { @@ -81,7 +82,8 @@ impl World { id: id.to_owned(), state: State::Uninitialized, agents: Some(HashMap::new()), - agent_tasks: None, + agent_processors: None, + agent_distributors: None, environment: EnvironmentBuilder::new().build(), messager: Messager::new(), } @@ -96,35 +98,48 @@ impl World { /// Runs the world through up to the [`State::Processing`] stage. pub async fn run(&mut self) { - self.run_state(State::Syncing).await; - - self.run_state(State::Startup).await; + self.execute(MachineInstruction::Sync).await; + self.execute(MachineInstruction::Start).await; + self.execute(MachineInstruction::Process).await; + } - self.run_state(State::Processing).await; + /// Stops the world by stopping all the behaviors that each of the agents is + /// running. + pub async fn stop(&mut self) { + self.execute(MachineInstruction::Stop).await; } } +// TODO: Idea, when we enter the `State::Processing`, we should pass the task +// into the struct. When we call `MachineInstruction::Stop` we should do message +// passing that will kill the tasks so that they return. This will allow us to +// do graceful shutdowns. + +// TODO: Worth explaining how the process stage is offloaded so it is +// understandable. + +// Right now what we do is we send a HALT message via the agent's distributor +// which means all behaviors should receive this now. If those behaviors all see +// this HALT message and then exit their process, then the await should finish. +// Actually we can probably not have to get the distributors up this high, but +// let's work with this for now. + #[async_trait::async_trait] impl StateMachine for World { - async fn run_state(&mut self, state: State) { - match state { - State::Uninitialized => { - unimplemented!("This never gets called.") - } - State::Syncing => { + async fn execute(&mut self, instruction: MachineInstruction) { + match instruction { + MachineInstruction::Sync => { info!("World is syncing."); - self.state = state; + self.state = State::Syncing; let agents = self.agents.take().unwrap(); - self.agent_tasks = Some(join_all(agents.into_values().map(|mut agent| { + let agent_tasks = join_all(agents.into_values().map(|mut agent| { tokio::spawn(async move { - agent.run_state(state).await; + agent.execute(instruction).await; agent }) - }))); + })); self.agents = Some( - self.agent_tasks - .take() - .unwrap() + agent_tasks .await .into_iter() .map(|res| { @@ -134,20 +149,18 @@ impl StateMachine for World { .collect::>(), ); } - State::Startup => { + MachineInstruction::Start => { info!("World is starting up."); - self.state = state; + self.state = State::Starting; let agents = self.agents.take().unwrap(); - self.agent_tasks = Some(join_all(agents.into_values().map(|mut agent| { + let agent_tasks = join_all(agents.into_values().map(|mut agent| { tokio::spawn(async move { - agent.run_state(state).await; + agent.execute(instruction).await; agent }) - }))); + })); self.agents = Some( - self.agent_tasks - .take() - .unwrap() + agent_tasks .await .into_iter() .map(|res| { @@ -157,51 +170,26 @@ impl StateMachine for World { .collect::>(), ); } - State::Processing => { + MachineInstruction::Process => { info!("World is processing."); - self.state = state; + self.state = State::Processing; let agents = self.agents.take().unwrap(); - self.agent_tasks = Some(join_all(agents.into_values().map(|mut agent| { + let mut agent_distributors = vec![]; + self.agent_processors = Some(join_all(agents.into_values().map(|mut agent| { + agent_distributors.push(agent.distributor.0.clone()); tokio::spawn(async move { - agent.run_state(state).await; + agent.execute(instruction).await; agent }) }))); - self.agents = Some( - self.agent_tasks - .take() - .unwrap() - .await - .into_iter() - .map(|res| { - let agent = res.unwrap(); - (agent.id.clone(), agent) - }) - .collect::>(), - ); + self.agent_distributors = Some(agent_distributors); } - State::Stopped => { - info!("World is starting up."); - self.state = state; - let agents = self.agents.take().unwrap(); - self.agent_tasks = Some(join_all(agents.into_values().map(|mut agent| { - tokio::spawn(async move { - agent.run_state(state).await; - agent - }) - }))); - self.agents = Some( - self.agent_tasks - .take() - .unwrap() - .await - .into_iter() - .map(|res| { - let agent = res.unwrap(); - (agent.id.clone(), agent) - }) - .collect::>(), - ); + MachineInstruction::Stop => { + let halt = serde_json::to_string(&MachineHalt).unwrap(); + for tx in self.agent_distributors.take().unwrap() { + tx.send(halt.clone()).unwrap(); + } + self.agent_processors.take().unwrap().await; } } } From d1a467c53d2fea177120cf90bc0bd84e705baa7b Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Fri, 19 Jan 2024 15:52:48 -0700 Subject: [PATCH 17/20] push up: test adjustment --- arbiter-engine/src/examples/timed_message.rs | 13 ++++++++----- arbiter-engine/src/examples/token_minter.rs | 10 +++++++--- arbiter-engine/src/machine.rs | 9 +++++++-- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/arbiter-engine/src/examples/timed_message.rs b/arbiter-engine/src/examples/timed_message.rs index 881d3e8f..90c69a96 100644 --- a/arbiter-engine/src/examples/timed_message.rs +++ b/arbiter-engine/src/examples/timed_message.rs @@ -2,6 +2,7 @@ const AGENT_ID: &str = "agent"; +use self::machine::MachineHalt; use super::*; use crate::{ agent::Agent, @@ -21,12 +22,9 @@ struct TimedMessage { #[async_trait::async_trait] impl Behavior for TimedMessage { - async fn process(&mut self, event: Message) { + async fn process(&mut self, event: Message) -> Option { trace!("Processing event."); - if self.count == self.max_count.unwrap_or(u64::MAX) {} - if event.data != self.receive_data { - return; - } else { + if event.data == self.receive_data { trace!("Event matches message. Sending a new message."); let message = Message { from: self.messager.id.clone().unwrap(), @@ -34,10 +32,15 @@ impl Behavior for TimedMessage { data: self.send_data.clone(), }; self.messager.send(message).await; + self.count += 1; + } + if self.count == self.max_count.unwrap_or(u64::MAX) { + return Some(MachineHalt); } tokio::time::sleep(std::time::Duration::from_secs(self.delay)).await; trace!("Processed event."); + None } async fn sync(&mut self) { diff --git a/arbiter-engine/src/examples/token_minter.rs b/arbiter-engine/src/examples/token_minter.rs index 35036fa2..f6fdb019 100644 --- a/arbiter-engine/src/examples/token_minter.rs +++ b/arbiter-engine/src/examples/token_minter.rs @@ -8,6 +8,7 @@ use ethers::{ }; use tracing::error; +use self::machine::MachineHalt; use super::*; use crate::{ agent::Agent, @@ -111,7 +112,7 @@ self.messager.id.as_deref()))] #[tracing::instrument(skip(self), fields(id = self.messager.id.as_deref()))] - async fn process(&mut self, event: Message) { + async fn process(&mut self, event: Message) -> Option { if self.tokens.is_none() { error!( "There were no tokens to deploy! You must add tokens to @@ -152,6 +153,7 @@ the token admin before running the simulation." .unwrap(); } } + None } } @@ -205,7 +207,7 @@ self.messager.id.as_deref()))] #[tracing::instrument(skip(self), fields(id = self.messager.id.as_deref()))] - async fn process(&mut self, event: Message) { + async fn process(&mut self, event: Message) -> Option { if let Ok(token_data) = serde_json::from_str::(&event.data) { trace!( "Got @@ -229,6 +231,7 @@ token: {:?}", }; self.messager.send(message).await; } + None } } @@ -236,7 +239,7 @@ token: {:?}", impl Behavior for TokenRequester { #[tracing::instrument(skip(self), fields(id = self.messager.id.as_deref()))] - async fn process(&mut self, event: arbiter_token::TransferFilter) { + async fn process(&mut self, event: arbiter_token::TransferFilter) -> Option { trace!( "Got event for `TokenRequester` logger: {:?}", @@ -254,6 +257,7 @@ self.messager.id.as_deref()))] .unwrap(), }; self.messager.send(message).await; + None } } diff --git a/arbiter-engine/src/machine.rs b/arbiter-engine/src/machine.rs index 50f9ec70..0a1e5c33 100644 --- a/arbiter-engine/src/machine.rs +++ b/arbiter-engine/src/machine.rs @@ -79,7 +79,7 @@ pub trait Behavior: Send + Sync + 'static { /// Used to process events. /// This is where the agent can engage in its specific processing /// of events that can lead to actions being taken. - async fn process(&mut self, event: E); + async fn process(&mut self, event: E) -> Option; } #[async_trait::async_trait] @@ -166,7 +166,12 @@ where println!("Event received: {:?}", event); let decoding_result = serde_json::from_str::(&event); match decoding_result { - Ok(event) => behavior.process(event).await, + Ok(event) => { + let halt_option = behavior.process(event).await; + if halt_option.is_some() { + break; + } + } Err(_) => match serde_json::from_str::(&event) { Ok(_) => { warn!("Behavior received `MachineHalt` message. Breaking!"); From 556e594e6166f7c1e39ae099726a2cabdae83e28 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Fri, 19 Jan 2024 17:16:24 -0700 Subject: [PATCH 18/20] calling it here --- .../src/tests/data_collection_integration.rs | 2 +- arbiter-engine/src/agent.rs | 9 +-- arbiter-engine/src/examples/timed_message.rs | 81 ++++++++++++++++--- arbiter-engine/src/examples/token_minter.rs | 81 ++++++++++++++++--- arbiter-engine/src/machine.rs | 5 +- arbiter-engine/src/world.rs | 22 +++-- 6 files changed, 161 insertions(+), 39 deletions(-) diff --git a/arbiter-core/src/tests/data_collection_integration.rs b/arbiter-core/src/tests/data_collection_integration.rs index 619a58c1..4bce2684 100644 --- a/arbiter-core/src/tests/data_collection_integration.rs +++ b/arbiter-core/src/tests/data_collection_integration.rs @@ -41,7 +41,7 @@ async fn generate_events( #[tokio::test] async fn data_capture() { - // + // let (env, client) = startup_user_controlled().unwrap(); let (arbx, arby, lex) = deploy_liquid_exchange(client.clone()).await.unwrap(); println!("Deployed contracts"); diff --git a/arbiter-engine/src/agent.rs b/arbiter-engine/src/agent.rs index b545f313..9ad86c7f 100644 --- a/arbiter-engine/src/agent.rs +++ b/arbiter-engine/src/agent.rs @@ -201,10 +201,7 @@ impl StateMachine for Agent { let sender = self.distributor.0.clone(); self.broadcast_task = Some(tokio::spawn(async move { while let Some(event) = event_stream.next().await { - println!("Broadcasting event through agent comms: {:?}", event); - sender.send(event).unwrap(); // TODO: If this errors - // out, we can exit the - // task + sender.send(event).unwrap(); } event_stream })); @@ -227,8 +224,8 @@ mod tests { #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn streaming() { - std::env::set_var("RUST_LOG", "trace"); - tracing_subscriber::fmt::init(); + // std::env::set_var("RUST_LOG", "trace"); + // tracing_subscriber::fmt::init(); let world = World::new("world"); let agent = Agent::new("agent", &world); diff --git a/arbiter-engine/src/examples/timed_message.rs b/arbiter-engine/src/examples/timed_message.rs index 90c69a96..74d95748 100644 --- a/arbiter-engine/src/examples/timed_message.rs +++ b/arbiter-engine/src/examples/timed_message.rs @@ -2,6 +2,10 @@ const AGENT_ID: &str = "agent"; +use std::time::Duration; + +use tokio::time::timeout; + use self::machine::MachineHalt; use super::*; use crate::{ @@ -35,6 +39,7 @@ impl Behavior for TimedMessage { self.count += 1; } if self.count == self.max_count.unwrap_or(u64::MAX) { + warn!("Reached max count. Halting behavior."); return Some(MachineHalt); } @@ -58,8 +63,8 @@ impl Behavior for TimedMessage { #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn echoer() { - std::env::set_var("RUST_LOG", "trace"); - tracing_subscriber::fmt::init(); + // std::env::set_var("RUST_LOG", "trace"); + // tracing_subscriber::fmt::init(); let mut world = World::new("world"); @@ -74,7 +79,7 @@ async fn echoer() { .unwrap() .join_with_id(Some(AGENT_ID.to_owned())), count: 0, - max_count: Some(5), + max_count: Some(2), }; world.add_agent(agent.with_behavior(behavior)); @@ -88,12 +93,30 @@ async fn echoer() { }; messager.send(message).await; task.await; + + let mut stream = Box::pin(messager.stream()); + let mut idx = 0; + + loop { + match timeout(Duration::from_secs(1), stream.next()).await { + Ok(Some(event)) => { + println!("Event received in outside world: {:?}", event); + idx += 1; + if idx == 2 { + break; + } + } + _ => { + panic!("Timeout reached. Test failed."); + } + } + } } #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn ping_pong() { - std::env::set_var("RUST_LOG", "trace"); - tracing_subscriber::fmt::init(); + // std::env::set_var("RUST_LOG", "trace"); + // tracing_subscriber::fmt::init(); let mut world = World::new("world"); @@ -108,7 +131,7 @@ async fn ping_pong() { .unwrap() .join_with_id(Some(AGENT_ID.to_owned())), count: 0, - max_count: Some(5), + max_count: Some(2), }; let behavior_pong = TimedMessage { delay: 1, @@ -120,7 +143,7 @@ async fn ping_pong() { .unwrap() .join_with_id(Some(AGENT_ID.to_owned())), count: 0, - max_count: Some(5), + max_count: Some(2), }; world.add_agent( @@ -140,12 +163,30 @@ async fn ping_pong() { messager.send(init_message).await; task.await; + + let mut stream = Box::pin(messager.stream()); + let mut idx = 0; + + loop { + match timeout(Duration::from_secs(1), stream.next()).await { + Ok(Some(event)) => { + println!("Event received in outside world: {:?}", event); + idx += 1; + if idx == 4 { + break; + } + } + _ => { + panic!("Timeout reached. Test failed."); + } + } + } } #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn ping_pong_two_agent() { - std::env::set_var("RUST_LOG", "trace"); - tracing_subscriber::fmt::init(); + // std::env::set_var("RUST_LOG", "trace"); + // tracing_subscriber::fmt::init(); let mut world = World::new("world"); @@ -160,7 +201,7 @@ async fn ping_pong_two_agent() { .unwrap() .join_with_id(Some("agent_ping".to_owned())), count: 0, - max_count: Some(5), + max_count: Some(2), }; let agent_pong = Agent::new("agent_pong", &world); @@ -174,7 +215,7 @@ async fn ping_pong_two_agent() { .unwrap() .join_with_id(Some("agent_pong".to_owned())), count: 0, - max_count: Some(5), + max_count: Some(2), }; world.add_agent(agent_ping.with_behavior(behavior_ping)); @@ -192,4 +233,22 @@ async fn ping_pong_two_agent() { messager.send(init_message).await; task.await; + + let mut stream = Box::pin(messager.stream()); + let mut idx = 0; + + loop { + match timeout(Duration::from_secs(1), stream.next()).await { + Ok(Some(event)) => { + println!("Event received in outside world: {:?}", event); + idx += 1; + if idx == 5 { + break; + } + } + _ => { + panic!("Timeout reached. Test failed."); + } + } + } } diff --git a/arbiter-engine/src/examples/token_minter.rs b/arbiter-engine/src/examples/token_minter.rs index f6fdb019..f75f7ef4 100644 --- a/arbiter-engine/src/examples/token_minter.rs +++ b/arbiter-engine/src/examples/token_minter.rs @@ -1,11 +1,13 @@ -use std::str::FromStr; +use std::{str::FromStr, time::Duration}; use anyhow::Context; use arbiter_bindings::bindings::arbiter_token; +use arbiter_core::data_collection::EventLogger; use ethers::{ abi::token, types::{transaction::request, Filter}, }; +use tokio::time::timeout; use tracing::error; use self::machine::MachineHalt; @@ -35,15 +37,26 @@ pub struct TokenAdmin { // explicitly, they should come from the Agent the behavior is given to. pub client: Arc, pub messager: Messager, + + count: u64, + + max_count: Option, } impl TokenAdmin { - pub fn new(client: Arc, messager: Messager) -> Self { + pub fn new( + client: Arc, + messager: Messager, + count: u64, + max_count: Option, + ) -> Self { Self { token_data: HashMap::new(), tokens: None, client, messager, + count, + max_count, } } @@ -151,6 +164,11 @@ the token admin before running the simulation." .unwrap() .await .unwrap(); + self.count += 1; + if self.count == self.max_count.unwrap_or(u64::MAX) { + warn!("Reached max count. Halting behavior."); + return Some(MachineHalt); + } } } None @@ -172,10 +190,19 @@ pub struct TokenRequester { /// The messaging layer for the token requester. pub messager: Messager, + + pub count: u64, + + pub max_count: Option, } impl TokenRequester { - pub fn new(client: Arc, messager: Messager) -> Self { + pub fn new( + client: Arc, + messager: Messager, + count: u64, + max_count: Option, + ) -> Self { Self { token_data: TokenData { name: TOKEN_NAME.to_owned(), @@ -186,6 +213,8 @@ impl TokenRequester { request_to: TOKEN_ADMIN_ID.to_owned(), client, messager, + count, + max_count, } } } @@ -231,7 +260,7 @@ token: {:?}", }; self.messager.send(message).await; } - None + Some(MachineHalt) } } @@ -257,6 +286,11 @@ self.messager.id.as_deref()))] .unwrap(), }; self.messager.send(message).await; + self.count += 1; + if self.count == self.max_count.unwrap_or(u64::MAX) { + warn!("Reached max count. Halting behavior."); + return Some(MachineHalt); + } None } } @@ -264,8 +298,8 @@ self.messager.id.as_deref()))] #[ignore] #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn token_minter_simulation() { - std::env::set_var("RUST_LOG", "trace"); - tracing_subscriber::fmt::init(); + // std::env::set_var("RUST_LOG", "trace"); + // tracing_subscriber::fmt::init(); let mut world = World::new("test_world"); @@ -278,6 +312,8 @@ async fn token_minter_simulation() { .as_ref() .unwrap() .join_with_id(Some(TOKEN_ADMIN_ID.to_owned())), + 0, + Some(4), ); token_admin_behavior.add_token(TokenData { name: TOKEN_NAME.to_owned(), @@ -296,12 +332,14 @@ async fn token_minter_simulation() { .as_ref() .unwrap() .join_with_id(Some(REQUESTER_ID.to_owned())), + 0, + Some(4), ); - let transfer_event = ArbiterToken::new( + let arb = ArbiterToken::new( Address::from_str("0x240a76d4c8a7dafc6286db5fa6b589e8b21fc00f").unwrap(), token_requester.client.clone(), - ) - .transfer_filter(); + ); + let transfer_event = arb.transfer_filter(); let token_requester_behavior_again = TokenRequester::new( token_requester.client.clone(), @@ -310,6 +348,8 @@ async fn token_minter_simulation() { .as_ref() .unwrap() .join_with_id(Some(REQUESTER_ID.to_owned())), + 0, + Some(4), ); world.add_agent( token_requester @@ -318,8 +358,27 @@ async fn token_minter_simulation() { .with_event(transfer_event), ); + let transfer_stream = EventLogger::builder() + .add_stream(arb.transfer_filter()) + .stream() + .unwrap(); + let mut stream = Box::pin(transfer_stream); + let mut idx = 0; + world.run().await; - std::thread::sleep(std::time::Duration::from_secs(1)); - world.stop().await; + loop { + match timeout(Duration::from_secs(1), stream.next()).await { + Ok(Some(event)) => { + println!("Event received in outside world: {:?}", event); + idx += 1; + if idx == 4 { + break; + } + } + _ => { + panic!("Timeout reached. Test failed."); + } + } + } } diff --git a/arbiter-engine/src/machine.rs b/arbiter-engine/src/machine.rs index 0a1e5c33..c16cd623 100644 --- a/arbiter-engine/src/machine.rs +++ b/arbiter-engine/src/machine.rs @@ -28,8 +28,10 @@ pub enum MachineInstruction { Stop, } +/// The message that can be used in a [`StateMachine`] to halt its processing. +/// Optionally returned by [`Behavior::process`] to close tasks. #[derive(Clone, Copy, Debug, Serialize, Deserialize)] -pub(crate) struct MachineHalt; +pub struct MachineHalt; /// The state used by any entity implementing [`StateMachine`]. #[derive(Clone, Copy, Debug)] @@ -163,7 +165,6 @@ where let mut receiver = self.event_receiver.take().unwrap(); let behavior_task = tokio::spawn(async move { while let Ok(event) = receiver.recv().await { - println!("Event received: {:?}", event); let decoding_result = serde_json::from_str::(&event); match decoding_result { Ok(event) => { diff --git a/arbiter-engine/src/world.rs b/arbiter-engine/src/world.rs index c993b9f5..427c514f 100644 --- a/arbiter-engine/src/world.rs +++ b/arbiter-engine/src/world.rs @@ -16,8 +16,8 @@ //! The world module contains the core world abstraction for the Arbiter Engine. use arbiter_core::environment::{builder::EnvironmentBuilder, Environment}; -use futures_util::future::{join_all, JoinAll}; -use tokio::{sync::broadcast::Sender as BroadcastSender, task::JoinHandle}; +use futures_util::future::join_all; +use tokio::sync::broadcast::Sender as BroadcastSender; use tracing::info; use self::machine::{MachineHalt, MachineInstruction}; @@ -64,8 +64,6 @@ pub struct World { /// The agents in the world. pub agents: Option>, - agent_processors: Option>>, - agent_distributors: Option>>, /// The environment for the world. @@ -82,7 +80,6 @@ impl World { id: id.to_owned(), state: State::Uninitialized, agents: Some(HashMap::new()), - agent_processors: None, agent_distributors: None, environment: EnvironmentBuilder::new().build(), messager: Messager::new(), @@ -175,21 +172,30 @@ impl StateMachine for World { self.state = State::Processing; let agents = self.agents.take().unwrap(); let mut agent_distributors = vec![]; - self.agent_processors = Some(join_all(agents.into_values().map(|mut agent| { + let agent_processors = join_all(agents.into_values().map(|mut agent| { agent_distributors.push(agent.distributor.0.clone()); tokio::spawn(async move { agent.execute(instruction).await; agent }) - }))); + })); self.agent_distributors = Some(agent_distributors); + self.agents = Some( + agent_processors + .await + .into_iter() + .map(|res| { + let agent = res.unwrap(); + (agent.id.clone(), agent) + }) + .collect::>(), + ); } MachineInstruction::Stop => { let halt = serde_json::to_string(&MachineHalt).unwrap(); for tx in self.agent_distributors.take().unwrap() { tx.send(halt.clone()).unwrap(); } - self.agent_processors.take().unwrap().await; } } } From d9d9647c3b4469f96bad6706123cedf757572183 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Sat, 20 Jan 2024 05:58:13 -0700 Subject: [PATCH 19/20] pin revm versions --- Cargo.lock | 638 ++++++++++++++++++++++++++--------------------------- Cargo.toml | 4 +- 2 files changed, 312 insertions(+), 330 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cc0ec144..ffca2403 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -51,9 +51,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" dependencies = [ "cfg-if", "getrandom", @@ -111,9 +111,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c0e5e60ff0e0c34c553822dabcfe0f5fece5a8c52f08a915be8c737de4b03fa" +checksum = "9c234f92024707f224510ff82419b2be0e1d8e1fd911defcac5a085cd7f83898" dependencies = [ "alloy-rlp", "bytes", @@ -122,6 +122,7 @@ dependencies = [ "derive_more", "hex-literal", "itoa", + "keccak-asm", "proptest", "rand", "ruint", @@ -131,21 +132,20 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc0fac0fc16baf1f63f78b47c3d24718f3619b0714076f6a02957d808d52cbef" +checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" dependencies = [ "alloy-rlp-derive", "arrayvec", "bytes", - "smol_str", ] [[package]] name = "alloy-rlp-derive" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0391754c09fab4eae3404d19d0d297aa1c670c1775ab51d8a5312afeca23157" +checksum = "1a047897373be4bbb0224c1afdabca92648dc57a9c9ef6e7b0be3aff7a859c83" dependencies = [ "proc-macro2", "quote", @@ -169,9 +169,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.4" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" dependencies = [ "anstyle", "anstyle-parse", @@ -189,30 +189,30 @@ checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -245,7 +245,7 @@ dependencies = [ "quote", "rayon", "revm", - "revm-primitives 1.3.0 (git+https://github.com/bluealloy/revm.git)", + "revm-primitives 1.3.0 (git+https://github.com/bluealloy/revm.git?rev=30bbcdfe81446c9d1e9b37acc95f208943ddf858)", "serde", "serde_json", "syn 2.0.43", @@ -288,7 +288,7 @@ dependencies = [ "rand", "rand_distr", "revm", - "revm-primitives 1.3.0 (git+https://github.com/bluealloy/revm.git)", + "revm-primitives 1.3.0 (git+https://github.com/bluealloy/revm.git?rev=30bbcdfe81446c9d1e9b37acc95f208943ddf858)", "serde", "serde_json", "statrs", @@ -641,9 +641,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64ct" @@ -663,7 +663,7 @@ version = "0.66.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2b84e06fc203107bfbad243f4aba2af864eb7db3b1cf46ea0a023b0b433d2a7" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "cexpr", "clang-sys", "lazy_static", @@ -703,9 +703,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" dependencies = [ "serde", ] @@ -777,9 +777,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c" +checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" dependencies = [ "memchr", "regex-automata 0.4.3", @@ -886,9 +886,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12024c4645c97566567129c204f65d5815a8c9aecf30fcbe682b2fe034996d36" +checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d" dependencies = [ "serde", ] @@ -909,10 +909,11 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.84" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f8e7c90afad890484a21653d08b6e209ae34770fb5ee298f9c699fcc1e5c856" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ + "jobserver", "libc", ] @@ -957,9 +958,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" dependencies = [ "glob", "libc", @@ -1044,7 +1045,7 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5286a0843c21f8367f7be734f89df9b822e0321d8bcce8d6e735aadff7d74979" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "bech32", "bs58", "digest 0.10.7", @@ -1110,9 +1111,9 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "constant_time_eq" @@ -1128,9 +1129,9 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -1138,15 +1139,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -1171,46 +1172,37 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.8" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.18" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crossterm" @@ -1218,7 +1210,7 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "crossterm_winapi", "libc", "parking_lot", @@ -1242,9 +1234,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28f85c3514d2a6e64160359b45a3918c3b4178bcbf4ae5d03ab2d02e521c479a" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", "rand_core", @@ -1273,9 +1265,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "der" @@ -1289,9 +1281,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", ] @@ -1421,9 +1413,9 @@ checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" [[package]] name = "ecdsa" -version = "0.16.8" +version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", "digest 0.10.7", @@ -1482,7 +1474,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe81b5c06ecfdbc71dd845216f225f53b62a10cb8a16c946836a3467f701d05b" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "bytes", "hex", "k256", @@ -1519,9 +1511,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" dependencies = [ "log", ] @@ -1630,9 +1622,9 @@ dependencies = [ [[package]] name = "ethers-addressbook" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c405f24ea3a517899ba7985385c43dc4a7eb1209af3b1e0a1a32d7dcc7f8d09" +checksum = "9bf35eb7d2e2092ad41f584951e08ec7c077b142dba29c4f1b8f52d2efddc49c" dependencies = [ "ethers-core", "once_cell", @@ -1661,9 +1653,9 @@ dependencies = [ [[package]] name = "ethers-contract-abigen" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51258120c6b47ea9d9bec0d90f9e8af71c977fbefbef8213c91bfed385fe45eb" +checksum = "bbdfb952aafd385b31d316ed80d7b76215ce09743c172966d840e96924427e0c" dependencies = [ "Inflector", "const-hex", @@ -1685,9 +1677,9 @@ dependencies = [ [[package]] name = "ethers-contract-derive" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936e7a0f1197cee2b62dc89f63eff3201dbf87c283ff7e18d86d38f83b845483" +checksum = "7465c814a2ecd0de0442160da13584205d1cdc08f4717a6511cad455bd5d7dc4" dependencies = [ "Inflector", "const-hex", @@ -1701,9 +1693,9 @@ dependencies = [ [[package]] name = "ethers-core" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f03e0bdc216eeb9e355b90cf610ef6c5bb8aca631f97b5ae9980ce34ea7878d" +checksum = "918b1a9ba585ea61022647def2f27c29ba19f6d2a4a4c8f68a9ae97fd5769737" dependencies = [ "arrayvec", "bytes", @@ -1731,9 +1723,9 @@ dependencies = [ [[package]] name = "ethers-etherscan" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abbac2c890bdbe0f1b8e549a53b00e2c4c1de86bb077c1094d1f38cdf9381a56" +checksum = "facabf8551b4d1a3c08cb935e7fca187804b6c2525cc0dafb8e5a6dd453a24de" dependencies = [ "chrono", "ethers-core", @@ -1780,7 +1772,7 @@ checksum = "25d6c0c9455d93d4990c06e049abf9b30daf148cf461ee939c11d88907c60816" dependencies = [ "async-trait", "auto_impl", - "base64 0.21.5", + "base64 0.21.7", "bytes", "const-hex", "enr", @@ -1831,9 +1823,9 @@ dependencies = [ [[package]] name = "ethers-solc" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64f710586d147864cff66540a6d64518b9ff37d73ef827fee430538265b595f" +checksum = "cc2e46e3ec8ef0c986145901fa9864205dc4dcee701f9846be2d56112d34bdea" dependencies = [ "cfg-if", "const-hex", @@ -1872,9 +1864,9 @@ checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" [[package]] name = "eyre" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +checksum = "b6267a1fa6f59179ea4afc8e50fd8612a3cc60bc858f786ff877a4a8cb042799" dependencies = [ "indenter", "once_cell", @@ -1921,9 +1913,9 @@ dependencies = [ [[package]] name = "figment" -version = "0.10.12" +version = "0.10.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "649f3e5d826594057e9a519626304d8da859ea8a0b18ce99500c586b8d45faee" +checksum = "2b6e5bc7bd59d60d0d45a6ccab6cf0f4ce28698fb4e81e750ddf229c9b824026" dependencies = [ "atomic", "pear", @@ -1984,9 +1976,9 @@ checksum = "ee1b05cbd864bcaecbd3455d6d967862d446e4ebfc3c2e5e5b9841e53cba6673" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -2171,9 +2163,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "js-sys", @@ -2184,9 +2176,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "glob" @@ -2196,15 +2188,15 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" +checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" dependencies = [ "aho-corasick", "bstr", - "fnv", "log", - "regex", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", ] [[package]] @@ -2232,9 +2224,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" dependencies = [ "bytes", "fnv", @@ -2242,7 +2234,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.3", + "indexmap", "slab", "tokio", "tokio-util", @@ -2274,7 +2266,7 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash 0.8.6", + "ahash 0.8.7", ] [[package]] @@ -2283,7 +2275,7 @@ version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ - "ahash 0.8.6", + "ahash 0.8.7", "allocator-api2", "rayon", "serde", @@ -2306,9 +2298,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" [[package]] name = "hex" @@ -2336,11 +2328,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2356,9 +2348,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -2379,9 +2371,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", @@ -2394,7 +2386,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2", "tokio", "tower-service", "tracing", @@ -2417,16 +2409,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core 0.51.1", + "windows-core", ] [[package]] @@ -2440,9 +2432,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -2492,16 +2484,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - [[package]] name = "indexmap" version = "2.1.0" @@ -2544,13 +2526,13 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" dependencies = [ "hermit-abi", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2573,15 +2555,24 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "jobserver" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +dependencies = [ + "libc", +] [[package]] name = "js-sys" -version = "0.3.65" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" dependencies = [ "wasm-bindgen", ] @@ -2603,7 +2594,7 @@ version = "8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "pem", "ring 0.16.20", "serde", @@ -2613,9 +2604,9 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f01b677d82ef7a676aa37e099defd83a28e15687112cafdd112d60236b6115b" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" dependencies = [ "cfg-if", "ecdsa", @@ -2627,13 +2618,23 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ "cpufeatures", ] +[[package]] +name = "keccak-asm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb8515fff80ed850aea4a1595f2e519c003e2a00a82fe168ebf5269196caf444" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + [[package]] name = "lalrpop" version = "0.20.0" @@ -2743,18 +2744,18 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.150" +version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -2769,7 +2770,7 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "libc", "redox_syscall", ] @@ -2782,9 +2783,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.4.11" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" @@ -2853,9 +2854,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memmap2" @@ -2866,15 +2867,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] - [[package]] name = "mime" version = "0.3.17" @@ -2898,9 +2890,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "wasi", @@ -3091,20 +3083,20 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ - "proc-macro-crate 2.0.0", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 2.0.43", @@ -3118,9 +3110,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -3180,9 +3172,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "parity-scale-codec" -version = "3.6.5" +version = "3.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dec8a8073036902368c2cdc0387e85ff9a37054d7e7c98e592145e0c92cd4fb" +checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" dependencies = [ "arrayvec", "bitvec", @@ -3194,11 +3186,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.5" +version = "3.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312270ee71e1cd70289dacf597cab7b207aa107d2f28191c2ae45b2ece18a260" +checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 2.0.0", "proc-macro2", "quote", "syn 1.0.109", @@ -3290,9 +3282,9 @@ dependencies = [ [[package]] name = "pear" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a386cd715229d399604b50d1361683fe687066f42d56f54be995bc6868f71c" +checksum = "4ccca0f6c17acc81df8e242ed473ec144cbf5c98037e69aa6d144780aad103c8" dependencies = [ "inlinable_string", "pear_codegen", @@ -3301,9 +3293,9 @@ dependencies = [ [[package]] name = "pear_codegen" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f0f13dac8069c139e8300a6510e3f4143ecf5259c60b116a9b271b4ca0d54" +checksum = "2e22670e8eb757cff11d6c199ca7b987f352f0346e0be4dd23869ec72cb53c77" dependencies = [ "proc-macro2", "proc-macro2-diagnostics", @@ -3328,15 +3320,15 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" +checksum = "1f200d8d83c44a45b21764d1916299752ca035d15ecd46faca3e9a2a2bf6ad06" dependencies = [ "memchr", "thiserror", @@ -3345,9 +3337,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2" +checksum = "bcd6ab1236bbdb3a49027e920e693192ebfe8913f6d60e294de57463a493cfde" dependencies = [ "pest", "pest_generator", @@ -3355,9 +3347,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227" +checksum = "2a31940305ffc96863a735bef7c7994a00b325a7138fdbc5bda0f1a0476d3275" dependencies = [ "pest", "pest_meta", @@ -3368,9 +3360,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6" +checksum = "a7ff62f5259e53b78d1af898941cdcdccfae7385cf7d793a6e55de5d05bb4b7d" dependencies = [ "once_cell", "pest", @@ -3384,7 +3376,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 2.1.0", + "indexmap", ] [[package]] @@ -3492,9 +3484,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" [[package]] name = "planus" @@ -3527,7 +3519,7 @@ version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce68a02f698ff7787c261aea1b4c040a8fe183a8fb200e2436d7f35d95a1b86f" dependencies = [ - "ahash 0.8.6", + "ahash 0.8.7", "arrow-format", "atoi_simd", "bytemuck", @@ -3573,14 +3565,14 @@ version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0f5efe734b6cbe5f97ea769be8360df5324fade396f1f3f5ad7fe9360ca4a23" dependencies = [ - "ahash 0.8.6", - "bitflags 2.4.1", + "ahash 0.8.7", + "bitflags 2.4.2", "bytemuck", "chrono", "comfy-table", "either", "hashbrown 0.14.3", - "indexmap 2.1.0", + "indexmap", "num-traits", "once_cell", "polars-arrow", @@ -3616,7 +3608,7 @@ version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d0458efe8946f4718fd352f230c0db5a37926bd0d2bd25af79dc24746abaaea" dependencies = [ - "ahash 0.8.6", + "ahash 0.8.7", "async-trait", "atoi_simd", "bytes", @@ -3654,11 +3646,11 @@ version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea47d46b7a98fa683ef235ad48b783abf61734828e754096cfbdc77404fff9b3" dependencies = [ - "ahash 0.8.6", + "ahash 0.8.7", "chrono", "fallible-streaming-iterator", "hashbrown 0.14.3", - "indexmap 2.1.0", + "indexmap", "itoa", "num-traits", "polars-arrow", @@ -3675,8 +3667,8 @@ version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d7105b40905bb38e8fc4a7fd736594b7491baa12fad3ac492969ca221a1b5d5" dependencies = [ - "ahash 0.8.6", - "bitflags 2.4.1", + "ahash 0.8.7", + "bitflags 2.4.2", "glob", "once_cell", "polars-arrow", @@ -3699,12 +3691,12 @@ version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e09afc456ab11e75e5dcb43e00a01c71f3a46a2781e450054acb6bb096ca78e" dependencies = [ - "ahash 0.8.6", + "ahash 0.8.7", "argminmax", "bytemuck", "either", "hashbrown 0.14.3", - "indexmap 2.1.0", + "indexmap", "memchr", "num-traits", "polars-arrow", @@ -3724,9 +3716,9 @@ version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ba24d67b1f64ab85143033dd46fa090b13c0f74acdf91b0780c16aecf005e3d" dependencies = [ - "ahash 0.8.6", + "ahash 0.8.7", "async-stream", - "base64 0.21.5", + "base64 0.21.7", "brotli", "ethnum", "flate2", @@ -3774,7 +3766,7 @@ version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384a175624d050c31c473ee11df9d7af5d729ae626375e522158cfb3d150acd0" dependencies = [ - "ahash 0.8.6", + "ahash 0.8.7", "bytemuck", "once_cell", "percent-encoding", @@ -3846,10 +3838,10 @@ version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b174ca4a77ad47d7b91a0460aaae65bbf874c8bfbaaa5308675dadef3976bbda" dependencies = [ - "ahash 0.8.6", + "ahash 0.8.7", "bytemuck", "hashbrown 0.14.3", - "indexmap 2.1.0", + "indexmap", "num-traits", "once_cell", "polars-error", @@ -3879,13 +3871,12 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "predicates" -version = "3.0.4" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dfc28575c2e3f19cb3c73b93af36460ae898d426eba6fc15b9bd2a5220758a0" +checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8" dependencies = [ "anstyle", "difflib", - "itertools 0.11.0", "predicates-core", ] @@ -3948,6 +3939,15 @@ dependencies = [ "toml_edit 0.20.7", ] +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit 0.21.0", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -4002,7 +4002,7 @@ checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.4.1", + "bitflags 2.4.2", "lazy_static", "num-traits", "rand", @@ -4092,9 +4092,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] name = "rayon" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" dependencies = [ "either", "rayon-core", @@ -4102,9 +4102,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -4132,18 +4132,18 @@ dependencies = [ [[package]] name = "ref-cast" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acde58d073e9c79da00f2b5b84eed919c8326832648a5b109b3fce1bb1175280" +checksum = "53313ec9f12686aeeffb43462c3ac77aa25f590a5f630eb2cde0de59417b29c7" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7473c2cfcf90008193dd0e3e16599455cb601a9fce322b5bb55de799664925" +checksum = "2566c4bf6845f2c2e83b27043c3f5dfcd5ba8f2937d6c00dc009bfb51a079dc4" dependencies = [ "proc-macro2", "quote", @@ -4202,11 +4202,11 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.22" +version = "0.11.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", @@ -4243,7 +4243,7 @@ dependencies = [ [[package]] name = "revm" version = "3.5.0" -source = "git+https://github.com/bluealloy/revm.git#30bbcdfe81446c9d1e9b37acc95f208943ddf858" +source = "git+https://github.com/bluealloy/revm.git?rev=30bbcdfe81446c9d1e9b37acc95f208943ddf858#30bbcdfe81446c9d1e9b37acc95f208943ddf858" dependencies = [ "auto_impl", "ethers-core", @@ -4259,22 +4259,22 @@ dependencies = [ [[package]] name = "revm-interpreter" version = "1.3.0" -source = "git+https://github.com/bluealloy/revm.git#30bbcdfe81446c9d1e9b37acc95f208943ddf858" +source = "git+https://github.com/bluealloy/revm.git?rev=30bbcdfe81446c9d1e9b37acc95f208943ddf858#30bbcdfe81446c9d1e9b37acc95f208943ddf858" dependencies = [ - "revm-primitives 1.3.0 (git+https://github.com/bluealloy/revm.git)", + "revm-primitives 1.3.0 (git+https://github.com/bluealloy/revm.git?rev=30bbcdfe81446c9d1e9b37acc95f208943ddf858)", "serde", ] [[package]] name = "revm-precompile" version = "2.2.0" -source = "git+https://github.com/bluealloy/revm.git#30bbcdfe81446c9d1e9b37acc95f208943ddf858" +source = "git+https://github.com/bluealloy/revm.git?rev=30bbcdfe81446c9d1e9b37acc95f208943ddf858#30bbcdfe81446c9d1e9b37acc95f208943ddf858" dependencies = [ "aurora-engine-modexp", "c-kzg", "k256", "once_cell", - "revm-primitives 1.3.0 (git+https://github.com/bluealloy/revm.git)", + "revm-primitives 1.3.0 (git+https://github.com/bluealloy/revm.git?rev=30bbcdfe81446c9d1e9b37acc95f208943ddf858)", "ripemd", "secp256k1", "sha2", @@ -4290,7 +4290,7 @@ dependencies = [ "alloy-primitives 0.4.2", "alloy-rlp", "auto_impl", - "bitflags 2.4.1", + "bitflags 2.4.2", "bitvec", "enumn", "hashbrown 0.14.3", @@ -4300,12 +4300,12 @@ dependencies = [ [[package]] name = "revm-primitives" version = "1.3.0" -source = "git+https://github.com/bluealloy/revm.git#30bbcdfe81446c9d1e9b37acc95f208943ddf858" +source = "git+https://github.com/bluealloy/revm.git?rev=30bbcdfe81446c9d1e9b37acc95f208943ddf858#30bbcdfe81446c9d1e9b37acc95f208943ddf858" dependencies = [ - "alloy-primitives 0.5.3", + "alloy-primitives 0.5.4", "alloy-rlp", "auto_impl", - "bitflags 2.4.1", + "bitflags 2.4.2", "bitvec", "c-kzg", "derive_more", @@ -4343,9 +4343,9 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.5" +version = "0.17.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" +checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" dependencies = [ "cc", "getrandom", @@ -4475,11 +4475,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "errno", "libc", "linux-raw-sys", @@ -4488,12 +4488,12 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.8" +version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "446e14c5cda4f3f30fe71863c34ec70f5ac79d6087097ad0bb433e1be5edf04c" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", - "ring 0.17.5", + "ring 0.17.7", "rustls-webpki", "sct", ] @@ -4504,7 +4504,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", ] [[package]] @@ -4513,7 +4513,7 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.5", + "ring 0.17.7", "untrusted 0.9.0", ] @@ -4537,9 +4537,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "safe_arch" @@ -4616,7 +4616,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.5", + "ring 0.17.7", "untrusted 0.9.0", ] @@ -4723,7 +4723,7 @@ version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ - "indexmap 2.1.0", + "indexmap", "itoa", "ryu", "serde", @@ -4741,9 +4741,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" dependencies = [ "serde", ] @@ -4792,6 +4792,16 @@ dependencies = [ "keccak", ] +[[package]] +name = "sha3-asm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bac61da6b35ad76b195eb4771210f947734321a8d81d7738e1580d953bc7a15e" +dependencies = [ + "cc", + "cfg-if", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -4818,9 +4828,9 @@ dependencies = [ [[package]] name = "signature" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", "rand_core", @@ -4841,11 +4851,11 @@ dependencies = [ [[package]] name = "simd-json" -version = "0.13.4" +version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a3720326b20bf5b95b72dbbd133caae7e0dcf71eae8f6e6656e71a7e5c9aaa" +checksum = "2faf8f101b9bc484337a6a6b0409cf76c139f2fb70a9e3aee6b6774be7bfbf76" dependencies = [ - "ahash 0.8.6", + "ahash 0.8.7", "getrandom", "halfbrown", "lexical-core", @@ -4892,9 +4902,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "smartstring" @@ -4907,30 +4917,11 @@ dependencies = [ "version_check", ] -[[package]] -name = "smol_str" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" -dependencies = [ - "serde", -] - [[package]] name = "snap" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831" - -[[package]] -name = "socket2" -version = "0.4.10" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] +checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" [[package]] name = "socket2" @@ -4970,9 +4961,9 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spki" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", "der", @@ -5144,9 +5135,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.30.4" +version = "0.30.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "717570a2533606f81f8cfac02a1915a620e725ffb78f6fc5e259769a4d747407" +checksum = "1fb4f3438c8f6389c864e61221cbc97e9bca98b4daf39a5beb7bea660f528bb2" dependencies = [ "cfg-if", "core-foundation-sys", @@ -5281,9 +5272,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" dependencies = [ "deranged", "itoa", @@ -5301,9 +5292,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" dependencies = [ "time-core", ] @@ -5346,7 +5337,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.5", + "socket2", "tokio-macros", "windows-sys 0.48.0", ] @@ -5427,7 +5418,7 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" dependencies = [ - "indexmap 2.1.0", + "indexmap", "serde", "serde_spanned", "toml_datetime", @@ -5461,7 +5452,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.1.0", + "indexmap", "serde", "serde_spanned", "toml_datetime", @@ -5474,7 +5465,7 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap 2.1.0", + "indexmap", "toml_datetime", "winnow", ] @@ -5485,7 +5476,7 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ - "indexmap 2.1.0", + "indexmap", "serde", "serde_spanned", "toml_datetime", @@ -5594,9 +5585,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tungstenite" @@ -5659,9 +5650,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -5704,9 +5695,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -5795,9 +5786,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.88" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -5805,9 +5796,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.88" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" dependencies = [ "bumpalo", "log", @@ -5820,9 +5811,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.38" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02" +checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" dependencies = [ "cfg-if", "js-sys", @@ -5832,9 +5823,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.88" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5842,9 +5833,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.88" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", @@ -5855,15 +5846,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.88" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" [[package]] name = "web-sys" -version = "0.3.65" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" +checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" dependencies = [ "js-sys", "wasm-bindgen", @@ -5871,9 +5862,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.2" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" +checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" [[package]] name = "which" @@ -5934,19 +5925,10 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ - "windows-core 0.52.0", + "windows-core", "windows-targets 0.52.0", ] -[[package]] -name = "windows-core" -version = "0.51.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-core" version = "0.52.0" @@ -6090,9 +6072,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.19" +version = "0.5.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" +checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16" dependencies = [ "memchr", ] @@ -6137,9 +6119,9 @@ dependencies = [ [[package]] name = "xxhash-rust" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9828b178da53440fa9c766a3d2f73f7cf5d0ac1fe3980c1e5018d899fd19e07b" +checksum = "53be06678ed9e83edb1745eb72efc0bbcd7b5c3c35711a860906aed827a13d61" [[package]] name = "yaml-rust" @@ -6164,18 +6146,18 @@ checksum = "1367295b8f788d371ce2dbc842c7b709c73ee1364d30351dd300ec2203b12377" [[package]] name = "zerocopy" -version = "0.7.25" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd369a67c0edfef15010f980c3cbe45d7f651deac2cd67ce097cd801de16557" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.25" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f140bda219a26ccc0cdb03dba58af72590c53b22642577d88a927bc5c87d6b" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 8dab0438..7c540f48 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,8 +26,8 @@ arbiter-core = { version = "*", path = "./arbiter-core" } ethers = { version = "2.0.11" } serde = { version = "1.0.193", features = ["derive"] } serde_json = { version = "=1.0.108" } -revm = { git = "https://github.com/bluealloy/revm.git", features = [ "ethersdb", "std", "serde"] } -revm-primitives = { git = "https://github.com/bluealloy/revm.git" } +revm = { git = "https://github.com/bluealloy/revm.git", features = [ "ethersdb", "std", "serde"], rev = "30bbcdfe81446c9d1e9b37acc95f208943ddf858" } +revm-primitives = { git = "https://github.com/bluealloy/revm.git", rev = "30bbcdfe81446c9d1e9b37acc95f208943ddf858" } thiserror = { version = "1.0.55" } syn = { version = "2.0.43" } quote = { version = "=1.0.33" } From a6744b86de662b7cf922d1ec75b77519d6960275 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Mon, 22 Jan 2024 12:18:14 -0700 Subject: [PATCH 20/20] fix error --- arbiter-engine/src/world.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arbiter-engine/src/world.rs b/arbiter-engine/src/world.rs index 8717c4cf..13b65d3a 100644 --- a/arbiter-engine/src/world.rs +++ b/arbiter-engine/src/world.rs @@ -91,7 +91,8 @@ impl World { Self { id: id.to_owned(), agents: Some(HashMap::new()), - agent_tasks: None, + state: State::Uninitialized, + agent_distributors: None, environment, messager: Messager::new(), }