From 13f3e25ebb5273505b0c0df573f04aa92d8c577e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Mon, 6 Sep 2021 13:30:28 +0200 Subject: [PATCH] Add initial contract macro benchmarks (#9600) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add erc20 benchmarks * Fix typos Co-authored-by: Michael Müller * Fix compilation issue on case sensitive fs Co-authored-by: Michael Müller --- .../frame/contracts/benchmarks/README.md | 9 + .../frame/contracts/benchmarks/ink_erc20.json | 819 ++++++++++++++++++ .../frame/contracts/benchmarks/ink_erc20.wasm | Bin 0 -> 30276 bytes .../contracts/benchmarks/ink_erc20_test.wasm | Bin 0 -> 29726 bytes .../contracts/benchmarks/solang_erc20.json | 581 +++++++++++++ .../contracts/benchmarks/solang_erc20.wasm | Bin 0 -> 12505 bytes .../frame/contracts/src/benchmarking/code.rs | 54 +- .../frame/contracts/src/benchmarking/mod.rs | 110 ++- 8 files changed, 1560 insertions(+), 13 deletions(-) create mode 100644 substrate/frame/contracts/benchmarks/README.md create mode 100644 substrate/frame/contracts/benchmarks/ink_erc20.json create mode 100644 substrate/frame/contracts/benchmarks/ink_erc20.wasm create mode 100644 substrate/frame/contracts/benchmarks/ink_erc20_test.wasm create mode 100644 substrate/frame/contracts/benchmarks/solang_erc20.json create mode 100644 substrate/frame/contracts/benchmarks/solang_erc20.wasm diff --git a/substrate/frame/contracts/benchmarks/README.md b/substrate/frame/contracts/benchmarks/README.md new file mode 100644 index 0000000000..a4b15bd840 --- /dev/null +++ b/substrate/frame/contracts/benchmarks/README.md @@ -0,0 +1,9 @@ +# Benchmarks + +This directory contains real world (ink!, solang) contracts which are used in macro benchmarks. +Those benchmarks are not used to determine weights but rather to compare different contract +languages and execution engines with larger wasm modules. + +Files in this directory are used by `#[extra]` benchmarks in `src/benchmarking`. The json +files are for informational purposes only and are not consumed by the benchmarks. + diff --git a/substrate/frame/contracts/benchmarks/ink_erc20.json b/substrate/frame/contracts/benchmarks/ink_erc20.json new file mode 100644 index 0000000000..390dd9b06c --- /dev/null +++ b/substrate/frame/contracts/benchmarks/ink_erc20.json @@ -0,0 +1,819 @@ +{ + "metadataVersion": "0.1.0", + "source": { + "hash": "0x6be8492017fe96b7a92bb39b4ede04b96effb8fcaf9237bfdccef7d9e732c760", + "language": "ink! 3.0.0-rc4", + "compiler": "rustc 1.56.0-nightly" + }, + "contract": { + "name": "erc20", + "version": "3.0.0-rc4", + "authors": [ + "Parity Technologies " + ] + }, + "spec": { + "constructors": [ + { + "args": [ + { + "name": "initial_supply", + "type": { + "displayName": [ + "Balance" + ], + "type": 1 + } + } + ], + "docs": [ + "Creates a new ERC-20 contract with the specified initial supply." + ], + "name": [ + "new" + ], + "selector": "0x9bae9d5e" + } + ], + "docs": [], + "events": [ + { + "args": [ + { + "docs": [], + "indexed": true, + "name": "from", + "type": { + "displayName": [ + "Option" + ], + "type": 15 + } + }, + { + "docs": [], + "indexed": true, + "name": "to", + "type": { + "displayName": [ + "Option" + ], + "type": 15 + } + }, + { + "docs": [], + "indexed": false, + "name": "value", + "type": { + "displayName": [ + "Balance" + ], + "type": 1 + } + } + ], + "docs": [ + " Event emitted when a token transfer occurs." + ], + "name": "Transfer" + }, + { + "args": [ + { + "docs": [], + "indexed": true, + "name": "owner", + "type": { + "displayName": [ + "AccountId" + ], + "type": 5 + } + }, + { + "docs": [], + "indexed": true, + "name": "spender", + "type": { + "displayName": [ + "AccountId" + ], + "type": 5 + } + }, + { + "docs": [], + "indexed": false, + "name": "value", + "type": { + "displayName": [ + "Balance" + ], + "type": 1 + } + } + ], + "docs": [ + " Event emitted when an approval occurs that `spender` is allowed to withdraw", + " up to the amount of `value` tokens from `owner`." + ], + "name": "Approval" + } + ], + "messages": [ + { + "args": [], + "docs": [ + " Returns the total token supply." + ], + "mutates": false, + "name": [ + "total_supply" + ], + "payable": false, + "returnType": { + "displayName": [ + "Balance" + ], + "type": 1 + }, + "selector": "0xdb6375a8" + }, + { + "args": [ + { + "name": "owner", + "type": { + "displayName": [ + "AccountId" + ], + "type": 5 + } + } + ], + "docs": [ + " Returns the account balance for the specified `owner`.", + "", + " Returns `0` if the account is non-existent." + ], + "mutates": false, + "name": [ + "balance_of" + ], + "payable": false, + "returnType": { + "displayName": [ + "Balance" + ], + "type": 1 + }, + "selector": "0x0f755a56" + }, + { + "args": [ + { + "name": "owner", + "type": { + "displayName": [ + "AccountId" + ], + "type": 5 + } + }, + { + "name": "spender", + "type": { + "displayName": [ + "AccountId" + ], + "type": 5 + } + } + ], + "docs": [ + " Returns the amount which `spender` is still allowed to withdraw from `owner`.", + "", + " Returns `0` if no allowance has been set `0`." + ], + "mutates": false, + "name": [ + "allowance" + ], + "payable": false, + "returnType": { + "displayName": [ + "Balance" + ], + "type": 1 + }, + "selector": "0x6a00165e" + }, + { + "args": [ + { + "name": "to", + "type": { + "displayName": [ + "AccountId" + ], + "type": 5 + } + }, + { + "name": "value", + "type": { + "displayName": [ + "Balance" + ], + "type": 1 + } + } + ], + "docs": [ + " Transfers `value` amount of tokens from the caller's account to account `to`.", + "", + " On success a `Transfer` event is emitted.", + "", + " # Errors", + "", + " Returns `InsufficientBalance` error if there are not enough tokens on", + " the caller's account balance." + ], + "mutates": true, + "name": [ + "transfer" + ], + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 12 + }, + "selector": "0x84a15da1" + }, + { + "args": [ + { + "name": "spender", + "type": { + "displayName": [ + "AccountId" + ], + "type": 5 + } + }, + { + "name": "value", + "type": { + "displayName": [ + "Balance" + ], + "type": 1 + } + } + ], + "docs": [ + " Allows `spender` to withdraw from the caller's account multiple times, up to", + " the `value` amount.", + "", + " If this function is called again it overwrites the current allowance with `value`.", + "", + " An `Approval` event is emitted." + ], + "mutates": true, + "name": [ + "approve" + ], + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 12 + }, + "selector": "0x681266a0" + }, + { + "args": [ + { + "name": "from", + "type": { + "displayName": [ + "AccountId" + ], + "type": 5 + } + }, + { + "name": "to", + "type": { + "displayName": [ + "AccountId" + ], + "type": 5 + } + }, + { + "name": "value", + "type": { + "displayName": [ + "Balance" + ], + "type": 1 + } + } + ], + "docs": [ + " Transfers `value` tokens on the behalf of `from` to the account `to`.", + "", + " This can be used to allow a contract to transfer tokens on ones behalf and/or", + " to charge fees in sub-currencies, for example.", + "", + " On success a `Transfer` event is emitted.", + "", + " # Errors", + "", + " Returns `InsufficientAllowance` error if there are not enough tokens allowed", + " for the caller to withdraw from `from`.", + "", + " Returns `InsufficientBalance` error if there are not enough tokens on", + " the account balance of `from`." + ], + "mutates": true, + "name": [ + "transfer_from" + ], + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 12 + }, + "selector": "0x0b396f18" + } + ] + }, + "storage": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x0000000000000000000000000000000000000000000000000000000000000000", + "ty": 1 + } + }, + "name": "total_supply" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x0100000000000000000000000000000000000000000000000000000000000000", + "ty": 2 + } + }, + "name": "header" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x0200000000000000000000000000000000000000000000000000000000000000", + "ty": 3 + } + }, + "name": "len" + }, + { + "layout": { + "array": { + "cellsPerElem": 1, + "layout": { + "cell": { + "key": "0x0200000001000000000000000000000000000000000000000000000000000000", + "ty": 4 + } + }, + "len": 4294967295, + "offset": "0x0300000000000000000000000000000000000000000000000000000000000000" + } + }, + "name": "elems" + } + ] + } + }, + "name": "entries" + } + ] + } + }, + "name": "keys" + }, + { + "layout": { + "hash": { + "layout": { + "cell": { + "key": "0x0300000001000000000000000000000000000000000000000000000000000000", + "ty": 9 + } + }, + "offset": "0x0200000001000000000000000000000000000000000000000000000000000000", + "strategy": { + "hasher": "Blake2x256", + "postfix": "", + "prefix": "0x696e6b20686173686d6170" + } + } + }, + "name": "values" + } + ] + } + }, + "name": "balances" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x0300000001000000000000000000000000000000000000000000000000000000", + "ty": 2 + } + }, + "name": "header" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x0400000001000000000000000000000000000000000000000000000000000000", + "ty": 3 + } + }, + "name": "len" + }, + { + "layout": { + "array": { + "cellsPerElem": 1, + "layout": { + "cell": { + "key": "0x0400000002000000000000000000000000000000000000000000000000000000", + "ty": 10 + } + }, + "len": 4294967295, + "offset": "0x0500000001000000000000000000000000000000000000000000000000000000" + } + }, + "name": "elems" + } + ] + } + }, + "name": "entries" + } + ] + } + }, + "name": "keys" + }, + { + "layout": { + "hash": { + "layout": { + "cell": { + "key": "0x0500000002000000000000000000000000000000000000000000000000000000", + "ty": 9 + } + }, + "offset": "0x0400000002000000000000000000000000000000000000000000000000000000", + "strategy": { + "hasher": "Blake2x256", + "postfix": "", + "prefix": "0x696e6b20686173686d6170" + } + } + }, + "name": "values" + } + ] + } + }, + "name": "allowances" + } + ] + } + }, + "types": [ + { + "def": { + "primitive": "u128" + } + }, + { + "def": { + "composite": { + "fields": [ + { + "name": "last_vacant", + "type": 3, + "typeName": "Index" + }, + { + "name": "len", + "type": 3, + "typeName": "u32" + }, + { + "name": "len_entries", + "type": 3, + "typeName": "u32" + } + ] + } + }, + "path": [ + "ink_storage", + "collections", + "stash", + "Header" + ] + }, + { + "def": { + "primitive": "u32" + } + }, + { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 8, + "typeName": "VacantEntry" + } + ], + "name": "Vacant" + }, + { + "fields": [ + { + "type": 5, + "typeName": "T" + } + ], + "name": "Occupied" + } + ] + } + }, + "params": [ + 5 + ], + "path": [ + "ink_storage", + "collections", + "stash", + "Entry" + ] + }, + { + "def": { + "composite": { + "fields": [ + { + "type": 6, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_env", + "types", + "AccountId" + ] + }, + { + "def": { + "array": { + "len": 32, + "type": 7 + } + } + }, + { + "def": { + "primitive": "u8" + } + }, + { + "def": { + "composite": { + "fields": [ + { + "name": "next", + "type": 3, + "typeName": "Index" + }, + { + "name": "prev", + "type": 3, + "typeName": "Index" + } + ] + } + }, + "path": [ + "ink_storage", + "collections", + "stash", + "VacantEntry" + ] + }, + { + "def": { + "composite": { + "fields": [ + { + "name": "value", + "type": 1, + "typeName": "V" + }, + { + "name": "key_index", + "type": 3, + "typeName": "KeyIndex" + } + ] + } + }, + "params": [ + 1 + ], + "path": [ + "ink_storage", + "collections", + "hashmap", + "ValueEntry" + ] + }, + { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 8, + "typeName": "VacantEntry" + } + ], + "name": "Vacant" + }, + { + "fields": [ + { + "type": 11, + "typeName": "T" + } + ], + "name": "Occupied" + } + ] + } + }, + "params": [ + 11 + ], + "path": [ + "ink_storage", + "collections", + "stash", + "Entry" + ] + }, + { + "def": { + "tuple": [ + 5, + 5 + ] + } + }, + { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 13, + "typeName": "T" + } + ], + "name": "Ok" + }, + { + "fields": [ + { + "type": 14, + "typeName": "E" + } + ], + "name": "Err" + } + ] + } + }, + "params": [ + 13, + 14 + ], + "path": [ + "Result" + ] + }, + { + "def": { + "tuple": [] + } + }, + { + "def": { + "variant": { + "variants": [ + { + "discriminant": 0, + "name": "InsufficientBalance" + }, + { + "discriminant": 1, + "name": "InsufficientAllowance" + } + ] + } + }, + "path": [ + "erc20", + "erc20", + "Error" + ] + }, + { + "def": { + "variant": { + "variants": [ + { + "name": "None" + }, + { + "fields": [ + { + "type": 5, + "typeName": "T" + } + ], + "name": "Some" + } + ] + } + }, + "params": [ + 5 + ], + "path": [ + "Option" + ] + } + ] +} \ No newline at end of file diff --git a/substrate/frame/contracts/benchmarks/ink_erc20.wasm b/substrate/frame/contracts/benchmarks/ink_erc20.wasm new file mode 100644 index 0000000000000000000000000000000000000000..ffd522760a02dd8416f8ee04db02c32e2172b8ff GIT binary patch literal 30276 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 literal 0 HcmV?d00001 diff --git a/substrate/frame/contracts/benchmarks/solang_erc20.json b/substrate/frame/contracts/benchmarks/solang_erc20.json new file mode 100644 index 0000000000..9d8fd5ce70 --- /dev/null +++ b/substrate/frame/contracts/benchmarks/solang_erc20.json @@ -0,0 +1,581 @@ +{ + "contract": { + "authors": [ + "unknown" + ], + "name": "ERC20PresetFixedSupply", + "version": "0.0.1" + }, + "metadataVersion": "0.1.0", + "source": { + "compiler": "solang 0.1.7", + "hash": "0x9c55e342566e89c741eb641eec3af796836da750fc930c55bccc0604a47ef700", + "language": "Solidity 0.1.7" + }, + "spec": { + "constructors": [ + { + "args": [ + { + "name": "name", + "type": { + "display_name": [ + "String" + ], + "type": 2 + } + }, + { + "name": "symbol", + "type": { + "display_name": [ + "String" + ], + "type": 2 + } + }, + { + "name": "initialSupply", + "type": { + "display_name": [ + "u256" + ], + "type": 1 + } + }, + { + "name": "owner", + "type": { + "display_name": [ + "AccountId" + ], + "type": 5 + } + } + ], + "docs": [ + "" + ], + "name": "new", + "selector": "0xa6f1f5e1" + } + ], + "events": [ + { + "args": [ + { + "indexed": true, + "name": "owner", + "type": { + "display_name": [ + "AccountId" + ], + "type": 5 + } + }, + { + "indexed": true, + "name": "spender", + "type": { + "display_name": [ + "AccountId" + ], + "type": 5 + } + }, + { + "indexed": false, + "name": "value", + "type": { + "display_name": [ + "u256" + ], + "type": 1 + } + } + ], + "docs": [ + "" + ], + "name": "Approval" + }, + { + "args": [ + { + "indexed": true, + "name": "from", + "type": { + "display_name": [ + "AccountId" + ], + "type": 5 + } + }, + { + "indexed": true, + "name": "to", + "type": { + "display_name": [ + "AccountId" + ], + "type": 5 + } + }, + { + "indexed": false, + "name": "value", + "type": { + "display_name": [ + "u256" + ], + "type": 1 + } + } + ], + "docs": [ + "" + ], + "name": "Transfer" + } + ], + "messages": [ + { + "args": [ + { + "name": "account", + "type": { + "display_name": [ + "AccountId" + ], + "type": 5 + } + }, + { + "name": "amount", + "type": { + "display_name": [ + "u256" + ], + "type": 1 + } + } + ], + "docs": [ + "" + ], + "mutates": true, + "name": "burnFrom", + "payable": false, + "return_type": null, + "selector": "0x0f1354f3" + }, + { + "args": [ + { + "name": "account", + "type": { + "display_name": [ + "AccountId" + ], + "type": 5 + } + } + ], + "docs": [ + "" + ], + "mutates": false, + "name": "balanceOf", + "payable": false, + "return_type": { + "display_name": [ + "u256" + ], + "type": 1 + }, + "selector": "0x6c7f1542" + }, + { + "args": [], + "docs": [ + "" + ], + "mutates": false, + "name": "totalSupply", + "payable": false, + "return_type": { + "display_name": [ + "u256" + ], + "type": 1 + }, + "selector": "0x18160ddd" + }, + { + "args": [], + "docs": [ + "" + ], + "mutates": false, + "name": "decimals", + "payable": false, + "return_type": { + "display_name": [ + "u8" + ], + "type": 3 + }, + "selector": "0x313ce567" + }, + { + "args": [ + { + "name": "owner", + "type": { + "display_name": [ + "AccountId" + ], + "type": 5 + } + }, + { + "name": "spender", + "type": { + "display_name": [ + "AccountId" + ], + "type": 5 + } + } + ], + "docs": [ + "" + ], + "mutates": false, + "name": "allowance", + "payable": false, + "return_type": { + "display_name": [ + "u256" + ], + "type": 1 + }, + "selector": "0xf2a9a8c7" + }, + { + "args": [], + "docs": [ + "" + ], + "mutates": false, + "name": "name", + "payable": false, + "return_type": { + "display_name": [ + "String" + ], + "type": 2 + }, + "selector": "0x06fdde03" + }, + { + "args": [ + { + "name": "spender", + "type": { + "display_name": [ + "AccountId" + ], + "type": 5 + } + }, + { + "name": "subtractedValue", + "type": { + "display_name": [ + "u256" + ], + "type": 1 + } + } + ], + "docs": [ + "" + ], + "mutates": true, + "name": "decreaseAllowance", + "payable": false, + "return_type": { + "display_name": [ + "bool" + ], + "type": 6 + }, + "selector": "0x4b76697b" + }, + { + "args": [ + { + "name": "sender", + "type": { + "display_name": [ + "AccountId" + ], + "type": 5 + } + }, + { + "name": "recipient", + "type": { + "display_name": [ + "AccountId" + ], + "type": 5 + } + }, + { + "name": "amount", + "type": { + "display_name": [ + "u256" + ], + "type": 1 + } + } + ], + "docs": [ + "" + ], + "mutates": true, + "name": "transferFrom", + "payable": false, + "return_type": { + "display_name": [ + "bool" + ], + "type": 6 + }, + "selector": "0x2fb840f5" + }, + { + "args": [], + "docs": [ + "" + ], + "mutates": false, + "name": "symbol", + "payable": false, + "return_type": { + "display_name": [ + "String" + ], + "type": 2 + }, + "selector": "0x95d89b41" + }, + { + "args": [ + { + "name": "spender", + "type": { + "display_name": [ + "AccountId" + ], + "type": 5 + } + }, + { + "name": "addedValue", + "type": { + "display_name": [ + "u256" + ], + "type": 1 + } + } + ], + "docs": [ + "" + ], + "mutates": true, + "name": "increaseAllowance", + "payable": false, + "return_type": { + "display_name": [ + "bool" + ], + "type": 6 + }, + "selector": "0xb936c899" + }, + { + "args": [ + { + "name": "recipient", + "type": { + "display_name": [ + "AccountId" + ], + "type": 5 + } + }, + { + "name": "amount", + "type": { + "display_name": [ + "u256" + ], + "type": 1 + } + } + ], + "docs": [ + "" + ], + "mutates": true, + "name": "transfer", + "payable": false, + "return_type": { + "display_name": [ + "bool" + ], + "type": 6 + }, + "selector": "0x6a467394" + }, + { + "args": [ + { + "name": "spender", + "type": { + "display_name": [ + "AccountId" + ], + "type": 5 + } + }, + { + "name": "amount", + "type": { + "display_name": [ + "u256" + ], + "type": 1 + } + } + ], + "docs": [ + "" + ], + "mutates": true, + "name": "approve", + "payable": false, + "return_type": { + "display_name": [ + "bool" + ], + "type": 6 + }, + "selector": "0x47144421" + }, + { + "args": [ + { + "name": "amount", + "type": { + "display_name": [ + "u256" + ], + "type": 1 + } + } + ], + "docs": [ + "" + ], + "mutates": true, + "name": "burn", + "payable": false, + "return_type": null, + "selector": "0x42966c68" + } + ] + }, + "storage": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x0000000000000000000000000000000000000000000000000000000000000002", + "ty": 1 + } + }, + "name": "_totalSupply" + }, + { + "layout": { + "cell": { + "key": "0x0000000000000000000000000000000000000000000000000000000000000003", + "ty": 2 + } + }, + "name": "_name" + }, + { + "layout": { + "cell": { + "key": "0x0000000000000000000000000000000000000000000000000000000000000004", + "ty": 2 + } + }, + "name": "_symbol" + } + ] + } + }, + "types": [ + { + "def": { + "primitive": "u256" + } + }, + { + "def": { + "primitive": "str" + } + }, + { + "def": { + "primitive": "u8" + } + }, + { + "def": { + "array": { + "len": 32, + "type": 3 + } + } + }, + { + "def": { + "composite": { + "fields": [ + { + "type": 4 + } + ] + } + }, + "path": [ + "AccountId" + ] + }, + { + "def": { + "primitive": "bool" + } + } + ] +} diff --git a/substrate/frame/contracts/benchmarks/solang_erc20.wasm b/substrate/frame/contracts/benchmarks/solang_erc20.wasm new file mode 100644 index 0000000000000000000000000000000000000000..0796085d33249b78871f4a336623444a0ef94e85 GIT binary patch literal 12505 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 PJ@CN6d-u(code); } let code = code.to_bytes().unwrap(); @@ -257,6 +254,34 @@ where T: Config, T::AccountId: UncheckedFrom + AsRef<[u8]>, { + /// Uses the supplied wasm module and instruments it when requested. + pub fn instrumented(code: &[u8], inject_gas: bool, inject_stack: bool) -> Self { + let module = { + let mut module = Module::from_bytes(code).unwrap(); + if inject_gas { + module = inject_gas_metering::(module); + } + if inject_stack { + module = inject_stack_metering::(module); + } + module + }; + let limits = module + .import_section() + .unwrap() + .entries() + .iter() + .find_map(|e| if let External::Memory(mem) = e.external() { Some(mem) } else { None }) + .unwrap() + .limits() + .clone(); + let code = module.to_bytes().unwrap(); + let hash = T::Hashing::hash(&code); + let memory = + ImportedMemory { min_pages: limits.initial(), max_pages: limits.maximum().unwrap() }; + Self { code, hash, memory: Some(memory) } + } + /// Creates a wasm module with an empty `call` and `deploy` function and nothing else. pub fn dummy() -> Self { ModuleDefinition::default().into() @@ -519,3 +544,14 @@ where { T::Schedule::get().limits.memory_pages } + +fn inject_gas_metering(module: Module) -> Module { + let schedule = T::Schedule::get(); + let gas_rules = schedule.rules(&module); + pwasm_utils::inject_gas_counter(module, &gas_rules, "seal0").unwrap() +} + +fn inject_stack_metering(module: Module) -> Module { + let height = T::Schedule::get().limits.stack_height; + pwasm_utils::stack_height::inject_limiter(module, height).unwrap() +} diff --git a/substrate/frame/contracts/src/benchmarking/mod.rs b/substrate/frame/contracts/src/benchmarking/mod.rs index 1ffb84dad9..c3757cf705 100644 --- a/substrate/frame/contracts/src/benchmarking/mod.rs +++ b/substrate/frame/contracts/src/benchmarking/mod.rs @@ -30,7 +30,7 @@ use self::{ sandbox::Sandbox, }; use crate::{ - exec::StorageKey, + exec::{AccountIdOf, StorageKey}, rent::Rent, schedule::{API_BENCHMARK_BATCH_SIZE, INSTR_BENCHMARK_BATCH_SIZE}, storage::Storage, @@ -124,9 +124,9 @@ where .saturating_mul(>::from(storage_size) / 2u32.into()) .saturating_add(T::DepositPerContract::get()); - (storage_size, endowment) + (Some(storage_size), endowment) }, - Endow::Max => (0u32.into(), Endow::max::()), + Endow::Max => (None, Endow::max::()), }; T::Currency::make_free_balance_be(&caller, caller_funding::()); let salt = vec![0xff]; @@ -158,7 +158,9 @@ where }; let mut contract = result.alive_info()?; - contract.storage_size = storage_size; + if let Some(size) = storage_size { + contract.storage_size = size; + } ContractInfoOf::::insert(&result.account_id, ContractInfo::Alive(contract)); Ok(result) @@ -278,6 +280,24 @@ fn caller_funding() -> BalanceOf { BalanceOf::::max_value() / 2u32.into() } +/// Load the specified contract file from disk by including it into the runtime. +/// +/// We need to load a different version of ink! contracts when the benchmark is run as +/// a test. This is because ink! contracts depend on the sizes of types that are defined +/// differently in the test environment. Solang is more lax in that regard. +macro_rules! load_benchmark { + ($name:expr) => {{ + #[cfg(not(test))] + { + include_bytes!(concat!("../../benchmarks/", $name, ".wasm")) + } + #[cfg(test)] + { + include_bytes!(concat!("../../benchmarks/", $name, "_test.wasm")) + } + }}; +} + benchmarks! { where_clause { where T::AccountId: UncheckedFrom, @@ -2536,6 +2556,88 @@ benchmarks! { #[cfg(not(feature = "std"))] return Err("Run this bench with a native runtime in order to see the schedule."); }: {} + + // Execute one erc20 transfer using the ink! erc20 example contract. + // + // `g` is used to enable gas instrumentation to compare the performance impact of + // that instrumentation at runtime. + #[extra] + ink_erc20_transfer { + let g in 0 .. 1; + let gas_metering = if g == 0 { false } else { true }; + let code = load_benchmark!("ink_erc20"); + let data = { + let new: ([u8; 4], BalanceOf) = ([0x9b, 0xae, 0x9d, 0x5e], 1000u32.into()); + new.encode() + }; + let instance = Contract::::new( + WasmModule::instrumented(code, gas_metering, true), data, Endow::Max, + )?; + let data = { + let transfer: ([u8; 4], AccountIdOf, BalanceOf) = ( + [0x84, 0xa1, 0x5d, 0xa1], + account::("receiver", 0, 0), + 1u32.into(), + ); + transfer.encode() + }; + }: { + >::bare_call( + instance.caller, + instance.account_id, + 0u32.into(), + Weight::MAX, + data, + false, + ) + .result?; + } + + // Execute one erc20 transfer using the open zeppelin erc20 contract compiled with solang. + // + // `g` is used to enable gas instrumentation to compare the performance impact of + // that instrumentation at runtime. + #[extra] + solang_erc20_transfer { + let g in 0 .. 1; + let gas_metering = if g == 0 { false } else { true }; + let code = include_bytes!("../../benchmarks/solang_erc20.wasm"); + let caller = account::("instantiator", 0, 0); + let mut balance = [0u8; 32]; + balance[0] = 100; + let data = { + let new: ([u8; 4], &str, &str, [u8; 32], AccountIdOf) = ( + [0xa6, 0xf1, 0xf5, 0xe1], + "KSM", + "K", + balance, + caller.clone(), + ); + new.encode() + }; + let instance = Contract::::with_caller( + caller, WasmModule::instrumented(code, gas_metering, true), data, Endow::Max, + )?; + balance[0] = 1; + let data = { + let transfer: ([u8; 4], AccountIdOf, [u8; 32]) = ( + [0x6a, 0x46, 0x73, 0x94], + account::("receiver", 0, 0), + balance, + ); + transfer.encode() + }; + }: { + >::bare_call( + instance.caller, + instance.account_id, + 0u32.into(), + Weight::MAX, + data, + false, + ) + .result?; + } } impl_benchmark_test_suite!(