Skip to content

Commit 3fa2297

Browse files
Add version to rlp ResourceConstraints
1 parent e207898 commit 3fa2297

File tree

2 files changed

+61
-8
lines changed

2 files changed

+61
-8
lines changed

arbos/constraints/storage.go

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@
44
package constraints
55

66
import (
7+
"fmt"
78
"io"
89

910
"github.com/ethereum/go-ethereum/rlp"
1011
)
1112

13+
// Version of the RLP serialization format for ResourceConstraints.
14+
const ResourceConstraintsVersion uint8 = 1
15+
1216
// storageBytes defines the interface for ArbOS storage.
1317
type storageBytes interface {
1418
Get() ([]byte, error)
@@ -27,19 +31,25 @@ func NewStorageResourceConstraints(storage storageBytes) *StorageResourceConstra
2731
}
2832
}
2933

30-
type resourceConstraintRLP struct {
34+
type rlpResourceConstraint struct {
3135
Resources []ResourceWeight
3236
Period PeriodSecs
3337
TargetPerSec uint64
3438
Backlog uint64
3539
}
3640

41+
// rlpConstraints is the RLP-encoded wrapper used for persistence.
42+
type rlpConstraints struct {
43+
Version uint8
44+
Constraints []*ResourceConstraint
45+
}
46+
3747
// EncodeRLP encodes ResourceConstraint deterministically,
3848
// ensuring the fixed-length weights array is preserved.
3949
func (c *ResourceConstraint) EncodeRLP(w io.Writer) error {
4050
weights := make([]ResourceWeight, len(c.Resources.weights))
4151
copy(weights, c.Resources.weights[:])
42-
return rlp.Encode(w, resourceConstraintRLP{
52+
return rlp.Encode(w, rlpResourceConstraint{
4353
Resources: weights,
4454
Period: c.Period,
4555
TargetPerSec: c.TargetPerSec,
@@ -50,7 +60,7 @@ func (c *ResourceConstraint) EncodeRLP(w io.Writer) error {
5060
// DecodeRLP decodes ResourceConstraint deterministically,
5161
// padding or truncating the weights slice to the correct array length.
5262
func (c *ResourceConstraint) DecodeRLP(s *rlp.Stream) error {
53-
var raw resourceConstraintRLP
63+
var raw rlpResourceConstraint
5464
if err := s.Decode(&raw); err != nil {
5565
return err
5666
}
@@ -79,18 +89,20 @@ func (src *StorageResourceConstraints) Load() (*ResourceConstraints, error) {
7989
return NewResourceConstraints(), nil
8090
}
8191

82-
var list []*ResourceConstraint
83-
if err := rlp.DecodeBytes(data, &list); err != nil {
92+
var payload rlpConstraints
93+
if err := rlp.DecodeBytes(data, &payload); err != nil {
8494
return nil, err
8595
}
96+
if payload.Version != ResourceConstraintsVersion {
97+
return nil, fmt.Errorf("unsupported constraints version %d", payload.Version)
98+
}
8699

87100
rc := NewResourceConstraints()
88-
for _, c := range list {
101+
for _, c := range payload.Constraints {
89102
rc.Set(c.Resources, c.Period, c.TargetPerSec)
90103
ptr := rc.Get(c.Resources, c.Period)
91104
ptr.Backlog = c.Backlog
92105
}
93-
94106
return rc, nil
95107
}
96108

@@ -106,7 +118,12 @@ func (src *StorageResourceConstraints) Write(rc *ResourceConstraints) error {
106118
return src.storage.Set(nil)
107119
}
108120

109-
data, err := rlp.EncodeToBytes(list)
121+
payload := rlpConstraints{
122+
Version: ResourceConstraintsVersion,
123+
Constraints: list,
124+
}
125+
126+
data, err := rlp.EncodeToBytes(&payload)
110127
if err != nil {
111128
return err
112129
}

arbos/constraints/storage_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,42 @@ func TestStorageResourceConstraintsRLPRoundTrip(t *testing.T) {
108108
}
109109
}
110110

111+
func TestStorageResourceConstraintsRLPBacklogPersistence(t *testing.T) {
112+
rc := NewResourceConstraints()
113+
res := EmptyResourceSet().
114+
WithResource(multigas.ResourceKindComputation, 1)
115+
rc.Set(res, PeriodSecs(30), 10_000_000)
116+
ptr := rc.Get(res, PeriodSecs(30))
117+
ptr.Backlog = 12345 // initial backlog value
118+
119+
store := &mockStorageBytes{}
120+
src := NewStorageResourceConstraints(store)
121+
122+
require.NoError(t, src.Write(rc))
123+
require.Greater(t, len(store.buf), 0, "storage should contain RLP bytes after Write")
124+
125+
loaded, err := src.Load()
126+
require.NoError(t, err, "Load() failed")
127+
require.Equal(t, 1, len(loaded.constraints), "expected one constraint")
128+
129+
for got := range loaded.All() {
130+
require.Equal(t, uint64(12345), got.Backlog,
131+
"initial backlog not persisted correctly")
132+
}
133+
134+
ptr.Backlog = 99999
135+
require.NoError(t, src.Write(rc), "Write() after backlog update failed")
136+
137+
loaded2, err := src.Load()
138+
require.NoError(t, err, "Load() after backlog update failed")
139+
require.Equal(t, 1, len(loaded2.constraints), "expected one constraint")
140+
141+
for got := range loaded2.All() {
142+
require.Equal(t, uint64(99999), got.Backlog,
143+
"updated backlog not persisted correctly")
144+
}
145+
}
146+
111147
func TestStorageResourceConstraintsEmptyLoad(t *testing.T) {
112148
store := &mockStorageBytes{}
113149
src := NewStorageResourceConstraints(store)

0 commit comments

Comments
 (0)