erigon-pulse/common/dbutils/helper.go
Alex Sharov 965d1101f4
Intermediate hash phase 4 (#396)
* another way to check if account has storage

* cleanup

* v0 of walk by db version

* save progress, to switch to another task. Put tombstone is still not correct.

* place tombstone only if exists something to hide

* db-based implementation

* db-based implementation

* db-based implementation

* fix prop check

* improve prop check logic

* Need custom logic to skip subtree for account and storage buckets because storage bucket has incarnation in key

* rebase to master

* remove all tombstones when account deleted

* remove all tombstones when account deleted

* added db integrity check

* don't rely on account.Root because it valid only about last incarnation

* remove all tombstones when account deleted

* dial with incarnation in MultiWalk2

* dial with incarnation in MultiWalk2

* when fixedbytes=40 resolver did compare cacheKey with storageKey without removing incarnation

* rebase to master

* rebase to master

Co-authored-by: alex.sharov <alex.sharov@lazada.com>
2020-03-20 11:30:14 +00:00

69 lines
1.5 KiB
Go

package dbutils
import "bytes"
// EncodeTimestamp has the property: if a < b, then Encoding(a) < Encoding(b) lexicographically
func EncodeTimestamp(timestamp uint64) []byte {
var suffix []byte
var limit uint64 = 32
for bytecount := 1; bytecount <= 8; bytecount++ {
if timestamp < limit {
suffix = make([]byte, bytecount)
b := timestamp
for i := bytecount - 1; i > 0; i-- {
suffix[i] = byte(b & 0xff)
b >>= 8
}
suffix[0] = byte(b) | (byte(bytecount) << 5) // 3 most significant bits of the first byte are bytecount
break
}
limit <<= 8
}
return suffix
}
func DecodeTimestamp(suffix []byte) (uint64, []byte) {
bytecount := int(suffix[0] >> 5)
timestamp := uint64(suffix[0] & 0x1f)
for i := 1; i < bytecount; i++ {
timestamp = (timestamp << 8) | uint64(suffix[i])
}
return timestamp, suffix[bytecount:]
}
func ChangeSetByIndexBucket(b []byte) []byte {
if bytes.Equal(b, AccountsHistoryBucket) {
return AccountChangeSetBucket
}
if bytes.Equal(b, StorageHistoryBucket) {
return StorageChangeSetBucket
}
panic("wrong bucket")
}
// Cmp - like bytes.Compare, but nil - means "bucket over" and has highest order.
func Cmp(k1, k2 []byte) int {
if k1 == nil && k2 == nil {
return 0
}
if k1 == nil {
return 1
}
if k2 == nil {
return -1
}
return bytes.Compare(k1, k2)
}
// IsBefore - kind of bytes.Compare, but nil is the last key. And return
func IsBefore(k1, k2 []byte) (bool, []byte) {
switch Cmp(k1, k2) {
case -1, 0:
return true, k1
default:
return false, k2
}
}