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	"github.com/hermeznetwork/tracerr"
  8)
  9
 10// L2Tx is a struct that represents an already forged L2 tx
 11type L2Tx struct {
 12	// Stored in DB: mandatory fileds
 13	TxID        TxID        `meddler:"id"`
 14	BatchNum    BatchNum    `meddler:"batch_num"` // batchNum in which this tx was forged.
 15	Position    int         `meddler:"position"`
 16	FromIdx     Idx         `meddler:"from_idx"`
 17	ToIdx       Idx         `meddler:"to_idx"`
 18	Amount      *big.Int    `meddler:"amount,bigint"`
 19	Fee         FeeSelector `meddler:"fee"`
 20	Nonce       Nonce       `meddler:"nonce"`
 21	Type        TxType      `meddler:"type"`
 22	EthBlockNum int64       `meddler:"eth_block_num"` // 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, tracerr.Wrap(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, tracerr.Wrap(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, tracerr.Wrap(err)
 49	}
 50	copy(txid[1:7], fromIdxBytes[:])
 51	nonceBytes, err := l2Tx.Nonce.Bytes()
 52	if err != nil {
 53		return l2Tx, tracerr.Wrap(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	batchNum := new(BatchNum)
 64	*batchNum = tx.BatchNum
 65	fee := new(FeeSelector)
 66	*fee = tx.Fee
 67	nonce := new(Nonce)
 68	*nonce = tx.Nonce
 69	return &Tx{
 70		IsL1:        false,
 71		TxID:        tx.TxID,
 72		Type:        tx.Type,
 73		Position:    tx.Position,
 74		FromIdx:     tx.FromIdx,
 75		ToIdx:       tx.ToIdx,
 76		Amount:      tx.Amount,
 77		BatchNum:    batchNum,
 78		EthBlockNum: tx.EthBlockNum,
 79		Fee:         fee,
 80		Nonce:       nonce,
 81	}
 82}
 83
 84// PoolL2Tx returns the data structure of PoolL2Tx with the parameters of a
 85// L2Tx filled
 86func (tx L2Tx) PoolL2Tx() *PoolL2Tx {
 87	return &PoolL2Tx{
 88		TxID:    tx.TxID,
 89		FromIdx: tx.FromIdx,
 90		ToIdx:   tx.ToIdx,
 91		Amount:  tx.Amount,
 92		Fee:     tx.Fee,
 93		Nonce:   tx.Nonce,
 94		Type:    tx.Type,
 95	}
 96}
 97
 98// L2TxsToPoolL2Txs returns an array of []*PoolL2Tx from an array of []*L2Tx,
 99// where the PoolL2Tx only have the parameters of a L2Tx filled.
100func L2TxsToPoolL2Txs(txs []L2Tx) []PoolL2Tx {
101	var r []PoolL2Tx
102	for _, tx := range txs {
103		r = append(r, *tx.PoolL2Tx())
104	}
105	return r
106}
107
108// BytesDataAvailability encodes a L2Tx into []byte for the Data Availability
109func (tx L2Tx) BytesDataAvailability(nLevels uint32) ([]byte, error) {
110	idxLen := nLevels / 8 //nolint:gomnd
111
112	b := make([]byte, ((nLevels*2)+16+8)/8) //nolint:gomnd
113
114	fromIdxBytes, err := tx.FromIdx.Bytes()
115	if err != nil {
116		return nil, tracerr.Wrap(err)
117	}
118	copy(b[0:idxLen], fromIdxBytes[6-idxLen:]) // [6-idxLen:] as is BigEndian
119
120	toIdxBytes, err := tx.ToIdx.Bytes()
121	if err != nil {
122		return nil, tracerr.Wrap(err)
123	}
124	copy(b[idxLen:idxLen*2], toIdxBytes[6-idxLen:])
125
126	amountFloat16, err := NewFloat16(tx.Amount)
127	if err != nil {
128		return nil, tracerr.Wrap(err)
129	}
130
131	copy(b[idxLen*2:idxLen*2+2], amountFloat16.Bytes())
132	b[idxLen*2+2] = byte(tx.Fee)
133
134	return b[:], nil
135}
136
137// L2TxFromBytes decodes a L1Tx from []byte
138func L2TxFromBytes(b []byte, nLevels int) (*L2Tx, error) {
139	idxLen := nLevels / 8 //nolint:gomnd
140	tx := &L2Tx{}
141	var err error
142
143	var paddedFromIdxBytes [6]byte
144	copy(paddedFromIdxBytes[6-idxLen:], b[0:idxLen])
145	tx.FromIdx, err = IdxFromBytes(paddedFromIdxBytes[:])
146	if err != nil {
147		return nil, tracerr.Wrap(err)
148	}
149
150	var paddedToIdxBytes [6]byte
151	copy(paddedToIdxBytes[6-idxLen:6], b[idxLen:idxLen*2])
152	tx.ToIdx, err = IdxFromBytes(paddedToIdxBytes[:])
153	if err != nil {
154		return nil, tracerr.Wrap(err)
155	}
156
157	tx.Amount = Float16FromBytes(b[idxLen*2 : idxLen*2+2]).BigInt()
158	tx.Fee = FeeSelector(b[idxLen*2+2])
159	return tx, nil
160}