Skip to content

Commit

Permalink
feat(proposer): add waitReceiptTimeout when proposing (taikoxyz#282)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidtaikocha committed Jun 13, 2023
1 parent d932147 commit 1892891
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 83 deletions.
74 changes: 16 additions & 58 deletions pkg/rpc/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ import (
"github.com/taikoxyz/taiko-client/bindings/encoding"
)

var (
waitReceiptPollingInterval = 3 * time.Second
defaultWaitReceiptTimeout = 1 * time.Minute
)

// GetProtocolStateVariables gets the protocol states from TaikoL1 contract.
func GetProtocolStateVariables(
taikoL1Client *bindings.TaikoL1Client,
Expand All @@ -30,41 +35,24 @@ func GetProtocolStateVariables(
return &stateVars, nil
}

// WaitConfirmations won't return before N blocks confirmations have been seen
// on destination chain.
func WaitConfirmations(ctx context.Context, client *ethclient.Client, confirmations uint64, begin uint64) error {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()

for {
select {
case <-ctx.Done():
return ctx.Err()
case <-ticker.C:
latest, err := client.BlockNumber(ctx)
if err != nil {
log.Error("Fetch latest block number error: %w", err)
continue
}

if latest < begin+confirmations {
continue
}

return nil
}
}
}

// WaitReceipt keeps waiting until the given transaction has an execution
// receipt to know whether it was reverted or not.
func WaitReceipt(ctx context.Context, client *ethclient.Client, tx *types.Transaction) (*types.Receipt, error) {
ticker := time.NewTicker(time.Second)
ticker := time.NewTicker(waitReceiptPollingInterval)
defer ticker.Stop()

var (
ctxWithTimeout = ctx
cancel context.CancelFunc
)
if _, ok := ctx.Deadline(); !ok {
ctxWithTimeout, cancel = context.WithTimeout(ctx, defaultWaitReceiptTimeout)
defer cancel()
}

for {
select {
case <-ctx.Done():
case <-ctxWithTimeout.Done():
return nil, ctx.Err()
case <-ticker.C:
receipt, err := client.TransactionReceipt(ctx, tx.Hash())
Expand All @@ -81,36 +69,6 @@ func WaitReceipt(ctx context.Context, client *ethclient.Client, tx *types.Transa
}
}

// GetReceiptsByBlock fetches all transaction receipts in a block.
func GetReceiptsByBlock(ctx context.Context, cli *rpc.Client, block *types.Block) (types.Receipts, error) {
reqs := make([]rpc.BatchElem, block.Transactions().Len())
receipts := make([]*types.Receipt, block.Transactions().Len())

for i, tx := range block.Transactions() {
reqs[i] = rpc.BatchElem{
Method: "eth_getTransactionReceipt",
Args: []interface{}{tx.Hash()},
Result: &receipts[i],
}
}

if err := cli.BatchCallContext(ctx, reqs); err != nil {
return nil, err
}

for i := range reqs {
if reqs[i].Error != nil {
return nil, reqs[i].Error
}

if receipts[i] == nil {
return nil, fmt.Errorf("got null receipt of transaction %s", block.Transactions()[i].Hash())
}
}

return receipts, nil
}

// NeedNewSystemProof checks whether the L2 block still needs a new system proof.
func NeedNewSystemProof(ctx context.Context, cli *Client, id *big.Int, realProofSkipSize *big.Int) (bool, error) {
if realProofSkipSize == nil || realProofSkipSize.Uint64() <= 1 {
Expand Down
23 changes: 0 additions & 23 deletions pkg/rpc/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,10 @@ import (
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/stretchr/testify/require"
)

func TestWaitConfirmations(t *testing.T) {
client := newTestClient(t)

l1Head, err := client.L1.BlockNumber(context.Background())
require.Nil(t, err)

require.Nil(t, client.L1RawRPC.CallContext(context.Background(), nil, "hardhat_mine", hexutil.EncodeUint64(4)))

require.Nil(t, WaitConfirmations(context.Background(), client.L1, 4, l1Head))
}

func TestWaitReceiptTimeout(t *testing.T) {
client := newTestClient(t)

Expand All @@ -35,17 +23,6 @@ func TestWaitReceiptTimeout(t *testing.T) {
require.ErrorContains(t, err, "context deadline exceeded")
}

func TestGetReceiptsByBlock(t *testing.T) {
client := newTestClient(t)

l1Genesis, err := client.L1.BlockByNumber(context.Background(), common.Big0)
require.Nil(t, err)

receipts, err := GetReceiptsByBlock(context.Background(), client.L1RawRPC, l1Genesis)
require.Nil(t, err)
require.Empty(t, receipts)
}

func TestSetHead(t *testing.T) {
require.Nil(t, SetHead(context.Background(), newTestClient(t).L2RawRPC, common.Big0))
}
Expand Down
8 changes: 6 additions & 2 deletions proposer/proposer.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ import (
)

var (
errNoNewTxs = errors.New("no new transactions")
errNoNewTxs = errors.New("no new transactions")
waitReceiptTimeout = 1 * time.Minute
)

// Proposer keep proposing new transactions from L2 execution engine's tx pool at a fixed interval.
Expand Down Expand Up @@ -303,7 +304,10 @@ func (p *Proposer) ProposeTxList(
return encoding.TryParsingCustomError(err)
}

if _, err := rpc.WaitReceipt(ctx, p.rpc.L1, proposeTx); err != nil {
ctxWithTimeout, cancel := context.WithTimeout(ctx, waitReceiptTimeout)
defer cancel()

if _, err := rpc.WaitReceipt(ctxWithTimeout, p.rpc.L1, proposeTx); err != nil {
return err
}

Expand Down

0 comments on commit 1892891

Please sign in to comment.