lotus/cmd/lotus-storage-miner/init.go
2019-08-02 16:15:14 +02:00

186 lines
3.9 KiB
Go

package main
import (
"github.com/ipfs/go-datastore"
"github.com/libp2p/go-libp2p-core/peer"
"golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/go-lotus/build"
"github.com/filecoin-project/go-lotus/chain/actors"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/chain/wallet"
lcli "github.com/filecoin-project/go-lotus/cli"
"github.com/filecoin-project/go-lotus/node/repo"
)
var initCmd = &cli.Command{
Name: "init",
Usage: "Initialize a lotus storage miner repo",
Action: func(cctx *cli.Context) error {
log.Info("Initializing lotus storage miner")
log.Info("Checking if repo exists")
r, err := repo.NewFS(cctx.String(FlagStorageRepo))
if err != nil {
return err
}
ok, err := r.Exists()
if err != nil {
return err
}
if ok {
return xerrors.Errorf("repo at '%s' is already initialized", cctx.String(FlagStorageRepo))
}
log.Info("Trying to connect to full node RPC")
api, err := lcli.GetAPI(cctx) // TODO: consider storing full node address in config
if err != nil {
return err
}
ctx := lcli.ReqContext(cctx)
log.Info("Checking full node version")
v, err := api.Version(ctx)
if err != nil {
return err
}
if v.APIVersion&build.MinorMask != build.APIVersion&build.MinorMask {
return xerrors.Errorf("Remote API version didn't match (local %x, remote %x)", build.APIVersion, v.APIVersion)
}
log.Info("Initializing repo")
if err := r.Init(); err != nil {
return err
}
lr, err := r.Lock()
if err != nil {
return err
}
defer lr.Close()
log.Info("Initializing wallet")
ks, err := lr.KeyStore()
if err != nil {
return err
}
wallet, err := wallet.NewWallet(ks)
if err != nil {
return err
}
log.Info("Initializing libp2p identity")
p2pSk, err := lr.Libp2pIdentity()
if err != nil {
return err
}
peerid, err := peer.IDFromPrivateKey(p2pSk)
if err != nil {
return err
}
log.Info("Creating StorageMarket.CreateStorageMiner message")
defOwner, err := api.WalletDefaultAddress(ctx)
if err != nil {
return err
}
nonce, err := api.MpoolGetNonce(ctx, defOwner)
if err != nil {
return err
}
k, err := wallet.GenerateKey(types.KTSecp256k1) // TODO: review: is this right?
if err != nil {
return err
}
collateral := types.NewInt(1000) // TODO: Get this from params
params, err := actors.SerializeParams(actors.CreateStorageMinerParams{
Owner: defOwner,
Worker: k,
SectorSize: types.NewInt(actors.SectorSize),
PeerID: peerid,
})
if err != nil {
return err
}
createStorageMinerMsg := types.Message{
To: actors.StorageMarketAddress,
From: defOwner,
Nonce: nonce,
Value: collateral,
Method: actors.SMAMethods.CreateStorageMiner,
Params: params,
}
unsigned, err := createStorageMinerMsg.Serialize()
if err != nil {
return err
}
log.Info("Signing StorageMarket.CreateStorageMiner")
sig, err := api.WalletSign(ctx, defOwner, unsigned)
if err != nil {
return err
}
signed := &types.SignedMessage{
Message: createStorageMinerMsg,
Signature: *sig,
}
log.Infof("Pushing %s to Mpool", signed.Cid())
err = api.MpoolPush(ctx, signed)
if err != nil {
return err
}
log.Infof("Waiting for confirmation")
mw, err := api.ChainWaitMsg(ctx, signed.Cid())
if err != nil {
return err
}
addr, err := address.NewFromBytes(mw.Receipt.Return)
if err != nil {
return err
}
log.Infof("New storage miners address is: %s", addr)
ds, err := lr.Datastore("/metadata")
if err != nil {
return err
}
if err := ds.Put(datastore.NewKey("miner-address"), addr.Bytes()); err != nil {
return err
}
// TODO: Point to setting storage price, maybe do it interactively or something
log.Info("Storage miner successfully created, you can now start it with 'lotus-storage-miner run'")
return nil
},
}