Skip to content
This repository was archived by the owner on Nov 6, 2020. It is now read-only.

Commit c0920b3

Browse files
adria0sorpaasAndronik Ordian
authored
Reduced gas cost for static calls made to precompiles EIP2046/1352 (#11583)
* Implemented eip2046 * Update ethcore/builtin/src/lib.rs Co-Authored-By: Wei Tang <accounts@that.world> * Update ethcore/builtin/src/lib.rs Co-Authored-By: Wei Tang <accounts@that.world> * Update ethcore/builtin/src/lib.rs Co-Authored-By: Andronik Ordian <write@reusable.software> * Update ethcore/builtin/src/lib.rs Co-Authored-By: Wei Tang <accounts@that.world> * move precompile address limit def to gasometer * use const instead lazy_static Co-authored-by: Wei Tang <accounts@that.world> Co-authored-by: Andronik Ordian <write@reusable.software>
1 parent 5627f04 commit c0920b3

File tree

11 files changed

+183
-5
lines changed

11 files changed

+183
-5
lines changed

ethcore/evm/src/interpreter/gasometer.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// along with Open Ethereum. If not, see <http://www.gnu.org/licenses/>.
1616

1717
use std::cmp;
18-
use ethereum_types::{BigEndianHash, U256};
18+
use ethereum_types::{BigEndianHash, U256, H160, Address};
1919
use super::u256_to_address;
2020

2121
use {evm, vm};
@@ -31,6 +31,8 @@ macro_rules! overflowing {
3131
}}
3232
}
3333

