From 663b13f1c18cb70978414988c3359b4df0dc2dce Mon Sep 17 00:00:00 2001 From: badgersrus <43809877+badgersrus@users.noreply.github.com> Date: Thu, 31 Oct 2024 17:00:40 +0100 Subject: [PATCH] Tweak blob gas pricing and improve debug wallet timeout (#2119) * tweak blob gas pricing and improve timeout on debug wallet --- go/ethadapter/geth_rpc_client.go | 8 +- go/host/l1/publisher.go | 85 ++++++++++--------- .../smartcontract/debug_mgmt_contract_lib.go | 11 +-- integration/smartcontract/debug_wallet.go | 58 +++++-------- .../smartcontract/smartcontracts_test.go | 4 +- 5 files changed, 78 insertions(+), 88 deletions(-) diff --git a/go/ethadapter/geth_rpc_client.go b/go/ethadapter/geth_rpc_client.go index e8233c1646..a9290cad6e 100644 --- a/go/ethadapter/geth_rpc_client.go +++ b/go/ethadapter/geth_rpc_client.go @@ -359,10 +359,14 @@ func (e *gethRPCClient) prepareBlobTxToRetry(ctx context.Context, txData types.T } blobFeeCap := calcBlobFeeCap(blobBaseFee, retryNumber) + baseFee := head.BaseFee + gasFeeCap := new(big.Int).Mul(baseFee, big.NewInt(2)) + gasFeeCap.Add(gasFeeCap, retryPrice) + return &types.BlobTx{ Nonce: nonce, - GasTipCap: uint256.MustFromBig(retryPrice), // aka maxPriorityFeePerGas - GasFeeCap: uint256.MustFromBig(retryPrice), // aka. maxFeePerGas + GasTipCap: uint256.MustFromBig(retryPrice), // maxPriorityFeePerGas + GasFeeCap: uint256.MustFromBig(gasFeeCap), // maxFeePerGas = (baseFee * 2) + maxPriorityFeePerGas Gas: gasLimit, To: *unEstimatedTx.To(), Value: uint256.MustFromBig(value), diff --git a/go/host/l1/publisher.go b/go/host/l1/publisher.go index 47f8a873f9..5675deacaa 100644 --- a/go/host/l1/publisher.go +++ b/go/host/l1/publisher.go @@ -231,55 +231,60 @@ func (p *Publisher) PublishSecretResponse(secretResponse *common.ProducedSecretR // ExtractRelevantTenTransactions will extract any transactions from the block that are relevant to TEN // todo (#2495) we should monitor for relevant L1 events instead of scanning every transaction in the block func (p *Publisher) ExtractRelevantTenTransactions(block *types.Block, receipts types.Receipts) ([]*common.TxAndReceiptAndBlobs, []*ethadapter.L1RollupTx, []*ethadapter.L1SetImportantContractsTx) { - txWithReceiptsAndBlobs := make([]*common.TxAndReceiptAndBlobs, 0) - rollupTxs := make([]*ethadapter.L1RollupTx, 0) - contractAddressTxs := make([]*ethadapter.L1SetImportantContractsTx, 0) - - txs := block.Transactions() - for i, rec := range receipts { - if rec.BlockNumber == nil { - continue // Skip non-relevant transactions - } + // temporarily add this host stopping check to prevent sim test failures until a more robust solution is implemented + for !p.hostStopper.IsStopping() { + txWithReceiptsAndBlobs := make([]*common.TxAndReceiptAndBlobs, 0) + rollupTxs := make([]*ethadapter.L1RollupTx, 0) + contractAddressTxs := make([]*ethadapter.L1SetImportantContractsTx, 0) + + txs := block.Transactions() + for i, rec := range receipts { + if rec.BlockNumber == nil { + continue // Skip non-relevant transactions + } - decodedTx := p.mgmtContractLib.DecodeTx(txs[i]) - var blobs []*kzg4844.Blob - var err error + decodedTx := p.mgmtContractLib.DecodeTx(txs[i]) + var blobs []*kzg4844.Blob + var err error - switch typedTx := decodedTx.(type) { - case *ethadapter.L1SetImportantContractsTx: - contractAddressTxs = append(contractAddressTxs, typedTx) - case *ethadapter.L1RollupHashes: - blobs, err = p.blobResolver.FetchBlobs(p.sendingContext, block.Header(), typedTx.BlobHashes) - if err != nil { - if errors.Is(err, ethereum.NotFound) { - p.logger.Crit("Blobs were not found on beacon chain or archive service", "block", block.Hash(), "error", err) - } else { - p.logger.Crit("could not fetch blobs", log.ErrKey, err) + switch typedTx := decodedTx.(type) { + case *ethadapter.L1SetImportantContractsTx: + contractAddressTxs = append(contractAddressTxs, typedTx) + case *ethadapter.L1RollupHashes: + blobs, err = p.blobResolver.FetchBlobs(p.sendingContext, block.Header(), typedTx.BlobHashes) + // temporarily add this host stopping check to prevent sim test failures until a more robust solution is implemented + if err != nil { + if errors.Is(err, ethereum.NotFound) { + p.logger.Crit("Blobs were not found on beacon chain or archive service", "block", block.Hash(), "error", err) + } else { + p.logger.Crit("could not fetch blobs", log.ErrKey, err) + } + continue } - continue - } - encodedRlp, err := ethadapter.DecodeBlobs(blobs) - if err != nil { - p.logger.Crit("could not decode blobs.", log.ErrKey, err) - continue - } + encodedRlp, err := ethadapter.DecodeBlobs(blobs) + if err != nil { + p.logger.Crit("could not decode blobs.", log.ErrKey, err) + continue + } - rlp := ðadapter.L1RollupTx{ - Rollup: encodedRlp, + rlp := ðadapter.L1RollupTx{ + Rollup: encodedRlp, + } + rollupTxs = append(rollupTxs, rlp) } - rollupTxs = append(rollupTxs, rlp) + + // compile the tx, receipt and blobs into a single struct for submission to the enclave + txWithReceiptsAndBlobs = append(txWithReceiptsAndBlobs, &common.TxAndReceiptAndBlobs{ + Tx: txs[i], + Receipt: rec, + Blobs: blobs, + }) } - // compile the tx, receipt and blobs into a single struct for submission to the enclave - txWithReceiptsAndBlobs = append(txWithReceiptsAndBlobs, &common.TxAndReceiptAndBlobs{ - Tx: txs[i], - Receipt: rec, - Blobs: blobs, - }) + return txWithReceiptsAndBlobs, rollupTxs, contractAddressTxs } - - return txWithReceiptsAndBlobs, rollupTxs, contractAddressTxs + return nil, nil, nil } // FindSecretResponseTx will scan the block for any secret response transactions. This is separate from the above method diff --git a/integration/smartcontract/debug_mgmt_contract_lib.go b/integration/smartcontract/debug_mgmt_contract_lib.go index bab07b5a5c..cf7d29b7ec 100644 --- a/integration/smartcontract/debug_mgmt_contract_lib.go +++ b/integration/smartcontract/debug_mgmt_contract_lib.go @@ -43,19 +43,20 @@ func (d *debugMgmtContractLib) AwaitedIssueRollup(rollup common.ExtRollup, clien } txData, err := d.CreateBlobRollup(ðadapter.L1RollupTx{Rollup: encodedRollup}) if err != nil { - return err + return fmt.Errorf("failed to create blob rollup: %w", err) } issuedTx, receipt, err := w.AwaitedSignAndSendTransaction(client, txData) if err != nil { - return err + return fmt.Errorf("failed to send and await transaction: %w", err) } if receipt.Status != types.ReceiptStatusSuccessful { - _, err := w.debugTransaction(client, issuedTx) - if err != nil { - return fmt.Errorf("transaction should have succeeded, expected %d got %d - reason: %w", types.ReceiptStatusSuccessful, receipt.Status, err) + debugOutput, debugErr := w.debugTransaction(client, issuedTx) + if debugErr != nil { + return fmt.Errorf("transaction failed with status %d and debug failed: %v", receipt.Status, debugErr) } + return fmt.Errorf("transaction failed with status %d: %s", receipt.Status, string(debugOutput)) } // rollup meta data is actually stored diff --git a/integration/smartcontract/debug_wallet.go b/integration/smartcontract/debug_wallet.go index 20941b6bc5..b3c277be19 100644 --- a/integration/smartcontract/debug_wallet.go +++ b/integration/smartcontract/debug_wallet.go @@ -2,79 +2,61 @@ package smartcontract import ( "context" - "errors" "fmt" "time" "github.com/ethereum/go-ethereum" + "github.com/ten-protocol/go-ten/go/common/retry" + "github.com/ethereum/go-ethereum/core/types" "github.com/ten-protocol/go-ten/go/ethadapter" "github.com/ten-protocol/go-ten/go/wallet" ) -var _timeout = 180 * time.Second - // debugWallet is a wrapper around the wallet that simplifies commonly used functions type debugWallet struct { wallet.Wallet + receiptTimeout time.Duration } -// newDebugWallet returns a new debug wrapped wallet -func newDebugWallet(w wallet.Wallet) *debugWallet { - return &debugWallet{w} +func newDebugWallet(w wallet.Wallet, timeout time.Duration) *debugWallet { + return &debugWallet{ + Wallet: w, + receiptTimeout: timeout, + } } // AwaitedSignAndSendTransaction signs a tx, issues the tx and awaits the tx to be minted into a block func (w *debugWallet) AwaitedSignAndSendTransaction(client ethadapter.EthClient, txData types.TxData) (*types.Transaction, *types.Receipt, error) { - var err error - - txData, err = client.PrepareTransactionToSend(context.Background(), txData, w.Address()) + txData, err := client.PrepareTransactionToSend(context.Background(), txData, w.Address()) if err != nil { w.SetNonce(w.GetNonce() - 1) return nil, nil, err } - signedTx, err := w.SignAndSendTransaction(client, txData) - if err != nil { - return nil, nil, err - } - receipt, err := waitTxResult(client, signedTx) - if err != nil { - return nil, nil, err - } - return signedTx, receipt, nil -} -// SignAndSendTransaction signs and sends a tx -func (w *debugWallet) SignAndSendTransaction(client ethadapter.EthClient, txData types.TxData) (*types.Transaction, error) { signedTx, err := w.SignTransaction(txData) if err != nil { - return nil, err + return nil, nil, err } err = client.SendTransaction(signedTx) if err != nil { - return nil, err + return nil, nil, err } - return signedTx, nil -} - -// waitTxResult waits for a tx to be minted into a block -func waitTxResult(client ethadapter.EthClient, tx *types.Transaction) (*types.Receipt, error) { var receipt *types.Receipt - var err error - for start := time.Now(); time.Since(start) < _timeout; time.Sleep(time.Second) { - receipt, err = client.TransactionReceipt(tx.Hash()) + err = retry.Do(func() error { + receipt, err = client.TransactionReceipt(signedTx.Hash()) if err != nil { - if errors.Is(err, ethereum.NotFound) { - continue - } - return nil, err + return err } + if receipt == nil { + return fmt.Errorf("no receipt yet") + } + return nil + }, retry.NewTimeoutStrategy(w.receiptTimeout, time.Second)) - return receipt, nil - } - return nil, fmt.Errorf("transaction not minted after timeout") + return signedTx, receipt, err } func (w *debugWallet) debugTransaction(client ethadapter.EthClient, tx *types.Transaction) ([]byte, error) { diff --git a/integration/smartcontract/smartcontracts_test.go b/integration/smartcontract/smartcontracts_test.go index ad4d050d80..8914d96357 100644 --- a/integration/smartcontract/smartcontracts_test.go +++ b/integration/smartcontract/smartcontracts_test.go @@ -86,15 +86,13 @@ func runGethNetwork(t *testing.T) *netInfo { } func TestManagementContract(t *testing.T) { - t.Skip("Skipping as it's too flaky.") - // run tests on one network sim := runGethNetwork(t) defer sim.eth2Network.Stop() //nolint: errcheck // set up the client and the (debug) wallet client := sim.ethClients[0] - w := newDebugWallet(sim.wallets[0]) + w := newDebugWallet(sim.wallets[0], 30*time.Second) for name, test := range map[string]func(*testing.T, *debugMgmtContractLib, *debugWallet, ethadapter.EthClient){ "secretCannotBeInitializedTwice": secretCannotBeInitializedTwice,