Skip to content

Commit

Permalink
feat: add get proof
Browse files Browse the repository at this point in the history
  • Loading branch information
driftluo committed Nov 10, 2023
1 parent cdc2944 commit 71070fb
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 22 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions common/apm/src/metrics/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ make_auto_flush_static_metric! {
eth_getUncleByBlockNumberAndIndex,
eth_getUncleCountByBlockHash,
eth_getUncleCountByBlockNumber,
eth_getProof,
}

pub label_enum Request_Result {
Expand Down
1 change: 1 addition & 0 deletions core/api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ tower-http = { version = "0.4", features = ["cors"] }

common-apm = { path = "../../common/apm" }
common-config-parser = { path = "../../common/config-parser" }
common-hasher = { path = "../../common/hasher" }
core-consensus = { path = "../../core/consensus" }
core-executor = { path = "../../core/executor" }
core-interoperation = { path = "../../core/interoperation" }
Expand Down
64 changes: 60 additions & 4 deletions core/api/src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ use protocol::traits::{
};
use protocol::trie::Trie as _;
use protocol::types::{
Account, BigEndianHash, Block, BlockNumber, Bytes, CkbRelatedInfo, ExecutorContext,
HardforkInfo, HardforkInfoInner, Hash, Header, Metadata, Proposal, Receipt, SignedTransaction,
TxResp, H160, H256, MAX_BLOCK_GAS_LIMIT, NIL_DATA, RLP_NULL, U256,
Account, BigEndianHash, Block, BlockNumber, Bytes, CkbRelatedInfo, EthAccountProof,
EthStorageProof, ExecutorContext, HardforkInfo, HardforkInfoInner, Hash, Hasher, Header, Hex,
Metadata, Proposal, Receipt, SignedTransaction, TxResp, H160, H256, MAX_BLOCK_GAS_LIMIT,
NIL_DATA, RLP_NULL, U256,
};
use protocol::{async_trait, codec::ProtocolCodec, trie, ProtocolResult};
use protocol::{async_trait, codec::ProtocolCodec, trie, ProtocolError, ProtocolResult};

use core_executor::{
system_contract::metadata::MetadataHandle, AxonExecutor, AxonExecutorReadOnlyAdapter, MPTTrie,
Expand Down Expand Up @@ -240,6 +241,61 @@ where
.ok_or_else(|| APIError::Adapter("Can't find this position".to_string()).into())
}

async fn get_proof(
&self,
_ctx: Context,
address: H160,
storage_position: Vec<U256>,
state_root: Hash,
) -> ProtocolResult<EthAccountProof> {
let state_mpt_tree = MPTTrie::from_root(state_root, Arc::clone(&self.trie_db))?;
let raw_account = state_mpt_tree
.get(address.as_bytes())?
.ok_or_else(|| APIError::Adapter("Can't find this address".to_string()))?;

let account = Account::decode(raw_account).unwrap();

let account_proof = state_mpt_tree
.get_proof(address.as_bytes())?
.into_iter()
.map(Hex::encode)
.collect();

let storage_mpt_tree = MPTTrie::from_root(account.storage_root, Arc::clone(&self.trie_db))?;

let mut storage_proofs = Vec::with_capacity(storage_position.len());

for h in storage_position {
let hash: Hash = BigEndianHash::from_uint(&h);
let proof = EthStorageProof {
key: hash,
value: storage_mpt_tree
.get(hash.as_bytes())?
.map(|v| H256::from_slice(&v))
.ok_or_else(|| {
Into::<ProtocolError>::into(APIError::Adapter(
"Can't find this position".to_string(),
))
})?,
proof: state_mpt_tree
.get_proof(hash.as_bytes())?
.into_iter()
.map(Hex::encode)
.collect(),
};
storage_proofs.push(proof);
}

Ok(EthAccountProof {
balance: account.balance,
code_hash: account.code_hash,
nonce: account.nonce,
storage_hash: Hasher::digest(&account.storage_root),
account_proof,
storage_proof: storage_proofs,
})
}

async fn get_metadata_by_number(
&self,
ctx: Context,
Expand Down
36 changes: 29 additions & 7 deletions core/api/src/jsonrpc/impl/web3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ use jsonrpsee::core::RpcResult;
use common_apm::metrics_rpc;
use protocol::traits::{APIAdapter, Context, Interoperation};
use protocol::types::{
Block, BlockNumber, Bytes, CellDepWithPubKey, Hash, Hasher, Header, Hex, Proposal, Receipt,
SignatureComponents, SignatureR, SignatureS, SignedTransaction, TxResp, UnverifiedTransaction,
BASE_FEE_PER_GAS, H160, H256, MAX_FEE_HISTORY, MAX_RPC_GAS_CAP, MIN_TRANSACTION_GAS_LIMIT,
U256,
Block, BlockNumber, Bytes, CellDepWithPubKey, EthAccountProof, Hash, Hasher, Header, Hex,
Proposal, Receipt, SignatureComponents, SignatureR, SignatureS, SignedTransaction, TxResp,
UnverifiedTransaction, BASE_FEE_PER_GAS, H160, H256, MAX_FEE_HISTORY, MAX_RPC_GAS_CAP,
MIN_TRANSACTION_GAS_LIMIT, U256,
};
use protocol::{
async_trait, ckb_blake2b_256, codec::ProtocolCodec, lazy::PROTOCOL_VERSION, ProtocolResult,
Expand Down Expand Up @@ -1042,15 +1042,15 @@ impl<Adapter: APIAdapter + 'static> Web3RpcServer for Web3RpcImpl<Adapter> {
) -> RpcResult<Hex> {
let number = self.get_block_number_by_id(block_id).await?;

let block = self
let header = self
.adapter
.get_block_by_number(Context::new(), number)
.get_block_header_by_number(Context::new(), number)
.await
.map_err(|e| RpcError::Internal(e.to_string()))?
.ok_or(RpcError::CannotFindBlock)?;
let value = self
.adapter
.get_storage_at(Context::new(), address, position, block.header.state_root)
.get_storage_at(Context::new(), address, position, header.state_root)
.await
.unwrap_or_else(|_| H256::default().as_bytes().to_vec().into());

Expand Down Expand Up @@ -1089,6 +1089,28 @@ impl<Adapter: APIAdapter + 'static> Web3RpcServer for Web3RpcImpl<Adapter> {
async fn get_uncle_count_by_block_number(&self, _number: BlockId) -> RpcResult<U256> {
Ok(U256::zero())
}

#[metrics_rpc("eth_getProof")]
async fn get_proof(
&self,
address: H160,
storage_position: Vec<U256>,
number: BlockId,
) -> RpcResult<EthAccountProof> {
let number = self.get_block_number_by_id(Some(number)).await?;

let header = self
.adapter
.get_block_header_by_number(Context::new(), number)
.await
.map_err(|e| RpcError::Internal(e.to_string()))?
.ok_or(RpcError::CannotFindBlock)?;

self.adapter
.get_proof(Context::new(), address, storage_position, header.state_root)
.await
.map_err(|e| RpcError::Internal(e.to_string()).into())
}
}

// 1. checks for rewardPercentile's sorted-ness
Expand Down
19 changes: 13 additions & 6 deletions core/api/src/jsonrpc/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod error;
mod r#impl;
mod web3_types;
pub mod web3_types;
mod ws_subscription;

use std::{collections::HashMap, sync::Arc};
Expand All @@ -14,19 +14,18 @@ use tower_http::cors::{Any as CorsAny, CorsLayer};
use common_config_parser::types::{spec::HardforkName, Config};
use protocol::traits::APIAdapter;
use protocol::types::{
Block, CkbRelatedInfo, Hash, Hex, Metadata, Proof, Proposal, H160, H256, U256,
Block, CkbRelatedInfo, EthAccountProof, Hash, Hex, Metadata, Proof, Proposal, H160, H256, U256,
};
use protocol::ProtocolResult;

use crate::jsonrpc::web3_types::{
BlockId, FilterChanges, HardforkStatus, RawLoggerFilter, Web3Block, Web3CallRequest,
Web3FeeHistory, Web3Filter, Web3Log, Web3Receipt, Web3SyncStatus, Web3Transaction,
BlockCount, BlockId, FilterChanges, HardforkStatus, RawLoggerFilter, Web3Block,
Web3CallRequest, Web3FeeHistory, Web3Filter, Web3Log, Web3Receipt, Web3SyncStatus,
Web3Transaction,
};
use crate::jsonrpc::ws_subscription::{ws_subscription_module, HexIdProvider};
use crate::APIError;

use self::web3_types::BlockCount;

#[rpc(server)]
pub trait Web3Rpc {
/// Sends signed transaction, returning its hash.
Expand Down Expand Up @@ -147,6 +146,14 @@ pub trait Web3Rpc {

#[method(name = "eth_getUncleCountByBlockNumber")]
async fn get_uncle_count_by_block_number(&self, number: BlockId) -> RpcResult<U256>;

#[method(name = "eth_getProof")]
async fn get_proof(
&self,
address: H160,
storage_position: Vec<U256>,
number: BlockId,
) -> RpcResult<EthAccountProof>;
}

#[rpc(server)]
Expand Down
13 changes: 11 additions & 2 deletions protocol/src/traits/api.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::types::{
Account, Block, BlockNumber, Bytes, CkbRelatedInfo, HardforkInfo, HardforkInfoInner, Hash,
Header, Metadata, Proposal, Receipt, SignedTransaction, TxResp, H160, H256, U256,
Account, Block, BlockNumber, Bytes, CkbRelatedInfo, EthAccountProof, HardforkInfo,
HardforkInfoInner, Hash, Header, Metadata, Proposal, Receipt, SignedTransaction, TxResp, H160,
H256, U256,
};
use crate::{async_trait, traits::Context, ProtocolResult};

Expand Down Expand Up @@ -109,4 +110,12 @@ pub trait APIAdapter: Send + Sync {
async fn hardfork_info(&self, ctx: Context) -> ProtocolResult<HardforkInfo>;

async fn hardfork_proposal(&self, ctx: Context) -> ProtocolResult<Option<HardforkInfoInner>>;

async fn get_proof(
&self,
_ctx: Context,
address: H160,
storage_position: Vec<U256>,
state_root: Hash,
) -> ProtocolResult<EthAccountProof>;
}
26 changes: 25 additions & 1 deletion protocol/src/types/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@ pub use evm::{backend::Log, Config, ExitError, ExitFatal, ExitReason, ExitRevert
pub use hasher::HasherKeccak;

use rlp_derive::{RlpDecodable, RlpEncodable};
use serde::{Deserialize, Serialize};

use crate::types::{Bloom, ExtraData, Hash, Hasher, Header, MerkleRoot, Proposal, H160, U256};
use crate::types::{
Bloom, ExtraData, Hash, Hasher, Header, MerkleRoot, Proposal, H160, H256, U256,
};

use super::Hex;

const BLOOM_BYTE_LENGTH: usize = 256;

Expand Down Expand Up @@ -88,6 +93,25 @@ impl From<&Header> for ExecutorContext {
}
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
pub struct EthAccountProof {
pub balance: U256,
pub code_hash: H256,
pub nonce: U256,
pub storage_hash: H256,
pub account_proof: Vec<Hex>,
pub storage_proof: Vec<EthStorageProof>,
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
pub struct EthStorageProof {
pub key: H256,
pub value: H256,
pub proof: Vec<Hex>,
}

pub fn logs_bloom<'a, I>(logs: I) -> Bloom
where
I: Iterator<Item = &'a Log>,
Expand Down
4 changes: 2 additions & 2 deletions protocol/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ pub use bytes::{Buf, BufMut, Bytes, BytesMut};
pub use ckb_client::*;
pub use evm::{backend::*, ExitError, ExitRevert, ExitSucceed};
pub use executor::{
logs_bloom, AccessList, AccessListItem, Account, Config, ExecResp, ExecutorContext, ExitReason,
HasherKeccak, TxResp,
logs_bloom, AccessList, AccessListItem, Account, Config, EthAccountProof, EthStorageProof,
ExecResp, ExecutorContext, ExitReason, HasherKeccak, TxResp,
};
pub use interoperation::*;
pub use primitive::*;
Expand Down

0 comments on commit 71070fb

Please sign in to comment.