Skip to content

Commit

Permalink
[move] set slow wallet entry function (#141)
Browse files Browse the repository at this point in the history
Co-authored-by: 0o-de-lally <>
Co-authored-by: 0o-de-lally <[email protected]>
  • Loading branch information
sirouk and 0o-de-lally authored Jan 13, 2024
1 parent 6b57485 commit a4c2f61
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 58 deletions.
36 changes: 36 additions & 0 deletions framework/cached-packages/src/libra_framework_sdk_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,11 @@ pub enum EntryFunctionCall {
code: Vec<Vec<u8>>,
},

/// Users can change their account to slow, by calling the entry function
/// Warning: this is permanent for the account. There's no way to
/// reverse a "slow wallet".
SlowWalletSetSlow {},

SlowWalletSmokeTestVmUnlock {
user_addr: AccountAddress,
unlocked: u64,
Expand Down Expand Up @@ -806,6 +811,7 @@ impl EntryFunctionCall {
metadata_serialized,
code,
),
SlowWalletSetSlow {} => slow_wallet_set_slow(),
SlowWalletSmokeTestVmUnlock {
user_addr,
unlocked,
Expand Down Expand Up @@ -2105,6 +2111,24 @@ pub fn resource_account_create_resource_account_and_publish_package(
))
}

/// Users can change their account to slow, by calling the entry function
/// Warning: this is permanent for the account. There's no way to
/// reverse a "slow wallet".
pub fn slow_wallet_set_slow() -> TransactionPayload {
TransactionPayload::EntryFunction(EntryFunction::new(
ModuleId::new(
AccountAddress::new([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1,
]),
ident_str!("slow_wallet").to_owned(),
),
ident_str!("set_slow").to_owned(),
vec![],
vec![],
))
}

pub fn slow_wallet_smoke_test_vm_unlock(
user_addr: AccountAddress,
unlocked: u64,
Expand Down Expand Up @@ -3064,6 +3088,14 @@ mod decoder {
}
}

pub fn slow_wallet_set_slow(payload: &TransactionPayload) -> Option<EntryFunctionCall> {
if let TransactionPayload::EntryFunction(_script) = payload {
Some(EntryFunctionCall::SlowWalletSetSlow {})
} else {
None
}
}

pub fn slow_wallet_smoke_test_vm_unlock(
payload: &TransactionPayload,
) -> Option<EntryFunctionCall> {
Expand Down Expand Up @@ -3446,6 +3478,10 @@ static SCRIPT_FUNCTION_DECODER_MAP: once_cell::sync::Lazy<EntryFunctionDecoderMa
"resource_account_create_resource_account_and_publish_package".to_string(),
Box::new(decoder::resource_account_create_resource_account_and_publish_package),
);
map.insert(
"slow_wallet_set_slow".to_string(),
Box::new(decoder::slow_wallet_set_slow),
);
map.insert(
"slow_wallet_smoke_test_vm_unlock".to_string(),
Box::new(decoder::slow_wallet_smoke_test_vm_unlock),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,6 @@ module ol_framework::ol_account {
public fun deposit_coins(to: address, coins: Coin<LibraCoin>) acquires
BurnTracker {
assert!(coin::is_account_registered<LibraCoin>(to), error::invalid_state(EACCOUNT_NOT_REGISTERED_FOR_GAS));
slow_wallet::maybe_track_unlocked_deposit(to, coin::value(&coins));
coin::deposit<LibraCoin>(to, coins);
// the incoming coins should trigger an update in tracker
maybe_update_burn_tracker_impl(to);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,10 @@ module ol_framework::slow_wallet {
}
}

public fun set_slow(sig: &signer) acquires SlowWalletList {
/// Users can change their account to slow, by calling the entry function
/// Warning: this is permanent for the account. There's no way to
/// reverse a "slow wallet".
public entry fun set_slow(sig: &signer) acquires SlowWalletList {
assert!(exists<SlowWalletList>(@ol_framework), error::invalid_argument(EGENESIS_ERROR));

let addr = signer::address_of(sig);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,23 +44,23 @@ module ol_framework::test_slow_wallet {
let a = vector::borrow(&set, 0);

assert!(slow_wallet::is_slow(*a), 7357000);
assert!(slow_wallet::unlocked_amount(*a) == 100, 735701);
assert!(slow_wallet::unlocked_amount(*a) == 0, 735701);

let coin = transaction_fee::test_root_withdraw_all(&root);
rewards::test_helper_pay_reward(&root, *a, coin, 0);

let (u, b) = ol_account::balance(*a);
assert!(b==100000100, 735702);
assert!(u==100, 735703);
assert!(u==0, 735703);

slow_wallet::slow_wallet_epoch_drip(&root, 233);
let (u, b) = ol_account::balance(*a);
assert!(b==100000100, 735704);
assert!(u==333, 735705);
assert!(u==233, 735705);
}

#[test(root = @ol_framework, alice = @0x123, bob = @0x456)]
fun test_deposit_unlocked_happy(root: signer, alice: signer) {
fun test_deposit_locked_happy(root: signer, alice: signer) {
mock::ol_test_genesis(&root);
let mint_cap = libra_coin::extract_mint_cap(&root);

Expand All @@ -79,59 +79,68 @@ module ol_framework::test_slow_wallet {
let alice_init_balance = 10000;
ol_account::deposit_coins(@0x123, coin::test_mint(alice_init_balance, &mint_cap));
coin::destroy_mint_cap(mint_cap);
// the transfer was of already unlocked coins, so they will post as unlocked on alice
assert!(slow_wallet::unlocked_amount(@0x123) == alice_init_balance, 735703);
// the deposit was not unlocked coins, so there should be no unlocked coins
assert!(slow_wallet::unlocked_amount(@0x123) == 0, 735703);
assert!(slow_wallet::transferred_amount(@0x123) == 0, 735704);

}


#[test(root = @ol_framework, alice = @0x123, bob = @0x456)]
fun test_transfer_unlocked_happy(root: signer, alice: signer) {
// scenario: testing sending unlocked coins from slow wallet to slow wallet
#[test(root = @ol_framework, alice = @0x123, bob = @0x456, carol = @0x789)]
fun test_transfer_unlocked_happy(root: signer, alice: signer, bob: signer, carol: signer) {
mock::ol_test_genesis(&root);
let mint_cap = libra_coin::extract_mint_cap(&root);

slow_wallet::initialize(&root);


// create alice account
// create alice, bob, and carol accounts
ol_account::create_account(&root, @0x123);
ol_account::create_account(&root, @0x456);
ol_account::create_account(&root, @0x789);

slow_wallet::set_slow(&alice);
// Make bob and carol accounts slow
slow_wallet::set_slow(&bob);
slow_wallet::set_slow(&carol);

assert!(slow_wallet::is_slow(@0x123), 7357000);
assert!(slow_wallet::unlocked_amount(@0x123) == 0, 735701);
assert!(slow_wallet::is_slow(@0x456), 7357000);
assert!(slow_wallet::unlocked_amount(@0x456) == 0, 735701);
assert!(slow_wallet::transferred_amount(@0x456) == 0, 735710);
assert!(slow_wallet::is_slow(@0x789), 7357011);
assert!(slow_wallet::unlocked_amount(@0x789) == 0, 735712);
assert!(slow_wallet::transferred_amount(@0x789) == 0, 735713);

// add some coins to alice
// add some coins to alice which are unlocked since they are not a slow wallet
let alice_init_balance = 10000;
ol_account::deposit_coins(@0x123, coin::test_mint(alice_init_balance, &mint_cap));
coin::destroy_mint_cap(mint_cap);
// the transfer was of already unlocked coins, so they will post as unlocked on alice
assert!(slow_wallet::unlocked_amount(@0x123) == alice_init_balance, 735703);
assert!(slow_wallet::transferred_amount(@0x123) == 0, 735704);


// transferring funds will create Bob's account
// the coins are also unlocked
let transfer_amount = 10;
ol_account::transfer(&alice, @0x456, transfer_amount);
// slow transfer
let b_balance = coin::balance<LibraCoin>(@0x456);
assert!(b_balance == transfer_amount, 735704);
assert!(slow_wallet::unlocked_amount(@0x123) == (alice_init_balance - transfer_amount), 735705);
assert!(slow_wallet::unlocked_amount(@0x456) == transfer_amount, 735706);

// alice should show a slow wallet transfer amount equal to sent;
assert!(slow_wallet::transferred_amount(@0x123) == transfer_amount, 735707);
// bob should show no change
assert!(slow_wallet::transferred_amount(@0x456) == 0, 735708);

// transfer unlocked coins from alice to bob
let alice_to_bob_transfer_amount = 100;
ol_account::transfer(&alice, @0x456, alice_to_bob_transfer_amount);

// the transfer was of already unlocked coins, so they will post as unlocked on bob
assert!(slow_wallet::unlocked_amount(@0x456) == alice_to_bob_transfer_amount, 735703);
assert!(slow_wallet::transferred_amount(@0x456) == 0, 735704);

// transfer 10 of bob's unlocked coins to carol
let bob_to_carol_transfer_amount = 10;
ol_account::transfer(&bob, @0x789, bob_to_carol_transfer_amount);
let b_balance = coin::balance<LibraCoin>(@0x789);
assert!(b_balance == bob_to_carol_transfer_amount, 735704);
assert!(slow_wallet::unlocked_amount(@0x456) == (alice_to_bob_transfer_amount - bob_to_carol_transfer_amount), 735705);
assert!(slow_wallet::unlocked_amount(@0x789) == bob_to_carol_transfer_amount, 735706);

// bob should show a slow wallet transfer amount equal to sent;
assert!(slow_wallet::transferred_amount(@0x456) == bob_to_carol_transfer_amount, 735707);
// carol should show no change
assert!(slow_wallet::transferred_amount(@0x789) == 0, 735708);

}

// scenario: testing trying send more funds than are unlocked
#[test(root = @ol_framework, alice = @0x123, bob = @0x456)]
#[expected_failure(abort_code = 196614, location = 0x1::ol_account)]
fun test_transfer_sad(root: signer, alice: signer) {
fun test_transfer_sad_no_unlocked_coins(root: signer, alice: signer) {
mock::ol_test_genesis(&root);
let mint_cap = libra_coin::extract_mint_cap(&root);
slow_wallet::initialize(&root);
Expand All @@ -140,23 +149,14 @@ module ol_framework::test_slow_wallet {
assert!(slow_wallet::is_slow(@0x123), 7357000);
assert!(slow_wallet::unlocked_amount(@0x123) == 0, 735701);

// fund alice
// let (burn_cap, mint_cap) = libra_coin::initialize_for_test(&root);
// fund alice with locked-only coins
ol_account::deposit_coins(@0x123, coin::test_mint(100, &mint_cap));
// coin::destroy_burn_cap(burn_cap);
coin::destroy_mint_cap(mint_cap);

// alice will transfer and create bob's account
ol_account::transfer(&alice, @0x456, 99);

let b_balance = coin::balance<LibraCoin>(@0x456);
assert!(b_balance == 99, 735702);
assert!(slow_wallet::unlocked_amount(@0x123) == 01, 735703);

ol_account::transfer(&alice, @0x456, 200); // TOO MUCH, should fail
}


#[test(root = @ol_framework)]
// we are testing that genesis creates the needed struct
// and a validator creation sets the users account to slow.
Expand Down
Binary file modified framework/releases/head.mrb
Binary file not shown.
18 changes: 18 additions & 0 deletions tools/genesis/src/supply.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,8 @@ fn test_genesis_math() {
// future uses is intended to equal 70% in this scenario.

supply.set_ratios_from_settings(&settings).unwrap();

println!("after");
dbg!(&supply);

// escrow comes out of validator locked only
Expand All @@ -240,4 +242,20 @@ fn test_genesis_math() {

let sum_all = to_escrow + new_slow + supply.normal + supply.donor_directed + supply.make_whole;
assert!(supply.total == sum_all);

dbg!(supply.normal / supply.total);
dbg!(supply.donor_directed / supply.total);
dbg!(supply.slow_total / supply.total);
dbg!(supply.slow_unlocked / supply.total);
dbg!(supply.make_whole / supply.total);

let out_of_play = supply.donor_directed + (supply.slow_total - supply.slow_unlocked);
let in_play_a = supply.total - out_of_play;

dbg!(in_play_a / supply.total);

let in_play_b = supply.make_whole + supply.normal + supply.slow_unlocked;
dbg!(in_play_b / supply.total);

assert!(in_play_a == in_play_b);
}
45 changes: 34 additions & 11 deletions tools/txs/src/txs_cli_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use diem_types::{
account_address::AccountAddress, account_config::CORE_CODE_ADDRESS,
transaction::TransactionPayload,
};
use libra_cached_packages::libra_stdlib::account_rotate_authentication_key;
use libra_cached_packages::libra_stdlib;
use libra_types::{
exports::{AuthenticationKey, Ed25519PrivateKey},
type_extensions::client_ext::ClientExt,
Expand All @@ -17,30 +17,53 @@ use libra_wallet::account_keys::get_keys_from_prompt;
#[derive(clap::Subcommand)]
pub enum UserTxs {
RotateKey(RotateKeyTx),
}

#[derive(clap::Args)]
pub struct RotateKeyTx {
#[clap(short, long)]
/// The new authkey to be used
new_private_key: Option<String>, // Dev NOTE: account address has the same bytes as AuthKey
SetSlow(SetSlowTx),
}

impl UserTxs {
pub async fn run(&self, sender: &mut Sender) -> anyhow::Result<()> {
match &self {
UserTxs::RotateKey(tx) => match tx.run(sender).await {
Ok(_) => println!("SUCCESS: privated key rotated"),
UserTxs::RotateKey(rotate) => match rotate.run(sender).await {
Ok(_) => println!("SUCCESS: private key rotated"),
Err(e) => {
println!("ERROR: could not rotate private key, message: {}", e);
}
},
UserTxs::SetSlow(slow) => match slow.run(sender).await {
Ok(_) => println!("SUCCESS: account set to Slow Wallet"),
Err(e) => {
println!(
"ERROR: could set the account to Slow Wallet, message: {}",
e
);
}
},
}

Ok(())
}
}

#[derive(clap::Args)]
pub struct SetSlowTx {
// TODO: any arguments needed? Confirmation?
}

impl SetSlowTx {
pub async fn run(&self, sender: &mut Sender) -> anyhow::Result<()> {
let payload = libra_stdlib::slow_wallet_set_slow();
sender.sign_submit_wait(payload).await?;
Ok(())
}
}

#[derive(clap::Args)]
pub struct RotateKeyTx {
#[clap(short, long)]
/// The new authkey to be used
new_private_key: Option<String>, // Dev NOTE: account address has the same bytes as AuthKey
}

impl RotateKeyTx {
pub async fn run(&self, sender: &mut Sender) -> anyhow::Result<()> {
let user_account: AccountAddress = sender.local_account.address();
Expand Down Expand Up @@ -94,7 +117,7 @@ pub fn rotate_key(
let rotation_proof_signed_by_new_private_key =
new_private_key.sign_arbitrary_message(&rotation_msg);

let payload = account_rotate_authentication_key(
let payload = libra_stdlib::account_rotate_authentication_key(
0,
// Existing public key
current_private_key.public_key().to_bytes().to_vec(),
Expand Down

0 comments on commit a4c2f61

Please sign in to comment.