Skip to content

kimsk/chia-tic-tac-toe

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Chia Tic Tac Toe

This repository is the continued work of tic-tac-toe game on Chia Blockchain from chia-concepts/tic-tac-toe.

Creating Tic Tac Toe Coin

In the chia-concepts/tic-tac-toe, in order to create an initial singleton game coin, both Alice and Bob have to be able to sign and spend their coins together.

create-singleton

The process is cumbersome and requires Bob to trust Alice not to steal his coin (because Bob has to provide his signature for his coin spend). Also, both Alice and Bob can't use standard wallets and have to prepare conditions for the standard spend manually.

# alice's coin creates a launcher coin
alice_conditions = [
    # create launcher coin with the odd_amount (odd)
    Program.to(
        [
            ConditionOpcode.CREATE_COIN,
            singleton_top_layer_v1_1.SINGLETON_LAUNCHER_HASH,
            game_amount,
        ]),
    # assert launcher coin announcement
    Program.to(
        [
            ConditionOpcode.ASSERT_COIN_ANNOUNCEMENT, 
            std_hash(launcher_id + launcher_announcement)
        ]),
    
    # change
    [ConditionOpcode.CREATE_COIN, alice.puzzle_hash, alice_coin.amount - (player_amount + 1)]
]

# bob's coin create change back to himself
bob_conditions = [
    [ConditionOpcode.CREATE_COIN, bob.puzzle_hash, bob_coin.amount - player_amount],
]

To resolve the issue, we introduced the waiting room puzzle allowing both Alice and Bob to send XCH to create their waiting room coins using their standard wallets.

Once the waiting room coins for both players are on the blockchain. Alice can create a spend bundle by spending two waiting room coins to create a Tic Tac Toe game coin.

If either Alice or Bob or both decide not to play the game (e.g., only one waiting room coin is created or both waiting room coins are created, but Alice doesn't spend them to create a game coin), players can claw back their XCH.

Each waiting coin also curries in the RETURN_AMOUNT (for clawback) and GAME_AMOUNT (amount to get when someone wins) that are agreed upon before creating the game.

Waiting Room Puzzle

; P1_PK                         : Player One PK
; P2_PK                         : Player Two PK
; RETURN_AMOUNT                 : Amount returned to player when clawback in mojos
; GAME_AMOUNT                   : Odd game amount in mojos
; P1_PH                         : P1 coin puzzle hash, null if this is P1 coin
; clawback_puzzle_hash          : Clawback Puzzle Hash, null if not clawback
; launcher_coin_announcement    : Expected coin announcement from the launcher coin, null if Clawback

Creating a tic tac toe coin

sequenceDiagram;
    actor A as Alice;
    actor B as Bob;
    participant a as Alice's Coin;
    participant b as Bob's Coin;
    participant s as Singleton Launcher
    participant t as Tic Tac Toe Coin;

    rect rgb(220, 220, 220);
    note over A,B: (1) PKs Exchanging;
    A-)B: Alice's PK;
    B-)A: Bob's PK;
    end;

    rect rgb(191, 223, 255);
    note over a,t: (4) Alice's and Bob's coin are spent and a singleton launcer is created and spent;
    A->>a: (2) Create Alice's Coin;
    activate a
    B->>b: (3) Create Bob's Coin;
    activate b
    a->>s: CREATE_COIN
    deactivate a
    deactivate b
    activate s
    s->>t: CREATE_COIN
    deactivate s
    end;
Loading
  1. Alice (P1) and Bob (P2) exchange their PKs.
  2. Alice creates her waiting room coin (Alice's coin) with her pk, bob's pk, agreed RETURN_AMOUNT and GAME_AMOUNT, and null for P1_PH.
  3. Bob creates his waiting room coin (Bob's coin) with Alice's pk, his pk, agreed RETURN_AMOUNT and GAME_AMOUNT, and calculated Alice's coin puzzle hash for P1_PH.
  4. Once two coins with Alice's and Bob's waiting room puzzles are created, Alice's and Bob's coin spends can be spent together in a spend bundle to create the tic tac toe singleton coin. Alice's coin creates an ephermeral launcher coin that creates the game coin. Bob's coin is burned.

Clawback

The waiting room puzzle for Alice allows the clawback after 100 blocks has passed if Bob has not created his waiting room coin. Or if Bob has created his coin, but Alice clawed back her XCH and didn't create a game.

sequenceDiagram;
    actor A as Alice;
    actor B as Bob;
    participant a as Alice's Coin;

    rect rgb(220, 220, 220);
    note over A,B: (1) PKs Exchanging;
    A-)B: Alice's PK;
    B-)A: Bob's PK;
    end;

    rect rgb(191, 223, 255);
    note over A,a: Bob doesn't create his coin, so Alice waits for 100 blocks and claw back her XCH
    A->>a: (2) Create Alice's Coin;
    activate a
    loop (3) Alice Waits for Bob to Create His Coin
        A->>B: Wait Until 100 Blocks Have Passed;
    end
    a->>A: (4) Alice Spends Her Coin To Claw back Her XCH;
    deactivate a
    end;
