Skip to content

Commit 04256ab

Browse files
authored
change: ETCM-9687 Fixes and documentation for util crates (#793)
* change: ETCM-9687 Fixes and documentation for util crates * allow deprecated * change deprecation version * simplify languge * fix clippy warning
1 parent 3fdc469 commit 04256ab

File tree

6 files changed

+176
-18
lines changed

6 files changed

+176
-18
lines changed

toolkit/data-sources/db-sync/src/db_model.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ FROM block INNER JOIN block as stable_block ON block.block_no - $1 = stable_bloc
328328
WHERE block.block_no IS NOT NULL
329329
ORDER BY block.block_no DESC
330330
LIMIT 1";
331+
#[allow(deprecated)]
331332
Ok(sqlx::query_as::<_, EpochNumberRow>(sql)
332333
.bind(BlockNumber(security_parameter))
333334
.fetch_optional(pool)

toolkit/sidechain/primitives/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use sidechain_domain::{ScEpochNumber, ScSlotNumber, UtxoId};
1111
mod tests;
1212

1313
/// Information about current Partner Chain slot and epoch.
14-
#[deprecated(since = "1.8.0", note = "See deprecation notes for [GetSidechainStatus]")]
14+
#[deprecated(since = "1.7.0", note = "See deprecation notes for [GetSidechainStatus]")]
1515
#[derive(TypeInfo, Clone, Encode, Decode)]
1616
pub struct SidechainStatus {
1717
/// current Partner Chain epoch
@@ -65,7 +65,7 @@ mod api_declarations {
6565
}
6666

6767
/// Runtime API for getting information about current Partner Chain slot and epoch
68-
#[deprecated(since = "1.8.0", note = "Code that needs this data should define its own runtime API instead.")]
68+
#[deprecated(since = "1.7.0", note = "Code that needs this data should define its own runtime API instead.")]
6969
pub trait GetSidechainStatus {
7070
/// Returns current Partner Chain slot and epoch
7171
fn get_sidechain_status() -> SidechainStatus;

toolkit/utils/byte-string-derivation/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ authors.workspace = true
66
edition.workspace = true
77
homepage.workspace = true
88
repository.workspace = true
9+
description = "Proc macros for generating conversions for byte string wrapper types"
910

1011
[lib]
1112
proc-macro = true

toolkit/utils/byte-string-derivation/src/lib.rs

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,57 @@
1+
//! Proc macros for generating conversions for byte string wrapper types.
2+
//! See documentation of [macro@byte_string] for more information.
13
use proc_macro::TokenStream;
24
use quote::ToTokens;
35
use quote::quote;
46
use syn::Generics;
57

68
extern crate alloc;
79

10+
/// Proc macro that can generate multiple helper functions and traits for types that wrap an
11+
/// array, [Vec], or [BoundedVec] of bytes. What code is generated by the macro is controlled
12+
/// by passing the following arguments:
13+
/// - `debug`:
14+
/// implements [Debug] that uses hex to encode the bytes
15+
/// - `hex_serialize`:
16+
/// implements `serde::Serialize` that encode the bytes to a hex string as intermediate format.
17+
/// This implementation is useful for saving bytes in Json and similar formats.
18+
/// - `hex_deserialize`:
19+
/// implements `serde::Deserialize` that decodes the type from a string containig hex-encoded
20+
/// bytes. This implementation is useful for decoding hex data from Json and similar formats.
21+
/// - `from_num`:
22+
/// implements [`From<u64>`]
23+
/// - `from_bytes`:
24+
/// implements either [`From<&[u8]>`] or [`TryFrom<&[u8]`] depending on whether the the type
25+
/// can be infallibly ([Vec]) or fallibly (array, [BoundedVec]) cast from a byte slice.
26+
/// - `decode_hex`:
27+
/// adds functions `decode_hex` and `decode_hex_unsafe` that decode the type from a [&str]
28+
/// and a [FromStr] implementation equivalent to calling `decode_hex`.
29+
/// - `to_hex_string`:
30+
/// adds a function `to_hex_string` that returns the inner bytes as a hex string.
31+
/// - `as_ref`: generates [`AsRef<[u8]>`] implementation
32+
///
33+
/// _Note_: As the code generated by this macro is meant to be `no_std`-compatible, some of the
34+
/// options require `alloc` crate to be available in the scope where the code is generated.
35+
///
36+
/// # Example
37+
///
38+
/// ```rust
39+
/// extern crate alloc;
40+
/// use byte_string_derive::byte_string;
41+
/// use sp_core::{ ConstU32, bounded_vec::BoundedVec };
42+
///
43+
/// #[byte_string(debug, hex_serialize, hex_deserialize, from_num, from_bytes, decode_hex, to_hex_string, as_ref)]
44+
/// pub struct MyArrayBytes([u8; 32]);
45+
///
46+
/// #[byte_string(debug, hex_serialize, hex_deserialize, from_num, from_bytes, decode_hex, to_hex_string, as_ref)]
47+
/// pub struct MyVecBytes(Vec<u8>);
48+
///
49+
/// #[byte_string(from_bytes)]
50+
/// pub struct MyBoundedVecBytes(BoundedVec<u8, ConstU32<32>>);
51+
/// ```
52+
///
53+
/// [BoundedVec]: https://paritytech.github.io/polkadot-sdk/master/sp_core/bounded_vec/struct.BoundedVec.html
54+
/// [FromStr]: std::str::FromStr
855
#[proc_macro_attribute]
956
pub fn byte_string(attr: TokenStream, input: TokenStream) -> TokenStream {
1057
let ast = syn::parse(input).expect("Cannot parse source");
@@ -182,7 +229,15 @@ fn gen_from_bytes(name: &syn::Ident, ty: &SupportedType, generics: &Generics) ->
182229
}
183230
}
184231
},
185-
_ => quote! {
232+
SupportedType::BoundedVec(ty) => quote! {
233+
impl<'a> TryFrom<&'a [u8]> for #name {
234+
type Error = <#ty as TryFrom<Vec<u8>>>::Error;
235+
fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
236+
Ok(#name(bytes.to_vec().try_into()?))
237+
}
238+
}
239+
},
240+
SupportedType::Vec => quote! {
186241
impl #impl_generics From<&[u8]> for #name #ty_generics #where_clause {
187242
fn from(bytes: &[u8]) -> Self {
188243
#name(bytes.clone().to_vec())

toolkit/utils/db-sync-sqlx/src/lib.rs

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
//! helpers and primitive types for querying Cardano [Db-Sync] data using [sqlx]
2+
//!
3+
//! # About
4+
//!
5+
//! This crate is meant to provide help when writing queries for data produced by [Db-Sync],
6+
//! a Cardano blockchain indexer. Db-Sync keeps the indexed data in a Postgre database that
7+
//! can be queried using SQL. This crate defines primitive types that correspond to column
8+
//! types used in the [Db-Sync schema], along with some other helpers and casts to types
9+
//! defined in [sidechain_domain].
10+
//!
11+
//! [sqlx]: https://github.com/launchbadge/sqlx
12+
//! [Db-Sync]: https://github.com/IntersectMBO/cardano-db-sync
13+
//! [Db-Sync schema]: https://github.com/IntersectMBO/cardano-db-sync/blob/master/doc/schema.md
114
use num_traits::ToPrimitive;
215
use sidechain_domain::*;
316
use sqlx::database::Database;
@@ -6,11 +19,17 @@ use sqlx::error::BoxDynError;
619
use sqlx::postgres::PgTypeInfo;
720
use sqlx::*;
821

9-
/// Generates sqlx implementations for an unsigned wrapper of types that are signed.
10-
/// We expect that values will have always 0 as the most significant bit.
11-
/// For example TxIndex is in range of [0, 2^15-1], it will be u16 in domain,
12-
/// but it requires encoding and decoding like i16.
13-
/// See txindex, word31 and word63 types in db-sync schema definition.
22+
/// Macro to handle numeric types that are non-negative but are stored by Db-Sync using
23+
/// signed SQL types.
24+
///
25+
/// This macro generates an unsigned numeric domain type and sqlx trait implementation for
26+
/// decoding it from signed data coming from Db-Sync database. It expects that values will
27+
/// always have 0 as the most significant bit.
28+
///
29+
/// For example because [TxIndex] is in range of \[0, 2^15-1\], it will be [u16] in domain,
30+
/// but it requires encoding and decoding as i16.
31+
///
32+
/// See `txindex`, `word31` `and` word63 types in Db-Sync schema definition.
1433
#[macro_export]
1534
macro_rules! sqlx_implementations_for_wrapper {
1635
($WRAPPED:ty, $DBTYPE:expr, $NAME:ty, $DOMAIN:ty) => {
@@ -62,28 +81,42 @@ macro_rules! sqlx_implementations_for_wrapper {
6281
};
6382
}
6483

84+
/// Cardano block number
6585
#[derive(Debug, Copy, Ord, PartialOrd, Clone, PartialEq, Eq)]
6686
pub struct BlockNumber(pub u32);
6787
sqlx_implementations_for_wrapper!(i32, "INT4", BlockNumber, McBlockNumber);
6888

89+
/// Cardano epoch number
6990
#[derive(Debug, Copy, Clone, PartialEq)]
7091
pub struct EpochNumber(pub u32);
7192
sqlx_implementations_for_wrapper!(i32, "INT4", EpochNumber, McEpochNumber);
7293

94+
/// Cardano slot number
7395
#[derive(Debug, Copy, Clone, PartialEq)]
7496
pub struct SlotNumber(pub u64);
7597
sqlx_implementations_for_wrapper!(i64, "INT8", SlotNumber, McSlotNumber);
7698

99+
/// Index of a Cardano transaction output
100+
///
101+
/// This type corresponds to the following SQL type defined by Db-Sync.
102+
/// ```sql
77103
/// CREATE DOMAIN txindex AS smallint CONSTRAINT txindex_check CHECK ((VALUE >= 0));
104+
/// ```
78105
#[derive(Debug, Clone, PartialEq)]
79106
pub struct TxIndex(pub u16);
80107
sqlx_implementations_for_wrapper!(i16, "INT2", TxIndex, UtxoIndex);
81108

109+
/// Index of a Cardano transaction with its block
82110
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
83111
pub struct TxIndexInBlock(pub u32);
84112
sqlx_implementations_for_wrapper!(i32, "INT4", TxIndexInBlock, McTxIndexInBlock);
85113

114+
/// Number of ADA expressed in Lovelace (1 million-th of ADA)
115+
///
116+
/// This type corresponds to the following SQL type defined by Db-Sync.
117+
/// ```sql
86118
/// CREATE DOMAIN int65type AS numeric (20, 0) CHECK (VALUE >= -18446744073709551615 AND VALUE <= 18446744073709551615);
119+
/// ```
87120
#[derive(Debug, Clone, PartialEq)]
88121
pub struct TxValue(pub i128);
89122

@@ -101,7 +134,12 @@ impl<'r> Decode<'r, Postgres> for TxValue {
101134
}
102135
}
103136

137+
/// Number of ADA delegated by a Cardano delegator to a single SPO, expressed in Lovelace (1 million-th of ADA)
138+
///
139+
/// This type corresponds to the following SQL type defined by Db-Sync.
140+
/// ```sql
104141
/// CREATE DOMAIN "lovelace" AS numeric(20,0) CONSTRAINT flyway_needs_this CHECK (VALUE >= 0::numeric AND VALUE <= '18446744073709551615'::numeric);
142+
/// ```
105143
#[derive(Debug, Clone, PartialEq)]
106144
pub struct StakeDelegation(pub u64);
107145

@@ -119,6 +157,7 @@ impl<'r> Decode<'r, Postgres> for StakeDelegation {
119157
}
120158
}
121159

160+
/// Cardano native asset name, typically UTF-8 encoding of a human-readable name
122161
#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
123162
pub struct AssetName(pub Vec<u8>);
124163

@@ -128,6 +167,7 @@ impl From<sidechain_domain::AssetName> for AssetName {
128167
}
129168
}
130169

170+
/// Cardano minting policy ID. This value is obtained by hashing the Plutus script of the policy.
131171
#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
132172
pub struct PolicyId(pub Vec<u8>);
133173

@@ -137,9 +177,12 @@ impl From<sidechain_domain::PolicyId> for PolicyId {
137177
}
138178
}
139179

180+
/// Full identifier of a Cardano native asset
140181
#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
141182
pub struct Asset {
183+
/// Minting policy ID of the asset
142184
pub policy_id: PolicyId,
185+
/// Asset name
143186
pub asset_name: AssetName,
144187
}
145188

@@ -156,15 +199,27 @@ impl From<sidechain_domain::AssetId> for Asset {
156199
}
157200
}
158201

