From e5a78cabd0ddb2663f531b65669d18286a4921b8 Mon Sep 17 00:00:00 2001 From: 0o-de-lally <1364012+0o-de-lally@users.noreply.github.com> Date: Wed, 12 Jan 2022 09:59:50 -0500 Subject: [PATCH] Release v5.0.9 (#940) * don't error if there's no vfn_ip * patch display IP address * ol whoami subcommand * patch ol init update-waypoint * make consistent implementation of operator namespace * patch namespaces of init * bump version numbers * include current stdlib compile --- Cargo.lock | 16 +- config/Cargo.toml | 2 +- config/management/Cargo.toml | 2 +- config/management/genesis/src/key.rs | 11 +- .../management/genesis/src/storage_helper.rs | 3 +- diem-node/Cargo.toml | 2 +- language/diem-framework/modules/doc/Audit.md | 3 +- .../diem-framework/modules/doc/DiemAccount.md | 33 +- .../diem-framework/modules/doc/DiemBlock.md | 21 +- .../modules/doc/FullnodeSubsidy.md | 8 +- .../diem-framework/modules/doc/Globals.md | 4 +- .../diem-framework/modules/doc/Migrations.md | 42 +- .../diem-framework/modules/doc/TowerState.md | 817 ++++++++++++++---- .../modules/doc/ol_miner_state.md | 2 +- .../diem-framework/modules/doc/overview.md | 5 +- .../artifacts/current/docs/modules/Audit.md | 3 +- .../current/docs/modules/DiemAccount.md | 33 +- .../current/docs/modules/DiemBlock.md | 21 +- .../{Reconfigure.md => EpochBoundary.md} | 37 +- .../current/docs/modules/FullnodeSubsidy.md | 8 +- .../artifacts/current/docs/modules/Globals.md | 4 +- .../current/docs/modules/Migrations.md | 42 +- .../artifacts/current/docs/modules/Mock.md | 114 +++ .../current/docs/modules/TowerState.md | 817 ++++++++++++++---- .../current/docs/modules/ol_miner_state.md | 2 +- .../current/docs/modules/overview.md | 5 +- .../docs/scripts/script_documentation.md | 3 +- .../error_description.errmap | Bin 14512 -> 14513 bytes .../artifacts/current/modules/025_Globals.mv | Bin 1080 -> 1080 bytes .../current/modules/026_TowerState.mv | Bin 5195 -> 6794 bytes .../current/modules/043_DiemAccount.mv | Bin 13453 -> 13460 bytes .../artifacts/current/modules/051_Audit.mv | Bin 472 -> 395 bytes .../modules/059_MigrateTowerCounter.mv | Bin 0 -> 364 bytes .../{059_Subsidy.mv => 060_Subsidy.mv} | Bin ...lnodeSubsidy.mv => 061_FullnodeSubsidy.mv} | Bin 488 -> 536 bytes .../modules/{061_Epoch.mv => 062_Epoch.mv} | Bin .../current/modules/062_EpochBoundary.mv | Bin 1727 -> 0 bytes .../current/modules/063_DiemBlock.mv | Bin 1226 -> 0 bytes .../current/modules/063_EpochBoundary.mv | Bin 0 -> 1690 bytes .../current/modules/064_DiemBlock.mv | Bin 0 -> 1295 bytes ...usConfig.mv => 065_DiemConsensusConfig.mv} | Bin ...65_DiemVMConfig.mv => 066_DiemVMConfig.mv} | Bin ...{066_DiemVersion.mv => 067_DiemVersion.mv} | Bin .../{067_Upgrade.mv => 068_Upgrade.mv} | Bin .../modules/{068_Oracle.mv => 069_Oracle.mv} | Bin .../{069_Genesis.mv => 070_Genesis.mv} | Bin .../current/modules/070_MigrateWallets.mv | Bin 469 -> 0 bytes .../artifacts/current/modules/071_Mock.mv | Bin 0 -> 621 bytes ..._OracleScripts.mv => 072_OracleScripts.mv} | Bin ...aymentScripts.mv => 073_PaymentScripts.mv} | Bin ...sistenceDemo.mv => 074_PersistenceDemo.mv} | Bin ....mv => 075_SystemAdministrationScripts.mv} | Bin ...75_TestFixtures.mv => 076_TestFixtures.mv} | Bin ...ateScripts.mv => 077_TowerStateScripts.mv} | Bin 565 -> 563 bytes ...nsferScripts.mv => 078_TransferScripts.mv} | Bin ...ts.mv => 079_TreasuryComplianceScripts.mv} | Bin ... => 080_ValidatorAdministrationScripts.mv} | Bin ...atorScripts.mv => 081_ValidatorScripts.mv} | Bin ..._WalletScripts.mv => 082_WalletScripts.mv} | Bin .../script_documentation.md | 3 +- language/diem-framework/staged/stdlib.mv | Bin 109231 -> 111356 bytes ol/changelog/5_0_9.md | 107 +++ ol/cli/Cargo.toml | 2 +- ol/cli/src/commands/init_cmd.rs | 104 ++- ol/cli/src/commands/whoami_cmd.rs | 31 +- ol/cli/src/mgmt/restore.rs | 2 +- .../validators/changing_onchain_ip_address.md | 12 +- ol/onboard/Cargo.toml | 2 +- ol/onboard/src/commands/fix_cmd.rs | 2 +- ol/onboard/src/commands/wizard_fork_cmd.rs | 2 +- ol/onboard/src/commands/wizard_val_cmd.rs | 2 +- ol/onboard/src/manifest.rs | 2 +- ol/tower/Cargo.toml | 2 +- ol/txs/Cargo.toml | 2 +- ol/types/src/account.rs | 2 +- ol/types/src/config.rs | 35 +- ol/types/src/fixtures.rs | 2 +- 77 files changed, 1771 insertions(+), 603 deletions(-) rename language/diem-framework/releases/artifacts/current/docs/modules/{Reconfigure.md => EpochBoundary.md} (80%) create mode 100644 language/diem-framework/releases/artifacts/current/docs/modules/Mock.md create mode 100644 language/diem-framework/releases/artifacts/current/modules/059_MigrateTowerCounter.mv rename language/diem-framework/releases/artifacts/current/modules/{059_Subsidy.mv => 060_Subsidy.mv} (100%) rename language/diem-framework/releases/artifacts/current/modules/{060_FullnodeSubsidy.mv => 061_FullnodeSubsidy.mv} (59%) rename language/diem-framework/releases/artifacts/current/modules/{061_Epoch.mv => 062_Epoch.mv} (100%) delete mode 100644 language/diem-framework/releases/artifacts/current/modules/062_EpochBoundary.mv delete mode 100644 language/diem-framework/releases/artifacts/current/modules/063_DiemBlock.mv create mode 100644 language/diem-framework/releases/artifacts/current/modules/063_EpochBoundary.mv create mode 100644 language/diem-framework/releases/artifacts/current/modules/064_DiemBlock.mv rename language/diem-framework/releases/artifacts/current/modules/{064_DiemConsensusConfig.mv => 065_DiemConsensusConfig.mv} (100%) rename language/diem-framework/releases/artifacts/current/modules/{065_DiemVMConfig.mv => 066_DiemVMConfig.mv} (100%) rename language/diem-framework/releases/artifacts/current/modules/{066_DiemVersion.mv => 067_DiemVersion.mv} (100%) rename language/diem-framework/releases/artifacts/current/modules/{067_Upgrade.mv => 068_Upgrade.mv} (100%) rename language/diem-framework/releases/artifacts/current/modules/{068_Oracle.mv => 069_Oracle.mv} (100%) rename language/diem-framework/releases/artifacts/current/modules/{069_Genesis.mv => 070_Genesis.mv} (100%) delete mode 100644 language/diem-framework/releases/artifacts/current/modules/070_MigrateWallets.mv create mode 100644 language/diem-framework/releases/artifacts/current/modules/071_Mock.mv rename language/diem-framework/releases/artifacts/current/modules/{071_OracleScripts.mv => 072_OracleScripts.mv} (100%) rename language/diem-framework/releases/artifacts/current/modules/{072_PaymentScripts.mv => 073_PaymentScripts.mv} (100%) rename language/diem-framework/releases/artifacts/current/modules/{073_PersistenceDemo.mv => 074_PersistenceDemo.mv} (100%) rename language/diem-framework/releases/artifacts/current/modules/{074_SystemAdministrationScripts.mv => 075_SystemAdministrationScripts.mv} (100%) rename language/diem-framework/releases/artifacts/current/modules/{075_TestFixtures.mv => 076_TestFixtures.mv} (100%) rename language/diem-framework/releases/artifacts/current/modules/{076_TowerStateScripts.mv => 077_TowerStateScripts.mv} (79%) rename language/diem-framework/releases/artifacts/current/modules/{077_TransferScripts.mv => 078_TransferScripts.mv} (100%) rename language/diem-framework/releases/artifacts/current/modules/{078_TreasuryComplianceScripts.mv => 079_TreasuryComplianceScripts.mv} (100%) rename language/diem-framework/releases/artifacts/current/modules/{079_ValidatorAdministrationScripts.mv => 080_ValidatorAdministrationScripts.mv} (100%) rename language/diem-framework/releases/artifacts/current/modules/{080_ValidatorScripts.mv => 081_ValidatorScripts.mv} (100%) rename language/diem-framework/releases/artifacts/current/modules/{081_WalletScripts.mv => 082_WalletScripts.mv} (100%) create mode 100644 ol/changelog/5_0_9.md diff --git a/Cargo.lock b/Cargo.lock index 5fe50f8781..1295a480eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1730,7 +1730,7 @@ dependencies = [ [[package]] name = "diem-config" -version = "5.0.8" +version = "5.0.9" dependencies = [ "bcs", "diem-crypto", @@ -2187,7 +2187,7 @@ dependencies = [ [[package]] name = "diem-management" -version = "5.0.8" +version = "5.0.9" dependencies = [ "anyhow", "bcs", @@ -2306,7 +2306,7 @@ dependencies = [ [[package]] name = "diem-node" -version = "5.0.8" +version = "5.0.9" dependencies = [ "backup-service", "consensus", @@ -5637,7 +5637,7 @@ dependencies = [ [[package]] name = "ol" -version = "5.0.8" +version = "5.0.9" dependencies = [ "abscissa_core", "abscissa_tokio", @@ -5783,7 +5783,7 @@ dependencies = [ [[package]] name = "onboard" -version = "5.0.8" +version = "5.0.9" dependencies = [ "abscissa_core", "anyhow", @@ -5808,7 +5808,7 @@ dependencies = [ "serde_json", "thiserror", "toml", - "tower 5.0.8", + "tower 5.0.9", "txs", "wait-timeout", "zip", @@ -8566,7 +8566,7 @@ dependencies = [ [[package]] name = "tower" -version = "5.0.8" +version = "5.0.9" dependencies = [ "abscissa_core", "ajson", @@ -8790,7 +8790,7 @@ dependencies = [ [[package]] name = "txs" -version = "5.0.8" +version = "5.0.9" dependencies = [ "abscissa_core", "ajson", diff --git a/config/Cargo.toml b/config/Cargo.toml index 7ac36a9455..75a9d83324 100644 --- a/config/Cargo.toml +++ b/config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "diem-config" -version = "5.0.8" +version = "5.0.9" authors = ["Diem Association "] description = "Diem diem-config" repository = "https://github.com/diem/diem" diff --git a/config/management/Cargo.toml b/config/management/Cargo.toml index 4cf774f6da..a338616d04 100644 --- a/config/management/Cargo.toml +++ b/config/management/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "diem-management" -version = "5.0.8" +version = "5.0.9" authors = ["Diem Association "] description = "Diem Management is a tool used to manage the configuration of a Diem Node" repository = "https://github.com/diem/diem" diff --git a/config/management/genesis/src/key.rs b/config/management/genesis/src/key.rs index 41f1c9c94e..5ee0e8f3f9 100644 --- a/config/management/genesis/src/key.rs +++ b/config/management/genesis/src/key.rs @@ -73,21 +73,20 @@ pub fn set_operator_key(path: &PathBuf, namespace: &str) { OnDiskStorage::new(path.join("key_store.json").to_owned()) ); // TODO: Remove hard coded field - let field = format!("{}-oper/operator", namespace); + let field = format!("{}/operator", namespace); let key = storage.get_public_key(&field).unwrap().public_key; let peer_id = diem_types::account_address::from_public_key(&key); storage.set(OPERATOR_ACCOUNT, peer_id).unwrap(); } //////// 0L ///////// -pub fn set_owner_key(path: &PathBuf, namespace: &str) { +pub fn set_owner_key(path: &PathBuf, namespace: &str, account: AccountAddress) { let mut storage = diem_secure_storage::Storage::OnDiskStorage( OnDiskStorage::new(path.join("key_store.json").to_owned()) ); // let authkey: AuthenticationKey = namespace.parse().unwrap(); // let account = authkey.derived_address(); - let account = namespace.parse::().unwrap(); - storage.set(&format!("{}-oper/{}", namespace, OWNER_ACCOUNT), account).unwrap(); + storage.set(&format!("{}/{}", namespace, OWNER_ACCOUNT), account).unwrap(); // storage.set(&format!("{}/{}", namespace, OWNER_ACCOUNT), account).unwrap(); } @@ -98,7 +97,7 @@ pub fn set_waypoint(path: &PathBuf, namespace: &str, waypoint: Waypoint) { let mut storage = diem_secure_storage::Storage::OnDiskStorage( OnDiskStorage::new(path.join("key_store.json").to_owned()) ); - storage.set(&format!("{}-oper/{}", namespace, WAYPOINT), waypoint).unwrap(); + storage.set(&format!("{}/{}", namespace, WAYPOINT), waypoint).unwrap(); } //////// 0L ///////// @@ -106,7 +105,7 @@ pub fn set_genesis_waypoint(path: &PathBuf, namespace: &str, waypoint: Waypoint) let mut storage = diem_secure_storage::Storage::OnDiskStorage( OnDiskStorage::new(path.join("key_store.json").to_owned()) ); - storage.set(&format!("{}-oper/{}", namespace, GENESIS_WAYPOINT), waypoint).unwrap(); + storage.set(&format!("{}/{}", namespace, GENESIS_WAYPOINT), waypoint).unwrap(); } #[derive(Debug, StructOpt)] diff --git a/config/management/genesis/src/storage_helper.rs b/config/management/genesis/src/storage_helper.rs index c8d909dac1..59514bb0b4 100644 --- a/config/management/genesis/src/storage_helper.rs +++ b/config/management/genesis/src/storage_helper.rs @@ -119,7 +119,7 @@ impl StorageHelper { &self, namespace: String, keys: KeyScheme, is_genesis: bool ) { let mut storage_owner = self.storage(namespace.clone()); - let mut storage_oper = self.storage(namespace.clone() + "-oper"); + let mut storage_oper = self.storage(namespace.clone()); if is_genesis { // Data needed for testnet, swarm, and genesis ceremony. @@ -138,7 +138,6 @@ impl StorageHelper { .import_private_key(OWNER_KEY, keys.child_0_owner.get_private_key()) .unwrap(); } - // storage_oper.set(OWNER_ACCOUNT, peer_id).unwrap(); storage_oper .import_private_key(OPERATOR_KEY, keys.child_1_operator.get_private_key()) diff --git a/diem-node/Cargo.toml b/diem-node/Cargo.toml index c67fa40e56..89988dfa77 100644 --- a/diem-node/Cargo.toml +++ b/diem-node/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "diem-node" -version = "5.0.8" +version = "5.0.9" authors = ["Diem Association "] description = "Diem node" repository = "https://github.com/diem/diem" diff --git a/language/diem-framework/modules/doc/Audit.md b/language/diem-framework/modules/doc/Audit.md index 4b72839bf2..93042403ba 100644 --- a/language/diem-framework/modules/doc/Audit.md +++ b/language/diem-framework/modules/doc/Audit.md @@ -11,7 +11,6 @@
use 0x1::AutoPay;
 use 0x1::DiemAccount;
-use 0x1::GAS;
 use 0x1::Testnet;
 use 0x1::TowerState;
 use 0x1::ValidatorConfig;
@@ -41,7 +40,7 @@
   let oper = ValidatorConfig::get_operator(val);
   if (oper == val) return false;
   // operator account has balance
-  if (DiemAccount::balance<GAS>(oper) < 50000 && !Testnet::is_testnet()) return false;
+  // if (DiemAccount::balance<GAS>(oper) < 50000 && !Testnet::is_testnet()) return false;
   // has autopay enabled
   if (!AutoPay::is_enabled(val)) return false;
   // has mining state
diff --git a/language/diem-framework/modules/doc/DiemAccount.md b/language/diem-framework/modules/doc/DiemAccount.md
index 1c1aa210af..2d51f9ce2f 100644
--- a/language/diem-framework/modules/doc/DiemAccount.md
+++ b/language/diem-framework/modules/doc/DiemAccount.md
@@ -935,39 +935,39 @@ Tried to create a balance for an account whose role does not allow holding balan
 
 
 
-
+
 
-The withdrawal of funds would have exceeded the the account's limits
 
 
-
const EWITHDRAWAL_EXCEEDS_LIMITS: u64 = 12016;
+
const ESLOW_WALLET_TRANSFERS_DISABLED_SYSTEMWIDE: u64 = 120127;
 
- + +The withdrawal of funds would have exceeded the the account's limits -
const EWITHDRAWAL_NOT_FOR_COMMUNITY_WALLET: u64 = 120126;
+
const EWITHDRAWAL_EXCEEDS_LIMITS: u64 = 12016;
 
- + -
const EWITHDRAWAL_SLOW_WAL_EXCEEDS_UNLOCKED_LIMIT: u64 = 120128;
+
const EWITHDRAWAL_NOT_FOR_COMMUNITY_WALLET: u64 = 120126;
 
- + -
const EWITHDRAWAL_TRANSFERS_DISABLED_SYSTEMWIDE: u64 = 120127;
+
const EWITHDRAWAL_SLOW_WAL_EXCEEDS_UNLOCKED_LIMIT: u64 = 120128;
 
@@ -2657,9 +2657,7 @@ the sender's account balance.
public fun extract_withdraw_capability(
     sender: &signer
 ): WithdrawCapability acquires DiemAccount {
-    //////// 0L //////// Transfers disabled by default
-    //////// 0L //////// Transfers of 10 GAS
-    //////// 0L //////// enabled when epoch is 1000
+
     let sender_addr = Signer::address_of(sender);
 
     /////// 0L /////////
@@ -2670,11 +2668,14 @@ the sender's account balance.
         Errors::limit_exceeded(EWITHDRAWAL_NOT_FOR_COMMUNITY_WALLET)
     );
     /////// 0L /////////
-    if (!DiemConfig::check_transfer_enabled()) {
-        // only VM can make TXs if transfers are not enabled.
+    // Slow wallet transfers disabled by default, enabled when epoch is 1000
+    // At that point slow wallets receive 1,000 coins unlocked per day.
+    if (is_slow(sender_addr) && !DiemConfig::check_transfer_enabled() ) {
+      // if transfers are not enabled for slow wallets
+      // then the tx should fail
         assert(
-            sender_addr == CoreAddresses::DIEM_ROOT_ADDRESS(),
-            Errors::limit_exceeded(EWITHDRAWAL_TRANSFERS_DISABLED_SYSTEMWIDE)
+            false,
+            Errors::limit_exceeded(ESLOW_WALLET_TRANSFERS_DISABLED_SYSTEMWIDE)
         );
     };
     // Abort if we already extracted the unique withdraw capability for this account.
diff --git a/language/diem-framework/modules/doc/DiemBlock.md b/language/diem-framework/modules/doc/DiemBlock.md
index 4391882432..62d03c6d53 100644
--- a/language/diem-framework/modules/doc/DiemBlock.md
+++ b/language/diem-framework/modules/doc/DiemBlock.md
@@ -4,6 +4,8 @@
 # Module `0x1::DiemBlock`
 
 This module defines a struct storing the metadata of the block and new block events.
+it also contains all of the block prologue logic which is called from the Rust executor.
+For 0L the following changes are applied to the block prologue
 
 
 -  [Resource `BlockMetadata`](#0x1_DiemBlock_BlockMetadata)
@@ -23,10 +25,11 @@ This module defines a struct storing the metadata of the block and new block eve
 use 0x1::DiemSystem;
 use 0x1::DiemTimestamp;
 use 0x1::Epoch;
-use 0x1::EpochBoundary;
+use 0x1::EpochBoundary;
 use 0x1::Errors;
 use 0x1::Event;
 use 0x1::GAS;
+use 0x1::MigrateTowerCounter;
 use 0x1::Migrations;
 use 0x1::Stats;
 
@@ -241,12 +244,12 @@ The runtime always runs this before executing the transactions in a block. DiemTimestamp::assert_operating(); // Operational constraint: can only be invoked by the VM. CoreAddresses::assert_vm(&vm); - // Authorization assert( proposer == CoreAddresses::VM_RESERVED_ADDRESS() || DiemSystem::is_validator(proposer), Errors::requires_address(EVM_OR_VALIDATOR) ); + //////// 0L //////// // increment stats Stats::process_set_votes(&vm, &previous_block_votes); @@ -259,6 +262,15 @@ The runtime always runs this before executing the transactions in a block. AutoPay::process_autopay(&vm); }; + // Do any pending migrations + // TODO: should this be round 2 (when upgrade writeset happens). May be a on off-by-one. + if (round == 3){ + // safety. Maybe init Migration struct + Migrations::init(&vm); + // Migration UID 1 + MigrateTowerCounter::migrate_tower_counter(&vm); + }; + let block_metadata_ref = borrow_global_mut<BlockMetadata>(CoreAddresses::DIEM_ROOT_ADDRESS()); DiemTimestamp::update_global_time(&vm, proposer, timestamp); block_metadata_ref.height = block_metadata_ref.height + 1; @@ -275,12 +287,11 @@ The runtime always runs this before executing the transactions in a block. //////// 0L //////// // EPOCH BOUNDARY if (Epoch::epoch_finished()) { - // Run migrations - Migrations::init(&vm); + // TODO: We don't need to pass block height to EpochBoundaryOL. // It should use the BlockMetadata. But there's a circular reference // there when we try. - EpochBoundary::reconfigure(&vm, get_current_block_height()); + EpochBoundary::reconfigure(&vm, get_current_block_height()); }; }
diff --git a/language/diem-framework/modules/doc/FullnodeSubsidy.md b/language/diem-framework/modules/doc/FullnodeSubsidy.md index 5d3a798197..e3cb78c46a 100644 --- a/language/diem-framework/modules/doc/FullnodeSubsidy.md +++ b/language/diem-framework/modules/doc/FullnodeSubsidy.md @@ -35,7 +35,8 @@
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.
@@ -44,8 +45,11 @@
   // 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
 }
 
diff --git a/language/diem-framework/modules/doc/Globals.md b/language/diem-framework/modules/doc/Globals.md index 7e7deb41ea..c5a1b62871 100644 --- a/language/diem-framework/modules/doc/Globals.md +++ b/language/diem-framework/modules/doc/Globals.md @@ -371,7 +371,7 @@ Get the constants for the current network max_validators_per_set: 100, subsidy_ceiling_gas: 296 * COIN_SCALING_FACTOR, vdf_difficulty: 100, - epoch_mining_thres_lower: 1, + 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, } @@ -383,7 +383,7 @@ Get the constants for the current network max_validators_per_set: 100, subsidy_ceiling_gas: 8640000 * COIN_SCALING_FACTOR, vdf_difficulty: 120000000, - epoch_mining_thres_lower: 1, + epoch_mining_thres_lower: 1, // in testnet, staging, we don't want to wait too long between proofs. epoch_mining_thres_upper: 72, // upper bound enforced at 20 mins per proof. epoch_slow_wallet_unlock: 10000000, } diff --git a/language/diem-framework/modules/doc/Migrations.md b/language/diem-framework/modules/doc/Migrations.md index e6e2544075..f532918a1e 100644 --- a/language/diem-framework/modules/doc/Migrations.md +++ b/language/diem-framework/modules/doc/Migrations.md @@ -1,27 +1,24 @@ - + -# Module `0x1::MigrateWallets` +# Module `0x1::MigrateTowerCounter` ## Summary -Module providing method to convert all wallets to "slow wallets" -migrations should have own module, since imports can cause dependency cycling. +Module to migrate the tower statistics from TowerState to TowerCounter - [Summary](#@Summary_0) - [Constants](#@Constants_1) -- [Function `migrate_slow_wallets`](#0x1_MigrateWallets_migrate_slow_wallets) +- [Function `migrate_tower_counter`](#0x1_MigrateTowerCounter_migrate_tower_counter)
use 0x1::CoreAddresses;
-use 0x1::DiemAccount;
 use 0x1::Migrations;
-use 0x1::ValidatorUniverse;
-use 0x1::Vector;
+use 0x1::TowerState;
 
@@ -31,22 +28,22 @@ migrations should have own module, since imports can cause dependency cycling. ## Constants - + -
const UID: u64 = 10;
+
const UID: u64 = 1;
 
- + -## Function `migrate_slow_wallets` +## Function `migrate_tower_counter` -
public fun migrate_slow_wallets(vm: &signer)
+
public fun migrate_tower_counter(vm: &signer)
 
@@ -55,21 +52,12 @@ migrations should have own module, since imports can cause dependency cycling. Implementation -
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");
+  if (!Migrations::has_run(UID)) {
+    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");
   };
 }
 
