Beispiel #1
0
func verifyProof(s *Snapshot, index, value []byte, proof *proto.TreeProof) {
	reconstructed, err := coname.ReconstructTree(proof, coname.ToBits(coname.IndexBits, index))
	if err != nil {
		panic(err)
	}
	redoneLookup, err := coname.TreeLookup(reconstructed, index)
	if err != nil {
		panic(err)
	}
	if got, want := redoneLookup, value; !bytes.Equal(got, want) {
		log.Panicf("reconstructed lookup got different result: %v rather than %v", got, want)
	}
	recomputedHash, err := coname.RecomputeHash(treeNonce, reconstructed)
	if err != nil {
		panic(err)
	}
	rootHash, err := s.GetRootHash()
	if err != nil {
		panic(err)
	}
	if got, want := recomputedHash, rootHash; !bytes.Equal(got, want) {
		log.Panicf("reconstructed hash differed: %x rather than %x", got, want)
	}
}
Beispiel #2
0
// Set updates the leaf value at the index (or inserts it if it did not exist).
// In-memory: doesn't actually touch the disk yet.
func (snapshot *NewSnapshot) Set(indexBytes []byte, value []byte) (err error) {
	if len(indexBytes) != coname.IndexBytes {
		return fmt.Errorf("Wrong index length")
	}
	if len(value) != coname.HashBytes {
		return fmt.Errorf("Wrong value length")
	}
	value = append([]byte(nil), value...) // Make a copy of value
	indexBits := coname.ToBits(coname.IndexBits, indexBytes)
	nodePointer := &snapshot.root
	position := 0
	// Traverse down the tree, following either the left or right child depending on the next bit.
	for *nodePointer != nil && !(*nodePointer).isLeaf {
		nodePointer, err = snapshot.tree.getChildPointer(*nodePointer, indexBits[position])
		if err != nil {
			return
		}
		position++
	}
	if *nodePointer == nil {
		// We've hit an empty branch where this leaf belongs -- put it there.
		*nodePointer = &node{
			diskNode: diskNode{
				isLeaf:     true,
				indexBytes: append([]byte{}, indexBytes...), // Make a copy of indexBytes
				value:      value,
			},
			prefixBits: indexBits[:position],
		}
	} else if bytes.Equal((*nodePointer).indexBytes, indexBytes) {
		// We have an existing leaf at this index; just replace the value
		(*nodePointer).value = value
	} else {
		// We have a different leaf with a matching prefix. We'll have to create new intermediate nodes.
		oldLeaf := *nodePointer
		oldLeafIndexBits := coname.ToBits(coname.IndexBits, oldLeaf.indexBytes)
		// Create a new intermediate node for each bit that has now become shared.
		for oldLeafIndexBits[position] == indexBits[position] {
			newNode := &node{
				diskNode: diskNode{
					isLeaf: false,
				},
				prefixBits: indexBits[:position],
			}
			*nodePointer, nodePointer = newNode, &newNode.children[coname.BitToIndex(indexBits[position])]
			position++
		}
		// Create a new node at which the tree now branches.
		splitNode := &node{
			diskNode: diskNode{
				isLeaf: false,
			},
			prefixBits: indexBits[:position],
		}
		// Create the new leaf under the splitNode
		newLeaf := &node{
			diskNode: diskNode{
				isLeaf:     true,
				indexBytes: append([]byte{}, indexBytes...), // Make a copy of the index
				value:      value,
			},
			prefixBits: indexBits[:position+1],
		}
		// Move the old leaf's index down
		oldLeaf.prefixBits = oldLeafIndexBits[:position+1]
		splitNode.children[coname.BitToIndex(indexBits[position])] = newLeaf
		splitNode.children[coname.BitToIndex(oldLeafIndexBits[position])] = oldLeaf
		*nodePointer = splitNode
	}
	return nil
}