mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
chore(rpc): use TypedData type in eth_signTypedData signature (#8845)
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -7883,6 +7883,7 @@ dependencies = [
|
||||
name = "reth-rpc-api"
|
||||
version = "1.0.0-rc.1"
|
||||
dependencies = [
|
||||
"alloy-dyn-abi",
|
||||
"jsonrpsee",
|
||||
"reth-engine-primitives",
|
||||
"reth-network-peers",
|
||||
|
||||
@ -19,9 +19,12 @@ reth-engine-primitives.workspace = true
|
||||
reth-network-peers.workspace = true
|
||||
|
||||
# misc
|
||||
alloy-dyn-abi = { workspace = true, features = ["eip712"] }
|
||||
jsonrpsee = { workspace = true, features = ["server", "macros"] }
|
||||
serde_json.workspace = true
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json.workspace = true
|
||||
|
||||
[features]
|
||||
client = ["jsonrpsee/client", "jsonrpsee/async-client"]
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use alloy_dyn_abi::TypedData;
|
||||
use jsonrpsee::{core::RpcResult, proc_macros::rpc};
|
||||
use reth_primitives::{Address, BlockId, BlockNumberOrTag, Bytes, B256, B64, U256, U64};
|
||||
use reth_rpc_types::{
|
||||
@ -296,7 +297,7 @@ pub trait EthApi {
|
||||
|
||||
/// Signs data via [EIP-712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md).
|
||||
#[method(name = "signTypedData")]
|
||||
async fn sign_typed_data(&self, address: Address, data: serde_json::Value) -> RpcResult<Bytes>;
|
||||
async fn sign_typed_data(&self, address: Address, data: TypedData) -> RpcResult<Bytes>;
|
||||
|
||||
/// Returns the account and storage values of the specified account including the Merkle-proof.
|
||||
/// This call can be used to verify that the data you are pulling from is not tampered with.
|
||||
|
||||
@ -159,6 +159,17 @@ where
|
||||
let transaction_request = TransactionRequest::default();
|
||||
let bytes = Bytes::default();
|
||||
let tx = Bytes::from(hex!("02f871018303579880850555633d1b82520894eee27662c2b8eba3cd936a23f039f3189633e4c887ad591c62bdaeb180c080a07ea72c68abfb8fca1bd964f0f99132ed9280261bdca3e549546c0205e800f7d0a05b4ef3039e9c9b9babc179a1878fb825b5aaf5aed2fa8744854150157b08d6f3"));
|
||||
let typed_data = serde_json::from_str(
|
||||
r#"{
|
||||
"types": {
|
||||
"EIP712Domain": []
|
||||
},
|
||||
"primaryType": "EIP712Domain",
|
||||
"domain": {},
|
||||
"message": {}
|
||||
}"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Implemented
|
||||
EthApiClient::protocol_version(client).await.unwrap();
|
||||
@ -180,9 +191,7 @@ where
|
||||
EthApiClient::uncle_by_block_hash_and_index(client, hash, index).await.unwrap();
|
||||
EthApiClient::uncle_by_block_number_and_index(client, block_number, index).await.unwrap();
|
||||
EthApiClient::sign(client, address, bytes.clone()).await.unwrap_err();
|
||||
EthApiClient::sign_typed_data(client, address, jsonrpsee::core::JsonValue::Null)
|
||||
.await
|
||||
.unwrap_err();
|
||||
EthApiClient::sign_typed_data(client, address, typed_data).await.unwrap_err();
|
||||
EthApiClient::transaction_by_hash(client, tx_hash).await.unwrap();
|
||||
EthApiClient::transaction_by_block_hash_and_index(client, hash, index).await.unwrap();
|
||||
EthApiClient::transaction_by_block_number_and_index(client, block_number, index).await.unwrap();
|
||||
|
||||
@ -24,10 +24,8 @@ futures.workspace = true
|
||||
jsonrpsee = { workspace = true, features = ["client", "async-client"] }
|
||||
serde_json.workspace = true
|
||||
|
||||
|
||||
# assertions
|
||||
similar-asserts.workspace = true
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { workspace = true, features = ["rt-multi-thread", "macros", "rt"] }
|
||||
|
||||
@ -1,6 +1,16 @@
|
||||
//! Implementation of the [`jsonrpsee`] generated [`reth_rpc_api::EthApiServer`] trait
|
||||
//! Handles RPC requests for the `eth_` namespace.
|
||||
|
||||
use super::EthApiSpec;
|
||||
use crate::{
|
||||
eth::{
|
||||
api::{EthApi, EthTransactions},
|
||||
error::EthApiError,
|
||||
revm_utils::EvmOverrides,
|
||||
},
|
||||
result::{internal_rpc_err, ToRpcResult},
|
||||
};
|
||||
use alloy_dyn_abi::TypedData;
|
||||
use jsonrpsee::core::RpcResult as Result;
|
||||
use reth_evm::ConfigureEvm;
|
||||
use reth_network_api::NetworkInfo;
|
||||
@ -16,20 +26,8 @@ use reth_rpc_types::{
|
||||
FeeHistory, Header, Index, RichBlock, StateContext, SyncStatus, TransactionRequest, Work,
|
||||
};
|
||||
use reth_transaction_pool::TransactionPool;
|
||||
use serde_json::Value;
|
||||
use tracing::trace;
|
||||
|
||||
use crate::{
|
||||
eth::{
|
||||
api::{EthApi, EthTransactions},
|
||||
error::EthApiError,
|
||||
revm_utils::EvmOverrides,
|
||||
},
|
||||
result::{internal_rpc_err, ToRpcResult},
|
||||
};
|
||||
|
||||
use super::EthApiSpec;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<Provider, Pool, Network, EvmConfig> EthApiServer for EthApi<Provider, Pool, Network, EvmConfig>
|
||||
where
|
||||
@ -391,7 +389,7 @@ where
|
||||
/// Handler for: `eth_sign`
|
||||
async fn sign(&self, address: Address, message: Bytes) -> Result<Bytes> {
|
||||
trace!(target: "rpc::eth", ?address, ?message, "Serving eth_sign");
|
||||
Ok(Self::sign(self, address, message).await?)
|
||||
Ok(Self::sign(self, address, &message).await?)
|
||||
}
|
||||
|
||||
/// Handler for: `eth_signTransaction`
|
||||
@ -400,9 +398,9 @@ where
|
||||
}
|
||||
|
||||
/// Handler for: `eth_signTypedData`
|
||||
async fn sign_typed_data(&self, address: Address, data: Value) -> Result<Bytes> {
|
||||
async fn sign_typed_data(&self, address: Address, data: TypedData) -> Result<Bytes> {
|
||||
trace!(target: "rpc::eth", ?address, ?data, "Serving eth_signTypedData");
|
||||
Ok(Self::sign_typed_data(self, data, address)?)
|
||||
Ok(Self::sign_typed_data(self, &data, address)?)
|
||||
}
|
||||
|
||||
/// Handler for: `eth_getProof`
|
||||
|
||||
@ -9,22 +9,14 @@ use crate::{
|
||||
};
|
||||
use alloy_dyn_abi::TypedData;
|
||||
use reth_primitives::{Address, Bytes};
|
||||
use serde_json::Value;
|
||||
|
||||
impl<Provider, Pool, Network, EvmConfig> EthApi<Provider, Pool, Network, EvmConfig> {
|
||||
pub(crate) async fn sign(&self, account: Address, message: Bytes) -> EthResult<Bytes> {
|
||||
Ok(self.find_signer(&account)?.sign(account, &message).await?.to_hex_bytes())
|
||||
pub(crate) async fn sign(&self, account: Address, message: &[u8]) -> EthResult<Bytes> {
|
||||
Ok(self.find_signer(&account)?.sign(account, message).await?.to_hex_bytes())
|
||||
}
|
||||
|
||||
pub(crate) fn sign_typed_data(&self, data: Value, account: Address) -> EthResult<Bytes> {
|
||||
Ok(self
|
||||
.find_signer(&account)?
|
||||
.sign_typed_data(
|
||||
account,
|
||||
&serde_json::from_value::<TypedData>(data)
|
||||
.map_err(|_| SignError::InvalidTypedData)?,
|
||||
)?
|
||||
.to_hex_bytes())
|
||||
pub(crate) fn sign_typed_data(&self, data: &TypedData, account: Address) -> EthResult<Bytes> {
|
||||
Ok(self.find_signer(&account)?.sign_typed_data(account, data)?.to_hex_bytes())
|
||||
}
|
||||
|
||||
pub(crate) fn find_signer(
|
||||
|
||||
@ -115,7 +115,6 @@ impl EthSigner for DevSigner {
|
||||
|
||||
fn sign_typed_data(&self, address: Address, payload: &TypedData) -> Result<Signature> {
|
||||
let encoded = payload.eip712_signing_hash().map_err(|_| SignError::InvalidTypedData)?;
|
||||
// let b256 = encoded;
|
||||
self.sign_hash(encoded, address)
|
||||
}
|
||||
}
|
||||
@ -136,8 +135,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_sign_type_data() {
|
||||
let eip_712_example = serde_json::json!(
|
||||
r#"{
|
||||
let eip_712_example = r#"{
|
||||
"types": {
|
||||
"EIP712Domain": [
|
||||
{
|
||||
@ -200,9 +198,8 @@ mod tests {
|
||||
},
|
||||
"contents": "Hello, Bob!"
|
||||
}
|
||||
}"#
|
||||
);
|
||||
let data: TypedData = serde_json::from_value(eip_712_example).unwrap();
|
||||
}"#;
|
||||
let data: TypedData = serde_json::from_str(eip_712_example).unwrap();
|
||||
let signer = build_signer();
|
||||
let sig = signer.sign_typed_data(Address::default(), &data).unwrap();
|
||||
let expected = Signature {
|
||||
|
||||
Reference in New Issue
Block a user