cfx_vm_interpreter/
evm.rs1use cfx_types::{U128, U256, U512};
23use cfx_vm_types::{Context, Error, GasLeft, Result, ReturnData};
24use std::{cmp, fmt, ops};
25
26#[derive(Debug)]
29pub struct FinalizationResult {
30 pub gas_left: U256,
32 pub apply_state: bool,
34 pub return_data: ReturnData,
36}
37
38pub trait Finalize {
43 fn finalize<C: Context>(self, context: C) -> Result<FinalizationResult>;
46}
47
48impl Finalize for Result<GasLeft> {
49 fn finalize<C: Context>(self, context: C) -> Result<FinalizationResult> {
50 match self {
51 Ok(GasLeft::Known(gas_left)) => Ok(FinalizationResult {
52 gas_left,
53 apply_state: true,
54 return_data: ReturnData::empty(),
55 }),
56 Ok(GasLeft::NeedsReturn {
57 gas_left,
58 data,
59 apply_state,
60 }) => context.ret(&gas_left, &data, apply_state).map(|gas_left| {
61 FinalizationResult {
62 gas_left,
63 apply_state,
64 return_data: data,
65 }
66 }),
67 Err(err) => Err(err),
68 }
69 }
70}
71
72impl Finalize for Error {
73 fn finalize<C: Context>(self, _context: C) -> Result<FinalizationResult> {
74 Err(self)
75 }
76}
77
78pub trait CostType:
81 Sized
82 + From<usize>
83 + Copy
84 + Send
85 + ops::Mul<Output = Self>
86 + ops::Div<Output = Self>
87 + ops::Add<Output = Self>
88 + ops::Sub<Output = Self>
89 + ops::Shr<usize, Output = Self>
90 + ops::Shl<usize, Output = Self>
91 + ops::AddAssign
92 + ops::SubAssign
93 + cmp::Ord
94 + fmt::Debug
95{
96 fn as_u256(&self) -> U256;
98 fn from_u256(val: U256) -> Result<Self>;
100 fn as_usize(&self) -> usize;
102 fn overflow_add(self, other: Self) -> (Self, bool);
104 fn overflow_mul(self, other: Self) -> (Self, bool);
106 fn overflow_mul_shr(self, other: Self, shr: usize) -> (Self, bool);
109}
110
111impl CostType for U256 {
112 fn as_u256(&self) -> U256 { *self }
113
114 fn from_u256(val: U256) -> Result<Self> { Ok(val) }
115
116 fn as_usize(&self) -> usize { self.as_u64() as usize }
117
118 fn overflow_add(self, other: Self) -> (Self, bool) {
119 self.overflowing_add(other)
120 }
121
122 fn overflow_mul(self, other: Self) -> (Self, bool) {
123 self.overflowing_mul(other)
124 }
125
126 fn overflow_mul_shr(self, other: Self, shr: usize) -> (Self, bool) {
127 let x = self.full_mul(other);
128 let U512(parts) = x;
129 let overflow = (parts[4] | parts[5] | parts[6] | parts[7]) > 0;
130 let U512(parts) = x >> shr;
131 (U256([parts[0], parts[1], parts[2], parts[3]]), overflow)
132 }
133}
134
135impl CostType for usize {
136 fn as_u256(&self) -> U256 { U256::from(*self) }
137
138 fn from_u256(val: U256) -> Result<Self> {
139 let res = val.low_u64() as usize;
140
141 if U256::from(res) != val {
143 return Err(Error::OutOfGas);
144 }
145
146 Ok(res)
147 }
148
149 fn as_usize(&self) -> usize { *self }
150
151 fn overflow_add(self, other: Self) -> (Self, bool) {
152 self.overflowing_add(other)
153 }
154
155 fn overflow_mul(self, other: Self) -> (Self, bool) {
156 self.overflowing_mul(other)
157 }
158
159 fn overflow_mul_shr(self, other: Self, shr: usize) -> (Self, bool) {
160 let (c, o) = U128::from(self).overflowing_mul(U128::from(other));
161 let U128(parts) = c;
162 let overflow = o | (parts[1] > 0);
163 let U128(parts) = c >> shr;
164 let result = parts[0] as usize;
165 let overflow = overflow | (parts[0] > result as u64);
166 (result, overflow)
167 }
168}
169
170#[cfg(test)]
171mod tests {
172 use super::CostType;
173 use cfx_types::U256;
174
175 #[test]
176 fn should_calculate_overflow_mul_shr_without_overflow() {
177 let num = 1048576;
179
180 let (res1, o1) = U256::from(num).overflow_mul_shr(U256::from(num), 20);
182 let (res2, o2) = num.overflow_mul_shr(num, 20);
183
184 assert_eq!(res1, U256::from(num));
186 assert!(!o1);
187 assert_eq!(res2, num);
188 assert!(!o2);
189 }
190
191 #[test]
192 fn should_calculate_overflow_mul_shr_with_overflow() {
193 let max = u64::max_value();
195 let num1 = U256([max, max, max, max]);
196 let num2 = usize::max_value();
197
198 let (res1, o1) = num1.overflow_mul_shr(num1, 256);
200 let (res2, o2) = num2.overflow_mul_shr(num2, 64);
201
202 assert_eq!(res2, num2 - 1);
204 assert!(o2);
205
206 assert_eq!(res1, !U256::zero() - U256::one());
207 assert!(o1);
208 }
209
210 #[test]
211 fn should_validate_u256_to_usize_conversion() {
212 let v = U256::from(usize::max_value()) + U256::from(1);
214
215 let res = usize::from_u256(v);
217
218 assert!(res.is_err());
220 }
221}