Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
2c41728
refactor contracts
ben-chain Jul 30, 2020
f49cb50
all existing tests passing
ben-chain Jul 31, 2020
c5ddbff
old test building, not passing
ben-chain Jul 31, 2020
7f3f272
merge master
ben-chain Jul 31, 2020
b953ec3
add missing merge resolution
ben-chain Jul 31, 2020
429b0bd
merged contract building
ben-chain Jul 31, 2020
28dea2d
more tests passing
ben-chain Aug 2, 2020
d33a37f
something still brokn
ben-chain Aug 3, 2020
b089d66
fix all non-metering tests
ben-chain Aug 3, 2020
e7e7b81
first pass gas meter tests passing
ben-chain Aug 4, 2020
a4fafe2
merge master, deployment config updates
ben-chain Aug 4, 2020
b6b9851
linting
ben-chain Aug 4, 2020
58990b6
linting
ben-chain Aug 4, 2020
b7e8456
remove rollup-core dependency from contracts
ben-chain Aug 4, 2020
a3e5feb
linting
ben-chain Aug 4, 2020
19ce5c4
remove missed import
ben-chain Aug 4, 2020
52c7182
PR feedback, adding tx base fee validation
ben-chain Aug 5, 2020
a81d322
break out more gas functions
ben-chain Aug 5, 2020
8017b28
linting
ben-chain Aug 5, 2020
f42b553
Merge branch 'master' into feat/YAS423/new-contracts-gas-metering
ben-chain Aug 5, 2020
67c2b87
update default params to getter function
ben-chain Aug 5, 2020
c24f56d
linting
ben-chain Aug 5, 2020
b9a8803
move gas consumer
ben-chain Aug 5, 2020
7dbfe75
util for exact gas consumption
ben-chain Aug 5, 2020
72b3496
small consumer improvements
ben-chain Aug 5, 2020
66e14db
fix broken test constants
ben-chain Aug 5, 2020
eed7026
improve test coverage
ben-chain Aug 5, 2020
cdab86f
linting
ben-chain Aug 5, 2020
0bbd535
fix hardcoded gas overhead
ben-chain Aug 5, 2020
ead9e37
WIP
ben-chain Aug 6, 2020
4006435
merge master
ben-chain Aug 6, 2020
f2b3d59
fix changed gas vals due to optimizer
ben-chain Aug 6, 2020
791758f
add some small improvements
ben-chain Aug 6, 2020
f7a8abe
bump timing out test
ben-chain Aug 6, 2020
826c8df
break out meter script
ben-chain Aug 6, 2020
a446a53
merge master
ben-chain Aug 6, 2020
606d7a0
update script
ben-chain Aug 6, 2020
5f28c8e
Merge remote-tracking branch 'origin' into karl-gas-testing
ben-chain Aug 6, 2020
28908ce
linting
ben-chain Aug 6, 2020
d2bc71b
Merge branch 'master' into karl-gas-testing
ben-chain Aug 27, 2020
49570b4
linting
ben-chain Aug 27, 2020
2b5cdaf
remove comments
ben-chain Aug 27, 2020
428ca74
add back broken contract
ben-chain Aug 27, 2020
828daf6
remove .only
ben-chain Aug 27, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
pragma solidity ^0.5.0;

import { ICrossDomainMessenger} from "../optimistic-ethereum/bridge/CrossDomainMessenger.interface.sol";
import { SimpleStorage } from "./SimpleStorage.sol";
import { SimpleStorageEVM } from "./SimpleStorageEVM.sol";

