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
d6444d25
Unverified
Commit
d6444d25
authored
Apr 08, 2023
by
protolambda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
op-program: kv store for pre-images
parent
8e355d1d
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
182 additions
and
0 deletions
+182
-0
disk.go
op-program/host/kvstore/disk.go
+64
-0
disk_test.go
op-program/host/kvstore/disk_test.go
+9
-0
kv.go
op-program/host/kvstore/kv.go
+16
-0
kv_test.go
op-program/host/kvstore/kv_test.go
+47
-0
mem.go
op-program/host/kvstore/mem.go
+38
-0
mem_test.go
op-program/host/kvstore/mem_test.go
+8
-0
No files found.
op-program/host/kvstore/disk.go
0 → 100644
View file @
d6444d25
package
kvstore
import
(
"encoding/hex"
"fmt"
"io"
"os"
"path"
"github.com/ethereum/go-ethereum/common"
)
// read/write mode for user/group/other, not executable.
const
diskPermission
=
0666
// DiskKV is a disk-backed key-value store, every key-value pair is a hex-encoded .txt file, with the value as content.
// DiskKV is safe for concurrent use; Puts may conflict, but write the exact same data anyway.
type
DiskKV
struct
{
path
string
}
// NewDiskKV creates a DiskKV that puts/gets pre-images as files in the given directory path.
// The path must exist, or subsequent Put/Get calls will error when it does not.
func
NewDiskKV
(
path
string
)
*
DiskKV
{
return
&
DiskKV
{
path
:
path
}
}
func
(
d
*
DiskKV
)
pathKey
(
k
common
.
Hash
)
string
{
return
path
.
Join
(
d
.
path
,
k
.
String
()
+
".txt"
)
}
func
(
d
*
DiskKV
)
Put
(
k
common
.
Hash
,
v
[]
byte
)
error
{
// no O_EXCL, the pre-image may already exist. It's fine to overwrite it.
f
,
err
:=
os
.
OpenFile
(
d
.
pathKey
(
k
),
os
.
O_WRONLY
|
os
.
O_CREATE
|
os
.
O_TRUNC
,
diskPermission
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to open new pre-image file %s: %w"
,
k
,
err
)
}
if
_
,
err
:=
f
.
Write
([]
byte
(
hex
.
EncodeToString
(
v
)));
err
!=
nil
{
_
=
f
.
Close
()
return
fmt
.
Errorf
(
"failed to write pre-image %s to disk: %w"
,
k
,
err
)
}
if
err
:=
f
.
Close
();
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to close pre-image %s file: %w"
,
k
,
err
)
}
return
nil
}
func
(
d
*
DiskKV
)
Get
(
k
common
.
Hash
)
([]
byte
,
error
)
{
f
,
err
:=
os
.
OpenFile
(
d
.
pathKey
(
k
),
os
.
O_RDONLY
,
diskPermission
)
if
err
!=
nil
{
if
os
.
IsNotExist
(
err
)
{
return
nil
,
NotFoundErr
}
return
nil
,
fmt
.
Errorf
(
"failed to open pre-image file %s: %w"
,
k
,
err
)
}
defer
f
.
Close
()
// fine to ignore closing error here
dat
,
err
:=
io
.
ReadAll
(
f
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to read pre-image from file %s: %w"
,
k
,
err
)
}
return
hex
.
DecodeString
(
string
(
dat
))
}
var
_
KV
=
(
*
DiskKV
)(
nil
)
op-program/host/kvstore/disk_test.go
0 → 100644
View file @
d6444d25
package
kvstore
import
"testing"
func
TestDiskKV
(
t
*
testing
.
T
)
{
tmp
:=
t
.
TempDir
()
// automatically removed by testing cleanup
kv
:=
NewDiskKV
(
tmp
)
kvTest
(
t
,
kv
)
}
op-program/host/kvstore/kv.go
0 → 100644
View file @
d6444d25
package
kvstore
import
(
"errors"
"github.com/ethereum/go-ethereum/common"
)
// NotFoundErr is returned when a pre-image cannot be found in the KV store.
var
NotFoundErr
=
errors
.
New
(
"not found"
)
// KV is a Key-Value store interface for pre-image data.
type
KV
interface
{
Put
(
k
common
.
Hash
,
v
[]
byte
)
error
Get
(
k
common
.
Hash
)
([]
byte
,
error
)
}
op-program/host/kvstore/kv_test.go
0 → 100644
View file @
d6444d25
package
kvstore
import
(
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
func
kvTest
(
t
*
testing
.
T
,
kv
KV
)
{
t
.
Run
(
"roundtrip"
,
func
(
t
*
testing
.
T
)
{
t
.
Parallel
()
_
,
err
:=
kv
.
Get
(
common
.
Hash
{
0xaa
})
require
.
Equal
(
t
,
err
,
NotFoundErr
,
"file (in new tmp dir) does not exist yet"
)
require
.
NoError
(
t
,
kv
.
Put
(
common
.
Hash
{
0xaa
},
[]
byte
(
"hello world"
)))
dat
,
err
:=
kv
.
Get
(
common
.
Hash
{
0xaa
})
require
.
NoError
(
t
,
err
,
"pre-image must exist now"
)
require
.
Equal
(
t
,
"hello world"
,
string
(
dat
),
"pre-image must match"
)
})
t
.
Run
(
"empty pre-image"
,
func
(
t
*
testing
.
T
)
{
t
.
Parallel
()
require
.
NoError
(
t
,
kv
.
Put
(
common
.
Hash
{
0xbb
},
[]
byte
{}))
dat
,
err
:=
kv
.
Get
(
common
.
Hash
{
0xbb
})
require
.
NoError
(
t
,
err
,
"pre-image must exist now"
)
require
.
Zero
(
t
,
len
(
dat
),
"pre-image must be empty"
)
})
t
.
Run
(
"zero pre-image key"
,
func
(
t
*
testing
.
T
)
{
t
.
Parallel
()
// in case we give a pre-image a special empty key. If it was a hash then we wouldn't know the pre-image.
require
.
NoError
(
t
,
kv
.
Put
(
common
.
Hash
{},
[]
byte
(
"hello"
)))
dat
,
err
:=
kv
.
Get
(
common
.
Hash
{})
require
.
NoError
(
t
,
err
,
"pre-image must exist now"
)
require
.
Equal
(
t
,
"hello"
,
string
(
dat
),
"pre-image must match"
)
})
t
.
Run
(
"non-string value"
,
func
(
t
*
testing
.
T
)
{
t
.
Parallel
()
// in case we give a pre-image a special empty key. If it was a hash then we wouldn't know the pre-image.
require
.
NoError
(
t
,
kv
.
Put
(
common
.
Hash
{
0xcc
},
[]
byte
{
4
,
2
}))
dat
,
err
:=
kv
.
Get
(
common
.
Hash
{
0xcc
})
require
.
NoError
(
t
,
err
,
"pre-image must exist now"
)
require
.
Equal
(
t
,
[]
byte
{
4
,
2
},
dat
,
"pre-image must match"
)
})
}
op-program/host/kvstore/mem.go
0 → 100644
View file @
d6444d25
package
kvstore
import
(
"sync"
"github.com/ethereum/go-ethereum/common"
)
// MemKV implements the KV store interface in memory, backed by a regular Go map.
// This should only be used in testing, as large programs may require more pre-image data than available memory.
// MemKV is safe for concurrent use.
type
MemKV
struct
{
sync
.
RWMutex
m
map
[
common
.
Hash
][]
byte
}
var
_
KV
=
(
*
MemKV
)(
nil
)
func
NewMemKV
()
*
MemKV
{
return
&
MemKV
{
m
:
make
(
map
[
common
.
Hash
][]
byte
)}
}
func
(
m
*
MemKV
)
Put
(
k
common
.
Hash
,
v
[]
byte
)
error
{
m
.
Lock
()
defer
m
.
Unlock
()
m
.
m
[
k
]
=
v
return
nil
}
func
(
m
*
MemKV
)
Get
(
k
common
.
Hash
)
([]
byte
,
error
)
{
m
.
RLock
()
defer
m
.
RUnlock
()
v
,
ok
:=
m
.
m
[
k
]
if
!
ok
{
return
nil
,
NotFoundErr
}
return
v
,
nil
}
op-program/host/kvstore/mem_test.go
0 → 100644
View file @
d6444d25
package
kvstore
import
"testing"
func
TestMemKV
(
t
*
testing
.
T
)
{
kv
:=
NewMemKV
()
kvTest
(
t
,
kv
)
}
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