Skip to content

Commit

Permalink
Merge pull request #500 from Concordium/unify-wasm-versions
Browse files Browse the repository at this point in the history
Unify WasmVersion into concordium_contracts_common
  • Loading branch information
limemloh authored Jan 16, 2024
2 parents 12e71c8 + e11cf52 commit bd93a27
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 77 deletions.
2 changes: 2 additions & 0 deletions rust-src/concordium_base/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
- Change `Debug` instance of `dodis_yampolskiy_prf::SecretKey` to hide the value.
- Remove `Timestamp` to instead reexport the similar type from `concordium_contracts_common`.
This adds several new methods, but results in a breaking change in the `serde::Serialize` implementation, which is now using string containing RFC3393 representation instead the underlying milliseconds.
- Remove `smart_contracts::WasmVersion` to instead reexport a similar type from `concordium_contracts_common`.
This adds a `FromStr` implementation and changes the associated type `TryFrom<u8>::Error` from `anyhow::Error` to `concordium_contracts_common::U8WasmVersionConvertError`.

## 3.2.0 (2023-11-22)

Expand Down
45 changes: 2 additions & 43 deletions rust-src/concordium_base/src/smart_contracts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::{
},
constants::*,
};
pub use concordium_contracts_common::WasmVersion;
/// Re-export of common helper functionality for smart contract, such as types
/// and serialization specific for smart contracts.
pub use concordium_contracts_common::{
Expand All @@ -25,48 +26,6 @@ use std::convert::{TryFrom, TryInto};
)]
pub type Parameter = OwnedParameter;

#[derive(
SerdeSerialize, SerdeDeserialize, Debug, Copy, Clone, Display, PartialEq, Eq, PartialOrd, Ord,
)]
#[serde(try_from = "u8", into = "u8")]
#[repr(u8)]
/// Version of the module. This determines the chain API that the module can
/// access.
pub enum WasmVersion {
#[display = "V0"]
/// The initial smart contracts version. This has a simple state API that
/// has very limited capacity. `V0` contracts also use message-passing as
/// the interaction method.
V0 = 0u8,
#[display = "V1"]
/// `V1` contracts were introduced with protocol version 4. In comparison to
/// `V0` contracts they use synchronous calls as the interaction method,
/// and they have access to a more fine-grained state API allowing for
/// unlimited (apart from NRG costs) state size.
V1,
}

/// V0 is the default version of smart contracts.
impl Default for WasmVersion {
fn default() -> Self { Self::V0 }
}

impl From<WasmVersion> for u8 {
fn from(x: WasmVersion) -> Self { x as u8 }
}

impl TryFrom<u8> for WasmVersion {
type Error = anyhow::Error;

fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::V0),
1 => Ok(Self::V1),
_ => anyhow::bail!("Only versions 0 and 1 of smart contracts are supported."),
}
}
}

impl Serial for WasmVersion {
#[inline(always)]
fn serial<B: Buffer>(&self, out: &mut B) { u32::from(u8::from(*self)).serial(out) }
Expand All @@ -76,7 +35,7 @@ impl Deserial for WasmVersion {
fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
let x = u32::deserial(source)?;
let tag = u8::try_from(x)?;
tag.try_into()
Ok(tag.try_into()?)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2491,12 +2491,91 @@ impl fmt::Display for ParseError {
#[cfg(feature = "std")]
impl std::error::Error for ParseError {}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[repr(u8)]
#[cfg_attr(feature = "derive-serde", derive(SerdeSerialize, SerdeDeserialize))]
#[cfg_attr(feature = "derive-serde", serde(try_from = "u8", into = "u8"))]
/// Version of the module. This determines the chain API that the module can
/// access.
pub enum WasmVersion {
/// The initial smart contracts version. This has a simple state API that
/// has very limited capacity. `V0` contracts also use message-passing as
/// the interaction method.
V0 = 0u8,
/// `V1` contracts were introduced with protocol version 4. In comparison to
/// `V0` contracts they use synchronous calls as the interaction method,
/// and they have access to a more fine-grained state API allowing for
/// unlimited (apart from NRG costs) state size.
V1,
}

impl fmt::Display for WasmVersion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
WasmVersion::V0 => f.write_str("V0"),
WasmVersion::V1 => f.write_str("V1"),
}
}
}

