mirror of
https://github.com/hinto-janai/cuprate.git
synced 2024-11-16 15:58:14 +00:00
From
serai types
This commit is contained in:
parent
4a1821e5e7
commit
a5316ad331
5 changed files with 226 additions and 18 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -885,9 +885,11 @@ dependencies = [
|
|||
name = "cuprate-types"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"bytes",
|
||||
"cuprate-epee-encoding",
|
||||
"cuprate-fixed-bytes",
|
||||
"cuprate-helper",
|
||||
"curve25519-dalek",
|
||||
"hex",
|
||||
"monero-serai",
|
||||
|
|
|
@ -13,14 +13,17 @@ default = ["blockchain", "epee", "serde", "json", "hex"]
|
|||
blockchain = []
|
||||
epee = ["dep:cuprate-epee-encoding"]
|
||||
serde = ["dep:serde"]
|
||||
bytemuck = ["dep:bytemuck"]
|
||||
proptest = ["dep:proptest", "dep:proptest-derive"]
|
||||
json = ["hex"]
|
||||
json = ["hex", "bytemuck", "dep:cuprate-helper"]
|
||||
hex = ["dep:hex", "dep:paste"]
|
||||
|
||||
[dependencies]
|
||||
cuprate-epee-encoding = { path = "../net/epee-encoding", optional = true }
|
||||
cuprate-helper = { path = "../helper", optional = true, features = ["cast"] }
|
||||
cuprate-fixed-bytes = { path = "../net/fixed-bytes" }
|
||||
|
||||
bytemuck = { workspace = true, features = ["derive"], optional = true }
|
||||
bytes = { workspace = true }
|
||||
curve25519-dalek = { workspace = true }
|
||||
monero-serai = { workspace = true }
|
||||
|
|
|
@ -3,6 +3,16 @@
|
|||
//! This module provides transparent wrapper types for
|
||||
//! arrays that (de)serialize from hexadecimal input/output.
|
||||
|
||||
#![cfg_attr(
|
||||
feature = "bytemuck",
|
||||
expect(
|
||||
clippy::allow_attributes,
|
||||
reason = "bytemuck uses allow in its derive macros"
|
||||
)
|
||||
)]
|
||||
|
||||
#[cfg(feature = "bytemuck")]
|
||||
use bytemuck::{Pod, TransparentWrapper, Zeroable};
|
||||
#[cfg(feature = "epee")]
|
||||
use cuprate_epee_encoding::{error, macros::bytes, EpeeValue, Marker};
|
||||
#[cfg(feature = "serde")]
|
||||
|
@ -19,6 +29,7 @@ macro_rules! generate_hex_array {
|
|||
$(
|
||||
#[doc = concat!("Wrapper type that (de)serializes from/to a ", stringify!($array_len), "-byte array.")]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "bytemuck", derive(Pod, Zeroable, TransparentWrapper))]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(transparent))]
|
||||
#[repr(transparent)]
|
||||
|
|
|
@ -3,7 +3,14 @@
|
|||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{hex::HexBytes32, json::output::Output};
|
||||
use monero_serai::{block, transaction};
|
||||
|
||||
use cuprate_helper::cast::usize_to_u64;
|
||||
|
||||
use crate::{
|
||||
hex::{HexBytes1, HexBytes32},
|
||||
json::output::{Output, TaggedKey, Target},
|
||||
};
|
||||
|
||||
/// JSON representation of a block.
|
||||
///
|
||||
|
@ -21,19 +28,25 @@ pub struct Block {
|
|||
pub tx_hashes: Vec<HexBytes32>,
|
||||
}
|
||||
|
||||
// impl From<monero_serai::block::Block> for Block {
|
||||
// fn from(b: monero_serai::block::Block) -> Self {
|
||||
// Self {
|
||||
// major_version: todo!(),
|
||||
// minor_version: todo!(),
|
||||
// timestamp: todo!(),
|
||||
// prev_id: todo!(),
|
||||
// nonce: todo!(),
|
||||
// miner_tx: todo!(),
|
||||
// tx_hashes: todo!(),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
impl From<block::Block> for Block {
|
||||
fn from(b: block::Block) -> Self {
|
||||
let Ok(miner_tx) = MinerTransaction::try_from(b.miner_transaction) else {
|
||||
unreachable!("input is a miner tx, this should never fail");
|
||||
};
|
||||
|
||||
let tx_hashes = b.transactions.into_iter().map(HexBytes32).collect();
|
||||
|
||||
Self {
|
||||
major_version: b.header.hardfork_version,
|
||||
minor_version: b.header.hardfork_signal,
|
||||
timestamp: b.header.timestamp,
|
||||
prev_id: HexBytes32(b.header.previous),
|
||||
nonce: b.header.nonce,
|
||||
miner_tx,
|
||||
tx_hashes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// [`Block::miner_tx`].
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
|
@ -54,6 +67,98 @@ pub enum MinerTransaction {
|
|||
},
|
||||
}
|
||||
|
||||
impl TryFrom<transaction::Transaction> for MinerTransaction {
|
||||
type Error = transaction::Transaction;
|
||||
|
||||
/// # Errors
|
||||
/// This function errors if the input is not a miner transaction.
|
||||
fn try_from(tx: transaction::Transaction) -> Result<Self, transaction::Transaction> {
|
||||
fn map_prefix(
|
||||
prefix: transaction::TransactionPrefix,
|
||||
version: u8,
|
||||
) -> Result<MinerTransactionPrefix, transaction::TransactionPrefix> {
|
||||
let Some(input) = prefix.inputs.first() else {
|
||||
return Err(prefix);
|
||||
};
|
||||
|
||||
let height = match input {
|
||||
transaction::Input::Gen(height) => usize_to_u64(*height),
|
||||
transaction::Input::ToKey { .. } => return Err(prefix),
|
||||
};
|
||||
|
||||
let vin = {
|
||||
let r#gen = Gen { height };
|
||||
let input = Input { r#gen };
|
||||
[input]
|
||||
};
|
||||
|
||||
let vout = prefix
|
||||
.outputs
|
||||
.into_iter()
|
||||
.map(|o| {
|
||||
let amount = o.amount.unwrap_or(0);
|
||||
|
||||
let target = match o.view_tag {
|
||||
Some(view_tag) => {
|
||||
let tagged_key = TaggedKey {
|
||||
key: HexBytes32(o.key.0),
|
||||
view_tag: HexBytes1([view_tag]),
|
||||
};
|
||||
|
||||
Target::TaggedKey { tagged_key }
|
||||
}
|
||||
None => Target::Key {
|
||||
key: HexBytes32(o.key.0),
|
||||
},
|
||||
};
|
||||
|
||||
Output { amount, target }
|
||||
})
|
||||
.collect();
|
||||
|
||||
// TODO: use cuprate_constants target time
|
||||
let unlock_time = match prefix.additional_timelock {
|
||||
transaction::Timelock::None => height,
|
||||
transaction::Timelock::Block(height_lock) => height + usize_to_u64(height_lock),
|
||||
transaction::Timelock::Time(seconds) => height + (seconds * 120),
|
||||
} + 60;
|
||||
|
||||
Ok(MinerTransactionPrefix {
|
||||
version,
|
||||
unlock_time,
|
||||
vin,
|
||||
vout,
|
||||
extra: prefix.extra,
|
||||
})
|
||||
}
|
||||
|
||||
Ok(match tx {
|
||||
transaction::Transaction::V1 { prefix, signatures } => {
|
||||
let prefix = match map_prefix(prefix, 1) {
|
||||
Ok(p) => p,
|
||||
Err(prefix) => return Err(transaction::Transaction::V1 { prefix, signatures }),
|
||||
};
|
||||
|
||||
Self::V1 {
|
||||
prefix,
|
||||
signatures: [(); 0],
|
||||
}
|
||||
}
|
||||
transaction::Transaction::V2 { prefix, proofs } => {
|
||||
let prefix = match map_prefix(prefix, 2) {
|
||||
Ok(p) => p,
|
||||
Err(prefix) => return Err(transaction::Transaction::V2 { prefix, proofs }),
|
||||
};
|
||||
|
||||
Self::V2 {
|
||||
prefix,
|
||||
rct_signatures: MinerTransactionRctSignatures { r#type: 0 },
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for MinerTransaction {
|
||||
fn default() -> Self {
|
||||
Self::V1 {
|
||||
|
@ -69,7 +174,7 @@ impl Default for MinerTransaction {
|
|||
pub struct MinerTransactionPrefix {
|
||||
pub version: u8,
|
||||
pub unlock_time: u64,
|
||||
pub vin: Vec<Input>,
|
||||
pub vin: [Input; 1],
|
||||
pub vout: Vec<Output>,
|
||||
pub extra: Vec<u8>,
|
||||
}
|
||||
|
|
|
@ -8,9 +8,13 @@
|
|||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use cuprate_helper::cast::usize_to_u64;
|
||||
|
||||
use monero_serai::transaction;
|
||||
|
||||
use crate::{
|
||||
hex::{HexBytes32, HexBytes64, HexBytes8},
|
||||
json::output::Output,
|
||||
hex::{HexBytes1, HexBytes32, HexBytes64, HexBytes8},
|
||||
json::output::{Output, TaggedKey, Target},
|
||||
};
|
||||
|
||||
/// JSON representation of a non-miner transaction.
|
||||
|
@ -48,6 +52,89 @@ pub struct TransactionPrefix {
|
|||
pub extra: Vec<u8>,
|
||||
}
|
||||
|
||||
impl From<transaction::Transaction> for Transaction {
|
||||
fn from(tx: transaction::Transaction) -> Self {
|
||||
fn map_prefix(prefix: transaction::TransactionPrefix, version: u8) -> TransactionPrefix {
|
||||
let mut height = 0;
|
||||
|
||||
let vin = prefix
|
||||
.inputs
|
||||
.into_iter()
|
||||
.filter_map(|input| match input {
|
||||
transaction::Input::ToKey {
|
||||
amount,
|
||||
key_offsets,
|
||||
key_image,
|
||||
} => {
|
||||
let key = Key {
|
||||
amount: amount.unwrap_or(0),
|
||||
key_offsets,
|
||||
k_image: HexBytes32(key_image.compress().0),
|
||||
};
|
||||
|
||||
Some(Input { key })
|
||||
}
|
||||
transaction::Input::Gen(h) => {
|
||||
height = usize_to_u64(h);
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let vout = prefix
|
||||
.outputs
|
||||
.into_iter()
|
||||
.map(|o| {
|
||||
let amount = o.amount.unwrap_or(0);
|
||||
|
||||
let target = match o.view_tag {
|
||||
Some(view_tag) => {
|
||||
let tagged_key = TaggedKey {
|
||||
key: HexBytes32(o.key.0),
|
||||
view_tag: HexBytes1([view_tag]),
|
||||
};
|
||||
|
||||
Target::TaggedKey { tagged_key }
|
||||
}
|
||||
None => Target::Key {
|
||||
key: HexBytes32(o.key.0),
|
||||
},
|
||||
};
|
||||
|
||||
Output { amount, target }
|
||||
})
|
||||
.collect();
|
||||
|
||||
// TODO: use cuprate_constants target time
|
||||
let unlock_time = match prefix.additional_timelock {
|
||||
transaction::Timelock::None => height,
|
||||
transaction::Timelock::Block(height_lock) => height + usize_to_u64(height_lock),
|
||||
transaction::Timelock::Time(seconds) => height + (seconds * 120),
|
||||
} + 60;
|
||||
|
||||
TransactionPrefix {
|
||||
version,
|
||||
unlock_time,
|
||||
vin,
|
||||
vout,
|
||||
extra: prefix.extra,
|
||||
}
|
||||
}
|
||||
|
||||
match tx {
|
||||
transaction::Transaction::V1 { prefix, signatures } => Self::V1 {
|
||||
prefix: map_prefix(prefix, 1),
|
||||
signatures: todo!(),
|
||||
},
|
||||
transaction::Transaction::V2 { prefix, proofs } => Self::V2 {
|
||||
prefix: map_prefix(prefix, 2),
|
||||
rct_signatures: todo!(),
|
||||
rctsig_prunable: todo!(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// [`Transaction::V2::rct_signatures`].
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
|
|
Loading…
Reference in a new issue