Skip to content

Commit

Permalink
new agent abstractions
Browse files Browse the repository at this point in the history
  • Loading branch information
0xJepsen committed Nov 5, 2023
1 parent a5a969b commit d0fe416
Show file tree
Hide file tree
Showing 12 changed files with 966 additions and 58 deletions.
262 changes: 258 additions & 4 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@ foundry-contracts = { path = "src/bindings" }
alloy-primitives = "0.4.2"
alloy-sol-types = "0.4.2"
durin-primitives = { git = "https://github.com/0xJepsen/durin.git" }
durin-fault = { git = "https://github.com/0xJepsen/durin.git", branch = "visibility" }
durin-fault = { git = "https://github.com/0xJepsen/durin.git", branch = "visibility" }
serde = { version = "1.0.130", features = ["derive"] }
config = "0.13.3"
clap = { version = "4.4.6", features = ["derive"] }
70 changes: 70 additions & 0 deletions src/agents/block_admin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use crate::settings::{SimulationConfig, parameters::Fixed};

use super::*;

/// A structure representing a block admin agent.
/// This agent is responsible for updating the block number and timestamp.
#[derive(Clone)]
pub struct BlockAdmin {
/// A client to interface with arbiter's revm middleware.
/// You can think of this as the agents wallet or EOA.
pub client: Arc<RevmMiddleware>,

/// The size of each timestep in the simulation, representing block time passage.
pub timestep_size: u64,

/// The current simulated block timestamp.
pub block_timestamp: u64,

/// The current simulated block number.
pub block_number: u64,
}

impl BlockAdmin {
/// Creates a new BlockAdmin using the provided environment and simulation configuration.
///
/// # Arguments
/// * [`Environment`] - The environment containing blockchain node information.
/// * [`SimulationConfig<Fixed>`] - The simulation configuration providing block timestep size.
///
/// # Returns
/// * [`Result<Self>`] - A result containing the new BlockAdmin or an error.
pub async fn new(environment: &Environment, config: &SimulationConfig<Fixed>) -> Result<Self> {
let client = RevmMiddleware::new(environment, "block_admin".into())?;
let timestep_size = config.block.timestep_size;
let block_number = client.get_block_number().await?.as_u64();
let block_timestamp = client.get_block_timestamp().await?.as_u64();

Ok(Self {
client,
timestep_size,
block_timestamp,
block_number,
})
}
/// Updates the simulated block information.
///
/// Increments the block number and calculates the new block timestamp based on the timestep size.
///
/// # Returns
/// * [`Result<()>`] - A result indicating the success or failure of the operation.
pub fn update_block(&mut self) -> Result<()> {
self.block_number += 1;
self.block_timestamp = self.block_number * self.timestep_size;
self.client
.update_block(self.block_number, self.block_timestamp)?;
Ok(())
}
}

#[async_trait::async_trait]
impl Agent for BlockAdmin {
async fn step(&mut self) -> Result<()> {
self.update_block()?;
Ok(())
}
async fn startup(&mut self) -> Result<()> {
self.update_block()?;
Ok(())
}
}
30 changes: 30 additions & 0 deletions src/agents/dishonest_actor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use super::*;

pub struct DishonestPlayer {
pub address: Address,
pub client: RevmMiddleware,
pub vm: AlphabetVM<RevmMiddleware>,
pub oracle: L2OutputOracle<RevmMiddleware>,
pub block_oracle: BlockOracle<RevmMiddleware>,
pub disputegame: FaultDisputeGame<RevmMiddleware>,
}

impl DishonestPlayer {
pub fn new() -> Self {
todo!()
}

pub fn generate_dishonest_dispute() {
todo!()
}

pub fn start_game_with_dishonest_dispute() {
todo!()
}

pub fn step() {
// randomly chose a move to make: attack, defend, or step
// randomly select a value in some range to has as move's claim
todo!()
}
}
41 changes: 1 addition & 40 deletions src/actors.rs → src/agents/honest_actor.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,4 @@
use std::sync::Arc;

