Skip to content

Commit

Permalink
[move] change data structure for tracking miner proofs used in Carpe …
Browse files Browse the repository at this point in the history
…payments (#890)

* scaffold new struct to count global proofs TowerCounter

* update Migration to include a migration from TowerState to TowerCounter

* change the Migration Tick from end of epoch to every round 3, after upgrade (round 2)

* add test for epoch resetting proof count

* hardened test for fullnode subsidy in base case

* test for tower counter state migration

* test for on the fly migration

* add notes/comments on block prologue

* divide by zero protection in FullnodeSubsidy

* meta test for checking we can destroy state when mocking migration cases

* create a separate module for repetitive mocks, Mock.move

* create test case for mixed validator cases

* legibility of comparison of proofs produced vs threshold

* add preflight check docs

* create future move tests for prod epoch changes

* patch tests and add upgrade documentation

* passing tests for fullnode_reconfig
  • Loading branch information
0o-de-lally authored Dec 10, 2021
1 parent 0b2f290 commit 9d34378
Show file tree
Hide file tree
Showing 29 changed files with 1,347 additions and 489 deletions.
2 changes: 1 addition & 1 deletion language/diem-framework/modules/0L/EpochBoundary.move
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ module EpochBoundary {
// TODO: this call is repeated in propose_new_set.
// Not sure if the performance hit at epoch boundary is worth the refactor.
if (TowerState::node_above_thresh(addr)) {
let count = TowerState::get_count_in_epoch(addr);
let count = TowerState::get_count_above_thresh_in_epoch(addr);

let miner_subsidy = count * proof_price;
FullnodeSubsidy::distribute_fullnode_subsidy(vm, addr, miner_subsidy);
Expand Down
136 changes: 0 additions & 136 deletions language/diem-framework/modules/0L/FullnodeState.depr

This file was deleted.

8 changes: 6 additions & 2 deletions language/diem-framework/modules/0L/FullnodeSubsidy.move
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ address 0x1 {
use 0x1::TowerState;

public fun get_proof_price(one_val_subsidy: u64): u64 {
let global_proofs = TowerState::get_fullnode_proofs();

let global_proofs = TowerState::get_fullnode_proofs_in_epoch_above_thresh();

// proof price is simple, miners divide the equivalent of one compliant
// validator's subsidy.
Expand All @@ -26,8 +27,11 @@ address 0x1 {
// Note to rascals: I know what you're thinking, but for the same effort
// you'll put into that idea, it would be more profitable to just run
// a validator node.
if (global_proofs > 0) {
return one_val_subsidy/global_proofs
};

one_val_subsidy/global_proofs
0
}

public fun distribute_fullnode_subsidy(
Expand Down
2 changes: 1 addition & 1 deletion language/diem-framework/modules/0L/Globals.move
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ module Globals {
max_validators_per_set: 100,
subsidy_ceiling_gas: 296 * COIN_SCALING_FACTOR,
vdf_difficulty: 100,
epoch_mining_thres_lower: 2, // Note: in test harness, the validators are in epoch 0 where they have 1 proof already committed from mock genesis ceremony.
epoch_mining_thres_lower: 2, //many tests depend on two proofs because the test harness already gives one at genesis to validators
epoch_mining_thres_upper: 1000, // upper bound unlimited
epoch_slow_wallet_unlock: 10,
}
Expand Down
29 changes: 8 additions & 21 deletions language/diem-framework/modules/0L/Migrations.move
Original file line number Diff line number Diff line change
Expand Up @@ -88,33 +88,20 @@ module Migrations {
}

/// # Summary
/// Module providing method to convert all wallets to "slow wallets"
/// migrations should have own module, since imports can cause dependency cycling.
module MigrateWallets {
use 0x1::Vector;
/// Module to migrate the tower statistics from TowerState to TowerCounter
module MigrateTowerCounter {
use 0x1::TowerState;
use 0x1::Migrations;
use 0x1::DiemAccount;
use 0x1::ValidatorUniverse;
use 0x1::CoreAddresses;

const UID: u64 = 10;

const UID:u64 = 1;
// Migration to migrate all wallets to be slow wallets
public fun migrate_slow_wallets(vm: &signer) {
public fun migrate_tower_counter(vm: &signer) {
CoreAddresses::assert_diem_root(vm);
if (!Migrations::has_run(UID)) {
let vec_addr = ValidatorUniverse::get_eligible_validators(vm);
// TODO: how to get other accounts?

// tag all accounts as slow wallets
let len = Vector::length<address>(&vec_addr);
let i = 0;
while (i < len) {
let addr = *Vector::borrow<address>(&vec_addr, i);
DiemAccount::vm_migrate_slow_wallet(vm, addr);
i = i + 1;
};
Migrations::push(vm, UID, b"MigrateWallets");
let (global, val, fn) = TowerState::danger_migrate_get_lifetime_proof_count();
TowerState::init_tower_counter(vm, global, val, fn);
Migrations::push(vm, UID, b"MigrateTowerCounter");
};
}

Expand Down
62 changes: 62 additions & 0 deletions language/diem-framework/modules/0L/Mock.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Some fixutres are complex and are repeatedly needed

address 0x1 {
module Mock {
use 0x1::DiemSystem;
use 0x1::TowerState;
use 0x1::Vector;
use 0x1::Stats;
use 0x1::Cases;

public fun mock_case_1(vm: &signer, addr: address){
// can only apply this to a validator
assert(DiemSystem::is_validator(addr) == true, 777701);
// mock mining for the address
// the validator would already have 1 proof from genesis
TowerState::test_helper_mock_mining_vm(vm, addr, 10);

// mock the consensus votes for the address
let voters = Vector::empty<address>();
Vector::push_back<address>(&mut voters, addr);

// Overwrite the statistics to mock that all have been validating.
let i = 1;
while (i < 16) {
// Mock the validator doing work for 15 blocks, and stats being updated.
Stats::process_set_votes(vm, &voters);
i = i + 1;
};

// TODO: careful that the range of heights is within the test
assert(Cases::get_case(vm, addr, 0 , 1000) == 1, 777703);

}


// did not do enough mining, but did validate.
public fun mock_case_2(vm: &signer, addr: address){
// can only apply this to a validator
assert(DiemSystem::is_validator(addr) == true, 777704);
// mock mining for the address
// insufficient number of proofs
TowerState::test_helper_mock_mining_vm(vm, addr, 0);
// assert(TowerState::get_count_in_epoch(addr) == 0, 777705);

// mock the consensus votes for the address
let voters = Vector::empty<address>();
Vector::push_back<address>(&mut voters, addr);

// Overwrite the statistics to mock that all have been validating.
let i = 1;
while (i < 16) {
// Mock the validator doing work for 15 blocks, and stats being updated.
Stats::process_set_votes(vm, &voters);
i = i + 1;
};

// TODO: careful that the range of heights is within the test
assert(Cases::get_case(vm, addr, 0 , 1000) == 2, 777706);

}
}
}
Loading

0 comments on commit 9d34378

Please sign in to comment.