Skip to content

Commit

Permalink
delegator bid optimization
Browse files Browse the repository at this point in the history
  • Loading branch information
EdHastingsCasperAssociation committed Jun 24, 2024
1 parent 27e0661 commit 679e927
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 43 deletions.
7 changes: 3 additions & 4 deletions storage/src/system/auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,6 @@ pub trait Auction:
// Compute next auction winners
let winners: ValidatorWeights = {
let locked_validators = validator_bids_detail.validator_weights(
self,
era_id,
era_end_timestamp_millis,
vesting_schedule_period_millis,
Expand All @@ -585,7 +584,6 @@ pub trait Auction:
let remaining_auction_slots = validator_slots.saturating_sub(locked_validators.len());
if remaining_auction_slots > 0 {
let unlocked_validators = validator_bids_detail.validator_weights(
self,
era_id,
era_end_timestamp_millis,
vesting_schedule_period_millis,
Expand Down Expand Up @@ -613,7 +611,8 @@ pub trait Auction:
}
};

let (validator_bids, validator_credits) = validator_bids_detail.destructure();
let (validator_bids, validator_credits, delegator_bids) =
validator_bids_detail.destructure();

// call prune BEFORE incrementing the era
detail::prune_validator_credits(self, era_id, &validator_credits);
Expand All @@ -628,7 +627,7 @@ pub trait Auction:
// Update seigniorage recipients for current era
{
let mut snapshot = detail::get_seigniorage_recipients_snapshot(self)?;
let recipients = seigniorage_recipients(self, &winners, &validator_bids)?;
let recipients = seigniorage_recipients(&winners, &validator_bids, &delegator_bids)?;
let previous_recipients = snapshot.insert(delayed_era, recipients);
assert!(previous_recipients.is_none());

Expand Down
100 changes: 61 additions & 39 deletions storage/src/system/auction/detail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ use casper_types::{
account::AccountHash,
bytesrepr::{FromBytes, ToBytes},
system::auction::{
BidAddr, BidKind, Delegator, Error, SeigniorageAllocation, SeigniorageRecipient,
SeigniorageRecipients, SeigniorageRecipientsSnapshot, UnbondingPurse, UnbondingPurses,
ValidatorBid, ValidatorBids, ValidatorCredit, ValidatorCredits, AUCTION_DELAY_KEY,
ERA_END_TIMESTAMP_MILLIS_KEY, ERA_ID_KEY, SEIGNIORAGE_RECIPIENTS_SNAPSHOT_KEY,
UNBONDING_DELAY_KEY, VALIDATOR_SLOTS_KEY,
BidAddr, BidKind, Delegator, DelegatorBids, Error, SeigniorageAllocation,
SeigniorageRecipient, SeigniorageRecipients, SeigniorageRecipientsSnapshot, UnbondingPurse,
UnbondingPurses, ValidatorBid, ValidatorBids, ValidatorCredit, ValidatorCredits,
AUCTION_DELAY_KEY, ERA_END_TIMESTAMP_MILLIS_KEY, ERA_ID_KEY,
SEIGNIORAGE_RECIPIENTS_SNAPSHOT_KEY, UNBONDING_DELAY_KEY, VALIDATOR_SLOTS_KEY,
},
ApiError, CLTyped, EraId, Key, KeyTag, PublicKey, URef, U512,
};
Expand Down Expand Up @@ -59,13 +59,15 @@ where
pub struct ValidatorBidsDetail {
validator_bids: ValidatorBids,
validator_credits: ValidatorCredits,
delegator_bids: DelegatorBids,
}

impl ValidatorBidsDetail {
pub fn new() -> Self {
ValidatorBidsDetail {
validator_bids: BTreeMap::new(),
validator_credits: BTreeMap::new(),
delegator_bids: BTreeMap::new(),
}
}

Expand All @@ -74,7 +76,9 @@ impl ValidatorBidsDetail {
&mut self,
validator: PublicKey,
validator_bid: Box<ValidatorBid>,
delegators: Vec<Box<Delegator>>,
) -> Option<Box<ValidatorBid>> {
self.delegator_bids.insert(validator.clone(), delegators);
self.validator_bids.insert(validator, validator_bid)
}

Expand Down Expand Up @@ -110,19 +114,15 @@ impl ValidatorBidsDetail {

/// Get validator weights.
#[allow(clippy::too_many_arguments)]
pub fn validator_weights<P>(
pub fn validator_weights(
&mut self,
provider: &mut P,
era_ending: EraId,
era_end_timestamp_millis: u64,
vesting_schedule_period_millis: u64,
locked: bool,
include_credits: bool,
cap: Ratio<U512>,
) -> Result<ValidatorWeights, Error>
where
P: RuntimeProvider + ?Sized + StorageProvider,
{
) -> Result<ValidatorWeights, Error> {
let mut ret = BTreeMap::new();

for (validator_public_key, bid) in self.validator_bids.iter().filter(|(_, v)| {
Expand All @@ -133,7 +133,13 @@ impl ValidatorBidsDetail {
)
&& !v.inactive()
}) {
let staked_amount = total_staked_amount(provider, bid)?;
let mut staked_amount = bid.staked_amount();
if let Some(delegators) = self.delegator_bids.get(validator_public_key) {
staked_amount = staked_amount
.checked_add(delegators.iter().map(|d| d.staked_amount()).sum())
.ok_or(Error::InvalidAmount)?;
}

let credit_amount = self.credit_amount(
validator_public_key,
era_ending,
Expand Down Expand Up @@ -182,8 +188,12 @@ impl ValidatorBidsDetail {
}

/// Consume self into in underlying collections.
pub fn destructure(self) -> (ValidatorBids, ValidatorCredits) {
(self.validator_bids, self.validator_credits)
pub fn destructure(self) -> (ValidatorBids, ValidatorCredits, DelegatorBids) {
(
self.validator_bids,
self.validator_credits,
self.delegator_bids,
)
}
}

Expand Down Expand Up @@ -215,7 +225,9 @@ where
for key in bids_keys {
match provider.read_bid(&key)? {
Some(BidKind::Validator(validator_bid)) => {
ret.insert_bid(validator_bid.validator_public_key().clone(), validator_bid);
let validator_public_key = validator_bid.validator_public_key();
let delegator_bids = delegators(provider, validator_public_key)?;
ret.insert_bid(validator_public_key.clone(), validator_bid, delegator_bids);
}
Some(BidKind::Credit(credit)) => {
ret.insert_credit(credit.validator_public_key().clone(), era_id, credit);
Expand Down Expand Up @@ -896,14 +908,11 @@ where
}
}

pub fn seigniorage_recipients<P>(
provider: &mut P,
pub fn seigniorage_recipients(
validator_weights: &ValidatorWeights,
validator_bids: &ValidatorBids,
) -> Result<SeigniorageRecipients, Error>
where
P: RuntimeProvider + ?Sized + StorageProvider,
{
delegator_bids: &DelegatorBids,
) -> Result<SeigniorageRecipients, Error> {
let mut recipients = SeigniorageRecipients::new();
for (validator_public_key, validator_total_weight) in validator_weights {
// check if validator bid exists before processing.
Expand All @@ -913,18 +922,32 @@ where
// calculate delegator portion(s), if any
let mut delegators_weight = U512::zero();
let mut delegators_stake: BTreeMap<PublicKey, U512> = BTreeMap::new();
for delegator_bid in read_delegator_bids(provider, validator_public_key)? {
if delegator_bid.staked_amount().is_zero() {
continue;
if let Some(delegators) = delegator_bids.get(validator_public_key) {
for delegator_bid in delegators {
if delegator_bid.staked_amount().is_zero() {
continue;
}
let delegator_staked_amount = delegator_bid.staked_amount();
delegators_weight = delegators_weight.saturating_add(delegator_staked_amount);
delegators_stake.insert(
delegator_bid.delegator_public_key().clone(),
delegator_staked_amount,
);
}
let delegator_staked_amount = delegator_bid.staked_amount();
delegators_weight = delegators_weight.saturating_add(delegator_staked_amount);
delegators_stake.insert(
delegator_bid.delegator_public_key().clone(),
delegator_staked_amount,
);
}

// for delegator_bid in read_delegator_bids(provider, validator_public_key)? {
// if delegator_bid.staked_amount().is_zero() {
// continue;
// }
// let delegator_staked_amount = delegator_bid.staked_amount();
// delegators_weight = delegators_weight.saturating_add(delegator_staked_amount);
// delegators_stake.insert(
// delegator_bid.delegator_public_key().clone(),
// delegator_staked_amount,
// );
// }

// determine validator's personal stake (total weight - sum of delegators weight)
let validator_stake = validator_total_weight.saturating_sub(delegators_weight);
let seigniorage_recipient = SeigniorageRecipient::new(
Expand Down Expand Up @@ -1007,26 +1030,25 @@ where
}
}

/// Returns the total staked amount of validator + all delegators
pub fn total_staked_amount<P>(provider: &mut P, validator_bid: &ValidatorBid) -> Result<U512, Error>
pub fn delegators<P>(
provider: &mut P,
validator_public_key: &PublicKey,
) -> Result<Vec<Box<Delegator>>, Error>
where
P: RuntimeProvider + ?Sized + StorageProvider,
{
let bid_addr = BidAddr::from(validator_bid.validator_public_key().clone());
let mut ret = vec![];
let bid_addr = BidAddr::from(validator_public_key.clone());
let delegator_bid_keys = provider.get_keys_by_prefix(
&bid_addr
.delegators_prefix()
.map_err(|_| Error::Serialization)?,
)?;

let mut sum = U512::zero();

for delegator_bid_key in delegator_bid_keys {
let delegator = read_delegator_bid(provider, &delegator_bid_key)?;
let staked_amount = delegator.staked_amount();
sum += staked_amount;
ret.push(delegator);
}

sum.checked_add(validator_bid.staked_amount())
.ok_or(Error::InvalidAmount)
Ok(ret)
}
3 changes: 3 additions & 0 deletions types/src/system/auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ pub type DelegationRate = u8;
/// Validators mapped to their bids.
pub type ValidatorBids = BTreeMap<PublicKey, Box<ValidatorBid>>;

/// Delegator bids mapped to their validator.
pub type DelegatorBids = BTreeMap<PublicKey, Vec<Box<Delegator>>>;

/// Validators mapped to their credits by era.
pub type ValidatorCredits = BTreeMap<PublicKey, BTreeMap<EraId, Box<ValidatorCredit>>>;

Expand Down

0 comments on commit 679e927

Please sign in to comment.