Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add explorer library #651

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 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
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ members = [
"cardano-legacy-address",
"sparse-array",
"typed-bytes",
"chain-explorer",
]

[profile.bench]
Expand Down
22 changes: 22 additions & 0 deletions chain-explorer/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
name = "chain-explorer"
version = "0.1.0"
authors = ["[email protected]"]
edition = "2018"
license = "MIT OR Apache-2.0"
repository = "https://github.com/input-output-hk/chain-libs"

[dependencies]
thiserror = "1.0.20"
tracing = "0.1"
rand = "0.8.3"
rand_chacha = "0.3.1"
sanakirja = "1.2.5"
zerocopy = "0.5.0"
byteorder = "1.4.3"
hex = "0.4.3"

chain-core = { path = "../chain-core" }
chain-addr = { path = "../chain-addr" }
chain-crypto = { path = "../chain-crypto" }
chain-impl-mockchain = { path = "../chain-impl-mockchain" }
139 changes: 139 additions & 0 deletions chain-explorer/src/chain_storable/certificate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
use crate::chain_storable::{Choice, VotePlanId};
use sanakirja::{direct_repr, Storable, UnsizedStorable};
use std::mem;
use zerocopy::AsBytes;

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[repr(C)]
pub struct TransactionCertificate {
tag: CertificateTag,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the advantage of an union + discriminant over an enum?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just that I don't need a max const fn to compute the size of the serialized thing...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be clear though, it is possible to store the whole thing as a data_len + tag + data, I just went with a fixed-size thing because it's easier to write (no need to deserialize, or use a DST), and for that the union gave me less trouble.

cert: SerializedCertificate,
}

impl TransactionCertificate {
pub fn from_vote_plan_id(id: VotePlanId) -> Self {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is VotePlanId a certificate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, not really... The graphql API should return a VotePlan. It's just that I stored the VotePlan info somewhere else, indexed by the VotePlanId, so this is just needed for that join.

It could be called from_vote_plan anyway, though.

TransactionCertificate {
tag: CertificateTag::VotePlan,
cert: SerializedCertificate { vote_plan: id },
}
}

pub fn from_public_vote_cast(vote: PublicVoteCast) -> Self {
TransactionCertificate {
tag: CertificateTag::PublicVoteCast,
cert: SerializedCertificate {
public_vote_cast: vote,
},
}
}

pub fn from_private_vote_cast(vote: PrivateVoteCast) -> Self {
TransactionCertificate {
tag: CertificateTag::PrivateVoteCast,
cert: SerializedCertificate {
private_vote_cast: vote,
},
}
}

pub fn as_vote_plan(&self) -> Option<&VotePlanId> {
unsafe {
match self {
Self {
tag: CertificateTag::VotePlan,
cert: SerializedCertificate { vote_plan },
} => Some(vote_plan),
_ => None,
}
}
}

pub fn as_public_vote_cast(&self) -> Option<&PublicVoteCast> {
unsafe {
match self {
Self {
tag: CertificateTag::PublicVoteCast,
cert: SerializedCertificate { public_vote_cast },
} => Some(public_vote_cast),
_ => None,
}
}
}

pub fn as_private_vote_cast(&self) -> Option<&PrivateVoteCast> {
unsafe {
match self {
Self {
tag: CertificateTag::PrivateVoteCast,
cert: SerializedCertificate { private_vote_cast },
} => Some(private_vote_cast),
_ => None,
}
}
}
}

direct_repr!(TransactionCertificate);

#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, AsBytes)]
#[repr(u8)]
pub(crate) enum CertificateTag {
VotePlan = 0,
PublicVoteCast = 1,
PrivateVoteCast = 2,
}

#[repr(C)]
#[derive(Clone, Copy)]
union SerializedCertificate {
vote_plan: VotePlanId,
public_vote_cast: PublicVoteCast,
private_vote_cast: PrivateVoteCast,
}

impl SerializedCertificate {
fn as_bytes(&self) -> &[u8; mem::size_of::<Self>()] {
unsafe { std::mem::transmute(self) }
}
}

impl PartialEq for SerializedCertificate {
fn eq(&self, other: &Self) -> bool {
self.as_bytes().eq(other.as_bytes())
}
}

impl Eq for SerializedCertificate {}

impl PartialOrd for SerializedCertificate {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.as_bytes().partial_cmp(other.as_bytes())
}
}

impl Ord for SerializedCertificate {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.as_bytes().cmp(other.as_bytes())
}
}

impl std::fmt::Debug for SerializedCertificate {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&hex::encode(self.as_bytes()))
}
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, AsBytes)]
#[repr(C)]
pub struct PublicVoteCast {
pub vote_plan_id: VotePlanId,
pub proposal_index: u8,
pub choice: Choice,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, AsBytes)]
#[repr(C)]
pub struct PrivateVoteCast {
pub vote_plan_id: VotePlanId,
pub proposal_index: u8,
}
Loading