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
0aab6a5c
Unverified
Commit
0aab6a5c
authored
Mar 21, 2023
by
mergify[bot]
Committed by
GitHub
Mar 21, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #5187 from ethereum-optimism/refcell/fix/channelo
fix(op-node): Fix Channel Out MaxSize Underflow
parents
568f0805
ba3e76ec
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
127 additions
and
121 deletions
+127
-121
channel_builder_test.go
op-batcher/batcher/channel_builder_test.go
+46
-57
channel_manager_test.go
op-batcher/batcher/channel_manager_test.go
+48
-59
channel_out.go
op-node/rollup/derive/channel_out.go
+17
-5
channel_out_test.go
op-node/rollup/derive/channel_out_test.go
+16
-0
No files found.
op-batcher/batcher/channel_builder_test.go
View file @
0aab6a5c
...
@@ -132,10 +132,10 @@ func FuzzDurationTimeoutZeroMaxChannelDuration(f *testing.F) {
...
@@ -132,10 +132,10 @@ func FuzzDurationTimeoutZeroMaxChannelDuration(f *testing.F) {
})
})
}
}
// FuzzDurationZero ensures that when whenever the MaxChannelDuration
// Fuzz
ChannelBuilder_
DurationZero ensures that when whenever the MaxChannelDuration
// is not set to 0, the channel builder will always have a duration timeout
// is not set to 0, the channel builder will always have a duration timeout
// as long as the channel builder's timeout is set to 0.
// as long as the channel builder's timeout is set to 0.
func
FuzzDurationZero
(
f
*
testing
.
F
)
{
func
Fuzz
ChannelBuilder_
DurationZero
(
f
*
testing
.
F
)
{
for
i
:=
range
[
10
]
int
{}
{
for
i
:=
range
[
10
]
int
{}
{
f
.
Add
(
uint64
(
i
),
uint64
(
i
))
f
.
Add
(
uint64
(
i
),
uint64
(
i
))
}
}
...
@@ -313,8 +313,8 @@ func FuzzSeqWindowZeroTimeoutClose(f *testing.F) {
...
@@ -313,8 +313,8 @@ func FuzzSeqWindowZeroTimeoutClose(f *testing.F) {
})
})
}
}
// Test
Builder
NextFrame tests calling NextFrame on a ChannelBuilder with only one frame
// Test
ChannelBuilder_
NextFrame tests calling NextFrame on a ChannelBuilder with only one frame
func
Test
Builder
NextFrame
(
t
*
testing
.
T
)
{
func
Test
ChannelBuilder_
NextFrame
(
t
*
testing
.
T
)
{
channelConfig
:=
defaultTestChannelConfig
channelConfig
:=
defaultTestChannelConfig
// Create a new channel builder
// Create a new channel builder
...
@@ -353,8 +353,8 @@ func TestBuilderNextFrame(t *testing.T) {
...
@@ -353,8 +353,8 @@ func TestBuilderNextFrame(t *testing.T) {
require
.
PanicsWithValue
(
t
,
"no next frame"
,
func
()
{
cb
.
NextFrame
()
})
require
.
PanicsWithValue
(
t
,
"no next frame"
,
func
()
{
cb
.
NextFrame
()
})
}
}
// Test
BuilderInvalidFrameId
tests that a panic is thrown when a frame is pushed with an invalid frame id
// Test
ChannelBuilder_OutputWrongFramePanic
tests that a panic is thrown when a frame is pushed with an invalid frame id
func
Test
Builder
WrongFramePanic
(
t
*
testing
.
T
)
{
func
Test
ChannelBuilder_Output
WrongFramePanic
(
t
*
testing
.
T
)
{
channelConfig
:=
defaultTestChannelConfig
channelConfig
:=
defaultTestChannelConfig
// Construct a channel builder
// Construct a channel builder
...
@@ -383,15 +383,14 @@ func TestBuilderWrongFramePanic(t *testing.T) {
...
@@ -383,15 +383,14 @@ func TestBuilderWrongFramePanic(t *testing.T) {
})
})
}
}
// Test
OutputFrames tests the OutputFrames function
// Test
ChannelBuilder_OutputFramesWorks tests the [ChannelBuilder] OutputFrames is successful.
func
Test
OutputFrame
s
(
t
*
testing
.
T
)
{
func
Test
ChannelBuilder_OutputFramesWork
s
(
t
*
testing
.
T
)
{
channelConfig
:=
defaultTestChannelConfig
channelConfig
:=
defaultTestChannelConfig
channelConfig
.
MaxFrameSize
=
2
channelConfig
.
MaxFrameSize
=
2
4
// Construct the channel builder
// Construct the channel builder
cb
,
err
:=
newChannelBuilder
(
channelConfig
)
cb
,
err
:=
newChannelBuilder
(
channelConfig
)
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
require
.
False
(
t
,
cb
.
IsFull
())
require
.
False
(
t
,
cb
.
IsFull
())
require
.
Equal
(
t
,
0
,
cb
.
NumFrames
())
require
.
Equal
(
t
,
0
,
cb
.
NumFrames
())
...
@@ -400,40 +399,34 @@ func TestOutputFrames(t *testing.T) {
...
@@ -400,40 +399,34 @@ func TestOutputFrames(t *testing.T) {
require
.
NoError
(
t
,
cb
.
OutputFrames
())
require
.
NoError
(
t
,
cb
.
OutputFrames
())
// There should be no ready bytes yet
// There should be no ready bytes yet
readyBytes
:=
cb
.
co
.
ReadyBytes
()
require
.
Equal
(
t
,
0
,
cb
.
co
.
ReadyBytes
())
require
.
Equal
(
t
,
0
,
readyBytes
)
// Let's add a block
// Let's add a block
err
=
addMiniBlock
(
cb
)
require
.
NoError
(
t
,
addMiniBlock
(
cb
)
)
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
cb
.
co
.
Flush
()
)
// Check how many ready bytes
// Check how many ready bytes
readyBytes
=
cb
.
co
.
ReadyBytes
()
// There should be more than the max frame size ready
require
.
Equal
(
t
,
2
,
readyBytes
)
require
.
Greater
(
t
,
uint64
(
cb
.
co
.
ReadyBytes
()),
channelConfig
.
MaxFrameSize
)
require
.
Equal
(
t
,
0
,
cb
.
NumFrames
())
require
.
Equal
(
t
,
0
,
cb
.
NumFrames
())
// The channel should not be full
// The channel should not be full
// but we want to output the frames for testing anyways
// but we want to output the frames for testing anyways
isFull
:=
cb
.
IsFull
()
require
.
False
(
t
,
cb
.
IsFull
())
require
.
False
(
t
,
isFull
)
// Since we manually set the max frame size to 2,
// we should be able to compress the two frames now
err
=
cb
.
OutputFrames
()
require
.
NoError
(
t
,
err
)
//
There should be one frame in the channel builder now
//
We should be able to output the frames
require
.
Equal
(
t
,
1
,
cb
.
Num
Frames
())
require
.
NoError
(
t
,
cb
.
Output
Frames
())
// There should no longer be any ready bytes
// There should be many frames in the channel builder now
readyBytes
=
cb
.
co
.
ReadyBytes
()
require
.
Greater
(
t
,
cb
.
NumFrames
(),
1
)
require
.
Equal
(
t
,
0
,
readyBytes
)
for
_
,
frame
:=
range
cb
.
frames
{
require
.
Len
(
t
,
frame
.
data
,
int
(
channelConfig
.
MaxFrameSize
))
}
}
}
// TestMaxRLPBytesPerChannel tests the [channelBuilder.OutputFrames]
// Test
ChannelBuilder_
MaxRLPBytesPerChannel tests the [channelBuilder.OutputFrames]
// function errors when the max RLP bytes per channel is reached.
// function errors when the max RLP bytes per channel is reached.
func
TestMaxRLPBytesPerChannel
(
t
*
testing
.
T
)
{
func
Test
ChannelBuilder_
MaxRLPBytesPerChannel
(
t
*
testing
.
T
)
{
t
.
Parallel
()
t
.
Parallel
()
channelConfig
:=
defaultTestChannelConfig
channelConfig
:=
defaultTestChannelConfig
channelConfig
.
MaxFrameSize
=
derive
.
MaxRLPBytesPerChannel
*
2
channelConfig
.
MaxFrameSize
=
derive
.
MaxRLPBytesPerChannel
*
2
...
@@ -449,13 +442,13 @@ func TestMaxRLPBytesPerChannel(t *testing.T) {
...
@@ -449,13 +442,13 @@ func TestMaxRLPBytesPerChannel(t *testing.T) {
require
.
ErrorIs
(
t
,
err
,
derive
.
ErrTooManyRLPBytes
)
require
.
ErrorIs
(
t
,
err
,
derive
.
ErrTooManyRLPBytes
)
}
}
// Test
OutputFramesMaxFrameIndex tests the [c
hannelBuilder.OutputFrames]
// Test
ChannelBuilder_OutputFramesMaxFrameIndex tests the [C
hannelBuilder.OutputFrames]
// function errors when the max frame index is reached.
// function errors when the max frame index is reached.
func
TestOutputFramesMaxFrameIndex
(
t
*
testing
.
T
)
{
func
Test
ChannelBuilder_
OutputFramesMaxFrameIndex
(
t
*
testing
.
T
)
{
channelConfig
:=
defaultTestChannelConfig
channelConfig
:=
defaultTestChannelConfig
channelConfig
.
MaxFrameSize
=
1
channelConfig
.
MaxFrameSize
=
24
channelConfig
.
TargetNumFrames
=
math
.
MaxInt
channelConfig
.
TargetNumFrames
=
math
.
MaxInt
channelConfig
.
TargetFrameSize
=
1
channelConfig
.
TargetFrameSize
=
24
channelConfig
.
ApproxComprRatio
=
0
channelConfig
.
ApproxComprRatio
=
0
// Continuously add blocks until the max frame index is reached
// Continuously add blocks until the max frame index is reached
...
@@ -477,6 +470,7 @@ func TestOutputFramesMaxFrameIndex(t *testing.T) {
...
@@ -477,6 +470,7 @@ func TestOutputFramesMaxFrameIndex(t *testing.T) {
Number
:
big
.
NewInt
(
0
),
Number
:
big
.
NewInt
(
0
),
},
txs
,
nil
,
nil
,
trie
.
NewStackTrie
(
nil
))
},
txs
,
nil
,
nil
,
trie
.
NewStackTrie
(
nil
))
_
,
err
=
cb
.
AddBlock
(
a
)
_
,
err
=
cb
.
AddBlock
(
a
)
require
.
NoError
(
t
,
cb
.
co
.
Flush
())
if
cb
.
IsFull
()
{
if
cb
.
IsFull
()
{
fullErr
:=
cb
.
FullErr
()
fullErr
:=
cb
.
FullErr
()
require
.
ErrorIs
(
t
,
fullErr
,
ErrMaxFrameIndex
)
require
.
ErrorIs
(
t
,
fullErr
,
ErrMaxFrameIndex
)
...
@@ -489,17 +483,15 @@ func TestOutputFramesMaxFrameIndex(t *testing.T) {
...
@@ -489,17 +483,15 @@ func TestOutputFramesMaxFrameIndex(t *testing.T) {
}
}
}
}
// Test
Builder
AddBlock tests the AddBlock function
// Test
ChannelBuilder_
AddBlock tests the AddBlock function
func
Test
Builder
AddBlock
(
t
*
testing
.
T
)
{
func
Test
ChannelBuilder_
AddBlock
(
t
*
testing
.
T
)
{
channelConfig
:=
defaultTestChannelConfig
channelConfig
:=
defaultTestChannelConfig
// Lower the max frame size so that we can batch
// Lower the max frame size so that we can batch
channelConfig
.
MaxFrameSize
=
2
channelConfig
.
MaxFrameSize
=
30
// Configure the Input Threshold params so we observe a full channel
// Configure the Input Threshold params so we observe a full channel
// In reality, we only need the input bytes (74) below to be greater than
channelConfig
.
TargetFrameSize
=
30
// or equal to the input threshold (3 * 2) / 1 = 6
channelConfig
.
TargetFrameSize
=
3
channelConfig
.
TargetNumFrames
=
2
channelConfig
.
TargetNumFrames
=
2
channelConfig
.
ApproxComprRatio
=
1
channelConfig
.
ApproxComprRatio
=
1
...
@@ -508,8 +500,8 @@ func TestBuilderAddBlock(t *testing.T) {
...
@@ -508,8 +500,8 @@ func TestBuilderAddBlock(t *testing.T) {
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
// Add a nonsense block to the channel builder
// Add a nonsense block to the channel builder
err
=
addMiniBlock
(
cb
)
require
.
NoError
(
t
,
addMiniBlock
(
cb
)
)
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
cb
.
co
.
Flush
()
)
// Check the fields reset in the AddBlock function
// Check the fields reset in the AddBlock function
require
.
Equal
(
t
,
74
,
cb
.
co
.
InputBytes
())
require
.
Equal
(
t
,
74
,
cb
.
co
.
InputBytes
())
...
@@ -519,23 +511,22 @@ func TestBuilderAddBlock(t *testing.T) {
...
@@ -519,23 +511,22 @@ func TestBuilderAddBlock(t *testing.T) {
// Since the channel output is full, the next call to AddBlock
// Since the channel output is full, the next call to AddBlock
// should return the channel out full error
// should return the channel out full error
err
=
addMiniBlock
(
cb
)
require
.
ErrorIs
(
t
,
addMiniBlock
(
cb
),
ErrInputTargetReached
)
require
.
ErrorIs
(
t
,
err
,
ErrInputTargetReached
)
}
}
// Test
BuilderReset tests the Reset
function
// Test
ChannelBuilder_Reset tests the [Reset]
function
func
Test
Builder
Reset
(
t
*
testing
.
T
)
{
func
Test
ChannelBuilder_
Reset
(
t
*
testing
.
T
)
{
channelConfig
:=
defaultTestChannelConfig
channelConfig
:=
defaultTestChannelConfig
// Lower the max frame size so that we can batch
// Lower the max frame size so that we can batch
channelConfig
.
MaxFrameSize
=
2
channelConfig
.
MaxFrameSize
=
2
4
cb
,
err
:=
newChannelBuilder
(
channelConfig
)
cb
,
err
:=
newChannelBuilder
(
channelConfig
)
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
// Add a nonsense block to the channel builder
// Add a nonsense block to the channel builder
err
=
addMiniBlock
(
cb
)
require
.
NoError
(
t
,
addMiniBlock
(
cb
)
)
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
cb
.
co
.
Flush
()
)
// Check the fields reset in the Reset function
// Check the fields reset in the Reset function
require
.
Equal
(
t
,
1
,
len
(
cb
.
blocks
))
require
.
Equal
(
t
,
1
,
len
(
cb
.
blocks
))
...
@@ -546,22 +537,20 @@ func TestBuilderReset(t *testing.T) {
...
@@ -546,22 +537,20 @@ func TestBuilderReset(t *testing.T) {
require
.
NoError
(
t
,
cb
.
fullErr
)
require
.
NoError
(
t
,
cb
.
fullErr
)
// Output frames so we can set the channel builder frames
// Output frames so we can set the channel builder frames
err
=
cb
.
OutputFrames
()
require
.
NoError
(
t
,
cb
.
OutputFrames
())
require
.
NoError
(
t
,
err
)
// Add another block to increment the block count
// Add another block to increment the block count
err
=
addMiniBlock
(
cb
)
require
.
NoError
(
t
,
addMiniBlock
(
cb
)
)
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
cb
.
co
.
Flush
()
)
// Check the fields reset in the Reset function
// Check the fields reset in the Reset function
require
.
Equal
(
t
,
2
,
len
(
cb
.
blocks
))
require
.
Equal
(
t
,
2
,
len
(
cb
.
blocks
))
require
.
Equal
(
t
,
1
,
len
(
cb
.
frames
)
)
require
.
Greater
(
t
,
len
(
cb
.
frames
),
1
)
require
.
Equal
(
t
,
timeout
,
cb
.
timeout
)
require
.
Equal
(
t
,
timeout
,
cb
.
timeout
)
require
.
NoError
(
t
,
cb
.
fullErr
)
require
.
NoError
(
t
,
cb
.
fullErr
)
// Reset the channel builder
// Reset the channel builder
err
=
cb
.
Reset
()
require
.
NoError
(
t
,
cb
.
Reset
())
require
.
NoError
(
t
,
err
)
// Check the fields reset in the Reset function
// Check the fields reset in the Reset function
require
.
Equal
(
t
,
0
,
len
(
cb
.
blocks
))
require
.
Equal
(
t
,
0
,
len
(
cb
.
blocks
))
...
...
op-batcher/batcher/channel_manager_test.go
View file @
0aab6a5c
...
@@ -32,8 +32,7 @@ func TestPendingChannelTimeout(t *testing.T) {
...
@@ -32,8 +32,7 @@ func TestPendingChannelTimeout(t *testing.T) {
require
.
False
(
t
,
timeout
)
require
.
False
(
t
,
timeout
)
// Set the pending channel
// Set the pending channel
err
:=
m
.
ensurePendingChannel
(
eth
.
BlockID
{})
require
.
NoError
(
t
,
m
.
ensurePendingChannel
(
eth
.
BlockID
{}))
require
.
NoError
(
t
,
err
)
// There are no confirmed transactions so
// There are no confirmed transactions so
// the pending channel cannot be timed out
// the pending channel cannot be timed out
...
@@ -85,14 +84,10 @@ func TestChannelManagerReturnsErrReorg(t *testing.T) {
...
@@ -85,14 +84,10 @@ func TestChannelManagerReturnsErrReorg(t *testing.T) {
ParentHash
:
common
.
Hash
{
0xff
},
ParentHash
:
common
.
Hash
{
0xff
},
},
nil
,
nil
,
nil
,
nil
)
},
nil
,
nil
,
nil
,
nil
)
err
:=
m
.
AddL2Block
(
a
)
require
.
NoError
(
t
,
m
.
AddL2Block
(
a
))
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
m
.
AddL2Block
(
b
))
err
=
m
.
AddL2Block
(
b
)
require
.
NoError
(
t
,
m
.
AddL2Block
(
c
))
require
.
NoError
(
t
,
err
)
require
.
ErrorIs
(
t
,
m
.
AddL2Block
(
x
),
ErrReorg
)
err
=
m
.
AddL2Block
(
c
)
require
.
NoError
(
t
,
err
)
err
=
m
.
AddL2Block
(
x
)
require
.
ErrorIs
(
t
,
err
,
ErrReorg
)
require
.
Equal
(
t
,
[]
*
types
.
Block
{
a
,
b
,
c
},
m
.
blocks
)
require
.
Equal
(
t
,
[]
*
types
.
Block
{
a
,
b
,
c
},
m
.
blocks
)
}
}
...
@@ -111,16 +106,14 @@ func TestChannelManagerReturnsErrReorgWhenDrained(t *testing.T) {
...
@@ -111,16 +106,14 @@ func TestChannelManagerReturnsErrReorgWhenDrained(t *testing.T) {
a
:=
newMiniL2Block
(
0
)
a
:=
newMiniL2Block
(
0
)
x
:=
newMiniL2BlockWithNumberParent
(
0
,
big
.
NewInt
(
1
),
common
.
Hash
{
0xff
})
x
:=
newMiniL2BlockWithNumberParent
(
0
,
big
.
NewInt
(
1
),
common
.
Hash
{
0xff
})
err
:=
m
.
AddL2Block
(
a
)
require
.
NoError
(
t
,
m
.
AddL2Block
(
a
))
require
.
NoError
(
t
,
err
)
_
,
err
=
m
.
TxData
(
eth
.
BlockID
{})
_
,
err
:
=
m
.
TxData
(
eth
.
BlockID
{})
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
_
,
err
=
m
.
TxData
(
eth
.
BlockID
{})
_
,
err
=
m
.
TxData
(
eth
.
BlockID
{})
require
.
ErrorIs
(
t
,
err
,
io
.
EOF
)
require
.
ErrorIs
(
t
,
err
,
io
.
EOF
)
err
=
m
.
AddL2Block
(
x
)
require
.
ErrorIs
(
t
,
m
.
AddL2Block
(
x
),
ErrReorg
)
require
.
ErrorIs
(
t
,
err
,
ErrReorg
)
}
}
// TestChannelManagerNextTxData checks the nextTxData function.
// TestChannelManagerNextTxData checks the nextTxData function.
...
@@ -136,8 +129,7 @@ func TestChannelManagerNextTxData(t *testing.T) {
...
@@ -136,8 +129,7 @@ func TestChannelManagerNextTxData(t *testing.T) {
// Set the pending channel
// Set the pending channel
// The nextTxData function should still return EOF
// The nextTxData function should still return EOF
// since the pending channel has no frames
// since the pending channel has no frames
err
=
m
.
ensurePendingChannel
(
eth
.
BlockID
{})
require
.
NoError
(
t
,
m
.
ensurePendingChannel
(
eth
.
BlockID
{}))
require
.
NoError
(
t
,
err
)
returnedTxData
,
err
=
m
.
nextTxData
()
returnedTxData
,
err
=
m
.
nextTxData
()
require
.
ErrorIs
(
t
,
err
,
io
.
EOF
)
require
.
ErrorIs
(
t
,
err
,
io
.
EOF
)
require
.
Equal
(
t
,
txData
{},
returnedTxData
)
require
.
Equal
(
t
,
txData
{},
returnedTxData
)
...
@@ -164,8 +156,10 @@ func TestChannelManagerNextTxData(t *testing.T) {
...
@@ -164,8 +156,10 @@ func TestChannelManagerNextTxData(t *testing.T) {
require
.
Equal
(
t
,
expectedTxData
,
m
.
pendingTransactions
[
expectedChannelID
])
require
.
Equal
(
t
,
expectedTxData
,
m
.
pendingTransactions
[
expectedChannelID
])
}
}
// TestClearChannelManager tests clearing the channel manager.
// TestChannelManager_Clear tests clearing the channel manager.
func
TestClearChannelManager
(
t
*
testing
.
T
)
{
func
TestChannelManager_Clear
(
t
*
testing
.
T
)
{
require
:=
require
.
New
(
t
)
// Create a channel manager
// Create a channel manager
log
:=
testlog
.
Logger
(
t
,
log
.
LvlCrit
)
log
:=
testlog
.
Logger
(
t
,
log
.
LvlCrit
)
rng
:=
rand
.
New
(
rand
.
NewSource
(
time
.
Now
()
.
UnixNano
()))
rng
:=
rand
.
New
(
rand
.
NewSource
(
time
.
Now
()
.
UnixNano
()))
...
@@ -176,15 +170,17 @@ func TestClearChannelManager(t *testing.T) {
...
@@ -176,15 +170,17 @@ func TestClearChannelManager(t *testing.T) {
ChannelTimeout
:
10
,
ChannelTimeout
:
10
,
// Have to set the max frame size here otherwise the channel builder would not
// Have to set the max frame size here otherwise the channel builder would not
// be able to output any frames
// be able to output any frames
MaxFrameSize
:
1
,
MaxFrameSize
:
24
,
TargetFrameSize
:
24
,
ApproxComprRatio
:
1.0
,
})
})
// Channel Manager state should be empty by default
// Channel Manager state should be empty by default
require
.
Empty
(
t
,
m
.
blocks
)
require
.
Empty
(
m
.
blocks
)
require
.
Equal
(
t
,
common
.
Hash
{},
m
.
tip
)
require
.
Equal
(
common
.
Hash
{},
m
.
tip
)
require
.
Nil
(
t
,
m
.
pendingChannel
)
require
.
Nil
(
m
.
pendingChannel
)
require
.
Empty
(
t
,
m
.
pendingTransactions
)
require
.
Empty
(
m
.
pendingTransactions
)
require
.
Empty
(
t
,
m
.
confirmedTransactions
)
require
.
Empty
(
m
.
confirmedTransactions
)
// Add a block to the channel manager
// Add a block to the channel manager
a
,
_
:=
derivetest
.
RandomL2Block
(
rng
,
4
)
a
,
_
:=
derivetest
.
RandomL2Block
(
rng
,
4
)
...
@@ -193,28 +189,25 @@ func TestClearChannelManager(t *testing.T) {
...
@@ -193,28 +189,25 @@ func TestClearChannelManager(t *testing.T) {
Hash
:
a
.
Hash
(),
Hash
:
a
.
Hash
(),
Number
:
a
.
NumberU64
(),
Number
:
a
.
NumberU64
(),
}
}
err
:=
m
.
AddL2Block
(
a
)
require
.
NoError
(
m
.
AddL2Block
(
a
))
require
.
NoError
(
t
,
err
)
// Make sure there is a channel builder
// Make sure there is a channel builder
err
=
m
.
ensurePendingChannel
(
l1BlockID
)
require
.
NoError
(
m
.
ensurePendingChannel
(
l1BlockID
))
require
.
NoError
(
t
,
err
)
require
.
NotNil
(
m
.
pendingChannel
)
require
.
NotNil
(
t
,
m
.
pendingChannel
)
require
.
Len
(
m
.
confirmedTransactions
,
0
)
require
.
Equal
(
t
,
0
,
len
(
m
.
confirmedTransactions
))
// Process the blocks
// Process the blocks
// We should have a pending channel with 1 frame
// We should have a pending channel with 1 frame
// and no more blocks since processBlocks consumes
// and no more blocks since processBlocks consumes
// the list
// the list
err
=
m
.
processBlocks
()
require
.
NoError
(
m
.
processBlocks
())
require
.
NoError
(
t
,
err
)
require
.
NoError
(
m
.
pendingChannel
.
co
.
Flush
())
err
=
m
.
pendingChannel
.
OutputFrames
()
require
.
NoError
(
m
.
pendingChannel
.
OutputFrames
())
require
.
NoError
(
t
,
err
)
_
,
err
:=
m
.
nextTxData
()
_
,
err
=
m
.
nextTxData
()
require
.
NoError
(
err
)
require
.
NoError
(
t
,
err
)
require
.
Len
(
m
.
blocks
,
0
)
require
.
Equal
(
t
,
0
,
len
(
m
.
blocks
))
require
.
Equal
(
newL1Tip
,
m
.
tip
)
require
.
Equal
(
t
,
newL1Tip
,
m
.
tip
)
require
.
Len
(
m
.
pendingTransactions
,
1
)
require
.
Equal
(
t
,
1
,
len
(
m
.
pendingTransactions
))
// Add a new block so we can test clearing
// Add a new block so we can test clearing
// the channel manager with a full state
// the channel manager with a full state
...
@@ -222,20 +215,19 @@ func TestClearChannelManager(t *testing.T) {
...
@@ -222,20 +215,19 @@ func TestClearChannelManager(t *testing.T) {
Number
:
big
.
NewInt
(
1
),
Number
:
big
.
NewInt
(
1
),
ParentHash
:
a
.
Hash
(),
ParentHash
:
a
.
Hash
(),
},
nil
,
nil
,
nil
,
nil
)
},
nil
,
nil
,
nil
,
nil
)
err
=
m
.
AddL2Block
(
b
)
require
.
NoError
(
m
.
AddL2Block
(
b
))
require
.
NoError
(
t
,
err
)
require
.
Len
(
m
.
blocks
,
1
)
require
.
Equal
(
t
,
1
,
len
(
m
.
blocks
))
require
.
Equal
(
b
.
Hash
(),
m
.
tip
)
require
.
Equal
(
t
,
b
.
Hash
(),
m
.
tip
)
// Clear the channel manager
// Clear the channel manager
m
.
Clear
()
m
.
Clear
()
// Check that the entire channel manager state cleared
// Check that the entire channel manager state cleared
require
.
Empty
(
t
,
m
.
blocks
)
require
.
Empty
(
m
.
blocks
)
require
.
Equal
(
t
,
common
.
Hash
{},
m
.
tip
)
require
.
Equal
(
common
.
Hash
{},
m
.
tip
)
require
.
Nil
(
t
,
m
.
pendingChannel
)
require
.
Nil
(
m
.
pendingChannel
)
require
.
Empty
(
t
,
m
.
pendingTransactions
)
require
.
Empty
(
m
.
pendingTransactions
)
require
.
Empty
(
t
,
m
.
confirmedTransactions
)
require
.
Empty
(
m
.
confirmedTransactions
)
}
}
// TestChannelManagerTxConfirmed checks the [ChannelManager.TxConfirmed] function.
// TestChannelManagerTxConfirmed checks the [ChannelManager.TxConfirmed] function.
...
@@ -251,8 +243,7 @@ func TestChannelManagerTxConfirmed(t *testing.T) {
...
@@ -251,8 +243,7 @@ func TestChannelManagerTxConfirmed(t *testing.T) {
// Let's add a valid pending transaction to the channel manager
// Let's add a valid pending transaction to the channel manager
// So we can demonstrate that TxConfirmed's correctness
// So we can demonstrate that TxConfirmed's correctness
err
:=
m
.
ensurePendingChannel
(
eth
.
BlockID
{})
require
.
NoError
(
t
,
m
.
ensurePendingChannel
(
eth
.
BlockID
{}))
require
.
NoError
(
t
,
err
)
channelID
:=
m
.
pendingChannel
.
ID
()
channelID
:=
m
.
pendingChannel
.
ID
()
frame
:=
frameData
{
frame
:=
frameData
{
data
:
[]
byte
{},
data
:
[]
byte
{},
...
@@ -270,7 +261,7 @@ func TestChannelManagerTxConfirmed(t *testing.T) {
...
@@ -270,7 +261,7 @@ func TestChannelManagerTxConfirmed(t *testing.T) {
require
.
Equal
(
t
,
expectedTxData
,
returnedTxData
)
require
.
Equal
(
t
,
expectedTxData
,
returnedTxData
)
require
.
Equal
(
t
,
0
,
m
.
pendingChannel
.
NumFrames
())
require
.
Equal
(
t
,
0
,
m
.
pendingChannel
.
NumFrames
())
require
.
Equal
(
t
,
expectedTxData
,
m
.
pendingTransactions
[
expectedChannelID
])
require
.
Equal
(
t
,
expectedTxData
,
m
.
pendingTransactions
[
expectedChannelID
])
require
.
Equal
(
t
,
1
,
len
(
m
.
pendingTransactions
)
)
require
.
Len
(
t
,
m
.
pendingTransactions
,
1
)
// An unknown pending transaction should not be marked as confirmed
// An unknown pending transaction should not be marked as confirmed
// and should not be removed from the pending transactions map
// and should not be removed from the pending transactions map
...
@@ -281,14 +272,14 @@ func TestChannelManagerTxConfirmed(t *testing.T) {
...
@@ -281,14 +272,14 @@ func TestChannelManagerTxConfirmed(t *testing.T) {
blockID
:=
eth
.
BlockID
{
Number
:
0
,
Hash
:
common
.
Hash
{
0x69
}}
blockID
:=
eth
.
BlockID
{
Number
:
0
,
Hash
:
common
.
Hash
{
0x69
}}
m
.
TxConfirmed
(
unknownTxID
,
blockID
)
m
.
TxConfirmed
(
unknownTxID
,
blockID
)
require
.
Empty
(
t
,
m
.
confirmedTransactions
)
require
.
Empty
(
t
,
m
.
confirmedTransactions
)
require
.
Equal
(
t
,
1
,
len
(
m
.
pendingTransactions
)
)
require
.
Len
(
t
,
m
.
pendingTransactions
,
1
)
// Now let's mark the pending transaction as confirmed
// Now let's mark the pending transaction as confirmed
// and check that it is removed from the pending transactions map
// and check that it is removed from the pending transactions map
// and added to the confirmed transactions map
// and added to the confirmed transactions map
m
.
TxConfirmed
(
expectedChannelID
,
blockID
)
m
.
TxConfirmed
(
expectedChannelID
,
blockID
)
require
.
Empty
(
t
,
m
.
pendingTransactions
)
require
.
Empty
(
t
,
m
.
pendingTransactions
)
require
.
Equal
(
t
,
1
,
len
(
m
.
confirmedTransactions
)
)
require
.
Len
(
t
,
m
.
confirmedTransactions
,
1
)
require
.
Equal
(
t
,
blockID
,
m
.
confirmedTransactions
[
expectedChannelID
])
require
.
Equal
(
t
,
blockID
,
m
.
confirmedTransactions
[
expectedChannelID
])
}
}
...
@@ -300,8 +291,7 @@ func TestChannelManagerTxFailed(t *testing.T) {
...
@@ -300,8 +291,7 @@ func TestChannelManagerTxFailed(t *testing.T) {
// Let's add a valid pending transaction to the channel
// Let's add a valid pending transaction to the channel
// manager so we can demonstrate correctness
// manager so we can demonstrate correctness
err
:=
m
.
ensurePendingChannel
(
eth
.
BlockID
{})
require
.
NoError
(
t
,
m
.
ensurePendingChannel
(
eth
.
BlockID
{}))
require
.
NoError
(
t
,
err
)
channelID
:=
m
.
pendingChannel
.
ID
()
channelID
:=
m
.
pendingChannel
.
ID
()
frame
:=
frameData
{
frame
:=
frameData
{
data
:
[]
byte
{},
data
:
[]
byte
{},
...
@@ -319,7 +309,7 @@ func TestChannelManagerTxFailed(t *testing.T) {
...
@@ -319,7 +309,7 @@ func TestChannelManagerTxFailed(t *testing.T) {
require
.
Equal
(
t
,
expectedTxData
,
returnedTxData
)
require
.
Equal
(
t
,
expectedTxData
,
returnedTxData
)
require
.
Equal
(
t
,
0
,
m
.
pendingChannel
.
NumFrames
())
require
.
Equal
(
t
,
0
,
m
.
pendingChannel
.
NumFrames
())
require
.
Equal
(
t
,
expectedTxData
,
m
.
pendingTransactions
[
expectedChannelID
])
require
.
Equal
(
t
,
expectedTxData
,
m
.
pendingTransactions
[
expectedChannelID
])
require
.
Equal
(
t
,
1
,
len
(
m
.
pendingTransactions
)
)
require
.
Len
(
t
,
m
.
pendingTransactions
,
1
)
// Trying to mark an unknown pending transaction as failed
// Trying to mark an unknown pending transaction as failed
// shouldn't modify state
// shouldn't modify state
...
@@ -348,8 +338,7 @@ func TestChannelManager_TxResend(t *testing.T) {
...
@@ -348,8 +338,7 @@ func TestChannelManager_TxResend(t *testing.T) {
a
,
_
:=
derivetest
.
RandomL2Block
(
rng
,
4
)
a
,
_
:=
derivetest
.
RandomL2Block
(
rng
,
4
)
err
:=
m
.
AddL2Block
(
a
)
require
.
NoError
(
m
.
AddL2Block
(
a
))
require
.
NoError
(
err
)
txdata0
,
err
:=
m
.
TxData
(
eth
.
BlockID
{})
txdata0
,
err
:=
m
.
TxData
(
eth
.
BlockID
{})
require
.
NoError
(
err
)
require
.
NoError
(
err
)
...
...
op-node/rollup/derive/channel_out.go
View file @
0aab6a5c
...
@@ -14,9 +14,17 @@ import (
...
@@ -14,9 +14,17 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rlp"
)
)
var
ErrMaxFrameSizeTooSmall
=
errors
.
New
(
"maxSize is too small to fit the fixed frame overhead"
)
var
ErrNotDepositTx
=
errors
.
New
(
"first transaction in block is not a deposit tx"
)
var
ErrNotDepositTx
=
errors
.
New
(
"first transaction in block is not a deposit tx"
)
var
ErrTooManyRLPBytes
=
errors
.
New
(
"batch would cause RLP bytes to go over limit"
)
var
ErrTooManyRLPBytes
=
errors
.
New
(
"batch would cause RLP bytes to go over limit"
)
// FrameV0OverHeadSize is the absolute minimum size of a frame.
// This is the fixed overhead frame size, calculated as specified
// in the [Frame Format] specs: 16 + 2 + 4 + 1 = 23 bytes.
//
// [Frame Format]: https://github.com/ethereum-optimism/optimism/blob/develop/specs/derivation.md#frame-format
const
FrameV0OverHeadSize
=
23
type
ChannelOut
struct
{
type
ChannelOut
struct
{
id
ChannelID
id
ChannelID
// Frame ID of the next frame to emit. Increment after emitting
// Frame ID of the next frame to emit. Increment after emitting
...
@@ -141,19 +149,23 @@ func (co *ChannelOut) Close() error {
...
@@ -141,19 +149,23 @@ func (co *ChannelOut) Close() error {
// OutputFrame writes a frame to w with a given max size and returns the frame
// OutputFrame writes a frame to w with a given max size and returns the frame
// number.
// number.
// Use `ReadyBytes`, `Flush`, and `Close` to modify the ready buffer.
// Use `ReadyBytes`, `Flush`, and `Close` to modify the ready buffer.
// Returns io.EOF when the channel is closed & there are no more frames
// Returns an error if the `maxSize` < FrameV0OverHeadSize.
// Returns io.EOF when the channel is closed & there are no more frames.
// Returns nil if there is still more buffered data.
// Returns nil if there is still more buffered data.
// Returns an
d
error if it ran into an error during processing.
// Returns an error if it ran into an error during processing.
func
(
co
*
ChannelOut
)
OutputFrame
(
w
*
bytes
.
Buffer
,
maxSize
uint64
)
(
uint16
,
error
)
{
func
(
co
*
ChannelOut
)
OutputFrame
(
w
*
bytes
.
Buffer
,
maxSize
uint64
)
(
uint16
,
error
)
{
f
:=
Frame
{
f
:=
Frame
{
ID
:
co
.
id
,
ID
:
co
.
id
,
FrameNumber
:
uint16
(
co
.
frame
),
FrameNumber
:
uint16
(
co
.
frame
),
}
}
// Check that the maxSize is large enough for the frame overhead size.
if
maxSize
<
FrameV0OverHeadSize
{
return
0
,
ErrMaxFrameSizeTooSmall
}
// Copy data from the local buffer into the frame data buffer
// Copy data from the local buffer into the frame data buffer
// Don't go past the maxSize with the fixed frame overhead.
maxDataSize
:=
maxSize
-
FrameV0OverHeadSize
// Fixed overhead: 16 + 2 + 4 + 1 = 23 bytes.
maxDataSize
:=
maxSize
-
23
if
maxDataSize
>
uint64
(
co
.
buf
.
Len
())
{
if
maxDataSize
>
uint64
(
co
.
buf
.
Len
())
{
maxDataSize
=
uint64
(
co
.
buf
.
Len
())
maxDataSize
=
uint64
(
co
.
buf
.
Len
())
// If we are closed & will not spill past the current frame
// If we are closed & will not spill past the current frame
...
...
op-node/rollup/derive/channel_out_test.go
View file @
0aab6a5c
...
@@ -29,6 +29,22 @@ func TestChannelOutAddBlock(t *testing.T) {
...
@@ -29,6 +29,22 @@ func TestChannelOutAddBlock(t *testing.T) {
})
})
}
}
// TestOutputFrameSmallMaxSize tests that calling [OutputFrame] with a small
// max size that is below the fixed frame size overhead of 23, will return
// an error.
func
TestOutputFrameSmallMaxSize
(
t
*
testing
.
T
)
{
cout
,
err
:=
NewChannelOut
()
require
.
NoError
(
t
,
err
)
// Call OutputFrame with the range of small max size values that err
var
w
bytes
.
Buffer
for
i
:=
0
;
i
<
23
;
i
++
{
fid
,
err
:=
cout
.
OutputFrame
(
&
w
,
uint64
(
i
))
require
.
ErrorIs
(
t
,
err
,
ErrMaxFrameSizeTooSmall
)
require
.
Zero
(
t
,
fid
)
}
}
// TestRLPByteLimit ensures that stream encoder is properly limiting the length.
// TestRLPByteLimit ensures that stream encoder is properly limiting the length.
// It will decode the input if `len(input) <= inputLimit`.
// It will decode the input if `len(input) <= inputLimit`.
func
TestRLPByteLimit
(
t
*
testing
.
T
)
{
func
TestRLPByteLimit
(
t
*
testing
.
T
)
{
...
...
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