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
d5f9ebfe
Unverified
Commit
d5f9ebfe
authored
Oct 24, 2023
by
protolambda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
op-node: disallow empty span batches, implement review suggestions
parent
b81df0e6
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
57 additions
and
7 deletions
+57
-7
batch_queue.go
op-node/rollup/derive/batch_queue.go
+9
-3
span_batch.go
op-node/rollup/derive/span_batch.go
+9
-1
span_batch_test.go
op-node/rollup/derive/span_batch_test.go
+39
-3
No files found.
op-node/rollup/derive/batch_queue.go
View file @
d5f9ebfe
...
@@ -70,7 +70,12 @@ func (bq *BatchQueue) Origin() eth.L1BlockRef {
...
@@ -70,7 +70,12 @@ func (bq *BatchQueue) Origin() eth.L1BlockRef {
return
bq
.
prev
.
Origin
()
return
bq
.
prev
.
Origin
()
}
}
// popNextBatch pops the next batch from the current queued up span-batch nextSpan.
// The queue must be non-empty, or the function will panic.
func
(
bq
*
BatchQueue
)
popNextBatch
(
safeL2Head
eth
.
L2BlockRef
)
*
SingularBatch
{
func
(
bq
*
BatchQueue
)
popNextBatch
(
safeL2Head
eth
.
L2BlockRef
)
*
SingularBatch
{
if
len
(
bq
.
nextSpan
)
==
0
{
panic
(
"popping non-existent span-batch, invalid state"
)
}
nextBatch
:=
bq
.
nextSpan
[
0
]
nextBatch
:=
bq
.
nextSpan
[
0
]
bq
.
nextSpan
=
bq
.
nextSpan
[
1
:
]
bq
.
nextSpan
=
bq
.
nextSpan
[
1
:
]
// Must set ParentHash before return. we can use safeL2Head because the parentCheck is verified in CheckBatch().
// Must set ParentHash before return. we can use safeL2Head because the parentCheck is verified in CheckBatch().
...
@@ -78,7 +83,7 @@ func (bq *BatchQueue) popNextBatch(safeL2Head eth.L2BlockRef) *SingularBatch {
...
@@ -78,7 +83,7 @@ func (bq *BatchQueue) popNextBatch(safeL2Head eth.L2BlockRef) *SingularBatch {
return
nextBatch
return
nextBatch
}
}
func
(
bq
*
BatchQueue
)
advanceEpochMaybe
(
nextBatch
*
SingularBatch
)
{
func
(
bq
*
BatchQueue
)
maybeAdvanceEpoch
(
nextBatch
*
SingularBatch
)
{
if
len
(
bq
.
l1Blocks
)
==
0
{
if
len
(
bq
.
l1Blocks
)
==
0
{
return
return
}
}
...
@@ -92,7 +97,7 @@ func (bq *BatchQueue) NextBatch(ctx context.Context, safeL2Head eth.L2BlockRef)
...
@@ -92,7 +97,7 @@ func (bq *BatchQueue) NextBatch(ctx context.Context, safeL2Head eth.L2BlockRef)
if
len
(
bq
.
nextSpan
)
>
0
{
if
len
(
bq
.
nextSpan
)
>
0
{
// If there are cached singular batches, pop first one and return.
// If there are cached singular batches, pop first one and return.
nextBatch
:=
bq
.
popNextBatch
(
safeL2Head
)
nextBatch
:=
bq
.
popNextBatch
(
safeL2Head
)
bq
.
advanceEpochMaybe
(
nextBatch
)
bq
.
maybeAdvanceEpoch
(
nextBatch
)
return
nextBatch
,
nil
return
nextBatch
,
nil
}
}
...
@@ -167,12 +172,13 @@ func (bq *BatchQueue) NextBatch(ctx context.Context, safeL2Head eth.L2BlockRef)
...
@@ -167,12 +172,13 @@ func (bq *BatchQueue) NextBatch(ctx context.Context, safeL2Head eth.L2BlockRef)
return
nil
,
NewCriticalError
(
err
)
return
nil
,
NewCriticalError
(
err
)
}
}
bq
.
nextSpan
=
singularBatches
bq
.
nextSpan
=
singularBatches
// span-batches are non-empty, so the below pop is safe.
nextBatch
=
bq
.
popNextBatch
(
safeL2Head
)
nextBatch
=
bq
.
popNextBatch
(
safeL2Head
)
default
:
default
:
return
nil
,
NewCriticalError
(
fmt
.
Errorf
(
"unrecognized batch type: %d"
,
batch
.
GetBatchType
()))
return
nil
,
NewCriticalError
(
fmt
.
Errorf
(
"unrecognized batch type: %d"
,
batch
.
GetBatchType
()))
}
}
bq
.
advanceEpochMaybe
(
nextBatch
)
bq
.
maybeAdvanceEpoch
(
nextBatch
)
return
nextBatch
,
nil
return
nextBatch
,
nil
}
}
...
...
op-node/rollup/derive/span_batch.go
View file @
d5f9ebfe
...
@@ -27,6 +27,8 @@ import (
...
@@ -27,6 +27,8 @@ import (
var
ErrTooBigSpanBatchFieldSize
=
errors
.
New
(
"batch would cause field bytes to go over limit"
)
var
ErrTooBigSpanBatchFieldSize
=
errors
.
New
(
"batch would cause field bytes to go over limit"
)
var
ErrEmptySpanBatch
=
errors
.
New
(
"span-batch must not be empty"
)
type
spanBatchPrefix
struct
{
type
spanBatchPrefix
struct
{
relTimestamp
uint64
// Relative timestamp of the first block
relTimestamp
uint64
// Relative timestamp of the first block
l1OriginNum
uint64
// L1 origin number
l1OriginNum
uint64
// L1 origin number
...
@@ -139,10 +141,13 @@ func (bp *spanBatchPrefix) decodePrefix(r *bytes.Reader) error {
...
@@ -139,10 +141,13 @@ func (bp *spanBatchPrefix) decodePrefix(r *bytes.Reader) error {
// decodeBlockCount parses data into bp.blockCount
// decodeBlockCount parses data into bp.blockCount
func
(
bp
*
spanBatchPayload
)
decodeBlockCount
(
r
*
bytes
.
Reader
)
error
{
func
(
bp
*
spanBatchPayload
)
decodeBlockCount
(
r
*
bytes
.
Reader
)
error
{
blockCount
,
err
:=
binary
.
ReadUvarint
(
r
)
blockCount
,
err
:=
binary
.
ReadUvarint
(
r
)
bp
.
blockCount
=
blockCount
if
err
!=
nil
{
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to read block count: %w"
,
err
)
return
fmt
.
Errorf
(
"failed to read block count: %w"
,
err
)
}
}
bp
.
blockCount
=
blockCount
if
blockCount
==
0
{
return
ErrEmptySpanBatch
}
return
nil
return
nil
}
}
...
@@ -362,6 +367,9 @@ func (b *RawSpanBatch) encodeBytes() ([]byte, error) {
...
@@ -362,6 +367,9 @@ func (b *RawSpanBatch) encodeBytes() ([]byte, error) {
// derive converts RawSpanBatch into SpanBatch, which has a list of spanBatchElement.
// derive converts RawSpanBatch into SpanBatch, which has a list of spanBatchElement.
// We need chain config constants to derive values for making payload attributes.
// We need chain config constants to derive values for making payload attributes.
func
(
b
*
RawSpanBatch
)
derive
(
blockTime
,
genesisTimestamp
uint64
,
chainID
*
big
.
Int
)
(
*
SpanBatch
,
error
)
{
func
(
b
*
RawSpanBatch
)
derive
(
blockTime
,
genesisTimestamp
uint64
,
chainID
*
big
.
Int
)
(
*
SpanBatch
,
error
)
{
if
b
.
blockCount
==
0
{
return
nil
,
ErrEmptySpanBatch
}
blockOriginNums
:=
make
([]
uint64
,
b
.
blockCount
)
blockOriginNums
:=
make
([]
uint64
,
b
.
blockCount
)
l1OriginBlockNumber
:=
b
.
l1OriginNum
l1OriginBlockNumber
:=
b
.
l1OriginNum
for
i
:=
int
(
b
.
blockCount
)
-
1
;
i
>=
0
;
i
--
{
for
i
:=
int
(
b
.
blockCount
)
-
1
;
i
>=
0
;
i
--
{
...
...
op-node/rollup/derive/span_batch_test.go
View file @
d5f9ebfe
...
@@ -6,12 +6,15 @@ import (
...
@@ -6,12 +6,15 @@ import (
"math/rand"
"math/rand"
"testing"
"testing"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/stretchr/testify/assert"
"github.com/ethereum-optimism/optimism/op-service/testutils"
"github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rlp"
"github.com/stretchr/testify/assert"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-service/testutils"
)
)
func
TestSpanBatchForBatchInterface
(
t
*
testing
.
T
)
{
func
TestSpanBatchForBatchInterface
(
t
*
testing
.
T
)
{
...
@@ -33,6 +36,39 @@ func TestSpanBatchForBatchInterface(t *testing.T) {
...
@@ -33,6 +36,39 @@ func TestSpanBatchForBatchInterface(t *testing.T) {
assert
.
True
(
t
,
spanBatch
.
CheckParentHash
(
singularBatches
[
0
]
.
ParentHash
))
assert
.
True
(
t
,
spanBatch
.
CheckParentHash
(
singularBatches
[
0
]
.
ParentHash
))
}
}
func
TestEmptySpanBatch
(
t
*
testing
.
T
)
{
rng
:=
rand
.
New
(
rand
.
NewSource
(
0x77556691
))
chainID
:=
big
.
NewInt
(
rng
.
Int63n
(
1000
))
spanTxs
,
err
:=
newSpanBatchTxs
(
nil
,
chainID
)
require
.
NoError
(
t
,
err
)
rawSpanBatch
:=
RawSpanBatch
{
spanBatchPrefix
:
spanBatchPrefix
{
relTimestamp
:
uint64
(
rng
.
Uint32
()),
l1OriginNum
:
rng
.
Uint64
(),
parentCheck
:
testutils
.
RandomData
(
rng
,
20
),
l1OriginCheck
:
testutils
.
RandomData
(
rng
,
20
),
},
spanBatchPayload
:
spanBatchPayload
{
blockCount
:
0
,
originBits
:
big
.
NewInt
(
0
),
blockTxCounts
:
[]
uint64
{},
txs
:
spanTxs
,
},
}
var
buf
bytes
.
Buffer
err
=
rawSpanBatch
.
encodeBlockCount
(
&
buf
)
assert
.
NoError
(
t
,
err
)
result
:=
buf
.
Bytes
()
r
:=
bytes
.
NewReader
(
result
)
var
sb
RawSpanBatch
err
=
sb
.
decodeBlockCount
(
r
)
require
.
ErrorIs
(
t
,
err
,
ErrEmptySpanBatch
)
}
func
TestSpanBatchOriginBits
(
t
*
testing
.
T
)
{
func
TestSpanBatchOriginBits
(
t
*
testing
.
T
)
{
rng
:=
rand
.
New
(
rand
.
NewSource
(
0x77665544
))
rng
:=
rand
.
New
(
rand
.
NewSource
(
0x77665544
))
chainID
:=
big
.
NewInt
(
rng
.
Int63n
(
1000
))
chainID
:=
big
.
NewInt
(
rng
.
Int63n
(
1000
))
...
...
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