Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle full_transactions flag in getBlock* RPCs #1976

Merged
merged 3 commits into from
May 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 65 additions & 19 deletions lib/ain-grpc/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use serde::{
};
use std::fmt;

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct RpcBlock {
pub hash: H256,
Expand All @@ -26,35 +26,58 @@ pub struct RpcBlock {
pub total_difficulty: Option<U256>,
pub seal_fields: Vec<Vec<u8>>,
pub uncles: Vec<H256>,
pub transactions: Vec<H256>,
pub transactions: BlockTransactions,
pub nonce: U256,
pub sha3_uncles: String,
pub logs_bloom: String,
pub size: String,
}

impl From<BlockAny> for RpcBlock {
fn from(b: BlockAny) -> Self {
let header_size = b.header.rlp_bytes().len();
impl RpcBlock {
pub fn from_block_with_tx(block: BlockAny, full_transactions: bool) -> Self {
let header_size = block.header.rlp_bytes().len();
RpcBlock {
hash: b.header.hash(),
mix_hash: b.header.hash(),
number: b.header.number,
parent_hash: b.header.parent_hash,
transactions_root: b.header.transactions_root,
state_root: b.header.state_root,
receipts_root: b.header.receipts_root,
miner: b.header.beneficiary,
difficulty: b.header.difficulty,
hash: block.header.hash(),
mix_hash: block.header.hash(),
number: block.header.number,
parent_hash: block.header.parent_hash,
transactions_root: block.header.transactions_root,
state_root: block.header.state_root,
receipts_root: block.header.receipts_root,
miner: block.header.beneficiary,
difficulty: block.header.difficulty,
total_difficulty: Some(U256::zero()),
seal_fields: vec![],
gas_limit: b.header.gas_limit,
gas_used: b.header.gas_used,
timestamp: b.header.timestamp.into(),
transactions: b.transactions.into_iter().map(|t| t.hash()).collect(),
gas_limit: block.header.gas_limit,
gas_used: block.header.gas_used,
timestamp: block.header.timestamp.into(),
transactions: {
if full_transactions {
// Discard failed to retrieved transactions with flat_map.
// Should not happen as the transaction should not make it in the block in the first place.
BlockTransactions::Full(
block
.transactions
.iter()
.enumerate()
.flat_map(|(index, tx)| {
EthTransactionInfo::try_from_tx_block_and_index(tx, &block, index)
})
.collect(),
)
} else {
BlockTransactions::Hashes(
block
.transactions
.iter()
.map(|transaction| transaction.hash())
.collect(),
)
}
},
uncles: vec![],
nonce: U256::default(),
extra_data: b.header.extra_data,
extra_data: block.header.extra_data,
sha3_uncles: String::default(),
logs_bloom: String::default(),
size: format!("{header_size:#x}"),
Expand Down Expand Up @@ -232,6 +255,8 @@ impl<'a> Visitor<'a> for BlockNumberVisitor {

use std::str::FromStr;

use crate::codegen::types::EthTransactionInfo;

impl FromStr for BlockNumber {
type Err = serde_json::Error;

Expand Down Expand Up @@ -281,3 +306,24 @@ mod tests {
assert_eq!(match_block_number(bn_tag_pending).unwrap(), 1001);
}
}

/// Block Transactions
#[derive(Debug, Deserialize, Clone, PartialEq)]
pub enum BlockTransactions {
/// Only hashes
Hashes(Vec<H256>),
/// Full transactions
Full(Vec<EthTransactionInfo>),
}

impl Serialize for BlockTransactions {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
BlockTransactions::Hashes(ref hashes) => hashes.serialize(serializer),
BlockTransactions::Full(ref ts) => ts.serialize(serializer),
}
}
}
96 changes: 12 additions & 84 deletions lib/ain-grpc/src/impls.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,30 @@
use std::convert::From;
use std::mem::size_of_val;

use ain_evm::transaction::{SignedTx, TransactionError};
use ethereum::{BlockAny, TransactionV2};
use primitive_types::{H160, H256, U256};
use ethereum::BlockAny;

use crate::codegen::types::{EthBlockInfo, EthPendingTransactionInfo, EthTransactionInfo};

fn format_hash(hash: H256) -> String {
format!("{hash:#x}")
}

fn format_address(hash: H160) -> String {
format!("{hash:#x}")
}

fn format_number(number: U256) -> String {
format!("{number:#x}")
}
use crate::codegen::types::EthBlockInfo;
use crate::utils::{format_h256, format_u256};

impl From<BlockAny> for EthBlockInfo {
fn from(block: BlockAny) -> Self {
EthBlockInfo {
block_number: format!("{:#x}", block.header.number),
hash: format_hash(block.header.hash()),
parent_hash: format_hash(block.header.parent_hash),
hash: format_h256(block.header.hash()),
parent_hash: format_h256(block.header.parent_hash),
nonce: format!("{:#x}", block.header.nonce),
sha3_uncles: format_hash(block.header.ommers_hash),
sha3_uncles: format_h256(block.header.ommers_hash),
logs_bloom: format!("{:#x}", block.header.logs_bloom),
transactions_root: format_hash(block.header.transactions_root),
state_root: format_hash(block.header.state_root),
receipt_root: format_hash(block.header.receipts_root),
transactions_root: format_h256(block.header.transactions_root),
state_root: format_h256(block.header.state_root),
receipt_root: format_h256(block.header.receipts_root),
miner: format!("{:#x}", block.header.beneficiary),
difficulty: format!("{:#x}", block.header.difficulty),
total_difficulty: format_number(block.header.difficulty),
total_difficulty: format_u256(block.header.difficulty),
extra_data: format!("{:#x?}", block.header.extra_data.to_ascii_lowercase()),
size: format!("{:#x}", size_of_val(&block)),
gas_limit: format_number(block.header.gas_limit),
gas_used: format_number(block.header.gas_used),
gas_limit: format_u256(block.header.gas_limit),
gas_used: format_u256(block.header.gas_used),
timestamps: format!("0x{:x}", block.header.timestamp),
transactions: block
.transactions
Expand All @@ -52,62 +39,3 @@ impl From<BlockAny> for EthBlockInfo {
}
}
}

impl TryFrom<TransactionV2> for EthTransactionInfo {
type Error = TransactionError;

fn try_from(tx: TransactionV2) -> Result<Self, Self::Error> {
let signed_tx: SignedTx = tx.try_into()?;

Ok(EthTransactionInfo {
from: format_address(signed_tx.sender),
to: signed_tx.to().map(format_address),
gas: signed_tx.gas_limit().as_u64(),
price: signed_tx.gas_price().to_string(),
value: signed_tx.value().to_string(),
data: hex::encode(signed_tx.data()),
nonce: signed_tx.nonce().to_string(),
})
}
}

impl TryFrom<&str> for EthPendingTransactionInfo {
type Error = TransactionError;

fn try_from(raw_tx: &str) -> Result<Self, Self::Error> {
let signed_tx: SignedTx = raw_tx.try_into()?;

let to = if let Some(signed_to) = signed_tx.to() {
format_address(signed_to)
} else {
String::from("null")
};

let input = if signed_tx.data().is_empty() {
String::from("0x0")
} else {
format!("0x{}", hex::encode(signed_tx.data()))
};

let pending_transaction = EthPendingTransactionInfo {
hash: format_hash(signed_tx.transaction.hash()),
nonce: format_number(signed_tx.nonce()),
block_hash: String::from(
"0x0000000000000000000000000000000000000000000000000000000000000000",
),
block_number: String::from("null"),
transaction_index: String::from("0x0"),
from: format_address(signed_tx.sender),
to,
value: format_number(signed_tx.value()),
gas: format_number(signed_tx.gas_limit()),
gas_price: format_number(signed_tx.gas_price()),
input,
v: format!("0x{:x}", signed_tx.v()),
r: format_hash(signed_tx.r()),
s: format_hash(signed_tx.s()),
};

Ok(pending_transaction)
}
}
2 changes: 2 additions & 0 deletions lib/ain-grpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ pub mod codegen;
mod impls;
mod receipt;
pub mod rpc;
mod transaction;
mod utils;

use env_logger::{Builder as LogBuilder, Env, Target};
use jsonrpsee::core::server::rpc_module::Methods;
Expand Down
Loading