From 485cc5e82e92274b1120fd8bb2ef7be03d85fdf4 Mon Sep 17 00:00:00 2001 From: Moncef AOUDIA Date: Fri, 3 Mar 2023 21:55:51 +0100 Subject: [PATCH] feat: add send_operations naif impl --- Cargo.lock | 1 + massa-grpc/Cargo.toml | 1 + massa-grpc/src/api.rs | 199 +++++++++++++++++- massa-grpc/src/config.rs | 4 + massa-grpc/src/error.rs | 1 + massa-node/src/main.rs | 5 +- massa-proto/proto/massa/api.proto | 6 +- massa-proto/src/api.bin | Bin 92237 -> 92245 bytes massa-proto/src/massa.api.v1.rs | 330 +++++++++++++++--------------- 9 files changed, 372 insertions(+), 175 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 713b9aa95bd..a9e45cd3dea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2747,6 +2747,7 @@ dependencies = [ "massa_proto", "massa_protocol_exports", "massa_serialization 0.1.0", + "massa_signature", "massa_storage", "massa_time", "massa_wallet", diff --git a/massa-grpc/Cargo.toml b/massa-grpc/Cargo.toml index 877965f8d49..483363ef8a4 100644 --- a/massa-grpc/Cargo.toml +++ b/massa-grpc/Cargo.toml @@ -30,4 +30,5 @@ massa_storage = { path = "../massa-storage" } massa_time = { path = "../massa-time" } massa_wallet = { path = "../massa-wallet" } massa_serialization = { path = "../massa-serialization" } +massa_signature = { path = "../massa-signature" } massa_proto = { path = "../massa-proto" } \ No newline at end of file diff --git a/massa-grpc/src/api.rs b/massa-grpc/src/api.rs index 48e929dfe9e..0bc456d1b22 100644 --- a/massa-grpc/src/api.rs +++ b/massa-grpc/src/api.rs @@ -1,15 +1,16 @@ //! Copyright (c) 2022 MASSA LABS //! gRPC API for a massa-node -use std::{error::Error, io::ErrorKind, pin::Pin}; +use std::{collections::HashMap, error::Error, io::ErrorKind, pin::Pin}; use crate::config::GrpcConfig; use massa_consensus_exports::{ConsensusChannels, ConsensusController}; use massa_models::{ block::{BlockDeserializer, BlockDeserializerArgs, SecureShareBlock}, error::ModelsError, + operation::{OperationDeserializer, SecureShareOperation}, secure_share::SecureShareDeserializer, }; -use massa_pool_exports::PoolChannels; +use massa_pool_exports::{PoolChannels, PoolController}; use massa_proto::massa::api::v1::{self as grpc, grpc_server::GrpcServer, FILE_DESCRIPTOR_SET}; use massa_serialization::{DeserializeError, Deserializer}; @@ -29,6 +30,8 @@ pub struct MassaService { pub consensus_channels: ConsensusChannels, /// link(channels) to the pool component pub pool_channels: PoolChannels, + /// link to the pool component + pub pool_command_sender: Box, /// link(channels) to the protocol component pub protocol_command_sender: ProtocolCommandSender, /// link to the storage component @@ -270,7 +273,7 @@ impl grpc::grpc_server::Grpc for MassaService { req_content.id.clone(), tx.clone(), tonic::Code::InvalidArgument, - "incomplete deserialization".to_owned(), + "there is data left after operation deserialization".to_owned(), ) .await; } @@ -349,9 +352,167 @@ impl grpc::grpc_server::Grpc for MassaService { async fn send_operations( &self, - _request: tonic::Request>, + request: tonic::Request>, ) -> Result, tonic::Status> { - Err(tonic::Status::unimplemented("not implemented")) + let mut cmd_sender = self.pool_command_sender.clone(); + let mut protocol_sender = self.protocol_command_sender.clone(); + let config = self.grpc_config.clone(); + let storage = self.storage.clone_without_refs(); + + let (tx, rx) = tokio::sync::mpsc::channel(config.max_channel_size); + let mut in_stream = request.into_inner(); + + tokio::spawn(async move { + while let Some(result) = in_stream.next().await { + match result { + Ok(req_content) => { + if req_content.operations.is_empty() { + let _res = sendoperations_notify_error( + req_content.id.clone(), + tx.clone(), + tonic::Code::InvalidArgument, + "the request payload is empty".to_owned(), + ) + .await; + } else { + let proto_operations = req_content.operations; + if proto_operations.len() as u32 > config.max_operations_per_message { + let _res = sendoperations_notify_error( + req_content.id.clone(), + tx.clone(), + tonic::Code::InvalidArgument, + "too many operations".to_owned(), + ) + .await; + } else { + let operation_deserializer = + SecureShareDeserializer::new(OperationDeserializer::new( + config.max_datastore_value_length, + config.max_function_name_length, + config.max_parameter_size, + config.max_op_datastore_entry_count, + config.max_op_datastore_key_length, + config.max_op_datastore_value_length, + )); + let verified_ops_res: Result, ModelsError> = proto_operations + .into_iter() + .map(|proto_operation| { + let mut op_serialized = Vec::new(); + op_serialized.extend(proto_operation.signature.as_bytes()); + op_serialized.extend(proto_operation.creator_public_key.as_bytes()); + op_serialized.extend(proto_operation.serialized_content); + let verified_op = match operation_deserializer.deserialize::(&op_serialized) { + Ok(tuple) => { + let (rest, res_operation): (&[u8], SecureShareOperation) = tuple; + if rest.is_empty() { + if let Ok(_verify_signature) = res_operation.verify_signature() { + Ok((res_operation.id.to_string(), res_operation)) + } else { + Err(ModelsError::MassaSignatureError(massa_signature::MassaSignatureError::SignatureError( + format!("wrong signature: {}", res_operation.signature).to_owned()) + )) + } + } else { + Err(ModelsError::DeserializeError( + "there is data left after operation deserialization".to_owned() + )) + } + }, + Err(e) => { + Err(ModelsError::DeserializeError(format!("failed to deserialize operation: {}", e).to_owned() + )) + } + }; + verified_op + }) + .collect(); + + match verified_ops_res { + Ok(verified_ops) => { + let mut operation_storage = storage.clone_without_refs(); + operation_storage.store_operations( + verified_ops.values().cloned().collect(), + ); + cmd_sender.add_operations(operation_storage.clone()); + + let _res = match protocol_sender + .propagate_operations(operation_storage) + { + Ok(()) => (), + Err(e) => { + let error = + format!("failed to propagate operations: {}", e); + let _res = sendoperations_notify_error( + req_content.id.clone(), + tx.clone(), + tonic::Code::Internal, + error.to_owned(), + ) + .await; + } + }; + + let result = grpc::OperationResult { + ids: verified_ops.keys().cloned().collect(), + }; + let _res = match tx + .send(Ok(grpc::SendOperationsResponse { + id: req_content.id.clone(), + message: Some( + grpc::send_operations_response::Message::Result( + result, + ), + ), + })) + .await + { + Ok(()) => (), + Err(e) => { + error!( + "failed to send back operations response: {}", + e + ) + } + }; + } + Err(e) => { + let error = format!("invalid operations:{}", e); + let _res = sendoperations_notify_error( + req_content.id.clone(), + tx.clone(), + tonic::Code::InvalidArgument, + error.to_owned(), + ) + .await; + } + } + } + } + } + Err(err) => { + if let Some(io_err) = match_for_io_error(&err) { + if io_err.kind() == ErrorKind::BrokenPipe { + warn!("client disconnected, broken pipe: {}", io_err); + break; + } + } + match tx.send(Err(err)).await { + Ok(_) => (), + Err(e) => { + error!("failed to send back sendblocks error response: {}", e); + break; + } + } + } + } + } + }); + + let out_stream = tokio_stream::wrappers::ReceiverStream::new(rx); + + Ok(tonic::Response::new( + Box::pin(out_stream) as Self::SendOperationsStream + )) } } @@ -382,3 +543,31 @@ async fn sendblocks_notify_error( } } } + +async fn sendoperations_notify_error( + id: String, + sender: tokio::sync::mpsc::Sender>, + code: tonic::Code, + error: String, +) -> Result<(), Box> { + error!("{}", error); + match sender + .send(Ok(grpc::SendOperationsResponse { + id, + message: Some(grpc::send_operations_response::Message::Error( + massa_proto::google::rpc::Status { + code: code.into(), + message: error, + details: Vec::new(), + }, + )), + })) + .await + { + Ok(()) => Ok(()), + Err(e) => { + error!("failed to send back sendoperations error response: {}", e); + Ok(()) + } + } +} diff --git a/massa-grpc/src/config.rs b/massa-grpc/src/config.rs index 9236fafc5b3..60ea88fc463 100644 --- a/massa-grpc/src/config.rs +++ b/massa-grpc/src/config.rs @@ -29,6 +29,8 @@ pub struct GrpcConfig { pub max_operations_per_block: u32, /// endorsement count pub endorsement_count: u32, + /// max endorsements per message + pub max_endorsements_per_message: u32, /// max datastore value length pub max_datastore_value_length: u64, /// max op datastore entry @@ -41,6 +43,8 @@ pub struct GrpcConfig { pub max_function_name_length: u16, /// max parameter size pub max_parameter_size: u32, + /// max operations per message in the network to avoid sending to big data packet + pub max_operations_per_message: u32, /// limits the maximum size of streaming channel pub max_channel_size: usize, } diff --git a/massa-grpc/src/error.rs b/massa-grpc/src/error.rs index c036f7c9252..1116f47c1b4 100644 --- a/massa-grpc/src/error.rs +++ b/massa-grpc/src/error.rs @@ -11,6 +11,7 @@ use massa_protocol_exports::ProtocolError; use massa_time::TimeError; use massa_wallet::WalletError; +//TODO handle custom error /// Errors of the gRPC component. #[non_exhaustive] #[derive(Display, thiserror::Error, Debug)] diff --git a/massa-node/src/main.rs b/massa-node/src/main.rs index 7eae18f6781..74031dc4d2b 100644 --- a/massa-node/src/main.rs +++ b/massa-node/src/main.rs @@ -48,7 +48,7 @@ use massa_models::config::constants::{ POS_SAVED_CYCLES, PROTOCOL_CONTROLLER_CHANNEL_SIZE, PROTOCOL_EVENT_CHANNEL_SIZE, ROLL_PRICE, T0, THREAD_COUNT, VERSION, }; -use massa_models::config::CONSENSUS_BOOTSTRAP_PART_SIZE; +use massa_models::config::{CONSENSUS_BOOTSTRAP_PART_SIZE, MAX_OPERATIONS_PER_MESSAGE}; use massa_network_exports::{Establisher, NetworkConfig, NetworkManager}; use massa_network_worker::start_network_controller; use massa_pool_exports::{PoolChannels, PoolConfig, PoolManager}; @@ -581,12 +581,14 @@ async fn launch( thread_count: THREAD_COUNT, max_operations_per_block: MAX_OPERATIONS_PER_BLOCK, endorsement_count: ENDORSEMENT_COUNT, + max_endorsements_per_message: MAX_ENDORSEMENTS_PER_MESSAGE, max_datastore_value_length: MAX_DATASTORE_VALUE_LENGTH, max_op_datastore_entry_count: MAX_OPERATION_DATASTORE_ENTRY_COUNT, max_op_datastore_key_length: MAX_OPERATION_DATASTORE_KEY_LENGTH, max_op_datastore_value_length: MAX_OPERATION_DATASTORE_VALUE_LENGTH, max_function_name_length: MAX_FUNCTION_NAME_LENGTH, max_parameter_size: MAX_PARAMETERS_SIZE, + max_operations_per_message: MAX_OPERATIONS_PER_MESSAGE, max_channel_size: SETTINGS.grpc.max_channel_size, }; @@ -594,6 +596,7 @@ async fn launch( consensus_controller: consensus_controller.clone(), consensus_channels: consensus_channels.clone(), pool_channels, + pool_command_sender: pool_controller.clone(), protocol_command_sender: ProtocolCommandSender(protocol_command_sender.clone()), storage: shared_storage.clone(), grpc_config: grpc_config.clone(), diff --git a/massa-proto/proto/massa/api.proto b/massa-proto/proto/massa/api.proto index ca9d637cd0b..46962abec87 100644 --- a/massa-proto/proto/massa/api.proto +++ b/massa-proto/proto/massa/api.proto @@ -3,7 +3,6 @@ syntax = "proto3"; package massa.api.v1; import "common.proto"; -import "operation.proto"; import "endorsement.proto"; import "google/api/annotations.proto"; @@ -19,7 +18,6 @@ option php_namespace = "Massa\\Api\\V1"; // Massa gRPC service service Grpc { - // GetVersion rpc GetVersion ( GetVersionRequest ) returns ( GetVersionResponse ) { option (google.api.http) = { get: "/v1/version" }; @@ -103,7 +101,7 @@ message SendOperationsRequest { // string field string id = 1; // object field - OperationInput operation = 2; + repeated SecureSharePayload operations = 2; } // SendOperationsResponse holds response from SendOperations @@ -120,5 +118,5 @@ message SendOperationsResponse { // Holds Operation response message OperationResult { // string field - string id = 1; + repeated string ids = 1; } diff --git a/massa-proto/src/api.bin b/massa-proto/src/api.bin index c4913fba17870f06fea6d2f001560ea27283fc8d..03bc113dcf9b335b1747ca62d15a8da59c6e9bca 100644 GIT binary patch delta 2270 zcmYjS&re)c6n^)|yuP_Z-;8f~1M`OY0h9(xsil*mEn%ir!k7VRnNkK!8j9^mo0bBl z61tHXS0?UAye6*PxNhPC7i!|lq)}6o`Um(YxN)oBxpNeU>^bsHEb82jY}-)*MA3JZDgOig|%hPMLyUxqIve zQ_h$Pjs${^-C&RNo(ZM`LC0?Jv@>LaDiCz+27O!30^vJTaedleJrf8zcCTifQByw_ z2s&02cb!0Hosw=ZvdUrB>rs)CuEP-xd7p@SDvi#wmCn;Wj8dr{m7pAiLN^m5v>Im5 z#0cGnlkdhz1|lb?R7NGKPQG~g!%#PpH!2{?^A(8P>O8ss&SU-0BFi-MC)6x~d^T^% z7=-fCc#K@2w`(ziY`(sv%7zvf3;aP8=#ASfd)PJ2p;d5m_C5!5AzzLW6;$4e5ts|J z%@~2XFn>=K4KqNIe;8$q;ghFiFP@BmNYU-Jr2-Pz%=ZqZ52`@JUse2 z9bR-ejdSFrj8QIWwg?i2vXN}Bs>1*a@KFD8m-SsB<%yFjQl7BNxQD60g&v&7ZWbb5gFF*7ch$ z=ANrsA|yamwemn9s#tl%7!OFJPU^B z63&>-f@J~%(}HCJ0@H%sN`eNk$V(Vaco6`dEb`N)6Cld@=4F>aC|evTs(Bc|C${B$ zpeJv$dB5dVi~*MnEE@w=oMB+u8UO;*vNZq%re(VvmzJ}_*JwH6ArNk^*zLGvt}O?R z9RQeX+c5)CE;kV8K-n%=%ywLk?X24E0HAF3q>Lz6?RJnu*($a(ik?mdQrvOw>PIVV z)W2gN^;6W;IyF_iux{Hy3?%Ee9Uzdbqn$aBc!9j(b27t0%yD}h@ z?b?+Ap==i`JBx-?Aoua7k0LGB*l=dw>oYwm>gj+-^pULsU|0usSU{NgLFx@-2?*Q= YLHE@K0{20G{=1*V_rdY=HTK&756lbfsQ>@~ delta 2297 zcmYLK&rcgi6y7&G-mC|*hQ(lPu-A|{kS6>{fPx@4wn+^MDGfBW0&Nw!iG|!I7%-_K zazIf}>7_kXnx3j2EA`Oaxbz;WRi&s>kL};kTW?jrnVqG#_q{jod*6F+X7`UbvESar zUcI(Yf3ML`{ueM_+w^jp{*jxrblFX`_nU`}qt@xcES-zBIlSZf0m~8B~CO^M6`CgdT-n+H8|MY0<|Kp?Ik{FP=MH-NUbJQ!73$#BvA`)i_ zTg}eX$49;=SnJUsfjhnh>-2{O;!J!wC>)<#)^n1HN^ ztV)kE)OB?T4RrqAH|!40%&fP=W&H^BHSF#+Rw& z&6wtyQZN@PfDNWO!vqATIimmwOmjv7Qwru;AbVG+zX*hZ&ojLm4y1zp89h26{-D_=BqL}C(CX^bg7WiT;@Ys762rdc_Kn8)}!yKIta#cI%CpswJJPs z4l<-wcz=YDRvCyW8PY1bK#XG6+~+mx7G(xxvOR=fmeZ?~r7CXkU3OmggOG}O`mu8$q}?6PiggIVm-n9ak=(1&x_8gbYXOcDP}c(F zUm&_#H}w$!QQg!B0#V&;$Wa@*&puQe8a}yimg6W@+k8ap0Kk;D&6I&uY+yKwfowa- z>*Y8M%h@r@0YKW$S(>8UG0Q;=X**cXIGQ=<^9R-^lo^&ku28{yVBW$x)lWnBGYcC7 zZJ36DK-Mq~0fDT6hH4;lecrS_rOaYpzL>`cp>&fbyr!GgBXSkxZaAW^Z(>Bdh7kcU z?ixlQFz%Waxk`DY}>2TGo} zIjtnFl(fU!0vpY>jT9hIwv7}ZP`1ss;%Zw5>`1?-6Cj*CFguGYnTK3|&N%>79`ZiD zB_I_`hAM$Tc?gy29mdtpI%a18Nb8uL0U@npb_RsB4t914%?Y2|&#dQiy+)V3XKqS2 hB~(+#x~T$eG<9s60s_^sX$lBb$6n&}**5*@{ReY?^%4L8 diff --git a/massa-proto/src/massa.api.v1.rs b/massa-proto/src/massa.api.v1.rs index 0aa22d3fa46..4b175957b6a 100644 --- a/massa-proto/src/massa.api.v1.rs +++ b/massa-proto/src/massa.api.v1.rs @@ -21,167 +21,6 @@ pub struct SecureSharePayload { #[prost(bytes = "vec", tag = "3")] pub serialized_content: ::prost::alloc::vec::Vec, } -/// region Operation -/// message struct -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct OperationInfo { - /// string field - #[prost(string, tag = "1")] - pub id: ::prost::alloc::string::String, - /// string field - #[prost(string, repeated, tag = "2")] - pub in_blocks: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - /// bool field - #[prost(bool, tag = "3")] - pub in_pool: bool, - /// bool field - #[prost(bool, tag = "4")] - pub is_final: bool, - /// object field - #[prost(message, optional, tag = "5")] - pub operation: ::core::option::Option, -} -/// message struct -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Roll { - /// int64 field - #[prost(int64, tag = "1")] - pub roll_count: i64, -} -/// message struct -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct OperationId { - /// string field - #[prost(string, tag = "1")] - pub value: ::prost::alloc::string::String, -} -/// message struct -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct OperationType { - /// object field - #[prost(message, optional, tag = "1")] - pub transaction: ::core::option::Option, - /// object field - #[prost(message, optional, tag = "2")] - pub execut_sc: ::core::option::Option, - /// object field - #[prost(message, optional, tag = "3")] - pub call_sc: ::core::option::Option, - /// object field - #[prost(message, optional, tag = "4")] - pub roll_buy: ::core::option::Option, - /// object field - #[prost(message, optional, tag = "5")] - pub roll_sell: ::core::option::Option, -} -/// message struct -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Transaction { - /// string field - #[prost(string, tag = "1")] - pub amount: ::prost::alloc::string::String, - /// string field - #[prost(string, tag = "2")] - pub recipient_address: ::prost::alloc::string::String, -} -/// message struct -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct CallSc { - /// string field - #[prost(string, tag = "1")] - pub target_addr: ::prost::alloc::string::String, - /// string field - #[prost(string, tag = "2")] - pub target_func: ::prost::alloc::string::String, - /// string field - #[prost(string, tag = "3")] - pub param: ::prost::alloc::string::String, - /// float field - #[prost(float, tag = "4")] - pub max_gas: f32, - /// float field - #[prost(float, tag = "5")] - pub sequential_coins: f32, - /// float field - #[prost(float, tag = "6")] - pub parallel_coins: f32, - /// float field - #[prost(float, tag = "7")] - pub gas_price: f32, -} -/// message struct -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ExecuteSc { - /// float field - #[prost(float, repeated, tag = "1")] - pub data: ::prost::alloc::vec::Vec, - /// float field - #[prost(float, tag = "2")] - pub max_gas: f32, - /// string field - #[prost(string, tag = "3")] - pub coins: ::prost::alloc::string::String, - /// string field - #[prost(string, tag = "4")] - pub gas_price: ::prost::alloc::string::String, -} -/// message struct -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct RollBuy { - /// float field - #[prost(float, tag = "1")] - pub roll_count: f32, -} -/// message struct -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct RollSell { - /// float field - #[prost(float, tag = "1")] - pub roll_count: f32, -} -/// message struct -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct OperationInput { - /// string field - #[prost(string, tag = "1")] - pub content_creator_pub_key: ::prost::alloc::string::String, - /// string field - #[prost(string, tag = "2")] - pub signature: ::prost::alloc::string::String, - /// string field - #[prost(string, repeated, tag = "3")] - pub serialized_content: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, -} -/// message struct -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct SecureShareOperation { - /// object field - #[prost(message, optional, tag = "1")] - pub content: ::core::option::Option, - /// string field - #[prost(string, tag = "2")] - pub signature: ::prost::alloc::string::String, - /// string field - #[prost(string, tag = "3")] - pub content_creator_pub_key: ::prost::alloc::string::String, - /// string field - #[prost(string, tag = "4")] - pub content_creator_address: ::prost::alloc::string::String, - /// string field - #[prost(string, tag = "5")] - pub id: ::prost::alloc::string::String, -} /// message struct #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -387,8 +226,8 @@ pub struct SendOperationsRequest { #[prost(string, tag = "1")] pub id: ::prost::alloc::string::String, /// object field - #[prost(message, optional, tag = "2")] - pub operation: ::core::option::Option, + #[prost(message, repeated, tag = "2")] + pub operations: ::prost::alloc::vec::Vec, } /// SendOperationsResponse holds response from SendOperations #[allow(clippy::derive_partial_eq_without_eq)] @@ -418,8 +257,8 @@ pub mod send_operations_response { #[derive(Clone, PartialEq, ::prost::Message)] pub struct OperationResult { /// string field - #[prost(string, tag = "1")] - pub id: ::prost::alloc::string::String, + #[prost(string, repeated, tag = "1")] + pub ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, } /// Generated client implementations. pub mod grpc_client { @@ -963,6 +802,167 @@ pub mod grpc_server { const NAME: &'static str = "massa.api.v1.Grpc"; } } +/// region Operation +/// message struct +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct OperationInfo { + /// string field + #[prost(string, tag = "1")] + pub id: ::prost::alloc::string::String, + /// string field + #[prost(string, repeated, tag = "2")] + pub in_blocks: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// bool field + #[prost(bool, tag = "3")] + pub in_pool: bool, + /// bool field + #[prost(bool, tag = "4")] + pub is_final: bool, + /// object field + #[prost(message, optional, tag = "5")] + pub operation: ::core::option::Option, +} +/// message struct +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Roll { + /// int64 field + #[prost(int64, tag = "1")] + pub roll_count: i64, +} +/// message struct +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct OperationId { + /// string field + #[prost(string, tag = "1")] + pub value: ::prost::alloc::string::String, +} +/// message struct +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct OperationType { + /// object field + #[prost(message, optional, tag = "1")] + pub transaction: ::core::option::Option, + /// object field + #[prost(message, optional, tag = "2")] + pub execut_sc: ::core::option::Option, + /// object field + #[prost(message, optional, tag = "3")] + pub call_sc: ::core::option::Option, + /// object field + #[prost(message, optional, tag = "4")] + pub roll_buy: ::core::option::Option, + /// object field + #[prost(message, optional, tag = "5")] + pub roll_sell: ::core::option::Option, +} +/// message struct +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Transaction { + /// string field + #[prost(string, tag = "1")] + pub amount: ::prost::alloc::string::String, + /// string field + #[prost(string, tag = "2")] + pub recipient_address: ::prost::alloc::string::String, +} +/// message struct +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CallSc { + /// string field + #[prost(string, tag = "1")] + pub target_addr: ::prost::alloc::string::String, + /// string field + #[prost(string, tag = "2")] + pub target_func: ::prost::alloc::string::String, + /// string field + #[prost(string, tag = "3")] + pub param: ::prost::alloc::string::String, + /// float field + #[prost(float, tag = "4")] + pub max_gas: f32, + /// float field + #[prost(float, tag = "5")] + pub sequential_coins: f32, + /// float field + #[prost(float, tag = "6")] + pub parallel_coins: f32, + /// float field + #[prost(float, tag = "7")] + pub gas_price: f32, +} +/// message struct +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ExecuteSc { + /// float field + #[prost(float, repeated, tag = "1")] + pub data: ::prost::alloc::vec::Vec, + /// float field + #[prost(float, tag = "2")] + pub max_gas: f32, + /// string field + #[prost(string, tag = "3")] + pub coins: ::prost::alloc::string::String, + /// string field + #[prost(string, tag = "4")] + pub gas_price: ::prost::alloc::string::String, +} +/// message struct +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RollBuy { + /// float field + #[prost(float, tag = "1")] + pub roll_count: f32, +} +/// message struct +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RollSell { + /// float field + #[prost(float, tag = "1")] + pub roll_count: f32, +} +/// message struct +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct OperationInput { + /// string field + #[prost(string, tag = "1")] + pub content_creator_pub_key: ::prost::alloc::string::String, + /// string field + #[prost(string, tag = "2")] + pub signature: ::prost::alloc::string::String, + /// string field + #[prost(string, repeated, tag = "3")] + pub serialized_content: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +/// message struct +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SecureShareOperation { + /// object field + #[prost(message, optional, tag = "1")] + pub content: ::core::option::Option, + /// string field + #[prost(string, tag = "2")] + pub signature: ::prost::alloc::string::String, + /// string field + #[prost(string, tag = "3")] + pub content_creator_pub_key: ::prost::alloc::string::String, + /// string field + #[prost(string, tag = "4")] + pub content_creator_address: ::prost::alloc::string::String, + /// string field + #[prost(string, tag = "5")] + pub id: ::prost::alloc::string::String, +} /// region Block /// message struct #[allow(clippy::derive_partial_eq_without_eq)]