-
Notifications
You must be signed in to change notification settings - Fork 665
/
disk_staker_diff_iterator.go
97 lines (84 loc) · 2.89 KB
/
disk_staker_diff_iterator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package state
import (
"encoding/binary"
"fmt"
"github.com/ava-labs/avalanchego/database"
"github.com/ava-labs/avalanchego/ids"
)
const (
// startDiffKey = [subnetID] + [inverseHeight]
startDiffKeyLength = ids.IDLen + database.Uint64Size
// diffKey = [subnetID] + [inverseHeight] + [nodeID]
diffKeyLength = startDiffKeyLength + ids.NodeIDLen
// diffKeyNodeIDOffset = [subnetIDLen] + [inverseHeightLen]
diffKeyNodeIDOffset = ids.IDLen + database.Uint64Size
// weightValue = [isNegative] + [weight]
weightValueLength = database.BoolSize + database.Uint64Size
)
var (
errUnexpectedDiffKeyLength = fmt.Errorf("expected diff key length %d", diffKeyLength)
errUnexpectedWeightValueLength = fmt.Errorf("expected weight value length %d", weightValueLength)
)
// marshalStartDiffKey is used to determine the starting key when iterating.
//
// Invariant: the result is a prefix of [marshalDiffKey] when called with the
// same arguments.
func marshalStartDiffKey(subnetID ids.ID, height uint64) []byte {
key := make([]byte, startDiffKeyLength)
copy(key, subnetID[:])
packIterableHeight(key[ids.IDLen:], height)
return key
}
func marshalDiffKey(subnetID ids.ID, height uint64, nodeID ids.NodeID) []byte {
key := make([]byte, diffKeyLength)
copy(key, subnetID[:])
packIterableHeight(key[ids.IDLen:], height)
copy(key[diffKeyNodeIDOffset:], nodeID.Bytes())
return key
}
func unmarshalDiffKey(key []byte) (ids.ID, uint64, ids.NodeID, error) {
if len(key) != diffKeyLength {
return ids.Empty, 0, ids.EmptyNodeID, errUnexpectedDiffKeyLength
}
var (
subnetID ids.ID
nodeID ids.NodeID
)
copy(subnetID[:], key)
height := unpackIterableHeight(key[ids.IDLen:])
copy(nodeID[:], key[diffKeyNodeIDOffset:])
return subnetID, height, nodeID, nil
}
func marshalWeightDiff(diff *ValidatorWeightDiff) []byte {
value := make([]byte, weightValueLength)
if diff.Decrease {
value[0] = database.BoolTrue
}
binary.BigEndian.PutUint64(value[database.BoolSize:], diff.Amount)
return value
}
func unmarshalWeightDiff(value []byte) (*ValidatorWeightDiff, error) {
if len(value) != weightValueLength {
return nil, errUnexpectedWeightValueLength
}
return &ValidatorWeightDiff{
Decrease: value[0] == database.BoolTrue,
Amount: binary.BigEndian.Uint64(value[database.BoolSize:]),
}, nil
}
// Note: [height] is encoded as a bit flipped big endian number so that
// iterating lexicographically results in iterating in decreasing heights.
//
// Invariant: [key] has sufficient length
func packIterableHeight(key []byte, height uint64) {
binary.BigEndian.PutUint64(key, ^height)
}
// Because we bit flip the height when constructing the key, we must remember to
// bip flip again here.
//
// Invariant: [key] has sufficient length
func unpackIterableHeight(key []byte) uint64 {
return ^binary.BigEndian.Uint64(key)
}