Skip to content

Commit

Permalink
Add commands to change the worker key
Browse files Browse the repository at this point in the history
  • Loading branch information
Stebalien committed Oct 21, 2020
1 parent c767399 commit fed47cd
Show file tree
Hide file tree
Showing 6 changed files with 230 additions and 41 deletions.
195 changes: 195 additions & 0 deletions cmd/lotus-storage-miner/actor.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ var actorCmd = &cli.Command{
actorSetPeeridCmd,
actorSetOwnerCmd,
actorControl,
actorProposeChangeWorker,
actorConfirmChangeWorker,
},
}

Expand Down Expand Up @@ -701,3 +703,196 @@ var actorSetOwnerCmd = &cli.Command{
return nil
},
}

var actorProposeChangeWorker = &cli.Command{
Name: "propose-change-worker",
Usage: "Propose a worker address change",
ArgsUsage: "[address]",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "really-do-it",
Usage: "Actually send transaction performing the action",
Value: false,
},
},
Action: func(cctx *cli.Context) error {
if !cctx.Bool("really-do-it") {
fmt.Println("Pass --really-do-it to actually execute this action")
return nil
}

if !cctx.Args().Present() {
return fmt.Errorf("must pass address of new worker address")
}

nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
if err != nil {
return err
}
defer closer()

api, acloser, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer acloser()

ctx := lcli.ReqContext(cctx)

na, err := address.NewFromString(cctx.Args().First())
if err != nil {
return err
}

newAddr, err := api.StateLookupID(ctx, na, types.EmptyTSK)
if err != nil {
return err
}

maddr, err := nodeApi.ActorAddress(ctx)
if err != nil {
return err
}

mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
if err != nil {
return err
}

if mi.NewWorker.Empty() {
if mi.Worker == newAddr {
return xerrors.Errorf("worker address already set to %s", newAddr)
}
} else {
if mi.NewWorker == newAddr {
return xerrors.Errorf("change to worker address %s already pending", newAddr)
}
}

cwp := &miner0.ChangeWorkerAddressParams{
NewWorker: newAddr,
NewControlAddrs: mi.ControlAddresses,
}

sp, err := actors.SerializeParams(cwp)
if err != nil {
return xerrors.Errorf("serializing params: %w", err)
}

smsg, err := api.MpoolPushMessage(ctx, &types.Message{
From: mi.Owner,
To: maddr,
Method: builtin2.MethodsMiner.ChangeWorkerAddress,
Value: big.Zero(),
Params: sp,
}, nil)
if err != nil {
return xerrors.Errorf("mpool push: %w", err)
}

fmt.Println("Propose Message CID:", smsg.Cid())

// wait for it to get mined into a block
wait, err := api.StateWaitMsg(ctx, smsg.Cid(), build.MessageConfidence)
if err != nil {
return err
}

// check it executed successfully
if wait.Receipt.ExitCode != 0 {
fmt.Println("Propose worker change failed!")
return err
}

return nil
},
}

