Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 18 additions & 11 deletions crates/cardano/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

use crate::{
pallas_extras::{
default_cost_models, default_drep_voting_thresholds, default_ex_unit_prices,
self, default_cost_models, default_drep_voting_thresholds, default_ex_unit_prices,
default_ex_units, default_nonce, default_pool_voting_thresholds, default_rational_number,
},
roll::{
Expand All @@ -36,7 +36,7 @@
epochs::{EpochStatsUpdate, NoncesUpdate, PParamsUpdate},
pools::{MintedBlocksInc, PoolRegistration, PoolRetirement},
},
ChainSummary,

Check warning on line 39 in crates/cardano/src/model.rs

View workflow job for this annotation

GitHub Actions / Check Build

unused import: `ChainSummary`
};

pub trait FixedNamespace {
Expand Down Expand Up @@ -112,7 +112,10 @@
pub active_pool: Option<Vec<u8>>,

#[n(10)]
pub drep: Option<DRep>,
pub latest_drep: Option<DRep>,

#[n(11)]
pub active_drep: Option<DRep>,
}

entity_boilerplate!(AccountState, "accounts");
Expand Down Expand Up @@ -611,6 +614,7 @@
ensure_pparam!(tau, RationalNumber);
ensure_pparam!(k, u32);
ensure_pparam!(a0, RationalNumber);
ensure_pparam!(drep_inactivity_period, u64);

ensure_pparam!(protocol_version, ProtocolVersion);

Expand Down Expand Up @@ -773,6 +777,18 @@
pub const EPOCH_KEY_SET: &[u8] = b"1";
pub const EPOCH_KEY_MARK: &[u8] = b"0";

pub fn drep_to_entity_key(value: DRep) -> EntityKey {
let bytes = match value {
DRep::Key(key) => [vec![pallas_extras::DREP_KEY_PREFIX], key.to_vec()].concat(),
DRep::Script(key) => [vec![pallas_extras::DREP_SCRIPT_PREFIX], key.to_vec()].concat(),
// Invented keys for convenience
DRep::Abstain => vec![0],
DRep::NoConfidence => vec![1],
};

EntityKey::from(bytes)
}

#[derive(Debug, Encode, Decode, Clone, Default)]
pub struct DRepState {
#[n(0)]
Expand All @@ -797,15 +813,6 @@
let first = self.drep_id.first().unwrap();
first & 0b00001111 == 0b00000011
}

pub fn retiring_epoch(
&self,
summary: &ChainSummary,
drep_inactivity_period: u64,
) -> Option<u32> {
self.last_active_slot
.map(|x| summary.slot_epoch(x).0 + drep_inactivity_period as u32)
}
}

entity_boilerplate!(DRepState, "dreps");
Expand Down
10 changes: 10 additions & 0 deletions crates/cardano/src/pallas_extras.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,3 +268,13 @@ pub fn default_cost_models() -> CostModels {
unknown: Default::default(),
}
}

pub const DREP_KEY_PREFIX: u8 = 0b00100010;
pub const DREP_SCRIPT_PREFIX: u8 = 0b00100011;

pub fn stake_cred_to_drep(cred: &StakeCredential) -> DRep {
match cred {
StakeCredential::AddrKeyhash(key) => DRep::Key(*key),
StakeCredential::ScriptHash(key) => DRep::Script(*key),
}
}
12 changes: 6 additions & 6 deletions crates/cardano/src/roll/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,14 +196,14 @@ impl dolos_core::EntityDelta for VoteDelegation {
let entity = entity.get_or_insert_default();

// save undo info
self.prev_drep_id = entity.drep.clone();
self.prev_drep_id = entity.latest_drep.clone();

entity.drep = Some(self.drep.clone());
entity.latest_drep = Some(self.drep.clone());
}

fn undo(&self, entity: &mut Option<AccountState>) {
let entity = entity.get_or_insert_default();
entity.drep = self.prev_drep_id.clone();
entity.latest_drep = self.prev_drep_id.clone();
}
}

Expand Down Expand Up @@ -244,18 +244,18 @@ impl dolos_core::EntityDelta for StakeDeregistration {
// save undo info
self.prev_registered_at = entity.registered_at;
self.prev_pool_id = entity.latest_pool.clone();
self.prev_drep = entity.drep.clone();
self.prev_drep = entity.latest_drep.clone();

entity.registered_at = None;
entity.latest_pool = None;
entity.drep = None;
entity.latest_drep = None;
}

fn undo(&self, entity: &mut Option<AccountState>) {
let entity = entity.get_or_insert_default();
entity.registered_at = self.prev_registered_at;
entity.latest_pool = self.prev_pool_id.clone();
entity.drep = self.prev_drep.clone();
entity.latest_drep = self.prev_drep.clone();
}
}

Expand Down
107 changes: 45 additions & 62 deletions crates/cardano/src/roll/dreps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,25 @@ use std::ops::Deref as _;

