Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
44 changes: 44 additions & 0 deletions arbitrum/multigas/constraint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package multigas

import "time"

// Constraint defines the max gas target per second for the given period for a single resource.
type constraint struct {
period time.Duration
target uint64
}

// ResourceConstraints is a set of constraints for all resources.
//
// The chain owner defines constraints to limit the usage of each resource. A resource can have
// multiple constraints with different periods, but there may be a single constraint given the
// resource and period.
//
// Example constraints:
// - X amount of computation over 12 seconds so nodes can keep up.
// - Y amount of computation over 7 days so fresh nodes can catch up with the chain.
// - Z amount of history growth over one month to avoid bloat.
type ResourceConstraints map[ResourceKind]map[uint32]constraint

func NewResourceConstraints() ResourceConstraints {
c := ResourceConstraints{}
for resource := ResourceKind(0); resource < NumResourceKind; resource++ {
c[resource] = map[uint32]constraint{}
}
return c
}

// SetConstraint adds or updates the given resource constraint.
func (rc ResourceConstraints) SetConstraint(
resource ResourceKind, periodSecs uint32, targetPerPeriod uint64,
) {
rc[resource][periodSecs] = constraint{
period: time.Duration(periodSecs) * time.Second,
target: targetPerPeriod / uint64(periodSecs),
}
}

// ClearConstraint removes the given resource constraint.
func (rc ResourceConstraints) ClearConstraint(resource ResourceKind, periodSecs uint32) {
delete(rc[resource], periodSecs)
}
66 changes: 66 additions & 0 deletions arbitrum/multigas/constraint_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package multigas

import (
"testing"
"time"
)

func TestResourceConstraints(t *testing.T) {
rc := NewResourceConstraints()

const (
minuteSecs = 60
daySecs = 24 * 60 * 60
weekSecs = 7 * daySecs
monthSecs = 30 * daySecs
)

// Adds a few constraints
rc.SetConstraint(ResourceKindComputation, minuteSecs, 5_000_000*minuteSecs)
rc.SetConstraint(ResourceKindComputation, weekSecs, 3_000_000*weekSecs)
rc.SetConstraint(ResourceKindHistoryGrowth, monthSecs, 1_000_000*monthSecs)
if len(rc[ResourceKindComputation]) != 2 {
t.Fatalf("expected 2 computation constraints")
}
if rc[ResourceKindComputation][minuteSecs].period != time.Duration(minuteSecs)*time.Second {
t.Errorf("wrong constraint period")
}
if rc[ResourceKindComputation][minuteSecs].target != 5_000_000 {
t.Errorf("wrong constraint target")
}
if rc[ResourceKindComputation][weekSecs].period != time.Duration(weekSecs)*time.Second {
t.Errorf("wrong constraint period")
}
if rc[ResourceKindComputation][weekSecs].target != 3_000_000 {
t.Errorf("wrong constraint target")
}
if len(rc[ResourceKindHistoryGrowth]) != 1 {
t.Fatalf("Expected 1 history growth constraints")
}
if rc[ResourceKindHistoryGrowth][monthSecs].period != time.Duration(monthSecs)*time.Second {
t.Errorf("wrong constraint period")
}
if rc[ResourceKindHistoryGrowth][monthSecs].target != 1_000_000 {
t.Errorf("wrong constraint target")
}

// Updates a constraint
rc.SetConstraint(ResourceKindHistoryGrowth, monthSecs, 500_000*monthSecs)
if len(rc[ResourceKindHistoryGrowth]) != 1 {
t.Fatalf("Expected 1 history growth constraints")
}
if rc[ResourceKindHistoryGrowth][monthSecs].target != 500_000 {
t.Errorf("wrong constraint target")
}

// Clear constraints
rc.ClearConstraint(ResourceKindComputation, minuteSecs)
rc.ClearConstraint(ResourceKindComputation, weekSecs)
rc.ClearConstraint(ResourceKindHistoryGrowth, monthSecs)
if len(rc[ResourceKindComputation]) != 0 {
t.Fatalf("Expected 0 computation constraints")
}
if len(rc[ResourceKindHistoryGrowth]) != 0 {
t.Fatalf("Expected 0 history growth constraints")
}
}
7 changes: 7 additions & 0 deletions arbitrum/multigas/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Package multigas defines multi-dimensional gas for the EVM.
//
// This package introduces mechanisms to track each resource used by the EVM separately. The
// possible resources are computation, history growth, storage access, and storage growth. By
// tracking each one individually and setting specific constraints, we can increase the overall gas
// target for the chain.
package multigas
15 changes: 15 additions & 0 deletions arbitrum/multigas/resources.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package multigas

// ResourceKind represents a dimension for the multi-dimensional gas.
type ResourceKind uint8

const (
ResourceKindComputation ResourceKind = iota
ResourceKindHistoryGrowth
ResourceKindStorageAccess
ResourceKindStorageGrowth
NumResourceKind
)

// MultiGas tracks gas for each resource separately.
type MultiGas [NumResourceKind]uint64
Loading