Skip to content

Commit

Permalink
Frank workshop upgrades (#295)
Browse files Browse the repository at this point in the history
* update workshop auction tutorial

* add workshop basic_bank tutorial

* add workshop tictactoe tutorial

* add workshop vote tutorial

* add workshop token tutorial and images

* add workshop battleship tutorial

* small formatting changes

* update all tutorials to match new workshop READMEs, added steps, fixed how to run section

---------

Co-authored-by: collin <[email protected]>
  • Loading branch information
frank-aleo and collinc97 authored Oct 18, 2023
1 parent 3d58d31 commit 4b25baa
Show file tree
Hide file tree
Showing 10 changed files with 1,418 additions and 131 deletions.
196 changes: 65 additions & 131 deletions documentation/leo/08_auction.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,110 +20,70 @@ We make following assumptions about the auction:
Under this model, we require that:
- Bidders do not learn any information about the value of other bids.

### Auction Flow
## Auction Flow

The auction is conducted in a series of stages.
- **Bidding**: In the bidding stage, bidders submit bids to the auctioneer. They do so by invoking the `place_bid` function.
- **Resolution**: In the resolution stage, the auctioneer resolves the bids in the order they were received. The auctioneer does so by invoking the `resolve` function. The resolution process produces a single winning bid.
- **Finishing**: In this stage, the auctioneer finishes the auction by invoking the `finish` function. This function returns the winning bid to the bidder, which the bidder can then use to claim the item.


## Language Features and Concepts
- `record` declarations
- `assert_eq`
- record ownership

## Setup

### 1. Install Leo
Follow the [**Leo Installation Instructions**](./01_installation.md)

### 2. Download the auction example code
Clone the source code for the auction example from [Github](https://github.com/AleoHQ/workshop/tree/master/auction).

## How to Run

### <a id="accounts"></a> Generating Accounts
The `program.json` file contains a private key and address.
This is the account that will be used to sign transactions and is checked for record ownership.
When executing programs as different parties, be sure to set the `private_key` and `address` fields in `program.json` to the appropriate values.
See `./run.sh` for an example of how to run the program as different parties.

Go to [**aleo.tools**](https://aleo.tools) to generate new accounts.
Follow the [Leo Installation Instructions](https://developer.aleo.org/leo/installation).

The web interface is powered by the [Aleo SDK](https://github.com/AleoHQ/sdk) and can be run locally.
This auction program can be run using the following bash script. Locally, it will execute Leo program functions to conduct, bid, and close a three party auction.

### Using an input file.
1. Modify `inputs/auction.in` with the desired inputs.
2. Run
```bash
leo run <function_name>
cd auction
./run.sh
```

The `.env` file contains a private key and address. This is the account that will be used to sign transactions and is checked for record ownership. When executing programs as different parties, be sure to set the `private_key` field in `.env` to the appropriate value. You can check out how we've set things up in `./run.sh` for a full example of how to run the program as different parties.

## Walkthrough

* [Step 0: Initializing the Auction](#step0)
* [Step 1: The First Bid](#step1)
* [Step 2: The Second Bid](#step2)
* [Step 3: Select the Winner](#step3)




## <a id="step0"></a> Step 0: Initializing the Auction

You can use the provided accounts or [generate your own](#accounts)
The three parties we'll be emulating are as follows:

```markdown
Bidder 1:
Private Key APrivateKey1zkpG9Af9z5Ha4ejVyMCqVFXRKknSm8L1ELEwcc4htk9YhVK
Address aleo1yzlta2q5h8t0fqe0v6dyh9mtv4aggd53fgzr068jvplqhvqsnvzq7pj2ke

Bidder 2:
Private Key APrivateKey1zkpAFshdsj2EqQzXh5zHceDapFWVCwR6wMCJFfkLYRKupug
Address aleo1esqchvevwn7n5p84e735w4dtwt2hdtu4dpguwgwy94tsxm2p7qpqmlrta4

Auctioneer:
Private Key APrivateKey1zkp5wvamYgK3WCAdpBQxZqQX8XnuN2u11Y6QprZTriVwZVc
Address aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh
Bidder 1 Private Key:
APrivateKey1zkpG9Af9z5Ha4ejVyMCqVFXRKknSm8L1ELEwcc4htk9YhVK
Bidder 1 Address:
aleo1yzlta2q5h8t0fqe0v6dyh9mtv4aggd53fgzr068jvplqhvqsnvzq7pj2ke

Bidder 2 Private Key:
APrivateKey1zkpAFshdsj2EqQzXh5zHceDapFWVCwR6wMCJFfkLYRKupug
Bidder 2 Address:
aleo1esqchvevwn7n5p84e735w4dtwt2hdtu4dpguwgwy94tsxm2p7qpqmlrta4

Auctioneer Private Key:
APrivateKey1zkp5wvamYgK3WCAdpBQxZqQX8XnuN2u11Y6QprZTriVwZVc
Auctioneer Address:
aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh
```

Swap in the private key and address of the first bidder to program.json.

```jsonld
{
"program": "auction.aleo",
"version": "0.0.0",
"description": "A sealed bid auction",
"development": {
"private_key": "APrivateKey1zkpG9Af9z5Ha4ejVyMCqVFXRKknSm8L1ELEwcc4htk9YhVK",
"address": "aleo1yzlta2q5h8t0fqe0v6dyh9mtv4aggd53fgzr068jvplqhvqsnvzq7pj2ke"
},
"license": "MIT"
}
```
## <a id="step1"></a> Step 1: The First Bid

Have the first bidder place a bid of 10.

## <a id="step1"></a> Step 1: The First Bid
Swap in the private key and address of the first bidder to `.env`.

Have the first bidder place a bid of 10.

```javascript=19
// Returns a new bid.
// - `bidder` : The address of the account that placed the bid.
// - `amount` : The amount of the bid.
// Requires that `bidder` matches the function caller.
// The owner of the record is set to the entity responsible for running the auction (auction runner).
// The address of the auction runner is aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh.
transition place_bid(bidder: address, amount: u64) -> Bid {
// Ensure the caller is the auction bidder.
console.assert_eq(self.caller, bidder);
// Return a new 'Bid' record for the auction bidder.
return Bid {
owner: aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh,
bidder: bidder,
amount: amount,
is_winner: false,
};
}
```bash
echo "
NETWORK=testnet3
PRIVATE_KEY=APrivateKey1zkpG9Af9z5Ha4ejVyMCqVFXRKknSm8L1ELEwcc4htk9YhVK
" > .env
```

Call the `place_bid` program function with bidder 1 and `10u64` arguments.
Expand All @@ -136,8 +96,14 @@ leo run place_bid aleo1yzlta2q5h8t0fqe0v6dyh9mtv4aggd53fgzr068jvplqhvqsnvzq7pj2k

Have the second bidder place a bid of 90.

Swap in the private key of the second bidder to `.env`.

Swap in the private key and address of the second bidder to program.json.
```bash
echo "
NETWORK=testnet3
PRIVATE_KEY=APrivateKey1zkpAFshdsj2EqQzXh5zHceDapFWVCwR6wMCJFfkLYRKupug
" > .env
```

Call the `place_bid` program function with bidder 2 and `90u64` arguments.

Expand All @@ -149,77 +115,45 @@ leo run place_bid aleo1esqchvevwn7n5p84e735w4dtwt2hdtu4dpguwgwy94tsxm2p7qpqmlrta

Have the auctioneer select the winning bid.

```javascript=38
// Returns the winning bid.
// - `first` : The first bid.
// - `second` : The second bid.
// Requires that the function caller is the auction runner.
// Assumes that the function is invoked only after the bidding period has ended.
// In the event of a tie, the first bid is selected.
transition resolve(first: Bid, second: Bid) -> Bid {
// Ensure the caller is the auctioneer.
assert_eq(self.caller, aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh);
// Resolve the winner of the auction.
if (first.amount >= second.amount) {
return first;
} else {
return second;
}
}
```
Swap in the private key of the auctioneer to `.env`.

Swap in the private key and address of the auctioneer to program.json.
```bash
echo "
NETWORK=testnet3
PRIVATE_KEY=APrivateKey1zkp5wvamYgK3WCAdpBQxZqQX8XnuN2u11Y6QprZTriVwZVc
" > .env
```

Provide the two `Bid` records as input to the `resolve` transition function.

```bash
leo run resolve "{
owner: aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh.private,
bidder: aleo1yzlta2q5h8t0fqe0v6dyh9mtv4aggd53fgzr068jvplqhvqsnvzq7pj2ke.private,
amount: 10u64.private,
is_winner: false.private,
_nonce: 4668394794828730542675887906815309351994017139223602571716627453741502624516group.public
}" "{
owner: aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh.private,
bidder: aleo1esqchvevwn7n5p84e735w4dtwt2hdtu4dpguwgwy94tsxm2p7qpqmlrta4.private,
amount: 90u64.private,
is_winner: false.private,
_nonce: 5952811863753971450641238938606857357746712138665944763541786901326522216736group.public
}"
owner: aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh.private,
bidder: aleo1yzlta2q5h8t0fqe0v6dyh9mtv4aggd53fgzr068jvplqhvqsnvzq7pj2ke.private,
amount: 10u64.private,
is_winner: false.private,
_nonce: 4668394794828730542675887906815309351994017139223602571716627453741502624516group.public
}" "{
owner: aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh.private,
bidder: aleo1esqchvevwn7n5p84e735w4dtwt2hdtu4dpguwgwy94tsxm2p7qpqmlrta4.private,
amount: 90u64.private,
is_winner: false.private,
_nonce: 5952811863753971450641238938606857357746712138665944763541786901326522216736group.public
}"
```

## <a id="step4"></a> Step 4: Finish the Auction

Have the auctioneer finish the auction.

```javascript=55
// Returns ownership of the bid to bidder.
// - `bid` : The winning bid.
// Requires that the function caller is the auction runner.
// Assumes that the function is invoked only after all bids have been resolved.
transition finish(bid: Bid) -> Bid {
// Ensure the caller is the auctioneer.
console.assert_eq(self.caller, aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh);
// Return 'is_winner' as 'true' in the winning 'Bid'.
return Bid {
owner: bid.bidder,
bidder: bid.bidder,
amount: bid.amount,
is_winner: true,
};
}
```

Call the `finish` transition function with the winning `Bid` record.

```bash
leo run finish "{
owner: aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh.private,
bidder: aleo1esqchvevwn7n5p84e735w4dtwt2hdtu4dpguwgwy94tsxm2p7qpqmlrta4.private,
amount: 90u64.private,
is_winner: false.private,
_nonce: 5952811863753971450641238938606857357746712138665944763541786901326522216736group.public
}"
owner: aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh.private,
bidder: aleo1esqchvevwn7n5p84e735w4dtwt2hdtu4dpguwgwy94tsxm2p7qpqmlrta4.private,
amount: 90u64.private,
is_winner: false.private,
_nonce: 5952811863753971450641238938606857357746712138665944763541786901326522216736group.public
}"
```


Congratulations! You've run a private auction. We recommend going to [aleo.tools](https://aleo.tools) to generate new accounts and trying the same commands with those addresses.
114 changes: 114 additions & 0 deletions documentation/leo/10_basic_bank.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
## Summary

This program implements a bank that issues tokens to users and allows users to deposit tokens to accrue simple interest on their deposits.

### User Flow
1. The bank issues users tokens via the `issue` function.
2. A user deposits tokens via the `deposit` function.
3. Upon a user's request to withdraw, the bank calculates the appropriate amount of compound interest and pays the user the principal and interest via the `withdraw` function.

Note that the program can be easily extended to include addition features such as a `transfer` function, which would allow users to transfer tokens to other users.

## Bugs

You may have already guessed that this program has a few bugs. We list some of them below:
- `withdraw` can only be invoked by the bank. A malicious bank could lock users' tokens by not invoking `withdraw`.
- `withdraw` fails if the sum of the interest and principal is greater than the user's balance.
- User's can increase their principal by depositing tokens multiple times, including immediately before withdrawl.
- Integer division rounds down; if the calculated interest is too small, then it will be rounded down to zero.

Can you find any others?

## Language Features and Concepts
- `record` declarations
- `assert_eq`
- core functions, e.g. `BHP256::hash`
- record ownership
- loops and bounded iteration
- mappings
- finalize

## How to Run

Follow the [Leo Installation Instructions](https://developer.aleo.org/leo/installation).

This basic bank program can be run using the following bash script. Locally, it will execute Leo program functions to issue, deposit, and withdraw tokens between a bank and a user.

```bash
cd basic_bank
./run.sh
```

The `.env` file contains a private key and address. This is the account that will be used to sign transactions and is checked for record ownership. When executing programs as different parties, be sure to set the `private_key` field in `.env` to the appropriate value. You can check out how we've set things up in `./run.sh` for a full example of how to run the program as different parties.

## Walkthrough

* [Step 0: Issue Tokens](#issue)
* [Step 1: Deposit Tokens](#deposit)
* [Step 2: Wait](#wait)
* [Step 3: Withdraw Tokens](#withdraw)

## <a id="issue"></a> Issue Tokens

We will be playing the role of two parties.

```bash
The private key and address of the bank.
private_key: APrivateKey1zkpHtqVWT6fSHgUMNxsuVf7eaR6id2cj7TieKY1Z8CP5rCD
address: aleo1t0uer3jgtsgmx5tq6x6f9ecu8tr57rzzfnc2dgmcqldceal0ls9qf6st7a

The private key and address of the user.
private_key: APrivateKey1zkp75cpr5NNQpVWc5mfsD9Uf2wg6XvHknf82iwB636q3rtc
address: aleo1zeklp6dd8e764spe74xez6f8w27dlua3w7hl4z2uln03re52egpsv46ngg
```

Let's make some bank transactions. We'll take the role of the bank and issue 100 tokens to the user. We swap the private key into `.env` and run the `issue` transition function. The inputs are simply the recipient of the issuance and the amount.

```bash
echo "
NETWORK=testnet3
PRIVATE_KEY=APrivateKey1zkpHtqVWT6fSHgUMNxsuVf7eaR6id2cj7TieKY1Z8CP5rCD
" > .env

leo run issue aleo1zeklp6dd8e764spe74xez6f8w27dlua3w7hl4z2uln03re52egpsv46ngg 100u64
```

## <a id="deposit"></a> Deposit Tokens

Now, let's have the user deposit 50 of their tokens with the bank. We'll take the role of the user and call the deposit function, having the user use the output record that was issued to them by the bank. The inputs are the output record from the `issue` transition and the amount the user wishes to deposit.

```bash
echo "
NETWORK=testnet3
PRIVATE_KEY=APrivateKey1zkp75cpr5NNQpVWc5mfsD9Uf2wg6XvHknf82iwB636q3rtc
" > .env

leo run deposit "{
owner: aleo1zeklp6dd8e764spe74xez6f8w27dlua3w7hl4z2uln03re52egpsv46ngg.private,
amount: 100u64.private,
_nonce: 4668394794828730542675887906815309351994017139223602571716627453741502624516group.public
}" 50u64
```

You'll see that the output contains a new private record belonging to the user with 50 credits, and a finalize `deposit` function taking the arguments (bank address, amount) that will update a public mapping with 50 credits. This information is queryable on-chain.

## <a id="wait"></a> Wait

With the 50 token deposit, let's say 15 periods of time pass with compounding interest at a rate of 12.34% on the principal amount.

You can run the calculation yourself, it comes out to 266 tokens accrued using those numbers.

## <a id="withdraw"></a> Withdraw Tokens

Now, let's have the bank withdraw all tokens after 15 periods. Let's switch to the bank role, and call the `withdraw` transition function. The inputs are the recipient's address, amount, rate, and periods.

```bash
echo "
NETWORK=testnet3
PRIVATE_KEY=APrivateKey1zkpHtqVWT6fSHgUMNxsuVf7eaR6id2cj7TieKY1Z8CP5rCD
" > .env

leo run withdraw aleo1zeklp6dd8e764spe74xez6f8w27dlua3w7hl4z2uln03re52egpsv46ngg 50u64 1234u64 15u64
```

You'll see here the withdrawal function creates a new private record for the user containing all 266 withdrawn tokens, and then calls the finalize `withdraw` function with arguments (address, amount), which will update the public balance of the bank back to 0. The public mapping will be queryable on-chain.
Loading

0 comments on commit 4b25baa

Please sign in to comment.