cfx_executor/executive/
executed.rs1use crate::{executive_observer::ExecutiveObserver, substate::Substate};
6use cfx_bytes::Bytes;
7use cfx_types::{AddressWithSpace, U256};
8use cfx_vm_types::Spec;
9use primitives::{
10 receipt::{SortedStorageChanges, StorageChange},
11 LogEntry, TransactionWithSignature,
12};
13use typemap::ShareDebugMap;
14
15use super::{
16 fresh_executive::CostInfo,
17 pre_checked_executive::{ExecutiveReturn, RefundInfo},
18};
19
20#[derive(Debug)]
21pub struct Executed {
22 pub base_gas: u64,
25
26 pub gas_used: U256,
28
29 pub fee: U256,
31
32 pub burnt_fee: Option<U256>,
34
35 pub gas_charged: U256,
37
38 pub gas_sponsor_paid: bool,
40
41 pub logs: Vec<LogEntry>,
43
44 pub storage_sponsor_paid: bool,
46
47 pub storage_collateralized: Vec<StorageChange>,
49
50 pub storage_released: Vec<StorageChange>,
52
53 pub contracts_created: Vec<AddressWithSpace>,
65
66 pub output: Bytes,
68
69 pub ext_result: ExecutedExt,
71}
72
73pub type ExecutedExt = ShareDebugMap;
74
75impl Executed {
76 pub(super) fn not_enough_balance_fee_charged(
77 tx: &TransactionWithSignature, actual_gas_cost: &U256, cost: CostInfo,
78 ext_result: ExecutedExt, spec: &Spec,
79 ) -> Self {
80 let gas_charged = if cost.gas_price == U256::zero() {
81 U256::zero()
82 } else {
83 actual_gas_cost / cost.gas_price
84 };
85 let mut gas_sponsor_paid = cost.gas_sponsored;
86 let mut storage_sponsor_paid = cost.storage_sponsored;
87 if !spec.cip78b {
88 gas_sponsor_paid = false;
89 storage_sponsor_paid = false;
90 }
91 if spec.cip145_fix {
92 gas_sponsor_paid = false;
93 }
94
95 let burnt_fee = spec.cip1559.then(|| {
96 let target_burnt = tx.gas().saturating_mul(cost.burnt_gas_price);
97 U256::min(*actual_gas_cost, target_burnt)
98 });
99
100 Self {
101 gas_used: *tx.gas(),
102 gas_charged,
103 fee: *actual_gas_cost,
104 burnt_fee,
105 gas_sponsor_paid,
106 logs: vec![],
107 contracts_created: vec![],
108 storage_sponsor_paid,
109 storage_collateralized: Vec::new(),
110 storage_released: Vec::new(),
111 output: Default::default(),
112 base_gas: cost.base_gas,
113 ext_result,
114 }
115 }
116
117 pub(super) fn execution_error_fully_charged(
118 tx: &TransactionWithSignature, cost: CostInfo, ext_result: ExecutedExt,
119 spec: &Spec,
120 ) -> Self {
121 let mut storage_sponsor_paid = cost.storage_sponsored;
122 let mut gas_sponsor_paid = cost.gas_sponsored;
123
124 if !spec.cip78b {
125 gas_sponsor_paid = false;
126 storage_sponsor_paid = false;
127 }
128 if spec.cip145 && !spec.cip145_fix {
129 gas_sponsor_paid = false;
130 }
131
132 let fee = tx.gas().saturating_mul(cost.gas_price);
133
134 let burnt_fee = spec
135 .cip1559
136 .then(|| tx.gas().saturating_mul(cost.burnt_gas_price));
137
138 Self {
139 gas_used: *tx.gas(),
140 gas_charged: *tx.gas(),
141 fee,
142 burnt_fee,
143 gas_sponsor_paid,
144 logs: vec![],
145 contracts_created: vec![],
146 storage_sponsor_paid,
147 storage_collateralized: Vec::new(),
148 storage_released: Vec::new(),
149 output: Default::default(),
150 base_gas: cost.base_gas,
151 ext_result,
152 }
153 }
154
155 pub(super) fn from_executive_return(
156 r: &ExecutiveReturn, refund_info: RefundInfo, cost: CostInfo,
157 substate: Substate, ext_result: ExecutedExt, spec: &Spec,
158 ) -> Self {
159 let output = r.return_data.to_vec();
160
161 let SortedStorageChanges {
162 storage_collateralized,
163 storage_released,
164 } = if r.apply_state {
165 substate.compute_storage_changes()
166 } else {
167 Default::default()
168 };
169
170 let RefundInfo {
171 gas_used,
172 gas_charged,
173 fees_value: fee,
174 burnt_fees_value: burnt_fee,
175 ..
176 } = refund_info;
177 let mut storage_sponsor_paid = if spec.cip78a {
178 cost.storage_sponsored
179 } else {
180 cost.storage_sponsor_eligible
181 };
182
183 let mut gas_sponsor_paid = cost.gas_sponsored;
184 if !r.apply_state && !spec.cip78a {
185 gas_sponsor_paid = false;
186 storage_sponsor_paid = false;
187 }
188
189 Executed {
190 gas_used,
191 gas_charged,
192 fee,
193 burnt_fee,
194 gas_sponsor_paid,
195 logs: substate.logs.to_vec(),
196 contracts_created: substate.contracts_created().to_vec(),
197 storage_sponsor_paid,
198 storage_collateralized,
199 storage_released,
200 output,
201 base_gas: cost.base_gas,
202 ext_result,
203 }
204 }
205}
206
207pub fn make_ext_result<O: ExecutiveObserver>(observer: O) -> ShareDebugMap {
208 let mut ext_result = ShareDebugMap::custom();
209 observer.drain_trace(&mut ext_result);
210 ext_result
211}