diff --git a/itests/kit2/ensemble.go b/itests/kit2/ensemble.go index 5d12c83e1..a66dac1e3 100644 --- a/itests/kit2/ensemble.go +++ b/itests/kit2/ensemble.go @@ -13,6 +13,7 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/exitcode" + "github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/go-storedcounter" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api/v1api" @@ -122,7 +123,19 @@ func NewEnsemble(t *testing.T, opts ...EnsembleOpt) *Ensemble { err := o(&options) require.NoError(t, err) } - return &Ensemble{t: t, options: &options} + + n := &Ensemble{t: t, options: &options} + + // add accounts from ensemble options to genesis. + for _, acc := range options.accounts { + n.genesis.accounts = append(n.genesis.accounts, genesis.Actor{ + Type: genesis.TAccount, + Balance: acc.initialBalance, + Meta: (&genesis.AccountMeta{Owner: acc.key.Address}).ActorMeta(), + }) + } + + return n } // FullNode enrolls a new full node. @@ -135,8 +148,7 @@ func (n *Ensemble) FullNode(full *TestFullNode, opts ...NodeOpt) *Ensemble { var key *wallet.Key if !n.bootstrapped && !options.balance.IsZero() { - // create a key+ddress, and assign it some FIL. - // this will be set as the default wallet. + // create a key+address, and assign it some FIL; this will be set as the default wallet. var err error key, err = wallet.GenerateKey(types.KTBLS) require.NoError(n.t, err) @@ -589,12 +601,22 @@ func (n *Ensemble) BeginMining(blocktime time.Duration, miners ...*TestMiner) [] } func (n *Ensemble) generateGenesis() *genesis.Template { + var verifRoot = gen.DefaultVerifregRootkeyActor + if k := n.options.verifiedRoot.key; k != nil { + verifRoot = genesis.Actor{ + Type: genesis.TAccount, + Balance: n.options.verifiedRoot.initialBalance, + Meta: (&genesis.AccountMeta{Owner: k.Address}).ActorMeta(), + } + } + templ := &genesis.Template{ + NetworkVersion: network.Version0, Accounts: n.genesis.accounts, Miners: n.genesis.miners, NetworkName: "test", Timestamp: uint64(time.Now().Unix() - 10000), // some time sufficiently far in the past - VerifregRootKey: gen.DefaultVerifregRootkeyActor, + VerifregRootKey: verifRoot, RemainderAccount: gen.DefaultRemainderAccountActor, } diff --git a/itests/kit2/ensemble_opts.go b/itests/kit2/ensemble_opts.go index 724113bdc..5e49976ec 100644 --- a/itests/kit2/ensemble_opts.go +++ b/itests/kit2/ensemble_opts.go @@ -4,14 +4,22 @@ import ( "time" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/wallet" ) type EnsembleOpt func(opts *ensembleOpts) error +type genesisAccount struct { + key *wallet.Key + initialBalance abi.TokenAmount +} + type ensembleOpts struct { - pastOffset time.Duration - proofType abi.RegisteredSealProof - mockProofs bool + pastOffset time.Duration + proofType abi.RegisteredSealProof + verifiedRoot genesisAccount + accounts []genesisAccount + mockProofs bool } var DefaultEnsembleOpts = ensembleOpts{ @@ -33,3 +41,25 @@ func MockProofs() EnsembleOpt { return nil } } + +// VerifierRootKey specifies the key to be enlisted as the verified clients +// registry root, as well as the initial balance to be attributed during +// genesis. +func VerifierRootKey(key *wallet.Key, balance abi.TokenAmount) EnsembleOpt { + return func(opts *ensembleOpts) error { + opts.verifiedRoot.key = key + opts.verifiedRoot.initialBalance = balance + return nil + } +} + +// Account sets up an account at genesis with the specified key and balance. +func Account(key *wallet.Key, balance abi.TokenAmount) EnsembleOpt { + return func(opts *ensembleOpts) error { + opts.accounts = append(opts.accounts, genesisAccount{ + key: key, + initialBalance: balance, + }) + return nil + } +} diff --git a/itests/kit2/node_opts_nv.go b/itests/kit2/node_opts_nv.go index 05d2c2287..6f682bd3a 100644 --- a/itests/kit2/node_opts_nv.go +++ b/itests/kit2/node_opts_nv.go @@ -1,36 +1,64 @@ package kit2 import ( + "context" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/lotus/chain/stmgr" + "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/node" + "github.com/ipfs/go-cid" ) +// DefaultTestUpgradeSchedule +var DefaultTestUpgradeSchedule = stmgr.UpgradeSchedule{{ + Network: network.Version9, + Height: 1, + Migration: stmgr.UpgradeActorsV2, +}, { + Network: network.Version10, + Height: 2, + Migration: stmgr.UpgradeActorsV3, +}, { + Network: network.Version12, + Height: 3, + Migration: stmgr.UpgradeActorsV4, +}, { + Network: network.Version13, + Height: 4, + Migration: stmgr.UpgradeActorsV5, +}} + func LatestActorsAt(upgradeHeight abi.ChainEpoch) node.Option { // Attention: Update this when introducing new actor versions or your tests will be sad return NetworkUpgradeAt(network.Version13, upgradeHeight) } +// InstantaneousNetworkVersion starts the network instantaneously at the +// specified version in height 1. +func InstantaneousNetworkVersion(version network.Version) node.Option { + // composes all migration functions + var mf stmgr.MigrationFunc = func(ctx context.Context, sm *stmgr.StateManager, cache stmgr.MigrationCache, cb stmgr.ExecMonitor, oldState cid.Cid, height abi.ChainEpoch, ts *types.TipSet) (newState cid.Cid, err error) { + var state = oldState + for _, u := range DefaultTestUpgradeSchedule { + if u.Network > version { + break + } + state, err = u.Migration(ctx, sm, cache, cb, state, height, ts) + if err != nil { + return cid.Undef, err + } + } + return state, nil + } + return node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{ + {Network: version, Height: 1, Migration: mf}, + }) +} + func NetworkUpgradeAt(version network.Version, upgradeHeight abi.ChainEpoch) node.Option { - fullSchedule := stmgr.UpgradeSchedule{{ - // prepare for upgrade. - Network: network.Version9, - Height: 1, - Migration: stmgr.UpgradeActorsV2, - }, { - Network: network.Version10, - Height: 2, - Migration: stmgr.UpgradeActorsV3, - }, { - Network: network.Version12, - Height: 3, - Migration: stmgr.UpgradeActorsV4, - }, { - Network: network.Version13, - Height: 4, - Migration: stmgr.UpgradeActorsV5, - }} + fullSchedule := stmgr.UpgradeSchedule{} schedule := stmgr.UpgradeSchedule{} for _, upgrade := range fullSchedule { diff --git a/itests/verifreg_test.go b/itests/verifreg_test.go index 180a194a6..b1e3bcfa4 100644 --- a/itests/verifreg_test.go +++ b/itests/verifreg_test.go @@ -2,13 +2,17 @@ package itests import ( "context" + "fmt" "strings" "testing" "time" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/network" + "github.com/filecoin-project/lotus/chain/wallet" verifreg4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/verifreg" + "github.com/stretchr/testify/require" lapi "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors" @@ -23,101 +27,102 @@ func TestVerifiedClientTopUp(t *testing.T) { test := func(nv network.Version, shouldWork bool) func(*testing.T) { return func(t *testing.T) { - nopts := kit2.ConstructorOpts(kit2.NetworkUpgradeAt(nv, -1)) + rootKey, err := wallet.GenerateKey(types.KTSecp256k1) + require.NoError(t, err) + + verifierKey, err := wallet.GenerateKey(types.KTSecp256k1) + require.NoError(t, err) + + verifiedClientKey, err := wallet.GenerateKey(types.KTBLS) + require.NoError(t, err) + + bal, err := types.ParseFIL("100fil") + require.NoError(t, err) + + node, _, ens := kit2.EnsembleMinimal(t, kit2.MockProofs(), + kit2.VerifierRootKey(rootKey, abi.NewTokenAmount(bal.Int64())), + kit2.Account(verifierKey, abi.NewTokenAmount(bal.Int64())), // assign some balance to the verifier so they can send an AddClient message. + kit2.ConstructorOpts(kit2.InstantaneousNetworkVersion(nv))) - node, _, ens := kit2.EnsembleMinimal(t, kit2.MockProofs(), nopts) ens.InterconnectAll().BeginMining(blockTime) api := node.FullNode.(*impl.FullNodeAPI) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - //Get VRH + // get VRH vrh, err := api.StateVerifiedRegistryRootKey(ctx, types.TipSetKey{}) - if err != nil { - t.Fatal(err) - } + fmt.Println(vrh.String()) + require.NoError(t, err) - //Add verifier - verifier, err := api.WalletDefaultAddress(ctx) - if err != nil { - t.Fatal(err) - } + // import the root key. + rootAddr, err := api.WalletImport(ctx, &rootKey.KeyInfo) + require.NoError(t, err) + + // import the verifier's key. + verifierAddr, err := api.WalletImport(ctx, &verifierKey.KeyInfo) + require.NoError(t, err) + + // import the verified client's key. + verifiedClientAddr, err := api.WalletImport(ctx, &verifiedClientKey.KeyInfo) + require.NoError(t, err) + + params, err := actors.SerializeParams(&verifreg4.AddVerifierParams{Address: verifierAddr, Allowance: big.NewInt(100000000000)}) + require.NoError(t, err) - params, err := actors.SerializeParams(&verifreg4.AddVerifierParams{Address: verifier, Allowance: big.NewInt(100000000000)}) - if err != nil { - t.Fatal(err) - } msg := &types.Message{ + From: rootAddr, To: verifreg.Address, - From: vrh, Method: verifreg.Methods.AddVerifier, Params: params, Value: big.Zero(), } sm, err := api.MpoolPushMessage(ctx, msg, nil) - if err != nil { - t.Fatal("AddVerifier failed: ", err) - } + require.NoError(t, err, "AddVerifier failed") + res, err := api.StateWaitMsg(ctx, sm.Cid(), 1, lapi.LookbackNoLimit, true) - if err != nil { - t.Fatal(err) - } - if res.Receipt.ExitCode != 0 { - t.Fatal("did not successfully send message") - } + require.NoError(t, err) + require.EqualValues(t, 0, res.Receipt.ExitCode) - //Assign datacap to a client + // assign datacap to a client datacap := big.NewInt(10000) - clientAddress, err := api.WalletNew(ctx, types.KTBLS) - if err != nil { - t.Fatal(err) - } - params, err = actors.SerializeParams(&verifreg4.AddVerifiedClientParams{Address: clientAddress, Allowance: datacap}) - if err != nil { - t.Fatal(err) - } + params, err = actors.SerializeParams(&verifreg4.AddVerifiedClientParams{Address: verifiedClientAddr, Allowance: datacap}) + require.NoError(t, err) msg = &types.Message{ + From: verifierAddr, To: verifreg.Address, - From: verifier, Method: verifreg.Methods.AddVerifiedClient, Params: params, Value: big.Zero(), } sm, err = api.MpoolPushMessage(ctx, msg, nil) - if err != nil { - t.Fatal("AddVerifiedClient faield: ", err) - } - res, err = api.StateWaitMsg(ctx, sm.Cid(), 1, lapi.LookbackNoLimit, true) - if err != nil { - t.Fatal(err) - } - if res.Receipt.ExitCode != 0 { - t.Fatal("did not successfully send message") - } + require.NoError(t, err) + + res, err = api.StateWaitMsg(ctx, sm.Cid(), 1, lapi.LookbackNoLimit, true) + require.NoError(t, err) + require.EqualValues(t, 0, res.Receipt.ExitCode) + + // check datacap balance + dcap, err := api.StateVerifiedClientStatus(ctx, verifiedClientAddr, types.EmptyTSK) + require.NoError(t, err) - //check datacap balance - dcap, err := api.StateVerifiedClientStatus(ctx, clientAddress, types.EmptyTSK) - if err != nil { - t.Fatal(err) - } if !dcap.Equals(datacap) { t.Fatal("") } - //try to assign datacap to the same client should fail for actor v4 and below - params, err = actors.SerializeParams(&verifreg4.AddVerifiedClientParams{Address: clientAddress, Allowance: datacap}) + // try to assign datacap to the same client should fail for actor v4 and below + params, err = actors.SerializeParams(&verifreg4.AddVerifiedClientParams{Address: verifiedClientAddr, Allowance: datacap}) if err != nil { t.Fatal(err) } msg = &types.Message{ + From: verifierAddr, To: verifreg.Address, - From: verifier, Method: verifreg.Methods.AddVerifiedClient, Params: params, Value: big.Zero(),