use dolos_core::{batch::WorkDeltas, ChainError, NsKey};
use pallas::ledger::{
primitives::{
conway::{self, Anchor},
StakeCredential,
},
primitives::conway::{self, Anchor, DRep},
traverse::{MultiEraBlock, MultiEraCert, MultiEraTx},
};
use serde::{Deserialize, Serialize};

use crate::{model::DRepState, roll::BlockVisitor, CardanoLogic, FixedNamespace as _};

const DREP_KEY_PREFIX: u8 = 0b00100010;
const DREP_SCRIPT_PREFIX: u8 = 0b00100011;

fn cred_to_id(cred: &StakeCredential) -> Vec<u8> {
match cred {
StakeCredential::AddrKeyhash(key) => [vec![DREP_KEY_PREFIX], key.to_vec()].concat(),
StakeCredential::ScriptHash(key) => [vec![DREP_SCRIPT_PREFIX], key.to_vec()].concat(),
}
}

fn drep_to_id(drep: &conway::DRep) -> Vec<u8> {
match drep {
conway::DRep::Key(key) => [vec![DREP_KEY_PREFIX], key.to_vec()].concat(),
conway::DRep::Script(key) => [vec![DREP_SCRIPT_PREFIX], key.to_vec()].concat(),
// Invented keys for convenience
conway::DRep::Abstain => vec![0],
conway::DRep::NoConfidence => vec![1],
}
}
use crate::{
drep_to_entity_key, model::DRepState, pallas_extras::stake_cred_to_drep, roll::BlockVisitor,
CardanoLogic, FixedNamespace as _,
};

