From f5493dd7d55113bcbebb9b471204a825b0021f33 Mon Sep 17 00:00:00 2001 From: Santiago Carmuega Date: Fri, 6 Sep 2024 20:58:58 -0300 Subject: [PATCH] feat(interop): map u5c Conway structs --- pallas-utxorpc/Cargo.toml | 5 +- pallas-utxorpc/src/certs.rs | 296 +++++++++++++++++++++++++++++++++++ pallas-utxorpc/src/lib.rs | 127 +-------------- pallas-utxorpc/src/params.rs | 9 +- 4 files changed, 313 insertions(+), 124 deletions(-) create mode 100644 pallas-utxorpc/src/certs.rs diff --git a/pallas-utxorpc/Cargo.toml b/pallas-utxorpc/Cargo.toml index ca30ba3b..a7340e17 100644 --- a/pallas-utxorpc/Cargo.toml +++ b/pallas-utxorpc/Cargo.toml @@ -11,11 +11,13 @@ readme = "README.md" authors = ["Santiago Carmuega "] [dependencies] +# utxorpc-spec = { path = "../../../utxorpc/spec/gen/rust" } +utxorpc-spec = { version = "0.10.0" } + pallas-traverse = { version = "=0.30.1", path = "../pallas-traverse" } pallas-primitives = { version = "=0.30.1", path = "../pallas-primitives" } pallas-codec = { version = "=0.30.1", path = "../pallas-codec" } pallas-crypto = { version = "=0.30.1", path = "../pallas-crypto" } -utxorpc-spec = { version = "0.9.0" } prost-types = "0.13.1" # TODO: remove this dep once we have multiera params in traverse @@ -25,4 +27,3 @@ pallas-applying = { version = "=0.30.1", path = "../pallas-applying" } hex = "0.4.3" serde_json = "1.0.120" pretty_assertions = "1.4.0" -# utxorpc-spec = { path = "../../../utxorpc/spec/gen/rust" } diff --git a/pallas-utxorpc/src/certs.rs b/pallas-utxorpc/src/certs.rs new file mode 100644 index 00000000..3ae99b80 --- /dev/null +++ b/pallas-utxorpc/src/certs.rs @@ -0,0 +1,296 @@ +use pallas_primitives::{alonzo, babbage, conway}; +use pallas_traverse as trv; +use utxorpc_spec::utxorpc::v1alpha::cardano as u5c; + +use crate::{LedgerContext, Mapper}; + +impl Mapper { + pub fn map_alonzo_compatible_cert( + &self, + x: &pallas_primitives::alonzo::Certificate, + tx: &trv::MultiEraTx, + order: u32, + ) -> u5c::Certificate { + let inner = match x { + alonzo::Certificate::StakeRegistration(a) => { + u5c::certificate::Certificate::StakeRegistration(self.map_stake_credential(a)) + } + alonzo::Certificate::StakeDeregistration(a) => { + u5c::certificate::Certificate::StakeDeregistration(self.map_stake_credential(a)) + } + alonzo::Certificate::StakeDelegation(a, b) => { + u5c::certificate::Certificate::StakeDelegation(u5c::StakeDelegationCert { + stake_credential: self.map_stake_credential(a).into(), + pool_keyhash: b.to_vec().into(), + }) + } + alonzo::Certificate::PoolRegistration { + operator, + vrf_keyhash, + pledge, + cost, + margin, + reward_account, + pool_owners, + relays, + pool_metadata, + } => u5c::certificate::Certificate::PoolRegistration(u5c::PoolRegistrationCert { + operator: operator.to_vec().into(), + vrf_keyhash: vrf_keyhash.to_vec().into(), + pledge: *pledge, + cost: *cost, + margin: u5c::RationalNumber { + numerator: margin.numerator as i32, + denominator: margin.denominator as u32, + } + .into(), + reward_account: reward_account.to_vec().into(), + pool_owners: pool_owners.iter().map(|x| x.to_vec().into()).collect(), + relays: relays.iter().map(|x| self.map_relay(x)).collect(), + pool_metadata: pool_metadata + .clone() + .map(|x| u5c::PoolMetadata { + url: x.url.clone(), + hash: x.hash.to_vec().into(), + }) + .into(), + }), + alonzo::Certificate::PoolRetirement(a, b) => { + u5c::certificate::Certificate::PoolRetirement(u5c::PoolRetirementCert { + pool_keyhash: a.to_vec().into(), + epoch: *b, + }) + } + alonzo::Certificate::GenesisKeyDelegation(a, b, c) => { + u5c::certificate::Certificate::GenesisKeyDelegation(u5c::GenesisKeyDelegationCert { + genesis_hash: a.to_vec().into(), + genesis_delegate_hash: b.to_vec().into(), + vrf_keyhash: c.to_vec().into(), + }) + } + alonzo::Certificate::MoveInstantaneousRewardsCert(a) => { + u5c::certificate::Certificate::MirCert(u5c::MirCert { + from: match &a.source { + babbage::InstantaneousRewardSource::Reserves => { + u5c::MirSource::Reserves.into() + } + babbage::InstantaneousRewardSource::Treasury => { + u5c::MirSource::Treasury.into() + } + }, + to: match &a.target { + babbage::InstantaneousRewardTarget::StakeCredentials(x) => x + .iter() + .map(|(k, v)| u5c::MirTarget { + stake_credential: self.map_stake_credential(k).into(), + delta_coin: *v, + }) + .collect(), + _ => Default::default(), + }, + other_pot: match &a.target { + babbage::InstantaneousRewardTarget::OtherAccountingPot(x) => *x, + _ => Default::default(), + }, + }) + } + }; + + u5c::Certificate { + certificate: inner.into(), + redeemer: tx + .find_certificate_redeemer(order) + .map(|r| self.map_redeemer(&r)), + } + } + + pub fn map_drep(&self, x: &conway::DRep) -> u5c::DRep { + u5c::DRep { + drep: match x { + conway::DRep::Key(x) => u5c::d_rep::Drep::AddrKeyHash(x.to_vec().into()).into(), + conway::DRep::Script(x) => u5c::d_rep::Drep::ScriptHash(x.to_vec().into()).into(), + conway::DRep::Abstain => u5c::d_rep::Drep::Abstain(true).into(), + conway::DRep::NoConfidence => u5c::d_rep::Drep::NoConfidence(true).into(), + }, + } + } + + pub fn map_conway_cert( + &self, + x: &conway::Certificate, + tx: &trv::MultiEraTx, + order: u32, + ) -> u5c::Certificate { + let inner = match x { + conway::Certificate::StakeRegistration(a) => { + u5c::certificate::Certificate::StakeRegistration(self.map_stake_credential(a)) + } + conway::Certificate::StakeDeregistration(a) => { + u5c::certificate::Certificate::StakeDeregistration(self.map_stake_credential(a)) + } + conway::Certificate::StakeDelegation(a, b) => { + u5c::certificate::Certificate::StakeDelegation(u5c::StakeDelegationCert { + stake_credential: self.map_stake_credential(a).into(), + pool_keyhash: b.to_vec().into(), + }) + } + conway::Certificate::PoolRegistration { + operator, + vrf_keyhash, + pledge, + cost, + margin, + reward_account, + pool_owners, + relays, + pool_metadata, + } => u5c::certificate::Certificate::PoolRegistration(u5c::PoolRegistrationCert { + operator: operator.to_vec().into(), + vrf_keyhash: vrf_keyhash.to_vec().into(), + pledge: *pledge, + cost: *cost, + margin: u5c::RationalNumber { + numerator: margin.numerator as i32, + denominator: margin.denominator as u32, + } + .into(), + reward_account: reward_account.to_vec().into(), + pool_owners: pool_owners.iter().map(|x| x.to_vec().into()).collect(), + relays: relays.iter().map(|x| self.map_relay(x)).collect(), + pool_metadata: pool_metadata + .clone() + .map(|x| u5c::PoolMetadata { + url: x.url.clone(), + hash: x.hash.to_vec().into(), + }) + .into(), + }), + conway::Certificate::PoolRetirement(a, b) => { + u5c::certificate::Certificate::PoolRetirement(u5c::PoolRetirementCert { + pool_keyhash: a.to_vec().into(), + epoch: *b, + }) + } + conway::Certificate::Reg(cred, coin) => { + u5c::certificate::Certificate::RegCert(u5c::RegCert { + stake_credential: self.map_stake_credential(cred).into(), + coin: *coin, + }) + } + conway::Certificate::UnReg(cred, coin) => { + u5c::certificate::Certificate::UnregCert(u5c::UnRegCert { + stake_credential: self.map_stake_credential(cred).into(), + coin: *coin, + }) + } + conway::Certificate::VoteDeleg(cred, drep) => { + u5c::certificate::Certificate::VoteDelegCert(u5c::VoteDelegCert { + stake_credential: self.map_stake_credential(cred).into(), + drep: self.map_drep(drep).into(), + }) + } + conway::Certificate::StakeVoteDeleg(stake_cred, pool_id, drep) => { + u5c::certificate::Certificate::StakeVoteDelegCert(u5c::StakeVoteDelegCert { + stake_credential: self.map_stake_credential(stake_cred).into(), + pool_keyhash: pool_id.to_vec().into(), + drep: self.map_drep(drep).into(), + }) + } + conway::Certificate::StakeRegDeleg(stake_cred, pool_id, coin) => { + u5c::certificate::Certificate::StakeRegDelegCert(u5c::StakeRegDelegCert { + stake_credential: self.map_stake_credential(stake_cred).into(), + pool_keyhash: pool_id.to_vec().into(), + coin: *coin, + }) + } + conway::Certificate::VoteRegDeleg(vote_cred, drep, coin) => { + u5c::certificate::Certificate::VoteRegDelegCert(u5c::VoteRegDelegCert { + stake_credential: self.map_stake_credential(vote_cred).into(), + drep: self.map_drep(drep).into(), + coin: *coin, + }) + } + conway::Certificate::StakeVoteRegDeleg(stake_cred, pool_id, drep, coin) => { + u5c::certificate::Certificate::StakeVoteRegDelegCert(u5c::StakeVoteRegDelegCert { + stake_credential: self.map_stake_credential(stake_cred).into(), + pool_keyhash: pool_id.to_vec().into(), + drep: self.map_drep(drep).into(), + coin: *coin, + }) + } + conway::Certificate::AuthCommitteeHot(cold_cred, hot_cred) => { + u5c::certificate::Certificate::AuthCommitteeHotCert(u5c::AuthCommitteeHotCert { + committee_cold_credential: self.map_stake_credential(cold_cred).into(), + committee_hot_credential: self.map_stake_credential(hot_cred).into(), + }) + } + conway::Certificate::ResignCommitteeCold(cold_cred, anchor) => { + u5c::certificate::Certificate::ResignCommitteeColdCert( + u5c::ResignCommitteeColdCert { + committee_cold_credential: self.map_stake_credential(cold_cred).into(), + anchor: anchor + .clone() + .map(|a| u5c::Anchor { + url: a.url, + content_hash: a.content_hash.to_vec().into(), + }) + .into(), + }, + ) + } + conway::Certificate::RegDRepCert(cred, coin, anchor) => { + u5c::certificate::Certificate::RegDrepCert(u5c::RegDRepCert { + drep_credential: self.map_stake_credential(cred).into(), + coin: *coin, + anchor: anchor + .clone() + .map(|a| u5c::Anchor { + url: a.url, + content_hash: a.content_hash.to_vec().into(), + }) + .into(), + }) + } + conway::Certificate::UnRegDRepCert(cred, coin) => { + u5c::certificate::Certificate::UnregDrepCert(u5c::UnRegDRepCert { + drep_credential: self.map_stake_credential(cred).into(), + coin: *coin, + }) + } + conway::Certificate::UpdateDRepCert(cred, anchor) => { + u5c::certificate::Certificate::UpdateDrepCert(u5c::UpdateDRepCert { + drep_credential: self.map_stake_credential(cred).into(), + anchor: anchor + .clone() + .map(|a| u5c::Anchor { + url: a.url, + content_hash: a.content_hash.to_vec().into(), + }) + .into(), + }) + } + }; + + u5c::Certificate { + certificate: inner.into(), + redeemer: tx + .find_certificate_redeemer(order) + .map(|r| self.map_redeemer(&r)), + } + } + + pub fn map_cert( + &self, + x: &trv::MultiEraCert, + tx: &trv::MultiEraTx, + order: u32, + ) -> Option { + match x { + pallas_traverse::MultiEraCert::AlonzoCompatible(x) => { + self.map_alonzo_compatible_cert(x, tx, order).into() + } + pallas_traverse::MultiEraCert::Conway(x) => self.map_conway_cert(x, tx, order).into(), + _ => None, + } + } +} diff --git a/pallas-utxorpc/src/lib.rs b/pallas-utxorpc/src/lib.rs index 47654d3f..fe973b47 100644 --- a/pallas-utxorpc/src/lib.rs +++ b/pallas-utxorpc/src/lib.rs @@ -12,6 +12,7 @@ pub use utxorpc_spec::utxorpc::v1alpha as spec; use utxorpc_spec::utxorpc::v1alpha::cardano as u5c; +mod certs; mod params; pub type TxHash = Hash<32>; @@ -55,8 +56,8 @@ impl Mapper { conway::RedeemerTag::Mint => u5c::RedeemerPurpose::Mint, conway::RedeemerTag::Cert => u5c::RedeemerPurpose::Cert, conway::RedeemerTag::Reward => u5c::RedeemerPurpose::Reward, - conway::RedeemerTag::Vote => todo!(), - conway::RedeemerTag::Propose => todo!(), + conway::RedeemerTag::Vote => u5c::RedeemerPurpose::Vote, + conway::RedeemerTag::Propose => u5c::RedeemerPurpose::Propose, } } @@ -169,7 +170,10 @@ impl Mapper { script: u5c::script::Script::PlutusV2(x.0.to_vec().into()).into(), } .into(), - Some(conway::PseudoScript::PlutusV3Script(_)) => todo!(), + Some(conway::PseudoScript::PlutusV3Script(x)) => u5c::Script { + script: u5c::script::Script::PlutusV3(x.0.to_vec().into()).into(), + } + .into(), None => None, }, } @@ -214,123 +218,6 @@ impl Mapper { } } - pub fn map_cert( - &self, - x: &trv::MultiEraCert, - tx: &trv::MultiEraTx, - order: u32, - ) -> Option { - match x { - pallas_traverse::MultiEraCert::AlonzoCompatible(x) => { - self.map_alonzo_cert(x, tx, order).into() - } - pallas_traverse::MultiEraCert::Conway(_) => { - // TODO: add conway certificates in spec - None - } - _ => None, - } - } - - pub fn map_alonzo_cert( - &self, - x: &pallas_primitives::alonzo::Certificate, - tx: &trv::MultiEraTx, - order: u32, - ) -> u5c::Certificate { - let inner = match x { - babbage::Certificate::StakeRegistration(a) => { - u5c::certificate::Certificate::StakeRegistration(self.map_stake_credential(a)) - } - babbage::Certificate::StakeDeregistration(a) => { - u5c::certificate::Certificate::StakeDeregistration(self.map_stake_credential(a)) - } - babbage::Certificate::StakeDelegation(a, b) => { - u5c::certificate::Certificate::StakeDelegation(u5c::StakeDelegationCert { - stake_credential: self.map_stake_credential(a).into(), - pool_keyhash: b.to_vec().into(), - }) - } - babbage::Certificate::PoolRegistration { - operator, - vrf_keyhash, - pledge, - cost, - margin, - reward_account, - pool_owners, - relays, - pool_metadata, - } => u5c::certificate::Certificate::PoolRegistration(u5c::PoolRegistrationCert { - operator: operator.to_vec().into(), - vrf_keyhash: vrf_keyhash.to_vec().into(), - pledge: *pledge, - cost: *cost, - margin: u5c::RationalNumber { - numerator: margin.numerator as i32, - denominator: margin.denominator as u32, - } - .into(), - reward_account: reward_account.to_vec().into(), - pool_owners: pool_owners.iter().map(|x| x.to_vec().into()).collect(), - relays: relays.iter().map(|x| self.map_relay(x)).collect(), - pool_metadata: pool_metadata - .clone() - .map(|x| u5c::PoolMetadata { - url: x.url.clone(), - hash: x.hash.to_vec().into(), - }) - .into(), - }), - babbage::Certificate::PoolRetirement(a, b) => { - u5c::certificate::Certificate::PoolRetirement(u5c::PoolRetirementCert { - pool_keyhash: a.to_vec().into(), - epoch: *b, - }) - } - babbage::Certificate::GenesisKeyDelegation(a, b, c) => { - u5c::certificate::Certificate::GenesisKeyDelegation(u5c::GenesisKeyDelegationCert { - genesis_hash: a.to_vec().into(), - genesis_delegate_hash: b.to_vec().into(), - vrf_keyhash: c.to_vec().into(), - }) - } - babbage::Certificate::MoveInstantaneousRewardsCert(a) => { - u5c::certificate::Certificate::MirCert(u5c::MirCert { - from: match &a.source { - babbage::InstantaneousRewardSource::Reserves => { - u5c::MirSource::Reserves.into() - } - babbage::InstantaneousRewardSource::Treasury => { - u5c::MirSource::Treasury.into() - } - }, - to: match &a.target { - babbage::InstantaneousRewardTarget::StakeCredentials(x) => x - .iter() - .map(|(k, v)| u5c::MirTarget { - stake_credential: self.map_stake_credential(k).into(), - delta_coin: *v, - }) - .collect(), - _ => Default::default(), - }, - other_pot: match &a.target { - babbage::InstantaneousRewardTarget::OtherAccountingPot(x) => *x, - _ => Default::default(), - }, - }) - } - }; - - u5c::Certificate { - certificate: inner.into(), - redeemer: tx - .find_certificate_redeemer(order) - .map(|r| self.map_redeemer(&r)), - } - } - pub fn map_withdrawals( &self, x: &(&[u8], u64), diff --git a/pallas-utxorpc/src/params.rs b/pallas-utxorpc/src/params.rs index 17178838..57bae920 100644 --- a/pallas-utxorpc/src/params.rs +++ b/pallas-utxorpc/src/params.rs @@ -1,5 +1,5 @@ use pallas_applying::MultiEraProtocolParameters; -use utxorpc_spec::utxorpc::v1alpha::cardano::{self as u5c, CostModel}; +use utxorpc_spec::utxorpc::v1alpha::cardano as u5c; use crate::{LedgerContext, Mapper}; @@ -49,7 +49,7 @@ impl Mapper { plutus_v1: params .cost_models_for_script_languages .first() - .map(|(_, data)| CostModel { + .map(|(_, data)| u5c::CostModel { values: data.to_vec(), }), ..Default::default() @@ -134,6 +134,7 @@ impl Mapper { .cost_models_for_script_languages .plutus_v2 .map(|values| u5c::CostModel { values }), + ..Default::default() } .into(), ..Default::default() @@ -193,6 +194,10 @@ impl Mapper { .cost_models_for_script_languages .plutus_v2 .map(|values| u5c::CostModel { values }), + plutus_v3: params + .cost_models_for_script_languages + .plutus_v3 + .map(|values| u5c::CostModel { values }), } .into(), ..Default::default()