Skip to content

Commit 014c5b5

Browse files
committed
Merge remote-tracking branch 'origin/master' into debug-block
2 parents 2f6cf8a + 21e4b11 commit 014c5b5

File tree

22 files changed

+626
-202
lines changed

22 files changed

+626
-202
lines changed

.github/workflows/_go-tests.yml

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -153,39 +153,71 @@ jobs:
153153
JIT_HASH=$(echo "$OUTPUT" | grep -oP 'hash \K[a-f0-9]+')
154154
echo "jit_hash=$JIT_HASH" >> $GITHUB_OUTPUT
155155
156-
- name: run the Rust validation server on block input json
156+
- name: run Rust validation server (Native & Continuous)
157157
if: inputs.run-defaults-a
158158
run: |
159-
# 1. Start server in background
159+
# 0. Build once
160160
make build-validation-server
161-
target/bin/validator --module-root-path ./target/machines/latest/module-root.txt &
162-
SERVER_PID=$!
163161
164-
# 2. Wait for server to respond (up to 5 seconds)
165-
echo "Waiting for validator to start..."
166-
timeout 5s bash -c 'until curl -s localhost:4141 > /dev/null; do sleep 1; done'
167-
168-
# 3. Send validation request
169-
RESPONSE=$(curl -s -X POST http://localhost:4141/validation_validate \
170-
-H "Content-Type: application/json" \
171-
-d @target/TestProgramStorage/block_inputs.json)
172-
173-
# 4. Stop the server
174-
kill $SERVER_PID
175-
176-
# 5. Compare hashes
177-
SERVER_HASH=$(echo "$RESPONSE" | jq -r '.BlockHash')
162+
# Capture the expected hash once
178163
JIT_HASH="${{ steps.jit.outputs.jit_hash }}"
164+
165+
validate_mode() {
166+
local MODE_NAME=$1
167+
local SERVER_ARGS=$2
168+
169+
echo "::group::Testing Mode: $MODE_NAME"
170+
171+
# 1. Start server in background
172+
echo "Starting server ($MODE_NAME)..."
173+
target/bin/validator --module-root-path ./target/machines/latest/module-root.txt $SERVER_ARGS &
174+
SERVER_PID=$!
175+
176+
# 2. Wait for server to respond (up to 5 seconds)
177+
echo "Waiting for validator ($MODE_NAME) to start..."
178+
if ! timeout 5s bash -c 'until curl -s localhost:4141 > /dev/null; do sleep 1; done'; then
179+
echo "❌ Server ($MODE_NAME) failed to start within timeout"
180+
kill $SERVER_PID
181+
exit 1
182+
fi
183+
184+
# 3. Send 2 validation requests
185+
RESPONSE1=$(curl -s -X POST http://localhost:4141/validation_validate \
186+
-H "Content-Type: application/json" \
187+
-d @target/TestProgramStorage/block_inputs.json)
188+
189+
RESPONSE2=$(curl -s -X POST http://localhost:4141/validation_validate \
190+
-H "Content-Type: application/json" \
191+
-d @target/TestProgramStorage/block_inputs.json)
192+
193+
# 4. Stop the server
194+
kill $SERVER_PID
195+
wait $SERVER_PID 2>/dev/null || true
196+
197+
# 5. Compare hashes
198+
SERVER_HASH1=$(echo "$RESPONSE1" | jq -r '.BlockHash')
199+
SERVER_HASH2=$(echo "$RESPONSE2" | jq -r '.BlockHash')
200+
201+
echo "JIT Hash: $JIT_HASH"
202+
echo "Server response 1 Hash: $SERVER_HASH1"
203+
echo "Server response 2 Hash: $SERVER_HASH2"
204+
205+
if [ "$JIT_HASH" == "$SERVER_HASH1" ] && [ "$JIT_HASH" == "$SERVER_HASH2" ]; then
206+
echo "✅ $MODE_NAME Validation successful"
207+
else
208+
echo "❌ $MODE_NAME Validation failed: hashes do not match"
209+
exit 1
210+
fi
211+
echo "::endgroup::"
212+
}
213+
214+
# --- RUN TESTS ---
179215
180-
echo "JIT Hash: $JIT_HASH"
181-
echo "Server Hash: $SERVER_HASH"
182-
183-
if [ "$JIT_HASH" == "$SERVER_HASH" ]; then
184-
echo "✅ Validation successful"
185-
else
186-
echo "❌ Validation failed: hashes do not match"
187-
exit 1
188-
fi
216+
# Run Validator in Native mode
217+
validate_mode "Native" ""
218+
219+
# Run Validator in Continuous mode
220+
validate_mode "Continuous" "--mode continuous"
189221
190222
# --------------------- FLAKY MODE --------------------------
191223

