Skip to content

Commit 9031552

Browse files
committed
WIP, interim updates, starting to construct TransactionBundle for simulator
1 parent 8bd8677 commit 9031552

File tree

2 files changed

+162
-65
lines changed

2 files changed

+162
-65
lines changed

src/referee.rs

+94-54
Original file line numberDiff line numberDiff line change
@@ -649,46 +649,46 @@ impl RefereeMaker {
649649
agg_sig_me_additional_data: &Hash,
650650
) -> Result<(TransactionBundle, CoinString), Error> {
651651
let puzzle_reveal = {
652-
let previous_args = {
653-
let previous_state = self.previous_state();
654-
let puzzle_hash = curry_referee_puzzle_hash(
655-
allocator,
656-
&self.referee_coin_puzzle_hash,
657-
&RefereePuzzleArgs {
658-
// XXX check polarity
659-
mover_puzzle_hash: self.my_identity.puzzle_hash.clone(),
660-
waiter_puzzle_hash: self.their_referee_puzzle_hash.clone(),
661-
timeout: self.timeout.clone(),
662-
amount: self.amount.clone(),
663-
referee_coin_puzzle_hash: self.referee_coin_puzzle_hash.clone(),
664-
game_move: previous_state.game_move.clone(),
665-
nonce: self.nonce,
666-
previous_validation_info_hash: previous_state
667-
.previous_validation_program_hash
668-
.clone(),
669-
},
670-
)?;
671-
let inner_conditions =
672-
// XXX puzzle_reveal
673-
(CREATE_COIN, (puzzle_hash.clone(), (self.amount.clone(), ()))).to_clvm(allocator).into_gen()?;
674-
let (solution, sig) =
675-
standard_solution(allocator, &self.my_identity.private_key, inner_conditions)?;
676-
let args_list: Vec<Node> = [
677-
previous_state.game_move.move_made.to_clvm(allocator).into_gen()?,
678-
previous_state
679-
.game_move.validation_info_hash
680-
.to_clvm(allocator)
681-
.into_gen()?,
682-
previous_state.game_move.mover_share.to_clvm(allocator).into_gen()?,
683-
previous_state.game_move.max_move_size.to_clvm(allocator).into_gen()?,
684-
puzzle_hash.to_clvm(allocator).into_gen()?,
685-
solution,
686-
]
652+
let previous_state = self.previous_state();
653+
let puzzle_hash = curry_referee_puzzle_hash(
654+
allocator,
655+
&self.referee_coin_puzzle_hash,
656+
&RefereePuzzleArgs {
657+
// XXX check polarity
658+
mover_puzzle_hash: self.my_identity.puzzle_hash.clone(),
659+
waiter_puzzle_hash: self.their_referee_puzzle_hash.clone(),
660+
timeout: self.timeout.clone(),
661+
amount: self.amount.clone(),
662+
referee_coin_puzzle_hash: self.referee_coin_puzzle_hash.clone(),
663+
game_move: previous_state.game_move.clone(),
664+
nonce: self.nonce,
665+
previous_validation_info_hash: previous_state
666+
.previous_validation_program_hash
667+
.clone(),
668+
},
669+
)?;
670+
671+
let inner_conditions =
672+
// XXX puzzle_reveal
673+
(CREATE_COIN, (puzzle_hash.clone(), (self.amount.clone(), ()))).to_clvm(allocator).into_gen()?;
674+
let (solution, sig) =
675+
standard_solution(allocator, &self.my_identity.private_key, inner_conditions)?;
676+
let args_list: Vec<Node> = [
677+
previous_state.game_move.move_made.to_clvm(allocator).into_gen()?,
678+
previous_state
679+
.game_move.validation_info_hash
680+
.to_clvm(allocator)
681+
.into_gen()?,
682+
previous_state.game_move.mover_share.to_clvm(allocator).into_gen()?,
683+
previous_state.game_move.max_move_size.to_clvm(allocator).into_gen()?,
684+
puzzle_hash.to_clvm(allocator).into_gen()?,
685+
solution,
686+
]
687687
.into_iter()
688688
.map(|n| Node(n))
689689
.collect();
690-
args_list.to_clvm(allocator).into_gen()?
691-
};
690+
691+
let previous_args = args_list.to_clvm(allocator).into_gen()?;
692692

693693
if let Some((bundle, cs_out)) = self.get_transaction(
694694
allocator,
@@ -850,6 +850,7 @@ impl RefereeMaker {
850850
)
851851
};
852852

853+
// Retrieve evidence from their turn handler.
853854
let result = handler.call_their_turn_driver(
854855
allocator,
855856
&TheirTurnInputs {
@@ -868,6 +869,30 @@ impl RefereeMaker {
868869

869870
match result {
870871
TheirTurnResult::MakeMove(handler, readable_move, message) => {
872+
// Mover puzzle turns the given solution into coin conditions
873+
// that pay the game's amount to us. It checks whether the
874+
// originally curried mover puzzle hash is the sha256tree of the
875+
// mover puzzle.
876+
//
877+
// This referee expects the mover puzzle to be a standard-like
878+
// puzzle or at least take standard coin arguments including the
879+
// list of conditions it produces itself.
880+
//
881+
// In case this succeeds, we'll direct the result to our mover
882+
// puzzle, which sets our identity for the game and is a value-
883+
// holding coin spendable by us.
884+
885+
// let validator_move_args = ValidatorMoveArgs {
886+
// game_move: details.clone(),
887+
// mover_puzzle: self.identity.puzzle.clone(),
888+
// solution:
889+
// };
890+
891+
// let validator_result = self.run_validator_for_their_move(
892+
// allocator,
893+
// validator_move_args
894+
// );
895+
871896
// XXX check for slashing.
872897
self.update_for_their_turn_move(
873898
allocator,
@@ -907,12 +932,31 @@ impl RefereeMaker {
907932
}
908933
}
909934

910-
fn target_puzzle_hash_for_slash(
935+
// It me.
936+
fn target_puzzle_hash_for_slash(&self) -> PuzzleHash {
937+
self.my_identity.puzzle_hash.clone()
938+
}
939+
940+
fn slashing_coin_solution(
911941
&self,
912942
allocator: &mut AllocEncoder,
913-
) -> Result<PuzzleHash, Error> {
914-
let target_inner_puzzle = puzzle_for_pk(allocator, &self.my_identity.public_key)?;
915-
puzzle_hash_for_pk(allocator, &self.my_identity.public_key)
943+
state: NodePtr,
944+
validation_program: Puzzle,
945+
slash_solution: NodePtr,
946+
coin_solution_after_slash: NodePtr
947+
) -> Result<NodePtr, Error> {
948+
(
949+
Node(state.clone()),
950+
(
951+
validation_program.clone(),
952+
(
953+
self.target_puzzle_hash_for_slash(),
954+
(Node(slash_solution), (Node(coin_solution_after_slash), ())),
955+
),
956+
),
957+
)
958+
.to_clvm(allocator)
959+
.into_gen()
916960
}
917961

918962
fn make_slash_for_their_turn(
@@ -938,23 +982,19 @@ impl RefereeMaker {
938982
current_state.validation_program.clone(),
939983
)
940984
};
985+
941986
let reward_amount = self.amount.clone() - current_mover_share;
942987
if reward_amount == Amount::default() {
943988
return Ok(TheirTurnCoinSpentResult::Slash(SlashOutcome::NoReward));
944989
}
945990

946-
let slashing_coin_solution = (
947-
Node(state.clone()),
948-
(
949-
Node(validation_program.clone()),
950-
(
951-
self.target_puzzle_hash_for_slash(allocator)?,
952-
(Node(slash_solution), (Node(solution), ())),
953-
),
954-
),
955-
)
956-
.to_clvm(allocator)
957-
.into_gen()?;
991+
let slashing_coin_solution = self.slashing_coin_solution(
992+
allocator,
993+
state,
994+
Puzzle::from_nodeptr(validation_program),
995+
slash_solution,
996+
solution
997+
)?;
958998

959999
let coin_string_of_output_coin =
9601000
CoinString::from_parts(&coin_string.to_coin_id(), &new_puzzle_hash, &reward_amount);
@@ -1069,7 +1109,7 @@ impl RefereeMaker {
10691109
let slash_conditions = (
10701110
CREATE_COIN,
10711111
(
1072-
self.target_puzzle_hash_for_slash(allocator)?,
1112+
self.target_puzzle_hash_for_slash(),
10731113
(self.amount.clone(), ()),
10741114
),
10751115
)

src/tests/simulator.rs

+68-11
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1+
use clvmr::allocator::NodePtr;
2+
13
use pyo3::prelude::*;
2-
use pyo3::types::PyNone;
4+
use pyo3::types::{PyNone, PyBytes, PyTuple};
35

46
use indoc::indoc;
57

6-
use crate::common::types::{ErrToError, Error};
8+
use crate::common::types::{ErrToError, Error, Puzzle, Amount, Hash, CoinString, CoinID, PuzzleHash, Aggsig, SpecificTransactionBundle};
79

810
// Allow simulator from rust.
911
struct Simulator {
1012
evloop: PyObject,
1113
sim: PyObject,
1214
client: PyObject,
1315
guard: PyObject,
16+
make_spend: PyObject,
17+
chia_rs_coin: PyObject,
1418
}
1519

1620
#[cfg(test)]
@@ -20,15 +24,23 @@ impl ErrToError for PyErr {
2024
}
2125
}
2226

27+
pub struct CoinSpend {
28+
coin: CoinString,
29+
puzzle_reveal: Puzzle,
30+
solution: NodePtr
31+
}
32+
33+
pub struct SpendBundle {
34+
coin_spends: Vec<CoinSpend>,
35+
aggregated_signature: Aggsig
36+
}
37+
2338
impl Drop for Simulator {
2439
fn drop(&mut self) {
2540
Python::with_gil(|py| -> PyResult<_> {
2641
let none = PyNone::get(py);
27-
let exit_task = self
28-
.guard
29-
.call_method1(py, "__aexit__", (none, none, none))?;
30-
self.evloop
31-
.call_method1(py, "run_until_complete", (exit_task,))?;
42+
let exit_task = self.guard.call_method1(py, "__aexit__", (none, none, none))?;
43+
self.evloop.call_method1(py, "run_until_complete", (exit_task,))?;
3244
Ok(())
3345
})
3446
.expect("should shutdown");
@@ -43,12 +55,14 @@ impl Simulator {
4355
indoc! {"
4456
import asyncio
4557
import chia.clvm.spend_sim
58+
from chia.types.coin_spend import make_spend
59+
from chia_rs import Coin
4660
4761
def start():
4862
evloop = asyncio.new_event_loop()
4963
sac_gen = chia.clvm.spend_sim.sim_and_client()
5064
(sim, client) = evloop.run_until_complete(sac_gen.__aenter__())
51-
return (evloop, sim, client, sac_gen)
65+
return (evloop, sim, client, sac_gen, make_spend, Coin)
5266
"},
5367
"tmod.py",
5468
"tmod",
@@ -59,24 +73,67 @@ impl Simulator {
5973
sim: evloop.get_item(1)?.extract()?,
6074
client: evloop.get_item(2)?.extract()?,
6175
guard: evloop.get_item(3)?.extract()?,
76+
make_spend: evloop.get_item(4)?.extract()?,
77+
chia_rs_coin: evloop.get_item(5)?.extract()?,
6278
})
6379
})
6480
.expect("should work")
6581
}
6682

83+
fn async_call<ArgT>(&self, py: Python<'_>, name: &str, args: ArgT) -> PyResult<PyObject>
84+
where
85+
ArgT: IntoPy<Py<PyTuple>>
86+
{
87+
let task = self.sim.call_method1(py, name, args)?;
88+
let res = self.evloop.call_method1(py, "run_until_complete", (task,))?;
89+
Ok(res.into())
90+
}
91+
6792
pub fn farm_block(&self) {
6893
Python::with_gil(|py| -> PyResult<_> {
69-
let farm_task = self.sim.call_method0(py, "farm_block")?;
70-
self.evloop
71-
.call_method1(py, "run_until_complete", (farm_task,))?;
94+
self.async_call(py, "farm_block", ())?;
7295
Ok(())
7396
})
7497
.expect("should farm");
7598
}
99+
100+
pub fn get_my_coins(&self) -> PyResult<Vec<CoinString>> {
101+
todo!();
102+
}
103+
104+
pub fn make_coin(&self, coin_string: &CoinString) -> PyResult<PyObject> {
105+
let (parent_id, puzzle_hash, amount) =
106+
if let Some(parts) = coin_string.to_parts() {
107+
parts
108+
} else {
109+
todo!();
110+
};
111+
112+
Python::with_gil(|py| -> PyResult<_> {
113+
let parent_parent_coin = PyBytes::new(py, &parent_id.bytes());
114+
let puzzle_hash_data = PyBytes::new(py, &puzzle_hash.bytes());
115+
let amt: u64 = amount.into();
116+
self.chia_rs_coin.call1(py, (parent_parent_coin, puzzle_hash_data, amt))
117+
})
118+
}
119+
120+
fn make_coin_spend(
121+
&self,
122+
parent_coin: &CoinString,
123+
puzzle_reveal: Puzzle,
124+
solution: NodePtr
125+
) -> PyResult<CoinSpend> {
126+
todo!();
127+
}
128+
129+
pub fn perform_spend(&self, tx: &[SpecificTransactionBundle]) -> PyResult<()> {
130+
todo!();
131+
}
76132
}
77133

78134
#[test]
79135
fn test_sim() {
80136
let s = Simulator::new();
81137
s.farm_block();
138+
let c = s.make_coin(&CoinString::from_parts(&CoinID::default(), &PuzzleHash::default(), &Amount::default()));
82139
}

0 commit comments

Comments
 (0)