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

v3: Change SDK::send's params to take new type IpldBlock #1152

Merged
merged 1 commit into from
Dec 17, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
129 changes: 65 additions & 64 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions ipld/encoding/src/cbor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ use serde::{Deserialize, Serialize};
use super::errors::Error;
use crate::{de, from_slice, ser, strict_bytes, to_vec};

pub const DAG_CBOR: u64 = 0x71;

/// Cbor utility functions for serializable objects
pub trait Cbor: ser::Serialize + de::DeserializeOwned {
/// Marshalls cbor encodable object into cbor bytes
Expand Down
5 changes: 5 additions & 0 deletions ipld/encoding/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,19 @@ impl From<Error> for io::Error {
/// This is used with the encoding errors, to detail the encoding protocol or any other
/// information about how the data was encoded or decoded
#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum CodecProtocol {
Unsupported,
Cbor,
Raw,
}

impl fmt::Display for CodecProtocol {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
CodecProtocol::Unsupported => write!(f, "Unsupported"),
CodecProtocol::Cbor => write!(f, "Cbor"),
CodecProtocol::Raw => write!(f, "Raw"),
}
}
}
59 changes: 59 additions & 0 deletions ipld/encoding/src/ipld_block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright 2021-2023 Protocol Labs
// SPDX-License-Identifier: Apache-2.0, MIT
use serde::de::value;
use {serde, serde_ipld_dagcbor};

use crate::{CodecProtocol, Error, RawBytes, DAG_CBOR, IPLD_RAW};

#[derive(Debug, PartialEq, Eq, Clone, Default)]
pub struct IpldBlock {
pub codec: u64,
pub data: Vec<u8>,
}

impl IpldBlock {
pub fn deserialize<'de, T>(&'de self) -> Result<T, Error>
where
T: serde::Deserialize<'de>,
{
match self.codec {
IPLD_RAW => T::deserialize(value::BytesDeserializer::<value::Error>::new(
self.data.as_slice(),
))
.map_err(|e| Error {
description: e.to_string(),
protocol: CodecProtocol::Raw,
}),
DAG_CBOR => Ok(serde_ipld_dagcbor::from_slice(self.data.as_slice())?),
_ => Err(Error {
description: "unsupported protocol".to_string(),
protocol: CodecProtocol::Unsupported,
}),
}
}
pub fn serialize<T: serde::Serialize + ?Sized>(codec: u64, value: &T) -> Result<Self, Error> {
let data = match codec {
IPLD_RAW => crate::raw::to_vec(value)?,
DAG_CBOR => crate::to_vec(value)?,
_ => {
return Err(Error {
description: "unsupported protocol".to_string(),
protocol: CodecProtocol::Unsupported,
});
}
};
Ok(IpldBlock { codec, data })
}
pub fn serialize_cbor<T: serde::Serialize + ?Sized>(value: &T) -> Result<Self, Error> {
IpldBlock::serialize(DAG_CBOR, value)
}
}

impl From<RawBytes> for Option<IpldBlock> {
fn from(other: RawBytes) -> Self {
(!other.is_empty()).then(|| IpldBlock {
codec: DAG_CBOR,
data: other.into(),
})
}
}
5 changes: 5 additions & 0 deletions ipld/encoding/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ mod bytes;
mod cbor;
mod cbor_store;
mod errors;
pub mod ipld_block;
mod raw;
mod vec;
use std::io;

Expand All @@ -17,6 +19,9 @@ pub use self::cbor_store::CborStore;
pub use self::errors::*;
pub use self::vec::*;

pub const DAG_CBOR: u64 = 0x71;
pub const IPLD_RAW: u64 = 0x55;

// TODO: these really don't work all that well in a shared context like this as anyone importing
// them also need to _explicitly_ import the serde_tuple & serde_repr crates. These are _macros_,
// not normal items.
Expand Down
169 changes: 169 additions & 0 deletions ipld/encoding/src/raw.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
// Copyright 2021-2023 Protocol Labs
// SPDX-License-Identifier: Apache-2.0, MIT
use thiserror::Error;

