FVM — Create Miner with Smart Contract (Native Actor) and Debug FVM (Part 1)

Web3 Eye
CoinsBench
Published in
7 min readNov 2, 2022

--

I originally wanted to write this post after the validation of the CreateMiner process that we will go around in a circle is completed, but the content is too long, and on the other hand, I can’t wait to summarize the work and efforts we have done in this direction (of course, the most work are still verifying whether the current FVM capabilities can support our work). Of course, if you don’t want to know the process, then we can summarize it in one sentence: under the current FVM implementation, it is not feasible for us to complete CreateMiner through native actors (that is, non-built-in actors, written and deployed by users). But in this article, in addition to being able to know this conclusion, you will additionally learn how to debug FVM and built-in actors locally, and how to debug when your smart contract execution encounters errors.

1 Preparation

Our code is still based on our example repository:

https://github.com/kikakkz/fvm-actor-example.git

Commit is 06a4801cc34372d12ef39813eb72d7c73f8092d0. Method 13 can be found in it, that is, we want to help us create a Miner by calling the built-in PowerActor, and return the information of the Miner to the smart contract.

The earliest test was still based on the wallaby test network. Of course, in order to be able to debug FVM locally in the later stage, we compiled FVM locally and built a local 2k test network, which made it easier for us to remove some limitations of the current implementation of FVM and verify how FVM can help us to manage miner through smart contract. The lotus repository at the time of writing this article:

https://github.com/filecoin-project/lotus.git

The branch is experimental/fvm-m2, and the commit is 1a06485a8c0463ea6a7a0604d0ad421bdcc2c953. Based on this branch, we connect the wallaby test network and build our own 2k test network.

【Note: Since the previous article has systematically explained the basics of compiling contracts, deploying virtual machines, and serializing parameters, we will not list the command lines in detail in this article, and will be more inclined to explanation of knowledge and obstacles encountered.】

2 Prepare CreateMiner Function

CreateMiner is the operation of creating a miner when a Filecoin storage operator participates in Filecoin mining. It essentially uses the CreateMiner method of PowerActor. The CreateMiner method of PowerActor requests InitActor to instantiate an instance of the built-in MinerActor according to the incoming parameters. Start maintaining the computing power status of the instance, and return the instance’s meta information (i.e. miner ID) to the account.

Invocation: In a distributed system (including but not limited to blockchain networks), the invocation is usually different from the invocation when we write code. The invocation in the distributed system is usually a remote call, the parameters are packaged and sent to the target. The target parses and executes the requested functionality then returns the result. The difference between the invocation of the blockchain and the traditional distributed system is that the call in the blockchain is always executed at the time of bookkeeping (i.e. block generation), and the caller queries the account book to determine the call result.

In our contract, the create_miner method is as follows:

Among them, the params parameter received by our contract function is the serialized CreateMinerParams, and the serialized result can be obtained by executing the code in tools/go:

Regarding the serialization of parameters, we have sorted out the complete serialization method, and we hope to accompany or specifically explain the serialization method of parameters in the next article.

After create_miner accepts the params parameter, it is sent to PowerActor as the params parameter in the CreateMiner method, and passed to PowerActor for execution.

3 Wallaby Testnet Execution

We will invoke the smart contract we have deployed on the wallaby testnet with the encoded parameters, and the wallaby testnet will return an error to us:

We parse the returned results in tools/rust and get:

The error code returned to us by the network is 18, and when we query the error code 18 in ref-fvm, we get:

It can be seen that in the implementation of FVM, the operation of CreateMiner is not allowed. We can only guess that the ability to create miners through the contract is limited, and we need to execute an FVM locally to confirm where the limit comes from.

4 Debug the local FVM

The deployment of 2k network can be done according to the official documents. The process is simply listed as follows:

./lotus/lotus-seed pre-seal — sector-size 2KiB — num-sectors 2

./lotus/lotus-seed genesis new localnet.json

./lotus/lotus-seed genesis add-miner localnet.json ~/.genesis-sectors/pre-seal-t01000.json

./lotus/lotus daemon — lotus-make-genesis=devgen.car — genesis-template=localnet.json — bootstrap=false — api=3456

./lotus/lotus wallet import — as-default ~/.genesis-sectors/pre-seal-t01000.key

./lotus/lotus-miner init — genesis-miner — actor=t01000 — sector-size=2KiB — pre-sealed-sectors=~/.genesis-sectors — pre-sealed-metadata=~/. genesis-sectors/pre-seal-t01000.json — nosync

./lotus/lotus-miner run — nosync

The 2k network deployed in this process will deploy the official preset builtin-actors, if we want to debug this part of the actors, we need to do much more complicated work. The builtin actors are implemented in the repository https://github.com/filecoin-project/builtin-actors.git the branch on which this article is written is next, and the commit is a7f261d9f6e1e9da6e7a89f07a96d4abf00d1e73. The early builtin actors were implemented in the go language and linked into the executable program at compile time, but since v16, the builtin actors are implemented in rust, and the compiled wasm binary code is packaged into the executable program in bundle mode then loaded into FVM at runtime. The switching of this method needs to be understood, otherwise, the working method and invocation process of the builtin actors in FVM cannot be understood.

To debug the local builtin actors, you first need to replace the preset actors in the lotus with the locally compiled actors. The process is as follows:

cd builtin-actors

make all-bundles bundle-devnet-wasm

cd output

tar — preserve-permissions — use-compress-program zstd -cf v8.tar.zst *.car

Then enter the lotus directory and replace the packaged v8.tar.zst with the file of the same name under build/actors. But this still does not replace the newly generated actors, and the car file under build/genesis needs to be replaced:

cp output/builtin-actors-butterflynet.car build/genesis/butterflynet.car

cp output/builtin-actors-calibrationnet.car build/genesis/calibrationnet.car

cp output/builtin-actors-devnet-wasm.car build/genesis/devnet.car

cp output/builtin-actors-mainnet.car build/genesis/mainnet.ca

then execute

make gen

After the commit of this article executes make gen, the NetworkVersion will change and cause the compilation to fail. At this time, we need to restore the files that caused the compilation to fail.

git checkout chain/state

Recompile the 2k executable

make clean 2k

Then clean and redeploy the 2k network environment, so you have a local FVM environment that you can modify and debug at any time.

5 Modify builtin-actors to complete CreateMiner

But we don’t know where the code 18 is returned from. At this time, we can enable the rust log of the lotus daemon to the trace level and execute it, so that we can see the execution process of the wasm code compiled by the contract from the lotus log. In the above invocation, we see that after the contract is executed, the output in the log is as follows:

Among them, we need to pay attention to the circled part, the calling format is:

calling caller -> target::method

The returning format is:

returning target: method -> caller (exit code)

It can be seen that after our contract innovate method 2 of t04, t04 returns 18 to us. t04 is the PowerActor of Filecoin, and method 2 is CreateMiner. Looking at the contract code of PowerActor, create_miner restricts that only Account and Multisig can create miners:

So we modify the limit function, lift the limit, and return directly

Invoke create contract again, and we will encounter the error that follows. We will not list the following errors one by one, but we already have the ability to debug the local FVM contract. We only need to modify the restrictions one by one, and then we can finally successfully create the miner with the contract address as the Owner and Worker.

6 What do we do next

FVM cannot directly support the creation of miners and a series of miner management capabilities. Next, we will try new ideas, which are still based on the contract’s management capabilities for miners. For example, after a miner is created by an account, the owner is changed to the contract address for further verification what FVM can do for us to manage miners.

--

--