Commit 472ea471 authored by protolambda's avatar protolambda

op-program: kv store add pre-image overwriting error

parent d6444d25
...@@ -30,9 +30,11 @@ func (d *DiskKV) pathKey(k common.Hash) string { ...@@ -30,9 +30,11 @@ func (d *DiskKV) pathKey(k common.Hash) string {
} }
func (d *DiskKV) Put(k common.Hash, v []byte) error { 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_EXCL|os.O_TRUNC, diskPermission)
f, err := os.OpenFile(d.pathKey(k), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, diskPermission)
if err != nil { if err != nil {
if os.IsExist(err) {
return ErrAlreadyExists
}
return fmt.Errorf("failed to open new pre-image file %s: %w", k, err) return fmt.Errorf("failed to open new pre-image file %s: %w", k, err)
} }
if _, err := f.Write([]byte(hex.EncodeToString(v))); err != nil { if _, err := f.Write([]byte(hex.EncodeToString(v))); err != nil {
...@@ -49,7 +51,7 @@ func (d *DiskKV) Get(k common.Hash) ([]byte, error) { ...@@ -49,7 +51,7 @@ func (d *DiskKV) Get(k common.Hash) ([]byte, error) {
f, err := os.OpenFile(d.pathKey(k), os.O_RDONLY, diskPermission) f, err := os.OpenFile(d.pathKey(k), os.O_RDONLY, diskPermission)
if err != nil { if err != nil {
if os.IsNotExist(err) { if os.IsNotExist(err) {
return nil, NotFoundErr return nil, ErrNotFound
} }
return nil, fmt.Errorf("failed to open pre-image file %s: %w", k, err) return nil, fmt.Errorf("failed to open pre-image file %s: %w", k, err)
} }
......
...@@ -6,11 +6,21 @@ import ( ...@@ -6,11 +6,21 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
) )
// NotFoundErr is returned when a pre-image cannot be found in the KV store. // ErrNotFound is returned when a pre-image cannot be found in the KV store.
var NotFoundErr = errors.New("not found") var ErrNotFound = errors.New("not found")
// ErrAlreadyExists is returned when a pre-image already exists in the KV store.
var ErrAlreadyExists = errors.New("already exists")
// KV is a Key-Value store interface for pre-image data. // KV is a Key-Value store interface for pre-image data.
type KV interface { type KV interface {
// Put puts the pre-image value v in the key-value store with key k.
// It returns ErrAlreadyExists when the key already exists.
// KV store implementations may return additional errors specific to the KV storage.
Put(k common.Hash, v []byte) error Put(k common.Hash, v []byte) error
// Get retrieves the pre-image with key k from the key-value store.
// It returns ErrNotFound when the pre-image cannot be found.
// KV store implementations may return additional errors specific to the KV storage.
Get(k common.Hash) ([]byte, error) Get(k common.Hash) ([]byte, error)
} }
...@@ -11,7 +11,7 @@ func kvTest(t *testing.T, kv KV) { ...@@ -11,7 +11,7 @@ func kvTest(t *testing.T, kv KV) {
t.Run("roundtrip", func(t *testing.T) { t.Run("roundtrip", func(t *testing.T) {
t.Parallel() t.Parallel()
_, err := kv.Get(common.Hash{0xaa}) _, err := kv.Get(common.Hash{0xaa})
require.Equal(t, err, NotFoundErr, "file (in new tmp dir) does not exist yet") require.Equal(t, err, ErrNotFound, "file (in new tmp dir) does not exist yet")
require.NoError(t, kv.Put(common.Hash{0xaa}, []byte("hello world"))) require.NoError(t, kv.Put(common.Hash{0xaa}, []byte("hello world")))
dat, err := kv.Get(common.Hash{0xaa}) dat, err := kv.Get(common.Hash{0xaa})
...@@ -44,4 +44,10 @@ func kvTest(t *testing.T, kv KV) { ...@@ -44,4 +44,10 @@ func kvTest(t *testing.T, kv KV) {
require.NoError(t, err, "pre-image must exist now") require.NoError(t, err, "pre-image must exist now")
require.Equal(t, []byte{4, 2}, dat, "pre-image must match") require.Equal(t, []byte{4, 2}, dat, "pre-image must match")
}) })
t.Run("not overwriting pre-image", func(t *testing.T) {
t.Parallel()
require.NoError(t, kv.Put(common.Hash{0xdd}, []byte{4, 2}))
require.ErrorIs(t, kv.Put(common.Hash{0xdd}, []byte{4, 2}), ErrAlreadyExists)
})
} }
...@@ -23,6 +23,9 @@ func NewMemKV() *MemKV { ...@@ -23,6 +23,9 @@ func NewMemKV() *MemKV {
func (m *MemKV) Put(k common.Hash, v []byte) error { func (m *MemKV) Put(k common.Hash, v []byte) error {
m.Lock() m.Lock()
defer m.Unlock() defer m.Unlock()
if _, ok := m.m[k]; ok {
return ErrAlreadyExists
}
m.m[k] = v m.m[k] = v
return nil return nil
} }
...@@ -32,7 +35,7 @@ func (m *MemKV) Get(k common.Hash) ([]byte, error) { ...@@ -32,7 +35,7 @@ func (m *MemKV) Get(k common.Hash) ([]byte, error) {
defer m.RUnlock() defer m.RUnlock()
v, ok := m.m[k] v, ok := m.m[k]
if !ok { if !ok {
return nil, NotFoundErr return nil, ErrNotFound
} }
return v, nil return v, nil
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment