Skip to content

Commit

Permalink
make TC a ptr
Browse files Browse the repository at this point in the history
  • Loading branch information
dboehm-avalabs committed Oct 26, 2023
1 parent 2148ac3 commit 6279744
Show file tree
Hide file tree
Showing 12 changed files with 54 additions and 43 deletions.
4 changes: 2 additions & 2 deletions x/merkledb/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ type MerkleDB interface {

type Config struct {
// TokenConfig determines the branching factor and other aspects of the tokens that make up a key
TokenConfig TokenConfiguration
TokenConfig *TokenConfiguration

// RootGenConcurrency is the number of goroutines to use when
// generating a new state root.
Expand Down Expand Up @@ -204,7 +204,7 @@ type merkleDB struct {
// [calculateNodeIDsHelper] at any given time.
calculateNodeIDsSema *semaphore.Weighted

tokenConfig TokenConfiguration
tokenConfig *TokenConfiguration
}

// New returns a new merkle database.
Expand Down
2 changes: 1 addition & 1 deletion x/merkledb/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -851,7 +851,7 @@ const (
opMax // boundary value, not an actual op
)

func runRandDBTest(require *require.Assertions, r *rand.Rand, rt randTest, tc TokenConfiguration) {
func runRandDBTest(require *require.Assertions, r *rand.Rand, rt randTest, tc *TokenConfiguration) {
db, err := getBasicDBWithBranchFactor(tc)
require.NoError(err)

Expand Down
2 changes: 1 addition & 1 deletion x/merkledb/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func getBasicDB() (*merkleDB, error) {
)
}

func getBasicDBWithBranchFactor(bf TokenConfiguration) (*merkleDB, error) {
func getBasicDBWithBranchFactor(bf *TokenConfiguration) (*merkleDB, error) {
config := newDefaultConfig()
config.TokenConfig = bf
return newDatabase(
Expand Down
4 changes: 2 additions & 2 deletions x/merkledb/history.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type trieHistory struct {
// Each change is tagged with this monotonic increasing number.
nextInsertNumber uint64

tc TokenConfiguration
tc *TokenConfiguration
}

// Tracks the beginning and ending state of a value.
Expand Down Expand Up @@ -65,7 +65,7 @@ func newChangeSummary(estimatedSize int) *changeSummary {
}
}

func newTrieHistory(maxHistoryLookback int, tc TokenConfiguration) *trieHistory {
func newTrieHistory(maxHistoryLookback int, tc *TokenConfiguration) *trieHistory {
return &trieHistory{
maxHistoryLen: maxHistoryLookback,
history: buffer.NewUnboundedDeque[*changeSummaryAndInsertNumber](maxHistoryLookback),
Expand Down
4 changes: 2 additions & 2 deletions x/merkledb/intermediate_node_db.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type intermediateNodeDB struct {
// the number of bytes to evict during an eviction batch
evictionBatchSize int
metrics merkleMetrics
tc TokenConfiguration
tc *TokenConfiguration
}

func newIntermediateNodeDB(
Expand All @@ -40,7 +40,7 @@ func newIntermediateNodeDB(
metrics merkleMetrics,
size int,
evictionBatchSize int,
tc TokenConfiguration,
tc *TokenConfiguration,
) *intermediateNodeDB {
result := &intermediateNodeDB{
metrics: metrics,
Expand Down
24 changes: 12 additions & 12 deletions x/merkledb/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,23 @@ import (
var (
ErrInvalidTokenConfig = errors.New("token configuration must match one of the predefined configurations ")

BranchFactor2TokenConfig = TokenConfiguration{
BranchFactor2TokenConfig = &TokenConfiguration{
branchFactor: 2,
bitsPerToken: 1,
}
BranchFactor4TokenConfig = TokenConfiguration{
BranchFactor4TokenConfig = &TokenConfiguration{
branchFactor: 4,
bitsPerToken: 2,
}
BranchFactor16TokenConfig = TokenConfiguration{
BranchFactor16TokenConfig = &TokenConfiguration{
branchFactor: 16,
bitsPerToken: 4,
}
BranchFactor256TokenConfig = TokenConfiguration{
BranchFactor256TokenConfig = &TokenConfiguration{
branchFactor: 256,
bitsPerToken: 8,
}
validTokenConfigurations = []TokenConfiguration{
validTokenConfigurations = []*TokenConfiguration{
BranchFactor2TokenConfig,
BranchFactor4TokenConfig,
BranchFactor16TokenConfig,
Expand All @@ -44,11 +44,11 @@ type TokenConfiguration struct {
bitsPerToken int
}

func (t TokenConfiguration) ToKey(val byte) Key {
func (t *TokenConfiguration) ToKey(val byte) Key {
return Key{value: string([]byte{val << dualBitIndex(t.bitsPerToken)}), length: t.bitsPerToken}
}

func (t TokenConfiguration) Valid() error {
func (t *TokenConfiguration) Valid() error {
for _, validConfig := range validTokenConfigurations {
if validConfig == t {
return nil
Expand All @@ -58,15 +58,15 @@ func (t TokenConfiguration) Valid() error {
}

// Token returns the token at the specified index,
func (t TokenConfiguration) Token(k Key, bitIndex int) byte {
func (t *TokenConfiguration) Token(k Key, bitIndex int) byte {
storageByte := k.value[bitIndex/8]
// Shift the byte right to get the token to the rightmost position.
storageByte >>= dualBitIndex((bitIndex + t.bitsPerToken) % 8)
// Apply a mask to remove any other tokens in the byte.
return storageByte & (0xFF >> dualBitIndex(t.bitsPerToken))
}

func (t TokenConfiguration) getLengthOfCommonPrefix(first, second Key, secondOffset int) int {
func (t *TokenConfiguration) getLengthOfCommonPrefix(first, second Key, secondOffset int) int {
commonIndex := 0
for first.length > commonIndex && second.length > commonIndex+secondOffset &&
t.Token(first, commonIndex) == t.Token(second, commonIndex+secondOffset) {
Expand All @@ -77,7 +77,7 @@ func (t TokenConfiguration) getLengthOfCommonPrefix(first, second Key, secondOff

// iteratedHasPrefix checks if the provided prefix path is a prefix of the current path after having skipped [skipTokens] tokens first
// this has better performance than constructing the actual path via Skip() then calling HasPrefix because it avoids the []byte allocation
func (t TokenConfiguration) hasPrefix(k Key, prefix Key, bitsToSkip int) bool {
func (t *TokenConfiguration) hasPrefix(k Key, prefix Key, bitsToSkip int) bool {
if k.length-bitsToSkip < prefix.length {
return false
}
Expand All @@ -89,11 +89,11 @@ func (t TokenConfiguration) hasPrefix(k Key, prefix Key, bitsToSkip int) bool {
return true
}

func (t TokenConfiguration) BranchFactor() int {
func (t *TokenConfiguration) BranchFactor() int {
return t.branchFactor
}

func (t TokenConfiguration) BitsPerToken() int {
func (t *TokenConfiguration) BitsPerToken() int {
return t.bitsPerToken
}

Expand Down
37 changes: 24 additions & 13 deletions x/merkledb/key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ import (
"github.com/stretchr/testify/require"
)

func TestTokenConfigValid(t *testing.T) {
require := require.New(t)
for _, tc := range validTokenConfigurations {
require.NoError(tc.Valid())
}
require.Error((&TokenConfiguration{}).Valid())

var nilTC *TokenConfiguration
require.Error(nilTC.Valid())
}

func TestHasPartialByte(t *testing.T) {
for _, branchFactor := range validTokenConfigurations {
t.Run(fmt.Sprint(branchFactor), func(t *testing.T) {
Expand Down Expand Up @@ -48,8 +59,8 @@ func TestHasPartialByte(t *testing.T) {
func Test_Key_Has_Prefix(t *testing.T) {
type test struct {
name string
keyA func(bf TokenConfiguration) Key
keyB func(bf TokenConfiguration) Key
keyA func(bf *TokenConfiguration) Key
keyB func(bf *TokenConfiguration) Key
isStrictPrefix bool
isPrefix bool
}
Expand All @@ -59,44 +70,44 @@ func Test_Key_Has_Prefix(t *testing.T) {
tests := []test{
{
name: "equal keys",
keyA: func(bf TokenConfiguration) Key { return ToKey([]byte(key)) },
keyB: func(bf TokenConfiguration) Key { return ToKey([]byte(key)) },
keyA: func(bf *TokenConfiguration) Key { return ToKey([]byte(key)) },
keyB: func(bf *TokenConfiguration) Key { return ToKey([]byte(key)) },
isPrefix: true,
isStrictPrefix: false,
},
{
name: "one key has one fewer token",
keyA: func(bf TokenConfiguration) Key { return ToKey([]byte(key)) },
keyB: func(bf TokenConfiguration) Key {
keyA: func(bf *TokenConfiguration) Key { return ToKey([]byte(key)) },
keyB: func(bf *TokenConfiguration) Key {
return ToKey([]byte(key)).Take(len(key)*8 - bf.bitsPerToken)
},
isPrefix: true,
isStrictPrefix: true,
},
{
name: "equal keys, both have one fewer token",
keyA: func(bf TokenConfiguration) Key {
keyA: func(bf *TokenConfiguration) Key {
return ToKey([]byte(key)).Take(len(key)*8 - bf.bitsPerToken)
},
keyB: func(bf TokenConfiguration) Key {
keyB: func(bf *TokenConfiguration) Key {
return ToKey([]byte(key)).Take(len(key)*8 - bf.bitsPerToken)
},
isPrefix: true,
isStrictPrefix: false,
},
{
name: "different keys",
keyA: func(bf TokenConfiguration) Key { return ToKey([]byte{0xF7}) },
keyB: func(bf TokenConfiguration) Key { return ToKey([]byte{0xF0}) },
keyA: func(bf *TokenConfiguration) Key { return ToKey([]byte{0xF7}) },
keyB: func(bf *TokenConfiguration) Key { return ToKey([]byte{0xF0}) },
isPrefix: false,
isStrictPrefix: false,
},
{
name: "same bytes, different lengths",
keyA: func(bf TokenConfiguration) Key {
keyA: func(bf *TokenConfiguration) Key {
return ToKey([]byte{0x10, 0x00}).Take(bf.bitsPerToken)
},
keyB: func(bf TokenConfiguration) Key {
keyB: func(bf *TokenConfiguration) Key {
return ToKey([]byte{0x10, 0x00}).Take(bf.bitsPerToken * 2)
},
isPrefix: false,
Expand Down Expand Up @@ -177,7 +188,7 @@ func Test_Key_Token(t *testing.T) {
type test struct {
name string
inputBytes []byte
branchFactor TokenConfiguration
branchFactor *TokenConfiguration
assertTokens func(*require.Assertions, Key)
}

Expand Down
4 changes: 2 additions & 2 deletions x/merkledb/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func (n *node) setValueDigest() {
// Adds [child] as a child of [n].
// Assumes [child]'s key is valid as a child of [n].
// That is, [n.key] is a prefix of [child.key].
func (n *node) addChild(tc TokenConfiguration, childNode *node) {
func (n *node) addChild(tc *TokenConfiguration, childNode *node) {
n.setChildEntry(
tc.Token(childNode.key, n.key.length),
child{
Expand All @@ -130,7 +130,7 @@ func (n *node) setChildEntry(index byte, childEntry child) {
}

// Removes [child] from [n]'s children.
func (n *node) removeChild(tc TokenConfiguration, child *node) {
func (n *node) removeChild(tc *TokenConfiguration, child *node) {
n.onNodeChanged()
delete(n.children, tc.Token(child.key, n.key.length))
}
Expand Down
8 changes: 4 additions & 4 deletions x/merkledb/proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ type Proof struct {
// Returns nil if the trie given in [proof] has root [expectedRootID].
// That is, this is a valid proof that [proof.Key] exists/doesn't exist
// in the trie with root [expectedRootID].
func (proof *Proof) Verify(ctx context.Context, tc TokenConfiguration, expectedRootID ids.ID) error {
func (proof *Proof) Verify(ctx context.Context, tc *TokenConfiguration, expectedRootID ids.ID) error {
// Make sure the proof is well-formed.
if len(proof.Path) == 0 {
return ErrNoProof
Expand Down Expand Up @@ -282,7 +282,7 @@ type RangeProof struct {
// If [end] is Nothing, all keys are considered < [end].
func (proof *RangeProof) Verify(
ctx context.Context,
tc TokenConfiguration,
tc *TokenConfiguration,
start maybe.Maybe[[]byte],
end maybe.Maybe[[]byte],
expectedRootID ids.ID,
Expand Down Expand Up @@ -734,7 +734,7 @@ func verifyKeyValues(kvs []KeyValue, start maybe.Maybe[[]byte], end maybe.Maybe[
// - Each key in [proof] is a strict prefix of [keyBytes], except possibly the last.
// - If the last element in [proof] is [Key], this is an inclusion proof.
// Otherwise, this is an exclusion proof and [keyBytes] must not be in [proof].
func verifyProofPath(tc TokenConfiguration, proof []ProofNode, key maybe.Maybe[Key]) error {
func verifyProofPath(tc *TokenConfiguration, proof []ProofNode, key maybe.Maybe[Key]) error {
if len(proof) == 0 {
return nil
}
Expand Down Expand Up @@ -871,7 +871,7 @@ func addPathInfo(
}

// getStandaloneTrieView returns a new view that has nothing in it besides the changes due to [ops]
func getStandaloneTrieView(ctx context.Context, ops []database.BatchOp, tc TokenConfiguration) (*trieView, error) {
func getStandaloneTrieView(ctx context.Context, ops []database.BatchOp, tc *TokenConfiguration) (*trieView, error) {
db, err := newDatabase(
ctx,
memdb.New(),
Expand Down
2 changes: 1 addition & 1 deletion x/merkledb/trie_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1213,7 +1213,7 @@ func Test_Trie_ConcurrentNewViewAndCommit(t *testing.T) {

// Returns the path of the only child of this node.
// Assumes this node has exactly one child.
func getSingleChildKey(tc TokenConfiguration, n *node) Key {
func getSingleChildKey(tc *TokenConfiguration, n *node) Key {
for index, entry := range n.children {
return n.key.DoubleExtend(tc.ToKey(index), entry.compressedKey)
}
Expand Down
2 changes: 1 addition & 1 deletion x/merkledb/trieview.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ type trieView struct {
// The root of the trie represented by this view.
root *node

tokenConfig TokenConfiguration
tokenConfig *TokenConfiguration
}

// NewView returns a new view on top of this Trie where the passed changes
Expand Down
4 changes: 2 additions & 2 deletions x/merkledb/value_node_db.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ type valueNodeDB struct {
metrics merkleMetrics

closed utils.Atomic[bool]
tokenConfig TokenConfiguration
tokenConfig *TokenConfiguration
}

func newValueNodeDB(
db database.Database,
bufferPool *sync.Pool,
metrics merkleMetrics,
cacheSize int,
tokenConfig TokenConfiguration,
tokenConfig *TokenConfiguration,
) *valueNodeDB {
return &valueNodeDB{
metrics: metrics,
Expand Down

0 comments on commit 6279744

Please sign in to comment.