-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy pathsnapshot.go
81 lines (64 loc) · 2.15 KB
/
snapshot.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package types
import (
"context"
"fmt"
"math"
"github.com/ethereum/go-ethereum/common"
"github.com/synapsecns/sanguine/core/merkle"
"github.com/synapsecns/sanguine/ethergo/signer/signer"
)
// Snapshot is the snapshot interface.
type Snapshot interface {
Encoder
// States are the states of the snapshot.
States() []State
// SnapshotRootAndProofs returns the snapshot root, calculated from the states, as well as each state's proof.
SnapshotRootAndProofs() ([32]byte, [][][]byte, error)
// SignSnapshot returns the signature of the snapshot payload signed by the signer
SignSnapshot(ctx context.Context, signer signer.Signer) (signer.Signature, []byte, common.Hash, error)
}
type snapshot struct {
states []State
}
// NewSnapshot creates a new snapshot.
func NewSnapshot(states []State) Snapshot {
return &snapshot{
states: states,
}
}
func (s snapshot) States() []State {
return s.states
}
func (s snapshot) SnapshotRootAndProofs() ([32]byte, [][][]byte, error) {
tree := merkle.NewTree(merkle.SnapshotTreeHeight)
for _, state := range s.states {
leftLeaf, rightLeaf, err := state.SubLeaves()
if err != nil {
return [32]byte{}, nil, fmt.Errorf("failed to hash state: %w", err)
}
tree.Insert(leftLeaf[:])
tree.Insert(rightLeaf[:])
}
snapshotRoot, err := tree.Root(uint32(len(s.states) * 2))
if err != nil {
return [32]byte{}, nil, fmt.Errorf("failed to get snapshot root: %w", err)
}
var snapshotRootB32 [32]byte
copy(snapshotRootB32[:], snapshotRoot)
proofs := make([][][]byte, len(s.states)*2)
for i := 0; i < len(s.states)*2; i += 2 {
proofs[i/2], err = tree.MerkleProof(uint32(i), uint32(len(s.states)*2))
if err != nil {
return [32]byte{}, nil, fmt.Errorf("failed to get merkle proof: %w", err)
}
}
return snapshotRootB32, proofs, nil
}
// TreeHeight returns the height of the merkle tree given `len(states)*2` leaves.
func (s snapshot) TreeHeight() uint32 {
return uint32(math.Log2(float64(len(s.states) * 2)))
}
func (s snapshot) SignSnapshot(ctx context.Context, signer signer.Signer) (signer.Signature, []byte, common.Hash, error) {
return signEncoder(ctx, signer, s, SnapshotValidSalt)
}
var _ Snapshot = &snapshot{}