@@ -34,24 +34,53 @@ type RangeFactory struct {
3434 Hash HashFn
3535}
3636
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
3838// hashes correspond to the roots of the minimal set of perfect sub-trees
3939// 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 ) {
4143 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 )
4345 }
4446 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
4662 }
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 }
4873}
4974
5075// NewEmptyRange returns a new Range for an empty [begin, begin) range. The
5176// value of begin defines where the range will start growing from when entries
5277// are appended to it.
78+ //
79+ // It is recommended to use MakeEmptyRange instead, which does not allocate.
80+ // If in doubt, NewEmptyRange is safer.
5381func (f * RangeFactory ) NewEmptyRange (begin uint64 ) * Range {
54- return & Range {f : f , begin : begin , end : begin }
82+ r := f .MakeEmptyRange (begin )
83+ return & r
5584}
5685
5786// Range represents a compact Merkle tree range for leaf indices [begin, end).
@@ -60,8 +89,21 @@ func (f *RangeFactory) NewEmptyRange(begin uint64) *Range {
6089// range. The structure is efficiently mergeable with other compact ranges that
6190// share one of the endpoints with it.
6291//
63- // For more details, see
92+ // For more details on compact ranges and how they can be used , see
6493// 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).
65107type Range struct {
66108 f * RangeFactory
67109 begin uint64
0 commit comments