...

Source file src/github.com/transparency-dev/merkle/compact/nodes.go

Documentation: github.com/transparency-dev/merkle/compact

     1  // Copyright 2019 Google LLC. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package compact
    16  
    17  import "math/bits"
    18  
    19  // NodeID identifies a node of a Merkle tree.
    20  //
    21  // The ID consists of a level and index within this level. Levels are numbered
    22  // from 0, which corresponds to the tree leaves. Within each level, nodes are
    23  // numbered with consecutive indices starting from 0.
    24  //
    25  //	L4:         ┌───────0───────┐                ...
    26  //	L3:     ┌───0───┐       ┌───1───┐       ┌─── ...
    27  //	L2:   ┌─0─┐   ┌─1─┐   ┌─2─┐   ┌─3─┐   ┌─4─┐  ...
    28  //	L1:  ┌0┐ ┌1┐ ┌2┐ ┌3┐ ┌4┐ ┌5┐ ┌6┐ ┌7┐ ┌8┐ ┌9┐ ...
    29  //	L0:  0 1 2 3 4 5 6 7 8 9 ... ... ... ... ... ...
    30  //
    31  // When the tree is not perfect, the nodes that would complement it to perfect
    32  // are called ephemeral. Algorithms that operate with ephemeral nodes still map
    33  // them to the same address space.
    34  type NodeID struct {
    35  	Level uint
    36  	Index uint64
    37  }
    38  
    39  // NewNodeID returns a NodeID with the passed in node coordinates.
    40  func NewNodeID(level uint, index uint64) NodeID {
    41  	return NodeID{Level: level, Index: index}
    42  }
    43  
    44  // Parent returns the ID of the parent node.
    45  func (id NodeID) Parent() NodeID {
    46  	return NewNodeID(id.Level+1, id.Index>>1)
    47  }
    48  
    49  // Sibling returns the ID of the sibling node.
    50  func (id NodeID) Sibling() NodeID {
    51  	return NewNodeID(id.Level, id.Index^1)
    52  }
    53  
    54  // Coverage returns the [begin, end) range of leaves covered by the node.
    55  func (id NodeID) Coverage() (uint64, uint64) {
    56  	return id.Index << id.Level, (id.Index + 1) << id.Level
    57  }
    58  
    59  // RangeNodes appends the IDs of the nodes that comprise the [begin, end)
    60  // compact range to the given slice, and returns the new slice. The caller may
    61  // pre-allocate space with the help of the RangeSize function.
    62  func RangeNodes(begin, end uint64, ids []NodeID) []NodeID {
    63  	left, right := Decompose(begin, end)
    64  
    65  	pos := begin
    66  	// Iterate over perfect subtrees along the left border of the range, ordered
    67  	// from lower to upper levels.
    68  	for bit := uint64(0); left != 0; pos, left = pos+bit, left^bit {
    69  		level := uint(bits.TrailingZeros64(left))
    70  		bit = uint64(1) << level
    71  		ids = append(ids, NewNodeID(level, pos>>level))
    72  	}
    73  
    74  	// Iterate over perfect subtrees along the right border of the range, ordered
    75  	// from upper to lower levels.
    76  	for bit := uint64(0); right != 0; pos, right = pos+bit, right^bit {
    77  		level := uint(bits.Len64(right)) - 1
    78  		bit = uint64(1) << level
    79  		ids = append(ids, NewNodeID(level, pos>>level))
    80  	}
    81  
    82  	return ids
    83  }
    84  
    85  // RangeSize returns the number of nodes in the [begin, end) compact range.
    86  func RangeSize(begin, end uint64) int {
    87  	left, right := Decompose(begin, end)
    88  	return bits.OnesCount64(left) + bits.OnesCount64(right)
    89  }
    90  

View as plain text