Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
17 changes: 17 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ color_reset = "\e[0;0m"
done = "%bdone!%b\n" $(color_pink) $(color_reset)

replay_wasm=$(output_latest)/replay.wasm
unified_replay_wasm=$(output_latest)/unified_replay.wasm

arb_brotli_files = $(wildcard crates/brotli/src/*.* crates/brotli/src/*/*.* crates/brotli/*.toml crates/brotli/*.rs) .make/cbrotli-lib .make/cbrotli-wasm

Expand Down Expand Up @@ -182,6 +183,7 @@ build-node-deps: $(go_source) build-prover-header build-prover-lib build-jit .ma
.PHONY: test-go-deps
test-go-deps: \
build-replay-env \
build-unified-replay-env \
build-validation-server \
$(stylus_test_wasms) \
$(arbitrator_stylus_lib) \
Expand All @@ -206,6 +208,12 @@ build-validation-server: $(validation_server)
.PHONY: build-replay-env
build-replay-env: $(prover_bin) $(arbitrator_jit) $(arbitrator_wasm_libs) $(replay_wasm) $(output_latest)/machine.v2.wavm.br

.PHONY: build-unified-replay-env
build-unified-replay-env: $(unified_replay_wasm) $(output_latest)/unified_machine.wavm.br

.PHONY: build-unified-wasm-bin
build-unified-wasm-bin: $(unified_replay_wasm)

.PHONY: build-wasm-libs
build-wasm-libs: $(arbitrator_wasm_libs)

Expand Down Expand Up @@ -369,6 +377,11 @@ $(replay_wasm): $(DEP_PREDICATE) $(go_source) .make/solgen
GOOS=wasip1 GOARCH=wasm go build -o $@ ./cmd/replay/...
./scripts/remove_reference_types.sh $@

$(unified_replay_wasm): $(DEP_PREDICATE) $(go_source) .make/solgen
mkdir -p `dirname $(unified_replay_wasm)`
GOOS=wasip1 GOARCH=wasm go build -o $@ ./cmd/unified-replay/...
./scripts/remove_reference_types.sh $@

$(prover_bin): $(DEP_PREDICATE) $(rust_prover_files)
mkdir -p `dirname $(prover_bin)`
cargo build --release --bin prover ${CARGOFLAGS}
Expand Down Expand Up @@ -487,6 +500,10 @@ $(output_latest)/machine.v2.wavm.br: $(DEP_PREDICATE) $(prover_bin) $(arbitrator
$(prover_bin) $(replay_wasm) --generate-binaries $(output_latest) \
$(patsubst %,-l $(output_latest)/%.wasm, forward soft-float wasi_stub host_io user_host arbcompress arbcrypto program_exec)

$(output_latest)/unified_machine.wavm.br: $(DEP_PREDICATE) $(prover_bin) $(arbitrator_wasm_libs) $(unified_replay_wasm)
$(prover_bin) $(unified_replay_wasm) --generate-binaries $(output_latest) --until-hostio-bin-filename="unified-until-host-io-state.bin" --brotli-wavm-machine-filename="unified_machine.wavm.br" --module-root-filename="unified-module-root.txt" \
$(patsubst %,-l $(output_latest)/%.wasm, forward soft-float wasi_stub host_io user_host arbcompress arbcrypto program_exec)

$(arbitrator_cases)/%.wasm: $(arbitrator_cases)/%.wat
wat2wasm $< -o $@

Expand Down
6 changes: 6 additions & 0 deletions changelog/rauljordan-NIT-4704.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
### Added
- Unified replay binary (`cmd/unified-replay/`) combining MEL message extraction and block production into a single WASM-compilable program
- `GetEndParentChainBlockHash` host I/O opcode for MEL proving
- `melwavmio` package providing WASM imports and native stubs for MEL
- Extended `GlobalState` to 4 bytes32 slots with backward-compatible hashing
- Makefile targets `build-unified-replay-env` and `build-unified-wasm-bin`
24 changes: 1 addition & 23 deletions cmd/replay/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package main
import (
"bytes"
"context"
"encoding/hex"
"encoding/json"
"fmt"
"io"
Expand Down Expand Up @@ -255,27 +254,6 @@ func (r *DACertificatePreimageReader) RecoverPayloadAndPreimages(
})
}

// To generate:
// key, _ := crypto.HexToECDSA("0000000000000000000000000000000000000000000000000000000000000001")
// sig, _ := crypto.Sign(make([]byte, 32), key)
// println(hex.EncodeToString(sig))
const sampleSignature = "a0b37f8fba683cc68f6574cd43b39f0343a50008bf6ccea9d13231d9e7e2e1e411edc8d307254296264aebfc3dc76cd8b668373a072fd64665b50000e9fcce5201"

// We call this early to populate the secp256k1 ecc basepoint cache in the cached early machine state.
// That means we don't need to re-compute it for every block.
func populateEcdsaCaches() {
signature, err := hex.DecodeString(sampleSignature)
if err != nil {
log.Warn("failed to decode sample signature to populate ECDSA cache", "err", err)
return
}
_, err = crypto.Ecrecover(make([]byte, 32), signature)
if err != nil {
log.Warn("failed to recover signature to populate ECDSA cache", "err", err)
return
}
}

func main() {
wavmio.OnInit()
gethhook.RequireHookedGeth()
Expand All @@ -285,7 +263,7 @@ func main() {
glogger.Verbosity(log.LevelError)
log.SetDefault(log.NewLogger(glogger))

populateEcdsaCaches()
wavmio.PopulateEcdsaCaches()

raw := rawdb.NewDatabase(PreimageDb{})
db := state.NewDatabase(triedb.NewDatabase(raw, nil), nil)
Expand Down
125 changes: 125 additions & 0 deletions cmd/unified-replay/db.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// Copyright 2021-2026, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE.md

package main

import (
"bytes"
"encoding/hex"
"errors"
"fmt"

"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb"

"github.com/offchainlabs/nitro/arbutil"
"github.com/offchainlabs/nitro/melwavmio"
)

type PreimageDb struct{}

func (db PreimageDb) Has(key []byte) (bool, error) {
if len(key) != 32 {
return false, nil
}
return false, errors.New("preimage DB doesn't support Has")
}

func (db PreimageDb) DeleteRange(start, end []byte) error {
return errors.New("preimage DB doesn't support DeleteRange")
}

func (db PreimageDb) Get(key []byte) ([]byte, error) {
var hash [32]byte
copy(hash[:], key)
if len(key) == 32 {
copy(hash[:], key)
} else if len(key) == len(rawdb.CodePrefix)+32 && bytes.HasPrefix(key, rawdb.CodePrefix) {
// Retrieving code
copy(hash[:], key[len(rawdb.CodePrefix):])
} else {
return nil, fmt.Errorf("preimage DB attempted to access non-hash key %v", hex.EncodeToString(key))
}
Comment on lines +33 to +42
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

[Suggestion] The unconditional copy(hash[:], key) on line 34 is dead code: if len(key) == 32, line 36 repeats the same copy; if it's the code prefix, line 39 overwrites; in the else branch at line 40 we return before hash is ever used. This mirrors the same pattern in cmd/replay/db.go:33-42, so it's pre-existing rather than introduced here — but since the file is brand new, good moment to drop the redundant line.

return melwavmio.ResolveTypedPreimage(arbutil.Keccak256PreimageType, hash)
}

func (db PreimageDb) Put(key []byte, value []byte) error {
return errors.New("preimage DB doesn't support Put")
}

func (db PreimageDb) Delete(key []byte) error {
return errors.New("preimage DB doesn't support Delete")
}

func (db PreimageDb) NewBatch() ethdb.Batch {
return NopBatcher{db}
}

func (db PreimageDb) NewBatchWithSize(size int) ethdb.Batch {
return NopBatcher{db}
}

func (db PreimageDb) NewIterator(prefix []byte, start []byte) ethdb.Iterator {
return ErrorIterator{}
}

func (db PreimageDb) Stat() (string, error) {
return "", errors.New("preimage DB doesn't support Stat")
}

func (db PreimageDb) Compact(start []byte, limit []byte) error {
return nil
}

func (db PreimageDb) Close() error {
return nil
}

func (db PreimageDb) Release() {
}

func (db PreimageDb) SyncAncient() error {
return nil // no-op
}

func (db PreimageDb) SyncKeyValue() error {
return nil // no-op
}

type NopBatcher struct {
ethdb.KeyValueStore
}

func (b NopBatcher) ValueSize() int {
return 0
}

func (b NopBatcher) Write() error {
return nil
}

func (b NopBatcher) Reset() {}

func (b NopBatcher) Replay(w ethdb.KeyValueWriter) error {
return nil
}

type ErrorIterator struct{}

func (i ErrorIterator) Next() bool {
return false
}

func (i ErrorIterator) Error() error {
return errors.New("preimage DB doesn't support iterators")
}

func (i ErrorIterator) Key() []byte {
return []byte{}
}

func (i ErrorIterator) Value() []byte {
return []byte{}
}

func (i ErrorIterator) Release() {}
Loading
Loading