diff --git a/framework/cached-packages/src/libra_framework_sdk_builder.rs b/framework/cached-packages/src/libra_framework_sdk_builder.rs index a3bae1d52..3c4909b23 100644 --- a/framework/cached-packages/src/libra_framework_sdk_builder.rs +++ b/framework/cached-packages/src/libra_framework_sdk_builder.rs @@ -474,6 +474,12 @@ pub enum EntryFunctionCall { epoch_expiry: u64, }, + /// update the bid using estimated net reward instead of the internal bid variables + ProofOfFeePofUpdateBidNetReward { + net_reward: u64, + epoch_expiry: u64, + }, + /// This function initiates governance for the multisig. It is called by the sponsor address, and is only callable once. /// init_gov fails gracefully if the governance is already initialized. /// init_type will throw errors if the type is already initialized. @@ -808,6 +814,10 @@ impl EntryFunctionCall { ProofOfFeePofUpdateBid { bid, epoch_expiry } => { proof_of_fee_pof_update_bid(bid, epoch_expiry) } + ProofOfFeePofUpdateBidNetReward { + net_reward, + epoch_expiry, + } => proof_of_fee_pof_update_bid_net_reward(net_reward, epoch_expiry), SafeInitPaymentMultisig { authorities } => safe_init_payment_multisig(authorities), SlowWalletSmokeTestVmUnlock { user_addr, @@ -2147,6 +2157,28 @@ pub fn proof_of_fee_pof_update_bid(bid: u64, epoch_expiry: u64) -> TransactionPa )) } +/// update the bid using estimated net reward instead of the internal bid variables +pub fn proof_of_fee_pof_update_bid_net_reward( + net_reward: u64, + epoch_expiry: u64, +) -> TransactionPayload { + TransactionPayload::EntryFunction(EntryFunction::new( + ModuleId::new( + AccountAddress::new([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, + ]), + ident_str!("proof_of_fee").to_owned(), + ), + ident_str!("pof_update_bid_net_reward").to_owned(), + vec![], + vec![ + bcs::to_bytes(&net_reward).unwrap(), + bcs::to_bytes(&epoch_expiry).unwrap(), + ], + )) +} + /// This function initiates governance for the multisig. It is called by the sponsor address, and is only callable once. /// init_gov fails gracefully if the governance is already initialized. /// init_type will throw errors if the type is already initialized. @@ -3105,6 +3137,19 @@ mod decoder { } } + pub fn proof_of_fee_pof_update_bid_net_reward( + payload: &TransactionPayload, + ) -> Option { + if let TransactionPayload::EntryFunction(script) = payload { + Some(EntryFunctionCall::ProofOfFeePofUpdateBidNetReward { + net_reward: bcs::from_bytes(script.args().first()?).ok()?, + epoch_expiry: bcs::from_bytes(script.args().get(1)?).ok()?, + }) + } else { + None + } + } + pub fn safe_init_payment_multisig(payload: &TransactionPayload) -> Option { if let TransactionPayload::EntryFunction(script) = payload { Some(EntryFunctionCall::SafeInitPaymentMultisig { @@ -3480,6 +3525,10 @@ static SCRIPT_FUNCTION_DECODER_MAP: once_cell::sync::Lazy 0, EWTF_WHY_IS_REWARD_ZERO); + assert!(net_reward < nominal_reward, ENET_REWARD_GREATER_THAN_REWARD); + + let pct_with_decimal = (net_reward * 10) / nominal_reward; + + return pct_with_decimal + } + + /// Instead of setting a bid with the internal variables of pct bid, we + /// allow the user to set their expected net_reward in an epoch + fun set_net_reward(account_sig: &signer, net_reward: u64, expiry_epoch: u64) acquires + ConsensusReward, ProofOfFeeAuction { + // double check the epoch expiry + let epoch_checked = check_epoch_expiry(expiry_epoch); + // convert to bid + let scaled_pct = convert_net_reward_to_bid(net_reward); + set_bid(account_sig, scaled_pct, epoch_checked); + } + + /// check if the expiry is too far in the future + /// and if so, return what the maximum allowed would be. + /// if within range returns the provided epoch without change + /// @returns checked epoch for bid expiration + fun check_epoch_expiry(expiry_epoch: u64): u64 { + let this_epoch = epoch_helper::get_current_epoch(); + if (expiry_epoch > MAXIMUM_BID_EXPIRATION_EPOCHS) { + return this_epoch + MAXIMUM_BID_EXPIRATION_EPOCHS + }; + expiry_epoch + } + /// Note that the validator will not be bidding on any future /// epochs if they retract their bid. The must set a new bid. fun retract_bid(account_sig: &signer) acquires ProofOfFeeAuction { @@ -770,6 +842,14 @@ module ol_framework::proof_of_fee { set_bid(sender, bid, epoch_expiry); } + /// update the bid using estimated net reward instead of the internal bid variables + public entry fun pof_update_bid_net_reward(sender: &signer, net_reward: u64, + epoch_expiry: u64) acquires ProofOfFeeAuction, ConsensusReward { + let checked_epoch = check_epoch_expiry(epoch_expiry); + // update the bid, initializes if not already. + set_net_reward(sender, net_reward, checked_epoch); + } + /// retract bid public entry fun pof_retract_bid(sender: signer) acquires ProofOfFeeAuction { // retract a bid diff --git a/framework/releases/head.mrb b/framework/releases/head.mrb index d0e20fa11..6bfd477db 100644 Binary files a/framework/releases/head.mrb and b/framework/releases/head.mrb differ diff --git a/tools/txs/src/txs_cli_vals.rs b/tools/txs/src/txs_cli_vals.rs index 6dbd3eef5..98d1ea749 100644 --- a/tools/txs/src/txs_cli_vals.rs +++ b/tools/txs/src/txs_cli_vals.rs @@ -6,8 +6,8 @@ use diem_genesis::config::OperatorConfiguration; use diem_types::account_address::AccountAddress; use libra_cached_packages::libra_stdlib::EntryFunctionCall::{ self, JailUnjailByVoucher, ProofOfFeePofRetractBid, ProofOfFeePofUpdateBid, - StakeUpdateNetworkAndFullnodeAddresses, ValidatorUniverseRegisterValidator, VouchRevoke, - VouchVouchFor, + ProofOfFeePofUpdateBidNetReward, StakeUpdateNetworkAndFullnodeAddresses, + ValidatorUniverseRegisterValidator, VouchRevoke, VouchVouchFor, }; use libra_config::validator_registration; use libra_types::global_config_dir; @@ -18,14 +18,17 @@ use std::{fs, path::PathBuf}; pub enum ValidatorTxs { /// Proof-of-Fee auction bidding Pof { + #[clap(short('r'), long)] + /// Estimated net reward you would like to receive each epoch + net_reward: u64, #[clap(short, long)] /// Percentage of the nominal reward you will bid to join the /// validator set, with three decimal places: 1.234 is 123.4% - bid_pct: f64, + bid_pct: Option, #[clap(short, long)] - /// Epoch until the bid is valid (will expire in `expiry` + 1) + /// Epoch until the bid is valid (will expire in `expiry` + 1). Max 30 epochs expiry: u64, - #[clap(short, long)] + #[clap(long)] /// Eliminates the bid. There are only a limited amount of retractions that can happen in an epoch retract: bool, }, @@ -69,15 +72,16 @@ impl ValidatorTxs { pub fn make_payload(&self) -> anyhow::Result { let p = match self { ValidatorTxs::Pof { + net_reward, bid_pct, - expiry: epoch_expiry, + expiry, retract, } => { if *retract { ProofOfFeePofRetractBid {} - } else { + } else if let Some(b) = bid_pct { // TODO: the u64 will truncate, but without rounding it will drop the last digit. - let scaled_bid = (bid_pct * 1000.0).round() as u64; // scale to 10ˆ3. + let scaled_bid = (b * 1000.0).round() as u64; // scale to 10ˆ3. if scaled_bid > 1100 { bail!( "a bid amount at 110.0% or above the epoch's reward, will be rejected" @@ -85,7 +89,13 @@ impl ValidatorTxs { } ProofOfFeePofUpdateBid { bid: scaled_bid, - epoch_expiry: *epoch_expiry, + epoch_expiry: *expiry, + } + } else { + // Default path is to update based on the expected net reward + ProofOfFeePofUpdateBidNetReward { + net_reward: *net_reward, + epoch_expiry: *expiry, } } }