consensus: introduce staking coins initial distribution logic

This commit is contained in:
aggstam
2022-12-27 18:10:08 +02:00
parent 4ff042dde9
commit 267fb82e56
7 changed files with 91 additions and 50 deletions

View File

@@ -30,7 +30,8 @@ use darkfi::{
consensus::{
constants::{
MAINNET_BOOTSTRAP_TIMESTAMP, MAINNET_GENESIS_HASH_BYTES, MAINNET_GENESIS_TIMESTAMP,
TESTNET_BOOTSTRAP_TIMESTAMP, TESTNET_GENESIS_HASH_BYTES, TESTNET_GENESIS_TIMESTAMP,
MAINNET_INITIAL_DISTRIBUTION, TESTNET_BOOTSTRAP_TIMESTAMP, TESTNET_GENESIS_HASH_BYTES,
TESTNET_GENESIS_TIMESTAMP, TESTNET_INITIAL_DISTRIBUTION,
},
proto::{ProtocolProposal, ProtocolSync, ProtocolSyncConsensus, ProtocolTx},
task::{block_sync_task, proposal_task},
@@ -298,13 +299,19 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'_>>) -> Result<()> {
let sled_db = sled::open(&db_path)?;
// Initialize validator state
let (bootstrap_ts, genesis_ts, genesis_data) = match args.chain.as_str() {
"mainnet" => {
(*MAINNET_BOOTSTRAP_TIMESTAMP, *MAINNET_GENESIS_TIMESTAMP, *MAINNET_GENESIS_HASH_BYTES)
}
"testnet" => {
(*TESTNET_BOOTSTRAP_TIMESTAMP, *TESTNET_GENESIS_TIMESTAMP, *TESTNET_GENESIS_HASH_BYTES)
}
let (bootstrap_ts, genesis_ts, genesis_data, initial_distribution) = match args.chain.as_str() {
"mainnet" => (
*MAINNET_BOOTSTRAP_TIMESTAMP,
*MAINNET_GENESIS_TIMESTAMP,
*MAINNET_GENESIS_HASH_BYTES,
*MAINNET_INITIAL_DISTRIBUTION,
),
"testnet" => (
*TESTNET_BOOTSTRAP_TIMESTAMP,
*TESTNET_GENESIS_TIMESTAMP,
*TESTNET_GENESIS_HASH_BYTES,
*TESTNET_INITIAL_DISTRIBUTION,
),
x => {
error!("Unsupported chain `{}`", x);
return Err(Error::UnsupportedChain)
@@ -330,6 +337,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'_>>) -> Result<()> {
bootstrap_ts,
genesis_ts,
genesis_data,
initial_distribution,
wallet.clone(),
faucet_pubkeys,
args.consensus,

View File

@@ -56,7 +56,8 @@ use darkfi::{
consensus::{
constants::{
MAINNET_BOOTSTRAP_TIMESTAMP, MAINNET_GENESIS_HASH_BYTES, MAINNET_GENESIS_TIMESTAMP,
TESTNET_BOOTSTRAP_TIMESTAMP, TESTNET_GENESIS_HASH_BYTES, TESTNET_GENESIS_TIMESTAMP,
MAINNET_INITIAL_DISTRIBUTION, TESTNET_BOOTSTRAP_TIMESTAMP, TESTNET_GENESIS_HASH_BYTES,
TESTNET_GENESIS_TIMESTAMP, TESTNET_INITIAL_DISTRIBUTION,
},
proto::{ProtocolSync, ProtocolTx},
task::block_sync_task,
@@ -528,13 +529,19 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'_>>) -> Result<()> {
let sled_db = sled::open(&db_path)?;
// Initialize validator state
let (bootstrap_ts, genesis_ts, genesis_data) = match args.chain.as_str() {
"mainnet" => {
(*MAINNET_BOOTSTRAP_TIMESTAMP, *MAINNET_GENESIS_TIMESTAMP, *MAINNET_GENESIS_HASH_BYTES)
}
"testnet" => {
(*TESTNET_BOOTSTRAP_TIMESTAMP, *TESTNET_GENESIS_TIMESTAMP, *TESTNET_GENESIS_HASH_BYTES)
}
let (bootstrap_ts, genesis_ts, genesis_data, initial_distribution) = match args.chain.as_str() {
"mainnet" => (
*MAINNET_BOOTSTRAP_TIMESTAMP,
*MAINNET_GENESIS_TIMESTAMP,
*MAINNET_GENESIS_HASH_BYTES,
*MAINNET_INITIAL_DISTRIBUTION,
),
"testnet" => (
*TESTNET_BOOTSTRAP_TIMESTAMP,
*TESTNET_GENESIS_TIMESTAMP,
*TESTNET_GENESIS_HASH_BYTES,
*TESTNET_INITIAL_DISTRIBUTION,
),
x => {
error!("Unsupported chain `{}`", x);
return Err(Error::UnsupportedChain)
@@ -560,6 +567,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'_>>) -> Result<()> {
bootstrap_ts,
genesis_ts,
genesis_data,
initial_distribution,
wallet.clone(),
faucet_pubkeys,
false,

View File

@@ -32,6 +32,9 @@ lazy_static! {
/// Bootstrap timestamp for the mainnet chain
pub static ref MAINNET_BOOTSTRAP_TIMESTAMP: Timestamp = Timestamp(1650887115);
/// Total sum of initial staking coins for the mainnet chain
pub static ref MAINNET_INITIAL_DISTRIBUTION: u64 = 1000;
/// Genesis hash for the testnet chain
pub static ref TESTNET_GENESIS_HASH_BYTES: blake3::Hash = blake3::hash(b"darkfi_testnet");
@@ -41,22 +44,25 @@ lazy_static! {
/// Bootstrap timestamp for the testnet chain
pub static ref TESTNET_BOOTSTRAP_TIMESTAMP: Timestamp = Timestamp(1671546600);
/// Total sum of initial staking coins for the testnet chain
pub static ref TESTNET_INITIAL_DISTRIBUTION: u64 = 1000;
// Commonly used Float10
pub static ref FLOAT10_ZERO: Float10 = Float10::from_str_native("0").unwrap().with_precision(RADIX_BITS).value();
pub static ref FLOAT10_ONE: Float10 = Float10::from_str_native("1").unwrap().with_precision(RADIX_BITS).value();
pub static ref FLOAT10_TWO: Float10 = Float10::from_str_native("2").unwrap().with_precision(RADIX_BITS).value();
pub static ref FLOAT10_THREE: Float10 = Float10::from_str_native("3").unwrap().with_precision(RADIX_BITS).value();
pub static ref FLOAT10_FIVE: Float10 = Float10::from_str_native("5").unwrap().with_precision(RADIX_BITS).value();
pub static ref FLOAT10_NINE: Float10 = Float10::from_str_native("9").unwrap().with_precision(RADIX_BITS).value();
pub static ref FLOAT10_TEN: Float10 = Float10::from_str_native("10").unwrap().with_precision(RADIX_BITS).value();
pub static ref FLOAT10_ZERO: Float10 = Float10::from_str_native("0").unwrap().with_precision(RADIX_BITS).value();
pub static ref FLOAT10_ONE: Float10 = Float10::from_str_native("1").unwrap().with_precision(RADIX_BITS).value();
pub static ref FLOAT10_TWO: Float10 = Float10::from_str_native("2").unwrap().with_precision(RADIX_BITS).value();
pub static ref FLOAT10_THREE: Float10 = Float10::from_str_native("3").unwrap().with_precision(RADIX_BITS).value();
pub static ref FLOAT10_FIVE: Float10 = Float10::from_str_native("5").unwrap().with_precision(RADIX_BITS).value();
pub static ref FLOAT10_NINE: Float10 = Float10::from_str_native("9").unwrap().with_precision(RADIX_BITS).value();
pub static ref FLOAT10_TEN: Float10 = Float10::from_str_native("10").unwrap().with_precision(RADIX_BITS).value();
// Consensus parameters
pub static ref DT: Float10 = Float10::from_str_native("0.1").unwrap().with_precision(RADIX_BITS).value();
pub static ref TI: Float10 = FLOAT10_ONE.clone();
pub static ref TD: Float10 = FLOAT10_ONE.clone();
pub static ref KP: Float10 = Float10::from_str_native("0.1").unwrap().with_precision(RADIX_BITS).value();
pub static ref KI: Float10 = Float10::from_str_native("0.03").unwrap().with_precision(RADIX_BITS).value();
pub static ref KD: Float10 = FLOAT10_ONE.clone();
pub static ref DT: Float10 = Float10::from_str_native("0.1").unwrap().with_precision(RADIX_BITS).value();
pub static ref TI: Float10 = FLOAT10_ONE.clone();
pub static ref TD: Float10 = FLOAT10_ONE.clone();
pub static ref KP: Float10 = Float10::from_str_native("0.1").unwrap().with_precision(RADIX_BITS).value();
pub static ref KI: Float10 = Float10::from_str_native("0.03").unwrap().with_precision(RADIX_BITS).value();
pub static ref KD: Float10 = FLOAT10_ONE.clone();
pub static ref PID_OUT_STEP: Float10 = Float10::from_str_native("0.1").unwrap().with_precision(RADIX_BITS).value();
pub static ref MAX_DER: Float10 = Float10::from_str_native("0.1").unwrap().with_precision(RADIX_BITS).value();
pub static ref MIN_DER: Float10 = Float10::from_str_native("-0.1").unwrap().with_precision(RADIX_BITS).value();
@@ -113,4 +119,4 @@ pub const PI_MU_Y_INDEX: usize = 8;
pub const PI_MU_RHO_INDEX: usize = 10;
pub const PI_SIGMA1_INDEX: usize = 12;
pub const PI_SIGMA2_INDEX: usize = 13;
pub const GENESIS_TOTAL_STAKE: i64 = 1;
pub const GENESIS_TOTAL_STAKE: u64 = 1;

View File

@@ -48,6 +48,8 @@ pub struct ConsensusState {
pub genesis_ts: Timestamp,
/// Genesis block hash
pub genesis_block: blake3::Hash,
/// Total sum of initial staking coins
pub initial_distribution: u64,
/// Slot the network was bootstrapped
pub bootstrap_slot: u64,
/// Participating start slot
@@ -83,6 +85,7 @@ impl ConsensusState {
bootstrap_ts: Timestamp,
genesis_ts: Timestamp,
genesis_data: blake3::Hash,
initial_distribution: u64,
) -> Result<Self> {
let genesis_block = Block::genesis_block(genesis_ts, genesis_data).blockhash();
Ok(Self {
@@ -90,6 +93,7 @@ impl ConsensusState {
bootstrap_ts,
genesis_ts,
genesis_block,
initial_distribution,
bootstrap_slot: 0,
participating: None,
proposing: false,
@@ -229,18 +233,10 @@ impl ConsensusState {
Ok(true)
}
/// return 2-term target approximation sigma coefficients.
/// Return 2-term target approximation sigma coefficients.
pub fn sigmas(&mut self) -> (pallas::Base, pallas::Base) {
let f = self.win_inv_prob_with_full_stake();
// Generate sigmas
let mut total_stake = self.total_stake(); // Only used for fine-tuning
// at genesis epoch first slot, of absolute index 0,
// the total stake would be 0, to avoid division by zero,
// we asume total stake at first division is GENESIS_TOTAL_STAKE.
if total_stake == 0 {
total_stake = constants::GENESIS_TOTAL_STAKE;
}
let total_stake = self.total_stake();
info!("sigmas(): f: {}", f);
info!("sigmas(): stake: {}", total_stake);
let one = constants::FLOAT10_ONE.clone();
@@ -284,10 +280,13 @@ impl ConsensusState {
// The wallet has specific tables for consensus coins.
// TODO: TESTNET: Token ID still has to be enforced properly in the consensus.
// Temporarily, we compete with zero stake
// Temporarily, we compete with fixed stake.
// This stake should be based on how many nodes we want to run, and they all
// must sum to initial distribution total coins.
let stake = self.initial_distribution;
let coin = LeadCoin::new(
eta,
rand::thread_rng().gen_range(0..1000),
stake,
slot,
epoch_secrets.secret_keys[0].inner(),
epoch_secrets.merkle_roots[0],
@@ -301,9 +300,9 @@ impl ConsensusState {
Ok(coins)
}
/// leadership reward, assuming constant reward
/// Leadership reward, assuming constant reward
/// TODO (res) implement reward mechanism with accord to DRK,DARK token-economics
fn reward() -> u64 {
fn reward(&self) -> u64 {
constants::REWARD
}
@@ -341,11 +340,19 @@ impl ConsensusState {
current_slot - blocks - self.get_current_offset(current_slot) - max_fork_length
}
/// total stake
/// assuming constant Reward.
fn total_stake(&mut self) -> i64 {
/// Network total stake, assuming constant reward.
/// Only used for fine-tuning. At genesis epoch first slot, of absolute index 0,
/// if no stake was distributed, the total stake would be 0.
/// To avoid division by zero, we asume total stake at first division is GENESIS_TOTAL_STAKE(1).
fn total_stake(&mut self) -> u64 {
let current_slot = self.current_slot();
((current_slot - self.overall_empty_slots(current_slot)) * Self::reward()) as i64
let rewarded_slots = current_slot - self.overall_empty_slots(current_slot);
let rewards = rewarded_slots * self.reward();
let total_stake = rewards + self.initial_distribution;
if total_stake == 0 {
return constants::GENESIS_TOTAL_STAKE
}
total_stake
}
/// Calculate how many leaders existed in previous slot and appends

View File

@@ -93,6 +93,7 @@ impl ValidatorState {
bootstrap_ts: Timestamp,
genesis_ts: Timestamp,
genesis_data: blake3::Hash,
initial_distribution: u64,
wallet: WalletPtr,
faucet_pubkeys: Vec<PublicKey>,
enable_participation: bool,
@@ -122,8 +123,13 @@ impl ValidatorState {
};
let blockchain = Blockchain::new(db, genesis_ts, genesis_data)?;
let consensus =
ConsensusState::new(blockchain.clone(), bootstrap_ts, genesis_ts, genesis_data)?;
let consensus = ConsensusState::new(
blockchain.clone(),
bootstrap_ts,
genesis_ts,
genesis_data,
initial_distribution,
)?;
let unconfirmed_txs = vec![];

View File

@@ -21,6 +21,7 @@ use darkfi::{
consensus::{
constants::{
TESTNET_BOOTSTRAP_TIMESTAMP, TESTNET_GENESIS_HASH_BYTES, TESTNET_GENESIS_TIMESTAMP,
TESTNET_INITIAL_DISTRIBUTION,
},
ValidatorState, ValidatorStatePtr,
},
@@ -86,6 +87,7 @@ impl DaoTestHarness {
*TESTNET_BOOTSTRAP_TIMESTAMP,
*TESTNET_GENESIS_TIMESTAMP,
*TESTNET_GENESIS_HASH_BYTES,
*TESTNET_INITIAL_DISTRIBUTION,
alice_wallet,
vec![],
false,

View File

@@ -21,6 +21,7 @@ use darkfi::{
consensus::{
constants::{
TESTNET_BOOTSTRAP_TIMESTAMP, TESTNET_GENESIS_HASH_BYTES, TESTNET_GENESIS_TIMESTAMP,
TESTNET_INITIAL_DISTRIBUTION,
},
ValidatorState, ValidatorStatePtr,
},
@@ -105,6 +106,7 @@ impl MoneyTestHarness {
*TESTNET_BOOTSTRAP_TIMESTAMP,
*TESTNET_GENESIS_TIMESTAMP,
*TESTNET_GENESIS_HASH_BYTES,
*TESTNET_INITIAL_DISTRIBUTION,
faucet_wallet,
faucet_pubkeys.clone(),
false,
@@ -116,6 +118,7 @@ impl MoneyTestHarness {
*TESTNET_BOOTSTRAP_TIMESTAMP,
*TESTNET_GENESIS_TIMESTAMP,
*TESTNET_GENESIS_HASH_BYTES,
*TESTNET_INITIAL_DISTRIBUTION,
alice_wallet,
faucet_pubkeys.clone(),
false,
@@ -127,6 +130,7 @@ impl MoneyTestHarness {
*TESTNET_BOOTSTRAP_TIMESTAMP,
*TESTNET_GENESIS_TIMESTAMP,
*TESTNET_GENESIS_HASH_BYTES,
*TESTNET_INITIAL_DISTRIBUTION,
bob_wallet,
faucet_pubkeys.clone(),
false,