diff --git a/blockchain/storagev2/leveldb/leveldb.go b/blockchain/storagev2/leveldb/leveldb.go index bb852c6be0..3140079b43 100644 --- a/blockchain/storagev2/leveldb/leveldb.go +++ b/blockchain/storagev2/leveldb/leveldb.go @@ -71,16 +71,20 @@ func openLevelDBStorage(path string, options *opt.Options) (*leveldb.DB, error) } // Get retrieves the key-value pair in leveldb storage -func (l *levelDB) Get(t uint8, k []byte) ([]byte, error) { +func (l *levelDB) Get(t uint8, k []byte) ([]byte, bool, error) { mc := tableMapper[t] k = append(k, mc...) data, err := l.db.Get(k, nil) if err != nil { - return nil, err + if err.Error() == "leveldb: not found" { + return nil, false, nil + } + + return nil, false, err } - return data, nil + return data, true, nil } // Close closes the leveldb storage instance diff --git a/blockchain/storagev2/leveldb/leveldb_perf_test.go b/blockchain/storagev2/leveldb/leveldb_perf_test.go index 0b73bd20ba..6a558e0851 100644 --- a/blockchain/storagev2/leveldb/leveldb_perf_test.go +++ b/blockchain/storagev2/leveldb/leveldb_perf_test.go @@ -236,7 +236,7 @@ func TestReadBlockPerf(t *testing.T) { watch := stopwatch.Start() _, err1 := s.ReadBody(n) - h, err2 := s.ReadCanonicalHash(n) + h, ok := s.ReadCanonicalHash(n) _, err3 := s.ReadHeader(n) _, err4 := s.ReadReceipts(n) b, err5 := s.ReadBlockLookup(h) @@ -244,7 +244,7 @@ func TestReadBlockPerf(t *testing.T) { watch.Stop() watchTime = watchTime + int(watch.Milliseconds()) - if err1 != nil || err2 != nil || err3 != nil || err4 != nil || err5 != nil { + if err1 != nil || !ok || err3 != nil || err4 != nil || err5 != nil { t.Logf("\terror") } diff --git a/blockchain/storagev2/mdbx/mdbx.go b/blockchain/storagev2/mdbx/mdbx.go index 180e5f8ef7..eb00551384 100644 --- a/blockchain/storagev2/mdbx/mdbx.go +++ b/blockchain/storagev2/mdbx/mdbx.go @@ -162,20 +162,24 @@ func (db *MdbxDB) openDBI(flags uint) error { } // Get retrieves the key-value pair in mdbx storage -func (db *MdbxDB) Get(t uint8, k []byte) ([]byte, error) { +func (db *MdbxDB) Get(t uint8, k []byte) ([]byte, bool, error) { tx, err := db.env.BeginTxn(nil, mdbx.Readonly) defer tx.Abort() if err != nil { - return nil, err + return nil, false, err } - v, err := tx.Get(db.dbi[t], k) + data, err := tx.Get(db.dbi[t], k) if err != nil { - return nil, err + if err.Error() == "key not found" { + return nil, false, nil + } + + return nil, false, err } - return v, nil + return data, true, nil } // Close closes the mdbx storage instance diff --git a/blockchain/storagev2/mdbx/mdbx_perf_test.go b/blockchain/storagev2/mdbx/mdbx_perf_test.go index 5142d5a060..ca5b313647 100644 --- a/blockchain/storagev2/mdbx/mdbx_perf_test.go +++ b/blockchain/storagev2/mdbx/mdbx_perf_test.go @@ -211,7 +211,7 @@ func TestReadBlockPerf(t *testing.T) { watch := stopwatch.Start() _, err1 := s.ReadBody(n) - h, err2 := s.ReadCanonicalHash(n) + h, ok := s.ReadCanonicalHash(n) _, err3 := s.ReadHeader(n) _, err4 := s.ReadReceipts(n) b, err5 := s.ReadBlockLookup(h) @@ -219,7 +219,7 @@ func TestReadBlockPerf(t *testing.T) { watch.Stop() watchTime = watchTime + int(watch.Milliseconds()) - if err1 != nil || err2 != nil || err3 != nil || err4 != nil || err5 != nil { + if err1 != nil || !ok || err3 != nil || err4 != nil || err5 != nil { t.Logf("\terror") } diff --git a/blockchain/storagev2/storage.go b/blockchain/storagev2/storage.go index 38a62a659f..b480bc04b2 100644 --- a/blockchain/storagev2/storage.go +++ b/blockchain/storagev2/storage.go @@ -2,13 +2,15 @@ package storagev2 import ( + "fmt" + "github.com/hashicorp/go-hclog" ) // Database interface. type Database interface { Close() error - Get(t uint8, k []byte) ([]byte, error) + Get(t uint8, k []byte) ([]byte, bool, error) NewBatch() Batch } @@ -57,6 +59,9 @@ var FORK_KEY = []byte("0000000f") var HEAD_HASH_KEY = []byte("0000000h") var HEAD_NUMBER_KEY = []byte("0000000n") +var ErrNotFound = fmt.Errorf("not found") +var ErrInvalidData = fmt.Errorf("invalid data") + func Open(logger hclog.Logger, db [2]Database) (*Storage, error) { return &Storage{logger: logger, db: db}, nil } diff --git a/blockchain/storagev2/storage_read.go b/blockchain/storagev2/storage_read.go index 35a10e0442..1ff2b01740 100644 --- a/blockchain/storagev2/storage_read.go +++ b/blockchain/storagev2/storage_read.go @@ -1,8 +1,6 @@ -//nolint:stylecheck package storagev2 import ( - "errors" "math/big" "github.com/0xPolygon/polygon-edge/helper/common" @@ -12,39 +10,39 @@ import ( // -- canonical hash -- // ReadCanonicalHash gets the hash from the number of the canonical chain -func (s *Storage) ReadCanonicalHash(n uint64) (types.Hash, error) { - data, err := s.get(CANONICAL, common.EncodeUint64ToBytes(n)) - if err != nil { - return types.Hash{}, err +func (s *Storage) ReadCanonicalHash(n uint64) (types.Hash, bool) { + data, ok := s.get(CANONICAL, common.EncodeUint64ToBytes(n)) + if !ok { + return types.Hash{}, false } - return types.BytesToHash(data), nil + return types.BytesToHash(data), true } // HEAD // // ReadHeadHash returns the hash of the head -func (s *Storage) ReadHeadHash() (types.Hash, error) { - data, err := s.get(HEAD_HASH, HEAD_HASH_KEY) - if err != nil { - return types.Hash{}, err +func (s *Storage) ReadHeadHash() (types.Hash, bool) { + data, ok := s.get(HEAD_HASH, HEAD_HASH_KEY) + if !ok { + return types.Hash{}, false } - return types.BytesToHash(data), nil + return types.BytesToHash(data), true } // ReadHeadNumber returns the number of the head -func (s *Storage) ReadHeadNumber() (uint64, error) { - data, err := s.get(HEAD_NUMBER, HEAD_NUMBER_KEY) - if err != nil { - return 0, err +func (s *Storage) ReadHeadNumber() (uint64, bool) { + data, ok := s.get(HEAD_NUMBER, HEAD_NUMBER_KEY) + if !ok { + return 0, false } if len(data) != 8 { - return 0, errors.New("Invalid data") + return 0, false } - return common.EncodeBytesToUint64(data), nil + return common.EncodeBytesToUint64(data), true } // FORK // @@ -60,13 +58,13 @@ func (s *Storage) ReadForks() ([]types.Hash, error) { // DIFFICULTY // // ReadTotalDifficulty reads the difficulty -func (s *Storage) ReadTotalDifficulty(bn uint64) (*big.Int, error) { - v, err := s.get(DIFFICULTY, common.EncodeUint64ToBytes(bn)) - if err != nil { - return nil, err +func (s *Storage) ReadTotalDifficulty(bn uint64) (*big.Int, bool) { + v, ok := s.get(DIFFICULTY, common.EncodeUint64ToBytes(bn)) + if !ok { + return nil, false } - return big.NewInt(0).SetBytes(v), nil + return big.NewInt(0).SetBytes(v), true } // HEADER // @@ -126,25 +124,29 @@ func (s *Storage) ReadBlockLookup(hash types.Hash) (uint64, error) { } func (s *Storage) readLookup(t uint8, hash types.Hash) (uint64, error) { - data, err := s.get(t, hash.Bytes()) - if err != nil { - return 0, err + data, ok := s.get(t, hash.Bytes()) + if !ok { + return 0, ErrNotFound } if len(data) != 8 { - return 0, errors.New("Invalid data") + return 0, ErrInvalidData } return common.EncodeBytesToUint64(data), nil } func (s *Storage) readRLP(t uint8, k []byte, raw types.RLPUnmarshaler) error { - data, err := s.getDB(t).Get(t, k) + data, ok, err := s.getDB(t).Get(t, k) if err != nil { return err } + if !ok { + return ErrNotFound + } + if obj, ok := raw.(types.RLPStoreUnmarshaler); ok { // decode in the store format if err := obj.UnmarshalStoreRLP(data); err != nil { @@ -160,14 +162,14 @@ func (s *Storage) readRLP(t uint8, k []byte, raw types.RLPUnmarshaler) error { return nil } -func (s *Storage) get(t uint8, k []byte) ([]byte, error) { - data, err := s.getDB(t).Get(t, k) +func (s *Storage) get(t uint8, k []byte) ([]byte, bool) { + data, ok, err := s.getDB(t).Get(t, k) if err != nil { - return nil, err + return nil, false } - return data, nil + return data, ok } func (s *Storage) getDB(t uint8) Database { diff --git a/blockchain/storagev2/testing.go b/blockchain/storagev2/testing.go index 3bf1acd65a..c64c47886c 100644 --- a/blockchain/storagev2/testing.go +++ b/blockchain/storagev2/testing.go @@ -92,8 +92,8 @@ func testCanonicalChain(t *testing.T, m PlaceholderStorage) { require.NoError(t, batch.WriteBatch()) - data, err := s.ReadCanonicalHash(cc.Number) - assert.NoError(t, err) + data, ok := s.ReadCanonicalHash(cc.Number) + assert.True(t, ok) if !reflect.DeepEqual(data, hash) { t.Fatal("not match") @@ -134,8 +134,8 @@ func testDifficulty(t *testing.T, m PlaceholderStorage) { require.NoError(t, batch.WriteBatch()) - diff, err := s.ReadTotalDifficulty(h.Number) - assert.NoError(t, err) + diff, ok := s.ReadTotalDifficulty(h.Number) + assert.True(t, ok) if !reflect.DeepEqual(cc.Diff, diff) { t.Fatal("bad") @@ -164,15 +164,15 @@ func testHead(t *testing.T, m PlaceholderStorage) { require.NoError(t, batch.WriteBatch()) - n2, err := s.ReadHeadNumber() - assert.NoError(t, err) + n2, ok := s.ReadHeadNumber() + assert.True(t, ok) if n2 != i { t.Fatal("bad") } - hash1, err := s.ReadHeadHash() - assert.NoError(t, err) + hash1, ok := s.ReadHeadHash() + assert.True(t, ok) if !reflect.DeepEqual(hash1, hash) { t.Fatal("bad") @@ -407,22 +407,22 @@ func testWriteCanonicalHeader(t *testing.T, m PlaceholderStorage) { t.Fatal("bad header") } - headHash, err := s.ReadHeadHash() - assert.NoError(t, err) + headHash, ok := s.ReadHeadHash() + assert.True(t, ok) if headHash != h.Hash { t.Fatal("head hash not correct") } - headNum, err := s.ReadHeadNumber() - assert.NoError(t, err) + headNum, ok := s.ReadHeadNumber() + assert.True(t, ok) if headNum != h.Number { t.Fatal("head num not correct") } - canHash, err := s.ReadCanonicalHash(h.Number) - assert.NoError(t, err) + canHash, ok := s.ReadCanonicalHash(h.Number) + assert.True(t, ok) if canHash != h.Hash { t.Fatal("canonical hash not correct")