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
7742c972
Unverified
Commit
7742c972
authored
Apr 12, 2023
by
Adrian Sutton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
op-program: Make L2 fetcher panic if it retrieves a block above the agreed L2 head
parent
8273a4c8
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
92 additions
and
52 deletions
+92
-52
fetcher.go
op-program/host/l2/fetcher.go
+11
-1
fetcher_test.go
op-program/host/l2/fetcher_test.go
+80
-50
l2.go
op-program/host/l2/l2.go
+1
-1
No files found.
op-program/host/l2/fetcher.go
View file @
7742c972
...
...
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/rawdb"
...
...
@@ -24,19 +25,25 @@ type CallContext interface {
type
FetchingL2Oracle
struct
{
ctx
context
.
Context
logger
log
.
Logger
head
eth
.
BlockInfo
blockSource
BlockSource
callContext
CallContext
}
func
NewFetchingL2Oracle
(
ctx
context
.
Context
,
logger
log
.
Logger
,
l2Url
string
)
(
*
FetchingL2Oracle
,
error
)
{
func
NewFetchingL2Oracle
(
ctx
context
.
Context
,
logger
log
.
Logger
,
l2Url
string
,
l2Head
common
.
Hash
)
(
*
FetchingL2Oracle
,
error
)
{
rpcClient
,
err
:=
rpc
.
Dial
(
l2Url
)
if
err
!=
nil
{
return
nil
,
err
}
ethClient
:=
ethclient
.
NewClient
(
rpcClient
)
head
,
err
:=
ethClient
.
HeaderByHash
(
ctx
,
l2Head
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"retrieve l2 head %v: %w"
,
l2Head
,
err
)
}
return
&
FetchingL2Oracle
{
ctx
:
ctx
,
logger
:
logger
,
head
:
eth
.
HeaderBlockInfo
(
head
),
blockSource
:
ethClient
,
callContext
:
rpcClient
,
},
nil
...
...
@@ -78,5 +85,8 @@ func (o *FetchingL2Oracle) BlockByHash(blockHash common.Hash) *types.Block {
if
err
!=
nil
{
panic
(
fmt
.
Errorf
(
"fetch block %s: %w"
,
blockHash
.
Hex
(),
err
))
}
if
block
.
NumberU64
()
>
o
.
head
.
NumberU64
()
{
panic
(
fmt
.
Errorf
(
"fetched block %v number %d above head block number %d"
,
blockHash
,
block
.
NumberU64
(),
o
.
head
.
NumberU64
()))
}
return
block
}
op-program/host/l2/fetcher_test.go
View file @
7742c972
...
...
@@ -5,12 +5,14 @@ import (
"encoding/json"
"errors"
"fmt"
"math/big"
"math/rand"
"reflect"
"testing"
"github.com/ethereum-optimism/optimism/op-node/testutils"
cll2
"github.com/ethereum-optimism/optimism/op-program/client/l2"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
...
...
@@ -23,35 +25,7 @@ import (
// Require the fetching oracle to implement StateOracle
var
_
cll2
.
StateOracle
=
(
*
FetchingL2Oracle
)(
nil
)
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
}
const
headBlockNumber
=
1000
func
TestNodeByHash
(
t
*
testing
.
T
)
{
rng
:=
rand
.
New
(
rand
.
NewSource
(
1234
))
...
...
@@ -152,31 +126,12 @@ func TestCodeByHash(t *testing.T) {
})
}
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
)
t
.
Run
(
"Success"
,
func
(
t
*
testing
.
T
)
{
block
,
_
:=
testutils
.
RandomBlock
(
rng
,
1
)
block
:=
blockWithNumber
(
rng
,
headBlockNumber
-
1
)
stub
:=
&
stubBlockSource
{
nextResult
:
block
}
fetcher
:=
newFetcher
(
stub
,
nil
)
...
...
@@ -194,7 +149,7 @@ func TestBlockByHash(t *testing.T) {
})
t
.
Run
(
"RequestArgs"
,
func
(
t
*
testing
.
T
)
{
stub
:=
&
stubBlockSource
{}
stub
:=
&
stubBlockSource
{
nextResult
:
blockWithNumber
(
rng
,
1
)
}
fetcher
:=
newFetcher
(
stub
,
nil
)
fetcher
.
BlockByHash
(
hash
)
...
...
@@ -203,11 +158,86 @@ func TestBlockByHash(t *testing.T) {
req
:=
stub
.
requests
[
0
]
require
.
Equal
(
t
,
hash
,
req
.
blockHash
)
})
t
.
Run
(
"PanicWhenBlockAboveHeadRequested"
,
func
(
t
*
testing
.
T
)
{
// Block that the source can provide but is above the head block number
block
:=
blockWithNumber
(
rng
,
headBlockNumber
+
1
)
stub
:=
&
stubBlockSource
{
nextResult
:
block
}
fetcher
:=
newFetcher
(
stub
,
nil
)
require
.
Panics
(
t
,
func
()
{
fetcher
.
BlockByHash
(
block
.
Hash
())
})
})
}
func
blockWithNumber
(
rng
*
rand
.
Rand
,
num
int64
)
*
types
.
Block
{
header
:=
testutils
.
RandomHeader
(
rng
)
header
.
Number
=
big
.
NewInt
(
num
)
return
types
.
NewBlock
(
header
,
nil
,
nil
,
nil
,
trie
.
NewStackTrie
(
nil
))
}
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
}
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
newFetcher
(
blockSource
BlockSource
,
callContext
CallContext
)
*
FetchingL2Oracle
{
rng
:=
rand
.
New
(
rand
.
NewSource
(
int64
(
1
)))
head
:=
testutils
.
MakeBlockInfo
(
func
(
i
*
testutils
.
MockBlockInfo
)
{
i
.
InfoNum
=
headBlockNumber
})(
rng
)
return
&
FetchingL2Oracle
{
ctx
:
context
.
Background
(),
logger
:
log
.
New
(),
head
:
head
,
blockSource
:
blockSource
,
callContext
:
callContext
,
}
...
...
op-program/host/l2/l2.go
View file @
7742c972
...
...
@@ -19,7 +19,7 @@ func NewFetchingEngine(ctx context.Context, logger log.Logger, cfg *config.Confi
if
err
!=
nil
{
return
nil
,
err
}
oracle
,
err
:=
NewFetchingL2Oracle
(
ctx
,
logger
,
cfg
.
L2URL
)
oracle
,
err
:=
NewFetchingL2Oracle
(
ctx
,
logger
,
cfg
.
L2URL
,
cfg
.
L2Head
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"connect l2 oracle: %w"
,
err
)
}
...
...
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