This repository has been archived by the owner on Jan 16, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 33
/
tx.go
211 lines (191 loc) · 6.48 KB
/
tx.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
package common
import (
"bytes"
"database/sql/driver"
"encoding/hex"
"errors"
"fmt"
"math/big"
"strings"
ethCommon "github.com/ethereum/go-ethereum/common"
"github.com/hermeznetwork/tracerr"
"github.com/iden3/go-iden3-crypto/babyjub"
)
const (
// TxIDPrefixL1UserTx is the prefix that determines that the TxID is for
// a L1UserTx
//nolinter:gomnd
TxIDPrefixL1UserTx = byte(0)
// TxIDPrefixL1CoordTx is the prefix that determines that the TxID is
// for a L1CoordinatorTx
//nolinter:gomnd
TxIDPrefixL1CoordTx = byte(1)
// TxIDPrefixL2Tx is the prefix that determines that the TxID is for a
// L2Tx (or PoolL2Tx)
//nolinter:gomnd
TxIDPrefixL2Tx = byte(2)
// TxIDLen is the length of the TxID byte array
TxIDLen = 33
)
var (
// SignatureConstantBytes contains the SignatureConstant in byte array
// format, which is equivalent to 3322668559 as uint32 in byte array in
// big endian representation.
SignatureConstantBytes = []byte{198, 11, 230, 15}
)
// TxID is the identifier of a Hermez network transaction
type TxID [TxIDLen]byte
// Scan implements Scanner for database/sql.
func (txid *TxID) Scan(src interface{}) error {
srcB, ok := src.([]byte)
if !ok {
return tracerr.Wrap(fmt.Errorf("can't scan %T into TxID", src))
}
if len(srcB) != TxIDLen {
return tracerr.Wrap(fmt.Errorf("can't scan []byte of len %d into TxID, need %d",
len(srcB), TxIDLen))
}
copy(txid[:], srcB)
return nil
}
// Value implements valuer for database/sql.
func (txid TxID) Value() (driver.Value, error) {
return txid[:], nil
}
// String returns a string hexadecimal representation of the TxID
func (txid TxID) String() string {
return "0x" + hex.EncodeToString(txid[:])
}
// NewTxIDFromString returns a string hexadecimal representation of the TxID
func NewTxIDFromString(idStr string) (TxID, error) {
txid := TxID{}
idStr = strings.TrimPrefix(idStr, "0x")
decoded, err := hex.DecodeString(idStr)
if err != nil {
return TxID{}, tracerr.Wrap(err)
}
if len(decoded) != TxIDLen {
return txid, tracerr.Wrap(errors.New("Invalid idStr"))
}
copy(txid[:], decoded)
return txid, nil
}
// MarshalText marshals a TxID
func (txid TxID) MarshalText() ([]byte, error) {
return []byte(txid.String()), nil
}
// UnmarshalText unmarshalls a TxID
func (txid *TxID) UnmarshalText(data []byte) error {
idStr := string(data)
id, err := NewTxIDFromString(idStr)
if err != nil {
return tracerr.Wrap(err)
}
*txid = id
return nil
}
// TxType is a string that represents the type of a Hermez network transaction
type TxType string
const (
// TxTypeExit represents L2->L1 token transfer. A leaf for this account appears in the exit
// tree of the block
TxTypeExit TxType = "Exit"
// TxTypeTransfer represents L2->L2 token transfer
TxTypeTransfer TxType = "Transfer"
// TxTypeDeposit represents L1->L2 transfer
TxTypeDeposit TxType = "Deposit"
// TxTypeCreateAccountDeposit represents creation of a new leaf in the state tree
// (newAcconut) + L1->L2 transfer
TxTypeCreateAccountDeposit TxType = "CreateAccountDeposit"
// TxTypeCreateAccountDepositTransfer represents L1->L2 transfer + L2->L2 transfer
TxTypeCreateAccountDepositTransfer TxType = "CreateAccountDepositTransfer"
// TxTypeDepositTransfer TBD
TxTypeDepositTransfer TxType = "DepositTransfer"
// TxTypeForceTransfer TBD
TxTypeForceTransfer TxType = "ForceTransfer"
// TxTypeForceExit TBD
TxTypeForceExit TxType = "ForceExit"
// TxTypeTransferToEthAddr TBD
TxTypeTransferToEthAddr TxType = "TransferToEthAddr"
// TxTypeTransferToBJJ TBD
TxTypeTransferToBJJ TxType = "TransferToBJJ"
)
// Tx is a struct used by the TxSelector & BatchBuilder as a generic type generated from L1Tx &
// PoolL2Tx
type Tx struct {
// Generic
IsL1 bool `meddler:"is_l1"`
TxID TxID `meddler:"id"`
Type TxType `meddler:"type"`
Position int `meddler:"position"`
FromIdx Idx `meddler:"from_idx"`
ToIdx Idx `meddler:"to_idx"`
Amount *big.Int `meddler:"amount,bigint"`
AmountFloat float64 `meddler:"amount_f"`
TokenID TokenID `meddler:"token_id"`
USD *float64 `meddler:"amount_usd"`
// BatchNum in which this tx was forged. If the tx is L2, this must be != 0
BatchNum *BatchNum `meddler:"batch_num"`
// Ethereum Block Number in which this L1Tx was added to the queue
EthBlockNum int64 `meddler:"eth_block_num"`
// L1
// ToForgeL1TxsNum in which the tx was forged / will be forged
ToForgeL1TxsNum *int64 `meddler:"to_forge_l1_txs_num"`
// UserOrigin is set to true if the tx was originated by a user, false if it was aoriginated
// by a coordinator. Note that this differ from the spec for implementation simplification
// purpposes
UserOrigin *bool `meddler:"user_origin"`
FromEthAddr ethCommon.Address `meddler:"from_eth_addr"`
FromBJJ babyjub.PublicKeyComp `meddler:"from_bjj"`
DepositAmount *big.Int `meddler:"deposit_amount,bigintnull"`
DepositAmountFloat *float64 `meddler:"deposit_amount_f"`
DepositAmountUSD *float64 `meddler:"deposit_amount_usd"`
// L2
Fee *FeeSelector `meddler:"fee"`
FeeUSD *float64 `meddler:"fee_usd"`
Nonce *Nonce `meddler:"nonce"`
}
func (tx *Tx) String() string {
buf := bytes.NewBufferString("")
fmt.Fprintf(buf, "Type: %s, ", tx.Type)
fmt.Fprintf(buf, "FromIdx: %s, ", tx.FromIdx)
if tx.Type == TxTypeTransfer ||
tx.Type == TxTypeDepositTransfer ||
tx.Type == TxTypeCreateAccountDepositTransfer {
fmt.Fprintf(buf, "ToIdx: %s, ", tx.ToIdx)
}
if tx.Type == TxTypeDeposit ||
tx.Type == TxTypeDepositTransfer ||
tx.Type == TxTypeCreateAccountDepositTransfer {
fmt.Fprintf(buf, "DepositAmount: %d, ", tx.DepositAmount)
}
if tx.Type != TxTypeDeposit {
fmt.Fprintf(buf, "Amount: %s, ", tx.Amount)
}
if tx.Type == TxTypeTransfer ||
tx.Type == TxTypeDepositTransfer ||
tx.Type == TxTypeCreateAccountDepositTransfer {
fmt.Fprintf(buf, "Fee: %d, ", tx.Fee)
}
fmt.Fprintf(buf, "TokenID: %d", tx.TokenID)
return buf.String()
}
// L1Tx returns a *L1Tx from the Tx
func (tx *Tx) L1Tx() (*L1Tx, error) {
return &L1Tx{
TxID: tx.TxID,
ToForgeL1TxsNum: tx.ToForgeL1TxsNum,
Position: tx.Position,
UserOrigin: *tx.UserOrigin,
FromIdx: tx.FromIdx,
FromEthAddr: tx.FromEthAddr,
FromBJJ: tx.FromBJJ,
ToIdx: tx.ToIdx,
TokenID: tx.TokenID,
Amount: tx.Amount,
DepositAmount: tx.DepositAmount,
EthBlockNum: tx.EthBlockNum,
Type: tx.Type,
BatchNum: tx.BatchNum,
}, nil
}