diff --git a/src/rpc/miner.rs b/src/rpc/miner.rs index ac82b87ffadec4ed00a98c38d0265c7ed041185b..9735c881ce631f380f2b9b2088b8fd5c399eb163 100644 --- a/src/rpc/miner.rs +++ b/src/rpc/miner.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use anyhow::format_err; use ecomobicoin_jsonrpc::types::{self}; -use ethereum_types::H256; +use ethereum_types::{H256, U64}; use fastrlp::Decodable; use itertools::Itertools; use jsonrpsee::{ @@ -13,7 +13,6 @@ use mdbx::WriteMap; use rand::Rng; use tracing::{debug, info}; -use crate::consensus::miner::get_latest_parent_header; use crate::{ accessors::chain, consensus::{ @@ -23,10 +22,12 @@ use crate::{ execution::{analysis_cache::AnalysisCache, tracer::NoopTracer}, kv::MdbxWithDirHandle, models::{ - behavior::BehaviorWithSignature, BlockNumber, ChainSpec, ExecutedBlock, - MessageWithSignature, + behavior::{Behavior, BehaviorWithSignature}, + BlockNumber, ChainId, ChainSpec, ExecutedBlock, MessageWithSignature, YParityAndChainId, }, + rpc::helpers::{new_jsonrpc_bx, new_jsonrpc_tx}, }; +use crate::{consensus::miner::get_latest_parent_header, models::behavior::BehaviorSignature}; use crate::{kv::tables, p2p::node::Node}; use super::helpers; @@ -34,11 +35,20 @@ use super::helpers; #[rpc(server, client, namespace = "emc")] pub trait MinerApi { #[method(name = "mine")] - async fn mine(&self, behavior: BehaviorWithSignature) -> RpcResult<ExecutedBlock>; + async fn mine( + &self, + behavior: ecomobicoin_jsonrpc::types::Behavior, + ) -> RpcResult<ecomobicoin_jsonrpc::types::Block>; #[method(name = "send_raw_behavior")] - async fn send_raw_behavior(&self, behavior_data: types::Bytes) -> RpcResult<H256>; + async fn send_raw_behavior( + &self, + behavior_data: ecomobicoin_jsonrpc::types::Bytes, + ) -> RpcResult<H256>; #[method(name = "send_raw_transaction")] - async fn send_raw_transaction(&self, transaction_data: types::Bytes) -> RpcResult<H256>; + async fn send_raw_transaction( + &self, + transaction_data: ecomobicoin_jsonrpc::types::Bytes, + ) -> RpcResult<H256>; // SendTransaction signs and submits a transaction (supposing the private key is managed by the node so not used yet by Ecomobicoin) // #[method(name = "send_behavior")] @@ -55,13 +65,16 @@ pub struct MinerRpc { #[async_trait] impl MinerApiServer for MinerRpc { - async fn mine(&self, behavior: BehaviorWithSignature) -> RpcResult<ExecutedBlock> { - let db1 = Arc::clone(&self.db); - let db2 = Arc::clone(&self.db); - let db3 = Arc::clone(&self.db); + async fn mine( + &self, + miner_behavior: ecomobicoin_jsonrpc::types::Behavior, + ) -> RpcResult<ecomobicoin_jsonrpc::types::Block> { + let db_engine = Arc::clone(&self.db); + let db_miner = Arc::clone(&self.db); + let db_spec = Arc::clone(&self.db); - let tx = db3.begin()?; - let last_header = get_latest_parent_header(&tx); + let txn = db_spec.begin()?; + let last_header = get_latest_parent_header(&txn); let last_block_number = { if last_header.is_err() { BlockNumber(0) @@ -74,18 +87,42 @@ impl MinerApiServer for MinerRpc { let block_spec = self.chain_spec.collect_block_spec(last_block_number); let node = self.node.clone(); + let total_difficulty = chain::td::read(&txn, last_block_number)?; + tokio::task::spawn_blocking(move || { let mut analysis_cache = AnalysisCache::default(); let mut tracer = NoopTracer; // engine already created in `akula.rs`, should we re-use it ? - let engine = engine_factory(Some(db1), chain_spec, None)?; + let engine = engine_factory(Some(db_engine), chain_spec, None)?; + + let YParityAndChainId { + odd_y_parity, + chain_id: chain_id_from_v, + } = YParityAndChainId::from_v(miner_behavior.v.as_u64()).unwrap(); + if chain_id_from_v.is_some() { + assert_eq!( + node.config.chain_spec.params.chain_id.0, + chain_id_from_v.unwrap().0 + ); + } - let miner_addr = behavior.recover_sender()?; + let behavior_model = BehaviorWithSignature { + behavior: Behavior { + chain_id: ChainId(miner_behavior.message.chain_id.as_u64()), + quantity: miner_behavior.message.quantity, + timestamp: miner_behavior.message.timestamp.as_u64(), + input: miner_behavior.message.input.into(), + }, + signature: BehaviorSignature::new(odd_y_parity, miner_behavior.r, miner_behavior.s) + .unwrap(), + }; + + let miner_addr = behavior_model.recover_sender()?; debug!( "mine() with Behavior:{:?} from {:?}", - behavior.clone(), + behavior_model.clone(), miner_addr.clone() ); @@ -102,19 +139,88 @@ impl MinerApiServer for MinerRpc { &mut analysis_cache, engine, &block_spec, - db2, + db_miner, node, ); //MINE - let executed_block: ExecutedBlock = miner.start_from_pob_m(behavior)?; + let executed_block: ExecutedBlock = miner.start_from_pob_m(behavior_model)?; + let block_hash = executed_block.header.hash(); + let block_number = executed_block.header.number; debug!( "Mined block #{:?}, hash {:?}", executed_block.header.number, executed_block.header.hash() ); debug!("Content of mined block {:?}", executed_block); - Ok(executed_block) + + let total_difficulty = if total_difficulty.is_some() { + Some(total_difficulty.unwrap() + executed_block.header.difficulty) + } else { + Some(executed_block.header.difficulty) + }; + + Ok(ecomobicoin_jsonrpc::types::Block { + number: Some(U64::from(block_number.0)), + hash: Some(block_hash), + parent_hash: executed_block.header.parent_hash, + sha3_uncles: executed_block.header.ommers_hash, + logs_bloom: Some(executed_block.header.logs_bloom), + behaviors_bloom: Some(executed_block.header.behaviors_bloom), + transactions_root: executed_block.header.transactions_root, + behaviors_root: executed_block.header.behaviors_root, + state_root: executed_block.header.state_root, + receipts_root: executed_block.header.receipts_root, + miner: miner_addr, + difficulty: executed_block.header.difficulty, + total_difficulty, + seal_fields: None, + nonce: Some(executed_block.header.nonce), + mix_hash: Some(executed_block.header.mix_hash), + extra_data: executed_block.header.extra_data.into(), + size: U64::zero(), + gas_limit: U64::from(executed_block.header.gas_limit), + gas_used: U64::from(executed_block.header.gas_used), + timestamp: U64::from(executed_block.header.timestamp), + behavior_total_quantity: executed_block.header.behavior_total_quantity, + transactions: executed_block + .transactions + .into_iter() + .enumerate() + .map(|(index, tx)| { + types::Tx::Transaction(Box::new(new_jsonrpc_tx( + tx.clone(), + tx.recover_sender().unwrap(), + Some(index as u64), + Some(block_hash), + Some(block_number), + ))) + }) + .collect(), + behaviors: executed_block + .behaviors + .into_iter() + .enumerate() + .map(|(index, bx)| { + types::Bx::Behavior(Box::new(new_jsonrpc_bx( + bx.clone(), + bx.recover_sender().unwrap(), + Some(index as u64), + Some(block_hash), + Some(block_number), + ))) + }) + .collect(), + uncles: executed_block + .ommers + .into_iter() + .map(|uncle| uncle.hash()) + .collect(), + base_fee_per_gas: executed_block.header.base_fee_per_gas, + vdf_challenge: executed_block.header.vdf_proof_challenge, + vdf_difficulty: U64::from(executed_block.header.vdf_difficulty), + vdf_result: executed_block.header.vdf_proof_result, + }) }) .await .unwrap_or_else(helpers::joinerror_to_result) diff --git a/src/rpc/otterscan.rs b/src/rpc/otterscan.rs index bef02d2dc4161f022f34b6885564ae25b429f628..a9bb7edb7d32712b40a9b053139037a8f1b9005e 100644 --- a/src/rpc/otterscan.rs +++ b/src/rpc/otterscan.rs @@ -15,7 +15,6 @@ use ecomobicoin_jsonrpc::{ use jsonrpsee::core::RpcResult; use tokio::pin; -use crate::models::behavior::BehaviorWithSignature; use crate::{ accessors::chain, consensus::{engine_factory, FinalizationChange},