Skip to content
This repository has been archived by the owner on Aug 2, 2021. It is now read-only.

file, testutil: Add reference file hasher #2099

Merged
merged 7 commits into from
Feb 24, 2020
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 35 additions & 6 deletions file/hasher/reference.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,22 +78,54 @@ func (r *ReferenceHasher) sum(lvl int) []byte {
// skips intermediate levels that end on span boundary
func (r *ReferenceHasher) digest() []byte {

// if we did not end on a chunk boundary, the last chunk hasn't been hashed
// we need to do this first
// if we didn't end on a chunk boundary we need to hash remaining chunks first
r.hashUnfinished()
acud marked this conversation as resolved.
Show resolved Hide resolved

// if the already hashed parts tree is balanced
r.moveDanglingChunk()

// the first section of the buffer will hold the root hash
return r.buffer[:r.params.SectionSize]
}

// hashes the remaining unhashed chunks at the end of each level
func (r *ReferenceHasher) hashUnfinished() {
if r.length%r.params.ChunkSize != 0 {
ref := r.sum(0)
acud marked this conversation as resolved.
Show resolved Hide resolved
copy(r.buffer[r.cursors[1]:], ref)
r.cursors[1] += len(ref)
r.cursors[0] = r.cursors[1]
}
}

// in case of a balanced tree this method concatenates the reference to the single reference
// at the highest level of the tree.
//
// Let F be full chunks (disregarding branching factor) and S be single references
// in the following scenario:
//
// S
// F F
// F F F
// F F F F S
//
// The result will be:
//
// SS
// F F
// F F F
// F F F F
//
// After which the SS will be hashed to obtain the final root hash
func (r *ReferenceHasher) moveDanglingChunk() {

// calculate the total number of levels needed to represent the data (including the data level)
targetLevel := getLevelsFromLength(r.length, r.params.SectionSize, r.params.Branches)

// sum every intermediate level and write to the level above it
for i := 1; i < targetLevel; i++ {
acud marked this conversation as resolved.
Show resolved Hide resolved

// if the tree is balanced or if there is a single reference outside a balanced tree on this level
// and if there is a single reference outside a balanced tree on this level
// don't hash it again but pass it on to the next level
if r.counts[i] > 0 {
// TODO: simplify if possible
Expand All @@ -109,7 +141,4 @@ func (r *ReferenceHasher) digest() []byte {
r.cursors[i+1] += len(ref)
r.cursors[i] = r.cursors[i+1]
}

// the first section of the buffer will hold the root hash
return r.buffer[:r.params.SectionSize]
}