mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-08 11:56:46 +01:00
Add TxCompressedData & V2 with some extra parsers for common
This commit is contained in:
@@ -1,13 +1,38 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
eth "github.com/ethereum/go-ethereum/common"
|
||||
"github.com/hermeznetwork/hermez-node/utils"
|
||||
"github.com/iden3/go-iden3-crypto/babyjub"
|
||||
)
|
||||
|
||||
// Nonce represents the nonce value in a uint64, which has the method Bytes that returns a byte array of length 5 (40 bits).
|
||||
type Nonce uint64
|
||||
|
||||
// Bytes returns a byte array of length 5 representing the Nonce
|
||||
func (n Nonce) Bytes() ([5]byte, error) {
|
||||
if n >= 1099511627776 { // 2**40bits
|
||||
return [5]byte{}, ErrNonceOverflow
|
||||
}
|
||||
var nonceBytes [8]byte
|
||||
binary.LittleEndian.PutUint64(nonceBytes[:], uint64(n))
|
||||
var b [5]byte
|
||||
copy(b[:], nonceBytes[:5])
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func NonceFromBytes(b [5]byte) (Nonce, error) {
|
||||
var nonceBytes [8]byte
|
||||
copy(nonceBytes[:], b[:5])
|
||||
nonce := binary.LittleEndian.Uint64(nonceBytes[:])
|
||||
return Nonce(nonce), nil
|
||||
}
|
||||
|
||||
// PoolL2Tx is a struct that represents a L2Tx sent by an account to the coordinator hat is waiting to be forged
|
||||
type PoolL2Tx struct {
|
||||
// Stored in DB: mandatory fileds
|
||||
@@ -19,7 +44,7 @@ type PoolL2Tx struct {
|
||||
TokenID TokenID `meddler:"token_id"`
|
||||
Amount *big.Int `meddler:"amount,bigint"` // TODO: change to float16
|
||||
Fee FeeSelector `meddler:"fee"`
|
||||
Nonce uint64 `meddler:"nonce"` // effective 48 bits used
|
||||
Nonce Nonce `meddler:"nonce"` // effective 40 bits used
|
||||
State PoolL2TxState `meddler:"state"`
|
||||
Signature babyjub.Signature `meddler:"signature"` // tx signature
|
||||
Timestamp time.Time `meddler:"timestamp,utctime"` // time when added to the tx pool
|
||||
@@ -40,6 +65,86 @@ type PoolL2Tx struct {
|
||||
RqTxCompressedData []byte `meddler:"-"` // 253 bits, optional for atomic txs
|
||||
}
|
||||
|
||||
// TxCompressedData spec:
|
||||
// [ 32 bits ] signatureConstant // 4 bytes: [0:4]
|
||||
// [ 16 bits ] chainId // 2 bytes: [4:6]
|
||||
// [ 48 bits ] fromIdx // 6 bytes: [6:12]
|
||||
// [ 48 bits ] toIdx // 6 bytes: [12:18]
|
||||
// [ 16 bits ] amountFloat16 // 2 bytes: [18:20]
|
||||
// [ 32 bits ] tokenID // 4 bytes: [20:24]
|
||||
// [ 40 bits ] nonce // 5 bytes: [24:29]
|
||||
// [ 8 bits ] userFee // 1 byte: [29:30]
|
||||
// [ 1 bits ] toBjjSign // 1 byte: [30:31]
|
||||
// Total bits compressed data: 241 bits // 31 bytes in *big.Int representation
|
||||
func (tx *PoolL2Tx) TxCompressedData() (*big.Int, error) {
|
||||
// sigconstant
|
||||
sc, ok := new(big.Int).SetString("3322668559", 10)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("error parsing SignatureConstant")
|
||||
}
|
||||
|
||||
amountFloat16, err := utils.NewFloat16(tx.Amount)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var b [31]byte
|
||||
copy(b[:4], SwapEndianness(sc.Bytes()))
|
||||
copy(b[4:6], []byte{1, 0, 0, 0}) // LittleEndian representation of uint32(1) for Ethereum
|
||||
copy(b[6:12], tx.FromIdx.Bytes())
|
||||
copy(b[12:18], tx.ToIdx.Bytes())
|
||||
copy(b[18:20], amountFloat16.Bytes())
|
||||
copy(b[20:24], tx.TokenID.Bytes())
|
||||
nonceBytes, err := tx.Nonce.Bytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(b[24:29], nonceBytes[:])
|
||||
b[29] = byte(tx.Fee)
|
||||
toBjjSign := byte(0)
|
||||
if babyjub.PointCoordSign(tx.ToBJJ.X) {
|
||||
toBjjSign = byte(1)
|
||||
}
|
||||
b[30] = toBjjSign
|
||||
bi := new(big.Int).SetBytes(SwapEndianness(b[:]))
|
||||
|
||||
return bi, nil
|
||||
}
|
||||
|
||||
// TxCompressedDataV2 spec:
|
||||
// [ 48 bits ] fromIdx // 6 bytes: [0:6]
|
||||
// [ 48 bits ] toIdx // 6 bytes: [6:12]
|
||||
// [ 16 bits ] amountFloat16 // 2 bytes: [12:14]
|
||||
// [ 32 bits ] tokenID // 4 bytes: [14:18]
|
||||
// [ 40 bits ] nonce // 5 bytes: [18:23]
|
||||
// [ 8 bits ] userFee // 1 byte: [23:24]
|
||||
// [ 1 bits ] toBjjSign // 1 byte: [24:25]
|
||||
// Total bits compressed data: 193 bits // 25 bytes in *big.Int representation
|
||||
func (tx *PoolL2Tx) TxCompressedDataV2() (*big.Int, error) {
|
||||
amountFloat16, err := utils.NewFloat16(tx.Amount)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var b [25]byte
|
||||
copy(b[0:6], tx.FromIdx.Bytes())
|
||||
copy(b[6:12], tx.ToIdx.Bytes())
|
||||
copy(b[12:14], amountFloat16.Bytes())
|
||||
copy(b[14:18], tx.TokenID.Bytes())
|
||||
nonceBytes, err := tx.Nonce.Bytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(b[18:23], nonceBytes[:])
|
||||
b[23] = byte(tx.Fee)
|
||||
toBjjSign := byte(0)
|
||||
if babyjub.PointCoordSign(tx.ToBJJ.X) {
|
||||
toBjjSign = byte(1)
|
||||
}
|
||||
b[24] = toBjjSign
|
||||
|
||||
bi := new(big.Int).SetBytes(SwapEndianness(b[:]))
|
||||
return bi, nil
|
||||
}
|
||||
|
||||
func (tx *PoolL2Tx) Tx() *Tx {
|
||||
return &Tx{
|
||||
TxID: tx.TxID,
|
||||
|
||||
Reference in New Issue
Block a user