go-ethereum/triedb/pathdb/history_trienode_utils.go
rjl493456442 494908a852
Some checks are pending
/ Linux Build (push) Waiting to run
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run
triedb/pathdb: change the bitmap to big endian (#33584)
The bitmap is used in compact-encoded trie nodes to indicate which elements 
have been modified. The bitmap format has been updated to use big-endian
encoding. 

Bit positions are numbered from 0 to 15, where position 0 corresponds to
the most significant bit of b[0], and position 15 corresponds to the least
significant bit of b[1].
2026-01-15 17:28:57 +08:00

106 lines
2.9 KiB
Go

// Copyright 2025 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package pathdb
import (
"encoding/binary"
"fmt"
"math/bits"
"slices"
)
// commonPrefixLen returns the length of the common prefix shared by a and b.
func commonPrefixLen(a, b []byte) int {
n := min(len(a), len(b))
for i := range n {
if a[i] != b[i] {
return i
}
}
return n
}
// encodeIDs sorts the given list of uint16 IDs and encodes them into a
// compact byte slice using variable-length unsigned integer encoding.
func encodeIDs(ids []uint16) []byte {
slices.Sort(ids)
buf := make([]byte, 0, len(ids))
for _, id := range ids {
buf = binary.AppendUvarint(buf, uint64(id))
}
return buf
}
// decodeIDs decodes a sequence of variable-length encoded uint16 IDs from the
// given byte slice and returns them as a set.
//
// Returns an error if the input buffer does not contain a complete Uvarint value.
func decodeIDs(buf []byte) ([]uint16, error) {
var res []uint16
for len(buf) > 0 {
id, n := binary.Uvarint(buf)
if n <= 0 {
return nil, fmt.Errorf("too short for decoding node id, %v", buf)
}
buf = buf[n:]
res = append(res, uint16(id))
}
return res, nil
}
// isAncestor reports whether node x is the ancestor of node y.
func isAncestor(x, y uint16) bool {
for y > x {
y = (y - 1) / 16 // parentID(y) = (y - 1) / 16
if y == x {
return true
}
}
return false
}
// isBitSet reports whether the bit at `index` in the byte slice `b` is set.
func isBitSet(b []byte, index int) bool {
return b[index/8]&(1<<(7-index%8)) != 0
}
// setBit sets the bit at `index` in the byte slice `b` to 1.
func setBit(b []byte, index int) {
b[index/8] |= 1 << (7 - index%8)
}
// bitPosTwoBytes returns the positions of set bits in a 2-byte bitmap.
//
// The bitmap is interpreted as a big-endian uint16. Bit positions are
// numbered from 0 to 15, where position 0 corresponds to the most
// significant bit of b[0], and position 15 corresponds to the least
// significant bit of b[1].
func bitPosTwoBytes(b []byte) []int {
if len(b) != 2 {
panic("expect 2 bytes")
}
var (
pos []int
mask = binary.BigEndian.Uint16(b)
)
for mask != 0 {
p := bits.LeadingZeros16(mask)
pos = append(pos, p)
mask &^= 1 << (15 - p)
}
return pos
}