Browse Source

Merge pull request #128 from hermeznetwork/feature/l1txbytes

Update common.L1Tx parsers, add test checks
feature/sql-semaphore1
Eduard S 4 years ago
committed by GitHub
parent
commit
05b273cc00
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 177 additions and 150 deletions
  1. +11
    -5
      common/account.go
  2. +1
    -1
      common/account_test.go
  3. +12
    -6
      common/float16.go
  4. +1
    -1
      common/float16_test.go
  5. +42
    -56
      common/l1tx.go
  6. +15
    -4
      common/l1tx_test.go
  7. +49
    -50
      common/pooll2tx.go
  8. +11
    -3
      common/pooll2tx_test.go
  9. +14
    -1
      common/token.go
  10. +14
    -15
      eth/rollup.go
  11. +7
    -8
      test/ethclient.go

+ 11
- 5
common/account.go

@ -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)

+ 1
- 1
common/account_test.go

@ -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) {

utils/utils.go → common/float16.go

@ -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
// of loss during the encoding.
// NewFloat16 encodes a *big.Int integer as a Float16, returning error in
// 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()

utils/utils_test.go → common/float16_test.go

@ -1,4 +1,4 @@
package utils
package common
import ( import (
"math/big" "math/big"

+ 42
- 56
common/l1tx.go

@ -1,6 +1,7 @@
package common package common
import ( import (
"fmt"
"math/big" "math/big"
ethCommon "github.com/ethereum/go-ethereum/common" ethCommon "github.com/ethereum/go-ethereum/common"
@ -8,11 +9,8 @@ import (
) )
const ( const (
fromBJJCompressedB = 256
fromEthAddrB = 160
f16B = 16
tokenIDB = 32
cidXB = 32
// L1TxBytesLen is the length of the byte array that represents the L1Tx
L1TxBytesLen = 68
) )
// L1Tx is a struct that represents a L1 tx // L1Tx is a struct that represents a L1 tx
@ -64,69 +62,57 @@ func (tx *L1Tx) Tx() *Tx {
} }
// Bytes encodes a L1Tx into []byte // Bytes encodes a L1Tx into []byte
func (tx *L1Tx) Bytes(nLevels int) []byte {
res := big.NewInt(0)
res = res.Add(res, big.NewInt(0).Or(big.NewInt(0), tx.ToIdx.BigInt()))
res = res.Add(res, big.NewInt(0).Lsh(big.NewInt(0).Or(big.NewInt(0), big.NewInt(int64(tx.TokenID))), uint(nLevels)))
res = res.Add(res, big.NewInt(0).Lsh(big.NewInt(0).Or(big.NewInt(0), tx.Amount), uint(nLevels+tokenIDB)))
res = res.Add(res, big.NewInt(0).Lsh(big.NewInt(0).Or(big.NewInt(0), tx.LoadAmount), uint(nLevels+tokenIDB+f16B)))
res = res.Add(res, big.NewInt(0).Lsh(big.NewInt(0).Or(big.NewInt(0), tx.FromIdx.BigInt()), uint(nLevels+tokenIDB+2*f16B)))
fromBJJ := big.NewInt(0)
fromBJJ.SetString(tx.FromBJJ.String(), 16)
fromBJJCompressed := big.NewInt(0).Or(big.NewInt(0), fromBJJ)
res = res.Add(res, big.NewInt(0).Lsh(fromBJJCompressed, uint(2*nLevels+tokenIDB+2*f16B)))
fromEthAddr := big.NewInt(0).Or(big.NewInt(0), tx.FromEthAddr.Hash().Big())
res = res.Add(res, big.NewInt(0).Lsh(fromEthAddr, uint(fromBJJCompressedB+2*nLevels+tokenIDB+2*f16B)))
return res.Bytes()
func (tx *L1Tx) Bytes(nLevels int) ([]byte, error) {
var b [68]byte
copy(b[0:20], tx.FromEthAddr.Bytes())
pkComp := tx.FromBJJ.Compress()
copy(b[20:52], pkComp[:])
copy(b[52:56], tx.FromIdx.Bytes())
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(l1TxEncoded []byte) (*L1Tx, error) {
l1Tx := &L1Tx{}
var idxB uint = cidXB
l1TxEncodedBI := big.NewInt(0)
l1TxEncodedBI.SetBytes(l1TxEncoded)
toIdx, err := IdxFromBigInt(extract(l1TxEncodedBI, 0, idxB))
func L1TxFromBytes(b []byte) (*L1Tx, error) {
if len(b) != L1TxBytesLen {
return nil, fmt.Errorf("Can not parse L1Tx bytes, expected length %d, current: %d", 68, len(b))
}
tx := &L1Tx{}
var err error
tx.FromEthAddr = ethCommon.BytesToAddress(b[0:20])
pkCompB := b[20:52]
var pkComp babyjub.PublicKeyComp
copy(pkComp[:], pkCompB)
tx.FromBJJ, err = pkComp.Decompress()
if err != nil { if err != nil {
return nil, err return nil, err
} }
l1Tx.ToIdx = toIdx
l1Tx.TokenID = TokenID(extract(l1TxEncodedBI, idxB, tokenIDB).Uint64())
l1Tx.Amount = extract(l1TxEncodedBI, idxB+tokenIDB, f16B)
l1Tx.LoadAmount = extract(l1TxEncodedBI, idxB+tokenIDB+f16B, f16B)
fromIdx, err := IdxFromBigInt(extract(l1TxEncodedBI, idxB+tokenIDB+2*f16B, f16B))
tx.FromIdx, err = IdxFromBytes(b[52:56])
if err != nil { if err != nil {
return nil, err return nil, err
} }
l1Tx.FromIdx = fromIdx
var pkComp babyjub.PublicKeyComp
copy(pkComp[:], extract(l1TxEncodedBI, 2*idxB+tokenIDB+2*f16B, fromBJJCompressedB).Bytes())
pk, err := pkComp.Decompress()
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 { if err != nil {
return nil, err return nil, err
} }
l1Tx.FromBJJ = pk
l1Tx.FromEthAddr = ethCommon.BigToAddress(extract(l1TxEncodedBI, fromBJJCompressedB+2*idxB+tokenIDB+2*f16B, fromEthAddrB))
return l1Tx, nil
}
// extract masks and shifts a bigInt
func extract(num *big.Int, origin uint, len uint) *big.Int {
mask := big.NewInt(0).Sub(big.NewInt(0).Lsh(big.NewInt(1), len), big.NewInt(1))
return big.NewInt(0).And(big.NewInt(0).Rsh(num, origin), mask)
return tx, nil
} }

+ 15
- 4
common/l1tx_test.go

@ -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),
@ -32,12 +32,23 @@ func TestL1TxCodec(t *testing.T) {
expected, err := utils.HexDecode("c58d29fa6e86e4fae04ddced660d45bcf3cb237056ca90f80d7c374ae7485e9bcc47d4ac399460948da6aeeb899311097925a72c00000002000200010000000500000003") expected, err := utils.HexDecode("c58d29fa6e86e4fae04ddced660d45bcf3cb237056ca90f80d7c374ae7485e9bcc47d4ac399460948da6aeeb899311097925a72c00000002000200010000000500000003")
require.Nil(t, err) require.Nil(t, err)
encodedData := l1Tx.Bytes(32)
encodedData, err := l1Tx.Bytes(32)
require.Nil(t, err)
assert.Equal(t, expected, encodedData) assert.Equal(t, expected, encodedData)
decodedData, err := L1TxFromBytes(encodedData) decodedData, err := L1TxFromBytes(encodedData)
require.Nil(t, err) require.Nil(t, err)
assert.Equal(t, l1Tx, decodedData)
encodedData2 := decodedData.Bytes(32)
encodedData2, err := decodedData.Bytes(32)
require.Nil(t, err)
assert.Equal(t, encodedData, encodedData2) assert.Equal(t, encodedData, encodedData2)
// expect error if length!=68
_, err = L1TxFromBytes(encodedData[:66])
require.NotNil(t, err)
_, err = L1TxFromBytes([]byte{})
require.NotNil(t, err)
_, err = L1TxFromBytes(nil)
require.NotNil(t, err)
} }

+ 49
- 50
common/pooll2tx.go

@ -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])
nonce := binary.LittleEndian.Uint64(nonceBytes[:])
copy(nonceBytes[3:], b[:])
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]
// [ 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]
// [ 1 bits ] toBJJSign // 1 byte
// [ 8 bits ] userFee // 1 byte
// [ 40 bits ] nonce // 5 bytes
// [ 32 bits ] tokenID // 4 bytes
// [ 16 bits ] amountFloat16 // 2 bytes
// [ 48 bits ] toIdx // 6 bytes
// [ 48 bits ] fromIdx // 6 bytes
// [ 16 bits ] chainId // 2 bytes
// [ 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
bi := new(big.Int).SetBytes(SwapEndianness(b[:]))
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())
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]
// [ 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]
// [ 1 bits ] toBJJSign // 1 byte
// [ 8 bits ] userFee // 1 byte
// [ 40 bits ] nonce // 5 bytes
// [ 32 bits ] tokenID // 4 bytes
// [ 16 bits ] amountFloat16 // 2 bytes
// [ 48 bits ] toIdx // 6 bytes
// [ 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
} }

