Wire up miner control addresses, use for post

This commit is contained in:
Łukasz Magiera
2020-08-20 01:17:03 +02:00
parent ed098390cb
commit 5ea61abfe1
6 changed files with 370 additions and 10 deletions
+92
View File
@@ -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
}
+1
View File
@@ -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
View File
@@ -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
}