From 8164cd26d9a6beb5b5ca7d3d6f02c5fa3f63d5aa Mon Sep 17 00:00:00 2001 From: soaresa <10797037+soaresa@users.noreply.github.com> Date: Tue, 13 Aug 2024 16:36:55 -0300 Subject: [PATCH] [move] enhance vouch system [breaking] (#303) --- .../src/libra_framework_sdk_builder.rs | 32 +- .../sources/create_signer.move | 1 + .../ol_sources/{ => config}/globals.move | 11 +- .../sources/ol_sources/epoch_boundary.move | 9 +- .../sources/ol_sources/migrations.move | 98 ++++ .../sources/ol_sources/mock.move | 20 +- .../sources/ol_sources/proof_of_fee.move | 40 +- .../ol_sources/tests/proof_of_fee.test.move | 83 +++- .../sources/ol_sources/tests/vouch.test.move | 336 +++++++++++++ .../tests/vouch_migration.test.move | 166 +++++++ .../ol_sources/validator_universe.move | 2 +- .../sources/ol_sources/vouch.move | 458 ++++++++++++++---- .../sources/ol_sources/vouch_migration.move | 33 ++ framework/releases/head.mrb | Bin 879183 -> 890459 bytes tools/txs/src/txs_cli_vals.rs | 4 +- 15 files changed, 1154 insertions(+), 139 deletions(-) rename framework/libra-framework/sources/ol_sources/{ => config}/globals.move (95%) create mode 100644 framework/libra-framework/sources/ol_sources/migrations.move create mode 100644 framework/libra-framework/sources/ol_sources/tests/vouch.test.move create mode 100644 framework/libra-framework/sources/ol_sources/tests/vouch_migration.test.move create mode 100644 framework/libra-framework/sources/ol_sources/vouch_migration.move diff --git a/framework/cached-packages/src/libra_framework_sdk_builder.rs b/framework/cached-packages/src/libra_framework_sdk_builder.rs index 83266963c..a3bae1d52 100644 --- a/framework/cached-packages/src/libra_framework_sdk_builder.rs +++ b/framework/cached-packages/src/libra_framework_sdk_builder.rs @@ -533,18 +533,18 @@ pub enum EntryFunctionCall { /// you may want to add people who are related to you /// there are no known use cases for this at the moment. VouchInsistVouchFor { - wanna_be_my_friend: AccountAddress, + friend_account: AccountAddress, }, VouchRevoke { - its_not_me_its_you: AccountAddress, + friend_account: AccountAddress, }, /// will only succesfully vouch if the two are not related by ancestry /// prevents spending a vouch that would not be counted. /// to add a vouch and ignore this check use insist_vouch VouchVouchFor { - wanna_be_my_friend: AccountAddress, + friend_account: AccountAddress, }, } @@ -856,11 +856,9 @@ impl EntryFunctionCall { fullnode_addresses, ), VersionSetVersion { major } => version_set_version(major), - VouchInsistVouchFor { wanna_be_my_friend } => { - vouch_insist_vouch_for(wanna_be_my_friend) - } - VouchRevoke { its_not_me_its_you } => vouch_revoke(its_not_me_its_you), - VouchVouchFor { wanna_be_my_friend } => vouch_vouch_for(wanna_be_my_friend), + VouchInsistVouchFor { friend_account } => vouch_insist_vouch_for(friend_account), + VouchRevoke { friend_account } => vouch_revoke(friend_account), + VouchVouchFor { friend_account } => vouch_vouch_for(friend_account), } } @@ -2329,7 +2327,7 @@ pub fn version_set_version(major: u64) -> TransactionPayload { /// you may want to add people who are related to you /// there are no known use cases for this at the moment. -pub fn vouch_insist_vouch_for(wanna_be_my_friend: AccountAddress) -> TransactionPayload { +pub fn vouch_insist_vouch_for(friend_account: AccountAddress) -> TransactionPayload { TransactionPayload::EntryFunction(EntryFunction::new( ModuleId::new( AccountAddress::new([ @@ -2340,11 +2338,11 @@ pub fn vouch_insist_vouch_for(wanna_be_my_friend: AccountAddress) -> Transaction ), ident_str!("insist_vouch_for").to_owned(), vec![], - vec![bcs::to_bytes(&wanna_be_my_friend).unwrap()], + vec![bcs::to_bytes(&friend_account).unwrap()], )) } -pub fn vouch_revoke(its_not_me_its_you: AccountAddress) -> TransactionPayload { +pub fn vouch_revoke(friend_account: AccountAddress) -> TransactionPayload { TransactionPayload::EntryFunction(EntryFunction::new( ModuleId::new( AccountAddress::new([ @@ -2355,14 +2353,14 @@ pub fn vouch_revoke(its_not_me_its_you: AccountAddress) -> TransactionPayload { ), ident_str!("revoke").to_owned(), vec![], - vec![bcs::to_bytes(&its_not_me_its_you).unwrap()], + vec![bcs::to_bytes(&friend_account).unwrap()], )) } /// will only succesfully vouch if the two are not related by ancestry /// prevents spending a vouch that would not be counted. /// to add a vouch and ignore this check use insist_vouch -pub fn vouch_vouch_for(wanna_be_my_friend: AccountAddress) -> TransactionPayload { +pub fn vouch_vouch_for(friend_account: AccountAddress) -> TransactionPayload { TransactionPayload::EntryFunction(EntryFunction::new( ModuleId::new( AccountAddress::new([ @@ -2373,7 +2371,7 @@ pub fn vouch_vouch_for(wanna_be_my_friend: AccountAddress) -> TransactionPayload ), ident_str!("vouch_for").to_owned(), vec![], - vec![bcs::to_bytes(&wanna_be_my_friend).unwrap()], + vec![bcs::to_bytes(&friend_account).unwrap()], )) } mod decoder { @@ -3206,7 +3204,7 @@ mod decoder { pub fn vouch_insist_vouch_for(payload: &TransactionPayload) -> Option { if let TransactionPayload::EntryFunction(script) = payload { Some(EntryFunctionCall::VouchInsistVouchFor { - wanna_be_my_friend: bcs::from_bytes(script.args().first()?).ok()?, + friend_account: bcs::from_bytes(script.args().first()?).ok()?, }) } else { None @@ -3216,7 +3214,7 @@ mod decoder { pub fn vouch_revoke(payload: &TransactionPayload) -> Option { if let TransactionPayload::EntryFunction(script) = payload { Some(EntryFunctionCall::VouchRevoke { - its_not_me_its_you: bcs::from_bytes(script.args().first()?).ok()?, + friend_account: bcs::from_bytes(script.args().first()?).ok()?, }) } else { None @@ -3226,7 +3224,7 @@ mod decoder { pub fn vouch_vouch_for(payload: &TransactionPayload) -> Option { if let TransactionPayload::EntryFunction(script) = payload { Some(EntryFunctionCall::VouchVouchFor { - wanna_be_my_friend: bcs::from_bytes(script.args().first()?).ok()?, + friend_account: bcs::from_bytes(script.args().first()?).ok()?, }) } else { None diff --git a/framework/libra-framework/sources/create_signer.move b/framework/libra-framework/sources/create_signer.move index a64c29882..d28c229f6 100644 --- a/framework/libra-framework/sources/create_signer.move +++ b/framework/libra-framework/sources/create_signer.move @@ -20,6 +20,7 @@ module diem_framework::create_signer { friend ol_framework::fee_maker; friend ol_framework::epoch_boundary; friend ol_framework::multi_action_migration; // TODO: remove after offer migration is completed + friend ol_framework::vouch_migration; // TODO: remove after vouch migration is completed public(friend) native fun create_signer(addr: address): signer; } diff --git a/framework/libra-framework/sources/ol_sources/globals.move b/framework/libra-framework/sources/ol_sources/config/globals.move similarity index 95% rename from framework/libra-framework/sources/ol_sources/globals.move rename to framework/libra-framework/sources/ol_sources/config/globals.move index 0d0779697..bac2b08ca 100644 --- a/framework/libra-framework/sources/ol_sources/globals.move +++ b/framework/libra-framework/sources/ol_sources/config/globals.move @@ -25,6 +25,7 @@ module ol_framework::globals { min_blocks_per_epoch: u64, validator_vouch_threshold: u64, signing_threshold_pct: u64, + max_vouches_per_validator: u64, } const COIN_DECIMAL_PLACES: u8 = 6; // Or 10^6, 1 coin is 1_000_000 units in the database. Any human display needs to consider this scaling factor. @@ -90,6 +91,11 @@ module ol_framework::globals { get_constants().validator_vouch_threshold } + /// Get the max number of vouches per validator + public fun get_max_vouches_per_validator(): u64 { + get_constants().max_vouches_per_validator + } + /// Get the threshold of number of signed blocks in an epoch per validator public fun get_signing_threshold(): u64 { get_constants().signing_threshold_pct @@ -113,6 +119,7 @@ module ol_framework::globals { min_blocks_per_epoch: 0, validator_vouch_threshold: 0, signing_threshold_pct: 3, + max_vouches_per_validator: 10, } }; @@ -137,6 +144,7 @@ module ol_framework::globals { min_blocks_per_epoch: 10000, validator_vouch_threshold: 2, // Production must be more than 1 vouch validator (at least 2) signing_threshold_pct: 3, + max_vouches_per_validator: 10, } } else { return GlobalConstants { @@ -157,7 +165,8 @@ module ol_framework::globals { min_blocks_per_epoch: 10000, validator_vouch_threshold: 2, // Production must be more than 1 vouch validator (at least 2) signing_threshold_pct: 3, + max_vouches_per_validator: 10, } } } -} \ No newline at end of file +} diff --git a/framework/libra-framework/sources/ol_sources/epoch_boundary.move b/framework/libra-framework/sources/ol_sources/epoch_boundary.move index ba93fa84c..b4f65c337 100644 --- a/framework/libra-framework/sources/ol_sources/epoch_boundary.move +++ b/framework/libra-framework/sources/ol_sources/epoch_boundary.move @@ -11,13 +11,15 @@ module diem_framework::epoch_boundary { use diem_framework::reconfiguration; use diem_framework::transaction_fee; use diem_framework::system_addresses; - use ol_framework::stake; use ol_framework::jail; use ol_framework::safe; use ol_framework::burn; + use ol_framework::stake; + use ol_framework::vouch; use ol_framework::rewards; use ol_framework::testnet; use ol_framework::fee_maker; + use ol_framework::migrations; use ol_framework::libra_coin; use ol_framework::slow_wallet; use ol_framework::match_index; @@ -265,6 +267,7 @@ module diem_framework::epoch_boundary { // when new modules or structures are added by chain upgrades. fun migrate_data(root: &signer) { randomness::initialize(root); + migrations::execute(root); } // Contains all of 0L's business logic for end of epoch. @@ -330,6 +333,10 @@ module diem_framework::epoch_boundary { status.pof_thermo_increase = t_increase; status.pof_thermo_amount = t_amount; + print(&string::utf8(b"set_vouch_price")); + let (nominal_reward, _, _, _) = proof_of_fee::get_consensus_reward(); + vouch::set_vouch_price(root, nominal_reward); + print(&string::utf8(b"subsidize_from_infra_escrow")); let (i_success, i_fee) = subsidize_from_infra_escrow(root); status.infra_subsidize_amount = i_fee; diff --git a/framework/libra-framework/sources/ol_sources/migrations.move b/framework/libra-framework/sources/ol_sources/migrations.move new file mode 100644 index 000000000..e1bb096ea --- /dev/null +++ b/framework/libra-framework/sources/ol_sources/migrations.move @@ -0,0 +1,98 @@ +module ol_framework::migrations { + use std::vector; + use std::string; + use std::error; + use diem_framework::system_addresses; + use ol_framework::epoch_helper; + + use diem_std::debug::print; + + // migrations + use ol_framework::vouch_migration; + + //////// CONST //////// + const EMIGRATIONS_NOT_INITIALIZED: u64 = 1; + + //////// STRUCTS //////// + struct Migration has store, copy { + number: u64, + epoch: u64, + description: vector, + } + + struct Migrations has key { + last_migration: u64, + history: vector, + } + + public fun execute(root: &signer) acquires Migrations { + // ensure ol_framework + system_addresses::assert_ol(root); + + // execute all migrations + if (apply_migration(root, 1, b"Vouch migration initializes GivenVouches, ReceivedVouches, and drop MyVouches")) { + vouch_migration::migrate_my_vouches(); + }; + + } + + fun apply_migration(root: &signer, mig_number: u64, description: vector): bool acquires Migrations { + if (can_execute_migration(mig_number)) { + print(&string::utf8(b">>> Migration started:")); + print(&mig_number); + print(&string::utf8(description)); + + register_migration(root, mig_number, description); + true + } else { + false + } + } + + fun can_execute_migration(mig_number: u64): bool acquires Migrations { + get_last_migration_number() < mig_number + } + + fun register_migration(root: &signer, mig_number: u64, description: vector) acquires Migrations { + let epoch = epoch_helper::get_current_epoch(); + + if (exists(@ol_framework)) { + // update + let state = borrow_global_mut(@diem_framework); + state.last_migration = mig_number; + vector::push_back(&mut state.history, Migration { + number: mig_number, + epoch: epoch, + description: description, + }); + } else { + // initialize + move_to(root, Migrations { + last_migration: mig_number, + history: vector[Migration { + number: mig_number, + epoch: epoch, + description: description, + }], + }); + }; + } + + public fun get_last_migration_number(): u64 acquires Migrations { + if (!exists(@ol_framework)) { + return 0 + }; + + let state = borrow_global(@ol_framework); + state.last_migration + } + + public fun get_last_migrations_history(): (u64, u64, vector) acquires Migrations { + assert!(exists(@ol_framework), error::invalid_state(EMIGRATIONS_NOT_INITIALIZED)); + + let state = borrow_global(@ol_framework); + let last_migration = vector::borrow(&state.history, vector::length(&state.history) -1); + (last_migration.number, last_migration.epoch, last_migration.description) + } + +} diff --git a/framework/libra-framework/sources/ol_sources/mock.move b/framework/libra-framework/sources/ol_sources/mock.move index 40acbcecd..8bf813019 100644 --- a/framework/libra-framework/sources/ol_sources/mock.move +++ b/framework/libra-framework/sources/ol_sources/mock.move @@ -257,6 +257,17 @@ module ol_framework::mock { #[test_only] /// mock up to 6 validators alice..frank public fun genesis_n_vals(root: &signer, num: u64): vector
{ + // create vals with vouches + create_vals(root, num, true); + + timestamp::fast_forward_seconds(2); // or else reconfigure wont happen + stake::test_reconfigure(root, validator_universe::get_eligible_validators()); + + stake::get_current_validators() + } + + #[test_only] + public fun create_vals(root: &signer, num: u64, with_vouches: bool) { system_addresses::assert_ol(root); let framework_sig = account::create_signer_for_test(@diem_framework); ol_test_genesis(&framework_sig); @@ -273,15 +284,12 @@ module ol_framework::mock { validator_universe::test_register_validator(root, &pk, &pop, &sig, 100, true, true); vouch::init(&sig); - vouch::test_set_buddies(*val, val_addr); + if (with_vouches) { + vouch::test_set_buddies(*val, val_addr); + }; i = i + 1; }; - - timestamp::fast_forward_seconds(2); // or else reconfigure wont happen - stake::test_reconfigure(root, validator_universe::get_eligible_validators()); - - stake::get_current_validators() } #[test_only] diff --git a/framework/libra-framework/sources/ol_sources/proof_of_fee.move b/framework/libra-framework/sources/ol_sources/proof_of_fee.move index bfc57be74..abf96b859 100644 --- a/framework/libra-framework/sources/ol_sources/proof_of_fee.move +++ b/framework/libra-framework/sources/ol_sources/proof_of_fee.move @@ -12,16 +12,16 @@ module ol_framework::proof_of_fee { use std::vector; use std::math64; use std::fixed_point32; - use diem_framework::validator_universe; - use diem_framework::transaction_fee; - use diem_framework::account; use diem_framework::stake; + use diem_framework::account; + use diem_framework::transaction_fee; use diem_framework::system_addresses; + use diem_framework::validator_universe; use ol_framework::jail; - use ol_framework::slow_wallet; use ol_framework::vouch; - use ol_framework::epoch_helper; use ol_framework::globals; + use ol_framework::slow_wallet; + use ol_framework::epoch_helper; use ol_framework::address_utils; //use diem_std::debug::print; @@ -32,9 +32,9 @@ module ol_framework::proof_of_fee { #[test_only] friend ol_framework::mock; + //////// CONST //////// /// The nominal reward for each validator in each epoch. - const GENESIS_BASELINE_REWARD: u64 = 1000000; - + const GENESIS_BASELINE_REWARD: u64 = 1_000_000; /// Number of vals needed before PoF becomes competitive for /// performant nodes as well const VAL_BOOT_UP_THRESHOLD: u64 = 21; @@ -51,6 +51,8 @@ module ol_framework::proof_of_fee { const SHORT_WINDOW: u64 = 5; // 5 epochs /// Long window period for extended bid trends. const LONG_WINDOW: u64 = 10; // 10 epochs + /// Margin for vouches + const VOUCH_MARGIN: u64 = 2; //////// ERRORS ///////// /// Not an active validator @@ -302,12 +304,34 @@ module ol_framework::proof_of_fee { public fun get_valid_vouchers_in_set(incoming_addr: address): (bool, u64) { let val_set = stake::get_current_validators(); let (frens_in_val_set, _found) = vouch::true_friends_in_list(incoming_addr, &val_set); - let threshold = globals::get_validator_vouch_threshold(); + let threshold = calculate_min_vouches_required(vector::length(&val_set)); let count_in_set = vector::length(&frens_in_val_set); (count_in_set >= threshold, count_in_set) } + #[view] + /// calculate the minimum vouches required for a validator to be seated + /// @params set_size the size of the validator set + /// @returns the minimum vouches required + public fun calculate_min_vouches_required(set_size: u64): u64 { + let required = globals::get_validator_vouch_threshold(); + + // TODO: set a features switch here + //if (false) { + if (set_size > VAL_BOOT_UP_THRESHOLD) { + // dynamically increase the amount of social proofing as the + // validator set increases + required = math64::min( + (set_size / 10) + 1, // formula to get the min vouches required after bootup + globals::get_max_vouches_per_validator() - VOUCH_MARGIN + ); + }; + //}; + + required + } + // Here we place the bidders into their seats. // The order of the bids will determine placement. diff --git a/framework/libra-framework/sources/ol_sources/tests/proof_of_fee.test.move b/framework/libra-framework/sources/ol_sources/tests/proof_of_fee.test.move index 26a849121..f1aa0fe21 100644 --- a/framework/libra-framework/sources/ol_sources/tests/proof_of_fee.test.move +++ b/framework/libra-framework/sources/ol_sources/tests/proof_of_fee.test.move @@ -10,9 +10,10 @@ module ol_framework::test_pof { use ol_framework::testnet; use ol_framework::globals; use diem_framework::stake; + use diem_framework::chain_id; use std::vector; - // use diem_std::debug::print; + //use diem_std::debug::print; const Alice: address = @0x1000a; const Bob: address = @0x1000b; @@ -649,4 +650,84 @@ module ol_framework::test_pof { assert!(did_increment == false, 7357050); assert!(amount == nominal_reward / 10, 7357051); } + // Tests for fun calculate_min_vouches_required + + #[test(root = @ol_framework)] + fun test_calculate_min_vouches_required_equal_to_threshold(root: signer) { + chain_id::initialize_for_test(&root, 1); + let set_size = 21; // Equal to VAL_BOOT_UP_THRESHOLD + let min_vouches = proof_of_fee::calculate_min_vouches_required(set_size); + assert!(min_vouches == 2, 7357001); // Expecting the global threshold value + } + + #[test(root = @ol_framework)] + fun test_calculate_min_vouches_required_boundary_over_bootup(root: signer) { + chain_id::initialize_for_test(&root, 1); + + let set_size = 22; // Boundary condition at 1 over boot-up + let min_vouches = proof_of_fee::calculate_min_vouches_required(set_size); + assert!(min_vouches == 3, 7357007); // Expecting dynamic calculation result + } + + #[test(root = @ol_framework)] + fun test_calculate_min_vouches_required_boundary_below_bootup(root: signer) { + chain_id::initialize_for_test(&root, 1); + + let set_size = 20; // Boundary condition at 1 below boot-up + let min_vouches = proof_of_fee::calculate_min_vouches_required(set_size); + assert!(min_vouches == 2, 7357008); // Expecting the global threshold value + } + + #[test(root = @ol_framework)] + fun test_calculate_min_vouches_required_above_threshold(root: signer) { + chain_id::initialize_for_test(&root, 1); + + let set_size = 29; + let min_vouches = proof_of_fee::calculate_min_vouches_required(set_size); + assert!(min_vouches == 3, 7357010); // Expecting dynamic calculation result + + let set_size = 30; + let min_vouches = proof_of_fee::calculate_min_vouches_required(set_size); + assert!(min_vouches == 4, 7357011); // Expecting dynamic calculation result + + let set_size = 31; + let min_vouches = proof_of_fee::calculate_min_vouches_required(set_size); + assert!(min_vouches == 4, 7357012); // Expecting dynamic calculation result + } + + #[test(root = @ol_framework)] + fun test_calculate_min_vouches_required_min_set_size(root: signer) { + chain_id::initialize_for_test(&root, 1); + + let set_size = 0; // Smallest possible set size + let min_vouches = proof_of_fee::calculate_min_vouches_required(set_size); + assert!(min_vouches == 2, 7357003); // Expecting the global threshold value + } + + #[test(root = @ol_framework)] + fun test_calculate_min_vouches_required_max_set_size(root: signer) { + chain_id::initialize_for_test(&root, 1); + + let set_size = 10_000; // Very large set size + let min_vouches = proof_of_fee::calculate_min_vouches_required(set_size); + assert!(min_vouches == 8, 7357004); // Expecting max vouches minus margin + } + + #[test(root = @ol_framework)] + fun test_calculate_min_vouches_required_exact_match(root: signer) { + chain_id::initialize_for_test(&root, 1); + + let set_size = 78; // Exact calculation match case + let min_vouches = proof_of_fee::calculate_min_vouches_required(set_size); + assert!(min_vouches == 8, 7357005); // Expecting max vouches minus margin + } + + #[test(root = @ol_framework)] + fun test_calculate_min_vouches_required_edge_vouch_margin(root: signer) { + chain_id::initialize_for_test(&root, 1); + + let set_size = 80; // Edge case at vouch margin + let min_vouches = proof_of_fee::calculate_min_vouches_required(set_size); + assert!(min_vouches == 8, 7357006); // Expecting max vouches minus margin + } } diff --git a/framework/libra-framework/sources/ol_sources/tests/vouch.test.move b/framework/libra-framework/sources/ol_sources/tests/vouch.test.move new file mode 100644 index 000000000..17a1acde8 --- /dev/null +++ b/framework/libra-framework/sources/ol_sources/tests/vouch.test.move @@ -0,0 +1,336 @@ +#[test_only] +module ol_framework::test_vouch { + use std::vector; + use ol_framework::vouch; + use ol_framework::mock; + use ol_framework::proof_of_fee; + + // use diem_std::debug::print; + + // Happy Day scenarios + + #[test(root = @ol_framework, alice = @0x1000a, bob = @0x1000b, carol = @0x1000c)] + fun vouch_for_unrelated(root: &signer, alice: &signer, carol: &signer) { + // create vals without vouches + mock::create_vals(root, 3, false); + vouch::set_vouch_price(root, 0); + + // check that no vouches exist + vector::for_each(vector[@0x1000a, @0x1000b, @0x1000c], |addr| { + let (given_vouches, given_epochs) = vouch::get_given_vouches(addr); + assert!(given_vouches == vector::empty(), 73570001); + assert!(given_epochs == vector::empty(), 73570002); + let (received_vouches, received_epochs) = vouch::get_received_vouches(addr); + assert!(received_vouches == vector::empty(), 73570003); + assert!(received_epochs == vector::empty(), 73570004); + }); + + // alice vouches for bob + vouch::vouch_for(alice, @0x1000b); + + // check alice + let (given_vouches, given_epochs) = vouch::get_given_vouches(@0x1000a); + assert!(given_vouches == vector[@0x1000b], 73570005); + assert!(given_epochs == vector[0], 73570006); + + // check bob + let (received_vouches, received_epochs) = vouch::get_received_vouches(@0x1000b); + assert!(received_vouches == vector[@0x1000a], 73570007); + assert!(received_epochs == vector[0], 73570008); + + // fast forward to epoch 1 + mock::trigger_epoch(root); + + // carol vouches for bob + vouch::vouch_for(carol, @0x1000b); + + // check alice + let (given_vouches, given_epochs) = vouch::get_given_vouches(@0x1000a); + assert!(given_vouches == vector[@0x1000b], 73570005); + assert!(given_epochs == vector[0], 73570006); + + // check carol + let (given_vouches, given_epochs) = vouch::get_given_vouches(@0x1000c); + assert!(given_vouches == vector[@0x1000b], 73570009); + assert!(given_epochs == vector[1], 73570010); + + // check bob + let (received_vouches, received_epochs) = vouch::get_received_vouches(@0x1000b); + assert!(received_vouches == vector[@0x1000a, @0x1000c], 73570011); + assert!(received_epochs == vector[0, 1], 73570012); + } + + #[test(root = @ol_framework, alice = @0x1000a, bob = @0x1000b, carol = @0x1000c)] + fun revoke_vouch(root: &signer, alice: &signer, carol: &signer) { + // create vals without vouches + mock::create_vals(root, 3, false); + vouch::set_vouch_price(root, 0); + + // alice and carol vouches for bob + vouch::vouch_for(alice, @0x1000b); + vouch::vouch_for(carol, @0x1000b); + + // alice revokes vouch for bob + vouch::revoke(alice, @0x1000b); + + // check alice + let (given_vouches, given_epochs) = vouch::get_given_vouches(@0x1000a); + assert!(given_vouches == vector::empty(), 73570013); + assert!(given_epochs == vector::empty(), 73570014); + + // check bob + let (received_vouches, received_epochs) = vouch::get_received_vouches(@0x1000b); + assert!(received_vouches == vector[@0x1000c], 73570015); + assert!(received_epochs == vector[0], 73570016); + } + + #[test(root = @ol_framework, alice = @0x1000a, bob = @0x1000b, carol = @0x1000c)] + fun epoch_boundary_update_vouch_price(root: &signer) { + // check default vouch micro-price + assert!(vouch::get_vouch_price() == 1_000, 73570025); + + // initialize vals and vouch price + mock::genesis_n_vals(root, 3); + vouch::set_vouch_price(root, 0); + assert!(vouch::get_vouch_price() == 0, 73570025); + + // mock to increase reward on the next epoch + proof_of_fee::test_mock_reward(root, 5_000, 1_000, 10, vector[10, 10, 10, 10, 10, 10]); + let (reward, _, _, _ ) = proof_of_fee::get_consensus_reward(); + assert!(reward == 5_000, 73570026); + + mock::trigger_epoch(root); + + // check new vouch price + let (reward, _, _, _ ) = proof_of_fee::get_consensus_reward(); + assert!(reward == 5_250, 73570027); + assert!(vouch::get_vouch_price() == 5_250, 73570026); + + mock::trigger_epoch(root); + + // check new vouch price + let (reward, _, _, _ ) = proof_of_fee::get_consensus_reward(); + assert!(reward == 5_512, 73570027); + assert!(vouch::get_vouch_price() == 5_512, 73570026); + + // mock to descrease reward on the next epoch + proof_of_fee::test_mock_reward(root, 10_000, 9_600, 960, vector[960, 960, 960, 960, 960, 960]); + + mock::trigger_epoch(root); + + // check new vouch price + let (reward, _, _, _ ) = proof_of_fee::get_consensus_reward(); + assert!(reward == 9_500, 73570026); + assert!(vouch::get_vouch_price() == 9_500, 73570027); + } + + #[test(root = @ol_framework, alice = @0x1000a, bob = @0x1000b)] + fun update_vouch(root: &signer, alice: &signer) { + // create vals without vouches + mock::create_vals(root, 2, false); + vouch::set_vouch_price(root, 0); + + // alice vouches for bob + vouch::vouch_for(alice, @0x1000b); + + // check alice + let (given_vouches, given_epochs) = vouch::get_given_vouches(@0x1000a); + assert!(given_vouches == vector[@0x1000b], 73570005); + assert!(given_epochs == vector[0], 73570006); + + // check bob + let (received_vouches, received_epochs) = vouch::get_received_vouches(@0x1000b); + assert!(received_vouches == vector[@0x1000a], 73570007); + assert!(received_epochs == vector[0], 73570008); + + // fast forward to epoch 1 + mock::trigger_epoch(root); + + // alice vouches for bob again + vouch::vouch_for(alice, @0x1000b); + + // check alice + let (given_vouches, given_epochs) = vouch::get_given_vouches(@0x1000a); + assert!(given_vouches == vector[@0x1000b], 73570005); + assert!(given_epochs == vector[1], 73570006); + + // check bob + let (received_vouches, received_epochs) = vouch::get_received_vouches(@0x1000b); + assert!(received_vouches == vector[@0x1000a], 73570007); + assert!(received_epochs == vector[1], 73570008); + } + + // Sad Day scenarios + + #[test(root = @ol_framework, alice = @0x1000a)] + #[expected_failure(abort_code = 0x10001, location = ol_framework::vouch)] + fun vouch_for_self(root: &signer, alice: &signer) { + // create vals without vouches + mock::create_vals(root, 1, false); + vouch::set_vouch_price(root, 0); + + // alice vouches for herself + vouch::vouch_for(alice, @0x1000a); + } + + #[test(root = @ol_framework, alice = @0x1000a)] + #[expected_failure(abort_code = 0x10001, location = ol_framework::vouch)] + fun revoke_self_vouch(root: &signer, alice: &signer) { + // create vals without vouches + mock::create_vals(root, 1, false); + + // alice try to revoke herself + vouch::revoke(alice, @0x1000a); + } + + #[test(root = @ol_framework, alice = @0x1000a, bob = @0x1000b)] + #[expected_failure(abort_code = 0x10005, location = ol_framework::vouch)] + fun revoke_not_vouched(root: &signer, alice: &signer) { + // create vals without vouches + mock::create_vals(root, 2, false); + + // alice vouches for bob + vouch::revoke(alice, @0x1000b); + } + + #[test(root = @ol_framework, alice = @0x1000a, bob = @0x1000b, v1 = @0x10001, v2 = @0x10002, v3 = @0x10003, v4 = @0x10004, v5 = @0x10005, v6 = @0x10006, v7 = @0x10007, v8 = @0x10008, v9 = @0x10009, v10 = @0x10010)] + #[expected_failure(abort_code = 0x30004, location = ol_framework::vouch)] + fun vouch_over_max(root: &signer, alice: &signer, v1: &signer, v2: &signer, v3: &signer, v4: &signer, v5: &signer, v6: &signer, v7: &signer, v8: &signer, v9: &signer, v10: &signer) { + // create vals without vouches + mock::create_vals(root, 2, false); + vouch::set_vouch_price(root, 0); + + // init vouch for 10 validators + vouch::init(v1); + vouch::init(v2); + vouch::init(v3); + vouch::init(v4); + vouch::init(v5); + vouch::init(v6); + vouch::init(v7); + vouch::init(v8); + vouch::init(v9); + vouch::init(v10); + + // alice vouches for 10 validators + vouch::insist_vouch_for(alice, @0x10001); + vouch::insist_vouch_for(alice, @0x10002); + vouch::insist_vouch_for(alice, @0x10003); + vouch::insist_vouch_for(alice, @0x10004); + vouch::insist_vouch_for(alice, @0x10005); + vouch::insist_vouch_for(alice, @0x10006); + vouch::insist_vouch_for(alice, @0x10007); + vouch::insist_vouch_for(alice, @0x10008); + vouch::insist_vouch_for(alice, @0x10009); + vouch::insist_vouch_for(alice, @0x10010); + + // alice try to vouch for one more + vouch::insist_vouch_for(alice, @0x1000b); + + // check alice + let (given_vouches, given_epochs) = vouch::get_given_vouches(@0x1000a); + assert!(given_vouches == vector[@0x10001, @0x10002, @0x10003, @0x10004, @0x10005, @0x10006, @0x10007, @0x10008, @0x10009, @0x10010], 73570017); + assert!(given_epochs == vector[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 73570018); + + // check bob + let (received_vouches, received_epochs) = vouch::get_received_vouches(@0x1000b); + assert!(received_vouches == vector::empty(), 73570019); + assert!(received_epochs == vector::empty(), 73570020); + } + + #[test(root = @ol_framework, alice = @0x1000a, bob = @0x1000b)] + #[expected_failure(abort_code = 0x30006, location = ol_framework::ol_account)] + fun vouch_without_coins(root: &signer, alice: &signer) { + // create vals without vouches + mock::create_vals(root, 2, false); + vouch::set_vouch_price(root, 9_999); + + // alice vouches for bob without coins + vouch::vouch_for(alice, @0x1000b); + + // check alice + let (given_vouches, given_epochs) = vouch::get_given_vouches(@0x1000a); + assert!(given_vouches == vector::empty(), 73570021); + assert!(given_epochs == vector::empty(), 73570022); + + // check bob + let (received_vouches, received_epochs) = vouch::get_received_vouches(@0x1000b); + assert!(received_vouches == vector::empty(), 73570023); + assert!(received_epochs == vector::empty(), 73570024); + } + + #[test(root = @ol_framework, alice = @0x1000a)] + #[expected_failure(abort_code = 0x30006, location = ol_framework::vouch)] + fun vouch_without_init(alice: &signer) { + // alice vouches for bob without init + vouch::vouch_for(alice, @0x1000b); + } + + #[test(root = @ol_framework, alice = @0x1000a)] + #[expected_failure(abort_code = 0x30002, location = ol_framework::vouch)] + fun vouch_for_account_not_init(root: &signer, alice: &signer) { + mock::create_vals(root, 1, false); + + // alice vouches for bob without init + vouch::vouch_for(alice, @0x1000b); + } + + #[test(root = @ol_framework, alice = @0x1000a, bob = @0x1000b)] + #[expected_failure(abort_code = 0x30006, location = ol_framework::vouch)] + fun revoke_without_init(alice: &signer) { + // alice try to revoke bob without vouch + vouch::revoke(alice, @0x1000b); + } + + #[test(root = @ol_framework, alice = @0x1000a)] + #[expected_failure(abort_code = 0x10005, location = ol_framework::vouch)] + fun revoke_account_not_vouched(root: &signer, alice: &signer) { + mock::create_vals(root, 2, false); + + // alice try to revoke bob without vouch + vouch::revoke(alice, @0x1000b); + } + + + #[test(root = @ol_framework, alice = @0x1000a)] + fun true_friends_not_init() { + // alice try to get true friends in list without init + let result = vouch::true_friends(@0x1000a); + + assert!(result == vector::empty(), 73570028); + } + + #[test(root = @ol_framework, alice = @0x1000a)] + fun true_friends_in_list_not_init() { + // alice try to get true friends in list without init + let (list, size) = vouch::true_friends_in_list(@0x1000a, &vector::singleton(@0x1000b)); + + assert!(list == vector::empty(), 73570028); + assert!(size == 0, 73570029); + } + + #[test(root = @ol_framework, alice = @0x1000a)] + fun get_received_vouches_not_init() { + // alice try to get received vouches without init + let (received_vouches, received_epochs) = vouch::get_received_vouches(@0x1000a); + + assert!(received_vouches == vector::empty(), 73570030); + assert!(received_epochs == vector::empty(), 73570031); + } + + #[test(root = @ol_framework, alice = @0x1000a)] + #[expected_failure(abort_code = 0x30003, location = ol_framework::vouch)] + fun get_given_vouches_not_init() { + // alice try to get given vouches without init + vouch::get_given_vouches(@0x1000a); + } + + #[test(root = @ol_framework, alice = @0x1000a)] + fun get_all_vouchers_not_init() { + // alice try to get all vouchers without init + let all_vouchers = vouch::all_vouchers(@0x1000a); + + assert!(all_vouchers == vector::empty(), 73570034); + } + +} diff --git a/framework/libra-framework/sources/ol_sources/tests/vouch_migration.test.move b/framework/libra-framework/sources/ol_sources/tests/vouch_migration.test.move new file mode 100644 index 000000000..bf5e864d1 --- /dev/null +++ b/framework/libra-framework/sources/ol_sources/tests/vouch_migration.test.move @@ -0,0 +1,166 @@ +/* + + This test is to ensure that the migration of vouches + from legacy to new validators is working as expected. + + 1. Legacy data: + - alice vouches for bob + - carol vouches for bob + - alice vouches for carol + 2. New data: + - dave vouches for eve + - eve vouches for frank + + trigger epoch to execute migration + - check migrated vals vouches + + */ + +#[test_only] +module ol_framework::test_vouch_migration { + use std::vector; + use ol_framework::vouch; + use ol_framework::mock; + use ol_framework::migrations; + + // use diem_std::debug::print; + + #[test(root = @ol_framework, alice = @0x1000a, bob = @0x1000b, carol = @0x1000c, dave = @0x1000d, eve = @0x1000e, frank = @0x1000f)] + fun migrate_given_and_received_vouches(root: &signer, alice: &signer, bob: &signer, carol: &signer, dave: &signer, eve: &signer) { + vouch::set_vouch_price(root, 0); + + // init validators with legacy struct MyVouches + vouch::legacy_init(alice); + vouch::legacy_init(bob); + vouch::legacy_init(carol); + + // create validators + mock::create_vals(root, 6, false); + + // alice vouches for bob using legacy struct MyVouches + vouch::legacy_vouch_for(alice, @0x1000b); + + // carol vouches for bob using legacy struct MyVouches + vouch::legacy_vouch_for(carol, @0x1000b); + + // alice vouches for carol using legacy struct MyVouches + vouch::legacy_vouch_for(alice, @0x1000c); + + // check bob received vouches on legacy struct MyVouches + let (received_vouches, received_epochs) = vouch::get_legacy_vouches(@0x1000b); + assert!(received_vouches == vector[@0x1000a, @0x1000c], 73570004); + assert!(received_epochs == vector[0, 0], 73570005); + + // check legacy validators only have legacy struct MyVouches + assert!(vouch::is_legacy_init(@0x1000a), 73570001); + assert!(vouch::is_legacy_init(@0x1000b), 73570002); + assert!(vouch::is_legacy_init(@0x1000c), 73570003); + assert!(!vouch::is_init(@0x1000a), 73570001); + assert!(!vouch::is_init(@0x1000b), 73570002); + assert!(!vouch::is_init(@0x1000c), 73570003); + + // check new validators only have new structs initialized + assert!(vouch::is_init(@0x1000d), 73570006); + assert!(vouch::is_init(@0x1000e), 73570007); + assert!(!vouch::is_legacy_init(@0x1000d), 73570008); + assert!(!vouch::is_legacy_init(@0x1000e), 73570009); + + // check legacy vouches + let (received_vouches, received_epochs) = vouch::get_legacy_vouches(@0x1000a); + assert!(received_vouches == vector::empty(), 73570010); + assert!(received_epochs == vector::empty(), 73570011); + let (received_vouches, received_epochs) = vouch::get_legacy_vouches(@0x1000b); + assert!(received_vouches == vector[@0x1000a, @0x1000c], 73570012); + assert!(received_epochs == vector[0, 0], 73570013); + let (received_vouches, received_epochs) = vouch::get_legacy_vouches(@0x1000c); + assert!(received_vouches == vector[@0x1000a], 73570014); + assert!(received_epochs == vector[0], 73570015); + + // dave vouches for eve using new structs + vouch::vouch_for(dave, @0x1000e); + + // eve vouches for frank using new structs + vouch::vouch_for(eve, @0x1000f); + + // check eve received vouches on new struct Vouches + let (received_vouches, received_epochs) = vouch::get_received_vouches(@0x1000e); + assert!(received_vouches == vector[@0x1000d], 73570006); + assert!(received_epochs == vector[0], 73570007); + + // check dave given vouches on new struct Vouches + let (given_vouches, given_epochs) = vouch::get_given_vouches(@0x1000d); + assert!(given_vouches == vector[@0x1000e], 73570008); + assert!(given_epochs == vector[0], 73570009); + + // check last migration number + assert!(migrations::get_last_migration_number() == 0, 73570010); + + // It is show time!!! RUN MIGRATION + mock::trigger_epoch(root); + + // check last migration number + assert!(migrations::get_last_migration_number() == 1, 73570011); + + // check last migration data + let (number, epoch, description) = migrations::get_last_migrations_history(); + assert!(number == 1, 73570012); + assert!(epoch == 0, 73570013); + assert!(description == b"Vouch migration initializes GivenVouches, ReceivedVouches, and drop MyVouches", 73570014); + + // check structs initialized after migration + assert!(vouch::is_init(@0x1000a), 73570010); + assert!(vouch::is_init(@0x1000b), 73570011); + assert!(vouch::is_init(@0x1000c), 73570012); + assert!(!vouch::is_legacy_init(@0x1000a), 73570013); + assert!(!vouch::is_legacy_init(@0x1000b), 73570014); + assert!(!vouch::is_legacy_init(@0x1000c), 73570015); + + // check alice vouches migrated + let (given_vouches, given_epochs) = vouch::get_given_vouches(@0x1000a); + assert!(given_vouches == vector[@0x1000b, @0x1000c], 73570016); + assert!(given_epochs == vector[0, 0], 73570017); + let (received_vouches, received_epochs) = vouch::get_received_vouches(@0x1000a); + assert!(received_vouches == vector::empty(), 73570018); + assert!(received_epochs == vector::empty(), 73570019); + + // check bob vouches migrated + let (given_vouches, given_epochs) = vouch::get_given_vouches(@0x1000b); + assert!(given_vouches == vector::empty(), 73570020); + assert!(given_epochs == vector::empty(), 73570021); + let (received_vouches, received_epochs) = vouch::get_received_vouches(@0x1000b); + assert!(received_vouches == vector[@0x1000a, @0x1000c], 73570018); + assert!(received_epochs == vector[0, 0], 73570019); + + // check carol vouches migrated + let (given_vouches, given_epochs) = vouch::get_given_vouches(@0x1000c); + assert!(given_vouches == vector[@0x1000b], 73570020); + assert!(given_epochs == vector[0], 73570021); + let (received_vouches, received_epochs) = vouch::get_received_vouches(@0x1000c); + assert!(received_vouches == vector[@0x1000a], 73570022); + assert!(received_epochs == vector[0], 73570023); + + // check dave vouches are okay + let (given_vouches, given_epochs) = vouch::get_given_vouches(@0x1000d); + assert!(given_vouches == vector[@0x1000e], 73570024); + assert!(given_epochs == vector[0], 73570025); + let (received_vouches, received_epochs) = vouch::get_received_vouches(@0x1000d); + assert!(received_vouches == vector::empty(), 73570026); + assert!(received_epochs == vector::empty(), 73570027); + + // check eve vouches are okay + let (received_vouches, received_epochs) = vouch::get_received_vouches(@0x1000e); + assert!(received_vouches == vector[@0x1000d], 73570028); + assert!(received_epochs == vector[0], 73570029); + let (given_vouches, given_epochs) = vouch::get_given_vouches(@0x1000e); + assert!(given_vouches == vector[@0x1000f], 73570030); + assert!(given_epochs == vector[0], 73570031); + + // check frank vouches are okay + let (received_vouches, received_epochs) = vouch::get_received_vouches(@0x1000f); + assert!(received_vouches == vector[@0x1000e], 73570032); + assert!(received_epochs == vector[0], 73570033); + let (given_vouches, given_epochs) = vouch::get_given_vouches(@0x1000f); + assert!(given_vouches == vector::empty(), 73570034); + assert!(given_epochs == vector::empty(), 73570035); + } +} diff --git a/framework/libra-framework/sources/ol_sources/validator_universe.move b/framework/libra-framework/sources/ol_sources/validator_universe.move index 04ed4ec9d..bcb350f76 100644 --- a/framework/libra-framework/sources/ol_sources/validator_universe.move +++ b/framework/libra-framework/sources/ol_sources/validator_universe.move @@ -4,10 +4,10 @@ module diem_framework::validator_universe { use std::signer; use std::vector; - use diem_framework::system_addresses; use ol_framework::jail; use ol_framework::vouch; use diem_framework::stake; + use diem_framework::system_addresses; #[test_only] use ol_framework::testnet; diff --git a/framework/libra-framework/sources/ol_sources/vouch.move b/framework/libra-framework/sources/ol_sources/vouch.move index b198e75ba..1f7473db9 100644 --- a/framework/libra-framework/sources/ol_sources/vouch.move +++ b/framework/libra-framework/sources/ol_sources/vouch.move @@ -1,162 +1,384 @@ module ol_framework::vouch { + use std::error; use std::signer; use std::vector; + use std::string; use ol_framework::ancestry; use ol_framework::ol_account; use ol_framework::epoch_helper; - use diem_framework::account; use diem_framework::system_addresses; use diem_framework::transaction_fee; + use diem_std::debug::print; + friend diem_framework::genesis; - friend ol_framework::validator_universe; friend ol_framework::proof_of_fee; friend ol_framework::jail; + friend ol_framework::epoch_boundary; + friend ol_framework::vouch_migration; // TODO: remove after vouch migration is completed + friend ol_framework::validator_universe; #[test_only] friend ol_framework::mock; #[test_only] friend ol_framework::test_pof; + #[test_only] + friend ol_framework::test_vouch; + #[test_only] + friend ol_framework::test_vouch_migration; + + //////// CONST //////// - /// trying to vouch for yourself? + /// How many epochs must pass before the voucher expires. + const EXPIRATION_ELAPSED_EPOCHS: u64 = 45; + + /// Maximum number of vouches + const BASE_MAX_VOUCHES: u64 = 10; + + + //////// ERROR CODES //////// + + /// Trying to vouch for yourself? const ETRY_SELF_VOUCH_REALLY: u64 = 1; - /// how many epochs must pass before the voucher expires. - const EXPIRATION_ELAPSED_EPOCHS: u64 = 90; + /// User cannot receive vouch because their vouch state is not initialized + const ERECEIVER_NOT_INIT: u64 = 2; + + /// Cannot query vouches because the GivenVouches state is not initialized + const EGIVEN_VOUCHES_NOT_INIT: u64 = 3; - // triggered once per epoch - struct MyVouches has key { - my_buddies: vector
, + /// Limit reached. You cannot give any new vouches. + const EMAX_LIMIT_GIVEN: u64 = 4; + + /// Vouch not found + const EVOUCH_NOT_FOUND: u64 = 5; + + /// Grantor state is not initialized + const EGRANTOR_NOT_INIT: u64 = 6; + + + //////// STRUCTS //////// + + // TODO: someday this should be renamed to ReceivedVouches + struct MyVouches has key, drop { + my_buddies: vector
, // incoming vouches epoch_vouched: vector, } + struct ReceivedVouches has key { + incoming_vouches: vector
, + epoch_vouched: vector, + } + + struct GivenVouches has key { + outgoing_vouches: vector
, + epoch_vouched: vector, + } + + /// struct to store the price to vouch for someone + struct VouchPrice has key { + amount: u64 + } + + /* + Oh, I get by with a little help from my friends, + Mm, I get high with a little help from my friends, + Mm, gonna try with a little help from my friends. + */ + // init the struct on a validators account. - public(friend) fun init(new_account_sig: &signer ) { + public(friend) fun init(new_account_sig: &signer) { let acc = signer::address_of(new_account_sig); - if (!is_init(acc)) { - move_to(new_account_sig, MyVouches { - my_buddies: vector::empty(), - epoch_vouched: vector::empty(), - }); - } + if (exists(acc)) { + // let migration handle the initialization of new structs + return + }; + + if (!exists(acc)) { + move_to(new_account_sig, ReceivedVouches { + incoming_vouches: vector::empty(), + epoch_vouched: vector::empty(), + }); + }; + + if (!exists(acc)) { + move_to(new_account_sig, GivenVouches { + outgoing_vouches: vector::empty(), + epoch_vouched: vector::empty(), + }); + }; } - #[view] - public fun is_init(acc: address ):bool { - exists(acc) + public(friend) fun set_vouch_price(framework: &signer, amount: u64) acquires VouchPrice { + system_addresses::assert_ol(framework); + if (!exists(@ol_framework)) { + move_to(framework, VouchPrice { amount }); + } else { + let price = borrow_global_mut(@ol_framework); + price.amount = amount; + }; } - fun vouch_impl(ill_be_your_friend: &signer, wanna_be_my_friend: address) acquires MyVouches { - let buddy_acc = signer::address_of(ill_be_your_friend); - assert!(buddy_acc != wanna_be_my_friend, ETRY_SELF_VOUCH_REALLY); + fun vouch_impl(grantor: &signer, friend_account: address, check_unrelated: bool) acquires ReceivedVouches, GivenVouches, VouchPrice { + let grantor_acc = signer::address_of(grantor); + assert!(grantor_acc != friend_account, error::invalid_argument(ETRY_SELF_VOUCH_REALLY)); + + // check if structures are initialized + assert!(is_init(grantor_acc), error::invalid_state(EGRANTOR_NOT_INIT)); + assert!(is_init(friend_account), error::invalid_state(ERECEIVER_NOT_INIT)); + + if (check_unrelated) { + ancestry::assert_unrelated(grantor_acc, friend_account); + }; + + // check if the grantor has already reached the limit of vouches + let (given_vouches, _) = get_given_vouches(grantor_acc); + assert!( + vector::length(&given_vouches) < BASE_MAX_VOUCHES, + error::invalid_state(EMAX_LIMIT_GIVEN) + ); - if (!exists(wanna_be_my_friend)) return; - let epoch = epoch_helper::get_current_epoch(); // this fee is paid to the system, cannot be reclaimed - let c = ol_account::withdraw(ill_be_your_friend, vouch_cost_microlibra()); - transaction_fee::user_pay_fee(ill_be_your_friend, c); + let price = get_vouch_price(); + if (price > 0) { + let vouch_cost = ol_account::withdraw(grantor, price); + transaction_fee::user_pay_fee(grantor, vouch_cost); + }; - let v = borrow_global_mut(wanna_be_my_friend); + let epoch = epoch_helper::get_current_epoch(); - let (found, i) = vector::index_of(&v.my_buddies, &buddy_acc); - if (found) { // prevent duplicates - // update date - let e = vector::borrow_mut(&mut v.epoch_vouched, i); - *e = epoch; + // add friend to grantor given vouches + add_given_vouches(grantor_acc, friend_account, epoch); + + // add grantor to friend received vouches + add_received_vouches(friend_account, grantor_acc, epoch); + } + + // Function to add given vouches + public fun add_given_vouches(grantor_acc: address, vouched_account: address, epoch: u64) acquires GivenVouches { + let given_vouches = borrow_global_mut(grantor_acc); + let (found, i) = vector::index_of(&given_vouches.outgoing_vouches, &vouched_account); + + if (found) { + // Update the epoch if the vouched account is already present + let epoch_value = vector::borrow_mut(&mut given_vouches.epoch_vouched, i); + *epoch_value = epoch; } else { - vector::push_back(&mut v.my_buddies, buddy_acc); - vector::push_back(&mut v.epoch_vouched, epoch); + // Add new vouched account and epoch if not already present + vector::push_back(&mut given_vouches.outgoing_vouches, vouched_account); + vector::push_back(&mut given_vouches.epoch_vouched, epoch); + } + } + + // Function to add received vouches + public fun add_received_vouches(vouched_account: address, grantor_acc: address, epoch: u64) acquires ReceivedVouches { + let received_vouches = borrow_global_mut(vouched_account); + let (found, i) = vector::index_of(&received_vouches.incoming_vouches, &grantor_acc); + + if (found) { + // Update the epoch if the vouching account is already present + let epoch_value = vector::borrow_mut(&mut received_vouches.epoch_vouched, i); + *epoch_value = epoch; + } else { + // Add new vouching account and epoch if not already present + vector::push_back(&mut received_vouches.incoming_vouches, grantor_acc); + vector::push_back(&mut received_vouches.epoch_vouched, epoch); } } /// will only succesfully vouch if the two are not related by ancestry /// prevents spending a vouch that would not be counted. /// to add a vouch and ignore this check use insist_vouch - public entry fun vouch_for(grantor: &signer, wanna_be_my_friend: address) acquires MyVouches { - ancestry::assert_unrelated(signer::address_of(grantor), wanna_be_my_friend); - vouch_impl(grantor, wanna_be_my_friend); + public entry fun vouch_for(grantor: &signer, friend_account: address) acquires ReceivedVouches, GivenVouches, VouchPrice { + vouch_impl(grantor, friend_account, true); } /// you may want to add people who are related to you /// there are no known use cases for this at the moment. - public entry fun insist_vouch_for(grantor: &signer, wanna_be_my_friend: address) acquires MyVouches { - vouch_impl(grantor, wanna_be_my_friend); + public entry fun insist_vouch_for(grantor: &signer, friend_account: address) acquires ReceivedVouches, GivenVouches, VouchPrice { + vouch_impl(grantor, friend_account, false); } - public entry fun revoke(buddy: &signer, its_not_me_its_you: address) acquires MyVouches { - let buddy_acc = signer::address_of(buddy); - assert!(buddy_acc!=its_not_me_its_you, ETRY_SELF_VOUCH_REALLY); - - if (!exists(its_not_me_its_you)) return; - - let v = borrow_global_mut(its_not_me_its_you); - let (found, i) = vector::index_of(&v.my_buddies, &buddy_acc); - if (found) { - vector::remove(&mut v.my_buddies, i); - vector::remove(&mut v.epoch_vouched, i); - }; + public entry fun revoke(grantor: &signer, friend_account: address) acquires ReceivedVouches, GivenVouches { + let grantor_acc = signer::address_of(grantor); + assert!(grantor_acc != friend_account, error::invalid_argument(ETRY_SELF_VOUCH_REALLY)); + + assert!(is_init(grantor_acc), error::invalid_state(EGRANTOR_NOT_INIT)); + + // remove friend from grantor given vouches + let v = borrow_global_mut(grantor_acc); + let (found, i) = vector::index_of(&v.outgoing_vouches, &friend_account); + assert!(found, error::invalid_argument(EVOUCH_NOT_FOUND)); + vector::remove
(&mut v.outgoing_vouches, i); + vector::remove(&mut v.epoch_vouched, i); + + // remove grantor from friends received vouches + let v = borrow_global_mut(friend_account); + let (found, i) = vector::index_of(&v.incoming_vouches, &grantor_acc); + assert!(found, error::invalid_argument(EVOUCH_NOT_FOUND)); + vector::remove(&mut v.incoming_vouches, i); + vector::remove(&mut v.epoch_vouched, i); } - public(friend) fun vm_migrate(vm: &signer, val: address, buddy_list: vector
) acquires MyVouches { + public(friend) fun vm_migrate(vm: &signer, val: address, buddy_list: vector
) acquires ReceivedVouches { system_addresses::assert_ol(vm); bulk_set(val, buddy_list); } - fun bulk_set(val: address, buddy_list: vector
) acquires MyVouches { - - if (!exists(val)) return; - - let v = borrow_global_mut(val); + fun bulk_set(val: address, buddy_list: vector
) acquires ReceivedVouches { + if (!exists(val)) return; // take self out of list + let v = borrow_global_mut(val); let (is_found, i) = vector::index_of(&buddy_list, &val); - if (is_found) { vector::swap_remove
(&mut buddy_list, i); }; - - v.my_buddies = buddy_list; + v.incoming_vouches = buddy_list; let epoch_data: vector = vector::map_ref(&buddy_list, |_e| { 0u64 } ); v.epoch_vouched = epoch_data; } + // The struct GivenVouches cannot not be lazy initialized because + // vouch module cannot depend on validator_universe (circle dependency) + // TODO: this migration function must be removed after all validators have migrated + public(friend) fun migrate_given_vouches(account_sig: &signer, all_accounts: vector
) acquires MyVouches { + let account = signer::address_of(account_sig); + + if (exists(account)) { + // struct already initialized + return + }; + + let new_outgoing_vouches = vector::empty(); + let new_epoch_vouched = vector::empty(); + + vector::for_each(all_accounts, |val| { + if (val != account && exists(val)) { + let legacy_state = borrow_global(val); + let incoming_vouches = legacy_state.my_buddies; + let epoch_vouched = legacy_state.epoch_vouched; + let (found, i) = vector::index_of(&incoming_vouches, &account); + if (found) { + vector::push_back(&mut new_outgoing_vouches, val); + vector::push_back(&mut new_epoch_vouched, *vector::borrow(&epoch_vouched, i)); + } + } + }); + + // add the new GivenVouches struct with the new data + move_to(account_sig, GivenVouches { + outgoing_vouches: new_outgoing_vouches, + epoch_vouched: new_epoch_vouched, + }); + + print(&string::utf8(b">>> Migrated GivenVouches for ")); + print(&account); + } + + // TODO: remove/deprecate after migration is completed + public(friend) fun migrate_received_vouches(account_sig: &signer) acquires MyVouches { + let account = signer::address_of(account_sig); + + if (!exists(account)) { + // struct not initialized + return + }; + + if (exists(account)) { + // struct already initialized + return + }; + + let state = borrow_global(account); + let new_incoming_vouches = state.my_buddies; + let new_epoch_vouched = state.epoch_vouched; + + // add the new ReceivedVouches struct with the legacy data + move_to(account_sig, ReceivedVouches { + incoming_vouches: new_incoming_vouches, + epoch_vouched: new_epoch_vouched, + }); + + // remove deprecated MyVouches struct + move_from(account); + + print(&string::utf8(b">>> Migrated ReceivedVouches for ")); + print(&account); + } + + ///////// GETTERS ////////// + #[view] - /// gets all buddies, including expired ones - public fun all_vouchers(val: address): vector
acquires MyVouches{ + public fun is_init(acc: address ):bool { + exists(acc) && exists(acc) + } + + #[view] + public fun get_received_vouches(acc: address): (vector
, vector) acquires ReceivedVouches { + if (!exists(acc)) { + return (vector::empty(), vector::empty()) + }; - if (!exists(val)) return vector::empty
(); - let state = borrow_global(val); - *&state.my_buddies + let state = borrow_global(acc); + (*&state.incoming_vouches, *&state.epoch_vouched) } #[view] - /// gets the buddies and checks if they are expired - public fun all_not_expired(addr: address): vector
acquires MyVouches{ + public fun get_given_vouches(acc: address): (vector
, vector) acquires GivenVouches { + assert!(exists(acc), error::invalid_state(EGIVEN_VOUCHES_NOT_INIT)); + + let state = borrow_global(acc); + (*&state.outgoing_vouches, *&state.epoch_vouched) + } + + #[view] + public fun get_vouch_price(): u64 acquires VouchPrice { + if (!exists(@ol_framework)) { + return 1_000 // previous micro-libra cost + }; + + let price = borrow_global(@ol_framework); + price.amount + } + + #[view] + /// gets all buddies, including expired ones + public fun all_vouchers(val: address): vector
acquires ReceivedVouches { + let (incoming_vouches, _) = get_received_vouches(val); + incoming_vouches + } + + #[view] + /// gets the received vouches not expired + public fun all_not_expired(addr: address): vector
acquires ReceivedVouches { let valid_vouches = vector::empty
(); - if (is_init(addr)) { - let state = borrow_global(addr); - vector::for_each(state.my_buddies, |buddy_acc| { - // account might have dropped - if (account::exists_at(buddy_acc)){ - if (is_not_expired(buddy_acc, state)) { - vector::push_back(&mut valid_vouches, buddy_acc) - } - } - }) + let (all_received, epoch_vouched) = get_received_vouches(addr); + let current_epoch = epoch_helper::get_current_epoch(); + + let i = 0; + while (i < vector::length(&all_received)) { + let vouch_received = vector::borrow(&all_received, i); + let when_vouched = *vector::borrow(&epoch_vouched, i); + // check if the vouch is expired + if ((when_vouched + EXPIRATION_ELAPSED_EPOCHS) > current_epoch) { + vector::push_back(&mut valid_vouches, *vouch_received) + }; + i = i + 1; }; + valid_vouches } #[view] /// filter expired vouches, and do ancestry check - public fun true_friends(addr: address): vector
acquires MyVouches{ - - if (!exists(addr)) return vector::empty
(); + public fun true_friends(addr: address): vector
acquires ReceivedVouches { + if (!exists(addr)) return vector::empty
(); let not_expired = all_not_expired(addr); let filtered_ancestry = ancestry::list_unrelated(not_expired); filtered_ancestry @@ -165,33 +387,20 @@ module ol_framework::vouch { #[view] /// check if the user is in fact a valid voucher public fun is_valid_voucher_for(voucher: address, recipient: address):bool - acquires MyVouches { + acquires ReceivedVouches { let list = true_friends(recipient); vector::contains(&list, &voucher) } - - fun is_not_expired(voucher: address, state: &MyVouches): bool { - let (found, i) = vector::index_of(&state.my_buddies, &voucher); - if (found) { - let when_vouched = vector::borrow(&state.epoch_vouched, i); - return (*when_vouched + EXPIRATION_ELAPSED_EPOCHS) > epoch_helper::get_current_epoch() - }; - false - } - /// for a given list find and count any of my vouchers - public(friend) fun true_friends_in_list(addr: address, list: &vector
): (vector
, u64) acquires MyVouches { - - if (!exists(addr)) return (vector::empty(), 0); + public(friend) fun true_friends_in_list(addr: address, list: &vector
): (vector
, u64) acquires ReceivedVouches { + if (!exists(addr)) return (vector::empty(), 0); let tf = true_friends(addr); - let buddies_in_list = vector::empty(); - let i = 0; + let i = 0; while (i < vector::length(&tf)) { let addr = vector::borrow(&tf, i); - if (vector::contains(list, addr)) { vector::push_back(&mut buddies_in_list, *addr); }; @@ -201,15 +410,60 @@ module ol_framework::vouch { (buddies_in_list, vector::length(&buddies_in_list)) } + #[test_only] + public fun test_set_buddies(val: address, buddy_list: vector
) acquires ReceivedVouches { + bulk_set(val, buddy_list); + } - // TODO: move to globals - // the cost to verify a vouch. Coins are burned. - fun vouch_cost_microlibra(): u64 { - 1000 + #[test_only] + public fun legacy_init(new_account_sig: &signer) { + let acc = signer::address_of(new_account_sig); + + if (!exists(acc)) { + move_to(new_account_sig, MyVouches { + my_buddies: vector::empty(), + epoch_vouched: vector::empty(), + }); + }; } #[test_only] - public fun test_set_buddies(val: address, buddy_list: vector
) acquires MyVouches { - bulk_set(val, buddy_list); + public fun legacy_vouch_for(ill_be_your_friend: &signer, wanna_be_my_friend: address) acquires MyVouches { + let buddy_acc = signer::address_of(ill_be_your_friend); + assert!(buddy_acc != wanna_be_my_friend, ETRY_SELF_VOUCH_REALLY); + + if (!exists(wanna_be_my_friend)) return; + let epoch = epoch_helper::get_current_epoch(); + + // this fee is paid to the system, cannot be reclaimed + // let c = ol_account::withdraw(ill_be_your_friend, vouch_cost_microlibra()); + // transaction_fee::user_pay_fee(ill_be_your_friend, c); + + let v = borrow_global_mut(wanna_be_my_friend); + + let (found, i) = vector::index_of(&v.my_buddies, &buddy_acc); + if (found) { // prevent duplicates + // update date + let e = vector::borrow_mut(&mut v.epoch_vouched, i); + *e = epoch; + } else { + vector::push_back(&mut v.my_buddies, buddy_acc); + vector::push_back(&mut v.epoch_vouched, epoch); + } + } + + #[test_only] + public fun get_legacy_vouches(acc: address): (vector
, vector) acquires MyVouches { + if (!exists(acc)) { + return (vector::empty(), vector::empty()) + }; + + let state = borrow_global(acc); + (*&state.my_buddies, *&state.epoch_vouched) + } + + #[test_only] + public fun is_legacy_init(acc: address): bool { + exists(acc) } } diff --git a/framework/libra-framework/sources/ol_sources/vouch_migration.move b/framework/libra-framework/sources/ol_sources/vouch_migration.move new file mode 100644 index 000000000..6a7d255a0 --- /dev/null +++ b/framework/libra-framework/sources/ol_sources/vouch_migration.move @@ -0,0 +1,33 @@ + +module ol_framework::vouch_migration { + use std::vector; + use diem_framework::validator_universe; + use diem_framework::create_signer::create_signer; + use ol_framework::vouch; + + // use diem_std::debug::print; + + #[test_only] + friend ol_framework::test_vouch_migration; + + friend ol_framework::migrations; + + public(friend) fun migrate_my_vouches() { + let all_vals = validator_universe::get_eligible_validators(); + vector::for_each(all_vals, |val| { + // We create the signer for the val here since this is required + // to add the GivenVouches resource. + let val_signer = &create_signer(val); // <<< DANGER + + vouch::migrate_given_vouches(val_signer, all_vals); + }); + + vector::for_each(all_vals, |val| { + // We create the signer for the val here since this is required + // to add the ReceivedVouches resource and drop MyVouches resource. + let val_signer = &create_signer(val); // <<< DANGER + + vouch::migrate_received_vouches(val_signer); + }); + } +} diff --git a/framework/releases/head.mrb b/framework/releases/head.mrb index 0dd8056543353576fead3fa3500c1f5c94a5ce30..630a669981746c807fc36665d398b3c665fe1ab7 100644 GIT binary patch delta 55813 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 delta 44685 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

8A60ah(5`b`~6N9(iW>#eHi+-%h<0tlK``k6yid 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 { if *revoke { VouchRevoke { - its_not_me_its_you: *vouch_acct, + friend_account: *vouch_acct, } } else { VouchVouchFor { - wanna_be_my_friend: *vouch_acct, + friend_account: *vouch_acct, } } }