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 = 68
 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}
 34
 35// Tx returns a *Tx from the L1Tx
 36func (tx *L1Tx) Tx() *Tx {
 37	f := new(big.Float).SetInt(tx.Amount)
 38	amountFloat, _ := f.Float64()
 39	genericTx := &Tx{
 40		IsL1:            true,
 41		TxID:            tx.TxID,
 42		Type:            tx.Type,
 43		Position:        tx.Position,
 44		FromIdx:         tx.FromIdx,
 45		ToIdx:           tx.ToIdx,
 46		Amount:          tx.Amount,
 47		AmountFloat:     amountFloat,
 48		TokenID:         tx.TokenID,
 49		ToForgeL1TxsNum: tx.ToForgeL1TxsNum,
 50		UserOrigin:      tx.UserOrigin,
 51		FromEthAddr:     tx.FromEthAddr,
 52		FromBJJ:         tx.FromBJJ,
 53		LoadAmount:      tx.LoadAmount,
 54		EthBlockNum:     tx.EthBlockNum,
 55	}
 56	if tx.LoadAmount != nil {
 57		lf := new(big.Float).SetInt(tx.LoadAmount)
 58		loadAmountFloat, _ := lf.Float64()
 59		genericTx.LoadAmountFloat = loadAmountFloat
 60	}
 61	return genericTx
 62}
 63
 64// Bytes encodes a L1Tx into []byte
 65func (tx *L1Tx) Bytes(nLevels int) ([]byte, error) {
 66	var b [68]byte
 67	copy(b[0:20], tx.FromEthAddr.Bytes())
 68	pkComp := tx.FromBJJ.Compress()
 69	copy(b[20:52], pkComp[:])
 70	copy(b[52:56], tx.FromIdx.Bytes())
 71	loadAmountFloat16, err := NewFloat16(tx.LoadAmount)
 72	if err != nil {
 73		return nil, err
 74	}
 75	copy(b[56:58], loadAmountFloat16.Bytes())
 76	amountFloat16, err := NewFloat16(tx.Amount)
 77	if err != nil {
 78		return nil, err
 79	}
 80	copy(b[58:60], amountFloat16.Bytes())
 81	copy(b[60:64], tx.TokenID.Bytes())
 82	copy(b[64:68], tx.ToIdx.Bytes())
 83	return b[:], nil
 84}
 85
 86// L1TxFromBytes decodes a L1Tx from []byte
 87func L1TxFromBytes(b []byte) (*L1Tx, error) {
 88	if len(b) != L1TxBytesLen {
 89		return nil, fmt.Errorf("Can not parse L1Tx bytes, expected length %d, current: %d", 68, len(b))
 90	}
 91
 92	tx := &L1Tx{}
 93	var err error
 94	tx.FromEthAddr = ethCommon.BytesToAddress(b[0:20])
 95	pkCompB := b[20:52]
 96	var pkComp babyjub.PublicKeyComp
 97	copy(pkComp[:], pkCompB)
 98	tx.FromBJJ, err = pkComp.Decompress()
 99	if err != nil {
100		return nil, err
101	}
102	tx.FromIdx, err = IdxFromBytes(b[52:56])
103	if err != nil {
104		return nil, err
105	}
106	tx.LoadAmount = Float16FromBytes(b[56:58]).BigInt()
107	tx.Amount = Float16FromBytes(b[58:60]).BigInt()
108	tx.TokenID, err = TokenIDFromBytes(b[60:64])
109	if err != nil {
110		return nil, err
111	}
112	tx.ToIdx, err = IdxFromBytes(b[64:68])
113	if err != nil {
114		return nil, err
115	}
116
117	return tx, nil
118}