Skip to content
This repository has been archived by the owner on May 11, 2024. It is now read-only.

Commit

Permalink
feat(prover): improve prover (#633)
Browse files Browse the repository at this point in the history
  • Loading branch information
mask-pp authored Mar 13, 2024
1 parent 1c90c6a commit b80ce2c
Show file tree
Hide file tree
Showing 12 changed files with 68 additions and 120 deletions.
7 changes: 6 additions & 1 deletion pkg/sender/sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ func NewSender(ctx context.Context, cfg *Config, client *rpc.EthClient, priv *ec
return sender, nil
}

// CLose closes the sender.
// Close closes the sender.
func (s *Sender) Close() {
close(s.stopCh)
s.wg.Wait()
Expand All @@ -166,6 +166,11 @@ func (s *Sender) GetOpts() *bind.TransactOpts {
}
}

// Address returns the sender's address.
func (s *Sender) Address() common.Address {
return s.opts.From
}

// TxToConfirmChannel returns a channel to wait the given transaction's confirmation.
func (s *Sender) TxToConfirmChannel(txID string) <-chan *TxToConfirm {
ch, ok := s.txToConfirmCh.Get(txID)
Expand Down
3 changes: 1 addition & 2 deletions prover/event_handler/block_proposed.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ func (h *BlockProposedEventHandler) checkL1Reorg(
} else {
h.sharedState.SetLastHandledBlockID(reorgCheckResult.LastHandledBlockIDToReset.Uint64())
}
h.sharedState.SetReorgDetectedFlag(true)
return errL1Reorged
}

Expand Down Expand Up @@ -370,7 +369,7 @@ type BlockProposedGuaridanEventHandler struct {
GuardianProverHeartbeater guardianProverHeartbeater.BlockSenderHeartbeater
}

// NewBlockProposedEventHandler creates a new BlockProposedEventHandler instance.
// NewBlockProposedEventGuardianHandler creates a new BlockProposedEventHandler instance.
func NewBlockProposedEventGuardianHandler(
opts *NewBlockProposedGuardianEventHandlerOps,
) *BlockProposedGuaridanEventHandler {
Expand Down
2 changes: 1 addition & 1 deletion prover/event_handler/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type TransitionContestedHandler interface {
Handle(ctx context.Context, event *bindings.TaikoL1ClientTransitionContested) error
}

// TransitionContestedHandler is the interface for handling `TaikoL1.TransitionProved` events.
// TransitionProvedHandler is the interface for handling `TaikoL1.TransitionProved` events.
type TransitionProvedHandler interface {
Handle(ctx context.Context, event *bindings.TaikoL1ClientTransitionProved) error
}
Expand Down
11 changes: 1 addition & 10 deletions prover/guardian.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,8 @@ func (p *Prover) gurdianProverHeartbeatLoop(ctx context.Context) {
p.wg.Add(1)
defer p.wg.Done()

if !p.IsGuardianProver() {
return
}

ticker := time.NewTicker(heartbeatInterval)
p.wg.Add(1)

defer func() {
ticker.Stop()
p.wg.Done()
}()
defer ticker.Stop()

for {
select {
Expand Down
22 changes: 10 additions & 12 deletions prover/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package prover

import (
"context"
"fmt"
"math/big"

"github.com/ethereum/go-ethereum"
Expand All @@ -10,7 +11,6 @@ import (
"github.com/ethereum/go-ethereum/log"

"github.com/taikoxyz/taiko-client/bindings/encoding"
"github.com/taikoxyz/taiko-client/pkg/rpc"
"github.com/taikoxyz/taiko-client/pkg/sender"
handler "github.com/taikoxyz/taiko-client/prover/event_handler"
proofProducer "github.com/taikoxyz/taiko-client/prover/proof_producer"
Expand Down Expand Up @@ -51,14 +51,7 @@ func (p *Prover) setApprovalAmount(ctx context.Context, contract common.Address)
return nil
}

// Start setting the allowance amount.
opts, err := bind.NewKeyedTransactorWithChainID(
p.cfg.L1ProverPrivKey,
p.rpc.L1.ChainID,
)
if err != nil {
return err
}
opts := p.txSender.GetOpts()
opts.Context = ctx

log.Info("Approving the contract for taiko token", "allowance", p.cfg.Allowance.String(), "contract", contract)
Expand All @@ -72,15 +65,18 @@ func (p *Prover) setApprovalAmount(ctx context.Context, contract common.Address)
return err
}

// Wait for the transaction receipt.
receipt, err := rpc.WaitReceipt(ctx, p.rpc.L1, tx)
id, err := p.txSender.SendTransaction(tx)
if err != nil {
return err
}
confirm := <-p.txSender.TxToConfirmChannel(id)
if confirm.Err != nil {
return confirm.Err
}

log.Info(
"Approved the contract for taiko token",
"txHash", receipt.TxHash.Hex(),
"txHash", confirm.Receipt.TxHash.Hex(),
"contract", contract,
)

Expand Down Expand Up @@ -128,6 +124,8 @@ func (p *Prover) initProofSubmitters(
producer = sgxProducer
case encoding.TierGuardianID:
producer = proofProducer.NewGuardianProofProducer(p.cfg.EnableLivenessBondProof)
default:
return fmt.Errorf("unsupported tier: %d", tier.ID)
}

if submitter, err = proofSubmitter.New(
Expand Down
2 changes: 1 addition & 1 deletion prover/proof_producer/dummy_producer.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"github.com/taikoxyz/taiko-client/bindings"
)

// OptimisticProofProducer always returns a dummy proof.
// DummyProofProducer always returns a dummy proof.
type DummyProofProducer struct{}

// RequestProof returns a dummy proof to the result channel.
Expand Down
5 changes: 1 addition & 4 deletions prover/proof_submitter/proof_submitter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,7 @@ func (s *ProofSubmitterTestSuite) SetupTest() {
sender, err := sender.NewSender(context.Background(), &sender.Config{}, s.RPCClient.L1, l1ProverPrivKey)
s.Nil(err)

builder := transaction.NewProveBlockTxBuilder(
s.RPCClient,
l1ProverPrivKey,
)
builder := transaction.NewProveBlockTxBuilder(s.RPCClient)

s.submitter, err = New(
s.RPCClient,
Expand Down
17 changes: 3 additions & 14 deletions prover/proof_submitter/transaction/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@ package transaction

import (
"context"
"crypto/ecdsa"
"errors"
"math/big"
"sync"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"

"github.com/taikoxyz/taiko-client/bindings"
Expand All @@ -27,23 +24,15 @@ type TxBuilder func() (*types.Transaction, error)

// ProveBlockTxBuilder is responsible for building ProveBlock transactions.
type ProveBlockTxBuilder struct {
rpc *rpc.Client
proverPrivateKey *ecdsa.PrivateKey
proverAddress common.Address
mutex *sync.Mutex
rpc *rpc.Client
mutex sync.Mutex
}

// NewProveBlockTxBuilder creates a new ProveBlockTxBuilder instance.
func NewProveBlockTxBuilder(
rpc *rpc.Client,
proverPrivateKey *ecdsa.PrivateKey,
) *ProveBlockTxBuilder {
return &ProveBlockTxBuilder{
rpc: rpc,
proverPrivateKey: proverPrivateKey,
proverAddress: crypto.PubkeyToAddress(proverPrivateKey.PublicKey),
mutex: new(sync.Mutex),
}
return &ProveBlockTxBuilder{rpc: rpc}
}

// Build creates a new TaikoL1.ProveBlock transaction with the given nonce.
Expand Down
2 changes: 1 addition & 1 deletion prover/proof_submitter/transaction/sender_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func (s *TransactionTestSuite) SetupTest() {
s.sender, err = NewSender(s.RPCClient, txSender)
s.Nil(err)

s.builder = NewProveBlockTxBuilder(s.RPCClient, l1ProverPrivKey)
s.builder = NewProveBlockTxBuilder(s.RPCClient)
}

func (s *TransactionTestSuite) TestIsSubmitProofTxErrorRetryable() {
Expand Down
87 changes: 35 additions & 52 deletions prover/prover.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"github.com/cenkalti/backoff/v4"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/urfave/cli/v2"

Expand All @@ -34,7 +33,10 @@ import (
// Prover keeps trying to prove newly proposed blocks.
type Prover struct {
// Configurations
cfg *Config
cfg *Config
backoff backoff.BackOffContext

txSender *sender.Sender

// Clients
rpc *rpc.Client
Expand All @@ -44,7 +46,7 @@ type Prover struct {
guardianProverHeartbeater guardianProverHeartbeater.BlockSenderHeartbeater

// Contract configurations
protocolConfigs *bindings.TaikoDataConfig
protocolConfig *bindings.TaikoDataConfig

// States
sharedState *state.SharedState
Expand Down Expand Up @@ -87,12 +89,15 @@ func (p *Prover) InitFromCli(ctx context.Context, c *cli.Context) error {
func InitFromConfig(ctx context.Context, p *Prover, cfg *Config) (err error) {
p.cfg = cfg
p.ctx = ctx

// Initialize state which will be shared by event handlers.
p.sharedState = state.New()

// Initialize state which will be shared by event handlers.
p.sharedState = state.New()
p.backoff = backoff.WithContext(
backoff.WithMaxRetries(
backoff.NewConstantBackOff(p.cfg.BackOffRetryInterval),
p.cfg.BackOffMaxRetrys,
),
p.ctx,
)

// Clients
if p.rpc, err = rpc.NewClient(p.ctx, &rpc.ClientConfig{
Expand All @@ -112,13 +117,11 @@ func InitFromConfig(ctx context.Context, p *Prover, cfg *Config) (err error) {
if err != nil {
return fmt.Errorf("failed to get protocol configs: %w", err)
}
p.protocolConfigs = &protocolConfigs

log.Info("Protocol configs", "configs", p.protocolConfigs)
p.protocolConfig = &protocolConfigs

proverAddress := crypto.PubkeyToAddress(p.cfg.L1ProverPrivKey.PublicKey)
log.Info("Protocol configs", "configs", p.protocolConfig)

chBufferSize := p.protocolConfigs.BlockMaxProposals
chBufferSize := p.protocolConfig.BlockMaxProposals
p.proofGenerationCh = make(chan *proofProducer.ProofWithHeader, chBufferSize)
p.assignmentExpiredCh = make(chan *bindings.TaikoL1ClientBlockProposed, chBufferSize)
p.proofSubmissionCh = make(chan *proofProducer.ProofRequestBody, p.cfg.Capacity)
Expand Down Expand Up @@ -152,21 +155,21 @@ func InitFromConfig(ctx context.Context, p *Prover, cfg *Config) (err error) {
senderCfg.MaxRetrys = 0
}

txSender, err := sender.NewSender(p.ctx, senderCfg, p.rpc.L1, p.cfg.L1ProverPrivKey)
p.txSender, err = sender.NewSender(p.ctx, senderCfg, p.rpc.L1, p.cfg.L1ProverPrivKey)
if err != nil {
return err
}
txBuilder := transaction.NewProveBlockTxBuilder(p.rpc, p.cfg.L1ProverPrivKey)
txBuilder := transaction.NewProveBlockTxBuilder(p.rpc)

// Proof submitters
if err := p.initProofSubmitters(txSender, txBuilder); err != nil {
if err := p.initProofSubmitters(p.txSender, txBuilder); err != nil {
return err
}

// Proof contester
p.proofContester, err = proofSubmitter.NewProofContester(
p.rpc,
txSender,
p.txSender,
p.cfg.Graffiti,
txBuilder,
)
Expand All @@ -191,7 +194,7 @@ func InitFromConfig(ctx context.Context, p *Prover, cfg *Config) (err error) {
}

// Guardian prover heartbeat sender
if p.IsGuardianProver() {
if p.IsGuardianProver() && p.cfg.GuardianProverHealthCheckServerEndpoint != nil {
// Check guardian prover contract address is correct.
if _, err := p.rpc.GuardianProver.MinGuardians(&bind.CallOpts{Context: ctx}); err != nil {
return fmt.Errorf("failed to get MinGuardians from guardian prover contract: %w", err)
Expand All @@ -201,7 +204,7 @@ func InitFromConfig(ctx context.Context, p *Prover, cfg *Config) (err error) {
p.cfg.L1ProverPrivKey,
p.cfg.GuardianProverHealthCheckServerEndpoint,
p.rpc,
proverAddress,
p.ProverAddress(),
)
}

Expand Down Expand Up @@ -271,7 +274,7 @@ func (p *Prover) eventLoop() {
defer forceProvingTicker.Stop()

// Channels
chBufferSize := p.protocolConfigs.BlockMaxProposals
chBufferSize := p.protocolConfig.BlockMaxProposals
blockProposedCh := make(chan *bindings.TaikoL1ClientBlockProposed, chBufferSize)
blockVerifiedCh := make(chan *bindings.TaikoL1ClientBlockVerified, chBufferSize)
transitionProvedCh := make(chan *bindings.TaikoL1ClientTransitionProved, chBufferSize)
Expand Down Expand Up @@ -328,30 +331,19 @@ func (p *Prover) Close(ctx context.Context) {

// proveOp iterates through BlockProposed events
func (p *Prover) proveOp() error {
firstTry := true

for firstTry || p.sharedState.GetReorgDetectedFlag() {
p.sharedState.SetReorgDetectedFlag(false)
firstTry = false

iter, err := eventIterator.NewBlockProposedIterator(p.ctx, &eventIterator.BlockProposedIteratorConfig{
Client: p.rpc.L1,
TaikoL1: p.rpc.TaikoL1,
StartHeight: new(big.Int).SetUint64(p.sharedState.GetL1Current().Number.Uint64()),
OnBlockProposedEvent: p.blockProposedHandler.Handle,
BlockConfirmations: &p.cfg.BlockConfirmations,
})
if err != nil {
log.Error("Failed to start event iterator", "event", "BlockProposed", "error", err)
return err
}

if err := iter.Iter(); err != nil {
return err
}
iter, err := eventIterator.NewBlockProposedIterator(p.ctx, &eventIterator.BlockProposedIteratorConfig{
Client: p.rpc.L1,
TaikoL1: p.rpc.TaikoL1,
StartHeight: new(big.Int).SetUint64(p.sharedState.GetL1Current().Number.Uint64()),
OnBlockProposedEvent: p.blockProposedHandler.Handle,
BlockConfirmations: &p.cfg.BlockConfirmations,
})
if err != nil {
log.Error("Failed to start event iterator", "event", "BlockProposed", "error", err)
return err
}

return nil
return iter.Iter()
}

// contestProofOp performs a proof contest operation.
Expand Down Expand Up @@ -453,24 +445,15 @@ func (p *Prover) IsGuardianProver() bool {

// ProverAddress returns the current prover account address.
func (p *Prover) ProverAddress() common.Address {
return crypto.PubkeyToAddress(p.cfg.L1ProverPrivKey.PublicKey)
return p.txSender.Address()
}

// withRetry retries the given function with prover backoff policy.
func (p *Prover) withRetry(f func() error) {
p.wg.Add(1)
go func() {
defer p.wg.Done()
err := backoff.Retry(
func() error {
if p.ctx.Err() != nil {
log.Error("Context is done, aborting", "error", p.ctx.Err())
return nil
}
return f()
},
backoff.WithMaxRetries(backoff.NewConstantBackOff(p.cfg.BackOffRetryInterval), p.cfg.BackOffMaxRetrys),
)
err := backoff.Retry(f, p.backoff)
if err != nil {
log.Error("Operation failed", "error", err)
}
Expand Down
Loading

0 comments on commit b80ce2c

Please sign in to comment.