Merge pull request #2076 from AleoHQ/example/auction

Update auction example.
This commit is contained in:
Collin Chin 2022-09-20 10:39:58 -07:00 committed by GitHub
commit 7501130e52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 213 additions and 63 deletions

View File

@ -1,7 +1,12 @@
# Build and run the auction Leo program.
(
cd ./project/examples/auction || exit
$LEO run main
$LEO run place_bid
$LEO run resolve
$LEO run finish
chmod +x ./run.sh
./run.sh
)
# Build and run the broken_bank Leo program.

View File

@ -1,11 +1,42 @@
// The program input for auction/src/main.leo
[main]
current: Auction = Auction {
[place_bid]
// Note that `bidder` must have the same address as the caller (refer to `program.json`).
// Swapping the below lines, will result in an error.
// bidder: address = aleo1y7065c2jxkra5yzu9jfxq55klweqev0zas89lt9nxmfrqrafmq9qw2ktdg;
bidder: address = aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh;
amount: u64 = 90u64;
[resolve]
first: Bid = Bid {
owner: aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh,
gates: 0u64,
winning_bidder: aleo1mgfq6g40l6zkhsm063n3uhr43qk5e0zsua5aszeq5080dsvlcvxsn0rrau,
winning_bid: 50u64,
_nonce: 0group
bidder: aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh,
amount: 10u64,
is_winner: false,
_nonce: 6480683131255842390406647532838179519970794442201387718334686863304493823461group,
};
bidder: address = aleo1ht2a9q0gsd38j0se4t9lsfulxgqrens2vgzgry3pkvs93xrrzu8s892zn7;
bid: u64 = 100u64;
second: Bid = Bid {
owner: aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh,
gates: 0u64,
bidder: aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh,
amount: 90u64,
is_winner: false,
_nonce: 1635474322959998727812727786860193861506102794050195384593971440884677453921group,
};
[finish]
bid: Bid = Bid {
owner: aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh,
gates: 0u64,
bidder: aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh,
amount: 90u64,
is_winner: false,
_nonce: 4195536711021629817871261453343069023119119274215827022954896024118351555272group,
};

115
examples/auction/run.sh Executable file
View File

@ -0,0 +1,115 @@
#!/bin/bash
# First check that Leo is installed.
if ! command -v leo &> /dev/null
then
echo "leo is not installed."
exit
fi
# The private key and address of the first bidder.
# Swap these into program.json, when running transactions as the first bidder.
# "private_key": "APrivateKey1zkpG9Af9z5Ha4ejVyMCqVFXRKknSm8L1ELEwcc4htk9YhVK"
# "address": aleo1yzlta2q5h8t0fqe0v6dyh9mtv4aggd53fgzr068jvplqhvqsnvzq7pj2ke
# The private key and address of the second bidder.
# Swap these into program.json, when running transactions as the second bidder.
# "private_key": "APrivateKey1zkpAFshdsj2EqQzXh5zHceDapFWVCwR6wMCJFfkLYRKupug"
# "address": aleo1esqchvevwn7n5p84e735w4dtwt2hdtu4dpguwgwy94tsxm2p7qpqmlrta4
# The private key and address of the auctioneer.
# Swap these into program.json, when running transactions as the auctioneer.
# "private_key": "APrivateKey1zkp5wvamYgK3WCAdpBQxZqQX8XnuN2u11Y6QprZTriVwZVc",
# "address": "aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh"
# Swap in the private key and address of the first bidder to program.json.
echo "{
\"program\": \"auction.aleo\",
\"version\": \"0.0.0\",
\"description\": \"\",
\"development\": {
\"private_key\": \"APrivateKey1zkpG9Af9z5Ha4ejVyMCqVFXRKknSm8L1ELEwcc4htk9YhVK\",
\"address\": \"aleo1yzlta2q5h8t0fqe0v6dyh9mtv4aggd53fgzr068jvplqhvqsnvzq7pj2ke\"
},
\"license\": \"MIT\"
}" > program.json
# Have the first bidder place a bid of 10.
echo "
The first bidder is placing a bid of 10."
leo run place_bid aleo1yzlta2q5h8t0fqe0v6dyh9mtv4aggd53fgzr068jvplqhvqsnvzq7pj2ke 10u64
# Swap in the private key and address of the second bidder to program.json.
echo "{
\"program\": \"auction.aleo\",
\"version\": \"0.0.0\",
\"description\": \"\",
\"development\": {
\"private_key\": \"APrivateKey1zkpAFshdsj2EqQzXh5zHceDapFWVCwR6wMCJFfkLYRKupug\",
\"address\": \"aleo1esqchvevwn7n5p84e735w4dtwt2hdtu4dpguwgwy94tsxm2p7qpqmlrta4\"
},
\"license\": \"MIT\"
}" > program.json
# Have the second bidder place a bid of 90.
echo "
The second bidder is placing a bid of 90."
leo run place_bid aleo1esqchvevwn7n5p84e735w4dtwt2hdtu4dpguwgwy94tsxm2p7qpqmlrta4 90u64
# Swap in the private key and address of the auctioneer to program.json.
echo "{
\"program\": \"auction.aleo\",
\"version\": \"0.0.0\",
\"description\": \"\",
\"development\": {
\"private_key\": \"APrivateKey1zkp5wvamYgK3WCAdpBQxZqQX8XnuN2u11Y6QprZTriVwZVc\",
\"address\": \"aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh\"
},
\"license\": \"MIT\"
}" > program.json
# Have the auctioneer select the winning bid.
echo "
The auctioneer is selecting the winning bid."
leo run resolve "{
owner: aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh.private,
gates: 0u64.private,
bidder: aleo1yzlta2q5h8t0fqe0v6dyh9mtv4aggd53fgzr068jvplqhvqsnvzq7pj2ke.private,
amount: 10u64.private,
is_winner: false.private,
_nonce: 4668394794828730542675887906815309351994017139223602571716627453741502624516group.public
}" "{
owner: aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh.private,
gates: 0u64.private,
bidder: aleo1esqchvevwn7n5p84e735w4dtwt2hdtu4dpguwgwy94tsxm2p7qpqmlrta4.private,
amount: 90u64.private,
is_winner: false.private,
_nonce: 5952811863753971450641238938606857357746712138665944763541786901326522216736group.public
}"
# Have the auctioneer finish the auction.
echo "
The auctioneer is finishing the auction."
leo run finish "{
owner: aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh.private,
gates: 0u64.private,
bidder: aleo1esqchvevwn7n5p84e735w4dtwt2hdtu4dpguwgwy94tsxm2p7qpqmlrta4.private,
amount: 90u64.private,
is_winner: false.private,
_nonce: 5952811863753971450641238938606857357746712138665944763541786901326522216736group.public
}"