use alloy_primitives::Address;
use durin_fault::{
providers::AlphabetTraceProvider, AlphaClaimSolver, FaultDisputeSolver, FaultDisputeState,
};

use arbiter_core::middleware::RevmMiddleware;
use foundry_contracts::{
alphabet_vm::AlphabetVM, block_oracle::BlockOracle, fault_dispute_game::FaultDisputeGame,
l2_output_oracle::L2OutputOracle,
};
use super::*;

/// actors can call
/// Move (alias for step) is a bisection step, pass in challenge index
Expand Down Expand Up @@ -62,31 +51,3 @@ impl HonestPlayer {
}
}

pub struct DishonestPlayer {
pub address: Address,
pub client: RevmMiddleware,
pub vm: AlphabetVM<RevmMiddleware>,
pub oracle: L2OutputOracle<RevmMiddleware>,
pub block_oracle: BlockOracle<RevmMiddleware>,
pub disputegame: FaultDisputeGame<RevmMiddleware>,
}

impl DishonestPlayer {
pub fn new() -> Self {
todo!()
}

pub fn generate_dishonest_dispute() {
todo!()
}

pub fn start_game_with_dishonest_dispute() {
todo!()
}

pub fn step() {
// randomly chose a move to make: attack, defend, or step
// randomly select a value in some range to has as move's claim
todo!()
}
}
86 changes: 86 additions & 0 deletions src/agents/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use super::*;

use crate::settings::{SimulationConfig, parameters::Fixed};
pub mod block_admin;
use std::sync::Arc;
use arbiter_core::environment::Environment;
use arbiter_core::middleware::RevmMiddleware;
use ethers::providers::Middleware;
// use settings::SimulationConfig;
use std::marker::{Send, Sync};
use alloy_primitives::Address;
use durin_fault::{
providers::AlphabetTraceProvider, AlphaClaimSolver, FaultDisputeSolver, FaultDisputeState,
};
use foundry_contracts::{
alphabet_vm::AlphabetVM, block_oracle::BlockOracle, fault_dispute_game::FaultDisputeGame,
l2_output_oracle::L2OutputOracle,
};

// use crate::settings::parameters::Fixed;

/// Universal agent methods for interacting with the simulation environment or
/// loop.
/// Agents are expected to be both [`Send`] and [`Sync`].
#[async_trait::async_trait]
pub trait Agent: Sync + Send {
/// Executed outside the main simulation loop.
async fn startup(&mut self) -> Result<()> {
Ok(())
}

/// Executed by each agent inside the main simulation loop.
/// Ordering is determined by placement in the simulation loop.
async fn step(&mut self) -> Result<()> {
Ok(())
}

/// Executed by each agent in a separate loop before the main loop.
async fn priority_step(&mut self) -> Result<()> {
Ok(())
}
}
/// A collection of agents that can be operated on collectively.
pub struct Agents(pub Vec<Box<dyn Agent>>);

impl Agents {
/// Returns a mutable iterator over the agents.
/// This can be used to invoke methods on each agent individually.
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Box<dyn Agent>> {
self.0.iter_mut()
}
}

impl Agents {
/// Constructs a new [`Agents`] collection.
/// This static method provides a way to create a new collection of agents.
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
Self(vec![])
}

/// Adds a new agent to the collection.
/// This method takes ownership of the agent and adds it to the collection.
#[allow(clippy::should_implement_trait)]
pub fn add(mut self, agent: impl Agent + 'static) -> Self {
self.0.push(Box::new(agent));
self
}
}

