Skip to content

Commit

Permalink
node: add transfer event deserialization
Browse files Browse the repository at this point in the history
  • Loading branch information
Neotamandua committed Oct 22, 2024
1 parent c368da1 commit e14bed4
Show file tree
Hide file tree
Showing 3 changed files with 267 additions and 10 deletions.
9 changes: 6 additions & 3 deletions rusk/src/lib/http/chain/graphql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@ use tx::*;

use async_graphql::{Context, FieldError, FieldResult, Object};
use execution_core::{transfer::TRANSFER_CONTRACT, ContractId};
#[cfg(feature = "archive")]
use node::archive::{Archive, MoonlightGroup};
use node::database::rocksdb::Backend;
use node::database::{Ledger, DB};
#[cfg(feature = "archive")]
use {
deserialized_archive_data::DeserializedMoonlightGroups,
node::archive::{Archive, MoonlightGroup},
};

use std::sync::Arc;
use tokio::sync::RwLock;
Expand Down Expand Up @@ -141,7 +144,7 @@ impl Query {
&self,
ctx: &Context<'_>,
address: String,
) -> OptResult<MoonlightTransactions> {
) -> OptResult<DeserializedMoonlightGroups> {
full_moonlight_history(ctx, address).await
}

Expand Down
227 changes: 227 additions & 0 deletions rusk/src/lib/http/chain/graphql/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,3 +337,230 @@ pub struct CallData {
fn_name: String,
data: String,
}

/// Interim solution for sending out deserialized event data
#[cfg(feature = "archive")]
pub(super) mod deserialized_archive_data {
use super::*;
use execution_core::stake::STAKE_CONTRACT;
use execution_core::transfer::withdraw::WithdrawReceiver;
use execution_core::transfer::{
ConvertEvent, DepositEvent, MoonlightTransactionEvent, WithdrawEvent,
CONVERT_TOPIC, DEPOSIT_TOPIC, MINT_TOPIC, MOONLIGHT_TOPIC,
TRANSFER_CONTRACT, WITHDRAW_TOPIC,
};
use node_data::events::contract::{
ContractEvent, TxHash, WrappedContractId,
};
use serde::ser::SerializeStruct;
use serde::{Deserialize, Serialize};

#[serde_with::serde_as]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct DeserializedMoonlightGroup {
pub events: serde_json::Value,
#[serde_as(as = "serde_with::hex::Hex")]
pub origin: TxHash,
pub block_height: u64,
}
pub struct DeserializedMoonlightGroups(pub Vec<DeserializedMoonlightGroup>);

#[Object]
impl DeserializedMoonlightGroups {
pub async fn json(&self) -> serde_json::Value {
serde_json::to_value(&self.0).unwrap_or_default()
}
}

#[derive(Debug, Clone, PartialEq)]
pub struct DeserializedMoonlightTransactionEvent(
pub MoonlightTransactionEvent,
);

impl Serialize for DeserializedMoonlightTransactionEvent {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let moonlight_event = &self.0;

let mut state =
serializer.serialize_struct("MoonlightTransactionEvent", 6)?;
state.serialize_field(
"sender",
&bs58::encode(moonlight_event.sender.to_bytes()).into_string(),
)?;
state.serialize_field(
"receiver",
&moonlight_event
.receiver
.map(|r| bs58::encode(r.to_bytes()).into_string()),
)?;
state.serialize_field("value", &moonlight_event.value)?;
state
.serialize_field("memo", &hex::encode(&moonlight_event.memo))?;
state.serialize_field("gas_spent", &moonlight_event.gas_spent)?;
state.serialize_field(
"refund_info",
&moonlight_event.refund_info.map(|(pk, amt)| {
(bs58::encode(pk.to_bytes()).into_string(), amt)
}),
)?;

state.end()
}
}

#[derive(Debug, Clone, PartialEq)]
pub struct DeserializedWithdrawEvent(pub WithdrawEvent);

impl Serialize for DeserializedWithdrawEvent {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let withdraw_event = &self.0;
let mut state = serializer.serialize_struct("WithdrawEvent", 3)?;
state.serialize_field(
"sender",
&WrappedContractId(withdraw_event.sender),
)?;
state.serialize_field(
"receiver",
&match withdraw_event.receiver {
WithdrawReceiver::Moonlight(pk) => {
bs58::encode(pk.to_bytes()).into_string()
}
WithdrawReceiver::Phoenix(pk) => {
bs58::encode(pk.to_bytes()).into_string()
}
},
)?;
state.serialize_field("value", &withdraw_event.value)?;

state.end()
}
}

#[derive(Debug, Clone, PartialEq)]
pub struct DeserializedConvertEvent(pub ConvertEvent);

impl Serialize for DeserializedConvertEvent {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let convert_event = &self.0;
let mut state = serializer.serialize_struct("ConvertEvent", 3)?;
state.serialize_field(
"sender",
&convert_event
.sender
.map(|pk| bs58::encode(pk.to_bytes()).into_string()),
)?;
state.serialize_field(
"receiver",
&match convert_event.receiver {
WithdrawReceiver::Moonlight(pk) => {
bs58::encode(pk.to_bytes()).into_string()
}
WithdrawReceiver::Phoenix(pk) => {
bs58::encode(pk.to_bytes()).into_string()
}
},
)?;
state.serialize_field("value", &convert_event.value)?;
state.end()
}
}

