rest of Aleo commands

This commit is contained in:
Michael Benfield 2024-11-21 12:09:35 -08:00
parent b2f7fd718b
commit 334881cef5
2 changed files with 131 additions and 14 deletions

View File

@ -256,7 +256,7 @@ pub struct Cursor<'a> {
pub signer: SvmAddress, pub signer: SvmAddress,
rng: ChaCha20Rng, pub rng: ChaCha20Rng,
pub block_height: u32, pub block_height: u32,
@ -322,14 +322,14 @@ impl<'a> Cursor<'a> {
self.globals.get(&GlobalId { program: context.program, name }).cloned() self.globals.get(&GlobalId { program: context.program, name }).cloned()
} }
fn lookup_mapping(&self, program: Option<Symbol>, name: Symbol) -> Option<&HashMap<Value, Value>> { pub fn lookup_mapping(&self, program: Option<Symbol>, name: Symbol) -> Option<&HashMap<Value, Value>> {
let Some(program) = program.or(self.contexts.last().map(|c| c.program)) else { let Some(program) = program.or(self.contexts.last().map(|c| c.program)) else {
panic!("no program for mapping lookup"); panic!("no program for mapping lookup");
}; };
self.mappings.get(&GlobalId { program, name }) self.mappings.get(&GlobalId { program, name })
} }
fn lookup_mapping_mut(&mut self, program: Option<Symbol>, name: Symbol) -> Option<&mut HashMap<Value, Value>> { pub fn lookup_mapping_mut(&mut self, program: Option<Symbol>, name: Symbol) -> Option<&mut HashMap<Value, Value>> {
let Some(program) = program.or(self.contexts.last().map(|c| c.program)) else { let Some(program) = program.or(self.contexts.last().map(|c| c.program)) else {
panic!("no program for mapping lookup"); panic!("no program for mapping lookup");
}; };

View File

@ -19,14 +19,39 @@ use super::*;
use leo_ast::{BinaryOperation, CoreFunction, IntegerType, Type, UnaryOperation}; use leo_ast::{BinaryOperation, CoreFunction, IntegerType, Type, UnaryOperation};
use snarkvm::{ use snarkvm::{
prelude::{Boolean, Identifier, Literal, LiteralType, PlaintextType, Register, TestnetV0, integers::Integer}, prelude::{
Boolean,
Field,
Identifier,
Literal,
LiteralType,
Network as _,
PlaintextType,
Register,
TestnetV0,
ToBits as _,
ToBytes as _,
integers::Integer,
},
synthesizer::{Command, Instruction}, synthesizer::{Command, Instruction},
}; };
use snarkvm_synthesizer_program::{CallOperator, CastType, Operand}; use snarkvm_synthesizer_program::{CallOperator, CastType, Operand};
use rand::Rng as _;
use rand_chacha::{ChaCha20Rng, rand_core::SeedableRng};
use std::mem; use std::mem;
impl Cursor<'_> { impl Cursor<'_> {
fn mapping_by_call_operator(&self, operator: &CallOperator<TestnetV0>) -> Option<&HashMap<Value, Value>> {
let (program, name) = match operator {
CallOperator::Locator(locator) => {
(Some(snarkvm_identifier_to_symbol(locator.name())), snarkvm_identifier_to_symbol(locator.resource()))
}
CallOperator::Resource(id) => (None, snarkvm_identifier_to_symbol(id)),
};
self.lookup_mapping(program, name)
}
fn get_register(&self, reg: Register<TestnetV0>) -> &Value { fn get_register(&self, reg: Register<TestnetV0>) -> &Value {
let Some(Frame { element: Element::AleoExecution { registers, .. }, .. }) = self.frames.last() else { let Some(Frame { element: Element::AleoExecution { registers, .. }, .. }) = self.frames.last() else {
panic!(); panic!();
@ -742,21 +767,108 @@ impl Cursor<'_> {
fn step_aleo_command(&mut self, command: Command<TestnetV0>) -> Result<()> { fn step_aleo_command(&mut self, command: Command<TestnetV0>) -> Result<()> {
use Command::*; use Command::*;
match command {
Instruction(instruction) => self.step_aleo_instruction(instruction)?, let (value, destination) = match command {
Instruction(instruction) => {
self.step_aleo_instruction(instruction)?;
return Ok(());
}
Await(await_) => { Await(await_) => {
let Value::Future(future) = self.get_register(await_.register().clone()) else { let Value::Future(future) = self.get_register(await_.register().clone()) else {
halt_no_span!("attempted to await a non-future"); halt_no_span!("attempted to await a non-future");
}; };
self.contexts.add_future(future.clone()); self.contexts.add_future(future.clone());
self.increment_instruction_index(); self.increment_instruction_index();
return Ok(());
}
Contains(contains) => {
let mapping = self.mapping_by_call_operator(contains.mapping()).expect("mapping should be present");
let key = self.operand_value(contains.key());
let result = Value::Bool(mapping.contains_key(&key));
self.increment_instruction_index();
(result, contains.destination().clone())
}
Get(get) => {
let key = self.operand_value(get.key());
let value = self.mapping_by_call_operator(get.mapping()).and_then(|mapping| mapping.get(&key)).cloned();
self.increment_instruction_index();
match value {
Some(v) => (v, get.destination().clone()),
None => halt_no_span!("map access failure: {key}"),
}
}
GetOrUse(get_or_use) => {
let key = self.operand_value(get_or_use.key());
let value =
self.mapping_by_call_operator(get_or_use.mapping()).and_then(|mapping| mapping.get(&key)).cloned();
let use_value = value.unwrap_or_else(|| self.operand_value(get_or_use.default()));
self.increment_instruction_index();
(use_value, get_or_use.destination().clone())
}
Remove(remove) => {
let key = self.operand_value(remove.key());
let mapping_name = snarkvm_identifier_to_symbol(remove.mapping_name());
let maybe_mapping = self.lookup_mapping_mut(None, mapping_name);
match maybe_mapping {
None => halt_no_span!("no such mapping {mapping_name}"),
Some(mapping) => {
mapping.remove(&key);
}
}
self.increment_instruction_index();
return Ok(());
}
Set(set) => {
let key = self.operand_value(set.key());
let value = self.operand_value(set.value());
let mapping_name = snarkvm_identifier_to_symbol(set.mapping_name());
let maybe_mapping = self.lookup_mapping_mut(None, mapping_name);
match maybe_mapping {
None => halt_no_span!("no such mapping {mapping_name}"),
Some(mapping) => {
mapping.insert(key, value);
}
}
self.increment_instruction_index();
return Ok(());
}
RandChaCha(rand) => {
// If there are operands, they are additional seeds.
let mut bits = Vec::new();
for value in rand.operands().iter().map(|op| self.operand_value(op)) {
value.write_bits_le(&mut bits);
}
let field: Field<TestnetV0> = self.rng.gen();
field.write_bits_le(&mut bits);
let seed_vec = TestnetV0::hash_bhp1024(&bits)?.to_bytes_le()?;
let mut seed = [0u8; 32];
seed.copy_from_slice(&seed_vec[..32]);
let mut rng = ChaCha20Rng::from_seed(seed);
let value = match rand.destination_type() {
LiteralType::Address => Value::Address(rng.gen()),
LiteralType::Boolean => Value::Bool(rng.gen()),
LiteralType::Field => Value::Field(rng.gen()),
LiteralType::Group => Value::Group(rng.gen()),
LiteralType::I8 => Value::I8(rng.gen()),
LiteralType::I16 => Value::I16(rng.gen()),
LiteralType::I32 => Value::I32(rng.gen()),
LiteralType::I64 => Value::I64(rng.gen()),
LiteralType::I128 => Value::I128(rng.gen()),
LiteralType::U8 => Value::U8(rng.gen()),
LiteralType::U16 => Value::U16(rng.gen()),
LiteralType::U32 => Value::U32(rng.gen()),
LiteralType::U64 => Value::U64(rng.gen()),
LiteralType::U128 => Value::U128(rng.gen()),
LiteralType::Scalar => Value::Scalar(rng.gen()),
LiteralType::Signature => halt_no_span!("Cannot create a random signature"),
LiteralType::String => halt_no_span!("Cannot create a random string"),
};
self.increment_instruction_index();
(value, rand.destination().clone())
} }
Contains(_) => todo!(),
Get(_) => todo!(),
GetOrUse(_) => todo!(),
RandChaCha(_) => todo!(),
Remove(_) => todo!(),
Set(_) => todo!(),
BranchEq(branch_eq) => { BranchEq(branch_eq) => {
let first = self.operand_value(branch_eq.first()); let first = self.operand_value(branch_eq.first());
let second = self.operand_value(branch_eq.second()); let second = self.operand_value(branch_eq.second());
@ -765,6 +877,7 @@ impl Cursor<'_> {
} else { } else {
self.increment_instruction_index(); self.increment_instruction_index();
} }
return Ok(());
} }
BranchNeq(branch_neq) => { BranchNeq(branch_neq) => {
let first = self.operand_value(branch_neq.first()); let first = self.operand_value(branch_neq.first());
@ -774,9 +887,13 @@ impl Cursor<'_> {
} else { } else {
self.increment_instruction_index(); self.increment_instruction_index();
} }
return Ok(());
} }
Position(_) => {} Position(_) => return Ok(()),
} };
self.set_register(destination, value);
Ok(()) Ok(())
} }