Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overshoot balance fix on estimate gas. #1970

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 22 additions & 12 deletions go/enclave/rpc/EstimateGas.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func EstimateGasExecute(builder *CallBuilder[CallParamsWithBlock, hexutil.Uint64
// TODO: Change to fixed time period quotes, rather than this.
publishingGas = publishingGas.Mul(publishingGas, gethcommon.Big2)

executionGasEstimate, err := rpc.doEstimateGas(builder.ctx, txArgs, blockNumber, rpc.config.GasLocalExecutionCapFlag)
executionGasEstimate, gasPrice, err := rpc.doEstimateGas(builder.ctx, txArgs, blockNumber, rpc.config.GasLocalExecutionCapFlag)
if err != nil {
err = fmt.Errorf("unable to estimate transaction - %w", err)

Expand All @@ -107,7 +107,17 @@ func EstimateGasExecute(builder *CallBuilder[CallParamsWithBlock, hexutil.Uint64
return nil
}

totalGasEstimate := hexutil.Uint64(publishingGas.Uint64() + uint64(executionGasEstimate))
totalGasEstimateUint64 := publishingGas.Uint64() + uint64(executionGasEstimate)
totalGasEstimate := hexutil.Uint64(totalGasEstimateUint64)
balance, err := rpc.chain.GetBalanceAtBlock(builder.ctx, *txArgs.From, blockNumber)
if err != nil {
return err
}

if balance.ToInt().Cmp(big.NewInt(0).Mul(gasPrice, big.NewInt(0).SetUint64(totalGasEstimateUint64))) < 0 {
return fmt.Errorf("insufficient funds for gas estimate")
}

builder.ReturnValue = &totalGasEstimate
return nil
}
Expand All @@ -116,7 +126,7 @@ func EstimateGasExecute(builder *CallBuilder[CallParamsWithBlock, hexutil.Uint64
// This is a copy of https://github.com/ethereum/go-ethereum/blob/master/internal/ethapi/api.go#L1055
// there's a high complexity to the method due to geth business rules (which is mimic'd here)
// once the work of obscuro gas mechanics is established this method should be simplified
func (rpc *EncryptionManager) doEstimateGas(ctx context.Context, args *gethapi.TransactionArgs, blkNumber *gethrpc.BlockNumber, gasCap uint64) (hexutil.Uint64, common.SystemError) { //nolint: gocognit
func (rpc *EncryptionManager) doEstimateGas(ctx context.Context, args *gethapi.TransactionArgs, blkNumber *gethrpc.BlockNumber, gasCap uint64) (hexutil.Uint64, *big.Int, common.SystemError) { //nolint: gocognit
// Binary search the gas requirement, as it may be higher than the amount used
var ( //nolint: revive
lo = params.TxGas - 1
Expand Down Expand Up @@ -148,7 +158,7 @@ func (rpc *EncryptionManager) doEstimateGas(ctx context.Context, args *gethapi.T
// Normalize the max fee per gas the call is willing to spend.
var feeCap *big.Int
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
return 0, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
return 0, gethcommon.Big0, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
} else if args.GasPrice != nil {
feeCap = args.GasPrice.ToInt()
} else if args.MaxFeePerGas != nil {
Expand All @@ -160,13 +170,13 @@ func (rpc *EncryptionManager) doEstimateGas(ctx context.Context, args *gethapi.T
if feeCap.BitLen() != 0 { //nolint:nestif
balance, err := rpc.chain.GetBalanceAtBlock(ctx, *args.From, blkNumber)
if err != nil {
return 0, fmt.Errorf("unable to fetch account balance - %w", err)
return 0, gethcommon.Big0, fmt.Errorf("unable to fetch account balance - %w", err)
}

available := new(big.Int).Set(balance.ToInt())
if args.Value != nil {
if args.Value.ToInt().Cmp(available) >= 0 {
return 0, errors.New("insufficient funds for transfer")
return 0, gethcommon.Big0, errors.New("insufficient funds for transfer")
}
available.Sub(available, args.Value.ToInt())
}
Expand Down Expand Up @@ -204,7 +214,7 @@ func (rpc *EncryptionManager) doEstimateGas(ctx context.Context, args *gethapi.T
// call or transaction will never be accepted no matter how much gas it is
// assigned. Return the error directly, don't struggle any more.
if err != nil {
return 0, err
return 0, gethcommon.Big0, err
}
if failed {
lo = mid
Expand All @@ -216,20 +226,20 @@ func (rpc *EncryptionManager) doEstimateGas(ctx context.Context, args *gethapi.T
if hi == cap { //nolint:nestif
failed, result, err := rpc.isGasEnough(ctx, args, hi, blkNumber)
if err != nil {
return 0, err
return 0, gethcommon.Big0, err
}
if failed {
if result != nil && result.Err != vm.ErrOutOfGas { //nolint: errorlint
if len(result.Revert()) > 0 {
return 0, newRevertError(result)
return 0, gethcommon.Big0, newRevertError(result)
}
return 0, result.Err
return 0, gethcommon.Big0, result.Err
}
// Otherwise, the specified gas cap is too low
return 0, fmt.Errorf("gas required exceeds allowance (%d)", cap)
return 0, gethcommon.Big0, fmt.Errorf("gas required exceeds allowance (%d)", cap)
}
}
return hexutil.Uint64(hi), nil
return hexutil.Uint64(hi), feeCap, nil
}

// Create a helper to check if a gas allowance results in an executable transaction
Expand Down
50 changes: 0 additions & 50 deletions go/host/enclave/guardian.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ func (g *Guardian) Start() error {
// Note: after HA work this will need additional check that we are the **active** sequencer enclave
go g.periodicBatchProduction()
go g.periodicRollupProduction()
//go g.periodicBundleSubmission()
}

// subscribe for L1 and P2P data
Expand Down Expand Up @@ -626,55 +625,6 @@ func (g *Guardian) periodicRollupProduction() {
}
}

func (g *Guardian) periodicBundleSubmission() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did you mean to remove this?
Shouldn't matter, but it might cause issues when cherry-picking to main

defer g.logger.Info("Stopping bundle submission")

interval := g.crossChainInterval
g.logger.Info("Starting cross chain bundle submission", "interval", interval)

bundleSubmissionTicker := time.NewTicker(interval)

fromSequenceNumber := uint64(0)

for {
select {
case <-bundleSubmissionTicker.C:
from, to, err := g.sl.L1Publisher().GetBundleRangeFromManagementContract()
if err != nil {
g.logger.Error("Unable to get bundle range from management contract", log.ErrKey, err)
continue
}

if from.Uint64() > fromSequenceNumber {
fromSequenceNumber = from.Uint64()
}

bundle, err := g.enclaveClient.ExportCrossChainData(context.Background(), fromSequenceNumber, to.Uint64())
if err != nil {
if !errors.Is(err, errutil.ErrCrossChainBundleNoBatches) {
g.logger.Error("Unable to export cross chain bundle from enclave", log.ErrKey, err)
}
continue
}

if len(bundle.CrossChainRootHashes) == 0 {
g.logger.Debug("No cross chain data to submit")
fromSequenceNumber = to.Uint64() + 1
continue
}

err = g.sl.L1Publisher().PublishCrossChainBundle(bundle)
if err != nil {
g.logger.Error("Unable to publish cross chain bundle", log.ErrKey, err)
continue
}
case <-g.hostInterrupter.Done():
bundleSubmissionTicker.Stop()
return
}
}
}

func (g *Guardian) streamEnclaveData() {
defer g.logger.Info("Stopping enclave data stream")
g.logger.Info("Starting L2 update stream from enclave")
Expand Down