Skip to content

Commit

Permalink
[Feature] Support ChaCha::rand_* (#2433)
Browse files Browse the repository at this point in the history
* Add tests for ChaCha::rand*

* Add Chacha::rand* to AST, tyc, and codegen

* Add lottery example

* Regen expectations

* Add check asserting that command is only used in finalize block

* Update example and related CI
  • Loading branch information
d0cd authored Jun 29, 2023
1 parent c373b89 commit b236918
Show file tree
Hide file tree
Showing 21 changed files with 465 additions and 1 deletion.
7 changes: 7 additions & 0 deletions .circleci/test-examples.sh
Original file line number Diff line number Diff line change
Expand Up @@ -341,3 +341,10 @@ if [ $EXITCODE -ne 0 ]; then
echo "The \`vote\` program failed to run successfully."
exit $EXITCODE
fi

# Build the lottery example Leo program.
echo "Building the \`lottery\` program..."
(
cd $EXAMPLES/lottery || exit
$LEO build || exit
)
218 changes: 218 additions & 0 deletions compiler/ast/src/functions/core_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,22 @@ pub enum CoreFunction {
BHP1024HashToU128,
BHP1024HashToScalar,

ChaChaRandAddress,
ChaChaRandBool,
ChaChaRandField,
ChaChaRandGroup,
ChaChaRandI8,
ChaChaRandI16,
ChaChaRandI32,
ChaChaRandI64,
ChaChaRandI128,
ChaChaRandU8,
ChaChaRandU16,
ChaChaRandU32,
ChaChaRandU64,
ChaChaRandU128,
ChaChaRandScalar,

Pedersen64CommitToAddress,
Pedersen64CommitToField,
Pedersen64CommitToGroup,
Expand Down Expand Up @@ -257,6 +273,22 @@ impl CoreFunction {
(sym::BHP1024, sym::hash_to_u128) => Self::BHP1024HashToU128,
(sym::BHP1024, sym::hash_to_scalar) => Self::BHP1024HashToScalar,

(sym::ChaCha, sym::rand_address) => Self::ChaChaRandAddress,
(sym::ChaCha, sym::rand_bool) => Self::ChaChaRandBool,
(sym::ChaCha, sym::rand_field) => Self::ChaChaRandField,
(sym::ChaCha, sym::rand_group) => Self::ChaChaRandGroup,
(sym::ChaCha, sym::rand_i8) => Self::ChaChaRandI8,
(sym::ChaCha, sym::rand_i16) => Self::ChaChaRandI16,
(sym::ChaCha, sym::rand_i32) => Self::ChaChaRandI32,
(sym::ChaCha, sym::rand_i64) => Self::ChaChaRandI64,
(sym::ChaCha, sym::rand_i128) => Self::ChaChaRandI128,
(sym::ChaCha, sym::rand_scalar) => Self::ChaChaRandScalar,
(sym::ChaCha, sym::rand_u8) => Self::ChaChaRandU8,
(sym::ChaCha, sym::rand_u16) => Self::ChaChaRandU16,
(sym::ChaCha, sym::rand_u32) => Self::ChaChaRandU32,
(sym::ChaCha, sym::rand_u64) => Self::ChaChaRandU64,
(sym::ChaCha, sym::rand_u128) => Self::ChaChaRandU128,

(sym::Pedersen64, sym::commit_to_address) => Self::Pedersen64CommitToAddress,
(sym::Pedersen64, sym::commit_to_field) => Self::Pedersen64CommitToField,
(sym::Pedersen64, sym::commit_to_group) => Self::Pedersen64CommitToGroup,
Expand Down Expand Up @@ -424,6 +456,22 @@ impl CoreFunction {
Self::BHP1024HashToU128 => 1,
Self::BHP1024HashToScalar => 1,

Self::ChaChaRandAddress => 0,
Self::ChaChaRandBool => 0,
Self::ChaChaRandField => 0,
Self::ChaChaRandGroup => 0,
Self::ChaChaRandI8 => 0,
Self::ChaChaRandI16 => 0,
Self::ChaChaRandI32 => 0,
Self::ChaChaRandI64 => 0,
Self::ChaChaRandI128 => 0,
Self::ChaChaRandU8 => 0,
Self::ChaChaRandU16 => 0,
Self::ChaChaRandU32 => 0,
Self::ChaChaRandU64 => 0,
Self::ChaChaRandU128 => 0,
Self::ChaChaRandScalar => 0,

Self::Pedersen64CommitToAddress => 2,
Self::Pedersen64CommitToField => 2,
Self::Pedersen64CommitToGroup => 2,
Expand Down Expand Up @@ -513,4 +561,174 @@ impl CoreFunction {
Self::GroupToYCoordinate => 1,
}
}

/// Returns whether or not this function is finalize command.
pub fn is_finalize_command(&self) -> bool {
match self {
CoreFunction::ChaChaRandAddress
| CoreFunction::ChaChaRandBool
| CoreFunction::ChaChaRandField
| CoreFunction::ChaChaRandGroup
| CoreFunction::ChaChaRandI8
| CoreFunction::ChaChaRandI16
| CoreFunction::ChaChaRandI32
| CoreFunction::ChaChaRandI64
| CoreFunction::ChaChaRandI128
| CoreFunction::ChaChaRandU8
| CoreFunction::ChaChaRandU16
| CoreFunction::ChaChaRandU32
| CoreFunction::ChaChaRandU64
| CoreFunction::ChaChaRandU128
| CoreFunction::MappingGet
| CoreFunction::MappingGetOrUse
| CoreFunction::ChaChaRandScalar
| CoreFunction::MappingSet => true,
CoreFunction::BHP256CommitToAddress
| CoreFunction::BHP256CommitToField
| CoreFunction::BHP256CommitToGroup
| CoreFunction::BHP256HashToAddress
| CoreFunction::BHP256HashToField
| CoreFunction::BHP256HashToGroup
| CoreFunction::BHP256HashToI8
| CoreFunction::BHP256HashToI16
| CoreFunction::BHP256HashToI32
| CoreFunction::BHP256HashToI64
| CoreFunction::BHP256HashToI128
| CoreFunction::BHP256HashToU8
| CoreFunction::BHP256HashToU16
| CoreFunction::BHP256HashToU32
| CoreFunction::BHP256HashToU64
| CoreFunction::BHP256HashToU128
| CoreFunction::BHP256HashToScalar
| CoreFunction::BHP512CommitToAddress
| CoreFunction::BHP512CommitToField
| CoreFunction::BHP512CommitToGroup
| CoreFunction::BHP512HashToAddress
| CoreFunction::BHP512HashToField
| CoreFunction::BHP512HashToGroup
| CoreFunction::BHP512HashToI8
| CoreFunction::BHP512HashToI16
| CoreFunction::BHP512HashToI32
| CoreFunction::BHP512HashToI64
| CoreFunction::BHP512HashToI128
| CoreFunction::BHP512HashToU8
| CoreFunction::BHP512HashToU16
| CoreFunction::BHP512HashToU32
| CoreFunction::BHP512HashToU64
| CoreFunction::BHP512HashToU128
| CoreFunction::BHP512HashToScalar
| CoreFunction::BHP768CommitToAddress
| CoreFunction::BHP768CommitToField
| CoreFunction::BHP768CommitToGroup
| CoreFunction::BHP768HashToAddress
| CoreFunction::BHP768HashToField
| CoreFunction::BHP768HashToGroup
| CoreFunction::BHP768HashToI8
| CoreFunction::BHP768HashToI16
| CoreFunction::BHP768HashToI32
| CoreFunction::BHP768HashToI64
| CoreFunction::BHP768HashToI128
| CoreFunction::BHP768HashToU8
| CoreFunction::BHP768HashToU16
| CoreFunction::BHP768HashToU32
| CoreFunction::BHP768HashToU64
| CoreFunction::BHP768HashToU128
| CoreFunction::BHP768HashToScalar
| CoreFunction::BHP1024CommitToAddress
| CoreFunction::BHP1024CommitToField
| CoreFunction::BHP1024CommitToGroup
| CoreFunction::BHP1024HashToAddress
| CoreFunction::BHP1024HashToField
| CoreFunction::BHP1024HashToGroup
| CoreFunction::BHP1024HashToI8
| CoreFunction::BHP1024HashToI16
| CoreFunction::BHP1024HashToI32
| CoreFunction::BHP1024HashToI64
| CoreFunction::BHP1024HashToI128
| CoreFunction::BHP1024HashToU8
| CoreFunction::BHP1024HashToU16
| CoreFunction::BHP1024HashToU32
| CoreFunction::BHP1024HashToU64
| CoreFunction::BHP1024HashToU128
| CoreFunction::BHP1024HashToScalar
| CoreFunction::Pedersen64CommitToAddress
| CoreFunction::Pedersen64CommitToField
| CoreFunction::Pedersen64CommitToGroup
| CoreFunction::Pedersen64HashToAddress
| CoreFunction::Pedersen64HashToField
| CoreFunction::Pedersen64HashToGroup
| CoreFunction::Pedersen64HashToI8
| CoreFunction::Pedersen64HashToI16
| CoreFunction::Pedersen64HashToI32
| CoreFunction::Pedersen64HashToI64
| CoreFunction::Pedersen64HashToI128
| CoreFunction::Pedersen64HashToU8
| CoreFunction::Pedersen64HashToU16
| CoreFunction::Pedersen64HashToU32
| CoreFunction::Pedersen64HashToU64
| CoreFunction::Pedersen64HashToU128
| CoreFunction::Pedersen64HashToScalar
| CoreFunction::Pedersen128CommitToAddress
| CoreFunction::Pedersen128CommitToField
| CoreFunction::Pedersen128CommitToGroup
| CoreFunction::Pedersen128HashToAddress
| CoreFunction::Pedersen128HashToField
| CoreFunction::Pedersen128HashToGroup
| CoreFunction::Pedersen128HashToI8
| CoreFunction::Pedersen128HashToI16
| CoreFunction::Pedersen128HashToI32
| CoreFunction::Pedersen128HashToI64
| CoreFunction::Pedersen128HashToI128
| CoreFunction::Pedersen128HashToU8
| CoreFunction::Pedersen128HashToU16
| CoreFunction::Pedersen128HashToU32
| CoreFunction::Pedersen128HashToU64
| CoreFunction::Pedersen128HashToU128
| CoreFunction::Pedersen128HashToScalar
| CoreFunction::Poseidon2HashToAddress
| CoreFunction::Poseidon2HashToField
| CoreFunction::Poseidon2HashToGroup
| CoreFunction::Poseidon2HashToI8
| CoreFunction::Poseidon2HashToI16
| CoreFunction::Poseidon2HashToI32
| CoreFunction::Poseidon2HashToI64
| CoreFunction::Poseidon2HashToI128
| CoreFunction::Poseidon2HashToU8
| CoreFunction::Poseidon2HashToU16
| CoreFunction::Poseidon2HashToU32
| CoreFunction::Poseidon2HashToU64
| CoreFunction::Poseidon2HashToU128
| CoreFunction::Poseidon2HashToScalar
| CoreFunction::Poseidon4HashToAddress
| CoreFunction::Poseidon4HashToField
| CoreFunction::Poseidon4HashToGroup
| CoreFunction::Poseidon4HashToI8
| CoreFunction::Poseidon4HashToI16
| CoreFunction::Poseidon4HashToI32
| CoreFunction::Poseidon4HashToI64
| CoreFunction::Poseidon4HashToI128
| CoreFunction::Poseidon4HashToU8
| CoreFunction::Poseidon4HashToU16
| CoreFunction::Poseidon4HashToU32
| CoreFunction::Poseidon4HashToU64
| CoreFunction::Poseidon4HashToU128
| CoreFunction::Poseidon4HashToScalar
| CoreFunction::Poseidon8HashToAddress
| CoreFunction::Poseidon8HashToField
| CoreFunction::Poseidon8HashToGroup
| CoreFunction::Poseidon8HashToI8
| CoreFunction::Poseidon8HashToI16
| CoreFunction::Poseidon8HashToI32
| CoreFunction::Poseidon8HashToI64
| CoreFunction::Poseidon8HashToI128
| CoreFunction::Poseidon8HashToU8
| CoreFunction::Poseidon8HashToU16
| CoreFunction::Poseidon8HashToU32
| CoreFunction::Poseidon8HashToU64
| CoreFunction::Poseidon8HashToU128
| CoreFunction::Poseidon8HashToScalar
| CoreFunction::GroupToXCoordinate
| CoreFunction::GroupToYCoordinate => false,
}
}
}
27 changes: 27 additions & 0 deletions compiler/passes/src/code_generation/visit_expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,33 @@ impl<'a> CodeGenerator<'a> {
_ => unreachable!("The only associated methods of group are to_x_coordinate and to_y_coordinate"),
}
}
Type::Identifier(Identifier { name: sym::ChaCha, .. }) => {
// Get the destination register.
let destination_register = get_destination_register();
// Construct the instruction template.
let mut instruction = format!(" rand.chacha into {destination_register} as ");
// Write the return type.
match input.name {
Identifier { name: sym::rand_address, .. } => writeln!(instruction, "address;"),
Identifier { name: sym::rand_bool, .. } => writeln!(instruction, "boolean;"),
Identifier { name: sym::rand_field, .. } => writeln!(instruction, "field;"),
Identifier { name: sym::rand_group, .. } => writeln!(instruction, "group;"),
Identifier { name: sym::rand_i8, .. } => writeln!(instruction, "i8;"),
Identifier { name: sym::rand_i16, .. } => writeln!(instruction, "i16;"),
Identifier { name: sym::rand_i32, .. } => writeln!(instruction, "i32;"),
Identifier { name: sym::rand_i64, .. } => writeln!(instruction, "i64;"),
Identifier { name: sym::rand_i128, .. } => writeln!(instruction, "i128;"),
Identifier { name: sym::rand_scalar, .. } => writeln!(instruction, "scalar;"),
Identifier { name: sym::rand_u8, .. } => writeln!(instruction, "u8;"),
Identifier { name: sym::rand_u16, .. } => writeln!(instruction, "u16;"),
Identifier { name: sym::rand_u32, .. } => writeln!(instruction, "u32;"),
Identifier { name: sym::rand_u64, .. } => writeln!(instruction, "u64;"),
Identifier { name: sym::rand_u128, .. } => writeln!(instruction, "u128;"),
_ => unreachable!("The only associated methods of ChaCha are `rand_*`"),
}
.expect("failed to write to string");
(destination_register, instruction)
}
_ => unreachable!("All core functions should be known at this phase of compilation"),
};
// Add the instruction to the list of instructions.
Expand Down
6 changes: 6 additions & 0 deletions compiler/passes/src/type_checking/check_expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
AccessExpression::AssociatedFunction(access) => {
// Check core struct name and function.
if let Some(core_instruction) = self.get_core_function_call(&access.ty, &access.name) {
// Check that operation is not restricted to finalize blocks.
if !self.is_finalize && core_instruction.is_finalize_command() {
self.emit_err(TypeCheckerError::operation_must_be_in_finalize_block(input.span()));
}

// Get the types of the arguments.
let argument_types = access
.arguments
Expand All @@ -59,6 +64,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
if let Some(expected) = expected {
self.assert_type(&return_type, expected, input.span());
}

return return_type;
} else {
self.emit_err(TypeCheckerError::invalid_core_function_call(access, access.span()));
Expand Down
15 changes: 15 additions & 0 deletions compiler/passes/src/type_checking/checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,21 @@ impl<'a> TypeChecker<'a> {
self.assert_group_type(&arguments[0].0, arguments[0].1);
Some(Type::Field)
}
CoreFunction::ChaChaRandAddress => Some(Type::Address),
CoreFunction::ChaChaRandBool => Some(Type::Boolean),
CoreFunction::ChaChaRandField => Some(Type::Field),
CoreFunction::ChaChaRandGroup => Some(Type::Group),
CoreFunction::ChaChaRandI8 => Some(Type::Integer(IntegerType::I8)),
CoreFunction::ChaChaRandI16 => Some(Type::Integer(IntegerType::I16)),
CoreFunction::ChaChaRandI32 => Some(Type::Integer(IntegerType::I32)),
CoreFunction::ChaChaRandI64 => Some(Type::Integer(IntegerType::I64)),
CoreFunction::ChaChaRandI128 => Some(Type::Integer(IntegerType::I128)),
CoreFunction::ChaChaRandScalar => Some(Type::Scalar),
CoreFunction::ChaChaRandU8 => Some(Type::Integer(IntegerType::U8)),
CoreFunction::ChaChaRandU16 => Some(Type::Integer(IntegerType::U16)),
CoreFunction::ChaChaRandU32 => Some(Type::Integer(IntegerType::U32)),
CoreFunction::ChaChaRandU64 => Some(Type::Integer(IntegerType::U64)),
CoreFunction::ChaChaRandU128 => Some(Type::Integer(IntegerType::U128)),
}
}

