Skip to content

Commit

Permalink
docs(actors): complete initial pass
Browse files Browse the repository at this point in the history
  • Loading branch information
rvagg committed Oct 4, 2024
1 parent 7984c32 commit 9f02fa4
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 5 deletions.
47 changes: 44 additions & 3 deletions documentation/misc/Builtin-actors_Development.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

This guide will walk through how to develop, update and test builtin-actors from within Lotus. The aim of this guide is to make it easier to contribute to builtin-actors by providing a clear path to follow through the somewhat complex web of dependencies and processes involved in integrating changes through to Lotus.

* [Context](#context)
* [Builtin-actors-only changes](#builtin-actors-only-changes)
* [Environment variable override](#environment-variable-override)
* [Replacing actors bundles](#replacing-actors-bundles)
* [Writing tests](#writing-tests)
* [Builtin-actors and chain or state type (go-state-types) changes](#builtin-actors-and-chain-or-state-type-go-state-types-changes)
* [Builtin-actors and (go-state-types) state migration changes](#builtin-actors-and-go-state-types-state-migration-changes)
* [Builtin-actors, (go-state-types) state migration and FVM changes](#builtin-actors-go-state-types-state-migration-and-fvm-changes)

## Context

[builtin-actors](https://github.com/filecoin-project/builtin-actors) is a Rust codebase that compiles to a set of WASM binaries that are bundled into CAR files and executed by the [FVM](https://github.com/filecoin-project/ref-fvm/) as required by messages in the Filecoin network. These actors are used to manage the state transitions of the Filecoin network and are critical to the operation of the network. The builtin-actors bundles are not just used by Lotus, but are shared by all Filecoin implementations. The compiled bundles are referenced by their CID for each network version. That CID must match what is in the CAR file and this process is repeated by each Filecoin implementation. Differences in the compiled actors can lead to consensus failures.
Expand Down Expand Up @@ -54,12 +63,44 @@ Where `local/20240930` is some arbitrary identifying string that is used for the

By default, the itests framework will use the current latest network version. Edits to the `build/builtin_actors_gen.go` file will result in an updated `latestNetworkVersion` in [`gen/inlinegen-data.json`](../../gen/inlinegen-data.json), which will result in a new `TestNetworkVersion` in [`build/buildconstants/params.go`](../../build/buildconstants/params.go) which is used in `DefaultEnsembleOpts` in [`itests/kit/ensemble_opts.go`](../../itests/kit/ensemble_opts.go) which will set the genesis network version of itests unless it is overridden.

...
This means that once the latest bundle is installed and `build/builtin_actors_gen.go` has an entry with the actors `Version` you want to test, you can proceed to write an itest using the same format as the existing itests without needing to provide additional options.

Sometimes, testing the upgrade boundary, or before and after upgrades, is desireable. For example, wanting to test that a feature works one way (or doesn't exist) before an upgrade, and another way after the upgrade, your itest will need an "upgrade schedule" which matches what is currently found in [`chain/consensus/filcns/upgrades.go`](../../chain/consensus/filcns/upgrades.go). The `kit.UpgradeSchedule` function in the itests framework can be used to set this up.

For example, to test a feature that is only available after the network upgrade to version 24, you would instantiate the itest ensemble with the following option to dictate that the network starts on NV23 (using `-1` as the `Height`) but will perform an upgrade at height 100 to NV24:

```go
kit.UpgradeSchedule(
stmgr.Upgrade{
Network: network.Version23,
Height: -1,
},
stmgr.Upgrade{
Network: network.Version24,
Height: 100,
Migration: filcns.UpgradeActorsV15,
},
)
```

There also exists a `kit.LatestActorsAt(100)` short-hand for this which will produce the same effect. However, this is tied to the `latestNetworkVersion` in `gen/inlinegen-data.json` and will not work when the network version is incremented in the future, so it is best to be explicit about network versions you are testing.

Using `client.WaitTillChain(ctx, kit.HeightAtLeast(105))` within your test will provide a boundary between the two network versions where you can test the feature before and after the upgrade, in this instance we are aiming at testing the feature at height `105` to provide a small buffer after the upgrade at `100`.

## Builtin-actors and chain or state type (go-state-types) changes

Similar to builtin-actors only, but requires additional steps to match go-state-types to builtin-actors types such that serialisation of message parameters, return types and/or state properties are consistent between the two so that Lotus can communicate with the actors correctly. Such changes require coordinating changes to both the builtin-actors and the go-state-types codebases as well as their integration into Lotus.

_**TODO**: More detail is needed on how to coordinate changes between builtin-actors and go-state-types_

## Builtin-actors and (go-state-types) state migration changes

*TODO*
Similar to builtin-actors and chain or state type changes, but requires additional steps to implement a state migration such that the state tree can be upgraded _at_ the correct upgrade epoch by Lotus and go-state-types and match what the new version of builtin-actors expects. This requires implementing a migration to be invoked in `builtin/vXX/migration/top.go` (where `XX` is the new actors version), properly calling it from [`chain/consensus/filcns/upgrades.go`](../../chain/consensus/filcns/upgrades.go) at the upgrade epoch and then implementing appropriate tests for the upgrade in [`itests/migration_test.go`](../../itests/migration_test.go) (and elsewhere as required).

_**TODO**: More detail is needed on how to coordinate changes between builtin-actors, go-state-types and Lotus for state migration_

## Builtin-actors, (go-state-types) state migration and FVM changes

*TODO*
Similar to builtin-actors and state migration changes, but requires additional coordination to integrate a new version of [ref-fvm](https://github.com/filecoin-project/ref-fvm/) with builtin-actors and [filecoin-ffi](https://github.com/filecoin-project/filecoin-ffi) and then integrate that into Lotus along with builtin-actors and go-state-types, along with appropriate tests.

_**TODO**: More detail is needed on how to coordinate changes between builtin-actors, go-state-types, ref-fvm and Lotus for state migration_
42 changes: 42 additions & 0 deletions itests/fevm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,18 @@ import (
"github.com/stretchr/testify/require"

"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
builtintypes "github.com/filecoin-project/go-state-types/builtin"
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/go-state-types/manifest"
"github.com/filecoin-project/go-state-types/network"

"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/build/buildconstants"
"github.com/filecoin-project/lotus/chain/consensus/filcns"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/types/ethtypes"
"github.com/filecoin-project/lotus/itests/kit"
Expand Down Expand Up @@ -1299,3 +1303,41 @@ func TestEthGetTransactionCount(t *testing.T) {
require.NoError(t, err)
require.Zero(t, contractNonceAfterDestroy)
}

func TestMcopy(t *testing.T) {
// MCOPY introduced in nv24, start the test on nv23 to check the error, then upgrade at epoch 100
// and check that an MCOPY contract can be deployed and run.
nv24epoch := abi.ChainEpoch(100)
upgradeSchedule := kit.UpgradeSchedule(
stmgr.Upgrade{
Network: network.Version23,
Height: -1,
},
stmgr.Upgrade{
Network: network.Version24,
Height: nv24epoch,
Migration: filcns.UpgradeActorsV15,
},
)

ctx, cancel, client := kit.SetupFEVMTest(t, upgradeSchedule)
defer cancel()

// TODO: below here ------------------------------------------------------------------------------

// try to deploy the contract before the upgrade, expect an error somewhere' in deploy or in call,
// if the error is in deploy we may need to implement DeployContractFromFilename here where we can
// assert an error
filenameActor := "contracts/Blocktest.hex"
fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor)
_, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "testChainID()", []byte{})
require.NoError(t, err)

// wait for the upgrade
client.WaitTillChain(ctx, kit.HeightAtLeast(nv24epoch+5))

// should be able to deploy and call the contract now
fromAddr, contractAddr = client.EVM().DeployContractFromFilename(ctx, filenameActor)
_, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "testChainID()", []byte{})
require.NoError(t, err)
}
6 changes: 4 additions & 2 deletions itests/kit/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ func removeLeadingZeros(data []byte) []byte {
return data[firstNonZeroIndex:]
}

func SetupFEVMTest(t *testing.T) (context.Context, context.CancelFunc, *TestFullNode) {
func SetupFEVMTest(t *testing.T, opts ...interface{}) (context.Context, context.CancelFunc, *TestFullNode) {
// make all logs extra quiet for fevm tests
lvl, err := logging.LevelFromString("error")
if err != nil {
Expand All @@ -419,7 +419,9 @@ func SetupFEVMTest(t *testing.T) (context.Context, context.CancelFunc, *TestFull
logging.SetAllLoggers(lvl)

blockTime := 100 * time.Millisecond
client, _, ens := EnsembleMinimal(t, MockProofs(), ThroughRPC())

opts = append([]interface{}{MockProofs(), ThroughRPC()}, opts...)
client, _, ens := EnsembleMinimal(t, opts...)
ens.InterconnectAll().BeginMining(blockTime)
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)

Expand Down

0 comments on commit 9f02fa4

Please sign in to comment.