/// V0 is the default version of smart contracts.
impl Default for WasmVersion {
fn default() -> Self { Self::V0 }
}

impl convert::From<WasmVersion> for u8 {
fn from(x: WasmVersion) -> Self { x as u8 }
}

#[cfg(feature = "derive-serde")]
mod serde_impl {
use super::*;
use serde::{de, de::Visitor, Deserializer, Serializer};
use std::{fmt, num};

#[derive(Debug, thiserror::Error)]
#[error("Unsupported version: {unexpected_string}. Only 'V0' and 'V1' are supported.")]
pub struct WasmVersionParseError {
pub unexpected_string: String,
}

impl str::FromStr for WasmVersion {
type Err = WasmVersionParseError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"V0" | "v0" => Ok(WasmVersion::V0),
"V1" | "v1" => Ok(WasmVersion::V1),
unexpected_string => Err(WasmVersionParseError {
unexpected_string: unexpected_string.to_string(),
}),
}
}
}

#[derive(Debug, thiserror::Error)]
#[error(
"Unsupported version: {unexpected_version}. Only versions 0 and 1 of smart contracts are \
supported."
)]
pub struct U8WasmVersionConvertError {
pub unexpected_version: u8,
}

impl TryFrom<u8> for WasmVersion {
type Error = U8WasmVersionConvertError;

fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::V0),
1 => Ok(Self::V1),
unexpected_version => Err(U8WasmVersionConvertError {
unexpected_version,
}),
}
}
}

/// An error that may occur when converting from a string to an exchange
/// rate.
#[derive(Debug, thiserror::Error)]
Expand Down
4 changes: 4 additions & 0 deletions smart-contracts/wasm-chain-integration/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

- Add a `branch_statistics` function to get insight into smart contract state
tree structure.
- Remove `utils::WasmVersion` to instead reexport a similar type from `concordium_contracts_common`.
This adds `Display`, `Default`, `TryFrom<u8>`, `serde::Serialize` and `serde::Deserialize` for `WasmVersion` and `From<WasmVersion>` for `u8`.
The associated type `FromStr::Err` changes from `anyhow::Error` to `concordium_contracts_common::WasmVersionParseError`.
The method `WasmVersin::read` is removed.

## concordium-smart-contract-engine 3.1.0 (2023-10-18)

Expand Down
36 changes: 2 additions & 34 deletions smart-contracts/wasm-chain-integration/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use crate::{v1::EmittedDebugStatement, ExecResult};
use anyhow::{anyhow, bail, ensure, Context};
pub use concordium_contracts_common::WasmVersion;
use concordium_contracts_common::{
self as concordium_std, from_bytes, hashes, schema, Cursor, Deserial,
};
Expand All @@ -17,39 +18,6 @@ use concordium_wasm::{
use rand::{prelude::*, RngCore};
use std::{collections::BTreeMap, default::Default};

#[derive(Debug, Clone, Copy)]
pub enum WasmVersion {
V0,
V1,
}

impl std::str::FromStr for WasmVersion {
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"V0" | "v0" => Ok(WasmVersion::V0),
"V1" | "v1" => Ok(WasmVersion::V1),
_ => anyhow::bail!("Unsupported version: '{}'. Only 'V0' and 'V1' are supported.", s),
}
}
}

impl WasmVersion {
/// Get the version from the cursor. This is not a Serial implementation
/// since it uses big-endian.
pub fn read(source: &mut std::io::Cursor<&[u8]>) -> anyhow::Result<WasmVersion> {
let mut data = [0u8; 4];
use std::io::Read;
source.read_exact(&mut data).context("Not enough data to read WasmVersion.")?;
match u32::from_be_bytes(data) {
0 => Ok(WasmVersion::V0),
1 => Ok(WasmVersion::V1),
n => bail!("Unsupported Wasm version {}.", n),
}
}
}

/// A host which traps for any function call.
pub struct TrapHost;

Expand Down Expand Up @@ -697,7 +665,7 @@ pub fn get_build_info_from_skeleton(
}
}
let Some(cs) = build_context_section else {
return Err(CustomSectionLookupError::Missing)
return Err(CustomSectionLookupError::Missing);
};
let info: VersionedBuildInfo = from_bytes(cs.contents).context("Failed parsing build info")?;
Ok(info)
Expand Down

0 comments on commit bd93a27

Please sign in to comment.