159-
#[derive(Debug, Copy, Clone, sqlx::FromRow, PartialEq)]
160-
pub struct EpochNumberRow(pub EpochNumber);
161-
162-
impl From<EpochNumberRow> for EpochNumber {
163-
fn from(r: EpochNumberRow) -> Self {
164-
r.0
202+
/// Helper row type for querying just epoch number
203+
#[allow(deprecated)]
204+
mod epoch_number_row {
205+
use super::*;
206+
#[deprecated(
207+
since = "1.7.0",
208+
note = "Deprecated due to not being either a primitive type or a complete Db-Sync table row."
209+
)]
210+
#[derive(Debug, Copy, Clone, sqlx::FromRow, PartialEq)]
211+
pub struct EpochNumberRow(pub EpochNumber);
212+
213+
#[allow(deprecated)]
214+
impl From<EpochNumberRow> for EpochNumber {
215+
fn from(r: EpochNumberRow) -> Self {
216+
r.0
217+
}
165218
}
166219
}
220+
pub use epoch_number_row::*;
167221

222+
/// Cardano address in human-readable form. Either Base58 for Byron addresses and Bech32 for Shelley.
168223
#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
169224
pub struct Address(pub String);
170225

@@ -174,5 +229,8 @@ impl From<MainchainAddress> for Address {
174229
}
175230
}
176231

