Skip to content

Commit

Permalink
feat(compute-tests): create rust_hero coroutine
Browse files Browse the repository at this point in the history
  • Loading branch information
stephenctw committed Sep 23, 2024
1 parent 4d9f607 commit e6de9bd
Show file tree
Hide file tree
Showing 16 changed files with 3,897 additions and 147 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
target/
snapshots/
common-rs/Cargo.lock
prt/prt-rs/Cargo.lock
prt/lua_poc/outputs/
prt/lua_poc/pixels/
node_modules
Expand Down
93 changes: 38 additions & 55 deletions prt/client-lua/utils/helper.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ local idle_template = [[ls player%d_idle 2>/dev/null | grep player%d_idle | wc -
local ps_template = [[ps %s | grep defunct | wc -l]]
local helper = {}

local function parse_datetime(datetime_str)
function helper.parse_datetime(datetime_str)
local patterns = {
-- Lua node timestamp format
"(%d%d)/(%d%d)/(%d%d%d%d) (%d%d):(%d%d):(%d%d)", -- MM/DD/YYYY HH:MM:SS
Expand Down Expand Up @@ -63,43 +63,47 @@ end
function helper.log_to_ts(player_index, reader, last_ts)
-- print everything hold in the buffer which has smaller timestamp
-- this is to synchronise when there're gaps in between the logs
local msg_output = 0
local prev_msg = false
while true do
local msg = reader:read()
if msg then
msg_output = msg_output + 1
helper.log_color(player_index, msg)

local timestamp, _ = parse_datetime(msg)
if timestamp then
if timestamp > last_ts then
last_ts = timestamp
local ts = helper.parse_datetime(msg)
if ts then
if ts > last_ts then
prev_msg = msg
break
end
else
break
end
helper.log_color(player_index, msg)
else
break
end
end
return last_ts, msg_output
return prev_msg
end

function helper.is_zombie(pid)
local reader = io.popen(string.format(ps_template, pid))
if reader then
local ret = reader:read()
reader:close()
return tonumber(ret) == 1
-- Check if the process is defunct
local handle = io.popen("ps -p " .. pid .. " -o stat=") -- Get the process status
if handle then
local status = handle:read("*l") -- Read the status
handle:close()
-- Check if the status indicates a defunct process
if status and status:match("Z") then
return true -- Process is defunct
else
return false
end
end
end

function helper.stop_players(pid_reader)
for pid, reader in pairs(pid_reader) do
print(string.format("Stopping player with pid %s...", pid))
os.execute(string.format("kill -15 %s", pid))
reader:close()
print "Player stopped"
end
function helper.stop_pid(reader, pid)
print(string.format("Stopping pid %s...", pid))
os.execute(string.format("kill -15 %s", pid))
reader:close()
print "Process stopped"
end

function helper.str_to_bool(str)
Expand All @@ -109,39 +113,6 @@ function helper.str_to_bool(str)
return string.lower(str) == 'true'
end

function helper.touch_player_idle(player_index)
os.execute(string.format("touch player%d_idle", player_index))
end

function helper.is_player_idle(player_index)
local reader = io.popen(string.format(idle_template, player_index, player_index))
if reader then
local ret = reader:read()
reader:close()
return tonumber(ret) == 1
end
end

function helper.rm_player_idle(player_index)
os.execute(string.format("rm player%d_idle 2>/dev/null", assert(player_index)))
end

function helper.all_players_idle(pid_player)
for _, player in pairs(pid_player) do
if not helper.is_player_idle(player) then
return false
end
end
return true
end

function helper.rm_all_players_idle(pid_player)
for _, player in pairs(pid_player) do
helper.rm_player_idle(player)
end
return true
end

--- Check if a file or directory exists in this path
function helper.exists(file)
local ok, err, code = os.rename(file, file)
Expand All @@ -154,4 +125,16 @@ function helper.exists(file)
return ok, err
end

function helper.is_pid_alive(pid)
-- Check if the process is alive
local ok, _, code = os.execute("kill -0 " .. pid .. " 2>/dev/null")
if ok then
if helper.is_zombie(pid) then
return false
end
return code == 0 -- Returns true if the process is alive
end
return false -- Returns false if the process is not alive
end

return helper
1 change: 1 addition & 0 deletions prt/prt-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ log = "0.4"
hex = "0.4.3"
num-traits = "0.2.19"
ruint = { version = "1.12", features = ["num-traits"] }
tokio = { version = "1", features = ["full"] }
10 changes: 5 additions & 5 deletions prt/prt-rs/src/strategy/gc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@ impl GarbageCollector {
Self { root_tournamet }
}

pub async fn react<'a>(
&mut self,
pub async fn react_once<'a>(
&self,
arena_sender: &'a impl ArenaSender,
tournament_states: TournamentStateMap,
tournament_states: &TournamentStateMap,
) -> Result<()> {
self.react_tournament(arena_sender, self.root_tournamet, &tournament_states)
.await
}

#[async_recursion]
async fn react_tournament<'a>(
&mut self,
&self,
arena_sender: &'a impl ArenaSender,
tournament_address: Address,
tournament_states: &TournamentStateMap,
Expand Down Expand Up @@ -70,7 +70,7 @@ impl GarbageCollector {

#[async_recursion]
async fn react_match<'a>(
&mut self,
&self,
arena_sender: &'a impl ArenaSender,
match_state: &MatchState,
tournament_states: &TournamentStateMap,
Expand Down
56 changes: 42 additions & 14 deletions prt/prt-rs/src/strategy/player.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::HashMap;

use ::log::info;
use ::log::{error, info};
use alloy::sol_types::private::Address;
use anyhow::Result;
use async_recursion::async_recursion;
Expand All @@ -9,10 +9,11 @@ use ruint::aliases::U256;

use crate::{
arena::{
ArenaSender, CommitmentMap, CommitmentState, MatchState, TournamentState,
TournamentStateMap, TournamentWinner,
ArenaSender, BlockchainConfig, CommitmentMap, CommitmentState, MatchState, StateReader,
TournamentState, TournamentStateMap, TournamentWinner,
},
machine::{constants, CachingMachineCommitmentBuilder, MachineCommitment, MachineInstance},
strategy::gc::GarbageCollector,
};
use cartesi_dave_merkle::{Digest, MerkleProof};

Expand All @@ -25,32 +26,59 @@ pub enum PlayerTournamentResult {
pub struct Player {
machine_path: String,
commitment_builder: CachingMachineCommitmentBuilder,
root_tournamet: Address,
root_tournament: Address,
reader: StateReader,
gc: GarbageCollector,
}

impl Player {
pub fn new(
blockchain_config: &BlockchainConfig,
machine_path: String,
commitment_builder: CachingMachineCommitmentBuilder,
root_tournamet: Address,
) -> Self {
Self {
root_tournament: Address,
) -> Result<Self> {
let reader = StateReader::new(&blockchain_config)?;
let gc = GarbageCollector::new(root_tournament);
let commitment_builder = CachingMachineCommitmentBuilder::new(machine_path.clone());
Ok(Self {
machine_path,
commitment_builder,
root_tournamet,
}
root_tournament,
reader,
gc,
})
}

pub async fn react<'a>(
&mut self,
arena_sender: &'a impl ArenaSender,
tournament_states: &TournamentStateMap,
interval: u64,
) -> Result<PlayerTournamentResult> {
loop {
let result = self.react_once(arena_sender).await;
match result {
Err(e) => error!("{}", e),
Ok(player_tournament_result) => {
if let Some(r) = player_tournament_result {
return Ok(r);
}
}
}
tokio::time::sleep(std::time::Duration::from_secs(interval)).await;
}
}

pub async fn react_once<'a>(
&mut self,
arena_sender: &'a impl ArenaSender,
) -> Result<Option<PlayerTournamentResult>> {
let tournament_states = self.reader.fetch_from_root(self.root_tournament).await?;
self.gc.react_once(arena_sender, &tournament_states).await?;
self.react_tournament(
arena_sender,
HashMap::new(),
self.root_tournamet,
tournament_states,
self.root_tournament,
&tournament_states,
)
.await
}
Expand Down Expand Up @@ -378,7 +406,7 @@ impl Player {
};

let agree_state_proof = if running_leaf_position.is_zero() {
MerkleProof::empty()
MerkleProof::leaf(commitment.implicit_hash, U256::ZERO)
} else {
commitment
.merkle
Expand Down
Loading

0 comments on commit e6de9bd

Please sign in to comment.