Skip to content

Commit

Permalink
Fix rem parsing to ensure long rems can be parsed, plumb in spend thr…
Browse files Browse the repository at this point in the history
…ough potato handler and channel handler so we can observe and react to spends of game coins at that layer and update our understanding. The spend on chain is causing an allowed slash, which needs to be investigated
  • Loading branch information
prozacchiwawa committed Nov 26, 2024
1 parent dfca5f9 commit d2383f9
Show file tree
Hide file tree
Showing 9 changed files with 280 additions and 83 deletions.
4 changes: 2 additions & 2 deletions src/channel_handler/game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ use clvmr::{run_program, NodePtr};

use clvm_tools_rs::classic::clvm::sexp::proper_list;

use crate::channel_handler::game_handler::{chia_dialect, GameHandler};
use crate::channel_handler::game_handler::GameHandler;
use crate::channel_handler::types::ValidationProgram;
use crate::channel_handler::GameStartInfo;
use crate::common::standard_coin::read_hex_puzzle;
use crate::common::types::{
atom_from_clvm, u64_from_atom, usize_from_atom, AllocEncoder, Amount, Error, GameID, Hash,
IntoErr, Timeout,
IntoErr, Timeout, chia_dialect
};

pub struct Game {
Expand Down
9 changes: 2 additions & 7 deletions src/channel_handler/game_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,17 @@ use clvm_tools_rs::compiler::comptypes::CompilerOpts;
use clvm_tools_rs::compiler::srcloc::Srcloc;
use clvm_traits::{ClvmEncoder, ToClvm};
use clvmr::allocator::NodePtr;
use clvmr::NO_UNKNOWN_OPS;
use clvmr::{run_program, ChiaDialect};
use clvmr::run_program;

use log::debug;

use crate::channel_handler::types::{Evidence, ReadableMove, ValidationInfo, ValidationProgram};
use crate::common::types::{
atom_from_clvm, u64_from_atom, usize_from_atom, Aggsig, AllocEncoder, Amount, Error, Hash,
IntoErr, Node, Program,
IntoErr, Node, Program, chia_dialect
};
use crate::referee::{GameMoveDetails, GameMoveStateInfo};

pub fn chia_dialect() -> ChiaDialect {
ChiaDialect::new(NO_UNKNOWN_OPS)
}

// How to call the clvm program in this object:
//
// My turn driver takes (readable_new_move amount last_state last_move last_mover_share entropy) and returns
Expand Down
48 changes: 41 additions & 7 deletions src/channel_handler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ use crate::channel_handler::types::{
CoinDataForReward, CoinSpentAccept, CoinSpentDisposition, CoinSpentMoveUp, CoinSpentResult,
DispositionResult, GameStartInfo, HandshakeResult, LiveGame, MoveResult, OnChainGameCoin,
OnChainGameState, PotatoAcceptCachedData, PotatoMoveCachedData, PotatoSignatures, ReadableMove,
UnrollCoin, UnrollCoinConditionInputs, UnrollTarget,
UnrollCoin, UnrollCoinConditionInputs, UnrollTarget, CoinSpentInformation,
CoinIdentificationByPuzzleHash,
};
use crate::common::constants::CREATE_COIN;
use crate::common::standard_coin::{
Expand All @@ -36,7 +37,7 @@ use crate::common::types::{
};
use crate::potato_handler::GameAction;
use crate::referee::{
GameMoveDetails, RefereeMaker, RefereeOnChainTransaction, TheirTurnCoinSpentResult,
GameMoveDetails, RefereeMaker, RefereeOnChainTransaction,
};

/// A channel handler runs the game by facilitating the phases of game startup
Expand Down Expand Up @@ -1490,21 +1491,54 @@ impl ChannelHandler {
))
}

