use crate::call_tree::NodeState;
pub use ethereum::TransactionV2 as Transaction;
use ethereum_types::{H160, H256, U256};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PoM {
pub root_id: H256,
pub challenge_id: H256,
#[serde(with = "transaction_wrapper")]
pub tx: Transaction,
pub timeout: u64,
pub caller: H160,
pub callee: Option<H160>,
pub call_depth: u64,
pub state: NodeState,
}
impl PoM {
pub fn to_json(&self) -> String {
serde_json::to_string(self).unwrap()
}
pub fn from_json(json_string: &str) -> PoM {
serde_json::from_str(json_string).unwrap()
}
}
// mod transaction_wrapper {
// use ethereum::{EnvelopedDecodable, EnvelopedEncodable, TransactionV2};
// use serde::de::Error;
// use serde::{Deserializer, Serializer};
// pub fn serialize<S>(tx: &TransactionV2, serializer: S) -> Result<S::Ok, S::Error>
// where
// S: Serializer,
// {
// let bytes = tx.encode();
// serializer.serialize_bytes(&bytes)
// }
// pub fn deserialize<'de, D>(deserializer: D) -> Result<TransactionV2, D::Error>
// where
// D: Deserializer<'de>,
// {
// let bytes: Vec<u8> = serde::Deserialize::deserialize(deserializer)?;
// //let rlp = Rlp::new(&bytes);
// TransactionV2::decode(&bytes).map_err(|err| D::Error::custom(format!("{:?}", err)))
// }
// }
// 为第三方类型创建可序列化的包装结构体
#[derive(Serialize)]
struct SerializableLegacyTransaction {
nonce: String,
gas_price: String,
gas_limit: String,
action: String,
value: String,
input: String,
signature: String,
}
#[derive(Serialize)]
struct SerializableEIP2930Transaction {
chain_id: u64,
nonce: String,
gas_price: String,
gas_limit: String,
action: String,
value: String,
input: String,
access_list: String,
odd_y_parity: bool,
r: String,
s: String,
}
#[derive(Serialize)]
struct SerializableEIP1559Transaction {
chain_id: u64,
nonce: String,
max_priority_fee_per_gas: String,
max_fee_per_gas: String,
gas_limit: String,
action: String,
value: String,
input: String,
access_list: String,
odd_y_parity: bool,
r: String,
s: String,
}
#[derive(Serialize)]
#[serde(tag = "type", content = "data")]
enum SerializableTransactionV2 {
Legacy(SerializableLegacyTransaction),
EIP2930(SerializableEIP2930Transaction),
EIP1559(SerializableEIP1559Transaction),
}
mod transaction_wrapper {
use super::*;
use ethereum::{EnvelopedDecodable, TransactionV2};
use serde::de::Error;
use serde::{Deserializer, Serializer};
// 将U256转换为十六进制字符串
fn u256_to_hex(u: &U256) -> String {
format!("0x{}", hex::encode(u.as_u64().to_be_bytes()))
}
// 将字节数组转换为十六进制字符串
fn bytes_to_hex(bytes: &[u8]) -> String {
format!("0x{}", hex::encode(bytes))
}
pub fn serialize<S>(tx: &TransactionV2, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let serializable_tx = match tx {
TransactionV2::Legacy(legacy) => {
SerializableTransactionV2::Legacy(SerializableLegacyTransaction {
nonce: u256_to_hex(&legacy.nonce),
gas_price: u256_to_hex(&legacy.gas_price),
gas_limit: u256_to_hex(&legacy.gas_limit),
action: format!("{:?}", legacy.action),
value: u256_to_hex(&legacy.value),
input: bytes_to_hex(&legacy.input),
signature: format!("{:?}", legacy.signature),
})
}
TransactionV2::EIP2930(eip2930) => {
SerializableTransactionV2::EIP2930(SerializableEIP2930Transaction {
chain_id: eip2930.chain_id,
nonce: u256_to_hex(&eip2930.nonce),
gas_price: u256_to_hex(&eip2930.gas_price),
gas_limit: u256_to_hex(&eip2930.gas_limit),
action: format!("{:?}", eip2930.action),
value: u256_to_hex(&eip2930.value),
input: bytes_to_hex(&eip2930.input),
access_list: format!("{:?}", eip2930.access_list),
odd_y_parity: eip2930.odd_y_parity,
r: format!("{:?}", eip2930.r),
s: format!("{:?}", eip2930.s),
})
}
TransactionV2::EIP1559(eip1559) => {
SerializableTransactionV2::EIP1559(SerializableEIP1559Transaction {
chain_id: eip1559.chain_id,
nonce: u256_to_hex(&eip1559.nonce),
max_priority_fee_per_gas: u256_to_hex(&eip1559.max_priority_fee_per_gas),
max_fee_per_gas: u256_to_hex(&eip1559.max_fee_per_gas),
gas_limit: u256_to_hex(&eip1559.gas_limit),
action: format!("{:?}", eip1559.action),
value: u256_to_hex(&eip1559.value),
input: bytes_to_hex(&eip1559.input),
access_list: format!("{:?}", eip1559.access_list),
odd_y_parity: eip1559.odd_y_parity,
r: format!("{:?}", eip1559.r),
s: format!("{:?}", eip1559.s),
})
}
};
serializable_tx.serialize(serializer)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<TransactionV2, D::Error>
where
D: Deserializer<'de>,
{
// 原始反序列化逻辑保持不变
let bytes: Vec<u8> = serde::Deserialize::deserialize(deserializer)?;
TransactionV2::decode(&bytes).map_err(|err| D::Error::custom(format!("{:?}", err)))
}
}
// 添加测试模块
#[cfg(test)]
mod tests {
use super::*;
use ethereum::{EnvelopedDecodable, EnvelopedEncodable};
use ethereum::{LegacyTransaction, TransactionAction, TransactionSignature, TransactionV2};
use ethereum_types::{H160, H256, U256};
// 生成测试用的 TransactionV2
fn create_test_transaction() -> TransactionV2 {
TransactionV2::Legacy(LegacyTransaction {
nonce: U256::from(1),
gas_price: U256::from(20_000_000_000_u64),
gas_limit: U256::from(21_000),
action: TransactionAction::Call(H160::random()),
value: U256::from(1_000_000_000_u64),
input: vec![1, 2, 3, 4].into(),
signature: ethereum::TransactionSignature::new(
27,
H256::from_slice(&[1u8; 32]),
H256::from_slice(&[2u8; 32]),
)
.ok_or("Failed to create signature")
.unwrap(),
})
}
#[test]
fn test_pom_serialization_deserialization() {
// 1. 创建测试 PoM 实例
let original_pom = PoM {
root_id: H256::random(),
challenge_id: H256::random(),
tx: create_test_transaction(),
timeout: 123456,
caller: H160::random(),
callee: Some(H160::random()),
call_depth: 5,
state: NodeState::Challenging, // 假设 NodeState::Active 可用
};
// 2. 序列化到 JSON
let json_string = original_pom.to_json();
println!("Serialized PoM: {}", json_string);
// 3. 反序列化回来
let deserialized_pom = PoM::from_json(&json_string);
// 4. 比较原始和反序列化后的对象
// 注意:PoM 未实现 PartialEq,我们需要手动比较字段
// 比较根 ID 和挑战 ID
assert_eq!(original_pom.root_id, deserialized_pom.root_id);
assert_eq!(original_pom.challenge_id, deserialized_pom.challenge_id);
// 比较交易:编码后检查字节相等性
let original_tx_bytes = original_pom.tx.encode();
let deserialized_tx_bytes = deserialized_pom.tx.encode();
assert_eq!(original_tx_bytes, deserialized_tx_bytes);
// 比较其他字段
assert_eq!(original_pom.timeout, deserialized_pom.timeout);
assert_eq!(original_pom.caller, deserialized_pom.caller);
assert_eq!(original_pom.callee, deserialized_pom.callee);
assert_eq!(original_pom.call_depth, deserialized_pom.call_depth);
assert_eq!(original_pom.state, deserialized_pom.state);
}
#[test]
fn test_pom_without_callee() {
// 测试没有 callee 的情况
let pom = PoM {
callee: None,
..create_test_pom() // 使用工厂函数简化创建
};
let json_string = pom.to_json();
let deserialized = PoM::from_json(&json_string);
assert!(deserialized.callee.is_none());
// 其他字段省略,实际测试中应包含完整检查
}
// 创建测试 PoM 的辅助函数
fn create_test_pom() -> PoM {
PoM {
root_id: H256::random(),
challenge_id: H256::random(),
tx: create_test_transaction(),
timeout: 1000,
caller: H160::random(),
callee: Some(H160::random()),
call_depth: 2,
state: NodeState::Responsed, // 另一个状态
}
}
}
反序列化失败
最新发布