.github/workflows/automated-changelog.yml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,9 @@ jobs:
2525
2626
const dir = 'changelog';
2727
28-
// Find the next available number
29-
let x = 1;
30-
while (fs.existsSync(path.join(dir, `dependabot-${x}.md`))) {
31-
x++;
32-
}
28+
const prNumber = context.payload.pull_request.number;
29+
const filename = path.join(dir, `dependabot-${prNumber}.md`);
3330
34-
const filename = path.join(dir, `dependabot-${x}.md`);
3531
const title = context.payload.pull_request.title;
3632
const content = `### Ignored\n- ${title}\n`;
3733

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Makefile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ stylus_files = $(wildcard $(stylus_dir)/*.toml $(stylus_dir)/src/*.rs) $(wasm_li
104104
jit_dir = crates/jit
105105
jit_files = $(wildcard $(jit_dir)/*.toml $(jit_dir)/*.rs $(jit_dir)/src/*.rs $(jit_dir)/src/*/*.rs) $(stylus_files)
106106

107+
validation_crate_dir = crates/validation
108+
validation_files = $(wildcard $(validation_crate_dir)/*.toml $(validation_crate_dir)/src/*.rs $(validation_crate_dir)/src/*/*.rs) $(rust_arbutil_files)
109+
110+
validator_dir = crates/validator
111+
validator_files = $(wildcard $(validator_dir)/*.toml $(validator_dir)/src/*.rs $(validator_dir)/src/*/*.rs) $(jit_files) $(validation_files)
112+
107113
wasm32_wasi = target/wasm32-wasip1/release
108114
wasm32_unknown = target/wasm32-unknown-unknown/release
109115

@@ -385,7 +391,7 @@ $(arbitrator_jit): $(DEP_PREDICATE) $(jit_files)
385391
cargo build --release -p jit ${CARGOFLAGS}
386392
install target/release/jit $@
387393

388-
$(validation_server): $(DEP_PREDICATE)
394+
$(validation_server): $(DEP_PREDICATE) $(validator_files)
389395
mkdir -p `dirname $(validation_server)`
390396
cargo build --release -p validator ${CARGOFLAGS}
391397
install target/release/validator $@

changelog/bragaigor-nit-4390.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
### Internal
2+
- Add support for multiple module roots for Validator
3+
- Fix Validator continuous mode to run jit binary from inside tokio runtime

changelog/gligneul-nit-4111.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
### Added
2+
- Multi-gas constraints to L2-pricing simulator
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
### Ignored
2+
- ensure dependabot changelog files are unique

cmd/l2pricing-simulator/config.go

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@
44
package main
55

