arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/common/tx.go
common/tx.goRaw
  1package common
  2
  3import (
  4	"database/sql/driver"
  5	"encoding/hex"
  6	"errors"
  7	"fmt"
  8	"math/big"
  9
 10	ethCommon "github.com/ethereum/go-ethereum/common"
 11	"github.com/iden3/go-iden3-crypto/babyjub"
 12)
 13
 14const (
 15	// TXIDPrefixL1UserTx is the prefix that determines that the TxID is
 16	// for a L1UserTx
 17	//nolinter:gomnd
 18	TxIDPrefixL1UserTx = byte(0)
 19
 20	// TXIDPrefixL1CoordTx is the prefix that determines that the TxID is
 21	// for a L1CoordinatorTx
 22	//nolinter:gomnd
 23	TxIDPrefixL1CoordTx = byte(1)
 24
 25	// TxIDPrefixL2Tx is the prefix that determines that the TxID is for a
 26	// L2Tx (or PoolL2Tx)
 27	//nolinter:gomnd
 28	TxIDPrefixL2Tx = byte(2)
 29
 30	// TxIDLen is the length of the TxID byte array
 31	TxIDLen = 12
 32)
 33
 34// TxID is the identifier of a Hermez network transaction
 35type TxID [TxIDLen]byte
 36
 37// Scan implements Scanner for database/sql.
 38func (txid *TxID) Scan(src interface{}) error {
 39	srcB, ok := src.([]byte)
 40	if !ok {
 41		return fmt.Errorf("can't scan %T into TxID", src)
 42	}
 43	if len(srcB) != TxIDLen {
 44		return fmt.Errorf("can't scan []byte of len %d into TxID, need %d", len(srcB), TxIDLen)
 45	}
 46	copy(txid[:], srcB)
 47	return nil
 48}
 49
 50// Value implements valuer for database/sql.
 51func (txid TxID) Value() (driver.Value, error) {
 52	return txid[:], nil
 53}
 54
 55// String returns a string hexadecimal representation of the TxID
 56func (txid TxID) String() string {
 57	return "0x" + hex.EncodeToString(txid[:])
 58}
 59
 60// TxType is a string that represents the type of a Hermez network transaction
 61type TxType string
 62
 63const (
 64	// TxTypeExit represents L2->L1 token transfer.  A leaf for this account appears in the exit tree of the block
 65	TxTypeExit TxType = "Exit"
 66	// TxTypeTransfer represents L2->L2 token transfer
 67	TxTypeTransfer TxType = "Transfer"
 68	// TxTypeDeposit represents L1->L2 transfer
 69	TxTypeDeposit TxType = "Deposit"
 70	// TxTypeCreateAccountDeposit represents creation of a new leaf in the state tree (newAcconut) + L1->L2 transfer
 71	TxTypeCreateAccountDeposit TxType = "CreateAccountDeposit"
 72	// TxTypeCreateAccountDepositTransfer represents L1->L2 transfer + L2->L2 transfer
 73	TxTypeCreateAccountDepositTransfer TxType = "CreateAccountDepositTransfer"
 74	// TxTypeDepositTransfer TBD
 75	TxTypeDepositTransfer TxType = "DepositTransfer"
 76	// TxTypeForceTransfer TBD
 77	TxTypeForceTransfer TxType = "ForceTransfer"
 78	// TxTypeForceExit TBD
 79	TxTypeForceExit TxType = "ForceExit"
 80	// TxTypeTransferToEthAddr TBD
 81	TxTypeTransferToEthAddr TxType = "TransferToEthAddr"
 82	// TxTypeTransferToBJJ TBD
 83	TxTypeTransferToBJJ TxType = "TransferToBJJ"
 84)
 85
 86// Tx is a struct used by the TxSelector & BatchBuilder as a generic type generated from L1Tx & PoolL2Tx
 87type Tx struct {
 88	// Generic
 89	IsL1        bool      `meddler:"is_l1"`
 90	TxID        TxID      `meddler:"id"`
 91	Type        TxType    `meddler:"type"`
 92	Position    int       `meddler:"position"`
 93	FromIdx     *Idx      `meddler:"from_idx"`
 94	ToIdx       *Idx      `meddler:"to_idx"`
 95	Amount      *big.Int  `meddler:"amount,bigint"`
 96	AmountFloat float64   `meddler:"amount_f"`
 97	TokenID     TokenID   `meddler:"token_id"`
 98	USD         *float64  `meddler:"amount_usd"`
 99	BatchNum    *BatchNum `meddler:"batch_num"`     // batchNum in which this tx was forged. If the tx is L2, this must be != 0
100	EthBlockNum int64     `meddler:"eth_block_num"` // Ethereum Block Number in which this L1Tx was added to the queue
101	// L1
102	ToForgeL1TxsNum *int64             `meddler:"to_forge_l1_txs_num"` // toForgeL1TxsNum in which the tx was forged / will be forged
103	UserOrigin      *bool              `meddler:"user_origin"`         // 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
104	FromEthAddr     *ethCommon.Address `meddler:"from_eth_addr"`
105	FromBJJ         *babyjub.PublicKey `meddler:"from_bjj"`
106	LoadAmount      *big.Int           `meddler:"load_amount,bigintnull"`
107	LoadAmountFloat *float64           `meddler:"load_amount_f"`
108	LoadAmountUSD   *float64           `meddler:"load_amount_usd"`
109	// L2
110	Fee    *FeeSelector `meddler:"fee"`
111	FeeUSD *float64     `meddler:"fee_usd"`
112	Nonce  *Nonce       `meddler:"nonce"`
113}
114
115// L1Tx returns a *L1Tx from the Tx
116func (tx *Tx) L1Tx() (*L1Tx, error) {
117	if tx.UserOrigin == nil || tx.FromEthAddr == nil {
118		return nil, errors.New("Tx must have UserOrigin != nil and FromEthAddr != nil in order to be able to transform to L1Tx")
119	}
120	return &L1Tx{
121		TxID:            tx.TxID,
122		ToForgeL1TxsNum: tx.ToForgeL1TxsNum,
123		Position:        tx.Position,
124		UserOrigin:      *tx.UserOrigin,
125		FromIdx:         tx.FromIdx,
126		FromEthAddr:     *tx.FromEthAddr,
127		FromBJJ:         tx.FromBJJ,
128		ToIdx:           *tx.ToIdx,
129		TokenID:         tx.TokenID,
130		Amount:          tx.Amount,
131		LoadAmount:      tx.LoadAmount,
132		EthBlockNum:     tx.EthBlockNum,
133		Type:            tx.Type,
134		BatchNum:        tx.BatchNum,
135	}, nil
136}