232+
/// Cardano epoch nonce, ie. random 32 bytes generated by Cardano every epoch.
233+
///
234+
/// This value can be used as a tamper-proof randomness seed.
177235
#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
178236
pub struct MainchainEpochNonce(pub Vec<u8>);

toolkit/utils/plutus/src/lib.rs

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,68 @@
1+
//! Minimal Plutus data types and encoding implementation
2+
//!
3+
//! This crate implements the `Data` type used by [Untyped Plutus Core], a low-level language
4+
//! used by Cardano smart contracts, along with traits for encoding Rust types as Plutus data
5+
//! and Plutus data CBOR bytes.
6+
//!
7+
//! This crate is developed as part of the [Partner Chains toolkit] for use in [no_std] contexts
8+
//! where existing alternatives ([uplc], [cardano-serialization-lib]) can not be used, and as
9+
//! such is not intended to be feature-complete for general use.
10+
//!
11+
//! [Untyped Plutus Core]: https://plutonomicon.github.io/plutonomicon/uplc
12+
//! [Partner Chains toolkit]: https://github.com/input-output-hk/partner-chains
13+
//! [no_std]: https://doc.rust-lang.org/reference/names/preludes.html?highlight=no_std#r-names.preludes.extern.no_std
14+
//! [uplc]: https://github.com/aiken-lang/aiken/tree/main/crates/uplc
15+
//! [cardano-serialization-lib]: https://github.com/Emurgo/cardano-serialization-lib
116
#![no_std]
17+
#![deny(missing_docs)]
218

