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}
 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 [L1TxBytesLen]byte
 67	copy(b[0:20], tx.FromEthAddr.Bytes())
 68	pkComp := tx.FromBJJ.Compress()
 69	copy(b[20:52], pkComp[:])
 70	fromIdxBytes, err := tx.FromIdx.Bytes()
 71	if err != nil {
 72		return nil, err
 73	}
 74	copy(b[52:58], fromIdxBytes[:])
 75	loadAmountFloat16, err := NewFloat16(tx.LoadAmount)
 76	if err != nil {
 77		return nil, err
 78	}
 79	copy(b[58:60], loadAmountFloat16.Bytes())
 80	amountFloat16, err := NewFloat16(tx.Amount)
 81	if err != nil {
 82		return nil, err
 83	}
 84	copy(b[60:62], amountFloat16.Bytes())
 85	copy(b[62:66], tx.TokenID.Bytes())
 86	toIdxBytes, err := tx.ToIdx.Bytes()
 87	if err != nil {
 88		return nil, err
 89	}
 90	copy(b[66:72], toIdxBytes[:])
 91	return b[:], nil
 92}
 93
 94// L1TxFromBytes decodes a L1Tx from []byte
 95func L1TxFromBytes(b []byte) (*L1Tx, error) {
 96	if len(b) != L1TxBytesLen {
 97		return nil, fmt.Errorf("Can not parse L1Tx bytes, expected length %d, current: %d", 68, len(b))
 98	}
 99
100	tx := &L1Tx{}
101	var err error
102	tx.FromEthAddr = ethCommon.BytesToAddress(b[0:20])
103	pkCompB := b[20:52]
104	var pkComp babyjub.PublicKeyComp
105	copy(pkComp[:], pkCompB)
106	tx.FromBJJ, err = pkComp.Decompress()
107	if err != nil {
108		return nil, err
109	}
110	tx.FromIdx, err = IdxFromBytes(b[52:58])
111	if err != nil {
112		return nil, err
113	}
114	tx.LoadAmount = Float16FromBytes(b[58:60]).BigInt()
115	tx.Amount = Float16FromBytes(b[60:62]).BigInt()
116	tx.TokenID, err = TokenIDFromBytes(b[62:66])
117	if err != nil {
118		return nil, err
119	}
120	tx.ToIdx, err = IdxFromBytes(b[66:72])
121	if err != nil {
122		return nil, err
123	}
124
125	return tx, nil
126}