This commit is contained in:
Pranav Gaddamadugu 2022-09-20 19:20:22 -07:00
parent 91a2137136
commit 975677f832
8 changed files with 133 additions and 15 deletions

View File

@ -40,13 +40,14 @@ Users may either specify input values via the command line or provide an input f
The `program.json` file contains a private key and address. 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. 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. 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. See `./run.sh` for an example of how to run the program as different parties.
The [Aleo SDK](https://github.com/AleoHQ/leo/tree/testnet3) provides a command line interface for generating new accounts. The [Aleo SDK](https://github.com/AleoHQ/leo/tree/testnet3) provides a command line interface for generating new accounts.
To generate a new account, run To generate a new account, run
``` ```
leo account new aleo account new
``` ```
@ -64,3 +65,9 @@ See `./run.sh` for an example.
```bash ```bash
leo run <function_name> leo run <function_name>
``` ```
For example,
```bash
leo run place_bid
leo run resolve
leo run finish
```

View File

@ -1,8 +1,83 @@
# bank.aleo # Blind Auction
## Build Guide A "broken" bank written in Leo.
To compile this Aleo program, run: ## Summary
```bash
aleo build A first-price sealed-bid auction (or blind auction) is a type of auction in which each participant submits a bid without knowing the bids of the other participants.
The bidder with the highest bid wins the auction.
In this model, there are two parties: the auctioneer and the bidders.
- **Bidder**: A participant in the auction.
- **Auctioneer**: The party responsible for conducting the auction.
We make following assumptions about the auction:
- The auctioneer is honest. That is, the auctioneer will resolve **all** bids in the order they are received. The auctioneer will not tamper with the bids.
- There is no limit to the number of bids.
- The auctioneer knows the identity of all bidders, but bidders do not necessarily know the identity of other bidders.
Under this model, we require that:
- Bidders do not learn any information about the value of other bids.
### 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.
## Vulnerabilities
You may have already guessed that this program has a few vulnerabilities. Can you find them?
## Language Features and Concepts
- `record` declarations
- `console.assert_eq`
- core functions, e.g. `BHP256::hash`
- record ownership
- loops and bounded iteration
- mappings
- finalize
## Running the Program
Leo provides users with a command line interface for compiling and running Leo programs.
Users may either specify input values via the command line or provide an input file in `inputs/`.
### Configuring 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.
The [Aleo SDK](https://github.com/AleoHQ/leo/tree/testnet3) provides a command line interface for generating new accounts.
To generate a new account, run
```
leo account new
```
### Providing inputs via the command line.
1. Run
```bash
leo run <function_name> <input_1> <input_2> ...
```
See `./run.sh` for an example.
### Using an input file.
1. Modify `inputs/auction.in` with the desired inputs.
2. Run
```bash
leo run <function_name>
```
For example,
```bash
leo run issue
leo run deposit
leo run withdraw
``` ```

View File

@ -1,8 +1,9 @@
// The program input for broken_bank/src/main.leo // Inputs for the `issue` function.
[issue] [issue]
owner: address = aleo1t0uer3jgtsgmx5tq6x6f9ecu8tr57rzzfnc2dgmcqldceal0ls9qf6st7a; owner: address = aleo1t0uer3jgtsgmx5tq6x6f9ecu8tr57rzzfnc2dgmcqldceal0ls9qf6st7a;
amount: u64 = 1234u64; amount: u64 = 1234u64;
// Inputs for the `deposit` function.
[deposit] [deposit]
token: Token = Token { token: Token = Token {
owner: aleo1t0uer3jgtsgmx5tq6x6f9ecu8tr57rzzfnc2dgmcqldceal0ls9qf6st7a, owner: aleo1t0uer3jgtsgmx5tq6x6f9ecu8tr57rzzfnc2dgmcqldceal0ls9qf6st7a,
@ -12,6 +13,7 @@ token: Token = Token {
}; };
amount: u64 = 321u64; amount: u64 = 321u64;
// Inputs for the `withdraw` function.
[withdraw] [withdraw]
recipient: address = aleo1t0uer3jgtsgmx5tq6x6f9ecu8tr57rzzfnc2dgmcqldceal0ls9qf6st7a; recipient: address = aleo1t0uer3jgtsgmx5tq6x6f9ecu8tr57rzzfnc2dgmcqldceal0ls9qf6st7a;
amount: u64 = 321u64; amount: u64 = 321u64;

View File

@ -1,5 +1,5 @@
{ {
"program": "bank.aleo", "program": "broken_bank.aleo",
"version": "0.0.0", "version": "0.0.0",
"description": "", "description": "",
"development": { "development": {

View File

@ -18,7 +18,7 @@ fi
# Swap in the private key and address of the bank to program.json. # Swap in the private key and address of the bank to program.json.
echo "{ echo "{
\"program\": \"bank.aleo\", \"program\": \"broken_bank.aleo\",
\"version\": \"0.0.0\", \"version\": \"0.0.0\",
\"description\": \"\", \"description\": \"\",
\"development\": { \"development\": {
@ -37,7 +37,7 @@ leo run issue aleo1zeklp6dd8e764spe74xez6f8w27dlua3w7hl4z2uln03re52egpsv46ngg 10
# Swap in the private key and address of the user to program.json. # Swap in the private key and address of the user to program.json.
echo "{ echo "{
\"program\": \"bank.aleo\", \"program\": \"broken_bank.aleo\",
\"version\": \"0.0.0\", \"version\": \"0.0.0\",
\"description\": \"\", \"description\": \"\",
\"development\": { \"development\": {
@ -61,7 +61,7 @@ leo run deposit "{
# Swap in the private key and address of the bank to program.json. # Swap in the private key and address of the bank to program.json.
echo "{ echo "{
\"program\": \"bank.aleo\", \"program\": \"broken_bank.aleo\",
\"version\": \"0.0.0\", \"version\": \"0.0.0\",
\"description\": \"\", \"description\": \"\",
\"development\": { \"development\": {

View File

@ -1,11 +1,22 @@
// A token, issued by a bank.
// - 'owner' : The address of the account that owns the record associated with this token.
// - 'gates' : The value associated with the record (always zero).
// - 'amount' : The amount of tokens owned by the account.
record Token { record Token {
owner: address, owner: address,
gates: u64, gates: u64,
amount: u64, amount: u64,
} }
// An on-chain mapping, storing the amount of tokens owned by each account
// The account is stored as a to preserve user privacy.
mapping balances: field => u64; mapping balances: field => u64;
// Returns a new Token.
// - `owner` : The address of the account to issue the token to.
// - `amount`: The amount of tokens to issue.
// Requires that the function caller is the bank.
// The bank's address is aleo1t0uer3jgtsgmx5tq6x6f9ecu8tr57rzzfnc2dgmcqldceal0ls9qf6st7a.
@program @program
function issue(owner: address, amount: u64) -> Token { function issue(owner: address, amount: u64) -> Token {
console.assert_eq(self.caller, aleo1t0uer3jgtsgmx5tq6x6f9ecu8tr57rzzfnc2dgmcqldceal0ls9qf6st7a); console.assert_eq(self.caller, aleo1t0uer3jgtsgmx5tq6x6f9ecu8tr57rzzfnc2dgmcqldceal0ls9qf6st7a);
@ -16,6 +27,10 @@ function issue(owner: address, amount: u64) -> Token {
}; };
} }
// Deposits some amount of money into the bank.
// Returns a new Token with the remaining amount of money.
// - `token` : A record containing tokens to deposit.
// - `amount`: The amount of tokens to deposit.
@program @program
function deposit(token: Token, amount: u64) -> Token { function deposit(token: Token, amount: u64) -> Token {
let difference: u64 = token.amount - amount; let difference: u64 = token.amount - amount;
@ -26,6 +41,7 @@ function deposit(token: Token, amount: u64) -> Token {
amount: difference, amount: difference,
}; };
// Compute the hash of the token owner.
let hash: field = BHP256::hash(token.owner); let hash: field = BHP256::hash(token.owner);
finalize(hash, amount); finalize(hash, amount);
@ -33,10 +49,19 @@ function deposit(token: Token, amount: u64) -> Token {
return remaining; return remaining;
} }
// Updates on-chain state by the amount of tokens deposited.
// - `hash` : The hash of the token owner.
// - `amount`: The amount of tokens that were deposited.
finalize deposit(hash: field, amount: u64) { finalize deposit(hash: field, amount: u64) {
increment(balances, hash, amount); increment(balances, hash, amount);
} }
// Returns a new Token containing the amount of money withdrawn.
// - `recipient`: The address of the account to withdraw the tokens to.
// - `amount` : The amount of tokens to withdraw.
// - `rate` : The compound interest rate.
// - `periods` : The number of periods to compound the interest over.
// Requires that the function caller is the bank.
@program @program
function withdraw(recipient: address, amount: u64, rate: u64, periods: u64) -> Token { function withdraw(recipient: address, amount: u64, rate: u64, periods: u64) -> Token {
console.assert_eq(self.caller, aleo1t0uer3jgtsgmx5tq6x6f9ecu8tr57rzzfnc2dgmcqldceal0ls9qf6st7a); console.assert_eq(self.caller, aleo1t0uer3jgtsgmx5tq6x6f9ecu8tr57rzzfnc2dgmcqldceal0ls9qf6st7a);
@ -55,10 +80,17 @@ function withdraw(recipient: address, amount: u64, rate: u64, periods: u64) -> T
return token; return token;
} }
// Updates on-chain state by the amount of tokens withdrawn.
// - `hash` : The hash of the token owner.
// - `amount`: The amount of tokens that were withdrawn.
finalize withdraw(hash: field, amount: u64) { finalize withdraw(hash: field, amount: u64) {
decrement(balances, hash, amount); decrement(balances, hash, amount);
} }
// Returns the total amount of tokens after compounding interest.
// - `principal`: The amount of tokens to compound interest over.
// - `rate` : The compound interest rate.
// - `periods` : The number of periods to compound the interest over.
function calculate_interest(principal: u64, rate: u64, periods: u64) -> u64 { function calculate_interest(principal: u64, rate: u64, periods: u64) -> u64 {
let amount: u64 = principal; let amount: u64 = principal;

View File

@ -31,3 +31,9 @@ See `./run.sh` for an example.
```bash ```bash
leo run <function_name> leo run <function_name>
``` ```
For example,
```bash
leo run new
leo run make_move
```

View File

@ -2,10 +2,6 @@
[new] [new]
// Inputs for the `make_move` function. // Inputs for the `make_move` function.
// - `player` : A u8 representing the player making the move. 1 for player 1, 2 for player 2.
// - `row` : A u8 representing the row to make the move in.
// - `column` : A u8 representing the column to make the move in.
// - `board` : A representation of the board state.
[make_move] [make_move]
player: u8 = 1u8; player: u8 = 1u8;
row: u8 = 1u8; row: u8 = 1u8;