From 1c54beca5a824ac54c5dcb16580ca184f150b91e Mon Sep 17 00:00:00 2001 From: laisolizq Date: Wed, 7 Oct 2020 12:40:20 +0200 Subject: [PATCH 1/3] Update ethclient rollup iteration 2 --- common/l1tx.go | 18 +++-- common/l1tx_test.go | 75 +++++++++++++++++---- eth/ethereum_test.go | 11 ++- eth/main_test.go | 6 +- eth/rollup.go | 155 +++++++++++++++++++++++++++++++++---------- eth/rollup_test.go | 121 ++++++++++++++++++++++++++++++++- 6 files changed, 320 insertions(+), 66 deletions(-) diff --git a/common/l1tx.go b/common/l1tx.go index 045211f..5997f83 100644 --- a/common/l1tx.go +++ b/common/l1tx.go @@ -158,8 +158,9 @@ func (tx *L1Tx) Tx() *Tx { func (tx *L1Tx) Bytes() ([]byte, error) { var b [L1TxBytesLen]byte copy(b[0:20], tx.FromEthAddr.Bytes()) - pkComp := tx.FromBJJ.Compress() - copy(b[20:52], pkComp[:]) + pkCompL := tx.FromBJJ.Compress() + pkCompB := SwapEndianness(pkCompL[:]) + copy(b[20:52], pkCompB[:]) fromIdxBytes, err := tx.FromIdx.Bytes() if err != nil { return nil, err @@ -193,8 +194,9 @@ func (tx *L1Tx) BytesCoordinatorTx(compressedSignatureBytes []byte) ([]byte, err b[0] = v copy(b[1:33], s) copy(b[33:65], r) - pkComp := tx.FromBJJ.Compress() - copy(b[65:97], pkComp[:]) + pkCompL := tx.FromBJJ.Compress() + pkCompB := SwapEndianness(pkCompL[:]) + copy(b[65:97], pkCompB[:]) copy(b[97:101], tx.TokenID.Bytes()) return b[:], nil } @@ -208,10 +210,13 @@ func L1TxFromBytes(b []byte) (*L1Tx, error) { tx := &L1Tx{} var err error tx.FromEthAddr = ethCommon.BytesToAddress(b[0:20]) + pkCompB := b[20:52] + pkCompL := SwapEndianness(pkCompB) var pkComp babyjub.PublicKeyComp - copy(pkComp[:], pkCompB) + copy(pkComp[:], pkCompL) tx.FromBJJ, err = pkComp.Decompress() + if err != nil { return nil, err } @@ -254,8 +259,9 @@ func L1TxFromCoordinatorBytes(b []byte) (*L1Tx, error) { r := b[33:65] pkCompB := b[65:97] + pkCompL := SwapEndianness(pkCompB) var pkComp babyjub.PublicKeyComp - copy(pkComp[:], pkCompB) + copy(pkComp[:], pkCompL) tx.FromBJJ, err = pkComp.Decompress() if err != nil { return nil, err diff --git a/common/l1tx_test.go b/common/l1tx_test.go index 6d8b63a..767d6b7 100644 --- a/common/l1tx_test.go +++ b/common/l1tx_test.go @@ -53,7 +53,8 @@ func TestNewL1CoordinatorTx(t *testing.T) { func TestL1TxByteParsers(t *testing.T) { var pkComp babyjub.PublicKeyComp - err := pkComp.UnmarshalText([]byte("0x56ca90f80d7c374ae7485e9bcc47d4ac399460948da6aeeb899311097925a72c")) + pkCompL := []byte("0x56ca90f80d7c374ae7485e9bcc47d4ac399460948da6aeeb899311097925a72c") + err := pkComp.UnmarshalText(pkCompL) require.Nil(t, err) pk, err := pkComp.Decompress() @@ -71,17 +72,11 @@ func TestL1TxByteParsers(t *testing.T) { FromEthAddr: ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370"), } - expected, err := utils.HexDecode("c58d29fa6e86e4fae04ddced660d45bcf3cb237056ca90f80d7c374ae7485e9bcc47d4ac399460948da6aeeb899311097925a72c0000000000020002000100000005000000000003") - require.Nil(t, err) - encodedData, err := l1Tx.Bytes() require.Nil(t, err) - assert.Equal(t, expected, encodedData) - decodedData, err := L1TxFromBytes(encodedData) require.Nil(t, err) assert.Equal(t, l1Tx, decodedData) - encodedData2, err := decodedData.Bytes() require.Nil(t, err) assert.Equal(t, encodedData, encodedData2) @@ -95,6 +90,40 @@ func TestL1TxByteParsers(t *testing.T) { require.NotNil(t, err) } +func TestL1TxByteParsersCompatibility(t *testing.T) { + // Data from compatibility test + var pkComp babyjub.PublicKeyComp + pkCompB, err := hex.DecodeString("0dd02deb2c81068e7a0f7e327df80b4ab79ee1f41a7def613e73a20c32eece5a") + require.Nil(t, err) + pkCompL := SwapEndianness(pkCompB) + err = pkComp.UnmarshalText([]byte(hex.EncodeToString(pkCompL))) + require.Nil(t, err) + + pk, err := pkComp.Decompress() + require.Nil(t, err) + + fromIdx := new(Idx) + *fromIdx = 29767899 + loadAmount := new(big.Int) + loadAmount.SetString("100000000000000000000", 10) + l1Tx := &L1Tx{ + ToIdx: 87865485, + TokenID: 2098076, + Amount: big.NewInt(2400000000000000000), + LoadAmount: loadAmount, + FromIdx: fromIdx, + FromBJJ: pk, + FromEthAddr: ethCommon.HexToAddress("0x85dab5b9e2e361d0c208d77be90efcc0439b0a53"), + } + + expected, err := utils.HexDecode("85dab5b9e2e361d0c208d77be90efcc0439b0a530dd02deb2c81068e7a0f7e327df80b4ab79ee1f41a7def613e73a20c32eece5a000001c638db8be880f00020039c0000053cb88d") + require.Nil(t, err) + + encodedData, err := l1Tx.Bytes() + require.Nil(t, err) + assert.Equal(t, expected, encodedData) +} + func TestL1CoordinatorTxByteParsers(t *testing.T) { privateKey, err := crypto.HexToECDSA("fad9c8855b740a0b7ed4c221dbad0f33a83a49cad6b3fe8d5817ac83d38b6a19") require.Nil(t, err) @@ -109,7 +138,8 @@ func TestL1CoordinatorTxByteParsers(t *testing.T) { require.Nil(t, err) fromEthAddr := crypto.PubkeyToAddress(*pubKey) var pkComp babyjub.PublicKeyComp - err = pkComp.UnmarshalText([]byte("0x56ca90f80d7c374ae7485e9bcc47d4ac399460948da6aeeb899311097925a72c")) + pkCompL := []byte("56ca90f80d7c374ae7485e9bcc47d4ac399460948da6aeeb899311097925a72c") + err = pkComp.UnmarshalText(pkCompL) require.Nil(t, err) pk, err := pkComp.Decompress() require.Nil(t, err) @@ -117,10 +147,11 @@ func TestL1CoordinatorTxByteParsers(t *testing.T) { bytesMessage2 := []byte("I authorize this babyjubjub key for hermez rollup account creation") babyjub := pk.Compress() + babyjubB := SwapEndianness(babyjub[:]) var data []byte data = append(data, bytesMessage1...) data = append(data, bytesMessage2...) - data = append(data, babyjub[:]...) + data = append(data, babyjubB[:]...) hash := crypto.Keccak256Hash(data) signature, err := crypto.Sign(hash.Bytes(), privateKey) require.Nil(t, err) @@ -139,9 +170,21 @@ func TestL1CoordinatorTxByteParsers(t *testing.T) { l1txDecoded, err := L1TxFromCoordinatorBytes(bytesCoordinatorL1) require.Nil(t, err) assert.Equal(t, l1Tx, l1txDecoded) + bytesCoordinatorL12, err := l1txDecoded.BytesCoordinatorTx(signature) + require.Nil(t, err) + assert.Equal(t, bytesCoordinatorL1, bytesCoordinatorL12) + + // expect error if length!=68 + _, err = L1TxFromCoordinatorBytes(bytesCoordinatorL1[:66]) + require.NotNil(t, err) + _, err = L1TxFromCoordinatorBytes([]byte{}) + require.NotNil(t, err) + _, err = L1TxFromCoordinatorBytes(nil) + require.NotNil(t, err) } func TestL1CoordinatorTxByteParsersCompatibility(t *testing.T) { + // Data from compatibility test var signature []byte r, err := hex.DecodeString("da71e5eb097e115405d84d1e7b464009b434b32c014a2df502d1f065ced8bc3b") require.Nil(t, err) @@ -155,13 +198,15 @@ func TestL1CoordinatorTxByteParsersCompatibility(t *testing.T) { signature = append(signature, v[:]...) var pkComp babyjub.PublicKeyComp - err = pkComp.UnmarshalText([]byte("0xa2c2807ee39c3b3378738cff85a46a9465bb8fcf44ea597c33da9719be7c259c")) + pkCompB, err := hex.DecodeString("a2c2807ee39c3b3378738cff85a46a9465bb8fcf44ea597c33da9719be7c259c") + require.Nil(t, err) + pkCompL := SwapEndianness(pkCompB) + err = pkComp.UnmarshalText([]byte(hex.EncodeToString(pkCompL))) require.Nil(t, err) // Data from the compatibility test - expected := "1b186d7122ff7f654cfed3156719774898d573900c86599a885a706dbdffe5ea8cda71e5eb097e115405d84d1e7b464009b434b32c014a2df502d1f065ced8bc3ba2c2807ee39c3b3378738cff85a46a9465bb8fcf44ea597c33da9719be7c259c000000e7" + require.Nil(t, err) pk, err := pkComp.Decompress() require.Nil(t, err) - l1Tx := &L1Tx{ TokenID: 231, FromBJJ: pk, @@ -169,5 +214,9 @@ func TestL1CoordinatorTxByteParsersCompatibility(t *testing.T) { encodeData, err := l1Tx.BytesCoordinatorTx(signature) require.Nil(t, err) - assert.Equal(t, expected, hex.EncodeToString(encodeData)) + + expected, err := utils.HexDecode("1b186d7122ff7f654cfed3156719774898d573900c86599a885a706dbdffe5ea8cda71e5eb097e115405d84d1e7b464009b434b32c014a2df502d1f065ced8bc3ba2c2807ee39c3b3378738cff85a46a9465bb8fcf44ea597c33da9719be7c259c000000e7") + require.Nil(t, err) + + assert.Equal(t, expected, encodeData) } diff --git a/eth/ethereum_test.go b/eth/ethereum_test.go index d9db2ff..302fb0b 100644 --- a/eth/ethereum_test.go +++ b/eth/ethereum_test.go @@ -1,24 +1,21 @@ package eth import ( - "os" "testing" - ethCommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestEthERC20(t *testing.T) { - address := ethCommon.HexToAddress("0x44021007485550008e0f9f1f7b506c7d970ad8ce") - ethClient, err := ethclient.Dial(os.Getenv("ETHCLIENT_DIAL_URL")) + ethClient, err := ethclient.Dial(ethClientDialURL) require.Nil(t, err) client := NewEthereumClient(ethClient, accountAux, ks, nil) - consts, err := client.EthERC20Consts(address) + consts, err := client.EthERC20Consts(tokenERC20AddressConst) require.Nil(t, err) - assert.Equal(t, "Golem Network Token", consts.Name) - assert.Equal(t, "GNT", consts.Symbol) + assert.Equal(t, "ERC20_0", consts.Name) + assert.Equal(t, "20_0", consts.Symbol) assert.Equal(t, uint64(18), consts.Decimals) } diff --git a/eth/main_test.go b/eth/main_test.go index d13fe19..041045d 100644 --- a/eth/main_test.go +++ b/eth/main_test.go @@ -133,11 +133,15 @@ func TestMain(m *testing.M) { // Controllable Governance Address ethereumClientGov := NewEthereumClient(ethClient, accountGov, ks, nil) + auctionClient, err = NewAuctionClient(ethereumClientGov, auctionAddressConst, tokenHEZAddressConst) + if err != nil { + panic(err) + } auctionClientTest, err = NewAuctionClient(ethereumClientGov, auctionTestAddressConst, tokenHEZAddressConst) if err != nil { panic(err) } - rollupClient, err = NewRollupClient(ethereumClientGov, hermezRollupAddressConst) + rollupClient, err = NewRollupClient(ethereumClientGov, hermezRollupAddressConst, tokenHEZAddressConst) if err != nil { panic(err) } diff --git a/eth/rollup.go b/eth/rollup.go index e7541dd..06df509 100644 --- a/eth/rollup.go +++ b/eth/rollup.go @@ -2,19 +2,23 @@ package eth import ( "context" + "fmt" "math/big" "strings" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" ethCommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/hermeznetwork/hermez-node/common" + ERC777 "github.com/hermeznetwork/hermez-node/eth/contracts/erc777" Hermez "github.com/hermeznetwork/hermez-node/eth/contracts/hermez" "github.com/hermeznetwork/hermez-node/log" "github.com/iden3/go-iden3-crypto/babyjub" + "golang.org/x/crypto/sha3" ) const ( @@ -249,12 +253,13 @@ func NewRollupEvents() RollupEvents { // RollupForgeBatchArgs are the arguments to the ForgeBatch function in the Rollup Smart Contract //nolint:structcheck,unused type RollupForgeBatchArgs struct { - NewLastIdx int64 - NewStRoot *big.Int - NewExitRoot *big.Int - L1CoordinatorTxs []*common.L1Tx - L2TxsData []*common.L2Tx - FeeIdxCoordinator []common.Idx + NewLastIdx int64 + NewStRoot *big.Int + NewExitRoot *big.Int + L1CoordinatorTxs []*common.L1Tx + L1CoordinatorTxsAuths [][]byte // Authorization for accountCreations for each L1CoordinatorTx + L2TxsData []*common.L2Tx + FeeIdxCoordinator []common.Idx // Circuit selector VerifierIdx uint8 L1Batch bool @@ -266,12 +271,12 @@ type RollupForgeBatchArgs struct { // RollupForgeBatchArgsAux are the arguments to the ForgeBatch function in the Rollup Smart Contract //nolint:structcheck,unused type RollupForgeBatchArgsAux struct { - NewLastIdx uint64 - NewStRoot *big.Int - NewExitRoot *big.Int - L1CoordinatorTxs []byte - L2TxsData []byte - FeeIdxCoordinator []byte + NewLastIdx *big.Int + NewStRoot *big.Int + NewExitRoot *big.Int + EncodedL1CoordinatorTx []byte + L2TxsData []byte + FeeIdxCoordinator []byte // Circuit selector VerifierIdx uint8 L1Batch bool @@ -289,7 +294,7 @@ type RollupInterface interface { // Public Functions RollupForgeBatch(*RollupForgeBatchArgs) (*types.Transaction, error) - RollupAddToken(tokenAddress ethCommon.Address) (*types.Transaction, error) + RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int) (*types.Transaction, error) RollupWithdraw(tokenID int64, balance *big.Int, babyPubKey *babyjub.PublicKey, numExitRoot int64, siblings []*big.Int, idx int64, instantWithdraw bool) (*types.Transaction, error) RollupForceExit(fromIdx int64, amountF common.Float16, tokenID int64) (*types.Transaction, error) @@ -328,34 +333,109 @@ type RollupInterface interface { // RollupClient is the implementation of the interface to the Rollup Smart Contract in ethereum. type RollupClient struct { - client *EthereumClient - address ethCommon.Address - contractAbi abi.ABI + client *EthereumClient + address ethCommon.Address + tokenAddress ethCommon.Address + gasLimit uint64 + contractAbi abi.ABI } // NewRollupClient creates a new RollupClient -func NewRollupClient(client *EthereumClient, address ethCommon.Address) (*RollupClient, error) { +func NewRollupClient(client *EthereumClient, address ethCommon.Address, tokenAddress ethCommon.Address) (*RollupClient, error) { contractAbi, err := abi.JSON(strings.NewReader(string(Hermez.HermezABI))) if err != nil { return nil, err } return &RollupClient{ - client: client, - address: address, - contractAbi: contractAbi, + client: client, + address: address, + tokenAddress: tokenAddress, + gasLimit: 1000000, //nolint:gomnd + contractAbi: contractAbi, }, nil } // RollupForgeBatch is the interface to call the smart contract function func (c *RollupClient) RollupForgeBatch(args *RollupForgeBatchArgs) (*types.Transaction, error) { - log.Error("TODO") - return nil, errTODO + var tx *types.Transaction + var err error + if tx, err = c.client.CallAuth( + c.gasLimit, + func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) { + hermez, err := Hermez.NewHermez(c.address, ec) + if err != nil { + return nil, err + } + rollupConst, err := c.RollupConstants() + if err != nil { + return nil, err + } + nLevels := rollupConst.Verifiers[args.VerifierIdx].NLevels + lenBytes := nLevels / 8 + newLastIdx := big.NewInt(int64(args.NewLastIdx)) + var l1CoordinatorBytes []byte + for i := 0; i < len(args.L1CoordinatorTxs); i++ { + l1 := args.L1CoordinatorTxs[i] + bytesl1, err := l1.BytesCoordinatorTx(args.L1CoordinatorTxsAuths[i]) + if err != nil { + return nil, err + } + l1CoordinatorBytes = append(l1CoordinatorBytes, bytesl1[:]...) + } + var l2DataBytes []byte + for i := 0; i < len(args.L2TxsData); i++ { + l2 := args.L2TxsData[i] + bytesl2, err := l2.Bytes(int(nLevels)) + if err != nil { + return nil, err + } + l2DataBytes = append(l2DataBytes, bytesl2[:]...) + } + var feeIdxCoordinator []byte + for i := 0; i < len(args.FeeIdxCoordinator); i++ { + feeIdx := args.FeeIdxCoordinator[i] + bytesFeeIdx, err := feeIdx.Bytes() + if err != nil { + return nil, err + } + feeIdxCoordinator = append(feeIdxCoordinator, bytesFeeIdx[len(bytesFeeIdx)-int(lenBytes):]...) + } + return hermez.ForgeBatch(auth, newLastIdx, args.NewStRoot, args.NewExitRoot, l1CoordinatorBytes, l2DataBytes, feeIdxCoordinator, args.VerifierIdx, args.L1Batch, args.ProofA, args.ProofB, args.ProofC) + }, + ); err != nil { + return nil, fmt.Errorf("Failed forge batch: %w", err) + } + return tx, nil } // RollupAddToken is the interface to call the smart contract function -func (c *RollupClient) RollupAddToken(tokenAddress ethCommon.Address) (*types.Transaction, error) { - log.Error("TODO") - return nil, errTODO +func (c *RollupClient) RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int) (*types.Transaction, error) { + var tx *types.Transaction + var err error + if tx, err = c.client.CallAuth( + c.gasLimit, + func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) { + tokens, err := ERC777.NewERC777(c.tokenAddress, ec) + if err != nil { + return nil, err + } + addTokenFnSignature := []byte("addToken(address)") + hash := sha3.NewLegacyKeccak256() + _, err = hash.Write(addTokenFnSignature) + if err != nil { + return nil, err + } + methodID := hash.Sum(nil)[:4] + var data []byte + data = append(data, methodID...) + paddedAddress := ethCommon.LeftPadBytes(tokenAddress.Bytes(), 32) + data = append(data, paddedAddress[:]...) + return tokens.Send(auth, c.address, feeAddToken, data) + }, + ); err != nil { + return nil, fmt.Errorf("Failed add Token %w", err) + } + return tx, nil } // RollupWithdrawSNARK is the interface to call the smart contract function @@ -589,31 +669,39 @@ func (c *RollupClient) RollupForgeBatchArgs(ethTxHash ethCommon.Hash) (*RollupFo return nil, err } txData := tx.Data() - method, err := c.contractAbi.MethodById(txData) + method, err := c.contractAbi.MethodById(txData[:4]) if err != nil { return nil, err } var aux RollupForgeBatchArgsAux - if err := method.Inputs.Unpack(&aux, txData); err != nil { + if err := method.Inputs.Unpack(&aux, txData[4:]); err != nil { return nil, err } var rollupForgeBatchArgs RollupForgeBatchArgs rollupForgeBatchArgs.L1Batch = aux.L1Batch rollupForgeBatchArgs.NewExitRoot = aux.NewExitRoot - rollupForgeBatchArgs.NewLastIdx = int64(aux.NewLastIdx) + rollupForgeBatchArgs.NewLastIdx = aux.NewLastIdx.Int64() rollupForgeBatchArgs.NewStRoot = aux.NewStRoot rollupForgeBatchArgs.ProofA = aux.ProofA rollupForgeBatchArgs.ProofB = aux.ProofB rollupForgeBatchArgs.ProofC = aux.ProofC rollupForgeBatchArgs.VerifierIdx = aux.VerifierIdx - - numTxsL1 := len(aux.L1CoordinatorTxs) / common.L1TxBytesLen + numTxsL1 := len(aux.EncodedL1CoordinatorTx) / common.L1CoordinatorTxBytesLen for i := 0; i < numTxsL1; i++ { - l1Tx, err := common.L1TxFromCoordinatorBytes(aux.L1CoordinatorTxs[i*common.L1CoordinatorTxBytesLen : (i+1)*common.L1CoordinatorTxBytesLen]) + bytesL1Coordinator := aux.EncodedL1CoordinatorTx[i*common.L1CoordinatorTxBytesLen : (i+1)*common.L1CoordinatorTxBytesLen] + var signature []byte + v := bytesL1Coordinator[0] + s := bytesL1Coordinator[1:33] + r := bytesL1Coordinator[33:65] + signature = append(signature, r[:]...) + signature = append(signature, s[:]...) + signature = append(signature, v) + l1Tx, err := common.L1TxFromCoordinatorBytes(bytesL1Coordinator) if err != nil { return nil, err } rollupForgeBatchArgs.L1CoordinatorTxs = append(rollupForgeBatchArgs.L1CoordinatorTxs, l1Tx) + rollupForgeBatchArgs.L1CoordinatorTxsAuths = append(rollupForgeBatchArgs.L1CoordinatorTxsAuths, signature) } rollupConsts, err := c.RollupConstants() if err != nil { @@ -646,9 +734,4 @@ func (c *RollupClient) RollupForgeBatchArgs(ethTxHash ethCommon.Hash) (*RollupFo rollupForgeBatchArgs.FeeIdxCoordinator = append(rollupForgeBatchArgs.FeeIdxCoordinator, FeeIdxCoordinator) } return &rollupForgeBatchArgs, nil - // tx := client.TransactionByHash(ethTxHash) -> types.Transaction - // txData := types.Transaction -> Data() - // m := abi.MethodById(txData) -> Method - // m.Inputs.Unpack(txData) -> Args - // client.TransactionReceipt()? } diff --git a/eth/rollup_test.go b/eth/rollup_test.go index 3709443..6920e50 100644 --- a/eth/rollup_test.go +++ b/eth/rollup_test.go @@ -1,18 +1,25 @@ package eth import ( + "encoding/hex" "math/big" "testing" + ethCommon "github.com/ethereum/go-ethereum/common" + "github.com/hermeznetwork/hermez-node/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) var rollupClient *RollupClient +var auctionClient *AuctionClient -var absoluteMaxL1L2BatchTimeout = uint8(240) -var maxTx = big.NewInt(512) -var nLevels = big.NewInt(32) +var ethHashForge ethCommon.Hash +var argsForge *RollupForgeBatchArgs + +var absoluteMaxL1L2BatchTimeout = int64(240) +var maxTx = int64(512) +var nLevels = int64(32) func TestRollupConstants(t *testing.T) { rollupConstants, err := rollupClient.RollupConstants() @@ -26,3 +33,111 @@ func TestRollupConstants(t *testing.T) { assert.Equal(t, safetyAddressConst, rollupConstants.SafetyAddress) assert.Equal(t, wdelayerAddressConst, rollupConstants.WithdrawDelayerContract) } + +func TestAddToken(t *testing.T) { + var feeAddToken = new(big.Int) + feeAddToken = big.NewInt(10) + // Addtoken + _, err := rollupClient.RollupAddToken(tokenERC777AddressConst, feeAddToken) + require.Nil(t, err) +} + +func TestRollupForgeBatch(t *testing.T) { + // Register Coordinator + forgerAddress := governanceAddressConst + _, err := auctionClient.AuctionSetCoordinator(forgerAddress, URL) + require.Nil(t, err) + + // MultiBid + currentSlot, err := auctionClient.AuctionGetCurrentSlotNumber() + require.Nil(t, err) + slotSet := [6]bool{true, false, true, false, true, false} + maxBid := new(big.Int) + maxBid.SetString("15000000000000000000", 10) + minBid := new(big.Int) + minBid.SetString("11000000000000000000", 10) + budget := new(big.Int) + budget.SetString("45200000000000000000", 10) + _, err = auctionClient.AuctionMultiBid(currentSlot+4, currentSlot+10, slotSet, maxBid, minBid, budget) + require.Nil(t, err) + + // Add Blocks + blockNum := int64(int(BLOCKSPERSLOT)*int(currentSlot+4) + genesisBlock) + currentBlockNum, _ := auctionClient.client.EthCurrentBlock() + blocksToAdd := blockNum - currentBlockNum + addBlocks(blocksToAdd, ethClientDialURL) + + // Forge + args := new(RollupForgeBatchArgs) + feeIdxCoordinatorBytes, err := hex.DecodeString("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + require.Nil(t, err) + lenFeeIdxCoordinatorBytes := int(4) + numFeeIdxCoordinator := len(feeIdxCoordinatorBytes) / lenFeeIdxCoordinatorBytes + for i := 0; i < numFeeIdxCoordinator; i++ { + var paddedFeeIdx [6]byte + if lenFeeIdxCoordinatorBytes < common.IdxBytesLen { + copy(paddedFeeIdx[6-lenFeeIdxCoordinatorBytes:], feeIdxCoordinatorBytes[i*lenFeeIdxCoordinatorBytes:(i+1)*lenFeeIdxCoordinatorBytes]) + } else { + copy(paddedFeeIdx[:], feeIdxCoordinatorBytes[i*lenFeeIdxCoordinatorBytes:(i+1)*lenFeeIdxCoordinatorBytes]) + } + FeeIdxCoordinator, err := common.IdxFromBytes(paddedFeeIdx[:]) + require.Nil(t, err) + args.FeeIdxCoordinator = append(args.FeeIdxCoordinator, FeeIdxCoordinator) + } + l1CoordinatorBytes, err := hex.DecodeString("1c660323607bb113e586183609964a333d07ebe4bef3be82ec13af453bae9590bd7711cdb6abf42f176eadfbe5506fbef5e092e5543733f91b0061d9a7747fa10694a915a6470fa230de387b51e6f4db0b09787867778687b55197ad6d6a86eac000000001") + require.Nil(t, err) + numTxsL1 := len(l1CoordinatorBytes) / common.L1CoordinatorTxBytesLen + for i := 0; i < numTxsL1; i++ { + bytesL1Coordinator := l1CoordinatorBytes[i*common.L1CoordinatorTxBytesLen : (i+1)*common.L1CoordinatorTxBytesLen] + var signature []byte + v := bytesL1Coordinator[0] + s := bytesL1Coordinator[1:33] + r := bytesL1Coordinator[33:65] + signature = append(signature, r[:]...) + signature = append(signature, s[:]...) + signature = append(signature, v) + L1Tx, err := common.L1TxFromCoordinatorBytes(bytesL1Coordinator) + require.Nil(t, err) + args.L1CoordinatorTxs = append(args.L1CoordinatorTxs, L1Tx) + args.L1CoordinatorTxsAuths = append(args.L1CoordinatorTxsAuths, signature) + } + newStateRoot := new(big.Int) + newStateRoot.SetString("18317824016047294649053625209337295956588174734569560016974612130063629505228", 10) + newExitRoot := big.NewInt(0) + args.NewLastIdx = int64(256) + args.NewStRoot = newStateRoot + args.NewExitRoot = newExitRoot + args.L1Batch = true + args.VerifierIdx = 0 + args.ProofA[0] = big.NewInt(0) + args.ProofA[1] = big.NewInt(0) + args.ProofB[0][0] = big.NewInt(0) + args.ProofB[0][1] = big.NewInt(0) + args.ProofB[1][0] = big.NewInt(0) + args.ProofB[1][1] = big.NewInt(0) + args.ProofC[0] = big.NewInt(0) + args.ProofC[1] = big.NewInt(0) + + argsForge = args + _, err = rollupClient.RollupForgeBatch(argsForge) + require.Nil(t, err) + + currentBlockNum, _ = rollupClient.client.EthCurrentBlock() + rollupEvents, _, _ := rollupClient.RollupEventsByBlock(currentBlockNum) + + assert.Equal(t, int64(1), rollupEvents.ForgeBatch[0].BatchNum) + ethHashForge = rollupEvents.ForgeBatch[0].EthTxHash +} + +func TestRollupForgeBatchArgs(t *testing.T) { + args, err := rollupClient.RollupForgeBatchArgs(ethHashForge) + require.Nil(t, err) + assert.Equal(t, argsForge.FeeIdxCoordinator, args.FeeIdxCoordinator) + assert.Equal(t, argsForge.L1Batch, args.L1Batch) + assert.Equal(t, argsForge.L1CoordinatorTxs, args.L1CoordinatorTxs) + assert.Equal(t, argsForge.L1CoordinatorTxsAuths, args.L1CoordinatorTxsAuths) + assert.Equal(t, argsForge.L2TxsData, args.L2TxsData) + assert.Equal(t, argsForge.NewLastIdx, args.NewLastIdx) + assert.Equal(t, argsForge.NewStRoot, args.NewStRoot) + assert.Equal(t, argsForge.VerifierIdx, args.VerifierIdx) +} From cbc46db6dace9c431abf0709bc781f739f4414a5 Mon Sep 17 00:00:00 2001 From: Eduard S Date: Thu, 8 Oct 2020 13:18:06 +0200 Subject: [PATCH 2/3] Update test ethclient, rename rollup var --- eth/rollup.go | 30 ++++++++++++++++-------------- eth/rollup_test.go | 3 +-- synchronizer/synchronizer_test.go | 3 ++- test/ethclient.go | 5 ++++- test/ethclient_test.go | 2 +- 5 files changed, 24 insertions(+), 19 deletions(-) diff --git a/eth/rollup.go b/eth/rollup.go index 06df509..fcd4b1c 100644 --- a/eth/rollup.go +++ b/eth/rollup.go @@ -333,25 +333,25 @@ type RollupInterface interface { // RollupClient is the implementation of the interface to the Rollup Smart Contract in ethereum. type RollupClient struct { - client *EthereumClient - address ethCommon.Address - tokenAddress ethCommon.Address - gasLimit uint64 - contractAbi abi.ABI + client *EthereumClient + address ethCommon.Address + tokenHEZAddress ethCommon.Address + gasLimit uint64 + contractAbi abi.ABI } // NewRollupClient creates a new RollupClient -func NewRollupClient(client *EthereumClient, address ethCommon.Address, tokenAddress ethCommon.Address) (*RollupClient, error) { +func NewRollupClient(client *EthereumClient, address ethCommon.Address, tokenHEZAddress ethCommon.Address) (*RollupClient, error) { contractAbi, err := abi.JSON(strings.NewReader(string(Hermez.HermezABI))) if err != nil { return nil, err } return &RollupClient{ - client: client, - address: address, - tokenAddress: tokenAddress, - gasLimit: 1000000, //nolint:gomnd - contractAbi: contractAbi, + client: client, + address: address, + tokenHEZAddress: tokenHEZAddress, + gasLimit: 1000000, //nolint:gomnd + contractAbi: contractAbi, }, nil } @@ -371,7 +371,7 @@ func (c *RollupClient) RollupForgeBatch(args *RollupForgeBatchArgs) (*types.Tran return nil, err } nLevels := rollupConst.Verifiers[args.VerifierIdx].NLevels - lenBytes := nLevels / 8 + lenBytes := nLevels / 8 //nolint:gomnd newLastIdx := big.NewInt(int64(args.NewLastIdx)) var l1CoordinatorBytes []byte for i := 0; i < len(args.L1CoordinatorTxs); i++ { @@ -408,14 +408,16 @@ func (c *RollupClient) RollupForgeBatch(args *RollupForgeBatchArgs) (*types.Tran return tx, nil } -// RollupAddToken is the interface to call the smart contract function +// RollupAddToken is the interface to call the smart contract function. +// `feeAddToken` is the amount of HEZ tokens that will be paid to add the +// token. `feeAddToken` must match the public value of the smart contract. func (c *RollupClient) RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int) (*types.Transaction, error) { var tx *types.Transaction var err error if tx, err = c.client.CallAuth( c.gasLimit, func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) { - tokens, err := ERC777.NewERC777(c.tokenAddress, ec) + tokens, err := ERC777.NewERC777(c.tokenHEZAddress, ec) if err != nil { return nil, err } diff --git a/eth/rollup_test.go b/eth/rollup_test.go index 6920e50..f7725fe 100644 --- a/eth/rollup_test.go +++ b/eth/rollup_test.go @@ -35,8 +35,7 @@ func TestRollupConstants(t *testing.T) { } func TestAddToken(t *testing.T) { - var feeAddToken = new(big.Int) - feeAddToken = big.NewInt(10) + feeAddToken := big.NewInt(10) // Addtoken _, err := rollupClient.RollupAddToken(tokenERC777AddressConst, feeAddToken) require.Nil(t, err) diff --git a/synchronizer/synchronizer_test.go b/synchronizer/synchronizer_test.go index db6b8eb..ad277f8 100644 --- a/synchronizer/synchronizer_test.go +++ b/synchronizer/synchronizer_test.go @@ -74,7 +74,8 @@ D (3): 15 // require.Greater(t, len(tokens), 0) for i := 1; i <= 3; i++ { - _, err := client.RollupAddToken(ethCommon.BigToAddress(big.NewInt(int64(i * 10000)))) + _, err := client.RollupAddToken(ethCommon.BigToAddress(big.NewInt(int64(i*10000))), + clientSetup.RollupVariables.FeeAddToken) require.Nil(t, err) } diff --git a/test/ethclient.go b/test/ethclient.go index 3c32d0f..47181ef 100644 --- a/test/ethclient.go +++ b/test/ethclient.go @@ -690,7 +690,7 @@ func (c *Client) addBatch(args *eth.RollupForgeBatchArgs) (*types.Transaction, e } // RollupAddToken is the interface to call the smart contract function -func (c *Client) RollupAddToken(tokenAddress ethCommon.Address) (tx *types.Transaction, err error) { +func (c *Client) RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int) (tx *types.Transaction, err error) { c.rw.Lock() defer c.rw.Unlock() cpy := c.nextBlock().copy() @@ -704,6 +704,9 @@ func (c *Client) RollupAddToken(tokenAddress ethCommon.Address) (tx *types.Trans if _, ok := r.State.TokenMap[tokenAddress]; ok { return nil, fmt.Errorf("Token %v already registered", tokenAddress) } + if feeAddToken.Cmp(r.Vars.FeeAddToken) != 0 { + return nil, fmt.Errorf("Expected fee: %v but got: %v", r.Vars.FeeAddToken, feeAddToken) + } r.State.TokenMap[tokenAddress] = true r.State.TokenList = append(r.State.TokenList, tokenAddress) diff --git a/test/ethclient_test.go b/test/ethclient_test.go index 66b9a78..a55c5d9 100644 --- a/test/ethclient_test.go +++ b/test/ethclient_test.go @@ -143,7 +143,7 @@ func TestClientRollup(t *testing.T) { // Add a token - tx, err := c.RollupAddToken(token1Addr) + tx, err := c.RollupAddToken(token1Addr, clientSetup.RollupVariables.FeeAddToken) require.Nil(t, err) assert.NotNil(t, tx) From d1002721f7669a71438568ca9ea1b38b7038b699 Mon Sep 17 00:00:00 2001 From: Eduard S Date: Thu, 8 Oct 2020 16:40:12 +0200 Subject: [PATCH 3/3] Remove nolints --- eth/auction.go | 2 +- eth/rollup.go | 6 +----- eth/wdelayer.go | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/eth/auction.go b/eth/auction.go index 8f9d447..714028c 100644 --- a/eth/auction.go +++ b/eth/auction.go @@ -168,7 +168,7 @@ type AuctionEventHEZClaimed struct { } // AuctionEvents is the list of events in a block of the Auction Smart Contract -type AuctionEvents struct { //nolint:structcheck +type AuctionEvents struct { NewBid []AuctionEventNewBid NewSlotDeadline []AuctionEventNewSlotDeadline NewClosedAuctionSlots []AuctionEventNewClosedAuctionSlots diff --git a/eth/rollup.go b/eth/rollup.go index fcd4b1c..9694c77 100644 --- a/eth/rollup.go +++ b/eth/rollup.go @@ -150,7 +150,6 @@ type RollupVariables struct { } // QueueStruct is the queue of L1Txs for a batch -//nolint:structcheck type QueueStruct struct { L1TxQueue []common.L1Tx TotalL1TxFee *big.Int @@ -171,7 +170,6 @@ type RollupVerifierStruct struct { } // RollupState represents the state of the Rollup in the Smart Contract -//nolint:structcheck,unused type RollupState struct { StateRoot *big.Int ExitRoots []*big.Int @@ -229,7 +227,7 @@ type RollupEventWithdrawEvent struct { } // RollupEvents is the list of events in a block of the Rollup Smart Contract -type RollupEvents struct { //nolint:structcheck +type RollupEvents struct { L1UserTx []RollupEventL1UserTx AddToken []RollupEventAddToken ForgeBatch []RollupEventForgeBatch @@ -251,7 +249,6 @@ func NewRollupEvents() RollupEvents { } // RollupForgeBatchArgs are the arguments to the ForgeBatch function in the Rollup Smart Contract -//nolint:structcheck,unused type RollupForgeBatchArgs struct { NewLastIdx int64 NewStRoot *big.Int @@ -269,7 +266,6 @@ type RollupForgeBatchArgs struct { } // RollupForgeBatchArgsAux are the arguments to the ForgeBatch function in the Rollup Smart Contract -//nolint:structcheck,unused type RollupForgeBatchArgsAux struct { NewLastIdx *big.Int NewStRoot *big.Int diff --git a/eth/wdelayer.go b/eth/wdelayer.go index 2865ab2..c032b23 100644 --- a/eth/wdelayer.go +++ b/eth/wdelayer.go @@ -80,7 +80,7 @@ type WDelayerEventNewHermezGovernanceDAOAddress struct { } // WDelayerEvents is the lis of events in a block of the WithdrawalDelayer Smart Contract -type WDelayerEvents struct { //nolint:structcheck +type WDelayerEvents struct { Deposit []WDelayerEventDeposit Withdraw []WDelayerEventWithdraw EmergencyModeEnabled []WDelayerEventEmergencyModeEnabled