#[derive(Debug, Clone, PartialEq)]
pub struct DeserializedDepositEvent(pub DepositEvent);

impl Serialize for DeserializedDepositEvent {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let deposit_event = &self.0;
let mut state = serializer.serialize_struct("DepositEvent", 3)?;
state.serialize_field(
"sender",
&deposit_event
.sender
.map(|pk| bs58::encode(pk.to_bytes()).into_string()),
)?;
state.serialize_field(
"receiver",
&WrappedContractId(deposit_event.receiver),
)?;
state.serialize_field("value", &deposit_event.value)?;

state.end()
}
}

#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct DeserializedContractEvent {
pub target: WrappedContractId,
pub topic: String,
pub data: serde_json::Value,
}

impl From<ContractEvent> for DeserializedContractEvent {
fn from(event: ContractEvent) -> Self {
let deserialized_data = if event.target.0 == TRANSFER_CONTRACT {
match event.topic.as_str() {
MOONLIGHT_TOPIC => rkyv::from_bytes::<
MoonlightTransactionEvent,
>(&event.data)
.map(|e| {
serde_json::to_value(
DeserializedMoonlightTransactionEvent(e),
)
})
.unwrap_or_else(|_| serde_json::to_value(event.data)),
WITHDRAW_TOPIC | MINT_TOPIC => rkyv::from_bytes::<
WithdrawEvent,
>(
&event.data
)
.map(|e| serde_json::to_value(DeserializedWithdrawEvent(e)))
.unwrap_or_else(|_| serde_json::to_value(event.data)),
CONVERT_TOPIC => {
rkyv::from_bytes::<ConvertEvent>(&event.data)
.map(|e| {
serde_json::to_value(DeserializedConvertEvent(
e,
))
})
.unwrap_or_else(|_| {
serde_json::to_value(event.data)
})
}
DEPOSIT_TOPIC => {
rkyv::from_bytes::<DepositEvent>(&event.data)
.map(|e| {
serde_json::to_value(DeserializedDepositEvent(
e,
))
})
.unwrap_or_else(|_| {
serde_json::to_value(event.data)
})
}
_ => serde_json::to_value(hex::encode(event.data)),
}
} else {
serde_json::to_value(hex::encode(event.data))
}
.unwrap_or_else(|e| serde_json::Value::String(e.to_string()));

Self {
target: event.target,
topic: event.topic,
data: deserialized_data,
}
}
}
}
41 changes: 34 additions & 7 deletions rusk/src/lib/http/chain/graphql/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,16 @@ use node::database::rocksdb::MD_HASH_KEY;
use node::database::{Mempool, Metadata};
#[cfg(feature = "archive")]
use {
data::deserialized_archive_data::*,
dusk_bytes::Serializable,
execution_core::signatures::bls::PublicKey as AccountPublicKey,
execution_core::transfer::{
ConvertEvent, DepositEvent, MoonlightTransactionEvent, WithdrawEvent,
CONVERT_TOPIC, MINT_TOPIC, MOONLIGHT_TOPIC, TRANSFER_CONTRACT,
WITHDRAW_TOPIC,
},
node::archive::MoonlightGroup,
node_data::events::contract::ContractEvent,
};

use super::*;
Expand Down Expand Up @@ -88,9 +95,7 @@ pub async fn mempool_by_hash<'a>(
pub(super) async fn full_moonlight_history(
ctx: &Context<'_>,
address: String,
) -> OptResult<MoonlightTransactions> {
use dusk_bytes::ParseHexStr;

) -> OptResult<DeserializedMoonlightGroups> {
let (_, archive) = ctx.data::<DBContext>()?;
let v = bs58::decode(address).into_vec()?;

Expand All @@ -101,12 +106,34 @@ pub(super) async fn full_moonlight_history(
let pk = AccountPublicKey::from_bytes(&pk_bytes)
.map_err(|_| anyhow::anyhow!("Failed to serialize given public key"))?;

let moonlight_events = archive.full_moonlight_history(pk)?;
let moonlight_groups = archive.full_moonlight_history(pk)?;

if let Some(moonlight_events) = moonlight_events {
Ok(Some(MoonlightTransactions(moonlight_events)))
} else {
// Deserialize the MoonlightGroup as an interim solution until the consumer
// api wrapper can do it
let mut deser_moonlight_groups = Vec::new();

if let Some(moonlight_groups) = moonlight_groups {
for moonlight_group in moonlight_groups {
let deser_events = moonlight_group
.events()
.iter()
.map(|event| event.clone().into())
.collect::<Vec<DeserializedContractEvent>>();

let deserialized_moonlight_group = DeserializedMoonlightGroup {
events: serde_json::to_value(deser_events)?,
origin: *moonlight_group.origin(),
block_height: moonlight_group.block_height(),
};

deser_moonlight_groups.push(deserialized_moonlight_group);
}
}

if deser_moonlight_groups.is_empty() {
Ok(None)
} else {
Ok(Some(DeserializedMoonlightGroups(deser_moonlight_groups)))
}
}

Expand Down

0 comments on commit e14bed4

Please sign in to comment.