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
549474c2
Unverified
Commit
549474c2
authored
Jul 30, 2023
by
mergify[bot]
Committed by
GitHub
Jul 30, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into aj/enable-peer-scoring
parents
c027a662
e86703dd
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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
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 @
c027a662
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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
c027a662
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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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 @
549474c2
...
...
@@ -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