diff --git a/language/diem-framework/modules/doc/TowerState.md b/language/diem-framework/modules/doc/TowerState.md index 256f2d3d45..272d50de7f 100644 --- a/language/diem-framework/modules/doc/TowerState.md +++ b/language/diem-framework/modules/doc/TowerState.md @@ -4,24 +4,15 @@ # Module `0x1::TowerState` - -## Summary - -TODO - - -- [Summary](#@Summary_0) - [Resource `TowerList`](#0x1_TowerState_TowerList) - [Resource `TowerStats`](#0x1_TowerState_TowerStats) +- [Resource `TowerCounter`](#0x1_TowerState_TowerCounter) - [Struct `Proof`](#0x1_TowerState_Proof) - [Resource `TowerProofHistory`](#0x1_TowerState_TowerProofHistory) -- [Constants](#@Constants_1) -- [Function `increment_stats`](#0x1_TowerState_increment_stats) -- [Function `epoch_reset`](#0x1_TowerState_epoch_reset) -- [Function `get_fullnode_proofs`](#0x1_TowerState_get_fullnode_proofs) +- [Constants](#@Constants_0) - [Function `init_miner_list`](#0x1_TowerState_init_miner_list) -- [Function `init_miner_stats`](#0x1_TowerState_init_miner_stats) +- [Function `init_tower_counter`](#0x1_TowerState_init_tower_counter) - [Function `init_miner_list_and_stats`](#0x1_TowerState_init_miner_list_and_stats) - [Function `is_init`](#0x1_TowerState_is_init) - [Function `is_onboarding`](#0x1_TowerState_is_onboarding) @@ -31,25 +22,37 @@ TODO - [Function `commit_state`](#0x1_TowerState_commit_state) - [Function `commit_state_by_operator`](#0x1_TowerState_commit_state_by_operator) - [Function `verify_and_update_state`](#0x1_TowerState_verify_and_update_state) -- [Function `update_metrics`](#0x1_TowerState_update_metrics) +- [Function `update_epoch_metrics_vals`](#0x1_TowerState_update_epoch_metrics_vals) - [Function `node_above_thresh`](#0x1_TowerState_node_above_thresh) - [Function `reconfig`](#0x1_TowerState_reconfig) - [Function `init_miner_state`](#0x1_TowerState_init_miner_state) - [Function `first_challenge_includes_address`](#0x1_TowerState_first_challenge_includes_address) - [Function `get_miner_latest_epoch`](#0x1_TowerState_get_miner_latest_epoch) - [Function `reset_rate_limit`](#0x1_TowerState_reset_rate_limit) +- [Function `increment_stats`](#0x1_TowerState_increment_stats) +- [Function `epoch_reset`](#0x1_TowerState_epoch_reset) - [Function `get_miner_list`](#0x1_TowerState_get_miner_list) - [Function `get_tower_height`](#0x1_TowerState_get_tower_height) -- [Function `get_epochs_mining`](#0x1_TowerState_get_epochs_mining) +- [Function `get_epochs_compliant`](#0x1_TowerState_get_epochs_compliant) - [Function `get_count_in_epoch`](#0x1_TowerState_get_count_in_epoch) +- [Function `get_count_above_thresh_in_epoch`](#0x1_TowerState_get_count_above_thresh_in_epoch) +- [Function `lazy_reset_count_in_epoch`](#0x1_TowerState_lazy_reset_count_in_epoch) - [Function `can_create_val_account`](#0x1_TowerState_can_create_val_account) -- [Function `test_helper_init_miner`](#0x1_TowerState_test_helper_init_miner) +- [Function `get_validator_proofs_in_epoch`](#0x1_TowerState_get_validator_proofs_in_epoch) +- [Function `get_fullnode_proofs_in_epoch`](#0x1_TowerState_get_fullnode_proofs_in_epoch) +- [Function `get_fullnode_proofs_in_epoch_above_thresh`](#0x1_TowerState_get_fullnode_proofs_in_epoch_above_thresh) +- [Function `get_lifetime_proof_count`](#0x1_TowerState_get_lifetime_proof_count) +- [Function `danger_migrate_get_lifetime_proof_count`](#0x1_TowerState_danger_migrate_get_lifetime_proof_count) +- [Function `test_helper_init_val`](#0x1_TowerState_test_helper_init_val) +- [Function `test_epoch_reset_counter`](#0x1_TowerState_test_epoch_reset_counter) - [Function `test_helper_operator_submits`](#0x1_TowerState_test_helper_operator_submits) - [Function `test_helper_mock_mining`](#0x1_TowerState_test_helper_mock_mining) - [Function `test_helper_mock_mining_vm`](#0x1_TowerState_test_helper_mock_mining_vm) +- [Function `danger_mock_mining`](#0x1_TowerState_danger_mock_mining) - [Function `test_helper_mock_reconfig`](#0x1_TowerState_test_helper_mock_reconfig) - [Function `test_helper_get_height`](#0x1_TowerState_test_helper_get_height) - [Function `test_helper_get_count`](#0x1_TowerState_test_helper_get_count) +- [Function `test_helper_get_nominal_count`](#0x1_TowerState_test_helper_get_nominal_count) - [Function `test_helper_get_contiguous_vm`](#0x1_TowerState_test_helper_get_contiguous_vm) - [Function `test_helper_set_rate_limit`](#0x1_TowerState_test_helper_set_rate_limit) - [Function `test_helper_set_epochs_mining`](#0x1_TowerState_test_helper_set_epochs_mining) @@ -57,6 +60,9 @@ TODO - [Function `test_helper_previous_proof_hash`](#0x1_TowerState_test_helper_previous_proof_hash) - [Function `test_helper_set_weight_vm`](#0x1_TowerState_test_helper_set_weight_vm) - [Function `test_helper_set_weight`](#0x1_TowerState_test_helper_set_weight) +- [Function `test_mock_depr_tower_stats`](#0x1_TowerState_test_mock_depr_tower_stats) +- [Function `test_get_liftime_proofs`](#0x1_TowerState_test_get_liftime_proofs) +- [Function `test_danger_destroy_tower_counter`](#0x1_TowerState_test_danger_destroy_tower_counter)
use 0x1::CoreAddresses;
@@ -107,6 +113,7 @@ A list of all miners' addresses
 
 ## Resource `TowerStats`
 
+To use in migration, and in future upgrade to deprecate.
 
 
 
struct TowerStats has key
@@ -140,6 +147,76 @@ A list of all miners' addresses
 
 
 
+
+
+
+
+## Resource `TowerCounter`
+
+The struct to store the global count of proofs in 0x0
+
+
+
struct TowerCounter has key
+
+ + + +
+Fields + + +
+
+lifetime_proofs: u64 +
+
+ +
+
+lifetime_validator_proofs: u64 +
+
+ +
+
+lifetime_fullnode_proofs: u64 +
+
+ +
+
+proofs_in_epoch: u64 +
+
+ +
+
+validator_proofs_in_epoch: u64 +
+
+ +
+
+fullnode_proofs_in_epoch: u64 +
+
+ +
+
+validator_proofs_in_epoch_above_thresh: u64 +
+
+ +
+
+fullnode_proofs_in_epoch_above_thresh: u64 +
+
+ +
+
+ +
@@ -272,7 +349,7 @@ the miner last created a new account - + ## Constants @@ -286,92 +363,6 @@ the miner last created a new account - - -## Function `increment_stats` - - - -
fun increment_stats(miner_addr: address)
-
- - - -
-Implementation - - -
fun increment_stats(miner_addr: address) acquires TowerStats {
-  assert(exists<TowerStats>(CoreAddresses::VM_RESERVED_ADDRESS()), 1301001);
-  let state = borrow_global_mut<TowerStats>(CoreAddresses::VM_RESERVED_ADDRESS());
-
-  if (ValidatorConfig::is_valid(miner_addr)) {
-    state.validator_proofs = state.validator_proofs + 1;
-  } else {
-    state.fullnode_proofs = state.fullnode_proofs + 1;
-  };
-
-  state.proofs_in_epoch = state.proofs_in_epoch + 1;
-}
-
- - - -
- - - -## Function `epoch_reset` - - - -
public fun epoch_reset(vm: &signer)
-
- - - -
-Implementation - - -
public fun epoch_reset(vm: &signer) acquires TowerStats {
-  CoreAddresses::assert_vm(vm);
-  let state = borrow_global_mut<TowerStats>(CoreAddresses::VM_RESERVED_ADDRESS());
-  state.proofs_in_epoch = 0;
-  state.validator_proofs = 0;
-  state.fullnode_proofs = 0;
-}
-
- - - -
- - - -## Function `get_fullnode_proofs` - - - -
public fun get_fullnode_proofs(): u64
-
- - - -
-Implementation - - -
public fun get_fullnode_proofs(): u64 acquires TowerStats{
-  let state = borrow_global<TowerStats>(CoreAddresses::VM_RESERVED_ADDRESS());
-  state.fullnode_proofs
-}
-
- - - -
- ## Function `init_miner_list` @@ -400,14 +391,14 @@ Create an empty list of miners - + -## Function `init_miner_stats` +## Function `init_tower_counter` Create an empty miner stats -
fun init_miner_stats(vm: &signer)
+
public fun init_tower_counter(vm: &signer, lifetime_proofs: u64, lifetime_validator_proofs: u64, lifetime_fullnode_proofs: u64)
 
@@ -416,12 +407,25 @@ Create an empty miner stats Implementation -
fun init_miner_stats(vm: &signer) {
-  move_to<TowerStats>(vm, TowerStats {
-    proofs_in_epoch: 0u64,
-    validator_proofs: 0u64,
-    fullnode_proofs: 0u64,
-  });
+
public fun init_tower_counter(
+  vm: &signer,
+  lifetime_proofs: u64,
+  lifetime_validator_proofs: u64,
+  lifetime_fullnode_proofs: u64,
+) {
+  if (!exists<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS())) {
+    move_to<TowerCounter>(vm, TowerCounter {
+      lifetime_proofs,
+      lifetime_validator_proofs,
+      lifetime_fullnode_proofs,
+      proofs_in_epoch: 0,
+      validator_proofs_in_epoch: 0,
+      fullnode_proofs_in_epoch: 0,
+      validator_proofs_in_epoch_above_thresh: 0,
+      fullnode_proofs_in_epoch_above_thresh: 0,
+    });
+  }
+
 }
 
@@ -447,7 +451,9 @@ Create empty miners list and stats
public fun init_miner_list_and_stats(vm: &signer) {
   init_miner_list(vm);
-  init_miner_stats(vm);
+
+  // Note: for testing migration we need to destroy this struct, see test_danger_destroy_tower_counter
+  init_tower_counter(vm, 0, 0, 0);
 }
 
@@ -497,9 +503,10 @@ is onboarding
public fun is_onboarding(addr: address): bool acquires TowerProofHistory {
+  let count = get_count_in_epoch(addr);
   let state = borrow_global<TowerProofHistory>(addr);
 
-  state.count_proofs_in_epoch < 2 &&
+  count < 2 &&
   state.epochs_since_last_account_creation < 2
 }
 
@@ -595,14 +602,13 @@ adds tower to list of towers solution: vector<u8>, difficulty: u64, security: u64, -) acquires TowerProofHistory, TowerList, TowerStats { +) acquires TowerProofHistory, TowerList, TowerCounter { // TODO: Previously in OLv3 is_genesis() returned true. // How to check that this is part of genesis? is_genesis returns false here. // In rust the vm_genesis creates a Signer for the miner. // So the SENDER is not the same and the Signer. - init_miner_state(miner_sig, &challenge, &solution, difficulty, security); // TODO: Move this elsewhere? // Initialize stats for first validator set from rust genesis. @@ -636,7 +642,7 @@ Permissions: PUBLIC, ANYONE
public fun commit_state(
   miner_sign: &signer,
   proof: Proof
-) acquires TowerProofHistory, TowerList, TowerStats {
+) acquires TowerProofHistory, TowerList, TowerCounter {
   // Get address, assumes the sender is the signer.
   let miner_addr = Signer::address_of(miner_sign);
 
@@ -657,7 +663,6 @@ Permissions: PUBLIC, ANYONE
     return
   };
 
-
   // Process the proof
   verify_and_update_state(miner_addr, proof, true);
 }
@@ -686,17 +691,16 @@ Permissions: PUBLIC, ANYONE
   operator_sig: &signer,
   miner_addr: address,
   proof: Proof
