Skip to content

Commit

Permalink
Bench precompile (#610)
Browse files Browse the repository at this point in the history
* Add stateful precompile benchmarks

* Add GH Action for bench precompiles

* Remove coverage from benchmarks

* Rename bench workflow
  • Loading branch information
aaronbuchwald authored Apr 11, 2023
1 parent a1865cc commit e4aa837
Show file tree
Hide file tree
Showing 12 changed files with 396 additions and 206 deletions.
19 changes: 19 additions & 0 deletions .github/workflows/bench.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Bench

on:
workflow_dispatch:
pull_request:

jobs:
bench:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: "1.19"
- run: go mod download
shell: bash
- run: ./scripts/build_bench_precompiles.sh
shell: bash

2 changes: 1 addition & 1 deletion core/state/test_statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/stretchr/testify/require"
)

func NewTestStateDB(t *testing.T) contract.StateDB {
func NewTestStateDB(t testing.TB) contract.StateDB {
db := memorydb.New()
stateDB, err := New(common.Hash{}, NewDatabase(db), nil)
require.NoError(t, err)
Expand Down
9 changes: 9 additions & 0 deletions precompile/allowlist/allowlist_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,12 @@ func TestAllowListRun(t *testing.T) {
}
RunPrecompileWithAllowListTests(t, dummyModule, state.NewTestStateDB, nil)
}

func BenchmarkAllowList(b *testing.B) {
dummyModule := modules.Module{
Address: dummyAddr,
Contract: CreateAllowListPrecompile(dummyAddr),
Configurator: &dummyConfigurator{},
}
BenchPrecompileWithAllowList(b, dummyModule, state.NewTestStateDB, nil)
}
57 changes: 38 additions & 19 deletions precompile/allowlist/test_allowlist.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest {
"set admin": {
Caller: TestAdminAddr,
BeforeHook: SetDefaultRoles(contractAddress),
InputFn: func(t *testing.T) []byte {
InputFn: func(t testing.TB) []byte {
input, err := PackModifyAllowList(TestNoRoleAddr, AdminRole)
require.NoError(t, err)

Expand All @@ -35,15 +35,15 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest {
SuppliedGas: ModifyAllowListGasCost,
ReadOnly: false,
ExpectedRes: []byte{},
AfterHook: func(t *testing.T, state contract.StateDB) {
AfterHook: func(t testing.TB, state contract.StateDB) {
res := GetAllowListStatus(state, contractAddress, TestNoRoleAddr)
require.Equal(t, AdminRole, res)
},
},
"set enabled": {
Caller: TestAdminAddr,
BeforeHook: SetDefaultRoles(contractAddress),
InputFn: func(t *testing.T) []byte {
InputFn: func(t testing.TB) []byte {
input, err := PackModifyAllowList(TestNoRoleAddr, EnabledRole)
require.NoError(t, err)

Expand All @@ -52,15 +52,15 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest {
SuppliedGas: ModifyAllowListGasCost,
ReadOnly: false,
ExpectedRes: []byte{},
AfterHook: func(t *testing.T, state contract.StateDB) {
AfterHook: func(t testing.TB, state contract.StateDB) {
res := GetAllowListStatus(state, contractAddress, TestNoRoleAddr)
require.Equal(t, EnabledRole, res)
},
},
"set no role": {
Caller: TestAdminAddr,
BeforeHook: SetDefaultRoles(contractAddress),
InputFn: func(t *testing.T) []byte {
InputFn: func(t testing.TB) []byte {
input, err := PackModifyAllowList(TestEnabledAddr, NoRole)
require.NoError(t, err)

Expand All @@ -69,15 +69,15 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest {
SuppliedGas: ModifyAllowListGasCost,
ReadOnly: false,
ExpectedRes: []byte{},
AfterHook: func(t *testing.T, state contract.StateDB) {
AfterHook: func(t testing.TB, state contract.StateDB) {
res := GetAllowListStatus(state, contractAddress, TestEnabledAddr)
require.Equal(t, NoRole, res)
},
},
"set no role from no role": {
Caller: TestNoRoleAddr,
BeforeHook: SetDefaultRoles(contractAddress),
InputFn: func(t *testing.T) []byte {
InputFn: func(t testing.TB) []byte {
input, err := PackModifyAllowList(TestEnabledAddr, NoRole)
require.NoError(t, err)

Expand All @@ -90,7 +90,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest {
"set enabled from no role": {
Caller: TestNoRoleAddr,
BeforeHook: SetDefaultRoles(contractAddress),
InputFn: func(t *testing.T) []byte {
InputFn: func(t testing.TB) []byte {
input, err := PackModifyAllowList(TestNoRoleAddr, EnabledRole)
require.NoError(t, err)

Expand All @@ -103,7 +103,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest {
"set admin from no role": {
Caller: TestNoRoleAddr,
BeforeHook: SetDefaultRoles(contractAddress),
InputFn: func(t *testing.T) []byte {
InputFn: func(t testing.TB) []byte {
input, err := PackModifyAllowList(TestEnabledAddr, AdminRole)
require.NoError(t, err)

Expand All @@ -116,7 +116,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest {
"set no role from enabled": {
Caller: TestEnabledAddr,
BeforeHook: SetDefaultRoles(contractAddress),
InputFn: func(t *testing.T) []byte {
InputFn: func(t testing.TB) []byte {
input, err := PackModifyAllowList(TestAdminAddr, NoRole)
require.NoError(t, err)

Expand All @@ -129,7 +129,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest {
"set enabled from enabled": {
Caller: TestEnabledAddr,
BeforeHook: SetDefaultRoles(contractAddress),
InputFn: func(t *testing.T) []byte {
InputFn: func(t testing.TB) []byte {
input, err := PackModifyAllowList(TestNoRoleAddr, EnabledRole)
require.NoError(t, err)

Expand All @@ -142,7 +142,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest {
"set admin from enabled": {
Caller: TestEnabledAddr,
BeforeHook: SetDefaultRoles(contractAddress),
InputFn: func(t *testing.T) []byte {
InputFn: func(t testing.TB) []byte {
input, err := PackModifyAllowList(TestNoRoleAddr, AdminRole)
require.NoError(t, err)

Expand All @@ -155,7 +155,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest {
"set no role with readOnly enabled": {
Caller: TestAdminAddr,
BeforeHook: SetDefaultRoles(contractAddress),
InputFn: func(t *testing.T) []byte {
InputFn: func(t testing.TB) []byte {
input, err := PackModifyAllowList(TestEnabledAddr, NoRole)
require.NoError(t, err)

Expand All @@ -168,7 +168,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest {
"set no role insufficient gas": {
Caller: TestAdminAddr,
BeforeHook: SetDefaultRoles(contractAddress),
InputFn: func(t *testing.T) []byte {
InputFn: func(t testing.TB) []byte {
input, err := PackModifyAllowList(TestEnabledAddr, NoRole)
require.NoError(t, err)

Expand Down Expand Up @@ -219,7 +219,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest {
),
SuppliedGas: 0,
ReadOnly: false,
AfterHook: func(t *testing.T, state contract.StateDB) {
AfterHook: func(t testing.TB, state contract.StateDB) {
require.Equal(t, AdminRole, GetAllowListStatus(state, contractAddress, TestNoRoleAddr))
require.Equal(t, AdminRole, GetAllowListStatus(state, contractAddress, TestEnabledAddr))
},
Expand All @@ -233,7 +233,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest {
),
SuppliedGas: 0,
ReadOnly: false,
AfterHook: func(t *testing.T, state contract.StateDB) {
AfterHook: func(t testing.TB, state contract.StateDB) {
require.Equal(t, EnabledRole, GetAllowListStatus(state, contractAddress, TestAdminAddr))
require.Equal(t, EnabledRole, GetAllowListStatus(state, contractAddress, TestNoRoleAddr))
},
Expand All @@ -243,8 +243,8 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest {

// SetDefaultRoles returns a BeforeHook that sets roles TestAdminAddr and TestEnabledAddr
// to have the AdminRole and EnabledRole respectively.
func SetDefaultRoles(contractAddress common.Address) func(t *testing.T, state contract.StateDB) {
return func(t *testing.T, state contract.StateDB) {
func SetDefaultRoles(contractAddress common.Address) func(t testing.TB, state contract.StateDB) {
return func(t testing.TB, state contract.StateDB) {
SetAllowListRole(state, contractAddress, TestAdminAddr, AdminRole)
SetAllowListRole(state, contractAddress, TestEnabledAddr, EnabledRole)
require.Equal(t, AdminRole, GetAllowListStatus(state, contractAddress, TestAdminAddr))
Expand All @@ -253,7 +253,7 @@ func SetDefaultRoles(contractAddress common.Address) func(t *testing.T, state co
}
}

func RunPrecompileWithAllowListTests(t *testing.T, module modules.Module, newStateDB func(t *testing.T) contract.StateDB, contractTests map[string]testutils.PrecompileTest) {
func RunPrecompileWithAllowListTests(t *testing.T, module modules.Module, newStateDB func(t testing.TB) contract.StateDB, contractTests map[string]testutils.PrecompileTest) {
t.Helper()
tests := AllowListTests(module)
// Add the contract specific tests to the map of tests to run.
Expand All @@ -270,3 +270,22 @@ func RunPrecompileWithAllowListTests(t *testing.T, module modules.Module, newSta
})
}
}

func BenchPrecompileWithAllowList(b *testing.B, module modules.Module, newStateDB func(t testing.TB) contract.StateDB, contractTests map[string]testutils.PrecompileTest) {
b.Helper()

tests := AllowListTests(module)
// Add the contract specific tests to the map of tests to run.
for name, test := range contractTests {
if _, exists := tests[name]; exists {
b.Fatalf("duplicate bench name: %s", name)
}
tests[name] = test
}

for name, test := range tests {
b.Run(name, func(b *testing.B) {
test.Bench(b, module, newStateDB(b))
})
}
}
3 changes: 3 additions & 0 deletions precompile/contract/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ type StateDB interface {

Suicide(common.Address) bool
Finalise(deleteEmptyObjects bool)

Snapshot() int
RevertToSnapshot(int)
}

// AccessibleState defines the interface exposed to stateful precompile contracts
Expand Down
4 changes: 4 additions & 0 deletions precompile/contracts/deployerallowlist/contract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@ import (
func TestContractDeployerAllowListRun(t *testing.T) {
allowlist.RunPrecompileWithAllowListTests(t, Module, state.NewTestStateDB, nil)
}

func BenchmarkContractDeployerAllowList(b *testing.B) {
allowlist.BenchPrecompileWithAllowList(b, Module, state.NewTestStateDB, nil)
}
Loading

0 comments on commit e4aa837

Please sign in to comment.