34+
const PRECOMPILES_ADDRESS_LIMIT: Address = H160([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xff,0xff]);
35+
3436
enum Request<Cost: ::evm::CostType> {
3537
Gas(Cost),
3638
GasMem(Cost, Cost),
@@ -224,7 +226,7 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
224226

225227
Request::GasMemProvide(gas, mem, Some(requested))
226228
},
227-
instructions::DELEGATECALL | instructions::STATICCALL => {
229+
instructions::DELEGATECALL => {
228230
let gas = Gas::from(schedule.call_gas);
229231
let mem = cmp::max(
230232
mem_needed(stack.peek(4), stack.peek(5))?,
@@ -234,6 +236,23 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
234236

235237
Request::GasMemProvide(gas, mem, Some(requested))
236238
},
239+
instructions::STATICCALL => {
240+
let code_address = u256_to_address(stack.peek(1));
241+
let gas = if code_address <= PRECOMPILES_ADDRESS_LIMIT {
242+
Gas::from(schedule.staticcall_precompile_gas)
243+
} else {
244+
Gas::from(schedule.call_gas)
245+
};
246+
247+
let mem = cmp::max(
248+
mem_needed(stack.peek(4), stack.peek(5))?, // out_off, out_size
249+
mem_needed(stack.peek(2), stack.peek(3))? // in_off, in_size
250+
);
251+
252+
let requested = *stack.peek(0);
253+
254+
Request::GasMemProvide(gas, mem, Some(requested))
255+
},
237256
instructions::CREATE => {
238257
let start = stack.peek(1);
239258
let len = stack.peek(2);

ethcore/machine/src/test_helpers.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ pub fn new_constantinople_fix_test_machine() -> Machine { load_machine(include_b
5555
/// Create a new Foundation Istanbul era spec.
5656
pub fn new_istanbul_test_machine() -> Machine { load_machine(include_bytes!("../../res/ethereum/istanbul_test.json")) }
5757

58+
/// Create a new Foundation Berlin era spec.
59+
pub fn new_berlin_test_machine() -> Machine { load_machine(include_bytes!("../../res/ethereum/berlin_test.json")) }
60+
5861
/// Create a new Musicoin-MCIP3-era spec.
5962
pub fn new_mcip3_test_machine() -> Machine { load_machine(include_bytes!("../../res/ethereum/mcip3_test.json")) }
6063

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
{
2+
"name": "Berlin (test)",
3+
"engine": {
4+
"Ethash": {
5+
"params": {
6+
"minimumDifficulty": "0x020000",
7+
"difficultyBoundDivisor": "0x0800",
8+
"durationLimit": "0x0d",
9+
"blockReward": "0x1BC16D674EC80000",
10+
"homesteadTransition": "0x0",
11+
"eip100bTransition": "0x0",
12+
"difficultyBombDelays": {
13+
"0": 5000000
14+
}
15+
}
16+
}
17+
},
18+
"params": {
19+
"gasLimitBoundDivisor": "0x0400",
20+
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
21+
"accountStartNonce": "0x00",
22+
"maximumExtraDataSize": "0x20",
23+
"minGasLimit": "0x1388",
24+
"networkID" : "0x1",
25+
"maxCodeSize": 24576,
26+
"maxCodeSizeTransition": "0x0",
27+
"eip150Transition": "0x0",
28+
"eip160Transition": "0x0",
29+
"eip161abcTransition": "0x0",
30+
"eip161dTransition": "0x0",
31+
"eip140Transition": "0x0",
32+
"eip211Transition": "0x0",
33+
"eip214Transition": "0x0",
34+
"eip155Transition": "0x0",
35+
"eip658Transition": "0x0",
36+
"eip145Transition": "0x0",
37+
"eip1014Transition": "0x0",
38+
"eip1052Transition": "0x0",
39+
"eip1283Transition": "0x0",
40+
"eip1283DisableTransition": "0x0",
41+
"eip1283ReenableTransition": "0x0",
42+
"eip1344Transition": "0x0",
43+
"eip1706Transition": "0x0",
44+
"eip1884Transition": "0x0",
45+
"eip2028Transition": "0x0",
46+
"eip2046Transition": "0x0"
47+
},
48+
"genesis": {
49+
"seal": {
50+
"ethereum": {
51+
"nonce": "0x0000000000000042",
52+
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
53+
}
54+
},
55+
"difficulty": "0x400000000",
56+
"author": "0x0000000000000000000000000000000000000000",
57+
"timestamp": "0x00",
58+
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
59+
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
60+
"gasLimit": "0x1388"
61+
},
62+
"accounts": {
63+
"0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
64+
"0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
65+
"0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
66+
"0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
67+
"0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 20 } } } },
68+
"0000000000000000000000000000000000000006": {
69+
"builtin": {
70+
"name": "alt_bn128_add",
71+
"pricing": {
72+
"0": {
73+
"price": { "alt_bn128_const_operations": { "price": 500 }}
74+
},
75+
"0": {
76+
"info": "EIP 1108 transition",
77+
"price": { "alt_bn128_const_operations": { "price": 150 }}
78+
}
79+
}
80+
}
81+
},
82+
"0000000000000000000000000000000000000007": {
83+
"builtin": {
84+
"name": "alt_bn128_mul",
85+
"pricing": {
86+
"0": {
87+
"price": { "alt_bn128_const_operations": { "price": 40000 }}
88+
},
89+
"0": {
90+
"info": "EIP 1108 transition",
91+
"price": { "alt_bn128_const_operations": { "price": 6000 }}
92+
}
93+
}
94+
}
95+
},
96+
"0000000000000000000000000000000000000008": {
97+
"builtin": {
98+
"name": "alt_bn128_pairing",
99+
"pricing": {
100+
"0": {
101+
"price": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 }}
102+
},
103+
"0": {
104+
"info": "EIP 1108 transition",
105+
"price": { "alt_bn128_pairing": { "base": 45000, "pair": 34000 }}
106+
}
107+
}
108+
}
109+
},
110+
"0000000000000000000000000000000000000009": {
111+
"builtin": {
112+
"name": "blake2_f",
113+
"activate_at": "0x00",
114+
"pricing": {
115+
"blake2_f": {
116+
"gas_per_round": 1
117+
}
118+
}
119+
}
120+
}
121+
}
122+
}

ethcore/spec/src/chain.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ bundle_test_spec! {
9191
"ethereum/byzantium_test" => new_byzantium_test,
9292
"ethereum/constantinople_test" => new_constantinople_test,
9393
"ethereum/istanbul_test" => new_istanbul_test,
94+
"ethereum/berlin_test" => new_berlin_test,
9495
"ethereum/eip150_test" => new_eip150_test,
9596
"ethereum/eip161_test" => new_eip161_test,
9697
"ethereum/eip210_test" => new_eip210_test,
@@ -117,6 +118,7 @@ bundle_test_machine! {
117118
"ethereum/byzantium_test" => new_byzantium_test_machine,
118119
"ethereum/constantinople_test" => new_constantinople_test_machine,
119120
"ethereum/istanbul_test" => new_istanbul_test_machine,
121+
"ethereum/berlin_test" => new_berlin_test_machine,
120122
"ethereum/eip210_test" => new_eip210_test_machine,
121123
"ethereum/frontier_test" => new_frontier_test_machine,
122124
"ethereum/homestead_test" => new_homestead_test_machine,

ethcore/src/test_helpers/evm_test_client.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ impl<'a> EvmTestClient<'a> {
110110
ForkSpec::Constantinople => Some(spec::new_constantinople_test()),
111111
ForkSpec::ConstantinopleFix => Some(spec::new_constantinople_fix_test()),
112112
ForkSpec::Istanbul => Some(spec::new_istanbul_test()),
113+
ForkSpec::Berlin => Some(spec::new_berlin_test()),
113114
ForkSpec::EIP158ToByzantiumAt5 => Some(spec::new_transition_test()),
114115
ForkSpec::FrontierToHomesteadAt5 | ForkSpec::HomesteadToDaoAt5 | ForkSpec::HomesteadToEIP150At5 => None,
115116
}

ethcore/types/src/engines/params.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ pub struct CommonParams {
100100
pub eip1884_transition: BlockNumber,
101101
/// Number of first block where EIP-2028 rules begin.
102102
pub eip2028_transition: BlockNumber,
103+
/// Number of first block where EIP-2046/1352 rules begin.
104+
pub eip2046_transition: BlockNumber,
103105
/// Number of first block where EIP-2200 advance transition begin.
104106
pub eip2200_advance_transition: BlockNumber,
105107
/// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin.
@@ -191,6 +193,9 @@ impl CommonParams {
191193
schedule.sload_gas = 800;
192194
schedule.sstore_dirty_gas = Some(800);
193195
}
196+
if block_number >= self.eip2046_transition {
197+
schedule.staticcall_precompile_gas = 40;
198+
}
194199
if block_number >= self.eip210_transition {
195200
schedule.blockhash_gas = 800;
196201
}
@@ -328,6 +333,10 @@ impl From<ethjson::spec::Params> for CommonParams {
328333
BlockNumber::max_value,
329334
Into::into,
330335
),
336+
eip2046_transition: p.eip2046_transition.map_or_else(
337+
BlockNumber::max_value,
338+
Into::into,
339+
),
331340
eip2200_advance_transition: p.eip2200_advance_transition.map_or_else(
332341
BlockNumber::max_value,
333342
Into::into,

ethcore/vm/src/schedule.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,10 @@ pub struct Schedule {
7171
pub log_topic_gas: usize,
7272
/// Gas price for `CREATE` opcode
7373
pub create_gas: usize,
74-
/// Gas price for `*CALL*` opcodes
74+
/// Gas price for `*CALL*` opcodes, EXCEPT for staticcall to precompiles
7575
pub call_gas: usize,
76+
/// Gas price for staticcall to precompiles
77+
pub staticcall_precompile_gas: usize,
7678
/// Stipend for transfer for `CALL|CALLCODE` opcode when `value>0`
7779
pub call_stipend: usize,
7880
/// Additional gas required for value transfer (`CALL|CALLCODE`)
@@ -250,6 +252,7 @@ impl Schedule {
250252
log_topic_gas: 375,
251253
create_gas: 32000,
252254
call_gas: 700,
255+
staticcall_precompile_gas: 700,
253256
call_stipend: 2300,
254257
call_value_transfer_gas: 9000,
255258
call_new_account_gas: 25000,
@@ -312,6 +315,13 @@ impl Schedule {
312315
schedule
313316
}
314317

318+
/// Schedule for the Berlin fork of the Ethereum main net.
319+
pub fn new_berlin() -> Schedule {
320+
let mut schedule = Self::new_istanbul();
321+
schedule.staticcall_precompile_gas = 40; // EIPs 2046 1352
322+
schedule
323+
}
324+
315325
fn new(efcd: bool, hdc: bool, tcg: usize) -> Schedule {
316326
Schedule {
317327
exceptional_failed_code_deposit: efcd,
@@ -341,6 +351,7 @@ impl Schedule {
341351
log_topic_gas: 375,
342352
create_gas: 32000,
343353
call_gas: 40,
354+
staticcall_precompile_gas: 40,
344355
call_stipend: 2300,
345356
call_value_transfer_gas: 9000,
346357
call_new_account_gas: 25000,

ethcore/vm/src/tests.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,13 @@ impl FakeExt {
107107
ext
108108
}
109109

110+
/// New fake externalities with Berlin schedule rules
111+
pub fn new_berlin() -> Self {
112+
let mut ext = FakeExt::default();
113+
ext.schedule = Schedule::new_berlin();
114+
ext
115+
}
116+
110117
/// Alter fake externalities to allow wasm
111118
pub fn with_wasm(mut self) -> Self {
112119
self.schedule.wasm = Some(Default::default());

json/src/spec/params.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ pub struct Params {
107107
/// See `CommonParams` docs.
108108
pub eip2028_transition: Option<Uint>,
109109
/// See `CommonParams` docs.
110+
pub eip2046_transition: Option<Uint>,
111+
/// See `CommonParams` docs.
110112
pub eip2200_advance_transition: Option<Uint>,
111113
/// See `CommonParams` docs.
112114
pub dust_protection_transition: Option<Uint>,

0 commit comments

Comments
 (0)