Expand Down
16 changes: 16 additions & 0 deletions compiler/span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ symbols! {
BHP512,
BHP768,
BHP1024,
ChaCha,
commit_to_address,
commit_to_field,
commit_to_group,
Expand All @@ -174,6 +175,21 @@ symbols! {
Poseidon2,
Poseidon4,
Poseidon8,
rand_address,
rand_bool,
rand_field,
rand_group,
rand_i8,
rand_i16,
rand_i32,
rand_i64,
rand_i128,
rand_scalar,
rand_u8,
rand_u16,
rand_u32,
rand_u64,
rand_u128,
set,
to_x_coordinate,
to_y_coordinate,
Expand Down
7 changes: 7 additions & 0 deletions errors/src/errors/type_checker/type_checker_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -635,4 +635,11 @@ create_messages!(
msg: format!("`{operation}` is not a valid operand in a finalize context."),
help: None,
}

@formatted
operation_must_be_in_finalize_block {
args: (),
msg: format!("This operation can only be used in a `finalize` block."),
help: None,
}
);
2 changes: 2 additions & 0 deletions examples/lottery/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
outputs/
build/
8 changes: 8 additions & 0 deletions examples/lottery/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# lottery.aleo

## Build Guide

To compile this Aleo program, run:
```bash
aleo build
```
4 changes: 4 additions & 0 deletions examples/lottery/inputs/lottery.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// The program input for lottery/src/main.leo
[main]
public a: u32 = 1u32;
b: u32 = 2u32;
Loading

0 comments on commit b236918

Please sign in to comment.