Skip to content

Commit

Permalink
Two more Packable derive (#1730)
Browse files Browse the repository at this point in the history
* Derive Packable for SignedTransactionPayload

* Derive Packable for BlockHeader
  • Loading branch information
thibault-martinez authored Dec 4, 2023
1 parent e794536 commit 6d91fc2
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 86 deletions.
77 changes: 25 additions & 52 deletions sdk/src/types/block/core/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use core::mem::size_of;
use crypto::hashes::{blake2b::Blake2b256, Digest};
use getset::{CopyGetters, Getters};
use packable::{
error::{UnexpectedEOF, UnpackError, UnpackErrorExt},
error::{UnexpectedEOF, UnpackError},
packer::{Packer, SlicePacker},
unpacker::{CounterUnpacker, SliceUnpacker, Unpacker},
Packable, PackableExt,
Expand Down Expand Up @@ -61,12 +61,16 @@ impl UnsignedBlock {
}
}

#[derive(Clone, Debug, Eq, PartialEq, CopyGetters)]
#[derive(Clone, Debug, Eq, PartialEq, CopyGetters, Packable)]
#[packable(unpack_error = Error)]
#[packable(unpack_visitor = ProtocolParameters)]
#[getset(get_copy = "pub")]
pub struct BlockHeader {
/// Protocol version of the network to which this block belongs.
#[packable(verify_with = verify_protocol_version)]
protocol_version: u8,
/// The identifier of the network to which this block belongs.
#[packable(verify_with = verify_network_id)]
network_id: u64,
/// The time at which the block was issued. It is a Unix timestamp in nanoseconds.
issuing_time: u64,
Expand Down Expand Up @@ -111,60 +115,29 @@ impl BlockHeader {

impl WorkScore for BlockHeader {}

impl Packable for BlockHeader {
type UnpackError = Error;
type UnpackVisitor = ProtocolParameters;

fn pack<P: Packer>(&self, packer: &mut P) -> Result<(), P::Error> {
self.protocol_version.pack(packer)?;
self.network_id.pack(packer)?;
self.issuing_time.pack(packer)?;
self.slot_commitment_id.pack(packer)?;
self.latest_finalized_slot.pack(packer)?;
self.issuer_id.pack(packer)?;

Ok(())
fn verify_protocol_version<const VERIFY: bool>(
protocol_version: &u8,
params: &ProtocolParameters,
) -> Result<(), Error> {
if VERIFY && *protocol_version != params.version() {
return Err(Error::ProtocolVersionMismatch {
expected: params.version(),
actual: *protocol_version,
});
}

fn unpack<U: Unpacker, const VERIFY: bool>(
unpacker: &mut U,
protocol_params: &Self::UnpackVisitor,
) -> Result<Self, UnpackError<Self::UnpackError, U::Error>> {
let protocol_version = u8::unpack::<_, VERIFY>(unpacker, &()).coerce()?;

if VERIFY && protocol_version != protocol_params.version() {
return Err(UnpackError::Packable(Error::ProtocolVersionMismatch {
expected: protocol_params.version(),
actual: protocol_version,
}));
}

let network_id = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?;

if VERIFY && network_id != protocol_params.network_id() {
return Err(UnpackError::Packable(Error::NetworkIdMismatch {
expected: protocol_params.network_id(),
actual: network_id,
}));
}

let issuing_time = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?;

let slot_commitment_id = SlotCommitmentId::unpack::<_, VERIFY>(unpacker, &()).coerce()?;

let latest_finalized_slot = SlotIndex::unpack::<_, VERIFY>(unpacker, &()).coerce()?;

let issuer_id = AccountId::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
Ok(())
}

Ok(Self {
protocol_version,
network_id,
issuing_time,
slot_commitment_id,
latest_finalized_slot,
issuer_id,
})
fn verify_network_id<const VERIFY: bool>(network_id: &u64, params: &ProtocolParameters) -> Result<(), Error> {
if VERIFY && *network_id != params.network_id() {
return Err(Error::NetworkIdMismatch {
expected: params.network_id(),
actual: *network_id,
});
}

Ok(())
}

/// Represent the object that nodes gossip around the network.
Expand Down
46 changes: 12 additions & 34 deletions sdk/src/types/block/payload/signed_transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
mod transaction;
mod transaction_id;

use packable::{error::UnpackError, packer::Packer, unpacker::Unpacker, Packable, PackableExt};
use packable::{Packable, PackableExt};

pub(crate) use self::transaction::{ContextInputCount, InputCount, OutputCount};
pub use self::{
Expand All @@ -20,7 +20,9 @@ use crate::types::block::{
};

/// A signed transaction to move funds.
#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Eq, PartialEq, Packable)]
#[packable(unpack_error = Error)]
#[packable(verify_with = verify_signed_transaction_payload)]
pub struct SignedTransactionPayload {
transaction: Transaction,
unlocks: Unlocks,
Expand All @@ -32,9 +34,11 @@ impl SignedTransactionPayload {

/// Creates a new [`SignedTransactionPayload`].
pub fn new(transaction: Transaction, unlocks: Unlocks) -> Result<Self, Error> {
verify_transaction_unlocks(&transaction, &unlocks)?;
let payload = Self { transaction, unlocks };

Ok(Self { transaction, unlocks })
verify_signed_transaction_payload::<true>(&payload)?;

Ok(payload)
}

/// Returns the transaction of a [`SignedTransactionPayload`].
Expand All @@ -57,37 +61,11 @@ impl WorkScore for SignedTransactionPayload {
}
}

impl Packable for SignedTransactionPayload {
type UnpackError = Error;
type UnpackVisitor = ProtocolParameters;

fn pack<P: Packer>(&self, packer: &mut P) -> Result<(), P::Error> {
self.transaction.pack(packer)?;
self.unlocks.pack(packer)?;

Ok(())
}

fn unpack<U: Unpacker, const VERIFY: bool>(
unpacker: &mut U,
visitor: &Self::UnpackVisitor,
) -> Result<Self, UnpackError<Self::UnpackError, U::Error>> {
let transaction = Transaction::unpack::<_, VERIFY>(unpacker, visitor)?;
let unlocks = Unlocks::unpack::<_, VERIFY>(unpacker, &())?;

if VERIFY {
verify_transaction_unlocks(&transaction, &unlocks).map_err(UnpackError::Packable)?;
}

Ok(Self { transaction, unlocks })
}
}

fn verify_transaction_unlocks(transaction: &Transaction, unlocks: &Unlocks) -> Result<(), Error> {
if transaction.inputs().len() != unlocks.len() {
fn verify_signed_transaction_payload<const VERIFY: bool>(payload: &SignedTransactionPayload) -> Result<(), Error> {
if payload.transaction.inputs().len() != payload.unlocks.len() {
return Err(Error::InputUnlockCountMismatch {
input_count: transaction.inputs().len(),
unlock_count: unlocks.len(),
input_count: payload.transaction.inputs().len(),
unlock_count: payload.unlocks.len(),
});
}

Expand Down

0 comments on commit 6d91fc2

Please sign in to comment.