More examples

This commit is contained in:
Pranav Gaddamadugu 2022-10-06 00:17:51 -07:00
parent e1a148a93e
commit d7813923d2
18 changed files with 693 additions and 660 deletions

View File

@ -416,7 +416,6 @@ impl ParserContext<'_> {
/// and function definition.
fn parse_function(&mut self) -> Result<(Identifier, Function)> {
// TODO: Handle dangling annotations.
// TODO: Handle duplicate annotations.
// Parse annotations, if they exist.
let mut annotations = Vec::new();
while self.look_ahead(0, |t| &t.token) == &Token::At {

View File

@ -1,10 +1,13 @@
// This function takes as input a field `a` and calls several core functions.
// Core functions are built-in to the Leo language and call handwritten, optimized circuits in the AVM.
// To call a core function, use the correct capitalized identifier followed by two colons
// and then the function name. Example: `Pedersen64::hash()`.
transition main(a: field) -> field {
program core.aleo {
// This function takes as input a field `a` and calls several core functions.
// Core functions are built-in to the Leo language and call handwritten, optimized circuits in the AVM.
// To call a core function, use the correct capitalized identifier followed by two colons
// and then the function name. Example: `Pedersen64::hash()`.
transition main(a: field) -> field {
let b: field = BHP256::hash(a);
let c: field = Poseidon2::hash(b);
let d: field = BHP256::commit(c, 1scalar);
return d;
}
}

View File

@ -1,7 +1,8 @@
// This function takes a group coordinate as input `a` and performs several operations which should output the `0group`.
// Note that the operations can be called as associated functions on the `a` variable.
program groups.aleo {
// This function takes a group coordinate as input `a` and performs several operations which should output the `0group`.
// Note that the operations can be called as associated functions on the `a` variable.
transition main(a: group) -> group {
transition main(a: group) -> group {
// unary
let e: group = a.double(); // 2a
let g: group = e.neg(); // -2a
@ -10,4 +11,6 @@ transition main(a: group) -> group {
let j: group = (a * 2scalar).add(g);
return j;
}
}

View File

@ -1,17 +1,18 @@
// The 'ntzdebruijn' main function.
// From Hacker's Delight 2nd ed. figure 5-26
transition main(public x: u32) -> u8 {
program ntzdebrujin.aleo {
// The 'ntzdebruijn' main function.
// From Hacker's Delight 2nd ed. figure 5-26
transition main(public x: u32) -> u8 {
if x == 0u32 {return 32u8;}
// 0x04D7651F = 81224991
x = (x & 0u32.sub_wrapped(x)).mul_wrapped(81224991u32);
let i: u32 = x >> 27u8;
return deBruijnTableLookup(i);
}
}
// { 0, 1, 2,24, 3,19, 6,25, 22, 4,20,10,16, 7,12,26,
// 31,23,18, 5,21, 9,15,11, 30,17, 8,14,29,13,28,27};
// { 0, 1, 2,24, 3,19, 6,25, 22, 4,20,10,16, 7,12,26,
// 31,23,18, 5,21, 9,15,11, 30,17, 8,14,29,13,28,27};
function deBruijnTableLookup(i: u32) -> u8 {
function deBruijnTableLookup(i: u32) -> u8 {
if i == 0u32 {return 0u8;} else
if i == 1u32 {return 1u8;} else
@ -49,4 +50,5 @@ function deBruijnTableLookup(i: u32) -> u8 {
if i == 30u32 {return 28u8;} else
if i == 31u32 {return 27u8;} else
{return 0u8;} // unused
}
}

View File

@ -1,6 +1,7 @@
// The 'ntzgaudet' main function.
// From Hacker's Delight 2nd ed. figure 5-24
transition main(public x: u32) -> u8 {
program ntzgaudet.aleo {
// The 'ntzgaudet' main function.
// From Hacker's Delight 2nd ed. figure 5-24
transition main(public x: u32) -> u8 {
let y: u32 = x & 0u32.sub_wrapped(x); // Isolate rightmost 1-bit
let bz: u8 = (y != 0u32) ? 0u8 : 1u8;
// 0x0000FFFF = 65535
@ -14,4 +15,5 @@ transition main(public x: u32) -> u8 {
// 0x55555555 = 1431655765
let b0: u8 = (y & 1431655765u32 != 0u32) ? 0u8 : 1u8;
return bz + b4 + b3 + b2 + b1 + b0;
}
}

View File

@ -1,6 +1,7 @@
// The 'ntzloops' main function.
// From Hacker's Delight 2nd ed. figure 5-23
transition main(public x: u32) -> u8 {
program ntzloops.aleo {
// The 'ntzloops' main function.
// From Hacker's Delight 2nd ed. figure 5-23
transition main(public x: u32) -> u8 {
x = !x & x.sub_wrapped(1u32);
let n: u8 = 0u8;
for i:u8 in 0u8..32u8 {
@ -10,4 +11,5 @@ transition main(public x: u32) -> u8 {
}
}
return n;
}
}

View File

@ -1,6 +1,7 @@
// The 'ntzmasks' main function.
// From Hacker's Delight 2nd ed. figure 5-20
transition main(public x: u32) -> u8 {
program ntzmasks.aleo {
// The 'ntzmasks' main function.
// From Hacker's Delight 2nd ed. figure 5-20
transition main(public x: u32) -> u8 {
if (x == 0u32) {return 32u8;}
let n: u8 = 1u8;
// x >>= 16u8 wasn't working, and I don't want to use
@ -12,4 +13,5 @@ transition main(public x: u32) -> u8 {
// can't do `return n - (x & 1u32);` because no typecasts, so:
if ((x & 1u32) == 1u32) {n -= 1u8;}
return n;
}
}

View File

@ -1,17 +1,18 @@
// The 'ntzreisers' main function.
// From Hacker's Delight 2nd ed. figure 5-27
transition main(public x: u32) -> u8 {
program ntzreisers.aleo {
// The 'ntzreisers' main function.
// From Hacker's Delight 2nd ed. figure 5-27
transition main(public x: u32) -> u8 {
x = (x & 0u32.sub_wrapped(x)).rem_wrapped(37u32);
return reisersTableLookup(x);
}
}
// There are 37 entries here
// {32, 0, 1, 26, 2, 23, 27,
// u, 3, 16, 24, 30, 28, 11, u, 13, 4,
// 7, 17, u, 25, 22, 31, 15, 29, 10, 12,
// 6, u, 21, 14, 9, 5, 20, 8, 19, 18};
// There are 37 entries here
// {32, 0, 1, 26, 2, 23, 27,
// u, 3, 16, 24, 30, 28, 11, u, 13, 4,
// 7, 17, u, 25, 22, 31, 15, 29, 10, 12,
// 6, u, 21, 14, 9, 5, 20, 8, 19, 18};
function reisersTableLookup(i: u32) -> u8 {
function reisersTableLookup(i: u32) -> u8 {
if i == 0u32 {return 32u8;} else
if i == 1u32 {return 0u8;} else
@ -55,4 +56,5 @@ function reisersTableLookup(i: u32) -> u8 {
if i == 36u32 {return 18u8;} else
{return 0u8;} // unused
}
}

View File

@ -1,19 +1,20 @@
// The 'nztseals' main function.
// From Hacker's Delight 2nd ed. figure 5-25
transition main(public x: u32) -> u8 {
program ntzseals.aleo {
// The 'nztseals' main function.
// From Hacker's Delight 2nd ed. figure 5-25
transition main(public x: u32) -> u8 {
// 0x0450FBAF = 72416175
x = (x & 0u32.sub_wrapped(x)).mul_wrapped(72416175u32);
return sealsTableLookup(x >> 26u8);
}
}
// Right now we do not have any structure that allows
// computable indexing, so simulate that with a function.
// {32, 0, 1,12, 2, 6, u,13, 3, u, 7, u, u, u, u,14,
// 10, 4, u, u, 8, u, u,25, u, u, u, u, u,21,27,15,
// 31,11, 5, u, u, u, u, u, 9, u, u,24, u, u,20,26,
// 30, u, u, u, u,23, u,19, 29, u,22,18,28,17,16, u};
// Right now we do not have any structure that allows
// computable indexing, so simulate that with a function.
// {32, 0, 1,12, 2, 6, u,13, 3, u, 7, u, u, u, u,14,
// 10, 4, u, u, 8, u, u,25, u, u, u, u, u,21,27,15,
// 31,11, 5, u, u, u, u, u, 9, u, u,24, u, u,20,26,
// 30, u, u, u, u,23, u,19, 29, u,22,18,28,17,16, u};
function sealsTableLookup(i: u32) -> u8 {
function sealsTableLookup(i: u32) -> u8 {
if i == 0u32 {return 32u8;} else
if i == 1u32 {return 0u8;} else
@ -87,4 +88,5 @@ function sealsTableLookup(i: u32) -> u8 {
if i == 62u32 {return 16u8;} else
if i == 63u32 {return 0u8;} else // unused
{return 0u8;} // unused
}
}

View File

@ -1,7 +1,8 @@
// The 'ntzsearchtree' main function.
// From Hacker's Delight 2nd ed. figure 5-22,
// expanded to a 32-bit version.
transition main(public x: u32) -> u8 {
program ntzsearchtree.aleo {
// The 'ntzsearchtree' main function.
// From Hacker's Delight 2nd ed. figure 5-22,
// expanded to a 32-bit version.
transition main(public x: u32) -> u8 {
if (x & 65535u32 != 0u32) {
if (x & 255u32 != 0u32) {
if (x & 15u32 != 0u32) {
@ -71,4 +72,5 @@ transition main(public x: u32) -> u8 {
else {
if (x != 0u32) {return 31u8;}
else {return 32u8;} } } } } }
}
}

View File

@ -1,6 +1,7 @@
// The 'ntzsmallvals' main function.
// From Hacker's Delight 2nd ed. figure 5-21
transition main(public x: u32) -> u8 {
program ntzsmallvals.aleo {
// The 'ntzsmallvals' main function.
// From Hacker's Delight 2nd ed. figure 5-21
transition main(public x: u32) -> u8 {
if (x == 0u32) {return 32u8;}
let n: u8 = 31u8;
let y: u32 = x.shl_wrapped(16u8); if (y != 0u32) {n = n - 16u8; x = y;}
@ -9,4 +10,5 @@ transition main(public x: u32) -> u8 {
y = x.shl_wrapped(2u8); if (y != 0u32) {n = n - 2u8; x = y;}
y = x.shl_wrapped(1u8); if (y != 0u32) {n = n - 1u8;}
return n;
}
}

View File

@ -1,4 +1,7 @@
// The 'helloworld' main function.
transition main(public a: u32, b: u32) -> u32 {
program helloworld.aleo {
// The 'helloworld' main function.
transition main(public a: u32, b: u32) -> u32 {
return a + b;
}
}

View File

@ -1,6 +1,7 @@
// This function calculates the interest accrued
// over ten iterations for some `capital` and `rate`.
transition fixed_iteration_interest(capital: u32, public rate: u32) -> u32 {
program interest.aleo {
// This function calculates the interest accrued
// over ten iterations for some `capital` and `rate`.
transition fixed_iteration_interest(capital: u32, public rate: u32) -> u32 {
let amount: u32 = capital;
// Accrue for exactly 10 iterations.
@ -9,12 +10,12 @@ transition fixed_iteration_interest(capital: u32, public rate: u32) -> u32 {
amount += (amount * rate) / 100u32;
}
return amount;
}
}
// This function calculates the interest accrued
// over a variable number of iterations (max 50) for some `capital` and `rate`.
transition bounded_iteration_interest(capital: u32,
// This function calculates the interest accrued
// over a variable number of iterations (max 50) for some `capital` and `rate`.
transition bounded_iteration_interest(capital: u32,
public rate: u32,
iterations: u8) -> u32 {
console.assert(iterations <= 50u8);
@ -32,4 +33,5 @@ transition bounded_iteration_interest(capital: u32,
}
}
return amount;
}
}

View File

@ -1,16 +1,16 @@
// This example demonstrates the definition and initialization of a "struct" in Leo.
// The "Message" struct.
struct Message {
program message.aleo {
// The "Message" struct.
struct Message {
// A struct member named "first" with type "field".
first: field,
// A struct member named "second" with type "field".
second: field,
}
}
// The "main" function of this Leo program takes a "Message" struct type as input.
// To see how to input variable "m" is passed in open up `inputs/message.in`.
transition main(m: Message) -> field {
// The "main" function of this Leo program takes a "Message" struct type as input.
// To see how to input variable "m" is passed in open up `inputs/message.in`.
transition main(m: Message) -> field {
// 1. Define the "Message" type.
// 2. Use brackets `{ }` to enclose the struct members.
@ -23,4 +23,5 @@ transition main(m: Message) -> field {
// Access the members of a struct with dot syntax.
// `struct_name.member`
return m1.first + m1.second;
}
}

View File

@ -1,28 +1,28 @@
// This example demonstrates an example of a minting and transferring a token in Leo.
// The `Token` record datatype.
record Token {
program simple_token.aleo {
// The `Token` record datatype.
record Token {
// The token owner.
owner: address,
// The Aleo balance (in gates).
gates: u64,
// The token amount.
amount: u64,
}
}
// The `mint` function initializes a new record with the
// specified number of tokens assigned to the specified receiver.
transition mint(owner: address, amount: u64) -> Token {
// The `mint` function initializes a new record with the
// specified number of tokens assigned to the specified receiver.
transition mint(owner: address, amount: u64) -> Token {
return Token {
owner: owner,
gates: 0u64,
amount: amount,
};
}
}
// The `transfer` function sends the specified number of tokens
// to the receiver from the provided token record.
transition transfer(token: Token, to: address, amount: u64) -> (Token, Token) {
// The `transfer` function sends the specified number of tokens
// to the receiver from the provided token record.
transition transfer(token: Token, to: address, amount: u64) -> (Token, Token) {
// Checks the given token record has sufficient balance.
// This `sub` operation is safe, and the proof will fail
@ -46,4 +46,5 @@ transition transfer(token: Token, to: address, amount: u64) -> (Token, Token) {
// Output the sender's change record and the receiver's record.
return (remaining, transferred);
}
}

View File

@ -1,38 +1,39 @@
// A row in a tic tac toe board.
// - `c1` : The first entry in the row.
// - `c2` : The second entry in the row.
// - `c3` : The third entry in the row.
// A valid entry is either 0, 1, or 2, where 0 is empty, 1 corresponds to player 1, and 2 corresponds to player 2.
// Any other values are invalid.
struct Row {
program tictactoe.aleo {
// A row in a tic tac toe board.
// - `c1` : The first entry in the row.
// - `c2` : The second entry in the row.
// - `c3` : The third entry in the row.
// A valid entry is either 0, 1, or 2, where 0 is empty, 1 corresponds to player 1, and 2 corresponds to player 2.
// Any other values are invalid.
struct Row {
c1: u8,
c2: u8,
c3: u8
}
}
// A tic tac toe board.
// - `r1` : The first row in the board.
// - `r2` : The second row in the board.
// - `r3` : The third row in the board.
struct Board {
// A tic tac toe board.
// - `r1` : The first row in the board.
// - `r2` : The second row in the board.
// - `r3` : The third row in the board.
struct Board {
r1: Row,
r2: Row,
r3: Row,
}
}
// Returns an empty board.
transition new() -> Board {
// Returns an empty board.
transition new() -> Board {
return Board {
r1: Row { c1: 0u8, c2: 0u8, c3: 0u8 },
r2: Row { c1: 0u8, c2: 0u8, c3: 0u8 },
r3: Row { c1: 0u8, c2: 0u8, c3: 0u8 },
};
}
}
// Returns `true` if there exists a row, column, or diagonal with all entries occupied by the same player.
// - `b` : A tic tac toe board.
// - `p` : A number corresponding to a player.
function check_for_win(b: Board, p: u8) -> bool {
// Returns `true` if there exists a row, column, or diagonal with all entries occupied by the same player.
// - `b` : A tic tac toe board.
// - `p` : A number corresponding to a player.
function check_for_win(b: Board, p: u8) -> bool {
return
(b.r1.c1 == p && b.r1.c2 == p && b.r1.c3 == p) || // row 1
(b.r2.c1 == p && b.r2.c2 == p && b.r2.c3 == p) || // row 2
@ -42,18 +43,18 @@ function check_for_win(b: Board, p: u8) -> bool {
(b.r1.c3 == p && b.r2.c3 == p && b.r3.c3 == p) || // column 3
(b.r1.c1 == p && b.r2.c2 == p && b.r3.c3 == p) || // diagonal
(b.r1.c3 == p && b.r2.c2 == p && b.r3.c1 == p); // other diagonal
}
}
// Returns an updated tic tac toe board with a move made by a player.
// Returns a `u8` corresponding to the player who won the game, or 0 if no one has won yet.
// - `player` : A number corresponding to a player.
// - `row` : The row of the move.
// - `col` : The column of the move.
// - `board` : A tic tac toe board.
// Assumes that `player` is either 1 or 2.
// Assumes that `row` and `col` are valid indices into the board.
// If an entry is already occupied, the move is invalid and the board is returned unchanged.
transition make_move(player: u8, row: u8, col: u8, board: Board) -> (Board, u8) {
// Returns an updated tic tac toe board with a move made by a player.
// Returns a `u8` corresponding to the player who won the game, or 0 if no one has won yet.
// - `player` : A number corresponding to a player.
// - `row` : The row of the move.
// - `col` : The column of the move.
// - `board` : A tic tac toe board.
// Assumes that `player` is either 1 or 2.
// Assumes that `row` and `col` are valid indices into the board.
// If an entry is already occupied, the move is invalid and the board is returned unchanged.
transition make_move(player: u8, row: u8, col: u8, board: Board) -> (Board, u8) {
// Check that inputs are valid.
console.assert(player == 1u8 || player == 2u8);
console.assert(1u8 <= row && row <= 3u8);
@ -106,4 +107,5 @@ transition make_move(player: u8, row: u8, col: u8, board: Board) -> (Board, u8)
} else {
return (updated, 0u8);
}
}
}

View File

@ -1,6 +1,7 @@
// This function calculates the number of powers of two ("twoadicity")
// in the prime factorization of the input number `n`.
transition main(public n: field) -> u8 {
program twoadicity.aleo {
// This function calculates the number of powers of two ("twoadicity")
// in the prime factorization of the input number `n`.
transition main(public n: field) -> u8 {
let remaining_n: field = n;
let powers_of_two: u8 = 0u8;
// Since field ints are 253 bits or fewer, any number in the field
@ -12,15 +13,16 @@ transition main(public n: field) -> u8 {
}
}
return powers_of_two;
}
}
/* We define the is_even predicate on fields as follows.
/* We define the is_even predicate on fields as follows.
If n is even and nonzero, clearly n/2 < n.
If n is odd, n-p is a field-equivalent negative number that is even, and
(n-p)/2 is a field-equivalent negative number closer to 0, greater than n-p.
If we add p to both of these negative numbers, we have
n/2 = (n-p)/2 + p = (n+p)/2 is greater than n and still less than p.
*/
function is_even_and_nonzero (n: field) -> bool {
*/
function is_even_and_nonzero (n: field) -> bool {
return n / 2field < n;
}
}

View File

@ -1,39 +1,39 @@
// The 'vote.leo' program.
// Proposal details
struct ProposalInfo {
program vote.aleo {
// Proposal details
struct ProposalInfo {
title: field,
content: field,
proposer: address,
}
}
// Proposal record records proposal info publicly
record Proposal {
// Proposal record records proposal info publicly
record Proposal {
owner: address,
gates: u64,
id: field,
info: ProposalInfo,
}
}
// Save proposal info in public storage.
mapping proposals: field => ProposalInfo;
// Save proposal info in public storage.
mapping proposals: field => ProposalInfo;
// Privacy tickets to vote
record Ticket {
// Privacy tickets to vote
record Ticket {
owner: address,
gates: u64,
pid: field,
}
}
// Count the total tickets issued for each proposal
mapping tickets: field => u64;
// Count the total tickets issued for each proposal
mapping tickets: field => u64;
mapping agree_votes: field => u64;
mapping agree_votes: field => u64;
mapping disagree_votes: field => u64;
mapping disagree_votes: field => u64;
// Propose a new proposal to vote on.
transition propose(public info: ProposalInfo) -> Proposal {
// Propose a new proposal to vote on.
transition propose(public info: ProposalInfo) -> Proposal {
// Authenticate proposer.
console.assert_eq(self.caller, info.proposer);
@ -50,17 +50,17 @@ transition propose(public info: ProposalInfo) -> Proposal {
id,
info,
};
}
// Create a new proposal in the "tickets" mapping.
finalize propose(public id: field) {
}
// Create a new proposal in the "tickets" mapping.
finalize propose(public id: field) {
increment(tickets, id, 0u64);
}
}
// Create a new ticket to vote with.
transition new_ticket(
// Create a new ticket to vote with.
transition new_ticket(
public pid: field,
public voter: address,
) -> Ticket {
) -> Ticket {
// Finalize the proposal id for the ticket.
async finalize(pid);
@ -69,28 +69,29 @@ transition new_ticket(
gates: 0u64,
pid,
};
}
// Create a new ticket on a proposal in the "tickets" mapping.
finalize new_ticket(public pid: field) {
}
// Create a new ticket on a proposal in the "tickets" mapping.
finalize new_ticket(public pid: field) {
increment(tickets, pid, 1u64);
}
}
// Vote privately to agree with a proposal.
transition agree(ticket: Ticket) {
// Vote privately to agree with a proposal.
transition agree(ticket: Ticket) {
// Finalize this vote.
async finalize(ticket.pid);
}
finalize agree(public pid: field) {
}
finalize agree(public pid: field) {
// Publicly increment the number of agree votes.
increment(agree_votes, pid, 1u64);
}
}
// Vote privately to disagree with a proposal.
transition disagree(ticket: Ticket) {
// Vote privately to disagree with a proposal.
transition disagree(ticket: Ticket) {
// Finalize this vote.
async finalize(ticket.pid);
}
finalize disagree(pid: field) {
}
finalize disagree(pid: field) {
// Publicly increment the number of disagree votes.
increment(disagree_votes, pid, 1u64);
}
}