arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
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}