Skip to content

Commit

Permalink
feat(ethexe/rpc): implement rpc methods (#4299)
Browse files Browse the repository at this point in the history
Co-authored-by: Dmitry Novikov <novikov.dm.al@gmail.com>
osipov-mit and breathx authored Nov 5, 2024
1 parent 386b3b0 commit 08e0da7
Showing 24 changed files with 403 additions and 105 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -50,4 +50,10 @@ numerated = { workspace = true, features = ["mock"] }
[features]
default = []
strict = []
std = ["serde/std", "dep:impl-serde", "wasmparser/std", "gear-core-errors/serde"]
std = [
"serde/std",
"dep:impl-serde",
"wasmparser/std",
"gear-core-errors/serde",
"gprimitives/serde",
]
1 change: 1 addition & 0 deletions core/src/buffer.rs
Original file line number Diff line number Diff line change
@@ -35,6 +35,7 @@ use scale_info::{
/// `E` is overflow error type.
/// `N` is max len which a vector can have.
#[derive(Clone, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Decode, Encode, TypeInfo)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub struct LimitedVec<T, E, const N: usize>(Vec<T>, PhantomData<E>);

/// Formatter for [`LimitedVec`] will print to precision of 8 by default, to print the whole data, use `{:+}`.
3 changes: 3 additions & 0 deletions core/src/message/common.rs
Original file line number Diff line number Diff line change
@@ -179,6 +179,7 @@ impl Message {
TypeInfo,
derive_more::From,
)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub enum MessageDetails {
/// Reply details.
Reply(ReplyDetails),
@@ -228,6 +229,7 @@ impl MessageDetails {
#[derive(
Clone, Copy, Default, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Decode, Encode, TypeInfo,
)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub struct ReplyDetails {
/// Message id, this message replies on.
to: MessageId,
@@ -261,6 +263,7 @@ impl ReplyDetails {
#[derive(
Clone, Copy, Default, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Decode, Encode, TypeInfo,
)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub struct SignalDetails {
/// Message id, which issues signal.
to: MessageId,
1 change: 1 addition & 0 deletions core/src/message/context.rs
Original file line number Diff line number Diff line change
@@ -144,6 +144,7 @@ impl ContextOutcome {

/// Store of previous message execution context.
#[derive(Clone, Default, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Decode, Encode, TypeInfo)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub struct ContextStore {
outgoing: BTreeMap<u32, Option<Payload>>,
reply: Option<Payload>,
2 changes: 2 additions & 0 deletions core/src/message/mod.rs
Original file line number Diff line number Diff line change
@@ -60,6 +60,7 @@ const _: () = assert!(MAX_PAYLOAD_SIZE <= u32::MAX as usize);
#[derive(
Clone, Copy, Default, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Decode, Encode, TypeInfo,
)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub struct PayloadSizeError;

impl From<PayloadSizeError> for &str {
@@ -113,6 +114,7 @@ pub enum MessageWaitedType {
#[derive(
Copy, Clone, Default, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Decode, Encode, TypeInfo,
)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub enum DispatchKind {
/// Initialization.
Init,
1 change: 1 addition & 0 deletions core/src/pages.rs
Original file line number Diff line number Diff line change
@@ -195,6 +195,7 @@ impl<const SIZE: u32> PartialOrd<PagesAmount<SIZE>> for Page<SIZE> {
Default,
derive_more::Into,
)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub struct Page<const SIZE: u32>(u32);

impl<const SIZE: u32> Page<SIZE> {
1 change: 1 addition & 0 deletions core/src/program.rs
Original file line number Diff line number Diff line change
@@ -124,6 +124,7 @@ pub enum ProgramState {

/// Struct defines infix of memory pages storage.
#[derive(Clone, Copy, Debug, Default, Decode, Encode, PartialEq, Eq, TypeInfo)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub struct MemoryInfix(u32);

impl MemoryInfix {
1 change: 1 addition & 0 deletions core/src/reservation.rs
Original file line number Diff line number Diff line change
@@ -40,6 +40,7 @@ use scale_info::{
#[derive(
Clone, Copy, Default, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Decode, Encode, TypeInfo,
)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub struct ReservationNonce(u64);

impl From<&InnerNonce> for ReservationNonce {
3 changes: 2 additions & 1 deletion ethexe/common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -32,6 +32,7 @@ pub use gprimitives;

use gprimitives::ActorId;
use parity_scale_codec::{Decode, Encode};
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Encode, Decode)]
pub enum BlockEvent {
@@ -61,7 +62,7 @@ impl From<wvara::Event> for BlockEvent {
}
}

#[derive(Clone, Debug, Encode, Decode)]
#[derive(Clone, Debug, Encode, Decode, Serialize, Deserialize)]
pub enum BlockRequestEvent {
Router(router::RequestEvent),
Mirror {
3 changes: 2 additions & 1 deletion ethexe/common/src/mirror.rs
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ use alloc::vec::Vec;
use gear_core::message::ReplyCode;
use gprimitives::{ActorId, MessageId, H256};
use parity_scale_codec::{Decode, Encode};
use serde::{Deserialize, Serialize};

/* Events section */

@@ -104,7 +105,7 @@ impl Event {
}
}

#[derive(Clone, Debug, Encode, Decode)]
#[derive(Clone, Debug, Encode, Decode, Serialize, Deserialize)]
pub enum RequestEvent {
ExecutableBalanceTopUpRequested {
value: u128,
3 changes: 2 additions & 1 deletion ethexe/common/src/router.rs
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ use alloc::vec::Vec;
use gear_core::message::{Message, ReplyDetails};
use gprimitives::{ActorId, CodeId, MessageId, H256};
use parity_scale_codec::{Decode, Encode};
use serde::{Deserialize, Serialize};

/* Storage related structures */

@@ -142,7 +143,7 @@ impl Event {
}
}

#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq)]
#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, Serialize, Deserialize)]
pub enum RequestEvent {
BaseWeightChanged {
base_weight: u64,
3 changes: 2 additions & 1 deletion ethexe/common/src/wvara.rs
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@

use gprimitives::{ActorId, U256};
use parity_scale_codec::{Decode, Encode};
use serde::{Deserialize, Serialize};

/* Events section */

@@ -44,7 +45,7 @@ impl Event {
}
}

#[derive(Clone, Debug, Encode, Decode)]
#[derive(Clone, Debug, Encode, Decode, Serialize, Deserialize)]
pub enum RequestEvent {
Transfer {
/// Never router, wvara or zero address.
4 changes: 3 additions & 1 deletion ethexe/rpc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ repository.workspace = true
tokio = { workspace = true }
anyhow.workspace = true
futures.workspace = true
gprimitives.workspace = true
gprimitives = { workspace = true, features = ["serde"] }
ethexe-db.workspace = true
ethexe-processor.workspace = true
jsonrpsee = { version = "0.24", features = ["server", "macros"] }
@@ -23,5 +23,7 @@ log.workspace = true
parity-scale-codec.workspace = true
hex.workspace = true
ethexe-common.workspace = true
ethexe-runtime-common = { workspace = true, features = ["std"] }
sp-core = { workspace = true, features = ["serde"] }
gear-core = { workspace = true, features = ["std"] }
serde = { workspace = true, features = ["std"] }
73 changes: 73 additions & 0 deletions ethexe/rpc/src/apis/block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// This file is part of Gear.
//
// Copyright (C) 2024 Gear Technologies Inc.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use crate::{common::block_header_at_or_latest, errors};
use ethexe_common::BlockRequestEvent;
use ethexe_db::{BlockHeader, BlockMetaStorage, Database};
use gprimitives::H256;
use jsonrpsee::{
core::{async_trait, RpcResult},
proc_macros::rpc,
};
use std::collections::VecDeque;

#[rpc(server)]
pub trait Block {
#[method(name = "block_header")]
async fn block_header(&self, hash: Option<H256>) -> RpcResult<(H256, BlockHeader)>;

#[method(name = "block_commitmentQueue")]
async fn block_commitment_queue(&self, hash: Option<H256>) -> RpcResult<VecDeque<H256>>;

#[method(name = "block_events")]
async fn block_events(&self, block_hash: Option<H256>) -> RpcResult<Vec<BlockRequestEvent>>;
}

#[derive(Clone)]
pub struct BlockApi {
db: Database,
}

impl BlockApi {
pub fn new(db: Database) -> Self {
Self { db }
}
}

#[async_trait]
impl BlockServer for BlockApi {
async fn block_header(&self, hash: Option<H256>) -> RpcResult<(H256, BlockHeader)> {
block_header_at_or_latest(&self.db, hash)
}

async fn block_commitment_queue(&self, hash: Option<H256>) -> RpcResult<VecDeque<H256>> {
let block_hash = block_header_at_or_latest(&self.db, hash)?.0;

self.db
.block_commitment_queue(block_hash)
.ok_or_else(|| errors::db("Block commitment queue wasn't found"))
}

async fn block_events(&self, hash: Option<H256>) -> RpcResult<Vec<BlockRequestEvent>> {
let block_hash = block_header_at_or_latest(&self.db, hash)?.0;

self.db
.block_events(block_hash)
.ok_or_else(|| errors::db("Block events weren't found"))
}
}
23 changes: 23 additions & 0 deletions ethexe/rpc/src/apis/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// This file is part of Gear.
//
// Copyright (C) 2024 Gear Technologies Inc.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

mod block;
mod program;

pub use block::{BlockApi, BlockServer};
pub use program::{ProgramApi, ProgramServer};
163 changes: 163 additions & 0 deletions ethexe/rpc/src/apis/program.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
// This file is part of Gear.
//
// Copyright (C) 2024 Gear Technologies Inc.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use crate::{common::block_header_at_or_latest, errors};
use ethexe_db::{CodesStorage, Database};
use ethexe_processor::Processor;
use ethexe_runtime_common::state::{
Mailbox, MemoryPages, MessageQueue, ProgramState, Storage, Waitlist,
};
use gear_core::message::ReplyInfo;
use gprimitives::{H160, H256};
use jsonrpsee::{
core::{async_trait, RpcResult},
proc_macros::rpc,
};
use parity_scale_codec::Encode;
use sp_core::Bytes;

#[rpc(server)]
pub trait Program {
#[method(name = "program_calculateReplyForHandle")]
async fn calculate_reply_for_handle(
&self,
at: Option<H256>,
source: H160,
program_id: H160,
payload: Bytes,
value: u128,
) -> RpcResult<ReplyInfo>;

#[method(name = "program_ids")]
async fn ids(&self) -> RpcResult<Vec<H160>>;

#[method(name = "program_codeId")]
async fn code_id(&self, program_id: H160) -> RpcResult<H256>;

#[method(name = "program_readState")]
async fn read_state(&self, hash: H256) -> RpcResult<ProgramState>;

#[method(name = "program_readQueue")]
async fn read_queue(&self, hash: H256) -> RpcResult<MessageQueue>;

#[method(name = "program_readMailbox")]
async fn read_mailbox(&self, hash: H256) -> RpcResult<Mailbox>;

#[method(name = "program_readPages")]
async fn read_pages(&self, hash: H256) -> RpcResult<MemoryPages>;

#[method(name = "program_readWaitlist")]
async fn read_waitlist(&self, hash: H256) -> RpcResult<Waitlist>;

#[method(name = "program_readPageData")]
async fn read_page_data(&self, hash: H256) -> RpcResult<Bytes>;
}

pub struct ProgramApi {
db: Database,
}

impl ProgramApi {
pub fn new(db: Database) -> Self {
Self { db }
}
}

#[async_trait]
impl ProgramServer for ProgramApi {
async fn calculate_reply_for_handle(
&self,
at: Option<H256>,
source: H160,
program_id: H160,
payload: Bytes,
value: u128,
) -> RpcResult<ReplyInfo> {
let block_hash = block_header_at_or_latest(&self.db, at)?.0;

// TODO (breathx): spawn in a new thread and catch panics. (?) Generally catch runtime panics (?).
// TODO (breathx): optimize here instantiation if matches actual runtime.
let processor = Processor::new(self.db.clone()).map_err(|_| errors::internal())?;

let mut overlaid_processor = processor.overlaid();

overlaid_processor
.execute_for_reply(
block_hash,
source.into(),
program_id.into(),
payload.0,
value,
)
.map_err(errors::runtime)
}

async fn ids(&self) -> RpcResult<Vec<H160>> {
Ok(self
.db
.program_ids()
.into_iter()
.map(|id| id.try_into().unwrap())
.collect())
}

async fn code_id(&self, program_id: H160) -> RpcResult<H256> {
self.db
.program_code_id(program_id.into())
.ok_or_else(|| errors::db("Failed to get code id"))
.map(|code_id| code_id.into())
}

async fn read_state(&self, hash: H256) -> RpcResult<ProgramState> {
self.db
.read_state(hash)
.ok_or_else(|| errors::db("Failed to read state by hash"))
}

async fn read_queue(&self, hash: H256) -> RpcResult<MessageQueue> {
self.db
.read_queue(hash)
.ok_or_else(|| errors::db("Failed to read queue by hash"))
}

async fn read_mailbox(&self, hash: H256) -> RpcResult<Mailbox> {
self.db
.read_mailbox(hash)
.ok_or_else(|| errors::db("Failed to read mailbox by hash"))
}

async fn read_pages(&self, hash: H256) -> RpcResult<MemoryPages> {
self.db
.read_pages(hash)
.ok_or_else(|| errors::db("Failed to read pages by hash"))
}

// TODO: read the whole program state in a single query
async fn read_waitlist(&self, hash: H256) -> RpcResult<Waitlist> {
self.db
.read_waitlist(hash)
.ok_or_else(|| errors::db("Failed to read waitlist by hash"))
}

async fn read_page_data(&self, hash: H256) -> RpcResult<Bytes> {
self.db
.read_page_data(hash)
.map(|buf| buf.encode().into())
.ok_or_else(|| errors::db("Failed to read page data by hash"))
}
}
36 changes: 36 additions & 0 deletions ethexe/rpc/src/common.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// This file is part of Gear.
//
// Copyright (C) 2024 Gear Technologies Inc.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use crate::errors;
use ethexe_db::{BlockHeader, BlockMetaStorage, Database};
use gprimitives::H256;
use jsonrpsee::core::RpcResult;

pub fn block_header_at_or_latest(
db: &Database,
at: impl Into<Option<H256>>,
) -> RpcResult<(H256, BlockHeader)> {
if let Some(hash) = at.into() {
db.block_header(hash)
.map(|header| (hash, header))
.ok_or_else(|| errors::db("Block header for requested hash wasn't found"))
} else {
db.latest_valid_block()
.ok_or_else(|| errors::db("Latest block header wasn't found"))
}
}
31 changes: 31 additions & 0 deletions ethexe/rpc/src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// This file is part of Gear.
//
// Copyright (C) 2024 Gear Technologies Inc.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use jsonrpsee::types::ErrorObject;

pub fn db(err: &'static str) -> ErrorObject<'static> {
ErrorObject::owned(8000, "Database error", Some(err))
}

pub fn runtime(err: anyhow::Error) -> ErrorObject<'static> {
ErrorObject::owned(8000, "Runtime error", Some(format!("{err}")))
}

pub fn internal() -> ErrorObject<'static> {
ErrorObject::owned(8000, "Internal error", None::<&str>)
}
110 changes: 12 additions & 98 deletions ethexe/rpc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -17,121 +17,31 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use anyhow::anyhow;
use ethexe_db::{BlockHeader, BlockMetaStorage, Database};
use ethexe_processor::Processor;
use apis::{BlockApi, BlockServer, ProgramApi, ProgramServer};
use ethexe_db::Database;
use futures::FutureExt;
use gear_core::message::ReplyInfo;
use gprimitives::{H160, H256};
use jsonrpsee::{
core::{async_trait, RpcResult},
proc_macros::rpc,
server::{
serve_with_graceful_shutdown, stop_channel, Server, ServerHandle, StopHandle,
TowerServiceBuilder,
},
types::ErrorObject,
Methods,
Methods, RpcModule as JsonrpcModule,
};
use sp_core::Bytes;
use std::net::SocketAddr;
use tokio::net::TcpListener;
use tower::Service;

mod apis;
mod common;
mod errors;

#[derive(Clone)]
struct PerConnection<RpcMiddleware, HttpMiddleware> {
methods: Methods,
stop_handle: StopHandle,
svc_builder: TowerServiceBuilder<RpcMiddleware, HttpMiddleware>,
}

#[rpc(server)]
pub trait RpcApi {
#[method(name = "blockHeader")]
async fn block_header(&self, hash: Option<H256>) -> RpcResult<(H256, BlockHeader)>;

#[method(name = "calculateReplyForHandle")]
async fn calculate_reply_for_handle(
&self,
at: Option<H256>,
source: H160,
program_id: H160,
payload: Bytes,
value: u128,
) -> RpcResult<ReplyInfo>;
}

pub struct RpcModule {
db: Database,
}

impl RpcModule {
pub fn new(db: Database) -> Self {
Self { db }
}

pub fn block_header_at_or_latest(
&self,
at: impl Into<Option<H256>>,
) -> RpcResult<(H256, BlockHeader)> {
if let Some(hash) = at.into() {
self.db
.block_header(hash)
.map(|header| (hash, header))
.ok_or_else(|| db_err("Block header for requested hash wasn't found"))
} else {
self.db
.latest_valid_block()
.ok_or_else(|| db_err("Latest block header wasn't found"))
}
}
}

#[async_trait]
impl RpcApiServer for RpcModule {
async fn block_header(&self, hash: Option<H256>) -> RpcResult<(H256, BlockHeader)> {
self.block_header_at_or_latest(hash)
}

async fn calculate_reply_for_handle(
&self,
at: Option<H256>,
source: H160,
program_id: H160,
payload: Bytes,
value: u128,
) -> RpcResult<ReplyInfo> {
let block_hash = self.block_header_at_or_latest(at)?.0;

// TODO (breathx): spawn in a new thread and catch panics. (?) Generally catch runtime panics (?).
// TODO (breathx): optimize here instantiation if matches actual runtime.
let processor = Processor::new(self.db.clone()).map_err(|_| internal())?;

let mut overlaid_processor = processor.overlaid();

overlaid_processor
.execute_for_reply(
block_hash,
source.into(),
program_id.into(),
payload.0,
value,
)
.map_err(runtime_err)
}
}

fn db_err(err: &'static str) -> ErrorObject<'static> {
ErrorObject::owned(8000, "Database error", Some(err))
}

fn runtime_err(err: anyhow::Error) -> ErrorObject<'static> {
ErrorObject::owned(8000, "Runtime error", Some(format!("{err}")))
}

fn internal() -> ErrorObject<'static> {
ErrorObject::owned(8000, "Internal error", None::<&str>)
}

pub struct RpcConfig {
port: u16,
db: Database,
@@ -153,7 +63,11 @@ impl RpcService {
TcpListener::bind(SocketAddr::from(([127, 0, 0, 1], self.config.port))).await?;

let service_builder = Server::builder().to_service_builder();
let module = RpcApiServer::into_rpc(RpcModule::new(self.config.db));
let mut module = JsonrpcModule::new(());
module.merge(ProgramServer::into_rpc(ProgramApi::new(
self.config.db.clone(),
)))?;
module.merge(BlockServer::into_rpc(BlockApi::new(self.config.db.clone())))?;

let (stop_handle, server_handle) = stop_channel();

10 changes: 9 additions & 1 deletion ethexe/runtime/common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -21,7 +21,15 @@ gear-core-errors.workspace = true
anyhow.workspace = true
parity-scale-codec.workspace = true
log.workspace = true
serde = { workspace = true, features = ["derive"], optional = true }

[features]
default = ["std"]
std = ["anyhow/std", "core-processor/std", "log/std"]
std = [
"anyhow/std",
"core-processor/std",
"gear-core/std",
"gprimitives/serde",
"log/std",
"serde/std",
]
6 changes: 6 additions & 0 deletions ethexe/runtime/common/src/state.rs
Original file line number Diff line number Diff line change
@@ -48,6 +48,7 @@ pub use gear_core::program::ProgramState as InitStatus;
pub const MAILBOX_VALIDITY: u32 = 54_000;

#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub struct HashAndLen {
pub hash: H256,
pub len: NonZero<u32>,
@@ -64,6 +65,7 @@ impl From<H256> for HashAndLen {
}

#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub enum MaybeHash {
Hash(HashAndLen),
Empty,
@@ -102,6 +104,7 @@ impl MaybeHash {
}

#[derive(Clone, Debug, Decode, Encode, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub struct ActiveProgram {
/// Hash of wasm memory pages allocations, see [`Allocations`].
pub allocations_hash: MaybeHash,
@@ -114,6 +117,7 @@ pub struct ActiveProgram {
}

#[derive(Clone, Debug, Decode, Encode, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub enum Program {
Active(ActiveProgram),
Exited(ProgramId),
@@ -138,6 +142,7 @@ impl Program {

/// ethexe program state.
#[derive(Clone, Debug, Decode, Encode, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub struct ProgramState {
/// Active, exited or terminated program state.
pub program: Program,
@@ -193,6 +198,7 @@ impl ProgramState {
}

#[derive(Clone, Debug, Encode, Decode)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub struct Dispatch {
/// Message id.
pub id: MessageId,
5 changes: 5 additions & 0 deletions ethexe/signer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@ mod digest;
mod signature;

pub use digest::{Digest, ToDigest};
use secp256k1::hashes::hex::{Case, DisplayHex};
pub use sha3;
pub use signature::Signature;

@@ -249,6 +250,10 @@ impl Signer {
let local_public = PublicKey::from_bytes(public_key.serialize());

let key_file = self.key_store.join(local_public.to_hex());
println!(
"Secret key: {}",
secret_key.secret_bytes().to_hex_string(Case::Lower)
);
fs::write(key_file, secret_key.secret_bytes())?;
Ok(local_public)
}
14 changes: 14 additions & 0 deletions gprimitives/src/lib.rs
Original file line number Diff line number Diff line change
@@ -119,6 +119,20 @@ impl From<H160> for ActorId {
}
}

impl TryInto<H160> for ActorId {
type Error = &'static str;

fn try_into(self) -> Result<H160, Self::Error> {
if !self.0[..12].iter().all(|i| i.eq(&0)) {
Err("ActorId has non-zero prefix")
} else {
let mut h160 = H160::zero();
h160.0.copy_from_slice(&self.into_bytes()[12..]);
Ok(h160)
}
}
}

impl fmt::Display for ActorId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let byte_array = utils::ByteArray(&self.0);

0 comments on commit 08e0da7

Please sign in to comment.