Wire up miner control addresses, use for post
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"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 api.MinerInfo, use AddrUse, minFunds abi.TokenAmount) (address.Address, error) {
|
||||
switch use {
|
||||
case PreCommitAddr, CommitAddr:
|
||||
// always use worker, at least for now
|
||||
return mi.Worker, nil
|
||||
}
|
||||
|
||||
for _, addr := range mi.ControlAddresses {
|
||||
b, err := a.WalletBalance(ctx, addr)
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("checking control address balance: %w", err)
|
||||
}
|
||||
|
||||
if b.GreaterThanEqual(minFunds) {
|
||||
k, err := a.StateAccountKey(ctx, addr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
log.Errorw("getting account key", "error", err)
|
||||
continue
|
||||
}
|
||||
|
||||
have, err := a.WalletHas(ctx, k)
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("failed to check control address: %w", err)
|
||||
}
|
||||
|
||||
if !have {
|
||||
log.Errorw("don't have key", "key", k)
|
||||
continue
|
||||
}
|
||||
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
log.Warnw("control address didn't have enough funds for PoSt message", "address", addr, "required", types.FIL(minFunds), "balance", types.FIL(b))
|
||||
}
|
||||
|
||||
// Try to use the owner account if we can, fallback to worker if we can't
|
||||
|
||||
b, err := a.WalletBalance(ctx, mi.Owner)
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("checking owner balance: %w", err)
|
||||
}
|
||||
|
||||
if !b.GreaterThanEqual(minFunds) {
|
||||
return mi.Worker, nil
|
||||
}
|
||||
|
||||
k, err := a.StateAccountKey(ctx, mi.Owner, types.EmptyTSK)
|
||||
if err != nil {
|
||||
log.Errorw("getting owner account key", "error", err)
|
||||
return mi.Worker, nil
|
||||
}
|
||||
|
||||
have, err := a.WalletHas(ctx, k)
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("failed to check owner address: %w", err)
|
||||
}
|
||||
|
||||
if !have {
|
||||
return mi.Worker, nil
|
||||
}
|
||||
|
||||
return mi.Owner, nil
|
||||
}
|
||||
@@ -67,6 +67,7 @@ type storageMinerApi interface {
|
||||
StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*api.MarketDeal, error)
|
||||
StateMinerFaults(context.Context, address.Address, types.TipSetKey) (abi.BitField, error)
|
||||
StateMinerRecoveries(context.Context, address.Address, types.TipSetKey) (abi.BitField, error)
|
||||
StateAccountKey(context.Context, address.Address, types.TipSetKey) (address.Address, error)
|
||||
|
||||
MpoolPushMessage(context.Context, *types.Message, *api.MessageSendSpec) (*types.SignedMessage, error)
|
||||
|
||||
|
||||
+26
-3
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/go-bitfield"
|
||||
@@ -172,11 +173,11 @@ func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uin
|
||||
|
||||
msg := &types.Message{
|
||||
To: s.actor,
|
||||
From: s.worker,
|
||||
Method: builtin.MethodsMiner.DeclareFaultsRecovered,
|
||||
Params: enc,
|
||||
Value: types.NewInt(0),
|
||||
}
|
||||
s.setSender(ctx, msg)
|
||||
|
||||
sm, err := s.api.MpoolPushMessage(ctx, msg, &api.MessageSendSpec{MaxFee: abi.TokenAmount(s.feeCfg.MaxWindowPoStGasFee)})
|
||||
if err != nil {
|
||||
@@ -254,11 +255,11 @@ func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64,
|
||||
|
||||
msg := &types.Message{
|
||||
To: s.actor,
|
||||
From: s.worker,
|
||||
Method: builtin.MethodsMiner.DeclareFaults,
|
||||
Params: enc,
|
||||
Value: types.NewInt(0), // TODO: Is there a fee?
|
||||
}
|
||||
s.setSender(ctx, msg)
|
||||
|
||||
sm, err := s.api.MpoolPushMessage(ctx, msg, &api.MessageSendSpec{MaxFee: abi.TokenAmount(s.feeCfg.MaxWindowPoStGasFee)})
|
||||
if err != nil {
|
||||
@@ -460,11 +461,11 @@ func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.Submi
|
||||
|
||||
msg := &types.Message{
|
||||
To: s.actor,
|
||||
From: s.worker,
|
||||
Method: builtin.MethodsMiner.SubmitWindowedPoSt,
|
||||
Params: enc,
|
||||
Value: types.NewInt(1000), // currently hard-coded late fee in actor, returned if not late
|
||||
}
|
||||
s.setSender(ctx, msg)
|
||||
|
||||
// TODO: consider maybe caring about the output
|
||||
sm, err := s.api.MpoolPushMessage(ctx, msg, &api.MessageSendSpec{MaxFee: abi.TokenAmount(s.feeCfg.MaxWindowPoStGasFee)})
|
||||
@@ -490,3 +491,25 @@ func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.Submi
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *WindowPoStScheduler) setSender(ctx context.Context, msg *types.Message) {
|
||||
mi, err := s.api.StateMinerInfo(ctx, s.actor, types.EmptyTSK)
|
||||
if err != nil {
|
||||
log.Errorw("error getting miner info", "error", err)
|
||||
|
||||
// better than just failing
|
||||
msg.From = s.worker
|
||||
return
|
||||
}
|
||||
|
||||
minFunds := big.Add(msg.RequiredFunds(), msg.Value)
|
||||
|
||||
pa, err := AddressFor(ctx, s.api, mi, PoStAddr, minFunds)
|
||||
if err != nil {
|
||||
log.Errorw("error selecting address for post", "error", err)
|
||||
msg.From = s.worker
|
||||
return
|
||||
}
|
||||
|
||||
msg.From = pa
|
||||
}
|
||||
Reference in New Issue
Block a user