Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Jakub Zajkowski committed Aug 14, 2024
1 parent 6c9537c commit ee01db4
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 38 deletions.
106 changes: 78 additions & 28 deletions types/src/transaction/transaction_target.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
use alloc::vec::Vec;
use core::fmt::{self, Debug, Display, Formatter};

use super::{
serialization::{BinaryPayload, CalltableFromBytes, CalltableToBytes},
TransactionInvocationTarget, TransactionRuntime,
};
use crate::bytesrepr::{self, Bytes, ToBytes};
#[cfg(any(feature = "testing", test))]
use crate::testing::TestRng;
#[cfg(feature = "datasize")]
use datasize::DataSize;
use macros::{CalltableFromBytes, CalltableToBytes};
#[cfg(any(feature = "testing", test))]
use rand::{Rng, RngCore};
#[cfg(feature = "json-schema")]
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

#[cfg(doc)]
use super::Transaction;
use super::{TransactionInvocationTarget, TransactionRuntime};
use crate::bytesrepr::{self, Bytes, FromBytes, ToBytes, U8_SERIALIZED_LENGTH};
#[cfg(any(feature = "testing", test))]
use crate::testing::TestRng;

const NATIVE_TAG: u8 = 0;
const STORED_TAG: u8 = 1;
const SESSION_TAG: u8 = 2;

