Transaction Action Types

TRANSCTIONACTION ID DESCRIPTION
1Issue from stores
2Subinventory transfer
3Direct organization transfer
4Cycle count adjustment
8Physical inventory adjustment
12Intransit receipt
21Intransit shipment
24Cost update
27Receipt into stores
28Staging transfer
29Delivery adjustments
30WIP scrap transaction
31Assembly completion
32Assembly return
33Negative component issue
34Negative component return
35Container transaction
40Lot Split
41Lot Merge
42Lot Translate
43Lot Update Quantity
50Container Pack
51Container Unpack
52Container Split
55Cost Group Transfer


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, // 另一个状态 } } } 反序列化失败
最新发布
06-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值