Skip to content
87 changes: 85 additions & 2 deletions common/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use serde_with::{hex::Hex, serde_as};
use std::cmp::Ordering;
use std::collections::{HashMap, HashSet};
use std::fmt::{Display, Formatter};
use std::ops::Neg;

/// Protocol era
#[derive(
Expand Down Expand Up @@ -126,7 +127,7 @@ pub struct AddressDelta {
pub address: Address,

/// Balance change
pub delta: i64,
pub delta: ValueDelta,
}

/// Stake balance change
Expand All @@ -139,6 +140,88 @@ pub struct StakeAddressDelta {
pub delta: i64,
}

/// Value (lovelace + multiasset)
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Value {
pub lovelace: u64,
pub assets: NativeAssets,
}

impl Value {
pub fn new(lovelace: u64, assets: NativeAssets) -> Self {
Self { lovelace, assets }
}

pub fn coin(&self) -> u64 {
self.lovelace
}
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ValueDelta {
pub lovelace: i64,
pub assets: Vec<(PolicyId, Vec<NativeAssetDelta>)>,
}

impl ValueDelta {
pub fn new(lovelace: i64, assets: Vec<(PolicyId, Vec<NativeAssetDelta>)>) -> Self {
Self { lovelace, assets }
}
}

impl From<&Value> for ValueDelta {
fn from(v: &Value) -> Self {
ValueDelta {
lovelace: v.lovelace as i64,
assets: v
.assets
.iter()
.map(|(pid, nas)| {
let nas_delta = nas
.iter()
.map(|na| NativeAssetDelta {
name: na.name.clone(),
amount: na.amount as i64,
})
.collect();
(*pid, nas_delta)
})
.collect(),
}
}
}

impl Neg for ValueDelta {
type Output = Self;

fn neg(mut self) -> Self::Output {
self.lovelace = -self.lovelace;
for (_, nas) in &mut self.assets {
for na in nas {
na.amount = -na.amount;
}
}
self
}
}

pub type PolicyId = [u8; 28];
pub type NativeAssets = Vec<(PolicyId, Vec<NativeAsset>)>;
pub type NativeAssetsDelta = Vec<(PolicyId, Vec<NativeAssetDelta>)>;
pub type AssetName = Vec<u8>;

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct NativeAsset {
pub name: AssetName,
pub amount: u64,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct NativeAssetDelta {
pub name: AssetName,
pub amount: i64,
}

/// Transaction output (UTXO)
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct TxOutput {
Expand All @@ -152,7 +235,7 @@ pub struct TxOutput {
pub address: Address,

/// Output value (Lovelace)
pub value: u64,
pub value: Value,
// todo: Implement datum /// Datum (raw)
// !!! pub datum: Vec<u8>,
}
Expand Down
4 changes: 2 additions & 2 deletions modules/genesis_bootstrapper/src/genesis_bootstrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use acropolis_common::{
CardanoMessage, GenesisCompleteMessage, Message, PotDeltasMessage, UTXODeltasMessage,
},
Address, BlockInfo, BlockStatus, ByronAddress, Era, Lovelace, LovelaceDelta, Pot, PotDelta,
TxOutput, UTXODelta,
TxOutput, UTXODelta, Value,
};
use anyhow::Result;
use caryatid_sdk::{module, Context, Module};
Expand Down Expand Up @@ -107,7 +107,7 @@ impl GenesisBootstrapper {
address: Address::Byron(ByronAddress {
payload: address.payload.to_vec(),
}),
value: *amount,
value: Value::new(*amount, Vec::new()),
};

utxo_deltas_message.deltas.push(UTXODelta::Output(tx_output));
Expand Down
10 changes: 5 additions & 5 deletions modules/stake_delta_filter/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,13 +277,13 @@ impl Tracker {
.map(|a| a.to_string())
.unwrap_or(Ok("(none)".to_owned()))
.unwrap_or("(???)".to_owned());
delta += event.address_delta.delta;
delta += event.address_delta.delta.lovelace;

chunk.push(format!(
" blk {}, {}: {} ({:?}) => {} ({:?})",
event.block.number,
src_addr,
event.address_delta.delta,
event.address_delta.delta.lovelace,
event.address_delta.address,
dst_addr,
event.stake_address
Expand Down Expand Up @@ -388,7 +388,7 @@ pub fn process_message(

let stake_delta = StakeAddressDelta {
address: stake_address,
delta: d.delta,
delta: d.delta.lovelace,
};
result.deltas.push(stake_delta);
}
Expand All @@ -402,15 +402,15 @@ mod test {
use acropolis_common::{
messages::AddressDeltasMessage, Address, AddressDelta, BlockInfo, BlockStatus,
ByronAddress, Era, ShelleyAddress, ShelleyAddressDelegationPart, ShelleyAddressPaymentPart,
ShelleyAddressPointer, StakeAddress, StakeAddressPayload,
ShelleyAddressPointer, StakeAddress, StakeAddressPayload, ValueDelta,
};
use bech32::{Bech32, Hrp};

fn parse_addr(s: &str) -> Result<AddressDelta> {
let a = pallas_addresses::Address::from_bech32(s)?;
Ok(AddressDelta {
address: map_address(&a)?,
delta: 1,
delta: ValueDelta::new(1, Vec::new()),
})
}

Expand Down
58 changes: 57 additions & 1 deletion modules/tx_unpacker/src/map_parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use pallas::ledger::{
ProtocolVersion as PallasProtocolVersion, Relay as PallasRelay, ScriptHash,
StakeCredential as PallasStakeCredential,
},
traverse::MultiEraCert,
traverse::{MultiEraCert, MultiEraPolicyAssets, MultiEraValue},
*,
};

Expand Down Expand Up @@ -855,3 +855,59 @@ pub fn map_all_governance_voting_procedures(

Ok(procs)
}

pub fn map_value(pallas_value: &MultiEraValue) -> Value {
let lovelace = pallas_value.coin();
let pallas_assets = pallas_value.assets();

let mut assets: NativeAssets = Vec::new();

for policy_group in pallas_assets {
match policy_group {
MultiEraPolicyAssets::AlonzoCompatibleOutput(policy, kvps) => {
match policy.as_ref().try_into() {
Ok(policy_id) => {
let native_assets = kvps
.iter()
.map(|(name, amt)| NativeAsset {
name: name.to_vec(),
amount: *amt,
})
.collect();

assets.push((policy_id, native_assets));
}
Err(_) => {
tracing::error!(
"Invalid policy id length: expected 28 bytes, got {}",
policy.len()
);
continue;
}
}
}
MultiEraPolicyAssets::ConwayOutput(policy, kvps) => match policy.as_ref().try_into() {
Ok(policy_id) => {
let native_assets = kvps
.iter()
.map(|(name, amt)| NativeAsset {
name: name.to_vec(),
amount: u64::from(*amt),
})
.collect();

assets.push((policy_id, native_assets));
}
Err(_) => {
tracing::error!(
"Invalid policy id length: expected 28 bytes, got {}",
policy.len()
);
continue;
}
},
_ => {}
}
}
Value::new(lovelace, assets)
}
2 changes: 1 addition & 1 deletion modules/tx_unpacker/src/tx_unpacker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ impl TxUnpacker {
tx_hash: *tx.hash(),
index: index as u64,
address: address,
value: output.value().coin(),
value: map_parameters::map_value(&output.value())
// !!! datum
};

Expand Down
4 changes: 2 additions & 2 deletions modules/utxo_state/src/address_delta_publisher.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Address delta publisher for the UTXO state Acropolis module
use acropolis_common::{
messages::{AddressDeltasMessage, CardanoMessage, Message},
Address, AddressDelta, BlockInfo,
Address, AddressDelta, BlockInfo, ValueDelta,
};
use async_trait::async_trait;
use caryatid_sdk::Context;
Expand Down Expand Up @@ -44,7 +44,7 @@ impl AddressDeltaObserver for AddressDeltaPublisher {
}

/// Observe an address delta and publish messages
async fn observe_delta(&self, address: &Address, delta: i64) {
async fn observe_delta(&self, address: &Address, delta: ValueDelta) {
// Accumulate the delta
self.deltas.lock().await.push(AddressDelta {
address: address.clone(),
Expand Down
4 changes: 2 additions & 2 deletions modules/utxo_state/src/fake_immutable_utxo_store.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Fake store for immutable UTXOs

use crate::state::{ImmutableUTXOStore, UTXOKey, UTXOValue};
use acropolis_common::Address;
use acropolis_common::{Address, Value};
use anyhow::Result;
use async_trait::async_trait;
use config::Config;
Expand Down Expand Up @@ -51,7 +51,7 @@ impl ImmutableUTXOStore for FakeImmutableUTXOStore {
async fn lookup_utxo(&self, _key: &UTXOKey) -> Result<Option<UTXOValue>> {
Ok(Some(UTXOValue {
address: Address::None,
value: 42,
value: Value::new(42, Vec::new()),
}))
}

Expand Down
95 changes: 0 additions & 95 deletions modules/utxo_state/src/rest.rs

This file was deleted.

Loading