pchain_runtime/execution/
phase.rs1use pchain_world_state::storage::WorldStateStorage;
18
19use crate::{
20 formulas::{TOTAL_BASE_FEE, TREASURY_CUT_OF_BASE_FEE},
21 gas,
22 transition::StateChangesResult,
23 TransitionError,
24};
25
26use super::state::ExecutionState;
27
28pub(crate) fn pre_charge<S>(state: &mut ExecutionState<S>) -> Result<u64, TransitionError>
30where
31 S: WorldStateStorage + Send + Sync + Clone + 'static,
32{
33 let init_gas = gas::tx_inclusion_cost(state.tx_size, state.commands_len);
34 if state.tx.gas_limit < init_gas {
35 return Err(TransitionError::PreExecutionGasExhausted);
36 }
37
38 let signer = state.tx.signer;
39 let origin_nonce = state.ws.nonce(signer);
40 if state.tx.nonce != origin_nonce {
41 return Err(TransitionError::WrongNonce);
42 }
43
44 let origin_balance = state.ws.balance(state.tx.signer);
45 let gas_limit = state.tx.gas_limit;
46 let base_fee = state.bd.this_base_fee;
47 let priority_fee = state.tx.priority_fee_per_gas;
48
49 let pre_charge = base_fee
51 .checked_add(priority_fee)
52 .and_then(|fee| gas_limit.checked_mul(fee) )
53 .ok_or(TransitionError::NotEnoughBalanceForGasLimit)?; let pre_charged_balance = origin_balance
57 .checked_sub(pre_charge)
58 .ok_or(TransitionError::NotEnoughBalanceForGasLimit)?; state.ws.with_commit().set_balance(signer, pre_charged_balance);
62
63 state.set_gas_consumed(init_gas);
64 Ok(init_gas)
65}
66
67pub(crate) fn finalize_gas_consumption<S>(
69 mut state: ExecutionState<S>,
70) -> Result<ExecutionState<S>, StateChangesResult<S>>
71where
72 S: pchain_world_state::storage::WorldStateStorage + Send + Sync + Clone + 'static,
73{
74 let gas_used = state.total_gas_to_be_consumed();
75 if state.tx.gas_limit < gas_used {
76 return Err(abort(state, TransitionError::ExecutionProperGasExhausted));
77 }
78 state.set_gas_consumed(gas_used);
79 Ok(state)
80}
81
82pub(crate) fn abort<S>(
84 mut state: ExecutionState<S>,
85 transition_err: TransitionError,
86) -> StateChangesResult<S>
87where
88 S: pchain_world_state::storage::WorldStateStorage + Send + Sync + Clone + 'static,
89{
90 state.revert_changes();
91 let gas_used = std::cmp::min(state.tx.gas_limit, state.total_gas_to_be_consumed());
92 state.set_gas_consumed(gas_used);
93 charge(state, Some(transition_err))
94}
95
96pub(crate) fn charge<S>(
98 mut state: ExecutionState<S>,
99 transition_result: Option<TransitionError>,
100) -> StateChangesResult<S>
101where
102 S: WorldStateStorage + Send + Sync + Clone + 'static,
103{
104 let signer = state.tx.signer;
105 let base_fee = state.bd.this_base_fee;
106 let priority_fee = state.tx.priority_fee_per_gas;
107 let gas_used = std::cmp::min(state.gas_consumed(), state.tx.gas_limit); let gas_unused = state.tx.gas_limit.saturating_sub(gas_used);
109
110 let signer_balance = state.purge_balance(signer);
112 let new_signer_balance = signer_balance + gas_unused * (base_fee + priority_fee);
113
114 let proposer_address = state.bd.proposer_address;
116 let mut proposer_balance = state.purge_balance(proposer_address);
117 if signer == proposer_address {
118 proposer_balance = new_signer_balance;
119 }
120 let new_proposer_balance = proposer_balance.saturating_add(gas_used * priority_fee);
121
122 let treasury_address = state.bd.treasury_address;
124 let mut treasury_balance = state.purge_balance(treasury_address);
125 if signer == treasury_address {
126 treasury_balance = new_signer_balance;
127 }
128 if proposer_address == treasury_address {
129 treasury_balance = new_proposer_balance;
130 }
131 let new_treasury_balance = treasury_balance
132 .saturating_add((gas_used * base_fee * TREASURY_CUT_OF_BASE_FEE) / TOTAL_BASE_FEE);
133
134 state
136 .ws
137 .with_commit()
138 .set_balance(signer, new_signer_balance);
139 state
140 .ws
141 .with_commit()
142 .set_balance(proposer_address, new_proposer_balance);
143 state
144 .ws
145 .with_commit()
146 .set_balance(treasury_address, new_treasury_balance);
147
148 let nonce = state.ws.nonce(signer).saturating_add(1);
150 state.ws.with_commit().set_nonce(signer, nonce);
151
152 state.set_gas_consumed(gas_used);
153 StateChangesResult::new(state, transition_result)
154}