Compare commits

...

3 Commits

Author SHA1 Message Date
Solovyov1796
d4066b6a3d using merge sort 2025-02-10 19:35:13 +08:00
Solovyov1796
7900795654 update 2025-02-10 17:55:58 +08:00
Solovyov1796
6df54c84b5 update suggetsion gas price code 2025-02-10 14:37:15 +08:00

View File

@ -5,6 +5,7 @@ import (
"math/big" "math/big"
"sort" "sort"
"github.com/0glabs/0g-chain/chaincfg"
"github.com/cockroachdb/errors" "github.com/cockroachdb/errors"
abci "github.com/cometbft/cometbft/abci/types" abci "github.com/cometbft/cometbft/abci/types"
gethtypes "github.com/ethereum/go-ethereum/core/types" gethtypes "github.com/ethereum/go-ethereum/core/types"
@ -42,6 +43,13 @@ type (
FeeMarketKeeper interface { FeeMarketKeeper interface {
SetSuggestionGasPrice(ctx sdk.Context, gas *big.Int) SetSuggestionGasPrice(ctx sdk.Context, gas *big.Int)
} }
txnInfo struct {
gasPrice *big.Int
gasLimit uint64
nonce uint64
sender string
}
) )
func NewDefaultProposalHandler(mp mempool.Mempool, txVerifier ProposalTxVerifier, feemarketKeeper FeeMarketKeeper) *DefaultProposalHandler { func NewDefaultProposalHandler(mp mempool.Mempool, txVerifier ProposalTxVerifier, feemarketKeeper FeeMarketKeeper) *DefaultProposalHandler {
@ -106,7 +114,7 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan
return abci.ResponsePrepareProposal{Txs: h.txSelector.SelectedTxs()} return abci.ResponsePrepareProposal{Txs: h.txSelector.SelectedTxs()}
} }
gasPriceSlice := make([]*big.Int, 0, h.mempool.CountTx()) txnInfoMap := make(map[string][]*txnInfo, h.mempool.CountTx())
iterator := h.mempool.Select(ctx, req.Txs) iterator := h.mempool.Select(ctx, req.Txs)
selectedTxsSignersSeqs := make(map[string]uint64) selectedTxsSignersSeqs := make(map[string]uint64)
@ -114,17 +122,6 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan
for iterator != nil { for iterator != nil {
memTx := iterator.Tx() memTx := iterator.Tx()
for _, msg := range memTx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if ok {
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err == nil {
gp := txData.GetGasPrice()
gasPriceSlice = append(gasPriceSlice, gp)
}
}
}
sigs, err := memTx.(signing.SigVerifiableTx).GetSignaturesV2() sigs, err := memTx.(signing.SigVerifiableTx).GetSignaturesV2()
if err != nil { if err != nil {
panic(fmt.Errorf("failed to get signatures: %w", err)) panic(fmt.Errorf("failed to get signatures: %w", err))
@ -157,10 +154,42 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan
txSignersSeqs[signer] = nonce txSignersSeqs[signer] = nonce
} }
} }
if _, exists := txnInfoMap[signer]; !exists {
txnInfoMap[signer] = make([]*txnInfo, 0, 128)
}
txnInfoMap[signer] = append(txnInfoMap[signer], &txnInfo{
gasPrice: ethTx.GasPrice(),
gasLimit: ethTx.Gas(),
nonce: nonce,
sender: signer,
})
} }
} }
} }
} else { } else {
// ignore multisig case now
fee := memTx.(sdk.Fee)
if len(sigs) == 1 {
signer := sdk.AccAddress(sigs[0].PubKey.Address()).String()
if _, exists := txnInfoMap[signer]; !exists {
txnInfoMap[signer] = make([]*txnInfo, 0, 16)
}
evmGasPrice, err := utilCosmosDemonGasPriceToEvmDemonGasPrice(fee.GetAmount())
if err == nil {
txnInfoMap[signer] = append(txnInfoMap[signer], &txnInfo{
gasPrice: evmGasPrice,
gasLimit: utilCosmosDemonGasLimitToEvmDemonGasLimit(fee.GetGas()),
nonce: sigs[0].Sequence,
sender: signer,
})
}
}
for _, sig := range sigs { for _, sig := range sigs {
signer := sdk.AccAddress(sig.PubKey.Address()).String() signer := sdk.AccAddress(sig.PubKey.Address()).String()
seq, ok := selectedTxsSignersSeqs[signer] seq, ok := selectedTxsSignersSeqs[signer]
@ -222,23 +251,54 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan
iterator = iterator.Next() iterator = iterator.Next()
} }
sort.Slice(gasPriceSlice, func(i, j int) bool { if len(txnInfoMap) == 0 {
return gasPriceSlice[i].Cmp(gasPriceSlice[j]) > 0 h.feemarketKeeper.SetSuggestionGasPrice(ctx, big.NewInt(0))
}) } else {
senderCnt := 0
remaing := gasPriceSuggestionBlockNum * int64(maxBlockGas) txnCnt := 0
for _, gp := range gasPriceSlice { for sender := range txnInfoMap {
if remaing <= 0 { sort.Slice(txnInfoMap[sender], func(i, j int) bool {
h.feemarketKeeper.SetSuggestionGasPrice(ctx, gp) return txnInfoMap[sender][i].nonce < txnInfoMap[sender][j].nonce
break })
txnCnt += len(txnInfoMap[sender])
senderCnt++
} }
remaing -= gp.Int64()
}
if remaing > 0 { remaing := gasPriceSuggestionBlockNum * int64(maxBlockGas)
if len(gasPriceSlice) > 0 { for len(txnInfoMap) > 0 && remaing > 0 {
h.feemarketKeeper.SetSuggestionGasPrice(ctx, gasPriceSlice[len(gasPriceSlice)-1])
} else { // pop each sender's first continuous decreasing subsequence
txnCnt := 0
senderNonceSortedSliceGroup := make([][]*txnInfo, 0, senderCnt)
for sender := range txnInfoMap {
endIndex := findFirstContinuousDecreasingSubsequence(txnInfoMap[sender])
appendSlice := txnInfoMap[sender][:endIndex]
senderNonceSortedSliceGroup = append(senderNonceSortedSliceGroup, appendSlice)
txnCnt += len(appendSlice)
txnInfoMap[sender] = txnInfoMap[sender][endIndex:]
if len(txnInfoMap[sender]) == 0 {
delete(txnInfoMap, sender)
}
}
var gasPriceSortedSlice []*txnInfo
if len(senderNonceSortedSliceGroup) > 0 {
gasPriceSortedSlice = make([]*txnInfo, 0, len(senderNonceSortedSliceGroup[0]))
for i := range senderNonceSortedSliceGroup {
gasPriceSortedSlice = mergeSort(len(gasPriceSortedSlice)+len(senderNonceSortedSliceGroup[i]), gasPriceSortedSlice, senderNonceSortedSliceGroup[i])
}
}
for i := range gasPriceSortedSlice {
remaing -= int64(gasPriceSortedSlice[i].gasLimit)
if remaing <= 0 {
h.feemarketKeeper.SetSuggestionGasPrice(ctx, gasPriceSortedSlice[i].gasPrice)
break
}
}
}
if remaing > 0 {
h.feemarketKeeper.SetSuggestionGasPrice(ctx, big.NewInt(0)) h.feemarketKeeper.SetSuggestionGasPrice(ctx, big.NewInt(0))
} }
} }
@ -381,3 +441,64 @@ func (ts *defaultTxSelector) SelectTxForProposal(maxTxBytes, maxBlockGas uint64,
// check if we've reached capacity; if so, we cannot select any more transactions // check if we've reached capacity; if so, we cannot select any more transactions
return ts.totalTxBytes >= maxTxBytes || (maxBlockGas > 0 && (ts.totalTxGas >= maxBlockGas)) return ts.totalTxBytes >= maxTxBytes || (maxBlockGas > 0 && (ts.totalTxGas >= maxBlockGas))
} }
func utilCosmosDemonGasPriceToEvmDemonGasPrice(gasGroup sdk.Coins) (*big.Int, error) {
gasPrice := big.NewInt(0)
for _, coin := range gasGroup {
if coin.Denom == chaincfg.GasDenom {
thisGasPrice := big.NewInt(0).SetUint64(coin.Amount.Uint64())
thisGasPrice = thisGasPrice.Mul(thisGasPrice, big.NewInt(0).SetInt64(chaincfg.GasDenomConversionMultiplier))
gasPrice = gasPrice.Add(gasPrice, thisGasPrice)
} else {
return big.NewInt(0), fmt.Errorf("invalid denom: %s", coin.Denom)
}
}
return gasPrice, nil
}
func utilCosmosDemonGasLimitToEvmDemonGasLimit(gasLimit uint64) uint64 {
return gasLimit * chaincfg.GasDenomConversionMultiplier
}
func findFirstContinuousDecreasingSubsequence(data []*txnInfo) int {
ll := len(data)
if ll < 2 {
return ll
}
for i := 0; i < ll-1; i++ {
if data[i].gasPrice.Cmp(data[i+1].gasPrice) >= 0 {
end := i + 1
for ; end < ll && data[end-1].gasPrice.Cmp(data[end].gasPrice) > 0; end++ {
}
if end == ll || data[end-1].gasPrice.Cmp(data[end].gasPrice) <= 0 {
return end
}
} else {
return i + 1
}
}
return ll
}
func mergeSort(size int, left, right []*txnInfo) []*txnInfo {
result := make([]*txnInfo, 0, size)
i, j := 0, 0
for i < len(left) && j < len(right) {
if left[i].gasPrice.Cmp(right[j].gasPrice) > 0 {
result = append(result, left[i])
i++
} else {
result = append(result, right[j])
j++
}
}
result = append(result, left[i:]...)
result = append(result, right[j:]...)
return result
}