-) acquires TowerProofHistory, TowerList, TowerStats {
+) acquires TowerProofHistory, TowerList, TowerCounter {
 
   // Check the signer is in fact an operator delegated by the owner.
 
   // Get address, assumes the sender is the signer.
   assert(ValidatorConfig::get_operator(miner_addr) == Signer::address_of(operator_sig), Errors::requires_role(130103));
-
   // Abort if not initialized. Assumes the validator Owner account already has submitted the 0th miner proof in onboarding.
   assert(exists<TowerProofHistory>(miner_addr), Errors::not_published(130104));
 
-  // return early if difficulty and security are not correct.
+  // Return early if difficulty and security are not correct.
   // Check vdf difficulty constant. Will be different in tests than in production.
   // Skip this check on local tests, we need tests to send differentdifficulties.
   if (!Testnet::is_testnet()){
@@ -738,14 +742,17 @@ Permissions: PUBLIC, ANYONE
   miner_addr: address,
   proof: Proof,
   steady_state: bool
-) acquires TowerProofHistory, TowerList, TowerStats {
+) acquires TowerProofHistory, TowerList, TowerCounter {
+  // instead of looping through all miners at end of epcoh the stats are only reset when the miner submits a new proof.
+  lazy_reset_count_in_epoch(miner_addr);
 
-  let miner_history = borrow_global<TowerProofHistory>(miner_addr);
   assert(
-    miner_history.count_proofs_in_epoch < Globals::get_epoch_mining_thres_upper(),
+    get_count_in_epoch(miner_addr) < Globals::get_epoch_mining_thres_upper(),
     Errors::invalid_state(130108)
   );
 
+  let miner_history = borrow_global<TowerProofHistory>(miner_addr);
+
   // If not genesis proof, check hash to ensure the proof continues the chain
   if (steady_state) {
     //If not genesis proof, check hash
@@ -784,13 +791,13 @@ Permissions: PUBLIC, ANYONE
 
 
 
-
+
 
-## Function `update_metrics`
+## Function `update_epoch_metrics_vals`
 
 
 
-
fun update_metrics(account: &signer, miner_addr: address)
+
fun update_epoch_metrics_vals(account: &signer, miner_addr: address)
 
@@ -799,7 +806,7 @@ Permissions: PUBLIC, ANYONE Implementation -
fun update_metrics(account: &signer, miner_addr: address) acquires TowerProofHistory {
+
fun update_epoch_metrics_vals(account: &signer, miner_addr: address) acquires TowerProofHistory {
   // The goal of update_metrics is to confirm that a miner participated in consensus during
   // an epoch, but also that there were mining proofs submitted in that epoch.
   CoreAddresses::assert_diem_root(account);
@@ -813,11 +820,10 @@ Permissions: PUBLIC, ANYONE
   // the resource was last emptied.
   let passed = node_above_thresh(miner_addr);
   let miner_history = borrow_global_mut<TowerProofHistory>(miner_addr);
-
   // Update statistics.
   if (passed) {
-      let this_epoch = DiemConfig::get_current_epoch();
-      miner_history.latest_epoch_mining = this_epoch;
+      // let this_epoch = DiemConfig::get_current_epoch();
+      // miner_history.latest_epoch_mining = this_epoch; // TODO: Don't need this
       miner_history.epochs_validating_and_mining
         = miner_history.epochs_validating_and_mining + 1u64;
       miner_history.contiguous_epochs_validating_and_mining
@@ -855,8 +861,7 @@ Checks to see if miner submitted enough proofs to be considered compliant
 
 
 
public fun node_above_thresh(miner_addr: address): bool acquires TowerProofHistory {
-  let miner_history = borrow_global<TowerProofHistory>(miner_addr);
-  miner_history.count_proofs_in_epoch > Globals::get_epoch_mining_thres_lower()
+  get_count_in_epoch(miner_addr) >= Globals::get_epoch_mining_thres_lower()
 }
 
@@ -870,7 +875,7 @@ Checks to see if miner submitted enough proofs to be considered compliant -
public fun reconfig(vm: &signer, migrate_eligible_validators: &vector<address>)
+
public fun reconfig(vm: &signer, outgoing_validators: &vector<address>)
 
@@ -879,38 +884,30 @@ Checks to see if miner submitted enough proofs to be considered compliant Implementation -
public fun reconfig(vm: &signer, migrate_eligible_validators: &vector<address>) acquires TowerProofHistory, TowerList {
+
public fun reconfig(vm: &signer, outgoing_validators: &vector<address>) acquires TowerProofHistory, TowerList, TowerCounter {
   // Check permissions
   CoreAddresses::assert_diem_root(vm);
 
-  // check TowerList exists, or use eligible_validators to initialize.
-  // Migration on hot upgrade
-  if (!exists<TowerList>(@0x0)) {
-    move_to<TowerList>(vm, TowerList {
-      list: *migrate_eligible_validators
-    });
-  };
-
-  let towerlist_state = borrow_global_mut<TowerList>(@0x0);
-
-  // Get list of validators from ValidatorUniverse
-  // let eligible_validators = ValidatorUniverse::get_eligible_validators(vm);
-
   // Iterate through validators and call update_metrics for each validator that had proofs this epoch
-  let size = Vector::length<address>(& *&towerlist_state.list); //TODO: These references are weird
+  let vals_len = Vector::length<address>(outgoing_validators); //TODO: These references are weird
   let i = 0;
-  while (i < size) {
-      let val = Vector::borrow(&towerlist_state.list, i);
+  while (i < vals_len) {
+      let val = Vector::borrow(outgoing_validators, i);
 
       // For testing: don't call update_metrics unless there is account state for the address.
       if (exists<TowerProofHistory>(*val)){
-          update_metrics(vm, *val);
+          update_epoch_metrics_vals(vm, *val);
       };
       i = i + 1;
   };
 
-  //reset miner list
-  towerlist_state.list = Vector::empty<address>();
+  epoch_reset(vm);
+  // safety
+  if (exists<TowerList>(@0x0)) {
+    //reset miner list
+    let towerlist_state = borrow_global_mut<TowerList>(@0x0);
+    towerlist_state.list = Vector::empty<address>();
+  };
 }
 
@@ -939,7 +936,7 @@ Checks to see if miner submitted enough proofs to be considered compliant solution: &vector<u8>, difficulty: u64, security: u64 -) acquires TowerProofHistory, TowerList, TowerStats { +) acquires TowerProofHistory, TowerList, TowerCounter { // NOTE Only Signer can update own state. // Should only happen once. @@ -964,7 +961,6 @@ Checks to see if miner submitted enough proofs to be considered compliant security, }; - //submit the proof verify_and_update_state(Signer::address_of(miner_sig), proof, false); } @@ -1018,7 +1014,7 @@ Checks to see if miner submitted enough proofs to be considered compliant -
public fun get_miner_latest_epoch(vm: &signer, addr: address): u64
+
public fun get_miner_latest_epoch(addr: address): u64
 
@@ -1027,8 +1023,7 @@ Checks to see if miner submitted enough proofs to be considered compliant Implementation -
public fun get_miner_latest_epoch(vm: &signer, addr: address): u64 acquires TowerProofHistory {
-  CoreAddresses::assert_diem_root(vm);
+
public fun get_miner_latest_epoch(addr: address): u64 acquires TowerProofHistory {
   let addr_state = borrow_global<TowerProofHistory>(addr);
   *&addr_state.latest_epoch_mining
 }
@@ -1061,6 +1056,83 @@ Checks to see if miner submitted enough proofs to be considered compliant
 
 
 
+
+
+
+
+## Function `increment_stats`
+
+
+
+
fun increment_stats(miner_addr: address)
+
+ + + +
+Implementation + + +
fun increment_stats(miner_addr: address) acquires TowerProofHistory, TowerCounter {
+  // safety. Don't cause VM to halt
+  if (!exists<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS())) return;
+
+  let above = node_above_thresh(miner_addr);
+
+  let state = borrow_global_mut<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS());
+
+  if (ValidatorConfig::is_valid(miner_addr)) {
+    state.validator_proofs_in_epoch = state.validator_proofs_in_epoch + 1;
+    state.lifetime_validator_proofs = state.lifetime_validator_proofs + 1;
+    // only proofs above threshold are counted here. The preceding proofs are not counted;
+    if (above) { state.validator_proofs_in_epoch_above_thresh = state.validator_proofs_in_epoch_above_thresh + 1; }
+  } else {
+    state.fullnode_proofs_in_epoch = state.fullnode_proofs_in_epoch + 1;
+    state.lifetime_fullnode_proofs = state.lifetime_fullnode_proofs + 1;
+    // Preceding proofs before threshold was met are not counted to payment.
+    if (above) { state.fullnode_proofs_in_epoch_above_thresh = state.fullnode_proofs_in_epoch_above_thresh + 1; }
+  };
+
+  state.proofs_in_epoch = state.proofs_in_epoch + 1;
+  state.lifetime_proofs = state.lifetime_proofs + 1;
+}
+
+ + + +
+ + + +## Function `epoch_reset` + +Reset the tower counter at the end of epoch. + + +
public fun epoch_reset(vm: &signer)
+
+ + + +
+Implementation + + +
public fun epoch_reset(vm: &signer) acquires TowerCounter {
+  CoreAddresses::assert_vm(vm);
+  if (!exists<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS())) return;
+
+  let state = borrow_global_mut<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS());
+  state.proofs_in_epoch = 0;
+  state.validator_proofs_in_epoch = 0;
+  state.fullnode_proofs_in_epoch = 0;
+  state.validator_proofs_in_epoch_above_thresh = 0;
+  state.fullnode_proofs_in_epoch_above_thresh = 0;
+}
+
+ + +
@@ -1118,13 +1190,13 @@ Public Getters /// - + -## Function `get_epochs_mining` +## Function `get_epochs_compliant` -
public fun get_epochs_mining(node_addr: address): u64
+
public fun get_epochs_compliant(node_addr: address): u64
 
@@ -1133,7 +1205,7 @@ Public Getters /// Implementation -
public fun get_epochs_mining(node_addr: address): u64 acquires TowerProofHistory {
+
public fun get_epochs_compliant(node_addr: address): u64 acquires TowerProofHistory {
   if (exists<TowerProofHistory>(node_addr)) {
     return borrow_global<TowerProofHistory>(node_addr).epochs_validating_and_mining
   };
@@ -1162,7 +1234,39 @@ Public Getters ///
 
 
public fun get_count_in_epoch(miner_addr: address): u64 acquires TowerProofHistory {
   if (exists<TowerProofHistory>(miner_addr)) {
-    return borrow_global<TowerProofHistory>(miner_addr).count_proofs_in_epoch
+    let s = borrow_global<TowerProofHistory>(miner_addr);
+    if (s.latest_epoch_mining == DiemConfig::get_current_epoch()) {
+      return s.count_proofs_in_epoch
+    };
+  };
+  0
+}
+
+ + + + + + + +## Function `get_count_above_thresh_in_epoch` + + + +
public fun get_count_above_thresh_in_epoch(miner_addr: address): u64
+
+ + + +
+Implementation + + +
public fun get_count_above_thresh_in_epoch(miner_addr: address): u64 acquires TowerProofHistory {
+  if (exists<TowerProofHistory>(miner_addr)) {
+    if (borrow_global<TowerProofHistory>(miner_addr).count_proofs_in_epoch > Globals::get_epoch_mining_thres_lower()) {
+      return borrow_global<TowerProofHistory>(miner_addr).count_proofs_in_epoch - Globals::get_epoch_mining_thres_lower()
+    }
   };
   0
 }
@@ -1170,6 +1274,33 @@ Public Getters ///
 
 
 
+
+ + + +## Function `lazy_reset_count_in_epoch` + + + +
fun lazy_reset_count_in_epoch(miner_addr: address)
+
+ + + +
+Implementation + + +
fun lazy_reset_count_in_epoch(miner_addr: address) acquires TowerProofHistory {
+  let s = borrow_global_mut<TowerProofHistory>(miner_addr);
+  if (s.latest_epoch_mining < DiemConfig::get_current_epoch()) {
+    s.count_proofs_in_epoch = 0;
+  };
+}
+
+ + +
@@ -1203,13 +1334,38 @@ Public Getters /// - + + +## Function `get_validator_proofs_in_epoch` + + + +
public fun get_validator_proofs_in_epoch(): u64
+
+ + + +
+Implementation + + +
public fun get_validator_proofs_in_epoch(): u64 acquires TowerCounter{
+  let state = borrow_global<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS());
+  state.validator_proofs_in_epoch
+}
+
+ + + +
+ + -## Function `test_helper_init_miner` +## Function `get_fullnode_proofs_in_epoch` -
public fun test_helper_init_miner(miner_sig: &signer, challenge: vector<u8>, solution: vector<u8>, difficulty: u64, security: u64)
+
public fun get_fullnode_proofs_in_epoch(): u64
 
@@ -1218,13 +1374,116 @@ Public Getters /// Implementation -
public fun test_helper_init_miner(
+
public fun get_fullnode_proofs_in_epoch(): u64 acquires TowerCounter{
+  let state = borrow_global<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS());
+  state.fullnode_proofs_in_epoch
+}
+
+ + + + + + + +## Function `get_fullnode_proofs_in_epoch_above_thresh` + + + +
public fun get_fullnode_proofs_in_epoch_above_thresh(): u64
+
+ + + +
+Implementation + + +
public fun get_fullnode_proofs_in_epoch_above_thresh(): u64 acquires TowerCounter{
+  let state = borrow_global<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS());
+  state.fullnode_proofs_in_epoch_above_thresh
+}
+
+ + + +
+ + + +## Function `get_lifetime_proof_count` + + + +
public fun get_lifetime_proof_count(): (u64, u64, u64)
+
+ + + +
+Implementation + + +
public fun get_lifetime_proof_count(): (u64, u64, u64) acquires TowerCounter{
+  let s = borrow_global<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS());
+  (s.lifetime_proofs, s.lifetime_validator_proofs, s.lifetime_fullnode_proofs)
+}
+
+ + + +
+ + + +## Function `danger_migrate_get_lifetime_proof_count` + + + +
public fun danger_migrate_get_lifetime_proof_count(): (u64, u64, u64)
+
+ + + +
+Implementation + + +
public fun danger_migrate_get_lifetime_proof_count(): (u64, u64, u64) acquires TowerStats{
+  if (exists<TowerStats>(CoreAddresses::VM_RESERVED_ADDRESS())) {
+    let s = borrow_global<TowerStats>(CoreAddresses::VM_RESERVED_ADDRESS());
+    return (s.proofs_in_epoch, s.validator_proofs, s.fullnode_proofs)
+  };
+  (0,0,0)
+}
+
+ + + +
+ + + +## Function `test_helper_init_val` + + + +
public fun test_helper_init_val(miner_sig: &signer, challenge: vector<u8>, solution: vector<u8>, difficulty: u64, security: u64)
+
+ + + +
+Implementation + + +
public fun test_helper_init_val(
     miner_sig: &signer,
     challenge: vector<u8>,
     solution: vector<u8>,
     difficulty: u64,
     security: u64,
-  ) acquires TowerProofHistory, TowerList, TowerStats {
+  ) acquires TowerProofHistory, TowerList, TowerCounter {
     assert(Testnet::is_testnet(), 130102014010);
 
     move_to<TowerProofHistory>(miner_sig, TowerProofHistory {
@@ -1252,6 +1511,40 @@ Public Getters ///
 
 
 
+
+ + + +## Function `test_epoch_reset_counter` + + + +
public fun test_epoch_reset_counter(vm: &signer)
+
+ + + +
+Implementation + + +
public fun test_epoch_reset_counter(vm: &signer) acquires TowerCounter {
+  assert(Testnet::is_testnet(), Errors::invalid_state(130118));
+  CoreAddresses::assert_vm(vm);
+  let state = borrow_global_mut<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS());
+  state.lifetime_proofs = 0;
+  state.lifetime_validator_proofs = 0;
+  state.lifetime_fullnode_proofs = 0;
+  state.proofs_in_epoch = 0;
+  state.validator_proofs_in_epoch = 0;
+  state.fullnode_proofs_in_epoch = 0;
+  state.validator_proofs_in_epoch_above_thresh = 0;
+  state.fullnode_proofs_in_epoch_above_thresh = 0;
+}
+
+ + +
@@ -1275,7 +1568,7 @@ Public Getters /// // differ slightly from api miner_addr: address, proof: Proof -) acquires TowerProofHistory, TowerList, TowerStats { +) acquires TowerProofHistory, TowerList, TowerCounter { assert(Testnet::is_testnet(), 130102014010); // Get address, assumes the sender is the signer. @@ -1321,18 +1614,10 @@ Public Getters /// Implementation -
public fun test_helper_mock_mining(sender: &signer,  count: u64) acquires TowerProofHistory, TowerStats {
+
public fun test_helper_mock_mining(sender: &signer,  count: u64) acquires TowerProofHistory, TowerCounter {
   assert(Testnet::is_testnet(), Errors::invalid_state(130118));
   let addr = Signer::address_of(sender);
-  let state = borrow_global_mut<TowerProofHistory>(addr);
-  state.count_proofs_in_epoch = count;
-  let i = 0;
-  while (i < count) {
-    increment_stats(addr);
-    i = i + 1;
-  }
-
-  // FullnodeState::mock_proof(sender, count);
+  danger_mock_mining(addr, count)
 }
 
@@ -1355,17 +1640,50 @@ Public Getters /// Implementation -
public fun test_helper_mock_mining_vm(vm: &signer, addr: address, count: u64) acquires TowerProofHistory, TowerStats {
+
public fun test_helper_mock_mining_vm(vm: &signer, addr: address, count: u64) acquires TowerProofHistory, TowerCounter {
   assert(Testnet::is_testnet(), Errors::invalid_state(130120));
   CoreAddresses::assert_diem_root(vm);
-  let state = borrow_global_mut<TowerProofHistory>(addr);
-  state.count_proofs_in_epoch = count;
+  danger_mock_mining(addr, count)
+}
+
+ + + + + + + +## Function `danger_mock_mining` + + + +
fun danger_mock_mining(addr: address, count: u64)
+
+ + + +
+Implementation + + +
fun danger_mock_mining(addr: address, count: u64) acquires TowerProofHistory, TowerCounter {
+  // again for safety
+  assert(Testnet::is_testnet(), Errors::invalid_state(130118));
+
 
   let i = 0;
   while (i < count) {
     increment_stats(addr);
+    let state = borrow_global_mut<TowerProofHistory>(addr);
+    // mock verify_and_update
+    state.verified_tower_height = state.verified_tower_height + 1;
+    state.count_proofs_in_epoch = state.count_proofs_in_epoch + 1;
     i = i + 1;
-  }
+  };
+
+  let state = borrow_global_mut<TowerProofHistory>(addr);
+  state.count_proofs_in_epoch = count;
+  state.latest_epoch_mining = DiemConfig::get_current_epoch();
 }
 
@@ -1388,10 +1706,12 @@ Public Getters /// Implementation -
public fun test_helper_mock_reconfig(account: &signer, miner_addr: address) acquires TowerProofHistory{
+
public fun test_helper_mock_reconfig(account: &signer, miner_addr: address) acquires TowerProofHistory, TowerCounter {
   CoreAddresses::assert_diem_root(account);
   assert(Testnet::is_testnet(), Errors::invalid_state(130122));
-  update_metrics(account, miner_addr);
+  // update_metrics(account, miner_addr);
+  epoch_reset(account);
+  update_epoch_metrics_vals(account, miner_addr);
 }
 
@@ -1445,7 +1765,35 @@ Public Getters ///
public fun test_helper_get_count(account: &signer): u64 acquires TowerProofHistory {
     assert(Testnet::is_testnet(), 130115014011);
     let addr = Signer::address_of(account);
-    borrow_global<TowerProofHistory>(addr).count_proofs_in_epoch
+    get_count_in_epoch(addr)
+}
+
+ + + +
+ + + +## Function `test_helper_get_nominal_count` + + + +
public fun test_helper_get_nominal_count(miner_addr: address): u64
+
+ + + +
+Implementation + + +
public fun test_helper_get_nominal_count(miner_addr: address): u64 acquires TowerProofHistory {
+  assert(Testnet::is_testnet(), Errors::invalid_state(130123));
+  assert(exists<TowerProofHistory>(miner_addr), Errors::not_published(130124));
+
+  let state = borrow_global<TowerProofHistory>(miner_addr);
+  *&state.count_proofs_in_epoch
 }
 
@@ -1640,6 +1988,103 @@ Public Getters /// +
+ + + +## Function `test_mock_depr_tower_stats` + + + +
public fun test_mock_depr_tower_stats(vm: &signer)
+
+ + + +
+Implementation + + +
public fun test_mock_depr_tower_stats(vm: &signer) {
+  assert(Testnet::is_testnet(), Errors::invalid_state(130113));
+  CoreAddresses::assert_vm(vm);
+  move_to<TowerStats>(vm, TowerStats{
+    proofs_in_epoch: 111,
+    validator_proofs: 222,
+    fullnode_proofs: 333,
+  });
+}
+
+ + + +
+ + + +## Function `test_get_liftime_proofs` + + + +
public fun test_get_liftime_proofs(): u64
+
+ + + +
+Implementation + + +
public fun test_get_liftime_proofs(): u64 acquires TowerCounter {
+  assert(Testnet::is_testnet(), Errors::invalid_state(130113));
+
+  let s = borrow_global<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS());
+  s.lifetime_proofs
+}
+
+ + + +
+ + + +## Function `test_danger_destroy_tower_counter` + + + +
public fun test_danger_destroy_tower_counter(vm: &signer)
+
+ + + +
+Implementation + + +
public fun test_danger_destroy_tower_counter(vm: &signer) acquires TowerCounter {
+  assert(Testnet::is_testnet(), Errors::invalid_state(130113));
+  CoreAddresses::assert_vm(vm);
+  assert(exists<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS()), Errors::invalid_state(130115));
+
+    // We destroy the data resource for sender
+    // move_from and then destructure
+
+    let TowerCounter {
+      lifetime_proofs: _,
+      lifetime_validator_proofs: _,
+      lifetime_fullnode_proofs: _,
+      proofs_in_epoch: _,
+      validator_proofs_in_epoch: _,
+      fullnode_proofs_in_epoch: _,
+      validator_proofs_in_epoch_above_thresh: _,
+      fullnode_proofs_in_epoch_above_thresh: _,
+   } = move_from<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS());
+}
+
+ + +
diff --git a/language/diem-framework/modules/doc/ol_miner_state.md b/language/diem-framework/modules/doc/ol_miner_state.md index f72f8a942d..f371c40e08 100644 --- a/language/diem-framework/modules/doc/ol_miner_state.md +++ b/language/diem-framework/modules/doc/ol_miner_state.md @@ -111,7 +111,7 @@
public(script) fun minerstate_helper(sender: signer) {
     assert(Testnet::is_testnet(), 01);
 
-    TowerState::test_helper_init_miner(
+    TowerState::test_helper_init_val(
         &sender,
         TestFixtures::alice_0_easy_chal(),
         TestFixtures::alice_0_easy_sol(),
diff --git a/language/diem-framework/modules/doc/overview.md b/language/diem-framework/modules/doc/overview.md
index dc30e0f1f3..2c6d1b6d7b 100644
--- a/language/diem-framework/modules/doc/overview.md
+++ b/language/diem-framework/modules/doc/overview.md
@@ -121,7 +121,7 @@ The Move modules in the Diem Framework can be bucketed in to a couple categories
 -  [`0x1::DiemVersion`](DiemVersion.md#0x1_DiemVersion)
 -  [`0x1::DualAttestation`](DualAttestation.md#0x1_DualAttestation)
 -  [`0x1::Epoch`](Epoch.md#0x1_Epoch)
--  [`0x1::EpochBoundary`](Reconfigure.md#0x1_EpochBoundary)
+-  [`0x1::EpochBoundary`](EpochBoundary.md#0x1_EpochBoundary)
 -  [`0x1::Errors`](../../../../../../move-stdlib/docs/Errors.md#0x1_Errors)
 -  [`0x1::Event`](../../../../../../move-stdlib/docs/Event.md#0x1_Event)
 -  [`0x1::FIFO`](FIFO.md#0x1_FIFO)
@@ -131,8 +131,9 @@ The Move modules in the Diem Framework can be bucketed in to a couple categories
 -  [`0x1::Genesis`](Genesis.md#0x1_Genesis)
 -  [`0x1::Globals`](Globals.md#0x1_Globals)
 -  [`0x1::Hash`](../../../../../../move-stdlib/docs/Hash.md#0x1_Hash)
--  [`0x1::MigrateWallets`](Migrations.md#0x1_MigrateWallets)
+-  [`0x1::MigrateTowerCounter`](Migrations.md#0x1_MigrateTowerCounter)
 -  [`0x1::Migrations`](Migrations.md#0x1_Migrations)
+-  [`0x1::Mock`](Mock.md#0x1_Mock)
 -  [`0x1::NodeWeight`](NodeWeight.md#0x1_NodeWeight)
 -  [`0x1::Option`](../../../../../../move-stdlib/docs/Option.md#0x1_Option)
 -  [`0x1::Oracle`](Oracle.md#0x1_Oracle)
diff --git a/language/diem-framework/releases/artifacts/current/docs/modules/Audit.md b/language/diem-framework/releases/artifacts/current/docs/modules/Audit.md
index 4b72839bf2..93042403ba 100644
--- a/language/diem-framework/releases/artifacts/current/docs/modules/Audit.md
+++ b/language/diem-framework/releases/artifacts/current/docs/modules/Audit.md
@@ -11,7 +11,6 @@
 
 
use 0x1::AutoPay;
 use 0x1::DiemAccount;
-use 0x1::GAS;
 use 0x1::Testnet;
 use 0x1::TowerState;
 use 0x1::ValidatorConfig;
@@ -41,7 +40,7 @@
   let oper = ValidatorConfig::get_operator(val);
   if (oper == val) return false;
   // operator account has balance
-  if (DiemAccount::balance<GAS>(oper) < 50000 && !Testnet::is_testnet()) return false;
+  // if (DiemAccount::balance<GAS>(oper) < 50000 && !Testnet::is_testnet()) return false;
   // has autopay enabled
   if (!AutoPay::is_enabled(val)) return false;
   // has mining state
diff --git a/language/diem-framework/releases/artifacts/current/docs/modules/DiemAccount.md b/language/diem-framework/releases/artifacts/current/docs/modules/DiemAccount.md
index 1c1aa210af..2d51f9ce2f 100644
--- a/language/diem-framework/releases/artifacts/current/docs/modules/DiemAccount.md
+++ b/language/diem-framework/releases/artifacts/current/docs/modules/DiemAccount.md
@@ -935,39 +935,39 @@ Tried to create a balance for an account whose role does not allow holding balan
 
 
 
-
+
 
-The withdrawal of funds would have exceeded the the account's limits
 
 
-
const EWITHDRAWAL_EXCEEDS_LIMITS: u64 = 12016;
+
const ESLOW_WALLET_TRANSFERS_DISABLED_SYSTEMWIDE: u64 = 120127;
 
- + +The withdrawal of funds would have exceeded the the account's limits -
const EWITHDRAWAL_NOT_FOR_COMMUNITY_WALLET: u64 = 120126;
+
const EWITHDRAWAL_EXCEEDS_LIMITS: u64 = 12016;
 
- + -
const EWITHDRAWAL_SLOW_WAL_EXCEEDS_UNLOCKED_LIMIT: u64 = 120128;
+
const EWITHDRAWAL_NOT_FOR_COMMUNITY_WALLET: u64 = 120126;
 
- + -
const EWITHDRAWAL_TRANSFERS_DISABLED_SYSTEMWIDE: u64 = 120127;
+
const EWITHDRAWAL_SLOW_WAL_EXCEEDS_UNLOCKED_LIMIT: u64 = 120128;
 
@@ -2657,9 +2657,7 @@ the sender's account balance.
public fun extract_withdraw_capability(
     sender: &signer
 ): WithdrawCapability acquires DiemAccount {
-    //////// 0L //////// Transfers disabled by default
-    //////// 0L //////// Transfers of 10 GAS
-    //////// 0L //////// enabled when epoch is 1000
+
     let sender_addr = Signer::address_of(sender);
 
     /////// 0L /////////
@@ -2670,11 +2668,14 @@ the sender's account balance.
         Errors::limit_exceeded(EWITHDRAWAL_NOT_FOR_COMMUNITY_WALLET)
     );
     /////// 0L /////////
-    if (!DiemConfig::check_transfer_enabled()) {
-        // only VM can make TXs if transfers are not enabled.
+    // Slow wallet transfers disabled by default, enabled when epoch is 1000
+    // At that point slow wallets receive 1,000 coins unlocked per day.
+    if (is_slow(sender_addr) && !DiemConfig::check_transfer_enabled() ) {
+      // if transfers are not enabled for slow wallets
+      // then the tx should fail
         assert(
-            sender_addr == CoreAddresses::DIEM_ROOT_ADDRESS(),
-            Errors::limit_exceeded(EWITHDRAWAL_TRANSFERS_DISABLED_SYSTEMWIDE)
+            false,
+            Errors::limit_exceeded(ESLOW_WALLET_TRANSFERS_DISABLED_SYSTEMWIDE)
         );
     };
     // Abort if we already extracted the unique withdraw capability for this account.
diff --git a/language/diem-framework/releases/artifacts/current/docs/modules/DiemBlock.md b/language/diem-framework/releases/artifacts/current/docs/modules/DiemBlock.md
index 4391882432..62d03c6d53 100644
--- a/language/diem-framework/releases/artifacts/current/docs/modules/DiemBlock.md
+++ b/language/diem-framework/releases/artifacts/current/docs/modules/DiemBlock.md
@@ -4,6 +4,8 @@
 # Module `0x1::DiemBlock`
 
 This module defines a struct storing the metadata of the block and new block events.
+it also contains all of the block prologue logic which is called from the Rust executor.
+For 0L the following changes are applied to the block prologue
 
 
 -  [Resource `BlockMetadata`](#0x1_DiemBlock_BlockMetadata)
@@ -23,10 +25,11 @@ This module defines a struct storing the metadata of the block and new block eve
 use 0x1::DiemSystem;
 use 0x1::DiemTimestamp;
 use 0x1::Epoch;
-use 0x1::EpochBoundary;
+use 0x1::EpochBoundary;
 use 0x1::Errors;
 use 0x1::Event;
 use 0x1::GAS;
+use 0x1::MigrateTowerCounter;
 use 0x1::Migrations;
 use 0x1::Stats;
 
@@ -241,12 +244,12 @@ The runtime always runs this before executing the transactions in a block. DiemTimestamp::assert_operating(); // Operational constraint: can only be invoked by the VM. CoreAddresses::assert_vm(&vm); - // Authorization assert( proposer == CoreAddresses::VM_RESERVED_ADDRESS() || DiemSystem::is_validator(proposer), Errors::requires_address(EVM_OR_VALIDATOR) ); + //////// 0L //////// // increment stats Stats::process_set_votes(&vm, &previous_block_votes); @@ -259,6 +262,15 @@ The runtime always runs this before executing the transactions in a block. AutoPay::process_autopay(&vm); }; + // Do any pending migrations + // TODO: should this be round 2 (when upgrade writeset happens). May be a on off-by-one. + if (round == 3){ + // safety. Maybe init Migration struct + Migrations::init(&vm); + // Migration UID 1 + MigrateTowerCounter::migrate_tower_counter(&vm); + }; + let block_metadata_ref = borrow_global_mut<BlockMetadata>(CoreAddresses::DIEM_ROOT_ADDRESS()); DiemTimestamp::update_global_time(&vm, proposer, timestamp); block_metadata_ref.height = block_metadata_ref.height + 1; @@ -275,12 +287,11 @@ The runtime always runs this before executing the transactions in a block. //////// 0L //////// // EPOCH BOUNDARY if (Epoch::epoch_finished()) { - // Run migrations - Migrations::init(&vm); + // TODO: We don't need to pass block height to EpochBoundaryOL. // It should use the BlockMetadata. But there's a circular reference // there when we try. - EpochBoundary::reconfigure(&vm, get_current_block_height()); + EpochBoundary::reconfigure(&vm, get_current_block_height()); }; }
diff --git a/language/diem-framework/releases/artifacts/current/docs/modules/Reconfigure.md b/language/diem-framework/releases/artifacts/current/docs/modules/EpochBoundary.md similarity index 80% rename from language/diem-framework/releases/artifacts/current/docs/modules/Reconfigure.md rename to language/diem-framework/releases/artifacts/current/docs/modules/EpochBoundary.md index a78cdaca73..aa04165556 100644 --- a/language/diem-framework/releases/artifacts/current/docs/modules/Reconfigure.md +++ b/language/diem-framework/releases/artifacts/current/docs/modules/EpochBoundary.md @@ -27,7 +27,6 @@ use 0x1::Stats; use 0x1::Subsidy; use 0x1::TowerState; -use 0x1::ValidatorUniverse; use 0x1::Vector;
@@ -39,7 +38,7 @@ -
public fun reconfigure(vm: &signer, height_now: u64)
+
public fun reconfigure(vm: &signer, height_now: u64)
 
@@ -48,7 +47,7 @@ Implementation -
public fun reconfigure(vm: &signer, height_now: u64) {
+
public fun reconfigure(vm: &signer, height_now: u64) {
     CoreAddresses::assert_vm(vm);
 
     let height_start = Epoch::get_timer_height_start(vm);
@@ -61,18 +60,18 @@
     let (subsidy_units, nominal_subsidy_per) =
         Subsidy::calculate_subsidy(vm, compliant_nodes_count);
 
-    process_fullnodes(vm, nominal_subsidy_per);
+    process_fullnodes(vm, nominal_subsidy_per);
 
-    process_validators(vm, subsidy_units, outgoing_compliant_set);
+    process_validators(vm, subsidy_units, *&outgoing_compliant_set);
 
-    let proposed_set = propose_new_set(vm, height_start, height_now);
+    let proposed_set = propose_new_set(vm, height_start, height_now);
 
     // Update all slow wallet limits
     if (DiemConfig::check_transfer_enabled()) {
         DiemAccount::slow_wallet_epoch_drip(vm, Globals::get_unlock());
         // update_validator_withdrawal_limit(vm);
     };
-    reset_counters(vm, proposed_set, height_now)
+    reset_counters(vm, proposed_set, outgoing_compliant_set, height_now)
 }
 
@@ -86,7 +85,7 @@ -
fun process_fullnodes(vm: &signer, nominal_subsidy_per_node: u64)
+
fun process_fullnodes(vm: &signer, nominal_subsidy_per_node: u64)
 
@@ -95,7 +94,7 @@ Implementation -
fun process_fullnodes(vm: &signer, nominal_subsidy_per_node: u64) {
+
fun process_fullnodes(vm: &signer, nominal_subsidy_per_node: u64) {
     // Fullnode subsidy
     // loop through validators and pay full node subsidies.
     // Should happen before transactionfees get distributed.
@@ -116,7 +115,7 @@
         // 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);
@@ -137,7 +136,7 @@
 
 
 
-
fun process_validators(vm: &signer, subsidy_units: u64, outgoing_compliant_set: vector<address>)
+
fun process_validators(vm: &signer, subsidy_units: u64, outgoing_compliant_set: vector<address>)
 
@@ -146,7 +145,7 @@ Implementation -
fun process_validators(
+
fun process_validators(
     vm: &signer, subsidy_units: u64, outgoing_compliant_set: vector<address>
 ) {
     // Process outgoing validators:
@@ -172,7 +171,7 @@
 
 
 
-
fun propose_new_set(vm: &signer, height_start: u64, height_now: u64): vector<address>
+
fun propose_new_set(vm: &signer, height_start: u64, height_now: u64): vector<address>
 
@@ -181,7 +180,7 @@ Implementation -
fun propose_new_set(vm: &signer, height_start: u64, height_now: u64): vector<address> {
+
fun propose_new_set(vm: &signer, height_start: u64, height_now: u64): vector<address> {
     // Propose upcoming validator set:
     // Step 1: Sort Top N eligible validators
     // Step 2: Jail non-performing validators
@@ -247,7 +246,7 @@
 
 
 
-
fun reset_counters(vm: &signer, proposed_set: vector<address>, height_now: u64)
+
fun reset_counters(vm: &signer, proposed_set: vector<address>, outgoing_compliant: vector<address>, height_now: u64)
 
@@ -256,15 +255,13 @@ Implementation -
fun reset_counters(vm: &signer, proposed_set: vector<address>, height_now: u64) {
+
fun reset_counters(vm: &signer, proposed_set: vector<address>, outgoing_compliant: vector<address>, height_now: u64) {
 
     // Reset Stats
     Stats::reconfig(vm, &proposed_set);
 
-    // Migrate TowerState list from elegible: in case there is no minerlist
-    // struct, use eligible for migrate_eligible_validators
-    let eligible = ValidatorUniverse::get_eligible_validators(vm);
-    TowerState::reconfig(vm, &eligible);
+    // Migrate TowerState list from elegible.
+    TowerState::reconfig(vm, &outgoing_compliant);
 
     // Reconfigure the network
     DiemSystem::bulk_update_validators(vm, proposed_set);
diff --git a/language/diem-framework/releases/artifacts/current/docs/modules/FullnodeSubsidy.md b/language/diem-framework/releases/artifacts/current/docs/modules/FullnodeSubsidy.md
index 5d3a798197..e3cb78c46a 100644
--- a/language/diem-framework/releases/artifacts/current/docs/modules/FullnodeSubsidy.md
+++ b/language/diem-framework/releases/artifacts/current/docs/modules/FullnodeSubsidy.md
@@ -35,7 +35,8 @@
 
 
 
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.
@@ -44,8 +45,11 @@
   // 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
 }
 
diff --git a/language/diem-framework/releases/artifacts/current/docs/modules/Globals.md b/language/diem-framework/releases/artifacts/current/docs/modules/Globals.md index 7e7deb41ea..c5a1b62871 100644 --- a/language/diem-framework/releases/artifacts/current/docs/modules/Globals.md +++ b/language/diem-framework/releases/artifacts/current/docs/modules/Globals.md @@ -371,7 +371,7 @@ Get the constants for the current network max_validators_per_set: 100, subsidy_ceiling_gas: 296 * COIN_SCALING_FACTOR, vdf_difficulty: 100, - epoch_mining_thres_lower: 1, + 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, } @@ -383,7 +383,7 @@ Get the constants for the current network max_validators_per_set: 100, subsidy_ceiling_gas: 8640000 * COIN_SCALING_FACTOR, vdf_difficulty: 120000000, - epoch_mining_thres_lower: 1, + epoch_mining_thres_lower: 1, // in testnet, staging, we don't want to wait too long between proofs. epoch_mining_thres_upper: 72, // upper bound enforced at 20 mins per proof. epoch_slow_wallet_unlock: 10000000, } diff --git a/language/diem-framework/releases/artifacts/current/docs/modules/Migrations.md b/language/diem-framework/releases/artifacts/current/docs/modules/Migrations.md index e6e2544075..f532918a1e 100644 --- a/language/diem-framework/releases/artifacts/current/docs/modules/Migrations.md +++ b/language/diem-framework/releases/artifacts/current/docs/modules/Migrations.md @@ -1,27 +1,24 @@ - + -# Module `0x1::MigrateWallets` +# Module `0x1::MigrateTowerCounter` ## Summary -Module providing method to convert all wallets to "slow wallets" -migrations should have own module, since imports can cause dependency cycling. +Module to migrate the tower statistics from TowerState to TowerCounter - [Summary](#@Summary_0) - [Constants](#@Constants_1) -- [Function `migrate_slow_wallets`](#0x1_MigrateWallets_migrate_slow_wallets) +- [Function `migrate_tower_counter`](#0x1_MigrateTowerCounter_migrate_tower_counter)
use 0x1::CoreAddresses;
-use 0x1::DiemAccount;
 use 0x1::Migrations;
-use 0x1::ValidatorUniverse;
-use 0x1::Vector;
+use 0x1::TowerState;
 
@@ -31,22 +28,22 @@ migrations should have own module, since imports can cause dependency cycling. ## Constants - + -
const UID: u64 = 10;
+
const UID: u64 = 1;
 
- + -## Function `migrate_slow_wallets` +## Function `migrate_tower_counter` -
public fun migrate_slow_wallets(vm: &signer)
+
public fun migrate_tower_counter(vm: &signer)
 
@@ -55,21 +52,12 @@ migrations should have own module, since imports can cause dependency cycling. Implementation -
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");
+  if (!Migrations::has_run(UID)) {
+    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");
   };
 }
 
diff --git a/language/diem-framework/releases/artifacts/current/docs/modules/Mock.md b/language/diem-framework/releases/artifacts/current/docs/modules/Mock.md new file mode 100644 index 0000000000..a7af455ce3 --- /dev/null +++ b/language/diem-framework/releases/artifacts/current/docs/modules/Mock.md @@ -0,0 +1,114 @@ + + + +# Module `0x1::Mock` + + + +- [Function `mock_case_1`](#0x1_Mock_mock_case_1) +- [Function `mock_case_2`](#0x1_Mock_mock_case_2) + + +
use 0x1::Cases;
+use 0x1::DiemSystem;
+use 0x1::Stats;
+use 0x1::TowerState;
+use 0x1::Vector;
+
+ + + + + +## Function `mock_case_1` + + + +
public fun mock_case_1(vm: &signer, addr: address)
+
+ + + +
+Implementation + + +
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);
+
+  }
+
+ + + +
+ + + +## Function `mock_case_2` + + + +
public fun mock_case_2(vm: &signer, addr: address)
+
+ + + +
+Implementation + + +
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);
+
+}
+
+ + + +
+ + +[//]: # ("File containing references which can be used from documentation") +[ACCESS_CONTROL]: https://github.com/diem/dip/blob/main/dips/dip-2.md +[ROLE]: https://github.com/diem/dip/blob/main/dips/dip-2.md#roles +[PERMISSION]: https://github.com/diem/dip/blob/main/dips/dip-2.md#permissions diff --git a/language/diem-framework/releases/artifacts/current/docs/modules/TowerState.md b/language/diem-framework/releases/artifacts/current/docs/modules/TowerState.md index 256f2d3d45..272d50de7f 100644 --- a/language/diem-framework/releases/artifacts/current/docs/modules/TowerState.md +++ b/language/diem-framework/releases/artifacts/current/docs/modules/TowerState.md @@ -4,24 +4,15 @@ # Module `0x1::TowerState` - -## Summary - -TODO - - -- [Summary](#@Summary_0) - [Resource `TowerList`](#0x1_TowerState_TowerList) - [Resource `TowerStats`](#0x1_TowerState_TowerStats) +- [Resource `TowerCounter`](#0x1_TowerState_TowerCounter) - [Struct `Proof`](#0x1_TowerState_Proof) - [Resource `TowerProofHistory`](#0x1_TowerState_TowerProofHistory) -- [Constants](#@Constants_1) -- [Function `increment_stats`](#0x1_TowerState_increment_stats) -- [Function `epoch_reset`](#0x1_TowerState_epoch_reset) -- [Function `get_fullnode_proofs`](#0x1_TowerState_get_fullnode_proofs) +- [Constants](#@Constants_0) - [Function `init_miner_list`](#0x1_TowerState_init_miner_list) -- [Function `init_miner_stats`](#0x1_TowerState_init_miner_stats) +- [Function `init_tower_counter`](#0x1_TowerState_init_tower_counter) - [Function `init_miner_list_and_stats`](#0x1_TowerState_init_miner_list_and_stats) - [Function `is_init`](#0x1_TowerState_is_init) - [Function `is_onboarding`](#0x1_TowerState_is_onboarding) @@ -31,25 +22,37 @@ TODO - [Function `commit_state`](#0x1_TowerState_commit_state) - [Function `commit_state_by_operator`](#0x1_TowerState_commit_state_by_operator) - [Function `verify_and_update_state`](#0x1_TowerState_verify_and_update_state) -- [Function `update_metrics`](#0x1_TowerState_update_metrics) +- [Function `update_epoch_metrics_vals`](#0x1_TowerState_update_epoch_metrics_vals) - [Function `node_above_thresh`](#0x1_TowerState_node_above_thresh) - [Function `reconfig`](#0x1_TowerState_reconfig) - [Function `init_miner_state`](#0x1_TowerState_init_miner_state) - [Function `first_challenge_includes_address`](#0x1_TowerState_first_challenge_includes_address) - [Function `get_miner_latest_epoch`](#0x1_TowerState_get_miner_latest_epoch) - [Function `reset_rate_limit`](#0x1_TowerState_reset_rate_limit) +- [Function `increment_stats`](#0x1_TowerState_increment_stats) +- [Function `epoch_reset`](#0x1_TowerState_epoch_reset) - [Function `get_miner_list`](#0x1_TowerState_get_miner_list) - [Function `get_tower_height`](#0x1_TowerState_get_tower_height) -- [Function `get_epochs_mining`](#0x1_TowerState_get_epochs_mining) +- [Function `get_epochs_compliant`](#0x1_TowerState_get_epochs_compliant) - [Function `get_count_in_epoch`](#0x1_TowerState_get_count_in_epoch) +- [Function `get_count_above_thresh_in_epoch`](#0x1_TowerState_get_count_above_thresh_in_epoch) +- [Function `lazy_reset_count_in_epoch`](#0x1_TowerState_lazy_reset_count_in_epoch) - [Function `can_create_val_account`](#0x1_TowerState_can_create_val_account) -- [Function `test_helper_init_miner`](#0x1_TowerState_test_helper_init_miner) +- [Function `get_validator_proofs_in_epoch`](#0x1_TowerState_get_validator_proofs_in_epoch) +- [Function `get_fullnode_proofs_in_epoch`](#0x1_TowerState_get_fullnode_proofs_in_epoch) +- [Function `get_fullnode_proofs_in_epoch_above_thresh`](#0x1_TowerState_get_fullnode_proofs_in_epoch_above_thresh) +- [Function `get_lifetime_proof_count`](#0x1_TowerState_get_lifetime_proof_count) +- [Function `danger_migrate_get_lifetime_proof_count`](#0x1_TowerState_danger_migrate_get_lifetime_proof_count) +- [Function `test_helper_init_val`](#0x1_TowerState_test_helper_init_val) +- [Function `test_epoch_reset_counter`](#0x1_TowerState_test_epoch_reset_counter) - [Function `test_helper_operator_submits`](#0x1_TowerState_test_helper_operator_submits) - [Function `test_helper_mock_mining`](#0x1_TowerState_test_helper_mock_mining) - [Function `test_helper_mock_mining_vm`](#0x1_TowerState_test_helper_mock_mining_vm) +- [Function `danger_mock_mining`](#0x1_TowerState_danger_mock_mining) - [Function `test_helper_mock_reconfig`](#0x1_TowerState_test_helper_mock_reconfig) - [Function `test_helper_get_height`](#0x1_TowerState_test_helper_get_height) - [Function `test_helper_get_count`](#0x1_TowerState_test_helper_get_count) +- [Function `test_helper_get_nominal_count`](#0x1_TowerState_test_helper_get_nominal_count) - [Function `test_helper_get_contiguous_vm`](#0x1_TowerState_test_helper_get_contiguous_vm) - [Function `test_helper_set_rate_limit`](#0x1_TowerState_test_helper_set_rate_limit) - [Function `test_helper_set_epochs_mining`](#0x1_TowerState_test_helper_set_epochs_mining) @@ -57,6 +60,9 @@ TODO - [Function `test_helper_previous_proof_hash`](#0x1_TowerState_test_helper_previous_proof_hash) - [Function `test_helper_set_weight_vm`](#0x1_TowerState_test_helper_set_weight_vm) - [Function `test_helper_set_weight`](#0x1_TowerState_test_helper_set_weight) +- [Function `test_mock_depr_tower_stats`](#0x1_TowerState_test_mock_depr_tower_stats) +- [Function `test_get_liftime_proofs`](#0x1_TowerState_test_get_liftime_proofs) +- [Function `test_danger_destroy_tower_counter`](#0x1_TowerState_test_danger_destroy_tower_counter)
use 0x1::CoreAddresses;
@@ -107,6 +113,7 @@ A list of all miners' addresses
 
 ## Resource `TowerStats`
 
+To use in migration, and in future upgrade to deprecate.
 
 
 
struct TowerStats has key
@@ -140,6 +147,76 @@ A list of all miners' addresses
 
 
 
+
+
+
+
+## Resource `TowerCounter`
+
+The struct to store the global count of proofs in 0x0
+
+
+
struct TowerCounter has key
+
+ + + +
+Fields + + +
+
+lifetime_proofs: u64 +
+
+ +
+
+lifetime_validator_proofs: u64 +
+
+ +
+
+lifetime_fullnode_proofs: u64 +
+
+ +
+
+proofs_in_epoch: u64 +
+
+ +
+
+validator_proofs_in_epoch: u64 +
+
+ +
+
+fullnode_proofs_in_epoch: u64 +
+
+ +
+
+validator_proofs_in_epoch_above_thresh: u64 +
+
+ +
+
+fullnode_proofs_in_epoch_above_thresh: u64 +
+
+ +
+
+ +
@@ -272,7 +349,7 @@ the miner last created a new account - + ## Constants @@ -286,92 +363,6 @@ the miner last created a new account - - -## Function `increment_stats` - - - -
fun increment_stats(miner_addr: address)
-
- - - -
-Implementation - - -
fun increment_stats(miner_addr: address) acquires TowerStats {
-  assert(exists<TowerStats>(CoreAddresses::VM_RESERVED_ADDRESS()), 1301001);
-  let state = borrow_global_mut<TowerStats>(CoreAddresses::VM_RESERVED_ADDRESS());
-
-  if (ValidatorConfig::is_valid(miner_addr)) {
-    state.validator_proofs = state.validator_proofs + 1;
-  } else {
-    state.fullnode_proofs = state.fullnode_proofs + 1;
-  };
-
-  state.proofs_in_epoch = state.proofs_in_epoch + 1;
-}
-
- - - -
- - - -## Function `epoch_reset` - - - -
public fun epoch_reset(vm: &signer)
-
- - - -
-Implementation - - -
public fun epoch_reset(vm: &signer) acquires TowerStats {
-  CoreAddresses::assert_vm(vm);
-  let state = borrow_global_mut<TowerStats>(CoreAddresses::VM_RESERVED_ADDRESS());
-  state.proofs_in_epoch = 0;
-  state.validator_proofs = 0;
-  state.fullnode_proofs = 0;
-}
-
- - - -
- - - -## Function `get_fullnode_proofs` - - - -
public fun get_fullnode_proofs(): u64
-
- - - -
-Implementation - - -
public fun get_fullnode_proofs(): u64 acquires TowerStats{
-  let state = borrow_global<TowerStats>(CoreAddresses::VM_RESERVED_ADDRESS());
-  state.fullnode_proofs
-}
-
- - - -
- ## Function `init_miner_list` @@ -400,14 +391,14 @@ Create an empty list of miners - + -## Function `init_miner_stats` +## Function `init_tower_counter` Create an empty miner stats -
fun init_miner_stats(vm: &signer)
+
public fun init_tower_counter(vm: &signer, lifetime_proofs: u64, lifetime_validator_proofs: u64, lifetime_fullnode_proofs: u64)
 
@@ -416,12 +407,25 @@ Create an empty miner stats Implementation -
fun init_miner_stats(vm: &signer) {
-  move_to<TowerStats>(vm, TowerStats {
-    proofs_in_epoch: 0u64,
-    validator_proofs: 0u64,
-    fullnode_proofs: 0u64,
-  });
+
public fun init_tower_counter(
+  vm: &signer,
+  lifetime_proofs: u64,
+  lifetime_validator_proofs: u64,
+  lifetime_fullnode_proofs: u64,
+) {
+  if (!exists<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS())) {
+    move_to<TowerCounter>(vm, TowerCounter {
+      lifetime_proofs,
+      lifetime_validator_proofs,
+      lifetime_fullnode_proofs,
+      proofs_in_epoch: 0,
+      validator_proofs_in_epoch: 0,
+      fullnode_proofs_in_epoch: 0,
+      validator_proofs_in_epoch_above_thresh: 0,
+      fullnode_proofs_in_epoch_above_thresh: 0,
+    });
+  }
+
 }
 
@@ -447,7 +451,9 @@ Create empty miners list and stats
public fun init_miner_list_and_stats(vm: &signer) {
   init_miner_list(vm);
-  init_miner_stats(vm);
+
+  // Note: for testing migration we need to destroy this struct, see test_danger_destroy_tower_counter
+  init_tower_counter(vm, 0, 0, 0);
 }
 
@@ -497,9 +503,10 @@ is onboarding
public fun is_onboarding(addr: address): bool acquires TowerProofHistory {
+  let count = get_count_in_epoch(addr);
   let state = borrow_global<TowerProofHistory>(addr);
 
-  state.count_proofs_in_epoch < 2 &&
+  count < 2 &&
   state.epochs_since_last_account_creation < 2
 }
 
@@ -595,14 +602,13 @@ adds tower to list of towers solution: vector<u8>, difficulty: u64, security: u64, -) acquires TowerProofHistory, TowerList, TowerStats { +) acquires TowerProofHistory, TowerList, TowerCounter { // TODO: Previously in OLv3 is_genesis() returned true. // How to check that this is part of genesis? is_genesis returns false here. // In rust the vm_genesis creates a Signer for the miner. // So the SENDER is not the same and the Signer. - init_miner_state(miner_sig, &challenge, &solution, difficulty, security); // TODO: Move this elsewhere? // Initialize stats for first validator set from rust genesis. @@ -636,7 +642,7 @@ Permissions: PUBLIC, ANYONE
public fun commit_state(
   miner_sign: &signer,
   proof: Proof
-) acquires TowerProofHistory, TowerList, TowerStats {
+) acquires TowerProofHistory, TowerList, TowerCounter {
   // Get address, assumes the sender is the signer.
   let miner_addr = Signer::address_of(miner_sign);
 
@@ -657,7 +663,6 @@ Permissions: PUBLIC, ANYONE
     return
   };
 
-
   // Process the proof
   verify_and_update_state(miner_addr, proof, true);
 }
@@ -686,17 +691,16 @@ Permissions: PUBLIC, ANYONE
   operator_sig: &signer,
   miner_addr: address,
   proof: Proof
-) acquires TowerProofHistory, TowerList, TowerStats {
+) acquires TowerProofHistory, TowerList, TowerCounter {
 
   // Check the signer is in fact an operator delegated by the owner.
 
   // Get address, assumes the sender is the signer.
   assert(ValidatorConfig::get_operator(miner_addr) == Signer::address_of(operator_sig), Errors::requires_role(130103));
-
   // Abort if not initialized. Assumes the validator Owner account already has submitted the 0th miner proof in onboarding.
   assert(exists<TowerProofHistory>(miner_addr), Errors::not_published(130104));
 
-  // return early if difficulty and security are not correct.
+  // Return early if difficulty and security are not correct.
   // Check vdf difficulty constant. Will be different in tests than in production.
   // Skip this check on local tests, we need tests to send differentdifficulties.
   if (!Testnet::is_testnet()){
@@ -738,14 +742,17 @@ Permissions: PUBLIC, ANYONE
   miner_addr: address,
   proof: Proof,
   steady_state: bool
-) acquires TowerProofHistory, TowerList, TowerStats {
+) acquires TowerProofHistory, TowerList, TowerCounter {
+  // instead of looping through all miners at end of epcoh the stats are only reset when the miner submits a new proof.
+  lazy_reset_count_in_epoch(miner_addr);
 
-  let miner_history = borrow_global<TowerProofHistory>(miner_addr);
   assert(
-    miner_history.count_proofs_in_epoch < Globals::get_epoch_mining_thres_upper(),
+    get_count_in_epoch(miner_addr) < Globals::get_epoch_mining_thres_upper(),
     Errors::invalid_state(130108)
   );
 
+  let miner_history = borrow_global<TowerProofHistory>(miner_addr);
+
   // If not genesis proof, check hash to ensure the proof continues the chain
   if (steady_state) {
     //If not genesis proof, check hash
@@ -784,13 +791,13 @@ Permissions: PUBLIC, ANYONE
 
 
 
-
+
 
-## Function `update_metrics`
+## Function `update_epoch_metrics_vals`
 
 
 
-
fun update_metrics(account: &signer, miner_addr: address)
+
fun update_epoch_metrics_vals(account: &signer, miner_addr: address)
 
@@ -799,7 +806,7 @@ Permissions: PUBLIC, ANYONE Implementation -
fun update_metrics(account: &signer, miner_addr: address) acquires TowerProofHistory {
+
fun update_epoch_metrics_vals(account: &signer, miner_addr: address) acquires TowerProofHistory {
   // The goal of update_metrics is to confirm that a miner participated in consensus during
   // an epoch, but also that there were mining proofs submitted in that epoch.
   CoreAddresses::assert_diem_root(account);
@@ -813,11 +820,10 @@ Permissions: PUBLIC, ANYONE
   // the resource was last emptied.
   let passed = node_above_thresh(miner_addr);
   let miner_history = borrow_global_mut<TowerProofHistory>(miner_addr);
-
   // Update statistics.
   if (passed) {
-      let this_epoch = DiemConfig::get_current_epoch();
-      miner_history.latest_epoch_mining = this_epoch;
+      // let this_epoch = DiemConfig::get_current_epoch();
+      // miner_history.latest_epoch_mining = this_epoch; // TODO: Don't need this
       miner_history.epochs_validating_and_mining
         = miner_history.epochs_validating_and_mining + 1u64;
       miner_history.contiguous_epochs_validating_and_mining
@@ -855,8 +861,7 @@ Checks to see if miner submitted enough proofs to be considered compliant
 
 
 
public fun node_above_thresh(miner_addr: address): bool acquires TowerProofHistory {
-  let miner_history = borrow_global<TowerProofHistory>(miner_addr);
-  miner_history.count_proofs_in_epoch > Globals::get_epoch_mining_thres_lower()
+  get_count_in_epoch(miner_addr) >= Globals::get_epoch_mining_thres_lower()
 }
 
@@ -870,7 +875,7 @@ Checks to see if miner submitted enough proofs to be considered compliant -
public fun reconfig(vm: &signer, migrate_eligible_validators: &vector<address>)
+
public fun reconfig(vm: &signer, outgoing_validators: &vector<address>)
 
@@ -879,38 +884,30 @@ Checks to see if miner submitted enough proofs to be considered compliant Implementation -
public fun reconfig(vm: &signer, migrate_eligible_validators: &vector<address>) acquires TowerProofHistory, TowerList {
+
public fun reconfig(vm: &signer, outgoing_validators: &vector<address>) acquires TowerProofHistory, TowerList, TowerCounter {
   // Check permissions
   CoreAddresses::assert_diem_root(vm);
 
-  // check TowerList exists, or use eligible_validators to initialize.
-  // Migration on hot upgrade
-  if (!exists<TowerList>(@0x0)) {
-    move_to<TowerList>(vm, TowerList {
-      list: *migrate_eligible_validators
-    });
-  };
-
-  let towerlist_state = borrow_global_mut<TowerList>(@0x0);
-
-  // Get list of validators from ValidatorUniverse
-  // let eligible_validators = ValidatorUniverse::get_eligible_validators(vm);
-
   // Iterate through validators and call update_metrics for each validator that had proofs this epoch
-  let size = Vector::length<address>(& *&towerlist_state.list); //TODO: These references are weird
+  let vals_len = Vector::length<address>(outgoing_validators); //TODO: These references are weird
   let i = 0;
-  while (i < size) {
-      let val = Vector::borrow(&towerlist_state.list, i);
+  while (i < vals_len) {
+      let val = Vector::borrow(outgoing_validators, i);
 
       // For testing: don't call update_metrics unless there is account state for the address.
       if (exists<TowerProofHistory>(*val)){
-          update_metrics(vm, *val);
+          update_epoch_metrics_vals(vm, *val);
       };
       i = i + 1;
   };
 
-  //reset miner list
-  towerlist_state.list = Vector::empty<address>();
+  epoch_reset(vm);
+  // safety
+  if (exists<TowerList>(@0x0)) {
+    //reset miner list
+    let towerlist_state = borrow_global_mut<TowerList>(@0x0);
+    towerlist_state.list = Vector::empty<address>();
+  };
 }
 
@@ -939,7 +936,7 @@ Checks to see if miner submitted enough proofs to be considered compliant solution: &vector<u8>, difficulty: u64, security: u64 -) acquires TowerProofHistory, TowerList, TowerStats { +) acquires TowerProofHistory, TowerList, TowerCounter { // NOTE Only Signer can update own state. // Should only happen once. @@ -964,7 +961,6 @@ Checks to see if miner submitted enough proofs to be considered compliant security, }; - //submit the proof verify_and_update_state(Signer::address_of(miner_sig), proof, false); } @@ -1018,7 +1014,7 @@ Checks to see if miner submitted enough proofs to be considered compliant -
public fun get_miner_latest_epoch(vm: &signer, addr: address): u64
+
public fun get_miner_latest_epoch(addr: address): u64
 
@@ -1027,8 +1023,7 @@ Checks to see if miner submitted enough proofs to be considered compliant Implementation -
public fun get_miner_latest_epoch(vm: &signer, addr: address): u64 acquires TowerProofHistory {
-  CoreAddresses::assert_diem_root(vm);
+
public fun get_miner_latest_epoch(addr: address): u64 acquires TowerProofHistory {
   let addr_state = borrow_global<TowerProofHistory>(addr);
   *&addr_state.latest_epoch_mining
 }
@@ -1061,6 +1056,83 @@ Checks to see if miner submitted enough proofs to be considered compliant
 
 
 
+
+
+
+
+## Function `increment_stats`
+
+
+
+
fun increment_stats(miner_addr: address)
+
+ + + +
+Implementation + + +
fun increment_stats(miner_addr: address) acquires TowerProofHistory, TowerCounter {
+  // safety. Don't cause VM to halt
+  if (!exists<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS())) return;
+
+  let above = node_above_thresh(miner_addr);
+
+  let state = borrow_global_mut<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS());
+
+  if (ValidatorConfig::is_valid(miner_addr)) {
+    state.validator_proofs_in_epoch = state.validator_proofs_in_epoch + 1;
+    state.lifetime_validator_proofs = state.lifetime_validator_proofs + 1;
+    // only proofs above threshold are counted here. The preceding proofs are not counted;
+    if (above) { state.validator_proofs_in_epoch_above_thresh = state.validator_proofs_in_epoch_above_thresh + 1; }
+  } else {
+    state.fullnode_proofs_in_epoch = state.fullnode_proofs_in_epoch + 1;
+    state.lifetime_fullnode_proofs = state.lifetime_fullnode_proofs + 1;
+    // Preceding proofs before threshold was met are not counted to payment.
+    if (above) { state.fullnode_proofs_in_epoch_above_thresh = state.fullnode_proofs_in_epoch_above_thresh + 1; }
+  };
+
+  state.proofs_in_epoch = state.proofs_in_epoch + 1;
+  state.lifetime_proofs = state.lifetime_proofs + 1;
+}
+
+ + + +
+ + + +## Function `epoch_reset` + +Reset the tower counter at the end of epoch. + + +
public fun epoch_reset(vm: &signer)
+
+ + + +
+Implementation + + +
public fun epoch_reset(vm: &signer) acquires TowerCounter {
+  CoreAddresses::assert_vm(vm);
+  if (!exists<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS())) return;
+
+  let state = borrow_global_mut<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS());
+  state.proofs_in_epoch = 0;
+  state.validator_proofs_in_epoch = 0;
+  state.fullnode_proofs_in_epoch = 0;
+  state.validator_proofs_in_epoch_above_thresh = 0;
+  state.fullnode_proofs_in_epoch_above_thresh = 0;
+}
+
+ + +
@@ -1118,13 +1190,13 @@ Public Getters /// - + -## Function `get_epochs_mining` +## Function `get_epochs_compliant` -
public fun get_epochs_mining(node_addr: address): u64
+
public fun get_epochs_compliant(node_addr: address): u64
 
@@ -1133,7 +1205,7 @@ Public Getters /// Implementation -
public fun get_epochs_mining(node_addr: address): u64 acquires TowerProofHistory {
+
public fun get_epochs_compliant(node_addr: address): u64 acquires TowerProofHistory {
   if (exists<TowerProofHistory>(node_addr)) {
     return borrow_global<TowerProofHistory>(node_addr).epochs_validating_and_mining
   };
@@ -1162,7 +1234,39 @@ Public Getters ///
 
 
public fun get_count_in_epoch(miner_addr: address): u64 acquires TowerProofHistory {
   if (exists<TowerProofHistory>(miner_addr)) {
-    return borrow_global<TowerProofHistory>(miner_addr).count_proofs_in_epoch
+    let s = borrow_global<TowerProofHistory>(miner_addr);
+    if (s.latest_epoch_mining == DiemConfig::get_current_epoch()) {
+      return s.count_proofs_in_epoch
+    };
+  };
+  0
+}
+
+ + + + + + + +## Function `get_count_above_thresh_in_epoch` + + + +
public fun get_count_above_thresh_in_epoch(miner_addr: address): u64
+
+ + + +
+Implementation + + +
public fun get_count_above_thresh_in_epoch(miner_addr: address): u64 acquires TowerProofHistory {
+  if (exists<TowerProofHistory>(miner_addr)) {
+    if (borrow_global<TowerProofHistory>(miner_addr).count_proofs_in_epoch > Globals::get_epoch_mining_thres_lower()) {
+      return borrow_global<TowerProofHistory>(miner_addr).count_proofs_in_epoch - Globals::get_epoch_mining_thres_lower()
+    }
   };
   0
 }
@@ -1170,6 +1274,33 @@ Public Getters ///
 
 
 
+
+ + + +## Function `lazy_reset_count_in_epoch` + + + +
fun lazy_reset_count_in_epoch(miner_addr: address)
+
+ + + +
+Implementation + + +
fun lazy_reset_count_in_epoch(miner_addr: address) acquires TowerProofHistory {
+  let s = borrow_global_mut<TowerProofHistory>(miner_addr);
+  if (s.latest_epoch_mining < DiemConfig::get_current_epoch()) {
+    s.count_proofs_in_epoch = 0;
+  };
+}
+
+ + +
@@ -1203,13 +1334,38 @@ Public Getters /// - + + +## Function `get_validator_proofs_in_epoch` + + + +
public fun get_validator_proofs_in_epoch(): u64
+
+ + + +
+Implementation + + +
public fun get_validator_proofs_in_epoch(): u64 acquires TowerCounter{
+  let state = borrow_global<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS());
+  state.validator_proofs_in_epoch
+}
+
+ + + +
+ + -## Function `test_helper_init_miner` +## Function `get_fullnode_proofs_in_epoch` -
public fun test_helper_init_miner(miner_sig: &signer, challenge: vector<u8>, solution: vector<u8>, difficulty: u64, security: u64)
+
public fun get_fullnode_proofs_in_epoch(): u64
 
@@ -1218,13 +1374,116 @@ Public Getters /// Implementation -
public fun test_helper_init_miner(
+
public fun get_fullnode_proofs_in_epoch(): u64 acquires TowerCounter{
+  let state = borrow_global<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS());
+  state.fullnode_proofs_in_epoch
+}
+
+ + + + + + + +## Function `get_fullnode_proofs_in_epoch_above_thresh` + + + +
public fun get_fullnode_proofs_in_epoch_above_thresh(): u64
+
+ + + +
+Implementation + + +
public fun get_fullnode_proofs_in_epoch_above_thresh(): u64 acquires TowerCounter{
+  let state = borrow_global<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS());
+  state.fullnode_proofs_in_epoch_above_thresh
+}
+
+ + + +
+ + + +## Function `get_lifetime_proof_count` + + + +
public fun get_lifetime_proof_count(): (u64, u64, u64)
+
+ + + +
+Implementation + + +
public fun get_lifetime_proof_count(): (u64, u64, u64) acquires TowerCounter{
+  let s = borrow_global<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS());
+  (s.lifetime_proofs, s.lifetime_validator_proofs, s.lifetime_fullnode_proofs)
+}
+
+ + + +
+ + + +## Function `danger_migrate_get_lifetime_proof_count` + + + +
public fun danger_migrate_get_lifetime_proof_count(): (u64, u64, u64)
+
+ + + +
+Implementation + + +
public fun danger_migrate_get_lifetime_proof_count(): (u64, u64, u64) acquires TowerStats{
+  if (exists<TowerStats>(CoreAddresses::VM_RESERVED_ADDRESS())) {
+    let s = borrow_global<TowerStats>(CoreAddresses::VM_RESERVED_ADDRESS());
+    return (s.proofs_in_epoch, s.validator_proofs, s.fullnode_proofs)
+  };
+  (0,0,0)
+}
+
+ + + +
+ + + +## Function `test_helper_init_val` + + + +
public fun test_helper_init_val(miner_sig: &signer, challenge: vector<u8>, solution: vector<u8>, difficulty: u64, security: u64)
+
+ + + +
+Implementation + + +
public fun test_helper_init_val(
     miner_sig: &signer,
     challenge: vector<u8>,
     solution: vector<u8>,
     difficulty: u64,
     security: u64,
-  ) acquires TowerProofHistory, TowerList, TowerStats {
+  ) acquires TowerProofHistory, TowerList, TowerCounter {
     assert(Testnet::is_testnet(), 130102014010);
 
     move_to<TowerProofHistory>(miner_sig, TowerProofHistory {
@@ -1252,6 +1511,40 @@ Public Getters ///
 
 
 
+
+ + + +## Function `test_epoch_reset_counter` + + + +
public fun test_epoch_reset_counter(vm: &signer)
+
+ + + +
+Implementation + + +
public fun test_epoch_reset_counter(vm: &signer) acquires TowerCounter {
+  assert(Testnet::is_testnet(), Errors::invalid_state(130118));
+  CoreAddresses::assert_vm(vm);
+  let state = borrow_global_mut<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS());
+  state.lifetime_proofs = 0;
+  state.lifetime_validator_proofs = 0;
+  state.lifetime_fullnode_proofs = 0;
+  state.proofs_in_epoch = 0;
+  state.validator_proofs_in_epoch = 0;
+  state.fullnode_proofs_in_epoch = 0;
+  state.validator_proofs_in_epoch_above_thresh = 0;
+  state.fullnode_proofs_in_epoch_above_thresh = 0;
+}
+
+ + +
@@ -1275,7 +1568,7 @@ Public Getters /// // differ slightly from api miner_addr: address, proof: Proof -) acquires TowerProofHistory, TowerList, TowerStats { +) acquires TowerProofHistory, TowerList, TowerCounter { assert(Testnet::is_testnet(), 130102014010); // Get address, assumes the sender is the signer. @@ -1321,18 +1614,10 @@ Public Getters /// Implementation -
public fun test_helper_mock_mining(sender: &signer,  count: u64) acquires TowerProofHistory, TowerStats {
+
public fun test_helper_mock_mining(sender: &signer,  count: u64) acquires TowerProofHistory, TowerCounter {
   assert(Testnet::is_testnet(), Errors::invalid_state(130118));
   let addr = Signer::address_of(sender);
-  let state = borrow_global_mut<TowerProofHistory>(addr);
-  state.count_proofs_in_epoch = count;
-  let i = 0;
-  while (i < count) {
-    increment_stats(addr);
-    i = i + 1;
-  }
-
-  // FullnodeState::mock_proof(sender, count);
+  danger_mock_mining(addr, count)
 }
 
@@ -1355,17 +1640,50 @@ Public Getters /// Implementation -
public fun test_helper_mock_mining_vm(vm: &signer, addr: address, count: u64) acquires TowerProofHistory, TowerStats {
+
public fun test_helper_mock_mining_vm(vm: &signer, addr: address, count: u64) acquires TowerProofHistory, TowerCounter {
   assert(Testnet::is_testnet(), Errors::invalid_state(130120));
   CoreAddresses::assert_diem_root(vm);
-  let state = borrow_global_mut<TowerProofHistory>(addr);
-  state.count_proofs_in_epoch = count;
+  danger_mock_mining(addr, count)
+}
+
+ + + + + + + +## Function `danger_mock_mining` + + + +
fun danger_mock_mining(addr: address, count: u64)
+
+ + + +
+Implementation + + +
fun danger_mock_mining(addr: address, count: u64) acquires TowerProofHistory, TowerCounter {
+  // again for safety
+  assert(Testnet::is_testnet(), Errors::invalid_state(130118));
+
 
   let i = 0;
   while (i < count) {
     increment_stats(addr);
+    let state = borrow_global_mut<TowerProofHistory>(addr);
+    // mock verify_and_update
+    state.verified_tower_height = state.verified_tower_height + 1;
+    state.count_proofs_in_epoch = state.count_proofs_in_epoch + 1;
     i = i + 1;
-  }
+  };
+
+  let state = borrow_global_mut<TowerProofHistory>(addr);
+  state.count_proofs_in_epoch = count;
+  state.latest_epoch_mining = DiemConfig::get_current_epoch();
 }
 
@@ -1388,10 +1706,12 @@ Public Getters /// Implementation -
public fun test_helper_mock_reconfig(account: &signer, miner_addr: address) acquires TowerProofHistory{
+
public fun test_helper_mock_reconfig(account: &signer, miner_addr: address) acquires TowerProofHistory, TowerCounter {
   CoreAddresses::assert_diem_root(account);
   assert(Testnet::is_testnet(), Errors::invalid_state(130122));
-  update_metrics(account, miner_addr);
+  // update_metrics(account, miner_addr);
+  epoch_reset(account);
+  update_epoch_metrics_vals(account, miner_addr);
 }
 
@@ -1445,7 +1765,35 @@ Public Getters ///
public fun test_helper_get_count(account: &signer): u64 acquires TowerProofHistory {
     assert(Testnet::is_testnet(), 130115014011);
     let addr = Signer::address_of(account);
-    borrow_global<TowerProofHistory>(addr).count_proofs_in_epoch
+    get_count_in_epoch(addr)
+}
+
+ + + +
+ + + +## Function `test_helper_get_nominal_count` + + + +
public fun test_helper_get_nominal_count(miner_addr: address): u64
+
+ + + +
+Implementation + + +
public fun test_helper_get_nominal_count(miner_addr: address): u64 acquires TowerProofHistory {
+  assert(Testnet::is_testnet(), Errors::invalid_state(130123));
+  assert(exists<TowerProofHistory>(miner_addr), Errors::not_published(130124));
+
+  let state = borrow_global<TowerProofHistory>(miner_addr);
+  *&state.count_proofs_in_epoch
 }
 
@@ -1640,6 +1988,103 @@ Public Getters /// +
+ + + +## Function `test_mock_depr_tower_stats` + + + +
public fun test_mock_depr_tower_stats(vm: &signer)
+
+ + + +
+Implementation + + +
public fun test_mock_depr_tower_stats(vm: &signer) {
+  assert(Testnet::is_testnet(), Errors::invalid_state(130113));
+  CoreAddresses::assert_vm(vm);
+  move_to<TowerStats>(vm, TowerStats{
+    proofs_in_epoch: 111,
+    validator_proofs: 222,
+    fullnode_proofs: 333,
+  });
+}
+
+ + + +
+ + + +## Function `test_get_liftime_proofs` + + + +
public fun test_get_liftime_proofs(): u64
+
+ + + +
+Implementation + + +
public fun test_get_liftime_proofs(): u64 acquires TowerCounter {
+  assert(Testnet::is_testnet(), Errors::invalid_state(130113));
+
+  let s = borrow_global<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS());
+  s.lifetime_proofs
+}
+
+ + + +
+ + + +## Function `test_danger_destroy_tower_counter` + + + +
public fun test_danger_destroy_tower_counter(vm: &signer)
+
+ + + +
+Implementation + + +
public fun test_danger_destroy_tower_counter(vm: &signer) acquires TowerCounter {
+  assert(Testnet::is_testnet(), Errors::invalid_state(130113));
+  CoreAddresses::assert_vm(vm);
+  assert(exists<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS()), Errors::invalid_state(130115));
+
+    // We destroy the data resource for sender
+    // move_from and then destructure
+
+    let TowerCounter {
+      lifetime_proofs: _,
+      lifetime_validator_proofs: _,
+      lifetime_fullnode_proofs: _,
+      proofs_in_epoch: _,
+      validator_proofs_in_epoch: _,
+      fullnode_proofs_in_epoch: _,
+      validator_proofs_in_epoch_above_thresh: _,
+      fullnode_proofs_in_epoch_above_thresh: _,
+   } = move_from<TowerCounter>(CoreAddresses::VM_RESERVED_ADDRESS());
+}
+
+ + +
diff --git a/language/diem-framework/releases/artifacts/current/docs/modules/ol_miner_state.md b/language/diem-framework/releases/artifacts/current/docs/modules/ol_miner_state.md index f72f8a942d..f371c40e08 100644 --- a/language/diem-framework/releases/artifacts/current/docs/modules/ol_miner_state.md +++ b/language/diem-framework/releases/artifacts/current/docs/modules/ol_miner_state.md @@ -111,7 +111,7 @@
public(script) fun minerstate_helper(sender: signer) {
     assert(Testnet::is_testnet(), 01);
 
-    TowerState::test_helper_init_miner(
+    TowerState::test_helper_init_val(
         &sender,
         TestFixtures::alice_0_easy_chal(),
         TestFixtures::alice_0_easy_sol(),
diff --git a/language/diem-framework/releases/artifacts/current/docs/modules/overview.md b/language/diem-framework/releases/artifacts/current/docs/modules/overview.md
index dc30e0f1f3..2c6d1b6d7b 100644
--- a/language/diem-framework/releases/artifacts/current/docs/modules/overview.md
+++ b/language/diem-framework/releases/artifacts/current/docs/modules/overview.md
@@ -121,7 +121,7 @@ The Move modules in the Diem Framework can be bucketed in to a couple categories
 -  [`0x1::DiemVersion`](DiemVersion.md#0x1_DiemVersion)
 -  [`0x1::DualAttestation`](DualAttestation.md#0x1_DualAttestation)
 -  [`0x1::Epoch`](Epoch.md#0x1_Epoch)
--  [`0x1::EpochBoundary`](Reconfigure.md#0x1_EpochBoundary)
+-  [`0x1::EpochBoundary`](EpochBoundary.md#0x1_EpochBoundary)
 -  [`0x1::Errors`](../../../../../../move-stdlib/docs/Errors.md#0x1_Errors)
 -  [`0x1::Event`](../../../../../../move-stdlib/docs/Event.md#0x1_Event)
 -  [`0x1::FIFO`](FIFO.md#0x1_FIFO)
@@ -131,8 +131,9 @@ The Move modules in the Diem Framework can be bucketed in to a couple categories
 -  [`0x1::Genesis`](Genesis.md#0x1_Genesis)
 -  [`0x1::Globals`](Globals.md#0x1_Globals)
 -  [`0x1::Hash`](../../../../../../move-stdlib/docs/Hash.md#0x1_Hash)
--  [`0x1::MigrateWallets`](Migrations.md#0x1_MigrateWallets)
+-  [`0x1::MigrateTowerCounter`](Migrations.md#0x1_MigrateTowerCounter)
 -  [`0x1::Migrations`](Migrations.md#0x1_Migrations)
+-  [`0x1::Mock`](Mock.md#0x1_Mock)
 -  [`0x1::NodeWeight`](NodeWeight.md#0x1_NodeWeight)
 -  [`0x1::Option`](../../../../../../move-stdlib/docs/Option.md#0x1_Option)
 -  [`0x1::Oracle`](Oracle.md#0x1_Oracle)
diff --git a/language/diem-framework/releases/artifacts/current/docs/scripts/script_documentation.md b/language/diem-framework/releases/artifacts/current/docs/scripts/script_documentation.md
index c70e66e14d..4d3a388f95 100644
--- a/language/diem-framework/releases/artifacts/current/docs/scripts/script_documentation.md
+++ b/language/diem-framework/releases/artifacts/current/docs/scripts/script_documentation.md
@@ -5276,12 +5276,13 @@ a reconfiguration of the system.
 -  [`0x1::DiemVersion`](../../../../../releases/artifacts/current/docs/modules/DiemVersion.md#0x1_DiemVersion)
 -  [`0x1::DualAttestation`](../../../../../releases/artifacts/current/docs/modules/DualAttestation.md#0x1_DualAttestation)
 -  [`0x1::Epoch`](../../../../../releases/artifacts/current/docs/modules/Epoch.md#0x1_Epoch)
--  [`0x1::EpochBoundary`](../../../../../releases/artifacts/current/docs/modules/Reconfigure.md#0x1_EpochBoundary)
+-  [`0x1::EpochBoundary`](../../../../../releases/artifacts/current/docs/modules/EpochBoundary.md#0x1_EpochBoundary)
 -  [`0x1::FIFO`](../../../../../releases/artifacts/current/docs/modules/FIFO.md#0x1_FIFO)
 -  [`0x1::FullnodeSubsidy`](../../../../../releases/artifacts/current/docs/modules/FullnodeSubsidy.md#0x1_FullnodeSubsidy)
 -  [`0x1::GAS`](../../../../../releases/artifacts/current/docs/modules/GAS.md#0x1_GAS)
 -  [`0x1::Genesis`](../../../../../releases/artifacts/current/docs/modules/Genesis.md#0x1_Genesis)
 -  [`0x1::Globals`](../../../../../releases/artifacts/current/docs/modules/Globals.md#0x1_Globals)
+-  [`0x1::MigrateTowerCounter`](../../../../../releases/artifacts/current/docs/modules/Migrations.md#0x1_MigrateTowerCounter)
 -  [`0x1::Migrations`](../../../../../releases/artifacts/current/docs/modules/Migrations.md#0x1_Migrations)
 -  [`0x1::NodeWeight`](../../../../../releases/artifacts/current/docs/modules/NodeWeight.md#0x1_NodeWeight)
 -  [`0x1::Oracle`](../../../../../releases/artifacts/current/docs/modules/Oracle.md#0x1_Oracle)
diff --git a/language/diem-framework/releases/artifacts/current/error_description/error_description.errmap b/language/diem-framework/releases/artifacts/current/error_description/error_description.errmap
index 7838e4a3acba977d39f8960575ae764b07ce4b1b..2230f36ba9a1c566b2bff9d88520841c3ea8cdc9 100644
GIT binary patch
delta 26
hcmdl`xUq19xg4*SYp{=hczn2{kB@7}W@ouvDFA{Q2+aTh

delta 25
gcmdm3xS?=^xg3wCYq)2Khf9!SxTDWz7r9(10C%4VRsaA1

diff --git a/language/diem-framework/releases/artifacts/current/modules/025_Globals.mv b/language/diem-framework/releases/artifacts/current/modules/025_Globals.mv
index b895b01dee74ce8d711238963997eabaa34571ba..9be1884aab8c42e6b4add6aeef626333827726aa 100644
GIT binary patch
delta 14
VcmdnNv4dm7PbNmD&A*uJ7y&CR1swnY

delta 14
VcmdnNv4dm7PbNmj&A*uJ7y&CL1snhX

diff --git a/language/diem-framework/releases/artifacts/current/modules/026_TowerState.mv b/language/diem-framework/releases/artifacts/current/modules/026_TowerState.mv
index 590ef9f139aaa04a91b96aa9db5853b6cee98e68..8f23617791ff7492e92b0b9ae611acd95843e29c 100644
GIT binary patch
literal 6794
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

literal 5195
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
UfA^CxUZO_`i-t6GcZECRzi*XJ{Qv*}

diff --git a/language/diem-framework/releases/artifacts/current/modules/043_DiemAccount.mv b/language/diem-framework/releases/artifacts/current/modules/043_DiemAccount.mv
index 0f6e4fff02c81966338da156cd3cb1a398d4cbca..066b173f6f80d718b5c00d95f8181caa413fdebd 100644
GIT binary patch
delta 223
zcmWm4y-LGS6ae6yoZO$>a~gYWGL!~Q(N=oY>tS6#4ZqR-94~=hE64BE@1Qn2?a*U+!L~m;s^A}mE+wh}

delta 220
zcmWm3u}T9$5CG7do7M|VEuO!o!#8YHjs3MZ?Pmi1JO6kMRP8R!i}?3(CNkNZ@&
zM`GDxWE!+qN9yVoNGXmTZgBaJD+GEdES^1XGq*Id0t|~diFtsm$k13M&eFm97eXh6
M;nahsqpb%107%;-;{X5v

diff --git a/language/diem-framework/releases/artifacts/current/modules/051_Audit.mv b/language/diem-framework/releases/artifacts/current/modules/051_Audit.mv
index fec6d4cd728f01d8cd532dba7a83ead4eb5c1c52..e655a97c234d22a373f159acae066c036b591e2e 100644
GIT binary patch
delta 178
zcmW;BtqlTE5Cq`a-P`wfkDoIHafC-81VaH>f~N%xWq?JXE@%Wb&}$u~0}
zxy$L*erpEc2wC!0ceOvfDg0=hZ+y0czz|eWI5Rv8B#?ljRZUj4W(H+bHL&2J1-T4T
xBJM72_q;xqblmeMp{a_f`p8Djlqg{#BW?P@6`AO?r!O+odCyQ}rR&In@dsL24%Ywx

delta 234
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
N?xQ`7v6wpY;2#D;Satva

literal 0
HcmV?d00001

diff --git a/language/diem-framework/releases/artifacts/current/modules/064_DiemBlock.mv b/language/diem-framework/releases/artifacts/current/modules/064_DiemBlock.mv
new file mode 100644
index 0000000000000000000000000000000000000000..c4ee074bb4ad462ecc1733eaea51a4a19dd181c0
GIT binary patch
literal 1295
zcmYjR&63+h5bmDQNb-y%d%WI1SV%TNmSkDNaj(wW1*u{Q6>sIL(%KVS6iyQ
z{8fa%1RekPpeNr2htZ$G&n*6{ZQ`ran*L;BO;wpn)%N~)
zT&@ZyYk9P(oLR)Rc#|(o<+8<6443727B~BILQXQf@rTxywi3g&DIEX0Kia#_r#5ru
zro1!us^&9RZgqKCRAS^ZSH(>#*T!X&%w_R+=B`mRB*|@^X1cWHyqvDg(bTwfyt0<~
z)2(S{^6AVS=SA-FY@YvUcKXGRFUhO)y>a4i@twll?SQ6Ewo*;FZ?a-CH^SESgcNjH
zR>t<0)~xe#RqY(sr8AXw)QEJEk1avQWihEb8THP(v|Ji0IWMNIonpP%dwre08jgmq
zUJnOpe=s0<6j5GlN|NGmG12^i+ZxbDN!bNTpfa&I>k
zWpLNNKV~$~Ww!C^iuV`W=BKXie%g%FSUq?#q-
zUD|XeG4-6&H^f-Y%tYC`+Bf-hWlda^E?ur}=Zz)Vl{+2^KPPb{d80+zU`i?_H<{k1QaV*6LoQw$KT6+m-AwBJ%
z@=&NS3PnPvAPQ9&pbn!T@|DjIRdAL-!gY&wucsw>DgH=2PT&$qjwSjvWxY=Mxp+pp
zgnn(^c?yw8KzfpCEky@<{(WW#QnX=Ti8e}y%ql^o~;3Hng;hlDzcScD3BTLE3(Gf7X?ZYj8AUAO?&)XsJ1
K2|Z_Z7ybnl9vO`Q

literal 0
HcmV?d00001

diff --git a/language/diem-framework/releases/artifacts/current/modules/064_DiemConsensusConfig.mv b/language/diem-framework/releases/artifacts/current/modules/065_DiemConsensusConfig.mv
similarity index 100%
rename from language/diem-framework/releases/artifacts/current/modules/064_DiemConsensusConfig.mv
rename to language/diem-framework/releases/artifacts/current/modules/065_DiemConsensusConfig.mv
diff --git a/language/diem-framework/releases/artifacts/current/modules/065_DiemVMConfig.mv b/language/diem-framework/releases/artifacts/current/modules/066_DiemVMConfig.mv
similarity index 100%
rename from language/diem-framework/releases/artifacts/current/modules/065_DiemVMConfig.mv
rename to language/diem-framework/releases/artifacts/current/modules/066_DiemVMConfig.mv
diff --git a/language/diem-framework/releases/artifacts/current/modules/066_DiemVersion.mv b/language/diem-framework/releases/artifacts/current/modules/067_DiemVersion.mv
similarity index 100%
rename from language/diem-framework/releases/artifacts/current/modules/066_DiemVersion.mv
rename to language/diem-framework/releases/artifacts/current/modules/067_DiemVersion.mv
diff --git a/language/diem-framework/releases/artifacts/current/modules/067_Upgrade.mv b/language/diem-framework/releases/artifacts/current/modules/068_Upgrade.mv
similarity index 100%
rename from language/diem-framework/releases/artifacts/current/modules/067_Upgrade.mv
rename to language/diem-framework/releases/artifacts/current/modules/068_Upgrade.mv
diff --git a/language/diem-framework/releases/artifacts/current/modules/068_Oracle.mv b/language/diem-framework/releases/artifacts/current/modules/069_Oracle.mv
similarity index 100%
rename from language/diem-framework/releases/artifacts/current/modules/068_Oracle.mv
rename to language/diem-framework/releases/artifacts/current/modules/069_Oracle.mv
diff --git a/language/diem-framework/releases/artifacts/current/modules/069_Genesis.mv b/language/diem-framework/releases/artifacts/current/modules/070_Genesis.mv
similarity index 100%
rename from language/diem-framework/releases/artifacts/current/modules/069_Genesis.mv
rename to language/diem-framework/releases/artifacts/current/modules/070_Genesis.mv
diff --git a/language/diem-framework/releases/artifacts/current/modules/070_MigrateWallets.mv b/language/diem-framework/releases/artifacts/current/modules/070_MigrateWallets.mv
deleted file mode 100644
index d0081fa9adec290eba9f8bedbeb9c5f507c765e9..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 469
zcmZvZ&q@O^5XNWncbkoE7fQYKpa`PkS&Fx!SC7`?y6wj8!geD`+CGo?2%dcgAH

5Dfq(jVk8_7MnBV8B7d8f8p0 zp$u3jesLu!0#B1p9MdYc4pIarxIm$SaY_|Oiiq*yC{zc?Hc=GYN^>eSRit}YSFQ-= zp=cTt{K1WNW>S{UcyD}qTbt!%KDVnjsNG;~Tc1sfrY?(M-F;iHjq^rK%{kI`hwK*-M a1qw5vh=`2u7;3_MDM*l*Nq&|B68Hk;G+HnK diff --git a/language/diem-framework/releases/artifacts/current/modules/071_Mock.mv b/language/diem-framework/releases/artifacts/current/modules/071_Mock.mv new file mode 100644 index 0000000000000000000000000000000000000000..e7a1ae658c0dcc9047573e62a58e2dd7f33177bb GIT binary patch literal 621 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 DH&PHk delta 5258 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 diff --git a/ol/changelog/5_0_9.md b/ol/changelog/5_0_9.md new file mode 100644 index 0000000000..e3d2d03cbd --- /dev/null +++ b/ol/changelog/5_0_9.md @@ -0,0 +1,107 @@ +## 5.0.9 + +Very minor changes to the config creator for the VFN configurations (vfn.node.yaml). The ID of the VFN needs to be permanent once shared in on-chain discovery info. + +This includes `txs` tooling for updating on-chain info, plus helpers to print what configs currently exist. + +### TL;DR Deployment + +#### Update 0L.toml file + +Under `profile` include a `vfn_ip` field, with the IP address. This will simplify and correctly display networking addresses for the info helpers. + +``` +[profile] +account = "foo" +auth_key = "bar" +statement = "baz" +ip = "127.0.0.1" +# NEW FIELD HERE: +vfn_ip = "x.y.z.0" +``` +#### Update binaries to use patches. + +``` + +# install new binaries +cd ~/libra +git fetch +git checkout v5.0.9 -f +make bins install + +``` + +#### Recreate your VFN configs, and deploy on VFN. + +``` +# On your validator (or wherever your key_store.json lives) +# create settings for the VFN, private fullnode +ol init --vfn + +# now copy the vfn.node.yaml file to your fullnode +``` + +#### Check and update your on-chain configuration + +More details here: +[Check and change your on-chain config](../documentation/node-ops/validators/changing_onchain_ip_address.md) + +``` + +# what are your keys +ol whoami + +# do your keys match what your node is using +ol whoami --check-yaml + +# what are your current on-chain configs +ol query --val-config + +# Update your configs based on what your mnemonic uses +# Note the `-o` which means you are sending this from the "operator" account. +txs -o val-config --val-ip --vfn-ip + + +# check if those changes persisted and if they are able to be read. +ol query --val-config + +``` + +### Summary + +This upgrade corrects behavior of vfn.node.yaml config creator, and provides tooling for updating on-chain node discovery information (update IP addresses). + +### Changes + +##### Move Changes +None + +##### Rust Changes + +A tool was needed to update on-chain discovery (network address) for validators and the validator's VFN fullnode. +1) people will change hosting solutions and need to be able to change IP addresses +2) Validators are migrating to having separate hosts for validator and fullnodes. All the on-chain discovery must be changed to include the new VFN information. + +- [x] `txs` subcommand `val-config` which accepts the validator and VFN as arguments. And using mnemonic will submit a tx to change validator configs on-chain. +- [x] correct `ol init --vfn` so that the public fullnode ID is permanent, and uses the appropriate key derivation. +- [x] cleanup implementation of ValConfigs, so network addresses are consistent. +- [x] Helper to display keys and network info of a mnemonic: `ol whoami` +- [x] Helper to display the network IDs used in a node.yaml file: `ol whoami --yaml-path ` +- [x] clean `onboard`and `ol init` commands to exist instead of panic. +- [x] `onboard val` to ask user to provide IP address of VFN +- [x] wizard gets external IP address for user from https://ifconfig.me + + +https://github.com/OLSF/libra/pull/938 + +##### Tests + +- All continuous integration tests passed. +- The diem-code was tested on a "Canary rollout" to three production nodes that were both synced and out of sync. + +##### Compatibility +The Move framework changes are backwards compatible with `diem-node` from v5.0.1 + +### Rust changes +#### Diem Node +Changes to `diem-node` is compatible with on-chain state from `v5.0.5`. diff --git a/ol/cli/Cargo.toml b/ol/cli/Cargo.toml index 0c5a15aae7..e2bb1331f0 100644 --- a/ol/cli/Cargo.toml +++ b/ol/cli/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ol" authors = [] -version = "5.0.8" +version = "5.0.9" edition = "2018" [dependencies] diff --git a/ol/cli/src/commands/init_cmd.rs b/ol/cli/src/commands/init_cmd.rs index 0aa87a81dd..a2beb1af8f 100644 --- a/ol/cli/src/commands/init_cmd.rs +++ b/ol/cli/src/commands/init_cmd.rs @@ -18,17 +18,13 @@ use diem_types::waypoint::Waypoint; use diem_wallet::WalletLibrary; use fs_extra::file::{copy, CopyOptions}; use ol_keys::{scheme::KeyScheme, wallet}; -use ol_types::fixtures; +use ol_types::{config::fix_missing_fields, fixtures}; use std::process::exit; use std::{fs, path::PathBuf}; use url::Url; /// `init` subcommand #[derive(Command, Debug, Default, Options)] pub struct InitCmd { - /// home path for app config - #[options(help = "home path for app config")] - path: Option, - /// An upstream peer to use in 0L.toml #[options(help = "An upstream peer to use in 0L.toml")] rpc_peer: Option, @@ -37,6 +33,10 @@ pub struct InitCmd { #[options(help = "Create the 0L.toml file for 0L apps")] app: bool, + /// home path for app config + #[options(help = "home path for app config")] + app_cfg_path: Option, + /// Create validator yaml file configuration #[options(help = "Create validator.node.yaml file configuration")] val: bool, @@ -81,11 +81,24 @@ pub struct InitCmd { impl Runnable for InitCmd { /// Print version message fn run(&self) { + + // TODO: This has no effect. This command will not load if the 0L.toml is malformed. + // this is an Abscissa issue. + // even with serde deny_unknown disabled the app will crash. + if self.app_cfg_path.is_some() && self.fix { + match fix_missing_fields(self.app_cfg_path.as_ref().unwrap().to_owned()) { + Ok(_) => println!("0L.toml has up-to-date schema"), + Err(e) => println!("could not update 0L.toml schema, exiting. Message: {:?}", e), + }; + return; + } + // start with a default value, or read from file if already initialized let mut app_cfg = app_config().to_owned(); let entry_args = entrypoint::get_args(); let is_swarm = *&entry_args.swarm_path.is_some(); + if self.update_waypoint { // TODO: will need to update the key_store.json file with waypoint info. if let Some(w) = self.waypoint { @@ -108,6 +121,9 @@ impl Runnable for InitCmd { match node.waypoint() { Ok(w) => { + key::set_waypoint(&app_cfg.workspace.node_home, &app_cfg.profile.account.to_string(), w); + key::set_genesis_waypoint(&app_cfg.workspace.node_home, &app_cfg.profile.account.to_string(), w); + app_cfg.chain_info.base_waypoint = Some(w); app_cfg.save_file(); return; @@ -173,7 +189,7 @@ impl Runnable for InitCmd { if self.vfn { println!("Creating vfn.node.yaml file."); - let namespace = app_cfg.profile.account.to_hex() + "-oper"; + let namespace = app_cfg.format_oper_namespace(); let output_dir = app_cfg.workspace.node_home; let val_ip_address = app_cfg.profile.ip; let gen_wp = app_cfg.chain_info.base_waypoint; @@ -199,7 +215,7 @@ impl Runnable for InitCmd { // TODO: check we can open key-store file - let namespace = app_cfg.profile.account.to_hex() + "-oper"; + let namespace = app_cfg.format_oper_namespace(); let output_dir = app_cfg.workspace.node_home; match ol_node_files::make_val_file(output_dir, None, &namespace) { @@ -244,8 +260,11 @@ impl Runnable for InitCmd { &self.source_path, ) .unwrap_or_else(|e| { - println!("could not initialize host with swarm configs, exiting. Message: {:?}", &e); - exit(1); + println!( + "could not initialize host with swarm configs, exiting. Message: {:?}", + &e + ); + exit(1); }); return; } @@ -262,23 +281,26 @@ impl Runnable for InitCmd { .interact() { Ok(t) => { - if t { - initialize_app_cfg( - authkey, - account, - &self.rpc_peer, - &self.path, - &None, // TODO: probably need an epoch option here. - &self.waypoint, - &self.source_path, - ) - .unwrap_or_else(|e| { - println!("could not initialize app configs 0L.toml, exiting. Message: {:?}", &e); - exit(1); - }); - } - }, - Err(_) => {}, + if t { + initialize_app_cfg( + authkey, + account, + &self.rpc_peer, + &self.app_cfg_path, + &None, // TODO: probably need an epoch option here. + &self.waypoint, + &self.source_path, + ) + .unwrap_or_else(|e| { + println!( + "could not initialize app configs 0L.toml, exiting. Message: {:?}", + &e + ); + exit(1); + }); + } + } + Err(_) => {} }; return; }; @@ -313,8 +335,8 @@ pub fn initialize_app_cfg( None, ) .unwrap_or_else(|e| { - println!("could not create app configs, exiting. Message: {:?}", &e); - exit(1); + println!("could not create app configs, exiting. Message: {:?}", &e); + exit(1); }); Ok(cfg) } @@ -339,10 +361,12 @@ pub fn initialize_host_swarm( if !&blocks_dir.exists() { // first run, create the directory if there is none, or if the user changed the configs. // note: user may have blocks but they are in a different directory than what miner.toml says. - fs::create_dir_all(&blocks_dir) - .unwrap_or_else(|e| { - println!("could not create directory for vdf proofs, exiting. Message: {:?}", &e); - exit(1); + fs::create_dir_all(&blocks_dir).unwrap_or_else(|e| { + println!( + "could not create directory for vdf proofs, exiting. Message: {:?}", + &e + ); + exit(1); }) }; @@ -358,20 +382,20 @@ pub fn initialize_host_swarm( /// Initializes the necessary validator config files: genesis.blob, key_store.json pub fn initialize_val_key_store( wallet: &WalletLibrary, - miner_config: &AppCfg, + app_cfg: &AppCfg, way_opt: Option, is_genesis: bool, ) -> Result<(), Error> { - let home_dir = &miner_config.workspace.node_home; + let home_dir = &app_cfg.workspace.node_home; let keys = KeyScheme::new(wallet); - let namespace = miner_config.profile.account.to_hex(); // same format as serializer for 0L/toml + let namespace = app_cfg.format_oper_namespace(); + let way = way_opt.unwrap_or("0:c12c01d2ac6deb028567c9a9c816ca3fe53fab9c461e4eab2f89125f975b63c3".parse().unwrap()); + init::key_store_init(home_dir, &namespace, keys, is_genesis); key::set_operator_key(home_dir, &namespace); - key::set_owner_key(home_dir, &namespace); - if let Some(way) = way_opt { - key::set_genesis_waypoint(home_dir, &namespace, way); - key::set_waypoint(home_dir, &namespace, way); - } + key::set_owner_key(home_dir, &namespace, app_cfg.profile.account); + key::set_genesis_waypoint(home_dir, &namespace, way.clone()); + key::set_waypoint(home_dir, &namespace, way); Ok(()) } diff --git a/ol/cli/src/commands/whoami_cmd.rs b/ol/cli/src/commands/whoami_cmd.rs index a108655cbb..56c7a89ae1 100644 --- a/ol/cli/src/commands/whoami_cmd.rs +++ b/ol/cli/src/commands/whoami_cmd.rs @@ -9,7 +9,7 @@ use anyhow::{anyhow, Error}; use diem_config::{config::NodeConfig, network_id::NetworkId}; use diem_crypto::x25519; use ol_keys::{scheme::KeyScheme, wallet}; -use ol_types::account::ValConfigs; +use ol_types::{account::ValConfigs}; use crate::prelude::app_config; @@ -39,7 +39,7 @@ impl Runnable for WhoamiCmd { None, KeyScheme::new(&wallet), app_cfg.profile.ip, - app_cfg.profile.vfn_ip, + app_cfg.profile.vfn_ip.unwrap_or("0.0.0.0".parse().unwrap()), None, None, ); @@ -50,22 +50,21 @@ impl Runnable for WhoamiCmd { let scheme = KeyScheme::new(&wallet); println!("----- pub ed25519 keys -----\n"); - println!("key 0: {}\n", scheme.child_0_owner.get_public()); - println!("key 1: {}\n", scheme.child_1_operator.get_public()); - println!("key 2: {}\n", scheme.child_2_val_network.get_public()); - println!("key 3: {}\n", scheme.child_3_fullnode_network.get_public()); - println!("key 4: {}\n", scheme.child_4_consensus.get_public()); - println!("key 5: {}\n", scheme.child_5_executor.get_public()); + println!("key 0 Owner: {}\n", scheme.child_0_owner.get_public()); + println!("key 1 Operator: {}\n", scheme.child_1_operator.get_public()); + println!("key 2 Val Network: {}\n", scheme.child_2_val_network.get_public()); + println!("key 3 Pub FN Network: {}\n", scheme.child_3_fullnode_network.get_public()); + println!("key 4 Consensus: {}\n", scheme.child_4_consensus.get_public()); + println!("key 5 Executor: {}\n", scheme.child_5_executor.get_public()); println!("----- pub x25519 network keys -----\n"); - // println!("0 key: {}\n", hex::encode()); let val_net_priv = scheme.child_2_val_network.get_private_key().to_bytes(); let key = x25519::PrivateKey::from_ed25519_private_bytes(&val_net_priv) .expect("Unable to convert key"); println!( - "key 3 - validator network key: {:?}\n", + "validator network key: {:?}\n", key.public_key().to_string() ); @@ -74,7 +73,7 @@ impl Runnable for WhoamiCmd { let key = x25519::PrivateKey::from_ed25519_private_bytes(&fn_net_priv) .expect("Unable to convert key"); println!( - "key 3 - fullnode network key: {:?}\n", + "fullnode network key: {:?}\n", &key.public_key().to_string() ); @@ -99,7 +98,13 @@ fn display_id_in_file(yaml_path: &PathBuf) -> Result<(), Error> { &e ) })?; - let ip = get_my_ip()?; + + println!("We will use this machines external IP for display. Note that if you move this file the IP will display differently on another machine. "); + let ip = get_my_ip().unwrap_or_else(|_| { + println!("could not get external IP, using 0.0.0.0 for display"); + "0.0.0.0".parse().unwrap() + }); + println!("\n ACTUAL NETWORK IDs IN {:?}\n", yaml_path.as_os_str()); println!("----- noise protocol addresses -----\n"); @@ -147,7 +152,7 @@ fn display_id_in_file(yaml_path: &PathBuf) -> Result<(), Error> { let addr = ValConfigs::make_unencrypted_addr( &ip, pub_key, - NetworkId::Validator, + NetworkId::Private("vfn".to_string()), ); println!("{:?}:\n", &peer_id); println!("{:?}\n", &addr); diff --git a/ol/cli/src/mgmt/restore.rs b/ol/cli/src/mgmt/restore.rs index 44367e653c..4c3c3c4ed3 100644 --- a/ol/cli/src/mgmt/restore.rs +++ b/ol/cli/src/mgmt/restore.rs @@ -111,7 +111,7 @@ impl Backup { restore_path: restore_path.clone(), archive_path: conf.workspace.node_home.join(format!("restore/restore-{}.tar.gz", restore_epoch)), waypoint: None, - node_namespace: format!("{}-oper", conf.profile.account.clone().to_hex()), // NOTE: needs to match namespace used in ol/onboard and config/management/genesis + node_namespace: conf.format_oper_namespace(), // NOTE: needs to match namespace used in ol/onboard and config/management/genesis } } /// Fetch backups diff --git a/ol/documentation/node-ops/validators/changing_onchain_ip_address.md b/ol/documentation/node-ops/validators/changing_onchain_ip_address.md index 1e6d01962a..01c9845b57 100644 --- a/ol/documentation/node-ops/validators/changing_onchain_ip_address.md +++ b/ol/documentation/node-ops/validators/changing_onchain_ip_address.md @@ -32,6 +32,12 @@ Your node.yaml could be malformed. You'll want to check that the IDs used in the ``` ol whoami --check-yaml ``` +If YOUR node.yaml file does not match what your `ol whoami` shows you may need to redo the node configs. + +``` +ol init --val +ol inti --vfn +``` ## Update the on-chain configs @@ -39,5 +45,9 @@ You will need to have two IP addresses 1) The validator IP, and 2) the VFN valid After displaying the new configs, you will be asked to confirm the changes. ``` -txs val-config --val_ip --vfn-ip +# send tx. Note the `-o` which means you are sending this from the "operator" account. +txs -o val-config --val_ip --vfn-ip + +# check if those changes persisted and if they are able to be read. +ol query --val-config ``` \ No newline at end of file diff --git a/ol/onboard/Cargo.toml b/ol/onboard/Cargo.toml index bdcd64fdef..75204a899d 100644 --- a/ol/onboard/Cargo.toml +++ b/ol/onboard/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "onboard" -version = "5.0.8" +version = "5.0.9" edition = "2018" authors = ["0L contributors"] description = "0L onboarding wizard" diff --git a/ol/onboard/src/commands/fix_cmd.rs b/ol/onboard/src/commands/fix_cmd.rs index b359609209..4d2861aa08 100644 --- a/ol/onboard/src/commands/fix_cmd.rs +++ b/ol/onboard/src/commands/fix_cmd.rs @@ -32,7 +32,7 @@ impl Runnable for FixCmd { status_info!("\nOnboard fix", "migrating account.json"); let cfg = app_config(); let home_dir = &cfg.workspace.node_home; - let namespace = cfg.profile.auth_key.to_string(); + let namespace = cfg.format_oper_namespace(); // set the waypoint if let Some(w) = self.waypoint { key::set_waypoint(home_dir, &namespace, w); diff --git a/ol/onboard/src/commands/wizard_fork_cmd.rs b/ol/onboard/src/commands/wizard_fork_cmd.rs index 58dc5234a8..32fdc649f2 100644 --- a/ol/onboard/src/commands/wizard_fork_cmd.rs +++ b/ol/onboard/src/commands/wizard_fork_cmd.rs @@ -282,7 +282,7 @@ pub fn write_account_json( Some(block), keys, cfg.profile.ip, - cfg.profile.vfn_ip, + cfg.profile.vfn_ip.unwrap_or("0.0.0.0".parse().unwrap()), autopay_batch, autopay_signed, ) diff --git a/ol/onboard/src/commands/wizard_val_cmd.rs b/ol/onboard/src/commands/wizard_val_cmd.rs index ed35d8e4bd..ccc5f25011 100644 --- a/ol/onboard/src/commands/wizard_val_cmd.rs +++ b/ol/onboard/src/commands/wizard_val_cmd.rs @@ -300,7 +300,7 @@ pub fn write_account_json( Some(block), keys, cfg.profile.ip, - cfg.profile.vfn_ip, + cfg.profile.vfn_ip.unwrap_or("0.0.0.0".parse().unwrap()), autopay_batch, autopay_signed, ) diff --git a/ol/onboard/src/manifest.rs b/ol/onboard/src/manifest.rs index 551b68f7a8..457a8204b6 100644 --- a/ol/onboard/src/manifest.rs +++ b/ol/onboard/src/manifest.rs @@ -34,7 +34,7 @@ pub fn write_manifest( Some(block), keys, cfg.profile.ip, - cfg.profile.vfn_ip, + cfg.profile.vfn_ip.unwrap_or("0.0.0.0".parse().unwrap()), autopay_batch, autopay_signed, ).create_manifest(miner_home); diff --git a/ol/tower/Cargo.toml b/ol/tower/Cargo.toml index 5c9d4c8493..57d868758c 100644 --- a/ol/tower/Cargo.toml +++ b/ol/tower/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tower" -version = "5.0.8" +version = "5.0.9" edition = "2018" authors = ["0L contributors"] description = "0L tower" diff --git a/ol/txs/Cargo.toml b/ol/txs/Cargo.toml index ddd955ce54..2cdff1cbe3 100644 --- a/ol/txs/Cargo.toml +++ b/ol/txs/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "txs" authors = [] -version = "5.0.8" +version = "5.0.9" edition = "2018" [dependencies] diff --git a/ol/types/src/account.rs b/ol/types/src/account.rs index 9fe17a4f8a..729e3faaef 100644 --- a/ol/types/src/account.rs +++ b/ol/types/src/account.rs @@ -130,7 +130,7 @@ impl ValConfigs { op_val_net_addr_for_vals: val_addr_for_val_net.to_owned(), op_val_net_addr_for_vfn: val_addr_for_vfn_net.to_owned(), op_vfn_net_addr_for_public: vfn_addr_obj.to_owned(), - op_human_name: format!("{}-oper", owner_address), + op_human_name: format!("{}-oper", owner_address), //NOTE: This must match ol/types/src/config.rs format_oper_namespace autopay_instructions, autopay_signed, } diff --git a/ol/types/src/config.rs b/ol/types/src/config.rs index f1b0368148..ab9c9673cb 100644 --- a/ol/types/src/config.rs +++ b/ol/types/src/config.rs @@ -61,16 +61,24 @@ pub struct AppCfg { } /// Get a AppCfg object from toml file -pub fn parse_toml(path: String) -> Result { - let mut config_toml = String::new(); +pub fn parse_toml(path: PathBuf) -> Result { + // let mut config_toml = path.to_str().unwrap().to_owned()).expect("could not parse app config from file"); + let mut toml_buf = "".to_string(); let mut file = File::open(&path)?; - file.read_to_string(&mut config_toml)?; + file.read_to_string(&mut toml_buf)?; - let cfg: AppCfg = toml::from_str(&config_toml).unwrap(); + let cfg: AppCfg = toml::from_str(&toml_buf)?; Ok(cfg) } +/// Get a AppCfg object from toml file +pub fn fix_missing_fields(path: PathBuf) -> Result<(), Error> { + let cfg: AppCfg = parse_toml(path)?; + cfg.save_file(); + Ok(()) +} + impl AppCfg { /// Gets the dynamic waypoint from diem node's key_store.json pub fn get_waypoint(&self, swarm_path_opt: Option) -> Result { @@ -104,6 +112,11 @@ impl AppCfg { } } + /// format the standard namespace for 0L validator + pub fn format_oper_namespace(&self) -> String { + format!("{}-oper", self.profile.account.to_hex()) + } + /// Get where the block/proofs are stored. pub fn get_block_dir(&self) -> PathBuf { let mut home = self.workspace.node_home.clone(); @@ -147,8 +160,8 @@ impl AppCfg { }; default_config.profile.vfn_ip = match ip { - Some(i) => i, - None => what_vfn_ip().unwrap(), + Some(i) => Some(i), + None => what_vfn_ip().ok(), }; default_config.workspace.node_home = @@ -355,7 +368,7 @@ impl Default for Workspace { /// Information about the Chain to mined for #[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(deny_unknown_fields)] +// #[serde(deny_unknown_fields)] pub struct ChainInfo { /// Chain that this work is being committed to pub chain_id: String, @@ -380,7 +393,7 @@ impl Default for ChainInfo { } /// Miner profile to commit this work chain to a particular identity #[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(deny_unknown_fields)] +// #[serde(deny_unknown_fields)] pub struct Profile { /// The 0L account for the Miner and prospective validator. This is derived from auth_key pub account: AccountAddress, @@ -395,7 +408,7 @@ pub struct Profile { pub ip: Ipv4Addr, /// ip address of the validator fullnodee - pub vfn_ip: Ipv4Addr, + pub vfn_ip: Option, /// Node URL and and port to submit transactions. Defaults to localhost:8080 pub default_node: Option, @@ -417,7 +430,7 @@ impl Default for Profile { .unwrap(), statement: "Protests rage across the nation".to_owned(), ip: "0.0.0.0".parse().unwrap(), - vfn_ip: "0.0.0.0".parse().unwrap(), + vfn_ip: "0.0.0.0".parse().ok(), default_node: Some("http://localhost:8080".parse().expect("parse url")), upstream_nodes: Some(vec!["http://localhost:8080".parse().expect("parse url")]), tower_link: None, @@ -477,7 +490,7 @@ impl TxConfigs { /// Transaction preferences for a given type of transaction #[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(deny_unknown_fields)] +// #[serde(deny_unknown_fields)] pub struct TxCost { /// Max gas units to pay per transaction pub max_gas_unit_for_tx: u64, // gas UNITS of computation diff --git a/ol/types/src/fixtures.rs b/ol/types/src/fixtures.rs index 5cd9762529..f4e53ba227 100644 --- a/ol/types/src/fixtures.rs +++ b/ol/types/src/fixtures.rs @@ -74,7 +74,7 @@ pub fn get_persona_toml_configs(persona: &str) -> AppCfg { .parent() .unwrap() .join("fixtures/configs").join(format!("{}.toml", persona)); - parse_toml(buf.to_str().unwrap().to_owned()).expect("could not parse app config from file") + parse_toml(buf).expect("could not get fixtures for persona") }