mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 22:26:42 +00:00
feat&perf: reversed bit of key when persisting zktrie (#410)
* bit reverse when persisting zktrie * fix according to review * Update version.go --------- Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
This commit is contained in:
parent
a677ee3ccf
commit
134e1b8f92
3 changed files with 132 additions and 4 deletions
|
|
@ -23,8 +23,8 @@ import (
|
|||
|
||||
const (
|
||||
VersionMajor = 4 // Major version component of the current release
|
||||
VersionMinor = 2 // Minor version component of the current release
|
||||
VersionPatch = 11 // Patch version component of the current release
|
||||
VersionMinor = 3 // Minor version component of the current release
|
||||
VersionPatch = 0 // Patch version component of the current release
|
||||
VersionMeta = "sepolia" // Version metadata to append to the version string
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,13 @@ import (
|
|||
"github.com/scroll-tech/go-ethereum/ethdb"
|
||||
)
|
||||
|
||||
// ZktrieDatabase Database adaptor imple zktrie.ZktrieDatbase
|
||||
// ZktrieDatabase Database adaptor implements zktrie.ZktrieDatbase
|
||||
// It also reverses the bit order of the key being persisted.
|
||||
// This ensures that the adjacent leaf in zktrie maintains minimal
|
||||
// distance when persisted with dictionary order in LevelDB.
|
||||
// Consequently, this optimizes the snapshot operation, allowing it
|
||||
// to iterate through adjacent leaves at a reduced cost.
|
||||
|
||||
type ZktrieDatabase struct {
|
||||
db *Database
|
||||
prefix []byte
|
||||
|
|
@ -29,6 +35,7 @@ func NewZktrieDatabaseFromTriedb(db *Database) *ZktrieDatabase {
|
|||
|
||||
// Put saves a key:value into the Storage
|
||||
func (l *ZktrieDatabase) Put(k, v []byte) error {
|
||||
k = bitReverse(k)
|
||||
l.db.lock.Lock()
|
||||
l.db.rawDirties.Put(Concat(l.prefix, k[:]), v)
|
||||
l.db.lock.Unlock()
|
||||
|
|
@ -37,6 +44,7 @@ func (l *ZktrieDatabase) Put(k, v []byte) error {
|
|||
|
||||
// Get retrieves a value from a key in the Storage
|
||||
func (l *ZktrieDatabase) Get(key []byte) ([]byte, error) {
|
||||
key = bitReverse(key)
|
||||
concatKey := Concat(l.prefix, key[:])
|
||||
l.db.lock.RLock()
|
||||
value, ok := l.db.rawDirties.Get(concatKey)
|
||||
|
|
@ -78,7 +86,7 @@ func (l *ZktrieDatabase) Iterate(f func([]byte, []byte) (bool, error)) error {
|
|||
iter := l.db.diskdb.NewIterator(l.prefix, nil)
|
||||
defer iter.Release()
|
||||
for iter.Next() {
|
||||
localKey := iter.Key()[len(l.prefix):]
|
||||
localKey := bitReverse(iter.Key()[len(l.prefix):])
|
||||
if cont, err := f(localKey, iter.Value()); err != nil {
|
||||
return err
|
||||
} else if !cont {
|
||||
|
|
@ -109,3 +117,54 @@ func (l *ZktrieDatabase) List(limit int) ([]KV, error) {
|
|||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func bitReverseForNibble(b byte) byte {
|
||||
switch b {
|
||||
case 0:
|
||||
return 0
|
||||
case 1:
|
||||
return 8
|
||||
case 2:
|
||||
return 4
|
||||
case 3:
|
||||
return 12
|
||||
case 4:
|
||||
return 2
|
||||
case 5:
|
||||
return 10
|
||||
case 6:
|
||||
return 6
|
||||
case 7:
|
||||
return 14
|
||||
case 8:
|
||||
return 1
|
||||
case 9:
|
||||
return 9
|
||||
case 10:
|
||||
return 5
|
||||
case 11:
|
||||
return 13
|
||||
case 12:
|
||||
return 3
|
||||
case 13:
|
||||
return 11
|
||||
case 14:
|
||||
return 7
|
||||
case 15:
|
||||
return 15
|
||||
default:
|
||||
panic("unexpected input")
|
||||
}
|
||||
}
|
||||
|
||||
func bitReverse(inp []byte) (out []byte) {
|
||||
|
||||
l := len(inp)
|
||||
out = make([]byte, l)
|
||||
|
||||
for i, b := range inp {
|
||||
out[l-i-1] = bitReverseForNibble(b&15)<<4 + bitReverseForNibble(b>>4)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
|||
69
trie/zk_trie_database_test.go
Normal file
69
trie/zk_trie_database_test.go
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
package trie
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/scroll-tech/go-ethereum/common"
|
||||
)
|
||||
|
||||
// grep from `feat/snap`
|
||||
func reverseBitInPlace(b []byte) {
|
||||
var v [8]uint8
|
||||
for i := 0; i < len(b); i++ {
|
||||
for j := 0; j < 8; j++ {
|
||||
v[j] = (b[i] >> j) & 1
|
||||
}
|
||||
var tmp uint8 = 0
|
||||
for j := 0; j < 8; j++ {
|
||||
tmp |= v[8-j-1] << j
|
||||
}
|
||||
b[i] = tmp
|
||||
}
|
||||
}
|
||||
|
||||
func reverseBytesInPlace(b []byte) {
|
||||
for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
|
||||
b[i], b[j] = b[j], b[i]
|
||||
}
|
||||
}
|
||||
|
||||
func TestBitReverse(t *testing.T) {
|
||||
|
||||
for _, testBytes := range [][]byte{
|
||||
common.FromHex("7b908cce3bc16abb3eac5dff6c136856526f15225f74ce860a2bec47912a5492"),
|
||||
common.FromHex("fac65cd2ad5e301083d0310dd701b5faaff1364cbe01cdbfaf4ec3609bb4149e"),
|
||||
common.FromHex("55791f6ec2f83fee512a2d3d4b505784fdefaea89974e10440d01d62a18a298a"),
|
||||
common.FromHex("5ab775b64d86a8058bb71c3c765d0f2158c14bbeb9cb32a65eda793a7e95e30f"),
|
||||
common.FromHex("ccb464abf67804538908c62431b3a6788e8dc6dee62aff9bfe6b10136acfceac"),
|
||||
common.FromHex("b908adff17a5aa9d6787324c39014a74b04cef7fba6a92aeb730f48da1ca665d"),
|
||||
} {
|
||||
|
||||
b1 := bitReverse(testBytes)
|
||||
reverseBitInPlace(testBytes)
|
||||
reverseBytesInPlace(testBytes)
|
||||
if !bytes.Equal(b1, testBytes) {
|
||||
t.Errorf("unexpected bit reversed %x vs %x", b1, testBytes)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestBitDoubleReverse(t *testing.T) {
|
||||
|
||||
for _, testBytes := range [][]byte{
|
||||
common.FromHex("7b908cce3bc16abb3eac5dff6c136856526f15225f74ce860a2bec47912a5492"),
|
||||
common.FromHex("fac65cd2ad5e301083d0310dd701b5faaff1364cbe01cdbfaf4ec3609bb4149e"),
|
||||
common.FromHex("55791f6ec2f83fee512a2d3d4b505784fdefaea89974e10440d01d62a18a298a"),
|
||||
common.FromHex("5ab775b64d86a8058bb71c3c765d0f2158c14bbeb9cb32a65eda793a7e95e30f"),
|
||||
common.FromHex("ccb464abf67804538908c62431b3a6788e8dc6dee62aff9bfe6b10136acfceac"),
|
||||
common.FromHex("b908adff17a5aa9d6787324c39014a74b04cef7fba6a92aeb730f48da1ca665d"),
|
||||
} {
|
||||
|
||||
b := bitReverse(bitReverse(testBytes))
|
||||
if !bytes.Equal(b, testBytes) {
|
||||
t.Errorf("unexpected double bit reversed %x vs %x", b, testBytes)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in a new issue