hermez-node/common/l2tx.go
common/l2tx.goRaw
1package common
2
3import (
4 "fmt"
5 "math/big"
6)
7
8// L2Tx is a struct that represents an already forged L2 tx
9type L2Tx struct {
10 // Stored in DB: mandatory fileds
11 TxID TxID
12 BatchNum BatchNum // batchNum in which this tx was forged.
13 Position int
14 FromIdx Idx
15 ToIdx Idx
16 Amount *big.Int
17 USD *float64
18 Fee FeeSelector
19 FeeUSD *float64
20 Nonce Nonce
21 Type TxType
22 EthBlockNum int64 // Ethereum Block Number in which this L2Tx was added to the queue
23}
24
25// NewL2Tx returns the given L2Tx with the TxId & Type parameters calculated
26// from the L2Tx values
27func NewL2Tx(l2Tx *L2Tx) (*L2Tx, error) {
28 // calculate TxType
29 var txType TxType
30 if l2Tx.ToIdx == Idx(1) {
31 txType = TxTypeExit
32 } else if l2Tx.ToIdx >= IdxUserThreshold {
33 txType = TxTypeTransfer
34 } else {
35 return l2Tx, fmt.Errorf("Can not determine type of L2Tx, invalid ToIdx value: %d", l2Tx.ToIdx)
36 }
37
38 // if TxType!=l2Tx.TxType return error
39 if l2Tx.Type != "" && l2Tx.Type != txType {
40 return l2Tx, fmt.Errorf("L2Tx.Type: %s, should be: %s", l2Tx.Type, txType)
41 }
42 l2Tx.Type = txType
43
44 var txid [TxIDLen]byte
45 txid[0] = TxIDPrefixL2Tx
46 fromIdxBytes, err := l2Tx.FromIdx.Bytes()
47 if err != nil {
48 return l2Tx, err
49 }
50 copy(txid[1:7], fromIdxBytes[:])
51 nonceBytes, err := l2Tx.Nonce.Bytes()
52 if err != nil {
53 return l2Tx, err
54 }
55 copy(txid[7:12], nonceBytes[:])
56 l2Tx.TxID = TxID(txid)
57
58 return l2Tx, nil
59}
60
61// Tx returns a *Tx from the L2Tx
62func (tx *L2Tx) Tx() *Tx {
63 f := new(big.Float).SetInt(tx.Amount)
64 amountFloat, _ := f.Float64()
65 batchNum := new(BatchNum)
66 *batchNum = tx.BatchNum
67 fee := new(FeeSelector)
68 *fee = tx.Fee
69 nonce := new(Nonce)
70 *nonce = tx.Nonce
71 return &Tx{
72 IsL1: false,
73 TxID: tx.TxID,
74 Type: tx.Type,
75 Position: tx.Position,
76 FromIdx: tx.FromIdx,
77 ToIdx: tx.ToIdx,
78 Amount: tx.Amount,
79 USD: tx.USD,
80 AmountFloat: amountFloat,
81 BatchNum: batchNum,
82 EthBlockNum: tx.EthBlockNum,
83 Fee: fee,
84 FeeUSD: tx.FeeUSD,
85 Nonce: nonce,
86 }
87}
88
89// PoolL2Tx returns the data structure of PoolL2Tx with the parameters of a
90// L2Tx filled
91func (tx *L2Tx) PoolL2Tx() *PoolL2Tx {
92 return &PoolL2Tx{
93 TxID: tx.TxID,
94 BatchNum: tx.BatchNum,
95 FromIdx: tx.FromIdx,
96 ToIdx: tx.ToIdx,
97 Amount: tx.Amount,
98 Fee: tx.Fee,
99 Nonce: tx.Nonce,
100 Type: tx.Type,
101 }
102}
103
104// L2TxsToPoolL2Txs returns an array of []*PoolL2Tx from an array of []*L2Tx,
105// where the PoolL2Tx only have the parameters of a L2Tx filled.
106func L2TxsToPoolL2Txs(txs []*L2Tx) []*PoolL2Tx {
107 var r []*PoolL2Tx
108 for _, tx := range txs {
109 r = append(r, tx.PoolL2Tx())
110 }
111 return r
112}
113
114// Bytes encodes a L2Tx into []byte
115func (tx *L2Tx) Bytes(nLevels int) ([]byte, error) {
116 fromIdxNumBytes := nLevels / 8 //nolint:gomnd
117 toIdxNumBytes := nLevels / 8 //nolint:gomnd
118 var b []byte
119 fromIdxBytes, err := tx.FromIdx.Bytes()
120 if err != nil {
121 return nil, err
122 }
123 b = append(b, fromIdxBytes[6-fromIdxNumBytes:]...)
124 toIdxBytes, err := tx.ToIdx.Bytes()
125 if err != nil {
126 return nil, err
127 }
128 b = append(b, toIdxBytes[6-toIdxNumBytes:]...)
129 amountFloat16, err := NewFloat16(tx.Amount)
130 if err != nil {
131 return nil, err
132 }
133 b = append(b, amountFloat16.Bytes()...)
134 b = append(b, byte(tx.Fee))
135 return b[:], nil
136}
137
138// L2TxFromBytes decodes a L1Tx from []byte
139func L2TxFromBytes(b []byte, nLevels int) (*L2Tx, error) {
140 fromIdxNumByte := nLevels / 8 //nolint:gomnd
141 toIdxNumByte := fromIdxNumByte + nLevels/8 //nolint:gomnd
142 amountLenBytes := 2
143 amountNumByte := toIdxNumByte + amountLenBytes
144 tx := &L2Tx{}
145 var err error
146 var paddedFromIdxBytes [6]byte
147 copy(paddedFromIdxBytes[6-len(b[0:fromIdxNumByte]):], b[0:fromIdxNumByte])
148 tx.FromIdx, err = IdxFromBytes(paddedFromIdxBytes[:])
149 if err != nil {
150 return nil, err
151 }
152 var paddedToIdxBytes [6]byte
153 copy(paddedToIdxBytes[6-len(b[fromIdxNumByte:toIdxNumByte]):6], b[fromIdxNumByte:toIdxNumByte])
154 tx.ToIdx, err = IdxFromBytes(paddedToIdxBytes[:])
155 if err != nil {
156 return nil, err
157 }
158 tx.Amount = Float16FromBytes(b[toIdxNumByte:amountNumByte]).BigInt()
159 tx.Fee = FeeSelector(b[amountNumByte])
160 return tx, nil
161}