Browse Source

Add reverts, forge in test ethClient, update auction

feature/sql-semaphore1
Eduard S 3 years ago
parent
commit
852cd762d3
11 changed files with 577 additions and 240 deletions
  1. +18
    -12
      config/config.go
  2. +31
    -31
      coordinator/batch.go
  3. +25
    -25
      coordinator/batch_test.go
  4. +28
    -21
      coordinator/coordinator.go
  5. +3
    -1
      coordinator/coordinator_test.go
  6. +36
    -10
      coordinator/proofpool.go
  7. +100
    -62
      eth/auction.go
  8. +21
    -0
      eth/rollup.go
  9. +11
    -6
      node/node.go
  10. +292
    -67
      test/ethclient.go
  11. +12
    -5
      test/ethclient_test.go

+ 18
- 12
config/config.go

@ -25,10 +25,28 @@ func (d *Duration) UnmarshalText(data []byte) error {
return nil
}
// ServerProof is the server proof configuration data.
type ServerProof struct {
URL string `validate:"required"`
}
// Coordinator is the coordinator specific configuration.
type Coordinator struct {
ForgerAddress ethCommon.Address `validate:"required"`
ForgeLoopInterval Duration `validate:"required"`
L2DB struct {
Name string `validate:"required"`
SafetyPeriod uint16 `validate:"required"`
MaxTxs uint32 `validate:"required"`
TTL Duration `validate:"required"`
} `validate:"required"`
TxSelector struct {
Path string `validate:"required"`
} `validate:"required"`
BatchBuilder struct {
Path string `validate:"required"`
} `validate:"required"`
ServerProofs []ServerProof `validate:"required"`
}
// Node is the hermez node configuration.
@ -42,24 +60,12 @@ type Node struct {
User string `validate:"required"`
Password string `validate:"required"`
} `validate:"required"`
L2DB struct {
Name string `validate:"required"`
SafetyPeriod uint16 `validate:"required"`
MaxTxs uint32 `validate:"required"`
TTL Duration `validate:"required"`
} `validate:"required"`
HistoryDB struct {
Name string `validate:"required"`
} `validate:"required"`
Web3 struct {
URL string `validate:"required"`
} `validate:"required"`
TxSelector struct {
Path string `validate:"required"`
} `validate:"required"`
BatchBuilder struct {
Path string `validate:"required"`
} `validate:"required"`
Synchronizer struct {
SyncLoopInterval Duration `validate:"required"`
} `validate:"required"`

+ 31
- 31
coordinator/batch.go

