From f5db7c9bef448a63d9971822c4a848001b985fb7 Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Tue, 20 Dec 2022 09:28:09 +0700 Subject: [PATCH] e3: kv/temporal prototype 2 (#792) --- common/length/length.go | 2 + kv/kv_interface.go | 1 + kv/temporal/historyv2/find_by_history.go | 78 ++++++++++++++++++++++++ state/inverted_index.go | 7 +++ 4 files changed, 88 insertions(+) create mode 100644 kv/temporal/historyv2/find_by_history.go diff --git a/common/length/length.go b/common/length/length.go index 25fabcfee..07836a690 100644 --- a/common/length/length.go +++ b/common/length/length.go @@ -24,6 +24,8 @@ const ( Addr = 20 // BlockNumberLen length of uint64 big endian BlockNum = 8 + // Ts TimeStamp (BlockNum, TxNum or any other uint64 equivalent of Time) + Ts = 8 // Incarnation length of uint64 for contract incarnations Incarnation = 8 ) diff --git a/kv/kv_interface.go b/kv/kv_interface.go index 47adb3b0c..8a6b631eb 100644 --- a/kv/kv_interface.go +++ b/kv/kv_interface.go @@ -26,6 +26,7 @@ import ( //Naming: // ts - TimeStamp // tx - Database Transaction +// txn - Ethereum Transaction (and TxNum - is also number of Etherum Transaction) // RoTx - Read-Only Database Transaction // RwTx - Read-Write Database Transaction // k - key diff --git a/kv/temporal/historyv2/find_by_history.go b/kv/temporal/historyv2/find_by_history.go new file mode 100644 index 000000000..42c895f2f --- /dev/null +++ b/kv/temporal/historyv2/find_by_history.go @@ -0,0 +1,78 @@ +/* + Copyright 2022 Erigon contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package historyv2 + +import ( + "bytes" + "errors" + "fmt" + + "github.com/RoaringBitmap/roaring/roaring64" + "github.com/ledgerwatch/erigon-lib/common/length" + "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon-lib/kv/bitmapdb" +) + +func FindByHistory(indexC kv.Cursor, changesC kv.CursorDupSort, storage bool, key []byte, timestamp uint64) ([]byte, bool, error) { + var csBucket string + if storage { + csBucket = kv.StorageChangeSet + } else { + csBucket = kv.AccountChangeSet + } + + k, v, seekErr := indexC.Seek(Mapper[csBucket].IndexChunkKey(key, timestamp)) + if seekErr != nil { + return nil, false, seekErr + } + + if k == nil { + return nil, false, nil + } + if storage { + if !bytes.Equal(k[:length.Addr], key[:length.Addr]) || + !bytes.Equal(k[length.Addr:length.Addr+length.Hash], key[length.Addr+length.Incarnation:]) { + return nil, false, nil + } + } else { + if !bytes.HasPrefix(k, key) { + return nil, false, nil + } + } + index := roaring64.New() + if _, err := index.ReadFrom(bytes.NewReader(v)); err != nil { + return nil, false, err + } + found, ok := bitmapdb.SeekInBitmap64(index, timestamp) + changeSetBlock := found + + var data []byte + var err error + if ok { + data, err = Mapper[csBucket].Find(changesC, changeSetBlock, key) + if err != nil { + if !errors.Is(err, ErrNotFound) { + return nil, false, fmt.Errorf("finding %x in the changeset %d: %w", key, changeSetBlock, err) + } + return nil, false, nil + } + } else { + return nil, false, nil + } + + return data, true, nil +} diff --git a/state/inverted_index.go b/state/inverted_index.go index 390c69775..1ef06e455 100644 --- a/state/inverted_index.go +++ b/state/inverted_index.go @@ -569,6 +569,13 @@ func (it *InvertedIterator) Next() uint64 { it.advance() return n } +func (it *InvertedIterator) ToBitamp() *roaring64.Bitmap { + bm := bitmapdb.NewBitmap64() + for it.HasNext() { + bm.Add(it.Next()) + } + return bm +} type InvertedIndexContext struct { ii *InvertedIndex