var actorConfirmChangeWorker = &cli.Command{
Name: "confirm-change-worker",
Usage: "Confirm a worker address change",
ArgsUsage: "[address]",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "really-do-it",
Usage: "Actually send transaction performing the action",
Value: false,
},
},
Action: func(cctx *cli.Context) error {
if !cctx.Bool("really-do-it") {
fmt.Println("Pass --really-do-it to actually execute this action")
return nil
}

if !cctx.Args().Present() {
return fmt.Errorf("must pass address of new worker address")
}

nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
if err != nil {
return err
}
defer closer()

api, acloser, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer acloser()

ctx := lcli.ReqContext(cctx)

na, err := address.NewFromString(cctx.Args().First())
if err != nil {
return err
}

newAddr, err := api.StateLookupID(ctx, na, types.EmptyTSK)
if err != nil {
return err
}

maddr, err := nodeApi.ActorAddress(ctx)
if err != nil {
return err
}

mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
if err != nil {
return err
}

if mi.NewWorker.Empty() {
return xerrors.Errorf("no worker key change proposed")
} else if mi.NewWorker != newAddr {
return xerrors.Errorf("worker key %s does not match current worker key proposal %s", newAddr, mi.NewWorker)
}

smsg, err := api.MpoolPushMessage(ctx, &types.Message{
From: mi.Owner,
To: maddr,
Method: builtin2.MethodsMiner.ConfirmUpdateWorkerKey,
Value: big.Zero(),
}, nil)
if err != nil {
return xerrors.Errorf("mpool push: %w", err)
}

fmt.Println("Confirm Message CID:", smsg.Cid())

// wait for it to get mined into a block
wait, err := api.StateWaitMsg(ctx, smsg.Cid(), build.MessageConfidence)
if err != nil {
return err
}

// check it executed successfully
if wait.Receipt.ExitCode != 0 {
fmt.Println("Worker change failed!")
return err
}

return nil
},
}
14 changes: 2 additions & 12 deletions node/modules/storageminer.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,22 +186,12 @@ func StorageMiner(fc config.MinerFeeConfig) func(params StorageMinerParams) (*st

ctx := helpers.LifecycleCtx(mctx, lc)

mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
fps, err := storage.NewWindowedPoStScheduler(api, fc, sealer, sealer, j, maddr)
if err != nil {
return nil, err
}

worker, err := api.StateAccountKey(ctx, mi.Worker, types.EmptyTSK)
if err != nil {
return nil, err
}

fps, err := storage.NewWindowedPoStScheduler(api, fc, sealer, sealer, j, maddr, worker)
if err != nil {
return nil, err
}

sm, err := storage.NewMiner(api, maddr, worker, h, ds, sealer, sc, verif, gsd, fc, j)
sm, err := storage.NewMiner(api, maddr, h, ds, sealer, sc, verif, gsd, fc, j)
if err != nil {
return nil, err
}
Expand Down
20 changes: 14 additions & 6 deletions storage/miner.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ type Miner struct {
sc sealing.SectorIDCounter
verif ffiwrapper.Verifier

maddr address.Address
worker address.Address
maddr address.Address

getSealConfig dtypes.GetSealingConfigFunc
sealing *sealing.Sealing
Expand Down Expand Up @@ -112,7 +111,7 @@ type storageMinerApi interface {
WalletHas(context.Context, address.Address) (bool, error)
}

func NewMiner(api storageMinerApi, maddr, worker address.Address, h host.Host, ds datastore.Batching, sealer sectorstorage.SectorManager, sc sealing.SectorIDCounter, verif ffiwrapper.Verifier, gsd dtypes.GetSealingConfigFunc, feeCfg config.MinerFeeConfig, journal journal.Journal) (*Miner, error) {
func NewMiner(api storageMinerApi, maddr address.Address, h host.Host, ds datastore.Batching, sealer sectorstorage.SectorManager, sc sealing.SectorIDCounter, verif ffiwrapper.Verifier, gsd dtypes.GetSealingConfigFunc, feeCfg config.MinerFeeConfig, journal journal.Journal) (*Miner, error) {
m := &Miner{
api: api,
feeCfg: feeCfg,
Expand All @@ -123,7 +122,6 @@ func NewMiner(api storageMinerApi, maddr, worker address.Address, h host.Host, d
verif: verif,

maddr: maddr,
worker: worker,
getSealConfig: gsd,
journal: journal,
sealingEvtType: journal.RegisterEventType("storage", "sealing_states"),
Expand Down Expand Up @@ -175,7 +173,17 @@ func (m *Miner) Stop(ctx context.Context) error {
}

func (m *Miner) runPreflightChecks(ctx context.Context) error {
has, err := m.api.WalletHas(ctx, m.worker)
mi, err := m.api.StateMinerInfo(ctx, m.maddr, types.EmptyTSK)
if err != nil {
return xerrors.Errorf("failed to resolve miner info: %w", err)
}

workerKey, err := m.api.StateAccountKey(ctx, mi.Worker, types.EmptyTSK)
if err != nil {
return xerrors.Errorf("failed to resolve worker key: %w", err)
}

has, err := m.api.WalletHas(ctx, workerKey)
if err != nil {
return xerrors.Errorf("failed to check wallet for worker key: %w", err)
}
Expand All @@ -184,7 +192,7 @@ func (m *Miner) runPreflightChecks(ctx context.Context) error {
return errors.New("key for worker not found in local wallet")
}

log.Infof("starting up miner %s, worker addr %s", m.maddr, m.worker)
log.Infof("starting up miner %s, worker addr %s", m.maddr, workerKey)
return nil
}

Expand Down
32 changes: 16 additions & 16 deletions storage/wdpost_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,13 +289,14 @@ func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uin

msg := &types.Message{
To: s.actor,
From: s.worker,
Method: builtin0.MethodsMiner.DeclareFaultsRecovered,
Params: enc,
Value: types.NewInt(0),
}
spec := &api.MessageSendSpec{MaxFee: abi.TokenAmount(s.feeCfg.MaxWindowPoStGasFee)}
s.setSender(ctx, msg, spec)
if err := s.setSender(ctx, msg, spec); err != nil {
return recoveries, nil, err
}

sm, err := s.api.MpoolPushMessage(ctx, msg, &api.MessageSendSpec{MaxFee: abi.TokenAmount(s.feeCfg.MaxWindowPoStGasFee)})
if err != nil {
Expand Down Expand Up @@ -373,13 +374,14 @@ func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64,

msg := &types.Message{
To: s.actor,
From: s.worker,
Method: builtin0.MethodsMiner.DeclareFaults,
Params: enc,
Value: types.NewInt(0), // TODO: Is there a fee?
}
spec := &api.MessageSendSpec{MaxFee: abi.TokenAmount(s.feeCfg.MaxWindowPoStGasFee)}
s.setSender(ctx, msg, spec)
if err := s.setSender(ctx, msg, spec); err != nil {
return faults, nil, err
}

sm, err := s.api.MpoolPushMessage(ctx, msg, spec)
if err != nil {
Expand Down Expand Up @@ -718,13 +720,14 @@ func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.Submi

msg := &types.Message{
To: s.actor,
From: s.worker,
Method: builtin0.MethodsMiner.SubmitWindowedPoSt,
Params: enc,
Value: types.NewInt(0),
}
spec := &api.MessageSendSpec{MaxFee: abi.TokenAmount(s.feeCfg.MaxWindowPoStGasFee)}
s.setSender(ctx, msg, spec)
if err := s.setSender(ctx, msg, spec); err != nil {
return nil, err
}

// TODO: consider maybe caring about the output
sm, err := s.api.MpoolPushMessage(ctx, msg, spec)
Expand Down Expand Up @@ -752,21 +755,18 @@ func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.Submi
return sm, nil
}

func (s *WindowPoStScheduler) setSender(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec) {
func (s *WindowPoStScheduler) setSender(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec) error {
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
return xerrors.Errorf("error getting miner info: %w", err)
}
// use the worker as a fallback
msg.From = mi.Worker

gm, err := s.api.GasEstimateMessageGas(ctx, msg, spec, types.EmptyTSK)
if err != nil {
log.Errorw("estimating gas", "error", err)
msg.From = s.worker
return
return nil
}
*msg = *gm

Expand All @@ -775,9 +775,9 @@ func (s *WindowPoStScheduler) setSender(ctx context.Context, msg *types.Message,
pa, err := AddressFor(ctx, s.api, mi, PoStAddr, minFunds)
if err != nil {
log.Errorw("error selecting address for window post", "error", err)
msg.From = s.worker
return
return nil
}

msg.From = pa
return nil
}
2 changes: 0 additions & 2 deletions storage/wdpost_run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ func TestWDPostDoPost(t *testing.T) {

proofType := abi.RegisteredPoStProof_StackedDrgWindow2KiBV1
postAct := tutils.NewIDAddr(t, 100)
workerAct := tutils.NewIDAddr(t, 101)

mockStgMinerAPI := newMockStorageMinerAPI()

Expand Down Expand Up @@ -168,7 +167,6 @@ func TestWDPostDoPost(t *testing.T) {
faultTracker: &mockFaultTracker{},
proofType: proofType,
actor: postAct,
worker: workerAct,
journal: journal.NilJournal(),
}

Expand Down
Loading

0 comments on commit fed47cd

Please sign in to comment.