From fdd07a94cf81a23d577d62109ce1182ab4831c79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Wed, 11 Aug 2021 12:03:55 +0200 Subject: [PATCH 1/3] Add erc20 benchmarks --- 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 frame/contracts/benchmarks/solang_ERC20.json | 581 +++++++++++++ frame/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 frame/contracts/benchmarks/README.md create mode 100644 frame/contracts/benchmarks/ink_erc20.json create mode 100644 frame/contracts/benchmarks/ink_erc20.wasm create mode 100644 frame/contracts/benchmarks/ink_erc20_test.wasm create mode 100644 frame/contracts/benchmarks/solang_ERC20.json create mode 100644 frame/contracts/benchmarks/solang_ERC20.wasm diff --git a/frame/contracts/benchmarks/README.md b/frame/contracts/benchmarks/README.md new file mode 100644 index 0000000000000..95630d9e89d9a --- /dev/null +++ b/frame/contracts/benchmarks/README.md @@ -0,0 +1,9 @@ +# Benchmarks + +This directory contain 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/frame/contracts/benchmarks/ink_erc20.json b/frame/contracts/benchmarks/ink_erc20.json new file mode 100644 index 0000000000000..390dd9b06cd4c --- /dev/null +++ b/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/frame/contracts/benchmarks/ink_erc20.wasm b/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/frame/contracts/benchmarks/solang_ERC20.json b/frame/contracts/benchmarks/solang_ERC20.json new file mode 100644 index 0000000000000..9d8fd5ce70e70 --- /dev/null +++ b/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/frame/contracts/benchmarks/solang_ERC20.wasm b/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/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index 1ffb84dad9aa5..c3757cf705bf4 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/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!( From a6793567524733adb03615e59182edc992e2c058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Mon, 30 Aug 2021 12:01:22 +0200 Subject: [PATCH 2/3] Fix typos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michael Müller --- frame/contracts/benchmarks/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/contracts/benchmarks/README.md b/frame/contracts/benchmarks/README.md index 95630d9e89d9a..a4b15bd840db4 100644 --- a/frame/contracts/benchmarks/README.md +++ b/frame/contracts/benchmarks/README.md @@ -1,6 +1,6 @@ # Benchmarks -This directory contain real world (ink, solang) contracts which are used in macro 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. From 931a427a39ebffc6933ffbbaa15bab33d57b2439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Mon, 6 Sep 2021 12:51:39 +0200 Subject: [PATCH 3/3] Fix compilation issue on case sensitive fs --- .../{solang_ERC20.json => solang_erc20.json} | 0 .../{solang_ERC20.wasm => solang_erc20.wasm} | Bin 2 files changed, 0 insertions(+), 0 deletions(-) rename frame/contracts/benchmarks/{solang_ERC20.json => solang_erc20.json} (100%) rename frame/contracts/benchmarks/{solang_ERC20.wasm => solang_erc20.wasm} (100%) diff --git a/frame/contracts/benchmarks/solang_ERC20.json b/frame/contracts/benchmarks/solang_erc20.json similarity index 100% rename from frame/contracts/benchmarks/solang_ERC20.json rename to frame/contracts/benchmarks/solang_erc20.json diff --git a/frame/contracts/benchmarks/solang_ERC20.wasm b/frame/contracts/benchmarks/solang_erc20.wasm similarity index 100% rename from frame/contracts/benchmarks/solang_ERC20.wasm rename to frame/contracts/benchmarks/solang_erc20.wasm