@@ -34,24 +34,53 @@ type RangeFactory struct {
34
34
Hash HashFn
35
35
}
36
36
37
- // NewRange creates a Range for [begin, end) with the given set of hashes. The
37
+ // MakeRange creates a Range for [begin, end) with the given set of hashes. The
38
38
// hashes correspond to the roots of the minimal set of perfect sub-trees
39
39
// covering the [begin, end) leaves range, ordered left to right.
40
- func (f * RangeFactory ) NewRange (begin , end uint64 , hashes [][]byte ) (* Range , error ) {
40
+ //
41
+ // See the Hazard in the Range comment to avoid pitfalls.
42
+ func (f * RangeFactory ) MakeRange (begin , end uint64 , hashes [][]byte ) (Range , error ) {
41
43
if end < begin {
42
- return nil , fmt .Errorf ("invalid range: end=%d, want >= %d" , end , begin )
44
+ return Range {} , fmt .Errorf ("invalid range: end=%d, want >= %d" , end , begin )
43
45
}
44
46
if got , want := len (hashes ), RangeSize (begin , end ); got != want {
45
- return nil , fmt .Errorf ("invalid hashes: got %d values, want %d" , got , want )
47
+ return Range {}, fmt .Errorf ("invalid hashes: got %d values, want %d" , got , want )
48
+ }
49
+ return Range {f : f , begin : begin , end : end , hashes : hashes }, nil
50
+ }
51
+
52
+ // NewRange creates a Range for [begin, end) with the given set of hashes. The
53
+ // hashes correspond to the roots of the minimal set of perfect sub-trees
54
+ // covering the [begin, end) leaves range, ordered left to right.
55
+ //
56
+ // It is recommended to use MakeRange instead, which does not allocate.
57
+ // If in doubt, NewRange is safer.
58
+ func (f * RangeFactory ) NewRange (begin , end uint64 , hashes [][]byte ) (* Range , error ) {
59
+ r , err := f .MakeRange (begin , end , hashes )
60
+ if err != nil {
61
+ return nil , err
46
62
}
47
- return & Range {f : f , begin : begin , end : end , hashes : hashes }, nil
63
+ return & r , nil
64
+ }
65
+
66
+ // MakeEmptyRange returns a new Range for an empty [begin, begin) range. The
67
+ // value of begin defines where the range will start growing from when entries
68
+ // are appended to it.
69
+ //
70
+ // See the Hazard in the Range comment to avoid pitfalls.
71
+ func (f * RangeFactory ) MakeEmptyRange (begin uint64 ) Range {
72
+ return Range {f : f , begin : begin , end : begin }
48
73
}
49
74
50
75
// NewEmptyRange returns a new Range for an empty [begin, begin) range. The
51
76
// value of begin defines where the range will start growing from when entries
52
77
// are appended to it.
78
+ //
79
+ // It is recommended to use MakeEmptyRange instead, which does not allocate.
80
+ // If in doubt, NewEmptyRange is safer.
53
81
func (f * RangeFactory ) NewEmptyRange (begin uint64 ) * Range {
54
- return & Range {f : f , begin : begin , end : begin }
82
+ r := f .MakeEmptyRange (begin )
83
+ return & r
55
84
}
56
85
57
86
// Range represents a compact Merkle tree range for leaf indices [begin, end).
@@ -60,8 +89,21 @@ func (f *RangeFactory) NewEmptyRange(begin uint64) *Range {
60
89
// range. The structure is efficiently mergeable with other compact ranges that
61
90
// share one of the endpoints with it.
62
91
//
63
- // For more details, see
92
+ // For more details on compact ranges and how they can be used , see
64
93
// https://github.com/transparency-dev/merkle/blob/main/docs/compact_ranges.md.
94
+ //
95
+ // Hazard: the Range is mutable, and its internal slice can be updated in-place
96
+ // by Append* methods.
97
+ //
98
+ // cr := factory.MakeRange(0, 10, hashes)
99
+ // populate(cr, leaves) // internally calls cr.Append()
100
+ // use(cr) // hazard: cr could be corrupted by populate()
101
+ //
102
+ // To be safe, the Range should be used by pointer. When using by value, be
103
+ // sure that it is either semantically immutable, or the value is updated after
104
+ // mutations (e.g., in the example above, the updated Range is returned from
105
+ // the populate() function and assigned to cr). The latter is a common pattern
106
+ // in Go, think slices: slice = append(slice, value).
65
107
type Range struct {
66
108
f * RangeFactory
67
109
begin uint64
0 commit comments