Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
40e952d8
Unverified
Commit
40e952d8
authored
Jul 30, 2023
by
clabby
Committed by
GitHub
Jul 30, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "op-program: Boot program using output root"
parent
f30fdd3f
Changes
35
Hide whitespace changes
Inline
Side-by-side
Showing
35 changed files
with
106 additions
and
520 deletions
+106
-520
l2_verifier.go
op-e2e/actions/l2_verifier.go
+0
-1
system_fpp_test.go
op-e2e/system_fpp_test.go
+4
-13
output.go
op-node/eth/output.go
+0
-70
output_test.go
op-node/eth/output_test.go
+0
-26
api.go
op-node/node/api.go
+32
-7
server_test.go
op-node/node/server_test.go
+14
-6
output_root.go
op-node/rollup/output_root.go
+16
-17
l2_client.go
op-node/sources/l2_client.go
+0
-29
mock_l2.go
op-node/testutils/mock_l2.go
+0
-8
random.go
op-node/testutils/random.go
+0
-8
boot.go
op-program/client/boot.go
+4
-4
boot_test.go
op-program/client/boot_test.go
+3
-3
cache.go
op-program/client/l2/cache.go
+8
-22
cache_test.go
op-program/client/l2/cache_test.go
+0
-20
engine_backend.go
op-program/client/l2/engine_backend.go
+2
-8
engine_backend_test.go
op-program/client/l2/engine_backend_test.go
+2
-9
hints.go
op-program/client/l2/hints.go
+0
-9
oracle.go
op-program/client/l2/oracle.go
+0
-12
oracle_test.go
op-program/client/l2/oracle_test.go
+0
-18
stub_oracle.go
op-program/client/l2/test/stub_oracle.go
+3
-20
program.go
op-program/client/program.go
+3
-3
main_test.go
op-program/host/cmd/main_test.go
+0
-18
config.go
op-program/host/config/config.go
+3
-24
config_test.go
op-program/host/config/config_test.go
+1
-9
flags.go
op-program/host/flags/flags.go
+1
-7
host.go
op-program/host/host.go
+2
-2
host_test.go
op-program/host/host_test.go
+2
-4
local.go
op-program/host/kvstore/local.go
+3
-3
local_test.go
op-program/host/kvstore/local_test.go
+2
-2
l2_client.go
op-program/host/l2_client.go
+0
-49
prefetcher.go
op-program/host/prefetcher/prefetcher.go
+0
-7
prefetcher_test.go
op-program/host/prefetcher/prefetcher_test.go
+0
-9
retry.go
op-program/host/prefetcher/retry.go
+0
-14
retry_test.go
op-program/host/prefetcher/retry_test.go
+0
-33
goerli.go
op-program/verify/cmd/goerli.go
+1
-26
No files found.
op-e2e/actions/l2_verifier.go
View file @
40e952d8
...
...
@@ -54,7 +54,6 @@ type L2API interface {
InfoByHash
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
eth
.
BlockInfo
,
error
)
// GetProof returns a proof of the account, it may return a nil result without error if the address was not found.
GetProof
(
ctx
context
.
Context
,
address
common
.
Address
,
storage
[]
common
.
Hash
,
blockTag
string
)
(
*
eth
.
AccountResult
,
error
)
OutputV0AtBlock
(
ctx
context
.
Context
,
blockHash
common
.
Hash
)
(
*
eth
.
OutputV0
,
error
)
}
func
NewL2Verifier
(
t
Testing
,
log
log
.
Logger
,
l1
derive
.
L1Fetcher
,
eng
L2API
,
cfg
*
rollup
.
Config
)
*
L2Verifier
{
...
...
op-e2e/system_fpp_test.go
View file @
40e952d8
...
...
@@ -86,10 +86,7 @@ func testVerifyL2OutputRootEmptyBlock(t *testing.T, detached bool) {
require
.
NoError
(
t
,
waitForSafeHead
(
ctx
,
receipt
.
BlockNumber
.
Uint64
(),
rollupClient
))
t
.
Logf
(
"Capture current L2 head as agreed starting point. l2Head=%x l2BlockNumber=%v"
,
receipt
.
BlockHash
,
receipt
.
BlockNumber
)
agreedL2Output
,
err
:=
rollupClient
.
OutputAtBlock
(
ctx
,
receipt
.
BlockNumber
.
Uint64
())
require
.
NoError
(
t
,
err
,
"could not retrieve l2 agreed block"
)
l2Head
:=
agreedL2Output
.
BlockRef
.
Hash
l2OutputRoot
:=
agreedL2Output
.
OutputRoot
l2Head
:=
receipt
.
BlockHash
t
.
Log
(
"=====Stopping batch submitter====="
)
err
=
sys
.
BatchSubmitter
.
Stop
(
ctx
)
...
...
@@ -139,7 +136,6 @@ func testVerifyL2OutputRootEmptyBlock(t *testing.T, detached bool) {
testFaultProofProgramScenario
(
t
,
ctx
,
sys
,
&
FaultProofProgramTestScenario
{
L1Head
:
l1Head
,
L2Head
:
l2Head
,
L2OutputRoot
:
common
.
Hash
(
l2OutputRoot
),
L2Claim
:
common
.
Hash
(
l2Claim
),
L2ClaimBlockNumber
:
l2ClaimBlockNumber
,
Detached
:
detached
,
...
...
@@ -185,12 +181,9 @@ func testVerifyL2OutputRoot(t *testing.T, detached bool) {
})
t
.
Log
(
"Capture current L2 head as agreed starting point"
)
latestBlock
,
err
:=
l2Seq
.
BlockByNumber
(
ctx
,
nil
)
require
.
NoError
(
t
,
err
)
agreedL2Output
,
err
:=
rollupClient
.
OutputAtBlock
(
ctx
,
latestBlock
.
NumberU64
())
l2AgreedBlock
,
err
:=
l2Seq
.
BlockByNumber
(
ctx
,
nil
)
require
.
NoError
(
t
,
err
,
"could not retrieve l2 agreed block"
)
l2Head
:=
agreedL2Output
.
BlockRef
.
Hash
l2OutputRoot
:=
agreedL2Output
.
OutputRoot
l2Head
:=
l2AgreedBlock
.
Hash
()
t
.
Log
(
"Sending transactions to modify existing state, within challenged period"
)
SendDepositTx
(
t
,
cfg
,
l1Client
,
l2Seq
,
opts
,
func
(
l2Opts
*
DepositTxOpts
)
{
...
...
@@ -221,7 +214,6 @@ func testVerifyL2OutputRoot(t *testing.T, detached bool) {
testFaultProofProgramScenario
(
t
,
ctx
,
sys
,
&
FaultProofProgramTestScenario
{
L1Head
:
l1Head
,
L2Head
:
l2Head
,
L2OutputRoot
:
common
.
Hash
(
l2OutputRoot
),
L2Claim
:
common
.
Hash
(
l2Claim
),
L2ClaimBlockNumber
:
l2ClaimBlockNumber
,
Detached
:
detached
,
...
...
@@ -231,7 +223,6 @@ func testVerifyL2OutputRoot(t *testing.T, detached bool) {
type
FaultProofProgramTestScenario
struct
{
L1Head
common
.
Hash
L2Head
common
.
Hash
L2OutputRoot
common
.
Hash
L2Claim
common
.
Hash
L2ClaimBlockNumber
uint64
Detached
bool
...
...
@@ -240,7 +231,7 @@ type FaultProofProgramTestScenario struct {
// testFaultProofProgramScenario runs the fault proof program in several contexts, given a test scenario.
func
testFaultProofProgramScenario
(
t
*
testing
.
T
,
ctx
context
.
Context
,
sys
*
System
,
s
*
FaultProofProgramTestScenario
)
{
preimageDir
:=
t
.
TempDir
()
fppConfig
:=
oppconf
.
NewConfig
(
sys
.
RollupConfig
,
sys
.
L2GenesisCfg
.
Config
,
s
.
L1Head
,
s
.
L2Head
,
s
.
L2OutputRoot
,
common
.
Hash
(
s
.
L2Claim
),
s
.
L2ClaimBlockNumber
)
fppConfig
:=
oppconf
.
NewConfig
(
sys
.
RollupConfig
,
sys
.
L2GenesisCfg
.
Config
,
s
.
L1Head
,
s
.
L2Head
,
common
.
Hash
(
s
.
L2Claim
),
s
.
L2ClaimBlockNumber
)
fppConfig
.
L1URL
=
sys
.
NodeEndpoint
(
"l1"
)
fppConfig
.
L2URL
=
sys
.
NodeEndpoint
(
"sequencer"
)
fppConfig
.
DataDir
=
preimageDir
...
...
op-node/eth/output.go
View file @
40e952d8
package
eth
import
(
"errors"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
)
type
OutputResponse
struct
{
...
...
@@ -15,70 +12,3 @@ type OutputResponse struct {
StateRoot
common
.
Hash
`json:"stateRoot"`
Status
*
SyncStatus
`json:"syncStatus"`
}
var
(
ErrInvalidOutput
=
errors
.
New
(
"invalid output"
)
ErrInvalidOutputVersion
=
errors
.
New
(
"invalid output version"
)
OutputVersionV0
=
Bytes32
{}
)
type
Output
interface
{
// Version returns the version of the L2 output
Version
()
Bytes32
// Marshal a L2 output into a byte slice for hashing
Marshal
()
[]
byte
}
type
OutputV0
struct
{
StateRoot
Bytes32
MessagePasserStorageRoot
Bytes32
BlockHash
common
.
Hash
}
func
(
o
*
OutputV0
)
Version
()
Bytes32
{
return
OutputVersionV0
}
func
(
o
*
OutputV0
)
Marshal
()
[]
byte
{
var
buf
[
128
]
byte
version
:=
o
.
Version
()
copy
(
buf
[
:
32
],
version
[
:
])
copy
(
buf
[
32
:
],
o
.
StateRoot
[
:
])
copy
(
buf
[
64
:
],
o
.
MessagePasserStorageRoot
[
:
])
copy
(
buf
[
96
:
],
o
.
BlockHash
[
:
])
return
buf
[
:
]
}
// OutputRoot returns the keccak256 hash of the marshaled L2 output
func
OutputRoot
(
output
Output
)
Bytes32
{
marshaled
:=
output
.
Marshal
()
return
Bytes32
(
crypto
.
Keccak256Hash
(
marshaled
))
}
func
UnmarshalOutput
(
data
[]
byte
)
(
Output
,
error
)
{
if
len
(
data
)
<
32
{
return
nil
,
ErrInvalidOutput
}
var
ver
Bytes32
copy
(
ver
[
:
],
data
[
:
32
])
switch
ver
{
case
OutputVersionV0
:
return
unmarshalOutputV0
(
data
)
default
:
return
nil
,
ErrInvalidOutputVersion
}
}
func
unmarshalOutputV0
(
data
[]
byte
)
(
*
OutputV0
,
error
)
{
if
len
(
data
)
!=
128
{
return
nil
,
ErrInvalidOutput
}
var
output
OutputV0
// data[:32] is the version
copy
(
output
.
StateRoot
[
:
],
data
[
32
:
64
])
copy
(
output
.
MessagePasserStorageRoot
[
:
],
data
[
64
:
96
])
copy
(
output
.
BlockHash
[
:
],
data
[
96
:
128
])
return
&
output
,
nil
}
op-node/eth/output_test.go
deleted
100644 → 0
View file @
f30fdd3f
package
eth
import
(
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
func
TestOutputV0Codec
(
t
*
testing
.
T
)
{
output
:=
OutputV0
{
StateRoot
:
Bytes32
{
1
,
2
,
3
},
MessagePasserStorageRoot
:
Bytes32
{
4
,
5
,
6
},
BlockHash
:
common
.
Hash
{
7
,
8
,
9
},
}
marshaled
:=
output
.
Marshal
()
unmarshaled
,
err
:=
UnmarshalOutput
(
marshaled
)
require
.
NoError
(
t
,
err
)
unmarshaledV0
:=
unmarshaled
.
(
*
OutputV0
)
require
.
Equal
(
t
,
output
,
*
unmarshaledV0
)
_
,
err
=
UnmarshalOutput
([]
byte
{
0
:
0xA
,
32
:
0xA
})
require
.
ErrorIs
(
t
,
err
,
ErrInvalidOutputVersion
)
_
,
err
=
UnmarshalOutput
([]
byte
{
64
:
0xA
})
require
.
ErrorIs
(
t
,
err
,
ErrInvalidOutput
)
}
op-node/node/api.go
View file @
40e952d8
...
...
@@ -4,10 +4,12 @@ import (
"context"
"fmt"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/version"
...
...
@@ -18,7 +20,6 @@ type l2EthClient interface {
// GetProof returns a proof of the account, it may return a nil result without error if the address was not found.
// Optionally keys of the account storage trie can be specified to include with corresponding values in the proof.
GetProof
(
ctx
context
.
Context
,
address
common
.
Address
,
storage
[]
common
.
Hash
,
blockTag
string
)
(
*
eth
.
AccountResult
,
error
)
OutputV0AtBlock
(
ctx
context
.
Context
,
blockHash
common
.
Hash
)
(
*
eth
.
OutputV0
,
error
)
}
type
driverClient
interface
{
...
...
@@ -98,16 +99,40 @@ func (n *nodeAPI) OutputAtBlock(ctx context.Context, number hexutil.Uint64) (*et
return
nil
,
fmt
.
Errorf
(
"failed to get L2 block ref with sync status: %w"
,
err
)
}
output
,
err
:=
n
.
client
.
OutputV0AtBlock
(
ctx
,
ref
.
Hash
)
head
,
err
:=
n
.
client
.
InfoByHash
(
ctx
,
ref
.
Hash
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to get L2
output at block
%s: %w"
,
ref
,
err
)
return
nil
,
fmt
.
Errorf
(
"failed to get L2
block by hash
%s: %w"
,
ref
,
err
)
}
if
head
==
nil
{
return
nil
,
ethereum
.
NotFound
}
proof
,
err
:=
n
.
client
.
GetProof
(
ctx
,
predeploys
.
L2ToL1MessagePasserAddr
,
[]
common
.
Hash
{},
ref
.
Hash
.
String
())
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to get contract proof at block %s: %w"
,
ref
,
err
)
}
if
proof
==
nil
{
return
nil
,
fmt
.
Errorf
(
"proof %w"
,
ethereum
.
NotFound
)
}
// make sure that the proof (including storage hash) that we retrieved is correct by verifying it against the state-root
if
err
:=
proof
.
Verify
(
head
.
Root
());
err
!=
nil
{
n
.
log
.
Error
(
"invalid withdrawal root detected in block"
,
"stateRoot"
,
head
.
Root
(),
"blocknum"
,
number
,
"msg"
,
err
)
return
nil
,
fmt
.
Errorf
(
"invalid withdrawal root hash, state root was %s: %w"
,
head
.
Root
(),
err
)
}
var
l2OutputRootVersion
eth
.
Bytes32
// it's zero for now
l2OutputRoot
,
err
:=
rollup
.
ComputeL2OutputRootV0
(
head
,
proof
.
StorageHash
)
if
err
!=
nil
{
n
.
log
.
Error
(
"Error computing L2 output root, nil ptr passed to hashing function"
)
return
nil
,
err
}
return
&
eth
.
OutputResponse
{
Version
:
output
.
Version
()
,
OutputRoot
:
eth
.
OutputRoot
(
output
)
,
Version
:
l2OutputRootVersion
,
OutputRoot
:
l2OutputRoot
,
BlockRef
:
ref
,
WithdrawalStorageRoot
:
common
.
Hash
(
output
.
MessagePasserStorageRoot
)
,
StateRoot
:
common
.
Hash
(
output
.
StateRoot
),
WithdrawalStorageRoot
:
proof
.
StorageHash
,
StateRoot
:
head
.
Root
(
),
Status
:
status
,
},
nil
}
...
...
op-node/node/server_test.go
View file @
40e952d8
...
...
@@ -16,6 +16,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/metrics"
"github.com/ethereum-optimism/optimism/op-node/rollup"
...
...
@@ -83,6 +84,17 @@ func TestOutputAtBlock(t *testing.T) {
}
l2Client
:=
&
testutils
.
MockL2Client
{}
info
:=
&
testutils
.
MockBlockInfo
{
InfoHash
:
header
.
Hash
(),
InfoParentHash
:
header
.
ParentHash
,
InfoCoinbase
:
header
.
Coinbase
,
InfoRoot
:
header
.
Root
,
InfoNum
:
header
.
Number
.
Uint64
(),
InfoTime
:
header
.
Time
,
InfoMixDigest
:
header
.
MixDigest
,
InfoBaseFee
:
header
.
BaseFee
,
InfoReceiptRoot
:
header
.
ReceiptHash
,
}
ref
:=
eth
.
L2BlockRef
{
Hash
:
header
.
Hash
(),
Number
:
header
.
Number
.
Uint64
(),
...
...
@@ -91,12 +103,8 @@ func TestOutputAtBlock(t *testing.T) {
L1Origin
:
eth
.
BlockID
{},
SequenceNumber
:
0
,
}
output
:=
&
eth
.
OutputV0
{
StateRoot
:
eth
.
Bytes32
(
header
.
Root
),
BlockHash
:
ref
.
Hash
,
MessagePasserStorageRoot
:
eth
.
Bytes32
(
result
.
StorageHash
),
}
l2Client
.
ExpectOutputV0AtBlock
(
common
.
HexToHash
(
"0x8512bee03061475e4b069171f7b406097184f16b22c3f5c97c0abfc49591c524"
),
output
,
nil
)
l2Client
.
ExpectInfoByHash
(
common
.
HexToHash
(
"0x8512bee03061475e4b069171f7b406097184f16b22c3f5c97c0abfc49591c524"
),
info
,
nil
)
l2Client
.
ExpectGetProof
(
predeploys
.
L2ToL1MessagePasserAddr
,
[]
common
.
Hash
{},
"0x8512bee03061475e4b069171f7b406097184f16b22c3f5c97c0abfc49591c524"
,
&
result
,
nil
)
drClient
:=
&
mockDriverClient
{}
status
:=
randomSyncStatus
(
rand
.
New
(
rand
.
NewSource
(
123
)))
...
...
op-node/rollup/output_root.go
View file @
40e952d8
...
...
@@ -5,33 +5,32 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum/go-ethereum/crypto"
)
var
ErrNilProof
=
errors
.
New
(
"o
utput root proof is nil"
)
var
NilProof
=
errors
.
New
(
"O
utput root proof is nil"
)
// ComputeL2OutputRoot computes the L2 output root by hashing an output root proof.
func
ComputeL2OutputRoot
(
proofElements
*
bindings
.
TypesOutputRootProof
)
(
eth
.
Bytes32
,
error
)
{
if
proofElements
==
nil
{
return
eth
.
Bytes32
{},
Err
NilProof
return
eth
.
Bytes32
{},
NilProof
}
if
proofElements
.
Version
!=
[
32
]
byte
{}
{
return
eth
.
Bytes32
{},
errors
.
New
(
"unsupported output root version"
)
}
l2Output
:=
eth
.
OutputV0
{
StateRoot
:
eth
.
Bytes32
(
proofElements
.
StateRoot
),
MessagePasserStorageRoot
:
proofElements
.
MessagePasserStorageRoot
,
BlockHash
:
proofElements
.
LatestBlockhash
,
}
return
eth
.
OutputRoot
(
&
l2Output
),
nil
digest
:=
crypto
.
Keccak256Hash
(
proofElements
.
Version
[
:
],
proofElements
.
StateRoot
[
:
],
proofElements
.
MessagePasserStorageRoot
[
:
],
proofElements
.
LatestBlockhash
[
:
],
)
return
eth
.
Bytes32
(
digest
),
nil
}
func
ComputeL2OutputRootV0
(
block
eth
.
BlockInfo
,
storageRoot
[
32
]
byte
)
(
eth
.
Bytes32
,
error
)
{
stateRoot
:=
block
.
Root
()
l2Output
:=
eth
.
OutputV0
{
StateRoot
:
eth
.
Bytes32
(
stateRoot
),
var
l2OutputRootVersion
eth
.
Bytes32
// it's zero for now
return
ComputeL2OutputRoot
(
&
bindings
.
TypesOutputRootProof
{
Version
:
l2OutputRootVersion
,
StateRoot
:
block
.
Root
(),
MessagePasserStorageRoot
:
storageRoot
,
BlockHash
:
block
.
Hash
(),
}
return
eth
.
OutputRoot
(
&
l2Output
),
nil
LatestBlockhash
:
block
.
Hash
(),
})
}
op-node/sources/l2_client.go
View file @
40e952d8
...
...
@@ -10,7 +10,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-node/client"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup"
...
...
@@ -166,31 +165,3 @@ func (s *L2Client) SystemConfigByL2Hash(ctx context.Context, hash common.Hash) (
s
.
systemConfigsCache
.
Add
(
hash
,
cfg
)
return
cfg
,
nil
}
func
(
s
*
L2Client
)
OutputV0AtBlock
(
ctx
context
.
Context
,
blockHash
common
.
Hash
)
(
*
eth
.
OutputV0
,
error
)
{
head
,
err
:=
s
.
InfoByHash
(
ctx
,
blockHash
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to get L2 block by hash: %w"
,
err
)
}
if
head
==
nil
{
return
nil
,
ethereum
.
NotFound
}
proof
,
err
:=
s
.
GetProof
(
ctx
,
predeploys
.
L2ToL1MessagePasserAddr
,
[]
common
.
Hash
{},
blockHash
.
String
())
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to get contract proof at block %s: %w"
,
blockHash
,
err
)
}
if
proof
==
nil
{
return
nil
,
fmt
.
Errorf
(
"proof %w"
,
ethereum
.
NotFound
)
}
// make sure that the proof (including storage hash) that we retrieved is correct by verifying it against the state-root
if
err
:=
proof
.
Verify
(
head
.
Root
());
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"invalid withdrawal root hash, state root was %s: %w"
,
head
.
Root
(),
err
)
}
stateRoot
:=
head
.
Root
()
return
&
eth
.
OutputV0
{
StateRoot
:
eth
.
Bytes32
(
stateRoot
),
MessagePasserStorageRoot
:
eth
.
Bytes32
(
proof
.
StorageHash
),
BlockHash
:
blockHash
,
},
nil
}
op-node/testutils/mock_l2.go
View file @
40e952d8
...
...
@@ -43,11 +43,3 @@ func (m *MockL2Client) SystemConfigByL2Hash(ctx context.Context, hash common.Has
func
(
m
*
MockL2Client
)
ExpectSystemConfigByL2Hash
(
hash
common
.
Hash
,
cfg
eth
.
SystemConfig
,
err
error
)
{
m
.
Mock
.
On
(
"SystemConfigByL2Hash"
,
hash
)
.
Once
()
.
Return
(
cfg
,
&
err
)
}
func
(
m
*
MockL2Client
)
OutputV0AtBlock
(
ctx
context
.
Context
,
blockHash
common
.
Hash
)
(
*
eth
.
OutputV0
,
error
)
{
return
m
.
Mock
.
MethodCalled
(
"OutputV0AtBlock"
,
blockHash
)
.
Get
(
0
)
.
(
*
eth
.
OutputV0
),
nil
}
func
(
m
*
MockL2Client
)
ExpectOutputV0AtBlock
(
blockHash
common
.
Hash
,
output
*
eth
.
OutputV0
,
err
error
)
{
m
.
Mock
.
On
(
"OutputV0AtBlock"
,
blockHash
)
.
Once
()
.
Return
(
output
,
&
err
)
}
op-node/testutils/random.go
View file @
40e952d8
...
...
@@ -269,11 +269,3 @@ func RandomOutputResponse(rng *rand.Rand) *eth.OutputResponse {
},
}
}
func
RandomOutputV0
(
rng
*
rand
.
Rand
)
*
eth
.
OutputV0
{
return
&
eth
.
OutputV0
{
StateRoot
:
eth
.
Bytes32
(
RandomHash
(
rng
)),
MessagePasserStorageRoot
:
eth
.
Bytes32
(
RandomHash
(
rng
)),
BlockHash
:
RandomHash
(
rng
),
}
}
op-program/client/boot.go
View file @
40e952d8
...
...
@@ -12,7 +12,7 @@ import (
const
(
L1HeadLocalIndex
preimage
.
LocalIndexKey
=
iota
+
1
L2
OutputRoot
LocalIndex
L2
Head
LocalIndex
L2ClaimLocalIndex
L2ClaimBlockNumberLocalIndex
L2ChainConfigLocalIndex
...
...
@@ -21,7 +21,7 @@ const (
type
BootInfo
struct
{
L1Head
common
.
Hash
L2
OutputRoot
common
.
Hash
L2
Head
common
.
Hash
L2Claim
common
.
Hash
L2ClaimBlockNumber
uint64
L2ChainConfig
*
params
.
ChainConfig
...
...
@@ -42,7 +42,7 @@ func NewBootstrapClient(r oracleClient) *BootstrapClient {
func
(
br
*
BootstrapClient
)
BootInfo
()
*
BootInfo
{
l1Head
:=
common
.
BytesToHash
(
br
.
r
.
Get
(
L1HeadLocalIndex
))
l2
OutputRoot
:=
common
.
BytesToHash
(
br
.
r
.
Get
(
L2OutputRoot
LocalIndex
))
l2
Head
:=
common
.
BytesToHash
(
br
.
r
.
Get
(
L2Head
LocalIndex
))
l2Claim
:=
common
.
BytesToHash
(
br
.
r
.
Get
(
L2ClaimLocalIndex
))
l2ClaimBlockNumber
:=
binary
.
BigEndian
.
Uint64
(
br
.
r
.
Get
(
L2ClaimBlockNumberLocalIndex
))
l2ChainConfig
:=
new
(
params
.
ChainConfig
)
...
...
@@ -58,7 +58,7 @@ func (br *BootstrapClient) BootInfo() *BootInfo {
return
&
BootInfo
{
L1Head
:
l1Head
,
L2
OutputRoot
:
l2OutputRoot
,
L2
Head
:
l2Head
,
L2Claim
:
l2Claim
,
L2ClaimBlockNumber
:
l2ClaimBlockNumber
,
L2ChainConfig
:
l2ChainConfig
,
...
...
op-program/client/boot_test.go
View file @
40e952d8
...
...
@@ -15,7 +15,7 @@ import (
func
TestBootstrapClient
(
t
*
testing
.
T
)
{
bootInfo
:=
&
BootInfo
{
L1Head
:
common
.
HexToHash
(
"0x1111"
),
L2
OutputRoot
:
common
.
HexToHash
(
"0x2222"
),
L2
Head
:
common
.
HexToHash
(
"0x2222"
),
L2Claim
:
common
.
HexToHash
(
"0x3333"
),
L2ClaimBlockNumber
:
1
,
L2ChainConfig
:
params
.
GoerliChainConfig
,
...
...
@@ -34,8 +34,8 @@ func (o *mockBoostrapOracle) Get(key preimage.Key) []byte {
switch
key
.
PreimageKey
()
{
case
L1HeadLocalIndex
.
PreimageKey
()
:
return
o
.
b
.
L1Head
[
:
]
case
L2
OutputRoot
LocalIndex
.
PreimageKey
()
:
return
o
.
b
.
L2
OutputRoot
[
:
]
case
L2
Head
LocalIndex
.
PreimageKey
()
:
return
o
.
b
.
L2
Head
[
:
]
case
L2ClaimLocalIndex
.
PreimageKey
()
:
return
o
.
b
.
L2Claim
[
:
]
case
L2ClaimBlockNumberLocalIndex
.
PreimageKey
()
:
...
...
op-program/client/l2/cache.go
View file @
40e952d8
package
l2
import
(
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/hashicorp/golang-lru/v2/simplelru"
...
...
@@ -14,24 +13,21 @@ const nodeCacheSize = 100_000
const
codeCacheSize
=
10
_000
type
CachingOracle
struct
{
oracle
Oracle
blocks
*
simplelru
.
LRU
[
common
.
Hash
,
*
types
.
Block
]
nodes
*
simplelru
.
LRU
[
common
.
Hash
,
[]
byte
]
codes
*
simplelru
.
LRU
[
common
.
Hash
,
[]
byte
]
outputs
*
simplelru
.
LRU
[
common
.
Hash
,
eth
.
Output
]
oracle
Oracle
blocks
*
simplelru
.
LRU
[
common
.
Hash
,
*
types
.
Block
]
nodes
*
simplelru
.
LRU
[
common
.
Hash
,
[]
byte
]
codes
*
simplelru
.
LRU
[
common
.
Hash
,
[]
byte
]
}
func
NewCachingOracle
(
oracle
Oracle
)
*
CachingOracle
{
blockLRU
,
_
:=
simplelru
.
NewLRU
[
common
.
Hash
,
*
types
.
Block
](
blockCacheSize
,
nil
)
nodeLRU
,
_
:=
simplelru
.
NewLRU
[
common
.
Hash
,
[]
byte
](
nodeCacheSize
,
nil
)
codeLRU
,
_
:=
simplelru
.
NewLRU
[
common
.
Hash
,
[]
byte
](
codeCacheSize
,
nil
)
outputLRU
,
_
:=
simplelru
.
NewLRU
[
common
.
Hash
,
eth
.
Output
](
codeCacheSize
,
nil
)
return
&
CachingOracle
{
oracle
:
oracle
,
blocks
:
blockLRU
,
nodes
:
nodeLRU
,
codes
:
codeLRU
,
outputs
:
outputLRU
,
oracle
:
oracle
,
blocks
:
blockLRU
,
nodes
:
nodeLRU
,
codes
:
codeLRU
,
}
}
...
...
@@ -64,13 +60,3 @@ func (o *CachingOracle) BlockByHash(blockHash common.Hash) *types.Block {
o
.
blocks
.
Add
(
blockHash
,
block
)
return
block
}
func
(
o
*
CachingOracle
)
OutputByRoot
(
root
common
.
Hash
)
eth
.
Output
{
output
,
ok
:=
o
.
outputs
.
Get
(
root
)
if
ok
{
return
output
}
output
=
o
.
oracle
.
OutputByRoot
(
root
)
o
.
outputs
.
Add
(
root
,
output
)
return
output
}
op-program/client/l2/cache_test.go
View file @
40e952d8
...
...
@@ -4,7 +4,6 @@ import (
"math/rand"
"testing"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/testutils"
"github.com/ethereum-optimism/optimism/op-program/client/l2/test"
"github.com/ethereum/go-ethereum/common"
...
...
@@ -67,22 +66,3 @@ func TestCodeByHash(t *testing.T) {
actual
=
oracle
.
CodeByHash
(
hash
)
require
.
Equal
(
t
,
node
,
actual
)
}
func
TestOutputByRoot
(
t
*
testing
.
T
)
{
stub
,
_
:=
test
.
NewStubOracle
(
t
)
oracle
:=
NewCachingOracle
(
stub
)
rng
:=
rand
.
New
(
rand
.
NewSource
(
1
))
output
:=
testutils
.
RandomOutputV0
(
rng
)
// Initial call retrieves from the stub
root
:=
common
.
Hash
(
eth
.
OutputRoot
(
output
))
stub
.
Outputs
[
root
]
=
output
actual
:=
oracle
.
OutputByRoot
(
root
)
require
.
Equal
(
t
,
output
,
actual
)
// Later calls should retrieve from cache
delete
(
stub
.
Outputs
,
root
)
actual
=
oracle
.
OutputByRoot
(
root
)
require
.
Equal
(
t
,
output
,
actual
)
}
op-program/client/l2/engine_backend.go
View file @
40e952d8
...
...
@@ -4,7 +4,6 @@ import (
"fmt"
"math/big"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-program/client/l2/engineapi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
...
...
@@ -40,13 +39,8 @@ type OracleBackedL2Chain struct {
var
_
engineapi
.
EngineBackend
=
(
*
OracleBackedL2Chain
)(
nil
)
func
NewOracleBackedL2Chain
(
logger
log
.
Logger
,
oracle
Oracle
,
chainCfg
*
params
.
ChainConfig
,
l2OutputRoot
common
.
Hash
)
(
*
OracleBackedL2Chain
,
error
)
{
output
:=
oracle
.
OutputByRoot
(
l2OutputRoot
)
outputV0
,
ok
:=
output
.
(
*
eth
.
OutputV0
)
if
!
ok
{
return
nil
,
fmt
.
Errorf
(
"unsupported L2 output version: %d"
,
output
.
Version
())
}
head
:=
oracle
.
BlockByHash
(
outputV0
.
BlockHash
)
func
NewOracleBackedL2Chain
(
logger
log
.
Logger
,
oracle
Oracle
,
chainCfg
*
params
.
ChainConfig
,
l2Head
common
.
Hash
)
(
*
OracleBackedL2Chain
,
error
)
{
head
:=
oracle
.
BlockByHash
(
l2Head
)
logger
.
Info
(
"Loaded L2 head"
,
"hash"
,
head
.
Hash
(),
"number"
,
head
.
Number
())
return
&
OracleBackedL2Chain
{
log
:
logger
,
...
...
op-program/client/l2/engine_backend_test.go
View file @
40e952d8
...
...
@@ -5,7 +5,6 @@ import (
"testing"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-program/client/l2/engineapi"
"github.com/ethereum-optimism/optimism/op-program/client/l2/engineapi/test"
...
...
@@ -200,8 +199,7 @@ func setupOracleBackedChainWithLowerHead(t *testing.T, blockCount int, headBlock
logger
:=
testlog
.
Logger
(
t
,
log
.
LvlDebug
)
chainCfg
,
blocks
,
oracle
:=
setupOracle
(
t
,
blockCount
,
headBlockNumber
)
head
:=
blocks
[
headBlockNumber
]
.
Hash
()
stubOutput
:=
eth
.
OutputV0
{
BlockHash
:
head
}
chain
,
err
:=
NewOracleBackedL2Chain
(
logger
,
oracle
,
chainCfg
,
common
.
Hash
(
eth
.
OutputRoot
(
&
stubOutput
)))
chain
,
err
:=
NewOracleBackedL2Chain
(
logger
,
oracle
,
chainCfg
,
head
)
require
.
NoError
(
t
,
err
)
return
blocks
,
chain
}
...
...
@@ -234,12 +232,7 @@ func setupOracle(t *testing.T, blockCount int, headBlockNumber int) (*params.Cha
genesisBlock
:=
l2Genesis
.
MustCommit
(
db
)
blocks
,
_
:=
core
.
GenerateChain
(
chainCfg
,
genesisBlock
,
consensus
,
db
,
blockCount
,
func
(
i
int
,
gen
*
core
.
BlockGen
)
{})
blocks
=
append
([]
*
types
.
Block
{
genesisBlock
},
blocks
...
)
var
outputs
[]
eth
.
Output
for
_
,
block
:=
range
blocks
{
outputs
=
append
(
outputs
,
&
eth
.
OutputV0
{
BlockHash
:
block
.
Hash
()})
}
oracle
:=
l2test
.
NewStubOracleWithBlocks
(
t
,
blocks
[
:
headBlockNumber
+
1
],
outputs
,
db
)
oracle
:=
l2test
.
NewStubOracleWithBlocks
(
t
,
blocks
[
:
headBlockNumber
+
1
],
db
)
return
chainCfg
,
blocks
,
oracle
}
...
...
op-program/client/l2/hints.go
View file @
40e952d8
...
...
@@ -11,7 +11,6 @@ const (
HintL2Transactions
=
"l2-transactions"
HintL2Code
=
"l2-code"
HintL2StateNode
=
"l2-state-node"
HintL2Output
=
"l2-output"
)
type
BlockHeaderHint
common
.
Hash
...
...
@@ -45,11 +44,3 @@ var _ preimage.Hint = StateNodeHint{}
func
(
l
StateNodeHint
)
Hint
()
string
{
return
HintL2StateNode
+
" "
+
(
common
.
Hash
)(
l
)
.
String
()
}
type
L2OutputHint
common
.
Hash
var
_
preimage
.
Hint
=
L2OutputHint
{}
func
(
l
L2OutputHint
)
Hint
()
string
{
return
HintL2Output
+
" "
+
(
common
.
Hash
)(
l
)
.
String
()
}
op-program/client/l2/oracle.go
View file @
40e952d8
...
...
@@ -32,8 +32,6 @@ type Oracle interface {
// BlockByHash retrieves the block with the given hash.
BlockByHash
(
blockHash
common
.
Hash
)
*
types
.
Block
OutputByRoot
(
root
common
.
Hash
)
eth
.
Output
}
// PreimageOracle implements Oracle using by interfacing with the pure preimage.Oracle
...
...
@@ -87,13 +85,3 @@ func (p *PreimageOracle) CodeByHash(codeHash common.Hash) []byte {
p
.
hint
.
Hint
(
CodeHint
(
codeHash
))
return
p
.
oracle
.
Get
(
preimage
.
Keccak256Key
(
codeHash
))
}
func
(
p
*
PreimageOracle
)
OutputByRoot
(
l2OutputRoot
common
.
Hash
)
eth
.
Output
{
p
.
hint
.
Hint
(
L2OutputHint
(
l2OutputRoot
))
data
:=
p
.
oracle
.
Get
(
preimage
.
Keccak256Key
(
l2OutputRoot
))
output
,
err
:=
eth
.
UnmarshalOutput
(
data
)
if
err
!=
nil
{
panic
(
fmt
.
Errorf
(
"invalid L2 output data for root %s: %w"
,
l2OutputRoot
,
err
))
}
return
output
}
op-program/client/l2/oracle_test.go
View file @
40e952d8
...
...
@@ -122,21 +122,3 @@ func TestPreimageOracleCodeByHash(t *testing.T) {
})
}
}
func
TestPreimageOracleOutputByRoot
(
t
*
testing
.
T
)
{
rng
:=
rand
.
New
(
rand
.
NewSource
(
123
))
for
i
:=
0
;
i
<
10
;
i
++
{
t
.
Run
(
fmt
.
Sprintf
(
"output_%d"
,
i
),
func
(
t
*
testing
.
T
)
{
po
,
hints
,
preimages
:=
mockPreimageOracle
(
t
)
output
:=
testutils
.
RandomOutputV0
(
rng
)
h
:=
common
.
Hash
(
eth
.
OutputRoot
(
output
))
preimages
[
preimage
.
Keccak256Key
(
h
)
.
PreimageKey
()]
=
output
.
Marshal
()
hints
.
On
(
"hint"
,
L2OutputHint
(
h
)
.
Hint
())
.
Once
()
.
Return
()
gotOutput
:=
po
.
OutputByRoot
(
h
)
hints
.
AssertExpectations
(
t
)
require
.
Equal
(
t
,
hexutil
.
Bytes
(
output
.
Marshal
()),
hexutil
.
Bytes
(
gotOutput
.
Marshal
()),
"output matches"
)
})
}
}
op-program/client/l2/test/stub_oracle.go
View file @
40e952d8
...
...
@@ -3,7 +3,6 @@ package test
import
(
"testing"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
...
...
@@ -17,9 +16,8 @@ type stateOracle interface {
}
type
StubBlockOracle
struct
{
t
*
testing
.
T
Blocks
map
[
common
.
Hash
]
*
types
.
Block
Outputs
map
[
common
.
Hash
]
eth
.
Output
t
*
testing
.
T
Blocks
map
[
common
.
Hash
]
*
types
.
Block
stateOracle
}
...
...
@@ -28,25 +26,18 @@ func NewStubOracle(t *testing.T) (*StubBlockOracle, *StubStateOracle) {
blockOracle
:=
StubBlockOracle
{
t
:
t
,
Blocks
:
make
(
map
[
common
.
Hash
]
*
types
.
Block
),
Outputs
:
make
(
map
[
common
.
Hash
]
eth
.
Output
),
stateOracle
:
stateOracle
,
}
return
&
blockOracle
,
stateOracle
}
func
NewStubOracleWithBlocks
(
t
*
testing
.
T
,
chain
[]
*
types
.
Block
,
outputs
[]
eth
.
Output
,
db
ethdb
.
Database
)
*
StubBlockOracle
{
func
NewStubOracleWithBlocks
(
t
*
testing
.
T
,
chain
[]
*
types
.
Block
,
db
ethdb
.
Database
)
*
StubBlockOracle
{
blocks
:=
make
(
map
[
common
.
Hash
]
*
types
.
Block
,
len
(
chain
))
for
_
,
block
:=
range
chain
{
blocks
[
block
.
Hash
()]
=
block
}
o
:=
make
(
map
[
common
.
Hash
]
eth
.
Output
,
len
(
outputs
))
for
_
,
output
:=
range
outputs
{
o
[
common
.
Hash
(
eth
.
OutputRoot
(
output
))]
=
output
}
return
&
StubBlockOracle
{
t
:
t
,
Blocks
:
blocks
,
Outputs
:
o
,
stateOracle
:
&
KvStateOracle
{
t
:
t
,
Source
:
db
},
}
}
...
...
@@ -59,14 +50,6 @@ func (o StubBlockOracle) BlockByHash(blockHash common.Hash) *types.Block {
return
block
}
func
(
o
StubBlockOracle
)
OutputByRoot
(
root
common
.
Hash
)
eth
.
Output
{
output
,
ok
:=
o
.
Outputs
[
root
]
if
!
ok
{
o
.
t
.
Fatalf
(
"requested unknown output root %s"
,
root
)
}
return
output
}
// KvStateOracle loads data from a source ethdb.KeyValueStore
type
KvStateOracle
struct
{
t
*
testing
.
T
...
...
op-program/client/program.go
View file @
40e952d8
...
...
@@ -53,7 +53,7 @@ func RunProgram(logger log.Logger, preimageOracle io.ReadWriter, preimageHinter
bootInfo
.
RollupConfig
,
bootInfo
.
L2ChainConfig
,
bootInfo
.
L1Head
,
bootInfo
.
L2
OutputRoot
,
bootInfo
.
L2
Head
,
bootInfo
.
L2Claim
,
bootInfo
.
L2ClaimBlockNumber
,
l1PreimageOracle
,
...
...
@@ -62,9 +62,9 @@ func RunProgram(logger log.Logger, preimageOracle io.ReadWriter, preimageHinter
}
// runDerivation executes the L2 state transition, given a minimal interface to retrieve data.
func
runDerivation
(
logger
log
.
Logger
,
cfg
*
rollup
.
Config
,
l2Cfg
*
params
.
ChainConfig
,
l1Head
common
.
Hash
,
l2
OutputRoot
common
.
Hash
,
l2Claim
common
.
Hash
,
l2ClaimBlockNum
uint64
,
l1Oracle
l1
.
Oracle
,
l2Oracle
l2
.
Oracle
)
error
{
func
runDerivation
(
logger
log
.
Logger
,
cfg
*
rollup
.
Config
,
l2Cfg
*
params
.
ChainConfig
,
l1Head
common
.
Hash
,
l2
Head
common
.
Hash
,
l2Claim
common
.
Hash
,
l2ClaimBlockNum
uint64
,
l1Oracle
l1
.
Oracle
,
l2Oracle
l2
.
Oracle
)
error
{
l1Source
:=
l1
.
NewOracleL1Client
(
logger
,
l1Oracle
,
l1Head
)
engineBackend
,
err
:=
l2
.
NewOracleBackedL2Chain
(
logger
,
l2Oracle
,
l2Cfg
,
l2
OutputRoot
)
engineBackend
,
err
:=
l2
.
NewOracleBackedL2Chain
(
logger
,
l2Oracle
,
l2Cfg
,
l2
Head
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to create oracle-backed L2 chain: %w"
,
err
)
}
...
...
op-program/host/cmd/main_test.go
View file @
40e952d8
...
...
@@ -20,7 +20,6 @@ var (
l1HeadValue
=
common
.
HexToHash
(
"0x111111"
)
.
Hex
()
l2HeadValue
=
common
.
HexToHash
(
"0x222222"
)
.
Hex
()
l2ClaimValue
=
common
.
HexToHash
(
"0x333333"
)
.
Hex
()
l2OutputRoot
=
common
.
HexToHash
(
"0x444444"
)
.
Hex
()
l2ClaimBlockNumber
=
uint64
(
1203
)
// Note: This is actually the L1 goerli genesis config. Just using it as an arbitrary, valid genesis config
l2Genesis
=
core
.
DefaultGoerliGenesisBlock
()
...
...
@@ -49,7 +48,6 @@ func TestDefaultCLIOptionsMatchDefaultConfig(t *testing.T) {
config
.
OPGoerliChainConfig
,
common
.
HexToHash
(
l1HeadValue
),
common
.
HexToHash
(
l2HeadValue
),
common
.
HexToHash
(
l2OutputRoot
),
common
.
HexToHash
(
l2ClaimValue
),
l2ClaimBlockNumber
)
require
.
Equal
(
t
,
defaultCfg
,
cfg
)
...
...
@@ -138,21 +136,6 @@ func TestL2Head(t *testing.T) {
})
}
func
TestL2OutputRoot
(
t
*
testing
.
T
)
{
t
.
Run
(
"Required"
,
func
(
t
*
testing
.
T
)
{
verifyArgsInvalid
(
t
,
"flag l2.outputroot is required"
,
addRequiredArgsExcept
(
"--l2.outputroot"
))
})
t
.
Run
(
"Valid"
,
func
(
t
*
testing
.
T
)
{
cfg
:=
configForArgs
(
t
,
replaceRequiredArg
(
"--l2.outputroot"
,
l2OutputRoot
))
require
.
Equal
(
t
,
common
.
HexToHash
(
l2OutputRoot
),
cfg
.
L2OutputRoot
)
})
t
.
Run
(
"Invalid"
,
func
(
t
*
testing
.
T
)
{
verifyArgsInvalid
(
t
,
config
.
ErrInvalidL2OutputRoot
.
Error
(),
replaceRequiredArg
(
"--l2.outputroot"
,
"something"
))
})
}
func
TestL1Head
(
t
*
testing
.
T
)
{
t
.
Run
(
"Required"
,
func
(
t
*
testing
.
T
)
{
verifyArgsInvalid
(
t
,
"flag l1.head is required"
,
addRequiredArgsExcept
(
"--l1.head"
))
...
...
@@ -324,7 +307,6 @@ func requiredArgs() map[string]string {
"--network"
:
"goerli"
,
"--l1.head"
:
l1HeadValue
,
"--l2.head"
:
l2HeadValue
,
"--l2.outputroot"
:
l2OutputRoot
,
"--l2.claim"
:
l2ClaimValue
,
"--l2.blocknumber"
:
strconv
.
FormatUint
(
l2ClaimBlockNumber
,
10
),
}
...
...
op-program/host/config/config.go
View file @
40e952d8
...
...
@@ -22,7 +22,6 @@ var (
ErrMissingL2Genesis
=
errors
.
New
(
"missing l2 genesis"
)
ErrInvalidL1Head
=
errors
.
New
(
"invalid l1 head"
)
ErrInvalidL2Head
=
errors
.
New
(
"invalid l2 head"
)
ErrInvalidL2OutputRoot
=
errors
.
New
(
"invalid l2 output root"
)
ErrL1AndL2Inconsistent
=
errors
.
New
(
"l1 and l2 options must be specified together or both omitted"
)
ErrInvalidL2Claim
=
errors
.
New
(
"invalid l2 claim"
)
ErrInvalidL2ClaimBlock
=
errors
.
New
(
"invalid l2 claim block number"
)
...
...
@@ -42,12 +41,9 @@ type Config struct {
L1TrustRPC
bool
L1RPCKind
sources
.
RPCProviderKind
// L2Head is the l2 block hash contained in the L2 Output referenced by the L2OutputRoot
// TODO(inphi): This can be made optional with hardcoded rollup configs and output oracle addresses by searching the oracle for the l2 output root
// L2Head is the agreed L2 block to start derivation from
L2Head
common
.
Hash
// L2OutputRoot is the agreed L2 output root to start derivation from
L2OutputRoot
common
.
Hash
L2URL
string
L2URL
string
// L2Claim is the claimed L2 output root to verify
L2Claim
common
.
Hash
// L2ClaimBlockNumber is the block number the claimed L2 output root is from
...
...
@@ -77,9 +73,6 @@ func (c *Config) Check() error {
if
c
.
L2Head
==
(
common
.
Hash
{})
{
return
ErrInvalidL2Head
}
if
c
.
L2OutputRoot
==
(
common
.
Hash
{})
{
return
ErrInvalidL2OutputRoot
}
if
c
.
L2Claim
==
(
common
.
Hash
{})
{
return
ErrInvalidL2Claim
}
...
...
@@ -106,21 +99,12 @@ func (c *Config) FetchingEnabled() bool {
}
// NewConfig creates a Config with all optional values set to the CLI default value
func
NewConfig
(
rollupCfg
*
rollup
.
Config
,
l2Genesis
*
params
.
ChainConfig
,
l1Head
common
.
Hash
,
l2Head
common
.
Hash
,
l2OutputRoot
common
.
Hash
,
l2Claim
common
.
Hash
,
l2ClaimBlockNum
uint64
,
)
*
Config
{
func
NewConfig
(
rollupCfg
*
rollup
.
Config
,
l2Genesis
*
params
.
ChainConfig
,
l1Head
common
.
Hash
,
l2Head
common
.
Hash
,
l2Claim
common
.
Hash
,
l2ClaimBlockNum
uint64
)
*
Config
{
return
&
Config
{
Rollup
:
rollupCfg
,
L2ChainConfig
:
l2Genesis
,
L1Head
:
l1Head
,
L2Head
:
l2Head
,
L2OutputRoot
:
l2OutputRoot
,
L2Claim
:
l2Claim
,
L2ClaimBlockNumber
:
l2ClaimBlockNum
,
L1RPCKind
:
sources
.
RPCKindBasic
,
...
...
@@ -139,10 +123,6 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) {
if
l2Head
==
(
common
.
Hash
{})
{
return
nil
,
ErrInvalidL2Head
}
l2OutputRoot
:=
common
.
HexToHash
(
ctx
.
String
(
flags
.
L2OutputRoot
.
Name
))
if
l2OutputRoot
==
(
common
.
Hash
{})
{
return
nil
,
ErrInvalidL2OutputRoot
}
l2Claim
:=
common
.
HexToHash
(
ctx
.
String
(
flags
.
L2Claim
.
Name
))
if
l2Claim
==
(
common
.
Hash
{})
{
return
nil
,
ErrInvalidL2Claim
...
...
@@ -172,7 +152,6 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) {
L2URL
:
ctx
.
String
(
flags
.
L2NodeAddr
.
Name
),
L2ChainConfig
:
l2ChainConfig
,
L2Head
:
l2Head
,
L2OutputRoot
:
l2OutputRoot
,
L2Claim
:
l2Claim
,
L2ClaimBlockNumber
:
l2ClaimBlockNum
,
L1Head
:
l1Head
,
...
...
op-program/host/config/config_test.go
View file @
40e952d8
...
...
@@ -16,7 +16,6 @@ var (
validL1Head
=
common
.
Hash
{
0xaa
}
validL2Head
=
common
.
Hash
{
0xbb
}
validL2Claim
=
common
.
Hash
{
0xcc
}
validL2OutputRoot
=
common
.
Hash
{
0xdd
}
validL2ClaimBlockNum
=
uint64
(
15
)
)
...
...
@@ -56,13 +55,6 @@ func TestL2HeadRequired(t *testing.T) {
require
.
ErrorIs
(
t
,
err
,
ErrInvalidL2Head
)
}
func
TestL2OutputRootRequired
(
t
*
testing
.
T
)
{
config
:=
validConfig
()
config
.
L2OutputRoot
=
common
.
Hash
{}
err
:=
config
.
Check
()
require
.
ErrorIs
(
t
,
err
,
ErrInvalidL2OutputRoot
)
}
func
TestL2ClaimRequired
(
t
*
testing
.
T
)
{
config
:=
validConfig
()
config
.
L2Claim
=
common
.
Hash
{}
...
...
@@ -159,7 +151,7 @@ func TestRejectExecAndServerMode(t *testing.T) {
}
func
validConfig
()
*
Config
{
cfg
:=
NewConfig
(
validRollupConfig
,
validL2Genesis
,
validL1Head
,
validL2Head
,
validL2
OutputRoot
,
validL2
Claim
,
validL2ClaimBlockNum
)
cfg
:=
NewConfig
(
validRollupConfig
,
validL2Genesis
,
validL1Head
,
validL2Head
,
validL2Claim
,
validL2ClaimBlockNum
)
cfg
.
DataDir
=
"/tmp/configTest"
return
cfg
}
op-program/host/flags/flags.go
View file @
40e952d8
...
...
@@ -47,14 +47,9 @@ var (
}
L2Head
=
&
cli
.
StringFlag
{
Name
:
"l2.head"
,
Usage
:
"Hash of the
L2 block at l2.outputroot
"
,
Usage
:
"Hash of the
agreed L2 block to start derivation from
"
,
EnvVars
:
prefixEnvVars
(
"L2_HEAD"
),
}
L2OutputRoot
=
&
cli
.
StringFlag
{
Name
:
"l2.outputroot"
,
Usage
:
"Agreed L2 Output Root to start derivation from"
,
EnvVars
:
prefixEnvVars
(
"L2_OUTPUT_ROOT"
),
}
L2Claim
=
&
cli
.
StringFlag
{
Name
:
"l2.claim"
,
Usage
:
"Claimed L2 output root to validate"
,
...
...
@@ -108,7 +103,6 @@ var Flags []cli.Flag
var
requiredFlags
=
[]
cli
.
Flag
{
L1Head
,
L2Head
,
L2OutputRoot
,
L2Claim
,
L2BlockNumber
,
}
...
...
op-program/host/host.go
View file @
40e952d8
...
...
@@ -26,7 +26,7 @@ import (
)
type
L2Source
struct
{
*
L2Client
*
sources
.
L2Client
*
sources
.
DebugClient
}
...
...
@@ -205,7 +205,7 @@ func makePrefetcher(ctx context.Context, logger log.Logger, kv kvstore.KV, cfg *
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to create L1 client: %w"
,
err
)
}
l2Cl
,
err
:=
NewL2Client
(
l2RPC
,
logger
,
nil
,
&
L2ClientConfig
{
L2ClientConfig
:
l2ClCfg
,
L2Head
:
cfg
.
L2Head
}
)
l2Cl
,
err
:=
sources
.
NewL2Client
(
l2RPC
,
logger
,
nil
,
l2ClCfg
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to create L2 client: %w"
,
err
)
}
...
...
op-program/host/host_test.go
View file @
40e952d8
...
...
@@ -23,8 +23,7 @@ func TestServerMode(t *testing.T) {
dir
:=
t
.
TempDir
()
l1Head
:=
common
.
Hash
{
0x11
}
l2OutputRoot
:=
common
.
Hash
{
0x33
}
cfg
:=
config
.
NewConfig
(
&
chaincfg
.
Goerli
,
config
.
OPGoerliChainConfig
,
l1Head
,
common
.
Hash
{
0x22
},
l2OutputRoot
,
common
.
Hash
{
0x44
},
1000
)
cfg
:=
config
.
NewConfig
(
&
chaincfg
.
Goerli
,
config
.
OPGoerliChainConfig
,
l1Head
,
common
.
Hash
{
0x22
},
common
.
Hash
{
0x33
},
1000
)
cfg
.
DataDir
=
dir
cfg
.
ServerMode
=
true
...
...
@@ -44,8 +43,7 @@ func TestServerMode(t *testing.T) {
hClient
:=
preimage
.
NewHintWriter
(
hintClient
)
l1PreimageOracle
:=
l1
.
NewPreimageOracle
(
pClient
,
hClient
)
require
.
Equal
(
t
,
l1Head
.
Bytes
(),
pClient
.
Get
(
client
.
L1HeadLocalIndex
),
"Should get l1 head preimages"
)
require
.
Equal
(
t
,
l2OutputRoot
.
Bytes
(),
pClient
.
Get
(
client
.
L2OutputRootLocalIndex
),
"Should get l2 output root preimages"
)
require
.
Equal
(
t
,
l1Head
.
Bytes
(),
pClient
.
Get
(
client
.
L1HeadLocalIndex
),
"Should get preimages"
)
// Should exit when a preimage is unavailable
require
.
Panics
(
t
,
func
()
{
...
...
op-program/host/kvstore/local.go
View file @
40e952d8
...
...
@@ -19,7 +19,7 @@ func NewLocalPreimageSource(config *config.Config) *LocalPreimageSource {
var
(
l1HeadKey
=
client
.
L1HeadLocalIndex
.
PreimageKey
()
l2
OutputRootKey
=
client
.
L2OutputRoot
LocalIndex
.
PreimageKey
()
l2
HeadKey
=
client
.
L2Head
LocalIndex
.
PreimageKey
()
l2ClaimKey
=
client
.
L2ClaimLocalIndex
.
PreimageKey
()
l2ClaimBlockNumberKey
=
client
.
L2ClaimBlockNumberLocalIndex
.
PreimageKey
()
l2ChainConfigKey
=
client
.
L2ChainConfigLocalIndex
.
PreimageKey
()
...
...
@@ -30,8 +30,8 @@ func (s *LocalPreimageSource) Get(key common.Hash) ([]byte, error) {
switch
[
32
]
byte
(
key
)
{
case
l1HeadKey
:
return
s
.
config
.
L1Head
.
Bytes
(),
nil
case
l2
OutputRoot
Key
:
return
s
.
config
.
L2
OutputRoot
.
Bytes
(),
nil
case
l2
Head
Key
:
return
s
.
config
.
L2
Head
.
Bytes
(),
nil
case
l2ClaimKey
:
return
s
.
config
.
L2Claim
.
Bytes
(),
nil
case
l2ClaimBlockNumberKey
:
...
...
op-program/host/kvstore/local_test.go
View file @
40e952d8
...
...
@@ -17,7 +17,7 @@ func TestLocalPreimageSource(t *testing.T) {
cfg
:=
&
config
.
Config
{
Rollup
:
&
chaincfg
.
Goerli
,
L1Head
:
common
.
HexToHash
(
"0x1111"
),
L2
OutputRoot
:
common
.
HexToHash
(
"0x2222"
),
L2
Head
:
common
.
HexToHash
(
"0x2222"
),
L2Claim
:
common
.
HexToHash
(
"0x3333"
),
L2ClaimBlockNumber
:
1234
,
L2ChainConfig
:
params
.
GoerliChainConfig
,
...
...
@@ -29,7 +29,7 @@ func TestLocalPreimageSource(t *testing.T) {
expected
[]
byte
}{
{
"L1Head"
,
l1HeadKey
,
cfg
.
L1Head
.
Bytes
()},
{
"L2
OutputRoot"
,
l2OutputRootKey
,
cfg
.
L2OutputRoot
.
Bytes
()},
{
"L2
Head"
,
l2HeadKey
,
cfg
.
L2Head
.
Bytes
()},
{
"L2Claim"
,
l2ClaimKey
,
cfg
.
L2Claim
.
Bytes
()},
{
"L2ClaimBlockNumber"
,
l2ClaimBlockNumberKey
,
binary
.
BigEndian
.
AppendUint64
(
nil
,
cfg
.
L2ClaimBlockNumber
)},
{
"Rollup"
,
rollupKey
,
asJson
(
t
,
cfg
.
Rollup
)},
...
...
op-program/host/l2_client.go
deleted
100644 → 0
View file @
f30fdd3f
package
host
import
(
"context"
"fmt"
"github.com/ethereum-optimism/optimism/op-node/client"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/sources"
"github.com/ethereum-optimism/optimism/op-node/sources/caching"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
)
type
L2Client
struct
{
*
sources
.
L2Client
// l2Head is the L2 block hash that we use to fetch L2 output
l2Head
common
.
Hash
}
type
L2ClientConfig
struct
{
*
sources
.
L2ClientConfig
L2Head
common
.
Hash
}
func
NewL2Client
(
client
client
.
RPC
,
log
log
.
Logger
,
metrics
caching
.
Metrics
,
config
*
L2ClientConfig
)
(
*
L2Client
,
error
)
{
l2Client
,
err
:=
sources
.
NewL2Client
(
client
,
log
,
metrics
,
config
.
L2ClientConfig
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
L2Client
{
L2Client
:
l2Client
,
l2Head
:
config
.
L2Head
,
},
nil
}
func
(
s
*
L2Client
)
OutputByRoot
(
ctx
context
.
Context
,
l2OutputRoot
common
.
Hash
)
(
eth
.
Output
,
error
)
{
output
,
err
:=
s
.
OutputV0AtBlock
(
ctx
,
s
.
l2Head
)
if
err
!=
nil
{
return
nil
,
err
}
if
eth
.
OutputRoot
(
output
)
!=
eth
.
Bytes32
(
l2OutputRoot
)
{
// For fault proofs, we only reference outputs at the l2 head at boot time
// The caller shouldn't be requesting outputs at any other block
return
nil
,
fmt
.
Errorf
(
"unknown output root"
)
}
return
output
,
nil
}
op-program/host/prefetcher/prefetcher.go
View file @
40e952d8
...
...
@@ -29,7 +29,6 @@ type L2Source interface {
InfoAndTxsByHash
(
ctx
context
.
Context
,
blockHash
common
.
Hash
)
(
eth
.
BlockInfo
,
types
.
Transactions
,
error
)
NodeByHash
(
ctx
context
.
Context
,
hash
common
.
Hash
)
([]
byte
,
error
)
CodeByHash
(
ctx
context
.
Context
,
hash
common
.
Hash
)
([]
byte
,
error
)
OutputByRoot
(
ctx
context
.
Context
,
root
common
.
Hash
)
(
eth
.
Output
,
error
)
}
type
Prefetcher
struct
{
...
...
@@ -125,12 +124,6 @@ func (p *Prefetcher) prefetch(ctx context.Context, hint string) error {
return
fmt
.
Errorf
(
"failed to fetch L2 contract code %s: %w"
,
hash
,
err
)
}
return
p
.
kvStore
.
Put
(
preimage
.
Keccak256Key
(
hash
)
.
PreimageKey
(),
code
)
case
l2
.
HintL2Output
:
output
,
err
:=
p
.
l2Fetcher
.
OutputByRoot
(
ctx
,
hash
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to fetch L2 output root %s: %w"
,
hash
,
err
)
}
return
p
.
kvStore
.
Put
(
preimage
.
Keccak256Key
(
hash
)
.
PreimageKey
(),
output
.
Marshal
())
}
return
fmt
.
Errorf
(
"unknown hint type: %v"
,
hintType
)
}
...
...
op-program/host/prefetcher/prefetcher_test.go
View file @
40e952d8
...
...
@@ -286,15 +286,6 @@ type l2Client struct {
*
testutils
.
MockDebugClient
}
func
(
m
*
l2Client
)
OutputByRoot
(
ctx
context
.
Context
,
root
common
.
Hash
)
(
eth
.
Output
,
error
)
{
out
:=
m
.
Mock
.
MethodCalled
(
"OutputByRoot"
,
root
)
return
out
[
0
]
.
(
eth
.
Output
),
*
out
[
1
]
.
(
*
error
)
}
func
(
m
*
l2Client
)
ExpectOutputByRoot
(
root
common
.
Hash
,
output
eth
.
Output
,
err
error
)
{
m
.
Mock
.
On
(
"OutputByRoot"
,
root
)
.
Once
()
.
Return
(
output
,
&
err
)
}
func
createPrefetcher
(
t
*
testing
.
T
)
(
*
Prefetcher
,
*
testutils
.
MockL1Source
,
*
l2Client
,
kvstore
.
KV
)
{
logger
:=
testlog
.
Logger
(
t
,
log
.
LvlDebug
)
kv
:=
kvstore
.
NewMemKV
()
...
...
op-program/host/prefetcher/retry.go
View file @
40e952d8
...
...
@@ -125,20 +125,6 @@ func (s *RetryingL2Source) CodeByHash(ctx context.Context, hash common.Hash) ([]
return
code
,
err
}
func
(
s
*
RetryingL2Source
)
OutputByRoot
(
ctx
context
.
Context
,
root
common
.
Hash
)
(
eth
.
Output
,
error
)
{
var
output
eth
.
Output
err
:=
backoff
.
DoCtx
(
ctx
,
maxAttempts
,
s
.
strategy
,
func
()
error
{
o
,
err
:=
s
.
source
.
OutputByRoot
(
ctx
,
root
)
if
err
!=
nil
{
s
.
logger
.
Warn
(
"Failed to fetch l2 output"
,
"root"
,
root
,
"err"
,
err
)
return
err
}
output
=
o
return
nil
})
return
output
,
err
}
func
NewRetryingL2Source
(
logger
log
.
Logger
,
source
L2Source
)
*
RetryingL2Source
{
return
&
RetryingL2Source
{
logger
:
logger
,
...
...
op-program/host/prefetcher/retry_test.go
View file @
40e952d8
...
...
@@ -119,8 +119,6 @@ func TestRetryingL2Source(t *testing.T) {
&
types
.
Transaction
{},
}
data
:=
[]
byte
{
1
,
2
,
3
,
4
,
5
}
output
:=
&
eth
.
OutputV0
{}
wrongOutput
:=
&
eth
.
OutputV0
{
BlockHash
:
common
.
Hash
{
0x99
}}
t
.
Run
(
"InfoAndTxsByHash Success"
,
func
(
t
*
testing
.
T
)
{
source
,
mock
:=
createL2Source
(
t
)
...
...
@@ -189,28 +187,6 @@ func TestRetryingL2Source(t *testing.T) {
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
data
,
actual
)
})
t
.
Run
(
"OutputByRoot Success"
,
func
(
t
*
testing
.
T
)
{
source
,
mock
:=
createL2Source
(
t
)
defer
mock
.
AssertExpectations
(
t
)
mock
.
ExpectOutputByRoot
(
hash
,
output
,
nil
)
actualOutput
,
err
:=
source
.
OutputByRoot
(
ctx
,
hash
)
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
output
,
actualOutput
)
})
t
.
Run
(
"OutputByRoot Error"
,
func
(
t
*
testing
.
T
)
{
source
,
mock
:=
createL2Source
(
t
)
defer
mock
.
AssertExpectations
(
t
)
expectedErr
:=
errors
.
New
(
"boom"
)
mock
.
ExpectOutputByRoot
(
hash
,
wrongOutput
,
expectedErr
)
mock
.
ExpectOutputByRoot
(
hash
,
output
,
nil
)
actualOutput
,
err
:=
source
.
OutputByRoot
(
ctx
,
hash
)
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
output
,
actualOutput
)
})
}
func
createL2Source
(
t
*
testing
.
T
)
(
*
RetryingL2Source
,
*
MockL2Source
)
{
...
...
@@ -241,11 +217,6 @@ func (m *MockL2Source) CodeByHash(ctx context.Context, hash common.Hash) ([]byte
return
out
[
0
]
.
([]
byte
),
*
out
[
1
]
.
(
*
error
)
}
func
(
m
*
MockL2Source
)
OutputByRoot
(
ctx
context
.
Context
,
root
common
.
Hash
)
(
eth
.
Output
,
error
)
{
out
:=
m
.
Mock
.
MethodCalled
(
"OutputByRoot"
,
root
)
return
out
[
0
]
.
(
eth
.
Output
),
*
out
[
1
]
.
(
*
error
)
}
func
(
m
*
MockL2Source
)
ExpectInfoAndTxsByHash
(
blockHash
common
.
Hash
,
info
eth
.
BlockInfo
,
txs
types
.
Transactions
,
err
error
)
{
m
.
Mock
.
On
(
"InfoAndTxsByHash"
,
blockHash
)
.
Once
()
.
Return
(
info
,
txs
,
&
err
)
}
...
...
@@ -258,8 +229,4 @@ func (m *MockL2Source) ExpectCodeByHash(hash common.Hash, code []byte, err error
m
.
Mock
.
On
(
"CodeByHash"
,
hash
)
.
Once
()
.
Return
(
code
,
&
err
)
}
func
(
m
*
MockL2Source
)
ExpectOutputByRoot
(
root
common
.
Hash
,
output
eth
.
Output
,
err
error
)
{
m
.
Mock
.
On
(
"OutputByRoot"
,
root
)
.
Once
()
.
Return
(
output
,
&
err
)
}
var
_
L2Source
=
(
*
MockL2Source
)(
nil
)
op-program/verify/cmd/goerli.go
View file @
40e952d8
...
...
@@ -100,31 +100,7 @@ func Run(l1RpcUrl string, l2RpcUrl string, l2OracleAddr common.Address) error {
if
err
!=
nil
{
return
fmt
.
Errorf
(
"retrieve agreed l2 block: %w"
,
err
)
}
agreedOutputIndex
,
err
:=
outputOracle
.
GetL2OutputIndexAfter
(
callOpts
,
l2AgreedBlock
.
Number
())
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to output index after agreed block"
)
}
// Find an output that differs from what is being claimed
var
agreedOutput
bindings
.
TypesOutputProposal
for
{
agreedOutput
,
err
=
outputOracle
.
GetL2Output
(
callOpts
,
agreedOutputIndex
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"retrieve agreed output: %w"
,
err
)
}
if
agreedOutput
.
OutputRoot
!=
output
.
OutputRoot
{
break
}
fmt
.
Printf
(
"Output at %v equals output at finalized block. Continuing search...
\n
"
,
agreedOutput
.
L2BlockNumber
)
agreedOutputIndex
.
Sub
(
agreedOutputIndex
,
big
.
NewInt
(
1
))
if
agreedOutputIndex
.
Int64
()
<
0
{
return
fmt
.
Errorf
(
"failed to find an output different from finalized block output"
)
}
}
l2BlockAtOutput
,
err
:=
l2Client
.
BlockByNumber
(
ctx
,
agreedOutput
.
L2BlockNumber
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"retrieve agreed block: %w"
,
err
)
}
l2Head
:=
l2BlockAtOutput
.
Hash
()
l2Head
:=
l2AgreedBlock
.
Hash
()
temp
,
err
:=
os
.
MkdirTemp
(
""
,
"oracledata"
)
if
err
!=
nil
{
...
...
@@ -144,7 +120,6 @@ func Run(l1RpcUrl string, l2RpcUrl string, l2OracleAddr common.Address) error {
"--datadir"
,
temp
,
"--l1.head"
,
l1Head
.
Hex
(),
"--l2.head"
,
l2Head
.
Hex
(),
"--l2.outputroot"
,
common
.
Bytes2Hex
(
agreedOutput
.
OutputRoot
[
:
]),
"--l2.claim"
,
l2Claim
.
Hex
(),
"--l2.blocknumber"
,
l2BlockNumber
.
String
(),
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment