From 23cdd947123327e7923f27b60db79525087a80f4 Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Thu, 22 Apr 2021 17:31:28 -0400 Subject: [PATCH 01/14] Some simple benchmarks for the Near EVM --- Cargo.lock | 925 ++++++++++++++++++++++++++++++++++--- Cargo.toml | 14 + benches/common.rs | 228 +++++++++ benches/eth_deploy_code.rs | 69 +++ benches/eth_transfer.rs | 50 ++ src/lib.rs | 4 +- 6 files changed, 1225 insertions(+), 65 deletions(-) create mode 100644 benches/common.rs create mode 100644 benches/eth_deploy_code.rs create mode 100644 benches/eth_transfer.rs diff --git a/Cargo.lock b/Cargo.lock index 846c78110..8c98376e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -101,19 +101,24 @@ name = "aurora-engine" version = "0.0.0" dependencies = [ "borsh", + "criterion", "ethabi", "evm", "hex", "libsecp256k1", "lunarity-lexer", - "near-crypto", + "near-crypto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "near-primitives-core 0.1.0 (git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f)", "near-sdk", "near-sdk-sim", + "near-vm-logic 3.0.0 (git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f)", + "near-vm-runner 3.0.0", "primitive-types", + "rand 0.7.3", "ripemd160", "rjson", "rlp", - "sha2", + "sha2 0.9.3", "sha3 0.9.1", "wee_alloc", ] @@ -208,7 +213,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10a5720225ef5daecf08657f23791354e1685a8c91a4c60c7f3d3b2892f978f4" dependencies = [ - "crypto-mac", + "crypto-mac 0.8.0", "digest 0.9.0", "opaque-debug 0.3.0", ] @@ -224,7 +229,7 @@ dependencies = [ "cc", "cfg-if 0.1.10", "constant_time_eq", - "crypto-mac", + "crypto-mac 0.8.0", "digest 0.9.0", ] @@ -316,6 +321,24 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" +[[package]] +name = "bstr" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d" +dependencies = [ + "lazy_static", + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe" + [[package]] name = "byte-slice-cast" version = "1.0.0" @@ -384,6 +407,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a4f925191b4367301851c6d99b09890311d74b0d43f274c0b34c86d308a3663" +[[package]] +name = "cast" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc38c385bfd7e444464011bb24820f40dd1c76bcdfa1b78611cb7c2e5cafab75" +dependencies = [ + "rustc_version", +] + [[package]] name = "cc" version = "1.0.67" @@ -490,6 +522,16 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "cpp_demangle" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44919ecaf6f99e8e737bc239408931c9a01e9a6c74814fee8242dd2506b65390" +dependencies = [ + "cfg-if 1.0.0", + "glob", +] + [[package]] name = "cpuid-bool" version = "0.1.2" @@ -514,6 +556,15 @@ dependencies = [ "cranelift-entity 0.68.0", ] +[[package]] +name = "cranelift-bforest" +version = "0.72.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841476ab6d3530136b5162b64a2c6969d68141843ad2fd59126e5ea84fd9b5fe" +dependencies = [ + "cranelift-entity 0.72.0", +] + [[package]] name = "cranelift-codegen" version = "0.67.0" @@ -553,6 +604,26 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cranelift-codegen" +version = "0.72.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b5619cef8d19530298301f91e9a0390d369260799a3d8dd01e28fc88e53637a" +dependencies = [ + "byteorder", + "cranelift-bforest 0.72.0", + "cranelift-codegen-meta 0.72.0", + "cranelift-codegen-shared 0.72.0", + "cranelift-entity 0.72.0", + "gimli 0.23.0", + "log", + "regalloc 0.0.31", + "serde", + "smallvec", + "target-lexicon 0.11.2", + "thiserror", +] + [[package]] name = "cranelift-codegen-meta" version = "0.67.0" @@ -573,6 +644,16 @@ dependencies = [ "cranelift-entity 0.68.0", ] +[[package]] +name = "cranelift-codegen-meta" +version = "0.72.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a319709b8267939155924114ea83f2a5b5af65ece3ac6f703d4735f3c66bb0d" +dependencies = [ + "cranelift-codegen-shared 0.72.0", + "cranelift-entity 0.72.0", +] + [[package]] name = "cranelift-codegen-shared" version = "0.67.0" @@ -585,6 +666,15 @@ version = "0.68.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6759012d6d19c4caec95793f052613e9d4113e925e7f14154defbac0f1d4c938" +[[package]] +name = "cranelift-codegen-shared" +version = "0.72.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15925b23cd3a448443f289d85a8f53f3cf7a80f0137aa53c8e3b01ae8aefaef7" +dependencies = [ + "serde", +] + [[package]] name = "cranelift-entity" version = "0.67.0" @@ -603,6 +693,15 @@ dependencies = [ "serde", ] +[[package]] +name = "cranelift-entity" +version = "0.72.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "610cf464396c89af0f9f7c64b5aa90aa9e8812ac84084098f1565b40051bc415" +dependencies = [ + "serde", +] + [[package]] name = "cranelift-frontend" version = "0.67.0" @@ -627,6 +726,18 @@ dependencies = [ "target-lexicon 0.11.2", ] +[[package]] +name = "cranelift-frontend" +version = "0.72.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d20c8bd4a1c41ded051734f0e33ad1d843a0adc98b9bd975ee6657e2c70cdc9" +dependencies = [ + "cranelift-codegen 0.72.0", + "log", + "smallvec", + "target-lexicon 0.11.2", +] + [[package]] name = "cranelift-native" version = "0.67.0" @@ -638,6 +749,16 @@ dependencies = [ "target-lexicon 0.11.2", ] +[[package]] +name = "cranelift-native" +version = "0.72.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "304e100df41f34a5a15291b37bfe0fd7abd0427a2c84195cc69578b4137f9099" +dependencies = [ + "cranelift-codegen 0.72.0", + "target-lexicon 0.11.2", +] + [[package]] name = "cranelift-wasm" version = "0.67.0" @@ -653,6 +774,23 @@ dependencies = [ "wasmparser 0.59.0", ] +[[package]] +name = "cranelift-wasm" +version = "0.72.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4efd473b2917303957e0bfaea6ea9d08b8c93695bee015a611a2514ce5254abc" +dependencies = [ + "cranelift-codegen 0.72.0", + "cranelift-entity 0.72.0", + "cranelift-frontend 0.72.0", + "itertools 0.10.0", + "log", + "serde", + "smallvec", + "thiserror", + "wasmparser 0.76.0", +] + [[package]] name = "crc32fast" version = "1.2.1" @@ -662,6 +800,42 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "criterion" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab327ed7354547cc2ef43cbe20ef68b988e70b4b593cbd66a2a61733123a3d23" +dependencies = [ + "atty", + "cast", + "clap", + "criterion-plot", + "csv", + "itertools 0.10.0", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_cbor", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022feadec601fba1649cfa83586381a4ad31c6bf3a9ab7d408118b05dd9889d" +dependencies = [ + "cast", + "itertools 0.9.0", +] + [[package]] name = "crossbeam-channel" version = "0.5.0" @@ -713,6 +887,16 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-mac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +dependencies = [ + "generic-array 0.12.4", + "subtle 1.0.0", +] + [[package]] name = "crypto-mac" version = "0.8.0" @@ -720,7 +904,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ "generic-array 0.14.4", - "subtle", + "subtle 2.4.0", +] + +[[package]] +name = "csv" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +dependencies = [ + "bstr", + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +dependencies = [ + "memchr", ] [[package]] @@ -732,7 +938,7 @@ dependencies = [ "byteorder", "digest 0.9.0", "rand_core 0.5.1", - "subtle", + "subtle 2.4.0", "zeroize", ] @@ -891,7 +1097,7 @@ dependencies = [ "ed25519", "rand 0.7.3", "serde", - "sha2", + "sha2 0.9.3", "zeroize", ] @@ -1079,6 +1285,12 @@ dependencies = [ "sha3 0.8.2", ] +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + [[package]] name = "fallible-iterator" version = "0.2.0" @@ -1300,6 +1512,11 @@ name = "gimli" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" +dependencies = [ + "fallible-iterator", + "indexmap", + "stable_deref_trait", +] [[package]] name = "glob" @@ -1307,6 +1524,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +[[package]] +name = "half" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3" + [[package]] name = "hash-db" version = "0.15.2" @@ -1364,6 +1587,27 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" +dependencies = [ + "crypto-mac 0.7.0", + "digest 0.8.1", +] + +[[package]] +name = "hmac-drbg" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6e570451493f10f6581b48cdd530413b63ea9e780f544bfd3bdcaa0d89d1a7b" +dependencies = [ + "digest 0.8.1", + "generic-array 0.12.4", + "hmac", +] + [[package]] name = "humantime" version = "1.3.0" @@ -1437,6 +1681,24 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "itertools" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.7" @@ -1473,6 +1735,15 @@ dependencies = [ "libc", ] +[[package]] +name = "js-sys" +version = "0.3.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc15e39392125075f60c95ba416f5381ff6c3a948ff02ab12464715adf56c821" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "keccak" version = "0.1.0" @@ -1555,8 +1826,11 @@ dependencies = [ "arrayref", "crunchy", "digest 0.8.1", + "hmac-drbg", "rand 0.7.3", - "subtle", + "sha2 0.8.2", + "subtle 2.4.0", + "typenum", ] [[package]] @@ -1697,6 +1971,30 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" +[[package]] +name = "near-crypto" +version = "0.1.0" +source = "git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f#3744f07e13bf43a9522fb39fa8f6f128396d0e1f" +dependencies = [ + "arrayref", + "blake2", + "borsh", + "bs58", + "c2-chacha", + "curve25519-dalek", + "derive_more", + "ed25519-dalek", + "lazy_static", + "libc", + "parity-secp256k1", + "rand 0.7.3", + "rand_core 0.5.1", + "serde", + "serde_json", + "subtle 2.4.0", + "thiserror", +] + [[package]] name = "near-crypto" version = "0.1.0" @@ -1718,7 +2016,7 @@ dependencies = [ "rand_core 0.5.1", "serde", "serde_json", - "subtle", + "subtle 2.4.0", "thiserror", ] @@ -1740,8 +2038,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bde79472f7cfc0675733b65f79f9e50c20bfbb9806298ab2872916869a45dccd" dependencies = [ "borsh", - "near-crypto", - "near-primitives", + "near-crypto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "near-primitives 0.1.0-pre.1", "rand 0.7.3", ] @@ -1761,9 +2059,9 @@ dependencies = [ "hex", "jemallocator", "lazy_static", - "near-crypto", + "near-crypto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "near-primitives-core 0.4.0", - "near-rpc-error-macro", + "near-rpc-error-macro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "near-vm-errors 4.0.0-pre.1", "num-rational", "primitive-types", @@ -1772,11 +2070,59 @@ dependencies = [ "regex", "serde", "serde_json", - "sha2", + "sha2 0.9.3", + "smart-default", + "validator", +] + +[[package]] +name = "near-primitives" +version = "0.1.0" +source = "git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f#3744f07e13bf43a9522fb39fa8f6f128396d0e1f" +dependencies = [ + "base64 0.13.0", + "borsh", + "bs58", + "byteorder", + "chrono", + "derive_more", + "easy-ext", + "hex", + "jemallocator", + "lazy_static", + "near-crypto 0.1.0 (git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f)", + "near-primitives-core 0.1.0 (git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f)", + "near-rpc-error-macro 0.1.0 (git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f)", + "near-vm-errors 3.0.0 (git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f)", + "num-rational", + "primitive-types", + "rand 0.7.3", + "reed-solomon-erasure", + "regex", + "serde", + "serde_json", + "sha2 0.9.3", "smart-default", "validator", ] +[[package]] +name = "near-primitives-core" +version = "0.1.0" +source = "git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f#3744f07e13bf43a9522fb39fa8f6f128396d0e1f" +dependencies = [ + "base64 0.11.0", + "borsh", + "bs58", + "derive_more", + "hex", + "lazy_static", + "num-rational", + "serde", + "serde_json", + "sha2 0.9.3", +] + [[package]] name = "near-primitives-core" version = "0.1.0" @@ -1792,7 +2138,7 @@ dependencies = [ "num-rational", "serde", "serde_json", - "sha2", + "sha2 0.9.3", ] [[package]] @@ -1810,29 +2156,26 @@ dependencies = [ "num-rational", "serde", "serde_json", - "sha2", + "sha2 0.9.3", ] [[package]] name = "near-rpc-error-core" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffa8dbf8437a28ac40fcb85859ab0d0b8385013935b000c7a51ae79631dd74d9" +source = "git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f#3744f07e13bf43a9522fb39fa8f6f128396d0e1f" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", "serde", - "serde_json", "syn 1.0.57", ] [[package]] -name = "near-rpc-error-macro" +name = "near-rpc-error-core" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6111d713e90c7c551dee937f4a06cb9ea2672243455a4454cc7566387ba2d9" +checksum = "ffa8dbf8437a28ac40fcb85859ab0d0b8385013935b000c7a51ae79631dd74d9" dependencies = [ - "near-rpc-error-core", "proc-macro2 1.0.24", "quote 1.0.9", "serde", @@ -1841,8 +2184,35 @@ dependencies = [ ] [[package]] -name = "near-runtime" -version = "4.0.0-pre.1" +name = "near-rpc-error-macro" +version = "0.1.0" +source = "git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f#3744f07e13bf43a9522fb39fa8f6f128396d0e1f" +dependencies = [ + "near-rpc-error-core 0.1.0 (git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f)", + "proc-macro2 1.0.24", + "quote 1.0.9", + "serde", + "serde_json", + "syn 1.0.57", +] + +[[package]] +name = "near-rpc-error-macro" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6111d713e90c7c551dee937f4a06cb9ea2672243455a4454cc7566387ba2d9" +dependencies = [ + "near-rpc-error-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.24", + "quote 1.0.9", + "serde", + "serde_json", + "syn 1.0.57", +] + +[[package]] +name = "near-runtime" +version = "4.0.0-pre.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e4c0a4cd2ee5ccbc1fd5d492180ebf33ac1159d721b2e0c58c11953131fb449" dependencies = [ @@ -1852,14 +2222,14 @@ dependencies = [ "hex", "lazy_static", "log", - "near-crypto", + "near-crypto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "near-metrics", - "near-primitives", + "near-primitives 0.1.0-pre.1", "near-runtime-utils 4.0.0-pre.1", "near-store", "near-vm-errors 4.0.0-pre.1", "near-vm-logic 4.0.0-pre.1", - "near-vm-runner", + "near-vm-runner 4.0.0-pre.1", "num-bigint", "num-rational", "num-traits", @@ -1868,6 +2238,15 @@ dependencies = [ "serde_json", ] +[[package]] +name = "near-runtime-utils" +version = "3.0.0" +source = "git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f#3744f07e13bf43a9522fb39fa8f6f128396d0e1f" +dependencies = [ + "lazy_static", + "regex", +] + [[package]] name = "near-runtime-utils" version = "3.0.0" @@ -1896,9 +2275,9 @@ dependencies = [ "base64 0.13.0", "borsh", "bs58", - "near-primitives-core 0.1.0", + "near-primitives-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "near-sdk-macros", - "near-vm-logic 3.0.0", + "near-vm-logic 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde", "serde_json", "wee_alloc", @@ -1933,9 +2312,9 @@ source = "git+https://github.com/near/near-sdk-rs?rev=9d99077c6acfde68c06845f2a1 dependencies = [ "funty", "lazy-static-include", - "near-crypto", + "near-crypto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "near-pool", - "near-primitives", + "near-primitives 0.1.0-pre.1", "near-runtime", "near-sdk", "near-store", @@ -1954,8 +2333,8 @@ dependencies = [ "derive_more", "elastic-array", "lazy_static", - "near-crypto", - "near-primitives", + "near-crypto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "near-primitives 0.1.0-pre.1", "num_cpus", "rand 0.7.3", "rocksdb", @@ -1964,6 +2343,17 @@ dependencies = [ "strum", ] +[[package]] +name = "near-vm-errors" +version = "3.0.0" +source = "git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f#3744f07e13bf43a9522fb39fa8f6f128396d0e1f" +dependencies = [ + "borsh", + "hex", + "near-rpc-error-macro 0.1.0 (git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f)", + "serde", +] + [[package]] name = "near-vm-errors" version = "3.0.0" @@ -1972,7 +2362,7 @@ checksum = "53a100dda565c5375ac061126167afc5c33cdba1f2e325cfae3ce08f4a5a432a" dependencies = [ "borsh", "hex", - "near-rpc-error-macro", + "near-rpc-error-macro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde", ] @@ -1984,8 +2374,25 @@ checksum = "e281d8730ed8cb0e3e69fb689acee6b93cdb43824cd69a8ffd7e1bfcbd1177d7" dependencies = [ "borsh", "hex", - "near-rpc-error-macro", + "near-rpc-error-macro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", +] + +[[package]] +name = "near-vm-logic" +version = "3.0.0" +source = "git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f#3744f07e13bf43a9522fb39fa8f6f128396d0e1f" +dependencies = [ + "base64 0.13.0", + "borsh", + "bs58", + "byteorder", + "near-primitives-core 0.1.0 (git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f)", + "near-runtime-utils 3.0.0 (git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f)", + "near-vm-errors 3.0.0 (git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f)", "serde", + "sha2 0.9.3", + "sha3 0.9.1", ] [[package]] @@ -1998,11 +2405,11 @@ dependencies = [ "borsh", "bs58", "byteorder", - "near-primitives-core 0.1.0", - "near-runtime-utils 3.0.0", - "near-vm-errors 3.0.0", + "near-primitives-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "near-runtime-utils 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "near-vm-errors 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde", - "sha2", + "sha2 0.9.3", "sha3 0.9.1", ] @@ -2020,10 +2427,37 @@ dependencies = [ "near-runtime-utils 4.0.0-pre.1", "near-vm-errors 4.0.0-pre.1", "serde", - "sha2", + "sha2 0.9.3", "sha3 0.9.1", ] +[[package]] +name = "near-vm-runner" +version = "3.0.0" +source = "git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f#3744f07e13bf43a9522fb39fa8f6f128396d0e1f" +dependencies = [ + "anyhow", + "borsh", + "cached", + "near-primitives 0.1.0", + "near-vm-errors 3.0.0 (git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f)", + "near-vm-logic 3.0.0 (git+https://github.com/near/nearcore?rev=3744f07e13bf43a9522fb39fa8f6f128396d0e1f)", + "parity-wasm", + "pwasm-utils", + "serde", + "threadpool", + "tracing", + "wasmer", + "wasmer-compiler-cranelift", + "wasmer-compiler-singlepass", + "wasmer-engine-native", + "wasmer-runtime-core-near", + "wasmer-runtime-near", + "wasmer-types", + "wasmer-vm", + "wasmtime 0.25.0", +] + [[package]] name = "near-vm-runner" version = "4.0.0-pre.1" @@ -2034,7 +2468,7 @@ dependencies = [ "borsh", "cached", "log", - "near-primitives", + "near-primitives 0.1.0-pre.1", "near-vm-errors 4.0.0-pre.1", "near-vm-logic 4.0.0-pre.1", "parity-wasm", @@ -2045,7 +2479,7 @@ dependencies = [ "wasmer-runtime-core-near", "wasmer-runtime-near", "wasmer-types", - "wasmtime", + "wasmtime 0.20.0", ] [[package]] @@ -2150,6 +2584,10 @@ name = "object" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" +dependencies = [ + "crc32fast", + "indexmap", +] [[package]] name = "once_cell" @@ -2157,6 +2595,12 @@ version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + [[package]] name = "opaque-debug" version = "0.2.3" @@ -2271,6 +2715,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "paste" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58" + [[package]] name = "peeking_take_while" version = "0.1.2" @@ -2295,6 +2745,34 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "plotters" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45ca0ae5f169d0917a7c7f5a9c1a3d3d9598f18f529dd2b8373ed988efea307a" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07fffcddc1cb3a1de753caa4e4df03b79922ba43cf882acc1bdd7e8df9f4590" + +[[package]] +name = "plotters-svg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b38a02e23bd9604b842a812063aec4ef702b57989c37b655254bb61c471ad211" +dependencies = [ + "plotters-backend", +] + [[package]] name = "ppv-lite86" version = "0.2.10" @@ -2398,6 +2876,15 @@ version = "2.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b7f4a129bb3754c25a4e04032a90173c68f85168f77118ac4cb4936e7f06f92" +[[package]] +name = "psm" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3abf49e5417290756acfd26501536358560c4a5cc4a0934d390939acb3e7083a" +dependencies = [ + "cc", +] + [[package]] name = "pwasm-utils" version = "0.12.0" @@ -2599,6 +3086,7 @@ checksum = "571f7f397d61c4755285cd37853fe8e03271c243424a907415909379659381c5" dependencies = [ "log", "rustc-hash", + "serde", "smallvec", ] @@ -2613,6 +3101,15 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-automata" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" +dependencies = [ + "byteorder", +] + [[package]] name = "regex-syntax" version = "0.6.23" @@ -2721,6 +3218,15 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scopeguard" version = "1.1.0" @@ -2770,6 +3276,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_cbor" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622" +dependencies = [ + "half", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.118" @@ -2793,6 +3309,18 @@ dependencies = [ "serde", ] +[[package]] +name = "sha2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + [[package]] name = "sha2" version = "0.9.3" @@ -2926,6 +3454,12 @@ dependencies = [ "syn 1.0.57", ] +[[package]] +name = "subtle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" + [[package]] name = "subtle" version = "2.4.0" @@ -3036,6 +3570,15 @@ dependencies = [ "syn 1.0.57", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + [[package]] name = "time" version = "0.1.43" @@ -3055,6 +3598,16 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "tinyvec" version = "1.1.1" @@ -3248,6 +3801,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -3260,6 +3824,60 @@ version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +[[package]] +name = "wasm-bindgen" +version = "0.2.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fe8f61dba8e5d645a4d8132dc7a0a66861ed5e1045d2c0ed940fab33bac0fbe" +dependencies = [ + "cfg-if 1.0.0", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046ceba58ff062da072c7cb4ba5b22a37f00a302483f7e2a6cdc18fedbdc1fd3" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2 1.0.24", + "quote 1.0.9", + "syn 1.0.57", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef9aa01d36cda046f797c57959ff5f3c615c9cc63997a8d545831ec7976819b" +dependencies = [ + "quote 1.0.9", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96eb45c1b2ee33545a813a92dbb53856418bf7eb54ab34f7f7ff1448a5b3735d" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.9", + "syn 1.0.57", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7148f4696fb4960a346eaa60bbfb42a1ac4ebba21f750f75fc1375b098d5ffa" + [[package]] name = "wasmer" version = "1.0.2" @@ -3539,6 +4157,12 @@ version = "0.65.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87cc2fe6350834b4e528ba0901e7aa405d78b89dc1fa3145359eb4de0e323fcf" +[[package]] +name = "wasmparser" +version = "0.76.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "755a9a4afe3f6cccbbe6d7e965eef44cf260b001f93e547eba84255c1d0187d8" + [[package]] name = "wasmtime" version = "0.20.0" @@ -3558,10 +4182,38 @@ dependencies = [ "smallvec", "target-lexicon 0.11.2", "wasmparser 0.59.0", - "wasmtime-environ", - "wasmtime-jit", - "wasmtime-profiling", - "wasmtime-runtime", + "wasmtime-environ 0.20.0", + "wasmtime-jit 0.20.0", + "wasmtime-profiling 0.20.0", + "wasmtime-runtime 0.20.0", + "winapi", +] + +[[package]] +name = "wasmtime" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26ea2ad49bb047e10ca292f55cd67040bef14b676d07e7b04ed65fd312d52ece" +dependencies = [ + "anyhow", + "backtrace", + "bincode", + "cfg-if 1.0.0", + "cpp_demangle", + "indexmap", + "libc", + "log", + "paste", + "region", + "rustc-demangle", + "serde", + "smallvec", + "target-lexicon 0.11.2", + "wasmparser 0.76.0", + "wasmtime-environ 0.25.0", + "wasmtime-jit 0.25.0", + "wasmtime-profiling 0.25.0", + "wasmtime-runtime 0.25.0", "winapi", ] @@ -3574,8 +4226,22 @@ dependencies = [ "cranelift-codegen 0.67.0", "cranelift-entity 0.67.0", "cranelift-frontend 0.67.0", - "cranelift-wasm", - "wasmtime-environ", + "cranelift-wasm 0.67.0", + "wasmtime-environ 0.20.0", +] + +[[package]] +name = "wasmtime-cranelift" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e769b80abbb89255926f69ba37085f7dd6608c980134838c3c89d7bf6e776bc" +dependencies = [ + "cranelift-codegen 0.72.0", + "cranelift-entity 0.72.0", + "cranelift-frontend 0.72.0", + "cranelift-wasm 0.72.0", + "wasmparser 0.76.0", + "wasmtime-environ 0.25.0", ] [[package]] @@ -3591,7 +4257,23 @@ dependencies = [ "target-lexicon 0.11.2", "thiserror", "wasmparser 0.59.0", - "wasmtime-environ", + "wasmtime-environ 0.20.0", +] + +[[package]] +name = "wasmtime-debug" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38501788c936a4932b0ddf61135963a4b7d1f549f63a6908ae56a1c86d74fc7b" +dependencies = [ + "anyhow", + "gimli 0.23.0", + "more-asserts", + "object 0.23.0", + "target-lexicon 0.11.2", + "thiserror", + "wasmparser 0.76.0", + "wasmtime-environ 0.25.0", ] [[package]] @@ -3604,7 +4286,7 @@ dependencies = [ "cfg-if 0.1.10", "cranelift-codegen 0.67.0", "cranelift-entity 0.67.0", - "cranelift-wasm", + "cranelift-wasm 0.67.0", "gimli 0.21.0", "indexmap", "log", @@ -3614,6 +4296,27 @@ dependencies = [ "wasmparser 0.59.0", ] +[[package]] +name = "wasmtime-environ" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fae793ea1387b2fede277d209bb27285366df58f0a3ae9d59e58a7941dce60fa" +dependencies = [ + "anyhow", + "cfg-if 1.0.0", + "cranelift-codegen 0.72.0", + "cranelift-entity 0.72.0", + "cranelift-wasm 0.72.0", + "gimli 0.23.0", + "indexmap", + "log", + "more-asserts", + "region", + "serde", + "thiserror", + "wasmparser 0.76.0", +] + [[package]] name = "wasmtime-jit" version = "0.20.0" @@ -3625,8 +4328,8 @@ dependencies = [ "cranelift-codegen 0.67.0", "cranelift-entity 0.67.0", "cranelift-frontend 0.67.0", - "cranelift-native", - "cranelift-wasm", + "cranelift-native 0.67.0", + "cranelift-wasm 0.67.0", "gimli 0.21.0", "log", "more-asserts", @@ -3636,12 +4339,44 @@ dependencies = [ "target-lexicon 0.11.2", "thiserror", "wasmparser 0.59.0", - "wasmtime-cranelift", - "wasmtime-debug", - "wasmtime-environ", - "wasmtime-obj", - "wasmtime-profiling", - "wasmtime-runtime", + "wasmtime-cranelift 0.20.0", + "wasmtime-debug 0.20.0", + "wasmtime-environ 0.20.0", + "wasmtime-obj 0.20.0", + "wasmtime-profiling 0.20.0", + "wasmtime-runtime 0.20.0", + "winapi", +] + +[[package]] +name = "wasmtime-jit" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b3bd0fae8396473a68a1491559d61776127bb9bea75c9a6a6c038ae4a656eb2" +dependencies = [ + "addr2line", + "anyhow", + "cfg-if 1.0.0", + "cranelift-codegen 0.72.0", + "cranelift-entity 0.72.0", + "cranelift-frontend 0.72.0", + "cranelift-native 0.72.0", + "cranelift-wasm 0.72.0", + "gimli 0.23.0", + "log", + "more-asserts", + "object 0.23.0", + "region", + "serde", + "target-lexicon 0.11.2", + "thiserror", + "wasmparser 0.76.0", + "wasmtime-cranelift 0.25.0", + "wasmtime-debug 0.25.0", + "wasmtime-environ 0.25.0", + "wasmtime-obj 0.25.0", + "wasmtime-profiling 0.25.0", + "wasmtime-runtime 0.25.0", "winapi", ] @@ -3655,8 +4390,22 @@ dependencies = [ "more-asserts", "object 0.21.1", "target-lexicon 0.11.2", - "wasmtime-debug", - "wasmtime-environ", + "wasmtime-debug 0.20.0", + "wasmtime-environ 0.20.0", +] + +[[package]] +name = "wasmtime-obj" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a79fa098a3be8fabc50f5be60f8e47694d569afdc255de37850fc80295485012" +dependencies = [ + "anyhow", + "more-asserts", + "object 0.23.0", + "target-lexicon 0.11.2", + "wasmtime-debug 0.25.0", + "wasmtime-environ 0.25.0", ] [[package]] @@ -3671,8 +4420,24 @@ dependencies = [ "libc", "serde", "target-lexicon 0.11.2", - "wasmtime-environ", - "wasmtime-runtime", + "wasmtime-environ 0.20.0", + "wasmtime-runtime 0.20.0", +] + +[[package]] +name = "wasmtime-profiling" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d81e2106efeef4c01917fd16956a91d39bb78c07cf97027abdba9ca98da3f258" +dependencies = [ + "anyhow", + "cfg-if 1.0.0", + "lazy_static", + "libc", + "serde", + "target-lexicon 0.11.2", + "wasmtime-environ 0.25.0", + "wasmtime-runtime 0.25.0", ] [[package]] @@ -3692,7 +4457,31 @@ dependencies = [ "more-asserts", "region", "thiserror", - "wasmtime-environ", + "wasmtime-environ 0.20.0", + "winapi", +] + +[[package]] +name = "wasmtime-runtime" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f747c656ca4680cad7846ae91c57d03f2dd4f4170da77a700df4e21f0d805378" +dependencies = [ + "anyhow", + "backtrace", + "cc", + "cfg-if 1.0.0", + "indexmap", + "lazy_static", + "libc", + "log", + "memoffset 0.6.3", + "more-asserts", + "psm", + "rand 0.7.3", + "region", + "thiserror", + "wasmtime-environ 0.25.0", "winapi", ] @@ -3714,6 +4503,16 @@ dependencies = [ "wast", ] +[[package]] +name = "web-sys" +version = "0.3.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59fe19d70f5dacc03f6e46777213facae5ac3801575d56ca6cbd4c93dcd12310" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "wee_alloc" version = "0.4.5" diff --git a/Cargo.toml b/Cargo.toml index 742081490..0147120f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,6 +56,20 @@ hex = { version = "0.4.3", default-features = false } near-sdk = { git = "https://github.com/near/near-sdk-rs", rev = "9d99077c6acfde68c06845f2a1eb2b5ed7983401" } near-sdk-sim = { git = "https://github.com/near/near-sdk-rs", rev = "9d99077c6acfde68c06845f2a1eb2b5ed7983401" } near-crypto = "0.1.0" +near-vm-runner = { git = "https://github.com/near/nearcore", rev = "3744f07e13bf43a9522fb39fa8f6f128396d0e1f" } +near-primitives-core = { git = "https://github.com/near/nearcore", rev = "3744f07e13bf43a9522fb39fa8f6f128396d0e1f" } +near-vm-logic = { git = "https://github.com/near/nearcore", rev = "3744f07e13bf43a9522fb39fa8f6f128396d0e1f" } +libsecp256k1 = "0.3.5" +rand = "0.7.3" +criterion = "0.3.4" + +[[bench]] +name = "eth_transfer" +harness = false + +[[bench]] +name = "eth_deploy_code" +harness = false [features] default = ["sha2", "std"] diff --git a/benches/common.rs b/benches/common.rs new file mode 100644 index 000000000..e256ebc1c --- /dev/null +++ b/benches/common.rs @@ -0,0 +1,228 @@ +use borsh::BorshSerialize; +use near_primitives_core::config::VMConfig; +use near_primitives_core::contract::ContractCode; +use near_primitives_core::profile::ProfileData; +use near_primitives_core::runtime::fees::RuntimeFeesConfig; +use near_vm_logic::mocks::mock_external::MockedExternal; +use near_vm_logic::{VMContext, VMOutcome}; +use near_vm_runner::{MockCompiledContractCache, VMError}; + +use primitive_types::U256; +use rlp::RlpStream; +use secp256k1::{self, Message, PublicKey, SecretKey}; + +use aurora_engine::parameters::NewCallArgs; +use aurora_engine::prelude::Address; +use aurora_engine::storage; +use aurora_engine::transaction::{EthSignedTransaction, EthTransaction}; +use aurora_engine::types; + +near_sdk_sim::lazy_static_include::lazy_static_include_bytes! { + EVM_WASM_BYTES => "release.wasm" +} + +pub const RAW_CALL: &str = "raw_call"; + +pub struct AuroraRunner { + pub aurora_account_id: String, + pub chain_id: u64, + pub code: ContractCode, + pub cache: MockCompiledContractCache, + pub ext: MockedExternal, + pub context: VMContext, + pub wasm_config: VMConfig, + pub fees_config: RuntimeFeesConfig, + pub current_protocol_version: u32, + pub profile: ProfileData, +} + +/// Same as `AuroraRunner`, but consumes `self` on execution (thus preventing building on +/// the `ext` post-state with future calls to the contract. +#[derive(Clone)] +pub struct OneShotAuroraRunner<'a> { + pub base: &'a AuroraRunner, + pub ext: MockedExternal, + pub context: VMContext, +} + +impl<'a> OneShotAuroraRunner<'a> { + pub fn call( + mut self, + method_name: &str, + caller_account_id: String, + input: Vec, + ) -> (Option, Option) { + AuroraRunner::update_context(&mut self.context, caller_account_id, input); + + near_vm_runner::run( + &self.base.code, + method_name, + &mut self.ext, + self.context.clone(), + &self.base.wasm_config, + &self.base.fees_config, + &[], + self.base.current_protocol_version, + Some(&self.base.cache), + &self.base.profile, + ) + } +} + +impl AuroraRunner { + pub fn one_shot(&self) -> OneShotAuroraRunner { + OneShotAuroraRunner { + base: &self, + ext: self.ext.clone(), + context: self.context.clone(), + } + } + + fn update_context(context: &mut VMContext, caller_account_id: String, input: Vec) { + context.block_index += 1; + context.block_timestamp += 100; + context.input = input; + context.signer_account_id = caller_account_id.clone(); + context.predecessor_account_id = caller_account_id; + } + + pub fn call( + &mut self, + method_name: &str, + caller_account_id: String, + input: Vec, + ) -> (Option, Option) { + Self::update_context(&mut self.context, caller_account_id, input); + + near_vm_runner::run( + &self.code, + method_name, + &mut self.ext, + self.context.clone(), + &self.wasm_config, + &self.fees_config, + &[], + self.current_protocol_version, + Some(&self.cache), + &self.profile, + ) + } + + pub fn create_address(&mut self, address: Address, init_balance: U256, init_nonce: U256) { + let trie = &mut self.ext.fake_trie; + + let balance_key = storage::address_to_key(storage::KeyPrefix::Balance, &address); + let balance_value = types::u256_to_arr(&init_balance); + + let nonce_key = storage::address_to_key(storage::KeyPrefix::Nonce, &address); + let nonce_value = types::u256_to_arr(&init_nonce); + + trie.insert(balance_key.to_vec(), balance_value.to_vec()); + trie.insert(nonce_key.to_vec(), nonce_value.to_vec()); + } +} + +impl Default for AuroraRunner { + fn default() -> Self { + let aurora_account_id = "aurora".to_string(); + Self { + aurora_account_id: aurora_account_id.clone(), + chain_id: 1313161556, // NEAR betanet + code: ContractCode::new(EVM_WASM_BYTES.to_vec(), None), + cache: Default::default(), + ext: Default::default(), + context: VMContext { + current_account_id: aurora_account_id.clone(), + signer_account_id: aurora_account_id.clone(), + signer_account_pk: vec![], + predecessor_account_id: aurora_account_id, + input: vec![], + block_index: 0, + block_timestamp: 0, + epoch_height: 0, + account_balance: 10u128.pow(25), + account_locked_balance: 0, + storage_usage: 100, + attached_deposit: 0, + prepaid_gas: 10u64.pow(18), + random_seed: vec![], + is_view: false, + output_data_receivers: vec![], + }, + wasm_config: Default::default(), + fees_config: Default::default(), + current_protocol_version: u32::MAX, + profile: Default::default(), + } + } +} + +pub fn deploy_evm() -> AuroraRunner { + let mut runner = AuroraRunner::default(); + let args = NewCallArgs { + chain_id: types::u256_to_arr(&U256::from(runner.chain_id)), + owner_id: runner.aurora_account_id.clone(), + bridge_prover_id: "prover.near".to_string(), + upgrade_delay_blocks: 1, + }; + + let (_, maybe_error) = runner.call( + "new", + runner.aurora_account_id.clone(), + args.try_to_vec().unwrap(), + ); + + assert!(maybe_error.is_none()); + + runner +} + +pub fn create_eth_transaction( + to: Option
, + value: U256, + data: Vec, + chain_id: Option, + secret_key: &SecretKey, +) -> EthSignedTransaction { + // nonce, gas_price and gas are not used by EVM contract currently + let tx = EthTransaction { + nonce: Default::default(), + gas_price: Default::default(), + gas: Default::default(), + to, + value, + data, + }; + sign_transaction(tx, chain_id, secret_key) +} + +pub fn sign_transaction( + tx: EthTransaction, + chain_id: Option, + secret_key: &SecretKey, +) -> EthSignedTransaction { + let mut rlp_stream = RlpStream::new(); + tx.rlp_append_unsigned(&mut rlp_stream, chain_id); + let message_hash = types::keccak(rlp_stream.as_raw()); + let message = Message::parse_slice(message_hash.as_bytes()).unwrap(); + + let (signature, recovery_id) = secp256k1::sign(&message, secret_key); + let v: u64 = match chain_id { + Some(chain_id) => (recovery_id.serialize() as u64) + 2 * chain_id + 35, + None => (recovery_id.serialize() as u64) + 27, + }; + let r = U256::from_big_endian(&signature.r.b32()); + let s = U256::from_big_endian(&signature.s.b32()); + EthSignedTransaction { + transaction: tx, + v, + r, + s, + } +} + +pub fn address_from_secret_key(sk: &SecretKey) -> Address { + let pk = PublicKey::from_secret_key(sk); + let hash = types::keccak(&pk.serialize()[1..]); + Address::from_slice(&hash[12..]) +} diff --git a/benches/eth_deploy_code.rs b/benches/eth_deploy_code.rs new file mode 100644 index 000000000..660570329 --- /dev/null +++ b/benches/eth_deploy_code.rs @@ -0,0 +1,69 @@ +use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion, Throughput}; +use secp256k1::SecretKey; + +mod common; + +use common::{address_from_secret_key, create_eth_transaction, deploy_evm, RAW_CALL}; + +const INITIAL_BALANCE: u64 = 1000; +const INITIAL_NONCE: u64 = 0; +const TRANSFER_AMOUNT: u64 = 0; + +fn eth_deploy_code_benchmark(c: &mut Criterion) { + let mut runner = deploy_evm(); + let mut rng = rand::thread_rng(); + let source_account = SecretKey::random(&mut rng); + runner.create_address( + address_from_secret_key(&source_account), + INITIAL_BALANCE.into(), + INITIAL_NONCE.into(), + ); + let inputs: Vec<_> = [1, 5, 10, 15, 20] + .iter() + .copied() + .map(|n| { + let code_size = 2usize.pow(n); + let code: Vec = std::iter::repeat(0).take(code_size).collect(); + let transaction = create_eth_transaction( + None, + TRANSFER_AMOUNT.into(), + code, + Some(runner.chain_id), + &source_account, + ); + rlp::encode(&transaction).to_vec() + }) + .collect(); + let calling_account_id = "some-account.near".to_string(); + + // measure gas usage + for input in inputs.iter() { + let input_size = input.len(); + let (output, _) = + runner + .one_shot() + .call(RAW_CALL, calling_account_id.clone(), input.clone()); + let gas = output.unwrap().burnt_gas; + // TODO: capture this in a file + println!("ETH_DEPLOY_CODE_{:?} GAS: {:?}", input_size, gas); + } + + // measure wall-clock time + let mut group = c.benchmark_group("deploy_code"); + for input in inputs { + let input_size = input.len() as u64; + let id = BenchmarkId::from_parameter(input_size); + group.throughput(Throughput::Bytes(input_size)); + group.bench_function(id, |b| { + b.iter_batched( + || (runner.one_shot(), calling_account_id.clone(), input.clone()), + |(r, c, i)| r.call(RAW_CALL, c, i), + BatchSize::SmallInput, + ) + }); + } + group.finish(); +} + +criterion_group!(benches, eth_deploy_code_benchmark); +criterion_main!(benches); diff --git a/benches/eth_transfer.rs b/benches/eth_transfer.rs new file mode 100644 index 000000000..871430fe8 --- /dev/null +++ b/benches/eth_transfer.rs @@ -0,0 +1,50 @@ +use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; +use secp256k1::SecretKey; + +mod common; + +use common::{address_from_secret_key, create_eth_transaction, deploy_evm, RAW_CALL}; + +const INITIAL_BALANCE: u64 = 1000; +const INITIAL_NONCE: u64 = 0; +const TRANSFER_AMOUNT: u64 = 123; + +fn eth_transfer_benchmark(c: &mut Criterion) { + let mut runner = deploy_evm(); + let mut rng = rand::thread_rng(); + let source_account = SecretKey::random(&mut rng); + runner.create_address( + address_from_secret_key(&source_account), + INITIAL_BALANCE.into(), + INITIAL_NONCE.into(), + ); + let dest_account = address_from_secret_key(&SecretKey::random(&mut rng)); + let transaction = create_eth_transaction( + Some(dest_account), + TRANSFER_AMOUNT.into(), + vec![], + Some(runner.chain_id), + &source_account, + ); + let input = rlp::encode(&transaction).to_vec(); + let calling_account_id = "some-account.near".to_string(); + + // measure gas usage + let (output, _) = runner + .one_shot() + .call(RAW_CALL, calling_account_id.clone(), input.clone()); + let gas = output.unwrap().burnt_gas; + println!("ETH_TRANSFER GAS: {:?}", gas); // TODO: capture this in a file + + // measure wall-clock time + c.bench_function("eth_transfer", |b| { + b.iter_batched( + || (runner.one_shot(), calling_account_id.clone(), input.clone()), + |(r, c, i)| r.call(RAW_CALL, c, i), + BatchSize::SmallInput, + ) + }); +} + +criterion_group!(benches, eth_transfer_benchmark); +criterion_main!(benches); diff --git a/src/lib.rs b/src/lib.rs index cf9a15256..76c7db763 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,8 +11,8 @@ pub mod meta_parsing; pub mod parameters; mod precompiles; pub mod prelude; -mod storage; -mod transaction; +pub mod storage; +pub mod transaction; pub mod types; #[cfg(feature = "contract")] From ecb4c99622358266369c372f16bef23d8eafebf7 Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Mon, 26 Apr 2021 14:11:22 -0400 Subject: [PATCH 02/14] Check no errors occur when running benchmarks --- benches/eth_deploy_code.rs | 5 +++-- benches/eth_transfer.rs | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/benches/eth_deploy_code.rs b/benches/eth_deploy_code.rs index 660570329..588537523 100644 --- a/benches/eth_deploy_code.rs +++ b/benches/eth_deploy_code.rs @@ -18,7 +18,7 @@ fn eth_deploy_code_benchmark(c: &mut Criterion) { INITIAL_BALANCE.into(), INITIAL_NONCE.into(), ); - let inputs: Vec<_> = [1, 5, 10, 15, 20] + let inputs: Vec<_> = [1, 4, 8, 12, 16] .iter() .copied() .map(|n| { @@ -39,10 +39,11 @@ fn eth_deploy_code_benchmark(c: &mut Criterion) { // measure gas usage for input in inputs.iter() { let input_size = input.len(); - let (output, _) = + let (output, maybe_err) = runner .one_shot() .call(RAW_CALL, calling_account_id.clone(), input.clone()); + assert!(maybe_err.is_none()); let gas = output.unwrap().burnt_gas; // TODO: capture this in a file println!("ETH_DEPLOY_CODE_{:?} GAS: {:?}", input_size, gas); diff --git a/benches/eth_transfer.rs b/benches/eth_transfer.rs index 871430fe8..e7d08766d 100644 --- a/benches/eth_transfer.rs +++ b/benches/eth_transfer.rs @@ -30,9 +30,10 @@ fn eth_transfer_benchmark(c: &mut Criterion) { let calling_account_id = "some-account.near".to_string(); // measure gas usage - let (output, _) = runner + let (output, maybe_err) = runner .one_shot() .call(RAW_CALL, calling_account_id.clone(), input.clone()); + assert!(maybe_err.is_none()); let gas = output.unwrap().burnt_gas; println!("ETH_TRANSFER GAS: {:?}", gas); // TODO: capture this in a file From bed015cd694c001bb6e4462cb5a9646b30c94af7 Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Mon, 26 Apr 2021 15:51:17 -0400 Subject: [PATCH 03/14] cargo fmt --- benches/eth_transfer.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/benches/eth_transfer.rs b/benches/eth_transfer.rs index e7d08766d..355794ae2 100644 --- a/benches/eth_transfer.rs +++ b/benches/eth_transfer.rs @@ -30,9 +30,10 @@ fn eth_transfer_benchmark(c: &mut Criterion) { let calling_account_id = "some-account.near".to_string(); // measure gas usage - let (output, maybe_err) = runner - .one_shot() - .call(RAW_CALL, calling_account_id.clone(), input.clone()); + let (output, maybe_err) = + runner + .one_shot() + .call(RAW_CALL, calling_account_id.clone(), input.clone()); assert!(maybe_err.is_none()); let gas = output.unwrap().burnt_gas; println!("ETH_TRANSFER GAS: {:?}", gas); // TODO: capture this in a file From e1fa0b525b6a82b4589fc646060149147fd7fdeb Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Mon, 26 Apr 2021 16:39:33 -0400 Subject: [PATCH 04/14] ERC20 benchmark --- Cargo.toml | 4 + benches/eth_erc20.rs | 220 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 224 insertions(+) create mode 100644 benches/eth_erc20.rs diff --git a/Cargo.toml b/Cargo.toml index 0147120f7..5eee9a271 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -71,6 +71,10 @@ harness = false name = "eth_deploy_code" harness = false +[[bench]] +name = "eth_erc20" +harness = false + [features] default = ["sha2", "std"] std = ["borsh/std", "evm/std", "primitive-types/std", "rlp/std", "sha3/std", "ethabi/std", "lunarity-lexer/std"] diff --git a/benches/eth_erc20.rs b/benches/eth_erc20.rs new file mode 100644 index 000000000..9e587b276 --- /dev/null +++ b/benches/eth_erc20.rs @@ -0,0 +1,220 @@ +use aurora_engine::prelude::{Address, U256}; +use aurora_engine::transaction::EthTransaction; +use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion}; +use near_vm_logic::VMOutcome; +use secp256k1::SecretKey; + +// We don't use everything in `common`, but that's ok, other benchmarks do +#[allow(dead_code)] +mod common; + +use common::{ + address_from_secret_key, deploy_evm, sign_transaction, AuroraRunner, RAW_CALL, +}; + +const INITIAL_BALANCE: u64 = 1000; +const INITIAL_NONCE: u64 = 0; +const TRANSFER_AMOUNT: u64 = 67; + +fn eth_erc20_benchmark(c: &mut Criterion) { + let mut runner = deploy_evm(); + let mut rng = rand::thread_rng(); + let source_account = SecretKey::random(&mut rng); + runner.create_address( + address_from_secret_key(&source_account), + INITIAL_BALANCE.into(), + INITIAL_NONCE.into(), + ); + let calling_account_id = "some-account.near".to_string(); + + // deploy the erc20 contract + let constructor = ERC20Constructor::load(); + let output = exec_transaction( + &mut runner, + constructor.deploy("Benchmarker", "BENCH", U256::zero()), + &source_account, + ); + let erc20_address = output.return_data.as_value().unwrap(); + let contract = ERC20 { + abi: constructor.abi, + address: Address::from_slice(&erc20_address), + }; + + // create the transaction for minting + let tx = contract.mint( + address_from_secret_key(&source_account), + INITIAL_BALANCE.into(), + U256::from(INITIAL_NONCE + 1), + ); + let signed_tx = sign_transaction(tx, Some(runner.chain_id), &source_account); + let mint_tx_bytes = rlp::encode(&signed_tx).to_vec(); + + // create the transaction for transfer + let dest_address = address_from_secret_key(&SecretKey::random(&mut rng)); + let tx = contract.transfer( + dest_address, + TRANSFER_AMOUNT.into(), + U256::from(INITIAL_NONCE + 2), + ); + let signed_tx = sign_transaction(tx, Some(runner.chain_id), &source_account); + let transfer_tx_bytes = rlp::encode(&signed_tx).to_vec(); + + let mut group = c.benchmark_group("erc20"); + let mint_id = BenchmarkId::from_parameter("mint"); + let transfer_id = BenchmarkId::from_parameter("transfer"); + + // measure mint wall-clock time + group.bench_function(mint_id, |b| { + b.iter_batched( + || { + ( + runner.one_shot(), + calling_account_id.clone(), + mint_tx_bytes.clone(), + ) + }, + |(r, c, i)| r.call(RAW_CALL, c, i), + BatchSize::SmallInput, + ) + }); + + // Measure mint gas usage; don't use `one_shot` because we want to keep this state change for + // the next benchmark where we transfer some of the minted tokens. + let (output, maybe_error) = + runner.call(RAW_CALL, calling_account_id.clone(), mint_tx_bytes.clone()); + assert!(maybe_error.is_none()); + let gas = output.unwrap().burnt_gas; + println!("ETH_ERC20_MINT GAS: {:?}", gas); // TODO: capture this in a file + + // Measure transfer gas usage + let (output, maybe_err) = runner.one_shot().call( + RAW_CALL, + calling_account_id.clone(), + transfer_tx_bytes.clone(), + ); + assert!(maybe_err.is_none()); + let gas = output.unwrap().burnt_gas; + println!("ETH_ERC20_TRANSFER GAS: {:?}", gas); // TODO: capture this in a file + + // measure transfer wall-clock time + group.bench_function(transfer_id, |b| { + b.iter_batched( + || { + ( + runner.one_shot(), + calling_account_id.clone(), + transfer_tx_bytes.clone(), + ) + }, + |(r, c, i)| r.call(RAW_CALL, c, i), + BatchSize::SmallInput, + ) + }); + + group.finish(); +} + +struct ERC20Constructor { + abi: ethabi::Contract, + code: Vec, +} + +struct ERC20 { + abi: ethabi::Contract, + address: Address, +} + +impl ERC20Constructor { + fn load() -> Self { + let hex_rep = std::fs::read_to_string("benches/res/ERC20PresetMinterPauser.bin").unwrap(); + let code = hex::decode(&hex_rep).unwrap(); + let reader = std::fs::File::open("benches/res/ERC20PresetMinterPauser.abi").unwrap(); + let abi = ethabi::Contract::load(reader).unwrap(); + + Self { abi, code } + } + + fn deploy(&self, name: &str, symbol: &str, nonce: U256) -> EthTransaction { + let data = self + .abi + .constructor() + .unwrap() + .encode_input( + self.code.clone(), + &[ + ethabi::Token::String(name.to_string()), + ethabi::Token::String(symbol.to_string()), + ], + ) + .unwrap(); + EthTransaction { + nonce, + gas_price: Default::default(), + gas: Default::default(), + to: None, + value: Default::default(), + data, + } + } +} + +impl ERC20 { + fn mint(&self, recipient: Address, amount: U256, nonce: U256) -> EthTransaction { + let data = self + .abi + .function("mint") + .unwrap() + .encode_input(&[ + ethabi::Token::Address(recipient), + ethabi::Token::Uint(amount), + ]) + .unwrap(); + EthTransaction { + nonce, + gas_price: Default::default(), + gas: Default::default(), + to: Some(self.address), + value: Default::default(), + data, + } + } + + fn transfer(&self, recipient: Address, amount: U256, nonce: U256) -> EthTransaction { + let data = self + .abi + .function("transfer") + .unwrap() + .encode_input(&[ + ethabi::Token::Address(recipient), + ethabi::Token::Uint(amount), + ]) + .unwrap(); + EthTransaction { + nonce, + gas_price: Default::default(), + gas: Default::default(), + to: Some(self.address), + value: Default::default(), + data, + } + } +} + +fn exec_transaction( + runner: &mut AuroraRunner, + tx: EthTransaction, + account: &SecretKey, +) -> VMOutcome { + let calling_account_id = "some-account.near".to_string(); + let signed_tx = sign_transaction(tx, Some(runner.chain_id), &account); + let (output, maybe_err) = runner.call( + RAW_CALL, + calling_account_id, + rlp::encode(&signed_tx).to_vec(), + ); + assert!(maybe_err.is_none()); + output.unwrap() +} + +criterion_group!(benches, eth_erc20_benchmark); +criterion_main!(benches); From 74a21e43dda321a6a7c1844848cc6e740ddef48b Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Tue, 27 Apr 2021 11:16:47 -0400 Subject: [PATCH 05/14] Automatically download and compile the solidity sources for the erc20 benchmark --- Cargo.lock | 87 ++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + benches/eth_erc20.rs | 43 +++++++++++++++++++--- benches/solidity.rs | 44 ++++++++++++++++++++++ 4 files changed, 170 insertions(+), 5 deletions(-) create mode 100644 benches/solidity.rs diff --git a/Cargo.lock b/Cargo.lock index 8c98376e7..1d668da11 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -104,6 +104,7 @@ dependencies = [ "criterion", "ethabi", "evm", + "git2", "hex", "libsecp256k1", "lunarity-lexer", @@ -1518,6 +1519,21 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "git2" +version = "0.13.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b483c6c2145421099df1b4efd50e0f6205479a072199460eff852fa15e5603c7" +dependencies = [ + "bitflags", + "libc", + "libgit2-sys", + "log", + "openssl-probe", + "openssl-sys", + "url", +] + [[package]] name = "glob" version = "0.3.0" @@ -1785,6 +1801,20 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56d855069fafbb9b344c0f962150cd2c1187975cb1c22c1522c240d8c4986714" +[[package]] +name = "libgit2-sys" +version = "0.12.19+1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f322155d574c8b9ebe991a04f6908bb49e68a79463338d24a43d6274cb6443e6" +dependencies = [ + "cc", + "libc", + "libssh2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", +] + [[package]] name = "libloading" version = "0.5.2" @@ -1833,6 +1863,32 @@ dependencies = [ "typenum", ] +[[package]] +name = "libssh2-sys" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0186af0d8f171ae6b9c4c90ec51898bad5d08a2d5e470903a50d9ad8959cbee" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "libz-sys" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "lock_api" version = "0.3.4" @@ -2613,6 +2669,25 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "openssl-probe" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" + +[[package]] +name = "openssl-sys" +version = "0.9.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "313752393519e876837e09e1fa183ddef0be7735868dced3196f4472d536277f" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "page_size" version = "0.4.2" @@ -2745,6 +2820,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" + [[package]] name = "plotters" version = "0.3.0" @@ -3783,6 +3864,12 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad9680608df133af2c1ddd5eaf1ddce91d60d61b6bc51494ef326458365a470a" +[[package]] +name = "vcpkg" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbdbff6266a24120518560b5dc983096efb98462e51d0d68169895b237be3e5d" + [[package]] name = "vec_map" version = "0.8.2" diff --git a/Cargo.toml b/Cargo.toml index 5eee9a271..f803d29bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,6 +62,7 @@ near-vm-logic = { git = "https://github.com/near/nearcore", rev = "3744f07e13bf4 libsecp256k1 = "0.3.5" rand = "0.7.3" criterion = "0.3.4" +git2 = "0.13" [[bench]] name = "eth_transfer" diff --git a/benches/eth_erc20.rs b/benches/eth_erc20.rs index 9e587b276..7e304fbed 100644 --- a/benches/eth_erc20.rs +++ b/benches/eth_erc20.rs @@ -3,14 +3,14 @@ use aurora_engine::transaction::EthTransaction; use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion}; use near_vm_logic::VMOutcome; use secp256k1::SecretKey; +use std::path::{Path, PathBuf}; // We don't use everything in `common`, but that's ok, other benchmarks do #[allow(dead_code)] mod common; +mod solidity; -use common::{ - address_from_secret_key, deploy_evm, sign_transaction, AuroraRunner, RAW_CALL, -}; +use common::{address_from_secret_key, deploy_evm, sign_transaction, AuroraRunner, RAW_CALL}; const INITIAL_BALANCE: u64 = 1000; const INITIAL_NONCE: u64 = 0; @@ -126,9 +126,25 @@ struct ERC20 { impl ERC20Constructor { fn load() -> Self { - let hex_rep = std::fs::read_to_string("benches/res/ERC20PresetMinterPauser.bin").unwrap(); + let artifacts_base_path = Self::solidity_artifacts_path(); + let hex_path = artifacts_base_path.join("ERC20PresetMinterPauser.bin"); + let hex_rep = match std::fs::read_to_string(&hex_path) { + Ok(hex) => hex, + Err(_) => { + // An error occurred opening the file, maybe the contract hasn't been compiled? + let sources_root = Self::download_solidity_sources(); + solidity::compile( + sources_root, + "token/ERC20/presets/ERC20PresetMinterPauser.sol", + &artifacts_base_path, + ); + // If another error occurs, then we can't handle it so we just unwrap. + std::fs::read_to_string(hex_path).unwrap() + } + }; let code = hex::decode(&hex_rep).unwrap(); - let reader = std::fs::File::open("benches/res/ERC20PresetMinterPauser.abi").unwrap(); + let abi_path = artifacts_base_path.join("ERC20PresetMinterPauser.abi"); + let reader = std::fs::File::open(abi_path).unwrap(); let abi = ethabi::Contract::load(reader).unwrap(); Self { abi, code } @@ -156,6 +172,23 @@ impl ERC20Constructor { data, } } + + fn download_solidity_sources() -> PathBuf { + let sources_dir = Path::new("target").join("openzeppelin-contracts"); + let contracts_dir = sources_dir.join("contracts"); + if contracts_dir.exists() { + contracts_dir + } else { + let url = "https://github.com/OpenZeppelin/openzeppelin-contracts"; + let repo = git2::Repository::clone(url, sources_dir).unwrap(); + // repo.path() gives the path of the .git directory, so we need to use the parent + repo.path().parent().unwrap().join("contracts") + } + } + + fn solidity_artifacts_path() -> PathBuf { + Path::new("target").join("solidity_build") + } } impl ERC20 { diff --git a/benches/solidity.rs b/benches/solidity.rs new file mode 100644 index 000000000..ee441f5e1 --- /dev/null +++ b/benches/solidity.rs @@ -0,0 +1,44 @@ +use std::fs; +use std::path::Path; +use std::process::Command; + +/// Compiles a solidity contract. `source_path` gives the directory containing all solidity +/// source files to consider (including imports). `contract_file` must be +/// given relative to `source_path`. `output_path` gives the directory where the compiled +/// artifacts are written. Requires Docker to be installed. +pub fn compile(source_path: P1, contract_file: P2, output_path: P3) +where + P1: AsRef, + P2: AsRef, + P3: AsRef, +{ + let source_path = fs::canonicalize(source_path).unwrap(); + fs::create_dir_all(&output_path).unwrap(); + let output_path = fs::canonicalize(output_path).unwrap(); + let source_mount_arg = format!("{}:/contracts", source_path.to_str().unwrap()); + let output_mount_arg = format!("{}:/output", output_path.to_str().unwrap()); + let contract_arg = format!("/contracts/{}", contract_file.as_ref().to_str().unwrap()); + let output = Command::new("/usr/bin/docker") + .args(&[ + "run", + "-v", + &source_mount_arg, + "-v", + &output_mount_arg, + "ethereum/solc:stable", + "--allow-paths", + "/contracts/", + "-o", + "/output", + "--abi", + "--bin", + "--overwrite", + &contract_arg, + ]) + .output() + .unwrap(); + println!("{}", String::from_utf8(output.stdout).unwrap()); + if !output.status.success() { + panic!("{}", String::from_utf8(output.stderr).unwrap()); + } +} From b7333d89f11697a0839a2b0eb1df5691765ae85b Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Tue, 27 Apr 2021 11:32:54 -0400 Subject: [PATCH 06/14] Use INITIAL_NONCE constant --- benches/eth_erc20.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benches/eth_erc20.rs b/benches/eth_erc20.rs index 7e304fbed..59bbeb54b 100644 --- a/benches/eth_erc20.rs +++ b/benches/eth_erc20.rs @@ -31,7 +31,7 @@ fn eth_erc20_benchmark(c: &mut Criterion) { let constructor = ERC20Constructor::load(); let output = exec_transaction( &mut runner, - constructor.deploy("Benchmarker", "BENCH", U256::zero()), + constructor.deploy("Benchmarker", "BENCH", INITIAL_NONCE.into()), &source_account, ); let erc20_address = output.return_data.as_value().unwrap(); From d45b7fcdff1200fb2bd40d5092b4227a7c5c27cd Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Tue, 27 Apr 2021 16:46:48 -0400 Subject: [PATCH 07/14] Add benchmark for the Standard Precompiles --- Cargo.toml | 4 + benches/eth_standard_precompiles.rs | 153 +++++++++++++++++++ benches/res/StandardPrecompiles.sol | 223 ++++++++++++++++++++++++++++ 3 files changed, 380 insertions(+) create mode 100644 benches/eth_standard_precompiles.rs create mode 100644 benches/res/StandardPrecompiles.sol diff --git a/Cargo.toml b/Cargo.toml index 551559b8f..2cf57c13c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,6 +79,10 @@ harness = false name = "eth_erc20" harness = false +[[bench]] +name = "eth_standard_precompiles" +harness = false + [features] default = ["sha2", "std"] std = ["borsh/std", "evm/std", "primitive-types/std", "rlp/std", "sha3/std", "ethabi/std", "lunarity-lexer/std", "bn/std"] diff --git a/benches/eth_standard_precompiles.rs b/benches/eth_standard_precompiles.rs new file mode 100644 index 000000000..20d3dc42d --- /dev/null +++ b/benches/eth_standard_precompiles.rs @@ -0,0 +1,153 @@ +use aurora_engine::prelude::{Address, U256}; +use aurora_engine::transaction::EthTransaction; +use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; +use secp256k1::SecretKey; +use std::path::{Path, PathBuf}; + +// We don't use everything in `common`, but that's ok, other benchmarks do +#[allow(dead_code)] +mod common; +mod solidity; + +use common::{address_from_secret_key, deploy_evm, sign_transaction, RAW_CALL}; + +const INITIAL_BALANCE: u64 = 1000; +const INITIAL_NONCE: u64 = 0; + +fn eth_standard_precompiles_benchmark(c: &mut Criterion) { + let mut runner = deploy_evm(); + let mut rng = rand::thread_rng(); + let source_account = SecretKey::random(&mut rng); + runner.create_address( + address_from_secret_key(&source_account), + INITIAL_BALANCE.into(), + INITIAL_NONCE.into(), + ); + let calling_account_id = "some-account.near".to_string(); + + // deploy StandardPrecompiles contract + let constructor = ContractConstructor::load(); + let tx = constructor.deploy(INITIAL_NONCE.into()); + let signed_tx = sign_transaction(tx, Some(runner.chain_id), &source_account); + let (output, maybe_err) = runner.call( + RAW_CALL, + calling_account_id.clone(), + rlp::encode(&signed_tx).to_vec(), + ); + assert!(maybe_err.is_none()); + let contract_address = output.unwrap().return_data.as_value().unwrap(); + let contract = Contract { + abi: constructor.abi, + address: Address::from_slice(&contract_address), + }; + + // create testing transaction + let tx = contract.test_all(U256::from(INITIAL_NONCE + 1)); + let signed_tx = sign_transaction(tx, Some(runner.chain_id), &source_account); + let tx_bytes = rlp::encode(&signed_tx).to_vec(); + + // measure gas usage + let (output, maybe_err) = + runner + .one_shot() + .call(RAW_CALL, calling_account_id.clone(), tx_bytes.clone()); + println!("{:?}", maybe_err); + assert!(maybe_err.is_none()); + let gas = output.unwrap().burnt_gas; + println!("ETH_STANDARD_PRECOMPILES GAS: {:?}", gas); // TODO: capture this in a file + + // measure wall-clock time + c.bench_function("eth_standard_precompiles", |b| { + b.iter_batched( + || { + ( + runner.one_shot(), + calling_account_id.clone(), + tx_bytes.clone(), + ) + }, + |(r, c, i)| r.call(RAW_CALL, c, i), + BatchSize::SmallInput, + ) + }); +} + +struct ContractConstructor { + abi: ethabi::Contract, + code: Vec, +} + +struct Contract { + abi: ethabi::Contract, + address: Address, +} + +impl ContractConstructor { + fn load() -> Self { + let artifacts_base_path = Self::solidity_artifacts_path(); + let hex_path = artifacts_base_path.join("StandardPrecompiles.bin"); + let hex_rep = match std::fs::read_to_string(&hex_path) { + Ok(hex) => hex, + Err(_) => { + // An error occurred opening the file, maybe the contract hasn't been compiled? + let sources_root = Path::new("benches").join("res"); + solidity::compile( + sources_root, + "StandardPrecompiles.sol", + &artifacts_base_path, + ); + // If another error occurs, then we can't handle it so we just unwrap. + std::fs::read_to_string(hex_path).unwrap() + } + }; + let code = hex::decode(&hex_rep).unwrap(); + let abi_path = artifacts_base_path.join("StandardPrecompiles.abi"); + let reader = std::fs::File::open(abi_path).unwrap(); + let abi = ethabi::Contract::load(reader).unwrap(); + + Self { abi, code } + } + + fn deploy(&self, nonce: U256) -> EthTransaction { + let data = self + .abi + .constructor() + .unwrap() + .encode_input(self.code.clone(), &[]) + .unwrap(); + EthTransaction { + nonce, + gas_price: Default::default(), + gas: Default::default(), + to: None, + value: Default::default(), + data, + } + } + + fn solidity_artifacts_path() -> PathBuf { + Path::new("target").join("solidity_build") + } +} + +impl Contract { + fn test_all(&self, nonce: U256) -> EthTransaction { + let data = self + .abi + .function("test_all") + .unwrap() + .encode_input(&[]) + .unwrap(); + EthTransaction { + nonce, + gas_price: Default::default(), + gas: Default::default(), + to: Some(self.address), + value: Default::default(), + data, + } + } +} + +criterion_group!(benches, eth_standard_precompiles_benchmark); +criterion_main!(benches); diff --git a/benches/res/StandardPrecompiles.sol b/benches/res/StandardPrecompiles.sol new file mode 100644 index 000000000..e55f7718e --- /dev/null +++ b/benches/res/StandardPrecompiles.sol @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; + +//import "hardhat/console.sol"; + +contract StandardPrecompiles { + constructor() payable { + //console.log("Deploying StandardPrecompiles"); + } + + function test_all() public view returns(bool) { + require(test_ecrecover(), "erroneous ecrecover precompile"); + require(test_sha256(), "erroneous sha256 precompile"); + require(test_ripemd160(), "erroneous ripemd160 precompile"); + require(test_identity(), "erroneous identity precompile"); + require(test_modexp(), "erroneous modexp precompile"); + require(test_ecadd(), "erroneous ecadd precompile"); + require(test_ecmul(), "erroneous ecmul precompile"); + // TODO: ecpair uses up all the gas (by itself) for some reason, need to look into this. + // require(test_ecpair(), "erroneous ecpair precompile"); + require(test_blake2f(), "erroneous blake2f precompile"); + return true; + } + + // See: https://docs.soliditylang.org/en/develop/units-and-global-variables.html#mathematical-and-cryptographic-functions + // See: https://etherscan.io/address/0x0000000000000000000000000000000000000001 + function test_ecrecover() public pure returns(bool) { + bytes32 hash = hex"1111111111111111111111111111111111111111111111111111111111111111"; + bytes memory sig = hex"b9f0bb08640d3c1c00761cdd0121209268f6fd3816bc98b9e6f3cc77bf82b69812ac7a61788a0fdc0e19180f14c945a8e1088a27d92a74dce81c0981fb6447441b"; + address signer = 0x1563915e194D8CfBA1943570603F7606A3115508; + return ecverify(hash, sig, signer); + } + + // See: https://docs.soliditylang.org/en/develop/units-and-global-variables.html#mathematical-and-cryptographic-functions + // See: https://etherscan.io/address/0x0000000000000000000000000000000000000002 + function test_sha256() public pure returns(bool) { + return sha256("") == hex"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; + } + + // See: https://docs.soliditylang.org/en/develop/units-and-global-variables.html#mathematical-and-cryptographic-functions + // See: https://etherscan.io/address/0x0000000000000000000000000000000000000003 + function test_ripemd160() public pure returns(bool) { + return ripemd160("") == hex"9c1185a5c5e9fc54612808977ee8f548b2258d31"; + } + + // See: https://etherscan.io/address/0x0000000000000000000000000000000000000004 + function test_identity() public view returns(bool) { + bytes memory data = hex"1111111111111111111111111111111111111111111111111111111111111111"; + return keccak256(datacopy(data)) == keccak256(data); + } + + // See: https://eips.ethereum.org/EIPS/eip-198 + // See: https://etherscan.io/address/0x0000000000000000000000000000000000000005 + function test_modexp() public view returns(bool) { + uint256 base = 3; + uint256 exponent = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e; + uint256 modulus = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f; + return modexp(base, exponent, modulus) == 1; + } + + // See: https://eips.ethereum.org/EIPS/eip-196 + // See: https://etherscan.io/address/0x0000000000000000000000000000000000000006 + function test_ecadd() public view returns(bool) { + // alt_bn128_add_chfast1: + bytes32[2] memory result; + result = ecadd( + 0x18b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9, + 0x063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f37266, + 0x07c2b7f58a84bd6145f00c9c2bc0bb1a187f20ff2c92963a88019e7c6a014eed, + 0x06614e20c147e940f2d70da3f74c9a17df361706a4485c742bd6788478fa17d7 + ); + return result[0] == 0x2243525c5efd4b9c3d3c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee202839703 && result[1] == 0x301d1d33be6da8e509df21cc35964723180eed7532537db9ae5e7d48f195c915; + } + + // See: https://eips.ethereum.org/EIPS/eip-196 + // See: https://etherscan.io/address/0x0000000000000000000000000000000000000007 + function test_ecmul() public view returns(bool) { + // alt_bn128_mul_chfast1: + bytes32[2] memory result; + result = ecmul( + 0x2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb7, + 0x21611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb204, + 0x00000000000000000000000000000000000000000000000011138ce750fa15c2 + ); + return result[0] == 0x070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c && result[1] == 0x031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc; + } + + // See: https://eips.ethereum.org/EIPS/eip-197 + // See: https://etherscan.io/address/0x0000000000000000000000000000000000000008 + function test_ecpair() public view returns(bool) { + // alt_bn128_pairing_jeff1: + bytes32 result = ecpair(hex"1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa"); + return result == 0x0000000000000000000000000000000000000000000000000000000000000001; + } + + // See: https://eips.ethereum.org/EIPS/eip-152 + // See: https://etherscan.io/address/0x0000000000000000000000000000000000000009 + function test_blake2f() public view returns(bool) { + uint32 rounds = 12; + bytes32[2] memory h; + h[0] = hex"48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5"; + h[1] = hex"d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b"; + bytes32[4] memory m; + m[0] = hex"6162630000000000000000000000000000000000000000000000000000000000"; + m[1] = hex"0000000000000000000000000000000000000000000000000000000000000000"; + m[2] = hex"0000000000000000000000000000000000000000000000000000000000000000"; + m[3] = hex"0000000000000000000000000000000000000000000000000000000000000000"; + bytes8[2] memory t; + t[0] = hex"03000000"; + t[1] = hex"00000000"; + bool f = true; + bytes32[2] memory result = blake2f(rounds, h, m, t, f); + return result[0] == hex"ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1" && result[1] == hex"7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923"; + } + + function ecverify(bytes32 hash, bytes memory sig, address signer) private pure returns (bool) { + bool ok; + address addr; + (ok, addr) = ecrecovery(hash, sig); + return ok && addr == signer; + } + + function ecrecovery(bytes32 hash, bytes memory sig) private pure returns (bool, address) { + if (sig.length != 65) + return (false, address(0)); + + bytes32 r; + bytes32 s; + uint8 v; + assembly { + r := mload(add(sig, 32)) + s := mload(add(sig, 64)) + v := byte(0, mload(add(sig, 96))) + } + + address addr = ecrecover(hash, v, r, s); + return (true, addr); + } + + function datacopy(bytes memory input) private view returns (bytes memory) { + bytes memory output = new bytes(input.length); + assembly { + let len := mload(input) + let ok := staticcall(gas(), 0x04, add(input, 32), len, add(output, 32), len) + switch ok + case 0 { + revert(0, 0) + } + } + return output; + } + + function modexp(uint256 base, uint256 exponent, uint256 modulus) private view returns (uint256 output) { + assembly { + let ptr := mload(0x40) + mstore(ptr, 32) + mstore(add(ptr, 0x20), 32) + mstore(add(ptr, 0x40), 32) + mstore(add(ptr, 0x60), base) + mstore(add(ptr, 0x80), exponent) + mstore(add(ptr, 0xA0), modulus) + let ok := staticcall(gas(), 0x05, ptr, 0xC0, ptr, 0x20) + switch ok + case 0 { + revert(0, 0) + } + default { + output := mload(ptr) + } + } + } + + function ecadd(bytes32 ax, bytes32 ay, bytes32 bx, bytes32 by) private view returns (bytes32[2] memory output) { + bytes32[4] memory input = [ax, ay, bx, by]; + assembly { + let ok := staticcall(gas(), 0x06, input, 0x80, output, 0x40) + switch ok + case 0 { + revert(0, 0) + } + } + } + + function ecmul(bytes32 x, bytes32 y, bytes32 scalar) private view returns (bytes32[2] memory output) { + bytes32[3] memory input = [x, y, scalar]; + assembly { + let ok := staticcall(gas(), 0x07, input, 0x60, output, 0x40) + switch ok + case 0 { + revert(0, 0) + } + } + } + + function ecpair(bytes memory input) private view returns (bytes32 output) { + uint256 len = input.length; + require(len % 192 == 0); + assembly { + let ptr := mload(0x40) + let ok := staticcall(gas(), 0x08, add(input, 32), len, ptr, 0x20) + switch ok + case 0 { + revert(0, 0) + } + default { + output := mload(ptr) + } + } + } + + function blake2f(uint32 rounds, bytes32[2] memory h, bytes32[4] memory m, bytes8[2] memory t, bool f) private view returns (bytes32[2] memory) { + bytes32[2] memory output; + bytes memory args = abi.encodePacked(rounds, h[0], h[1], m[0], m[1], m[2], m[3], t[0], t[1], f); + assembly { + let ok := staticcall(gas(), 0x09, add(args, 32), 0xD5, output, 0x40) + switch ok + case 0 { + revert(0, 0) + } + } + return output; + } +} From b9bc8a74aa75caa91105432ed2114881d8adb1ca Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Wed, 28 Apr 2021 10:39:24 -0400 Subject: [PATCH 08/14] Benchmark each pre-compile individually in addition to all of them together --- benches/eth_standard_precompiles.rs | 87 +++++++++++++++++++---------- 1 file changed, 59 insertions(+), 28 deletions(-) diff --git a/benches/eth_standard_precompiles.rs b/benches/eth_standard_precompiles.rs index 20d3dc42d..e46246572 100644 --- a/benches/eth_standard_precompiles.rs +++ b/benches/eth_standard_precompiles.rs @@ -1,6 +1,6 @@ use aurora_engine::prelude::{Address, U256}; use aurora_engine::transaction::EthTransaction; -use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; +use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion}; use secp256k1::SecretKey; use std::path::{Path, PathBuf}; @@ -41,35 +41,50 @@ fn eth_standard_precompiles_benchmark(c: &mut Criterion) { address: Address::from_slice(&contract_address), }; - // create testing transaction - let tx = contract.test_all(U256::from(INITIAL_NONCE + 1)); - let signed_tx = sign_transaction(tx, Some(runner.chain_id), &source_account); - let tx_bytes = rlp::encode(&signed_tx).to_vec(); + let test_names = Contract::all_method_names(); + let bench_ids: Vec<_> = test_names.iter().map(BenchmarkId::from_parameter).collect(); + + // create testing transactions + let transactions: Vec<_> = test_names + .iter() + .map(|method_name| { + let tx = contract.call_method(method_name, U256::from(INITIAL_NONCE + 1)); + let signed_tx = sign_transaction(tx, Some(runner.chain_id), &source_account); + rlp::encode(&signed_tx).to_vec() + }) + .collect(); // measure gas usage - let (output, maybe_err) = - runner - .one_shot() - .call(RAW_CALL, calling_account_id.clone(), tx_bytes.clone()); - println!("{:?}", maybe_err); - assert!(maybe_err.is_none()); - let gas = output.unwrap().burnt_gas; - println!("ETH_STANDARD_PRECOMPILES GAS: {:?}", gas); // TODO: capture this in a file + for (tx_bytes, name) in transactions.iter().zip(test_names.iter()) { + let (output, maybe_err) = + runner + .one_shot() + .call(RAW_CALL, calling_account_id.clone(), tx_bytes.clone()); + assert!(maybe_err.is_none()); + let gas = output.unwrap().burnt_gas; + println!("ETH_STANDARD_PRECOMPILES_{} GAS: {:?}", name, gas); // TODO: capture this in a file + } + + let mut group = c.benchmark_group("standard_precompiles"); // measure wall-clock time - c.bench_function("eth_standard_precompiles", |b| { - b.iter_batched( - || { - ( - runner.one_shot(), - calling_account_id.clone(), - tx_bytes.clone(), - ) - }, - |(r, c, i)| r.call(RAW_CALL, c, i), - BatchSize::SmallInput, - ) - }); + for (tx_bytes, id) in transactions.iter().zip(bench_ids.into_iter()) { + group.bench_function(id, |b| { + b.iter_batched( + || { + ( + runner.one_shot(), + calling_account_id.clone(), + tx_bytes.clone(), + ) + }, + |(r, c, i)| r.call(RAW_CALL, c, i), + BatchSize::SmallInput, + ) + }); + } + + group.finish(); } struct ContractConstructor { @@ -131,10 +146,10 @@ impl ContractConstructor { } impl Contract { - fn test_all(&self, nonce: U256) -> EthTransaction { + fn call_method(&self, method_name: &str, nonce: U256) -> EthTransaction { let data = self .abi - .function("test_all") + .function(method_name) .unwrap() .encode_input(&[]) .unwrap(); @@ -147,6 +162,22 @@ impl Contract { data, } } + + fn all_method_names() -> &'static [&'static str] { + &[ + "test_ecrecover", + "test_sha256", + "test_ripemd160", + "test_identity", + "test_modexp", + "test_ecadd", + "test_ecmul", + // TODO: ecpair uses up all the gas (by itself) for some reason, need to look into this. + // "test_ecpair", + "test_blake2f", + "test_all", + ] + } } criterion_group!(benches, eth_standard_precompiles_benchmark); From 3161d1668edd2ab461af8e11389248eaf7b33dfc Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Wed, 28 Apr 2021 10:42:26 -0400 Subject: [PATCH 09/14] Reference issue numbers in remaining TODOs --- benches/eth_deploy_code.rs | 2 +- benches/eth_erc20.rs | 6 ++++-- benches/eth_standard_precompiles.rs | 5 +++-- benches/eth_transfer.rs | 3 ++- benches/res/StandardPrecompiles.sol | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/benches/eth_deploy_code.rs b/benches/eth_deploy_code.rs index 588537523..429d1dc6b 100644 --- a/benches/eth_deploy_code.rs +++ b/benches/eth_deploy_code.rs @@ -45,7 +45,7 @@ fn eth_deploy_code_benchmark(c: &mut Criterion) { .call(RAW_CALL, calling_account_id.clone(), input.clone()); assert!(maybe_err.is_none()); let gas = output.unwrap().burnt_gas; - // TODO: capture this in a file + // TODO(#45): capture this in a file println!("ETH_DEPLOY_CODE_{:?} GAS: {:?}", input_size, gas); } diff --git a/benches/eth_erc20.rs b/benches/eth_erc20.rs index 59bbeb54b..468ee9957 100644 --- a/benches/eth_erc20.rs +++ b/benches/eth_erc20.rs @@ -84,7 +84,8 @@ fn eth_erc20_benchmark(c: &mut Criterion) { runner.call(RAW_CALL, calling_account_id.clone(), mint_tx_bytes.clone()); assert!(maybe_error.is_none()); let gas = output.unwrap().burnt_gas; - println!("ETH_ERC20_MINT GAS: {:?}", gas); // TODO: capture this in a file + // TODO(#45): capture this in a file + println!("ETH_ERC20_MINT GAS: {:?}", gas); // Measure transfer gas usage let (output, maybe_err) = runner.one_shot().call( @@ -94,7 +95,8 @@ fn eth_erc20_benchmark(c: &mut Criterion) { ); assert!(maybe_err.is_none()); let gas = output.unwrap().burnt_gas; - println!("ETH_ERC20_TRANSFER GAS: {:?}", gas); // TODO: capture this in a file + // TODO(#45): capture this in a file + println!("ETH_ERC20_TRANSFER GAS: {:?}", gas); // measure transfer wall-clock time group.bench_function(transfer_id, |b| { diff --git a/benches/eth_standard_precompiles.rs b/benches/eth_standard_precompiles.rs index e46246572..0b2960416 100644 --- a/benches/eth_standard_precompiles.rs +++ b/benches/eth_standard_precompiles.rs @@ -62,7 +62,8 @@ fn eth_standard_precompiles_benchmark(c: &mut Criterion) { .call(RAW_CALL, calling_account_id.clone(), tx_bytes.clone()); assert!(maybe_err.is_none()); let gas = output.unwrap().burnt_gas; - println!("ETH_STANDARD_PRECOMPILES_{} GAS: {:?}", name, gas); // TODO: capture this in a file + // TODO(#45): capture this in a file + println!("ETH_STANDARD_PRECOMPILES_{} GAS: {:?}", name, gas); } let mut group = c.benchmark_group("standard_precompiles"); @@ -172,7 +173,7 @@ impl Contract { "test_modexp", "test_ecadd", "test_ecmul", - // TODO: ecpair uses up all the gas (by itself) for some reason, need to look into this. + // TODO(#46): ecpair uses up all the gas (by itself) for some reason, need to look into this. // "test_ecpair", "test_blake2f", "test_all", diff --git a/benches/eth_transfer.rs b/benches/eth_transfer.rs index 355794ae2..2fbff42cf 100644 --- a/benches/eth_transfer.rs +++ b/benches/eth_transfer.rs @@ -36,7 +36,8 @@ fn eth_transfer_benchmark(c: &mut Criterion) { .call(RAW_CALL, calling_account_id.clone(), input.clone()); assert!(maybe_err.is_none()); let gas = output.unwrap().burnt_gas; - println!("ETH_TRANSFER GAS: {:?}", gas); // TODO: capture this in a file + // TODO(#45): capture this in a file + println!("ETH_TRANSFER GAS: {:?}", gas); // measure wall-clock time c.bench_function("eth_transfer", |b| { diff --git a/benches/res/StandardPrecompiles.sol b/benches/res/StandardPrecompiles.sol index e55f7718e..0d1fe4c97 100644 --- a/benches/res/StandardPrecompiles.sol +++ b/benches/res/StandardPrecompiles.sol @@ -16,7 +16,7 @@ contract StandardPrecompiles { require(test_modexp(), "erroneous modexp precompile"); require(test_ecadd(), "erroneous ecadd precompile"); require(test_ecmul(), "erroneous ecmul precompile"); - // TODO: ecpair uses up all the gas (by itself) for some reason, need to look into this. + // TODO(#46): ecpair uses up all the gas (by itself) for some reason, need to look into this. // require(test_ecpair(), "erroneous ecpair precompile"); require(test_blake2f(), "erroneous blake2f precompile"); return true; From 58c720dfcd159f177a875eedaac0cc5829dd6855 Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Thu, 29 Apr 2021 11:49:53 -0400 Subject: [PATCH 10/14] Add feature flag for profiling eth gas used as well --- Cargo.toml | 1 + benches/common.rs | 17 +++++++++++++++++ benches/eth_deploy_code.rs | 12 ++++++++++-- benches/eth_erc20.rs | 22 ++++++++++++++++++---- benches/eth_standard_precompiles.rs | 11 +++++++++-- benches/eth_transfer.rs | 5 ++++- src/engine.rs | 18 ++++++++++++++++++ src/prelude.rs | 3 +++ 8 files changed, 80 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2cf57c13c..36471ae3e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -89,3 +89,4 @@ std = ["borsh/std", "evm/std", "primitive-types/std", "rlp/std", "sha3/std", "et testnet = [] contract = [] evm_bully = [] +profile_eth_gas = [] diff --git a/benches/common.rs b/benches/common.rs index e256ebc1c..ae88d5e98 100644 --- a/benches/common.rs +++ b/benches/common.rs @@ -17,6 +17,9 @@ use aurora_engine::storage; use aurora_engine::transaction::{EthSignedTransaction, EthTransaction}; use aurora_engine::types; +#[cfg(feature = "profile_eth_gas")] +use aurora_engine::prelude::ETH_GAS_USED; + near_sdk_sim::lazy_static_include::lazy_static_include_bytes! { EVM_WASM_BYTES => "release.wasm" } @@ -226,3 +229,17 @@ pub fn address_from_secret_key(sk: &SecretKey) -> Address { let hash = types::keccak(&pk.serialize()[1..]); Address::from_slice(&hash[12..]) } + +#[cfg(feature = "profile_eth_gas")] +pub fn parse_eth_gas(output: &VMOutcome) -> u64 { + for log in output.logs.iter() { + if log.starts_with(ETH_GAS_USED) { + let eth_gas: Option = log + .split_ascii_whitespace() + .last() + .and_then(|x| x.parse().ok()); + return eth_gas.unwrap(); + } + } + panic!("Failed to parse Eth gas from the output logs. Was the EVM contract compiled with `--features profile_eth_gas`?"); +} diff --git a/benches/eth_deploy_code.rs b/benches/eth_deploy_code.rs index 429d1dc6b..11782a7e9 100644 --- a/benches/eth_deploy_code.rs +++ b/benches/eth_deploy_code.rs @@ -44,9 +44,17 @@ fn eth_deploy_code_benchmark(c: &mut Criterion) { .one_shot() .call(RAW_CALL, calling_account_id.clone(), input.clone()); assert!(maybe_err.is_none()); - let gas = output.unwrap().burnt_gas; + let output = output.unwrap(); + let gas = output.burnt_gas; // TODO(#45): capture this in a file - println!("ETH_DEPLOY_CODE_{:?} GAS: {:?}", input_size, gas); + println!("ETH_DEPLOY_CODE_{:?} NEAR GAS: {:?}", input_size, gas); + + #[cfg(feature = "profile_eth_gas")] + { + let eth_gas = common::parse_eth_gas(&output); + // TODO(#45): capture this in a file + println!("ETH_DEPLOY_CODE_{:?} ETH GAS: {:?}", input_size, eth_gas); + } } // measure wall-clock time diff --git a/benches/eth_erc20.rs b/benches/eth_erc20.rs index 468ee9957..634f1f137 100644 --- a/benches/eth_erc20.rs +++ b/benches/eth_erc20.rs @@ -83,9 +83,16 @@ fn eth_erc20_benchmark(c: &mut Criterion) { let (output, maybe_error) = runner.call(RAW_CALL, calling_account_id.clone(), mint_tx_bytes.clone()); assert!(maybe_error.is_none()); - let gas = output.unwrap().burnt_gas; + let output = output.unwrap(); + let gas = output.burnt_gas; // TODO(#45): capture this in a file - println!("ETH_ERC20_MINT GAS: {:?}", gas); + println!("ETH_ERC20_MINT NEAR GAS: {:?}", gas); + #[cfg(feature = "profile_eth_gas")] + { + let eth_gas = common::parse_eth_gas(&output); + // TODO(#45): capture this in a file + println!("ETH_ERC20_MINT ETH GAS: {:?}", eth_gas); + } // Measure transfer gas usage let (output, maybe_err) = runner.one_shot().call( @@ -94,9 +101,16 @@ fn eth_erc20_benchmark(c: &mut Criterion) { transfer_tx_bytes.clone(), ); assert!(maybe_err.is_none()); - let gas = output.unwrap().burnt_gas; + let output = output.unwrap(); + let gas = output.burnt_gas; // TODO(#45): capture this in a file - println!("ETH_ERC20_TRANSFER GAS: {:?}", gas); + println!("ETH_ERC20_TRANSFER NEAR GAS: {:?}", gas); + #[cfg(feature = "profile_eth_gas")] + { + let eth_gas = common::parse_eth_gas(&output); + // TODO(#45): capture this in a file + println!("ETH_ERC20_TRANSFER ETH GAS: {:?}", eth_gas); + } // measure transfer wall-clock time group.bench_function(transfer_id, |b| { diff --git a/benches/eth_standard_precompiles.rs b/benches/eth_standard_precompiles.rs index 0b2960416..000c5238c 100644 --- a/benches/eth_standard_precompiles.rs +++ b/benches/eth_standard_precompiles.rs @@ -61,9 +61,16 @@ fn eth_standard_precompiles_benchmark(c: &mut Criterion) { .one_shot() .call(RAW_CALL, calling_account_id.clone(), tx_bytes.clone()); assert!(maybe_err.is_none()); - let gas = output.unwrap().burnt_gas; + let output = output.unwrap(); + let gas = output.burnt_gas; // TODO(#45): capture this in a file - println!("ETH_STANDARD_PRECOMPILES_{} GAS: {:?}", name, gas); + println!("ETH_STANDARD_PRECOMPILES_{} NEAR GAS: {:?}", name, gas); + #[cfg(feature = "profile_eth_gas")] + { + let eth_gas = common::parse_eth_gas(&output); + // TODO(#45): capture this in a file + println!("ETH_STANDARD_PRECOMPILES_{} ETH GAS: {:?}", name, eth_gas); + } } let mut group = c.benchmark_group("standard_precompiles"); diff --git a/benches/eth_transfer.rs b/benches/eth_transfer.rs index 2fbff42cf..09c438afb 100644 --- a/benches/eth_transfer.rs +++ b/benches/eth_transfer.rs @@ -1,6 +1,7 @@ use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; use secp256k1::SecretKey; +#[allow(dead_code)] mod common; use common::{address_from_secret_key, create_eth_transaction, deploy_evm, RAW_CALL}; @@ -37,7 +38,9 @@ fn eth_transfer_benchmark(c: &mut Criterion) { assert!(maybe_err.is_none()); let gas = output.unwrap().burnt_gas; // TODO(#45): capture this in a file - println!("ETH_TRANSFER GAS: {:?}", gas); + println!("ETH_TRANSFER NEAR GAS: {:?}", gas); + #[cfg(feature = "profile_eth_gas")] + println!("ETH_TRANSFER ETH GAS: {:?}", 21_000); // measure wall-clock time c.bench_function("eth_transfer", |b| { diff --git a/src/engine.rs b/src/engine.rs index 33b4a1d4a..d92870cab 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -258,6 +258,10 @@ impl Engine { executor.transact_create(origin, value, Vec::from(input), u64::MAX), address, ); + + #[cfg(feature = "profile_eth_gas")] + log_eth_gas_used(&executor); + let (values, logs) = executor.into_state().deconstruct(); self.apply(values, logs, true); (status, result) @@ -279,6 +283,10 @@ impl Engine { ) -> (ExitReason, Vec) { let mut executor = self.make_executor(); let (status, result) = executor.transact_call(origin, contract, value, input, u64::MAX); + + #[cfg(feature = "profile_eth_gas")] + log_eth_gas_used(&executor); + let (values, logs) = executor.into_state().deconstruct(); self.apply(values, logs, true); (status, result) @@ -318,6 +326,16 @@ impl Engine { } } +#[cfg(feature = "profile_eth_gas")] +fn log_eth_gas_used(executor: &StackExecutor>) { + use alloc::format; + sdk::log(format!( + "{}: {}", + crate::prelude::ETH_GAS_USED, + executor.used_gas() + )); +} + impl evm::backend::Backend for Engine { fn gas_price(&self) -> U256 { U256::zero() diff --git a/src/prelude.rs b/src/prelude.rs index 957686442..ae7b69619 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -26,3 +26,6 @@ pub type Address = H160; pub fn Address(input: [u8; 20]) -> Address { H160(input) } + +#[cfg(feature = "profile_eth_gas")] +pub const ETH_GAS_USED: &str = "ETH_GAS_USED"; From ba85dd496da59f6fbcbea8680a1dbef21fd94b9b Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Fri, 30 Apr 2021 12:08:12 -0400 Subject: [PATCH 11/14] Re-organize code so there is a single entry-point for all benchmarks --- Cargo.toml | 16 +++------------- benches/eth_deploy_code.rs | 9 +++------ benches/eth_erc20.rs | 15 +++++---------- benches/eth_standard_precompiles.rs | 13 ++++--------- benches/eth_transfer.rs | 8 ++------ benches/{common.rs => main.rs} | 14 ++++++++++++++ 6 files changed, 31 insertions(+), 44 deletions(-) rename benches/{common.rs => main.rs} (96%) diff --git a/Cargo.toml b/Cargo.toml index 36471ae3e..2b6326bee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ homepage = "https://github.com/aurora-is-near/aurora-engine" repository = "https://github.com/aurora-is-near/aurora-engine" license = "CC0-1.0" publish = false +autobenches = false [lib] crate-type = ["cdylib", "rlib"] @@ -68,19 +69,8 @@ criterion = "0.3.4" git2 = "0.13" [[bench]] -name = "eth_transfer" -harness = false - -[[bench]] -name = "eth_deploy_code" -harness = false - -[[bench]] -name = "eth_erc20" -harness = false - -[[bench]] -name = "eth_standard_precompiles" +name = "benches" +path = "benches/main.rs" harness = false [features] diff --git a/benches/eth_deploy_code.rs b/benches/eth_deploy_code.rs index 11782a7e9..6a5f8dc02 100644 --- a/benches/eth_deploy_code.rs +++ b/benches/eth_deploy_code.rs @@ -1,9 +1,7 @@ -use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion, Throughput}; +use criterion::{criterion_group, BatchSize, BenchmarkId, Criterion, Throughput}; use secp256k1::SecretKey; -mod common; - -use common::{address_from_secret_key, create_eth_transaction, deploy_evm, RAW_CALL}; +use super::{address_from_secret_key, create_eth_transaction, deploy_evm, RAW_CALL}; const INITIAL_BALANCE: u64 = 1000; const INITIAL_NONCE: u64 = 0; @@ -51,7 +49,7 @@ fn eth_deploy_code_benchmark(c: &mut Criterion) { #[cfg(feature = "profile_eth_gas")] { - let eth_gas = common::parse_eth_gas(&output); + let eth_gas = super::parse_eth_gas(&output); // TODO(#45): capture this in a file println!("ETH_DEPLOY_CODE_{:?} ETH GAS: {:?}", input_size, eth_gas); } @@ -75,4 +73,3 @@ fn eth_deploy_code_benchmark(c: &mut Criterion) { } criterion_group!(benches, eth_deploy_code_benchmark); -criterion_main!(benches); diff --git a/benches/eth_erc20.rs b/benches/eth_erc20.rs index 634f1f137..19a09062b 100644 --- a/benches/eth_erc20.rs +++ b/benches/eth_erc20.rs @@ -1,16 +1,12 @@ use aurora_engine::prelude::{Address, U256}; use aurora_engine::transaction::EthTransaction; -use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion}; +use criterion::{criterion_group, BatchSize, BenchmarkId, Criterion}; use near_vm_logic::VMOutcome; use secp256k1::SecretKey; use std::path::{Path, PathBuf}; -// We don't use everything in `common`, but that's ok, other benchmarks do -#[allow(dead_code)] -mod common; -mod solidity; - -use common::{address_from_secret_key, deploy_evm, sign_transaction, AuroraRunner, RAW_CALL}; +use super::{address_from_secret_key, deploy_evm, sign_transaction, AuroraRunner, RAW_CALL}; +use crate::solidity; const INITIAL_BALANCE: u64 = 1000; const INITIAL_NONCE: u64 = 0; @@ -89,7 +85,7 @@ fn eth_erc20_benchmark(c: &mut Criterion) { println!("ETH_ERC20_MINT NEAR GAS: {:?}", gas); #[cfg(feature = "profile_eth_gas")] { - let eth_gas = common::parse_eth_gas(&output); + let eth_gas = super::parse_eth_gas(&output); // TODO(#45): capture this in a file println!("ETH_ERC20_MINT ETH GAS: {:?}", eth_gas); } @@ -107,7 +103,7 @@ fn eth_erc20_benchmark(c: &mut Criterion) { println!("ETH_ERC20_TRANSFER NEAR GAS: {:?}", gas); #[cfg(feature = "profile_eth_gas")] { - let eth_gas = common::parse_eth_gas(&output); + let eth_gas = super::parse_eth_gas(&output); // TODO(#45): capture this in a file println!("ETH_ERC20_TRANSFER ETH GAS: {:?}", eth_gas); } @@ -266,4 +262,3 @@ fn exec_transaction( } criterion_group!(benches, eth_erc20_benchmark); -criterion_main!(benches); diff --git a/benches/eth_standard_precompiles.rs b/benches/eth_standard_precompiles.rs index 000c5238c..c81952d2f 100644 --- a/benches/eth_standard_precompiles.rs +++ b/benches/eth_standard_precompiles.rs @@ -1,15 +1,11 @@ use aurora_engine::prelude::{Address, U256}; use aurora_engine::transaction::EthTransaction; -use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion}; +use criterion::{criterion_group, BatchSize, BenchmarkId, Criterion}; use secp256k1::SecretKey; use std::path::{Path, PathBuf}; -// We don't use everything in `common`, but that's ok, other benchmarks do -#[allow(dead_code)] -mod common; -mod solidity; - -use common::{address_from_secret_key, deploy_evm, sign_transaction, RAW_CALL}; +use super::{address_from_secret_key, deploy_evm, sign_transaction, RAW_CALL}; +use crate::solidity; const INITIAL_BALANCE: u64 = 1000; const INITIAL_NONCE: u64 = 0; @@ -67,7 +63,7 @@ fn eth_standard_precompiles_benchmark(c: &mut Criterion) { println!("ETH_STANDARD_PRECOMPILES_{} NEAR GAS: {:?}", name, gas); #[cfg(feature = "profile_eth_gas")] { - let eth_gas = common::parse_eth_gas(&output); + let eth_gas = super::parse_eth_gas(&output); // TODO(#45): capture this in a file println!("ETH_STANDARD_PRECOMPILES_{} ETH GAS: {:?}", name, eth_gas); } @@ -189,4 +185,3 @@ impl Contract { } criterion_group!(benches, eth_standard_precompiles_benchmark); -criterion_main!(benches); diff --git a/benches/eth_transfer.rs b/benches/eth_transfer.rs index 09c438afb..80cc64b16 100644 --- a/benches/eth_transfer.rs +++ b/benches/eth_transfer.rs @@ -1,10 +1,7 @@ -use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; +use criterion::{criterion_group, BatchSize, Criterion}; use secp256k1::SecretKey; -#[allow(dead_code)] -mod common; - -use common::{address_from_secret_key, create_eth_transaction, deploy_evm, RAW_CALL}; +use super::{address_from_secret_key, create_eth_transaction, deploy_evm, RAW_CALL}; const INITIAL_BALANCE: u64 = 1000; const INITIAL_NONCE: u64 = 0; @@ -53,4 +50,3 @@ fn eth_transfer_benchmark(c: &mut Criterion) { } criterion_group!(benches, eth_transfer_benchmark); -criterion_main!(benches); diff --git a/benches/common.rs b/benches/main.rs similarity index 96% rename from benches/common.rs rename to benches/main.rs index ae88d5e98..f2174aef4 100644 --- a/benches/common.rs +++ b/benches/main.rs @@ -1,4 +1,5 @@ use borsh::BorshSerialize; +use criterion::criterion_main; use near_primitives_core::config::VMConfig; use near_primitives_core::contract::ContractCode; use near_primitives_core::profile::ProfileData; @@ -20,12 +21,25 @@ use aurora_engine::types; #[cfg(feature = "profile_eth_gas")] use aurora_engine::prelude::ETH_GAS_USED; +mod eth_deploy_code; +mod eth_erc20; +mod eth_standard_precompiles; +mod eth_transfer; +mod solidity; + near_sdk_sim::lazy_static_include::lazy_static_include_bytes! { EVM_WASM_BYTES => "release.wasm" } pub const RAW_CALL: &str = "raw_call"; +criterion_main!( + eth_deploy_code::benches, + eth_erc20::benches, + eth_standard_precompiles::benches, + eth_transfer::benches +); + pub struct AuroraRunner { pub aurora_account_id: String, pub chain_id: u64, From 4fb6f98cad83c948c7f07d741b46426f4a39f48c Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Fri, 30 Apr 2021 12:12:34 -0400 Subject: [PATCH 12/14] Use vec macro --- benches/eth_deploy_code.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benches/eth_deploy_code.rs b/benches/eth_deploy_code.rs index 6a5f8dc02..b5a6defe7 100644 --- a/benches/eth_deploy_code.rs +++ b/benches/eth_deploy_code.rs @@ -21,7 +21,7 @@ fn eth_deploy_code_benchmark(c: &mut Criterion) { .copied() .map(|n| { let code_size = 2usize.pow(n); - let code: Vec = std::iter::repeat(0).take(code_size).collect(); + let code: Vec = vec![0; code_size]; let transaction = create_eth_transaction( None, TRANSFER_AMOUNT.into(), From 58e0cc479a92e2aabd6beadf27087a5c5fef74eb Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Fri, 30 Apr 2021 12:17:59 -0400 Subject: [PATCH 13/14] sdk::log takes &str instead of String --- src/engine.rs | 2 +- src/sdk.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine.rs b/src/engine.rs index d92870cab..62925e20b 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -329,7 +329,7 @@ impl Engine { #[cfg(feature = "profile_eth_gas")] fn log_eth_gas_used(executor: &StackExecutor>) { use alloc::format; - sdk::log(format!( + sdk::log(&format!( "{}: {}", crate::prelude::ETH_GAS_USED, executor.used_gas() diff --git a/src/sdk.rs b/src/sdk.rs index d5d4e31b5..8832e31fb 100644 --- a/src/sdk.rs +++ b/src/sdk.rs @@ -343,7 +343,7 @@ pub fn get_contract_data(key: &str) -> T { } #[allow(dead_code)] -pub fn log(data: String) { +pub fn log(data: &str) { log_utf8(data.as_bytes()) } From 4c62a87b44014d4725622d7e44d6c502b1dfa69e Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Mon, 3 May 2021 11:13:04 -0400 Subject: [PATCH 14/14] Use new SubmitResult return data --- Cargo.toml | 1 - benches/eth_deploy_code.rs | 15 ++++------- benches/eth_erc20.rs | 41 ++++++++++++----------------- benches/eth_standard_precompiles.rs | 24 ++++++++--------- benches/eth_transfer.rs | 7 +++-- benches/main.rs | 24 +++++++---------- src/engine.rs | 16 ----------- src/prelude.rs | 3 --- 8 files changed, 47 insertions(+), 84 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2b6326bee..842afc4db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,4 +79,3 @@ std = ["borsh/std", "evm/std", "primitive-types/std", "rlp/std", "sha3/std", "et testnet = [] contract = [] evm_bully = [] -profile_eth_gas = [] diff --git a/benches/eth_deploy_code.rs b/benches/eth_deploy_code.rs index b5a6defe7..7fa9a6df0 100644 --- a/benches/eth_deploy_code.rs +++ b/benches/eth_deploy_code.rs @@ -1,7 +1,7 @@ use criterion::{criterion_group, BatchSize, BenchmarkId, Criterion, Throughput}; use secp256k1::SecretKey; -use super::{address_from_secret_key, create_eth_transaction, deploy_evm, RAW_CALL}; +use super::{address_from_secret_key, create_eth_transaction, deploy_evm, SUBMIT}; const INITIAL_BALANCE: u64 = 1000; const INITIAL_NONCE: u64 = 0; @@ -40,19 +40,14 @@ fn eth_deploy_code_benchmark(c: &mut Criterion) { let (output, maybe_err) = runner .one_shot() - .call(RAW_CALL, calling_account_id.clone(), input.clone()); + .call(SUBMIT, calling_account_id.clone(), input.clone()); assert!(maybe_err.is_none()); let output = output.unwrap(); let gas = output.burnt_gas; + let eth_gas = super::parse_eth_gas(&output); // TODO(#45): capture this in a file println!("ETH_DEPLOY_CODE_{:?} NEAR GAS: {:?}", input_size, gas); - - #[cfg(feature = "profile_eth_gas")] - { - let eth_gas = super::parse_eth_gas(&output); - // TODO(#45): capture this in a file - println!("ETH_DEPLOY_CODE_{:?} ETH GAS: {:?}", input_size, eth_gas); - } + println!("ETH_DEPLOY_CODE_{:?} ETH GAS: {:?}", input_size, eth_gas); } // measure wall-clock time @@ -64,7 +59,7 @@ fn eth_deploy_code_benchmark(c: &mut Criterion) { group.bench_function(id, |b| { b.iter_batched( || (runner.one_shot(), calling_account_id.clone(), input.clone()), - |(r, c, i)| r.call(RAW_CALL, c, i), + |(r, c, i)| r.call(SUBMIT, c, i), BatchSize::SmallInput, ) }); diff --git a/benches/eth_erc20.rs b/benches/eth_erc20.rs index 19a09062b..d95df69f7 100644 --- a/benches/eth_erc20.rs +++ b/benches/eth_erc20.rs @@ -1,11 +1,13 @@ +use aurora_engine::parameters::SubmitResult; use aurora_engine::prelude::{Address, U256}; use aurora_engine::transaction::EthTransaction; +use borsh::BorshDeserialize; use criterion::{criterion_group, BatchSize, BenchmarkId, Criterion}; use near_vm_logic::VMOutcome; use secp256k1::SecretKey; use std::path::{Path, PathBuf}; -use super::{address_from_secret_key, deploy_evm, sign_transaction, AuroraRunner, RAW_CALL}; +use super::{address_from_secret_key, deploy_evm, sign_transaction, AuroraRunner, SUBMIT}; use crate::solidity; const INITIAL_BALANCE: u64 = 1000; @@ -30,10 +32,12 @@ fn eth_erc20_benchmark(c: &mut Criterion) { constructor.deploy("Benchmarker", "BENCH", INITIAL_NONCE.into()), &source_account, ); - let erc20_address = output.return_data.as_value().unwrap(); + let submit_result = + SubmitResult::try_from_slice(&output.return_data.as_value().unwrap()).unwrap(); + let erc20_address = Address::from_slice(&submit_result.result); let contract = ERC20 { abi: constructor.abi, - address: Address::from_slice(&erc20_address), + address: erc20_address, }; // create the transaction for minting @@ -69,7 +73,7 @@ fn eth_erc20_benchmark(c: &mut Criterion) { mint_tx_bytes.clone(), ) }, - |(r, c, i)| r.call(RAW_CALL, c, i), + |(r, c, i)| r.call(SUBMIT, c, i), BatchSize::SmallInput, ) }); @@ -77,36 +81,28 @@ fn eth_erc20_benchmark(c: &mut Criterion) { // Measure mint gas usage; don't use `one_shot` because we want to keep this state change for // the next benchmark where we transfer some of the minted tokens. let (output, maybe_error) = - runner.call(RAW_CALL, calling_account_id.clone(), mint_tx_bytes.clone()); + runner.call(SUBMIT, calling_account_id.clone(), mint_tx_bytes.clone()); assert!(maybe_error.is_none()); let output = output.unwrap(); let gas = output.burnt_gas; + let eth_gas = super::parse_eth_gas(&output); // TODO(#45): capture this in a file println!("ETH_ERC20_MINT NEAR GAS: {:?}", gas); - #[cfg(feature = "profile_eth_gas")] - { - let eth_gas = super::parse_eth_gas(&output); - // TODO(#45): capture this in a file - println!("ETH_ERC20_MINT ETH GAS: {:?}", eth_gas); - } + println!("ETH_ERC20_MINT ETH GAS: {:?}", eth_gas); // Measure transfer gas usage let (output, maybe_err) = runner.one_shot().call( - RAW_CALL, + SUBMIT, calling_account_id.clone(), transfer_tx_bytes.clone(), ); assert!(maybe_err.is_none()); let output = output.unwrap(); let gas = output.burnt_gas; + let eth_gas = super::parse_eth_gas(&output); // TODO(#45): capture this in a file println!("ETH_ERC20_TRANSFER NEAR GAS: {:?}", gas); - #[cfg(feature = "profile_eth_gas")] - { - let eth_gas = super::parse_eth_gas(&output); - // TODO(#45): capture this in a file - println!("ETH_ERC20_TRANSFER ETH GAS: {:?}", eth_gas); - } + println!("ETH_ERC20_TRANSFER ETH GAS: {:?}", eth_gas); // measure transfer wall-clock time group.bench_function(transfer_id, |b| { @@ -118,7 +114,7 @@ fn eth_erc20_benchmark(c: &mut Criterion) { transfer_tx_bytes.clone(), ) }, - |(r, c, i)| r.call(RAW_CALL, c, i), + |(r, c, i)| r.call(SUBMIT, c, i), BatchSize::SmallInput, ) }); @@ -252,11 +248,8 @@ fn exec_transaction( ) -> VMOutcome { let calling_account_id = "some-account.near".to_string(); let signed_tx = sign_transaction(tx, Some(runner.chain_id), &account); - let (output, maybe_err) = runner.call( - RAW_CALL, - calling_account_id, - rlp::encode(&signed_tx).to_vec(), - ); + let (output, maybe_err) = + runner.call(SUBMIT, calling_account_id, rlp::encode(&signed_tx).to_vec()); assert!(maybe_err.is_none()); output.unwrap() } diff --git a/benches/eth_standard_precompiles.rs b/benches/eth_standard_precompiles.rs index c81952d2f..4d8cc6691 100644 --- a/benches/eth_standard_precompiles.rs +++ b/benches/eth_standard_precompiles.rs @@ -1,10 +1,12 @@ +use aurora_engine::parameters::SubmitResult; use aurora_engine::prelude::{Address, U256}; use aurora_engine::transaction::EthTransaction; +use borsh::BorshDeserialize; use criterion::{criterion_group, BatchSize, BenchmarkId, Criterion}; use secp256k1::SecretKey; use std::path::{Path, PathBuf}; -use super::{address_from_secret_key, deploy_evm, sign_transaction, RAW_CALL}; +use super::{address_from_secret_key, deploy_evm, sign_transaction, SUBMIT}; use crate::solidity; const INITIAL_BALANCE: u64 = 1000; @@ -26,15 +28,17 @@ fn eth_standard_precompiles_benchmark(c: &mut Criterion) { let tx = constructor.deploy(INITIAL_NONCE.into()); let signed_tx = sign_transaction(tx, Some(runner.chain_id), &source_account); let (output, maybe_err) = runner.call( - RAW_CALL, + SUBMIT, calling_account_id.clone(), rlp::encode(&signed_tx).to_vec(), ); assert!(maybe_err.is_none()); - let contract_address = output.unwrap().return_data.as_value().unwrap(); + let submit_result = + SubmitResult::try_from_slice(&output.unwrap().return_data.as_value().unwrap()).unwrap(); + let contract_address = Address::from_slice(&submit_result.result); let contract = Contract { abi: constructor.abi, - address: Address::from_slice(&contract_address), + address: contract_address, }; let test_names = Contract::all_method_names(); @@ -55,18 +59,14 @@ fn eth_standard_precompiles_benchmark(c: &mut Criterion) { let (output, maybe_err) = runner .one_shot() - .call(RAW_CALL, calling_account_id.clone(), tx_bytes.clone()); + .call(SUBMIT, calling_account_id.clone(), tx_bytes.clone()); assert!(maybe_err.is_none()); let output = output.unwrap(); let gas = output.burnt_gas; + let eth_gas = super::parse_eth_gas(&output); // TODO(#45): capture this in a file println!("ETH_STANDARD_PRECOMPILES_{} NEAR GAS: {:?}", name, gas); - #[cfg(feature = "profile_eth_gas")] - { - let eth_gas = super::parse_eth_gas(&output); - // TODO(#45): capture this in a file - println!("ETH_STANDARD_PRECOMPILES_{} ETH GAS: {:?}", name, eth_gas); - } + println!("ETH_STANDARD_PRECOMPILES_{} ETH GAS: {:?}", name, eth_gas); } let mut group = c.benchmark_group("standard_precompiles"); @@ -82,7 +82,7 @@ fn eth_standard_precompiles_benchmark(c: &mut Criterion) { tx_bytes.clone(), ) }, - |(r, c, i)| r.call(RAW_CALL, c, i), + |(r, c, i)| r.call(SUBMIT, c, i), BatchSize::SmallInput, ) }); diff --git a/benches/eth_transfer.rs b/benches/eth_transfer.rs index 80cc64b16..f0623ac9e 100644 --- a/benches/eth_transfer.rs +++ b/benches/eth_transfer.rs @@ -1,7 +1,7 @@ use criterion::{criterion_group, BatchSize, Criterion}; use secp256k1::SecretKey; -use super::{address_from_secret_key, create_eth_transaction, deploy_evm, RAW_CALL}; +use super::{address_from_secret_key, create_eth_transaction, deploy_evm, SUBMIT}; const INITIAL_BALANCE: u64 = 1000; const INITIAL_NONCE: u64 = 0; @@ -31,19 +31,18 @@ fn eth_transfer_benchmark(c: &mut Criterion) { let (output, maybe_err) = runner .one_shot() - .call(RAW_CALL, calling_account_id.clone(), input.clone()); + .call(SUBMIT, calling_account_id.clone(), input.clone()); assert!(maybe_err.is_none()); let gas = output.unwrap().burnt_gas; // TODO(#45): capture this in a file println!("ETH_TRANSFER NEAR GAS: {:?}", gas); - #[cfg(feature = "profile_eth_gas")] println!("ETH_TRANSFER ETH GAS: {:?}", 21_000); // measure wall-clock time c.bench_function("eth_transfer", |b| { b.iter_batched( || (runner.one_shot(), calling_account_id.clone(), input.clone()), - |(r, c, i)| r.call(RAW_CALL, c, i), + |(r, c, i)| r.call(SUBMIT, c, i), BatchSize::SmallInput, ) }); diff --git a/benches/main.rs b/benches/main.rs index f2174aef4..62030c6d8 100644 --- a/benches/main.rs +++ b/benches/main.rs @@ -1,10 +1,11 @@ -use borsh::BorshSerialize; +use borsh::{BorshDeserialize, BorshSerialize}; use criterion::criterion_main; use near_primitives_core::config::VMConfig; use near_primitives_core::contract::ContractCode; use near_primitives_core::profile::ProfileData; use near_primitives_core::runtime::fees::RuntimeFeesConfig; use near_vm_logic::mocks::mock_external::MockedExternal; +use near_vm_logic::types::ReturnData; use near_vm_logic::{VMContext, VMOutcome}; use near_vm_runner::{MockCompiledContractCache, VMError}; @@ -12,7 +13,7 @@ use primitive_types::U256; use rlp::RlpStream; use secp256k1::{self, Message, PublicKey, SecretKey}; -use aurora_engine::parameters::NewCallArgs; +use aurora_engine::parameters::{NewCallArgs, SubmitResult}; use aurora_engine::prelude::Address; use aurora_engine::storage; use aurora_engine::transaction::{EthSignedTransaction, EthTransaction}; @@ -31,7 +32,7 @@ near_sdk_sim::lazy_static_include::lazy_static_include_bytes! { EVM_WASM_BYTES => "release.wasm" } -pub const RAW_CALL: &str = "raw_call"; +pub const SUBMIT: &str = "submit"; criterion_main!( eth_deploy_code::benches, @@ -244,16 +245,11 @@ pub fn address_from_secret_key(sk: &SecretKey) -> Address { Address::from_slice(&hash[12..]) } -#[cfg(feature = "profile_eth_gas")] pub fn parse_eth_gas(output: &VMOutcome) -> u64 { - for log in output.logs.iter() { - if log.starts_with(ETH_GAS_USED) { - let eth_gas: Option = log - .split_ascii_whitespace() - .last() - .and_then(|x| x.parse().ok()); - return eth_gas.unwrap(); - } - } - panic!("Failed to parse Eth gas from the output logs. Was the EVM contract compiled with `--features profile_eth_gas`?"); + let submit_result_bytes = match &output.return_data { + ReturnData::Value(bytes) => bytes.as_slice(), + ReturnData::None | ReturnData::ReceiptIndex(_) => panic!("Unexpected ReturnData"), + }; + let submit_result = SubmitResult::try_from_slice(submit_result_bytes).unwrap(); + submit_result.gas_used } diff --git a/src/engine.rs b/src/engine.rs index 05770a9ea..468d79aa2 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -367,9 +367,6 @@ impl Engine { address, ); - #[cfg(feature = "profile_eth_gas")] - log_eth_gas_used(&executor); - let is_succeed = status.is_succeed(); status.into_result()?; let used_gas = executor.used_gas(); @@ -401,9 +398,6 @@ impl Engine { let mut executor = self.make_executor(); let (status, result) = executor.transact_call(origin, contract, value, input, u64::MAX); - #[cfg(feature = "profile_eth_gas")] - log_eth_gas_used(&executor); - let used_gas = executor.used_gas(); let (values, logs) = executor.into_state().deconstruct(); let is_succeed = status.is_succeed(); @@ -455,16 +449,6 @@ impl Engine { } } -#[cfg(feature = "profile_eth_gas")] -fn log_eth_gas_used(executor: &StackExecutor>) { - use alloc::format; - sdk::log(&format!( - "{}: {}", - crate::prelude::ETH_GAS_USED, - executor.used_gas() - )); -} - impl evm::backend::Backend for Engine { /// Returns the gas price. /// diff --git a/src/prelude.rs b/src/prelude.rs index 48505967b..a81da0d5d 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -27,6 +27,3 @@ pub type Address = H160; pub fn Address(input: [u8; 20]) -> Address { H160(input) } - -#[cfg(feature = "profile_eth_gas")] -pub const ETH_GAS_USED: &str = "ETH_GAS_USED";