You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

118 lines
3.3 KiB

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