contract CrossDomainSimpleStorage is SimpleStorage {
contract CrossDomainSimpleStorage is SimpleStorageEVM {
ICrossDomainMessenger crossDomainMessenger;
address public crossDomainMsgSender;

Expand Down
40 changes: 37 additions & 3 deletions packages/contracts/contracts/test-helpers/SimpleStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,44 @@ contract SimpleStorage {
mapping(bytes32 => bytes32) public builtInStorage;

function setStorage(bytes32 key, bytes32 value) public {
builtInStorage[key] = value;
bytes memory EMcalldata = abi.encodeWithSelector(bytes4(keccak256(bytes("ovmSSTORE()"))), key, value);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we rename this to SimpleStorageOVM just to clarify the separation?


(bool success,) = msg.sender.call(EMcalldata);

}

function getStorage(bytes32 key) public returns (bytes32) {
bytes memory EMcalldata = abi.encodeWithSelector(bytes4(keccak256(bytes("ovmSLOAD()"))), key);

(bool success, bytes memory response) = msg.sender.call(EMcalldata);

return bytesToBytes32(response);
}

function setSequentialSlots(uint startKey, bytes32 value, uint numIterations) public {
for (uint i = 0; i < numIterations; i++) {
setStorage(bytes32(startKey + i), value);
}
}

function setSameSlotRepeated(bytes32 key, bytes32 value, uint numIterations) public {
for (uint i = 0; i < numIterations; i++) {
setStorage(key, value);
}
}

function getStorages(bytes32 key, uint numIterations) public {
for (uint i = 0; i < numIterations; i++) {
getStorage(key);
}
}

function getStorage(bytes32 key) public view returns (bytes32) {
return builtInStorage[key];
function bytesToBytes32(bytes memory source) private pure returns (bytes32 result) {
if (source.length == 0) {
return 0x0;
}
assembly {
result := mload(add(source, 32))
}
}
}
13 changes: 13 additions & 0 deletions packages/contracts/contracts/test-helpers/SimpleStorageEVM.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
pragma solidity ^0.5.0;

contract SimpleStorageEVM {
mapping(bytes32 => bytes32) public builtInStorage;

function setStorage(bytes32 key, bytes32 value) public {
builtInStorage[key] = value;
}

function getStorage(bytes32 key) public view returns (bytes32) {
return builtInStorage[key];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
import '../../setup'

/* External Imports */
import { ethers } from '@nomiclabs/buidler'
import {
getLogger,
ZERO_ADDRESS,
NULL_ADDRESS,
hexStrToNumber,
numberToHexString,
} from '@eth-optimism/core-utils'
import { Contract, ContractFactory, Signer } from 'ethers'
import { fromPairs } from 'lodash'

/* Internal Imports */
import {
GAS_LIMIT,
Address,
makeAddressResolver,
deployAndRegister,
AddressResolverMapping,
} from '../../test-helpers'

/* Logging */
const log = getLogger('partial-state-manager-gas-metering', true)

/* Testing Constants */

const OVM_TX_BASE_GAS_FEE = 30_000
const OVM_TX_MAX_GAS = 100_000_000
const GAS_RATE_LIMIT_EPOCH_IN_SECONDS = 60_000
const MAX_GAS_PER_EPOCH = 2_000_000_000

const key = '0x' + '12'.repeat(32)
const numIterationsToDo = 30
const startIndexForMultipleKeys = 1
const multipleSequentialKeys = new Array<string>(numIterationsToDo)
.fill('lol')
.map((v, i) => {
return numberToHexString(startIndexForMultipleKeys + i, 32)
})
const val = '0x' + '23'.repeat(32)

/*********
* TESTS *
*********/

describe.skip('Partial State Manager -- Storage Performance Testing Script', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why this is skipped right now?

let wallet: Signer
let walletAddress: string
let resolver: AddressResolverMapping
let ExecutionManager: ContractFactory
let PartialStateManager: ContractFactory

let executionManager: Contract
let stateManager: Contract

let SimpleStorage: ContractFactory
let simpleStorageNative: Contract
const simpleStorageOVMAddress: Address = '0x' + '45'.repeat(20)

const getSimpleStorageCallCallback = (methodName: string, params: any[]) => {
const internalCallBytes = SimpleStorage.interface.encodeFunctionData(
methodName,
params
)

const EMCallBytes = ExecutionManager.interface.encodeFunctionData(
'executeTransaction',
[
1_000_000,
0,
simpleStorageOVMAddress,
internalCallBytes,
walletAddress,
ZERO_ADDRESS,
OVM_TX_MAX_GAS,
false,
]
)

return async () => {
return wallet.sendTransaction({
to: executionManager.address,
data: EMCallBytes,
gasLimit: GAS_LIMIT,
})
}
}

const getCumulativeSequencedGas = async (): Promise<number> => {
return hexStrToNumber(
(await executionManager.getCumulativeSequencedGas())._hex
)
}

const getChangeInCumulativeGas = async (
callbackConsumingGas: () => Promise<any>
): Promise<{
internalToOVM: number
additionalExecuteTransactionOverhead: number
}> => {
const before: number = await getCumulativeSequencedGas()
const tx = await callbackConsumingGas()
const after: number = await getCumulativeSequencedGas()

const receipt = await executionManager.provider.getTransactionReceipt(
tx.hash
)

const change = after - before

return {
internalToOVM: change,
additionalExecuteTransactionOverhead:
hexStrToNumber(receipt.gasUsed._hex) - change,
}
}

before(async () => {
;[wallet] = await ethers.getSigners()
walletAddress = await wallet.getAddress()
resolver = await makeAddressResolver(wallet)
ExecutionManager = await ethers.getContractFactory('ExecutionManager')
PartialStateManager = await ethers.getContractFactory('PartialStateManager')
SimpleStorage = await ethers.getContractFactory('SimpleStorage')

executionManager = await deployAndRegister(
resolver.addressResolver,
wallet,
'ExecutionManager',
{
factory: ExecutionManager,
params: [
resolver.addressResolver.address,
NULL_ADDRESS,
[
OVM_TX_BASE_GAS_FEE,
OVM_TX_MAX_GAS,
GAS_RATE_LIMIT_EPOCH_IN_SECONDS,
MAX_GAS_PER_EPOCH,
MAX_GAS_PER_EPOCH,
],
],
}
)

stateManager = (
await deployAndRegister(
resolver.addressResolver,
wallet,
'StateManager',
{
factory: PartialStateManager,
params: [resolver.addressResolver.address, walletAddress],
}
)
).connect(wallet)

simpleStorageNative = await SimpleStorage.deploy()

await stateManager.insertVerifiedContract(walletAddress, walletAddress, 0)

await stateManager.insertVerifiedContract(
simpleStorageOVMAddress,
simpleStorageNative.address,
0
)
})

beforeEach(async () => {
// reset the single key value so that sstore costs are the same between tests
await stateManager.insertVerifiedStorage(
simpleStorageOVMAddress,
key,
'0x' + '00'.repeat(32)
)
// reset the sequential keys we set so sstore costs are the same between tests (new set vs update)
for (const aKey of multipleSequentialKeys) {
await stateManager.insertVerifiedStorage(
simpleStorageOVMAddress,
aKey,
'0x' + '00'.repeat(32)
)
}
})

it('setStorage', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think generally better to put each function into a separate describe() and then list out the cases within an it().

const doCall = getSimpleStorageCallCallback('setStorage', [key, val])
const change = await getChangeInCumulativeGas(doCall)
log.debug(
`OVM gas cost of a single setStorage is ${change.internalToOVM}, with + ${change.additionalExecuteTransactionOverhead} EVM overhead from executeTransaction().`
)
})

it('getstorage', async () => {
const doCall = getSimpleStorageCallCallback('getStorage', [key])
const change = await getChangeInCumulativeGas(doCall)
log.debug(
`OVM gas cost of a single getStorage is ${change.internalToOVM}, with + ${change.additionalExecuteTransactionOverhead} EVM overhead from executeTransaction().`
)
})

it(`getstorages (${numIterationsToDo}x)`, async () => {
const doCall = getSimpleStorageCallCallback('getStorages', [
key,
numIterationsToDo,
])
const change = await getChangeInCumulativeGas(doCall)
log.debug(
`OVM gas cost of ${numIterationsToDo} getStorages is ${change.internalToOVM}, with + ${change.additionalExecuteTransactionOverhead} EVM overhead from executeTransaction().`
)
log.debug(
`This corresponds to an OVM cost of ${change.internalToOVM /
numIterationsToDo} per iteration.`
)
})

it(`setSameSlotRepeated (${numIterationsToDo}x set storage, same key)`, async () => {
const doCall = getSimpleStorageCallCallback('setSameSlotRepeated', [
key,
val,
numIterationsToDo,
])
const change = await getChangeInCumulativeGas(doCall)
log.debug(
`OVM gas cost of ${numIterationsToDo} setStorages (repeated) is ${change.internalToOVM}, with + ${change.additionalExecuteTransactionOverhead} EVM overhead from executeTransaction().`
)
log.debug(
`This corresponds to an OVM cost of ${change.internalToOVM /
numIterationsToDo} per iteration.`
)
})

it(`setStorages (${numIterationsToDo}x, sequential unset keys)`, async () => {
const doCall = getSimpleStorageCallCallback('setSequentialSlots', [
startIndexForMultipleKeys,
val,
numIterationsToDo,
])
const change = await getChangeInCumulativeGas(doCall)
log.debug(
`OVM gas cost of ${numIterationsToDo} setStorages (unique) is ${change.internalToOVM}, with + ${change.additionalExecuteTransactionOverhead} EVM overhead from executeTransaction().`
)
log.debug(
`This corresponds to an OVM cost of ${change.internalToOVM /
numIterationsToDo} per iteration.`
)
})
})