Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

20241007 potato go on chain #44

Draft
wants to merge 35 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
3585869
Starting to add go on chain to potato handler
prozacchiwawa Oct 7, 2024
be745e4
WIP
prozacchiwawa Oct 8, 2024
f8bad49
Completed the loop logically but not spendable yet
prozacchiwawa Oct 9, 2024
668cafc
Organic move on chain is spending the channel coin and we need to pus…
prozacchiwawa Oct 14, 2024
c3579b9
We're spending the unroll coin i think at the right state along with …
prozacchiwawa Oct 18, 2024
851ef70
WIP: routed in puzzle and solution for requested coins
prozacchiwawa Nov 7, 2024
3aadb66
WIP: we're now starting to engage with spent handlers in channel handler
prozacchiwawa Nov 7, 2024
aa36e29
Merge remote-tracking branch 'upstream/main' into 20241007-potato-go-…
prozacchiwawa Nov 7, 2024
36fe1f1
Merge remote-tracking branch 'upstream/main' into 20241007-potato-go-…
prozacchiwawa Nov 7, 2024
42b305c
fmt + clippy
prozacchiwawa Nov 8, 2024
aadbd68
clippy
prozacchiwawa Nov 8, 2024
b7cd791
Merge up
prozacchiwawa Nov 8, 2024
77e1ee6
Change comment language
prozacchiwawa Nov 8, 2024
be2444f
Small wip
prozacchiwawa Nov 9, 2024
5442af6
Up to spend, wrong puzzle provided (WIP)
prozacchiwawa Nov 12, 2024
32d43fe
More parameterization which gives us the freedom to match things
prozacchiwawa Nov 12, 2024
9ba499e
Ensure that we can give a correct spend of the channel coin downstrea…
prozacchiwawa Nov 14, 2024
08cda55
Add decision about whether we add our half of the signature or whethe…
prozacchiwawa Nov 14, 2024
54e7d53
Add an unroll time lock into channel handler. This is needed to prev…
prozacchiwawa Nov 14, 2024
565ccdb
Rename get_unroll_coin_transaction to get_create_unroll_coin_transact…
prozacchiwawa Nov 14, 2024
4844ccc
Timeout
prozacchiwawa Nov 14, 2024
873fc26
Converting to a better rendition of the state machine given a new und…
prozacchiwawa Nov 14, 2024
1832cb8
Small cleanup: deduplicate some code
prozacchiwawa Nov 14, 2024
2f22c49
Fix up some flow, fallout of deduplication. Primed for the next roun…
prozacchiwawa Nov 14, 2024
5144436
Fix up timeout reporting and filtering in full coinset reports in pee…
prozacchiwawa Nov 14, 2024
4bb00eb
We can spend the unroll coin after the timeout (from the first user's…
prozacchiwawa Nov 15, 2024
d713df5
both players complete on chain transition. We need to populate finis…
prozacchiwawa Nov 16, 2024
328159f
Passing test
prozacchiwawa Nov 16, 2024
e8f4fc8
fmt
prozacchiwawa Nov 16, 2024
5a8309d
Fix most of the clippy traffic.
prozacchiwawa Nov 16, 2024
8bc013d
Ensure we can find the clone method. Figure out something better
prozacchiwawa Nov 16, 2024
7ce16b8
Deref
prozacchiwawa Nov 16, 2024
4880720
fmt + clippy
prozacchiwawa Nov 16, 2024
a0db32e
clippy update
prozacchiwawa Nov 16, 2024
ab2cf99
fmt
prozacchiwawa Nov 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 90 additions & 26 deletions src/channel_handler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,23 @@ use crate::channel_handler::types::{
CachedPotatoRegenerateLastHop, ChannelCoin, ChannelCoinInfo, ChannelCoinSpendInfo,
ChannelCoinSpentResult, ChannelHandlerEnv, ChannelHandlerInitiationData,
ChannelHandlerInitiationResult, ChannelHandlerPrivateKeys, ChannelHandlerUnrollSpendInfo,
CoinSpentAccept, CoinSpentDisposition, CoinSpentMoveUp, CoinSpentResult, DispositionResult,
GameStartInfo, HandshakeResult, LiveGame, MoveResult, OnChainGameCoin, PotatoAcceptCachedData,
PotatoMoveCachedData, PotatoSignatures, ReadableMove, UnrollCoin, UnrollCoinConditionInputs,
CoinDataForReward, CoinSpentAccept, CoinSpentDisposition, CoinSpentMoveUp, CoinSpentResult,
DispositionResult, GameStartInfo, HandshakeResult, LiveGame, MoveResult, OnChainGameCoin,
PotatoAcceptCachedData, PotatoMoveCachedData, PotatoSignatures, ReadableMove, UnrollCoin,
UnrollCoinConditionInputs, UnrollTarget,
};
use crate::common::constants::CREATE_COIN;
use crate::common::standard_coin::{
private_to_public_key, puzzle_for_pk, puzzle_for_synthetic_public_key, puzzle_hash_for_pk,
puzzle_hash_for_synthetic_public_key, sign_agg_sig_me, standard_solution_unsafe, ChiaIdentity,
};
#[cfg(test)]
use crate::common::types::Node;
use crate::common::types::{
usize_from_atom, Aggsig, Amount, BrokenOutCoinSpendInfo, CoinCondition, CoinID, CoinSpend,
CoinString, Error, GameID, Hash, IntoErr, PrivateKey, Program, PublicKey, Puzzle, PuzzleHash,
Sha256tree, Spend, SpendRewardResult, ToQuotedProgram,
CoinString, Error, GameID, Hash, IntoErr, Node, PrivateKey, Program, PublicKey, Puzzle,
PuzzleHash, Sha256tree, Spend, SpendRewardResult, ToQuotedProgram,
};
use crate::referee::RefereeMaker;

pub struct CoinDataForReward {
coin_string: CoinString,
// parent: CoinID,
// puzzle_hash: PuzzleHash,
// amount: Amount,
}

/// A channel handler runs the game by facilitating the phases of game startup
/// and passing on move information as well as termination to other layers.
///
Expand Down Expand Up @@ -143,6 +135,15 @@ impl ChannelHandler {
}
}

