From 18a5aee38c9bcf7aaf4cd9721234cdcf2ce37090 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 10 Mar 2021 22:13:28 +0000 Subject: [PATCH 1/2] EVMHost: Introduce gas metering for precompiles --- test/EVMHost.cpp | 411 +++++++++++++++++++++++++++++++++++------------ test/EVMHost.h | 15 +- 2 files changed, 316 insertions(+), 110 deletions(-) diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index c36c2aaf3..28756c73d 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -223,11 +223,26 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept else if (_message.destination == 0x0000000000000000000000000000000000000005_address && m_evmVersion >= langutil::EVMVersion::byzantium()) return precompileModExp(_message); else if (_message.destination == 0x0000000000000000000000000000000000000006_address && m_evmVersion >= langutil::EVMVersion::byzantium()) - return precompileALTBN128G1Add(_message); + { + if (m_evmVersion <= langutil::EVMVersion::istanbul()) + return precompileALTBN128G1Add(_message); + else + return precompileALTBN128G1Add(_message); + } else if (_message.destination == 0x0000000000000000000000000000000000000007_address && m_evmVersion >= langutil::EVMVersion::byzantium()) - return precompileALTBN128G1Mul(_message); + { + if (m_evmVersion <= langutil::EVMVersion::istanbul()) + return precompileALTBN128G1Mul(_message); + else + return precompileALTBN128G1Mul(_message); + } else if (_message.destination == 0x0000000000000000000000000000000000000008_address && m_evmVersion >= langutil::EVMVersion::byzantium()) - return precompileALTBN128PairingProduct(_message); + { + if (m_evmVersion <= langutil::EVMVersion::istanbul()) + return precompileALTBN128PairingProduct(_message); + else + return precompileALTBN128PairingProduct(_message); + } auto const stateBackup = accounts; @@ -401,7 +416,11 @@ evmc::bytes32 EVMHost::convertToEVMC(h256 const& _data) evmc::result EVMHost::precompileECRecover(evmc_message const& _message) noexcept { // NOTE this is a partial implementation for some inputs. - static map const inputOutput{ + + // Fixed cost of 3000 gas. + constexpr int64_t gas_cost = 3000; + + static map const inputOutput{ { fromHex( "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c" @@ -409,7 +428,10 @@ evmc::result EVMHost::precompileECRecover(evmc_message const& _message) noexcept "73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f" "eeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549" ), - fromHex("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b") + { + fromHex("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b"), + gas_cost + } }, { fromHex( @@ -418,15 +440,19 @@ evmc::result EVMHost::precompileECRecover(evmc_message const& _message) noexcept "debaaa0cddb321b2dcaaf846d39605de7b97e77ba6106587855b9106cb104215" "61a22d94fa8b8a687ff9c911c844d1c016d1a685a9166858f9c7c1bc85128aca" ), - fromHex("0000000000000000000000008743523d96a1b2cbe0c6909653a56da18ed484af") + { + fromHex("0000000000000000000000008743523d96a1b2cbe0c6909653a56da18ed484af"), + gas_cost + } } }; evmc::result result = precompileGeneric(_message, inputOutput); // ECRecover will return success with empty response in case of failure - if (result.status_code != EVMC_SUCCESS) + if (result.status_code != EVMC_SUCCESS && result.status_code != EVMC_OUT_OF_GAS) +// return resultWithGas(_message.gas, gas_cost, {}); { result.status_code = EVMC_SUCCESS; - result.gas_left = _message.gas; + result.gas_left = _message.gas - gas_cost; result.output_data = {}; result.output_size = 0; } @@ -442,32 +468,56 @@ evmc::result EVMHost::precompileSha256(evmc_message const& _message) noexcept _message.input_data + _message.input_size )); - return resultWithGas(_message, hash); + // Base 60 gas + 12 gas / word. + int64_t gas_cost = 60 + 12 * ((static_cast(_message.input_size) + 31) / 32); + + return resultWithGas(_message.gas, gas_cost, hash); } evmc::result EVMHost::precompileRipeMD160(evmc_message const& _message) noexcept { // NOTE this is a partial implementation for some inputs. - static map const inputOutput{ + + // Base 600 gas + 120 gas / word. + constexpr auto calc_cost = [](int64_t size) -> int64_t { + return 600 + 120 * ((size + 31) / 32); + }; + + static map const inputOutput{ { bytes{}, - fromHex("0000000000000000000000009c1185a5c5e9fc54612808977ee8f548b2258d31") + { + fromHex("0000000000000000000000009c1185a5c5e9fc54612808977ee8f548b2258d31"), + calc_cost(0) + } }, { fromHex("0000000000000000000000000000000000000000000000000000000000000004"), - fromHex("0000000000000000000000001b0f3c404d12075c68c938f9f60ebea4f74941a0") + { + fromHex("0000000000000000000000001b0f3c404d12075c68c938f9f60ebea4f74941a0"), + calc_cost(32) + } }, { fromHex("0000000000000000000000000000000000000000000000000000000000000005"), - fromHex("000000000000000000000000ee54aa84fc32d8fed5a5fe160442ae84626829d9") + { + fromHex("000000000000000000000000ee54aa84fc32d8fed5a5fe160442ae84626829d9"), + calc_cost(32) + } }, { fromHex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - fromHex("0000000000000000000000001cf4e77f5966e13e109703cd8a0df7ceda7f3dc3") + { + fromHex("0000000000000000000000001cf4e77f5966e13e109703cd8a0df7ceda7f3dc3"), + calc_cost(32) + } }, { fromHex("0000000000000000000000000000000000000000000000000000000000000000"), - fromHex("000000000000000000000000f93175303eba2a7b372174fc9330237f5ad202fc") + { + fromHex("000000000000000000000000f93175303eba2a7b372174fc9330237f5ad202fc"), + calc_cost(32) + } }, { fromHex( @@ -476,7 +526,10 @@ evmc::result EVMHost::precompileRipeMD160(evmc_message const& _message) noexcept "0000000400000000000000000000000000000000000000000000000000000000" "00000100" ), - fromHex("000000000000000000000000f93175303eba2a7b372174fc9330237f5ad202fc") + { + fromHex("000000000000000000000000f93175303eba2a7b372174fc9330237f5ad202fc"), + calc_cost(100) + } }, { fromHex( @@ -485,7 +538,10 @@ evmc::result EVMHost::precompileRipeMD160(evmc_message const& _message) noexcept "0000000500000000000000000000000000000000000000000000000000000000" "00000100" ), - fromHex("0000000000000000000000004f4fc112e2bfbe0d38f896a46629e08e2fcfad5") + { + fromHex("0000000000000000000000004f4fc112e2bfbe0d38f896a46629e08e2fcfad5"), + calc_cost(100) + } }, { fromHex( @@ -494,18 +550,27 @@ evmc::result EVMHost::precompileRipeMD160(evmc_message const& _message) noexcept "ffffffff00000000000000000000000000000000000000000000000000000000" "00000100" ), - fromHex("000000000000000000000000c0a2e4b1f3ff766a9a0089e7a410391730872495") + { + fromHex("000000000000000000000000c0a2e4b1f3ff766a9a0089e7a410391730872495"), + calc_cost(100) + } }, { fromHex( "6162636465666768696a6b6c6d6e6f707172737475767778797a414243444546" "4748494a4b4c4d4e4f505152535455565758595a303132333435363738393f21" ), - fromHex("00000000000000000000000036c6b90a49e17d4c1e1b0e634ec74124d9b207da") + { + fromHex("00000000000000000000000036c6b90a49e17d4c1e1b0e634ec74124d9b207da"), + calc_cost(64) + } }, { fromHex("6162636465666768696a6b6c6d6e6f707172737475767778797a414243444546"), - fromHex("000000000000000000000000ac5ab22e07b0fb80c69b6207902f725e2507e546") + { + fromHex("000000000000000000000000ac5ab22e07b0fb80c69b6207902f725e2507e546"), + calc_cost(32) + } } }; return precompileGeneric(_message, inputOutput); @@ -517,7 +582,10 @@ evmc::result EVMHost::precompileIdentity(evmc_message const& _message) noexcept bytes static data; data = bytes(_message.input_data, _message.input_data + _message.input_size); - return resultWithGas(_message, data); + // Base 15 gas + 3 gas / word. + int64_t gas_cost = 15 + 3 * ((static_cast(_message.input_size) + 31) / 32); + + return resultWithGas(_message.gas, gas_cost, data); } evmc::result EVMHost::precompileModExp(evmc_message const&) noexcept @@ -526,11 +594,15 @@ evmc::result EVMHost::precompileModExp(evmc_message const&) noexcept return resultWithFailure(); } +template evmc::result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noexcept { // NOTE this is a partial implementation for some inputs. - static map const inputOutput{ + // Fixed 500 or 150 gas. + int64_t gas_cost = (Revision < EVMC_ISTANBUL) ? 500 : 150; + + static map const inputOutput{ { fromHex( "0000000000000000000000000000000000000000000000000000000000000000" @@ -540,10 +612,13 @@ evmc::result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" ), - fromHex( - "1385281136ff5b2c326807ff0a824b6ca4f21fcc7c8764e9801bc4ad497d5012" - "02254594be8473dcf018a2aa66ea301e38fc865823acf75a9901721d1fc6bf4c" - ) + { + fromHex( + "1385281136ff5b2c326807ff0a824b6ca4f21fcc7c8764e9801bc4ad497d5012" + "02254594be8473dcf018a2aa66ea301e38fc865823acf75a9901721d1fc6bf4c" + ), + gas_cost + } }, { fromHex( @@ -554,10 +629,13 @@ evmc::result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" ), - fromHex( - "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd3" - "15ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4" - ) + { + fromHex( + "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd3" + "15ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4" + ), + gas_cost + } }, { fromHex( @@ -568,10 +646,13 @@ evmc::result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" ), - fromHex( - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" - ) + { + fromHex( + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + ), + gas_cost + } }, { fromHex( @@ -582,10 +663,13 @@ evmc::result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" ), - fromHex( - "16aed5ed486df6b2fb38015ded41400009ed4f34bef65b87b1f90f47052f8d94" - "16dabf21b3f25b9665269d98dc17b1da6118251dc0b403ae50e96dfe91239375" - ) + { + fromHex( + "16aed5ed486df6b2fb38015ded41400009ed4f34bef65b87b1f90f47052f8d94" + "16dabf21b3f25b9665269d98dc17b1da6118251dc0b403ae50e96dfe91239375" + ), + gas_cost + } }, { fromHex( @@ -596,10 +680,13 @@ evmc::result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" ), - fromHex( - "1e018816fc9bbd91313301ae9c254bb7d64d6cd54f3b49b92925e43e256b5faa" - "1d1f2259c715327bedb42c095af6c0267e4e1be836b4e04b3f0502552f93cca9" - ) + { + fromHex( + "1e018816fc9bbd91313301ae9c254bb7d64d6cd54f3b49b92925e43e256b5faa" + "1d1f2259c715327bedb42c095af6c0267e4e1be836b4e04b3f0502552f93cca9" + ), + gas_cost + } }, { fromHex( @@ -610,10 +697,13 @@ evmc::result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" ), - fromHex( - "29d160febeef9770d47a32ee3b763850eb0594844fa57dd31b8ed02c78fdb797" - "2c7cdf62c2498486fd52646e577a06723ce97737b3c958262d78c4a413661e8a" - ), + { + fromHex( + "29d160febeef9770d47a32ee3b763850eb0594844fa57dd31b8ed02c78fdb797" + "2c7cdf62c2498486fd52646e577a06723ce97737b3c958262d78c4a413661e8a" + ), + gas_cost + } }, { fromHex( @@ -624,10 +714,13 @@ evmc::result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" ), - fromHex( - "2583ed10e418133e44619c336f1be5ddae9e20d634a7683d9661401c750d7df4" - "0185fbba22de9e698262925665735dbc4d6e8288bc3fc39fae10ca58e16e77f7" - ) + { + fromHex( + "2583ed10e418133e44619c336f1be5ddae9e20d634a7683d9661401c750d7df4" + "0185fbba22de9e698262925665735dbc4d6e8288bc3fc39fae10ca58e16e77f7" + ), + gas_cost + } }, { fromHex( @@ -638,10 +731,13 @@ evmc::result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" ), - fromHex( - "1496064626ba8bffeb7805f0d16143a65649bb0850333ea512c03fcdaf31e254" - "07b4f210ab542533f1ee5633ae4406cd16c63494b537ce3f1cf4afff6f76a48f" - ), + { + fromHex( + "1496064626ba8bffeb7805f0d16143a65649bb0850333ea512c03fcdaf31e254" + "07b4f210ab542533f1ee5633ae4406cd16c63494b537ce3f1cf4afff6f76a48f" + ), + gas_cost + } }, { fromHex( @@ -652,10 +748,13 @@ evmc::result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" ), - fromHex( - "2801b21090cbc48409e352647f3857134d373f81741f9d5e3d432f336d76f517" - "13cf106acf943c2a331de21c7d5e3351354e7412f2dba2918483a6593a6828d4" - ) + { + fromHex( + "2801b21090cbc48409e352647f3857134d373f81741f9d5e3d432f336d76f517" + "13cf106acf943c2a331de21c7d5e3351354e7412f2dba2918483a6593a6828d4" + ), + gas_cost + } }, { fromHex( @@ -666,10 +765,13 @@ evmc::result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" ), - fromHex( - "10b4876441e14a6be92a7fe66550848c01c676a12ac31d7cc13b21f49c4307c8" - "09f5528bdb0ef9354837a0f4b4c9da973bd5b805d359976f719ab0b74e0a7368" - ) + { + fromHex( + "10b4876441e14a6be92a7fe66550848c01c676a12ac31d7cc13b21f49c4307c8" + "09f5528bdb0ef9354837a0f4b4c9da973bd5b805d359976f719ab0b74e0a7368" + ), + gas_cost + } }, { fromHex( @@ -680,10 +782,13 @@ evmc::result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" ), - fromHex( - "186bac5188a98c45e6016873d107f5cd131f3a3e339d0375e58bd6219347b008" - "1e396bc242de0214898b0f68035f53ad5a6f96c6c8390ac56ed6ec9561d23159" - ) + { + fromHex( + "186bac5188a98c45e6016873d107f5cd131f3a3e339d0375e58bd6219347b008" + "1e396bc242de0214898b0f68035f53ad5a6f96c6c8390ac56ed6ec9561d23159" + ), + gas_cost + } }, { fromHex( @@ -694,10 +799,13 @@ evmc::result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" ), - fromHex( - "20a754d2071d4d53903e3b31a7e98ad6882d58aec240ef981fdf0a9d22c5926a" - "29c853fcea789887315916bbeb89ca37edb355b4f980c9a12a94f30deeed3021" - ) + { + fromHex( + "20a754d2071d4d53903e3b31a7e98ad6882d58aec240ef981fdf0a9d22c5926a" + "29c853fcea789887315916bbeb89ca37edb355b4f980c9a12a94f30deeed3021" + ), + gas_cost + } }, { fromHex( @@ -708,10 +816,13 @@ evmc::result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" ), - fromHex( - "18014701594179c6b9ccae848e3d15c1f76f8a68b8092578296520e46c9bae0c" - "1b5ed0e9e8f3ff35589ea81a45cf63887d4a92c099a3be1d97b26f0db96323dd" - ), + { + fromHex( + "18014701594179c6b9ccae848e3d15c1f76f8a68b8092578296520e46c9bae0c" + "1b5ed0e9e8f3ff35589ea81a45cf63887d4a92c099a3be1d97b26f0db96323dd" + ), + gas_cost + } }, { fromHex( @@ -722,10 +833,13 @@ evmc::result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" ), - fromHex( - "27231d5cdd0011259ff75678cf5a8f7840c22cb71d52b25e21e071205e8d9bc4" - "26dd3d225c9a71476db0cf834232eba84020f3073c6d20c519963e0b98f235e1" - ) + { + fromHex( + "27231d5cdd0011259ff75678cf5a8f7840c22cb71d52b25e21e071205e8d9bc4" + "26dd3d225c9a71476db0cf834232eba84020f3073c6d20c519963e0b98f235e1" + ), + gas_cost + } }, { fromHex( @@ -736,71 +850,121 @@ evmc::result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" ), - fromHex( - "26dcfbc2e0bc9d82efb4acd73cb3e99730e27e10177fcfb78b6399a4bfcdf391" - "27c440dbd5053253a3a692f9bf89b9b6e9612127cf97db1e11ffa9679acc933b" - ) + { + fromHex( + "26dcfbc2e0bc9d82efb4acd73cb3e99730e27e10177fcfb78b6399a4bfcdf391" + "27c440dbd5053253a3a692f9bf89b9b6e9612127cf97db1e11ffa9679acc933b" + ), + gas_cost + } } }; return precompileGeneric(_message, inputOutput); } +template evmc::result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noexcept { // NOTE this is a partial implementation for some inputs. - static map const inputOutput{ + + // Fixed 40000 or 6000 gas. + int64_t gas_cost = (Revision < EVMC_ISTANBUL) ? 40000 : 6000; + + static map const inputOutput{ { fromHex("0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000"), - fromHex("030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4") + { + fromHex("030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4"), + gas_cost + } }, { fromHex("0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000"), - fromHex("17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c") + { + fromHex("17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c"), + gas_cost + } }, { fromHex("09b54f111d3b2d1b2fe1ae9669b3db3d7bf93b70f00647e65c849275de6dc7fe18b2e77c63a3e400d6d1f1fbc6e1a1167bbca603d34d03edea231eb0ab7b14b4030f7b0c405c888aff922307ea2cd1c70f64664bab76899500341f4260a209290000000000000000000000000000000000000000000000000000000000000000"), - fromHex("16a1d378d1a98cf5383cdc512011234287ca43b6a078d1842d5c58c5b1f475cc1309377a7026d08ca1529eab74381a7e0d3a4b79d80bacec207cd52fc8e3769c") + { + fromHex("16a1d378d1a98cf5383cdc512011234287ca43b6a078d1842d5c58c5b1f475cc1309377a7026d08ca1529eab74381a7e0d3a4b79d80bacec207cd52fc8e3769c"), + gas_cost + } }, { fromHex("0a6de0e2240aa253f46ce0da883b61976e3588146e01c9d8976548c145fe6e4a04fbaa3a4aed4bb77f30ebb07a3ec1c7d77a7f2edd75636babfeff97b1ea686e1551dcd4965285ef049512d2d30cbfc1a91acd5baad4a6e19e22e93176197f170000000000000000000000000000000000000000000000000000000000000000"), - fromHex("28d3c57516712e7843a5b3cfa7d7274a037943f5bd57c227620ad207728e42832795fa9df21d4b8b329a45bae120f1fd9df9049ecacaa9dd1eca18bc6a55cd2f") + { + fromHex("28d3c57516712e7843a5b3cfa7d7274a037943f5bd57c227620ad207728e42832795fa9df21d4b8b329a45bae120f1fd9df9049ecacaa9dd1eca18bc6a55cd2f"), + gas_cost + } }, { fromHex("0c54b42137b67cc268cbb53ac62b00ecead23984092b494a88befe58445a244a18e3723d37fae9262d58b548a0575f59d9c3266db7afb4d5739555837f6b8b3e0c692b41f1acc961f6ea83bae2c3a1a55c54f766c63ba76989f52c149c17b5e70000000000000000000000000000000000000000000000000000000000000000"), - fromHex("258f1faa356e470cca19c928afa5ceed6215c756912af5725b8db5777cc8f3b6175ced8a58d0c132c2b95ba14c16dde93e7f7789214116ff69da6f44daa966e6") + { + fromHex("258f1faa356e470cca19c928afa5ceed6215c756912af5725b8db5777cc8f3b6175ced8a58d0c132c2b95ba14c16dde93e7f7789214116ff69da6f44daa966e6"), + gas_cost + } }, { fromHex("0f103f14a584d4203c27c26155b2c955f8dfa816980b24ba824e1972d6486a5d0c4165133b9f5be17c804203af781bcf168da7386620479f9b885ecbcd27b17b0ea71d0abb524cac7cfff5323e1d0b14ab705842426c978f96753ccce258ed930000000000000000000000000000000000000000000000000000000000000000"), - fromHex("2a49621e12910cd90f3e731083d454255bf1c533d6e15b8699156778d0f27f5d2590ee31824548d159aa2d22296bf149d564c0872f41b89b7dc5c6e6e3cd1c4d") + { + fromHex("2a49621e12910cd90f3e731083d454255bf1c533d6e15b8699156778d0f27f5d2590ee31824548d159aa2d22296bf149d564c0872f41b89b7dc5c6e6e3cd1c4d"), + gas_cost + } }, { fromHex("111e2e2a5f8828f80ddad08f9f74db56dac1cc16c1cb278036f79a84cf7a116f1d7d62e192b219b9808faa906c5ced871788f6339e8d91b83ac1343e20a16b3000000000000000000000000000000000000000e40800000000000000008cdcbc0000000000000000000000000000000000000000000000000000000000000000"), - fromHex("25ff95a3abccf32adc6a4c3c8caddca67723d8ada802e9b9f612e3ddb40b20050d82b09bb4ec927bbf182bdc402790429322b7e2f285f2aad8ea135cbf7143d8") + { + fromHex("25ff95a3abccf32adc6a4c3c8caddca67723d8ada802e9b9f612e3ddb40b20050d82b09bb4ec927bbf182bdc402790429322b7e2f285f2aad8ea135cbf7143d8"), + gas_cost + } }, { fromHex("17d5d09b4146424bff7e6fb01487c477bbfcd0cdbbc92d5d6457aae0b6717cc502b5636903efbf46db9235bbe74045d21c138897fda32e079040db1a16c1a7a11887420878c0c8e37605291c626585eabbec8d8b97a848fe8d58a37b004583510000000000000000000000000000000000000000000000000000000000000000"), - fromHex("2364294faf6b89fedeede9986aa777c4f6c2f5c4a4559ee93dfec9b7b94ef80b05aeae62655ea23865ae6661ae371a55c12098703d0f2301f4223e708c92efc6") + { + fromHex("2364294faf6b89fedeede9986aa777c4f6c2f5c4a4559ee93dfec9b7b94ef80b05aeae62655ea23865ae6661ae371a55c12098703d0f2301f4223e708c92efc6"), + gas_cost + } }, { fromHex("1c36e713d4d54e3a9644dffca1fc524be4868f66572516025a61ca542539d43f042dcc4525b82dfb242b09cb21909d5c22643dcdbe98c4d082cc2877e96b24db016086cc934d5cab679c6991a4efcedbab26d7e4fb23b6a1ad4e6b5c2fb59ce50000000000000000000000000000000000000000000000000000000000000000"), - fromHex("1644e84fef7b7fdc98254f0654580173307a3bc44db990581e7ab55a22446dcf28c2916b7e875692b195831945805438fcd30d2693d8a80cf8c88ec6ef4c315d") + { + fromHex("1644e84fef7b7fdc98254f0654580173307a3bc44db990581e7ab55a22446dcf28c2916b7e875692b195831945805438fcd30d2693d8a80cf8c88ec6ef4c315d"), + gas_cost + } }, { fromHex("1e39e9f0f91fa7ff8047ffd90de08785777fe61c0e3434e728fce4cf35047ddc2e0b64d75ebfa86d7f8f8e08abbe2e7ae6e0a1c0b34d028f19fa56e9450527cb1eec35a0e955cad4bee5846ae0f1d0b742d8636b278450c534e38e06a60509f90000000000000000000000000000000000000000000000000000000000000000"), - fromHex("1385281136ff5b2c326807ff0a824b6ca4f21fcc7c8764e9801bc4ad497d501202254594be8473dcf018a2aa66ea301e38fc865823acf75a9901721d1fc6bf4c") + { + fromHex("1385281136ff5b2c326807ff0a824b6ca4f21fcc7c8764e9801bc4ad497d501202254594be8473dcf018a2aa66ea301e38fc865823acf75a9901721d1fc6bf4c"), + gas_cost + } }, { fromHex("232063b584fb76c8d07995bee3a38fa7565405f3549c6a918ddaa90ab971e7f82ac9b135a81d96425c92d02296322ad56ffb16299633233e4880f95aafa7fda70689c3dc4311426ee11707866b2cbdf9751dacd07245bf99d2113d3f5a8cac470000000000000000000000000000000000000000000000000000000000000000"), - fromHex("2174f0221490cd9c15b0387f3251ec3d49517a51c37a8076eac12afb4a95a7071d1c3fcd3161e2a417b4df0955f02db1fffa9005210fb30c5aa3755307e9d1f5") + { + fromHex("2174f0221490cd9c15b0387f3251ec3d49517a51c37a8076eac12afb4a95a7071d1c3fcd3161e2a417b4df0955f02db1fffa9005210fb30c5aa3755307e9d1f5"), + gas_cost + } } }; return precompileGeneric(_message, inputOutput); } +template evmc::result EVMHost::precompileALTBN128PairingProduct(evmc_message const& _message) noexcept { + // Base + per pairing gas. + constexpr auto calc_cost = [](unsigned points) -> int64_t { + // Number of 192-byte points. + return (Revision < EVMC_ISTANBUL) ? + (100000 + 80000 * points): + (45000 + 34000 * points); + }; + // NOTE this is a partial implementation for some inputs. - static map const inputOutput{ + static map const inputOutput{ { fromHex( "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa9" @@ -816,7 +980,10 @@ evmc::result EVMHost::precompileALTBN128PairingProduct(evmc_message const& _mess "19b763513924a736e4eebd0d78c91c1bc1d657fee4214057d21414011cfcc763" "2f8d9f9ab83727c77a2fec063cb7b6e5eb23044ccf535ad49d46d394fb6f6bf6" ), - fromHex("0000000000000000000000000000000000000000000000000000000000000001") + { + fromHex("0000000000000000000000000000000000000000000000000000000000000001"), + calc_cost(2) + } }, { fromHex( @@ -833,7 +1000,10 @@ evmc::result EVMHost::precompileALTBN128PairingProduct(evmc_message const& _mess "090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b" "12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa" ), - fromHex("0000000000000000000000000000000000000000000000000000000000000001") + { + fromHex("0000000000000000000000000000000000000000000000000000000000000001"), + calc_cost(2) + } }, { fromHex( @@ -850,7 +1020,10 @@ evmc::result EVMHost::precompileALTBN128PairingProduct(evmc_message const& _mess "090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b" "12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa" ), - fromHex("0000000000000000000000000000000000000000000000000000000000000001") + { + fromHex("0000000000000000000000000000000000000000000000000000000000000001"), + calc_cost(2) + } }, { fromHex( @@ -867,7 +1040,10 @@ evmc::result EVMHost::precompileALTBN128PairingProduct(evmc_message const& _mess "090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b" "12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa" ), - fromHex("0000000000000000000000000000000000000000000000000000000000000001") + { + fromHex("0000000000000000000000000000000000000000000000000000000000000001"), + calc_cost(2) + } }, { fromHex( @@ -884,7 +1060,10 @@ evmc::result EVMHost::precompileALTBN128PairingProduct(evmc_message const& _mess "090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b" "12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa" ), - fromHex("0000000000000000000000000000000000000000000000000000000000000001") + { + fromHex("0000000000000000000000000000000000000000000000000000000000000001"), + calc_cost(2) + } }, { fromHex( @@ -907,7 +1086,10 @@ evmc::result EVMHost::precompileALTBN128PairingProduct(evmc_message const& _mess "21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237" "096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f" ), - fromHex("0000000000000000000000000000000000000000000000000000000000000001") + { + fromHex("0000000000000000000000000000000000000000000000000000000000000001"), + calc_cost(3) + } }, { fromHex( @@ -930,7 +1112,10 @@ evmc::result EVMHost::precompileALTBN128PairingProduct(evmc_message const& _mess "090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b" "12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa" ), - fromHex("0000000000000000000000000000000000000000000000000000000000000001") + { + fromHex("0000000000000000000000000000000000000000000000000000000000000001"), + calc_cost(3) + } } }; return precompileGeneric(_message, inputOutput); @@ -938,11 +1123,14 @@ evmc::result EVMHost::precompileALTBN128PairingProduct(evmc_message const& _mess evmc::result EVMHost::precompileGeneric( evmc_message const& _message, - map const& _inOut) noexcept + map const& _inOut) noexcept { bytes input(_message.input_data, _message.input_data + _message.input_size); if (_inOut.count(input)) - return resultWithGas(_message, _inOut.at(input)); + { + auto const& ret = _inOut.at(input); + return resultWithGas(_message.gas, ret.gas_used, ret.output); + } else return resultWithFailure(); } @@ -955,13 +1143,22 @@ evmc::result EVMHost::resultWithFailure() noexcept } evmc::result EVMHost::resultWithGas( - evmc_message const& _message, + int64_t gas_limit, + int64_t gas_required, bytes const& _data ) noexcept { evmc::result result({}); - result.status_code = EVMC_SUCCESS; - result.gas_left = _message.gas; + if (gas_limit < gas_required) + { + result.status_code = EVMC_OUT_OF_GAS; + result.gas_left = 0; + } + else + { + result.status_code = EVMC_SUCCESS; + result.gas_left = gas_limit - gas_required; + } result.output_data = _data.data(); result.output_size = _data.size(); return result; diff --git a/test/EVMHost.h b/test/EVMHost.h index 584ba27ea..4b1f6748a 100644 --- a/test/EVMHost.h +++ b/test/EVMHost.h @@ -37,6 +37,11 @@ namespace solidity::test using Address = util::h160; using StorageMap = std::map; +struct EVMPrecompileOutput { + bytes const output; + int64_t gas_used; +}; + class EVMHost: public evmc::MockedHost { public: @@ -110,13 +115,17 @@ private: static evmc::result precompileRipeMD160(evmc_message const& _message) noexcept; static evmc::result precompileIdentity(evmc_message const& _message) noexcept; static evmc::result precompileModExp(evmc_message const& _message) noexcept; + template static evmc::result precompileALTBN128G1Add(evmc_message const& _message) noexcept; + template static evmc::result precompileALTBN128G1Mul(evmc_message const& _message) noexcept; + template static evmc::result precompileALTBN128PairingProduct(evmc_message const& _message) noexcept; - static evmc::result precompileGeneric(evmc_message const& _message, std::map const& _inOut) noexcept; - /// @returns a result object with no gas usage and result data taken from @a _data. + static evmc::result precompileGeneric(evmc_message const& _message, std::map const& _inOut) noexcept; + /// @returns a result object with gas usage and result data taken from @a _data. + /// The outcome will be a failure if the limit < required. /// @note The return value is only valid as long as @a _data is alive! - static evmc::result resultWithGas(evmc_message const& _message, bytes const& _data) noexcept; + static evmc::result resultWithGas(int64_t gas_limit, int64_t gas_required, bytes const& _data) noexcept; static evmc::result resultWithFailure() noexcept; evmc::VM& m_vm; From b74b55198d0d09ed1bba60d78e25899bd7c85acc Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 11 Mar 2021 00:33:37 +0000 Subject: [PATCH 2/2] Update tests --- .../externalContracts/deposit_contract.sol | 30 +++++++++---------- .../semanticTests/externalContracts/snark.sol | 9 ++++-- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol index 7b5418ed1..389661fd7 100644 --- a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol +++ b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol @@ -176,35 +176,35 @@ contract DepositContract is IDepositContract, ERC165 { } // ---- // constructor() -// gas irOptimized: 1428137 -// gas legacy: 2425301 -// gas legacyOptimized: 1770477 +// gas irOptimized: 1430741 +// gas legacy: 2427905 +// gas legacyOptimized: 1773081 // supportsInterface(bytes4): 0x0 -> 0 // supportsInterface(bytes4): 0xffffffff00000000000000000000000000000000000000000000000000000000 -> false # defined to be false by ERC-165 # // supportsInterface(bytes4): 0x01ffc9a700000000000000000000000000000000000000000000000000000000 -> true # ERC-165 id # // supportsInterface(bytes4): 0x8564090700000000000000000000000000000000000000000000000000000000 -> true # the deposit interface id # // get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e -// gas irOptimized: 114626 -// gas legacy: 149888 -// gas legacyOptimized: 121887 +// gas irOptimized: 117398 +// gas legacy: 152660 +// gas legacyOptimized: 124659 // get_deposit_count() -> 0x20, 8, 0 # TODO: check balance and logs after each deposit # // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0 -> FAILURE # Empty input # // get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e -// gas irOptimized: 114626 -// gas legacy: 149888 -// gas legacyOptimized: 121887 +// gas irOptimized: 117398 +// gas legacy: 152660 +// gas legacyOptimized: 124659 // get_deposit_count() -> 0x20, 8, 0 // deposit(bytes,bytes,bytes,bytes32), 1 ether: 0x80, 0xe0, 0x120, 0xaa4a8d0b7d9077248630f1a4701ae9764e42271d7f22b7838778411857fd349e, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0x00f50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8 -> # txhash: 0x7085c586686d666e8bb6e9477a0f0b09565b2060a11f1c4209d3a52295033832 # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0xf50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x08, 0xca9a3b00000000000000000000000000000000000000000000000000000000, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8, 0x08, 0x00 // get_deposit_root() -> 0x2089653123d9c721215120b6db6738ba273bbc5228ac093b1f983badcdc8a438 -// gas irOptimized: 114611 -// gas legacy: 149898 -// gas legacyOptimized: 121900 +// gas irOptimized: 117383 +// gas legacy: 152670 +// gas legacyOptimized: 124672 // get_deposit_count() -> 0x20, 8, 0x0100000000000000000000000000000000000000000000000000000000000000 // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0x80, 0xe0, 0x120, 0xdbd986dc85ceb382708cf90a3500f500f0a393c5ece76963ac3ed72eccd2c301, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x00344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d -> # txhash: 0x404d8e109822ce448e68f45216c12cb051b784d068fbe98317ab8e50c58304ac # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x08, 0x40597307000000000000000000000000000000000000000000000000000000, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d, 0x08, 0x0100000000000000000000000000000000000000000000000000000000000000 // get_deposit_root() -> 0x40255975859377d912c53aa853245ebd939bdd2b33a28e084babdcc1ed8238ee -// gas irOptimized: 114611 -// gas legacy: 149898 -// gas legacyOptimized: 121900 +// gas irOptimized: 117383 +// gas legacy: 152670 +// gas legacyOptimized: 124672 // get_deposit_count() -> 0x20, 8, 0x0200000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/externalContracts/snark.sol b/test/libsolidity/semanticTests/externalContracts/snark.sol index 7d04b5af6..4c3cb78f9 100644 --- a/test/libsolidity/semanticTests/externalContracts/snark.sol +++ b/test/libsolidity/semanticTests/externalContracts/snark.sol @@ -294,8 +294,11 @@ contract Test { // f() -> true // g() -> true // pair() -> true +// gas irOptimized: 270080 +// gas legacy: 275952 +// gas legacyOptimized: 267239 // verifyTx() -> true // ~ emit Verified(string): 0x20, 0x16, "Successfully verified." -// gas irOptimized: 95261 -// gas legacy: 116473 -// gas legacyOptimized: 83670 +// gas irOptimized: 783949 +// gas legacy: 805423 +// gas legacyOptimized: 772571