Transaction Action Types

TRANSCTIONACTION IDDESCRIPTION
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
在 UVM 中使用枚举变量是一种常见的做法,特别是在定义行为控制或状态管理时。枚举类型可以通过 `typedef enum` 来定义,并且可以与 UVM 的类和方法结合使用,以提高代码的可读性和维护性。 ### 定义枚举类型 在 UVM 中定义枚举类型时,通常使用 `typedef enum` 来创建一个类型别名,以便后续变量声明更加简洁。例如,可以定义一个名为 `action_e` 的枚举类型来表示不同的操作行为: ```systemverilog typedef enum { ACTION_NONE, ACTION_START, ACTION_STOP, ACTION_PAUSE, ACTION_RESUME } action_e; ``` 该枚举类型可以用于类的成员变量定义,或者作为函数参数传递,以控制对象的行为。 ### 在类中使用枚举变量 枚举变量可以在 UVM 类中作为成员变量使用,用于表示对象的当前状态或执行的操作。例如: ```systemverilog class my_component extends uvm_component; action_e current_action; function void build_phase(uvm_phase phase); current_action = ACTION_START; endfunction function void run_phase(uvm_phase phase); case(current_action) ACTION_START: `uvm_info("RUN", "Starting...", UVM_LOW) ACTION_STOP: `uvm_info("RUN", "Stopping...", UVM_LOW) default: `uvm_info("RUN", "Unknown action", UVM_LOW) endcase endfunction endclass ``` 在 `run_phase` 中通过 `case` 语句对 `current_action` 枚举变量进行判断,执行相应的操作。这种方式可以清晰地表达不同状态之间的逻辑关系。 ### 枚举与 UVM 资源管理 在 UVM 的资源管理中,枚举类型也常用于控制资源的行为。例如,在 `uvm_resource_types` 类中定义了多个枚举类型,用于设置资源的访问权限和优先级。其中 `override_e` 枚举用于表示资源的覆盖类型: ```systemverilog typedef enum override_t { TYPE_OVERRIDE = 2'b01, NAME_OVERRIDE = 2'b10 } override_e; ``` 这种定义方式可以增强代码的语义表达,使开发者能够更直观地理解资源的配置方式。 ### 使用枚举控制消息行为 在 UVM 中,消息的行为可以通过枚举常量进行控制。例如,`uvm_action_type` 枚举定义了一系列动作,用于控制消息的输出方式: ```systemverilog typedef enum { UVM_NO_ACTION = 'b000000, UVM_DISPLAY = 'b000001, UVM_LOG = 'b000010, UVM_COUNT = 'b000100, UVM_EXIT = 'b001000, UVM_CALL_HOOK = 'b010000, UVM_STOP = 'b100000 } uvm_action_type; ``` 这些枚举常量可以用于控制消息是否显示、是否记录到日志文件、是否触发退出等行为。通过将这些常量赋值给特定的变量,可以在运行时动态调整消息处理方式。 ### 示例:结合 UVM 使用枚举变量 以下是一个完整的示例,展示如何在 UVM 测试平台中使用枚举变量来控制事务的行为: ```systemverilog typedef enum { ACTION_NONE, ACTION_READ, ACTION_WRITE } transaction_action_e; class my_transaction extends uvm_sequence_item; transaction_action_e action; `uvm_object_utils_begin(my_transaction) `uvm_field_enum(transaction_action_e, action, UVM_ALL_ON) `uvm_object_utils_end function new(string name = "my_transaction"); super.new(name); endfunction function void do_print(uvm_printer printer); printer.print_enum("action", action.name()); endfunction endclass ``` 在这个示例中,`transaction_action_e` 枚举用于表示事务的操作类型,并通过 `do_print` 方法输出其名称,增强了调试信息的可读性。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值