Merge pull request #2223 from filecoin-project/feat/miner-msg-select-use-gas-price-is-more-better

miner: Use gas price when selecting messages
This commit is contained in:
Łukasz Magiera 2020-07-09 21:53:16 +02:00 committed by GitHub
commit 18199ff323
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -4,11 +4,14 @@ import (
"bytes" "bytes"
"context" "context"
"fmt" "fmt"
big2 "math/big"
"sort"
"sync" "sync"
"time" "time"
address "github.com/filecoin-project/go-address" address "github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin/power" "github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/crypto" "github.com/filecoin-project/specs-actors/actors/crypto"
lru "github.com/hashicorp/golang-lru" lru "github.com/hashicorp/golang-lru"
@ -482,10 +485,19 @@ func SelectMessages(ctx context.Context, al ActorLookup, ts *types.TipSet, msgs
fallback: al, fallback: al,
}).StateGetActor }).StateGetActor
out := make([]*types.SignedMessage, 0, build.BlockMessageLimit) type senderMeta struct {
lastReward abi.TokenAmount
lastGasLimit int64
gasReward []abi.TokenAmount
gasLimit []int64
msgs []*types.SignedMessage
}
inclNonces := make(map[address.Address]uint64) inclNonces := make(map[address.Address]uint64)
inclBalances := make(map[address.Address]types.BigInt) inclBalances := make(map[address.Address]big.Int)
inclCount := make(map[address.Address]int) outBySender := make(map[address.Address]*senderMeta)
tooLowFundMsgs := 0 tooLowFundMsgs := 0
tooHighNonceMsgs := 0 tooHighNonceMsgs := 0
@ -494,6 +506,10 @@ func SelectMessages(ctx context.Context, al ActorLookup, ts *types.TipSet, msgs
vmValid := time.Duration(0) vmValid := time.Duration(0)
getbal := time.Duration(0) getbal := time.Duration(0)
sort.Slice(msgs, func(i, j int) bool {
return msgs[i].Message.Nonce < msgs[j].Message.Nonce
})
for _, msg := range msgs { for _, msg := range msgs {
vmstart := time.Now() vmstart := time.Now()
@ -549,11 +565,78 @@ func SelectMessages(ctx context.Context, al ActorLookup, ts *types.TipSet, msgs
inclNonces[from] = msg.Message.Nonce + 1 inclNonces[from] = msg.Message.Nonce + 1
inclBalances[from] = types.BigSub(inclBalances[from], msg.Message.RequiredFunds()) inclBalances[from] = types.BigSub(inclBalances[from], msg.Message.RequiredFunds())
inclCount[from]++ sm := outBySender[from]
if sm == nil {
sm = &senderMeta{
lastReward: big.Zero(),
}
}
out = append(out, msg) sm.gasLimit = append(sm.gasLimit, sm.lastGasLimit+msg.Message.GasLimit)
if len(out) >= build.BlockMessageLimit { sm.lastGasLimit = sm.gasLimit[len(sm.gasLimit)-1]
break
estimatedReward := big.Mul(types.NewInt(uint64(msg.Message.GasLimit)), msg.Message.GasPrice)
// TODO: estimatedReward = estimatedReward * (guessActualGasUse(msg) / msg.GasLimit)
sm.gasReward = append(sm.gasReward, big.Add(sm.lastReward, estimatedReward))
sm.lastReward = sm.gasReward[len(sm.gasReward)-1]
sm.msgs = append(sm.msgs, msg)
outBySender[from] = sm
}
gasLimitLeft := int64(build.BlockGasLimit)
out := make([]*types.SignedMessage, 0, build.BlockMessageLimit)
{
for {
var bestSender address.Address
var nBest int
var bestGasToReward float64
// TODO: This is O(n^2)-ish, could use something like container/heap to cache this math
for sender, meta := range outBySender {
for n := range meta.msgs {
if meta.gasLimit[n] > gasLimitLeft {
break
}
if n+len(out) > build.BlockMessageLimit {
break
}
gasToReward, _ := new(big2.Float).SetInt(meta.gasReward[n].Int).Float64()
gasToReward /= float64(meta.gasLimit[n])
if gasToReward >= bestGasToReward {
bestSender = sender
nBest = n + 1
bestGasToReward = gasToReward
}
}
}
if nBest == 0 {
break // block gas limit reached
}
{
out = append(out, outBySender[bestSender].msgs[:nBest]...)
gasLimitLeft -= outBySender[bestSender].gasLimit[nBest-1]
outBySender[bestSender].msgs = outBySender[bestSender].msgs[nBest:]
outBySender[bestSender].gasLimit = outBySender[bestSender].gasLimit[nBest:]
outBySender[bestSender].gasReward = outBySender[bestSender].gasReward[nBest:]
if len(outBySender[bestSender].msgs) == 0 {
delete(outBySender, bestSender)
}
}
if len(out) >= build.BlockMessageLimit {
break
}
} }
} }