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
42 changes: 24 additions & 18 deletions common/examples/test_streaming_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@
use acropolis_common::epoch_snapshot::SnapshotsContainer;
use acropolis_common::ledger_state::SPOState;
use acropolis_common::snapshot::protocol_parameters::ProtocolParameters;
use acropolis_common::snapshot::streaming_snapshot::GovernanceProtocolParametersCallback;
use acropolis_common::snapshot::streaming_snapshot::{
AccountsCallback, DRepCallback, DRepRecord, GovernanceProtocolParametersCallback, UtxoCallback,
UtxoEntry,
};
use acropolis_common::snapshot::EpochCallback;
use acropolis_common::snapshot::{
AccountState, AccountsCallback, DRepCallback, DRepInfo, GovernanceProposal, PoolCallback,
ProposalCallback, SnapshotCallbacks, SnapshotMetadata, SnapshotsCallback,
StreamingSnapshotParser, UtxoCallback, UtxoEntry,
AccountState, GovernanceProposal, PoolCallback, ProposalCallback, SnapshotCallbacks,
SnapshotMetadata, SnapshotsCallback, StreamingSnapshotParser,
};
use acropolis_common::{NetworkId, PoolRegistration};
use acropolis_common::{DRepCredential, NetworkId, PoolRegistration};
use anyhow::Result;
use std::collections::HashMap;
use std::env;
use std::time::Instant;
use tracing::info;
Expand All @@ -35,7 +38,7 @@ struct CountingCallbacks {
sample_utxos: Vec<UtxoEntry>,
sample_pools: Vec<PoolRegistration>,
sample_accounts: Vec<AccountState>,
sample_dreps: Vec<DRepInfo>,
sample_dreps: Vec<(DRepCredential, DRepRecord)>,
sample_proposals: Vec<GovernanceProposal>,
gs_previous_params: Option<ProtocolParameters>,
gs_current_params: Option<ProtocolParameters>,
Expand Down Expand Up @@ -137,26 +140,27 @@ impl AccountsCallback for CountingCallbacks {
}

impl DRepCallback for CountingCallbacks {
fn on_dreps(&mut self, dreps: Vec<DRepInfo>) -> Result<()> {
fn on_dreps(&mut self, epoch: u64, dreps: HashMap<DRepCredential, DRepRecord>) -> Result<()> {
self.drep_count = dreps.len();
eprintln!("Parsed {} DReps", self.drep_count);
eprintln!("Parsed {} DReps for epoch {}", self.drep_count, epoch);

// Show first 10 DReps
for (i, drep) in dreps.iter().take(10).enumerate() {
if let Some(anchor) = &drep.anchor {
for (i, (cred, record)) in dreps.iter().take(10).enumerate() {
let drep_id = cred.to_drep_bech32().unwrap_or_else(|_| "invalid_cred".to_string());
if let Some(anchor) = &record.anchor {
eprintln!(
" DRep #{}: {} (deposit: {}) - {}",
i + 1,
drep.drep_id.to_drep_bech32().unwrap(),
drep.deposit,
drep_id,
record.deposit,
anchor.url
);
} else {
eprintln!(
" DRep #{}: {} (deposit: {})",
i + 1,
drep.drep_id.to_drep_bech32().unwrap(),
drep.deposit
drep_id,
record.deposit
);
}
}
Expand Down Expand Up @@ -548,14 +552,16 @@ fn main() {
// Show sample DReps
if !callbacks.sample_dreps.is_empty() {
println!("Sample DReps (first 10):");
for (i, drep) in callbacks.sample_dreps.iter().enumerate() {
for (i, (cred, record)) in callbacks.sample_dreps.iter().enumerate() {
let drep_id =
cred.to_drep_bech32().unwrap_or_else(|_| "invalid_cred".to_string());
print!(
" {}: {} (deposit: {} lovelace)",
i + 1,
drep.drep_id.to_drep_bech32().unwrap(),
drep.deposit
drep_id,
record.deposit
);
if let Some(anchor) = &drep.anchor {
if let Some(anchor) = &record.anchor {
println!(" - {}", anchor.url);
} else {
println!();
Expand Down
138 changes: 138 additions & 0 deletions common/src/drep.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
//! DRep (Delegated Representative) types and structures

use crate::rational_number::RationalNumber;
use crate::types::{Credential, Lovelace};
use serde_with::{hex::Hex, serde_as};

pub type DRepCredential = Credential;

/// Anchor - verifiable link on-chain identifiers with off-chain content,
/// typically metadata that describes a DRep's identity, platform, or governance
/// philosophy.
#[serde_as]
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct Anchor {
/// Metadata URL
pub url: String,

/// Metadata hash
#[serde_as(as = "Hex")]
pub data_hash: Vec<u8>,
}

impl<'b, C> minicbor::Decode<'b, C> for Anchor {
fn decode(
d: &mut minicbor::Decoder<'b>,
_ctx: &mut C,
) -> Result<Self, minicbor::decode::Error> {
d.array()?;

// URL can be either bytes or text string (snapshot format uses bytes)
let url = match d.datatype()? {
minicbor::data::Type::Bytes => {
let url_bytes = d.bytes()?;
String::from_utf8_lossy(url_bytes).to_string()
}
minicbor::data::Type::String => d.str()?.to_string(),
_ => {
return Err(minicbor::decode::Error::message(
"Expected bytes or string for URL",
))
}
};

// data_hash is encoded as direct bytes, not an array
let data_hash = d.bytes()?.to_vec();

Ok(Self { url, data_hash })
}
}

/// DRep Record - represents the current state of a DRep in the ledger
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct DRepRecord {
/// Deposit amount in lovelace
pub deposit: Lovelace,
/// Optional anchor (metadata reference)
pub anchor: Option<Anchor>,
}

impl DRepRecord {
pub fn new(deposit: Lovelace, anchor: Option<Anchor>) -> Self {
Self { deposit, anchor }
}
}

/// DRepChoice (=CDDL drep, badly named)
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum DRepChoice {
/// Address key
Key(crate::KeyHash),

/// Script key
Script(crate::KeyHash),

/// Abstain
Abstain,

/// No confidence
NoConfidence,
}

/// DRep Registration = reg_drep_cert
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct DRepRegistration {
/// DRep credential
pub credential: DRepCredential,

/// Deposit paid
pub deposit: Lovelace,

/// Optional anchor
pub anchor: Option<Anchor>,
}

/// DRep Deregistration = unreg_drep_cert
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct DRepDeregistration {
/// DRep credential
pub credential: DRepCredential,

/// Deposit to refund
pub refund: Lovelace,
}

/// DRep Update = update_drep_cert
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct DRepUpdate {
/// DRep credential
pub credential: DRepCredential,

/// Optional anchor
pub anchor: Option<Anchor>,
}

/// DRep voting thresholds for governance actions
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone, minicbor::Decode)]
pub struct DRepVotingThresholds {
#[n(0)]
pub motion_no_confidence: RationalNumber,
#[n(1)]
pub committee_normal: RationalNumber,
#[n(2)]
pub committee_no_confidence: RationalNumber,
#[n(3)]
pub update_constitution: RationalNumber,
#[n(4)]
pub hard_fork_initiation: RationalNumber,
#[n(5)]
pub pp_network_group: RationalNumber,
#[n(6)]
pub pp_economic_group: RationalNumber,
#[n(7)]
pub pp_technical_group: RationalNumber,
#[n(8)]
pub pp_governance_group: RationalNumber,
#[n(9)]
pub treasury_withdrawal: RationalNumber,
}
2 changes: 2 additions & 0 deletions common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub mod cip19;
pub mod commands;
pub mod configuration;
pub mod crypto;
pub mod drep;
pub mod epoch_snapshot;
pub mod genesis_values;
pub mod hash;
Expand All @@ -32,5 +33,6 @@ pub mod validation;

// Flattened re-exports
pub use self::address::*;
pub use self::drep::*;
pub use self::metadata::*;
pub use self::types::*;
9 changes: 8 additions & 1 deletion common/src/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ use crate::Pots;
use std::collections::HashMap;

use crate::cbor::u128_cbor_codec;
use crate::types::*;
use crate::validation::ValidationStatus;
use crate::{types::*, DRepRecord};

// Caryatid core messages which we re-export
use crate::epoch_snapshot::SnapshotsContainer;
Expand Down Expand Up @@ -350,6 +350,12 @@ pub enum SnapshotMessage {
Dump(SnapshotStateMessage),
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct DRepBootstrapMessage {
pub epoch: u64,
pub dreps: HashMap<DRepCredential, DRepRecord>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct SnapshotDumpMessage {
pub block_height: u64,
Expand Down Expand Up @@ -436,6 +442,7 @@ pub enum SnapshotStateMessage {
SPOState(SPOState),
EpochState(EpochBootstrapMessage),
AccountsState(AccountsBootstrapMessage),
DRepState(DRepBootstrapMessage),
}

// === Global message enum ===
Expand Down
2 changes: 1 addition & 1 deletion common/src/snapshot/mark_set_go.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ impl RawSnapshot {
ctx: &mut SnapshotContext,
snapshot_name: &str,
) -> Result<RawSnapshot> {
info!("Parsing snapshot {}", snapshot_name);
info!("Parsing snapshot {snapshot_name}");
match decoder.datatype().context("Failed to read snapshot datatype")? {
minicbor::data::Type::Array => {
decoder.array().context("Failed to parse snapshot array")?;
Expand Down
Loading