+ 11
- 3
common/pooll2tx_test.go

@ -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:])
} }

+ 14
- 1
common/token.go

@ -2,12 +2,16 @@ package common
import ( import (
"encoding/binary" "encoding/binary"
"fmt"
"math/big" "math/big"
"time" "time"
ethCommon "github.com/ethereum/go-ethereum/common" ethCommon "github.com/ethereum/go-ethereum/common"
) )
// tokenIDBytesLen defines the length of the TokenID byte array representation
const tokenIDBytesLen = 4
// Token is a struct that represents an Ethereum token that is supported in Hermez network // Token is a struct that represents an Ethereum token that is supported in Hermez network
type Token struct { type Token struct {
TokenID TokenID `meddler:"token_id"` TokenID TokenID `meddler:"token_id"`
@ -33,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[:]
} }
@ -41,3 +45,12 @@ func (t TokenID) Bytes() []byte {
func (t TokenID) BigInt() *big.Int { func (t TokenID) BigInt() *big.Int {
return big.NewInt(int64(t)) return big.NewInt(int64(t))
} }
// TokenIDFromBytes returns TokenID from a byte array
func TokenIDFromBytes(b []byte) (TokenID, error) {
if len(b) != tokenIDBytesLen {
return 0, fmt.Errorf("can not parse TokenID, bytes len %d, expected 4", len(b))
}
tid := binary.BigEndian.Uint32(b[:4])
return TokenID(tid), nil
}

+ 14
- 15
eth/rollup.go

@ -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)
RollupForceTransfer(fromIdx int64, amountF utils.Float16, tokenID, toIdx int64) (*types.Transaction, error)
RollupForceExit(fromIdx int64, amountF common.Float16, tokenID 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)
RollupDepositTransfer(fromIdx int64, loadAmountF, amountF utils.Float16,
loadAmountF, amountF common.Float16, tokenID int64, toIdx int64) (*types.Transaction, error)
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)
RollupCreateAccountDeposit(babyPubKey babyjub.PublicKey, loadAmountF utils.Float16,
babyPubKey babyjub.PublicKey, loadAmountF common.Float16) (*types.Transaction, error)
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
} }

+ 7
- 8
test/ethclient.go

@ -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()

Loading…
Cancel
Save