# FastSSZ

https://github.com/ferranbt/fastssz

## FastSSZ Changes

#26 - Added the possibility
to use a different hash function. Sina wanted to use `keccak256`

as hash
function.

#27 - Added `PutUint32`

,
`PutUint16`

, and `PutUint8`

to the hasher. Used to only have `PutUint64`

.

#28
- Created new schema,
- Added verification function for one of the structs,
- Some hand-crafted test cases,
- Pending to make `verify`

more general so its not only for one struct.
- New Files:
- `tests/codetrie.go`

:
- `tests/codetrie_encoding.go`

: Automatically generated by fastssz
- `tests/codetrie_test.go`

: Verify proof tests

#32
- Added new `proof.go`

; which included functions to verify proofs and verify
multiproof as other helper functions.

#33 - Added support for multiproof generation

#38
- Adds a `--experimental`

flag to get the tree-backing of an object
- Given the tree-backing you can compute the root, generate and verify
proofs.

#39 (pending PR) - Remove duplicate leafs from proof

## ProveMulti

path: `tree.go`

- Input: indices
- Output: Multiproof

Get the required indices (`getRequiredIndices`

).

Defines `proof`

as a `Multiproof`

object, declared with the provided indices,
an empty Leaves array or arrays, an empty Hashes array of arrays.

For each provided index, get the node based on the index. Adds the node as a **Leave**.

For each `reqIndices`

, get the node based on that index, Adds the node as
a **Hash**.

Returns the proof.

```
func (n *Node) ProveMulti(indices []int) (*Multiproof, error) {
reqIndices := getRequiredIndices(indices)
proof := &Multiproof{Indices: indices, Leaves: make([][]byte, len(indices)), Hashes: make([][]byte, len(reqIndices))}
for i, gi := range indices {
node, err := n.Get(gi)
if err != nil {
return nil, err
}
proof.Leaves[i] = node.value
}
for i, gi := range reqIndices {
cur, err := n.Get(gi)
if err != nil {
return nil, err
}
proof.Hashes[i] = hashNode(cur)
}
return proof, nil
}
```

## Compress (Multiproof)

- (Multiproof) Compress: Returns a
`*CompressedMultiproof`

`tree.go`

```
// Compress returns a new proof with zero hashes omitted.
// See `CompressedMultiproof` for more info.
func (p *Multiproof) Compress() *CompressedMultiproof {
compressed := &CompressedMultiproof{
Indices: p.Indices,
Leaves: p.Leaves,
Hashes: make([][]byte, 0, len(p.Hashes)),
ZeroLevels: make([]int, 0, len(p.Hashes)),
}
for _, h := range p.Hashes {
if l, ok := zeroHashLevels[string(h)]; ok {
compressed.ZeroLevels = append(compressed.ZeroLevels, l)
compressed.Hashes = append(compressed.Hashes, nil)
} else {
compressed.Hashes = append(compressed.Hashes, h)
}
}
return compressed
}
```

#### Multiproof:

```
// Multiproof represents a merkle proof of several leaves.
type Multiproof struct {
Indices []int
Leaves [][]byte
Hashes [][]byte
}
```

## CompressedMultiproof:

```
// CompressedMultiproof represents a compressed merkle proof of several leaves.
// Compression is achieved by omitting zero hashes (and their hashes). `ZeroLevels`
// contains information which helps the verifier fill in those hashes.
type CompressedMultiproof struct {
Indices []int
Leaves [][]byte
Hashes [][]byte
ZeroLevels []int // Stores the level for every omitted zero hash in the proof
}
```