/// Serialize the given value to a vec. This method rejects all types except "raw bytes".
pub fn to_vec<T: serde::Serialize + ?Sized>(value: &T) -> Result<Vec<u8>, super::Error> {
serde::Serialize::serialize(value, Serializer).map_err(|e| super::Error {
description: e.to_string(),
protocol: crate::CodecProtocol::Raw,
})
}

#[derive(Error, Debug)]
enum Error {
#[error("IPLD kind not supported by the raw codec")]
KindNotSupported,
#[error("i/o error when serializing: {0}")]
Other(String),
}

impl serde::ser::Error for Error {
fn custom<T>(msg: T) -> Self
where
T: std::fmt::Display,
{
Error::Other(msg.to_string())
}
}

struct Serializer;

macro_rules! reject {
($($method:ident $t:ty),*) => {
$(
fn $method(self, _: $t) -> Result<Self::Ok, Self::Error> {
Err(Error::KindNotSupported)
}
)*
};
}

impl serde::ser::Serializer for Serializer {
type Ok = Vec<u8>;
type Error = Error;
type SerializeSeq = serde::ser::Impossible<Vec<u8>, Error>;
type SerializeTuple = serde::ser::Impossible<Vec<u8>, Error>;
type SerializeTupleStruct = serde::ser::Impossible<Vec<u8>, Error>;
type SerializeTupleVariant = serde::ser::Impossible<Vec<u8>, Error>;
type SerializeMap = serde::ser::Impossible<Vec<u8>, Error>;
type SerializeStruct = serde::ser::Impossible<Vec<u8>, Error>;
type SerializeStructVariant = serde::ser::Impossible<Vec<u8>, Error>;

fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
Ok(v.to_owned())
}

reject! {
serialize_bool bool,
serialize_i8 i8,
serialize_i16 i16,
serialize_i32 i32,
serialize_i64 i64,
serialize_u8 u8,
serialize_u16 u16,
serialize_u32 u32,
serialize_u64 u64,
serialize_f32 f32,
serialize_f64 f64,
serialize_char char,
serialize_str &str,
serialize_unit_struct &'static str
}

fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Err(Error::KindNotSupported)
}

fn serialize_some<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
where
T: serde::Serialize,
{
Err(Error::KindNotSupported)
}

fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Err(Error::KindNotSupported)
}

fn serialize_unit_variant(
self,
_: &'static str,
_: u32,
_: &'static str,
) -> Result<Self::Ok, Self::Error> {
Err(Error::KindNotSupported)
}

fn serialize_newtype_struct<T: ?Sized>(
self,
_: &'static str,
_: &T,
) -> Result<Self::Ok, Self::Error>
where
T: serde::Serialize,
{
Err(Error::KindNotSupported)
}

fn serialize_newtype_variant<T: ?Sized>(
self,
_: &'static str,
_: u32,
_: &'static str,
_: &T,
) -> Result<Self::Ok, Self::Error>
where
T: serde::Serialize,
{
Err(Error::KindNotSupported)
}

fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
Err(Error::KindNotSupported)
}

fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
Err(Error::KindNotSupported)
}

fn serialize_tuple_struct(
self,
_: &'static str,
_: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error> {
Err(Error::KindNotSupported)
}

fn serialize_tuple_variant(
self,
_: &'static str,
_: u32,
_: &'static str,
_: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
Err(Error::KindNotSupported)
}

fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
Err(Error::KindNotSupported)
}

fn serialize_struct(
self,
_: &'static str,
_: usize,
) -> Result<Self::SerializeStruct, Self::Error> {
Err(Error::KindNotSupported)
}

