-
Notifications
You must be signed in to change notification settings - Fork 57
/
types.go
283 lines (235 loc) · 10.4 KB
/
types.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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
package xchain
import (
"crypto/sha256"
"fmt"
"math/big"
"strconv"
"strings"
"time"
"github.com/omni-network/omni/lib/errors"
"github.com/ethereum/go-ethereum/common"
)
// BroadcastChainID is the chain ID used by broadcast messages.
const BroadcastChainID uint64 = 0
//go:generate stringer -type=ConfLevel -linecomment
// ChainVersion defines a version of a source chain; either some draft (fuzzy) version or finalized.
type ChainVersion struct {
ID uint64 // Source chain ID as per https://chainlist.org/
ConfLevel ConfLevel // ConfLevel defines the block "version"; either some fuzzy version or finalized.
}
func NewChainVersion(chainID uint64, confLevel ConfLevel) ChainVersion {
return ChainVersion{
ID: chainID,
ConfLevel: confLevel,
}
}
// ConfLevel defines a xblock confirmation level.
// This is similar to a "version"; with ConfFinalized being the final version and fuzzy conf levels being drafts.
type ConfLevel byte
// Valid returns true if this confirmation level is valid.
func (c ConfLevel) Valid() bool {
return c > ConfUnknown && c < confSentinel && !strings.Contains(c.String(), "ConfLevel")
}
// IsFuzzy returns true if this confirmation level is not ConfFinalized.
func (c ConfLevel) IsFuzzy() bool {
return !c.IsFinalized()
}
// IsFinalized returns true if this confirmation level is ConfFinalized.
func (c ConfLevel) IsFinalized() bool {
return c == ConfFinalized
}
// Label returns a short label for the confirmation level.
// IT is the uppercase first letter of the confirmation level.
func (c ConfLevel) Label() string {
return strings.ToUpper(c.String()[:1])
}
// ConfLevel values MUST never change as they are persisted on-chain.
const (
ConfUnknown ConfLevel = 0 // unknown
ConfLatest ConfLevel = 1 // latest
_ ConfLevel = 2 // reserved
_ ConfLevel = 3 // reserved
ConfFinalized ConfLevel = 4 // final
confSentinel ConfLevel = 5 // sentinel must always be last
)
// FuzzyConfLevels returns a list of all fuzzy confirmation levels.
func FuzzyConfLevels() []ConfLevel {
return []ConfLevel{ConfLatest}
}
type ShardID uint64
const (
// ShardFinalized0 is the default finalized confirmation level shard.
ShardFinalized0 = ShardID(ConfFinalized)
// ShardLatest0 is the default latest confirmation level shard.
ShardLatest0 = ShardID(ConfLatest)
// ShardBroadcast0 is the default broadcast shard. It uses the finalized confirmation level.
ShardBroadcast0 = ShardID(ConfFinalized) | 0x0100
)
// ConfLevel returns confirmation level encoded in the
// last 8 bits of the shardID.
func (s ShardID) ConfLevel() ConfLevel {
return ConfLevel(byte(s & 0xFF))
}
// Flags returns flags encoded in the 2nd-to-last byte of the shardID.
func (s ShardID) Flags() byte {
return byte((s >> 8) & 0xFF)
}
// Label returns a short label for the shard.
// IT is the uppercase first letter of the confirmation level.
func (s ShardID) Label() string {
resp, ok := map[ShardID]string{
ShardFinalized0: "F",
ShardLatest0: "L",
ShardBroadcast0: "B",
}[s]
if ok {
return resp
}
return strconv.FormatUint(uint64(s), 10)
}
// Broadcast returns the value of the 8th flag (least significant bit).
func (s ShardID) Broadcast() bool {
return s.Flags()&0b00000001 == 1
}
// Signature65 is a 65 byte Ethereum signature [R || S || V] format.
type Signature65 [65]byte
// StreamID uniquely identifies a cross-chain stream.
// A stream is a logical representation of a cross-chain connection between two chains.
type StreamID struct {
SourceChainID uint64 // Source chain ID as per https://chainlist.org/
DestChainID uint64 // Destination chain ID as per https://chainlist.org/
ShardID ShardID // ShardID identifies a sequence of xmsgs (and maps to ConfLevel).
}
func (s StreamID) ConfLevel() ConfLevel {
return ConfLevel(s.ShardID)
}
func (s StreamID) ChainVersion() ChainVersion {
return ChainVersion{ID: s.SourceChainID, ConfLevel: s.ConfLevel()}
}
// MsgID uniquely identifies a cross-chain message.
type MsgID struct {
StreamID // Unique ID of the Stream this message belongs to
StreamOffset uint64 // Monotonically incremented offset of Msg in the Stream (1-indexed)
}
// Hash returns the RouteScan cross-transaction IDHash of the MsgID.
func (m MsgID) Hash() common.Hash {
s := fmt.Sprintf("omni#%d#%d#%d#%d", m.SourceChainID, m.DestChainID, m.ShardID, m.StreamOffset)
return sha256.Sum256([]byte(s))
}
// Msg is a cross-chain message.
type Msg struct {
MsgID // Unique ID of the message
SourceMsgSender common.Address // Sender on source chain, set to msg.Sender
DestAddress common.Address // Target/To address to "call" on destination chain
Data []byte // Data to provide to "call" on destination chain
DestGasLimit uint64 // Gas limit to use for "call" on destination chain
TxHash common.Hash // Hash of the source chain transaction that emitted the message
Fees *big.Int // Fees paid for the xcall
LogIndex uint64 // Evm event log index in block, used for sorting
}
// Receipt is a cross-chain message receipt, the result of applying the Msg on the destination chain.
type Receipt struct {
MsgID // Unique ID of the cross chain message that was applied.
GasUsed uint64 // Gas used during message "call"
Success bool // Result, true for success, false for revert
Error []byte // Error message if the message failed
RelayerAddress common.Address // Address of relayer that submitted the message
TxHash common.Hash // Hash of the relayer submission transaction
LogIndex uint64 // Evm event log index in block, used for sorting
}
// BlockHeader uniquely identifies a cross chain block.
type BlockHeader struct {
ChainID uint64 // Source chain ID as per https://chainlist.org
BlockHeight uint64 // Height of the source-chain block
BlockHash common.Hash // Hash of the source-chain block
}
// Block is a deterministic representation of the omni cross-chain properties of a source chain EVM block.
type Block struct {
BlockHeader
Msgs []Msg // All cross-chain messages sent/emittted in the block
Receipts []Receipt // Receipts of all submitted cross-chain messages applied in the block
ParentHash common.Hash // ParentHash is the hash of the parent block.
Timestamp time.Time // Timestamp of the source chain block
}
// ShouldAttest returns true if the xblock should be attested by the omni consensus chain validators.
// All "non-empty" xblocks should be attested to.
// Every Nth block based on the chain's attest interval should be attested to.
// Attested blocks are assigned an incremented AttestOffset.
func (b Block) ShouldAttest(attestInterval uint64) bool {
if len(b.Msgs) > 0 {
return true
}
if attestInterval == 0 {
return false // Avoid empty attestations for zero interval.
}
return b.BlockHeight%attestInterval == 0
}
func (b Block) MsgByID(msgID MsgID) (Msg, error) {
for _, msg := range b.Msgs {
if msg.MsgID == msgID {
return msg, nil
}
}
return Msg{}, errors.New("msg not found")
}
func (b Block) ReceiptByID(msgID MsgID) (Receipt, error) {
for _, receipt := range b.Receipts {
if receipt.MsgID == msgID {
return receipt, nil
}
}
return Receipt{}, errors.New("receipt not found")
}
// AttestHeader uniquely identifies an attestation that require quorum vote.
// This is used to determine duplicate votes.
type AttestHeader struct {
ConsensusChainID uint64 // Omni consensus chain ID this attestation/vote belangs to. Used for replay-protection.
ChainVersion ChainVersion // ChainVersion defines a "version" of a chain being attested to ; either some fuzzy version or finalized.
AttestOffset uint64 // Monotonically increasing offset of this vote per chain version. 1-indexed.
}
// Vote by a validator for a cross-chain Block.
type Vote struct {
AttestHeader // AttestHeader identifies the attestation this vote should be included in.
BlockHeader // BlockHeader identifies the cross-chain Block being voted for.
MsgRoot common.Hash // Merkle root of all messages in the cross-chain Block
Signature SigTuple // Validator signature and public key
}
// Attestation containing quorum votes by the validator set of a cross-chain Block.
type Attestation struct {
AttestHeader // AttestHeader uniquely identifies the attestation.
BlockHeader // BlockHeader identifies the cross-chain Block
MsgRoot common.Hash // Merkle root of all messages in the cross-chain Block
Signatures []SigTuple // Validator signatures and public keys
ValidatorSetID uint64 // Validator set that approved this attestation.
}
func (a Attestation) AttestationRoot() ([32]byte, error) {
return AttestationRoot(a.AttestHeader, a.BlockHeader, a.MsgRoot)
}
// SigTuple is a validator signature and address.
type SigTuple struct {
ValidatorAddress common.Address // Validator Ethereum address
Signature Signature65 // Validator signature over XBlockRoot; Ethereum 65 bytes [R || S || V] format.
}
// Submission is a cross-chain submission of a set of messages and their proofs.
type Submission struct {
AttestationRoot common.Hash // Attestation merkle root of the cross-chain Block
ValidatorSetID uint64 // Validator set that approved the attestation.
AttHeader AttestHeader // AttestHeader identifies the attestation this submission belongs to.
BlockHeader BlockHeader // BlockHeader identifies the cross-chain Block
Msgs []Msg // Messages to be submitted
Proof [][32]byte // Merkle multi proofs of the messages
ProofFlags []bool // Flags indicating whether the proof is a left or right proof
Signatures []SigTuple // Validator signatures and public keys
DestChainID uint64 // Destination chain ID, for internal use only
}
// SubmitCursor is a cursor that tracks the progress of a cross-chain stream on destination portal contracts.
type SubmitCursor struct {
StreamID // Stream ID of the Stream this cursor belongs to
MsgOffset uint64 // Latest submitted Msg offset of the Stream
AttestOffset uint64 // Latest submitted cross chain attest offset
}
// EmitCursor is a cursor that tracks the progress of a cross-chain stream on source portal contracts.
type EmitCursor struct {
StreamID // Stream ID of the Stream this cursor belongs to
MsgOffset uint64 // Latest emitted Msg offset of the Stream
}