2020-08-19 20:08:04 +00:00
package storage
import (
"context"
2020-08-20 04:49:10 +00:00
2020-08-19 20:08:04 +00:00
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
2020-09-07 03:49:10 +00:00
"github.com/filecoin-project/go-state-types/abi"
2020-10-07 17:41:07 +00:00
"github.com/filecoin-project/go-state-types/big"
2020-08-19 20:08:04 +00:00
2020-10-07 17:41:07 +00:00
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
2020-08-19 20:08:04 +00:00
"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 )
}
2020-10-07 17:41:07 +00:00
func AddressFor ( ctx context . Context , a addrSelectApi , mi miner . MinerInfo , use AddrUse , goodFunds , minFunds abi . TokenAmount ) ( address . Address , abi . TokenAmount , error ) {
2020-08-19 20:08:04 +00:00
switch use {
case PreCommitAddr , CommitAddr :
// always use worker, at least for now
2020-10-07 17:41:07 +00:00
return mi . Worker , big . Zero ( ) , nil
2020-08-19 20:08:04 +00:00
}
2020-10-26 15:28:39 +00:00
leastBad := mi . Worker
2020-10-07 17:41:07 +00:00
bestAvail := minFunds
2020-10-26 15:28:39 +00:00
for _ , addr := range append ( mi . ControlAddresses , mi . Owner , mi . Worker ) {
if maybeUseAddress ( ctx , a , addr , goodFunds , & leastBad , & bestAvail ) {
return leastBad , bestAvail , nil
2020-10-07 17:41:07 +00:00
}
2020-10-26 15:28:39 +00:00
}
2020-10-07 17:41:07 +00:00
2020-10-26 15:28:39 +00:00
if bestAvail . GreaterThan ( minFunds ) {
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 ) )
2020-08-19 20:08:04 +00:00
2020-10-26 15:28:39 +00:00
return leastBad , bestAvail , nil
2020-08-19 20:08:04 +00:00
}
2020-10-26 15:28:39 +00:00
// This most likely won't work, but can't hurt to try
2020-08-19 20:08:04 +00:00
2020-10-26 15:28:39 +00:00
workerBalance , err := a . WalletBalance ( ctx , mi . Worker )
2020-08-19 20:08:04 +00:00
if err != nil {
2020-10-26 15:28:39 +00:00
return address . Undef , big . Zero ( ) , xerrors . Errorf ( "checking owner balance: %w" , err )
2020-08-19 20:08:04 +00:00
}
2020-10-26 15:28:39 +00:00
log . Warnw ( "No address had enough funds to for minimum PoSt message Fee, selecting worker address as a fallback" , "address" , mi . Worker , "balance" , types . FIL ( workerBalance ) , "optimalFunds" , types . FIL ( goodFunds ) , "minFunds" , types . FIL ( minFunds ) )
return mi . Worker , workerBalance , 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 )
2020-10-07 17:41:07 +00:00
if err != nil {
2020-10-26 15:28:39 +00:00
log . Errorw ( "checking control address balance" , "addr" , addr , "error" , err )
return false
2020-08-19 20:08:04 +00:00
}
2020-10-26 15:28:39 +00:00
if b . GreaterThanEqual ( goodFunds ) {
k , err := a . StateAccountKey ( ctx , addr , types . EmptyTSK )
2020-10-07 17:41:07 +00:00
if err != nil {
2020-10-26 15:28:39 +00:00
log . Errorw ( "getting account key" , "error" , err )
return false
2020-10-07 17:41:07 +00:00
}
2020-10-26 15:28:39 +00:00
have , err := a . WalletHas ( ctx , k )
if err != nil {
log . Errorw ( "failed to check control address" , "addr" , addr , "error" , err )
return false
2020-10-07 17:41:07 +00:00
}
2020-10-26 15:28:39 +00:00
if ! have {
log . Errorw ( "don't have key" , "key" , k )
return false
2020-10-07 17:41:07 +00:00
}
2020-08-19 20:08:04 +00:00
2020-10-26 15:28:39 +00:00
* leastBad = addr
* bestAvail = b
return true
2020-10-07 17:41:07 +00:00
}
2020-10-26 15:28:39 +00:00
if b . GreaterThan ( * bestAvail ) {
* leastBad = addr
* bestAvail = b
2020-10-07 17:41:07 +00:00
}
2020-10-26 15:28:39 +00:00
log . Warnw ( "address didn't have enough funds for window post message" , "address" , addr , "required" , types . FIL ( goodFunds ) , "balance" , types . FIL ( b ) )
return false
2020-08-19 23:26:13 +00:00
}