Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
ea3785b1
Commit
ea3785b1
authored
Nov 20, 2020
by
ben-chain
Committed by
GitHub
Nov 20, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
first pass (#71)
parent
a72141f4
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
570 additions
and
6 deletions
+570
-6
Helper_GasMeasurer.sol
...s/contracts/contracts/test-helpers/Helper_GasMeasurer.sol
+32
-0
package.json
packages/contracts/package.json
+1
-1
OVM_StateManager.gas-spec.ts
...test/contracts/OVM/execution/OVM_StateManager.gas-spec.ts
+527
-0
OVM_StateManager.spec.ts
...cts/test/contracts/OVM/execution/OVM_StateManager.spec.ts
+2
-5
constants.ts
packages/contracts/test/helpers/constants.ts
+8
-0
No files found.
packages/contracts/contracts/test-helpers/Helper_GasMeasurer.sol
0 → 100644
View file @
ea3785b1
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
contract Helper_GasMeasurer {
function measureCallGas(
address _target,
bytes memory _data
)
public
returns ( uint )
{
uint gasBefore;
uint gasAfter;
uint calldataStart;
uint calldataLength;
assembly {
calldataStart := add(_data,0x20)
calldataLength := mload(_data)
}
bool success;
assembly {
gasBefore := gas()
success := call(gas(), _target, 0, calldataStart, calldataLength, 0, 0)
gasAfter := gas()
}
require(success, "Call failed, but calls we want to measure gas for should succeed!");
return gasBefore - gasAfter;
}
}
packages/contracts/package.json
View file @
ea3785b1
...
...
@@ -19,9 +19,9 @@
"build:typechain"
:
"buidler typechain"
,
"test"
:
"yarn run test:contracts"
,
"test:contracts"
:
"buidler test --show-stack-traces"
,
"test:gas"
:
"buidler test
\"
test/contracts/OVM/execution/OVM_StateManager.gas-spec.ts
\"
--no-compile --show-stack-traces"
,
"lint"
:
"yarn run lint:typescript"
,
"lint:typescript"
:
"tslint --format stylish --project ."
,
"lint:fix"
:
"yarn run lint:fix:typescript"
,
"lint:fix:typescript"
:
"prettier --config prettier-config.json --write
\"
buidler.config.ts
\"
\"
{src,test}/**/*.ts
\"
"
,
"clean"
:
"rm -rf ./artifacts ./build ./cache"
,
"deploy"
:
"./bin/deploy.js"
...
...
packages/contracts/test/contracts/OVM/execution/OVM_StateManager.gas-spec.ts
0 → 100644
View file @
ea3785b1
import
{
expect
}
from
'
../../../setup
'
/* External Imports */
import
{
ethers
}
from
'
@nomiclabs/buidler
'
import
{
Contract
,
ContractFactory
,
Signer
,
BigNumber
}
from
'
ethers
'
import
_
from
'
lodash
'
/* Internal Imports */
import
{
DUMMY_ACCOUNTS
,
DUMMY_BYTES32
,
ZERO_ADDRESS
,
EMPTY_ACCOUNT_CODE_HASH
,
NON_ZERO_ADDRESS
,
NON_NULL_BYTES32
,
STORAGE_XOR_VALUE
}
from
'
../../../helpers
'
const
DUMMY_ACCOUNT
=
DUMMY_ACCOUNTS
[
0
]
const
DUMMY_KEY
=
DUMMY_BYTES32
[
0
]
const
DUMMY_VALUE_1
=
DUMMY_BYTES32
[
1
]
const
DUMMY_VALUE_2
=
DUMMY_BYTES32
[
2
]
describe
(
'
OVM_StateManager gas consumption
'
,
()
=>
{
let
owner
:
Signer
before
(
async
()
=>
{
;[
owner
]
=
await
ethers
.
getSigners
()
})
let
Factory__OVM_StateManager
:
ContractFactory
let
Helper_GasMeasurer
:
Contract
before
(
async
()
=>
{
Factory__OVM_StateManager
=
await
ethers
.
getContractFactory
(
'
OVM_StateManager
'
)
Helper_GasMeasurer
=
await
(
await
(
await
ethers
.
getContractFactory
(
'
Helper_GasMeasurer
'
)).
deploy
()).
connect
(
owner
)
})
let
OVM_StateManager
:
Contract
beforeEach
(
async
()
=>
{
OVM_StateManager
=
(
await
Factory__OVM_StateManager
.
deploy
(
await
owner
.
getAddress
())
).
connect
(
owner
)
await
OVM_StateManager
.
setExecutionManager
(
Helper_GasMeasurer
.
address
)
})
const
measure
=
(
methodName
:
string
,
methodArgs
:
Array
<
any
>
=
[],
doFirst
:
()
=>
Promise
<
any
>
=
async
()
=>
{
return
}
)
=>
{
it
(
'
measured consumption!
'
,
async
()
=>
{
await
doFirst
()
await
getSMGasCost
(
methodName
,
methodArgs
)
})
}
const
getSMGasCost
=
async
(
methodName
:
string
,
methodArgs
:
Array
<
any
>
=
[]):
Promise
<
number
>
=>
{
const
gasCost
:
number
=
await
Helper_GasMeasurer
.
callStatic
.
measureCallGas
(
OVM_StateManager
.
address
,
OVM_StateManager
.
interface
.
encodeFunctionData
(
methodName
,
methodArgs
)
)
console
.
log
(
` calculated gas cost of
${
gasCost
}
`
)
return
gasCost
}
const
setupFreshAccount
=
async
()
=>
{
await
OVM_StateManager
.
putAccount
(
DUMMY_ACCOUNT
.
address
,
{
...
DUMMY_ACCOUNT
.
data
,
isFresh
:
true
,
})
}
const
setupNonFreshAccount
=
async
()
=>
{
await
OVM_StateManager
.
putAccount
(
DUMMY_ACCOUNT
.
address
,
DUMMY_ACCOUNT
.
data
)
}
const
putSlot
=
async
(
value
:
string
)
=>
{
await
OVM_StateManager
.
putContractStorage
(
DUMMY_ACCOUNT
.
address
,
DUMMY_KEY
,
value
)
}
describe
(
'
ItemState testAndSetters
'
,
()
=>
{
describe
(
'
testAndSetAccountLoaded
'
,
()
=>
{
describe
(
'
when account ItemState is ITEM_UNTOUCHED
'
,
()
=>
{
measure
(
'
testAndSetAccountLoaded
'
,
[
NON_ZERO_ADDRESS
]
)
})
describe
(
'
when account ItemState is ITEM_LOADED
'
,
()
=>
{
measure
(
'
testAndSetAccountLoaded
'
,
[
NON_ZERO_ADDRESS
],
async
()
=>
{
await
OVM_StateManager
.
testAndSetAccountLoaded
(
NON_ZERO_ADDRESS
)
}
)
})
describe
(
'
when account ItemState is ITEM_CHANGED
'
,
()
=>
{
measure
(
'
testAndSetAccountLoaded
'
,
[
NON_ZERO_ADDRESS
],
async
()
=>
{
await
OVM_StateManager
.
testAndSetAccountChanged
(
NON_ZERO_ADDRESS
)
}
)
})
})
describe
(
'
testAndSetAccountChanged
'
,
()
=>
{
describe
(
'
when account ItemState is ITEM_UNTOUCHED
'
,
()
=>
{
measure
(
'
testAndSetAccountChanged
'
,
[
NON_ZERO_ADDRESS
]
)
})
describe
(
'
when account ItemState is ITEM_LOADED
'
,
()
=>
{
measure
(
'
testAndSetAccountChanged
'
,
[
NON_ZERO_ADDRESS
],
async
()
=>
{
await
OVM_StateManager
.
testAndSetAccountLoaded
(
NON_ZERO_ADDRESS
)
}
)
})
describe
(
'
when account ItemState is ITEM_CHANGED
'
,
()
=>
{
measure
(
'
testAndSetAccountChanged
'
,
[
NON_ZERO_ADDRESS
],
async
()
=>
{
await
OVM_StateManager
.
testAndSetAccountChanged
(
NON_ZERO_ADDRESS
)
}
)
})
})
describe
(
'
testAndSetContractStorageLoaded
'
,
()
=>
{
describe
(
'
when storage ItemState is ITEM_UNTOUCHED
'
,
()
=>
{
measure
(
'
testAndSetContractStorageLoaded
'
,
[
NON_ZERO_ADDRESS
,
DUMMY_KEY
]
)
})
describe
(
'
when storage ItemState is ITEM_LOADED
'
,
()
=>
{
measure
(
'
testAndSetContractStorageLoaded
'
,
[
NON_ZERO_ADDRESS
,
DUMMY_KEY
],
async
()
=>
{
await
OVM_StateManager
.
testAndSetContractStorageLoaded
(
NON_ZERO_ADDRESS
,
DUMMY_KEY
)
}
)
})
describe
(
'
when storage ItemState is ITEM_CHANGED
'
,
()
=>
{
measure
(
'
testAndSetContractStorageLoaded
'
,
[
NON_ZERO_ADDRESS
,
DUMMY_KEY
],
async
()
=>
{
await
OVM_StateManager
.
testAndSetContractStorageChanged
(
NON_ZERO_ADDRESS
,
DUMMY_KEY
)
}
)
})
})
describe
(
'
testAndSetContractStorageChanged
'
,
()
=>
{
describe
(
'
when storage ItemState is ITEM_UNTOUCHED
'
,
()
=>
{
measure
(
'
testAndSetContractStorageChanged
'
,
[
NON_ZERO_ADDRESS
,
DUMMY_KEY
]
)
})
describe
(
'
when storage ItemState is ITEM_LOADED
'
,
()
=>
{
measure
(
'
testAndSetContractStorageChanged
'
,
[
NON_ZERO_ADDRESS
,
DUMMY_KEY
],
async
()
=>
{
await
OVM_StateManager
.
testAndSetContractStorageLoaded
(
NON_ZERO_ADDRESS
,
DUMMY_KEY
)
}
)
})
describe
(
'
when storage ItemState is ITEM_CHANGED
'
,
()
=>
{
measure
(
'
testAndSetContractStorageChanged
'
,
[
NON_ZERO_ADDRESS
,
DUMMY_KEY
],
async
()
=>
{
await
OVM_StateManager
.
testAndSetContractStorageChanged
(
NON_ZERO_ADDRESS
,
DUMMY_KEY
)
}
)
})
})
})
describe
(
'
incrementTotalUncommittedAccounts
'
,
()
=>
{
describe
(
'
when totalUncommittedAccounts is 0
'
,
()
=>
{
measure
(
'
incrementTotalUncommittedAccounts
'
)
})
describe
(
'
when totalUncommittedAccounts is nonzero
'
,
()
=>
{
const
doFirst
=
async
()
=>
{
await
OVM_StateManager
.
incrementTotalUncommittedAccounts
()
}
measure
(
'
incrementTotalUncommittedAccounts
'
,
[],
doFirst
)
})
})
describe
(
'
incrementTotalUncommittedContractStorage
'
,
()
=>
{
describe
(
'
when totalUncommittedContractStorage is 0
'
,
()
=>
{
measure
(
'
incrementTotalUncommittedContractStorage
'
)
})
describe
(
'
when totalUncommittedContractStorage is nonzero
'
,
()
=>
{
const
doFirst
=
async
()
=>
{
await
OVM_StateManager
.
incrementTotalUncommittedContractStorage
()
}
measure
(
'
incrementTotalUncommittedContractStorage
'
,
[],
doFirst
)
})
})
describe
(
'
hasAccount
'
,
()
=>
{
describe
(
'
when it does have the account
'
,
()
=>
{
const
doFirst
=
async
()
=>
{
await
OVM_StateManager
.
putAccount
(
DUMMY_ACCOUNT
.
address
,
DUMMY_ACCOUNT
.
data
)
}
measure
(
'
hasAccount
'
,
[
DUMMY_ACCOUNT
.
address
],
doFirst
)
})
})
describe
(
'
hasEmptyAccount
'
,
()
=>
{
describe
(
'
when it does have an empty account
'
,
()
=>
{
measure
(
'
hasEmptyAccount
'
,
[
DUMMY_ACCOUNT
.
address
],
async
()
=>
{
await
OVM_StateManager
.
putAccount
(
DUMMY_ACCOUNT
.
address
,
{
...
DUMMY_ACCOUNT
.
data
,
codeHash
:
EMPTY_ACCOUNT_CODE_HASH
,
})
}
)
})
describe
(
'
when it has an account which is not emtpy
'
,
()
=>
{
measure
(
'
hasEmptyAccount
'
,
[
DUMMY_ACCOUNT
.
address
],
async
()
=>
{
await
OVM_StateManager
.
putAccount
(
DUMMY_ACCOUNT
.
address
,
DUMMY_ACCOUNT
.
data
)
}
)
})
})
describe
(
'
setAccountNonce
'
,
()
=>
{
describe
(
'
when the nonce is 0 and set to 0
'
,
()
=>
{
measure
(
'
setAccountNonce
'
,
[
DUMMY_ACCOUNT
.
address
,
0
],
async
()
=>
{
await
OVM_StateManager
.
putAccount
(
DUMMY_ACCOUNT
.
address
,
{
...
DUMMY_ACCOUNT
.
data
,
nonce
:
0
}
)
}
)
})
describe
(
'
when the nonce is 0 and set to nonzero
'
,
()
=>
{
measure
(
'
setAccountNonce
'
,
[
DUMMY_ACCOUNT
.
address
,
1
],
async
()
=>
{
await
OVM_StateManager
.
putAccount
(
DUMMY_ACCOUNT
.
address
,
{
...
DUMMY_ACCOUNT
.
data
,
nonce
:
0
}
)
}
)
})
describe
(
'
when the nonce is nonzero and set to 0
'
,
()
=>
{
measure
(
'
setAccountNonce
'
,
[
DUMMY_ACCOUNT
.
address
,
0
],
async
()
=>
{
await
OVM_StateManager
.
putAccount
(
DUMMY_ACCOUNT
.
address
,
{
...
DUMMY_ACCOUNT
.
data
,
nonce
:
1
}
)
}
)
})
describe
(
'
when the nonce is nonzero and set to nonzero
'
,
()
=>
{
measure
(
'
setAccountNonce
'
,
[
DUMMY_ACCOUNT
.
address
,
2
],
async
()
=>
{
await
OVM_StateManager
.
putAccount
(
DUMMY_ACCOUNT
.
address
,
{
...
DUMMY_ACCOUNT
.
data
,
nonce
:
1
}
)
}
)
})
})
describe
(
'
getAccountNonce
'
,
()
=>
{
describe
(
'
when the nonce is 0
'
,
()
=>
{
measure
(
'
getAccountNonce
'
,
[
DUMMY_ACCOUNT
.
address
]
)
})
describe
(
'
when the nonce is nonzero
'
,
()
=>
{
measure
(
'
getAccountNonce
'
,
[
DUMMY_ACCOUNT
.
address
],
async
()
=>
{
await
OVM_StateManager
.
putAccount
(
DUMMY_ACCOUNT
.
address
,
{
...
DUMMY_ACCOUNT
.
data
,
nonce
:
1
}
)
}
)
})
})
describe
(
'
getAccountEthAddress
'
,
()
=>
{
describe
(
'
when the ethAddress is a random address
'
,
()
=>
{
measure
(
'
getAccountEthAddress
'
,
[
DUMMY_ACCOUNT
.
address
],
async
()
=>
{
await
OVM_StateManager
.
putAccount
(
DUMMY_ACCOUNT
.
address
,
{
...
DUMMY_ACCOUNT
.
data
,
ethAddress
:
NON_ZERO_ADDRESS
}
)
}
)
})
describe
(
'
when the ethAddress is zero
'
,
()
=>
{
measure
(
'
getAccountEthAddress
'
,
[
DUMMY_ACCOUNT
.
address
],
async
()
=>
{
await
OVM_StateManager
.
putAccount
(
DUMMY_ACCOUNT
.
address
,
{
...
DUMMY_ACCOUNT
.
data
,
ethAddress
:
ZERO_ADDRESS
}
)
}
)
})
})
describe
(
'
initPendingAccount
'
,
()
=>
{
// note: this method should only be accessibl if _hasEmptyAccount is true, so it should always be empty nonce etc
measure
(
'
initPendingAccount
'
,
[
NON_ZERO_ADDRESS
]
)
})
describe
(
'
commitPendingAccount
'
,
()
=>
{
// this should only set ethAddress and codeHash from ZERO to NONZERO, so one case should be sufficient
measure
(
'
commitPendingAccount
'
,
[
NON_ZERO_ADDRESS
,
NON_ZERO_ADDRESS
,
NON_NULL_BYTES32
],
async
()
=>
{
await
OVM_StateManager
.
initPendingAccount
(
NON_ZERO_ADDRESS
)
}
)
})
describe
(
'
getContractStorage
'
,
()
=>
{
// confirm with kelvin that this covers all cases
describe
(
'
when the account isFresh
'
,
()
=>
{
describe
(
'
when the storage slot value has not been set
'
,
()
=>
{
measure
(
'
getContractStorage
'
,
[
DUMMY_ACCOUNT
.
address
,
DUMMY_KEY
],
setupFreshAccount
)
})
describe
(
'
when the storage slot has already been set
'
,
()
=>
{
describe
(
'
when the storage slot value is STORAGE_XOR_VALUE
'
,
()
=>
{
measure
(
'
getContractStorage
'
,
[
DUMMY_ACCOUNT
.
address
,
DUMMY_KEY
],
async
()
=>
{
await
setupFreshAccount
()
await
putSlot
(
STORAGE_XOR_VALUE
)
}
)
})
describe
(
'
when the storage slot value is something other than STORAGE_XOR_VALUE
'
,
()
=>
{
measure
(
'
getContractStorage
'
,
[
DUMMY_ACCOUNT
.
address
,
DUMMY_KEY
],
async
()
=>
{
await
setupFreshAccount
()
await
putSlot
(
DUMMY_VALUE_1
)
}
)
})
})
})
describe
(
'
when the account is not fresh
'
,
()
=>
{
describe
(
'
when the storage slot value is STORAGE_XOR_VALUE
'
,
()
=>
{
measure
(
'
getContractStorage
'
,
[
DUMMY_ACCOUNT
.
address
,
DUMMY_KEY
],
async
()
=>
{
await
setupNonFreshAccount
()
await
putSlot
(
STORAGE_XOR_VALUE
)
}
)
})
describe
(
'
when the storage slot value is something other than STORAGE_XOR_VALUE
'
,
()
=>
{
measure
(
'
getContractStorage
'
,
[
DUMMY_ACCOUNT
.
address
,
DUMMY_KEY
],
async
()
=>
{
await
setupNonFreshAccount
()
await
putSlot
(
DUMMY_VALUE_1
)
}
)
})
})
})
describe
(
'
putContractStorage
'
,
()
=>
{
const
relevantValues
=
[
DUMMY_VALUE_1
,
DUMMY_VALUE_2
,
STORAGE_XOR_VALUE
]
for
(
let
preValue
of
relevantValues
)
{
for
(
let
postValue
of
relevantValues
)
{
describe
(
`when overwriting
${
preValue
}
with
${
postValue
}
`
,
()
=>
{
measure
(
'
putContractStorage
'
,
[
NON_ZERO_ADDRESS
,
DUMMY_KEY
,
postValue
],
async
()
=>
{
await
OVM_StateManager
.
putContractStorage
(
NON_ZERO_ADDRESS
,
DUMMY_KEY
,
preValue
)
}
)
})
}
}
})
describe
(
'
hasContractStorage
'
,
()
=>
{
describe
(
'
when the account is fresh
'
,
()
=>
{
describe
(
'
when the storage slot has not been set
'
,
()
=>
{
measure
(
'
hasContractStorage
'
,
[
DUMMY_ACCOUNT
.
address
,
DUMMY_KEY
],
setupFreshAccount
)
})
describe
(
'
when the slot has already been set
'
,
()
=>
{
measure
(
'
hasContractStorage
'
,
[
DUMMY_ACCOUNT
.
address
,
DUMMY_KEY
],
async
()
=>
{
await
setupFreshAccount
()
await
OVM_StateManager
.
putContractStorage
(
DUMMY_ACCOUNT
.
address
,
DUMMY_KEY
,
DUMMY_VALUE_1
)
}
)
})
})
describe
(
'
when the account is not fresh
'
,
()
=>
{
measure
(
'
hasContractStorage
'
,
[
DUMMY_ACCOUNT
.
address
,
DUMMY_KEY
],
async
()
=>
{
await
OVM_StateManager
.
putContractStorage
(
DUMMY_ACCOUNT
.
address
,
DUMMY_KEY
,
DUMMY_VALUE_1
)
}
)
})
})
})
\ No newline at end of file
packages/contracts/test/contracts/OVM/execution/OVM_StateManager.spec.ts
View file @
ea3785b1
...
...
@@ -6,12 +6,9 @@ import { Contract, ContractFactory, Signer, BigNumber } from 'ethers'
import
_
from
'
lodash
'
/* Internal Imports */
import
{
DUMMY_ACCOUNTS
,
DUMMY_BYTES32
,
ZERO_ADDRESS
}
from
'
../../../helpers
'
import
{
DUMMY_ACCOUNTS
,
DUMMY_BYTES32
,
ZERO_ADDRESS
,
EMPTY_ACCOUNT_CODE_HASH
,
KECCAK_256_NULL
}
from
'
../../../helpers
'
const
EMPTY_ACCOUNT_CODE_HASH
=
'
0x00004B1DC0DE000000004B1DC0DE000000004B1DC0DE000000004B1DC0DE0000
'
const
KECCAK_256_NULL
=
'
0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
'
describe
(
'
OVM_StateManager
'
,
()
=>
{
let
signer1
:
Signer
...
...
packages/contracts/test/helpers/constants.ts
View file @
ea3785b1
...
...
@@ -26,6 +26,9 @@ export const NON_ZERO_ADDRESS = makeAddress('11')
export
const
VERIFIED_EMPTY_CONTRACT_HASH
=
'
0x00004B1DC0DE000000004B1DC0DE000000004B1DC0DE000000004B1DC0DE0000
'
export
const
STORAGE_XOR_VALUE
=
'
0xFEEDFACECAFEBEEFFEEDFACECAFEBEEFFEEDFACECAFEBEEFFEEDFACECAFEBEEF
'
export
const
NUISANCE_GAS_COSTS
=
{
NUISANCE_GAS_SLOAD
:
20000
,
NUISANCE_GAS_SSTORE
:
20000
,
...
...
@@ -42,3 +45,8 @@ export const STORAGE_XOR =
export
const
getStorageXOR
=
(
key
:
string
):
string
=>
{
return
toHexString
(
xor
(
fromHexString
(
key
),
fromHexString
(
STORAGE_XOR
)))
}
export
const
EMPTY_ACCOUNT_CODE_HASH
=
'
0x00004B1DC0DE000000004B1DC0DE000000004B1DC0DE000000004B1DC0DE0000
'
export
const
KECCAK_256_NULL
=
'
0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
'
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment