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

Fix max fee per gas less than block base fee #289

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
130 changes: 76 additions & 54 deletions ethstorage/miner/l1_mining_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,65 +85,21 @@ func (m *l1MiningAPI) GetDataHashes(ctx context.Context, contract common.Address

func (m *l1MiningAPI) SubmitMinedResult(ctx context.Context, contract common.Address, rst result, cfg Config) (common.Hash, error) {
m.lg.Debug("Submit mined result", "shard", rst.startShardId, "block", rst.blockNumber, "nonce", rst.nonce)
headerRlp, err := m.getRandaoProof(ctx, rst.blockNumber)
calldata, err := m.composeCalldata(ctx, rst)
if err != nil {
m.lg.Error("Failed to get randao proof", "error", err)
m.lg.Error("Failed to compose calldata", "error", err)
return common.Hash{}, err
}
uint256Type, _ := abi.NewType("uint256", "", nil)
uint256Array, _ := abi.NewType("uint256[]", "", nil)
addrType, _ := abi.NewType("address", "", nil)
bytes32Array, _ := abi.NewType("bytes32[]", "", nil)
bytesArray, _ := abi.NewType("bytes[]", "", nil)
bytesType, _ := abi.NewType("bytes", "", nil)
dataField, _ := abi.Arguments{
{Type: uint256Type},
{Type: uint256Type},
{Type: addrType},
{Type: uint256Type},
{Type: bytes32Array},
{Type: uint256Array},
{Type: bytesType},
{Type: bytesArray},
{Type: bytesArray},
}.Pack(
rst.blockNumber,
new(big.Int).SetUint64(rst.startShardId),
rst.miner,
new(big.Int).SetUint64(rst.nonce),
rst.encodedData,
rst.masks,
headerRlp,
rst.inclusiveProofs,
rst.decodeProof,
)
calldata := append(mineSig[0:4], dataField...)
m.lg.Debug("Submit mined result", "calldata", common.Bytes2Hex(calldata))
gasPrice := cfg.GasPrice
if gasPrice == nil || gasPrice.Cmp(common.Big0) == 0 {
suggested, err := m.SuggestGasPrice(ctx)
if err != nil {
m.lg.Error("Query gas price failed", "error", err.Error())
return common.Hash{}, err
}
gasPrice = suggested
m.lg.Info("Query gas price done", "gasPrice", gasPrice)
}
tip := cfg.PriorityGasPrice
if tip == nil || tip.Cmp(common.Big0) == 0 {
suggested, err := m.SuggestGasTipCap(ctx)
if err != nil {
m.lg.Error("Query gas tip cap failed", "error", err.Error())
suggested = common.Big0
}
tip = suggested
m.lg.Info("Query gas tip cap done", "gasTipGap", tip)
tip, gasFeeCap, predictedGasPrice, err := m.suggestGasPrices(ctx, cfg)
if err != nil {
m.lg.Error("Failed to suggest gas prices", "error", err)
return common.Hash{}, err
}
estimatedGas, err := m.EstimateGas(ctx, ethereum.CallMsg{
From: cfg.SignerAddr,
To: &contract,
GasTipCap: tip,
GasFeeCap: gasPrice,
GasFeeCap: gasFeeCap,
Value: common.Big0,
Data: calldata,
})
Expand All @@ -152,7 +108,7 @@ func (m *l1MiningAPI) SubmitMinedResult(ctx context.Context, contract common.Add
return common.Hash{}, fmt.Errorf("failed to estimate gas: %w", err)
}
m.lg.Info("Estimated gas done", "gas", estimatedGas)
cost := new(big.Int).Mul(new(big.Int).SetUint64(estimatedGas), gasPrice)
cost := new(big.Int).Mul(new(big.Int).SetUint64(estimatedGas), predictedGasPrice)
syntrust marked this conversation as resolved.
Show resolved Hide resolved
reward, err := m.GetMiningReward(rst.startShardId, rst.blockNumber.Int64())
if err != nil {
m.lg.Error("Query mining reward failed", "error", err.Error())
Expand All @@ -167,6 +123,7 @@ func (m *l1MiningAPI) SubmitMinedResult(ctx context.Context, contract common.Add
)
return common.Hash{}, errDropped
}

sign := cfg.SignerFnFactory(m.NetworkID)
nonce, err := m.NonceAt(ctx, cfg.SignerAddr, big.NewInt(rpc.LatestBlockNumber.Int64()))
if err != nil {
Expand All @@ -179,7 +136,7 @@ func (m *l1MiningAPI) SubmitMinedResult(ctx context.Context, contract common.Add
ChainID: m.NetworkID,
Nonce: nonce,
GasTipCap: tip,
GasFeeCap: gasPrice,
GasFeeCap: gasFeeCap,
Gas: gas,
To: &contract,
Value: common.Big0,
Expand All @@ -192,7 +149,7 @@ func (m *l1MiningAPI) SubmitMinedResult(ctx context.Context, contract common.Add
}
err = m.SendTransaction(ctx, signedTx)
if err != nil {
m.lg.Error("Send tx failed", "txNonce", nonce, "gasPrice", gasPrice, "error", err)
m.lg.Error("Send tx failed", "txNonce", nonce, "gasFeeCap", gasFeeCap, "error", err)
return common.Hash{}, err
}
m.lg.Info("Submit mined result done", "shard", rst.startShardId, "block", rst.blockNumber,
Expand Down Expand Up @@ -221,3 +178,68 @@ func (m *l1MiningAPI) getRandaoProof(ctx context.Context, blockNumber *big.Int)
}
return headerRlp, nil
}

func (m *l1MiningAPI) composeCalldata(ctx context.Context, rst result) ([]byte, error) {
headerRlp, err := m.getRandaoProof(ctx, rst.blockNumber)
if err != nil {
m.lg.Error("Failed to get randao proof", "error", err)
return nil, err
}
uint256Type, _ := abi.NewType("uint256", "", nil)
uint256Array, _ := abi.NewType("uint256[]", "", nil)
addrType, _ := abi.NewType("address", "", nil)
bytes32Array, _ := abi.NewType("bytes32[]", "", nil)
bytesArray, _ := abi.NewType("bytes[]", "", nil)
bytesType, _ := abi.NewType("bytes", "", nil)
dataField, _ := abi.Arguments{
{Type: uint256Type},
{Type: uint256Type},
{Type: addrType},
{Type: uint256Type},
{Type: bytes32Array},
{Type: uint256Array},
{Type: bytesType},
{Type: bytesArray},
{Type: bytesArray},
}.Pack(
rst.blockNumber,
new(big.Int).SetUint64(rst.startShardId),
rst.miner,
new(big.Int).SetUint64(rst.nonce),
rst.encodedData,
rst.masks,
headerRlp,
rst.inclusiveProofs,
rst.decodeProof,
)
calldata := append(mineSig[0:4], dataField...)
return calldata, nil
}

func (m *l1MiningAPI) suggestGasPrices(ctx context.Context, cfg Config) (*big.Int, *big.Int, *big.Int, error) {
tip := cfg.PriorityGasPrice
if tip == nil || tip.Cmp(common.Big0) == 0 {
suggested, err := m.SuggestGasTipCap(ctx)
if err != nil {
m.lg.Error("Query gas tip cap failed", "error", err.Error())
suggested = common.Big0
}
tip = suggested
m.lg.Info("Query gas tip cap done", "gasTipGap", tip)
}
gasFeeCap := cfg.GasPrice
predictedGasPrice := gasFeeCap
if gasFeeCap == nil || gasFeeCap.Cmp(common.Big0) == 0 {
blockHeader, err := m.HeaderByNumber(ctx, nil)
if err != nil {
m.lg.Error("Failed to get block header", "error", err)
return nil, nil, nil, err
}
// Doubling the base fee to ensure the transaction will remain marketable for six consecutive 100% full blocks.
gasFeeCap = new(big.Int).Add(tip, new(big.Int).Mul(blockHeader.BaseFee, common.Big2))
// Use `tip + base fee` as predicted gas price that will be used to evaluate the mining profit
predictedGasPrice = new(big.Int).Add(tip, blockHeader.BaseFee)
m.lg.Info("Compute gas fee cap done", "gasFeeCap", gasFeeCap, "predictedGasPrice", predictedGasPrice)
}
return tip, gasFeeCap, predictedGasPrice, nil
}
Loading