fn serialize_struct_variant(
self,
_: &'static str,
_: u32,
_: &'static str,
_: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
Err(Error::KindNotSupported)
}
}
15 changes: 9 additions & 6 deletions sdk/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
// SPDX-License-Identifier: Apache-2.0, MIT
use std::convert::TryInto;

use fvm_ipld_encoding::DAG_CBOR;
use fvm_ipld_encoding::ipld_block::IpldBlock;
use fvm_shared::econ::TokenAmount;
use fvm_shared::sys::out::vm::MessageContext;
use fvm_shared::sys::{BlockId, Codec};
use fvm_shared::sys::BlockId;
use fvm_shared::{ActorID, MethodNum};

use crate::{sys, SyscallResult, NO_DATA_BLOCK_ID};
Expand Down Expand Up @@ -65,13 +65,16 @@ pub fn gas_premium() -> TokenAmount {
.expect("invalid bigint")
}

/// Returns the message codec and parameters.
pub fn params_raw(id: BlockId) -> SyscallResult<(Codec, Vec<u8>)> {
/// Returns the message parameters as an Option<IpldBlock>.
pub fn params_raw(id: BlockId) -> SyscallResult<Option<IpldBlock>> {
if id == NO_DATA_BLOCK_ID {
return Ok((DAG_CBOR, Vec::default())); // DAG_CBOR is a lie, but we have no nil codec.
return Ok(None);
}
unsafe {
let fvm_shared::sys::out::ipld::IpldStat { codec, size } = sys::ipld::block_stat(id)?;
Ok((codec, crate::ipld::get_block(id, Some(size))?))
Ok(Some(IpldBlock {
codec,
data: crate::ipld::get_block(id, Some(size))?,
}))
}
}
12 changes: 6 additions & 6 deletions sdk/src/send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
// SPDX-License-Identifier: Apache-2.0, MIT
use std::convert::TryInto;

use fvm_ipld_encoding::{RawBytes, DAG_CBOR};
use fvm_ipld_encoding::ipld_block::IpldBlock;
use fvm_ipld_encoding::RawBytes;
use fvm_shared::address::Address;
use fvm_shared::econ::TokenAmount;
use fvm_shared::error::{ErrorNumber, ExitCode};
Expand All @@ -18,7 +19,7 @@ use crate::{sys, SyscallResult, NO_DATA_BLOCK_ID};
pub fn send(
to: &Address,
method: MethodNum,
params: RawBytes,
params: Option<IpldBlock>,
value: TokenAmount,
gas_limit: Option<u64>,
flags: SendFlags,
Expand All @@ -30,10 +31,9 @@ pub fn send(
unsafe {
// Insert parameters as a block. Nil parameters is represented as the
// NO_DATA_BLOCK_ID block ID in the FFI interface.
let params_id = if params.len() > 0 {
sys::ipld::block_create(DAG_CBOR, params.as_ptr(), params.len() as u32)?
} else {
NO_DATA_BLOCK_ID
let params_id = match params {
Some(p) => sys::ipld::block_create(p.codec, p.data.as_ptr(), p.data.len() as u32)?,
None => NO_DATA_BLOCK_ID,
};

// Perform the syscall to send the message.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0, MIT
use anyhow::{anyhow, Result};
use cid::multihash::Code;
use fvm_ipld_encoding::{RawBytes, DAG_CBOR};
use fvm_ipld_encoding::DAG_CBOR;
use fvm_sdk::message::params_raw;
use fvm_sdk::vm::abort;
use fvm_shared::address::{Address, Protocol};
Expand Down Expand Up @@ -225,7 +225,7 @@ fn lcg8(seed: u64) -> impl Iterator<Item = u8> {
}

fn read_params<T: DeserializeOwned>(params_ptr: u32) -> Result<T> {
let params = params_raw(params_ptr)?.1;
let value = RawBytes::new(params).deserialize()?;
let params = params_raw(params_ptr).unwrap().unwrap();
let value = params.deserialize()?;
Ok(value)
}
Loading