diff --git a/ethexe/common/src/primitives.rs b/ethexe/common/src/primitives.rs index 070e5052d5a..a7fba6d2935 100644 --- a/ethexe/common/src/primitives.rs +++ b/ethexe/common/src/primitives.rs @@ -78,7 +78,7 @@ pub struct SimpleBlockData { pub header: BlockHeader, } -#[cfg_attr(feature = "serde", derive(Hash))] +#[cfg_attr(feature = "serde", derive(Hash, serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, Encode, Decode, TypeInfo, PartialEq, Eq, derive_more::Display)] #[display( "Announce(block: {block_hash}, parent: {parent}, gas: {gas_allowance:?}, txs: {injected_transactions:?})" @@ -140,7 +140,7 @@ pub enum PromisePolicy { } #[derive(PartialEq, Eq, Hash, Debug, Clone, Copy, Default, Encode, Decode, TypeInfo)] -#[cfg_attr(feature = "std", derive(serde::Serialize))] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub struct StateHashWithQueueSize { pub hash: H256, pub canonical_queue_size: u8, diff --git a/ethexe/rpc/src/apis/announce.rs b/ethexe/rpc/src/apis/announce.rs new file mode 100644 index 00000000000..13923f55f60 --- /dev/null +++ b/ethexe/rpc/src/apis/announce.rs @@ -0,0 +1,89 @@ +// This file is part of Gear. +// +// Copyright (C) 2026 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 . + +use crate::{errors, utils}; +use ethexe_common::{Announce, ProgramStates, db::AnnounceStorageRO, gear::StateTransition}; +use ethexe_db::Database; +use jsonrpsee::{ + core::{RpcResult, async_trait}, + proc_macros::rpc, +}; +use sp_core::H256; + +#[cfg_attr(not(feature = "client"), rpc(server))] +#[cfg_attr(feature = "client", rpc(server, client))] +pub trait Announce { + #[method(name = "announce_by_hash")] + async fn announce(&self, announce_hash: Option) -> RpcResult<(H256, Announce)>; + + #[method(name = "announce_outcome")] + async fn announce_outcome( + &self, + announce_hash: Option, + ) -> RpcResult>; + + #[method(name = "announce_program_states")] + async fn announce_program_states( + &self, + announce_hash: Option, + ) -> RpcResult; +} + +#[derive(Debug, Clone)] +pub struct AnnounceApi { + db: Database, +} + +impl AnnounceApi { + pub fn new(db: Database) -> Self { + Self { db } + } +} + +#[async_trait] +impl AnnounceServer for AnnounceApi { + async fn announce(&self, announce_hash: Option) -> RpcResult<(H256, Announce)> { + let hash = utils::announce_at_or_latest_computed(&self.db, announce_hash)?; + let announce = self + .db + .announce(hash) + .ok_or_else(|| errors::db("Announce wasn't found"))?; + + Ok((hash.inner(), announce)) + } + + async fn announce_outcome( + &self, + announce_hash: Option, + ) -> RpcResult> { + let hash = utils::announce_at_or_latest_computed(&self.db, announce_hash)?; + self.db + .announce_outcome(hash) + .ok_or_else(|| errors::db("Announce outcome wasn't found")) + } + + async fn announce_program_states( + &self, + announce_hash: Option, + ) -> RpcResult { + let hash = utils::announce_at_or_latest_computed(&self.db, announce_hash)?; + self.db + .announce_program_states(hash) + .ok_or_else(|| errors::db("Announce program states weren't found")) + } +} diff --git a/ethexe/rpc/src/apis/mod.rs b/ethexe/rpc/src/apis/mod.rs index 8ed642f4ca1..1c4ec34bbef 100644 --- a/ethexe/rpc/src/apis/mod.rs +++ b/ethexe/rpc/src/apis/mod.rs @@ -16,11 +16,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +mod announce; mod block; mod code; mod injected; mod program; +pub use announce::{AnnounceApi, AnnounceServer}; pub use block::{BlockApi, BlockServer}; pub use code::{CodeApi, CodeServer}; pub use injected::{InjectedApi, InjectedServer}; @@ -28,5 +30,6 @@ pub use program::{FullProgramState, ProgramApi, ProgramServer}; #[cfg(feature = "client")] pub use crate::apis::{ - block::BlockClient, code::CodeClient, injected::InjectedClient, program::ProgramClient, + announce::AnnounceClient, block::BlockClient, code::CodeClient, injected::InjectedClient, + program::ProgramClient, }; diff --git a/ethexe/rpc/src/lib.rs b/ethexe/rpc/src/lib.rs index 4a142649b76..300533cd913 100644 --- a/ethexe/rpc/src/lib.rs +++ b/ethexe/rpc/src/lib.rs @@ -17,12 +17,14 @@ // along with this program. If not, see . #[cfg(feature = "client")] -pub use crate::apis::{BlockClient, CodeClient, FullProgramState, InjectedClient, ProgramClient}; +pub use crate::apis::{ + AnnounceClient, BlockClient, CodeClient, FullProgramState, InjectedClient, ProgramClient, +}; use anyhow::Result; use apis::{ - BlockApi, BlockServer, CodeApi, CodeServer, InjectedApi, InjectedServer, ProgramApi, - ProgramServer, + AnnounceApi, AnnounceServer, BlockApi, BlockServer, CodeApi, CodeServer, InjectedApi, + InjectedServer, ProgramApi, ProgramServer, }; use ethexe_common::injected::{ AddressedInjectedTransaction, InjectedTransactionAcceptance, SignedPromise, @@ -113,6 +115,7 @@ impl RpcServer { let server_apis = RpcServerApis { code: CodeApi::new(self.db.clone()), block: BlockApi::new(self.db.clone()), + announce: AnnounceApi::new(self.db.clone()), program: ProgramApi::new(self.db.clone(), processor, self.config.gas_allowance), injected: InjectedApi::new(rpc_sender), }; @@ -181,6 +184,7 @@ impl FusedStream for RpcService { struct RpcServerApis { pub block: BlockApi, + pub announce: AnnounceApi, pub code: CodeApi, pub injected: InjectedApi, pub program: ProgramApi, @@ -193,6 +197,9 @@ impl RpcServerApis { module .merge(BlockServer::into_rpc(self.block)) .expect("No conflicts"); + module + .merge(AnnounceServer::into_rpc(self.announce)) + .expect("No conflicts"); module .merge(CodeServer::into_rpc(self.code)) .expect("No conflicts");