Diff returns a leaf-level discriminant; bit i is set when leaf i differs.
(ht2 AggregatedHashTree)
| 15 | |
| 16 | // Diff returns a leaf-level discriminant; bit i is set when leaf i differs. |
| 17 | func (ht *HashTree) Diff(ht2 AggregatedHashTree) (*Bitset, error) { |
| 18 | _, isHashTree := ht2.(*HashTree) |
| 19 | if ht2 == nil || !isHashTree { |
| 20 | return nil, ErrIllegalArguments |
| 21 | } |
| 22 | |
| 23 | height := ht.Height() |
| 24 | if height != ht2.Height() { |
| 25 | return nil, fmt.Errorf("%w: hash trees of different heights are non-comparable", ErrIllegalArguments) |
| 26 | } |
| 27 | |
| 28 | leavesCount := LeavesCount(height) |
| 29 | digests1 := make([]Digest, leavesCount) |
| 30 | digests2 := make([]Digest, leavesCount) |
| 31 | |
| 32 | walk := NewBitset(1) |
| 33 | walk.Set(0) // root |
| 34 | |
| 35 | for l := 0; l <= height; l++ { |
| 36 | if _, err := ht.Level(l, walk, digests1); err != nil { |
| 37 | return nil, err |
| 38 | } |
| 39 | if _, err := ht2.Level(l, walk, digests2); err != nil { |
| 40 | return nil, err |
| 41 | } |
| 42 | |
| 43 | nextWalk, levelDiffCount, err := LevelDiff(l, height, walk, digests1, digests2) |
| 44 | if err != nil { |
| 45 | return nil, err |
| 46 | } |
| 47 | |
| 48 | if l == height { |
| 49 | return walk, nil |
| 50 | } |
| 51 | if levelDiffCount == 0 { |
| 52 | return NewBitset(leavesCount), nil |
| 53 | } |
| 54 | walk = nextWalk |
| 55 | } |
| 56 | |
| 57 | return NewBitset(leavesCount), nil |
| 58 | } |