forked from renproject/multichain
-
Notifications
You must be signed in to change notification settings - Fork 0
/
multichain.go
398 lines (335 loc) · 12.5 KB
/
multichain.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
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
// Package multichain defines all supported assets and chains. It also
// re-exports the individual multichain APIs.
package multichain
import (
"github.com/renproject/multichain/api/account"
"github.com/renproject/multichain/api/address"
"github.com/renproject/multichain/api/contract"
"github.com/renproject/multichain/api/gas"
"github.com/renproject/multichain/api/utxo"
"github.com/renproject/surge"
)
type (
// An Address is a human-readable representation of a public identity. It can
// be the address of an external account, contract, or script.
Address = address.Address
// The AddressEncodeDecoder interfaces combines encoding and decoding
// functionality into one interface.
AddressEncodeDecoder = address.EncodeDecoder
// RawAddress is an address that has been decoded into its binary form.
RawAddress = address.RawAddress
)
type (
// The AccountTx interface defines the functionality that must be exposed by
// account-based transactions.
AccountTx = account.Tx
// The AccountTxBuilder interface defines the functionality required to build
// account-based transactions. Most chain implementations require additional
// information, and this should be accepted during the construction of the
// chain-specific transaction builder.
AccountTxBuilder = account.TxBuilder
// The AccountClient interface defines the functionality required to interact
// with a chain over RPC.
AccountClient = account.Client
)
type (
// A UTXOutpoint identifies a specific output produced by a transaction.
UTXOutpoint = utxo.Outpoint
// A UTXOutput is produced by a transaction. It includes the conditions
// required to spend the output (called the pubkey script, based on Bitcoin).
UTXOutput = utxo.Output
// A UTXOInput specifies an existing output, produced by a previous
// transaction, to be consumed by another transaction. It includes the script
// that meets the conditions specified by the consumed output (called the sig
// script, based on Bitcoin).
UTXOInput = utxo.Input
// A UTXORecipient specifies an address, and an amount, for which a
// transaction will produce an output. Depending on the output, the address
// can take on different formats (e.g. in Bitcoin, addresses can be P2PK,
// P2PKH, or P2SH).
UTXORecipient = utxo.Recipient
// A UTXOTx interfaces defines the functionality that must be exposed by
// utxo-based transactions.
UTXOTx = utxo.Tx
// A UTXOTxBuilder interface defines the functionality required to build
// account-based transactions. Most chain implementations require additional
// information, and this should be accepted during the construction of the
// chain-specific transaction builder.
UTXOTxBuilder = utxo.TxBuilder
// A UTXOClient interface defines the functionality required to interact with
// a chain over RPC.
UTXOClient = utxo.Client
)
type (
// ContractCallData is used to specify a function and its parameters when
// invoking business logic on a contract.
ContractCallData = contract.CallData
// The ContractCaller interface defines the functionality required to call
// readonly functions on a contract. Calling functions that mutate contract
// state should be done using the Account API.
ContractCaller = contract.Caller
)
type (
// The GasEstimator interface defines the functionality required to know the
// current recommended gas prices.
GasEstimator = gas.Estimator
)
// An Asset uniquely identifies assets using human-readable strings.
type Asset string
// Enumeration of supported assets. When introducing a new chain, or new asset
// from an existing chain, you must add a human-readable string to this set of
// enumerated values. Assets must be listed in alphabetical order.
const (
BCH = Asset("BCH") // Bitcoin Cash
BNB = Asset("BNB") // Binance Coin
BTC = Asset("BTC") // Bitcoin
CELO = Asset("CELO") // Celo
DGB = Asset("DGB") // DigiByte
DOGE = Asset("DOGE") // Dogecoin
ETH = Asset("ETH") // Ether
FIL = Asset("FIL") // Filecoin
FTM = Asset("FTM") // Fantom
SOL = Asset("SOL") // Solana
LUNA = Asset("LUNA") // Luna
ZEC = Asset("ZEC") // Zcash
// These assets are defined separately because they are mock assets. These
// assets should only be used for testing.
AMOCK1 = Asset("AMOCK1") // Account-based mock asset
AMOCK2 = Asset("AMOCK2") // Account-based mock asset
UMOCK = Asset("UMOCK") // UTXO-based mock asset
)
// OriginChain returns the chain upon which the asset originates. For example,
// the origin chain of BTC is Bitcoin.
func (asset Asset) OriginChain() Chain {
switch asset {
case BCH:
return BitcoinCash
case BNB:
return BinanceSmartChain
case BTC:
return Bitcoin
case CELO:
return Celo
case DGB:
return DigiByte
case DOGE:
return Dogecoin
case ETH:
return Ethereum
case FIL:
return Filecoin
case FTM:
return Fantom
case LUNA:
return Terra
case SOL:
return Solana
case ZEC:
return Zcash
// These assets are handled separately because they are mock assets. These
// assets should only be used for testing.
case AMOCK1:
return AccountMocker1
case AMOCK2:
return AccountMocker2
case UMOCK:
return UTXOMocker
default:
return Chain("")
}
}
// ChainType returns the chain-type (Account or UTXO) for the given asset
func (asset Asset) ChainType() ChainType {
switch asset {
case BCH, BTC, DGB, DOGE, ZEC:
return ChainTypeUTXOBased
case BNB, ETH, FIL, LUNA:
return ChainTypeAccountBased
// These assets are handled separately because they are mock assets. These
// assets should only be used for testing.
case AMOCK1, AMOCK2:
return ChainTypeAccountBased
case UMOCK:
return ChainTypeUTXOBased
default:
return ChainType("")
}
}
// SizeHint returns the number of bytes required to represent the asset in
// binary.
func (asset Asset) SizeHint() int {
return surge.SizeHintString(string(asset))
}
// Marshal the asset to binary.
func (asset Asset) Marshal(buf []byte, rem int) ([]byte, int, error) {
return surge.MarshalString(string(asset), buf, rem)
}
// Unmarshal the asset from binary.
func (asset *Asset) Unmarshal(buf []byte, rem int) ([]byte, int, error) {
return surge.UnmarshalString((*string)(asset), buf, rem)
}
// A Chain uniquely identifies a blockchain using a human-readable string.
type Chain string
// Enumeration of supported chains. When introducing a new chain, you must add a
// human-readable string to this set of enumerated values. Chains must be listed
// in alphabetical order.
const (
Acala = Chain("Acala")
BinanceSmartChain = Chain("BinanceSmartChain")
Bitcoin = Chain("Bitcoin")
BitcoinCash = Chain("BitcoinCash")
Celo = Chain("Celo")
DigiByte = Chain("DigiByte")
Dogecoin = Chain("Dogecoin")
Ethereum = Chain("Ethereum")
Fantom = Chain("Fantom")
Filecoin = Chain("Filecoin")
Solana = Chain("Solana")
Terra = Chain("Terra")
Zcash = Chain("Zcash")
// These chains are defined separately because they are mock chains. These
// chains should only be used for testing.
AccountMocker1 = Chain("AccountMocker1")
AccountMocker2 = Chain("AccountMocker2")
UTXOMocker = Chain("UTXOMocker")
)
// SizeHint returns the number of bytes required to represent the chain in
// binary.
func (chain Chain) SizeHint() int {
return surge.SizeHintString(string(chain))
}
// Marshal the chain to binary. You should not call this function directly,
// unless you are implementing marshalling for a container type.
func (chain Chain) Marshal(buf []byte, rem int) ([]byte, int, error) {
return surge.MarshalString(string(chain), buf, rem)
}
// Unmarshal the chain from binary. You should not call this function directly,
// unless you are implementing unmarshalling for a container type.
func (chain *Chain) Unmarshal(buf []byte, rem int) ([]byte, int, error) {
return surge.UnmarshalString((*string)(chain), buf, rem)
}
// ChainType returns the chain type (whether account-based or utxo-based chain)
// for the chain.
func (chain Chain) ChainType() ChainType {
switch chain {
case Bitcoin, BitcoinCash, DigiByte, Dogecoin, Zcash:
return ChainTypeUTXOBased
case BinanceSmartChain, Ethereum, Filecoin, Terra:
return ChainTypeAccountBased
// These chains are handled separately because they are mock chains. These
// chains should only be used for testing.
case AccountMocker1, AccountMocker2:
return ChainTypeAccountBased
case UTXOMocker:
return ChainTypeUTXOBased
default:
return ChainType("")
}
}
// IsAccountBased returns true when invoked on an account-based chain, otherwise
// returns false.
func (chain Chain) IsAccountBased() bool {
return chain.ChainType() == ChainTypeAccountBased
}
// IsUTXOBased returns true when invoked on a utxo-based chain, otherwise
// returns false.
func (chain Chain) IsUTXOBased() bool {
return chain.ChainType() == ChainTypeUTXOBased
}
// NativeAsset returns the underlying native asset for a chain. For example, the
// root asset of Bitcoin chain is BTC.
func (chain Chain) NativeAsset() Asset {
switch chain {
case BinanceSmartChain:
return BNB
case BitcoinCash:
return BCH
case Bitcoin:
return BTC
case DigiByte:
return DGB
case Dogecoin:
return DOGE
case Ethereum:
return ETH
case Filecoin:
return FIL
case Terra:
return LUNA
case Zcash:
return ZEC
// These chains are handled separately because they are mock chains. These
// chains should only be used for testing.
case AccountMocker1:
return AMOCK1
case AccountMocker2:
return AMOCK2
case UTXOMocker:
return UMOCK
default:
return Asset("")
}
}
// ChainType represents the type of chain (whether account-based or utxo-based)
type ChainType string
const (
// ChainTypeAccountBased is an identifier for all account-based chains,
// namely, BinanceSmartChain, Ethereum, Filecoin, and so on.
ChainTypeAccountBased = ChainType("Account")
// ChainTypeUTXOBased is an identifier for all utxo-based chains, namely,
// Bitcoin, BitcoinCash, DigiByte, and so on.
ChainTypeUTXOBased = ChainType("UTXO")
)
// SizeHint returns the number of bytes required to represent the chain type in
// binary.
func (chainType ChainType) SizeHint() int {
return surge.SizeHintString(string(chainType))
}
// Marshal the chain type to binary. You should not call this function directly,
// unless you are implementing marshalling for a container type.
func (chainType ChainType) Marshal(buf []byte, rem int) ([]byte, int, error) {
return surge.MarshalString(string(chainType), buf, rem)
}
// Unmarshal the chain type from binary. You should not call this function
// directly, unless you are implementing unmarshalling for a container type.
func (chainType *ChainType) Unmarshal(buf []byte, rem int) ([]byte, int, error) {
return surge.UnmarshalString((*string)(chainType), buf, rem)
}
// Network identifies the network type for the multichain deployment
type Network string
const (
// NetworkLocalnet represents a local network for chains. It is usually only
// accessible from the device running the network, and is not accessible
// over the Internet. Chain rules are often slightly different to allow for
// faster block times and easier access to testing funds. This is also
// sometimes referred to as "regnet" or "regression network". It should only
// be used for local testing.
NetworkLocalnet = Network("localnet")
// NetworkDevnet represents the development network for chains. This network
// is typically a deployed version of the localnet. Chain rules are often
// slightly different to allow for faster block times and easier access to
// testing funds.
NetworkDevnet = Network("devnet")
// NetworkTestnet represents the test network for chains. This network is
// typically a publicly accessible network that has the same, or very
// similar, chain rules compared to mainnet. Assets on this type of network
// are usually not considered to have value.
NetworkTestnet = Network("testnet")
// NetworkMainnet represents the main network for chains.
NetworkMainnet = Network("mainnet")
)
// SizeHint returns the number of bytes required to represent the network in
// binary.
func (net Network) SizeHint() int {
return surge.SizeHintString(string(net))
}
// Marshal the network to binary. You should not call this function directly,
// unless you are implementing marshalling for a container type.
func (net Network) Marshal(buf []byte, rem int) ([]byte, int, error) {
return surge.MarshalString(string(net), buf, rem)
}
// Unmarshal the network from binary. You should not call this function
// directly, unless you are implementing unmarshalling for a container type.
func (net *Network) Unmarshal(buf []byte, rem int) ([]byte, int, error) {
return surge.UnmarshalString((*string)(net), buf, rem)
}