This repository has been archived by the owner on Aug 27, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 27
/
txtype.go
265 lines (242 loc) · 8.49 KB
/
txtype.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
// Copyright (c) 2021 The qitmeer developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package types
import (
"fmt"
"github.com/Qitmeer/qitmeer/common/math"
)
// TxType indicates the type of transactions
// such as regular or other tx type (coinbase, stake or token).
type TxType int
const (
TxTypeRegular TxType = iota
TxTypeCoinbase TxType = 0x1
TxTypeGenesisLock TxType = 0x2 // the tx try to lock the genesis output to the stake pool
TxTypeStakebase TxType = 0x10 // the special tx which vote for stake_purchase and reward stake holder from the stake_reserve
TyTypeStakeReserve TxType = 0x11 // the tx reserve consensus-based value to a special stake_reserve address
TxTypeStakePurchase TxType = 0x12 // the tx of stake holder who lock value into stake pool
TxTypeStakeDispose TxType = 0x13 // the opposite tx of stake_purchase
TxTypeTokenRegulation TxType = 0x80 // token-regulation is reserved, not for using.
TxTypeTokenNew TxType = 0x81 // new coin-id, owners, up-limit etc. the token is disabled after token-new.
TxTypeTokenRenew TxType = 0x82 // update owners, up-limits etc. can't change coin-id. renew works only when the token is disabled.
TxTypeTokenValidate TxType = 0x83 // enable the token.
TxTypeTokenInvalidate TxType = 0x84 // disable the token.
TxTypeTokenRevoke TxType = 0x8f // revoke the coin-id. token-revoke is reserved, not used at current stage.
TxTypeTokenbase TxType = 0x90 // token-base is reserved, not used at current stage.
TxTypeTokenMint TxType = 0x91 // token owner mint token amount by locking MEER. (must validated token)
TxTypeTokenUnmint TxType = 0x92 // token owner unmint token amount by releasing MEER. (must validated token)
)
func (tt TxType) String() string {
switch tt {
case TxTypeRegular:
return "TxTypeRegular"
case TxTypeCoinbase:
return "TxTypeCoinbase"
case TxTypeGenesisLock:
return "TxTypeGenesisLock"
case TxTypeStakebase:
return "TxTypeStakebase"
case TyTypeStakeReserve:
return "TyTypeStakeReserve"
case TxTypeStakePurchase:
return "TxTypeStakePurchase"
case TxTypeStakeDispose:
return "TxTypeStakeDispose"
case TxTypeTokenRegulation:
return "TxTypeTokenRegulation"
case TxTypeTokenNew:
return "TxTypeTokenNew"
case TxTypeTokenRenew:
return "TxTypeTokenRenew"
case TxTypeTokenValidate:
return "TxTypeTokenValidate"
case TxTypeTokenInvalidate:
return "TxTypeTokenInvalidate"
case TxTypeTokenRevoke:
return "TxTypeTokenRevoke"
case TxTypeTokenbase:
return "TxTypeTokenbase"
case TxTypeTokenMint:
return "TxTypeTokenMint"
case TxTypeTokenUnmint:
return "TxTypeTokenUnmint"
}
return "Unknow"
}
// DetermineTxType determines the type of transaction
func DetermineTxType(tx *Transaction) TxType {
if IsCoinBaseTx(tx) {
return TxTypeCoinbase
}
if IsGenesisLockTx(tx) {
return TxTypeGenesisLock
}
if IsTokenNewTx(tx) {
return TxTypeTokenNew
}
if IsTokenRenewTx(tx) {
return TxTypeTokenRenew
}
if IsTokenValidateTx(tx) {
return TxTypeTokenValidate
}
if IsTokenInvalidateTx(tx) {
return TxTypeTokenInvalidate
}
if IsTokenMintTx(tx) {
return TxTypeTokenMint
}
if IsTokenUnmintTx(tx) {
return TxTypeTokenUnmint
}
//TODO more txType
return TxTypeRegular
}
// IsCoinBaseTx determines whether or not a transaction is a coinbase. A
// coinbase is a special transaction created by miners that has no inputs.
// This is represented in the block chain by a transaction with a single input
// that has a previous output transaction index set to the maximum value along
// with a zero hash.
//
// This function only differs from IsCoinBase in that it works with a raw wire
// transaction as opposed to a higher level util transaction.
func IsCoinBaseTx(tx *Transaction) bool {
// A coin base must only have one transaction input.
if len(tx.TxIn) != 1 {
return false
}
// The previous output of a coin base must have a max value index and a
// zero hash.
prevOut := &tx.TxIn[0].PreviousOut
/*if prevOut.OutIndex != math.MaxUint32 || !prevOut.Hash.IsEqual(&hash.ZeroHash) {
return false
}*/
return prevOut.OutIndex == math.MaxUint32
}
// --------------------------------------------------------------------------------
// The Genesis_XXX transactions
//
// the transactions related to the genesis UTXOs
//
// - genesis_lock how lock the genesis output to the stake pool
// --------------------------------------------------------------------------------
// CheckGenesisLock returns an error if a transaction is not a genesis_lock transaction.
// It makes sure the number of inputs/outputs, and related scripts are valid.
//
// genesis_lock transactions are specified as below:
//
// 1.) Inputs:
// genesis output 1 [index 0]
// genesis output 2 [index 1]
// ...
//
// 2.) Outputs:
// OP_STAKE_LOCK tagged output [index 0]
// OP_RETURN push of input 1's stake reward receiving address [index 1]
// OP_STAKE_LOCK tagged output [index 2]
// OP_RETURN push of input 2's stake reward receiving address [index 3]
// ...
// Note: The output OP_RETURN pushes should be of size 20 bytes (standard address).
//
// 3.) NO changes are allowed for the tx && NO fee are allowed for this tx.
// inputs amount == output amount
//
func CheckGenesisLock(tx *Transaction) error {
return fmt.Errorf("CheckGenesisLock is not supported yet")
}
// IsGenesisLockTx returns whether or not a transaction is a genesis_lock transaction.
func IsGenesisLockTx(tx *Transaction) bool {
return CheckGenesisLock(tx) == nil
}
// --------------------------------------------------------------------------------
// Stake_XXX Transaction
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Token_XXX Transaction
//
//
// The workflow of an new token
// roles
// - token operator : the controller of a token who provide & organize the financial services using the token and
// take the responsibility as the legislate entity.
// - token regulator : the main supervising body who assure all token operator follow regulatory guidelines, such as AML policy etc.
// who in charge of new token approve and supervision the running token service.
// workflow
// 1. token operator request to token regulator, fulfil the requirement of the new token application. (off-chain)
// 2. if 1. is accepted, token regulator issue token_new (on chain).
// 3. consensus-based vote for token_validate (on chain).
// 4. if 3. is ok, token can be operated by token operator officially.
// 5. token operator do token_mint, the consensus-based token amount assessable. (on chain)
// --------------------------------------------------------------------------------
func IsTokenNewTx(tx *Transaction) bool {
if len(tx.TxOut) != 1 || len(tx.TxIn) != 1 {
return false
}
if tx.TxIn[0].PreviousOut.OutIndex != TokenPrevOutIndex {
return false
}
return TxType(tx.TxIn[0].Sequence) == TxTypeTokenNew
}
func IsTokenRenewTx(tx *Transaction) bool {
if len(tx.TxOut) != 1 || len(tx.TxIn) != 1 {
return false
}
if tx.TxIn[0].PreviousOut.OutIndex != TokenPrevOutIndex {
return false
}
return TxType(tx.TxIn[0].Sequence) == TxTypeTokenRenew
}
func IsTokenValidateTx(tx *Transaction) bool {
if len(tx.TxOut) != 1 || len(tx.TxIn) != 1 {
return false
}
if tx.TxIn[0].PreviousOut.OutIndex != TokenPrevOutIndex {
return false
}
return TxType(tx.TxIn[0].Sequence) == TxTypeTokenValidate
}
func IsTokenInvalidateTx(tx *Transaction) bool {
if len(tx.TxOut) != 1 || len(tx.TxIn) != 1 {
return false
}
if tx.TxIn[0].PreviousOut.OutIndex != TokenPrevOutIndex {
return false
}
return TxType(tx.TxIn[0].Sequence) == TxTypeTokenInvalidate
}
func IsTokenMintTx(tx *Transaction) bool {
if len(tx.TxOut) < 1 || len(tx.TxIn) <= 1 {
return false
}
if tx.TxIn[0].PreviousOut.OutIndex != TokenPrevOutIndex {
return false
}
return TxType(tx.TxIn[0].Sequence) == TxTypeTokenMint
}
func IsTokenUnmintTx(tx *Transaction) bool {
if len(tx.TxOut) < 1 || len(tx.TxIn) <= 1 {
return false
}
if tx.TxIn[0].PreviousOut.OutIndex != TokenPrevOutIndex {
return false
}
return TxType(tx.TxIn[0].Sequence) == TxTypeTokenUnmint
}
func IsTokenTx(tx *Transaction) bool {
return IsTokenNewTx(tx) ||
IsTokenRenewTx(tx) ||
IsTokenValidateTx(tx) ||
IsTokenInvalidateTx(tx) ||
IsTokenMintTx(tx) ||
IsTokenUnmintTx(tx)
}
// Standard transaction type
var StdTxs = []TxType{TxTypeRegular, TxTypeCoinbase}
var NonStdTxs = []TxType{
TxTypeTokenNew,
TxTypeTokenRenew,
TxTypeTokenInvalidate,
TxTypeTokenValidate,
TxTypeTokenMint,
}