Loading
  1. Alice (P1) and Bob (P2) exchange their PKs.
  2. Alice creates her waiting room coin (Alice's coin) with her pk, bob's pk, agreed RETURN_AMOUNT and GAME_AMOUNT, and null for P1_PH.
  3. Alice waits for Bob to create his waiting room coin.
  4. After 100 blocks have passed, Alice can spend her waiting room coin to claw back her XCH.

Security

Alice's, Bob's, and the launcher coin have to be spent together in one transaction to create a singleton tic-tac-toe game coin.

flowchart TB
    classDef waiting_room fill:#87CEFA; 
    classDef coin_announcement fill:#FFA07A, stroke-dasharray: 5 5;
    classDef puzzle_announcement fill:#CD5C5C, stroke-dasharray: 5 5;
    subgraph Atomic Transaction
        a((Alice's)):::waiting_room-->|CREATE_PUZZLE_ANNOUNCEMENT|aca[/Alice's Puzzle Anouncement/]:::puzzle_announcement
        b((Bob's)):::waiting_room-->|ASSERT_PUZZLE_ANNOUNCEMENT|aca
        a==>|CREATE_COIN|l((Launcher))
        l-->|CREATE_COIN_ANNOUNCEMENT|lca[/Launcher Coin Anouncement/]:::coin_announcement
        a-->|ASSERT_COIN_ANNOUNCEMENT|lca
    end
    style t0 fill:#FFC0CB,stroke:#FF69B4,stroke-width:2px
    l==>|CREATE_COIN|t0((Tic-Tac-Toe 0))
Loading
  • When Alice's coin is spent, the launcher coin is created and spent in the same transaction. The launcher coin also creates the game coin and generates the coin announcement. Alice's coin then asserts the launcher coin announcement.
(list ASSERT_COIN_ANNOUNCEMENT launcher_coin_announcement)
  • Alice provides launcher_coin_announcement in a solution and sign it with her secret key.
alice_waiting_room_coin_spend = CoinSpend(
    alice_waiting_room_coin,
    alice_waiting_room_puzzle,
    Program.to([
        0, # null if not clawback
        launcher_coin_announcement
    ])
)
...
message: bytes = launcher_coin_announcement
sig_alice_spend: G2Element = AugSchemeMPL.sign(
    alice_sk,
    message
    + alice_waiting_room_coin.name()
    + DEFAULT_CONSTANTS.AGG_SIG_ME_ADDITIONAL_DATA
)
  • Alice's coin verifies the signature.
(list AGG_SIG_ME P1_PK launcher_coin_announcement)
  • Both Alice's and Bob's coins are curried in both players' PKs and agreed amounts which is also provided to the launcher coin as Key/Value. A tree hash of the launcher solution is launcher_announcement which will be asserted when all coins are spent.
  • Key/Value List for the launcher coin:
launcher_solution = Program.to(
    [
        singleton_puzzle.get_tree_hash(),
        game_amount,
        [
            ("game", "tic-tac-toe"), 
            ("p1_pk", alice_pk),
            ("p2_pk", bob_pk),
            ("return_amount", play_amount),
            ("game_amount", game_amount)
        ]
    ]
)

launcher_announcement = launcher_solution.get_tree_hash()
  • Bob's coin is curried with Alice's coin puzzle hash (P1_PH). Bob can calculate the P1_PH himself.
  • Bob's coin also asserts the puzzle announcement of the launcher coin announcement announced by Alice's coin.
; P2 asserts a puzzle announcement from P1
; We want to secure P2 spend without AGG_SIG_ME
(list ASSERT_PUZZLE_ANNOUNCEMENT (sha256 P1_PH launcher_coin_announcement))
            
  • In Clawback case, a player has to sign their clawback_puzzle_hash and the return amount with their secret key to claw back their XCH. The clawback case is valid only after 100 blocks have passed after the waiting room coin is created.
  (defconstant CLAWBACK_BLOCKS 100)
  ...
    (defun-inline clawback (RETURN_AMOUNT P1_PH clawback_puzzle_hash)
    (list 
        (list ASSERT_HEIGHT_RELATIVE CLAWBACK_BLOCKS) ; clawback condition valid after CLAWBACK_BLOCKS blocks have passed
        (list CREATE_COIN clawback_puzzle_hash RETURN_AMOUNT) ; return mojos to provided puzzle hash 
        (list 
            AGG_SIG_ME
            (if P1_PH
                P2_PK
                P1_PK ; null if this is P1 coin
            )
            (sha256 clawback_puzzle_hash RETURN_AMOUNT))
    )
)

Notebooks

References