diff --git a/Cargo.lock b/Cargo.lock index 18eef11fc0..9ad072d229 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1722,6 +1722,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "microbench" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4c44e40aee4e6fd2f4257bb91e5948ce79285aeb949129448889cf2fbf6da0b" + [[package]] name = "mime" version = "0.3.17" @@ -2409,6 +2415,16 @@ dependencies = [ "serde", ] +[[package]] +name = "revm-test" +version = "0.1.0" +dependencies = [ + "bytes", + "hex", + "microbench", + "revm", +] + [[package]] name = "revme" version = "0.2.0" diff --git a/bins/revm-test/Cargo.toml b/bins/revm-test/Cargo.toml new file mode 100644 index 0000000000..a745c67572 --- /dev/null +++ b/bins/revm-test/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "revm-test" +version = "0.1.0" +edition = "2021" +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +bytes = "1.4" +hex = "0.4" +revm = { path = "../../crates/revm", version = "3.3.0",default-features=false } +microbench = "0.5" + +[[bin]] +name = "analysis" + +[[bin]] +name = "snailtracer" + +[[bin]] +name = "transfer" \ No newline at end of file diff --git a/bins/revm-test/src/bin/analysis.rs b/bins/revm-test/src/bin/analysis.rs new file mode 100644 index 0000000000..a7a81af9ce --- /dev/null +++ b/bins/revm-test/src/bin/analysis.rs @@ -0,0 +1,60 @@ +use std::time::Instant; + +use revm::{ + db::BenchmarkDB, + interpreter::analysis::to_analysed, + primitives::{Bytecode, Bytes, TransactTo}, +}; +extern crate alloc; + +fn main() { + let contract_data : Bytes = hex::decode( "6060604052341561000f57600080fd5b604051610dd1380380610dd18339810160405280805190602001909190805182019190602001805190602001909190805182019190505083600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508360008190555082600390805190602001906100a79291906100e3565b5081600460006101000a81548160ff021916908360ff16021790555080600590805190602001906100d99291906100e3565b5050505050610188565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061012457805160ff1916838001178555610152565b82800160010185558215610152579182015b82811115610151578251825591602001919060010190610136565b5b50905061015f9190610163565b5090565b61018591905b80821115610181576000816000905550600101610169565b5090565b90565b610c3a806101976000396000f3006060604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b4578063095ea7b31461014257806318160ddd1461019c57806323b872dd146101c557806327e235e31461023e578063313ce5671461028b5780635c658165146102ba57806370a082311461032657806395d89b4114610373578063a9059cbb14610401578063dd62ed3e1461045b575b600080fd5b34156100bf57600080fd5b6100c76104c7565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101075780820151818401526020810190506100ec565b50505050905090810190601f1680156101345780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561014d57600080fd5b610182600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610565565b604051808215151515815260200191505060405180910390f35b34156101a757600080fd5b6101af610657565b6040518082815260200191505060405180910390f35b34156101d057600080fd5b610224600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061065d565b604051808215151515815260200191505060405180910390f35b341561024957600080fd5b610275600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506108f7565b6040518082815260200191505060405180910390f35b341561029657600080fd5b61029e61090f565b604051808260ff1660ff16815260200191505060405180910390f35b34156102c557600080fd5b610310600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610922565b6040518082815260200191505060405180910390f35b341561033157600080fd5b61035d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610947565b6040518082815260200191505060405180910390f35b341561037e57600080fd5b610386610990565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103c65780820151818401526020810190506103ab565b50505050905090810190601f1680156103f35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561040c57600080fd5b610441600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610a2e565b604051808215151515815260200191505060405180910390f35b341561046657600080fd5b6104b1600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610b87565b6040518082815260200191505060405180910390f35b60038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561055d5780601f106105325761010080835404028352916020019161055d565b820191906000526020600020905b81548152906001019060200180831161054057829003601f168201915b505050505081565b600081600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60005481565b600080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905082600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015801561072e5750828110155b151561073957600080fd5b82600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555082600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110156108865782600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a360019150509392505050565b60016020528060005260406000206000915090505481565b600460009054906101000a900460ff1681565b6002602052816000526040600020602052806000526040600020600091509150505481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60058054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a265780601f106109fb57610100808354040283529160200191610a26565b820191906000526020600020905b815481529060010190602001808311610a0957829003601f168201915b505050505081565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a7e57600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050929150505600a165627a7a72305820df254047bc8f2904ad3e966b6db116d703bebd40efadadb5e738c836ffc8f58a0029" ).unwrap().into(); + + // BenchmarkDB is dummy state that implements Database trait. + let mut evm = revm::new(); + + // execution globals block hash/gas_limit/coinbase/timestamp.. + evm.env.tx.caller = "0x1000000000000000000000000000000000000000" + .parse() + .unwrap(); + evm.env.tx.transact_to = TransactTo::Call( + "0x0000000000000000000000000000000000000000" + .parse() + .unwrap(), + ); + //evm.env.tx.data = Bytes::from(hex::decode("30627b7c").unwrap()); + evm.env.tx.data = Bytes::from(hex::decode("8035F0CE").unwrap()); + + let bytecode_raw = Bytecode::new_raw(contract_data.clone()); + let bytecode_checked = Bytecode::new_raw(contract_data.clone()).to_checked(); + let bytecode_analysed = to_analysed(Bytecode::new_raw(contract_data)); + + evm.database(BenchmarkDB::new_bytecode(bytecode_raw)); + + // just to spead up processor. + for _ in 0..10000 { + let _ = evm.transact().unwrap(); + } + + let timer = Instant::now(); + for _ in 0..30000 { + let _ = evm.transact().unwrap(); + } + println!("Raw elapsed time: {:?}", timer.elapsed()); + + evm.database(BenchmarkDB::new_bytecode(bytecode_checked)); + + let timer = Instant::now(); + for _ in 0..30000 { + let _ = evm.transact().unwrap(); + } + println!("Checked elapsed time: {:?}", timer.elapsed()); + + evm.database(BenchmarkDB::new_bytecode(bytecode_analysed)); + + let timer = Instant::now(); + for _ in 0..30000 { + let _ = evm.transact().unwrap(); + } + println!("Analysed elapsed time: {:?}", timer.elapsed()); +} diff --git a/bins/revm-test/src/bin/snailtracer.rs b/bins/revm-test/src/bin/snailtracer.rs new file mode 100644 index 0000000000..19ed7df595 --- /dev/null +++ b/bins/revm-test/src/bin/snailtracer.rs @@ -0,0 +1,59 @@ +use revm::{ + db::BenchmarkDB, + interpreter::analysis::to_analysed, + primitives::{Bytecode, Bytes, TransactTo}, +}; +extern crate alloc; + +pub fn simple_example() { + let contract_data : Bytes = hex::decode("608060405234801561001057600080fd5b506004361061004c5760003560e01c806330627b7c1461005157806375ac892a14610085578063784f13661461011d578063c294360114610146575b600080fd5b610059610163565b604080516001600160f81b03199485168152928416602084015292168183015290519081900360600190f35b6100a86004803603604081101561009b57600080fd5b50803590602001356102d1565b6040805160208082528351818301528351919283929083019185019080838360005b838110156100e25781810151838201526020016100ca565b50505050905090810190601f16801561010f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6100596004803603606081101561013357600080fd5b508035906020810135906040013561055b565b6100a86004803603602081101561015c57600080fd5b5035610590565b6000806000610176610400610300610834565b60405180606001604052806001546000546207d5dc028161019357fe5b058152600060208083018290526040928301919091528251600b81905583820151600c81905593830151600d819055835160608082018652928152808401959095528484015282519081018352600654815260075491810191909152600854918101919091526102259161021c916102139161020e91612ef7565b612f64565b6207d5dc612feb565b620f424061301e565b8051600e556020810151600f55604001516010556102416142dd565b61025a816102556102006101806008613064565b613212565b90506102708161025561014561021c6008613064565b905061028481610255610258806008613064565b905061029a8161025561020a61020c6008613064565b90506102a781600461301e565b90506102b1613250565b8051602082015160409092015160f891821b9692821b9550901b92509050565b606060005b6000548112156104c95760006102ed828686613064565b90506002816000015160f81b90808054603f811680603e811461032a576002830184556001831661031c578192505b600160028404019350610342565b600084815260209081902060ff198516905560419094555b505050600190038154600116156103685790600052602060002090602091828204019190065b909190919091601f036101000a81548160ff02191690600160f81b840402179055506002816020015160f81b90808054603f811680603e81146103c557600283018455600183166103b7578192505b6001600284040193506103dd565b600084815260209081902060ff198516905560419094555b505050600190038154600116156104035790600052602060002090602091828204019190065b909190919091601f036101000a81548160ff02191690600160f81b840402179055506002816040015160f81b90808054603f811680603e81146104605760028301845560018316610452578192505b600160028404019350610478565b600084815260209081902060ff198516905560419094555b5050506001900381546001161561049e5790600052602060002090602091828204019190065b815460ff601f929092036101000a9182021916600160f81b90930402919091179055506001016102d6565b506002805460408051602060018416156101000260001901909316849004601f8101849004840282018401909252818152929183018282801561054d5780601f106105225761010080835404028352916020019161054d565b820191906000526020600020905b81548152906001019060200180831161053057829003601f168201915b505050505090505b92915050565b60008060008061056c878787613064565b8051602082015160409092015160f891821b9a92821b9950901b9650945050505050565b600154606090600019015b600081126107a35760005b6000548112156107995760006105bd828487613064565b90506002816000015160f81b90808054603f811680603e81146105fa57600283018455600183166105ec578192505b600160028404019350610612565b600084815260209081902060ff198516905560419094555b505050600190038154600116156106385790600052602060002090602091828204019190065b909190919091601f036101000a81548160ff02191690600160f81b840402179055506002816020015160f81b90808054603f811680603e81146106955760028301845560018316610687578192505b6001600284040193506106ad565b600084815260209081902060ff198516905560419094555b505050600190038154600116156106d35790600052602060002090602091828204019190065b909190919091601f036101000a81548160ff02191690600160f81b840402179055506002816040015160f81b90808054603f811680603e81146107305760028301845560018316610722578192505b600160028404019350610748565b600084815260209081902060ff198516905560419094555b5050506001900381546001161561076e5790600052602060002090602091828204019190065b815460ff601f929092036101000a9182021916600160f81b90930402919091179055506001016105a6565b506000190161059b565b506002805460408051602060018416156101000260001901909316849004601f810184900484028201840190925281815292918301828280156108275780601f106107fc57610100808354040283529160200191610827565b820191906000526020600020905b81548152906001019060200180831161080a57829003601f168201915b505050505090505b919050565b8160008190555080600181905550604051806080016040528060405180606001604052806302faf08081526020016303197500815260200163119e7f8081525081526020016108a460405180606001604052806000815260200161a673198152602001620f423f19815250612f64565b815260006020808301829052604092830182905283518051600355808201516004558301516005558381015180516006559081015160075582015160085582820151600955606092830151600a805460ff1916911515919091179055815192830190915260015490548291906207d5dc028161091c57fe5b058152600060208083018290526040928301919091528251600b81905583820151600c81905593830151600d819055835160608082018652928152808401959095528484015282519081018352600654815260075491810191909152600854918101919091526109979161021c916102139161020e91612ef7565b8051600e55602080820151600f55604091820151601055815160a08101835264174876e8008152825160608082018552641748862a40825263026e8f00828501526304dd1e008286015282840191825284518082018652600080825281860181905281870181905284870191825286518084018852620b71b081526203d09081880181905281890152928501928352608085018181526011805460018082018355919093528651600b9093027f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c688101938455955180517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c69880155808901517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6a8801558901517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6b870155925180517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6c870155808801517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6d8701558801517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6e860155925180517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6f860155958601517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c7085015594909501517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c71830155517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c72909101805492949192909160ff1990911690836002811115610c1057fe5b0217905550505060116040518060a0016040528064174876e8008152602001604051806060016040528064174290493f19815260200163026e8f0081526020016304dd1e008152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806203d09081526020016203d0908152602001620b71b0815250815260200160006002811115610cb657fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff1990921691908490811115610d5857fe5b0217905550505060116040518060a0016040528064174876e800815260200160405180606001604052806302faf080815260200163026e8f00815260200164174876e800815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620b71b08152602001620b71b08152602001620b71b0815250815260200160006002811115610dfd57fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff1990921691908490811115610e9f57fe5b0217905550505060116040518060a0016040528064174876e800815260200160405180606001604052806302faf080815260200163026e8f00815260200164173e54e97f1981525081526020016040518060600160405280600081526020016000815260200160008152508152602001604051806060016040528060008152602001600081526020016000815250815260200160006002811115610f3f57fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff1990921691908490811115610fe157fe5b0217905550505060116040518060a0016040528064174876e800815260200160405180606001604052806302faf080815260200164174876e80081526020016304dd1e00815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620b71b08152602001620b71b08152602001620b71b081525081526020016000600281111561108657fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff199092169190849081111561112857fe5b0217905550505060116040518060a0016040528064174876e800815260200160405180606001604052806302faf080815260200164174399c9ff1981526020016304dd1e00815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620b71b08152602001620b71b08152602001620b71b08152508152602001600060028111156111ce57fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff199092169190849081111561127057fe5b0217905550505060116040518060a0016040528062fbc5208152602001604051806060016040528063019bfcc0815260200162fbc52081526020016302cd29c0815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561131157fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff19909216919084908111156113b357fe5b0217905550505060116040518060a001604052806323c34600815260200160405180606001604052806302faf080815260200163289c455081526020016304dd1e008152508152602001604051806060016040528062b71b00815260200162b71b00815260200162b71b00815250815260200160405180606001604052806000815260200160008152602001600081525081526020016000600281111561145657fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff19909216919084908111156114f857fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f208152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001630188c2e081526020016305a1f4a081525081526020016040518060600160405280630459e44081526020016302f34f6081526020016304a62f808152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561160c57fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff19909216919084908111156116fd57fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f20815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001600081526020016304a62f8081525081526020016040518060600160405280630459e440815260200163016a8c8081526020016305a1f4a08152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561180e57fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff19909216919084908111156118ff57fe5b0217905550505060126040518060e001604052806040518060600160405280630555a9608152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630459e44081526020016302f34f6081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001630188c2e081526020016305a1f4a08152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e58815250815260200160016002811115611a1357fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff1990921691908490811115611b0457fe5b0217905550505060126040518060e001604052806040518060600160405280630555a960815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630459e440815260200163016a8c8081526020016305a1f4a081525081526020016040518060600160405280630459e4408152602001600081526020016304a62f808152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e58815250815260200160016002811115611c1557fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff1990921691908490811115611d0657fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f208152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630459e44081526020016302f34f6081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001630188c2e081526020016303aa6a608152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e58815250815260200160016002811115611e1a57fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff1990921691908490811115611f0b57fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f20815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630459e440815260200163016a8c8081526020016303aa6a6081525081526020016040518060600160405280630459e4408152602001600081526020016304a62f808152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561201c57fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff199092169190849081111561210d57fe5b0217905550505060126040518060e001604052806040518060600160405280630555a9608152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001630188c2e081526020016303aa6a6081525081526020016040518060600160405280630459e44081526020016302f34f6081526020016304a62f808152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561222157fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff199092169190849081111561231257fe5b0217905550505060126040518060e001604052806040518060600160405280630555a960815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001600081526020016304a62f8081525081526020016040518060600160405280630459e440815260200163016a8c8081526020016303aa6a608152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561242357fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff199092169190849081111561251457fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f208152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001630188c2e081526020016303aa6a6081525081526020016040518060600160405280630555a9608152602001630188c2e081526020016304a62f808152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561262857fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff199092169190849081111561271957fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f208152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630555a9608152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001630188c2e081526020016305a1f4a08152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561282d57fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff199092169190849081111561291e57fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f20815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630555a960815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630459e440815260200163016a8c8081526020016303aa6a608152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e58815250815260200160016002811115612a3257fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff1990921691908490811115612b2357fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f20815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630459e440815260200163016a8c8081526020016305a1f4a081525081526020016040518060600160405280630555a960815260200163016a8c8081526020016304a62f808152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e58815250815260200160016002811115612c3757fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff1990921691908490811115612d2857fe5b0217905550505060005b601254811015612ef257600060128281548110612d4b57fe5b600091825260209182902060408051610140810182526013909302909101805460e08401908152600182015461010085015260028083015461012086015290845282516060818101855260038401548252600484015482880152600584015482860152858701919091528351808201855260068401548152600784015481880152600884015481860152858501528351808201855260098401548152600a84015481880152600b840154818601528186015283518082018552600c8401548152600d84015481880152600e84015481860152608086015283519081018452600f830154815260108301549581019590955260118201549285019290925260a0830193909352601283015491929160c084019160ff90911690811115612e6c57fe5b6002811115612e7757fe5b815250509050612eac61020e612e95836020015184600001516132cd565b612ea7846040015185600001516132cd565b612ef7565b60128381548110612eb957fe5b60009182526020918290208351600960139093029091019182015590820151600a820155604090910151600b9091015550600101612d32565b505050565b612eff6142dd565b604051806060016040528083602001518560400151028460400151866020015102038152602001836040015185600001510284600001518660400151020381526020018360000151856020015102846020015186600001510203815250905092915050565b612f6c6142dd565b604082015160208301518351600092612f9292918002918002919091019080020161330c565b90506040518060600160405280828560000151620f42400281612fb157fe5b058152602001828560200151620f42400281612fc957fe5b058152602001828560400151620f42400281612fe157fe5b0590529392505050565b612ff36142dd565b5060408051606081018252835183028152602080850151840290820152928101519091029082015290565b6130266142dd565b60405180606001604052808385600001518161303e57fe5b0581526020018385602001518161305157fe5b05815260200183856040015181612fe157fe5b61306c6142dd565b6000546013805463ffffffff1916918502860163ffffffff169190911790556130936142dd565b905060005b828112156131f157600061317261314c61021c613115600b60405180606001604052908160008201548152602001600182015481526020016002820154815250506207a1206000546207a1206130ec613343565b63ffffffff16816130f957fe5b0663ffffffff168d620f424002018161310e57fe5b0503612feb565b60408051606081018252600e548152600f5460208201526010549181019190915260015461025591906207a12090816130ec613343565b604080516060810182526006548152600754602082015260085491810191909152613212565b6040805160e081019091526003546080820190815260045460a083015260055460c083015291925060009181906131ae9061025586608c612feb565b81526020016131bc84612f64565b815260006020820181905260409091015290506131e5846102556131df8461336c565b8861301e565b93505050600101613098565b5061320861021c61320183613753565b60ff612feb565b90505b9392505050565b61321a6142dd565b50604080516060810182528251845101815260208084015181860151019082015291810151928101519092019181019190915290565b60008080556001819055613266906002906142fe565b60006003819055600481905560058190556006819055600781905560088190556009819055600a805460ff19169055600b819055600c819055600d819055600e819055600f81905560108190556132bf90601190614345565b6132cb60126000614366565b565b6132d56142dd565b5060408051606081018252825184510381526020808401518186015103908201528282015184830151039181019190915292915050565b80600260018201055b8181121561333d5780915060028182858161332c57fe5b05018161333557fe5b059050613315565b50919050565b6013805463ffffffff19811663ffffffff9182166341c64e6d0261303901821617918290551690565b6133746142dd565b600a826040015113156133a657604051806060016040528060008152602001600081526020016000815250905061082f565b60008060006133b48561379f565b91945092509050826133e857604051806060016040528060008152602001600081526020016000815250935050505061082f565b6133f0614387565b6133f86143c7565b6134006142dd565b6134086142dd565b600086600181111561341657fe5b1415613505576011858154811061342957fe5b60009182526020918290206040805160a081018252600b90930290910180548352815160608082018452600183015482526002808401548388015260038401548386015285870192909252835180820185526004840154815260058401548188015260068401548186015285850152835180820185526007840154815260088401549681019690965260098301549386019390935291830193909352600a830154919291608084019160ff909116908111156134e157fe5b60028111156134ec57fe5b8152505093508360600151915083604001519050613653565b6012858154811061351257fe5b600091825260209182902060408051610140810182526013909302909101805460e08401908152600182015461010085015260028083015461012086015290845282516060818101855260038401548252600484015482880152600584015482860152858701919091528351808201855260068401548152600784015481880152600884015481860152858501528351808201855260098401548152600a84015481880152600b840154818601528186015283518082018552600c8401548152600d84015481880152600e84015481860152608086015283519081018452600f830154815260108301549581019590955260118201549285019290925260a0830193909352601283015491929160c084019160ff9091169081111561363357fe5b600281111561363e57fe5b8152505092508260a001519150826080015190505b6040820151600190811215613669575060408201515b808360200151131561367c575060208201515b808360400151131561368f575060408201515b60408a01805160010190819052600512156136f75780620f42406136b1613343565b63ffffffff16816136be57fe5b0663ffffffff1612156136e8576136e16136db84620f4240612feb565b8261301e565b92506136f7565b50965061082f95505050505050565b6136ff6142dd565b600088600181111561370d57fe5b14156137255761371e8b878b613a57565b9050613733565b6137308b868b613aec565b90505b6137448361025561021c8785613baa565b9b9a5050505050505050505050565b61375b6142dd565b60405180606001604052806137738460000151613be8565b81526020016137858460200151613be8565b81526020016137978460400151613be8565b905292915050565b60008080808080805b6011548110156138c2576000613890601183815481106137c457fe5b60009182526020918290206040805160a081018252600b90930290910180548352815160608082018452600183015482526002808401548388015260038401548386015285870192909252835180820185526004840154815260058401548188015260068401548186015285850152835180820185526007840154815260088401549681019690965260098301549386019390935291830193909352600a830154919291608084019160ff9091169081111561387c57fe5b600281111561388757fe5b9052508a613c13565b90506000811380156138a957508415806138a957508481125b156138b957809450600093508192505b506001016137a8565b5060005b601254811015613a49576000613a17601283815481106138e257fe5b600091825260209182902060408051610140810182526013909302909101805460e08401908152600182015461010085015260028083015461012086015290845282516060818101855260038401548252600484015482880152600584015482860152858701919091528351808201855260068401548152600784015481880152600884015481860152858501528351808201855260098401548152600a84015481880152600b840154818601528186015283518082018552600c8401548152600d84015481880152600e84015481860152608086015283519081018452600f830154815260108301549581019590955260118201549285019290925260a0830193909352601283015491929160c084019160ff90911690811115613a0357fe5b6002811115613a0e57fe5b9052508a613cbb565b9050600081138015613a305750841580613a3057508481125b15613a4057809450600193508192505b506001016138c6565b509196909550909350915050565b613a5f6142dd565b6000613a7a856000015161025561021c886020015187612feb565b90506000613a8f61020e8387602001516132cd565b9050600085608001516002811115613aa357fe5b1415613ae1576000613ab9828860200151613e0c565b12613acd57613aca81600019612feb565b90505b613ad8868383613e31565b9250505061320b565b613ad8868383613fc1565b613af46142dd565b6000613b0f856000015161025561021c886020015187612feb565b6060860151909150620a2c2a9015613b2757506216e3605b6000620f4240613b3f87606001518960200151613e0c565b81613b4657fe5b05905060008112613b55576000035b64e8d4a5100081800281038380020281900590036000811215613b8c57613b8188858960600151613fc1565b94505050505061320b565b613b9e88858960600151868686614039565b98975050505050505050565b613bb26142dd565b50604080516060810182528251845102815260208084015181860151029082015291810151928101519092029181019190915290565b600080821215613bfa5750600061082f565b620f4240821315613c0f5750620f424061082f565b5090565b600080613c28846020015184600001516132cd565b90506000620f4240613c3e838660200151613e0c565b81613c4557fe5b865191900591506000908002613c5b8480613e0c565b838402030190506000811215613c775760009350505050610555565b613c808161330c565b90506103e88183031315613c9957900391506105559050565b6103e88183011315613caf570191506105559050565b50600095945050505050565b600080613cd0846020015185600001516132cd565b90506000613ce6856040015186600001516132cd565b90506000613cf8856020015183612ef7565b90506000620f4240613d0a8584613e0c565b81613d1157fe5b0590506103e71981138015613d2757506103e881125b15613d39576000945050505050610555565b85518751600091613d49916132cd565b9050600082613d588386613e0c565b81613d5f57fe5b0590506000811280613d735750620f424081135b15613d875760009650505050505050610555565b6000613d938388612ef7565b9050600084613da68b6020015184613e0c565b81613dad57fe5b0590506000811280613dc35750620f4240818401135b15613dd957600098505050505050505050610555565b600085613de68985613e0c565b81613ded57fe5b0590506103e88112156137445760009950505050505050505050610555565b6040808201519083015160208084015190850151845186510291020191020192915050565b613e396142dd565b6000620f424080613e48613343565b63ffffffff1681613e5557fe5b0663ffffffff16625fdfb00281613e6857fe5b0590506000620f4240613e79613343565b63ffffffff1681613e8657fe5b0663ffffffff1690506000613e9a8261330c565b6103e8029050613ea86142dd565b620186a0613eb98760000151614216565b1315613ee657604051806060016040528060008152602001620f4240815260200160008152509050613f09565b6040518060600160405280620f4240815260200160008152602001600081525090505b613f1661020e8288612ef7565b90506000613f2761020e8884612ef7565b9050613f7f61020e613f64613f5285620f424088613f448c61422e565b0281613f4c57fe5b05612feb565b61025585620f424089613f448d61424e565b6102558a613f7689620f42400361330c565b6103e802612feb565b9150613fb460405180608001604052808a81526020018481526020018b6040015181526020018b60600151151581525061336c565b9998505050505050505050565b613fc96142dd565b6000613ffb61020e8660200151613ff686620f4240613fec898c60200151613e0c565b60020281613f4c57fe5b6132cd565b90506140306040518060800160405280868152602001838152602001876040015181526020018760600151151581525061336c565b95945050505050565b6140416142dd565b60608701516000199015614053575060015b600061408961020e61021c61406c8c602001518a612feb565b613ff68b6140798a61330c565b620f42408c8e0205018802612feb565b60608a0151909150620f42408601906140ba57620f42406140aa838a613e0c565b816140b157fe5b05620f42400390505b60408a0151619c406c0c9f2c9cd04674edea40000000620ea6008480028502850285020205019060021261415e5761412a61411f60405180608001604052808d81526020018681526020018e6040015181526020018e6060015115151581525061336c565b82620f424003612feb565b92506141448361025561413e8e8e8e613fc1565b84612feb565b925061415383620f424061301e565b94505050505061420c565b600281056203d09001620f4240614173613343565b63ffffffff168161418057fe5b0663ffffffff1612156141b2576141536141a461419e8d8d8d613fc1565b83612feb565b600283056203d0900161301e565b6142056141f76141ec60405180608001604052808e81526020018781526020018f6040015181526020018f6060015115151581525061336c565b83620f424003612feb565b60028305620b71b00361301e565b9450505050505b9695505050505050565b60008082131561422757508061082f565b5060000390565b60008061423a8361424e565b905061320b81820264e8d4a510000361330c565b60005b600082121561426757625fdfb082019150614251565b5b625fdfb0821261427f57625fdfb082039150614268565b6001828160025b818313156142d457818385028161429957fe5b0585019450620f4240808788860202816142af57fe5b05816142b757fe5b600095909503940592506001810181029190910290600201614286565b50505050919050565b60405180606001604052806000815260200160008152602001600081525090565b50805460018160011615610100020316600290046000825580601f106143245750614342565b601f0160209004906000526020600020908101906143429190614401565b50565b50805460008255600b02906000526020600020908101906143429190614416565b50805460008255601302906000526020600020908101906143429190614475565b6040518060a00160405280600081526020016143a16142dd565b81526020016143ae6142dd565b81526020016143bb6142dd565b81526020016000905290565b6040518060e001604052806143da6142dd565b81526020016143e76142dd565b81526020016143f46142dd565b81526020016143a16142dd565b5b80821115613c0f5760008155600101614402565b5b80821115613c0f57600080825560018201819055600282018190556003820181905560048201819055600582018190556006820181905560078201819055600882018190556009820155600a8101805460ff19169055600b01614417565b5b80821115613c0f576000808255600182018190556002820181905560038201819055600482018190556005820181905560068201819055600782018190556008820181905560098201819055600a8201819055600b8201819055600c8201819055600d8201819055600e8201819055600f820181905560108201819055601182015560128101805460ff1916905560130161447656fea2646970667358221220037024f5647853879c58fbcc61ac3616455f6f731cc6e84f91eb5a3b4e06c00464736f6c63430007060033").unwrap().into(); + + // BenchmarkDB is dummy state that implements Database trait. + let mut evm = revm::new(); + let bytecode = to_analysed(Bytecode::new_raw(contract_data)); + evm.database(BenchmarkDB::new_bytecode(bytecode.clone())); + + // execution globals block hash/gas_limit/coinbase/timestamp.. + evm.env.tx.caller = "0x1000000000000000000000000000000000000000" + .parse() + .unwrap(); + evm.env.tx.transact_to = TransactTo::Call( + "0x0000000000000000000000000000000000000000" + .parse() + .unwrap(), + ); + evm.env.tx.data = Bytes::from(hex::decode("30627b7c").unwrap()); + + // Microbenchmark + //let bench_options = microbench::Options::default().time(Duration::from_secs(2)); + + //let env = evm.env.clone(); + //microbench::bench( + // &bench_options, + // "Snailtracer Host+Interpreter benchmark", + // || { + let _ = evm.transact().unwrap(); + // }, + //); + /* + // revm interpreter + let contract = Contract { + input: evm.env.tx.data, + bytecode: BytecodeLocked::try_from(bytecode).unwrap(), + ..Default::default() + }; + + let mut host = DummyHost::new(env); + microbench::bench(&bench_options, "Snailtracer Interpreter benchmark", || { + let mut interpreter = Interpreter::new(Box::new(contract.clone()), u64::MAX, false); + interpreter.run::<_, BerlinSpec>(&mut host); + host.clear() + }); + */ +} + +fn main() { + //println!("Running snailtracer bench!"); + simple_example(); + //println!("end!"); +} diff --git a/bins/revm-test/src/bin/transfer.rs b/bins/revm-test/src/bin/transfer.rs new file mode 100644 index 0000000000..ff74d442c4 --- /dev/null +++ b/bins/revm-test/src/bin/transfer.rs @@ -0,0 +1,39 @@ +use revm::{ + db::BenchmarkDB, + primitives::{Bytecode, TransactTo, U256}, +}; +use std::time::{Duration, Instant}; +extern crate alloc; + +fn main() { + // BenchmarkDB is dummy state that implements Database trait. + let mut evm = revm::new(); + + // execution globals block hash/gas_limit/coinbase/timestamp.. + evm.env.tx.caller = "0x0000000000000000000000000000000000000001" + .parse() + .unwrap(); + evm.env.tx.value = U256::from(10); + evm.env.tx.transact_to = TransactTo::Call( + "0x0000000000000000000000000000000000000000" + .parse() + .unwrap(), + ); + //evm.env.tx.data = Bytes::from(hex::decode("30627b7c").unwrap()); + + evm.database(BenchmarkDB::new_bytecode(Bytecode::new())); + + // Microbenchmark + let bench_options = microbench::Options::default().time(Duration::from_secs(1)); + + microbench::bench(&bench_options, "Simple value transfer", || { + let _ = evm.transact().unwrap(); + }); + + let time = Instant::now(); + for _ in 0..10000 { + let _ = evm.transact().unwrap(); + } + let elapsed = time.elapsed(); + println!("10k runs in {:?}", elapsed.as_nanos() / 10_000); +} diff --git a/crates/interpreter/src/host.rs b/crates/interpreter/src/host.rs index 54607dff71..166cd91dc1 100644 --- a/crates/interpreter/src/host.rs +++ b/crates/interpreter/src/host.rs @@ -1,7 +1,7 @@ use crate::primitives::Bytecode; use crate::{ primitives::{Address, Bytes, Env, B256, U256}, - CallInputs, CreateInputs, Gas, InstructionResult, Interpreter, SelfDestructResult, + CallInputs, CreateInputs, Gas, InstructionResult, SelfDestructResult, }; use alloc::vec::Vec; pub use dummy::DummyHost; @@ -10,16 +10,6 @@ mod dummy; /// EVM context host. pub trait Host { - /// Called before the interpreter executes an instruction. - fn step(&mut self, interpreter: &mut Interpreter) -> InstructionResult; - - /// Called after the interpreter executes an instruction. - fn step_end( - &mut self, - interpreter: &mut Interpreter, - ret: InstructionResult, - ) -> InstructionResult; - /// Returns a mutable reference to the environment. fn env(&mut self) -> &mut Env; diff --git a/crates/interpreter/src/host/dummy.rs b/crates/interpreter/src/host/dummy.rs index 5b58bfbb2d..fbff409f6a 100644 --- a/crates/interpreter/src/host/dummy.rs +++ b/crates/interpreter/src/host/dummy.rs @@ -1,7 +1,7 @@ use crate::primitives::{hash_map::Entry, Bytecode, Bytes, HashMap, U256}; use crate::{ primitives::{Address, Env, Log, B256, KECCAK_EMPTY}, - CallInputs, CreateInputs, Gas, Host, InstructionResult, Interpreter, SelfDestructResult, + CallInputs, CreateInputs, Gas, Host, InstructionResult, SelfDestructResult, }; use alloc::vec::Vec; @@ -34,20 +34,6 @@ impl DummyHost { } impl Host for DummyHost { - #[inline] - fn step(&mut self, _interp: &mut Interpreter) -> InstructionResult { - InstructionResult::Continue - } - - #[inline] - fn step_end( - &mut self, - _interp: &mut Interpreter, - _ret: InstructionResult, - ) -> InstructionResult { - InstructionResult::Continue - } - #[inline] fn env(&mut self) -> &mut Env { &mut self.env diff --git a/crates/interpreter/src/instructions/arithmetic.rs b/crates/interpreter/src/instructions/arithmetic.rs index e0700ee3f3..f7c8a153f7 100644 --- a/crates/interpreter/src/instructions/arithmetic.rs +++ b/crates/interpreter/src/instructions/arithmetic.rs @@ -65,7 +65,7 @@ pub fn mulmod(interpreter: &mut Interpreter, _host: &mut H) { *op3 = op1.mul_mod(op2, *op3) } -pub fn exp(interpreter: &mut Interpreter, _host: &mut H) { +pub fn exp(interpreter: &mut Interpreter, _host: &mut H) { pop_top!(interpreter, op1, op2); gas_or_fail!(interpreter, gas::exp_cost::(*op2)); *op2 = op1.pow(*op2); diff --git a/crates/interpreter/src/instructions/bitwise.rs b/crates/interpreter/src/instructions/bitwise.rs index d9fffbfe3e..9fbea516cc 100644 --- a/crates/interpreter/src/instructions/bitwise.rs +++ b/crates/interpreter/src/instructions/bitwise.rs @@ -80,7 +80,7 @@ pub fn byte(interpreter: &mut Interpreter, _host: &mut H) { } /// EIP-145: Bitwise shifting instructions in EVM -pub fn shl(interpreter: &mut Interpreter, _host: &mut H) { +pub fn shl(interpreter: &mut Interpreter, _host: &mut H) { check!(interpreter, CONSTANTINOPLE); gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1, op2); @@ -88,7 +88,7 @@ pub fn shl(interpreter: &mut Interpreter, _host: &mut H) { } /// EIP-145: Bitwise shifting instructions in EVM -pub fn shr(interpreter: &mut Interpreter, _host: &mut H) { +pub fn shr(interpreter: &mut Interpreter, _host: &mut H) { check!(interpreter, CONSTANTINOPLE); gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1, op2); @@ -96,7 +96,7 @@ pub fn shr(interpreter: &mut Interpreter, _host: &mut H) { } /// EIP-145: Bitwise shifting instructions in EVM -pub fn sar(interpreter: &mut Interpreter, _host: &mut H) { +pub fn sar(interpreter: &mut Interpreter, _host: &mut H) { check!(interpreter, CONSTANTINOPLE); gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1, op2); diff --git a/crates/interpreter/src/instructions/control.rs b/crates/interpreter/src/instructions/control.rs index 9c28a1af97..5992d83158 100644 --- a/crates/interpreter/src/instructions/control.rs +++ b/crates/interpreter/src/instructions/control.rs @@ -65,7 +65,7 @@ pub fn ret(interpreter: &mut Interpreter, _host: &mut H) { } /// EIP-140: REVERT instruction -pub fn revert(interpreter: &mut Interpreter, _host: &mut H) { +pub fn revert(interpreter: &mut Interpreter, _host: &mut H) { check!(interpreter, BYZANTIUM); return_inner(interpreter, InstructionResult::Revert) } diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index babeba926c..16386140ec 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -10,7 +10,7 @@ use alloc::{boxed::Box, vec::Vec}; use core::cmp::min; use revm_primitives::BLOCK_HASH_HISTORY; -pub fn balance(interpreter: &mut Interpreter, host: &mut H) { +pub fn balance(interpreter: &mut Interpreter, host: &mut H) { pop_address!(interpreter, address); let Some((balance, is_cold)) = host.balance(address) else { interpreter.instruction_result = InstructionResult::FatalExternalError; @@ -31,7 +31,7 @@ pub fn balance(interpreter: &mut Interpreter, host: &mut H) } /// EIP-1884: Repricing for trie-size-dependent opcodes -pub fn selfbalance(interpreter: &mut Interpreter, host: &mut H) { +pub fn selfbalance(interpreter: &mut Interpreter, host: &mut H) { check!(interpreter, ISTANBUL); gas!(interpreter, gas::LOW); let Some((balance, _)) = host.balance(interpreter.contract.address) else { @@ -41,7 +41,7 @@ pub fn selfbalance(interpreter: &mut Interpreter, host: &mu push!(interpreter, balance); } -pub fn extcodesize(interpreter: &mut Interpreter, host: &mut H) { +pub fn extcodesize(interpreter: &mut Interpreter, host: &mut H) { pop_address!(interpreter, address); let Some((code, is_cold)) = host.code(address) else { interpreter.instruction_result = InstructionResult::FatalExternalError; @@ -66,7 +66,7 @@ pub fn extcodesize(interpreter: &mut Interpreter, host: &mu } /// EIP-1052: EXTCODEHASH opcode -pub fn extcodehash(interpreter: &mut Interpreter, host: &mut H) { +pub fn extcodehash(interpreter: &mut Interpreter, host: &mut H) { check!(interpreter, CONSTANTINOPLE); pop_address!(interpreter, address); let Some((code_hash, is_cold)) = host.code_hash(address) else { @@ -90,7 +90,7 @@ pub fn extcodehash(interpreter: &mut Interpreter, host: &mu push_b256!(interpreter, code_hash); } -pub fn extcodecopy(interpreter: &mut Interpreter, host: &mut H) { +pub fn extcodecopy(interpreter: &mut Interpreter, host: &mut H) { pop_address!(interpreter, address); pop!(interpreter, memory_offset, code_offset, len_u256); @@ -136,7 +136,7 @@ pub fn blockhash(interpreter: &mut Interpreter, host: &mut H) { *number = U256::ZERO; } -pub fn sload(interpreter: &mut Interpreter, host: &mut H) { +pub fn sload(interpreter: &mut Interpreter, host: &mut H) { pop!(interpreter, index); let Some((value, is_cold)) = host.sload(interpreter.contract.address, index) else { @@ -147,7 +147,7 @@ pub fn sload(interpreter: &mut Interpreter, host: &mut H) { push!(interpreter, value); } -pub fn sstore(interpreter: &mut Interpreter, host: &mut H) { +pub fn sstore(interpreter: &mut Interpreter, host: &mut H) { check_staticcall!(interpreter); pop!(interpreter, index, value); @@ -166,7 +166,7 @@ pub fn sstore(interpreter: &mut Interpreter, host: &mut H) /// EIP-1153: Transient storage opcodes /// Store value to transient storage -pub fn tstore(interpreter: &mut Interpreter, host: &mut H) { +pub fn tstore(interpreter: &mut Interpreter, host: &mut H) { check!(interpreter, CANCUN); check_staticcall!(interpreter); gas!(interpreter, gas::WARM_STORAGE_READ_COST); @@ -178,7 +178,7 @@ pub fn tstore(interpreter: &mut Interpreter, host: &mut H) /// EIP-1153: Transient storage opcodes /// Load value from transient storage -pub fn tload(interpreter: &mut Interpreter, host: &mut H) { +pub fn tload(interpreter: &mut Interpreter, host: &mut H) { check!(interpreter, CANCUN); gas!(interpreter, gas::WARM_STORAGE_READ_COST); @@ -187,7 +187,7 @@ pub fn tload(interpreter: &mut Interpreter, host: &mut H) { *index = host.tload(interpreter.contract.address, *index); } -pub fn log(interpreter: &mut Interpreter, host: &mut H) { +pub fn log(interpreter: &mut Interpreter, host: &mut H) { check_staticcall!(interpreter); pop!(interpreter, offset, len); @@ -217,7 +217,7 @@ pub fn log(interpreter: &mut Interpreter, host: &mut H) host.log(interpreter.contract.address, topics, data); } -pub fn selfdestruct(interpreter: &mut Interpreter, host: &mut H) { +pub fn selfdestruct(interpreter: &mut Interpreter, host: &mut H) { check_staticcall!(interpreter); pop_address!(interpreter, target); @@ -236,7 +236,7 @@ pub fn selfdestruct(interpreter: &mut Interpreter, host: &m } #[inline(never)] -pub fn prepare_create_inputs( +pub fn prepare_create_inputs( interpreter: &mut Interpreter, host: &mut H, create_inputs: &mut Option>, @@ -304,12 +304,12 @@ pub fn prepare_create_inputs( })); } -pub fn create( +pub fn create( interpreter: &mut Interpreter, host: &mut H, ) { let mut create_input: Option> = None; - prepare_create_inputs::(interpreter, host, &mut create_input); + prepare_create_inputs::(interpreter, host, &mut create_input); let Some(mut create_input) = create_input else { return; @@ -349,24 +349,24 @@ pub fn create( } } -pub fn call(interpreter: &mut Interpreter, host: &mut H) { - call_inner::(CallScheme::Call, interpreter, host); +pub fn call(interpreter: &mut Interpreter, host: &mut H) { + call_inner::(CallScheme::Call, interpreter, host); } -pub fn call_code(interpreter: &mut Interpreter, host: &mut H) { - call_inner::(CallScheme::CallCode, interpreter, host); +pub fn call_code(interpreter: &mut Interpreter, host: &mut H) { + call_inner::(CallScheme::CallCode, interpreter, host); } -pub fn delegate_call(interpreter: &mut Interpreter, host: &mut H) { - call_inner::(CallScheme::DelegateCall, interpreter, host); +pub fn delegate_call(interpreter: &mut Interpreter, host: &mut H) { + call_inner::(CallScheme::DelegateCall, interpreter, host); } -pub fn static_call(interpreter: &mut Interpreter, host: &mut H) { - call_inner::(CallScheme::StaticCall, interpreter, host); +pub fn static_call(interpreter: &mut Interpreter, host: &mut H) { + call_inner::(CallScheme::StaticCall, interpreter, host); } #[inline(never)] -fn prepare_call_inputs( +fn prepare_call_inputs( interpreter: &mut Interpreter, scheme: CallScheme, host: &mut H, @@ -504,7 +504,7 @@ fn prepare_call_inputs( })); } -pub fn call_inner( +pub fn call_inner( scheme: CallScheme, interpreter: &mut Interpreter, host: &mut H, @@ -521,7 +521,7 @@ pub fn call_inner( let mut out_offset: usize = 0; let mut out_len: usize = 0; let mut call_input: Option> = None; - prepare_call_inputs::( + prepare_call_inputs::( interpreter, scheme, host, diff --git a/crates/interpreter/src/instructions/host_env.rs b/crates/interpreter/src/instructions/host_env.rs index cce993bac6..61f2764d3d 100644 --- a/crates/interpreter/src/instructions/host_env.rs +++ b/crates/interpreter/src/instructions/host_env.rs @@ -5,7 +5,7 @@ use crate::{ }; /// EIP-1344: ChainID opcode -pub fn chainid(interpreter: &mut Interpreter, host: &mut H) { +pub fn chainid(interpreter: &mut Interpreter, host: &mut H) { check!(interpreter, ISTANBUL); gas!(interpreter, gas::BASE); push!(interpreter, U256::from(host.env().cfg.chain_id)); @@ -26,7 +26,7 @@ pub fn number(interpreter: &mut Interpreter, host: &mut H) { push!(interpreter, host.env().block.number); } -pub fn difficulty(interpreter: &mut Interpreter, host: &mut H) { +pub fn difficulty(interpreter: &mut Interpreter, host: &mut H) { gas!(interpreter, gas::BASE); if SPEC::enabled(MERGE) { push_b256!(interpreter, host.env().block.prevrandao.unwrap()); @@ -46,7 +46,7 @@ pub fn gasprice(interpreter: &mut Interpreter, host: &mut H) { } /// EIP-3198: BASEFEE opcode -pub fn basefee(interpreter: &mut Interpreter, host: &mut H) { +pub fn basefee(interpreter: &mut Interpreter, host: &mut H) { check!(interpreter, LONDON); gas!(interpreter, gas::BASE); push!(interpreter, host.env().block.basefee); @@ -58,7 +58,7 @@ pub fn origin(interpreter: &mut Interpreter, host: &mut H) { } // EIP-4844: Shard Blob Transactions -pub fn blob_hash(interpreter: &mut Interpreter, host: &mut H) { +pub fn blob_hash(interpreter: &mut Interpreter, host: &mut H) { check!(interpreter, CANCUN); gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, index); @@ -70,7 +70,7 @@ pub fn blob_hash(interpreter: &mut Interpreter, host: &mut } /// EIP-7516: BLOBBASEFEE opcode -pub fn blob_basefee(interpreter: &mut Interpreter, host: &mut H) { +pub fn blob_basefee(interpreter: &mut Interpreter, host: &mut H) { check!(interpreter, CANCUN); gas!(interpreter, gas::BASE); push!( diff --git a/crates/interpreter/src/instructions/memory.rs b/crates/interpreter/src/instructions/memory.rs index ec3a9bbabb..b9fac4f46a 100644 --- a/crates/interpreter/src/instructions/memory.rs +++ b/crates/interpreter/src/instructions/memory.rs @@ -38,7 +38,7 @@ pub fn msize(interpreter: &mut Interpreter, _host: &mut H) { } // EIP-5656: MCOPY - Memory copying instruction -pub fn mcopy(interpreter: &mut Interpreter, _host: &mut H) { +pub fn mcopy(interpreter: &mut Interpreter, _host: &mut H) { check!(interpreter, CANCUN); pop!(interpreter, dst, src, len); diff --git a/crates/interpreter/src/instructions/opcode.rs b/crates/interpreter/src/instructions/opcode.rs index 61ef794b51..2e971b77a9 100644 --- a/crates/interpreter/src/instructions/opcode.rs +++ b/crates/interpreter/src/instructions/opcode.rs @@ -6,11 +6,44 @@ use crate::{ primitives::{Spec, SpecId}, Host, Interpreter, }; +use alloc::boxed::Box; +use alloc::sync::Arc; use core::fmt; -/// EVM opcode function signature. pub type Instruction = fn(&mut Interpreter, &mut H); +pub type InstructionTable = [Instruction; 256]; + +/// Arc over plain instruction table +pub type InstructionTableArc = Arc>; + +/// EVM opcode function signature. +pub type BoxedInstruction<'a, H> = Box; + +/// A table of instructions. +pub type BoxedInstructionTable<'a, H> = [BoxedInstruction<'a, H>; 256]; + +/// Arc over instruction table +pub type BoxedInstructionTableArc<'a, H> = Arc>; + +/// Instruction set that contains plain instruction table that contains simple `fn` function pointer. +/// and Boxed `Fn` variant that contains `Box` function pointer. +#[derive(Clone)] +pub enum InstructionTables<'a, H> { + Plain(InstructionTableArc), + Boxed(BoxedInstructionTableArc<'a, H>), +} + +impl<'a, H> InstructionTables<'a, H> { + pub fn new_plain(table: InstructionTableArc) -> Self { + Self::Plain(table) + } + + pub fn new_boxed(table: BoxedInstructionTableArc<'a, H>) -> Self { + Self::Boxed(table) + } +} + macro_rules! opcodes { ($($val:literal => $name:ident => $f:expr),* $(,)?) => { // Constants for each opcode. This also takes care of duplicate names. @@ -33,43 +66,47 @@ macro_rules! opcodes { map }; - // Requires `inline_const` and `const_mut_refs` unstable features, - // but provides ~+2% extra performance. - // See: https://github.com/bluealloy/revm/issues/310#issuecomment-1664381513 - /* - type InstructionTable = [Instruction; 256]; - - const fn make_instruction_table() -> InstructionTable { - let mut table: InstructionTable = [control::not_found; 256]; - let mut i = 0usize; - while i < 256 { - table[i] = match i as u8 { - $($name => $f,)* - _ => control::not_found, - }; - i += 1; + /// Return the instruction function for the given opcode and spec. + pub fn instruction(opcode: u8) -> Instruction { + match opcode { + $($name => $f,)* + _ => control::not_found, } - table } - // in `eval`: - (const { make_instruction_table::() })[opcode as usize](interpreter, host) - */ - - /// Evaluates the opcode in the given context. - #[inline(always)] - pub fn eval(opcode: u8, interpreter: &mut Interpreter, host: &mut H) { - // See https://github.com/bluealloy/revm/issues/310#issuecomment-1664381513 - // for previous efforts on optimizing this function. - let f: Instruction = match opcode { - $($name => $f as Instruction,)* - _ => control::not_found as Instruction, - }; - f(interpreter, host); - } }; } +pub fn boxed_instruction<'a, SPEC: Spec, H: Host + 'a>(opcode: u8) -> BoxedInstruction<'a, H> { + let instruction = instruction::(opcode); + Box::new(instruction) +} + +/// Make instruction talbe +pub fn make_instruction_table() -> InstructionTable { + let mut table: InstructionTable = + core::array::from_fn(|_| control::not_found:: as Instruction); + let mut i = 0; + while i < 256 { + table[i] = instruction::(i as u8); + i += 1; + } + table +} + +/// Make instruction talbe +pub fn make_boxed_instruction_table<'a, SPEC: Spec, H: Host + 'a>() -> BoxedInstructionTable<'a, H> +{ + let mut table: BoxedInstructionTable = + core::array::from_fn(|_| Box::new(control::not_found::) as BoxedInstruction<'a, H>); + let mut i = 0; + while i < 256 { + table[i] = boxed_instruction::(i as u8); + i += 1; + } + table +} + // When adding new opcodes: // 1. add the opcode to the list below; make sure it's sorted by opcode value // 2. add its gas info in the `opcode_gas_info` function below @@ -87,7 +124,7 @@ opcodes! { 0x07 => SMOD => arithmetic::smod, 0x08 => ADDMOD => arithmetic::addmod, 0x09 => MULMOD => arithmetic::mulmod, - 0x0A => EXP => arithmetic::exp::, + 0x0A => EXP => arithmetic::exp::, 0x0B => SIGNEXTEND => arithmetic::signextend, // 0x0C // 0x0D @@ -104,9 +141,9 @@ opcodes! { 0x18 => XOR => bitwise::bitxor, 0x19 => NOT => bitwise::not, 0x1A => BYTE => bitwise::byte, - 0x1B => SHL => bitwise::shl::, - 0x1C => SHR => bitwise::shr::, - 0x1D => SAR => bitwise::sar::, + 0x1B => SHL => bitwise::shl::, + 0x1C => SHR => bitwise::shr::, + 0x1D => SAR => bitwise::sar::, // 0x1E // 0x1F 0x20 => KECCAK256 => system::keccak256, @@ -126,7 +163,7 @@ opcodes! { // 0x2E // 0x2F 0x30 => ADDRESS => system::address, - 0x31 => BALANCE => host::balance::, + 0x31 => BALANCE => host::balance::, 0x32 => ORIGIN => host_env::origin, 0x33 => CALLER => system::caller, 0x34 => CALLVALUE => system::callvalue, @@ -137,22 +174,22 @@ opcodes! { 0x39 => CODECOPY => system::codecopy, 0x3A => GASPRICE => host_env::gasprice, - 0x3B => EXTCODESIZE => host::extcodesize::, - 0x3C => EXTCODECOPY => host::extcodecopy::, - 0x3D => RETURNDATASIZE => system::returndatasize::, - 0x3E => RETURNDATACOPY => system::returndatacopy::, - 0x3F => EXTCODEHASH => host::extcodehash::, + 0x3B => EXTCODESIZE => host::extcodesize::, + 0x3C => EXTCODECOPY => host::extcodecopy::, + 0x3D => RETURNDATASIZE => system::returndatasize::, + 0x3E => RETURNDATACOPY => system::returndatacopy::, + 0x3F => EXTCODEHASH => host::extcodehash::, 0x40 => BLOCKHASH => host::blockhash, 0x41 => COINBASE => host_env::coinbase, 0x42 => TIMESTAMP => host_env::timestamp, 0x43 => NUMBER => host_env::number, - 0x44 => DIFFICULTY => host_env::difficulty::, + 0x44 => DIFFICULTY => host_env::difficulty::, 0x45 => GASLIMIT => host_env::gaslimit, - 0x46 => CHAINID => host_env::chainid::, - 0x47 => SELFBALANCE => host::selfbalance::, - 0x48 => BASEFEE => host_env::basefee::, - 0x49 => BLOBHASH => host_env::blob_hash::, - 0x4A => BLOBBASEFEE => host_env::blob_basefee::, + 0x46 => CHAINID => host_env::chainid::, + 0x47 => SELFBALANCE => host::selfbalance::, + 0x48 => BASEFEE => host_env::basefee::, + 0x49 => BLOBHASH => host_env::blob_hash::, + 0x4A => BLOBBASEFEE => host_env::blob_basefee::, // 0x4B // 0x4C // 0x4D @@ -162,91 +199,91 @@ opcodes! { 0x51 => MLOAD => memory::mload, 0x52 => MSTORE => memory::mstore, 0x53 => MSTORE8 => memory::mstore8, - 0x54 => SLOAD => host::sload::, - 0x55 => SSTORE => host::sstore::, + 0x54 => SLOAD => host::sload::, + 0x55 => SSTORE => host::sstore::, 0x56 => JUMP => control::jump, 0x57 => JUMPI => control::jumpi, 0x58 => PC => control::pc, 0x59 => MSIZE => memory::msize, 0x5A => GAS => system::gas, 0x5B => JUMPDEST => control::jumpdest, - 0x5C => TLOAD => host::tload::, - 0x5D => TSTORE => host::tstore::, - 0x5E => MCOPY => memory::mcopy::, - - 0x5F => PUSH0 => stack::push0::, - 0x60 => PUSH1 => stack::push::, - 0x61 => PUSH2 => stack::push::, - 0x62 => PUSH3 => stack::push::, - 0x63 => PUSH4 => stack::push::, - 0x64 => PUSH5 => stack::push::, - 0x65 => PUSH6 => stack::push::, - 0x66 => PUSH7 => stack::push::, - 0x67 => PUSH8 => stack::push::, - 0x68 => PUSH9 => stack::push::, - 0x69 => PUSH10 => stack::push::, - 0x6A => PUSH11 => stack::push::, - 0x6B => PUSH12 => stack::push::, - 0x6C => PUSH13 => stack::push::, - 0x6D => PUSH14 => stack::push::, - 0x6E => PUSH15 => stack::push::, - 0x6F => PUSH16 => stack::push::, - 0x70 => PUSH17 => stack::push::, - 0x71 => PUSH18 => stack::push::, - 0x72 => PUSH19 => stack::push::, - 0x73 => PUSH20 => stack::push::, - 0x74 => PUSH21 => stack::push::, - 0x75 => PUSH22 => stack::push::, - 0x76 => PUSH23 => stack::push::, - 0x77 => PUSH24 => stack::push::, - 0x78 => PUSH25 => stack::push::, - 0x79 => PUSH26 => stack::push::, - 0x7A => PUSH27 => stack::push::, - 0x7B => PUSH28 => stack::push::, - 0x7C => PUSH29 => stack::push::, - 0x7D => PUSH30 => stack::push::, - 0x7E => PUSH31 => stack::push::, - 0x7F => PUSH32 => stack::push::, - - 0x80 => DUP1 => stack::dup::, - 0x81 => DUP2 => stack::dup::, - 0x82 => DUP3 => stack::dup::, - 0x83 => DUP4 => stack::dup::, - 0x84 => DUP5 => stack::dup::, - 0x85 => DUP6 => stack::dup::, - 0x86 => DUP7 => stack::dup::, - 0x87 => DUP8 => stack::dup::, - 0x88 => DUP9 => stack::dup::, - 0x89 => DUP10 => stack::dup::, - 0x8A => DUP11 => stack::dup::, - 0x8B => DUP12 => stack::dup::, - 0x8C => DUP13 => stack::dup::, - 0x8D => DUP14 => stack::dup::, - 0x8E => DUP15 => stack::dup::, - 0x8F => DUP16 => stack::dup::, - - 0x90 => SWAP1 => stack::swap::, - 0x91 => SWAP2 => stack::swap::, - 0x92 => SWAP3 => stack::swap::, - 0x93 => SWAP4 => stack::swap::, - 0x94 => SWAP5 => stack::swap::, - 0x95 => SWAP6 => stack::swap::, - 0x96 => SWAP7 => stack::swap::, - 0x97 => SWAP8 => stack::swap::, - 0x98 => SWAP9 => stack::swap::, - 0x99 => SWAP10 => stack::swap::, - 0x9A => SWAP11 => stack::swap::, - 0x9B => SWAP12 => stack::swap::, - 0x9C => SWAP13 => stack::swap::, - 0x9D => SWAP14 => stack::swap::, - 0x9E => SWAP15 => stack::swap::, - 0x9F => SWAP16 => stack::swap::, - - 0xA0 => LOG0 => host::log::, - 0xA1 => LOG1 => host::log::, - 0xA2 => LOG2 => host::log::, - 0xA3 => LOG3 => host::log::, - 0xA4 => LOG4 => host::log::, + 0x5C => TLOAD => host::tload::, + 0x5D => TSTORE => host::tstore::, + 0x5E => MCOPY => memory::mcopy::, + + 0x5F => PUSH0 => stack::push0::, + 0x60 => PUSH1 => stack::push::<1, H>, + 0x61 => PUSH2 => stack::push::<2, H>, + 0x62 => PUSH3 => stack::push::<3, H>, + 0x63 => PUSH4 => stack::push::<4, H>, + 0x64 => PUSH5 => stack::push::<5, H>, + 0x65 => PUSH6 => stack::push::<6, H>, + 0x66 => PUSH7 => stack::push::<7, H>, + 0x67 => PUSH8 => stack::push::<8, H>, + 0x68 => PUSH9 => stack::push::<9, H>, + 0x69 => PUSH10 => stack::push::<10, H>, + 0x6A => PUSH11 => stack::push::<11, H>, + 0x6B => PUSH12 => stack::push::<12, H>, + 0x6C => PUSH13 => stack::push::<13, H>, + 0x6D => PUSH14 => stack::push::<14, H>, + 0x6E => PUSH15 => stack::push::<15, H>, + 0x6F => PUSH16 => stack::push::<16, H>, + 0x70 => PUSH17 => stack::push::<17, H>, + 0x71 => PUSH18 => stack::push::<18, H>, + 0x72 => PUSH19 => stack::push::<19, H>, + 0x73 => PUSH20 => stack::push::<20, H>, + 0x74 => PUSH21 => stack::push::<21, H>, + 0x75 => PUSH22 => stack::push::<22, H>, + 0x76 => PUSH23 => stack::push::<23, H>, + 0x77 => PUSH24 => stack::push::<24, H>, + 0x78 => PUSH25 => stack::push::<25, H>, + 0x79 => PUSH26 => stack::push::<26, H>, + 0x7A => PUSH27 => stack::push::<27, H>, + 0x7B => PUSH28 => stack::push::<28, H>, + 0x7C => PUSH29 => stack::push::<29, H>, + 0x7D => PUSH30 => stack::push::<30, H>, + 0x7E => PUSH31 => stack::push::<31, H>, + 0x7F => PUSH32 => stack::push::<32, H>, + + 0x80 => DUP1 => stack::dup::<1, H>, + 0x81 => DUP2 => stack::dup::<2, H>, + 0x82 => DUP3 => stack::dup::<3, H>, + 0x83 => DUP4 => stack::dup::<4, H>, + 0x84 => DUP5 => stack::dup::<5, H>, + 0x85 => DUP6 => stack::dup::<6, H>, + 0x86 => DUP7 => stack::dup::<7, H>, + 0x87 => DUP8 => stack::dup::<8, H>, + 0x88 => DUP9 => stack::dup::<9, H>, + 0x89 => DUP10 => stack::dup::<10, H>, + 0x8A => DUP11 => stack::dup::<11, H>, + 0x8B => DUP12 => stack::dup::<12, H>, + 0x8C => DUP13 => stack::dup::<13, H>, + 0x8D => DUP14 => stack::dup::<14, H>, + 0x8E => DUP15 => stack::dup::<15, H>, + 0x8F => DUP16 => stack::dup::<16, H>, + + 0x90 => SWAP1 => stack::swap::<1, H>, + 0x91 => SWAP2 => stack::swap::<2, H>, + 0x92 => SWAP3 => stack::swap::<3, H>, + 0x93 => SWAP4 => stack::swap::<4, H>, + 0x94 => SWAP5 => stack::swap::<5, H>, + 0x95 => SWAP6 => stack::swap::<6, H>, + 0x96 => SWAP7 => stack::swap::<7, H>, + 0x97 => SWAP8 => stack::swap::<8, H>, + 0x98 => SWAP9 => stack::swap::<9, H>, + 0x99 => SWAP10 => stack::swap::<10, H>, + 0x9A => SWAP11 => stack::swap::<11, H>, + 0x9B => SWAP12 => stack::swap::<12, H>, + 0x9C => SWAP13 => stack::swap::<13, H>, + 0x9D => SWAP14 => stack::swap::<14, H>, + 0x9E => SWAP15 => stack::swap::<15, H>, + 0x9F => SWAP16 => stack::swap::<16, H>, + + 0xA0 => LOG0 => host::log::<0, H>, + 0xA1 => LOG1 => host::log::<1, H>, + 0xA2 => LOG2 => host::log::<2, H>, + 0xA3 => LOG3 => host::log::<3, H>, + 0xA4 => LOG4 => host::log::<4, H>, // 0xA5 // 0xA6 // 0xA7 @@ -322,22 +359,22 @@ opcodes! { // 0xED // 0xEE // 0xEF - 0xF0 => CREATE => host::create::, - 0xF1 => CALL => host::call::, - 0xF2 => CALLCODE => host::call_code::, + 0xF0 => CREATE => host::create::, + 0xF1 => CALL => host::call::, + 0xF2 => CALLCODE => host::call_code::, 0xF3 => RETURN => control::ret, - 0xF4 => DELEGATECALL => host::delegate_call::, - 0xF5 => CREATE2 => host::create::, + 0xF4 => DELEGATECALL => host::delegate_call::, + 0xF5 => CREATE2 => host::create::, // 0xF6 // 0xF7 // 0xF8 // 0xF9 - 0xFA => STATICCALL => host::static_call::, + 0xFA => STATICCALL => host::static_call::, // 0xFB // 0xFC - 0xFD => REVERT => control::revert::, + 0xFD => REVERT => control::revert::, 0xFE => INVALID => control::invalid, - 0xFF => SELFDESTRUCT => host::selfdestruct::, + 0xFF => SELFDESTRUCT => host::selfdestruct::, } /// An EVM opcode. diff --git a/crates/interpreter/src/instructions/stack.rs b/crates/interpreter/src/instructions/stack.rs index 5387d7001d..c25f3cac83 100644 --- a/crates/interpreter/src/instructions/stack.rs +++ b/crates/interpreter/src/instructions/stack.rs @@ -14,7 +14,7 @@ pub fn pop(interpreter: &mut Interpreter, _host: &mut H) { /// EIP-3855: PUSH0 instruction /// /// Introduce a new instruction which pushes the constant value 0 onto the stack. -pub fn push0(interpreter: &mut Interpreter, _host: &mut H) { +pub fn push0(interpreter: &mut Interpreter, _host: &mut H) { check!(interpreter, SHANGHAI); gas!(interpreter, gas::BASE); if let Err(result) = interpreter.stack.push(U256::ZERO) { @@ -22,7 +22,7 @@ pub fn push0(interpreter: &mut Interpreter, _host: &mut H) } } -pub fn push(interpreter: &mut Interpreter, _host: &mut H) { +pub fn push(interpreter: &mut Interpreter, _host: &mut H) { gas!(interpreter, gas::VERYLOW); let start = interpreter.instruction_pointer; // Safety: In Analysis we appended needed bytes for bytecode so that we are safe to just add without @@ -37,14 +37,14 @@ pub fn push(interpreter: &mut Interpreter, _host: &mut interpreter.instruction_pointer = unsafe { start.add(N) }; } -pub fn dup(interpreter: &mut Interpreter, _host: &mut H) { +pub fn dup(interpreter: &mut Interpreter, _host: &mut H) { gas!(interpreter, gas::VERYLOW); if let Err(result) = interpreter.stack.dup::() { interpreter.instruction_result = result; } } -pub fn swap(interpreter: &mut Interpreter, _host: &mut H) { +pub fn swap(interpreter: &mut Interpreter, _host: &mut H) { gas!(interpreter, gas::VERYLOW); if let Err(result) = interpreter.stack.swap::() { interpreter.instruction_result = result; diff --git a/crates/interpreter/src/instructions/system.rs b/crates/interpreter/src/instructions/system.rs index e4976058ed..7be6eae1bf 100644 --- a/crates/interpreter/src/instructions/system.rs +++ b/crates/interpreter/src/instructions/system.rs @@ -98,7 +98,7 @@ pub fn calldatacopy(interpreter: &mut Interpreter, _host: &mut H) { } /// EIP-211: New opcodes: RETURNDATASIZE and RETURNDATACOPY -pub fn returndatasize(interpreter: &mut Interpreter, _host: &mut H) { +pub fn returndatasize(interpreter: &mut Interpreter, _host: &mut H) { check!(interpreter, BYZANTIUM); gas!(interpreter, gas::BASE); push!( @@ -108,7 +108,7 @@ pub fn returndatasize(interpreter: &mut Interpreter, _host: } /// EIP-211: New opcodes: RETURNDATASIZE and RETURNDATACOPY -pub fn returndatacopy(interpreter: &mut Interpreter, _host: &mut H) { +pub fn returndatacopy(interpreter: &mut Interpreter, _host: &mut H) { check!(interpreter, BYZANTIUM); pop!(interpreter, memory_offset, offset, len); let len = as_usize_or_fail!(interpreter, len); diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index f274b5cb54..b148362450 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -3,8 +3,8 @@ mod contract; mod memory; mod stack; -use crate::primitives::{Bytes, Spec}; -use crate::{alloc::boxed::Box, opcode::eval, Gas, Host, InstructionResult}; +use crate::primitives::Bytes; +use crate::{alloc::boxed::Box, Gas, Host, InstructionResult}; pub use analysis::BytecodeLocked; pub use contract::Contract; @@ -126,41 +126,33 @@ impl Interpreter { /// Executes the instruction at the current instruction pointer. #[inline(always)] - pub fn step(&mut self, host: &mut H) { - // step. + pub fn step(&mut self, instruction_table: &[FN; 256], host: &mut H) + where + FN: Fn(&mut Interpreter, &mut H), + { + // Get current opcode. let opcode = unsafe { *self.instruction_pointer }; + // Safety: In analysis we are doing padding of bytecode so that we are sure that last // byte instruction is STOP so we are safe to just increment program_counter bcs on last instruction // it will do noop and just stop execution of this contract self.instruction_pointer = unsafe { self.instruction_pointer.offset(1) }; - eval::(opcode, self, host); - } - /// Executes the interpreter until it returns or stops. - pub fn run(&mut self, host: &mut H) -> InstructionResult { - while self.instruction_result == InstructionResult::Continue { - self.step::(host); - } - self.instruction_result + // execute instruction. + (instruction_table[opcode as usize])(self, host) } - /// Executes the interpreter until it returns or stops. Same as `run` but with - /// calls to the [`Host::step`] and [`Host::step_end`] callbacks. - pub fn run_inspect(&mut self, host: &mut H) -> InstructionResult { + /// Executes the interpreter until it returns or stops. + pub fn run( + &mut self, + instruction_table: &[FN; 256], + host: &mut H, + ) -> InstructionResult + where + FN: Fn(&mut Interpreter, &mut H), + { while self.instruction_result == InstructionResult::Continue { - // step - let result = host.step(self); - if result != InstructionResult::Continue { - return result; - } - - self.step::(host); - - // step ends - let result = host.step_end(self, self.instruction_result); - if result != InstructionResult::Continue { - return result; - } + self.step(instruction_table, host); } self.instruction_result } diff --git a/crates/revm/benches/bench.rs b/crates/revm/benches/bench.rs index 37056277f9..ebfb111e19 100644 --- a/crates/revm/benches/bench.rs +++ b/crates/revm/benches/bench.rs @@ -8,6 +8,7 @@ use revm::{ address, bytes, hex, BerlinSpec, Bytecode, BytecodeState, Bytes, TransactTo, U256, }, }; +use revm_interpreter::opcode::make_instruction_table; use std::time::Duration; type Evm = revm::EVM; @@ -53,8 +54,8 @@ fn snailtracer(c: &mut Criterion) { let mut g = c.benchmark_group("snailtracer"); g.noise_threshold(0.03) - .warm_up_time(Duration::from_secs(3)) - .measurement_time(Duration::from_secs(10)) + .warm_up_time(Duration::from_secs(1)) + .measurement_time(Duration::from_secs(3)) .sample_size(10); bench_transact(&mut g, &mut evm); bench_eval(&mut g, &evm); @@ -93,9 +94,10 @@ fn bench_eval(g: &mut BenchmarkGroup<'_, WallTime>, evm: &Evm) { ..Default::default() }; let mut host = DummyHost::new(evm.env.clone()); + let instruction_table = make_instruction_table::(); b.iter(|| { let mut interpreter = Interpreter::new(Box::new(contract.clone()), u64::MAX, false); - let res = interpreter.run::<_, BerlinSpec>(&mut host); + let res = interpreter.run(&instruction_table, &mut host); host.clear(); res }) diff --git a/crates/revm/src/db/ethersdb.rs b/crates/revm/src/db/ethersdb.rs index 3a755ec945..0a403afa51 100644 --- a/crates/revm/src/db/ethersdb.rs +++ b/crates/revm/src/db/ethersdb.rs @@ -153,7 +153,7 @@ mod tests { .unwrap(); let client = Arc::new(client); - let mut ethersdb = EthersDB::new( + let ethersdb = EthersDB::new( Arc::clone(&client), // public infura mainnet Some(BlockId::from(16148323)), ) @@ -179,7 +179,7 @@ mod tests { .unwrap(); let client = Arc::new(client); - let mut ethersdb = EthersDB::new( + let ethersdb = EthersDB::new( Arc::clone(&client), // public infura mainnet Some(BlockId::from(16148323)), ) @@ -210,7 +210,7 @@ mod tests { .unwrap(); let client = Arc::new(client); - let mut ethersdb = EthersDB::new( + let ethersdb = EthersDB::new( Arc::clone(&client), // public infura mainnet None, ) diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 5c98d142bd..61f4003742 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -2,7 +2,6 @@ use crate::primitives::{specification, EVMError, EVMResult, Env, ExecutionResult use crate::{ db::{Database, DatabaseCommit, DatabaseRef}, evm_impl::{EVMImpl, Transact}, - inspectors::NoOpInspector, Inspector, }; use alloc::boxed::Box; @@ -77,7 +76,7 @@ impl EVM { /// Do checks that could make transaction fail before call/create pub fn preverify_transaction(&mut self) -> Result<(), EVMError> { if let Some(db) = self.db.as_mut() { - evm_inner::(&mut self.env, db, &mut NoOpInspector).preverify_transaction() + evm_inner::(&mut self.env, db, None).preverify_transaction() } else { panic!("Database needs to be set"); } @@ -87,7 +86,7 @@ impl EVM { /// state. pub fn transact_preverified(&mut self) -> EVMResult { if let Some(db) = self.db.as_mut() { - evm_inner::(&mut self.env, db, &mut NoOpInspector).transact_preverified() + evm_inner::(&mut self.env, db, None).transact_preverified() } else { panic!("Database needs to be set"); } @@ -96,7 +95,7 @@ impl EVM { /// Execute transaction without writing to DB, return change state. pub fn transact(&mut self) -> EVMResult { if let Some(db) = self.db.as_mut() { - evm_inner::(&mut self.env, db, &mut NoOpInspector).transact() + evm_inner::(&mut self.env, db, None).transact() } else { panic!("Database needs to be set"); } @@ -105,7 +104,7 @@ impl EVM { /// Execute transaction with given inspector, without wring to DB. Return change state. pub fn inspect>(&mut self, mut inspector: INSP) -> EVMResult { if let Some(db) = self.db.as_mut() { - evm_inner::(&mut self.env, db, &mut inspector).transact() + evm_inner::(&mut self.env, db, Some(&mut inspector)).transact() } else { panic!("Database needs to be set"); } @@ -116,12 +115,8 @@ impl<'a, DB: DatabaseRef> EVM { /// Do checks that could make transaction fail before call/create pub fn preverify_transaction_ref(&self) -> Result<(), EVMError> { if let Some(db) = self.db.as_ref() { - evm_inner::<_, false>( - &mut self.env.clone(), - &mut WrapDatabaseRef(db), - &mut NoOpInspector, - ) - .preverify_transaction() + evm_inner::<_>(&mut self.env.clone(), &mut WrapDatabaseRef(db), None) + .preverify_transaction() } else { panic!("Database needs to be set"); } @@ -131,12 +126,8 @@ impl<'a, DB: DatabaseRef> EVM { /// without writing to DB, return change state. pub fn transact_preverified_ref(&self) -> EVMResult { if let Some(db) = self.db.as_ref() { - evm_inner::<_, false>( - &mut self.env.clone(), - &mut WrapDatabaseRef(db), - &mut NoOpInspector, - ) - .transact_preverified() + evm_inner::<_>(&mut self.env.clone(), &mut WrapDatabaseRef(db), None) + .transact_preverified() } else { panic!("Database needs to be set"); } @@ -145,12 +136,7 @@ impl<'a, DB: DatabaseRef> EVM { /// Execute transaction without writing to DB, return change state. pub fn transact_ref(&self) -> EVMResult { if let Some(db) = self.db.as_ref() { - evm_inner::<_, false>( - &mut self.env.clone(), - &mut WrapDatabaseRef(db), - &mut NoOpInspector, - ) - .transact() + evm_inner::<_>(&mut self.env.clone(), &mut WrapDatabaseRef(db), None).transact() } else { panic!("Database needs to be set"); } @@ -162,10 +148,10 @@ impl<'a, DB: DatabaseRef> EVM { mut inspector: I, ) -> EVMResult { if let Some(db) = self.db.as_ref() { - evm_inner::<_, true>( + evm_inner::<_>( &mut self.env.clone(), &mut WrapDatabaseRef(db), - &mut inspector, + Some(&mut inspector), ) .transact() } else { @@ -198,14 +184,14 @@ impl EVM { } } -pub fn evm_inner<'a, DB: Database, const INSPECT: bool>( +pub fn evm_inner<'a, DB: Database>( env: &'a mut Env, db: &'a mut DB, - insp: &'a mut dyn Inspector, + insp: Option<&'a mut dyn Inspector>, ) -> Box + 'a> { macro_rules! create_evm { ($spec:ident) => { - Box::new(EVMImpl::<'a, $spec, DB, INSPECT>::new( + Box::new(EVMImpl::<'a, $spec, DB>::new( db, env, insp, diff --git a/crates/revm/src/evm_impl.rs b/crates/revm/src/evm_impl.rs index e8141d71f9..a66d272825 100644 --- a/crates/revm/src/evm_impl.rs +++ b/crates/revm/src/evm_impl.rs @@ -5,15 +5,18 @@ use crate::interpreter::{ SuccessOrHalt, Transfer, }; use crate::journaled_state::{is_precompile, JournalCheckpoint}; +use crate::make_inspector_instruction_table; use crate::primitives::{ keccak256, Address, AnalysisKind, Bytecode, Bytes, EVMError, EVMResult, Env, ExecutionResult, InvalidTransaction, Log, Output, ResultAndState, Spec, SpecId::*, TransactTo, B256, U256, }; use crate::{db::Database, journaled_state::JournaledState, precompile, Inspector}; use alloc::boxed::Box; +use alloc::sync::Arc; use alloc::vec::Vec; use core::marker::PhantomData; use revm_interpreter::gas::initial_tx_gas; +use revm_interpreter::opcode::{make_instruction_table, InstructionTables}; use revm_interpreter::MAX_CODE_SIZE; use revm_precompile::{Precompile, Precompiles}; @@ -34,10 +37,11 @@ pub struct EVMData<'a, DB: Database> { pub l1_block_info: Option, } -pub struct EVMImpl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> { - data: EVMData<'a, DB>, - inspector: &'a mut dyn Inspector, - handler: Handler, +pub struct EVMImpl<'a, GSPEC: Spec, DB: Database> { + pub data: EVMData<'a, DB>, + pub inspector: Option<&'a mut dyn Inspector>, + pub instruction_table: InstructionTables<'a, Self>, + pub handler: Handler, _phantomdata: PhantomData, } @@ -98,7 +102,7 @@ impl<'a, DB: Database> EVMData<'a, DB> { } #[cfg(feature = "optimism")] -impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, INSPECT> { +impl<'a, GSPEC: Spec, DB: Database> EVMImpl<'a, GSPEC, DB> { /// If the transaction is not a deposit transaction, subtract the L1 data fee from the /// caller's balance directly after minting the requested amount of ETH. fn remove_l1_cost( @@ -154,9 +158,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, } } -impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> Transact - for EVMImpl<'a, GSPEC, DB, INSPECT> -{ +impl<'a, GSPEC: Spec + 'static, DB: Database> Transact for EVMImpl<'a, GSPEC, DB> { fn preverify_transaction(&mut self) -> Result<(), EVMError> { let env = self.env(); @@ -248,7 +250,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> Transact #[cfg(feature = "optimism")] if self.data.env.cfg.optimism { - EVMImpl::::commit_mint_value( + EVMImpl::::commit_mint_value( tx_caller, self.data.env.tx.optimism.mint, self.data.db, @@ -256,7 +258,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> Transact )?; let is_deposit = self.data.env.tx.optimism.source_hash.is_some(); - EVMImpl::::remove_l1_cost( + EVMImpl::::remove_l1_cost( is_deposit, tx_caller, tx_l1_cost, @@ -396,14 +398,23 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> Transact } } -impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, INSPECT> { +impl<'a, GSPEC: Spec + 'static, DB: Database> EVMImpl<'a, GSPEC, DB> { pub fn new( db: &'a mut DB, env: &'a mut Env, - inspector: &'a mut dyn Inspector, + inspector: Option<&'a mut dyn Inspector>, precompiles: Precompiles, ) -> Self { let journaled_state = JournaledState::new(precompiles.len(), GSPEC::SPEC_ID); + let instruction_table = if inspector.is_some() { + let instruction_table = make_inspector_instruction_table::( + make_instruction_table::(), + ); + InstructionTables::Boxed(Arc::new(instruction_table)) + } else { + InstructionTables::Plain(Arc::new(make_instruction_table::())) + }; + Self { data: EVMData { env, @@ -415,6 +426,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, l1_block_info: None, }, inspector, + instruction_table, handler: Handler::mainnet::(), _phantomdata: PhantomData {}, } @@ -652,14 +664,13 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, #[cfg(not(feature = "memory_limit"))] let mut interpreter = Box::new(Interpreter::new(contract, gas_limit, is_static)); - if INSPECT { - self.inspector - .initialize_interp(&mut interpreter, &mut self.data); + if let Some(inspector) = self.inspector.as_mut() { + inspector.initialize_interp(&mut interpreter, &mut self.data); } - let exit_reason = if INSPECT { - interpreter.run_inspect::(self) - } else { - interpreter.run::(self) + + let exit_reason = match &mut self.instruction_table { + InstructionTables::Plain(table) => interpreter.run::<_, Self>(&table.clone(), self), + InstructionTables::Boxed(table) => interpreter.run::<_, Self>(&table.clone(), self), }; (exit_reason, interpreter) @@ -821,17 +832,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, } } -impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host - for EVMImpl<'a, GSPEC, DB, INSPECT> -{ - fn step(&mut self, interp: &mut Interpreter) -> InstructionResult { - self.inspector.step(interp, &mut self.data) - } - - fn step_end(&mut self, interp: &mut Interpreter, ret: InstructionResult) -> InstructionResult { - self.inspector.step_end(interp, &mut self.data, ret) - } - +impl<'a, GSPEC: Spec + 'static, DB: Database> Host for EVMImpl<'a, GSPEC, DB> { fn env(&mut self) -> &mut Env { self.data.env } @@ -923,8 +924,8 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host } fn log(&mut self, address: Address, topics: Vec, data: Bytes) { - if INSPECT { - self.inspector.log(&mut self.data, &address, &topics, &data); + if let Some(inspector) = self.inspector.as_mut() { + inspector.log(&mut self.data, &address, &topics, &data); } let log = Log { address, @@ -935,10 +936,9 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host } fn selfdestruct(&mut self, address: Address, target: Address) -> Option { - if INSPECT { + if let Some(inspector) = self.inspector.as_mut() { let acc = self.data.journaled_state.state.get(&address).unwrap(); - self.inspector - .selfdestruct(address, target, acc.info.balance); + inspector.selfdestruct(address, target, acc.info.balance); } self.data .journaled_state @@ -952,17 +952,15 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host inputs: &mut CreateInputs, ) -> (InstructionResult, Option
, Gas, Bytes) { // Call inspector - if INSPECT { - let (ret, address, gas, out) = self.inspector.create(&mut self.data, inputs); + if let Some(inspector) = self.inspector.as_mut() { + let (ret, address, gas, out) = inspector.create(&mut self.data, inputs); if ret != InstructionResult::Continue { - return self - .inspector - .create_end(&mut self.data, inputs, ret, address, gas, out); + return inspector.create_end(&mut self.data, inputs, ret, address, gas, out); } } let ret = self.create_inner(inputs); - if INSPECT { - self.inspector.create_end( + if let Some(inspector) = self.inspector.as_mut() { + inspector.create_end( &mut self.data, inputs, ret.result, @@ -976,17 +974,15 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host } fn call(&mut self, inputs: &mut CallInputs) -> (InstructionResult, Gas, Bytes) { - if INSPECT { - let (ret, gas, out) = self.inspector.call(&mut self.data, inputs); + if let Some(inspector) = self.inspector.as_mut() { + let (ret, gas, out) = inspector.call(&mut self.data, inputs); if ret != InstructionResult::Continue { - return self - .inspector - .call_end(&mut self.data, inputs, gas, ret, out); + return inspector.call_end(&mut self.data, inputs, gas, ret, out); } } let ret = self.call_inner(inputs); - if INSPECT { - self.inspector.call_end( + if let Some(inspector) = self.inspector.as_mut() { + inspector.call_end( &mut self.data, inputs, ret.gas, @@ -1025,30 +1021,26 @@ mod tests { journal .initial_account_load(caller, &[U256::from(100)], &mut db) .unwrap(); - assert!( - EVMImpl::::commit_mint_value( - caller, - mint_value, - &mut db, - &mut journal - ) - .is_ok(), - ); + assert!(EVMImpl::::commit_mint_value( + caller, + mint_value, + &mut db, + &mut journal + ) + .is_ok(),); // Check the account balance is updated. let (account, _) = journal.load_account(caller, &mut db).unwrap(); assert_eq!(account.info.balance, U256::from(101)); // No mint value should be a no-op. - assert!( - EVMImpl::::commit_mint_value( - caller, - None, - &mut db, - &mut journal - ) - .is_ok(), - ); + assert!(EVMImpl::::commit_mint_value( + caller, + None, + &mut db, + &mut journal + ) + .is_ok(),); let (account, _) = journal.load_account(caller, &mut db).unwrap(); assert_eq!(account.info.balance, U256::from(101)); } @@ -1062,7 +1054,7 @@ mod tests { journal .initial_account_load(caller, slots, &mut db) .unwrap(); - assert!(EVMImpl::::remove_l1_cost( + assert!(EVMImpl::::remove_l1_cost( true, caller, U256::ZERO, @@ -1089,7 +1081,7 @@ mod tests { journal .initial_account_load(caller, &[U256::from(100)], &mut db) .unwrap(); - assert!(EVMImpl::::remove_l1_cost( + assert!(EVMImpl::::remove_l1_cost( false, caller, U256::from(1), @@ -1121,7 +1113,7 @@ mod tests { .initial_account_load(caller, &[U256::from(100)], &mut db) .unwrap(); assert_eq!( - EVMImpl::::remove_l1_cost( + EVMImpl::::remove_l1_cost( false, caller, U256::from(101), diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index f66cbfcb60..0989c6013a 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -8,8 +8,10 @@ mod customprinter; #[cfg(all(feature = "std", feature = "serde"))] mod eip3155; mod gas; +mod instruction; mod noop; +pub use instruction::{inspector_instruction, make_inspector_instruction_table}; /// [Inspector] implementations. pub mod inspectors { #[cfg(feature = "std")] @@ -76,11 +78,9 @@ pub trait Inspector { &mut self, interp: &mut Interpreter, data: &mut EVMData<'_, DB>, - eval: InstructionResult, ) -> InstructionResult { let _ = interp; let _ = data; - let _ = eval; InstructionResult::Continue } diff --git a/crates/revm/src/inspector/customprinter.rs b/crates/revm/src/inspector/customprinter.rs index d431cea583..da44f83ae4 100644 --- a/crates/revm/src/inspector/customprinter.rs +++ b/crates/revm/src/inspector/customprinter.rs @@ -51,9 +51,8 @@ impl Inspector for CustomPrintTracer { &mut self, interp: &mut Interpreter, data: &mut EVMData<'_, DB>, - eval: InstructionResult, ) -> InstructionResult { - self.gas_inspector.step_end(interp, data, eval); + self.gas_inspector.step_end(interp, data); InstructionResult::Continue } diff --git a/crates/revm/src/inspector/eip3155.rs b/crates/revm/src/inspector/eip3155.rs index 9346f73c28..62d492b021 100644 --- a/crates/revm/src/inspector/eip3155.rs +++ b/crates/revm/src/inspector/eip3155.rs @@ -71,9 +71,8 @@ impl Inspector for TracerEip3155 { &mut self, interp: &mut Interpreter, data: &mut EVMData<'_, DB>, - eval: InstructionResult, ) -> InstructionResult { - self.gas_inspector.step_end(interp, data, eval); + self.gas_inspector.step_end(interp, data); if self.skip { self.skip = false; return InstructionResult::Continue; diff --git a/crates/revm/src/inspector/gas.rs b/crates/revm/src/inspector/gas.rs index 22639a3edc..335b469669 100644 --- a/crates/revm/src/inspector/gas.rs +++ b/crates/revm/src/inspector/gas.rs @@ -38,7 +38,6 @@ impl Inspector for GasInspector { &mut self, interp: &mut crate::interpreter::Interpreter, _data: &mut EVMData<'_, DB>, - _eval: InstructionResult, ) -> InstructionResult { let last_gas = core::mem::replace(&mut self.gas_remaining, interp.gas.remaining()); self.last_gas_cost = last_gas.saturating_sub(self.last_gas_cost); @@ -122,12 +121,11 @@ mod tests { &mut self, interp: &mut Interpreter, data: &mut EVMData<'_, DB>, - eval: InstructionResult, ) -> InstructionResult { - self.gas_inspector.step_end(interp, data, eval); + self.gas_inspector.step_end(interp, data); self.gas_remaining_steps .push((self.pc, self.gas_inspector.gas_remaining())); - eval + interp.instruction_result } fn call( @@ -191,8 +189,8 @@ mod tests { #[cfg(not(feature = "optimism"))] fn test_gas_inspector() { use crate::db::BenchmarkDB; - use crate::interpreter::{opcode, OpCode}; - use crate::primitives::{address, Bytecode, Bytes, ResultAndState, TransactTo}; + use crate::interpreter::opcode; + use crate::primitives::{address, Bytecode, Bytes, TransactTo}; let contract_data: Bytes = Bytes::from(vec![ opcode::PUSH1, @@ -219,14 +217,22 @@ mod tests { evm.env.tx.gas_limit = 21100; let mut inspector = StackInspector::default(); - let ResultAndState { result, state } = evm.inspect(&mut inspector).unwrap(); - println!("{result:?} {state:?} {inspector:?}"); - - for (pc, gas) in inspector.gas_remaining_steps { - println!( - "{pc} {} {gas:?}", - OpCode::new(bytecode.bytes()[pc]).unwrap().as_str(), - ); - } + evm.inspect(&mut inspector).unwrap(); + + // starting from 100gas + let steps = vec![ + // push1 -3 + (0, 97), + // push1 -3 + (2, 94), + // jumpi -10 + (4, 84), + // jumpdest 1 + (11, 83), + // stop 0 + (12, 83), + ]; + + assert_eq!(inspector.gas_remaining_steps, steps); } } diff --git a/crates/revm/src/inspector/instruction.rs b/crates/revm/src/inspector/instruction.rs new file mode 100644 index 0000000000..2f540c21e1 --- /dev/null +++ b/crates/revm/src/inspector/instruction.rs @@ -0,0 +1,75 @@ +use alloc::boxed::Box; +use revm_interpreter::{ + instructions::control, + opcode::{BoxedInstruction, BoxedInstructionTable, Instruction, InstructionTable}, + primitives::{db::Database, Spec}, + InstructionResult, Interpreter, +}; + +use crate::EVMImpl; + +/// Wrap instruction that would call inspector. +pub fn inspector_instruction<'a, SPEC: Spec + 'static, DB: Database>( + instruction: Instruction>, +) -> BoxedInstruction<'a, EVMImpl<'a, SPEC, DB>> { + let inspector_instruction = Box::new( + move |interpreter: &mut Interpreter, host: &mut EVMImpl<'a, SPEC, DB>| { + // step + let data = &mut host.data; + // Safety: as the PC was already incremented we need to subtract 1 to preserve the + // old Inspector behavior. + unsafe { + interpreter.instruction_pointer = interpreter.instruction_pointer.sub(1); + } + if let Some(inspector) = host.inspector.as_mut() { + if inspector.step(interpreter, data) != InstructionResult::Continue { + return; + } + } + + // Safety: return PC to previous state + unsafe { + interpreter.instruction_pointer = interpreter.instruction_pointer.add(1); + } + + // execute instruction. + instruction(interpreter, host); + + // step ends + let data = &mut host.data; + if let Some(inspector) = host.inspector.as_mut() { + inspector.step_end(interpreter, data); + } + }, + ); + + inspector_instruction +} + +/// make inspector table +pub fn make_inspector_instruction_table<'a, SPEC: Spec + 'static, DB: Database>( + table: InstructionTable>, +) -> BoxedInstructionTable<'a, EVMImpl<'a, SPEC, DB>> { + let mut inspector_table: BoxedInstructionTable<'a, EVMImpl<'a, SPEC, DB>> = + core::array::from_fn(|_| inspector_instruction(control::not_found)); + + for (i, instruction) in table.iter().enumerate() { + inspector_table[i] = inspector_instruction(*instruction); + } + inspector_table +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{db::EmptyDB, interpreter::opcode::*, primitives::BerlinSpec, EVMImpl}; + + #[test] + fn test() { + // test that this pattern builds. + let inst: InstructionTable> = + make_instruction_table::>(); + let _test: BoxedInstructionTable<'_, EVMImpl<'_, BerlinSpec, _>> = + make_inspector_instruction_table(inst); + } +} diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index 4101eb372e..4a567d3f6e 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -19,13 +19,12 @@ pub mod optimism; compile_error!("`with-serde` feature has been renamed to `serde`."); pub(crate) const USE_GAS: bool = !cfg!(feature = "no_gas_measuring"); -pub type DummyStateDB = InMemoryDB; +pub type DummyStateDB = InMemoryDB; #[cfg(feature = "std")] pub use db::{ CacheState, DBBox, State, StateBuilder, StateDBBox, TransitionAccount, TransitionState, }; - pub use db::{Database, DatabaseCommit, DatabaseRef, InMemoryDB}; pub use evm::{evm_inner, new, EVM}; pub use evm_impl::{EVMData, EVMImpl, Transact, CALL_STACK_LIMIT}; @@ -45,7 +44,7 @@ pub use revm_interpreter::primitives; // reexport inspector implementations pub use inspector::inspectors; -pub use inspector::Inspector; +pub use inspector::{inspector_instruction, make_inspector_instruction_table, Inspector}; // export Optimism types, helpers, and constants #[cfg(feature = "optimism")] diff --git a/documentation/src/crates/revm/host_trait.md b/documentation/src/crates/revm/host_trait.md index ba4c7be726..4abf291f5d 100644 --- a/documentation/src/crates/revm/host_trait.md +++ b/documentation/src/crates/revm/host_trait.md @@ -38,7 +38,7 @@ The [`EVMImpl`](./evm_impl.md) struct implements this `Host` trait. - `tload` & `tstore` - As defined in [EIP1153](https://eips.ethereum.org/EIPS/eip-1153), for transiant storage reads and writes. + As defined in [EIP1153](https://eips.ethereum.org/EIPS/eip-1153), for transient storage reads and writes. - `log` @@ -46,12 +46,12 @@ The [`EVMImpl`](./evm_impl.md) struct implements this `Host` trait. - `selfdestruct` - The selfdestruct method attempts to terminate the specified address, transferring its remaining balance to a given target address. If the INSPECT constant is true, the self-destruction event is observed or logged via an inspector. The method returns an Option, encapsulating the outcome of the operation: Some(SelfDestructResult) on success and None if an error occurs, with the error being stored internally for later reference. + The selfdestruct method attempts to terminate the specified address, transferring its remaining balance to a given target address. If the `Inspector` is `Some`, the self-destruction event is observed or logged via an inspector. The method returns an Option, encapsulating the outcome of the operation: Some(SelfDestructResult) on success and None if an error occurs, with the error being stored internally for later reference. - `create` - The create method initiates the creation of a contract with the provided CreateInputs. If the INSPECT constant is true, the creation process is observed or logged using an inspector, both at the start and end of the creation. The method returns a tuple consisting of the operation's result (InstructionResult), the optional address (Option) of the newly created contract, the amount of gas consumed (Gas), and the output data (Bytes). If the inspector intervenes and determines the instruction shouldn't continue, an early return occurs with the observed outcomes. + The create method initiates the creation of a contract with the provided CreateInputs. If the `Inspector` is `Some`, the creation process is observed or logged using an inspector, both at the start and end of the creation. The method returns a tuple consisting of the operation's result (InstructionResult), the optional address (Option) of the newly created contract, the amount of gas consumed (Gas), and the output data (Bytes). If the inspector intervenes and determines the instruction shouldn't continue, an early return occurs with the observed outcomes. - `call` - The call method manages a contract invocation using the provided CallInputs. If the INSPECT constant is active, the call event is observed or logged via an inspector before execution. The method yields a tuple representing the outcome of the call: the result status (InstructionResult), the consumed gas (Gas), and the output data (Bytes). If the inspector suggests early termination, the method returns immediately with the observed results. Otherwise, the main call execution is processed, and the outcomes, either raw or observed, are returned accordingly. \ No newline at end of file + The call method manages a contract invocation using the provided CallInputs. If the `Inspector` is `Some`, the call event is observed or logged via an inspector before execution. The method yields a tuple representing the outcome of the call: the result status (InstructionResult), the consumed gas (Gas), and the output data (Bytes). If the inspector suggests early termination, the method returns immediately with the observed results. Otherwise, the main call execution is processed, and the outcomes, either raw or observed, are returned accordingly. \ No newline at end of file