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
884ebe69
Unverified
Commit
884ebe69
authored
Apr 03, 2023
by
mergify[bot]
Committed by
GitHub
Apr 03, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #5309 from ethereum-optimism/aj/fpp-l2-fetcher
op-program: Add minimal L2 fetcher
parents
b9f8f3ce
60d9e4f6
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
261 additions
and
2 deletions
+261
-2
main.go
op-program/cmd/main.go
+13
-2
main_test.go
op-program/cmd/main_test.go
+13
-0
config.go
op-program/config/config.go
+6
-0
config_test.go
op-program/config/config_test.go
+13
-0
flags.go
op-program/flags/flags.go
+6
-0
fetcher.go
op-program/l2/fetcher.go
+57
-0
fetcher_test.go
op-program/l2/fetcher_test.go
+153
-0
No files found.
op-program/cmd/main.go
View file @
884ebe69
package
main
package
main
import
(
import
(
"errors"
"fmt"
"fmt"
"os"
"os"
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-program/config"
"github.com/ethereum-optimism/optimism/op-program/config"
"github.com/ethereum-optimism/optimism/op-program/flags"
"github.com/ethereum-optimism/optimism/op-program/flags"
"github.com/ethereum-optimism/optimism/op-program/l2"
"github.com/ethereum-optimism/optimism/op-program/version"
"github.com/ethereum-optimism/optimism/op-program/version"
oplog
"github.com/ethereum-optimism/optimism/op-service/log"
oplog
"github.com/ethereum-optimism/optimism/op-service/log"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
...
@@ -84,7 +86,16 @@ func setupLogging(ctx *cli.Context) (log.Logger, error) {
...
@@ -84,7 +86,16 @@ func setupLogging(ctx *cli.Context) (log.Logger, error) {
}
}
// FaultProofProgram is the programmatic entry-point for the fault proof program
// FaultProofProgram is the programmatic entry-point for the fault proof program
func
FaultProofProgram
(
log
log
.
Logger
,
cfg
*
config
.
Config
)
error
{
func
FaultProofProgram
(
logger
log
.
Logger
,
cfg
*
config
.
Config
)
error
{
cfg
.
Rollup
.
LogDescription
(
log
,
chaincfg
.
L2ChainIDToNetworkName
)
cfg
.
Rollup
.
LogDescription
(
logger
,
chaincfg
.
L2ChainIDToNetworkName
)
if
!
cfg
.
FetchingEnabled
()
{
return
errors
.
New
(
"offline mode not supported"
)
}
logger
.
Info
(
"Connecting to L2 node"
,
"l2"
,
cfg
.
L2URL
)
_
,
err
:=
l2
.
NewFetchingL2Oracle
(
logger
,
cfg
.
L2URL
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"connect l2 oracle: %w"
,
err
)
}
return
nil
return
nil
}
}
op-program/cmd/main_test.go
View file @
884ebe69
...
@@ -66,6 +66,19 @@ func TestNetwork(t *testing.T) {
...
@@ -66,6 +66,19 @@ func TestNetwork(t *testing.T) {
}
}
}
}
func
TestL2
(
t
*
testing
.
T
)
{
expected
:=
"https://example.com:8545"
cfg
:=
configForArgs
(
t
,
addRequiredArgs
(
"--l2"
,
expected
))
require
.
Equal
(
t
,
expected
,
cfg
.
L2URL
)
}
// Offline support will be added later, but for now it just bails out with an error
func
TestOfflineModeNotSupported
(
t
*
testing
.
T
)
{
logger
:=
log
.
New
()
err
:=
FaultProofProgram
(
logger
,
config
.
NewConfig
(
&
chaincfg
.
Goerli
))
require
.
ErrorContains
(
t
,
err
,
"offline mode not supported"
)
}
func
verifyArgsInvalid
(
t
*
testing
.
T
,
messageContains
string
,
cliArgs
[]
string
)
{
func
verifyArgsInvalid
(
t
*
testing
.
T
,
messageContains
string
,
cliArgs
[]
string
)
{
_
,
_
,
err
:=
runWithArgs
(
cliArgs
)
_
,
_
,
err
:=
runWithArgs
(
cliArgs
)
require
.
ErrorContains
(
t
,
err
,
messageContains
)
require
.
ErrorContains
(
t
,
err
,
messageContains
)
...
...
op-program/config/config.go
View file @
884ebe69
...
@@ -15,6 +15,7 @@ var (
...
@@ -15,6 +15,7 @@ var (
type
Config
struct
{
type
Config
struct
{
Rollup
*
rollup
.
Config
Rollup
*
rollup
.
Config
L2URL
string
}
}
func
(
c
*
Config
)
Check
()
error
{
func
(
c
*
Config
)
Check
()
error
{
...
@@ -27,6 +28,10 @@ func (c *Config) Check() error {
...
@@ -27,6 +28,10 @@ func (c *Config) Check() error {
return
nil
return
nil
}
}
func
(
c
*
Config
)
FetchingEnabled
()
bool
{
return
c
.
L2URL
!=
""
}
// NewConfig creates a Config with all optional values set to the CLI default value
// NewConfig creates a Config with all optional values set to the CLI default value
func
NewConfig
(
rollupCfg
*
rollup
.
Config
)
*
Config
{
func
NewConfig
(
rollupCfg
*
rollup
.
Config
)
*
Config
{
return
&
Config
{
return
&
Config
{
...
@@ -44,5 +49,6 @@ func NewConfigFromCLI(ctx *cli.Context) (*Config, error) {
...
@@ -44,5 +49,6 @@ func NewConfigFromCLI(ctx *cli.Context) (*Config, error) {
}
}
return
&
Config
{
return
&
Config
{
Rollup
:
rollupCfg
,
Rollup
:
rollupCfg
,
L2URL
:
ctx
.
GlobalString
(
flags
.
L2NodeAddr
.
Name
),
},
nil
},
nil
}
}
op-program/config/config_test.go
View file @
884ebe69
...
@@ -24,3 +24,16 @@ func TestRollupConfig(t *testing.T) {
...
@@ -24,3 +24,16 @@ func TestRollupConfig(t *testing.T) {
require
.
ErrorIs
(
t
,
err
,
rollup
.
ErrBlockTimeZero
)
require
.
ErrorIs
(
t
,
err
,
rollup
.
ErrBlockTimeZero
)
})
})
}
}
func
TestFetchingEnabled
(
t
*
testing
.
T
)
{
t
.
Run
(
"FetchingNotEnabledWhenNoFetcherUrlsSpecified"
,
func
(
t
*
testing
.
T
)
{
cfg
:=
NewConfig
(
&
chaincfg
.
Beta1
)
require
.
False
(
t
,
cfg
.
FetchingEnabled
(),
"Should not enable fetching when node URL not supplied"
)
})
t
.
Run
(
"FetchingEnabledWhenFetcherUrlsSpecified"
,
func
(
t
*
testing
.
T
)
{
cfg
:=
NewConfig
(
&
chaincfg
.
Beta1
)
cfg
.
L2URL
=
"https://example.com:1234"
require
.
True
(
t
,
cfg
.
FetchingEnabled
(),
"Should enable fetching when node URL supplied"
)
})
}
op-program/flags/flags.go
View file @
884ebe69
...
@@ -23,6 +23,11 @@ var (
...
@@ -23,6 +23,11 @@ var (
Usage
:
fmt
.
Sprintf
(
"Predefined network selection. Available networks: %s"
,
strings
.
Join
(
chaincfg
.
AvailableNetworks
(),
", "
)),
Usage
:
fmt
.
Sprintf
(
"Predefined network selection. Available networks: %s"
,
strings
.
Join
(
chaincfg
.
AvailableNetworks
(),
", "
)),
EnvVar
:
service
.
PrefixEnvVar
(
envVarPrefix
,
"NETWORK"
),
EnvVar
:
service
.
PrefixEnvVar
(
envVarPrefix
,
"NETWORK"
),
}
}
L2NodeAddr
=
cli
.
StringFlag
{
Name
:
"l2"
,
Usage
:
"Address of L2 JSON-RPC endpoint to use (eth and debug namespace required)"
,
EnvVar
:
service
.
PrefixEnvVar
(
envVarPrefix
,
"L2_RPC"
),
}
)
)
// Flags contains the list of configuration options available to the binary.
// Flags contains the list of configuration options available to the binary.
...
@@ -31,6 +36,7 @@ var Flags []cli.Flag
...
@@ -31,6 +36,7 @@ var Flags []cli.Flag
var
programFlags
=
[]
cli
.
Flag
{
var
programFlags
=
[]
cli
.
Flag
{
RollupConfig
,
RollupConfig
,
Network
,
Network
,
L2NodeAddr
,
}
}
func
init
()
{
func
init
()
{
...
...
op-program/l2/fetcher.go
0 → 100644
View file @
884ebe69
package
l2
import
(
"context"
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
)
type
BlockSource
interface
{
BlockByHash
(
ctx
context
.
Context
,
blockHash
common
.
Hash
)
(
*
types
.
Block
,
error
)
}
type
CallContext
interface
{
CallContext
(
ctx
context
.
Context
,
result
interface
{},
method
string
,
args
...
interface
{})
error
}
type
FetchingL2Oracle
struct
{
logger
log
.
Logger
blockSource
BlockSource
callContext
CallContext
}
func
NewFetchingL2Oracle
(
logger
log
.
Logger
,
l2Url
string
)
(
*
FetchingL2Oracle
,
error
)
{
rpcClient
,
err
:=
rpc
.
Dial
(
l2Url
)
if
err
!=
nil
{
return
nil
,
err
}
ethClient
:=
ethclient
.
NewClient
(
rpcClient
)
return
&
FetchingL2Oracle
{
logger
:
logger
,
blockSource
:
ethClient
,
callContext
:
rpcClient
,
},
nil
}
func
(
s
FetchingL2Oracle
)
NodeByHash
(
ctx
context
.
Context
,
nodeHash
common
.
Hash
)
([]
byte
,
error
)
{
var
node
hexutil
.
Bytes
err
:=
s
.
callContext
.
CallContext
(
ctx
,
&
node
,
"debug_dbGet"
,
nodeHash
.
Hex
())
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"fetch node %s: %w"
,
nodeHash
.
Hex
(),
err
)
}
return
node
,
nil
}
func
(
s
FetchingL2Oracle
)
BlockByHash
(
ctx
context
.
Context
,
blockHash
common
.
Hash
)
(
*
types
.
Block
,
error
)
{
block
,
err
:=
s
.
blockSource
.
BlockByHash
(
ctx
,
blockHash
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"fetch block %s: %w"
,
blockHash
.
Hex
(),
err
)
}
return
block
,
nil
}
op-program/l2/fetcher_test.go
0 → 100644
View file @
884ebe69
package
l2
import
(
"context"
"encoding/json"
"errors"
"fmt"
"math/rand"
"reflect"
"testing"
"github.com/ethereum-optimism/optimism/op-node/testutils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
)
type
callContextRequest
struct
{
ctx
context
.
Context
method
string
args
[]
interface
{}
}
type
stubCallContext
struct
{
nextResult
any
nextErr
error
requests
[]
callContextRequest
}
func
(
c
*
stubCallContext
)
CallContext
(
ctx
context
.
Context
,
result
any
,
method
string
,
args
...
interface
{})
error
{
if
result
!=
nil
&&
reflect
.
TypeOf
(
result
)
.
Kind
()
!=
reflect
.
Ptr
{
return
fmt
.
Errorf
(
"call result parameter must be pointer or nil interface: %v"
,
result
)
}
c
.
requests
=
append
(
c
.
requests
,
callContextRequest
{
ctx
:
ctx
,
method
:
method
,
args
:
args
})
if
c
.
nextErr
!=
nil
{
return
c
.
nextErr
}
res
,
err
:=
json
.
Marshal
(
c
.
nextResult
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"json marshal: %w"
,
err
)
}
err
=
json
.
Unmarshal
(
res
,
result
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"json unmarshal: %w"
,
err
)
}
return
nil
}
func
TestNodeByHash
(
t
*
testing
.
T
)
{
rng
:=
rand
.
New
(
rand
.
NewSource
(
1234
))
hash
:=
testutils
.
RandomHash
(
rng
)
ctx
:=
context
.
Background
()
t
.
Run
(
"Error"
,
func
(
t
*
testing
.
T
)
{
stub
:=
&
stubCallContext
{
nextErr
:
errors
.
New
(
"oops"
),
}
fetcher
:=
newFetcher
(
nil
,
stub
)
node
,
err
:=
fetcher
.
NodeByHash
(
ctx
,
hash
)
require
.
ErrorIs
(
t
,
err
,
stub
.
nextErr
)
require
.
Nil
(
t
,
node
)
})
t
.
Run
(
"Success"
,
func
(
t
*
testing
.
T
)
{
expected
:=
(
hexutil
.
Bytes
)([]
byte
{
12
,
34
})
stub
:=
&
stubCallContext
{
nextResult
:
expected
,
}
fetcher
:=
newFetcher
(
nil
,
stub
)
node
,
err
:=
fetcher
.
NodeByHash
(
ctx
,
hash
)
require
.
NoError
(
t
,
err
)
require
.
EqualValues
(
t
,
expected
,
node
)
})
t
.
Run
(
"RequestArgs"
,
func
(
t
*
testing
.
T
)
{
stub
:=
&
stubCallContext
{
nextResult
:
(
hexutil
.
Bytes
)([]
byte
{
12
,
34
}),
}
fetcher
:=
newFetcher
(
nil
,
stub
)
_
,
_
=
fetcher
.
NodeByHash
(
ctx
,
hash
)
require
.
Len
(
t
,
stub
.
requests
,
1
,
"should make single request"
)
req
:=
stub
.
requests
[
0
]
require
.
Equal
(
t
,
"debug_dbGet"
,
req
.
method
)
require
.
Equal
(
t
,
[]
interface
{}{
hash
.
Hex
()},
req
.
args
)
})
}
type
blockRequest
struct
{
ctx
context
.
Context
blockHash
common
.
Hash
}
type
stubBlockSource
struct
{
requests
[]
blockRequest
nextErr
error
nextResult
*
types
.
Block
}
func
(
s
*
stubBlockSource
)
BlockByHash
(
ctx
context
.
Context
,
blockHash
common
.
Hash
)
(
*
types
.
Block
,
error
)
{
s
.
requests
=
append
(
s
.
requests
,
blockRequest
{
ctx
:
ctx
,
blockHash
:
blockHash
,
})
return
s
.
nextResult
,
s
.
nextErr
}
func
TestBlockByHash
(
t
*
testing
.
T
)
{
rng
:=
rand
.
New
(
rand
.
NewSource
(
1234
))
hash
:=
testutils
.
RandomHash
(
rng
)
ctx
:=
context
.
Background
()
t
.
Run
(
"Success"
,
func
(
t
*
testing
.
T
)
{
block
,
_
:=
testutils
.
RandomBlock
(
rng
,
1
)
stub
:=
&
stubBlockSource
{
nextResult
:
block
}
fetcher
:=
newFetcher
(
stub
,
nil
)
res
,
err
:=
fetcher
.
BlockByHash
(
ctx
,
hash
)
require
.
NoError
(
t
,
err
)
require
.
Same
(
t
,
block
,
res
)
})
t
.
Run
(
"Error"
,
func
(
t
*
testing
.
T
)
{
stub
:=
&
stubBlockSource
{
nextErr
:
errors
.
New
(
"boom"
)}
fetcher
:=
newFetcher
(
stub
,
nil
)
res
,
err
:=
fetcher
.
BlockByHash
(
ctx
,
hash
)
require
.
ErrorIs
(
t
,
err
,
stub
.
nextErr
)
require
.
Nil
(
t
,
res
)
})
t
.
Run
(
"RequestArgs"
,
func
(
t
*
testing
.
T
)
{
stub
:=
&
stubBlockSource
{}
fetcher
:=
newFetcher
(
stub
,
nil
)
_
,
_
=
fetcher
.
BlockByHash
(
ctx
,
hash
)
require
.
Len
(
t
,
stub
.
requests
,
1
,
"should make single request"
)
req
:=
stub
.
requests
[
0
]
require
.
Equal
(
t
,
hash
,
req
.
blockHash
)
})
}
func
newFetcher
(
blockSource
BlockSource
,
callContext
CallContext
)
*
FetchingL2Oracle
{
return
&
FetchingL2Oracle
{
logger
:
log
.
New
(),
blockSource
:
blockSource
,
callContext
:
callContext
,
}
}
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