forked from omni-network/omni
-
Notifications
You must be signed in to change notification settings - Fork 1
/
creator.go
75 lines (62 loc) · 2.21 KB
/
creator.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
package relayer
import (
"slices"
"github.com/omni-network/omni/lib/errors"
"github.com/omni-network/omni/lib/xchain"
)
// CreateSubmissions splits the update into multiple submissions that are each small enough (wrt calldata and gas)
// to be submitted on-chain.
func CreateSubmissions(up StreamUpdate) ([]xchain.Submission, error) {
// Sanity check on input, should only be for a single stream.
for i, msg := range up.Msgs {
if msg.SourceChainID != up.SourceChainID {
return nil, errors.New("invalid msgs [BUG]")
} else if i > 0 && msg.StreamOffset != up.Msgs[i-1].StreamOffset+1 {
return nil, errors.New("msgs not sequential [BUG]")
}
}
att := up.Attestation
attRoot, err := xchain.AttestationRoot(att.AttestHeader, att.BlockHeader, att.MsgRoot)
if err != nil {
return nil, err
}
var resp []xchain.Submission //nolint:prealloc // Cannot predetermine size
for _, msgs := range groupMsgsByCost(up.Msgs) {
multi, err := up.MsgTree.Proof(msgs)
if err != nil {
return nil, err
}
resp = append(resp, xchain.Submission{
AttestationRoot: attRoot,
ValidatorSetID: att.ValidatorSetID,
AttHeader: att.AttestHeader,
BlockHeader: att.BlockHeader,
Msgs: msgs,
Proof: multi.Proof,
ProofFlags: multi.ProofFlags,
Signatures: att.Signatures,
DestChainID: up.DestChainID,
})
}
return resp, nil
}
// groupMsgsByCost split the messages into groups that are each small enough (wrt calldata and gas)
// to be submitted on-chain.
func groupMsgsByCost(msgs []xchain.Msg) [][]xchain.Msg {
var resp [][]xchain.Msg
var current []xchain.Msg
for _, msg := range msgs {
// If adding the msg to the current batch will cross max limit, then
// complete the batch by adding it to the response and starting a new empty current batch.
// Note that even though the naive gas model doesn't work for all chains,
// it is good enough for this use-case; i.e., splitting xmsgs.
if naiveSubmissionGas(append(slices.Clone(current), msg)) > subGasMax {
resp = append(resp, current)
current = nil
}
// Add the message to the current batch
current = append(current, msg)
}
// Add current batch to response and return
return append(resp, current)
}