/// The execution target of a [`Transaction`].
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize)]
#[cfg_attr(feature = "datasize", derive(DataSize))]
Expand All @@ -26,29 +29,21 @@ use serde::{Deserialize, Serialize};
schemars(description = "Execution target of a Transaction.")
)]
#[serde(deny_unknown_fields)]
#[derive(CalltableToBytes, CalltableFromBytes)]
pub enum TransactionTarget {
/// The execution target is a native operation (e.g. a transfer).
#[calltable(variant_index = 0)]
Native,
/// The execution target is a stored entity or package.
#[calltable(variant_index = 1)]
Stored {
/// The identifier of the stored execution target.
#[calltable(field_index = 1)]
id: TransactionInvocationTarget,
/// The execution runtime to use.
#[calltable(field_index = 2)]
runtime: TransactionRuntime,
},
/// The execution target is the included module bytes, i.e. compiled Wasm.
#[calltable(variant_index = 2)]
Session {
/// The compiled Wasm.
#[calltable(field_index = 1)]
module_bytes: Bytes,
/// The execution runtime to use.
#[calltable(field_index = 2)]
runtime: TransactionRuntime,
},
}
Expand Down Expand Up @@ -76,12 +71,12 @@ impl TransactionTarget {
#[cfg(any(feature = "testing", test))]
pub fn random(rng: &mut TestRng) -> Self {
match rng.gen_range(0..3) {
0 => TransactionTarget::Native,
1 => TransactionTarget::new_stored(
NATIVE_TAG => TransactionTarget::Native,
STORED_TAG => TransactionTarget::new_stored(
TransactionInvocationTarget::random(rng),
TransactionRuntime::VmCasperV1,
),
2 => {
SESSION_TAG => {
let mut buffer = vec![0u8; rng.gen_range(0..100)];
rng.fill_bytes(buffer.as_mut());
TransactionTarget::new_session(Bytes::from(buffer), TransactionRuntime::VmCasperV1)
Expand Down Expand Up @@ -141,23 +136,78 @@ impl Debug for TransactionTarget {
}
}

impl ToBytes for TransactionTarget {
fn write_bytes(&self, writer: &mut Vec<u8>) -> Result<(), bytesrepr::Error> {
match self {
TransactionTarget::Native => NATIVE_TAG.write_bytes(writer),
TransactionTarget::Stored { id, runtime } => {
STORED_TAG.write_bytes(writer)?;
id.write_bytes(writer)?;
runtime.write_bytes(writer)
}
TransactionTarget::Session {
module_bytes,
runtime,
} => {
SESSION_TAG.write_bytes(writer)?;
module_bytes.write_bytes(writer)?;
runtime.write_bytes(writer)
}
}
}

fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
let mut buffer = bytesrepr::allocate_buffer(self)?;
self.write_bytes(&mut buffer)?;
Ok(buffer)
}

fn serialized_length(&self) -> usize {
U8_SERIALIZED_LENGTH
+ match self {
TransactionTarget::Native => 0,
TransactionTarget::Stored { id, runtime } => {
id.serialized_length() + runtime.serialized_length()
}
TransactionTarget::Session {
module_bytes,
runtime,
} => module_bytes.serialized_length() + runtime.serialized_length(),
}
}
}

impl FromBytes for TransactionTarget {
fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> {
let (tag, remainder) = u8::from_bytes(bytes)?;
match tag {
NATIVE_TAG => Ok((TransactionTarget::Native, remainder)),
STORED_TAG => {
let (id, remainder) = TransactionInvocationTarget::from_bytes(remainder)?;
let (runtime, remainder) = TransactionRuntime::from_bytes(remainder)?;
let target = TransactionTarget::new_stored(id, runtime);
Ok((target, remainder))
}
SESSION_TAG => {
let (module_bytes, remainder) = Bytes::from_bytes(remainder)?;
let (runtime, remainder) = TransactionRuntime::from_bytes(remainder)?;
let target = TransactionTarget::new_session(module_bytes, runtime);
Ok((target, remainder))
}
_ => Err(bytesrepr::Error::Formatting),
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::gens::transaction_target_arb;
use proptest::prelude::*;

#[test]
fn bytesrepr_roundtrip() {
let rng = &mut TestRng::new();
for _ in 0..10 {
bytesrepr::test_serialization_roundtrip(&TransactionTarget::random(rng));
}
}

proptest! {
#[test]
fn generative_bytesrepr_roundtrip(val in transaction_target_arb()) {
bytesrepr::test_serialization_roundtrip(&val);
}
}
}
57 changes: 47 additions & 10 deletions types/src/transaction/transaction_v1/transaction_v1_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,11 @@ use tracing::debug;
use super::TransactionV1;
use super::{InitiatorAddr, PricingMode};
use crate::{
bytesrepr::{self, ToBytes},
transaction::serialization::{BinaryPayload, CalltableFromBytes, CalltableToBytes},
bytesrepr::{self, FromBytes, ToBytes},
Digest, TimeDiff, Timestamp,
};
#[cfg(any(feature = "std", test))]
use crate::{InvalidTransactionV1, TransactionConfig, TransactionV1Hash};
use macros::{CalltableFromBytes, CalltableToBytes};

/// The header portion of a [`TransactionV1`].
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
Expand All @@ -35,19 +33,12 @@ use macros::{CalltableFromBytes, CalltableToBytes};
derive(JsonSchema),
schemars(description = "The header portion of a TransactionV1.")
)]
#[derive(CalltableToBytes, CalltableFromBytes)]
pub struct TransactionV1Header {
#[calltable(field_index = 0)]
chain_name: String,
#[calltable(field_index = 1)]
timestamp: Timestamp,
#[calltable(field_index = 2)]
ttl: TimeDiff,
#[calltable(field_index = 3)]
body_hash: Digest,
#[calltable(field_index = 4)]
pricing_mode: PricingMode,
#[calltable(field_index = 5)]
initiator_addr: InitiatorAddr,
}

Expand Down Expand Up @@ -184,6 +175,52 @@ impl TransactionV1Header {
}
}

impl ToBytes for TransactionV1Header {
fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
let mut buffer = bytesrepr::allocate_buffer(self)?;
self.write_bytes(&mut buffer)?;
Ok(buffer)
}

fn serialized_length(&self) -> usize {
self.chain_name.serialized_length()
+ self.timestamp.serialized_length()
+ self.ttl.serialized_length()
+ self.body_hash.serialized_length()
+ self.pricing_mode.serialized_length()
+ self.initiator_addr.serialized_length()
}

fn write_bytes(&self, writer: &mut Vec<u8>) -> Result<(), bytesrepr::Error> {
self.chain_name.write_bytes(writer)?;
self.timestamp.write_bytes(writer)?;
self.ttl.write_bytes(writer)?;
self.body_hash.write_bytes(writer)?;
self.pricing_mode.write_bytes(writer)?;
self.initiator_addr.write_bytes(writer)
}
}

impl FromBytes for TransactionV1Header {
fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> {
let (chain_name, remainder) = String::from_bytes(bytes)?;
let (timestamp, remainder) = Timestamp::from_bytes(remainder)?;
let (ttl, remainder) = TimeDiff::from_bytes(remainder)?;
let (body_hash, remainder) = Digest::from_bytes(remainder)?;
let (pricing_mode, remainder) = PricingMode::from_bytes(remainder)?;
let (initiator_addr, remainder) = InitiatorAddr::from_bytes(remainder)?;
let transaction_header = TransactionV1Header {
chain_name,
timestamp,
ttl,
body_hash,
pricing_mode,
initiator_addr,
};
Ok((transaction_header, remainder))
}
}

impl Display for TransactionV1Header {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
#[cfg(any(feature = "std", test))]
Expand Down

0 comments on commit ee01db4

Please sign in to comment.