88 lines
2.4 KiB
Go
88 lines
2.4 KiB
Go
package storage
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/filecoin-project/go-address"
|
|
"github.com/filecoin-project/go-state-types/abi"
|
|
"github.com/filecoin-project/go-state-types/big"
|
|
|
|
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
|
"github.com/filecoin-project/lotus/chain/types"
|
|
)
|
|
|
|
type AddrUse int
|
|
|
|
const (
|
|
PreCommitAddr AddrUse = iota
|
|
CommitAddr
|
|
PoStAddr
|
|
)
|
|
|
|
type addrSelectApi interface {
|
|
WalletBalance(context.Context, address.Address) (types.BigInt, error)
|
|
WalletHas(context.Context, address.Address) (bool, error)
|
|
|
|
StateAccountKey(context.Context, address.Address, types.TipSetKey) (address.Address, error)
|
|
}
|
|
|
|
func AddressFor(ctx context.Context, a addrSelectApi, mi miner.MinerInfo, use AddrUse, goodFunds, minFunds abi.TokenAmount) (address.Address, abi.TokenAmount, error) {
|
|
switch use {
|
|
case PreCommitAddr, CommitAddr:
|
|
// always use worker, at least for now
|
|
return mi.Worker, big.Zero(), nil
|
|
}
|
|
|
|
leastBad := mi.Worker
|
|
bestAvail := minFunds
|
|
|
|
for _, addr := range append(mi.ControlAddresses, mi.Owner, mi.Worker) {
|
|
if maybeUseAddress(ctx, a, addr, goodFunds, &leastBad, &bestAvail) {
|
|
return leastBad, bestAvail, nil
|
|
}
|
|
}
|
|
|
|
log.Warnw("No address had enough funds to for full PoSt message Fee, selecting least bad address", "address", leastBad, "balance", types.FIL(bestAvail), "optimalFunds", types.FIL(goodFunds), "minFunds", types.FIL(minFunds))
|
|
|
|
return leastBad, bestAvail, nil
|
|
}
|
|
|
|
func maybeUseAddress(ctx context.Context, a addrSelectApi, addr address.Address, goodFunds abi.TokenAmount, leastBad *address.Address, bestAvail *abi.TokenAmount) bool {
|
|
b, err := a.WalletBalance(ctx, addr)
|
|
if err != nil {
|
|
log.Errorw("checking control address balance", "addr", addr, "error", err)
|
|
return false
|
|
}
|
|
|
|
if b.GreaterThanEqual(goodFunds) {
|
|
k, err := a.StateAccountKey(ctx, addr, types.EmptyTSK)
|
|
if err != nil {
|
|
log.Errorw("getting account key", "error", err)
|
|
return false
|
|
}
|
|
|
|
have, err := a.WalletHas(ctx, k)
|
|
if err != nil {
|
|
log.Errorw("failed to check control address", "addr", addr, "error", err)
|
|
return false
|
|
}
|
|
|
|
if !have {
|
|
log.Errorw("don't have key", "key", k)
|
|
return false
|
|
}
|
|
|
|
*leastBad = addr
|
|
*bestAvail = b
|
|
return true
|
|
}
|
|
|
|
if b.GreaterThan(*bestAvail) {
|
|
*leastBad = addr
|
|
*bestAvail = b
|
|
}
|
|
|
|
log.Warnw("address didn't have enough funds for window post message", "address", addr, "required", types.FIL(goodFunds), "balance", types.FIL(b))
|
|
return false
|
|
}
|