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

[move] vouch reputation #245

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6032893
framework helper function to force voucher trimming
0o-de-lally May 22, 2024
c63cfd7
epoch boundary migrates vouch list
0o-de-lally May 22, 2024
348007d
production validators require 3 vouches minimum
0o-de-lally May 22, 2024
4d297cb
add struct to track given vouches
0o-de-lally May 24, 2024
3d94750
implement revoke tx and migration for GiveOut
0o-de-lally May 24, 2024
5e808e2
implements givin vouches with GivenOut struct
0o-de-lally May 24, 2024
11e8383
migration should heal existing accounts
0o-de-lally May 24, 2024
06a2ed3
testing some leaderboard structs
0o-de-lally May 24, 2024
b09ea36
implement setters for leaderboard
0o-de-lally May 24, 2024
f6fc8d6
leaderboard getters
0o-de-lally May 24, 2024
2c59bf1
make leaderboard callable by framework in epoch boundary
0o-de-lally May 24, 2024
a6ea871
process outgoing sets leaderboard
0o-de-lally May 24, 2024
6a3341f
initializers
0o-de-lally May 24, 2024
b986c78
genesis initializer
0o-de-lally May 24, 2024
ae30bf0
patch tests with initializer
0o-de-lally May 24, 2024
32bc00c
vouch limit calculator
0o-de-lally May 24, 2024
dce3bcb
separate reputation module
0o-de-lally May 25, 2024
b471dfd
add initialization of reputation
0o-de-lally May 25, 2024
ce16e28
batch scoring for reputation
0o-de-lally May 25, 2024
6db1b7d
construct vouch tree and make it happen on epoch boundary
0o-de-lally May 25, 2024
5128cad
compiles test fails
0o-de-lally May 25, 2024
44914ca
construct vouch trees lazily when add or removing vouches (not on epo…
0o-de-lally May 25, 2024
d73d080
scaffold reputation calcs on epoch boundary
0o-de-lally May 25, 2024
c6c1549
propose faster vouch expiration
0o-de-lally May 26, 2024
3543eb5
make the vouching cost dynamic (was effectively free at 0.001 LIBRA)
0o-de-lally May 26, 2024
3253147
cleanup separation of 0L specific feature flags, add dynamic vouch ff
0o-de-lally May 26, 2024
ac0248a
recursive reputation also a feature flag
0o-de-lally May 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions framework/libra-framework/sources/block.move
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,6 @@ module diem_framework::block {
};

if (timestamp - reconfiguration::last_reconfiguration_time() >= block_metadata_ref.epoch_interval) {
// if (!features::epoch_trigger_enabled() ||
// testnet::is_testnet()) {
if (testnet::is_testnet()) {
epoch_boundary::epoch_boundary(
vm,
Expand Down
2 changes: 2 additions & 0 deletions framework/libra-framework/sources/genesis.move
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ module diem_framework::genesis {
use ol_framework::musical_chairs;
use ol_framework::proof_of_fee;
use ol_framework::slow_wallet;
use ol_framework::leaderboard;
use ol_framework::libra_coin;
use ol_framework::infra_escrow;
use ol_framework::safe;
Expand Down Expand Up @@ -154,6 +155,7 @@ module diem_framework::genesis {
pledge_accounts::initialize(&diem_framework_account);
account::maybe_initialize_duplicate_originating(&diem_framework_account);
infra_escrow::initialize(&diem_framework_account);
leaderboard::initialize(&diem_framework_account);

let zero_x_two_sig = create_signer(@0x2);
sacred_cows::init(&zero_x_two_sig);
Expand Down
166 changes: 166 additions & 0 deletions framework/libra-framework/sources/leaderboard.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/// Validator track record
/// NOTE: other reputational metrics exist on jail.move
module diem_framework::leaderboard {

use std::vector;
use std::signer;
use diem_framework::system_addresses;

friend ol_framework::epoch_boundary;
friend ol_framework::genesis;
#[test_only]
friend ol_framework::test_reputation;

const BASE_REPUTATION: u64 = 2;

// NOTE: reputation will be a work in progress. As a dev strategy, let's break
// up the structs into small atomic pieces so we can increment without
// needing to migrate state when we imlpement new metrics.

// Who is in the Top 10 net proposals at end of last epoch.
// Note: in 0L validators all have equal weight, so the net proposals are a
// result of validator performance, and network topology
// global state on 0x1
struct TopTen has key {
list: vector<address>
}

/// Count total epochs participating as validator
/// count both successes and fails
struct TotalScore has key {
success: u64,
fail: u64
}

// How many epochs has this validator been in the set successfully without
// interruption
// resets on the first jail
struct WinStreak has key {
value: u64
}

// The count of epochs the validator has been in the Top Ten by net proposal count
struct TopTenStreak has key {
value: u64
}

public entry fun init(sig: &signer) {
let addr = signer::address_of(sig);
if (!exists<TotalScore>(addr)) {
move_to(sig, TotalScore {
success: 0,
fail: 0
})
};

if (!exists<WinStreak>(addr)) {
move_to(sig, WinStreak {
value: 0
})
};

if (!exists<TopTenStreak>(addr)) {
move_to(sig, TopTenStreak {
value: 0
})
}
}

/// genesis and migration initializer
public(friend) fun initialize(framework: &signer) {

if (!exists<TopTen>(@diem_framework)) {
move_to(framework, TopTen {
list: vector::empty()
})
}
}

/// sets the top 10
public(friend) fun set_top_ten(framework: &signer, list: vector<address>) acquires TopTen, TopTenStreak {
system_addresses::assert_diem_framework(framework);
let state = borrow_global_mut<TopTen>(@diem_framework);

// increament winning streak if again in the Top 10
vector::for_each(state.list, |acc| {
let state = borrow_global_mut<TopTenStreak>(acc);

if (vector::contains(&list, &acc)) {
state.value = state.value + 1;
} else {
// reset streak
state.value = 0;
}
});

state.list = list
}


/// The framework signer can increment the total stats for the validator at
/// epoch boundaries.
public(friend) fun increment_total(framework: &signer, acc: address, success: bool) acquires TotalScore {
system_addresses::assert_diem_framework(framework);
let state = borrow_global_mut<TotalScore>(acc);
if (success) {
state.success = state.success + 1;
} else {
state.fail = state.fail + 1;
}
}

/// The framework signer can increment the total stats for the validator at
/// epoch boundaries.
public(friend) fun increment_streak(framework: &signer, acc: address) acquires WinStreak {
system_addresses::assert_diem_framework(framework);
let state = borrow_global_mut<WinStreak>(acc);
state.value = state.value + 1;
}

/// The framework signer can increment the total stats for the validator at
/// epoch boundaries.
public(friend) fun reset_streak(framework: &signer, acc: address) acquires WinStreak {
system_addresses::assert_diem_framework(framework);
let state = borrow_global_mut<WinStreak>(acc);
state.value = 0;
}

//////// GETTERS ////////
#[view]
/// Get totals (success epochs, fail epochs)
public fun get_total(acc: address): (u64, u64) acquires TotalScore {
if (!exists<TotalScore>(acc)) return (0, 0);
let state = borrow_global<TotalScore>(acc);
(state.success, state.fail)
}

#[view]
/// Get win streak (success epochs, fail epochs)
public fun get_streak(acc: address): u64 acquires WinStreak {
if (!exists<TotalScore>(acc)) return 0;

let state = borrow_global<WinStreak>(acc);
state.value
}

#[view]
/// Get win streak (success epochs, fail epochs)
public fun get_topten_streak(acc: address): u64 acquires TopTenStreak {
if (!exists<TotalScore>(acc)) return 0;
let state = borrow_global<TopTenStreak>(acc);
state.value
}

#[test_only]
public(friend) fun test_mock_state(framework: &signer, acc: address, success: u64, fail: u64, win_streak: u64, toptep_streak: u64) acquires TotalScore, WinStreak, TopTenStreak {
system_addresses::assert_diem_framework(framework);
let ts = borrow_global_mut<TotalScore>(acc);
ts.success = success;
ts.fail = fail;
let ws = borrow_global_mut<WinStreak>(acc);
ws.value = win_streak;
let tts = borrow_global_mut<TopTenStreak>(acc);
tts.value = toptep_streak;

}
}
50 changes: 46 additions & 4 deletions framework/libra-framework/sources/ol_sources/epoch_boundary.move
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,18 @@ module diem_framework::epoch_boundary {
use ol_framework::jail;
use ol_framework::safe;
use ol_framework::burn;
use ol_framework::feature_flags;
use ol_framework::donor_voice_txs;
use ol_framework::fee_maker;
use ol_framework::infra_escrow;
use ol_framework::leaderboard;
use ol_framework::libra_coin;
use ol_framework::match_index;
use ol_framework::community_wallet_init;
use ol_framework::testnet;
use ol_framework::reputation;
use ol_framework::validator_universe;
use ol_framework::vouch;

use diem_framework::account;
use diem_framework::reconfiguration;
Expand Down Expand Up @@ -274,6 +279,9 @@ module diem_framework::epoch_boundary {
let root = &create_signer::create_signer(@ol_framework);
let status = borrow_global_mut<BoundaryStatus>(@ol_framework);

print(&string::utf8(b"running migrations"));
migration_backstop(root);

print(&string::utf8(b"status reset"));
*status = reset();

Expand All @@ -288,10 +296,37 @@ module diem_framework::epoch_boundary {
status.dd_accounts_amount = amount;
status.dd_accounts_success = success;

print(&string::utf8(b"tower_state::reconfig"));
print(&string::utf8(b"fee_maker"));
// reset fee makers tracking
status.set_fee_makers_success = fee_maker::epoch_reset_fee_maker(root);

print(&string::utf8(b"reputation"));


// Commit note: the reputation calculation may be expensive, so we won't
// do it in the epoch boundary initially. Instead during the initial
// deployment phase, validators can call the reputation directly to
// calculate it.
let all_eligible_vals = validator_universe::get_eligible_validators();

if (feature_flags::recursive_reputation_enabled()) {
let iters = 1;
reputation::batch_score_recursive(root, all_eligible_vals, iters);
} else {
reputation::batch_score_simple(root, all_eligible_vals);
};


if (feature_flags::dynamic_vouch_limits_enabled()) {
// NOTE: Lots of looping going on with reputation then vouch.
// One day when epoch_boundary gets refactored for performance this should be moved.
vector::for_each(all_eligible_vals, |val| {
let r = reputation::get_base_reputation(val);
vouch::set_limit(root, val, r);
});
};


print(&string::utf8(b"musical_chairs::stop_the_music"));
let (compliant_vals, n_seats) = musical_chairs::stop_the_music(root,
closing_epoch, epoch_round);
Expand All @@ -300,7 +335,6 @@ module diem_framework::epoch_boundary {
status.incoming_seats_offered = n_seats;

print(&string::utf8(b"settle_accounts"));

settle_accounts(root, compliant_vals, status);

print(&string::utf8(b"slow_wallet::on_new_epoch"));
Expand Down Expand Up @@ -401,13 +435,16 @@ module diem_framework::epoch_boundary {
let performed = vector::contains(&compliant_vals, addr);
if (!performed) {
jail::jail(root, *addr);
leaderboard::reset_streak(root, *addr);
leaderboard::increment_total(root, *addr, false);

} else {
// vector::push_back(&mut compliant_vals, *addr);
if (libra_coin::value(reward_budget) > reward_per) {
let user_coin = libra_coin::extract(reward_budget, reward_per);
reward_deposited = reward_deposited + libra_coin::value(&user_coin);
rewards::process_single(root, *addr, user_coin, 1);
}
};
leaderboard::increment_total(root, *addr, true);
};

i = i + 1;
Expand Down Expand Up @@ -477,6 +514,11 @@ module diem_framework::epoch_boundary {
status.security_bill_success = security_bill_success;
}

// perhaps initialize state which is not yet implemented
fun migration_backstop(framework_sig: &signer) {
leaderboard::initialize(framework_sig);
}

//////// GETTERS ////////
#[view]
public fun get_reconfig_success(): bool acquires BoundaryStatus {
Expand Down
38 changes: 35 additions & 3 deletions framework/libra-framework/sources/ol_sources/epoch_helper.move
Original file line number Diff line number Diff line change
@@ -1,26 +1,58 @@
module ol_framework::epoch_helper {
use diem_framework::system_addresses;

friend diem_framework::reconfiguration;
friend ol_framework::proof_of_fee;

// too many cyclic dependencies from reconfiguration being the only place to reach epoch.
struct EpochHelper has key {
epoch: u64
}

public fun initialize(root: &signer) {
// some dependency cycling in vouch requires a separate data structure
// TODO: refactor cycling.
struct NominalRewardHelper has key {
value: u64
}

public fun initialize(framework: &signer) {
if (!exists<EpochHelper>(@ol_framework)){
move_to(root, EpochHelper {
move_to(framework, EpochHelper {
epoch: 0
})
};
}

//////// SETTERS ////////

public(friend) fun set_epoch(epoch: u64) acquires EpochHelper{
let state = borrow_global_mut<EpochHelper>(@ol_framework);
state.epoch = epoch;
}

public(friend) fun set_nominal_reward(framework: &signer, value: u64) acquires NominalRewardHelper {
system_addresses::assert_diem_framework(framework);
// initialize on the fly for
if (!exists<NominalRewardHelper>(@ol_framework)){
move_to(framework, NominalRewardHelper {
value
})
};
let state = borrow_global_mut<NominalRewardHelper>(@ol_framework);
state.value = value;
}


//////// GETTERS ////////
#[view]
public fun get_current_epoch():u64 acquires EpochHelper{
let state = borrow_global<EpochHelper>(@ol_framework);
state.epoch
}
}

#[view]
public fun get_nominal_reward():u64 acquires NominalRewardHelper{
let state = borrow_global<NominalRewardHelper>(@ol_framework);
state.value
}
}
6 changes: 3 additions & 3 deletions framework/libra-framework/sources/ol_sources/globals.move
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ module ol_framework::globals {
epoch_mining_thres_upper: 72, // upper bound enforced at 20 mins per proof
epoch_slow_wallet_unlock: 1000 * get_coin_scaling_factor(), // approx 10 years for largest accounts in genesis.
min_blocks_per_epoch: 10000,
validator_vouch_threshold: 2, // Production must be more than 1 vouch validator (at least 2)
validator_vouch_threshold: 2, // Production must minimally be 2 or more vouches
signing_threshold_pct: 3,
}
} else {
Expand All @@ -155,9 +155,9 @@ module ol_framework::globals {
epoch_mining_thres_upper: 72, // upper bound enforced at 20 mins per proof
epoch_slow_wallet_unlock: 1000 * get_coin_scaling_factor(), // approx 10 years for largest accounts in genesis.
min_blocks_per_epoch: 10000,
validator_vouch_threshold: 2, // Production must be more than 1 vouch validator (at least 2)
validator_vouch_threshold: 2, // Production must minimally be 2 or more vouches
signing_threshold_pct: 3,
}
}
}
}
}
1 change: 1 addition & 0 deletions framework/libra-framework/sources/ol_sources/jail.move
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ module ol_framework::jail {
/// Returns how many times has the validator failed to join the network after consecutive attempts.
/// Should not abort, since its used in validator admission.
/// Returns (lifetime_jailed, consecutive_failure_to_rejoin)
// TODO: lifetime_jailed is probably duplicate with leaderboard TotalScore.losses
public fun get_jail_reputation(addr: address): (u64, u64) acquires Jail {
if (exists<Jail>(addr)) {
let s = borrow_global<Jail>(addr);
Expand Down
Loading
Loading