fn cert_to_id(cert: &MultiEraCert) -> Option<Vec<u8>> {
fn cert_drep(cert: &MultiEraCert) -> Option<DRep> {
match &cert {
MultiEraCert::Conway(conway) => match conway.deref().deref() {
conway::Certificate::RegDRepCert(cert, _, _) => Some(cred_to_id(cert)),
conway::Certificate::UnRegDRepCert(cert, _) => Some(cred_to_id(cert)),
conway::Certificate::UpdateDRepCert(cert, _) => Some(cred_to_id(cert)),
conway::Certificate::StakeVoteDeleg(_, _, drep) => Some(drep_to_id(drep)),
conway::Certificate::VoteRegDeleg(_, drep, _) => Some(drep_to_id(drep)),
conway::Certificate::VoteDeleg(_, drep) => Some(drep_to_id(drep)),
conway::Certificate::RegDRepCert(cert, _, _) => Some(stake_cred_to_drep(cert)),
conway::Certificate::UnRegDRepCert(cert, _) => Some(stake_cred_to_drep(cert)),
conway::Certificate::UpdateDRepCert(cert, _) => Some(stake_cred_to_drep(cert)),
conway::Certificate::StakeVoteDeleg(_, _, drep) => Some(drep.clone()),
conway::Certificate::VoteRegDeleg(_, drep, _) => Some(drep.clone()),
conway::Certificate::VoteDeleg(_, drep) => Some(drep.clone()),
_ => None,
},
_ => None,
Expand All @@ -49,7 +29,7 @@ fn cert_to_id(cert: &MultiEraCert) -> Option<Vec<u8>> {

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DRepRegistration {
drep_id: Vec<u8>,
drep: DRep,
slot: u64,
deposit: u64,
anchor: Option<Anchor>,
Expand All @@ -59,9 +39,9 @@ pub struct DRepRegistration {
}

impl DRepRegistration {
pub fn new(drep_id: Vec<u8>, slot: u64, deposit: u64, anchor: Option<Anchor>) -> Self {
pub fn new(drep: DRep, slot: u64, deposit: u64, anchor: Option<Anchor>) -> Self {
Self {
drep_id,
drep,
slot,
deposit,
anchor,
Expand All @@ -74,7 +54,7 @@ impl dolos_core::EntityDelta for DRepRegistration {
type Entity = DRepState;

fn key(&self) -> NsKey {
NsKey::from((DRepState::NS, self.drep_id.clone()))
NsKey::from((DRepState::NS, drep_to_entity_key(self.drep.clone())))
}

fn apply(&mut self, entity: &mut Option<DRepState>) {
Expand All @@ -99,17 +79,17 @@ impl dolos_core::EntityDelta for DRepRegistration {

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DRepUnRegistration {
drep_id: Vec<u8>,
drep: DRep,
deposit: u64,

// undo data
prev_voting_power: Option<u64>,
}

impl DRepUnRegistration {
pub fn new(drep_id: Vec<u8>, deposit: u64) -> Self {
pub fn new(drep: DRep, deposit: u64) -> Self {
Self {
drep_id,
drep,
deposit,
prev_voting_power: None,
}
Expand All @@ -120,7 +100,7 @@ impl dolos_core::EntityDelta for DRepUnRegistration {
type Entity = DRepState;

fn key(&self) -> NsKey {
NsKey::from((DRepState::NS, self.drep_id.clone()))
NsKey::from((DRepState::NS, drep_to_entity_key(self.drep.clone())))
}

fn apply(&mut self, entity: &mut Option<DRepState>) {
Expand All @@ -143,15 +123,15 @@ impl dolos_core::EntityDelta for DRepUnRegistration {

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DRepActivity {
drep_id: Vec<u8>,
drep: DRep,
slot: u64,
previous_last_active_slot: Option<u64>,
}

impl DRepActivity {
pub fn new(drep_id: Vec<u8>, slot: u64) -> Self {
pub fn new(drep: DRep, slot: u64) -> Self {
Self {
drep_id,
drep,
slot,
previous_last_active_slot: None,
}
Expand All @@ -162,7 +142,7 @@ impl dolos_core::EntityDelta for DRepActivity {
type Entity = DRepState;

fn key(&self) -> NsKey {
NsKey::from((DRepState::NS, self.drep_id.clone()))
NsKey::from((DRepState::NS, drep_to_entity_key(self.drep.clone())))
}

fn apply(&mut self, entity: &mut Option<DRepState>) {
Expand Down Expand Up @@ -192,25 +172,28 @@ impl BlockVisitor for DRepStateVisitor {
_: &MultiEraTx,
cert: &MultiEraCert,
) -> Result<(), ChainError> {
if let Some(drep_id) = cert_to_id(cert) {
deltas.add_for_entity(DRepActivity::new(drep_id.clone(), block.slot()));
if let MultiEraCert::Conway(conway) = &cert {
match conway.deref().deref() {
conway::Certificate::RegDRepCert(_, deposit, anchor) => {
deltas.add_for_entity(DRepRegistration::new(
drep_id.clone(),
block.slot(),
*deposit,
anchor.clone(),
));
}
conway::Certificate::UnRegDRepCert(_, coin) => {
deltas.add_for_entity(DRepUnRegistration::new(drep_id.clone(), *coin));
}
_ => (),
let Some(drep) = cert_drep(cert) else {
return Ok(());
};

deltas.add_for_entity(DRepActivity::new(drep.clone(), block.slot()));

if let MultiEraCert::Conway(conway) = &cert {
match conway.deref().deref() {
conway::Certificate::RegDRepCert(_, deposit, anchor) => {
deltas.add_for_entity(DRepRegistration::new(
drep.clone(),
block.slot(),
*deposit,
anchor.clone(),
));
}
};
}
conway::Certificate::UnRegDRepCert(_, coin) => {
deltas.add_for_entity(DRepUnRegistration::new(drep.clone(), *coin));
}
_ => (),
}
};

Ok(())
}
Expand Down
38 changes: 36 additions & 2 deletions crates/cardano/src/sweep/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,53 @@ impl BoundaryWork {
for record in accounts {
let (key, mut state) = record?;

if self.dropped_delegators.contains(&key) {
// clear pool if dropped
if self.dropped_pool_delegators.contains(&key) {
state.latest_pool = None;
}

// rotate pool
state.active_pool = state.latest_pool.clone();

// rotate stake
state.active_stake = state.wait_stake;
state.wait_stake = state.live_stake();

// add rewards
let rewards = self.delegator_rewards.get(&key).unwrap_or(&0);
state.rewards_sum += rewards;

state.active_pool = state.latest_pool.clone();
// clear drep if dropped
if self.dropped_drep_delegators.contains(&key) {
state.latest_drep = None;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

// rotate drep
state.active_drep = state.latest_drep.clone();

writer.write_entity_typed::<AccountState>(&key, &state)?;
}

Ok(())
}

fn update_drep_data<W: StateWriter>(
&self,
writer: &W,
dreps: impl Iterator<Item = Result<(EntityKey, crate::DRepState), StateError>>,
) -> Result<(), ChainError> {
for record in dreps {
let (key, mut state) = record?;

if self.retired_dreps.contains(&key) {
state.retired = true;
writer.write_entity_typed::<crate::DRepState>(&key, &state)?;
}
}

Ok(())
}

fn drop_active_epoch<W: StateWriter>(&self, writer: &W) -> Result<(), ChainError> {
writer.delete_entity(EpochState::NS, &EntityKey::from(EPOCH_KEY_GO))?;

Expand Down Expand Up @@ -138,10 +167,15 @@ impl BoundaryWork {
.state()
.iter_entities_typed::<PoolState>(PoolState::NS, None)?;

let dreps = domain
.state()
.iter_entities_typed::<crate::DRepState>(crate::DRepState::NS, None)?;

let writer = domain.state().start_writer()?;

self.rotate_pool_stake_data(&writer, pools)?;
self.rotate_account_stake_data(&writer, accounts)?;
self.update_drep_data(&writer, dreps)?;
self.drop_active_epoch(&writer)?;
self.promote_waiting_epoch(&writer)?;
self.promote_ending_epoch(&writer)?;
Expand Down
Loading
Loading