From 3982953881f11092e61b000431fa13b3235f61d4 Mon Sep 17 00:00:00 2001 From: Ignacio Duart Date: Wed, 15 Nov 2023 18:21:23 +0100 Subject: [PATCH 1/4] Minor display changes --- rust/src/client_api/client_events.rs | 9 +++++---- rust/src/contract_interface.rs | 17 +++++------------ rust/src/versioning.rs | 4 ++-- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/rust/src/client_api/client_events.rs b/rust/src/client_api/client_events.rs index 7d6f913..42ef512 100644 --- a/rust/src/client_api/client_events.rs +++ b/rust/src/client_api/client_events.rs @@ -79,8 +79,8 @@ impl ClientError { Ok(builder.finished_data().to_vec()) } - pub fn kind(&self) -> ErrorKind { - (*self.kind).clone() + pub fn kind(&self) -> &ErrorKind { + &self.kind } } @@ -121,6 +121,8 @@ pub enum ErrorKind { UnknownClient(usize), #[error(transparent)] RequestError(#[from] RequestError), + #[error("peer should shutdown")] + Shutdown, } impl Display for ClientError { @@ -1353,8 +1355,7 @@ mod client_request_test { } => { assert_eq!( contract.to_string(), - "wasm container version 0.0.1 of contract \ - Contract(D8fdVLbRyMLw5mZtPRpWMFcrXGN2z8Nq8UGcLGPFBg2W)" + "WasmContainer([api=0.0.1](D8fdVLbRyMLw5mZtPRpWMFcrXGN2z8Nq8UGcLGPFBg2W))" ); assert_eq!(contract.unwrap_v1().data.data(), &[1, 2, 3, 4, 5, 6, 7, 8]); assert_eq!(state.to_vec(), &[1, 2, 3, 4, 5, 6, 7, 8]); diff --git a/rust/src/contract_interface.rs b/rust/src/contract_interface.rs index b55e4f0..a4acf4d 100644 --- a/rust/src/contract_interface.rs +++ b/rust/src/contract_interface.rs @@ -1229,18 +1229,11 @@ impl From for State<'static> { impl std::fmt::Display for WrappedState { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let data: String = if self.0.len() > 8 { - let last_4 = self.0.len() - 4; - self.0[..4] - .iter() - .map(|b| char::from(*b)) - .chain("...".chars()) - .chain(self.0[last_4..].iter().map(|b| char::from(*b))) - .collect() - } else { - self.0.iter().copied().map(char::from).collect() - }; - write!(f, "ContractState(data: [{data}])") + write!(f, "ContractState(data: [0x")?; + for b in self.0.iter().take(8) { + write!(f, "{:02x}", b)?; + } + write!(f, "...])") } } diff --git a/rust/src/versioning.rs b/rust/src/versioning.rs index 5a03ae4..422d878 100644 --- a/rust/src/versioning.rs +++ b/rust/src/versioning.rs @@ -192,7 +192,7 @@ impl Display for ContractWasmAPIVersion { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { ContractWasmAPIVersion::V1(contract_v1) => { - write!(f, "version 0.0.1 of contract {contract_v1}") + write!(f, "[api=0.0.1]({contract_v1})") } } } @@ -254,7 +254,7 @@ impl Display for ContractContainer { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { ContractContainer::Wasm(wasm_version) => { - write!(f, "wasm container {wasm_version}") + write!(f, "WasmContainer({wasm_version})") } } } From 75d3d955bdcc9c6afc419e1744efddb749868615 Mon Sep 17 00:00:00 2001 From: Ignacio Duart Date: Mon, 27 Nov 2023 17:26:10 +0100 Subject: [PATCH 2/4] Change where generated fb files are placed --- rust/build.rs | 2 +- rust/src/client_api.rs | 2 +- rust/src/client_api/client_events.rs | 12 ++++++------ rust/src/client_api/regular.rs | 4 ++-- rust/src/contract_interface.rs | 2 +- rust/src/delegate_interface.rs | 2 +- .../client_request_generated.rs | 0 rust/src/{ => generated}/common_generated.rs | 0 .../host_response_generated.rs | 0 rust/src/lib.rs | 17 ++++++++++++----- rust/src/versioning.rs | 19 ++++++++++--------- 11 files changed, 34 insertions(+), 26 deletions(-) rename rust/src/{ => generated}/client_request_generated.rs (100%) rename rust/src/{ => generated}/common_generated.rs (100%) rename rust/src/{ => generated}/host_response_generated.rs (100%) diff --git a/rust/build.rs b/rust/build.rs index 9d66dc2..df45757 100644 --- a/rust/build.rs +++ b/rust/build.rs @@ -4,7 +4,7 @@ fn main() { let status = Command::new("flatc") .arg("--rust") .arg("-o") - .arg("src") + .arg("src/generated") .arg("../schemas/flatbuffers/common.fbs") .arg("../schemas/flatbuffers/client_request.fbs") .arg("../schemas/flatbuffers/host_response.fbs") diff --git a/rust/src/client_api.rs b/rust/src/client_api.rs index 8a1b1a6..fc0de02 100644 --- a/rust/src/client_api.rs +++ b/rust/src/client_api.rs @@ -67,7 +67,7 @@ impl WsApiError { } pub fn into_fbs_bytes(self) -> Vec { - use crate::host_response_generated::host_response::{ + use crate::generated::host_response::{ finish_host_response_buffer, Error, ErrorArgs, HostResponse, HostResponseArgs, HostResponseType, }; diff --git a/rust/src/client_api/client_events.rs b/rust/src/client_api/client_events.rs index 42ef512..18a44ee 100644 --- a/rust/src/client_api/client_events.rs +++ b/rust/src/client_api/client_events.rs @@ -4,12 +4,13 @@ use std::fmt::Display; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use crate::client_api::TryFromFbs; -use crate::client_request_generated::client_request::{ +use crate::generated::client_request::{ root_as_client_request, ClientRequestType, ContractRequest as FbsContractRequest, ContractRequestType, DelegateRequest as FbsDelegateRequest, DelegateRequestType, }; -use crate::common_generated::common::{ +use crate::delegate_interface::DelegateContext; +use crate::generated::common::{ ApplicationMessage as FbsApplicationMessage, ApplicationMessageArgs, ContractCode, ContractCodeArgs, ContractContainer as FbsContractContainer, ContractContainerArgs, ContractInstanceId, ContractInstanceIdArgs, ContractKey as FbsContractKey, ContractKeyArgs, @@ -21,8 +22,7 @@ use crate::common_generated::common::{ StateUpdate, StateUpdateArgs, UpdateData as FbsUpdateData, UpdateDataArgs, UpdateDataType, WasmContractV1, WasmContractV1Args, }; -use crate::delegate_interface::DelegateContext; -use crate::host_response_generated::host_response::{ +use crate::generated::host_response::{ finish_host_response_buffer, ClientResponse as FbsClientResponse, ClientResponseArgs, ContextUpdated as FbsContextUpdated, ContextUpdatedArgs, ContractResponse as FbsContractResponse, ContractResponseArgs, ContractResponseType, @@ -59,7 +59,7 @@ pub struct ClientError { impl ClientError { pub fn into_fbs_bytes(self) -> Result, Box> { - use crate::host_response_generated::host_response::{Error, ErrorArgs}; + use crate::generated::host_response::{Error, ErrorArgs}; let mut builder = flatbuffers::FlatBufferBuilder::new(); let msg_offset = builder.create_string(&self.to_string()); let err_offset = Error::create( @@ -1321,8 +1321,8 @@ impl From> for HostResponse { #[cfg(test)] mod client_request_test { use crate::client_api::{ContractRequest, TryFromFbs}; - use crate::client_request_generated::client_request::root_as_client_request; use crate::contract_interface::UpdateData; + use crate::generated::client_request::root_as_client_request; const EXPECTED_ENCODED_CONTRACT_ID: &str = "6kVs66bKaQAC6ohr8b43SvJ95r36tc2hnG7HezmaJHF9"; diff --git a/rust/src/client_api/regular.rs b/rust/src/client_api/regular.rs index f4c6aea..3d97187 100644 --- a/rust/src/client_api/regular.rs +++ b/rust/src/client_api/regular.rs @@ -189,8 +189,8 @@ async fn process_response( .await .map_err(|_| Error::ChannelClosed)?; } - Message::Ping(_) => { - conn.send(Message::Pong(vec![0, 5, 3, 9])).await?; + Message::Ping(ping) => { + conn.send(Message::Pong(ping)).await?; } Message::Pong(_) => {} Message::Close(_) => return Err(Error::ConnectionClosed), diff --git a/rust/src/contract_interface.rs b/rust/src/contract_interface.rs index a4acf4d..56a7f00 100644 --- a/rust/src/contract_interface.rs +++ b/rust/src/contract_interface.rs @@ -23,10 +23,10 @@ use serde::{Deserialize, Deserializer, Serialize}; use serde_with::serde_as; use crate::client_api::TryFromFbs; -use crate::client_request_generated::client_request::RelatedContracts as FbsRelatedContracts; use crate::common_generated::common::{ ContractKey as FbsContractKey, UpdateData as FbsUpdateData, UpdateDataType, }; +use crate::generated::client_request::RelatedContracts as FbsRelatedContracts; use crate::{client_api::WsApiError, code_hash::CodeHash, parameters::Parameters}; pub(crate) const CONTRACT_KEY_SIZE: usize = 32; diff --git a/rust/src/delegate_interface.rs b/rust/src/delegate_interface.rs index 9409a85..453c6d8 100644 --- a/rust/src/delegate_interface.rs +++ b/rust/src/delegate_interface.rs @@ -11,7 +11,7 @@ use blake3::{traits::digest::Digest, Hasher as Blake3}; use serde::{Deserialize, Deserializer, Serialize}; use serde_with::serde_as; -use crate::client_request_generated::client_request::{ +use crate::generated::client_request::{ DelegateKey as FbsDelegateKey, InboundDelegateMsg as FbsInboundDelegateMsg, InboundDelegateMsgType, }; diff --git a/rust/src/client_request_generated.rs b/rust/src/generated/client_request_generated.rs similarity index 100% rename from rust/src/client_request_generated.rs rename to rust/src/generated/client_request_generated.rs diff --git a/rust/src/common_generated.rs b/rust/src/generated/common_generated.rs similarity index 100% rename from rust/src/common_generated.rs rename to rust/src/generated/common_generated.rs diff --git a/rust/src/host_response_generated.rs b/rust/src/generated/host_response_generated.rs similarity index 100% rename from rust/src/host_response_generated.rs rename to rust/src/generated/host_response_generated.rs diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 01f101a..1739abe 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -12,11 +12,18 @@ mod versioning; pub use contract_interface::encoding as typed_contract; #[allow(dead_code, unused_imports, clippy::all)] -pub(crate) mod client_request_generated; -#[allow(dead_code, unused_imports, clippy::all)] -pub(crate) mod common_generated; -#[allow(dead_code, unused_imports, clippy::all)] -pub(crate) mod host_response_generated; +pub(crate) mod generated { + mod client_request_generated; + pub(crate) use client_request_generated::*; + pub(crate) mod common_generated; + pub(crate) use common_generated::*; + mod host_response_generated; + pub(crate) use host_response_generated::*; +} + +pub(crate) mod common_generated { + pub use super::generated::common_generated::*; +} pub mod client_api; #[cfg(feature = "contract")] diff --git a/rust/src/versioning.rs b/rust/src/versioning.rs index 422d878..96b29ad 100644 --- a/rust/src/versioning.rs +++ b/rust/src/versioning.rs @@ -7,16 +7,17 @@ use std::sync::Arc; use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use serde::{Deserialize, Serialize}; -use crate::client_api::{TryFromFbs, WsApiError}; -use crate::client_request_generated::client_request::{ - DelegateContainer as FbsDelegateContainer, DelegateType, +use crate::{ + client_api::{TryFromFbs, WsApiError}, + common_generated::common::{ContractContainer as FbsContractContainer, ContractType}, + contract_interface::{ContractInstanceId, ContractKey}, + generated::client_request::{DelegateContainer as FbsDelegateContainer, DelegateType}, + parameters::Parameters, + prelude::{ + CodeHash, ContractCode, ContractWasmAPIVersion::V1, Delegate, DelegateCode, DelegateKey, + WrappedContract, + }, }; -use crate::common_generated::common::{ContractContainer as FbsContractContainer, ContractType}; -use crate::contract_interface::ContractInstanceId; -use crate::parameters::Parameters; -use crate::prelude::ContractWasmAPIVersion::V1; -use crate::prelude::{CodeHash, Delegate, DelegateCode, DelegateKey, WrappedContract}; -use crate::{contract_interface::ContractKey, prelude::ContractCode}; /// Contains the different versions available for WASM delegates. #[non_exhaustive] From 73121030e7dbc84379dfeed80a21c6188f520d34 Mon Sep 17 00:00:00 2001 From: Ignacio Duart Date: Tue, 12 Dec 2023 11:00:49 +0100 Subject: [PATCH 3/4] Add some variants to client events ContractError --- rust/src/client_api/client_events.rs | 79 ++++++++++++++++++++++------ rust/src/client_api/regular.rs | 4 +- 2 files changed, 66 insertions(+), 17 deletions(-) diff --git a/rust/src/client_api/client_events.rs b/rust/src/client_api/client_events.rs index 18a44ee..8d4ec84 100644 --- a/rust/src/client_api/client_events.rs +++ b/rust/src/client_api/client_events.rs @@ -1,4 +1,5 @@ use flatbuffers::WIPOffset; +use std::borrow::Cow; use std::fmt::Display; use serde::{de::DeserializeOwned, Deserialize, Serialize}; @@ -92,10 +93,12 @@ impl From for ClientError { } } -impl From for ClientError { - fn from(cause: String) -> Self { +impl>> From for ClientError { + fn from(cause: T) -> Self { ClientError { - kind: Box::new(ErrorKind::Unhandled { cause }), + kind: Box::new(ErrorKind::Unhandled { + cause: cause.into(), + }), } } } @@ -106,7 +109,7 @@ pub enum ErrorKind { #[error("comm channel between client/host closed")] ChannelClosed, #[error("error while deserializing: {cause}")] - DeserializationError { cause: String }, + DeserializationError { cause: Cow<'static, str> }, #[error("client disconnected")] Disconnect, #[error("failed while trying to unpack state for {0}")] @@ -116,7 +119,7 @@ pub enum ErrorKind { #[error("lost the connection with the protocol hanling connections")] TransportProtocolDisconnect, #[error("unhandled error: {cause}")] - Unhandled { cause: String }, + Unhandled { cause: Cow<'static, str> }, #[error("unknown client id: {0}")] UnknownClient(usize), #[error(transparent)] @@ -153,7 +156,7 @@ pub enum DelegateError { #[error("error while registering delegate {0}")] RegisterError(DelegateKey), #[error("execution error, cause {0}")] - ExecutionError(String), + ExecutionError(Cow<'static, str>), #[error("missing delegate {0}")] Missing(DelegateKey), #[error("missing secret `{secret}` for delegate {key}")] @@ -167,22 +170,68 @@ pub enum DelegateError { #[non_exhaustive] pub enum ContractError { #[error("failed to get contract {key}, reason: {cause}")] - Get { key: ContractKey, cause: String }, + Get { + key: ContractKey, + cause: Cow<'static, str>, + }, #[error("put error for contract {key}, reason: {cause}")] - Put { key: ContractKey, cause: String }, + Put { + key: ContractKey, + cause: Cow<'static, str>, + }, #[error("update error for contract {key}, reason: {cause}")] - Update { key: ContractKey, cause: String }, + Update { + key: ContractKey, + cause: Cow<'static, str>, + }, #[error("failed to subscribe for contract {key}, reason: {cause}")] - Subscribe { key: ContractKey, cause: String }, - #[error("missing related contract: {key}")] - MissingRelated { - key: crate::contract_interface::ContractInstanceId, + Subscribe { + key: ContractKey, + cause: Cow<'static, str>, }, // todo: actually build a stack of the involved keys #[error("dependency contract stack overflow : {key}")] ContractStackOverflow { key: crate::contract_interface::ContractInstanceId, }, + #[error("missing related contract: {key}")] + MissingRelated { + key: crate::contract_interface::ContractInstanceId, + }, + #[error("missing related contract: {key}")] + MissingContract { + key: crate::contract_interface::ContractInstanceId, + }, +} + +impl ContractError { + const EXECUTION_ERROR: &'static str = "execution error"; + const INVALID_PUT: &'static str = "invalid put"; + + pub fn update_exec_error(key: ContractKey, additional_info: impl std::fmt::Display) -> Self { + Self::Update { + key, + cause: format!( + "{exec_err}: {additional_info}", + exec_err = Self::EXECUTION_ERROR + ) + .into(), + } + } + + pub fn invalid_put(key: ContractKey) -> Self { + Self::Put { + key, + cause: Self::INVALID_PUT.into(), + } + } + + pub fn invalid_update(key: ContractKey) -> Self { + Self::Update { + key, + cause: Self::INVALID_PUT.into(), + } + } } /// A request from a client application to the host. @@ -192,7 +241,7 @@ pub enum ContractError { pub enum ClientRequest<'a> { DelegateOp(#[serde(borrow)] DelegateRequest<'a>), ContractOp(#[serde(borrow)] ContractRequest<'a>), - Disconnect { cause: Option }, + Disconnect { cause: Option> }, Authenticate { token: String }, } @@ -263,7 +312,7 @@ impl ClientRequest<'_> { client_request.client_request_as_disconnect().unwrap(); let cause = delegate_request .cause() - .map(|cuase_msg| cuase_msg.to_string()); + .map(|cause_msg| cause_msg.to_string().into()); ClientRequest::Disconnect { cause } } ClientRequestType::Authenticate => { diff --git a/rust/src/client_api/regular.rs b/rust/src/client_api/regular.rs index 3d97187..3051ac3 100644 --- a/rust/src/client_api/regular.rs +++ b/rust/src/client_api/regular.rs @@ -1,4 +1,4 @@ -use std::task::Poll; +use std::{borrow::Cow, task::Poll}; use futures::{pin_mut, FutureExt, Sink, SinkExt, Stream, StreamExt}; use tokio::{ @@ -115,7 +115,7 @@ impl WebApi { res.ok_or_else(|| ClientError::from(ErrorKind::ChannelClosed))? } - pub async fn disconnect(self, cause: impl Into) { + pub async fn disconnect(self, cause: impl Into>) { let _ = self .request_tx .send(ClientRequest::Disconnect { From adcef021bacc4707200c785f5770bd4edf2f1f6f Mon Sep 17 00:00:00 2001 From: Ignacio Duart Date: Thu, 14 Dec 2023 13:22:10 +0100 Subject: [PATCH 4/4] Fix test and move examples to proper place --- rust/{tests => examples}/chatroom.rs | 2 ++ rust/{tests => examples}/contract_components.rs | 2 ++ rust/{tests => examples}/typed_contract.rs | 2 ++ rust/src/contract_interface.rs | 4 +--- 4 files changed, 7 insertions(+), 3 deletions(-) rename rust/{tests => examples}/chatroom.rs (99%) rename rust/{tests => examples}/contract_components.rs (99%) rename rust/{tests => examples}/typed_contract.rs (99%) diff --git a/rust/tests/chatroom.rs b/rust/examples/chatroom.rs similarity index 99% rename from rust/tests/chatroom.rs rename to rust/examples/chatroom.rs index 25e595f..29b4441 100644 --- a/rust/tests/chatroom.rs +++ b/rust/examples/chatroom.rs @@ -316,3 +316,5 @@ pub mod dependency_2 { } } } + +fn main() {} diff --git a/rust/tests/contract_components.rs b/rust/examples/contract_components.rs similarity index 99% rename from rust/tests/contract_components.rs rename to rust/examples/contract_components.rs index a454988..071af5c 100644 --- a/rust/tests/contract_components.rs +++ b/rust/examples/contract_components.rs @@ -367,3 +367,5 @@ mod children { } } } + +fn main() {} diff --git a/rust/tests/typed_contract.rs b/rust/examples/typed_contract.rs similarity index 99% rename from rust/tests/typed_contract.rs rename to rust/examples/typed_contract.rs index e717153..b126a9d 100644 --- a/rust/tests/typed_contract.rs +++ b/rust/examples/typed_contract.rs @@ -79,3 +79,5 @@ impl TypedContract for Contract { unimplemented!() } } + +fn main() {} diff --git a/rust/src/contract_interface.rs b/rust/src/contract_interface.rs index 56a7f00..e4b53d9 100644 --- a/rust/src/contract_interface.rs +++ b/rust/src/contract_interface.rs @@ -1307,9 +1307,7 @@ impl TryInto> for WrappedContract { impl Display for WrappedContract { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Contract(")?; - self.key.fmt(f)?; - write!(f, ")") + self.key.fmt(f) } }