View File

@ -1,54 +1,53 @@
// This example is suggestive of an auction smart contract,
// but it is much simpler of a full auction smart contract.
// This is a record that contains the current state of the auction,
// which in this example just consists of
// the address of the currently winning bidder
// and the currently winning amount.
// The owner and gates fields are required in a record;
// the owner address in general differs from the current auction winner:
// the owner is the one running the auction itself.
record Auction {
// This record defines a bid in the auction.
record Bid {
owner: address,
gates: u64,
winning_bidder: address,
winning_bid: u64
bidder: address,
amount: u64,
is_winner: bool,
}
// This function realizes the checking and possible incorporation of a new bid.
// Unlike a traditional auction, where the currently winning bid is known,
// and only higher bids would be normally brought up in the room,
// in a zero-knowledge context presumably bidding is blind,
// i.e. a bidder does not know the currently highest bid.
// Thus, this function represents a possible update of the auction state
// with a new bid:
// if the amount exceeds the currently winning one,
// the record is updated with the new bid and the new bidder's address;
// the latter is also passed as input.
// Again, this is just a simple example;
// in a serious auction smart contract,
// there will be some additional checks,
// and presumably ways to tie bidder and amount (e.g. commitments).
//
// In order to run this function, an Auction record must be passed to it.
// This is done in the input file, inputs/auction.in.
// Note that, when building that record,
// the owner address must be the same as the one in the program.json file.
// This function creates a new bid.
// This function checks that `bidder` invoked the function.
// Note that the owner of the record is set to the entity responsible for running the auction.
// The entity's address is aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh.
// This is necessary to allow the entity running the auction to process bids.
@program
function main(current: Auction, bidder: address, bid: u64) -> Auction {
let winning_bidder: address = current.winning_bidder;
let winning_bid: u64 = current.winning_bid;
if bid > current.winning_bid {
winning_bidder = bidder;
winning_bid = bid;
}
let new: Auction = Auction {
owner: current.owner,
gates: current.gates,
winning_bidder: winning_bidder,
winning_bid: winning_bid
function place_bid(bidder: address, amount: u64) -> Bid {
console.assert_eq(self.caller, bidder);
return Bid {
owner: aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh,
gates: 0u64,
bidder: bidder,
amount: amount,
is_winner: false,
};
}
// This function consumes two bids, selecting the winning one. In the event of a tie, the first bid is selected.
// This function should be invoked once the bidding period has ended.
// This function can only be called by the entity running the auction.
@program
function resolve(first: Bid, second: Bid) -> Bid {
console.assert_eq(self.caller, aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh);
if (first.amount >= second.amount) {
return first;
} else {
return second;
}
}
// This function returns ownership of the `Bid` record to the original bidder.
// This function should be called after all bids have been resolved.
// This function can only be called by the entity running the auction.
@program
function finish(bid: Bid) -> Bid {
console.assert_eq(self.caller, aleo1fxs9s0w97lmkwlcmgn0z3nuxufdee5yck9wqrs0umevp7qs0sg9q5xxxzh);
return Bid {
owner: bid.bidder,
gates: bid.gates,
bidder: bid.bidder,
amount: bid.amount,
is_winner: true,
};
return new;
}