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
38b4a12d
Unverified
Commit
38b4a12d
authored
Jan 24, 2023
by
mergify[bot]
Committed by
GitHub
Jan 24, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into clabby/e2e/garbage-batch
parents
3b166752
ff01cd62
Changes
5
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
266 additions
and
1 deletion
+266
-1
node.go
op-node/node/node.go
+8
-0
types.go
op-node/rollup/types.go
+89
-0
types_test.go
op-node/rollup/types_test.go
+157
-0
eth_client.go
op-node/sources/eth_client.go
+11
-0
engine.svg
specs/assets/engine.svg
+1
-1
No files found.
op-node/node/node.go
View file @
38b4a12d
...
...
@@ -124,6 +124,10 @@ func (n *OpNode) initL1(ctx context.Context, cfg *Config) error {
return
fmt
.
Errorf
(
"failed to create L1 source: %w"
,
err
)
}
if
err
:=
cfg
.
Rollup
.
ValidateL1Config
(
ctx
,
n
.
l1Source
);
err
!=
nil
{
return
err
}
// Keep subscribed to the L1 heads, which keeps the L1 maintainer pointing to the best headers to sync
n
.
l1HeadsSub
=
event
.
ResubscribeErr
(
time
.
Second
*
10
,
func
(
ctx
context
.
Context
,
err
error
)
(
event
.
Subscription
,
error
)
{
if
err
!=
nil
{
...
...
@@ -189,6 +193,10 @@ func (n *OpNode) initL2(ctx context.Context, cfg *Config, snapshotLog log.Logger
return
fmt
.
Errorf
(
"failed to create Engine client: %w"
,
err
)
}
if
err
:=
cfg
.
Rollup
.
ValidateL2Config
(
ctx
,
n
.
l2Source
);
err
!=
nil
{
return
err
}
n
.
l2Driver
=
driver
.
NewDriver
(
&
cfg
.
Driver
,
&
cfg
.
Rollup
,
n
.
l2Source
,
n
.
l1Source
,
n
,
n
.
log
,
snapshotLog
,
n
.
metrics
)
return
nil
...
...
op-node/rollup/types.go
View file @
38b4a12d
package
rollup
import
(
"context"
"errors"
"fmt"
"math/big"
...
...
@@ -55,6 +56,94 @@ type Config struct {
L1SystemConfigAddress
common
.
Address
`json:"l1_system_config_address"`
}
// ValidateL1Config checks L1 config variables for errors.
func
(
cfg
*
Config
)
ValidateL1Config
(
ctx
context
.
Context
,
client
L1Client
)
error
{
// Validate the L1 Client Chain ID
if
err
:=
cfg
.
CheckL1ChainID
(
ctx
,
client
);
err
!=
nil
{
return
err
}
// Validate the Rollup L1 Genesis Blockhash
if
err
:=
cfg
.
CheckL1GenesisBlockHash
(
ctx
,
client
);
err
!=
nil
{
return
err
}
return
nil
}
// ValidateL2Config checks L2 config variables for errors.
func
(
cfg
*
Config
)
ValidateL2Config
(
ctx
context
.
Context
,
client
L2Client
)
error
{
// Validate the L2 Client Chain ID
if
err
:=
cfg
.
CheckL2ChainID
(
ctx
,
client
);
err
!=
nil
{
return
err
}
// Validate the Rollup L2 Genesis Blockhash
if
err
:=
cfg
.
CheckL2GenesisBlockHash
(
ctx
,
client
);
err
!=
nil
{
return
err
}
return
nil
}
type
L1Client
interface
{
ChainID
(
context
.
Context
)
(
*
big
.
Int
,
error
)
L1BlockRefByNumber
(
context
.
Context
,
uint64
)
(
eth
.
L1BlockRef
,
error
)
}
// CheckL1ChainID checks that the configured L1 chain ID matches the client's chain ID.
func
(
cfg
*
Config
)
CheckL1ChainID
(
ctx
context
.
Context
,
client
L1Client
)
error
{
id
,
err
:=
client
.
ChainID
(
ctx
)
if
err
!=
nil
{
return
err
}
if
cfg
.
L1ChainID
.
Cmp
(
id
)
!=
0
{
return
fmt
.
Errorf
(
"incorrect L1 RPC chain id %d, expected %d"
,
cfg
.
L1ChainID
,
id
)
}
return
nil
}
// CheckL1GenesisBlockHash checks that the configured L1 genesis block hash is valid for the given client.
func
(
cfg
*
Config
)
CheckL1GenesisBlockHash
(
ctx
context
.
Context
,
client
L1Client
)
error
{
l1GenesisBlockRef
,
err
:=
client
.
L1BlockRefByNumber
(
ctx
,
cfg
.
Genesis
.
L1
.
Number
)
if
err
!=
nil
{
return
err
}
if
l1GenesisBlockRef
.
Hash
!=
cfg
.
Genesis
.
L1
.
Hash
{
return
fmt
.
Errorf
(
"incorrect L1 genesis block hash %d, expected %d"
,
cfg
.
Genesis
.
L1
.
Hash
,
l1GenesisBlockRef
.
Hash
)
}
return
nil
}
type
L2Client
interface
{
ChainID
(
context
.
Context
)
(
*
big
.
Int
,
error
)
L2BlockRefByNumber
(
context
.
Context
,
uint64
)
(
eth
.
L2BlockRef
,
error
)
}
// CheckL2ChainID checks that the configured L2 chain ID matches the client's chain ID.
func
(
cfg
*
Config
)
CheckL2ChainID
(
ctx
context
.
Context
,
client
L2Client
)
error
{
id
,
err
:=
client
.
ChainID
(
ctx
)
if
err
!=
nil
{
return
err
}
if
cfg
.
L2ChainID
.
Cmp
(
id
)
!=
0
{
return
fmt
.
Errorf
(
"incorrect L2 RPC chain id %d, expected %d"
,
cfg
.
L2ChainID
,
id
)
}
return
nil
}
// CheckL2GenesisBlockHash checks that the configured L2 genesis block hash is valid for the given client.
func
(
cfg
*
Config
)
CheckL2GenesisBlockHash
(
ctx
context
.
Context
,
client
L2Client
)
error
{
l2GenesisBlockRef
,
err
:=
client
.
L2BlockRefByNumber
(
ctx
,
cfg
.
Genesis
.
L2
.
Number
)
if
err
!=
nil
{
return
err
}
if
l2GenesisBlockRef
.
Hash
!=
cfg
.
Genesis
.
L2
.
Hash
{
return
fmt
.
Errorf
(
"incorrect L2 genesis block hash %d, expected %d"
,
cfg
.
Genesis
.
L2
.
Hash
,
l2GenesisBlockRef
.
Hash
)
}
return
nil
}
// Check verifies that the given configuration makes sense
func
(
cfg
*
Config
)
Check
()
error
{
if
cfg
.
BlockTime
==
0
{
...
...
op-node/rollup/types_test.go
View file @
38b4a12d
package
rollup
import
(
"context"
"encoding/json"
"math/big"
"math/rand"
...
...
@@ -55,3 +56,159 @@ func TestConfigJSON(t *testing.T) {
assert
.
NoError
(
t
,
json
.
Unmarshal
(
data
,
&
roundTripped
))
assert
.
Equal
(
t
,
&
roundTripped
,
config
)
}
type
mockL1Client
struct
{
chainID
*
big
.
Int
Hash
common
.
Hash
}
func
(
m
*
mockL1Client
)
ChainID
(
context
.
Context
)
(
*
big
.
Int
,
error
)
{
return
m
.
chainID
,
nil
}
func
(
m
*
mockL1Client
)
L1BlockRefByNumber
(
ctx
context
.
Context
,
number
uint64
)
(
eth
.
L1BlockRef
,
error
)
{
return
eth
.
L1BlockRef
{
Hash
:
m
.
Hash
,
Number
:
100
,
},
nil
}
func
TestValidateL1Config
(
t
*
testing
.
T
)
{
config
:=
randConfig
()
config
.
L1ChainID
=
big
.
NewInt
(
100
)
config
.
Genesis
.
L1
.
Number
=
100
config
.
Genesis
.
L1
.
Hash
=
[
32
]
byte
{
0x01
}
mockClient
:=
mockL1Client
{
chainID
:
big
.
NewInt
(
100
),
Hash
:
common
.
Hash
{
0x01
}}
err
:=
config
.
ValidateL1Config
(
context
.
TODO
(),
&
mockClient
)
assert
.
NoError
(
t
,
err
)
}
func
TestValidateL1ConfigInvalidChainIdFails
(
t
*
testing
.
T
)
{
config
:=
randConfig
()
config
.
L1ChainID
=
big
.
NewInt
(
101
)
config
.
Genesis
.
L1
.
Number
=
100
config
.
Genesis
.
L1
.
Hash
=
[
32
]
byte
{
0x01
}
mockClient
:=
mockL1Client
{
chainID
:
big
.
NewInt
(
100
),
Hash
:
common
.
Hash
{
0x01
}}
err
:=
config
.
ValidateL1Config
(
context
.
TODO
(),
&
mockClient
)
assert
.
Error
(
t
,
err
)
config
.
L1ChainID
=
big
.
NewInt
(
99
)
err
=
config
.
ValidateL1Config
(
context
.
TODO
(),
&
mockClient
)
assert
.
Error
(
t
,
err
)
}
func
TestValidateL1ConfigInvalidGenesisHashFails
(
t
*
testing
.
T
)
{
config
:=
randConfig
()
config
.
L1ChainID
=
big
.
NewInt
(
100
)
config
.
Genesis
.
L1
.
Number
=
100
config
.
Genesis
.
L1
.
Hash
=
[
32
]
byte
{
0x00
}
mockClient
:=
mockL1Client
{
chainID
:
big
.
NewInt
(
100
),
Hash
:
common
.
Hash
{
0x01
}}
err
:=
config
.
ValidateL1Config
(
context
.
TODO
(),
&
mockClient
)
assert
.
Error
(
t
,
err
)
config
.
Genesis
.
L1
.
Hash
=
[
32
]
byte
{
0x02
}
err
=
config
.
ValidateL1Config
(
context
.
TODO
(),
&
mockClient
)
assert
.
Error
(
t
,
err
)
}
func
TestCheckL1ChainID
(
t
*
testing
.
T
)
{
config
:=
randConfig
()
config
.
L1ChainID
=
big
.
NewInt
(
100
)
err
:=
config
.
CheckL1ChainID
(
context
.
TODO
(),
&
mockL1Client
{
chainID
:
big
.
NewInt
(
100
)})
assert
.
NoError
(
t
,
err
)
err
=
config
.
CheckL1ChainID
(
context
.
TODO
(),
&
mockL1Client
{
chainID
:
big
.
NewInt
(
101
)})
assert
.
Error
(
t
,
err
)
err
=
config
.
CheckL1ChainID
(
context
.
TODO
(),
&
mockL1Client
{
chainID
:
big
.
NewInt
(
99
)})
assert
.
Error
(
t
,
err
)
}
func
TestCheckL1BlockRefByNumber
(
t
*
testing
.
T
)
{
config
:=
randConfig
()
config
.
Genesis
.
L1
.
Number
=
100
config
.
Genesis
.
L1
.
Hash
=
[
32
]
byte
{
0x01
}
mockClient
:=
mockL1Client
{
chainID
:
big
.
NewInt
(
100
),
Hash
:
common
.
Hash
{
0x01
}}
err
:=
config
.
CheckL1GenesisBlockHash
(
context
.
TODO
(),
&
mockClient
)
assert
.
NoError
(
t
,
err
)
mockClient
.
Hash
=
common
.
Hash
{
0x02
}
err
=
config
.
CheckL1GenesisBlockHash
(
context
.
TODO
(),
&
mockClient
)
assert
.
Error
(
t
,
err
)
mockClient
.
Hash
=
common
.
Hash
{
0x00
}
err
=
config
.
CheckL1GenesisBlockHash
(
context
.
TODO
(),
&
mockClient
)
assert
.
Error
(
t
,
err
)
}
type
mockL2Client
struct
{
chainID
*
big
.
Int
Hash
common
.
Hash
}
func
(
m
*
mockL2Client
)
ChainID
(
context
.
Context
)
(
*
big
.
Int
,
error
)
{
return
m
.
chainID
,
nil
}
func
(
m
*
mockL2Client
)
L2BlockRefByNumber
(
ctx
context
.
Context
,
number
uint64
)
(
eth
.
L2BlockRef
,
error
)
{
return
eth
.
L2BlockRef
{
Hash
:
m
.
Hash
,
Number
:
100
,
},
nil
}
func
TestValidateL2Config
(
t
*
testing
.
T
)
{
config
:=
randConfig
()
config
.
L2ChainID
=
big
.
NewInt
(
100
)
config
.
Genesis
.
L2
.
Number
=
100
config
.
Genesis
.
L2
.
Hash
=
[
32
]
byte
{
0x01
}
mockClient
:=
mockL2Client
{
chainID
:
big
.
NewInt
(
100
),
Hash
:
common
.
Hash
{
0x01
}}
err
:=
config
.
ValidateL2Config
(
context
.
TODO
(),
&
mockClient
)
assert
.
NoError
(
t
,
err
)
}
func
TestValidateL2ConfigInvalidChainIdFails
(
t
*
testing
.
T
)
{
config
:=
randConfig
()
config
.
L2ChainID
=
big
.
NewInt
(
101
)
config
.
Genesis
.
L2
.
Number
=
100
config
.
Genesis
.
L2
.
Hash
=
[
32
]
byte
{
0x01
}
mockClient
:=
mockL2Client
{
chainID
:
big
.
NewInt
(
100
),
Hash
:
common
.
Hash
{
0x01
}}
err
:=
config
.
ValidateL2Config
(
context
.
TODO
(),
&
mockClient
)
assert
.
Error
(
t
,
err
)
config
.
L2ChainID
=
big
.
NewInt
(
99
)
err
=
config
.
ValidateL2Config
(
context
.
TODO
(),
&
mockClient
)
assert
.
Error
(
t
,
err
)
}
func
TestValidateL2ConfigInvalidGenesisHashFails
(
t
*
testing
.
T
)
{
config
:=
randConfig
()
config
.
L2ChainID
=
big
.
NewInt
(
100
)
config
.
Genesis
.
L2
.
Number
=
100
config
.
Genesis
.
L2
.
Hash
=
[
32
]
byte
{
0x00
}
mockClient
:=
mockL2Client
{
chainID
:
big
.
NewInt
(
100
),
Hash
:
common
.
Hash
{
0x01
}}
err
:=
config
.
ValidateL2Config
(
context
.
TODO
(),
&
mockClient
)
assert
.
Error
(
t
,
err
)
config
.
Genesis
.
L2
.
Hash
=
[
32
]
byte
{
0x02
}
err
=
config
.
ValidateL2Config
(
context
.
TODO
(),
&
mockClient
)
assert
.
Error
(
t
,
err
)
}
func
TestCheckL2ChainID
(
t
*
testing
.
T
)
{
config
:=
randConfig
()
config
.
L2ChainID
=
big
.
NewInt
(
100
)
err
:=
config
.
CheckL2ChainID
(
context
.
TODO
(),
&
mockL2Client
{
chainID
:
big
.
NewInt
(
100
)})
assert
.
NoError
(
t
,
err
)
err
=
config
.
CheckL2ChainID
(
context
.
TODO
(),
&
mockL2Client
{
chainID
:
big
.
NewInt
(
101
)})
assert
.
Error
(
t
,
err
)
err
=
config
.
CheckL2ChainID
(
context
.
TODO
(),
&
mockL2Client
{
chainID
:
big
.
NewInt
(
99
)})
assert
.
Error
(
t
,
err
)
}
func
TestCheckL2BlockRefByNumber
(
t
*
testing
.
T
)
{
config
:=
randConfig
()
config
.
Genesis
.
L2
.
Number
=
100
config
.
Genesis
.
L2
.
Hash
=
[
32
]
byte
{
0x01
}
mockClient
:=
mockL2Client
{
chainID
:
big
.
NewInt
(
100
),
Hash
:
common
.
Hash
{
0x01
}}
err
:=
config
.
CheckL2GenesisBlockHash
(
context
.
TODO
(),
&
mockClient
)
assert
.
NoError
(
t
,
err
)
mockClient
.
Hash
=
common
.
Hash
{
0x02
}
err
=
config
.
CheckL2GenesisBlockHash
(
context
.
TODO
(),
&
mockClient
)
assert
.
Error
(
t
,
err
)
mockClient
.
Hash
=
common
.
Hash
{
0x00
}
err
=
config
.
CheckL2GenesisBlockHash
(
context
.
TODO
(),
&
mockClient
)
assert
.
Error
(
t
,
err
)
}
op-node/sources/eth_client.go
View file @
38b4a12d
...
...
@@ -12,6 +12,7 @@ package sources
import
(
"context"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
...
...
@@ -216,6 +217,16 @@ func (s *EthClient) payloadCall(ctx context.Context, method string, id any) (*et
return
payload
,
nil
}
// ChainID fetches the chain id of the internal RPC.
func
(
s
*
EthClient
)
ChainID
(
ctx
context
.
Context
)
(
*
big
.
Int
,
error
)
{
var
id
hexutil
.
Big
err
:=
s
.
client
.
CallContext
(
ctx
,
&
id
,
"eth_chainId"
)
if
err
!=
nil
{
return
nil
,
err
}
return
(
*
big
.
Int
)(
&
id
),
nil
}
func
(
s
*
EthClient
)
InfoByHash
(
ctx
context
.
Context
,
hash
common
.
Hash
)
(
eth
.
BlockInfo
,
error
)
{
if
header
,
ok
:=
s
.
headersCache
.
Get
(
hash
);
ok
{
return
header
.
(
*
HeaderInfo
),
nil
...
...
specs/assets/engine.svg
View file @
38b4a12d
This diff is collapsed.
Click to expand it.
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