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
dbf29ae2
Unverified
Commit
dbf29ae2
authored
Feb 24, 2023
by
mergify[bot]
Committed by
GitHub
Feb 24, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #4957 from ethereum-optimism/aj/l2geth-e2e
op-e2e: Introduce op-geth e2e test util
parents
096d9c2b
49c57bcf
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
223 additions
and
155 deletions
+223
-155
op_geth.go
op-e2e/op_geth.go
+203
-0
op_geth_test.go
op-e2e/op_geth_test.go
+20
-155
No files found.
op-e2e/op_geth.go
0 → 100644
View file @
dbf29ae2
package
op_e2e
import
(
"context"
"errors"
"fmt"
"math/big"
"reflect"
"testing"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/client"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-node/sources"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"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"
gn
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/stretchr/testify/require"
)
var
(
// ErrForkChoiceUpdatedNotValid is returned when a forkChoiceUpdated returns a status other than Valid
ErrForkChoiceUpdatedNotValid
=
errors
.
New
(
"forkChoiceUpdated status was not valid"
)
// ErrNewPayloadNotValid is returned when a newPayload call returns a status other than Valid, indicating the new block is invalid
ErrNewPayloadNotValid
=
errors
.
New
(
"newPayload status was not valid"
)
)
// OpGeth is an actor that functions as a l2 op-geth node
// It provides useful functions for advancing and querying the chain
type
OpGeth
struct
{
node
*
gn
.
Node
l2Engine
*
sources
.
EngineClient
L2Client
*
ethclient
.
Client
SystemConfig
eth
.
SystemConfig
L1ChainConfig
*
params
.
ChainConfig
L2ChainConfig
*
params
.
ChainConfig
L1Head
eth
.
BlockInfo
L2Head
*
eth
.
ExecutionPayload
sequenceNum
uint64
}
func
NewOpGeth
(
t
*
testing
.
T
,
ctx
context
.
Context
,
cfg
*
SystemConfig
)
(
*
OpGeth
,
error
)
{
logger
:=
testlog
.
Logger
(
t
,
log
.
LvlCrit
)
l1Genesis
,
err
:=
genesis
.
BuildL1DeveloperGenesis
(
cfg
.
DeployConfig
)
require
.
Nil
(
t
,
err
)
l1Block
:=
l1Genesis
.
ToBlock
()
l2Genesis
,
err
:=
genesis
.
BuildL2DeveloperGenesis
(
cfg
.
DeployConfig
,
l1Block
)
require
.
Nil
(
t
,
err
)
l2GenesisBlock
:=
l2Genesis
.
ToBlock
()
rollupGenesis
:=
rollup
.
Genesis
{
L1
:
eth
.
BlockID
{
Hash
:
l1Block
.
Hash
(),
Number
:
l1Block
.
NumberU64
(),
},
L2
:
eth
.
BlockID
{
Hash
:
l2GenesisBlock
.
Hash
(),
Number
:
l2GenesisBlock
.
NumberU64
(),
},
L2Time
:
l2GenesisBlock
.
Time
(),
SystemConfig
:
e2eutils
.
SystemConfigFromDeployConfig
(
cfg
.
DeployConfig
),
}
node
,
_
,
err
:=
initL2Geth
(
"l2"
,
big
.
NewInt
(
int64
(
cfg
.
DeployConfig
.
L2ChainID
)),
l2Genesis
,
cfg
.
JWTFilePath
)
require
.
Nil
(
t
,
err
)
require
.
Nil
(
t
,
node
.
Start
())
auth
:=
rpc
.
WithHTTPAuth
(
gn
.
NewJWTAuth
(
cfg
.
JWTSecret
))
l2Node
,
err
:=
client
.
NewRPC
(
ctx
,
logger
,
node
.
WSAuthEndpoint
(),
auth
)
require
.
Nil
(
t
,
err
)
// Finally create the engine client
l2Engine
,
err
:=
sources
.
NewEngineClient
(
l2Node
,
logger
,
nil
,
sources
.
EngineClientDefaultConfig
(
&
rollup
.
Config
{
Genesis
:
rollupGenesis
}),
)
require
.
Nil
(
t
,
err
)
l2Client
,
err
:=
ethclient
.
Dial
(
node
.
HTTPEndpoint
())
require
.
Nil
(
t
,
err
)
genesisPayload
,
err
:=
eth
.
BlockAsPayload
(
l2GenesisBlock
)
require
.
Nil
(
t
,
err
)
return
&
OpGeth
{
node
:
node
,
L2Client
:
l2Client
,
l2Engine
:
l2Engine
,
SystemConfig
:
rollupGenesis
.
SystemConfig
,
L1ChainConfig
:
l1Genesis
.
Config
,
L2ChainConfig
:
l2Genesis
.
Config
,
L1Head
:
l1Block
,
L2Head
:
genesisPayload
,
},
nil
}
func
(
d
*
OpGeth
)
Close
()
{
_
=
d
.
node
.
Close
()
d
.
l2Engine
.
Close
()
d
.
L2Client
.
Close
()
}
// AddL2Block Appends a new L2 block to the current chain including the specified transactions
// The L1Info transaction is automatically prepended to the created block
func
(
d
*
OpGeth
)
AddL2Block
(
ctx
context
.
Context
,
txs
...*
types
.
Transaction
)
(
*
eth
.
ExecutionPayload
,
error
)
{
attrs
,
err
:=
d
.
CreatePayloadAttributes
(
txs
...
)
if
err
!=
nil
{
return
nil
,
err
}
res
,
err
:=
d
.
StartBlockBuilding
(
ctx
,
attrs
)
if
err
!=
nil
{
return
nil
,
err
}
payload
,
err
:=
d
.
l2Engine
.
GetPayload
(
ctx
,
*
res
.
PayloadID
)
if
err
!=
nil
{
return
nil
,
err
}
if
!
reflect
.
DeepEqual
(
payload
.
Transactions
,
attrs
.
Transactions
)
{
return
nil
,
errors
.
New
(
"required transactions were not included"
)
}
status
,
err
:=
d
.
l2Engine
.
NewPayload
(
ctx
,
payload
)
if
err
!=
nil
{
return
nil
,
err
}
if
status
.
Status
!=
eth
.
ExecutionValid
{
return
nil
,
fmt
.
Errorf
(
"%w: %s"
,
ErrNewPayloadNotValid
,
status
.
Status
)
}
fc
:=
eth
.
ForkchoiceState
{
HeadBlockHash
:
payload
.
BlockHash
,
SafeBlockHash
:
payload
.
BlockHash
,
}
res
,
err
=
d
.
l2Engine
.
ForkchoiceUpdate
(
ctx
,
&
fc
,
nil
)
if
err
!=
nil
{
return
nil
,
err
}
if
res
.
PayloadStatus
.
Status
!=
eth
.
ExecutionValid
{
return
nil
,
fmt
.
Errorf
(
"%w: %s"
,
ErrForkChoiceUpdatedNotValid
,
res
.
PayloadStatus
.
Status
)
}
d
.
L2Head
=
payload
d
.
sequenceNum
=
d
.
sequenceNum
+
1
return
payload
,
nil
}
// StartBlockBuilding begins block building for the specified PayloadAttributes by sending a engine_forkChoiceUpdated call.
// The current L2Head is used as the parent of the new block.
// ErrForkChoiceUpdatedNotValid is returned if the forkChoiceUpdate call returns a status other than valid.
func
(
d
*
OpGeth
)
StartBlockBuilding
(
ctx
context
.
Context
,
attrs
*
eth
.
PayloadAttributes
)
(
*
eth
.
ForkchoiceUpdatedResult
,
error
)
{
fc
:=
eth
.
ForkchoiceState
{
HeadBlockHash
:
d
.
L2Head
.
BlockHash
,
SafeBlockHash
:
d
.
L2Head
.
BlockHash
,
}
res
,
err
:=
d
.
l2Engine
.
ForkchoiceUpdate
(
ctx
,
&
fc
,
attrs
)
if
err
!=
nil
{
return
nil
,
err
}
if
res
.
PayloadStatus
.
Status
!=
eth
.
ExecutionValid
{
return
nil
,
fmt
.
Errorf
(
"%w: %s"
,
ErrForkChoiceUpdatedNotValid
,
res
.
PayloadStatus
.
Status
)
}
if
res
.
PayloadID
==
nil
{
return
nil
,
errors
.
New
(
"forkChoiceUpdated returned nil PayloadID"
)
}
return
res
,
nil
}
// CreatePayloadAttributes creates a valid PayloadAttributes containing a L1Info deposit transaction followed by the supplied transactions.
func
(
d
*
OpGeth
)
CreatePayloadAttributes
(
txs
...*
types
.
Transaction
)
(
*
eth
.
PayloadAttributes
,
error
)
{
timestamp
:=
d
.
L2Head
.
Timestamp
+
2
l1Info
,
err
:=
derive
.
L1InfoDepositBytes
(
d
.
sequenceNum
,
d
.
L1Head
,
d
.
SystemConfig
,
false
)
if
err
!=
nil
{
return
nil
,
err
}
var
txBytes
[]
hexutil
.
Bytes
txBytes
=
append
(
txBytes
,
l1Info
)
for
_
,
tx
:=
range
txs
{
bin
,
err
:=
tx
.
MarshalBinary
()
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"tx marshalling failed: %w"
,
err
)
}
txBytes
=
append
(
txBytes
,
bin
)
}
attrs
:=
eth
.
PayloadAttributes
{
Timestamp
:
timestamp
,
Transactions
:
txBytes
,
NoTxPool
:
true
,
GasLimit
:
(
*
eth
.
Uint64Quantity
)(
&
d
.
SystemConfig
.
GasLimit
),
}
return
&
attrs
,
nil
}
op-e2e/op_geth_test.go
View file @
dbf29ae2
...
@@ -6,91 +6,29 @@ import (
...
@@ -6,91 +6,29 @@ import (
"testing"
"testing"
"time"
"time"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/client"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-node/sources"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum/go-ethereum/common"
"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/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
gn
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/require"
)
)
// TestMissingGasLimit tests that op-geth cannot build a block without gas limit while optimism is active in the chain config.
// TestMissingGasLimit tests that op-geth cannot build a block without gas limit while optimism is active in the chain config.
func
TestMissingGasLimit
(
t
*
testing
.
T
)
{
func
TestMissingGasLimit
(
t
*
testing
.
T
)
{
// Setup an L2 EE and create a client connection to the engine.
// We also need to setup a L1 Genesis to create the rollup genesis.
log
:=
testlog
.
Logger
(
t
,
log
.
LvlCrit
)
cfg
:=
DefaultSystemConfig
(
t
)
cfg
:=
DefaultSystemConfig
(
t
)
cfg
.
DeployConfig
.
FundDevAccounts
=
false
cfg
.
DeployConfig
.
FundDevAccounts
=
false
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
60
*
time
.
Second
)
l1Genesis
,
err
:=
genesis
.
BuildL1DeveloperGenesis
(
cfg
.
DeployConfig
)
require
.
Nil
(
t
,
err
)
l1Block
:=
l1Genesis
.
ToBlock
()
l2Genesis
,
err
:=
genesis
.
BuildL2DeveloperGenesis
(
cfg
.
DeployConfig
,
l1Block
)
require
.
Nil
(
t
,
err
)
l2GenesisBlock
:=
l2Genesis
.
ToBlock
()
rollupGenesis
:=
rollup
.
Genesis
{
L1
:
eth
.
BlockID
{
Hash
:
l1Block
.
Hash
(),
Number
:
l1Block
.
NumberU64
(),
},
L2
:
eth
.
BlockID
{
Hash
:
l2GenesisBlock
.
Hash
(),
Number
:
l2GenesisBlock
.
NumberU64
(),
},
L2Time
:
l2GenesisBlock
.
Time
(),
SystemConfig
:
e2eutils
.
SystemConfigFromDeployConfig
(
cfg
.
DeployConfig
),
}
node
,
_
,
err
:=
initL2Geth
(
"l2"
,
big
.
NewInt
(
int64
(
cfg
.
DeployConfig
.
L2ChainID
)),
l2Genesis
,
writeDefaultJWT
(
t
))
require
.
Nil
(
t
,
err
)
require
.
Nil
(
t
,
node
.
Start
())
defer
node
.
Close
()
auth
:=
rpc
.
WithHTTPAuth
(
gn
.
NewJWTAuth
(
testingJWTSecret
))
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
2
*
time
.
Second
)
defer
cancel
()
defer
cancel
()
l2Node
,
err
:=
client
.
NewRPC
(
ctx
,
log
,
node
.
WSAuthEndpoint
(),
auth
)
opGeth
,
err
:=
NewOpGeth
(
t
,
ctx
,
&
cfg
)
require
.
Nil
(
t
,
err
)
require
.
NoError
(
t
,
err
)
defer
opGeth
.
Close
()
// Finally create the engine client
client
,
err
:=
sources
.
NewEngineClient
(
l2Node
,
log
,
nil
,
sources
.
EngineClientDefaultConfig
(
&
rollup
.
Config
{
Genesis
:
rollupGenesis
}),
)
require
.
Nil
(
t
,
err
)
attrs
:=
eth
.
PayloadAttributes
{
attrs
,
err
:=
opGeth
.
CreatePayloadAttributes
()
Timestamp
:
hexutil
.
Uint64
(
l2GenesisBlock
.
Time
()
+
2
),
require
.
NoError
(
t
,
err
)
Transactions
:
[]
hexutil
.
Bytes
{},
// Remove the GasLimit from the otherwise valid attributes
NoTxPool
:
true
,
attrs
.
GasLimit
=
nil
GasLimit
:
nil
,
// no gas limit
}
ctx
,
cancel
=
context
.
WithTimeout
(
context
.
Background
(),
2
*
time
.
Second
)
defer
cancel
()
fc
:=
eth
.
ForkchoiceState
{
res
,
err
:=
opGeth
.
StartBlockBuilding
(
ctx
,
attrs
)
HeadBlockHash
:
l2GenesisBlock
.
Hash
(),
SafeBlockHash
:
l2GenesisBlock
.
Hash
(),
}
res
,
err
:=
client
.
ForkchoiceUpdate
(
ctx
,
&
fc
,
&
attrs
)
require
.
ErrorIs
(
t
,
err
,
eth
.
InputError
{})
require
.
ErrorIs
(
t
,
err
,
eth
.
InputError
{})
require
.
Equal
(
t
,
eth
.
InvalidPayloadAttributes
,
err
.
(
eth
.
InputError
)
.
Code
)
require
.
Equal
(
t
,
eth
.
InvalidPayloadAttributes
,
err
.
(
eth
.
InputError
)
.
Code
)
require
.
Nil
(
t
,
res
)
require
.
Nil
(
t
,
res
)
...
@@ -99,109 +37,36 @@ func TestMissingGasLimit(t *testing.T) {
...
@@ -99,109 +37,36 @@ func TestMissingGasLimit(t *testing.T) {
// TestInvalidDepositInFCU runs an invalid deposit through a FCU/GetPayload/NewPayload/FCU set of calls.
// TestInvalidDepositInFCU runs an invalid deposit through a FCU/GetPayload/NewPayload/FCU set of calls.
// This tests that deposits must always allow the block to be built even if they are invalid.
// This tests that deposits must always allow the block to be built even if they are invalid.
func
TestInvalidDepositInFCU
(
t
*
testing
.
T
)
{
func
TestInvalidDepositInFCU
(
t
*
testing
.
T
)
{
// Setup an L2 EE and create a client connection to the engine.
// We also need to setup a L1 Genesis to create the rollup genesis.
log
:=
testlog
.
Logger
(
t
,
log
.
LvlCrit
)
cfg
:=
DefaultSystemConfig
(
t
)
cfg
:=
DefaultSystemConfig
(
t
)
cfg
.
DeployConfig
.
FundDevAccounts
=
false
cfg
.
DeployConfig
.
FundDevAccounts
=
false
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
60
*
time
.
Second
)
l1Genesis
,
err
:=
genesis
.
BuildL1DeveloperGenesis
(
cfg
.
DeployConfig
)
require
.
Nil
(
t
,
err
)
l1Block
:=
l1Genesis
.
ToBlock
()
l2Genesis
,
err
:=
genesis
.
BuildL2DeveloperGenesis
(
cfg
.
DeployConfig
,
l1Block
)
require
.
Nil
(
t
,
err
)
l2GenesisBlock
:=
l2Genesis
.
ToBlock
()
rollupGenesis
:=
rollup
.
Genesis
{
L1
:
eth
.
BlockID
{
Hash
:
l1Block
.
Hash
(),
Number
:
l1Block
.
NumberU64
(),
},
L2
:
eth
.
BlockID
{
Hash
:
l2GenesisBlock
.
Hash
(),
Number
:
l2GenesisBlock
.
NumberU64
(),
},
L2Time
:
l2GenesisBlock
.
Time
(),
SystemConfig
:
e2eutils
.
SystemConfigFromDeployConfig
(
cfg
.
DeployConfig
),
}
node
,
_
,
err
:=
initL2Geth
(
"l2"
,
big
.
NewInt
(
int64
(
cfg
.
DeployConfig
.
L2ChainID
)),
l2Genesis
,
writeDefaultJWT
(
t
))
require
.
Nil
(
t
,
err
)
require
.
Nil
(
t
,
node
.
Start
())
defer
node
.
Close
()
auth
:=
rpc
.
WithHTTPAuth
(
gn
.
NewJWTAuth
(
testingJWTSecret
))
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
2
*
time
.
Second
)
defer
cancel
()
defer
cancel
()
l2Node
,
err
:=
client
.
NewRPC
(
ctx
,
log
,
node
.
WSAuthEndpoint
(),
auth
)
opGeth
,
err
:=
NewOpGeth
(
t
,
ctx
,
&
cfg
)
require
.
Nil
(
t
,
err
)
require
.
NoError
(
t
,
err
)
defer
opGeth
.
Close
()
// Finally create the engine client
client
,
err
:=
sources
.
NewEngineClient
(
l2Node
,
log
,
nil
,
sources
.
EngineClientDefaultConfig
(
&
rollup
.
Config
{
Genesis
:
rollupGenesis
}),
)
require
.
Nil
(
t
,
err
)
// Create the test data (L1 Info Tx and then always failing deposit)
l1Info
,
err
:=
derive
.
L1InfoDepositBytes
(
1
,
l1Block
,
rollupGenesis
.
SystemConfig
,
false
)
require
.
Nil
(
t
,
err
)
// Create a deposit from alice that will always fail (not enough funds)
// Create a deposit from alice that will always fail (not enough funds)
fromAddr
:=
cfg
.
Secrets
.
Addresses
()
.
Alice
fromAddr
:=
cfg
.
Secrets
.
Addresses
()
.
Alice
l2Client
,
err
:=
ethclient
.
Dial
(
node
.
HTTPEndpoint
())
balance
,
err
:=
opGeth
.
L2Client
.
BalanceAt
(
ctx
,
fromAddr
,
nil
)
require
.
Nil
(
t
,
err
)
balance
,
err
:=
l2Client
.
BalanceAt
(
ctx
,
fromAddr
,
nil
)
require
.
Nil
(
t
,
err
)
require
.
Nil
(
t
,
err
)
require
.
Equal
(
t
,
0
,
balance
.
Cmp
(
common
.
Big0
))
require
.
Equal
(
t
,
0
,
balance
.
Cmp
(
common
.
Big0
))
badDepositTx
:=
types
.
NewTx
(
&
types
.
DepositTx
{
badDepositTx
:=
types
.
NewTx
(
&
types
.
DepositTx
{
// TODO: Source Hash
SourceHash
:
opGeth
.
L1Head
.
Hash
(),
From
:
fromAddr
,
From
:
fromAddr
,
To
:
&
fromAddr
,
// send it to ourselves
To
:
&
fromAddr
,
// send it to ourselves
Value
:
big
.
NewInt
(
params
.
Ether
),
Value
:
big
.
NewInt
(
params
.
Ether
),
Gas
:
25000
,
Gas
:
25000
,
IsSystemTransaction
:
false
,
IsSystemTransaction
:
false
,
})
})
badDeposit
,
err
:=
badDepositTx
.
MarshalBinary
()
require
.
Nil
(
t
,
err
)
attrs
:=
eth
.
PayloadAttributes
{
Timestamp
:
hexutil
.
Uint64
(
l2GenesisBlock
.
Time
()
+
2
),
Transactions
:
[]
hexutil
.
Bytes
{
l1Info
,
badDeposit
},
NoTxPool
:
true
,
GasLimit
:
(
*
eth
.
Uint64Quantity
)(
&
rollupGenesis
.
SystemConfig
.
GasLimit
),
}
// Go through the flow of FCU, GetPayload, NewPayload, FCU
// We are inserting a block with an invalid deposit.
// We are inserting a block with an invalid deposit.
// The invalid deposit should still remain in the block.
// The invalid deposit should still remain in the block.
ctx
,
cancel
=
context
.
WithTimeout
(
context
.
Background
(),
2
*
time
.
Second
)
_
,
err
=
opGeth
.
AddL2Block
(
ctx
,
badDepositTx
)
defer
cancel
(
)
require
.
NoError
(
t
,
err
)
fc
:=
eth
.
ForkchoiceState
{
// Deposit tx was included, but Alice still shouldn't have any ETH
HeadBlockHash
:
l2GenesisBlock
.
Hash
(),
balance
,
err
=
opGeth
.
L2Client
.
BalanceAt
(
ctx
,
fromAddr
,
nil
)
SafeBlockHash
:
l2GenesisBlock
.
Hash
(),
}
res
,
err
:=
client
.
ForkchoiceUpdate
(
ctx
,
&
fc
,
&
attrs
)
require
.
Nil
(
t
,
err
)
require
.
Nil
(
t
,
err
)
require
.
Equal
(
t
,
eth
.
ExecutionValid
,
res
.
PayloadStatus
.
Status
)
require
.
Equal
(
t
,
0
,
balance
.
Cmp
(
common
.
Big0
))
require
.
NotNil
(
t
,
res
.
PayloadID
)
payload
,
err
:=
client
.
GetPayload
(
ctx
,
*
res
.
PayloadID
)
require
.
Nil
(
t
,
err
)
require
.
NotNil
(
t
,
payload
)
require
.
Equal
(
t
,
payload
.
Transactions
,
attrs
.
Transactions
)
// Ensure we don't drop the transactions
status
,
err
:=
client
.
NewPayload
(
ctx
,
payload
)
require
.
Nil
(
t
,
err
)
require
.
Equal
(
t
,
eth
.
ExecutionValid
,
status
.
Status
)
fc
.
HeadBlockHash
=
payload
.
BlockHash
res
,
err
=
client
.
ForkchoiceUpdate
(
ctx
,
&
fc
,
nil
)
require
.
Nil
(
t
,
err
)
require
.
Equal
(
t
,
eth
.
ExecutionValid
,
res
.
PayloadStatus
.
Status
)
}
}
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