fn make_curried_unroll_puzzle<R: Rng>(
&self,
env: &mut ChannelHandlerEnv<R>,
) -> Result<NodePtr, Error> {
self.unroll
.coin
.make_curried_unroll_puzzle(env, &self.get_aggregate_unroll_public_key())
}

fn unroll_coin_condition_inputs(
&self,
my_ending_game_value: Amount,
Expand Down Expand Up @@ -543,6 +544,8 @@ impl ChannelHandler {
}

self.current_state_number += 1;
debug!("current state number now {}", self.current_state_number);
debug!("test_unroll updated {:?}", test_unroll.outcome);
self.timeout = Some(ChannelHandlerUnrollSpendInfo {
coin: test_unroll.clone(),
signatures: signatures.clone(),
Expand Down Expand Up @@ -1032,11 +1035,16 @@ impl ChannelHandler {
let unroll_puzzle_solution = use_unroll
.coin
.make_unroll_puzzle_solution(env, &self.get_aggregate_unroll_public_key())?;
let solution_program = Program::from_nodeptr(env.allocator, unroll_puzzle_solution)?;

debug!(
"get_unroll_coin_transaction {:?}",
solution_program.to_hex()
);
Ok(ChannelCoinSpentResult {
transaction: Spend {
puzzle: Puzzle::from_nodeptr(env.allocator, curried_unroll_puzzle)?,
solution: Program::from_nodeptr(env.allocator, unroll_puzzle_solution)?,
solution: solution_program,
signature: use_unroll.coin.get_unroll_coin_signature()?
+ use_unroll.signatures.my_unroll_half_signature_peer.clone(),
},
Expand Down Expand Up @@ -1095,15 +1103,15 @@ impl ChannelHandler {
let state_number = usize_from_atom(&rem_conditions[0])
.ok_or_else(|| Error::StrErr("Unconvertible state number".to_string()))?;

let our_parity = self.unroll.coin.state_number & 1;
let our_parity = full_coin.coin.state_number & 1;
let their_parity = state_number & 1;

debug!(
"CHANNEL COIN SPENT: my state {} coin state {} channel coin state {state_number}",
self.current_state_number, full_coin.coin.state_number
);

match state_number.cmp(&self.current_state_number) {
match state_number.cmp(&full_coin.coin.state_number) {
Ordering::Greater => Err(Error::StrErr(format!(
"Reply from the future onchain {} (me {}) vs {}",
state_number, self.current_state_number, self.unroll.coin.state_number
Expand Down Expand Up @@ -1259,7 +1267,7 @@ impl ChannelHandler {
}
}

pub fn get_new_game_coins_on_chain(
fn get_new_game_coins_on_chain(
&self,
unroll_coin: Option<&CoinID>,
skip_game: &[GameID],
Expand All @@ -1268,6 +1276,63 @@ impl ChannelHandler {
self.compute_game_coin_unroll_data(unroll_coin, skip_game, skip_coin_id, &self.live_games)
}

pub fn get_game_coins<R: Rng>(
&self,
env: &mut ChannelHandlerEnv<R>,
) -> Result<Vec<OnChainGameCoin>, Error> {
let state_number = self.unroll.coin.state_number;
// We need the view of the system as of the most recent timeout.
// I made a move, they have the potato, so we need to reconstruct the
// game states from the most recent their turn. If there's a move in the
// state cache then that game uses that puzzle hash and amount, otherwise
// it uses the one from the live game object. Once on chain, we'll need
// the actual puzzle, but that's a problem for a comment other than this
// one.
let unroll_puzzle = self.make_curried_unroll_puzzle(env)?;
let unroll_puzzle_hash = Node(unroll_puzzle).sha256tree(env.allocator);
let parent_coin = self.state_channel_coin().coin_string();
let unroll_coin = CoinString::from_parts(
&parent_coin.to_coin_id(),
&unroll_puzzle_hash,
&(self.my_out_of_game_balance.clone() + self.their_out_of_game_balance.clone()),
);

let disposition =
self.get_cached_disposition_for_spent_result(env, &unroll_coin, state_number)?;
self.get_new_game_coins_on_chain(
Some(&unroll_coin.to_coin_id()),
&disposition
.as_ref()
.map(|d| d.skip_game.clone())
.unwrap_or_default(),
disposition.as_ref().and_then(|d| d.skip_coin_id.as_ref()),
)
}

// Reset our state so that we generate the indicated puzzles from the live games.
pub fn set_state_for_coins<R: Rng>(
&mut self,
env: &mut ChannelHandlerEnv<R>,
coins: &[OnChainGameCoin],
) -> Result<(), Error> {
let mut res = Vec::new();
for game_coin in coins.iter() {
if let Some(live_game) = self
.live_games
.iter_mut()
.find(|f| game_coin.game_id_up == f.game_id)
{
res.append(&mut live_game.set_state_for_coin(env.allocator, game_coin)?);
} else {
// XXX Used to exist, needs ressurection from the cache to potentially replay
// the accept.
todo!();
}
}

Ok(())
}

// what our vanilla coin string is
// return these triplets for all the active games
// (id of game, coin string that's now on chain for it and the referee maker
Expand Down Expand Up @@ -1434,21 +1499,20 @@ impl ChannelHandler {
// Inititate a simple on chain spend.
//
// Currently used for testing but might be used elsewhere.
#[cfg(test)]
pub fn get_unroll_target<R: Rng>(
&self,
env: &mut ChannelHandlerEnv<R>,
) -> Result<(usize, PuzzleHash, Amount, Amount), Error> {
) -> Result<UnrollTarget, Error> {
let use_unroll = self.get_finished_unroll_coin();
let curried_unroll_puzzle = use_unroll
.coin
.make_curried_unroll_puzzle(env, &self.get_aggregate_unroll_public_key())?;

Ok((
use_unroll.coin.state_number,
Node(curried_unroll_puzzle).sha256tree(&mut env.allocator),
self.my_out_of_game_balance.clone(),
self.their_out_of_game_balance.clone(),
))
Ok(UnrollTarget {
state_number: use_unroll.coin.state_number,
unroll_puzzle_hash: Node(curried_unroll_puzzle).sha256tree(env.allocator),
my_amount: self.my_out_of_game_balance.clone(),
their_amount: self.their_out_of_game_balance.clone(),
})
}
}
64 changes: 58 additions & 6 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::types::{
CoinSpend, CoinString, Error, GameID, Hash, IntoErr, Node, PrivateKey, Program, PublicKey,
Puzzle, PuzzleHash, Sha256Input, Sha256tree, Spend, Timeout,
};
use crate::referee::{GameMoveDetails, RefereeMaker};
use crate::referee::{GameMoveDetails, LiveGameReplay, RefereeMaker};

#[derive(Clone)]
pub struct ChannelHandlerPrivateKeys {
Expand Down Expand Up @@ -667,11 +667,11 @@ pub struct UnrollCoinConditionInputs {
pub puzzle_hashes_and_amounts: Vec<(PuzzleHash, Amount)>,
}

#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct UnrollCoinOutcome {
pub conditions: NodePtr,
pub conditions_without_hash: NodePtr,
pub old_state_number: usize,
pub state_number: usize,
pub hash: PuzzleHash,
pub signature: Aggsig,
}
Expand Down Expand Up @@ -736,7 +736,7 @@ impl UnrollCoin {

fn get_old_state_number(&self) -> Result<usize, Error> {
if let Some(r) = self.outcome.as_ref() {
Ok(r.old_state_number)
Ok(r.state_number)
} else {
Err(Error::StrErr("no default setup".to_string()))
}
Expand Down Expand Up @@ -788,7 +788,7 @@ impl UnrollCoin {
program: env.unroll_puzzle.clone(),
args: clvm_curried_args!(
shared_puzzle_hash,
self.get_old_state_number()?,
self.get_old_state_number()? - 1,
conditions_hash
),
}
Expand Down Expand Up @@ -894,7 +894,7 @@ impl UnrollCoin {
self.outcome = Some(UnrollCoinOutcome {
conditions: unroll_conditions,
conditions_without_hash: unroll_conditions,
old_state_number: self.state_number - 1,
state_number: self.state_number,
hash: conditions_hash,
signature: unroll_signature.clone(),
});
Expand Down Expand Up @@ -931,3 +931,55 @@ impl UnrollCoin {
))
}
}

pub struct CoinDataForReward {
pub coin_string: CoinString,
// parent: CoinID,
// puzzle_hash: PuzzleHash,
// amount: Amount,
}

pub struct UnrollTarget {
pub state_number: usize,
pub unroll_puzzle_hash: PuzzleHash,
pub my_amount: Amount,
pub their_amount: Amount,
}

impl LiveGame {
/// Back up the live game state to the state we know so that we can generate the puzzle
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use the word "Copy" instead of "back up". "Back up is a little ambiguous - before I read further, I thought you meant "go to a previous state", but now I see you mean "grab a copy".

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it's literally about, if necessary, returning to an earlier state. I would say 'backup' if what i meant was storing the state.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe 'regress' is better.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also note this part of the code is badly in flux. i have no idea if this particular thing will survive. i'm experimenting with ideas around being able to figure out what i'm looking at as much as actually writing code that does the thing, although hopefully I'll be able to solidify that idea relatively soon.

/// for that state. We'll return the move needed to advance it fully.
pub fn set_state_for_coin(
&mut self,
allocator: &mut AllocEncoder,
coin: &OnChainGameCoin,
) -> Result<Vec<LiveGameReplay>, Error> {
let want_ph =
if let Some((_, ph, _)) = coin.coin_string_up.as_ref().and_then(|cs| cs.to_parts()) {
ph.clone()
} else {
// No coin string given so this game was ended. We need to ressurect it.
todo!();
};

let referee_puzzle_hash = self
.referee_maker
.curried_referee_puzzle_hash_for_validator(allocator, true)?;

if referee_puzzle_hash == want_ph {
return Ok(vec![]);
}

while self.referee_maker.rewind()? {
let new_puzzle_hash = self
.referee_maker
.curried_referee_puzzle_hash_for_validator(allocator, true)?;

if new_puzzle_hash == want_ph {
todo!();
}
}

todo!();
}
}
4 changes: 2 additions & 2 deletions src/common/standard_coin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ fn test_calculate_synthetic_offset() {
0xe2, 0xce, 0xdb,
];
let pk = PublicKey::from_bytes(pk_bytes).expect("should be ok");
let default_hidden_puzzle_hash = PuzzleHash::from_bytes(DEFAULT_HIDDEN_PUZZLE_HASH.clone());
let default_hidden_puzzle_hash = PuzzleHash::from_bytes(DEFAULT_HIDDEN_PUZZLE_HASH);
let offset = calculate_synthetic_offset(&pk, &default_hidden_puzzle_hash);
let want_offset_bytes = [
0x69, 0x51, 0x33, 0xf4, 0x61, 0x0a, 0x5e, 0x50, 0x7b, 0x2f, 0x24, 0x98, 0x22, 0x21, 0x91,
Expand Down Expand Up @@ -150,7 +150,7 @@ fn test_calculate_synthetic_public_key() {
0xe2, 0xce, 0xdb,
];
let pk = PublicKey::from_bytes(pk_bytes).expect("should be ok");
let default_hidden_puzzle_hash = PuzzleHash::from_bytes(DEFAULT_HIDDEN_PUZZLE_HASH.clone());
let default_hidden_puzzle_hash = PuzzleHash::from_bytes(DEFAULT_HIDDEN_PUZZLE_HASH);
let spk =
calculate_synthetic_public_key(&pk, &default_hidden_puzzle_hash).expect("should be ok");
let want_spk_bytes: [u8; 48] = [
Expand Down
5 changes: 5 additions & 0 deletions src/common/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,11 @@ impl Program {
Ok(Program(bytes))
}

pub fn from_hex(s: &str) -> Result<Program, Error> {
let bytes = hex::decode(s).into_gen()?;
Ok(Program::from_bytes(&bytes))
}

pub fn from_bytes(by: &[u8]) -> Program {
Program(by.to_vec())
}
Expand Down
Loading
Loading