Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Add transfer_public_as_signer to credits.aleo #2402

Merged
merged 12 commits into from Mar 22, 2024
5 changes: 5 additions & 0 deletions parameters/src/mainnet/mod.rs
Expand Up @@ -91,6 +91,9 @@ impl_local!(TransferPrivateVerifier, "resources/", "transfer_private", "verifier
// TransferPublic
impl_remote!(TransferPublicProver, REMOTE_URL, "resources/", "transfer_public", "prover");
impl_local!(TransferPublicVerifier, "resources/", "transfer_public", "verifier");
// TransferPublicAsSigner
impl_remote!(TransferPublicAsSignerProver, REMOTE_URL, "resources/", "transfer_public_as_signer", "prover");
impl_local!(TransferPublicAsSignerVerifier, "resources/", "transfer_public_as_signer", "verifier");
// TransferPrivateToPublic
impl_remote!(TransferPrivateToPublicProver, REMOTE_URL, "resources/", "transfer_private_to_public", "prover");
impl_local!(TransferPrivateToPublicVerifier, "resources/", "transfer_private_to_public", "verifier");
Expand Down Expand Up @@ -122,6 +125,7 @@ macro_rules! insert_credit_keys {
$crate::insert_key!($map, string, $type<$network>, ("set_validator_state", $crate::mainnet::[<SetValidatorState $variant>]::load_bytes()));
$crate::insert_key!($map, string, $type<$network>, ("transfer_private", $crate::mainnet::[<TransferPrivate $variant>]::load_bytes()));
$crate::insert_key!($map, string, $type<$network>, ("transfer_public", $crate::mainnet::[<TransferPublic $variant>]::load_bytes()));
$crate::insert_key!($map, string, $type<$network>, ("transfer_public_as_signer", $crate::mainnet::[<TransferPublicAsSigner $variant>]::load_bytes()));
$crate::insert_key!($map, string, $type<$network>, ("transfer_private_to_public", $crate::mainnet::[<TransferPrivateToPublic $variant>]::load_bytes()));
$crate::insert_key!($map, string, $type<$network>, ("transfer_public_to_private", $crate::mainnet::[<TransferPublicToPrivate $variant>]::load_bytes()));
$crate::insert_key!($map, string, $type<$network>, ("join", $crate::mainnet::[<Join $variant>]::load_bytes()));
Expand Down Expand Up @@ -179,6 +183,7 @@ mod tests {
SetValidatorStateVerifier::load_bytes().expect("Failed to load set_validator_state verifier");
TransferPrivateVerifier::load_bytes().expect("Failed to load transfer_private verifier");
TransferPublicVerifier::load_bytes().expect("Failed to load transfer_public verifier");
TransferPublicAsSignerVerifier::load_bytes().expect("Failed to load transfer_public_as_signer verifier");
TransferPrivateToPublicVerifier::load_bytes().expect("Failed to load transfer_private_to_public verifier");
TransferPublicToPrivateVerifier::load_bytes().expect("Failed to load transfer_public_to_private verifier");
FeePrivateProver::load_bytes().expect("Failed to load fee_private prover");
Expand Down
@@ -0,0 +1,6 @@
{
"prover_checksum": "7cfc669dd92593e052a8a37d6b3a7c40d09f191c754b41230f69e19e9d0f9c76",
"prover_size": 28915282,
"verifier_checksum": "18e99de56f2098b27318dc9b92eee1743792837c27a4a7001ef19a42c7dbb798",
"verifier_size": 665
}
Binary file not shown.
28 changes: 28 additions & 0 deletions synthesizer/process/src/tests/test_credits.rs
Expand Up @@ -2088,6 +2088,34 @@ mod sanity_checks {
assert_eq!((28243, 38006, 16679), assignment.num_nonzeros());
}

#[test]
fn test_sanity_check_transfer_public_as_signer() {
let rng = &mut TestRng::default();

// Initialize a new signer account.
let private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let signer = Address::try_from(&private_key).unwrap();

// Construct a new process.
let process = Process::load().unwrap();
// Retrieve the stack.
let stack = process.get_stack(ProgramID::from_str("credits.aleo").unwrap()).unwrap();

// Declare the function name.
let function_name = Identifier::from_str("transfer_public_as_signer").unwrap();

// Declare the inputs.
let r0 = Value::<CurrentNetwork>::from_str(&format!("{signer}")).unwrap();
let r1 = Value::<CurrentNetwork>::from_str("1_500_000_000_000_000_u64").unwrap();

// Compute the assignment.
let assignment = get_assignment::<_, CurrentAleo>(stack, &private_key, function_name, &[r0, r1], rng);
assert_eq!(11, assignment.num_public());
assert_eq!(12323, assignment.num_private());
assert_eq!(12330, assignment.num_constraints());
assert_eq!((28257, 38029, 16684), assignment.num_nonzeros());
}

#[test]
fn test_sanity_check_fee_private() {
let rng = &mut TestRng::default();
Expand Down
2 changes: 1 addition & 1 deletion synthesizer/process/src/tests/test_execute.rs
Expand Up @@ -478,7 +478,7 @@ output r1 as token.record;",
}

#[test]
fn test_process_execute_transfer_public() {
fn test_process_execute_transfer_public_to_private() {
// Initialize a new program.
let program = Program::<CurrentNetwork>::credits().unwrap();

Expand Down
37 changes: 35 additions & 2 deletions synthesizer/program/src/resources/credits.aleo
Expand Up @@ -713,7 +713,7 @@ finalize set_validator_state:
/**********************************************************************************************************************/

// The `transfer_public` function sends the specified amount
// from the sender's `account` to the receiver's `account`.
// from the caller's `account` to the receiver's `account`.
function transfer_public:
// Input the receiver.
input r0 as address.public;
Expand All @@ -725,7 +725,7 @@ function transfer_public:
output r2 as credits.aleo/transfer_public.future;

finalize transfer_public:
// Input the sender.
// Input the caller.
input r0 as address.public;
// Input the receiver.
input r1 as address.public;
Expand All @@ -745,6 +745,39 @@ finalize transfer_public:

/**********************************************************************************************************************/

// The `transfer_public_as_signer` function sends the specified amount
// from the signer's `account` to the receiver's `account`.
function transfer_public_as_signer:
// Input the receiver.
input r0 as address.public;
// Input the amount.
input r1 as u64.public;
// Transfer the credits publicly.
async transfer_public_as_signer self.signer r0 r1 into r2;
// Output the finalize future.
output r2 as credits.aleo/transfer_public_as_signer.future;

finalize transfer_public_as_signer:
// Input the signer.
input r0 as address.public;
// Input the receiver.
input r1 as address.public;
// Input the amount.
input r2 as u64.public;
// Decrements `account[r0]` by `r2`.
// If `account[r0] - r2` underflows, `transfer_public_as_signer` is reverted.
get account[r0] into r3;
sub r3 r2 into r4;
set r4 into account[r0];
// Increments `account[r1]` by `r2`.
// If `account[r1]` does not exist, 0u64 is used.
// If `account[r1] + r2` overflows, `transfer_public_as_signer` is reverted.
get.or_use account[r1] 0u64 into r5;
add r5 r2 into r6;
set r6 into account[r1];

/**********************************************************************************************************************/

// The `transfer_private` function sends the specified amount
// from the sender's record to the receiver in a record.
function transfer_private:
Expand Down
34 changes: 34 additions & 0 deletions synthesizer/src/vm/execute.rs
Expand Up @@ -317,6 +317,40 @@ mod tests {
}
}

#[test]
fn test_transfer_public_as_signer_transaction_size() {
let rng = &mut TestRng::default();

// Initialize a new signer.
let signer = crate::vm::test_helpers::sample_genesis_private_key(rng);
let address = Address::try_from(&signer).unwrap();

// Prepare the VM and records.
let (vm, _) = prepare_vm(rng).unwrap();

// Prepare the inputs.
let inputs = [
Value::<CurrentNetwork>::from_str(&address.to_string()).unwrap(),
Value::<CurrentNetwork>::from_str("1u64").unwrap(),
]
.into_iter();

// Execute.
let transaction =
vm.execute(&signer, ("credits.aleo", "transfer_public_as_signer"), inputs, None, 0, None, rng).unwrap();

// Assert the size of the transaction.
let transaction_size_in_bytes = transaction.to_bytes_le().unwrap().len();
assert_eq!(2891, transaction_size_in_bytes, "Update me if serialization has changed");

// Assert the size of the execution.
assert!(matches!(transaction, Transaction::Execute(_, _, _)));
if let Transaction::Execute(_, execution, _) = &transaction {
let execution_size_in_bytes = execution.to_bytes_le().unwrap().len();
assert_eq!(1440, execution_size_in_bytes, "Update me if serialization has changed");
}
}

#[test]
fn test_join_transaction_size() {
let rng = &mut TestRng::default();
Expand Down