Skip to content
Merged
10 changes: 10 additions & 0 deletions prdoc/pr_9177.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
title: align eth-rpc response with geth
doc:
- audience: Runtime Dev
description: |-
- Update serde encoding for eth-rpc to match serialization behavior of Geth
crates:
- name: pallet-revive
bump: patch
- name: pallet-revive-eth-rpc
bump: patch
Binary file modified substrate/frame/revive/rpc/revive_chain.metadata
Binary file not shown.
3 changes: 1 addition & 2 deletions substrate/frame/revive/rpc/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -665,8 +665,7 @@ impl Client {
transactions_root: extrinsics_root,
number: header.number.into(),
timestamp: timestamp.into(),
difficulty: Some(0u32.into()),
base_fee_per_gas: runtime_api.gas_price().await.ok(),
base_fee_per_gas: runtime_api.gas_price().await.ok().unwrap_or_default(),
gas_limit,
gas_used,
receipts_root: extrinsics_root,
Expand Down
14 changes: 11 additions & 3 deletions substrate/frame/revive/rpc/src/client/storage_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@
// limitations under the License.

use crate::{
subxt_client::{self, runtime_types::pallet_revive::storage::ContractInfo, SrcChainConfig},
subxt_client::{
self,
runtime_types::pallet_revive::storage::{AccountType, ContractInfo},
SrcChainConfig,
},
ClientError, H160,
};
use subxt::{storage::Storage, OnlineClient};
Expand All @@ -39,12 +43,16 @@ impl StorageApi {
// TODO: remove once subxt is updated
let contract_address: subxt::utils::H160 = contract_address.0.into();

let query = subxt_client::storage().revive().contract_info_of(contract_address);
let query = subxt_client::storage().revive().account_info_of(contract_address);
let Some(info) = self.0.fetch(&query).await? else {
return Err(ClientError::ContractNotFound);
};

Ok(info)
let AccountType::Contract(contract_info) = info.account_type else {
return Err(ClientError::ContractNotFound);
};

Ok(contract_info)
}

/// Get the contract trie id for the given contract address.
Expand Down
4 changes: 2 additions & 2 deletions substrate/frame/revive/rpc/src/example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl<Client: EthRpcClient + Sync + Send> SubmittedTransaction<Client> {
);
return Ok(receipt)
} else {
anyhow::bail!("Transaction failed")
anyhow::bail!("Transaction failed receipt: {receipt:?}")
}
}
}
Expand Down Expand Up @@ -180,7 +180,7 @@ impl<Client: EthRpcClient + Send + Sync> TransactionBuilder<Client> {
let hash = client
.send_raw_transaction(bytes.into())
.await
.with_context(|| "transaction failed")?;
.with_context(|| "send_raw_transaction failed")?;

Ok(SubmittedTransaction {
tx: GenericTransaction::from_signed(signed_tx, gas_price, Some(from)),
Expand Down
4 changes: 2 additions & 2 deletions substrate/frame/revive/rpc/src/fee_history_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl FeeHistoryProvider {
let block_number: SubstrateBlockNumber =
block.number.try_into().expect("Block number is always valid");

let base_fee = block.base_fee_per_gas.unwrap_or_default().as_u128();
let base_fee = block.base_fee_per_gas.as_u128();
let gas_used = block.gas_used.as_u128();
let gas_used_ratio = (gas_used as f64) / (block.gas_limit.as_u128() as f64);
let mut result = FeeHistoryCacheItem { base_fee, gas_used_ratio, rewards: vec![] };
Expand Down Expand Up @@ -160,7 +160,7 @@ impl FeeHistoryProvider {
async fn test_update_fee_history() {
let block = Block {
number: U256::from(200u64),
base_fee_per_gas: Some(U256::from(1000u64)),
base_fee_per_gas: U256::from(1000u64),
gas_used: U256::from(600u64),
gas_limit: U256::from(1200u64),
..Default::default()
Expand Down
2 changes: 1 addition & 1 deletion substrate/frame/revive/rpc/src/receipt_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ impl<B: BlockInfoProvider> ReceiptProvider<B> {
topics,
transaction_hash: H256::from_slice(&transaction_hash),
transaction_index: U256::from(transaction_index as u64),
removed: None,
removed: false,
})
})
.fetch_all(&self.pool)
Expand Down
6 changes: 3 additions & 3 deletions substrate/frame/revive/src/evm/api/debug_rpc_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,13 +258,13 @@ where
#[derive(
TypeInfo, Default, Encode, Decode, Serialize, Deserialize, Clone, Debug, Eq, PartialEq,
)]
#[serde(rename_all = "camelCase")]
pub struct CallTrace<Gas = U256> {
/// Address of the sender.
pub from: H160,
/// Amount of gas provided for the call.
pub gas: Gas,
/// Amount of gas used.
#[serde(rename = "gasUsed")]
pub gas_used: Gas,
/// Address of the receiver.
pub to: H160,
Expand All @@ -277,7 +277,7 @@ pub struct CallTrace<Gas = U256> {
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
/// The revert reason, if the call reverted.
#[serde(rename = "revertReason", skip_serializing_if = "Option::is_none")]
#[serde(skip_serializing_if = "Option::is_none")]
pub revert_reason: Option<String>,
/// List of sub-calls.
#[serde(skip_serializing_if = "Vec::is_empty")]
Expand Down Expand Up @@ -313,9 +313,9 @@ pub struct CallLog {

/// A transaction trace
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TransactionTrace {
/// The transaction hash.
#[serde(rename = "txHash")]
pub tx_hash: H256,
/// The trace of the transaction.
#[serde(rename = "result")]
Expand Down
73 changes: 72 additions & 1 deletion substrate/frame/revive/src/evm/api/rlp_codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ impl TransactionUnsigned {
use TransactionUnsigned::*;
let mut s = rlp::RlpStream::new();
match self {
Transaction7702Unsigned(ref tx) => {
s.append(&tx.r#type.value());
s.append(tx);
},
Transaction2930Unsigned(ref tx) => {
s.append(&tx.r#type.value());
s.append(tx);
Expand Down Expand Up @@ -54,6 +58,7 @@ impl TransactionSigned {
use TransactionSigned::*;
use TransactionUnsigned::*;
match self {
Transaction7702Signed(tx) => Transaction7702Unsigned(tx.transaction_7702_unsigned),
Transaction2930Signed(tx) => Transaction2930Unsigned(tx.transaction_2930_unsigned),
Transaction1559Signed(tx) => Transaction1559Unsigned(tx.transaction_1559_unsigned),
Transaction4844Signed(tx) => Transaction4844Unsigned(tx.transaction_4844_unsigned),
Expand All @@ -67,6 +72,10 @@ impl TransactionSigned {
use TransactionSigned::*;
let mut s = rlp::RlpStream::new();
match self {
Transaction7702Signed(ref tx) => {
s.append(&tx.transaction_7702_unsigned.r#type.value());
s.append(tx);
},
Transaction2930Signed(ref tx) => {
s.append(&tx.transaction_2930_unsigned.r#type.value());
s.append(tx);
Expand Down Expand Up @@ -198,6 +207,31 @@ impl Decodable for AccessListEntry {
}
}

impl Encodable for AuthorizationListEntry {
fn rlp_append(&self, s: &mut rlp::RlpStream) {
s.begin_list(6);
s.append(&self.chain_id);
s.append(&self.address);
s.append(&self.nonce);
s.append(&self.y_parity);
s.append(&self.r);
s.append(&self.s);
}
}

impl Decodable for AuthorizationListEntry {
fn decode(rlp: &rlp::Rlp) -> Result<Self, rlp::DecoderError> {
Ok(AuthorizationListEntry {
chain_id: rlp.val_at(0)?,
address: rlp.val_at(1)?,
nonce: rlp.val_at(2)?,
y_parity: rlp.val_at(3)?,
r: rlp.val_at(4)?,
s: rlp.val_at(5)?,
})
}
}

/// See <https://eips.ethereum.org/EIPS/eip-1559>
impl Encodable for Transaction1559Unsigned {
fn rlp_append(&self, s: &mut rlp::RlpStream) {
Expand Down Expand Up @@ -344,7 +378,23 @@ impl Decodable for Transaction2930Signed {
}
}

//See https://eips.ethereum.org/EIPS/eip-4844
//See https://eips.ethereum.org/EIPS/eip-7702
impl Encodable for Transaction7702Unsigned {
fn rlp_append(&self, s: &mut rlp::RlpStream) {
s.begin_list(10);
s.append(&self.chain_id);
s.append(&self.nonce);
s.append(&self.max_priority_fee_per_gas);
s.append(&self.max_fee_per_gas);
s.append(&self.gas);
s.append(&self.to);
s.append(&self.value);
s.append(&self.input.0);
s.append_list(&self.access_list);
s.append_list(&self.authorization_list);
}
}

impl Encodable for Transaction4844Unsigned {
fn rlp_append(&self, s: &mut rlp::RlpStream) {
s.begin_list(11);
Expand All @@ -362,6 +412,27 @@ impl Encodable for Transaction4844Unsigned {
}
}

//See https://eips.ethereum.org/EIPS/eip-7702
impl Encodable for Transaction7702Signed {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I confirm that this is working with real-ethereum block data, from PR: #9538

fn rlp_append(&self, s: &mut rlp::RlpStream) {
let tx = &self.transaction_7702_unsigned;
s.begin_list(13);
s.append(&tx.chain_id);
s.append(&tx.nonce);
s.append(&tx.max_priority_fee_per_gas);
s.append(&tx.max_fee_per_gas);
s.append(&tx.gas);
s.append(&tx.to);
s.append(&tx.value);
s.append(&tx.input.0);
s.append_list(&tx.access_list);
s.append_list(&tx.authorization_list);
s.append(&self.y_parity);
s.append(&self.r);
s.append(&self.s);
}
}

//See https://eips.ethereum.org/EIPS/eip-4844
impl Encodable for Transaction4844Signed {
fn rlp_append(&self, s: &mut rlp::RlpStream) {
Expand Down
67 changes: 67 additions & 0 deletions substrate/frame/revive/src/evm/api/rpc_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ impl From<TransactionSigned> for TransactionUnsigned {
fn from(tx: TransactionSigned) -> Self {
use TransactionSigned::*;
match tx {
Transaction7702Signed(tx) => tx.transaction_7702_unsigned.into(),
Transaction4844Signed(tx) => tx.transaction_4844_unsigned.into(),
Transaction1559Signed(tx) => tx.transaction_1559_unsigned.into(),
Transaction2930Signed(tx) => tx.transaction_2930_unsigned.into(),
Expand Down Expand Up @@ -281,6 +282,26 @@ impl GenericTransaction {
access_list: Some(tx.access_list),
..Default::default()
},
Transaction7702Unsigned(tx) => GenericTransaction {
from,
r#type: Some(tx.r#type.as_byte()),
chain_id: Some(tx.chain_id),
input: tx.input.into(),
nonce: Some(tx.nonce),
value: Some(tx.value),
to: tx.to,
gas: Some(tx.gas),
gas_price: Some(
base_gas_price
.saturating_add(tx.max_priority_fee_per_gas)
.min(tx.max_fee_per_gas),
),
access_list: Some(tx.access_list),
authorization_list: tx.authorization_list,
max_fee_per_gas: Some(tx.max_fee_per_gas),
max_priority_fee_per_gas: Some(tx.max_priority_fee_per_gas),
..Default::default()
},
}
}

Expand Down Expand Up @@ -339,6 +360,21 @@ impl GenericTransaction {
blob_versioned_hashes: self.blob_versioned_hashes,
}
.into()),
TYPE_EIP7702 => Ok(Transaction7702Unsigned {
r#type: TypeEip7702 {},
chain_id: self.chain_id.unwrap_or_default(),
input: self.input.to_bytes(),
nonce: self.nonce.unwrap_or_default(),
value: self.value.unwrap_or_default(),
to: self.to,
gas: self.gas.unwrap_or_default(),
gas_price: self.max_fee_per_gas.unwrap_or_default(),
max_fee_per_gas: self.max_fee_per_gas.unwrap_or_default(),
max_priority_fee_per_gas: self.max_priority_fee_per_gas.unwrap_or_default(),
access_list: self.access_list.unwrap_or_default(),
authorization_list: self.authorization_list,
}
.into()),
_ => Err(()),
}
}
Expand Down Expand Up @@ -387,3 +423,34 @@ fn from_unsigned_works_for_1559() {
let tx2 = generic.try_into_unsigned().unwrap();
assert_eq!(tx, tx2);
}

#[test]
fn from_unsigned_works_for_7702() {
let base_gas_price = U256::from(10);
let tx = TransactionUnsigned::from(Transaction7702Unsigned {
chain_id: U256::from(1),
input: Bytes::from(vec![1u8]),
nonce: U256::from(1),
value: U256::from(1),
to: Some(H160::zero()),
gas: U256::from(1),
gas_price: U256::from(20),
max_fee_per_gas: U256::from(20),
max_priority_fee_per_gas: U256::from(1),
authorization_list: vec![AuthorizationListEntry {
chain_id: U256::from(1),
address: H160::from_low_u64_be(42),
nonce: U256::from(0),
y_parity: U256::from(1),
r: U256::from(1),
s: U256::from(2),
}],
..Default::default()
});

let generic = GenericTransaction::from_unsigned(tx.clone(), base_gas_price, None);
assert_eq!(generic.gas_price, Some(U256::from(11)));

let tx2 = generic.try_into_unsigned().unwrap();
assert_eq!(tx, tx2);
}
Loading
Loading