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
9ee1d5c2
Unverified
Commit
9ee1d5c2
authored
Apr 06, 2023
by
Adrian Sutton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
op-program: Implement oracle backed engine API backend
parent
5eae8164
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
469 additions
and
22 deletions
+469
-22
engine_backend.go
op-program/l2/engine_backend.go
+200
-0
engine_backend_test.go
op-program/l2/engine_backend_test.go
+235
-0
block_processor.go
op-program/l2/engineapi/block_processor.go
+2
-2
l2_engine_api.go
op-program/l2/engineapi/l2_engine_api.go
+2
-3
l2_engine_api_tests.go
op-program/l2/engineapi/test/l2_engine_api_tests.go
+16
-16
oracle.go
op-program/l2/oracle.go
+14
-1
No files found.
op-program/l2/engine_backend.go
0 → 100644
View file @
9ee1d5c2
package
l2
import
(
"fmt"
"math/big"
"github.com/ethereum-optimism/optimism/op-program/l2/engineapi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/beacon"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
)
type
OracleBackedL2Chain
struct
{
log
log
.
Logger
oracle
Oracle
chainCfg
*
params
.
ChainConfig
engine
consensus
.
Engine
head
*
types
.
Header
safe
*
types
.
Header
finalized
*
types
.
Header
vmCfg
vm
.
Config
// Inserted blocks
blocks
map
[
common
.
Hash
]
*
types
.
Block
db
ethdb
.
KeyValueStore
}
var
_
engineapi
.
EngineBackend
=
(
*
OracleBackedL2Chain
)(
nil
)
func
NewOracleBackedL2Chain
(
logger
log
.
Logger
,
oracle
Oracle
,
chainCfg
*
params
.
ChainConfig
,
l2Head
common
.
Hash
)
(
*
OracleBackedL2Chain
,
error
)
{
head
,
err
:=
oracle
.
BlockByHash
(
l2Head
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"loading l2 head: %w"
,
err
)
}
return
&
OracleBackedL2Chain
{
log
:
logger
,
oracle
:
oracle
,
chainCfg
:
chainCfg
,
engine
:
beacon
.
New
(
nil
),
// Treat the agreed starting head as finalized - nothing before it can be disputed
head
:
head
.
Header
(),
safe
:
head
.
Header
(),
finalized
:
head
.
Header
(),
blocks
:
make
(
map
[
common
.
Hash
]
*
types
.
Block
),
db
:
NewOracleBackedDB
(
oracle
),
},
nil
}
func
(
o
*
OracleBackedL2Chain
)
CurrentHeader
()
*
types
.
Header
{
return
o
.
head
}
func
(
o
*
OracleBackedL2Chain
)
GetHeaderByNumber
(
n
uint64
)
*
types
.
Header
{
// Walk back from current head to the requested block number
h
:=
o
.
head
if
h
.
Number
.
Uint64
()
<
n
{
return
nil
}
for
h
.
Number
.
Uint64
()
>
n
{
h
=
o
.
GetHeaderByHash
(
h
.
ParentHash
)
}
return
h
}
func
(
o
*
OracleBackedL2Chain
)
GetTd
(
hash
common
.
Hash
,
number
uint64
)
*
big
.
Int
{
// Difficulty is always 0 post-merge and bedrock starts post-merge so total difficulty also always 0
return
common
.
Big0
}
func
(
o
*
OracleBackedL2Chain
)
CurrentSafeBlock
()
*
types
.
Header
{
return
o
.
safe
}
func
(
o
*
OracleBackedL2Chain
)
CurrentFinalBlock
()
*
types
.
Header
{
return
o
.
finalized
}
func
(
o
*
OracleBackedL2Chain
)
GetHeaderByHash
(
hash
common
.
Hash
)
*
types
.
Header
{
block
:=
o
.
GetBlockByHash
(
hash
)
if
block
==
nil
{
return
nil
}
return
block
.
Header
()
}
func
(
o
*
OracleBackedL2Chain
)
GetBlockByHash
(
hash
common
.
Hash
)
*
types
.
Block
{
// Check inserted blocks
block
,
ok
:=
o
.
blocks
[
hash
]
if
ok
{
return
block
}
// Retrieve from the oracle
block
,
err
:=
o
.
oracle
.
BlockByHash
(
hash
)
if
err
!=
nil
{
handleError
(
err
)
}
if
block
==
nil
{
return
nil
}
return
block
}
func
(
o
*
OracleBackedL2Chain
)
GetBlock
(
hash
common
.
Hash
,
number
uint64
)
*
types
.
Block
{
block
:=
o
.
GetBlockByHash
(
hash
)
if
block
==
nil
{
return
nil
}
if
block
.
NumberU64
()
!=
number
{
return
nil
}
return
block
}
func
(
o
*
OracleBackedL2Chain
)
GetHeader
(
hash
common
.
Hash
,
u
uint64
)
*
types
.
Header
{
block
:=
o
.
GetBlock
(
hash
,
u
)
if
block
==
nil
{
return
nil
}
return
block
.
Header
()
}
func
(
o
*
OracleBackedL2Chain
)
HasBlockAndState
(
hash
common
.
Hash
,
number
uint64
)
bool
{
block
:=
o
.
GetBlock
(
hash
,
number
)
return
block
!=
nil
}
func
(
o
*
OracleBackedL2Chain
)
GetCanonicalHash
(
n
uint64
)
common
.
Hash
{
header
:=
o
.
GetHeaderByNumber
(
n
)
if
header
==
nil
{
return
common
.
Hash
{}
}
return
header
.
Hash
()
}
func
(
o
*
OracleBackedL2Chain
)
GetVMConfig
()
*
vm
.
Config
{
return
&
o
.
vmCfg
}
func
(
o
*
OracleBackedL2Chain
)
Config
()
*
params
.
ChainConfig
{
return
o
.
chainCfg
}
func
(
o
*
OracleBackedL2Chain
)
Engine
()
consensus
.
Engine
{
return
o
.
engine
}
func
(
o
*
OracleBackedL2Chain
)
StateAt
(
root
common
.
Hash
)
(
*
state
.
StateDB
,
error
)
{
return
state
.
New
(
root
,
state
.
NewDatabase
(
rawdb
.
NewDatabase
(
o
.
db
)),
nil
)
}
func
(
o
*
OracleBackedL2Chain
)
InsertBlockWithoutSetHead
(
block
*
types
.
Block
)
error
{
processor
,
err
:=
engineapi
.
NewBlockProcessorFromHeader
(
o
,
block
.
Header
())
if
err
!=
nil
{
return
err
}
for
i
,
tx
:=
range
block
.
Transactions
()
{
err
=
processor
.
AddTx
(
tx
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"invalid transaction (%d): %w"
,
i
,
err
)
}
}
expected
,
err
:=
processor
.
Assemble
()
if
err
!=
nil
{
return
fmt
.
Errorf
(
"invalid block: %w"
,
err
)
}
if
expected
.
Hash
()
!=
block
.
Hash
()
{
return
fmt
.
Errorf
(
"block root mismatch, expected: %v, actual: %v"
,
expected
.
Hash
(),
block
.
Hash
())
}
err
=
processor
.
Commit
()
if
err
!=
nil
{
return
fmt
.
Errorf
(
"commit block: %w"
,
err
)
}
o
.
blocks
[
block
.
Hash
()]
=
block
return
nil
}
func
(
o
*
OracleBackedL2Chain
)
SetCanonical
(
head
*
types
.
Block
)
(
common
.
Hash
,
error
)
{
o
.
head
=
head
.
Header
()
return
head
.
Hash
(),
nil
}
func
(
o
*
OracleBackedL2Chain
)
SetFinalized
(
header
*
types
.
Header
)
{
o
.
finalized
=
header
}
func
(
o
*
OracleBackedL2Chain
)
SetSafe
(
header
*
types
.
Header
)
{
o
.
safe
=
header
}
func
handleError
(
err
error
)
{
panic
(
err
)
}
op-program/l2/engine_backend_test.go
0 → 100644
View file @
9ee1d5c2
package
l2
import
(
"math/big"
"testing"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-program/l2/engineapi"
"github.com/ethereum-optimism/optimism/op-program/l2/engineapi/test"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/beacon"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
)
var
fundedKey
,
_
=
crypto
.
GenerateKey
()
var
fundedAddress
=
crypto
.
PubkeyToAddress
(
fundedKey
.
PublicKey
)
var
targetAddress
=
common
.
HexToAddress
(
"0x001122334455"
)
func
TestInitialState
(
t
*
testing
.
T
)
{
blocks
,
chain
:=
setupOracleBackedChain
(
t
,
5
)
head
:=
blocks
[
5
]
require
.
Equal
(
t
,
head
.
Header
(),
chain
.
CurrentHeader
())
require
.
Equal
(
t
,
head
.
Header
(),
chain
.
CurrentSafeBlock
())
require
.
Equal
(
t
,
head
.
Header
(),
chain
.
CurrentFinalBlock
())
}
func
TestGetBlocks
(
t
*
testing
.
T
)
{
blocks
,
chain
:=
setupOracleBackedChain
(
t
,
5
)
for
i
,
block
:=
range
blocks
{
blockNumber
:=
uint64
(
i
)
assertBlockDataAvailable
(
t
,
chain
,
block
,
blockNumber
)
require
.
Equal
(
t
,
block
.
Hash
(),
chain
.
GetCanonicalHash
(
blockNumber
),
"get canonical hash for block %v"
,
blockNumber
)
}
}
func
TestUnknownBlock
(
t
*
testing
.
T
)
{
_
,
chain
:=
setupOracleBackedChain
(
t
,
1
)
hash
:=
common
.
HexToHash
(
"0x556677881122"
)
blockNumber
:=
uint64
(
1
)
require
.
Nil
(
t
,
chain
.
GetBlockByHash
(
hash
))
require
.
Nil
(
t
,
chain
.
GetHeaderByHash
(
hash
))
require
.
Nil
(
t
,
chain
.
GetBlock
(
hash
,
blockNumber
))
require
.
Nil
(
t
,
chain
.
GetHeader
(
hash
,
blockNumber
))
require
.
False
(
t
,
chain
.
HasBlockAndState
(
hash
,
blockNumber
))
}
func
TestCanonicalHashNotFoundPastChainHead
(
t
*
testing
.
T
)
{
blocks
,
chain
:=
setupOracleBackedChainWithLowerHead
(
t
,
5
,
3
)
for
i
:=
0
;
i
<=
3
;
i
++
{
require
.
Equal
(
t
,
blocks
[
i
]
.
Hash
(),
chain
.
GetCanonicalHash
(
uint64
(
i
)))
require
.
Equal
(
t
,
blocks
[
i
]
.
Header
(),
chain
.
GetHeaderByNumber
(
uint64
(
i
)))
}
for
i
:=
4
;
i
<=
5
;
i
++
{
require
.
Equal
(
t
,
common
.
Hash
{},
chain
.
GetCanonicalHash
(
uint64
(
i
)))
require
.
Nil
(
t
,
chain
.
GetHeaderByNumber
(
uint64
(
i
)))
}
}
func
TestAppendToChain
(
t
*
testing
.
T
)
{
blocks
,
chain
:=
setupOracleBackedChainWithLowerHead
(
t
,
4
,
3
)
newBlock
:=
blocks
[
4
]
require
.
Nil
(
t
,
chain
.
GetBlockByHash
(
newBlock
.
Hash
()),
"block unknown before being added"
)
require
.
NoError
(
t
,
chain
.
InsertBlockWithoutSetHead
(
newBlock
))
require
.
Equal
(
t
,
blocks
[
3
]
.
Header
(),
chain
.
CurrentHeader
(),
"should not update chain head yet"
)
require
.
Equal
(
t
,
common
.
Hash
{},
chain
.
GetCanonicalHash
(
uint64
(
4
)),
"not yet a canonical hash"
)
require
.
Nil
(
t
,
chain
.
GetHeaderByNumber
(
uint64
(
4
)),
"not yet a canonical header"
)
assertBlockDataAvailable
(
t
,
chain
,
newBlock
,
4
)
canonical
,
err
:=
chain
.
SetCanonical
(
newBlock
)
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
newBlock
.
Hash
(),
canonical
)
require
.
Equal
(
t
,
newBlock
.
Hash
(),
chain
.
GetCanonicalHash
(
uint64
(
4
)),
"get canonical hash for new head"
)
require
.
Equal
(
t
,
newBlock
.
Header
(),
chain
.
GetHeaderByNumber
(
uint64
(
4
)),
"get canonical header for new head"
)
}
func
TestSetFinalized
(
t
*
testing
.
T
)
{
blocks
,
chain
:=
setupOracleBackedChainWithLowerHead
(
t
,
5
,
0
)
for
_
,
block
:=
range
blocks
[
1
:
]
{
require
.
NoError
(
t
,
chain
.
InsertBlockWithoutSetHead
(
block
))
}
chain
.
SetFinalized
(
blocks
[
2
]
.
Header
())
require
.
Equal
(
t
,
blocks
[
2
]
.
Header
(),
chain
.
CurrentFinalBlock
())
}
func
TestSetSafe
(
t
*
testing
.
T
)
{
blocks
,
chain
:=
setupOracleBackedChainWithLowerHead
(
t
,
5
,
0
)
for
_
,
block
:=
range
blocks
[
1
:
]
{
require
.
NoError
(
t
,
chain
.
InsertBlockWithoutSetHead
(
block
))
}
chain
.
SetSafe
(
blocks
[
2
]
.
Header
())
require
.
Equal
(
t
,
blocks
[
2
]
.
Header
(),
chain
.
CurrentSafeBlock
())
}
func
TestUpdateStateDatabaseWhenImportingBlock
(
t
*
testing
.
T
)
{
blocks
,
chain
:=
setupOracleBackedChain
(
t
,
3
)
newBlock
:=
createBlock
(
t
,
chain
)
db
,
err
:=
chain
.
StateAt
(
blocks
[
1
]
.
Root
())
require
.
NoError
(
t
,
err
)
balance
:=
db
.
GetBalance
(
fundedAddress
)
require
.
NotEqual
(
t
,
big
.
NewInt
(
0
),
balance
,
"should have balance at imported block"
)
require
.
NotEqual
(
t
,
blocks
[
1
]
.
Root
(),
newBlock
.
Root
(),
"block should have modified world state"
)
_
,
err
=
chain
.
StateAt
(
newBlock
.
Root
())
require
.
Error
(
t
,
err
,
"state from non-imported block should not be available"
)
err
=
chain
.
InsertBlockWithoutSetHead
(
newBlock
)
require
.
NoError
(
t
,
err
)
db
,
err
=
chain
.
StateAt
(
newBlock
.
Root
())
require
.
NoError
(
t
,
err
,
"state should be available after importing"
)
balance
=
db
.
GetBalance
(
fundedAddress
)
require
.
NotEqual
(
t
,
big
.
NewInt
(
0
),
balance
,
"should have balance from imported block"
)
}
func
TestRejectBlockWithStateRootMismatch
(
t
*
testing
.
T
)
{
_
,
chain
:=
setupOracleBackedChain
(
t
,
1
)
newBlock
:=
createBlock
(
t
,
chain
)
// Create invalid block by keeping the modified state root but exclude the transaction
invalidBlock
:=
types
.
NewBlockWithHeader
(
newBlock
.
Header
())
err
:=
chain
.
InsertBlockWithoutSetHead
(
invalidBlock
)
require
.
ErrorContains
(
t
,
err
,
"block root mismatch"
)
}
func
assertBlockDataAvailable
(
t
*
testing
.
T
,
chain
*
OracleBackedL2Chain
,
block
*
types
.
Block
,
blockNumber
uint64
)
{
require
.
Equal
(
t
,
block
,
chain
.
GetBlockByHash
(
block
.
Hash
()),
"get block %v by hash"
,
blockNumber
)
require
.
Equal
(
t
,
block
.
Header
(),
chain
.
GetHeaderByHash
(
block
.
Hash
()),
"get header %v by hash"
,
blockNumber
)
require
.
Equal
(
t
,
block
,
chain
.
GetBlock
(
block
.
Hash
(),
blockNumber
),
"get block %v by hash and number"
,
blockNumber
)
require
.
Equal
(
t
,
block
.
Header
(),
chain
.
GetHeader
(
block
.
Hash
(),
blockNumber
),
"get header %v by hash and number"
,
blockNumber
)
require
.
True
(
t
,
chain
.
HasBlockAndState
(
block
.
Hash
(),
blockNumber
),
"has block and state for block %v"
,
blockNumber
)
}
func
setupOracleBackedChain
(
t
*
testing
.
T
,
blockCount
int
)
([]
*
types
.
Block
,
*
OracleBackedL2Chain
)
{
return
setupOracleBackedChainWithLowerHead
(
t
,
blockCount
,
blockCount
)
}
func
setupOracleBackedChainWithLowerHead
(
t
*
testing
.
T
,
blockCount
int
,
headBlockNumber
int
)
([]
*
types
.
Block
,
*
OracleBackedL2Chain
)
{
logger
:=
testlog
.
Logger
(
t
,
log
.
LvlDebug
)
chainCfg
,
blocks
,
oracle
:=
setupOracle
(
t
,
blockCount
,
headBlockNumber
)
head
:=
blocks
[
headBlockNumber
]
.
Hash
()
chain
,
err
:=
NewOracleBackedL2Chain
(
logger
,
oracle
,
chainCfg
,
head
)
require
.
NoError
(
t
,
err
)
return
blocks
,
chain
}
func
setupOracle
(
t
*
testing
.
T
,
blockCount
int
,
headBlockNumber
int
)
(
*
params
.
ChainConfig
,
[]
*
types
.
Block
,
*
stubBlockOracle
)
{
deployConfig
:=
&
genesis
.
DeployConfig
{
L1ChainID
:
900
,
L2ChainID
:
901
,
L2BlockTime
:
2
,
FundDevAccounts
:
true
,
L2GenesisBlockGasLimit
:
30
_000_000
,
}
l1Genesis
,
err
:=
genesis
.
NewL1Genesis
(
deployConfig
)
require
.
NoError
(
t
,
err
)
l2Genesis
,
err
:=
genesis
.
NewL2Genesis
(
deployConfig
,
l1Genesis
.
ToBlock
())
require
.
NoError
(
t
,
err
)
l2Genesis
.
Alloc
[
fundedAddress
]
=
core
.
GenesisAccount
{
Balance
:
big
.
NewInt
(
1
_000_000_000_000_000_000
),
Nonce
:
0
,
}
chainCfg
:=
l2Genesis
.
Config
consensus
:=
beacon
.
New
(
nil
)
db
:=
rawdb
.
NewMemoryDatabase
()
// Set minimal amount of stuff to avoid nil references later
genesisBlock
:=
l2Genesis
.
MustCommit
(
db
)
blocks
,
_
:=
core
.
GenerateChain
(
chainCfg
,
genesisBlock
,
consensus
,
db
,
blockCount
,
func
(
i
int
,
gen
*
core
.
BlockGen
)
{})
blocks
=
append
([]
*
types
.
Block
{
genesisBlock
},
blocks
...
)
oracle
:=
newStubBlockOracle
(
blocks
[
:
headBlockNumber
+
1
],
db
)
return
chainCfg
,
blocks
,
oracle
}
func
createBlock
(
t
*
testing
.
T
,
chain
*
OracleBackedL2Chain
)
*
types
.
Block
{
parent
:=
chain
.
GetBlockByHash
(
chain
.
CurrentHeader
()
.
Hash
())
parentDB
,
err
:=
chain
.
StateAt
(
parent
.
Root
())
require
.
NoError
(
t
,
err
)
nonce
:=
parentDB
.
GetNonce
(
fundedAddress
)
config
:=
chain
.
Config
()
db
:=
rawdb
.
NewDatabase
(
NewOracleBackedDB
(
chain
.
oracle
))
blocks
,
_
:=
core
.
GenerateChain
(
config
,
parent
,
chain
.
Engine
(),
db
,
1
,
func
(
i
int
,
gen
*
core
.
BlockGen
)
{
rawTx
:=
&
types
.
DynamicFeeTx
{
ChainID
:
config
.
ChainID
,
Nonce
:
nonce
,
To
:
&
targetAddress
,
GasTipCap
:
big
.
NewInt
(
0
),
GasFeeCap
:
parent
.
BaseFee
(),
Gas
:
21
_000
,
Value
:
big
.
NewInt
(
1
),
}
tx
:=
types
.
MustSignNewTx
(
fundedKey
,
types
.
NewLondonSigner
(
config
.
ChainID
),
rawTx
)
gen
.
AddTx
(
tx
)
})
return
blocks
[
0
]
}
type
stubBlockOracle
struct
{
blocks
map
[
common
.
Hash
]
*
types
.
Block
kvStateOracle
}
func
newStubBlockOracle
(
chain
[]
*
types
.
Block
,
db
ethdb
.
Database
)
*
stubBlockOracle
{
blocks
:=
make
(
map
[
common
.
Hash
]
*
types
.
Block
,
len
(
chain
))
for
_
,
block
:=
range
chain
{
blocks
[
block
.
Hash
()]
=
block
}
return
&
stubBlockOracle
{
blocks
:
blocks
,
kvStateOracle
:
kvStateOracle
{
source
:
db
},
}
}
func
(
o
stubBlockOracle
)
BlockByHash
(
blockHash
common
.
Hash
)
(
*
types
.
Block
,
error
)
{
return
o
.
blocks
[
blockHash
],
nil
}
func
TestEngineAPITests
(
t
*
testing
.
T
)
{
test
.
RunEngineAPITests
(
t
,
func
()
engineapi
.
EngineBackend
{
_
,
chain
:=
setupOracleBackedChain
(
t
,
0
)
return
chain
})
}
op-program/l2/engineapi/block_processor.go
View file @
9ee1d5c2
...
...
@@ -54,7 +54,7 @@ func NewBlockProcessorFromPayloadAttributes(provider BlockDataProvider, parent c
}
func
NewBlockProcessorFromHeader
(
provider
BlockDataProvider
,
h
*
types
.
Header
)
(
*
BlockProcessor
,
error
)
{
header
:=
*
h
// Copy to avoid mutating the original header
header
:=
types
.
CopyHeader
(
h
)
// Copy to avoid mutating the original header
if
header
.
GasLimit
>
params
.
MaxGasLimit
{
return
nil
,
fmt
.
Errorf
(
"invalid gasLimit: have %v, max %v"
,
header
.
GasLimit
,
params
.
MaxGasLimit
)
...
...
@@ -72,7 +72,7 @@ func NewBlockProcessorFromHeader(provider BlockDataProvider, h *types.Header) (*
header
.
GasUsed
=
0
gasPool
:=
new
(
core
.
GasPool
)
.
AddGas
(
header
.
GasLimit
)
return
&
BlockProcessor
{
header
:
&
header
,
header
:
header
,
state
:
statedb
,
gasPool
:
gasPool
,
dataProvider
:
provider
,
...
...
op-program/l2/engineapi/l2_engine_api.go
View file @
9ee1d5c2
...
...
@@ -20,7 +20,6 @@ import (
)
type
EngineBackend
interface
{
CurrentBlock
()
*
types
.
Header
CurrentSafeBlock
()
*
types
.
Header
CurrentFinalBlock
()
*
types
.
Header
GetBlockByHash
(
hash
common
.
Hash
)
*
types
.
Block
...
...
@@ -222,7 +221,7 @@ func (ea *L2EngineAPI) ForkchoiceUpdatedV1(ctx context.Context, state *eth.Forkc
if
latestValid
,
err
:=
ea
.
backend
.
SetCanonical
(
block
);
err
!=
nil
{
return
&
eth
.
ForkchoiceUpdatedResult
{
PayloadStatus
:
eth
.
PayloadStatusV1
{
Status
:
eth
.
ExecutionInvalid
,
LatestValidHash
:
&
latestValid
}},
err
}
}
else
if
ea
.
backend
.
Current
Block
()
.
Hash
()
==
state
.
HeadBlockHash
{
}
else
if
ea
.
backend
.
Current
Header
()
.
Hash
()
==
state
.
HeadBlockHash
{
// If the specified head matches with our local head, do nothing and keep
// generating the payload. It's a special corner case that a few slots are
// missing and we are requested to generate the payload in slot.
...
...
@@ -336,7 +335,7 @@ func (ea *L2EngineAPI) NewPayloadV1(ctx context.Context, payload *eth.ExecutionP
}
func
(
ea
*
L2EngineAPI
)
invalid
(
err
error
,
latestValid
*
types
.
Header
)
*
eth
.
PayloadStatusV1
{
currentHash
:=
ea
.
backend
.
Current
Block
()
.
Hash
()
currentHash
:=
ea
.
backend
.
Current
Header
()
.
Hash
()
if
latestValid
!=
nil
{
// Set latest valid hash to 0x0 if parent is PoW block
currentHash
=
common
.
Hash
{}
...
...
op-program/l2/engineapi/test/l2_engine_api_tests.go
View file @
9ee1d5c2
...
...
@@ -28,7 +28,7 @@ func RunEngineAPITests(t *testing.T, createBackend func() engineapi.EngineBacken
t
.
Run
(
"IncludeRequiredTransactions"
,
func
(
t
*
testing
.
T
)
{
api
:=
newTestHelper
(
t
,
createBackend
)
genesis
:=
api
.
backend
.
Current
Block
()
genesis
:=
api
.
backend
.
Current
Header
()
txData
,
err
:=
derive
.
L1InfoDeposit
(
1
,
eth
.
HeaderBlockInfo
(
genesis
),
eth
.
SystemConfig
{},
true
)
api
.
assert
.
NoError
(
err
)
...
...
@@ -46,7 +46,7 @@ func RunEngineAPITests(t *testing.T, createBackend func() engineapi.EngineBacken
t
.
Run
(
"RejectCreatingBlockWithInvalidRequiredTransaction"
,
func
(
t
*
testing
.
T
)
{
api
:=
newTestHelper
(
t
,
createBackend
)
genesis
:=
api
.
backend
.
Current
Block
()
genesis
:=
api
.
backend
.
Current
Header
()
txData
,
err
:=
derive
.
L1InfoDeposit
(
1
,
eth
.
HeaderBlockInfo
(
genesis
),
eth
.
SystemConfig
{},
true
)
api
.
assert
.
NoError
(
err
)
...
...
@@ -84,7 +84,7 @@ func RunEngineAPITests(t *testing.T, createBackend func() engineapi.EngineBacken
t
.
Run
(
"AllowBuildingOnOlderBlock"
,
func
(
t
*
testing
.
T
)
{
api
:=
newTestHelper
(
t
,
createBackend
)
genesis
:=
api
.
backend
.
Current
Block
()
genesis
:=
api
.
backend
.
Current
Header
()
api
.
addBlock
()
block
:=
api
.
addBlock
()
api
.
assert
.
Equal
(
block
.
BlockHash
,
api
.
headHash
(),
"should have extended chain"
)
...
...
@@ -112,7 +112,7 @@ func RunEngineAPITests(t *testing.T, createBackend func() engineapi.EngineBacken
t
.
Run
(
"RejectBlockWithInvalidStateTransition"
,
func
(
t
*
testing
.
T
)
{
api
:=
newTestHelper
(
t
,
createBackend
)
genesis
:=
api
.
backend
.
Current
Block
()
genesis
:=
api
.
backend
.
Current
Header
()
// Build a valid block
payloadID
:=
api
.
startBlockBuilding
(
genesis
,
eth
.
Uint64Quantity
(
genesis
.
Time
+
2
))
...
...
@@ -129,7 +129,7 @@ func RunEngineAPITests(t *testing.T, createBackend func() engineapi.EngineBacken
t
.
Run
(
"RejectBlockWithSameTimeAsParent"
,
func
(
t
*
testing
.
T
)
{
api
:=
newTestHelper
(
t
,
createBackend
)
genesis
:=
api
.
backend
.
Current
Block
()
genesis
:=
api
.
backend
.
Current
Header
()
// Start with a valid time
payloadID
:=
api
.
startBlockBuilding
(
genesis
,
eth
.
Uint64Quantity
(
genesis
.
Time
+
1
))
...
...
@@ -146,7 +146,7 @@ func RunEngineAPITests(t *testing.T, createBackend func() engineapi.EngineBacken
t
.
Run
(
"RejectBlockWithTimeBeforeParent"
,
func
(
t
*
testing
.
T
)
{
api
:=
newTestHelper
(
t
,
createBackend
)
genesis
:=
api
.
backend
.
Current
Block
()
genesis
:=
api
.
backend
.
Current
Header
()
// Start with a valid time
payloadID
:=
api
.
startBlockBuilding
(
genesis
,
eth
.
Uint64Quantity
(
genesis
.
Time
+
1
))
...
...
@@ -163,7 +163,7 @@ func RunEngineAPITests(t *testing.T, createBackend func() engineapi.EngineBacken
t
.
Run
(
"RejectCreateBlockWithSameTimeAsParent"
,
func
(
t
*
testing
.
T
)
{
api
:=
newTestHelper
(
t
,
createBackend
)
genesis
:=
api
.
backend
.
Current
Block
()
genesis
:=
api
.
backend
.
Current
Header
()
result
,
err
:=
api
.
engine
.
ForkchoiceUpdatedV1
(
api
.
ctx
,
&
eth
.
ForkchoiceState
{
HeadBlockHash
:
genesis
.
Hash
(),
...
...
@@ -183,7 +183,7 @@ func RunEngineAPITests(t *testing.T, createBackend func() engineapi.EngineBacken
t
.
Run
(
"RejectCreateBlockWithTimeBeforeParent"
,
func
(
t
*
testing
.
T
)
{
api
:=
newTestHelper
(
t
,
createBackend
)
genesis
:=
api
.
backend
.
Current
Block
()
genesis
:=
api
.
backend
.
Current
Header
()
result
,
err
:=
api
.
engine
.
ForkchoiceUpdatedV1
(
api
.
ctx
,
&
eth
.
ForkchoiceState
{
HeadBlockHash
:
genesis
.
Hash
(),
...
...
@@ -203,7 +203,7 @@ func RunEngineAPITests(t *testing.T, createBackend func() engineapi.EngineBacken
t
.
Run
(
"RejectCreateBlockWithGasLimitAboveMax"
,
func
(
t
*
testing
.
T
)
{
api
:=
newTestHelper
(
t
,
createBackend
)
genesis
:=
api
.
backend
.
Current
Block
()
genesis
:=
api
.
backend
.
Current
Header
()
gasLimit
:=
eth
.
Uint64Quantity
(
params
.
MaxGasLimit
+
1
)
...
...
@@ -238,7 +238,7 @@ func RunEngineAPITests(t *testing.T, createBackend func() engineapi.EngineBacken
t
.
Run
(
"RejectSafeHeadWhenNotAncestor"
,
func
(
t
*
testing
.
T
)
{
api
:=
newTestHelper
(
t
,
createBackend
)
genesis
:=
api
.
backend
.
Current
Block
()
genesis
:=
api
.
backend
.
Current
Header
()
api
.
addBlock
()
chainA2
:=
api
.
addBlock
()
...
...
@@ -258,7 +258,7 @@ func RunEngineAPITests(t *testing.T, createBackend func() engineapi.EngineBacken
t
.
Run
(
"RejectFinalizedHeadWhenNotAncestor"
,
func
(
t
*
testing
.
T
)
{
api
:=
newTestHelper
(
t
,
createBackend
)
genesis
:=
api
.
backend
.
Current
Block
()
genesis
:=
api
.
backend
.
Current
Header
()
api
.
addBlock
()
chainA2
:=
api
.
addBlock
()
...
...
@@ -308,7 +308,7 @@ func newTestHelper(t *testing.T, createBackend func() engineapi.EngineBackend) *
}
func
(
h
*
testHelper
)
headHash
()
common
.
Hash
{
return
h
.
backend
.
Current
Block
()
.
Hash
()
return
h
.
backend
.
Current
Header
()
.
Hash
()
}
func
(
h
*
testHelper
)
safeHash
()
common
.
Hash
{
...
...
@@ -324,12 +324,12 @@ func (h *testHelper) Log(args ...any) {
}
func
(
h
*
testHelper
)
addBlock
(
txs
...*
types
.
Transaction
)
*
eth
.
ExecutionPayload
{
head
:=
h
.
backend
.
Current
Block
()
head
:=
h
.
backend
.
Current
Header
()
return
h
.
addBlockWithParent
(
head
,
eth
.
Uint64Quantity
(
head
.
Time
+
2
),
txs
...
)
}
func
(
h
*
testHelper
)
addBlockWithParent
(
head
*
types
.
Header
,
timestamp
eth
.
Uint64Quantity
,
txs
...*
types
.
Transaction
)
*
eth
.
ExecutionPayload
{
prevHead
:=
h
.
backend
.
Current
Block
()
prevHead
:=
h
.
backend
.
Current
Header
()
id
:=
h
.
startBlockBuilding
(
head
,
timestamp
,
txs
...
)
block
:=
h
.
getPayload
(
id
)
...
...
@@ -340,10 +340,10 @@ func (h *testHelper) addBlockWithParent(head *types.Header, timestamp eth.Uint64
h
.
newPayload
(
block
)
// Should not have changed the chain head yet
h
.
assert
.
Equal
(
prevHead
,
h
.
backend
.
Current
Block
())
h
.
assert
.
Equal
(
prevHead
,
h
.
backend
.
Current
Header
())
h
.
forkChoiceUpdated
(
block
.
BlockHash
,
head
.
Hash
(),
head
.
Hash
())
h
.
assert
.
Equal
(
block
.
BlockHash
,
h
.
backend
.
Current
Block
()
.
Hash
())
h
.
assert
.
Equal
(
block
.
BlockHash
,
h
.
backend
.
Current
Header
()
.
Hash
())
return
block
}
...
...
op-program/l2/oracle.go
View file @
9ee1d5c2
package
l2
import
"github.com/ethereum/go-ethereum/common"
import
(
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// StateOracle defines the high-level API used to retrieve L2 state data pre-images
// The returned data is always the preimage of the requested hash.
...
...
@@ -16,3 +19,13 @@ type StateOracle interface {
// Returns an error if the pre-image is unavailable.
CodeByHash
(
codeHash
common
.
Hash
)
([]
byte
,
error
)
}
// Oracle defines the high-level API used to retrieve L2 data.
// The returned data is always the preimage of the requested hash.
type
Oracle
interface
{
StateOracle
// BlockByHash retrieves the block with the given hash.
// Returns an error if the block is not available.
BlockByHash
(
blockHash
common
.
Hash
)
(
*
types
.
Block
,
error
)
}
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