91 lines
13 KiB
Markdown
91 lines
13 KiB
Markdown
|
# Creating a storage miner
|
||
|
|
||
|
This document explains the code flow of the [storage miner](https://filecoin-project.github.io/specs/#systems__filecoin_mining) creation process. It describes the flow on two dimensions: at the network level, from the local node to the rest of the Filecoin network, and at the VM level, from the CLI commands to the new chain state. It assumes the reader is already familiar with the general Lotus [architecture](architecture-2.md), relying especially on the descriptions of the CLI/API interface and the VM chain state.
|
||
|
|
||
|
Note we are not following the [Storage Mining](https://lotu.sh/en+mining) user documentation where the miner is created along with the owner through the faucet, but we do those in separate stages try to exercise what will be the closest code path to Mainnet, using the `createStorageMiner()` call in the CLI (when `--actor` is not provided).
|
||
|
|
||
|
FIXME: Check that all the information it assumes throughout this document is actually present in the main architecture doc.
|
||
|
|
||
|
Topics with new information covered here (at different levels of detail) are:
|
||
|
* Addresses
|
||
|
* Wallet, key store
|
||
|
* Account actor
|
||
|
* Filecoin Message
|
||
|
* Storage node type
|
||
|
* Miner actor, owner and worker addresses
|
||
|
* Message generation and message pool
|
||
|
* Message execution in the VM
|
||
|
* Power actor
|
||
|
* PubSub/GossipSub
|
||
|
|
||
|
## Wallet
|
||
|
|
||
|
We start by creating a new wallet which will be associated with the miner. A "wallet" is just an abstraction over a Filecoin [address](https://filecoin-project.github.io/specs/#appendix__address) associated to an [account actor](https://filecoin-project.github.io/specs/#actor): an actor (object) in the VM that represents a user in the network.
|
||
|
|
||
|
```
|
||
|
lotus wallet new
|
||
|
# t1ildao7vmywh67lolnd7esq7bqkfkhnalxsj74wq
|
||
|
```
|
||
|
|
||
|
The returned (random-looking) string is the address associated with the new wallet. The first part of the string encodes its [`Protocol`](https://github.com/filecoin-project/go-address/blob/master/address.go), in this case type 1 (`t1`), which corresponds to a public-key address generated from the [`secp256k1`](https://en.bitcoin.it/wiki/Secp256k1) elliptic curve (default option in the `wallet` command, alternatively it can also generate the [BLS](https://en.wikipedia.org/wiki/Boneh%E2%80%93Lynn%E2%80%93Shacham) signature scheme).
|
||
|
|
||
|
At this point the address still hasn't been transmitted to the network, it is just reflected on the key store of our local node. The key store (by default in `~/.lotus/keystore/`) contains all the keys generated by this node, including this new key which will be set as the *default* and will be used by other commands (like the miner creation one). (See the [`WalletNew()`](https://github.com/filecoin-project/lotus/blob/master/chain/wallet/wallet.go) API for more information about key generation and storage.)
|
||
|
|
||
|
It is important to note that the key store also holds the *private* key associated with the public one (that represent a Filecoin address) but this one is *never* transmitted over the network, it is just used locally to sign messages and prove this node is in possession of it and hence represents the account actor associated to the address/wallet.
|
||
|
|
||
|
## Account actor
|
||
|
|
||
|
There is no explicit Filecoin message or CLI command that creates an account actor but rather it is implicit in the public-key address reflected by the wallet. The first time the VM sees it as the receiving address of a Filecoin message it will automatically create the associated account actor.
|
||
|
|
||
|
We will trigger its creation then by sending funds to it, needed for the creation of the storage miner (note this document reflects the Filecoin Testnet, where we actually don't need funds to create a miner but will do the full procedure regardless to show the full cycle). In the Testnet we can send funds to an account trough the [Faucet](https://faucet.testnet.filecoin.io/funds.html), inserting the address returned by the `wallet new` command.
|
||
|
|
||
|
FIXME: Is there an easy way to visualize the message generated by the Faucet?
|
||
|
|
||
|
## Storage miner node
|
||
|
|
||
|
The `lotus-storage-miner` command provides a set of tools to manage the miners associated with the local storage miner node. At this point it is important to note the different [node types](https://github.com/filecoin-project/lotus/blob/master/node/repo/fsrepo.go), in the previous document we always referred to a *single* local node, `FullNode`, which handled the sync process and any other communication with the Filecoin network (the term *full* stands for full validation of the consensus protocol, there are no *light* clients at the moment that do not do the full validation). We now create a new node of type [`StorageMiner`](https://github.com/filecoin-project/lotus/blob/master/node/repo/fsrepo.go), with its own repo (each node is always associated to its own repo), by default in `~/.lotusstorage`. The difference between the two nodes lies in the services they run (see build options in the main architecture document).
|
||
|
|
||
|
The `lotus-storage-miner init` command option creates a new storage miner node. We will only be able to run the command once the chain has been synced by the full node (which needs to be running) and it will also require the download of the [proof parameters](https://filecoin.io/blog/filecoin-proof-system/) (of several GBs, so it may take some time).
|
||
|
|
||
|
The main options that define a miner are the owner and worker addresses associated to it (stored in [`MinerInfo`](https://github.com/filecoin-project/specs-actors/blob/master/actors/builtin/miner/miner_state.go), a substructure of the Miner Actor State) and its peer ID. We use default values for all of these options in the command and briefly described them here:
|
||
|
|
||
|
* Owner: address of the account actor that manages this miner (receives its payments, can change its information, etc.). By default this option is set to the default wallet address (and associated account actor), in the case of this example it will be the address just created with the `wallet new` command.
|
||
|
|
||
|
* Worker: address of an account actor that signs blocks and submits proofs associated with this miner, it can be the same as the owner address. By default the command will create a new wallet address for it, of type BLS (the only one accepted for worker addresses).
|
||
|
|
||
|
* [Peer ID](https://docs.libp2p.io/reference/glossary/#peerid): a network ID (belonging to the `libp2p` stack) used to contact the miner directly off-chain (e.g., to make a storage deal). Note the difference with the rest of the communication in the Filecoin network that happens largely inside the chain itself: when we "send" messages to the different actors that is actually a VM abstraction meaning we execute the method in the VM itself run by logic of the targeted actor, physically (at the network TCP/IP level) we broadcast the message to all of our peers to be included in a Filecoin block.
|
||
|
|
||
|
With the miner information filled the command constructs a Filecoin message to broadcast to the network and be included in a Filecoin block by a miner (see [`createStorageMiner()`](https://github.com/filecoin-project/lotus/blob/master/cmd/lotus-storage-miner/init.go)). We will wait for that block to be synced to the chain (by the full node) before returning the miner ID address. The ID address is another way to refer to the miner through a unique ID in the chain, it has a type 0 and it is the address that is normally seen in chain visualization tools, e.g., `t01475` (since, in contrast with the public-key types of addresses, it is easily readable by humans).
|
||
|
|
||
|
The Filecoin message constructed will be targeted to the [Power Actor](https://filecoin-project.github.io/specs/#systems__filecoin_blockchain__storage_power_consensus__storage_power_actor) (`StoragePowerActorAddr`), which tracks the amount of power (storage capacity) every miner has, and it will have the method number of the [`CreateMiner`](https://github.com/filecoin-project/specs-actors/blob/master/actors/builtin/methods.go) constant.
|
||
|
|
||
|
## Message broadcast
|
||
|
|
||
|
At the network level, the message (to be included in a block) is sent through the [message pool](https://filecoin-project.github.io/specs/#systems__filecoin_blockchain__message_pool) to the miners. The message pool is an abstraction over `libp2p`'s [PubSub protocol](https://docs.libp2p.io/reference/glossary/#pubsub), a communication pattern where peers subscribe to a topic (an identifying string) and other peers publish to it (broadcasting to all the subscribed peers it has registered). (Particularly in Lotus we use the [GossipSub](https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/README.md) implementation of that protocol.) In this case the topic we publish to is [`/fil/msgs`](https://github.com/filecoin-project/lotus/blob/master/build/params_shared.go), to which the miners will be subscribed and will receive, validate and process the message (see [`HandleIncomingMessages`](https://github.com/filecoin-project/lotus/blob/master/node/modules/services.go) in the [miner node construction](https://github.com/filecoin-project/lotus/blob/master/node/builder.go) for more details).
|
||
|
|
||
|
It is of interest to note that the GossipSub protocol is the same that miners themselves use to publish mined blocks in the `/fil/blocks` topic, to which the full node is subscribed to, used in the sync process (along with the `hello` protocol described in the architecture doc).
|
||
|
|
||
|
Back to the CLI command, the [`MpoolPushMessage`](https://github.com/filecoin-project/lotus/blob/master/node/impl/full/mpool.go) API in the full node takes care of populating the rest of the Filecoin message (e.g., inserting the correct nonce) and serializing it before actually publishing to the GossipSub network. After that, it explicitly waits for the message to be included by a miner in a block and then for that block to reach the chain where the full node will receive it as part of the sync process (see [`StateWaitMsg`](https://github.com/filecoin-project/lotus/blob/master/node/impl/full/state.go)), checking its return code for success and its return value for the miner ID.
|
||
|
|
||
|
## VM: message execution
|
||
|
|
||
|
We describe here the code flow inside the VM when it executes the `CreateMiner` method (of the message sent by the `lotus-storage-miner` command included by a miner in a block). This execution will be the same seen by all participants in the Filecoin protocol, the miner including the message in the block, the full node syncing to it, and any other peer receiving also this message.
|
||
|
|
||
|
There is a one-to-one mapping between the pair of actor and method number (`To:`/`Method:` fields) in a message in the VM, and the Go function in an actor's exported methods list that implement it. In this case, for the Power Actor list of method numbers defined in [`MethodsPower`](https://github.com/filecoin-project/specs-actors/blob/master/actors/builtin/methods.go), the `CreateMiner` method number 2 will correspond to the Go function with the same index in the list of methods returned by [`Exports()`](https://github.com/filecoin-project/specs-actors/blob/master/actors/builtin/power/power_actor.go) (and normally also the same name, here `(Actor).CreateMiner()`).
|
||
|
|
||
|
The Power Actor in `CreateMiner()` will do two things:
|
||
|
|
||
|
1. Send *another* message, `Exec`, to the Init Actor to instruct it to create the miner actor with the information provided by `lotus-storage-miner` and receive its ID address (this ID is the one returned to the CLI command).
|
||
|
|
||
|
2. Generate an entry in its list of power claims ([`State.Claims`](https://github.com/filecoin-project/specs-actors/blob/master/actors/builtin/power/power_state.go)) for the newly created ID address of the miner.
|
||
|
|
||
|
### Init Actor: create a new actor
|
||
|
|
||
|
The [`Init`](https://github.com/filecoin-project/specs-actors/blob/master/actors/builtin/init/init_actor.go) actor is the only way to create actors (besides the initial actors included in the genesis block). It has a single method (besides its own constructor), `Exec`. An actor is nothing more than an entry in the `Init`'s [`State.AddressMap`](https://github.com/filecoin-project/specs-actors/blob/master/actors/builtin/init/init_actor_state.go), a [HAMT](https://en.wikipedia.org/wiki/Hash_array_mapped_trie) that maps an ([`Actor`](https://github.com/filecoin-project/specs-actors/blob/master/vendor/github.com/filecoin-project/go-address/address.go)) address to an ID one. The `Actor` address is a unique address provided by the `Runtime` ([`NewActorAddress()`](https://github.com/filecoin-project/lotus/blob/master/chain/vm/runtime.go)) derived from the public key of the message's origin address, in this case the `--owner` defined in the CLI command.
|
||
|
|
||
|
### Miner Actor: constructor
|
||
|
|
||
|
The Init actor will also call the constructor for the type of actor it created, in this case a [Miner](https://github.com/filecoin-project/specs-actors/blob/master/actors/builtin/miner/miner_actor.go). The constructor is always the method numbered 1 for any actor.
|
||
|
|
||
|
FIXME: Do we want to say anything about the constructor? The setting of the proving period? Everything else seems like default values.
|