Example #1
0
// the game is: walk the tree from the root to the target leaf
func (t *Tree) membershipProof(target, index, layer, version int, proof *MembershipProof) (err error) {
	if layer == 0 {
		return
	}
	// the number of events to the left of the node
	n := index + util.Pow(2, layer-1)
	if target < n {
		// go left, but should we save right first? We need to save right if there are any leaf nodes
		// fixed by the right node (otherwise we know it's hash is nil), dictated by the version of the
		// tree we are generating
		if version >= n {
			p := new(ProofPosition)
			p.Index = n
			p.Layer = layer - 1
			p.Hash, err = t.getHashedNode(p.Index, p.Layer, version, false)
			if err != nil {
				return
			}
			proof.Nodes = append(proof.Nodes, *p)
		}
		return t.membershipProof(target, index, layer-1, version, proof)
	}
	// go right, once we have saved the left node
	p := new(ProofPosition)
	p.Index = index
	p.Layer = layer - 1
	p.Hash, err = t.getHashedNode(p.Index, p.Layer, version, false)
	if err != nil {
		return
	}
	proof.Nodes = append(proof.Nodes, *p)

	return t.membershipProof(target, n, layer-1, version, proof)

}
Example #2
0
// layeR, Index, Version
// See Figure 5 in "Efficient Data Structures for Tamper-Evident Logging"
func (t *Tree) getHashedNode(index, layer, version int, proofMode bool) (value []byte, err error) {
	// always prefer frozen hashes, if we have calculated them
	if proofMode || version >= index+util.Pow(2, layer)-1 {
		if t.isFrozenHash(index, layer) {
			return t.getFrozenHash(index, layer)
		}
	}

	// special case for child nodes
	if layer == 0 && version >= index {
		event, err := t.getEvent(index)
		if err != nil {
			return nil, errors.New("no event with the provided index")
		}

		value = util.Hash(prefixZero, event)
		// have version determine if the right node is there or not
	} else if version >= index+util.Pow(2, layer-1) {
		a1, err := t.getHashedNode(index, layer-1, version, proofMode)
		if err != nil {
			return nil, errors.New("failed to get internal node with index " + strconv.Itoa(index))
		}
		a2, err := t.getHashedNode(index+util.Pow(2, layer-1), layer-1, version, proofMode)
		if err != nil {
			return nil, errors.New("failed to get internal node with index " + strconv.Itoa(index))
		}

		value = util.Hash(prefixOne, a1, a2)
	} else {
		a, err := t.getHashedNode(index, layer-1, version, proofMode)
		if err != nil {
			return nil, errors.New("failed to get internal node with index " + strconv.Itoa(index))
		}
		value = util.Hash(prefixOne, a)
	}

	// should we add this to the frozen hash cache?
	if version >= index+util.Pow(2, layer)-1 {
		t.setFrozenHash(index, layer, value)
	}

	return
}