Playing with the XO Transaction Family¶
XO is an example transaction family that implements the game tic-tac-toe, also known as Noughts and Crosses or X’s and O’s. We chose XO as an example transaction family for Sawtooth because of its simplicity, global player base, and straightforward implementation as a computer program. This transaction family demonstrates the functionality of Sawtooth; in addition, the code that implements it serves as a reference for building other transaction processors.
This section introduces the concepts of a Sawtooth transaction family with XO,
summarizes XO game rules, and describes how use the
xo client application
to play a game of tic-tac-toe on the blockchain.
About the XO Transaction Family¶
The XO transaction family defines the data model and business logic for playing tic-tac-toe on the blockchain by submitting transactions for create, take, and delete actions. For more information, see XO Transaction Family
The XO transaction family includes:
Transaction processors in several languages, including Go (
xo-tp-python). These transaction processors implement the business logic of XO game play.
xoclient: A set of commands that provide a command-line interface for playing XO. The
xoclient handles the construction and submission of transactions. For more information, see xo.
In tic-tac-toe, two players take turns marking spaces on a 3x3 grid.
The first player (player 1) marks spaces with an X. Player 1 always makes the first move.
The second player (player 2) marks spaces with an O.
A player wins the game by marking three adjoining spaces in a horizontal, vertical, or diagonal row.
The game is a tie if all nine spaces on the grid have been marked, but no player has won.
Playing XO with the xo Client¶
This procedure introduces you to the XO transaction family by playing a game
xo client. Each
xo command is a transaction that the client
submits to the validator via the REST API.
A working Sawtooth node, as described in Setting Up a Sawtooth Node for Testing. This node must be running a validator, a REST API, a consensus engine, and the Settings transaction processor. (The IntegerKey transaction processor is not used in this procedure.)
This procedure also requires the XO transaction processor. The Docker and Kubernetes procedures start it automatically. For Ubuntu, this procedure shows how to start the XO transaction processor if necessary.
Step 1: Connect to the Sawtooth Node¶
To connect to the Sawtooth node, use the steps for your platform:
Step 2: Confirm Connectivity to the REST API¶
Verify that you can connect to the REST API. The step will help determine if
The REST API is at the default location (
xo client sends requests to update and query the blockchain to the
URL of the REST API (by default,
If the REST API’s URL is not
http://127.0.0.1:8008, you must add the
--url argument to each
xo command in this procedure.
In the Docker environment, the REST API is at
http://rest-api:8008. You must add
--url http://rest-api:8008to all
xocommands in this procedure. For example:
$ xo create my-game --username jack --url http://rest-api:8008
Kubernetes: See Step 6: Confirm Connectivity to the REST API (for Kubernetes)
Step 3. Ubuntu only: Start the XO Transaction Processor¶
For Ubuntu: If the XO transaction processor is not running on your Sawtooth node, start it now.
Open a new terminal window (the xo window).
Check whether the XO transaction processor is running.
user@xo$ ps aux | grep [x]o-tp root 1546 0.0 0.1 52700 3776 pts/2 S+ 19:15 0:00 sudo -u sawtooth xo-tp-python -v sawtooth 1547 0.0 1.5 277784 31192 pts/2 Sl+ 19:15 0:00 /usr/bin/python3 /usr/bin/xo-tp-python -v
If the output does not show that
/usr/bin/xo-tp-pythonis running, start the XO transaction processor with the following command:
user@xo$ sudo -u sawtooth xo-tp-python -v
For more information, see Step 8: Start the Transaction Processors.
Step 4. Create Players¶
Create keys for two players to play the game:
$ sawtooth keygen jack writing file: /home/ubuntu/.sawtooth/keys/jack.priv writing file: /home/ubuntu/.sawtooth/keys/jack.addr $ sawtooth keygen jill writing file: /home/ubuntu/.sawtooth/keys/jill.priv writing file: /home/ubuntu/.sawtooth/keys/jill.addr
The output may differ slightly from this example.
Step 5. Create a Game¶
Create a game named
my-game with the following command:
$ xo create my-game --username jack
--username argument is required for
xo create and
so that a single player (you) can play as two players. By default,
<username> is the Linux user name of the person playing the game.
Verify that the
create transaction was committed by displaying the list of
$ xo list GAME PLAYER 1 PLAYER 2 BOARD STATE my-game --------- P1-NEXT
xo list command is a wrapper that provides a quick way to show game
state rather than using
curl with the REST API’s URL to request state.
Step 6. Take a Space as Player 1¶
The first player to issue an
xo take command to a newly created game is
PLAYER 1 . The second player to issue a
take command is
recorded by username as
--username argument determines where the
xo client should look
for the player’s key to sign the transaction. By default, if you’re logged in
xo would look for the key file named
~/.sawtooth/keys/root.priv. Instead, the following command specifies
xo should use the key file
Start playing tic-tac-toe by taking a space as the first player, Jack. In this example, Jack takes space 5:
$ xo take my-game 5 --username jack
This diagram shows the number of each space.
1 | 2 | 3 ---|---|--- 4 | 5 | 6 ---|---|--- 7 | 8 | 9
What Happens During a Game Move?
xo command is a transaction. A successful transaction updates global
state with the game name, board state, game state, and player keys, using
Each time a player attempts to take a space, the transaction processor will verify that their username matches the name of the player whose turn it is. This ensures that no player is able to mark a space out of turn.
After each turn, the XO transaction processor scans the board state for a
win or tie. If either condition occurs, no more
take actions are allowed
on the finished game.
Step 7. Take a Space as Player 2¶
Next, take a space on the board as player 2, Jill. In this example, Jill takes space 1:
$ xo take my-game 1 --username jill
Step 8. Show the Current Game Board¶
Whenever you want to see the current state of the game board, enter the following command:
$ xo show my-game
The output includes the game name, the first six characters of each player’s
public key, the game state, and the current board state. This example shows the
P1-NEXT (player 1 has the next turn) and a board with Jack’s X in
space 5 and Jill’s O in space 1.
GAME: : my-game PLAYER 1 : 02403a PLAYER 2 : 03729b STATE : P1-NEXT O | | ---|---|--- | X | ---|---|--- | |
xo client formats the global state data so that it’s easier to read
than the state returned to the transaction processor:
Step 9. Continue the Game¶
Players take turns using
xo take my-game <space> to mark spaces on the grid.
You can continue the game until one of the players wins or the game ends in a tie, as in this example:
$ xo show my-game GAME: : my-game PLAYER 1 : 02403a PLAYER 2 : 03729b STATE : TIE O | X | O ---|---|--- X | X | O ---|---|--- X | O | X
Step 10. Delete the Game¶
Either player can use the
xo delete command to remove the game data from
$ xo delete my-game
Using Authentication with the xo Client¶
The XO client supports optional authentication. If the REST API is connected
to an authentication proxy, you can point the XO client at it with the
argument. You must also specify your authentication information using the
--auth-user [user] and
--auth-password [password] options for each
Note that the value of the
--auth-user argument is not the
same username that is entered with the