/// [`Agent`] trait implementation for a collection of agents.
/// This allows collective operations on the group of agents.
#[async_trait::async_trait]
impl Agent for Agents {
/// Implementation of the `step` method for the collection.
/// This allows the collection to forward the step action to each agent.
async fn step(&mut self) -> Result<()> {
Ok(())
}

/// Implementation of the `priority_step` method for the collection.
/// This allows the collection to forward the priority step action to each agent.
async fn priority_step(&mut self) -> Result<()> {
Ok(())
}
}
3 changes: 3 additions & 0 deletions src/config/dispute_game.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
simulation = "dispute_game"
output_directory = "analysis/dispute_game"

89 changes: 77 additions & 12 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ use foundry_contracts::{
fault_dispute_game::fault_dispute_game::FaultDisputeGame,
l2_output_oracle::l2_output_oracle::L2OutputOracle,
};

use std::time::Instant;
use clap::{ArgAction, CommandFactory, Parser, Subcommand};

pub mod agents;
pub mod settings;
pub mod simulations;
use std::{error::Error, sync::Arc};
mod actors;
mod startup;

const ENV_LABEL: &str = "OPTIMISM_FRAUD_PROOF";
const SUBMISSION_INTERVAL: f64 = 1800.0; // output every 30minutes
Expand All @@ -26,19 +31,79 @@ const FINALIZATION_PERIOD_SECONDS: f64 = 700.0;
// uint256 internal finalizationPeriodSeconds = 7 days;
// https://github.com/ethereum-optimism/optimism/tree/develop/op-challenger

#[tokio::main]
pub async fn main() -> Result<(), Box<dyn Error>> {
let (mut _manager, admin, _alice, _bob, _multisig) = startup::set_up_agents().await?;

let _contracts = startup::deploy_contracts(admin).await?;
/// Represents command-line arguments passed to this binary.
#[derive(Parser)]
#[clap(name = "Excalibur")]
#[clap(version = env!("CARGO_PKG_VERSION"))]
#[clap(about = "Simulation driven development.", long_about = None)]
#[clap(author)]
struct Args {
/// Defines the subcommand to execute.
#[command(subcommand)]
command: Option<Commands>,

#[clap(short, long, global = true, required = false, action = ArgAction::Count, value_parser(
clap::value_parser!(u8)))]
verbose: Option<u8>,
}

/// Defines available subcommands for the `Arbiter` tool.
#[derive(Subcommand)]
enum Commands {
/// Represents the `Bind` subcommand.
Simulate {
#[clap(index = 1, default_value = "src/config/gbm.toml")]
config_path: String,
},
}

// make our agents
// #[tokio::main]
// pub async fn main() -> Result<(), Box<dyn Error>> {
// let (mut _manager, admin, _alice, _bob, _multisig) = startup::set_up_agents().await?;

// main sim loop
// check for event
// make action depending on whos turns
// let _contracts = startup::deploy_contracts(admin).await?;

// Things to note:
// // make our agents

// // main sim loop
// // check for event
// // make action depending on whos turns

// // Things to note:

// Ok(())
// }

/// The entry point for the simulation tool.
///
/// This binary provides a command-line interface for the simulation-driven development.
/// It allows users to run simulations by specifying configuration paths, with detailed command-line
/// feedback provided through the `clap` crate.
///
/// # Usage
/// Run the binary without arguments to see available commands and options.
/// Example usage for running simulations:
/// ```
/// $ cargo run simulate [path_to_config]
/// ```
///
/// By default, if no configuration path is provided, it will read from "src/config/gbm.toml".
///
/// These simulations are performed in Arbiter's in memory revm instance and with the exposed RevmMiddleware.
fn main() -> Result<()> {
let args = Args::parse();

match &args.command {
Some(Commands::Simulate { config_path }) => {
println!("Reading from config path: {}", config_path);
let start = Instant::now();
// This is the entry point for the simulation
simulations::batch(config_path)?;
let duration = start.elapsed();
println!("Total duration of simulations: {:?}", duration);
}
None => Args::command().print_long_help()?,
}
Ok(())
}
}
Loading

0 comments on commit d0fe416

Please sign in to comment.