319
mod cbor;
420

521
extern crate alloc;
622

723
use crate::Datum::*;
24+
#[doc(hidden)]
825
pub use alloc::{vec, vec::Vec};
926
use core::fmt::{Debug, Formatter};
1027
use num_bigint::BigInt;
1128

29+
/// Plutus datum type
1230
#[derive(Clone, PartialEq)]
1331
pub enum Datum {
32+
/// Integer value
1433
IntegerDatum(BigInt),
34+
/// Byte string value
1535
ByteStringDatum(Vec<u8>),
16-
ConstructorDatum { constructor: u64, fields: Vec<Datum> },
36+
/// Constructor value
37+
///
38+
/// A Plutus constructor datum consists of an ordered list of Plutus field values together
39+
/// with numeric constructor ID that marks the constructor variant used. These can only be
40+
/// interpreted against an external schema that specifies expected content of `fields` and
41+
/// their interpretation.
42+
ConstructorDatum {
43+
/// Constructor variant number
44+
constructor: u64,
45+
/// List of field values
46+
fields: Vec<Datum>,
47+
},
48+
/// List of values
1749
ListDatum(Vec<Datum>),
50+
/// Key-value mapping
1851
MapDatum(Vec<MapDatumEntry>),
1952
}
2053

54+
/// Key-value pair stored in [Datum::MapDatum]
2155
#[derive(Clone, Debug, PartialEq)]
2256
pub struct MapDatumEntry {
57+
/// Key
2358
key: Datum,
59+
/// Value
2460
value: Datum,
2561
}
2662

63+
/// Trait for types that can be encoded as a Plutus [Datum].
2764
pub trait ToDatum {
65+
/// Encodes `self` to [Datum].
2866
fn to_datum(&self) -> Datum;
2967
}
3068

@@ -81,6 +119,7 @@ impl Datum {
81119
IntegerDatum(BigInt::from(value))
82120
}
83121

122+
/// Returns byte content if `self` is a [Datum::ByteStringDatum] and [None] otherwise.
84123
pub fn as_bytestring(&self) -> Option<&Vec<u8>> {
85124
match self {
86125
ByteStringDatum(bytes) => Some(bytes),
@@ -118,9 +157,13 @@ impl Debug for Datum {
118157
}
119158
}
120159

121-
// tip: this function accepts Option<T> for any T: Datum
122-
// so it's better to call it with explicit type to avoid hard to
123-
// find bugs when types change
160+
/// Encodes a message as a Plutus [Datum] and returns [CBOR] encoding of this datum.
161+
///
162+
/// tip: this function accepts `Option<T>` for any `T: Datum`
163+
/// so it's better to call it with explicit type to avoid hard to
164+
/// find bugs when types change
165+
///
166+
/// [CBOR]: https://cbor.io
124167
pub fn to_datum_cbor_bytes<T: ToDatum>(msg: T) -> Vec<u8> {
125168
minicbor::to_vec(msg.to_datum()).expect("Infallible error type never fails")
126169
}

0 commit comments

Comments
 (0)