@ -11,7 +11,7 @@ type Proof struct {
// BatchInfo contans the Batch information
type BatchInfo struct {
batchNum common.BatchNum
serverProof *ServerProofInfo
serverProof ServerProofInterface
zkInputs *common.ZKInputs
proof *Proof
L1UserTxsExtra []*common.L1Tx
@ -21,8 +21,8 @@ type BatchInfo struct {
}
// NewBatchInfo creates a new BatchInfo with the given batchNum &
// ServerProofInfo
func NewBatchInfo(batchNum common.BatchNum, serverProof *ServerProofInfo) BatchInfo {
// ServerProof
func NewBatchInfo(batchNum common.BatchNum, serverProof ServerProofInterface) BatchInfo {
return BatchInfo{
batchNum: batchNum,
serverProof: serverProof,
@ -43,8 +43,8 @@ func (bi *BatchInfo) SetZKInputs(zkInputs *common.ZKInputs) {
bi.zkInputs = zkInputs
}
// SetServerProof sets the ServerProofInfo to the BatchInfo data structure
func (bi *BatchInfo) SetServerProof(serverProof *ServerProofInfo) {
// SetServerProof sets the ServerProof to the BatchInfo data structure
func (bi *BatchInfo) SetServerProof(serverProof ServerProofInterface) {
bi.serverProof = serverProof
}
@ -53,29 +53,29 @@ func (bi *BatchInfo) SetProof(proof *Proof) {
bi.proof = proof
}
// BatchQueue implements a FIFO queue of BatchInfo
type BatchQueue struct {
queue []*BatchInfo
}
// NewBatchQueue returns a new *BatchQueue
func NewBatchQueue() *BatchQueue {
return &BatchQueue{
queue: []*BatchInfo{},
}
}
// Push adds the given BatchInfo to the BatchQueue
func (bq *BatchQueue) Push(b *BatchInfo) {
bq.queue = append(bq.queue, b)
}
// Pop pops the first BatchInfo from the BatchQueue
func (bq *BatchQueue) Pop() *BatchInfo {
if len(bq.queue) == 0 {
return nil
}
b := bq.queue[0]
bq.queue = bq.queue[1:]
return b
}
// // BatchQueue implements a FIFO queue of BatchInfo
// type BatchQueue struct {
// queue []*BatchInfo
// }
//
// // NewBatchQueue returns a new *BatchQueue
// func NewBatchQueue() *BatchQueue {
// return &BatchQueue{
// queue: []*BatchInfo{},
// }
// }
//
// // Push adds the given BatchInfo to the BatchQueue
// func (bq *BatchQueue) Push(b *BatchInfo) {
// bq.queue = append(bq.queue, b)
// }
//
// // Pop pops the first BatchInfo from the BatchQueue
// func (bq *BatchQueue) Pop() *BatchInfo {
// if len(bq.queue) == 0 {
// return nil
// }
// b := bq.queue[0]
// bq.queue = bq.queue[1:]
// return b
// }

+ 25
- 25
coordinator/batch_test.go

@ -1,27 +1,27 @@
package coordinator
import (
"testing"
"github.com/hermeznetwork/hermez-node/common"
"github.com/stretchr/testify/assert"
)
func TestBatchQueue(t *testing.T) {
bq := BatchQueue{}
bq.Push(&BatchInfo{
batchNum: 0,
})
bq.Push(&BatchInfo{
batchNum: 2,
})
bq.Push(&BatchInfo{
batchNum: 1,
})
assert.Equal(t, common.BatchNum(0), bq.Pop().batchNum)
assert.Equal(t, common.BatchNum(2), bq.Pop().batchNum)
assert.Equal(t, common.BatchNum(1), bq.Pop().batchNum)
assert.Nil(t, bq.Pop())
}
// import (
// "testing"
//
// "github.com/hermeznetwork/hermez-node/common"
// "github.com/stretchr/testify/assert"
// )
//
// func TestBatchQueue(t *testing.T) {
// bq := BatchQueue{}
//
// bq.Push(&BatchInfo{
// batchNum: 0,
// })
// bq.Push(&BatchInfo{
// batchNum: 2,
// })
// bq.Push(&BatchInfo{
// batchNum: 1,
// })
//
// assert.Equal(t, common.BatchNum(0), bq.Pop().batchNum)
// assert.Equal(t, common.BatchNum(2), bq.Pop().batchNum)
// assert.Equal(t, common.BatchNum(1), bq.Pop().batchNum)
// assert.Nil(t, bq.Pop())
// }

+ 28
- 21
coordinator/coordinator.go

@ -31,7 +31,7 @@ type Coordinator struct {
config Config
batchNum common.BatchNum
serverProofPool ServerProofPool
serverProofPool *ServerProofPool
// synchronizer *synchronizer.Synchronizer
hdb *historydb.HistoryDB
@ -47,14 +47,20 @@ func NewCoordinator(conf Config,
hdb *historydb.HistoryDB,
txsel *txselector.TxSelector,
bb *batchbuilder.BatchBuilder,
serverProofs []ServerProofInterface,
ethClient *eth.Client) *Coordinator { // once synchronizer is ready, synchronizer.Synchronizer will be passed as parameter here
serverProofPool := NewServerProofPool(len(serverProofs))
for _, serverProof := range serverProofs {
serverProofPool.Add(serverProof)
}
c := Coordinator{
config: conf,
hdb: hdb,
txsel: txsel,
batchBuilder: bb,
ethClient: ethClient,
ethTxStore: memory.NewMemoryStorage(),
config: conf,
serverProofPool: serverProofPool,
hdb: hdb,
txsel: txsel,
batchBuilder: bb,
ethClient: ethClient,
ethTxStore: memory.NewMemoryStorage(),
}
return &c
}
@ -97,13 +103,14 @@ func (c *Coordinator) ForgeLoopFn(outBatchCh chan *BatchInfo, stopCh chan bool)
// 0. If there's an available server proof: Start pipeline for batchNum = batchNum + 1.
// non-blocking call, returns nil if a server proof is
// not available, or non-nil otherwise.
serverProofInfo, err := c.serverProofPool.GetNextAvailable(stopCh)
serverProof, err := c.serverProofPool.Get(stopCh)
if err != nil {
return true, err
}
log.Debugw("got serverProof", "server", serverProof)
log.Debugw("start forge")
batchInfo, err := c.forge(serverProofInfo)
batchInfo, err := c.forge(serverProof)
if err != nil {
log.Errorw("forge", "error", err)
return true, err
@ -123,7 +130,7 @@ func (c *Coordinator) GetProofCallForgeLoopFn(inBatchCh, outBatchCh chan *BatchI
return ErrStop
case batchInfo := <-inBatchCh:
log.Debugw("start getProofCallForge", "batchNum", batchInfo.batchNum)
if err := c.getProofCallForge(batchInfo); err != nil {
if err := c.getProofCallForge(batchInfo, stopCh); err != nil {
return err
}
log.Debugw("end getProofCallForge", "batchNum", batchInfo.batchNum)
@ -150,7 +157,7 @@ func (c *Coordinator) ForgeCallConfirmLoopFn(inBatchCh chan *BatchInfo, stopCh c
return nil
}
func (c *Coordinator) forge(serverProofInfo *ServerProofInfo) (*BatchInfo, error) {
func (c *Coordinator) forge(serverProof ServerProofInterface) (*BatchInfo, error) {
// remove transactions from the pool that have been there for too long
err := c.purgeRemoveByTimeout()
if err != nil {
@ -158,7 +165,7 @@ func (c *Coordinator) forge(serverProofInfo *ServerProofInfo) (*BatchInfo, error
}
c.batchNum = c.batchNum + 1
batchInfo := NewBatchInfo(c.batchNum, serverProofInfo) // to accumulate metadata of the batch
batchInfo := NewBatchInfo(c.batchNum, serverProof) // to accumulate metadata of the batch
var poolL2Txs []*common.PoolL2Tx
// var feesInfo
@ -216,9 +223,9 @@ func (c *Coordinator) forge(serverProofInfo *ServerProofInfo) (*BatchInfo, error
}
// getProofCallForge gets the generated zkProof & sends it to the SmartContract
func (c *Coordinator) getProofCallForge(batchInfo *BatchInfo) error {
serverProofInfo := batchInfo.serverProof
proof, err := serverProofInfo.GetProof() // blocking call, until not resolved don't continue. Returns when the proof server has calculated the proof
func (c *Coordinator) getProofCallForge(batchInfo *BatchInfo, stopCh chan bool) error {
serverProof := batchInfo.serverProof
proof, err := serverProof.GetProof(stopCh) // blocking call, until not resolved don't continue. Returns when the proof server has calculated the proof
if err != nil {
return err
}
@ -254,26 +261,26 @@ func (c *Coordinator) forgeCallConfirm(batchInfo *BatchInfo) error {
}
func (c *Coordinator) handleReorg() error {
return nil
return nil // TODO
}
// isForgeSequence returns true if the node is the Forger in the current ethereum block
func (c *Coordinator) isForgeSequence() bool {
return c.isForgeSeq
return c.isForgeSeq // TODO
}
func (c *Coordinator) purgeRemoveByTimeout() error {
return nil
return nil // TODO
}
func (c *Coordinator) purgeInvalidDueToL2TxsSelection(l2Txs []*common.PoolL2Tx) error {
return nil
return nil // TODO
}
func (c *Coordinator) shouldL1L2Batch() bool {
return false
return false // TODO
}
func (c *Coordinator) prepareForgeBatchArgs(batchInfo *BatchInfo) *eth.RollupForgeBatchArgs {
return nil
return nil // TODO
}

+ 3
- 1
coordinator/coordinator_test.go

@ -126,7 +126,9 @@ func TestCoordinator(t *testing.T) {
conf := Config{}
hdb := &historydb.HistoryDB{}
c := NewCoordinator(conf, hdb, txsel, bb, &eth.Client{})
serverProofs := []ServerProofInterface{&ServerProof{}, &ServerProof{}}
ethClient := &eth.Client{}
c := NewCoordinator(conf, hdb, txsel, bb, serverProofs, ethClient)
cn := NewCoordNode(c)
cn.Start()
time.Sleep(1 * time.Second)

+ 36
- 10
coordinator/proofpool.go

@ -5,35 +5,61 @@ import (
"github.com/hermeznetwork/hermez-node/log"
)
// ServerProofInfo contains the data related to a ServerProof
type ServerProofInfo struct {
type ServerProofInterface interface {
CalculateProof(zkInputs *common.ZKInputs) error
GetProof(stopCh chan bool) (*Proof, error)
}
// ServerProof contains the data related to a ServerProof
type ServerProof struct {
// TODO
URL string
Available bool
}
func NewServerProof(URL string) *ServerProof {
return &ServerProof{URL: URL}
}
// CalculateProof sends the *common.ZKInputs to the ServerProof to compute the
// Proof
func (p *ServerProofInfo) CalculateProof(zkInputs *common.ZKInputs) error {
func (p *ServerProof) CalculateProof(zkInputs *common.ZKInputs) error {
return nil
}
// GetProof retreives the Proof from the ServerProof
func (p *ServerProofInfo) GetProof() (*Proof, error) {
func (p *ServerProof) GetProof(stopCh chan bool) (*Proof, error) {
return nil, nil
}
// ServerProofPool contains the multiple ServerProofInfo
// ServerProofPool contains the multiple ServerProof
type ServerProofPool struct {
// pool []ServerProofInfo
pool chan ServerProofInterface
}
func NewServerProofPool(maxServerProofs int) *ServerProofPool {
return &ServerProofPool{
pool: make(chan ServerProofInterface, maxServerProofs),
}
}
// GetNextAvailable returns the available ServerProofInfo
func (p *ServerProofPool) GetNextAvailable(stopCh chan bool) (*ServerProofInfo, error) {
func (p *ServerProofPool) Add(serverProof ServerProofInterface) {
p.pool <- serverProof
}
// Get returns the available ServerProof
func (p *ServerProofPool) Get(stopCh chan bool) (ServerProofInterface, error) {
select {
case <-stopCh:
log.Info("ServerProofPool.GetNextAvailable stopped")
log.Info("ServerProofPool.Get stopped")
return nil, ErrStop
default:
select {
case <-stopCh:
log.Info("ServerProofPool.Get stopped")
return nil, ErrStop
case serverProof := <-p.pool:
return serverProof, nil
}
}
return nil, nil
}

+ 100
- 62
eth/auction.go

@ -7,6 +7,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
HermezAuctionProtocol "github.com/hermeznetwork/hermez-node/eth/contracts/auction"
"github.com/hermeznetwork/hermez-node/log"
)
// AuctionConstants are the constants of the Rollup Smart Contract
@ -35,6 +36,16 @@ type SlotState struct {
Fulfilled bool
}
// NewSlotState returns an empty SlotState
func NewSlotState() *SlotState {
return &SlotState{
Forger: ethCommon.Address{},
BidAmount: big.NewInt(0),
ClosedMinBid: big.NewInt(0),
Fulfilled: false,
}
}
// Coordinator is the details of the Coordinator identified by the forger address
type Coordinator struct {
WithdrawalAddress ethCommon.Address
@ -48,15 +59,15 @@ type AuctionVariables struct {
// Boot Coordinator Address
BootCoordinator ethCommon.Address
// The minimum bid value in a series of 6 slots
MinBidEpoch [6]*big.Int
DefaultSlotSetBid [6]*big.Int
// Distance (#slots) to the closest slot to which you can bid ( 2 Slots = 2 * 40 Blocks = 20 min )
ClosedAuctionSlots uint16
// Distance (#slots) to the farthest slot to which you can bid (30 days = 4320 slots )
OpenAuctionSlots uint16
// How the HEZ tokens deposited by the slot winner are distributed (Burn: 40% - Donation: 40% - HGT: 20%)
AllocationRatio [3]uint8
AllocationRatio [3]uint16
// Minimum outbid (percentage) over the previous one to consider it valid
Outbidding uint8
Outbidding uint16
// Number of blocks at the end of a slot in which any coordinator can forge if the winner has not forged one before
SlotDeadline uint8
}
@ -90,7 +101,7 @@ type AuctionEventNewClosedAuctionSlots struct {
// AuctionEventNewOutbidding is an event of the Auction Smart Contract
type AuctionEventNewOutbidding struct {
NewOutbidding uint8
NewOutbidding uint16
}
// AuctionEventNewDonationAddress is an event of the Auction Smart Contract
@ -110,7 +121,7 @@ type AuctionEventNewOpenAuctionSlots struct {
// AuctionEventNewAllocationRatio is an event of the Auction Smart Contract
type AuctionEventNewAllocationRatio struct {
NewAllocationRatio [3]uint8
NewAllocationRatio [3]uint16
}
// AuctionEventNewCoordinator is an event of the Auction Smart Contract
@ -136,9 +147,9 @@ type AuctionEventNewForgeAllocated struct {
GovernanceAmount *big.Int
}
// AuctionEventNewMinBidEpoch is an event of the Auction Smart Contract
type AuctionEventNewMinBidEpoch struct {
SlotEpoch int64
// AuctionEventNewDefaultSlotSetBid is an event of the Auction Smart Contract
type AuctionEventNewDefaultSlotSetBid struct {
SlotSet int64
NewInitialMinBid *big.Int
}
@ -167,7 +178,7 @@ type AuctionEvents struct { //nolint:structcheck
NewCoordinator []AuctionEventNewCoordinator
CoordinatorUpdated []AuctionEventCoordinatorUpdated
NewForgeAllocated []AuctionEventNewForgeAllocated
NewMinBidEpoch []AuctionEventNewMinBidEpoch
NewDefaultSlotSetBid []AuctionEventNewDefaultSlotSetBid
NewForge []AuctionEventNewForge
HEZClaimed []AuctionEventHEZClaimed
}
@ -186,7 +197,7 @@ func NewAuctionEvents() AuctionEvents {
NewCoordinator: make([]AuctionEventNewCoordinator, 0),
CoordinatorUpdated: make([]AuctionEventCoordinatorUpdated, 0),
NewForgeAllocated: make([]AuctionEventNewForgeAllocated, 0),
NewMinBidEpoch: make([]AuctionEventNewMinBidEpoch, 0),
NewDefaultSlotSetBid: make([]AuctionEventNewDefaultSlotSetBid, 0),
NewForge: make([]AuctionEventNewForge, 0),
HEZClaimed: make([]AuctionEventHEZClaimed, 0),
}
@ -205,15 +216,15 @@ type AuctionInterface interface {
AuctionGetOpenAuctionSlots() (uint16, error)
AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (*types.Transaction, error)
AuctionGetClosedAuctionSlots() (uint16, error)
AuctionSetOutbidding(newOutbidding uint8) (*types.Transaction, error)
AuctionGetOutbidding() (uint8, error)
AuctionSetAllocationRatio(newAllocationRatio [3]uint8) (*types.Transaction, error)
AuctionGetAllocationRatio() ([3]uint8, error)
AuctionSetOutbidding(newOutbidding uint16) (*types.Transaction, error)
AuctionGetOutbidding() (uint16, error)
AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (*types.Transaction, error)
AuctionGetAllocationRatio() ([3]uint16, error)
AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (*types.Transaction, error)
AuctionGetDonationAddress() (*ethCommon.Address, error)
AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address) (*types.Transaction, error)
AuctionGetBootCoordinator() (*ethCommon.Address, error)
AuctionChangeEpochMinBid(slotEpoch int64, newInitialMinBid *big.Int) (*types.Transaction, error)
AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (*types.Transaction, error)
// Coordinator Management
AuctionRegisterCoordinator(forgerAddress ethCommon.Address, URL string) (*types.Transaction, error)
@ -223,13 +234,13 @@ type AuctionInterface interface {
// Slot Info
AuctionGetCurrentSlotNumber() (int64, error)
AuctionGetMinBidBySlot(slot int64) (*big.Int, error)
AuctionGetMinBidEpoch(epoch uint8) (*big.Int, error)
AuctionGetDefaultSlotSetBid(slotSet uint8) (*big.Int, error)
// Bidding
// AuctionTokensReceived(operator, from, to ethCommon.Address, amount *big.Int,
// userData, operatorData []byte) error // Only called from another smart contract
AuctionBid(slot int64, bidAmount *big.Int, forger ethCommon.Address) (*types.Transaction, error)
AuctionMultiBid(startingSlot int64, endingSlot int64, slotEpoch [6]bool,
AuctionMultiBid(startingSlot int64, endingSlot int64, slotSet [6]bool,
maxBid, closedMinBid, budget *big.Int, forger ethCommon.Address) (*types.Transaction, error)
// Forge
@ -267,6 +278,7 @@ func NewAuctionClient(client *EthereumClient, address ethCommon.Address) *Auctio
// AuctionSetSlotDeadline is the interface to call the smart contract function
func (c *AuctionClient) AuctionSetSlotDeadline(newDeadline uint8) (*types.Transaction, error) {
log.Error("TODO")
return nil, errTODO
}
@ -288,6 +300,7 @@ func (c *AuctionClient) AuctionGetSlotDeadline() (uint8, error) {
// AuctionSetOpenAuctionSlots is the interface to call the smart contract function
func (c *AuctionClient) AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (*types.Transaction, error) {
log.Error("TODO")
return nil, errTODO
}
@ -309,6 +322,7 @@ func (c *AuctionClient) AuctionGetOpenAuctionSlots() (uint16, error) {
// AuctionSetClosedAuctionSlots is the interface to call the smart contract function
func (c *AuctionClient) AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (*types.Transaction, error) {
log.Error("TODO")
return nil, errTODO
}
@ -329,49 +343,58 @@ func (c *AuctionClient) AuctionGetClosedAuctionSlots() (uint16, error) {
}
// AuctionSetOutbidding is the interface to call the smart contract function
func (c *AuctionClient) AuctionSetOutbidding(newOutbidding uint8) (*types.Transaction, error) {
func (c *AuctionClient) AuctionSetOutbidding(newOutbidding uint16) (*types.Transaction, error) {
log.Error("TODO")
return nil, errTODO
}
// AuctionGetOutbidding is the interface to call the smart contract function
func (c *AuctionClient) AuctionGetOutbidding() (uint8, error) {
var outbidding uint8
if err := c.client.Call(func(ec *ethclient.Client) error {
auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
if err != nil {
return err
}
outbidding, err = auction.GetOutbidding(nil)
return err
}); err != nil {
return 0, err
}
return outbidding, nil
func (c *AuctionClient) AuctionGetOutbidding() (uint16, error) {
// TODO: Update
// var outbidding uint8
// if err := c.client.Call(func(ec *ethclient.Client) error {
// auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
// if err != nil {
// return err
// }
// outbidding, err = auction.GetOutbidding(nil)
// return err
// }); err != nil {
// return 0, err
// }
// return outbidding, nil
log.Error("TODO")
return 0, errTODO
}
// AuctionSetAllocationRatio is the interface to call the smart contract function
func (c *AuctionClient) AuctionSetAllocationRatio(newAllocationRatio [3]uint8) (*types.Transaction, error) {
func (c *AuctionClient) AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (*types.Transaction, error) {
log.Error("TODO")
return nil, errTODO
}
// AuctionGetAllocationRatio is the interface to call the smart contract function
func (c *AuctionClient) AuctionGetAllocationRatio() ([3]uint8, error) {
var allocationRation [3]uint8
if err := c.client.Call(func(ec *ethclient.Client) error {
auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
if err != nil {
return err
}
allocationRation, err = auction.GetAllocationRatio(nil)
return err
}); err != nil {
return [3]uint8{}, err
}
return allocationRation, nil
func (c *AuctionClient) AuctionGetAllocationRatio() ([3]uint16, error) {
// TODO: Update
// var allocationRation [3]uint8
// if err := c.client.Call(func(ec *ethclient.Client) error {
// auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
// if err != nil {
// return err
// }
// allocationRation, err = auction.GetAllocationRatio(nil)
// return err
// }); err != nil {
// return [3]uint8{}, err
// }
// return allocationRation, nil
log.Error("TODO")
return [3]uint16{}, errTODO
}
// AuctionSetDonationAddress is the interface to call the smart contract function
func (c *AuctionClient) AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (*types.Transaction, error) {
log.Error("TODO")
return nil, errTODO
}
@ -393,6 +416,7 @@ func (c *AuctionClient) AuctionGetDonationAddress() (*ethCommon.Address, error)
// AuctionSetBootCoordinator is the interface to call the smart contract function
func (c *AuctionClient) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address) (*types.Transaction, error) {
log.Error("TODO")
return nil, errTODO
}
@ -412,23 +436,27 @@ func (c *AuctionClient) AuctionGetBootCoordinator() (*ethCommon.Address, error)
return &bootCoordinator, nil
}
// AuctionChangeEpochMinBid is the interface to call the smart contract function
func (c *AuctionClient) AuctionChangeEpochMinBid(slotEpoch int64, newInitialMinBid *big.Int) (*types.Transaction, error) {
// AuctionChangeDefaultSlotSetBid is the interface to call the smart contract function
func (c *AuctionClient) AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (*types.Transaction, error) {
log.Error("TODO")
return nil, errTODO
}
// AuctionRegisterCoordinator is the interface to call the smart contract function
func (c *AuctionClient) AuctionRegisterCoordinator(forgerAddress ethCommon.Address, URL string) (*types.Transaction, error) {
log.Error("TODO")
return nil, errTODO
}
// AuctionIsRegisteredCoordinator is the interface to call the smart contract function
func (c *AuctionClient) AuctionIsRegisteredCoordinator(forgerAddress ethCommon.Address) (bool, error) {
log.Error("TODO")
return false, errTODO
}
// AuctionUpdateCoordinatorInfo is the interface to call the smart contract function
func (c *AuctionClient) AuctionUpdateCoordinatorInfo(forgerAddress ethCommon.Address, newWithdrawAddress ethCommon.Address, newURL string) (*types.Transaction, error) {
log.Error("TODO")
return nil, errTODO
}
@ -466,20 +494,24 @@ func (c *AuctionClient) AuctionGetMinBidBySlot(slot int64) (*big.Int, error) {
return minBid, nil
}
// AuctionGetMinBidEpoch is the interface to call the smart contract function
func (c *AuctionClient) AuctionGetMinBidEpoch(epoch uint8) (*big.Int, error) {
var minBidEpoch *big.Int
if err := c.client.Call(func(ec *ethclient.Client) error {
auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
if err != nil {
return err
}
minBidEpoch, err = auction.GetMinBidEpoch(nil, epoch)
return err
}); err != nil {
return big.NewInt(0), err
}
return minBidEpoch, nil
// AuctionGetDefaultSlotSetBid is the interface to call the smart contract function
func (c *AuctionClient) AuctionGetDefaultSlotSetBid(slotSet uint8) (*big.Int, error) {
// TODO: Update
// var DefaultSlotSetBid *big.Int
// if err := c.client.Call(func(ec *ethclient.Client) error {
// auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
// if err != nil {
// return err
// }
// defaultSlotSetBid, err = auction.GetDefaultSlotSetBid(nil, slotSet)
// return err
// }); err != nil {
// return big.NewInt(0), err
// }
// return defaultSlotSetBid, nil
log.Error("TODO")
return nil, errTODO
}
// AuctionTokensReceived is the interface to call the smart contract function
@ -489,16 +521,19 @@ func (c *AuctionClient) AuctionGetMinBidEpoch(epoch uint8) (*big.Int, error) {
// AuctionBid is the interface to call the smart contract function
func (c *AuctionClient) AuctionBid(slot int64, bidAmount *big.Int, forger ethCommon.Address) (*types.Transaction, error) {
log.Error("TODO")
return nil, errTODO
}
// AuctionMultiBid is the interface to call the smart contract function
func (c *AuctionClient) AuctionMultiBid(startingSlot int64, endingSlot int64, slotEpoch [6]bool, maxBid, closedMinBid, budget *big.Int, forger ethCommon.Address) (*types.Transaction, error) {
func (c *AuctionClient) AuctionMultiBid(startingSlot int64, endingSlot int64, slotSet [6]bool, maxBid, closedMinBid, budget *big.Int, forger ethCommon.Address) (*types.Transaction, error) {
log.Error("TODO")
return nil, errTODO
}
// AuctionCanForge is the interface to call the smart contract function
func (c *AuctionClient) AuctionCanForge(forger ethCommon.Address) (bool, error) {
log.Error("TODO")
return false, errTODO
}
@ -509,15 +544,18 @@ func (c *AuctionClient) AuctionCanForge(forger ethCommon.Address) (bool, error)
// AuctionClaimHEZ is the interface to call the smart contract function
func (c *AuctionClient) AuctionClaimHEZ() (*types.Transaction, error) {
log.Error("TODO")
return nil, errTODO
}
// AuctionConstants returns the Constants of the Auction Smart Contract
func (c *AuctionClient) AuctionConstants() (*AuctionConstants, error) {
log.Error("TODO")
return nil, errTODO
}
// AuctionEventsByBlock returns the events in a block that happened in the Auction Smart Contract
func (c *AuctionClient) AuctionEventsByBlock(blockNum int64) (*AuctionEvents, *ethCommon.Hash, error) {
log.Error("TODO")
return nil, nil, errTODO
}

+ 21
- 0
eth/rollup.go

@ -6,6 +6,7 @@ import (
ethCommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/hermeznetwork/hermez-node/common"
"github.com/hermeznetwork/hermez-node/log"
"github.com/hermeznetwork/hermez-node/utils"
"github.com/iden3/go-iden3-crypto/babyjub"
)
@ -219,11 +220,13 @@ type RollupClient struct {
// 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
}
// 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
}
@ -234,76 +237,91 @@ func (c *RollupClient) RollupAddToken(tokenAddress ethCommon.Address) (*types.Tr
// RollupWithdrawMerkleProof is the interface to call the smart contract function
func (c *RollupClient) RollupWithdrawMerkleProof(tokenID int64, balance *big.Int, babyPubKey *babyjub.PublicKey, numExitRoot int64, siblings []*big.Int, idx int64, instantWithdraw bool) (*types.Transaction, error) {
log.Error("TODO")
return nil, errTODO
}
// RollupForceExit is the interface to call the smart contract function
func (c *RollupClient) RollupForceExit(fromIdx int64, amountF utils.Float16, tokenID int64) (*types.Transaction, error) {
log.Error("TODO")
return nil, errTODO
}
// 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) {
log.Error("TODO")
return nil, errTODO
}
// 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) {
log.Error("TODO")
return nil, errTODO
}
// 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) {
log.Error("TODO")
return nil, errTODO
}
// RollupDeposit is the interface to call the smart contract function
func (c *RollupClient) RollupDeposit(fromIdx int64, loadAmountF utils.Float16, tokenID int64) (*types.Transaction, error) {
log.Error("TODO")
return nil, errTODO
}
// 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) {
log.Error("TODO")
return nil, errTODO
}
// 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) {
log.Error("TODO")
return nil, errTODO
}
// RollupGetTokenAddress is the interface to call the smart contract function
func (c *RollupClient) RollupGetTokenAddress(tokenID int64) (*ethCommon.Address, error) {
log.Error("TODO")
return nil, errTODO
}
// RollupGetL1TxFromQueue is the interface to call the smart contract function
func (c *RollupClient) RollupGetL1TxFromQueue(queue int64, position int64) ([]byte, error) {
log.Error("TODO")
return nil, errTODO
}
// RollupGetQueue is the interface to call the smart contract function
func (c *RollupClient) RollupGetQueue(queue int64) ([]byte, error) {
log.Error("TODO")
return nil, errTODO
}
// RollupUpdateForgeL1Timeout is the interface to call the smart contract function
func (c *RollupClient) RollupUpdateForgeL1Timeout(newForgeL1Timeout int64) (*types.Transaction, error) {
log.Error("TODO")
return nil, errTODO
}
// RollupUpdateFeeL1UserTx is the interface to call the smart contract function
func (c *RollupClient) RollupUpdateFeeL1UserTx(newFeeL1UserTx *big.Int) (*types.Transaction, error) {
log.Error("TODO")
return nil, errTODO
}
// RollupUpdateFeeAddToken is the interface to call the smart contract function
func (c *RollupClient) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (*types.Transaction, error) {
log.Error("TODO")
return nil, errTODO
}
// RollupUpdateTokensHEZ is the interface to call the smart contract function
func (c *RollupClient) RollupUpdateTokensHEZ(newTokenHEZ ethCommon.Address) (*types.Transaction, error) {
log.Error("TODO")
return nil, errTODO
}
@ -314,11 +332,13 @@ func (c *RollupClient) RollupUpdateTokensHEZ(newTokenHEZ ethCommon.Address) (*ty
// RollupConstants returns the Constants of the Rollup Smart Contract
func (c *RollupClient) RollupConstants() (*RollupConstants, error) {
log.Error("TODO")
return nil, errTODO
}
// RollupEventsByBlock returns the events in a block that happened in the Rollup Smart Contract
func (c *RollupClient) RollupEventsByBlock(blockNum int64) (*RollupEvents, *ethCommon.Hash, error) {
log.Error("TODO")
return nil, nil, errTODO
}
@ -329,5 +349,6 @@ func (c *RollupClient) RollupForgeBatchArgs(ethTxHash ethCommon.Hash) (*RollupFo
// m := abi.MethodById(txData) -> Method
// m.Inputs.Unpack(txData) -> Args
// client.TransactionReceipt()?
log.Error("TODO")
return nil, errTODO
}

+ 11
- 6
node/node.go

@ -86,28 +86,32 @@ func NewNode(mode Mode, cfg *config.Node, coordCfg *config.Coordinator) (*Node,
cfg.PostgreSQL.Host,
cfg.PostgreSQL.User,
cfg.PostgreSQL.Password,
cfg.L2DB.Name,
cfg.L2DB.SafetyPeriod,
cfg.L2DB.MaxTxs,
cfg.L2DB.TTL.Duration,
coordCfg.L2DB.Name,
coordCfg.L2DB.SafetyPeriod,
coordCfg.L2DB.MaxTxs,
coordCfg.L2DB.TTL.Duration,
)
if err != nil {
return nil, err
}
// TODO: Get (maxL1UserTxs, maxL1OperatorTxs, maxTxs) from the smart contract
txSelector, err := txselector.NewTxSelector(cfg.TxSelector.Path, stateDB, l2DB, 10, 10, 10)
txSelector, err := txselector.NewTxSelector(coordCfg.TxSelector.Path, stateDB, l2DB, 10, 10, 10)
if err != nil {
return nil, err
}
// TODO: Get (configCircuits []ConfigCircuit, batchNum common.BatchNum, nLevels uint64) from smart contract
nLevels := uint64(32) //nolint:gomnd
batchBuilder, err := batchbuilder.NewBatchBuilder(cfg.BatchBuilder.Path, stateDB, nil, 0, nLevels)
batchBuilder, err := batchbuilder.NewBatchBuilder(coordCfg.BatchBuilder.Path, stateDB, nil, 0, nLevels)
if err != nil {
return nil, err
}
if err != nil {
return nil, err
}
serverProofs := make([]coordinator.ServerProofInterface, len(coordCfg.ServerProofs))
for i, serverProofCfg := range coordCfg.ServerProofs {
serverProofs[i] = coordinator.NewServerProof(serverProofCfg.URL)
}
coord = coordinator.NewCoordinator(
coordinator.Config{
ForgerAddress: coordCfg.ForgerAddress,
@ -115,6 +119,7 @@ func NewNode(mode Mode, cfg *config.Node, coordCfg *config.Coordinator) (*Node,
historyDB,
txSelector,
batchBuilder,
serverProofs,
client,
)
}

+ 292
- 67
test/ethclient.go

@ -65,8 +65,8 @@ func (a *AuctionBlock) getCurrentSlotNumber() int64 {
return a.getSlotNumber(a.Eth.BlockNum)
}
func (a *AuctionBlock) getEpoch(slot int64) int64 {
return slot % int64(len(a.Vars.MinBidEpoch))
func (a *AuctionBlock) getSlotSet(slot int64) int64 {
return slot % int64(len(a.Vars.DefaultSlotSetBid))
}
func (a *AuctionBlock) getMinBidBySlot(slot int64) (*big.Int, error) {
@ -74,23 +74,89 @@ func (a *AuctionBlock) getMinBidBySlot(slot int64) (*big.Int, error) {
return nil, errBidClosed
}
epoch := a.getEpoch(slot)
slotSet := a.getSlotSet(slot)
// fmt.Println("slot:", slot, "slotSet:", slotSet)
var prevBid *big.Int
slotState, ok := a.State.Slots[slot]
if !ok {
slotState = eth.NewSlotState()
a.State.Slots[slot] = slotState
}
// If the bidAmount for a slot is 0 it means that it has not yet been bid, so the midBid will be the minimum
// bid for the slot time plus the outbidding set, otherwise it will be the bidAmount plus the outbidding
if !ok || slotState.BidAmount.Cmp(big.NewInt(0)) == 0 {
prevBid = a.Vars.MinBidEpoch[epoch]
if slotState.BidAmount.Cmp(big.NewInt(0)) == 0 {
prevBid = a.Vars.DefaultSlotSetBid[slotSet]
} else {
prevBid = slotState.BidAmount
}
outBid := new(big.Int).Set(prevBid)
// fmt.Println("outBid:", outBid)
outBid.Mul(outBid, big.NewInt(int64(a.Vars.Outbidding)))
outBid.Div(outBid, big.NewInt(100)) //nolint:gomnd
outBid.Div(outBid, big.NewInt(10000)) //nolint:gomnd
outBid.Add(prevBid, outBid)
// fmt.Println("minBid:", outBid)
return outBid, nil
}
func (a *AuctionBlock) forge(forger ethCommon.Address) error {
if ok, err := a.canForge(forger, a.Eth.BlockNum); err != nil {
return err
} else if !ok {
return fmt.Errorf("Can't forge")
}
slotToForge := a.getSlotNumber(a.Eth.BlockNum)
slotState, ok := a.State.Slots[slotToForge]
if !ok {
slotState = eth.NewSlotState()
a.State.Slots[slotToForge] = slotState
}
slotState.Fulfilled = true
a.Events.NewForge = append(a.Events.NewForge, eth.AuctionEventNewForge{
Forger: forger,
CurrentSlot: slotToForge,
})
return nil
}
func (a *AuctionBlock) canForge(forger ethCommon.Address, blockNum int64) (bool, error) {
if blockNum < a.Constants.GenesisBlockNum {
return false, fmt.Errorf("Auction has not started yet")
}
slotToForge := a.getSlotNumber(blockNum)
// Get the relativeBlock to check if the slotDeadline has been exceeded
relativeBlock := blockNum - (a.Constants.GenesisBlockNum + (slotToForge * int64(a.Constants.BlocksPerSlot)))
// If the closedMinBid is 0 it means that we have to take as minBid the one that is set for this slot set,
// otherwise the one that has been saved will be used
var minBid *big.Int
slotState, ok := a.State.Slots[slotToForge]
if !ok {
slotState = eth.NewSlotState()
a.State.Slots[slotToForge] = slotState
}
if slotState.ClosedMinBid.Cmp(big.NewInt(0)) == 0 {
minBid = a.Vars.DefaultSlotSetBid[a.getSlotSet(slotToForge)]
} else {
minBid = slotState.ClosedMinBid
}
if !slotState.Fulfilled && (relativeBlock >= int64(a.Vars.SlotDeadline)) {
// if the relative block has exceeded the slotDeadline and no batch has been forged, anyone can forge
return true, nil
} else if slotState.Forger == forger && slotState.BidAmount.Cmp(minBid) >= 0 {
// if forger bidAmount has exceeded the minBid it can forge
return true, nil
} else if a.Vars.BootCoordinator == forger && slotState.BidAmount.Cmp(minBid) == -1 {
// if it's the boot coordinator and it has not been bid or the bid is below the minimum it can forge
return true, nil
} else {
return false, nil
}
}
// EthereumBlock stores all the generic data related to the an ethereum block
type EthereumBlock struct {
BlockNum int64
@ -107,13 +173,18 @@ type Block struct {
Eth *EthereumBlock
}
// Next prepares the successive block.
func (b *Block) Next() *Block {
blockNextRaw, err := copystructure.Copy(b)
func (b *Block) copy() *Block {
bCopyRaw, err := copystructure.Copy(b)
if err != nil {
panic(err)
}
blockNext := blockNextRaw.(*Block)
bCopy := bCopyRaw.(*Block)
return bCopy
}
// Next prepares the successive block.
func (b *Block) Next() *Block {
blockNext := b.copy()
blockNext.Rollup.Events = eth.NewRollupEvents()
blockNext.Auction.Events = eth.NewAuctionEvents()
blockNext.Eth = &EthereumBlock{
@ -138,34 +209,59 @@ type ClientSetup struct {
}
// NewClientSetupExample returns a ClientSetup example with hardcoded realistic values.
// TODO: Fill all values that are currently default.
//nolint:gomnd
func NewClientSetupExample() *ClientSetup {
rollupConstants := &eth.RollupConstants{}
rfield, ok := new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10)
if !ok {
panic("bad rfield")
}
initialMinimalBidding, ok := new(big.Int).SetString("10000000000000000000", 10) // 10 * (1e18)
if !ok {
panic("bad initialMinimalBidding")
}
tokenHEZ := ethCommon.HexToAddress("0x51D243D62852Bba334DD5cc33f242BAc8c698074")
governanceAddress := ethCommon.HexToAddress("0x688EfD95BA4391f93717CF02A9aED9DBD2855cDd")
rollupConstants := &eth.RollupConstants{
MaxAmountDeposit: new(big.Int).Lsh(big.NewInt(1), 128),
MaxAmountL2: new(big.Int).Lsh(big.NewInt(1), 192),
MaxTokens: 0xffffffff,
MaxL1Tx: 256,
MaxL1UserTx: 128,
Rfield: rfield,
L1CoordinatorBytes: 101,
L1UserBytes: 68,
L2Bytes: 11,
}
rollupVariables := &eth.RollupVariables{
MaxTxVerifiers: make([]int, 0),
TokenHEZ: ethCommon.Address{},
GovernanceAddress: ethCommon.Address{},
SafetyBot: ethCommon.Address{},
ConsensusContract: ethCommon.Address{},
WithdrawalContract: ethCommon.Address{},
FeeAddToken: big.NewInt(1),
ForgeL1Timeout: 16,
FeeL1UserTx: big.NewInt(2),
MaxTxVerifiers: []int{512, 1024, 2048},
TokenHEZ: tokenHEZ,
GovernanceAddress: governanceAddress,
SafetyBot: ethCommon.HexToAddress("0x84d8B79E84fe87B14ad61A554e740f6736bF4c20"),
ConsensusContract: ethCommon.HexToAddress("0x8E442975805fb1908f43050c9C1A522cB0e28D7b"),
WithdrawalContract: ethCommon.HexToAddress("0x5CB7979cBdbf65719BEE92e4D15b7b7Ed3D79114"),
FeeAddToken: big.NewInt(11),
ForgeL1Timeout: 9,
FeeL1UserTx: big.NewInt(22),
}
auctionConstants := &eth.AuctionConstants{
BlocksPerSlot: 40,
DelayGenesis: 0,
BlocksPerSlot: 40,
InitialMinimalBidding: initialMinimalBidding,
GenesisBlockNum: 0,
GovernanceAddress: governanceAddress,
TokenHEZ: tokenHEZ,
HermezRollup: ethCommon.HexToAddress("0x474B6e29852257491cf283EfB1A9C61eBFe48369"),
}
auctionVariables := &eth.AuctionVariables{
DonationAddress: ethCommon.Address{},
BootCoordinator: ethCommon.Address{},
MinBidEpoch: [6]*big.Int{
big.NewInt(10), big.NewInt(11), big.NewInt(12),
big.NewInt(13), big.NewInt(14), big.NewInt(15)},
DonationAddress: ethCommon.HexToAddress("0x61Ed87CF0A1496b49A420DA6D84B58196b98f2e7"),
BootCoordinator: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
DefaultSlotSetBid: [6]*big.Int{
big.NewInt(1000), big.NewInt(1100), big.NewInt(1200),
big.NewInt(1300), big.NewInt(1400), big.NewInt(1500)},
ClosedAuctionSlots: 2,
OpenAuctionSlots: 100,
AllocationRatio: [3]uint8{},
Outbidding: 10,
OpenAuctionSlots: 4320,
AllocationRatio: [3]uint16{4000, 4000, 2000},
Outbidding: 1000,
SlotDeadline: 20,
}
return &ClientSetup{
@ -277,6 +373,17 @@ func NewClient(l bool, timer Timer, addr ethCommon.Address, setup *ClientSetup)
// Mock Control
//
func (c *Client) setNextBlock(block *Block) {
c.blocks[c.blockNum+1] = block
}
func (c *Client) revertIfErr(err error, block *Block) {
if err != nil {
log.Infow("TestClient revert", "block", block.Eth.BlockNum, "err", err)
c.setNextBlock(block)
}
}
// Debugf calls log.Debugf if c.log is true
func (c *Client) Debugf(template string, args ...interface{}) {
if c.log {
@ -439,11 +546,30 @@ func (c *Client) newTransaction(name string, value interface{}) *types.Transacti
}
// RollupForgeBatch is the interface to call the smart contract function
func (c *Client) RollupForgeBatch(*eth.RollupForgeBatchArgs) (*types.Transaction, error) {
func (c *Client) RollupForgeBatch(args *eth.RollupForgeBatchArgs) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
return nil, errTODO
a := c.nextBlock().Auction
ok, err := a.canForge(c.addr, a.Eth.BlockNum)
if err != nil {
return nil, err
}
if !ok {
return nil, fmt.Errorf("incorrect slot")
}
// TODO: Verify proof
// Auction
err = a.forge(c.addr)
if err != nil {
return nil, err
}
return c.addBatch(args)
}
// CtlAddBatch adds forged batch to the Rollup, without checking any ZKProof
@ -451,11 +577,17 @@ func (c *Client) CtlAddBatch(args *eth.RollupForgeBatchArgs) {
c.rw.Lock()
defer c.rw.Unlock()
if _, err := c.addBatch(args); err != nil {
panic(err)
}
}
func (c *Client) addBatch(args *eth.RollupForgeBatchArgs) (*types.Transaction, error) {
nextBlock := c.nextBlock()
r := nextBlock.Rollup
r.State.StateRoot = args.NewStRoot
if args.NewLastIdx < r.State.CurrentIdx {
panic("args.NewLastIdx < r.State.CurrentIdx")
return nil, fmt.Errorf("args.NewLastIdx < r.State.CurrentIdx")
}
r.State.CurrentIdx = args.NewLastIdx
r.State.ExitRoots = append(r.State.ExitRoots, args.NewExitRoot)
@ -472,12 +604,16 @@ func (c *Client) CtlAddBatch(args *eth.RollupForgeBatchArgs) {
BatchNum: int64(len(r.State.ExitRoots)),
EthTxHash: ethTx.Hash(),
})
return ethTx, nil
}
// RollupAddToken is the interface to call the smart contract function
func (c *Client) RollupAddToken(tokenAddress ethCommon.Address) (*types.Transaction, error) {
func (c *Client) RollupAddToken(tokenAddress ethCommon.Address) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
nextBlock := c.nextBlock()
r := nextBlock.Rollup
@ -498,66 +634,90 @@ func (c *Client) RollupAddToken(tokenAddress ethCommon.Address) (*types.Transact
// }
// RollupWithdrawMerkleProof is the interface to call the smart contract function
func (c *Client) RollupWithdrawMerkleProof(tokenID int64, balance *big.Int, babyPubKey *babyjub.PublicKey, numExitRoot int64, siblings []*big.Int, idx int64, instantWithdraw bool) (*types.Transaction, error) {
func (c *Client) RollupWithdrawMerkleProof(tokenID int64, balance *big.Int, babyPubKey *babyjub.PublicKey, numExitRoot int64, siblings []*big.Int, idx int64, instantWithdraw bool) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
// RollupForceExit is the interface to call the smart contract function
func (c *Client) RollupForceExit(fromIdx int64, amountF utils.Float16, tokenID int64) (*types.Transaction, error) {
func (c *Client) RollupForceExit(fromIdx int64, amountF utils.Float16, tokenID int64) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
// RollupForceTransfer is the interface to call the smart contract function
func (c *Client) RollupForceTransfer(fromIdx int64, amountF utils.Float16, tokenID, toIdx int64) (*types.Transaction, error) {
func (c *Client) RollupForceTransfer(fromIdx int64, amountF utils.Float16, tokenID, toIdx int64) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
// 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) (*types.Transaction, error) {
func (c *Client) RollupCreateAccountDepositTransfer(babyPubKey babyjub.PublicKey, loadAmountF, amountF utils.Float16, tokenID int64, toIdx int64) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
// RollupDepositTransfer is the interface to call the smart contract function
func (c *Client) RollupDepositTransfer(fromIdx int64, loadAmountF, amountF utils.Float16, tokenID int64, toIdx int64) (*types.Transaction, error) {
func (c *Client) RollupDepositTransfer(fromIdx int64, loadAmountF, amountF utils.Float16, tokenID int64, toIdx int64) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
// RollupDeposit is the interface to call the smart contract function
func (c *Client) RollupDeposit(fromIdx int64, loadAmountF utils.Float16, tokenID int64) (*types.Transaction, error) {
func (c *Client) RollupDeposit(fromIdx int64, loadAmountF utils.Float16, tokenID int64) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
// RollupCreateAccountDepositFromRelayer is the interface to call the smart contract function
func (c *Client) RollupCreateAccountDepositFromRelayer(accountCreationAuthSig []byte, babyPubKey babyjub.PublicKey, loadAmountF utils.Float16) (*types.Transaction, error) {
func (c *Client) RollupCreateAccountDepositFromRelayer(accountCreationAuthSig []byte, babyPubKey babyjub.PublicKey, loadAmountF utils.Float16) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
// RollupCreateAccountDeposit is the interface to call the smart contract function
func (c *Client) RollupCreateAccountDeposit(babyPubKey babyjub.PublicKey, loadAmountF utils.Float16, tokenID int64) (*types.Transaction, error) {
func (c *Client) RollupCreateAccountDeposit(babyPubKey babyjub.PublicKey, loadAmountF utils.Float16, tokenID int64) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
@ -566,6 +726,7 @@ func (c *Client) RollupGetTokenAddress(tokenID int64) (*ethCommon.Address, error
c.rw.RLock()
defer c.rw.RUnlock()
log.Error("TODO")
return nil, errTODO
}
@ -574,6 +735,7 @@ func (c *Client) RollupGetL1TxFromQueue(queue int64, position int64) ([]byte, er
c.rw.RLock()
defer c.rw.RUnlock()
log.Error("TODO")
return nil, errTODO
}
@ -582,38 +744,51 @@ func (c *Client) RollupGetQueue(queue int64) ([]byte, error) {
c.rw.RLock()
defer c.rw.RUnlock()
log.Error("TODO")
return nil, errTODO
}
// RollupUpdateForgeL1Timeout is the interface to call the smart contract function
func (c *Client) RollupUpdateForgeL1Timeout(newForgeL1Timeout int64) (*types.Transaction, error) {
func (c *Client) RollupUpdateForgeL1Timeout(newForgeL1Timeout int64) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
// RollupUpdateFeeL1UserTx is the interface to call the smart contract function
func (c *Client) RollupUpdateFeeL1UserTx(newFeeL1UserTx *big.Int) (*types.Transaction, error) {
func (c *Client) RollupUpdateFeeL1UserTx(newFeeL1UserTx *big.Int) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
// RollupUpdateFeeAddToken is the interface to call the smart contract function
func (c *Client) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (*types.Transaction, error) {
func (c *Client) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
// RollupUpdateTokensHEZ is the interface to call the smart contract function
func (c *Client) RollupUpdateTokensHEZ(newTokenHEZ ethCommon.Address) (*types.Transaction, error) {
func (c *Client) RollupUpdateTokensHEZ(newTokenHEZ ethCommon.Address) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
@ -627,6 +802,7 @@ func (c *Client) RollupConstants() (*eth.RollupConstants, error) {
c.rw.RLock()
defer c.rw.RUnlock()
log.Error("TODO")
return nil, errTODO
}
@ -659,10 +835,13 @@ func (c *Client) RollupForgeBatchArgs(ethTxHash ethCommon.Hash) (*eth.RollupForg
//
// AuctionSetSlotDeadline is the interface to call the smart contract function
func (c *Client) AuctionSetSlotDeadline(newDeadline uint8) (*types.Transaction, error) {
func (c *Client) AuctionSetSlotDeadline(newDeadline uint8) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
@ -671,14 +850,18 @@ func (c *Client) AuctionGetSlotDeadline() (uint8, error) {
c.rw.RLock()
defer c.rw.RUnlock()
log.Error("TODO")
return 0, errTODO
}
// AuctionSetOpenAuctionSlots is the interface to call the smart contract function
func (c *Client) AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (*types.Transaction, error) {
func (c *Client) AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
@ -687,14 +870,18 @@ func (c *Client) AuctionGetOpenAuctionSlots() (uint16, error) {
c.rw.RLock()
defer c.rw.RUnlock()
log.Error("TODO")
return 0, errTODO
}
// AuctionSetClosedAuctionSlots is the interface to call the smart contract function
func (c *Client) AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (*types.Transaction, error) {
func (c *Client) AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
@ -703,46 +890,58 @@ func (c *Client) AuctionGetClosedAuctionSlots() (uint16, error) {
c.rw.RLock()
defer c.rw.RUnlock()
log.Error("TODO")
return 0, errTODO
}
// AuctionSetOutbidding is the interface to call the smart contract function
func (c *Client) AuctionSetOutbidding(newOutbidding uint8) (*types.Transaction, error) {
func (c *Client) AuctionSetOutbidding(newOutbidding uint16) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
// AuctionGetOutbidding is the interface to call the smart contract function
func (c *Client) AuctionGetOutbidding() (uint8, error) {
func (c *Client) AuctionGetOutbidding() (uint16, error) {
c.rw.RLock()
defer c.rw.RUnlock()
log.Error("TODO")
return 0, errTODO
}
// AuctionSetAllocationRatio is the interface to call the smart contract function
func (c *Client) AuctionSetAllocationRatio(newAllocationRatio [3]uint8) (*types.Transaction, error) {
func (c *Client) AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
// AuctionGetAllocationRatio is the interface to call the smart contract function
func (c *Client) AuctionGetAllocationRatio() ([3]uint8, error) {
func (c *Client) AuctionGetAllocationRatio() ([3]uint16, error) {
c.rw.RLock()
defer c.rw.RUnlock()
return [3]uint8{}, errTODO
log.Error("TODO")
return [3]uint16{}, errTODO
}
// AuctionSetDonationAddress is the interface to call the smart contract function
func (c *Client) AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (*types.Transaction, error) {
func (c *Client) AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
@ -751,14 +950,18 @@ func (c *Client) AuctionGetDonationAddress() (*ethCommon.Address, error) {
c.rw.RLock()
defer c.rw.RUnlock()
log.Error("TODO")
return nil, errTODO
}
// AuctionSetBootCoordinator is the interface to call the smart contract function
func (c *Client) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address) (*types.Transaction, error) {
func (c *Client) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
@ -773,18 +976,23 @@ func (c *Client) AuctionGetBootCoordinator() (*ethCommon.Address, error) {
return &a.Vars.BootCoordinator, nil
}
// AuctionChangeEpochMinBid is the interface to call the smart contract function
func (c *Client) AuctionChangeEpochMinBid(slotEpoch int64, newInitialMinBid *big.Int) (*types.Transaction, error) {
// AuctionChangeDefaultSlotSetBid is the interface to call the smart contract function
func (c *Client) AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
// AuctionRegisterCoordinator is the interface to call the smart contract function
func (c *Client) AuctionRegisterCoordinator(forgerAddress ethCommon.Address, URL string) (*types.Transaction, error) {
func (c *Client) AuctionRegisterCoordinator(forgerAddress ethCommon.Address, URL string) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
nextBlock := c.nextBlock()
a := nextBlock.Auction
@ -816,14 +1024,18 @@ func (c *Client) AuctionIsRegisteredCoordinator(forgerAddress ethCommon.Address)
c.rw.RLock()
defer c.rw.RUnlock()
log.Error("TODO")
return false, errTODO
}
// AuctionUpdateCoordinatorInfo is the interface to call the smart contract function
func (c *Client) AuctionUpdateCoordinatorInfo(forgerAddress ethCommon.Address, newWithdrawAddress ethCommon.Address, newURL string) (*types.Transaction, error) {
func (c *Client) AuctionUpdateCoordinatorInfo(forgerAddress ethCommon.Address, newWithdrawAddress ethCommon.Address, newURL string) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
@ -832,6 +1044,7 @@ func (c *Client) AuctionGetCurrentSlotNumber() (int64, error) {
c.rw.RLock()
defer c.rw.RUnlock()
log.Error("TODO")
return 0, errTODO
}
@ -840,14 +1053,16 @@ func (c *Client) AuctionGetMinBidBySlot(slot int64) (*big.Int, error) {
c.rw.RLock()
defer c.rw.RUnlock()
log.Error("TODO")
return nil, errTODO
}
// AuctionGetMinBidEpoch is the interface to call the smart contract function
func (c *Client) AuctionGetMinBidEpoch(epoch uint8) (*big.Int, error) {
// AuctionGetDefaultSlotSetBid is the interface to call the smart contract function
func (c *Client) AuctionGetDefaultSlotSetBid(slotSet uint8) (*big.Int, error) {
c.rw.RLock()
defer c.rw.RUnlock()
log.Error("TODO")
return nil, errTODO
}
@ -857,9 +1072,11 @@ func (c *Client) AuctionGetMinBidEpoch(epoch uint8) (*big.Int, error) {
// }
// AuctionBid is the interface to call the smart contract function
func (c *Client) AuctionBid(slot int64, bidAmount *big.Int, forger ethCommon.Address) (*types.Transaction, error) {
func (c *Client) AuctionBid(slot int64, bidAmount *big.Int, forger ethCommon.Address) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { func() { c.revertIfErr(err, cpy) }() }()
nextBlock := c.nextBlock()
a := nextBlock.Auction
@ -886,7 +1103,7 @@ func (c *Client) AuctionBid(slot int64, bidAmount *big.Int, forger ethCommon.Add
slotState, ok := a.State.Slots[slot]
if !ok {
slotState = &eth.SlotState{}
slotState = eth.NewSlotState()
a.State.Slots[slot] = slotState
}
slotState.Forger = forger
@ -904,10 +1121,13 @@ func (c *Client) AuctionBid(slot int64, bidAmount *big.Int, forger ethCommon.Add
}
// AuctionMultiBid is the interface to call the smart contract function
func (c *Client) AuctionMultiBid(startingSlot int64, endingSlot int64, slotEpoch [6]bool, maxBid, closedMinBid, budget *big.Int, forger ethCommon.Address) (*types.Transaction, error) {
func (c *Client) AuctionMultiBid(startingSlot int64, endingSlot int64, slotSet [6]bool, maxBid, closedMinBid, budget *big.Int, forger ethCommon.Address) (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}
@ -916,7 +1136,9 @@ func (c *Client) AuctionCanForge(forger ethCommon.Address) (bool, error) {
c.rw.RLock()
defer c.rw.RUnlock()
return false, errTODO
currentBlock := c.currentBlock()
a := currentBlock.Auction
return a.canForge(forger, a.Eth.BlockNum)
}
// AuctionForge is the interface to call the smart contract function
@ -925,10 +1147,13 @@ func (c *Client) AuctionCanForge(forger ethCommon.Address) (bool, error) {
// }
// AuctionClaimHEZ is the interface to call the smart contract function
func (c *Client) AuctionClaimHEZ() (*types.Transaction, error) {
func (c *Client) AuctionClaimHEZ() (tx *types.Transaction, err error) {
c.rw.Lock()
defer c.rw.Unlock()
cpy := c.nextBlock().copy()
defer func() { c.revertIfErr(err, cpy) }()
log.Error("TODO")
return nil, errTODO
}

+ 12
- 5
test/ethclient_test.go

@ -72,16 +72,22 @@ func TestClientAuction(t *testing.T) {
var timer timer
clientSetup := NewClientSetupExample()
clientSetup.AuctionVariables.ClosedAuctionSlots = 2
clientSetup.AuctionVariables.OpenAuctionSlots = 100
clientSetup.AuctionVariables.OpenAuctionSlots = 4320
clientSetup.AuctionVariables.DefaultSlotSetBid = [6]*big.Int{
big.NewInt(1000), big.NewInt(1100), big.NewInt(1200),
big.NewInt(1300), big.NewInt(1400), big.NewInt(1500)}
c := NewClient(true, &timer, addrWithdraw, clientSetup)
// Check several cases in which bid doesn't succed, and also do 2 successful bids.
_, err := c.AuctionBid(0, big.NewInt(1), addrForge)
assert.Equal(t, errBidClosed, err)
_, err = c.AuctionBid(102, big.NewInt(1), addrForge)
_, err = c.AuctionBid(4322, big.NewInt(1), addrForge)
assert.Equal(t, errBidNotOpen, err)
_, err = c.AuctionBid(101, big.NewInt(16), addrForge)
// 101 % 6 = 5; defaultSlotSetBid[5] = 1500; 1500 + 10% = 1650
_, err = c.AuctionBid(101, big.NewInt(1650), addrForge)
assert.Equal(t, errCoordNotReg, err)
_, err = c.AuctionRegisterCoordinator(addrForge, "https://foo.bar")
@ -90,7 +96,7 @@ func TestClientAuction(t *testing.T) {
_, err = c.AuctionBid(3, big.NewInt(1), addrForge)
assert.Equal(t, errBidBelowMin, err)
_, err = c.AuctionBid(3, big.NewInt(16), addrForge)
_, err = c.AuctionBid(3, big.NewInt(1650), addrForge)
assert.Nil(t, err)
_, err = c.AuctionRegisterCoordinator(addrForge2, "https://foo2.bar")
@ -99,7 +105,8 @@ func TestClientAuction(t *testing.T) {
_, err = c.AuctionBid(3, big.NewInt(16), addrForge2)
assert.Equal(t, errBidBelowMin, err)
_, err = c.AuctionBid(3, big.NewInt(17), addrForge2)
// 1650 + 10% = 1815
_, err = c.AuctionBid(3, big.NewInt(1815), addrForge2)
assert.Nil(t, err)
c.CtlMineBlock()

Loading…
Cancel
Save