66
import (
7+
"encoding/json"
78
"fmt"
89
"io"
10+
"os"
11+
"strings"
12+
"unicode"
913

1014
"github.com/spf13/pflag"
1115

@@ -99,26 +103,26 @@ func (c *LegacyConfig) Print(w io.Writer) {
99103
fmt.Fprintln(w, "Backlog tolerance:\t", c.BacklogTolerance)
100104
}
101105

102-
type ConstraintsConfig struct {
106+
type SingleGasConfig struct {
103107
CommonConfig
104108
Targets []int64
105109
Windows []int64
106110
Backlogs []int64
107111
}
108112

109-
var DefaultConstraintConfig = ConstraintsConfig{
113+
var DefaultConstraintConfig = SingleGasConfig{
110114
Targets: []int64{60_000_000, 41_000_000, 29_000_000, 20_000_000, 14_000_000, 10_000_000},
111115
Windows: []int64{9, 52, 329, 2_105, 13_485, 86_400},
112116
}
113117

114-
func (c *ConstraintsConfig) AddFlags(flags *pflag.FlagSet) {
118+
func (c *SingleGasConfig) AddFlags(flags *pflag.FlagSet) {
115119
c.CommonConfig.AddFlags(flags)
116120
flags.Int64SliceVar(&c.Targets, "targets", DefaultConstraintConfig.Targets, "List of constraints' targets; previously speed-limit")
117121
flags.Int64SliceVar(&c.Windows, "windows", DefaultConstraintConfig.Windows, "List of constraints' adjustment windows; previously inertia")
118122
flags.Int64SliceVar(&c.Backlogs, "backlogs", DefaultConstraintConfig.Backlogs, "List of constraints' initial backlogs")
119123
}
120124

121-
func (c *ConstraintsConfig) Print(w io.Writer) {
125+
func (c *SingleGasConfig) Print(w io.Writer) {
122126
c.CommonConfig.Print(w)
123127
fmt.Fprintln(w, "Number of constraints:\t", len(c.Targets))
124128
for i := range len(c.Targets) {
@@ -132,7 +136,7 @@ func (c *ConstraintsConfig) Print(w io.Writer) {
132136
}
133137
}
134138

135-
func (c *ConstraintsConfig) Validate() error {
139+
func (c *SingleGasConfig) Validate() error {
136140
for _, target := range c.Targets {
137141
if target < 0 {
138142
return fmt.Errorf("invalid negative target")
@@ -159,3 +163,66 @@ func (c *ConstraintsConfig) Validate() error {
159163
}
160164
return nil
161165
}
166+
167+
type MultiGasConfig struct {
168+
CommonConfig
169+
Constraints []MultiGasConstraint
170+
constraintsJson string
171+
constraintsJsonPath string
172+
printConstraints bool
173+
}
174+
175+
var DefaultMultiGasConfig = MultiGasConfig{
176+
constraintsJson: DefaultMultiGasConstraints,
177+
printConstraints: false,
178+
}
179+
180+
func (c *MultiGasConfig) AddFlags(flags *pflag.FlagSet) {
181+
c.CommonConfig.AddFlags(flags)
182+
defaultConstraints := strings.Map(func(r rune) rune {
183+
if unicode.IsSpace(r) {
184+
return -1
185+
}
186+
return r
187+
}, DefaultMultiGasConstraints)
188+
flags.StringVar(&c.constraintsJson, "constraints", defaultConstraints, "Multi-gas constraints specified as JSON")
189+
flags.StringVar(&c.constraintsJsonPath, "constraints-path", "", "If set, load the constraints from the file")
190+
flags.BoolVar(&c.printConstraints, "print-constraints", DefaultMultiGasConfig.printConstraints, "print the constraints")
191+
}
192+
193+
func (c *MultiGasConfig) Print(w io.Writer) {
194+
c.CommonConfig.Print(w)
195+
if c.printConstraints {
196+
result, err := json.MarshalIndent(c.Constraints, " ", " ")
197+
if err != nil {
198+
fmt.Fprintf(w, "Failed to print constraints: %v\n", err.Error())
199+
} else {
200+
fmt.Fprintf(w, "Constraints: %v\n", string(result))
201+
}
202+
} else {
203+
fmt.Fprintf(w, "Number of constraints: %v\n", len(c.Constraints))
204+
}
205+
}
206+
207+
func (c *MultiGasConfig) Validate() error {
208+
var constraintsJson []byte
209+
if c.constraintsJsonPath != "" {
210+
var err error
211+
constraintsJson, err = os.ReadFile(c.constraintsJsonPath)
212+
if err != nil {
213+
return fmt.Errorf("failed to read constraints file: %w", err)
214+
}
215+
} else {
216+
constraintsJson = []byte(c.constraintsJson)
217+
}
218+
err := json.Unmarshal(constraintsJson, &c.Constraints)
219+
if err != nil {
220+
return fmt.Errorf("failed to parse constraints: %w", err)
221+
}
222+
for _, constraint := range c.Constraints {
223+
if err := constraint.Validate(); err != nil {
224+
return err
225+
}
226+
}
227+
return nil
228+
}

cmd/l2pricing-simulator/main.go

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ func runLegacyModel(args []string) error {
6767
return nil
6868
}
6969

70-
func runConstraintsModel(args []string) error {
71-
var config ConstraintsConfig
70+
func runSingleGasModel(args []string) error {
71+
var config SingleGasConfig
7272
if err := ParseConfig(&config, args); err != nil {
7373
return err
7474
}
@@ -116,20 +116,62 @@ func runConstraintsModel(args []string) error {
116116
return nil
117117
}
118118

119+
func runMultiGasModel(args []string) error {
120+
var config MultiGasConfig
121+
if err := ParseConfig(&config, args); err != nil {
122+
return err
123+
}
124+
125+
pricing, err := newPricingState(params.ArbosVersion_MultiGasConstraintsVersion)
126+
if err != nil {
127+
return err
128+
}
129+
130+
longTermWindow := uint32(0)
131+
longTermTarget := uint64(0)
132+
for _, constraint := range config.Constraints {
133+
_ = pricing.AddMultiGasConstraint(constraint.Target, constraint.Window, constraint.Backlog, constraint.Weights)
134+
if constraint.Window > longTermWindow {
135+
longTermWindow = constraint.Window
136+
longTermTarget = constraint.Target
137+
}
138+
}
139+
140+
gasSimulator := NewGasSimulator(config.CommonConfig, longTermTarget)
141+
142+
results := []Result{}
143+
for i := range config.Iterations() {
144+
baseFee, _ := pricing.BaseFeeWei()
145+
gas := gasSimulator.compute(i, baseFee)
146+
_ = pricing.GrowBacklog(gas, multigas.ComputationGas(gas))
147+
pricing.UpdatePricingModel(1)
148+
baseFee, _ = pricing.BaseFeeWei()
149+
results = append(results, Result{
150+
baseFee: baseFee,
151+
gasRatio: float64(gas) / float64(longTermTarget),
152+
})
153+
}
154+
155+
printOutput(&config, results)
156+
return nil
157+
}
158+
119159
func main() {
120160
args := os.Args
121161
if len(args) < 2 {
122-
fmt.Println("Usage: l2pricing-simulator [legacy|constraints] ...")
162+
fmt.Println("Usage: l2pricing-simulator [legacy|singlegas|multigas] ...")
123163
os.Exit(1)
124164
}
125165
var err error
126166
switch strings.ToLower(args[1]) {
127167
case "legacy":
128168
err = runLegacyModel(args[2:])
129-
case "constraints":
130-
err = runConstraintsModel(args[2:])
169+
case "singlegas":
170+
err = runSingleGasModel(args[2:])
171+
case "multigas":
172+
err = runMultiGasModel(args[2:])
131173
default:
132-
err = fmt.Errorf("unknown command '%s', valid commands are: legacy and constraints", args[1])
174+
err = fmt.Errorf("unknown command '%s', valid commands are: legacy, singlegas, multigas", args[1])
133175
}
134176
if err != nil {
135177
fmt.Fprintf(os.Stderr, "Error: %v\n", err)

0 commit comments

Comments
 (0)