pub fn their_turn_coin_spent<R: Rng>(
pub fn game_coin_spent<R: Rng>(
&mut self,
env: &mut ChannelHandlerEnv<R>,
game_id: &GameID,
coin_string: &CoinString,
conditions: &NodePtr,
) -> Result<TheirTurnCoinSpentResult, Error> {
conditions: &[CoinCondition]
) -> Result<CoinSpentInformation, Error> {
let live_game_idx = self.get_game_by_id(game_id)?;
let referee_pk = private_to_public_key(&self.referee_private_key());
let reward_puzzle_hash = puzzle_hash_for_pk(env.allocator, &referee_pk)?;
let game_puzzle_hash = self.live_games[live_game_idx].outcome_puzzle_hash(env.allocator)?;

if self.live_games[live_game_idx].processing_my_turn() {
// Try to determine if the spend was us.
let expected_creation =
conditions.iter().filter_map(|c| {
if let CoinCondition::CreateCoin(ph, amt) = c {
if game_puzzle_hash == *ph {

return Some(CoinIdentificationByPuzzleHash::Game(ph.clone(), amt.clone()));
} else if reward_puzzle_hash == *ph {
return Some(CoinIdentificationByPuzzleHash::Reward(ph.clone(), amt.clone()));
}
}
None
}).next();
{
// It was the spend we expected from our own actions to continue the game.
match expected_creation {
Some(CoinIdentificationByPuzzleHash::Reward(ph, amt)) => {
return Ok(CoinSpentInformation::OurReward(ph.clone(), amt.clone()));
}
Some(CoinIdentificationByPuzzleHash::Game(ph, amt)) => {
return Ok(CoinSpentInformation::OurSpend(ph.clone(), amt.clone()));
}
_ => { }
}
}

todo!();
}

self.live_games[live_game_idx].their_turn_coin_spent(
Ok(CoinSpentInformation::TheirSpend(self.live_games[live_game_idx].their_turn_coin_spent(
env.allocator,
coin_string,
conditions,
self.current_state_number,
)
)?))
}

pub fn get_redo_action<R: Rng>(
Expand Down
24 changes: 20 additions & 4 deletions src/channel_handler/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::common::standard_coin::{
use crate::common::types::{
atom_from_clvm, usize_from_atom, Aggsig, AllocEncoder, Amount, BrokenOutCoinSpendInfo, CoinID,
CoinSpend, CoinString, Error, GameID, Hash, IntoErr, Node, PrivateKey, Program, PublicKey,
Puzzle, PuzzleHash, Sha256Input, Sha256tree, Spend, Timeout,
Puzzle, PuzzleHash, Sha256Input, Sha256tree, Spend, Timeout, CoinCondition,
};
use crate::referee::{
GameMoveDetails, GameMoveWireData, RefereeMaker, RefereeOnChainTransaction,
Expand Down Expand Up @@ -1007,6 +1007,10 @@ impl LiveGame {
self.referee_maker.on_chain_referee_puzzle_hash(allocator)
}

pub fn outcome_puzzle_hash(&self, allocator: &mut AllocEncoder) -> Result<PuzzleHash, Error> {
self.referee_maker.outcome_referee_puzzle_hash(allocator)
}

pub fn internal_make_move(
&mut self,
allocator: &mut AllocEncoder,
Expand Down Expand Up @@ -1068,18 +1072,17 @@ impl LiveGame {
allocator: &mut AllocEncoder,
data: &[u8],
) -> Result<ReadableMove, Error> {
assert!(!self.referee_maker.is_my_turn());
self.referee_maker.receive_readable(allocator, data)
}

pub fn their_turn_coin_spent(
&mut self,
allocator: &mut AllocEncoder,
coin_string: &CoinString,
conditions: &NodePtr,
conditions: &[CoinCondition],
current_state: usize,
) -> Result<TheirTurnCoinSpentResult, Error> {
assert!(!self.referee_maker.is_my_turn());
assert!(!self.referee_maker.processing_my_turn());
self.referee_maker
.their_turn_coin_spent(allocator, coin_string, conditions, current_state)
}
Expand Down Expand Up @@ -1110,3 +1113,16 @@ impl LiveGame {
Ok(None)
}
}

/// Identifies the game phase that an on chain spend represented.
/// If their turn, gives a referee TheirTurnCoinSpentResult, otherwise gives the new coin.
pub enum CoinSpentInformation {
OurReward(PuzzleHash, Amount),
OurSpend(PuzzleHash, Amount),
TheirSpend(TheirTurnCoinSpentResult)
}

pub enum CoinIdentificationByPuzzleHash {
Reward(PuzzleHash, Amount),
Game(PuzzleHash, Amount),
}
41 changes: 30 additions & 11 deletions src/common/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use std::io;
use std::ops::{Add, AddAssign, Sub, SubAssign};
use std::rc::Rc;

use log::debug;

use serde::de::Visitor;
use serde::{Deserialize, Deserializer, Serialize, Serializer};

Expand All @@ -16,10 +18,12 @@ use sha2::{Digest, Sha256};
use clvmr::allocator::{Allocator, NodePtr, SExp};
use clvmr::reduction::EvalErr;
use clvmr::serde::{node_from_bytes, node_to_bytes};
use clvmr::{ChiaDialect, run_program, NO_UNKNOWN_OPS};

use clvm_tools_rs::classic::clvm::sexp::proper_list;
use clvm_tools_rs::classic::clvm::syntax_error::SyntaxErr;
use clvm_tools_rs::classic::clvm_tools::sha256tree::sha256tree;
use clvm_tools_rs::classic::clvm_tools::binutils::disassemble;

use crate::common::constants::{AGG_SIG_ME_ATOM, AGG_SIG_UNSAFE_ATOM, CREATE_COIN_ATOM, REM_ATOM};

Expand All @@ -30,6 +34,10 @@ use clvm_traits::{ClvmEncoder, ToClvm, ToClvmError};
#[cfg(test)]
use clvm_tools_rs::compiler::runtypes::RunFailure;

pub fn chia_dialect() -> ChiaDialect {
ChiaDialect::new(NO_UNKNOWN_OPS)
}

/// CoinID
#[derive(Default, Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Hash)]
pub struct CoinID(Hash);
Expand Down Expand Up @@ -954,18 +962,10 @@ fn parse_condition(allocator: &mut AllocEncoder, condition: NodePtr) -> Option<C
Amount::new(amt),
));
}
} else {
return None;
}
} else if exploded.len() > 1
&& matches!(
(
allocator.allocator().sexp(exploded[0]),
allocator.allocator().sexp(exploded[1])
),
(SExp::Atom, SExp::Atom)
)
{
}

if !exploded.is_empty() && exploded.iter().all(|e| matches!(allocator.allocator().sexp(*e), SExp::Atom)) {
let atoms: Vec<Vec<u8>> = exploded
.iter()
.map(|a| allocator.allocator().atom(*a).to_vec())
Expand All @@ -992,6 +992,25 @@ impl CoinCondition {
Vec::new()
}
}

pub fn from_puzzle_and_solution(allocator: &mut AllocEncoder, puzzle: &Program, solution: &Program) -> Result<Vec<CoinCondition>, Error> {
let run_puzzle = puzzle.to_nodeptr(allocator)?;
let run_args = solution.to_nodeptr(allocator)?;
let conditions = run_program(
allocator.allocator(),
&chia_dialect(),
run_puzzle,
run_args,
0,
)
.into_gen()?;
debug!(
"conditions to parse {}",
disassemble(allocator.allocator(), conditions.1, None)
);

Ok(CoinCondition::from_nodeptr(allocator, conditions.1))
}
}

#[derive(Clone, Debug, Serialize, Deserialize)]
Expand Down
Loading

0 comments on commit d2383f9

Please sign in to comment.