arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/common/l1tx.go
common/l1tx.goRaw
  1package common
  2
  3import (
  4	"fmt"
  5	"math/big"
  6
  7	ethCommon "github.com/ethereum/go-ethereum/common"
  8	"github.com/iden3/go-iden3-crypto/babyjub"
  9)
 10
 11const (
 12	// L1TxBytesLen is the length of the byte array that represents the L1Tx
 13	L1TxBytesLen = 72
 14)
 15
 16// L1Tx is a struct that represents a L1 tx
 17type L1Tx struct {
 18	// Stored in DB: mandatory fileds
 19	TxID            TxID
 20	ToForgeL1TxsNum int64 // toForgeL1TxsNum in which the tx was forged / will be forged
 21	Position        int
 22	UserOrigin      bool // 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
 23	FromIdx         Idx  // FromIdx is used by L1Tx/Deposit to indicate the Idx receiver of the L1Tx.LoadAmount (deposit)
 24	FromEthAddr     ethCommon.Address
 25	FromBJJ         *babyjub.PublicKey
 26	ToIdx           Idx // ToIdx is ignored in L1Tx/Deposit, but used in the L1Tx/DepositAndTransfer
 27	TokenID         TokenID
 28	Amount          *big.Int
 29	LoadAmount      *big.Int
 30	EthBlockNum     int64 // Ethereum Block Number in which this L1Tx was added to the queue
 31	Type            TxType
 32	BatchNum        *BatchNum
 33	USD             *float64
 34	LoadAmountUSD   *float64
 35}
 36
 37// Tx returns a *Tx from the L1Tx
 38func (tx *L1Tx) Tx() *Tx {
 39	f := new(big.Float).SetInt(tx.Amount)
 40	amountFloat, _ := f.Float64()
 41	genericTx := &Tx{
 42		IsL1:            true,
 43		TxID:            tx.TxID,
 44		Type:            tx.Type,
 45		Position:        tx.Position,
 46		FromIdx:         tx.FromIdx,
 47		ToIdx:           tx.ToIdx,
 48		Amount:          tx.Amount,
 49		AmountFloat:     amountFloat,
 50		TokenID:         tx.TokenID,
 51		ToForgeL1TxsNum: tx.ToForgeL1TxsNum,
 52		UserOrigin:      tx.UserOrigin,
 53		FromEthAddr:     tx.FromEthAddr,
 54		FromBJJ:         tx.FromBJJ,
 55		LoadAmount:      tx.LoadAmount,
 56		EthBlockNum:     tx.EthBlockNum,
 57		USD:             tx.USD,
 58		LoadAmountUSD:   tx.LoadAmountUSD,
 59	}
 60	if tx.LoadAmount != nil {
 61		lf := new(big.Float).SetInt(tx.LoadAmount)
 62		loadAmountFloat, _ := lf.Float64()
 63		genericTx.LoadAmountFloat = &loadAmountFloat
 64	}
 65	return genericTx
 66}
 67
 68// Bytes encodes a L1Tx into []byte
 69func (tx *L1Tx) Bytes(nLevels int) ([]byte, error) {
 70	var b [L1TxBytesLen]byte
 71	copy(b[0:20], tx.FromEthAddr.Bytes())
 72	pkComp := tx.FromBJJ.Compress()
 73	copy(b[20:52], pkComp[:])
 74	fromIdxBytes, err := tx.FromIdx.Bytes()
 75	if err != nil {
 76		return nil, err
 77	}
 78	copy(b[52:58], fromIdxBytes[:])
 79	loadAmountFloat16, err := NewFloat16(tx.LoadAmount)
 80	if err != nil {
 81		return nil, err
 82	}
 83	copy(b[58:60], loadAmountFloat16.Bytes())
 84	amountFloat16, err := NewFloat16(tx.Amount)
 85	if err != nil {
 86		return nil, err
 87	}
 88	copy(b[60:62], amountFloat16.Bytes())
 89	copy(b[62:66], tx.TokenID.Bytes())
 90	toIdxBytes, err := tx.ToIdx.Bytes()
 91	if err != nil {
 92		return nil, err
 93	}
 94	copy(b[66:72], toIdxBytes[:])
 95	return b[:], nil
 96}
 97
 98// L1TxFromBytes decodes a L1Tx from []byte
 99func L1TxFromBytes(b []byte) (*L1Tx, error) {
100	if len(b) != L1TxBytesLen {
101		return nil, fmt.Errorf("Can not parse L1Tx bytes, expected length %d, current: %d", 68, len(b))
102	}
103
104	tx := &L1Tx{}
105	var err error
106	tx.FromEthAddr = ethCommon.BytesToAddress(b[0:20])
107	pkCompB := b[20:52]
108	var pkComp babyjub.PublicKeyComp
109	copy(pkComp[:], pkCompB)
110	tx.FromBJJ, err = pkComp.Decompress()
111	if err != nil {
112		return nil, err
113	}
114	tx.FromIdx, err = IdxFromBytes(b[52:58])
115	if err != nil {
116		return nil, err
117	}
118	tx.LoadAmount = Float16FromBytes(b[58:60]).BigInt()
119	tx.Amount = Float16FromBytes(b[60:62]).BigInt()
120	tx.TokenID, err = TokenIDFromBytes(b[62:66])
121	if err != nil {
122		return nil, err
123	}
124	tx.ToIdx, err = IdxFromBytes(b[66:72])
125	if err != nil {
126		return nil, err
127	}
128
129	return tx, nil
130}