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
aaca212f
Unverified
Commit
aaca212f
authored
Apr 12, 2023
by
Adrian Sutton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
op-program: Implement caching for the L2 oracle.
parent
cfc45742
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
216 additions
and
75 deletions
+216
-75
cache.go
op-program/client/l2/cache.go
+52
-0
cache_test.go
op-program/client/l2/cache_test.go
+67
-0
db_test.go
op-program/client/l2/db_test.go
+0
-48
engine_backend_test.go
op-program/client/l2/engine_backend_test.go
+1
-26
stub_oracle_test.go
op-program/client/l2/stub_oracle_test.go
+94
-0
l2.go
op-program/host/l2/l2.go
+2
-1
No files found.
op-program/client/l2/cache.go
0 → 100644
View file @
aaca212f
package
l2
import
(
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
type
CachingOracle
struct
{
oracle
Oracle
blocks
map
[
common
.
Hash
]
*
types
.
Block
nodes
map
[
common
.
Hash
][]
byte
codes
map
[
common
.
Hash
][]
byte
}
func
NewCachingOracle
(
oracle
Oracle
)
*
CachingOracle
{
return
&
CachingOracle
{
oracle
:
oracle
,
blocks
:
make
(
map
[
common
.
Hash
]
*
types
.
Block
),
nodes
:
make
(
map
[
common
.
Hash
][]
byte
),
codes
:
make
(
map
[
common
.
Hash
][]
byte
),
}
}
func
(
o
CachingOracle
)
NodeByHash
(
nodeHash
common
.
Hash
)
[]
byte
{
node
,
ok
:=
o
.
nodes
[
nodeHash
]
if
ok
{
return
node
}
node
=
o
.
oracle
.
NodeByHash
(
nodeHash
)
o
.
nodes
[
nodeHash
]
=
node
return
node
}
func
(
o
CachingOracle
)
CodeByHash
(
codeHash
common
.
Hash
)
[]
byte
{
code
,
ok
:=
o
.
codes
[
codeHash
]
if
ok
{
return
code
}
code
=
o
.
oracle
.
CodeByHash
(
codeHash
)
o
.
codes
[
codeHash
]
=
code
return
code
}
func
(
o
CachingOracle
)
BlockByHash
(
blockHash
common
.
Hash
)
*
types
.
Block
{
block
,
ok
:=
o
.
blocks
[
blockHash
]
if
ok
{
return
block
}
block
=
o
.
oracle
.
BlockByHash
(
blockHash
)
o
.
blocks
[
blockHash
]
=
block
return
block
}
op-program/client/l2/cache_test.go
0 → 100644
View file @
aaca212f
package
l2
import
(
"math/rand"
"testing"
"github.com/ethereum-optimism/optimism/op-node/testutils"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
// Should be an Oracle implementation
var
_
Oracle
=
(
*
CachingOracle
)(
nil
)
func
TestBlockByHash
(
t
*
testing
.
T
)
{
stub
,
_
:=
newStubOracle
(
t
)
oracle
:=
NewCachingOracle
(
stub
)
rng
:=
rand
.
New
(
rand
.
NewSource
(
1
))
block
,
_
:=
testutils
.
RandomBlock
(
rng
,
1
)
// Initial call retrieves from the stub
stub
.
blocks
[
block
.
Hash
()]
=
block
actual
:=
oracle
.
BlockByHash
(
block
.
Hash
())
require
.
Equal
(
t
,
block
,
actual
)
// Later calls should retrieve from cache
delete
(
stub
.
blocks
,
block
.
Hash
())
actual
=
oracle
.
BlockByHash
(
block
.
Hash
())
require
.
Equal
(
t
,
block
,
actual
)
}
func
TestNodeByHash
(
t
*
testing
.
T
)
{
stub
,
stateStub
:=
newStubOracle
(
t
)
oracle
:=
NewCachingOracle
(
stub
)
node
:=
[]
byte
{
12
,
3
,
4
}
hash
:=
common
.
Hash
{
0xaa
}
// Initial call retrieves from the stub
stateStub
.
data
[
hash
]
=
node
actual
:=
oracle
.
NodeByHash
(
hash
)
require
.
Equal
(
t
,
node
,
actual
)
// Later calls should retrieve from cache
delete
(
stateStub
.
data
,
hash
)
actual
=
oracle
.
NodeByHash
(
hash
)
require
.
Equal
(
t
,
node
,
actual
)
}
func
TestCodeByHash
(
t
*
testing
.
T
)
{
stub
,
stateStub
:=
newStubOracle
(
t
)
oracle
:=
NewCachingOracle
(
stub
)
node
:=
[]
byte
{
12
,
3
,
4
}
hash
:=
common
.
Hash
{
0xaa
}
// Initial call retrieves from the stub
stateStub
.
code
[
hash
]
=
node
actual
:=
oracle
.
CodeByHash
(
hash
)
require
.
Equal
(
t
,
node
,
actual
)
// Later calls should retrieve from cache
delete
(
stateStub
.
code
,
hash
)
actual
=
oracle
.
CodeByHash
(
hash
)
require
.
Equal
(
t
,
node
,
actual
)
}
op-program/client/l2/db_test.go
View file @
aaca212f
...
@@ -194,51 +194,3 @@ func assertStateDataAvailable(t *testing.T, db ethdb.KeyValueStore, l2Genesis *c
...
@@ -194,51 +194,3 @@ func assertStateDataAvailable(t *testing.T, db ethdb.KeyValueStore, l2Genesis *c
require
.
Nil
(
t
,
statedb
.
GetCode
(
unknownAccount
),
"unset account code"
)
require
.
Nil
(
t
,
statedb
.
GetCode
(
unknownAccount
),
"unset account code"
)
require
.
Equal
(
t
,
common
.
Hash
{},
statedb
.
GetCodeHash
(
unknownAccount
),
"unset account code hash"
)
require
.
Equal
(
t
,
common
.
Hash
{},
statedb
.
GetCodeHash
(
unknownAccount
),
"unset account code hash"
)
}
}
func
newStubStateOracle
(
t
*
testing
.
T
)
*
stubStateOracle
{
return
&
stubStateOracle
{
t
:
t
,
data
:
make
(
map
[
common
.
Hash
][]
byte
),
code
:
make
(
map
[
common
.
Hash
][]
byte
),
}
}
type
stubStateOracle
struct
{
t
*
testing
.
T
data
map
[
common
.
Hash
][]
byte
code
map
[
common
.
Hash
][]
byte
}
func
(
o
*
stubStateOracle
)
NodeByHash
(
nodeHash
common
.
Hash
)
[]
byte
{
data
,
ok
:=
o
.
data
[
nodeHash
]
if
!
ok
{
o
.
t
.
Fatalf
(
"no value for node %v"
,
nodeHash
)
}
return
data
}
func
(
o
*
stubStateOracle
)
CodeByHash
(
hash
common
.
Hash
)
[]
byte
{
data
,
ok
:=
o
.
code
[
hash
]
if
!
ok
{
o
.
t
.
Fatalf
(
"no value for code %v"
,
hash
)
}
return
data
}
// kvStateOracle loads data from a source ethdb.KeyValueStore
type
kvStateOracle
struct
{
t
*
testing
.
T
source
ethdb
.
KeyValueStore
}
func
(
o
*
kvStateOracle
)
NodeByHash
(
nodeHash
common
.
Hash
)
[]
byte
{
val
,
err
:=
o
.
source
.
Get
(
nodeHash
.
Bytes
())
if
err
!=
nil
{
o
.
t
.
Fatalf
(
"error retrieving node %v: %v"
,
nodeHash
,
err
)
}
return
val
}
func
(
o
*
kvStateOracle
)
CodeByHash
(
hash
common
.
Hash
)
[]
byte
{
return
rawdb
.
ReadCode
(
o
.
source
,
hash
)
}
op-program/client/l2/engine_backend_test.go
View file @
aaca212f
...
@@ -14,7 +14,6 @@ import (
...
@@ -14,7 +14,6 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/require"
...
@@ -168,7 +167,7 @@ func setupOracle(t *testing.T, blockCount int, headBlockNumber int) (*params.Cha
...
@@ -168,7 +167,7 @@ func setupOracle(t *testing.T, blockCount int, headBlockNumber int) (*params.Cha
genesisBlock
:=
l2Genesis
.
MustCommit
(
db
)
genesisBlock
:=
l2Genesis
.
MustCommit
(
db
)
blocks
,
_
:=
core
.
GenerateChain
(
chainCfg
,
genesisBlock
,
consensus
,
db
,
blockCount
,
func
(
i
int
,
gen
*
core
.
BlockGen
)
{})
blocks
,
_
:=
core
.
GenerateChain
(
chainCfg
,
genesisBlock
,
consensus
,
db
,
blockCount
,
func
(
i
int
,
gen
*
core
.
BlockGen
)
{})
blocks
=
append
([]
*
types
.
Block
{
genesisBlock
},
blocks
...
)
blocks
=
append
([]
*
types
.
Block
{
genesisBlock
},
blocks
...
)
oracle
:=
newStub
BlockOracle
(
t
,
blocks
[
:
headBlockNumber
+
1
],
db
)
oracle
:=
newStub
OracleWithBlocks
(
t
,
blocks
[
:
headBlockNumber
+
1
],
db
)
return
chainCfg
,
blocks
,
oracle
return
chainCfg
,
blocks
,
oracle
}
}
...
@@ -195,30 +194,6 @@ func createBlock(t *testing.T, chain *OracleBackedL2Chain) *types.Block {
...
@@ -195,30 +194,6 @@ func createBlock(t *testing.T, chain *OracleBackedL2Chain) *types.Block {
return
blocks
[
0
]
return
blocks
[
0
]
}
}
type
stubBlockOracle
struct
{
blocks
map
[
common
.
Hash
]
*
types
.
Block
kvStateOracle
}
func
newStubBlockOracle
(
t
*
testing
.
T
,
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
{
t
:
t
,
source
:
db
},
}
}
func
(
o
stubBlockOracle
)
BlockByHash
(
blockHash
common
.
Hash
)
*
types
.
Block
{
block
,
ok
:=
o
.
blocks
[
blockHash
]
if
!
ok
{
o
.
t
.
Fatalf
(
"requested unknown block %s"
,
blockHash
)
}
return
block
}
func
TestEngineAPITests
(
t
*
testing
.
T
)
{
func
TestEngineAPITests
(
t
*
testing
.
T
)
{
test
.
RunEngineAPITests
(
t
,
func
(
t
*
testing
.
T
)
engineapi
.
EngineBackend
{
test
.
RunEngineAPITests
(
t
,
func
(
t
*
testing
.
T
)
engineapi
.
EngineBackend
{
_
,
chain
:=
setupOracleBackedChain
(
t
,
0
)
_
,
chain
:=
setupOracleBackedChain
(
t
,
0
)
...
...
op-program/client/l2/stub_oracle_test.go
0 → 100644
View file @
aaca212f
package
l2
import
(
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
)
type
stubBlockOracle
struct
{
t
*
testing
.
T
blocks
map
[
common
.
Hash
]
*
types
.
Block
StateOracle
}
func
newStubOracle
(
t
*
testing
.
T
)
(
*
stubBlockOracle
,
*
stubStateOracle
)
{
stateOracle
:=
newStubStateOracle
(
t
)
blockOracle
:=
stubBlockOracle
{
t
:
t
,
blocks
:
make
(
map
[
common
.
Hash
]
*
types
.
Block
),
StateOracle
:
stateOracle
,
}
return
&
blockOracle
,
stateOracle
}
func
newStubOracleWithBlocks
(
t
*
testing
.
T
,
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
,
StateOracle
:
&
kvStateOracle
{
t
:
t
,
source
:
db
},
}
}
func
(
o
stubBlockOracle
)
BlockByHash
(
blockHash
common
.
Hash
)
*
types
.
Block
{
block
,
ok
:=
o
.
blocks
[
blockHash
]
if
!
ok
{
o
.
t
.
Fatalf
(
"requested unknown block %s"
,
blockHash
)
}
return
block
}
// kvStateOracle loads data from a source ethdb.KeyValueStore
type
kvStateOracle
struct
{
t
*
testing
.
T
source
ethdb
.
KeyValueStore
}
func
(
o
*
kvStateOracle
)
NodeByHash
(
nodeHash
common
.
Hash
)
[]
byte
{
val
,
err
:=
o
.
source
.
Get
(
nodeHash
.
Bytes
())
if
err
!=
nil
{
o
.
t
.
Fatalf
(
"error retrieving node %v: %v"
,
nodeHash
,
err
)
}
return
val
}
func
(
o
*
kvStateOracle
)
CodeByHash
(
hash
common
.
Hash
)
[]
byte
{
return
rawdb
.
ReadCode
(
o
.
source
,
hash
)
}
func
newStubStateOracle
(
t
*
testing
.
T
)
*
stubStateOracle
{
return
&
stubStateOracle
{
t
:
t
,
data
:
make
(
map
[
common
.
Hash
][]
byte
),
code
:
make
(
map
[
common
.
Hash
][]
byte
),
}
}
// Stub StateOracle implementation that reads from simple maps
type
stubStateOracle
struct
{
t
*
testing
.
T
data
map
[
common
.
Hash
][]
byte
code
map
[
common
.
Hash
][]
byte
}
func
(
o
*
stubStateOracle
)
NodeByHash
(
nodeHash
common
.
Hash
)
[]
byte
{
data
,
ok
:=
o
.
data
[
nodeHash
]
if
!
ok
{
o
.
t
.
Fatalf
(
"no value for node %v"
,
nodeHash
)
}
return
data
}
func
(
o
*
stubStateOracle
)
CodeByHash
(
hash
common
.
Hash
)
[]
byte
{
data
,
ok
:=
o
.
code
[
hash
]
if
!
ok
{
o
.
t
.
Fatalf
(
"no value for code %v"
,
hash
)
}
return
data
}
op-program/host/l2/l2.go
View file @
aaca212f
...
@@ -19,10 +19,11 @@ func NewFetchingEngine(ctx context.Context, logger log.Logger, cfg *config.Confi
...
@@ -19,10 +19,11 @@ func NewFetchingEngine(ctx context.Context, logger log.Logger, cfg *config.Confi
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
oracle
,
err
:=
NewFetchingL2Oracle
(
ctx
,
logger
,
cfg
.
L2URL
,
cfg
.
L2Head
)
fetcher
,
err
:=
NewFetchingL2Oracle
(
ctx
,
logger
,
cfg
.
L2URL
,
cfg
.
L2Head
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"connect l2 oracle: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"connect l2 oracle: %w"
,
err
)
}
}
oracle
:=
cll2
.
NewCachingOracle
(
fetcher
)
engineBackend
,
err
:=
cll2
.
NewOracleBackedL2Chain
(
logger
,
oracle
,
genesis
,
cfg
.
L2Head
)
engineBackend
,
err
:=
cll2
.
NewOracleBackedL2Chain
(
logger
,
oracle
,
genesis
,
cfg
.
L2Head
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
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