mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 03:16:45 +01:00
Change endianness to BigEndian :(
Change endianness to BigEndian (ಥ﹏ಥ), spec has been updated to achieve compatibility with js & smart contracts & circuits implementations.
This commit is contained in:
@@ -37,7 +37,7 @@ type Idx uint32
|
|||||||
// Bytes returns a byte array representing the Idx
|
// Bytes returns a byte array representing the Idx
|
||||||
func (idx Idx) Bytes() []byte {
|
func (idx Idx) Bytes() []byte {
|
||||||
var b [4]byte
|
var b [4]byte
|
||||||
binary.LittleEndian.PutUint32(b[:], uint32(idx))
|
binary.BigEndian.PutUint32(b[:], uint32(idx))
|
||||||
return b[:]
|
return b[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ func IdxFromBytes(b []byte) (Idx, error) {
|
|||||||
if len(b) != idxBytesLen {
|
if len(b) != idxBytesLen {
|
||||||
return 0, fmt.Errorf("can not parse Idx, bytes len %d, expected 4", len(b))
|
return 0, fmt.Errorf("can not parse Idx, bytes len %d, expected 4", len(b))
|
||||||
}
|
}
|
||||||
idx := binary.LittleEndian.Uint32(b[:4])
|
idx := binary.BigEndian.Uint32(b[:4])
|
||||||
return Idx(idx), nil
|
return Idx(idx), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +84,10 @@ func (a *Account) String() string {
|
|||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bytes returns the bytes representing the Account, in a way that each BigInt is represented by 32 bytes, in spite of the BigInt could be represented in less bytes (due a small big.Int), so in this way each BigInt is always 32 bytes and can be automatically parsed from a byte array.
|
// Bytes returns the bytes representing the Account, in a way that each BigInt
|
||||||
|
// is represented by 32 bytes, in spite of the BigInt could be represented in
|
||||||
|
// less bytes (due a small big.Int), so in this way each BigInt is always 32
|
||||||
|
// bytes and can be automatically parsed from a byte array.
|
||||||
func (a *Account) Bytes() ([32 * NLeafElems]byte, error) {
|
func (a *Account) Bytes() ([32 * NLeafElems]byte, error) {
|
||||||
var b [32 * NLeafElems]byte
|
var b [32 * NLeafElems]byte
|
||||||
|
|
||||||
@@ -105,7 +108,7 @@ func (a *Account) Bytes() ([32 * NLeafElems]byte, error) {
|
|||||||
if babyjub.PointCoordSign(a.PublicKey.X) {
|
if babyjub.PointCoordSign(a.PublicKey.X) {
|
||||||
b[10] = 1
|
b[10] = 1
|
||||||
}
|
}
|
||||||
copy(b[32:64], SwapEndianness(a.Balance.Bytes())) // SwapEndianness, as big.Int uses BigEndian
|
copy(b[32:64], SwapEndianness(a.Balance.Bytes()))
|
||||||
copy(b[64:96], SwapEndianness(a.PublicKey.Y.Bytes()))
|
copy(b[64:96], SwapEndianness(a.PublicKey.Y.Bytes()))
|
||||||
copy(b[96:116], a.EthAddr.Bytes())
|
copy(b[96:116], a.EthAddr.Bytes())
|
||||||
|
|
||||||
@@ -159,7 +162,10 @@ func AccountFromBigInts(e [NLeafElems]*big.Int) (*Account, error) {
|
|||||||
|
|
||||||
// AccountFromBytes returns a Account from a byte array
|
// AccountFromBytes returns a Account from a byte array
|
||||||
func AccountFromBytes(b [32 * NLeafElems]byte) (*Account, error) {
|
func AccountFromBytes(b [32 * NLeafElems]byte) (*Account, error) {
|
||||||
tokenID := binary.LittleEndian.Uint32(b[0:4])
|
tokenID, err := TokenIDFromBytes(b[0:4])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
var nonceBytes5 [5]byte
|
var nonceBytes5 [5]byte
|
||||||
copy(nonceBytes5[:], b[4:9])
|
copy(nonceBytes5[:], b[4:9])
|
||||||
nonce := NonceFromBytes(nonceBytes5)
|
nonce := NonceFromBytes(nonceBytes5)
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ func TestAccountHashValue(t *testing.T) {
|
|||||||
|
|
||||||
v, err := account.HashValue()
|
v, err := account.HashValue()
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, "16085711911723375585301279875451049849443101031421093098714359651259271023730", v.String())
|
assert.Equal(t, "9478468711598093334066833736294178928569163287501434518121324135729106649559", v.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccountErrNotInFF(t *testing.T) {
|
func TestAccountErrNotInFF(t *testing.T) {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
// Package utils provides methods to work with Hermez custom half float
|
// Package common Float16 provides methods to work with Hermez custom half float
|
||||||
// precision, 16 bits, codification internally called Float16 has been adopted
|
// precision, 16 bits, codification internally called Float16 has been adopted
|
||||||
// to encode large integers. This is done in order to save bits when L2
|
// to encode large integers. This is done in order to save bits when L2
|
||||||
// transactions are published.
|
// transactions are published.
|
||||||
//nolint:gomnd
|
//nolint:gomnd
|
||||||
package utils
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
@@ -19,13 +19,19 @@ var (
|
|||||||
// Float16 represents a float in a 16 bit format
|
// Float16 represents a float in a 16 bit format
|
||||||
type Float16 uint16
|
type Float16 uint16
|
||||||
|
|
||||||
// Bytes return a byte array of length 2 with the Float16 value encoded in LittleEndian
|
// Bytes return a byte array of length 2 with the Float16 value encoded in BigEndian
|
||||||
func (f16 Float16) Bytes() []byte {
|
func (f16 Float16) Bytes() []byte {
|
||||||
var b [2]byte
|
var b [2]byte
|
||||||
binary.LittleEndian.PutUint16(b[:], uint16(f16))
|
binary.BigEndian.PutUint16(b[:], uint16(f16))
|
||||||
return b[:]
|
return b[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Float16FromBytes returns a Float16 from a byte array of 2 bytes.
|
||||||
|
func Float16FromBytes(b []byte) *Float16 {
|
||||||
|
f16 := Float16(binary.BigEndian.Uint16(b[:2]))
|
||||||
|
return &f16
|
||||||
|
}
|
||||||
|
|
||||||
// BigInt converts the Float16 to a *big.Int integer
|
// BigInt converts the Float16 to a *big.Int integer
|
||||||
func (f16 *Float16) BigInt() *big.Int {
|
func (f16 *Float16) BigInt() *big.Int {
|
||||||
fl := int64(*f16)
|
fl := int64(*f16)
|
||||||
@@ -67,8 +73,8 @@ func floorFix2Float(_f *big.Int) Float16 {
|
|||||||
return Float16(m.Int64() | e<<11)
|
return Float16(m.Int64() | e<<11)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFloat16 encodes a *big.Int integer as a Float16, returning error in case
|
// NewFloat16 encodes a *big.Int integer as a Float16, returning error in
|
||||||
// of loss during the encoding.
|
// case of loss during the encoding.
|
||||||
func NewFloat16(f *big.Int) (Float16, error) {
|
func NewFloat16(f *big.Int) (Float16, error) {
|
||||||
fl1 := floorFix2Float(f)
|
fl1 := floorFix2Float(f)
|
||||||
fi1 := fl1.BigInt()
|
fi1 := fl1.BigInt()
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package utils
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
ethCommon "github.com/ethereum/go-ethereum/common"
|
ethCommon "github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/hermeznetwork/hermez-node/utils"
|
|
||||||
"github.com/iden3/go-iden3-crypto/babyjub"
|
"github.com/iden3/go-iden3-crypto/babyjub"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -65,55 +64,55 @@ func (tx *L1Tx) Tx() *Tx {
|
|||||||
// Bytes encodes a L1Tx into []byte
|
// Bytes encodes a L1Tx into []byte
|
||||||
func (tx *L1Tx) Bytes(nLevels int) ([]byte, error) {
|
func (tx *L1Tx) Bytes(nLevels int) ([]byte, error) {
|
||||||
var b [68]byte
|
var b [68]byte
|
||||||
copy(b[0:4], tx.ToIdx.Bytes())
|
copy(b[0:20], tx.FromEthAddr.Bytes())
|
||||||
copy(b[4:8], tx.TokenID.Bytes())
|
|
||||||
amountFloat16, err := utils.NewFloat16(tx.Amount)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
copy(b[8:10], amountFloat16.Bytes())
|
|
||||||
loadAmountFloat16, err := utils.NewFloat16(tx.LoadAmount)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
copy(b[10:12], loadAmountFloat16.Bytes())
|
|
||||||
copy(b[12:16], tx.FromIdx.Bytes())
|
|
||||||
pkComp := tx.FromBJJ.Compress()
|
pkComp := tx.FromBJJ.Compress()
|
||||||
copy(b[16:48], SwapEndianness(pkComp[:]))
|
copy(b[20:52], pkComp[:])
|
||||||
copy(b[48:68], SwapEndianness(tx.FromEthAddr.Bytes()))
|
copy(b[52:56], tx.FromIdx.Bytes())
|
||||||
return SwapEndianness(b[:]), nil
|
loadAmountFloat16, err := NewFloat16(tx.LoadAmount)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
copy(b[56:58], loadAmountFloat16.Bytes())
|
||||||
|
amountFloat16, err := NewFloat16(tx.Amount)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
copy(b[58:60], amountFloat16.Bytes())
|
||||||
|
copy(b[60:64], tx.TokenID.Bytes())
|
||||||
|
copy(b[64:68], tx.ToIdx.Bytes())
|
||||||
|
return b[:], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// L1TxFromBytes decodes a L1Tx from []byte
|
// L1TxFromBytes decodes a L1Tx from []byte
|
||||||
func L1TxFromBytes(bRaw []byte) (*L1Tx, error) {
|
func L1TxFromBytes(b []byte) (*L1Tx, error) {
|
||||||
if len(bRaw) != L1TxBytesLen {
|
if len(b) != L1TxBytesLen {
|
||||||
return nil, fmt.Errorf("Can not parse L1Tx bytes, expected length %d, current: %d", 68, len(bRaw))
|
return nil, fmt.Errorf("Can not parse L1Tx bytes, expected length %d, current: %d", 68, len(b))
|
||||||
}
|
}
|
||||||
|
|
||||||
b := SwapEndianness(bRaw)
|
|
||||||
tx := &L1Tx{}
|
tx := &L1Tx{}
|
||||||
var err error
|
var err error
|
||||||
tx.ToIdx, err = IdxFromBytes(b[0:4])
|
tx.FromEthAddr = ethCommon.BytesToAddress(b[0:20])
|
||||||
if err != nil {
|
pkCompB := b[20:52]
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
tx.TokenID, err = TokenIDFromBytes(b[4:8])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
tx.Amount = new(big.Int).SetBytes(SwapEndianness(b[8:10]))
|
|
||||||
tx.LoadAmount = new(big.Int).SetBytes(SwapEndianness(b[10:12]))
|
|
||||||
tx.FromIdx, err = IdxFromBytes(b[12:16])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pkCompB := SwapEndianness(b[16:48])
|
|
||||||
var pkComp babyjub.PublicKeyComp
|
var pkComp babyjub.PublicKeyComp
|
||||||
copy(pkComp[:], pkCompB)
|
copy(pkComp[:], pkCompB)
|
||||||
tx.FromBJJ, err = pkComp.Decompress()
|
tx.FromBJJ, err = pkComp.Decompress()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tx.FromEthAddr = ethCommon.BytesToAddress(SwapEndianness(b[48:68]))
|
tx.FromIdx, err = IdxFromBytes(b[52:56])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tx.LoadAmount = Float16FromBytes(b[56:58]).BigInt()
|
||||||
|
tx.Amount = Float16FromBytes(b[58:60]).BigInt()
|
||||||
|
tx.TokenID, err = TokenIDFromBytes(b[60:64])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tx.ToIdx, err = IdxFromBytes(b[64:68])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return tx, nil
|
return tx, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestL1TxCodec(t *testing.T) {
|
func TestL1TxByteParsers(t *testing.T) {
|
||||||
var pkComp babyjub.PublicKeyComp
|
var pkComp babyjub.PublicKeyComp
|
||||||
err := pkComp.UnmarshalText([]byte("0x56ca90f80d7c374ae7485e9bcc47d4ac399460948da6aeeb899311097925a72c"))
|
err := pkComp.UnmarshalText([]byte("0x56ca90f80d7c374ae7485e9bcc47d4ac399460948da6aeeb899311097925a72c"))
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
@@ -19,7 +19,7 @@ func TestL1TxCodec(t *testing.T) {
|
|||||||
pk, err := pkComp.Decompress()
|
pk, err := pkComp.Decompress()
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
l1Tx := L1Tx{
|
l1Tx := &L1Tx{
|
||||||
ToIdx: 3,
|
ToIdx: 3,
|
||||||
TokenID: 5,
|
TokenID: 5,
|
||||||
Amount: big.NewInt(1),
|
Amount: big.NewInt(1),
|
||||||
@@ -38,7 +38,7 @@ func TestL1TxCodec(t *testing.T) {
|
|||||||
|
|
||||||
decodedData, err := L1TxFromBytes(encodedData)
|
decodedData, err := L1TxFromBytes(encodedData)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.Equal(t, l1Tx, *decodedData)
|
assert.Equal(t, l1Tx, decodedData)
|
||||||
|
|
||||||
encodedData2, err := decodedData.Bytes(32)
|
encodedData2, err := decodedData.Bytes(32)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
ethCommon "github.com/ethereum/go-ethereum/common"
|
ethCommon "github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/hermeznetwork/hermez-node/utils"
|
|
||||||
"github.com/iden3/go-iden3-crypto/babyjub"
|
"github.com/iden3/go-iden3-crypto/babyjub"
|
||||||
"github.com/iden3/go-iden3-crypto/poseidon"
|
"github.com/iden3/go-iden3-crypto/poseidon"
|
||||||
)
|
)
|
||||||
@@ -21,9 +20,9 @@ func (n Nonce) Bytes() ([5]byte, error) {
|
|||||||
return [5]byte{}, ErrNonceOverflow
|
return [5]byte{}, ErrNonceOverflow
|
||||||
}
|
}
|
||||||
var nonceBytes [8]byte
|
var nonceBytes [8]byte
|
||||||
binary.LittleEndian.PutUint64(nonceBytes[:], uint64(n))
|
binary.BigEndian.PutUint64(nonceBytes[:], uint64(n))
|
||||||
var b [5]byte
|
var b [5]byte
|
||||||
copy(b[:], nonceBytes[:5])
|
copy(b[:], nonceBytes[3:])
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,8 +34,8 @@ func (n Nonce) BigInt() *big.Int {
|
|||||||
// NonceFromBytes returns Nonce from a [5]byte
|
// NonceFromBytes returns Nonce from a [5]byte
|
||||||
func NonceFromBytes(b [5]byte) Nonce {
|
func NonceFromBytes(b [5]byte) Nonce {
|
||||||
var nonceBytes [8]byte
|
var nonceBytes [8]byte
|
||||||
copy(nonceBytes[:], b[:5])
|
copy(nonceBytes[3:], b[:])
|
||||||
nonce := binary.LittleEndian.Uint64(nonceBytes[:])
|
nonce := binary.BigEndian.Uint64(nonceBytes[:])
|
||||||
return Nonce(nonce)
|
return Nonce(nonce)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,15 +74,15 @@ type PoolL2Tx struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TxCompressedData spec:
|
// TxCompressedData spec:
|
||||||
// [ 32 bits ] signatureConstant // 4 bytes: [0:4]
|
// [ 1 bits ] toBJJSign // 1 byte
|
||||||
// [ 16 bits ] chainId // 2 bytes: [4:6]
|
// [ 8 bits ] userFee // 1 byte
|
||||||
// [ 48 bits ] fromIdx // 6 bytes: [6:12]
|
// [ 40 bits ] nonce // 5 bytes
|
||||||
// [ 48 bits ] toIdx // 6 bytes: [12:18]
|
// [ 32 bits ] tokenID // 4 bytes
|
||||||
// [ 16 bits ] amountFloat16 // 2 bytes: [18:20]
|
// [ 16 bits ] amountFloat16 // 2 bytes
|
||||||
// [ 32 bits ] tokenID // 4 bytes: [20:24]
|
// [ 48 bits ] toIdx // 6 bytes
|
||||||
// [ 40 bits ] nonce // 5 bytes: [24:29]
|
// [ 48 bits ] fromIdx // 6 bytes
|
||||||
// [ 8 bits ] userFee // 1 byte: [29:30]
|
// [ 16 bits ] chainId // 2 bytes
|
||||||
// [ 1 bits ] toBJJSign // 1 byte: [30:31]
|
// [ 32 bits ] signatureConstant // 4 bytes
|
||||||
// Total bits compressed data: 241 bits // 31 bytes in *big.Int representation
|
// Total bits compressed data: 241 bits // 31 bytes in *big.Int representation
|
||||||
func (tx *PoolL2Tx) TxCompressedData() (*big.Int, error) {
|
func (tx *PoolL2Tx) TxCompressedData() (*big.Int, error) {
|
||||||
// sigconstant
|
// sigconstant
|
||||||
@@ -92,65 +91,65 @@ func (tx *PoolL2Tx) TxCompressedData() (*big.Int, error) {
|
|||||||
return nil, fmt.Errorf("error parsing SignatureConstant")
|
return nil, fmt.Errorf("error parsing SignatureConstant")
|
||||||
}
|
}
|
||||||
|
|
||||||
amountFloat16, err := utils.NewFloat16(tx.Amount)
|
amountFloat16, err := NewFloat16(tx.Amount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var b [31]byte
|
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)
|
toBJJSign := byte(0)
|
||||||
if babyjub.PointCoordSign(tx.ToBJJ.X) {
|
if babyjub.PointCoordSign(tx.ToBJJ.X) {
|
||||||
toBJJSign = byte(1)
|
toBJJSign = byte(1)
|
||||||
}
|
}
|
||||||
b[30] = toBJJSign
|
b[0] = toBJJSign
|
||||||
bi := new(big.Int).SetBytes(SwapEndianness(b[:]))
|
b[1] = byte(tx.Fee)
|
||||||
|
nonceBytes, err := tx.Nonce.Bytes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
copy(b[2:7], nonceBytes[:])
|
||||||
|
copy(b[7:11], tx.TokenID.Bytes())
|
||||||
|
copy(b[11:13], amountFloat16.Bytes())
|
||||||
|
copy(b[13+2:19], tx.ToIdx.Bytes())
|
||||||
|
copy(b[19+2:25], tx.FromIdx.Bytes())
|
||||||
|
copy(b[25:27], []byte{0, 1, 0, 0}) // TODO check js implementation (unexpected behaviour from test vector generated from js)
|
||||||
|
copy(b[27:31], sc.Bytes())
|
||||||
|
|
||||||
|
bi := new(big.Int).SetBytes(b[:])
|
||||||
return bi, nil
|
return bi, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TxCompressedDataV2 spec:
|
// TxCompressedDataV2 spec:
|
||||||
// [ 48 bits ] fromIdx // 6 bytes: [0:6]
|
// [ 1 bits ] toBJJSign // 1 byte
|
||||||
// [ 48 bits ] toIdx // 6 bytes: [6:12]
|
// [ 8 bits ] userFee // 1 byte
|
||||||
// [ 16 bits ] amountFloat16 // 2 bytes: [12:14]
|
// [ 40 bits ] nonce // 5 bytes
|
||||||
// [ 32 bits ] tokenID // 4 bytes: [14:18]
|
// [ 32 bits ] tokenID // 4 bytes
|
||||||
// [ 40 bits ] nonce // 5 bytes: [18:23]
|
// [ 16 bits ] amountFloat16 // 2 bytes
|
||||||
// [ 8 bits ] userFee // 1 byte: [23:24]
|
// [ 48 bits ] toIdx // 6 bytes
|
||||||
// [ 1 bits ] toBJJSign // 1 byte: [24:25]
|
// [ 48 bits ] fromIdx // 6 bytes
|
||||||
// Total bits compressed data: 193 bits // 25 bytes in *big.Int representation
|
// Total bits compressed data: 193 bits // 25 bytes in *big.Int representation
|
||||||
func (tx *PoolL2Tx) TxCompressedDataV2() (*big.Int, error) {
|
func (tx *PoolL2Tx) TxCompressedDataV2() (*big.Int, error) {
|
||||||
amountFloat16, err := utils.NewFloat16(tx.Amount)
|
amountFloat16, err := NewFloat16(tx.Amount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var b [25]byte
|
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)
|
toBJJSign := byte(0)
|
||||||
if babyjub.PointCoordSign(tx.ToBJJ.X) {
|
if babyjub.PointCoordSign(tx.ToBJJ.X) {
|
||||||
toBJJSign = byte(1)
|
toBJJSign = byte(1)
|
||||||
}
|
}
|
||||||
b[24] = toBJJSign
|
b[0] = toBJJSign
|
||||||
|
b[1] = byte(tx.Fee)
|
||||||
|
nonceBytes, err := tx.Nonce.Bytes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
copy(b[2:7], nonceBytes[:])
|
||||||
|
copy(b[7:11], tx.TokenID.Bytes())
|
||||||
|
copy(b[11:13], amountFloat16.Bytes())
|
||||||
|
copy(b[13+2:19], tx.ToIdx.Bytes())
|
||||||
|
copy(b[19+2:25], tx.FromIdx.Bytes())
|
||||||
|
|
||||||
bi := new(big.Int).SetBytes(SwapEndianness(b[:]))
|
bi := new(big.Int).SetBytes(b[:])
|
||||||
return bi, nil
|
return bi, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ func TestNonceParser(t *testing.T) {
|
|||||||
nBytes, err := n.Bytes()
|
nBytes, err := n.Bytes()
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 5, len(nBytes))
|
assert.Equal(t, 5, len(nBytes))
|
||||||
assert.Equal(t, "0100000000", hex.EncodeToString(nBytes[:]))
|
assert.Equal(t, "0000000001", hex.EncodeToString(nBytes[:]))
|
||||||
n2 := NonceFromBytes(nBytes)
|
n2 := NonceFromBytes(nBytes)
|
||||||
assert.Equal(t, n, n2)
|
assert.Equal(t, n, n2)
|
||||||
|
|
||||||
@@ -51,7 +51,11 @@ func TestTxCompressedData(t *testing.T) {
|
|||||||
txCompressedData, err := tx.TxCompressedData()
|
txCompressedData, err := tx.TxCompressedData()
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
// test vector value generated from javascript implementation
|
// test vector value generated from javascript implementation
|
||||||
assert.Equal(t, "1766847064778421992193717128424891165872736891548909569553540449389241871", txCompressedData.String())
|
expectedStr := "1766847064778421992193717128424891165872736891548909569553540449389241871"
|
||||||
|
assert.Equal(t, expectedStr, txCompressedData.String())
|
||||||
|
expected, ok := new(big.Int).SetString(expectedStr, 10)
|
||||||
|
assert.True(t, ok)
|
||||||
|
assert.Equal(t, expected.Bytes(), txCompressedData.Bytes())
|
||||||
assert.Equal(t, "10000000000060000000500040000000000030000000000020001c60be60f", hex.EncodeToString(txCompressedData.Bytes())[1:])
|
assert.Equal(t, "10000000000060000000500040000000000030000000000020001c60be60f", hex.EncodeToString(txCompressedData.Bytes())[1:])
|
||||||
|
|
||||||
tx = PoolL2Tx{
|
tx = PoolL2Tx{
|
||||||
@@ -66,7 +70,11 @@ func TestTxCompressedData(t *testing.T) {
|
|||||||
txCompressedData, err = tx.TxCompressedDataV2()
|
txCompressedData, err = tx.TxCompressedDataV2()
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
// test vector value generated from javascript implementation
|
// test vector value generated from javascript implementation
|
||||||
assert.Equal(t, "6571340879233176732837827812956721483162819083004853354503", txCompressedData.String())
|
expectedStr = "6571340879233176732837827812956721483162819083004853354503"
|
||||||
|
assert.Equal(t, expectedStr, txCompressedData.String())
|
||||||
|
expected, ok = new(big.Int).SetString(expectedStr, 10)
|
||||||
|
assert.True(t, ok)
|
||||||
|
assert.Equal(t, expected.Bytes(), txCompressedData.Bytes())
|
||||||
assert.Equal(t, "10c000000000b0000000a0009000000000008000000000007", hex.EncodeToString(txCompressedData.Bytes())[1:])
|
assert.Equal(t, "10c000000000b0000000a0009000000000008000000000007", hex.EncodeToString(txCompressedData.Bytes())[1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ type TokenID uint32 // current implementation supports up to 2^32 tokens
|
|||||||
// Bytes returns a byte array of length 4 representing the TokenID
|
// Bytes returns a byte array of length 4 representing the TokenID
|
||||||
func (t TokenID) Bytes() []byte {
|
func (t TokenID) Bytes() []byte {
|
||||||
var tokenIDBytes [4]byte
|
var tokenIDBytes [4]byte
|
||||||
binary.LittleEndian.PutUint32(tokenIDBytes[:], uint32(t))
|
binary.BigEndian.PutUint32(tokenIDBytes[:], uint32(t))
|
||||||
return tokenIDBytes[:]
|
return tokenIDBytes[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +51,6 @@ func TokenIDFromBytes(b []byte) (TokenID, error) {
|
|||||||
if len(b) != tokenIDBytesLen {
|
if len(b) != tokenIDBytesLen {
|
||||||
return 0, fmt.Errorf("can not parse TokenID, bytes len %d, expected 4", len(b))
|
return 0, fmt.Errorf("can not parse TokenID, bytes len %d, expected 4", len(b))
|
||||||
}
|
}
|
||||||
tid := binary.LittleEndian.Uint32(b[:4])
|
tid := binary.BigEndian.Uint32(b[:4])
|
||||||
return TokenID(tid), nil
|
return TokenID(tid), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
"github.com/hermeznetwork/hermez-node/common"
|
"github.com/hermeznetwork/hermez-node/common"
|
||||||
Hermez "github.com/hermeznetwork/hermez-node/eth/contracts/hermez"
|
Hermez "github.com/hermeznetwork/hermez-node/eth/contracts/hermez"
|
||||||
"github.com/hermeznetwork/hermez-node/log"
|
"github.com/hermeznetwork/hermez-node/log"
|
||||||
"github.com/hermeznetwork/hermez-node/utils"
|
|
||||||
"github.com/iden3/go-iden3-crypto/babyjub"
|
"github.com/iden3/go-iden3-crypto/babyjub"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -177,16 +176,16 @@ type RollupInterface interface {
|
|||||||
RollupAddToken(tokenAddress ethCommon.Address) (*types.Transaction, error)
|
RollupAddToken(tokenAddress ethCommon.Address) (*types.Transaction, error)
|
||||||
RollupWithdraw(tokenID int64, balance *big.Int, babyPubKey *babyjub.PublicKey,
|
RollupWithdraw(tokenID int64, balance *big.Int, babyPubKey *babyjub.PublicKey,
|
||||||
numExitRoot int64, siblings []*big.Int, idx int64, instantWithdraw bool) (*types.Transaction, error)
|
numExitRoot int64, siblings []*big.Int, idx int64, instantWithdraw bool) (*types.Transaction, error)
|
||||||
RollupForceExit(fromIdx int64, amountF utils.Float16, tokenID int64) (*types.Transaction, error)
|
RollupForceExit(fromIdx int64, amountF common.Float16, tokenID int64) (*types.Transaction, error)
|
||||||
RollupForceTransfer(fromIdx int64, amountF utils.Float16, tokenID, toIdx int64) (*types.Transaction, error)
|
RollupForceTransfer(fromIdx int64, amountF common.Float16, tokenID, toIdx int64) (*types.Transaction, error)
|
||||||
RollupCreateAccountDepositTransfer(babyPubKey babyjub.PublicKey,
|
RollupCreateAccountDepositTransfer(babyPubKey babyjub.PublicKey,
|
||||||
loadAmountF, amountF utils.Float16, tokenID int64, toIdx int64) (*types.Transaction, error)
|
loadAmountF, amountF common.Float16, tokenID int64, toIdx int64) (*types.Transaction, error)
|
||||||
RollupDepositTransfer(fromIdx int64, loadAmountF, amountF utils.Float16,
|
RollupDepositTransfer(fromIdx int64, loadAmountF, amountF common.Float16,
|
||||||
tokenID int64, toIdx int64) (*types.Transaction, error)
|
tokenID int64, toIdx int64) (*types.Transaction, error)
|
||||||
RollupDeposit(fromIdx int64, loadAmountF utils.Float16, tokenID int64) (*types.Transaction, error)
|
RollupDeposit(fromIdx int64, loadAmountF common.Float16, tokenID int64) (*types.Transaction, error)
|
||||||
RollupCreateAccountDepositFromRelayer(accountCreationAuthSig []byte,
|
RollupCreateAccountDepositFromRelayer(accountCreationAuthSig []byte,
|
||||||
babyPubKey babyjub.PublicKey, loadAmountF utils.Float16) (*types.Transaction, error)
|
babyPubKey babyjub.PublicKey, loadAmountF common.Float16) (*types.Transaction, error)
|
||||||
RollupCreateAccountDeposit(babyPubKey babyjub.PublicKey, loadAmountF utils.Float16,
|
RollupCreateAccountDeposit(babyPubKey babyjub.PublicKey, loadAmountF common.Float16,
|
||||||
tokenID int64) (*types.Transaction, error)
|
tokenID int64) (*types.Transaction, error)
|
||||||
|
|
||||||
RollupGetCurrentTokens() (*big.Int, error)
|
RollupGetCurrentTokens() (*big.Int, error)
|
||||||
@@ -249,43 +248,43 @@ func (c *RollupClient) RollupWithdraw(tokenID int64, balance *big.Int, babyPubKe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RollupForceExit is the interface to call the smart contract function
|
// RollupForceExit is the interface to call the smart contract function
|
||||||
func (c *RollupClient) RollupForceExit(fromIdx int64, amountF utils.Float16, tokenID int64) (*types.Transaction, error) {
|
func (c *RollupClient) RollupForceExit(fromIdx int64, amountF common.Float16, tokenID int64) (*types.Transaction, error) {
|
||||||
log.Error("TODO")
|
log.Error("TODO")
|
||||||
return nil, errTODO
|
return nil, errTODO
|
||||||
}
|
}
|
||||||
|
|
||||||
// RollupForceTransfer is the interface to call the smart contract function
|
// RollupForceTransfer is the interface to call the smart contract function
|
||||||
func (c *RollupClient) RollupForceTransfer(fromIdx int64, amountF utils.Float16, tokenID, toIdx int64) (*types.Transaction, error) {
|
func (c *RollupClient) RollupForceTransfer(fromIdx int64, amountF common.Float16, tokenID, toIdx int64) (*types.Transaction, error) {
|
||||||
log.Error("TODO")
|
log.Error("TODO")
|
||||||
return nil, errTODO
|
return nil, errTODO
|
||||||
}
|
}
|
||||||
|
|
||||||
// RollupCreateAccountDepositTransfer is the interface to call the smart contract function
|
// RollupCreateAccountDepositTransfer is the interface to call the smart contract function
|
||||||
func (c *RollupClient) RollupCreateAccountDepositTransfer(babyPubKey babyjub.PublicKey, loadAmountF, amountF utils.Float16, tokenID int64, toIdx int64) (*types.Transaction, error) {
|
func (c *RollupClient) RollupCreateAccountDepositTransfer(babyPubKey babyjub.PublicKey, loadAmountF, amountF common.Float16, tokenID int64, toIdx int64) (*types.Transaction, error) {
|
||||||
log.Error("TODO")
|
log.Error("TODO")
|
||||||
return nil, errTODO
|
return nil, errTODO
|
||||||
}
|
}
|
||||||
|
|
||||||
// RollupDepositTransfer is the interface to call the smart contract function
|
// RollupDepositTransfer is the interface to call the smart contract function
|
||||||
func (c *RollupClient) RollupDepositTransfer(fromIdx int64, loadAmountF, amountF utils.Float16, tokenID int64, toIdx int64) (*types.Transaction, error) {
|
func (c *RollupClient) RollupDepositTransfer(fromIdx int64, loadAmountF, amountF common.Float16, tokenID int64, toIdx int64) (*types.Transaction, error) {
|
||||||
log.Error("TODO")
|
log.Error("TODO")
|
||||||
return nil, errTODO
|
return nil, errTODO
|
||||||
}
|
}
|
||||||
|
|
||||||
// RollupDeposit is the interface to call the smart contract function
|
// RollupDeposit is the interface to call the smart contract function
|
||||||
func (c *RollupClient) RollupDeposit(fromIdx int64, loadAmountF utils.Float16, tokenID int64) (*types.Transaction, error) {
|
func (c *RollupClient) RollupDeposit(fromIdx int64, loadAmountF common.Float16, tokenID int64) (*types.Transaction, error) {
|
||||||
log.Error("TODO")
|
log.Error("TODO")
|
||||||
return nil, errTODO
|
return nil, errTODO
|
||||||
}
|
}
|
||||||
|
|
||||||
// RollupCreateAccountDepositFromRelayer is the interface to call the smart contract function
|
// RollupCreateAccountDepositFromRelayer is the interface to call the smart contract function
|
||||||
func (c *RollupClient) RollupCreateAccountDepositFromRelayer(accountCreationAuthSig []byte, babyPubKey babyjub.PublicKey, loadAmountF utils.Float16) (*types.Transaction, error) {
|
func (c *RollupClient) RollupCreateAccountDepositFromRelayer(accountCreationAuthSig []byte, babyPubKey babyjub.PublicKey, loadAmountF common.Float16) (*types.Transaction, error) {
|
||||||
log.Error("TODO")
|
log.Error("TODO")
|
||||||
return nil, errTODO
|
return nil, errTODO
|
||||||
}
|
}
|
||||||
|
|
||||||
// RollupCreateAccountDeposit is the interface to call the smart contract function
|
// RollupCreateAccountDeposit is the interface to call the smart contract function
|
||||||
func (c *RollupClient) RollupCreateAccountDeposit(babyPubKey babyjub.PublicKey, loadAmountF utils.Float16, tokenID int64) (*types.Transaction, error) {
|
func (c *RollupClient) RollupCreateAccountDeposit(babyPubKey babyjub.PublicKey, loadAmountF common.Float16, tokenID int64) (*types.Transaction, error) {
|
||||||
log.Error("TODO")
|
log.Error("TODO")
|
||||||
return nil, errTODO
|
return nil, errTODO
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import (
|
|||||||
"github.com/hermeznetwork/hermez-node/common"
|
"github.com/hermeznetwork/hermez-node/common"
|
||||||
"github.com/hermeznetwork/hermez-node/eth"
|
"github.com/hermeznetwork/hermez-node/eth"
|
||||||
"github.com/hermeznetwork/hermez-node/log"
|
"github.com/hermeznetwork/hermez-node/log"
|
||||||
"github.com/hermeznetwork/hermez-node/utils"
|
|
||||||
"github.com/iden3/go-iden3-crypto/babyjub"
|
"github.com/iden3/go-iden3-crypto/babyjub"
|
||||||
"github.com/mitchellh/copystructure"
|
"github.com/mitchellh/copystructure"
|
||||||
)
|
)
|
||||||
@@ -643,7 +642,7 @@ func (c *Client) RollupWithdraw(tokenID int64, balance *big.Int, babyPubKey *bab
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RollupForceExit is the interface to call the smart contract function
|
// RollupForceExit is the interface to call the smart contract function
|
||||||
func (c *Client) RollupForceExit(fromIdx int64, amountF utils.Float16, tokenID int64) (tx *types.Transaction, err error) {
|
func (c *Client) RollupForceExit(fromIdx int64, amountF common.Float16, tokenID int64) (tx *types.Transaction, err error) {
|
||||||
c.rw.Lock()
|
c.rw.Lock()
|
||||||
defer c.rw.Unlock()
|
defer c.rw.Unlock()
|
||||||
cpy := c.nextBlock().copy()
|
cpy := c.nextBlock().copy()
|
||||||
@@ -654,7 +653,7 @@ func (c *Client) RollupForceExit(fromIdx int64, amountF utils.Float16, tokenID i
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RollupForceTransfer is the interface to call the smart contract function
|
// RollupForceTransfer is the interface to call the smart contract function
|
||||||
func (c *Client) RollupForceTransfer(fromIdx int64, amountF utils.Float16, tokenID, toIdx int64) (tx *types.Transaction, err error) {
|
func (c *Client) RollupForceTransfer(fromIdx int64, amountF common.Float16, tokenID, toIdx int64) (tx *types.Transaction, err error) {
|
||||||
c.rw.Lock()
|
c.rw.Lock()
|
||||||
defer c.rw.Unlock()
|
defer c.rw.Unlock()
|
||||||
cpy := c.nextBlock().copy()
|
cpy := c.nextBlock().copy()
|
||||||
@@ -665,7 +664,7 @@ func (c *Client) RollupForceTransfer(fromIdx int64, amountF utils.Float16, token
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RollupCreateAccountDepositTransfer is the interface to call the smart contract function
|
// RollupCreateAccountDepositTransfer is the interface to call the smart contract function
|
||||||
func (c *Client) RollupCreateAccountDepositTransfer(babyPubKey babyjub.PublicKey, loadAmountF, amountF utils.Float16, tokenID int64, toIdx int64) (tx *types.Transaction, err error) {
|
func (c *Client) RollupCreateAccountDepositTransfer(babyPubKey babyjub.PublicKey, loadAmountF, amountF common.Float16, tokenID int64, toIdx int64) (tx *types.Transaction, err error) {
|
||||||
c.rw.Lock()
|
c.rw.Lock()
|
||||||
defer c.rw.Unlock()
|
defer c.rw.Unlock()
|
||||||
cpy := c.nextBlock().copy()
|
cpy := c.nextBlock().copy()
|
||||||
@@ -685,7 +684,7 @@ func (c *Client) RollupGetCurrentTokens() (*big.Int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RollupDepositTransfer is the interface to call the smart contract function
|
// RollupDepositTransfer is the interface to call the smart contract function
|
||||||
func (c *Client) RollupDepositTransfer(fromIdx int64, loadAmountF, amountF utils.Float16, tokenID int64, toIdx int64) (tx *types.Transaction, err error) {
|
func (c *Client) RollupDepositTransfer(fromIdx int64, loadAmountF, amountF common.Float16, tokenID int64, toIdx int64) (tx *types.Transaction, err error) {
|
||||||
c.rw.Lock()
|
c.rw.Lock()
|
||||||
defer c.rw.Unlock()
|
defer c.rw.Unlock()
|
||||||
cpy := c.nextBlock().copy()
|
cpy := c.nextBlock().copy()
|
||||||
@@ -696,7 +695,7 @@ func (c *Client) RollupDepositTransfer(fromIdx int64, loadAmountF, amountF utils
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RollupDeposit is the interface to call the smart contract function
|
// RollupDeposit is the interface to call the smart contract function
|
||||||
func (c *Client) RollupDeposit(fromIdx int64, loadAmountF utils.Float16, tokenID int64) (tx *types.Transaction, err error) {
|
func (c *Client) RollupDeposit(fromIdx int64, loadAmountF common.Float16, tokenID int64) (tx *types.Transaction, err error) {
|
||||||
c.rw.Lock()
|
c.rw.Lock()
|
||||||
defer c.rw.Unlock()
|
defer c.rw.Unlock()
|
||||||
cpy := c.nextBlock().copy()
|
cpy := c.nextBlock().copy()
|
||||||
@@ -707,7 +706,7 @@ func (c *Client) RollupDeposit(fromIdx int64, loadAmountF utils.Float16, tokenID
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RollupCreateAccountDepositFromRelayer is the interface to call the smart contract function
|
// RollupCreateAccountDepositFromRelayer is the interface to call the smart contract function
|
||||||
func (c *Client) RollupCreateAccountDepositFromRelayer(accountCreationAuthSig []byte, babyPubKey babyjub.PublicKey, loadAmountF utils.Float16) (tx *types.Transaction, err error) {
|
func (c *Client) RollupCreateAccountDepositFromRelayer(accountCreationAuthSig []byte, babyPubKey babyjub.PublicKey, loadAmountF common.Float16) (tx *types.Transaction, err error) {
|
||||||
c.rw.Lock()
|
c.rw.Lock()
|
||||||
defer c.rw.Unlock()
|
defer c.rw.Unlock()
|
||||||
cpy := c.nextBlock().copy()
|
cpy := c.nextBlock().copy()
|
||||||
@@ -718,7 +717,7 @@ func (c *Client) RollupCreateAccountDepositFromRelayer(accountCreationAuthSig []
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RollupCreateAccountDeposit is the interface to call the smart contract function
|
// RollupCreateAccountDeposit is the interface to call the smart contract function
|
||||||
func (c *Client) RollupCreateAccountDeposit(babyPubKey babyjub.PublicKey, loadAmountF utils.Float16, tokenID int64) (tx *types.Transaction, err error) {
|
func (c *Client) RollupCreateAccountDeposit(babyPubKey babyjub.PublicKey, loadAmountF common.Float16, tokenID int64) (tx *types.Transaction, err error) {
|
||||||
c.rw.Lock()
|
c.rw.Lock()
|
||||||
defer c.rw.Unlock()
|
defer c.rw.Unlock()
|
||||||
cpy := c.nextBlock().copy()
|
cpy := c.nextBlock().copy()
|
||||||
|
|||||||
Reference in New Issue
Block a user