2022-06-07 03:14:35 +00:00
package itests
import (
"context"
"fmt"
"testing"
"time"
"github.com/ipfs/go-cid"
mh "github.com/multiformats/go-multihash"
"github.com/stretchr/testify/require"
2022-06-08 23:46:51 +00:00
"github.com/filecoin-project/go-address"
2022-06-07 03:14:35 +00:00
"github.com/filecoin-project/go-state-types/manifest"
"github.com/filecoin-project/go-state-types/network"
2022-06-08 23:46:51 +00:00
gstStore "github.com/filecoin-project/go-state-types/store"
2022-06-07 03:14:35 +00:00
"github.com/filecoin-project/specs-actors/v8/actors/util/adt"
2022-06-08 23:46:51 +00:00
"github.com/filecoin-project/lotus/blockstore"
"github.com/filecoin-project/lotus/chain/actors"
2022-06-07 03:14:35 +00:00
"github.com/filecoin-project/lotus/chain/consensus/filcns"
2022-06-08 23:46:51 +00:00
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/stmgr"
2022-06-07 03:14:35 +00:00
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/itests/kit"
)
func TestLiteMigration ( t * testing . T ) {
ctx := context . Background ( )
kit . QuietMiningLogs ( )
client16 , _ , ens := kit . EnsembleMinimal ( t , kit . MockProofs ( ) , kit . GenesisNetworkVersion ( network . Version16 ) )
ens . InterconnectAll ( ) . BeginMining ( 10 * time . Millisecond )
client16 . WaitTillChain ( ctx , func ( set * types . TipSet ) bool {
return set . Height ( ) > 100
} )
bs := blockstore . NewAPIBlockstore ( client16 )
2022-06-08 23:46:51 +00:00
ctxStore := gstStore . WrapBlockStore ( ctx , bs )
2022-06-07 03:14:35 +00:00
ts , err := client16 . ChainHead ( ctx )
require . NoError ( t , err )
stateRoot := ts . ParentState ( )
2022-06-08 23:46:51 +00:00
oldStateTree , err := state . LoadStateTree ( ctxStore , stateRoot )
2022-06-07 03:14:35 +00:00
require . NoError ( t , err )
2022-06-08 23:46:51 +00:00
oldManifest , err := stmgr . GetManifestFromStateTree ( ctx , oldStateTree )
2022-06-07 03:14:35 +00:00
require . NoError ( t , err )
2022-06-08 23:46:51 +00:00
newManifestCid := makeTestManifest ( t , ctxStore )
// Use the Cid we generated to get the new manifest instead of loading it from the state tree, because that would not test that we have the correct manifest in the state
2022-06-07 03:14:35 +00:00
var newManifest manifest . Manifest
err = ctxStore . Get ( ctx , newManifestCid , & newManifest )
require . NoError ( t , err )
err = newManifest . Load ( ctx , ctxStore )
require . NoError ( t , err )
2022-06-08 23:46:51 +00:00
newManifestData := manifest . ManifestData { }
err = ctxStore . Get ( ctx , newManifest . Data , & newManifestData )
require . NoError ( t , err )
newStateRoot , err := filcns . LiteMigration ( ctx , bs , newManifestCid , stateRoot , actors . Version8 , types . StateTreeVersion4 , types . StateTreeVersion4 )
require . NoError ( t , err )
2022-06-07 03:14:35 +00:00
2022-06-08 23:46:51 +00:00
newStateTree , err := state . LoadStateTree ( ctxStore , newStateRoot )
require . NoError ( t , err )
migrations := make ( map [ cid . Cid ] cid . Cid )
for _ , entry := range newManifestData . Entries {
oldCodeCid , ok := oldManifest . Get ( entry . Name )
require . True ( t , ok )
migrations [ oldCodeCid ] = entry . Code
}
2022-06-07 03:14:35 +00:00
2022-06-08 23:46:51 +00:00
err = newStateTree . ForEach ( func ( addr address . Address , newActorState * types . Actor ) error {
oldActor , err := oldStateTree . GetActor ( addr )
require . NoError ( t , err )
newCodeCid , ok := migrations [ oldActor . Code ]
require . True ( t , ok )
require . Equal ( t , newCodeCid , newActorState . Code )
return nil
} )
require . NoError ( t , err )
2022-06-07 03:14:35 +00:00
}
func makeTestManifest ( t * testing . T , ctxStore adt . Store ) cid . Cid {
builder := cid . V1Builder { Codec : cid . Raw , MhType : mh . IDENTITY }
manifestData := manifest . ManifestData { }
for _ , name := range [ ] string { "system" , "init" , "cron" , "account" , "storagepower" , "storageminer" , "storagemarket" , "paymentchannel" , "multisig" , "reward" , "verifiedregistry" } {
codeCid , err := builder . Sum ( [ ] byte ( fmt . Sprintf ( "fil/8/%s" , name ) ) )
if err != nil {
t . Fatal ( err )
}
manifestData . Entries = append ( manifestData . Entries ,
manifest . ManifestEntry {
Name : name ,
Code : codeCid ,
} )
}
manifestDataCid , err := ctxStore . Put ( ctxStore . Context ( ) , & manifestData )
if err != nil {
t . Fatal ( err )
}
mf := manifest . Manifest {
Version : 1 ,
Data : manifestDataCid ,
}
manifestCid , err := ctxStore . Put ( ctxStore . Context ( ) , & mf )
if err != nil {
t . Fatal ( err )
}
return manifestCid
}