diff --git a/chain/stmgr/forks.go b/chain/stmgr/forks.go index ca3b52d52..3d5a07610 100644 --- a/chain/stmgr/forks.go +++ b/chain/stmgr/forks.go @@ -422,20 +422,9 @@ func doTransfer(tree types.StateTree, from, to address.Address, amt abi.TokenAmo if cb != nil { // record the transfer in execution traces - fakeMsg := &types.Message{ - From: from, - To: to, - Value: amt, - } - fakeRct := &types.MessageReceipt{ - ExitCode: 0, - Return: nil, - GasUsed: 0, - } - cb(types.ExecutionTrace{ - Msg: fakeMsg, - MsgRct: fakeRct, + Msg: makeFakeMsg(from, to, amt, 0), + MsgRct: makeFakeRct(), Error: "", Duration: 0, GasCharges: nil, @@ -699,24 +688,14 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, _ Migratio if cb != nil { // record the transfer in execution traces - fakeMsg := &types.Message{ - From: builtin.SystemActorAddr, - To: builtin.SystemActorAddr, - Value: big.Zero(), - Nonce: uint64(epoch), - } - fakeRct := &types.MessageReceipt{ - ExitCode: 0, - Return: nil, - GasUsed: 0, - } + fakeMsg := makeFakeMsg(builtin.SystemActorAddr, builtin.SystemActorAddr, big.Zero(), uint64(epoch)) if err := cb(fakeMsg.Cid(), fakeMsg, &vm.ApplyRet{ - MessageReceipt: *fakeRct, + MessageReceipt: *makeFakeRct(), ActorErr: nil, ExecutionTrace: types.ExecutionTrace{ Msg: fakeMsg, - MsgRct: fakeRct, + MsgRct: makeFakeRct(), Error: "", Duration: 0, GasCharges: nil, @@ -915,6 +894,66 @@ func UpgradeCalico(ctx context.Context, sm *StateManager, _ MigrationCache, cb E return newRoot, nil } +func terminateActor(ctx context.Context, tree *state.StateTree, addr address.Address, cb ExecCallback, epoch abi.ChainEpoch) error { + a, err := tree.GetActor(addr) + if xerrors.Is(err, types.ErrActorNotFound) { + return types.ErrActorNotFound + } else if err != nil { + return xerrors.Errorf("failed to get actor to delete: %w", err) + } + + var trace types.ExecutionTrace + if err := doTransfer(tree, addr, builtin.BurntFundsActorAddr, a.Balance, func(t types.ExecutionTrace) { + trace = t + }); err != nil { + return xerrors.Errorf("transferring terminated actor's balance: %w", err) + } + + if cb != nil { + // record the transfer in execution traces + + fakeMsg := makeFakeMsg(builtin.SystemActorAddr, addr, big.Zero(), uint64(epoch)) + + if err := cb(fakeMsg.Cid(), fakeMsg, &vm.ApplyRet{ + MessageReceipt: *makeFakeRct(), + ActorErr: nil, + ExecutionTrace: trace, + Duration: 0, + GasCosts: nil, + }); err != nil { + return xerrors.Errorf("recording transfers: %w", err) + } + } + + err = tree.DeleteActor(addr) + if err != nil { + return xerrors.Errorf("deleting actor from tree: %w", err) + } + + ia, err := tree.GetActor(init_.Address) + if err != nil { + return xerrors.Errorf("loading init actor: %w", err) + } + + ias, err := init_.Load(&state.AdtStore{IpldStore: tree.Store}, ia) + if err != nil { + return xerrors.Errorf("loading init actor state: %w", err) + } + + if err := ias.Remove(addr); err != nil { + return xerrors.Errorf("deleting entry from address map: %w", err) + } + + nih, err := tree.Store.Put(ctx, ias) + if err != nil { + return xerrors.Errorf("writing new init actor state: %w", err) + } + + ia.Head = nih + + return tree.SetActor(init_.Address, ia) +} + func UpgradeActorsV3(ctx context.Context, sm *StateManager, cache MigrationCache, cb ExecCallback, root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) { // Use all the CPUs except 3. workerCount := runtime.NumCPU() - 3 @@ -933,16 +972,21 @@ func UpgradeActorsV3(ctx context.Context, sm *StateManager, cache MigrationCache return cid.Undef, xerrors.Errorf("migrating actors v3 state: %w", err) } - // perform some basic sanity checks to make sure everything still works. - store := store.ActorStore(ctx, sm.ChainStore().Blockstore()) - if newSm, err := state.LoadStateTree(store, newRoot); err != nil { - return cid.Undef, xerrors.Errorf("state tree sanity load failed: %w", err) - } else if newRoot2, err := newSm.Flush(ctx); err != nil { - return cid.Undef, xerrors.Errorf("state tree sanity flush failed: %w", err) - } else if newRoot2 != newRoot { - return cid.Undef, xerrors.Errorf("state-root mismatch: %s != %s", newRoot, newRoot2) - } else if _, err := newSm.GetActor(init_.Address); err != nil { - return cid.Undef, xerrors.Errorf("failed to load init actor after upgrade: %w", err) + tree, err := sm.StateTree(newRoot) + if err != nil { + return cid.Undef, xerrors.Errorf("getting state tree: %w", err) + } + + if build.BuildType == build.BuildMainnet { + err := terminateActor(ctx, tree, build.ZeroAddress, cb, epoch) + if err != nil && !xerrors.Is(err, types.ErrActorNotFound) { + return cid.Undef, xerrors.Errorf("deleting zero bls actor: %w", err) + } + + newRoot, err = tree.Flush(ctx) + if err != nil { + return cid.Undef, xerrors.Errorf("flushing state tree: %w", err) + } } return newRoot, nil @@ -1139,24 +1183,14 @@ func splitGenesisMultisig0(ctx context.Context, cb ExecCallback, addr address.Ad if cb != nil { // record the transfer in execution traces - fakeMsg := &types.Message{ - From: builtin.SystemActorAddr, - To: addr, - Value: big.Zero(), - Nonce: uint64(epoch), - } - fakeRct := &types.MessageReceipt{ - ExitCode: 0, - Return: nil, - GasUsed: 0, - } + fakeMsg := makeFakeMsg(builtin.SystemActorAddr, addr, big.Zero(), uint64(epoch)) if err := cb(fakeMsg.Cid(), fakeMsg, &vm.ApplyRet{ - MessageReceipt: *fakeRct, + MessageReceipt: *makeFakeRct(), ActorErr: nil, ExecutionTrace: types.ExecutionTrace{ Msg: fakeMsg, - MsgRct: fakeRct, + MsgRct: makeFakeRct(), Error: "", Duration: 0, GasCharges: nil, @@ -1275,3 +1309,20 @@ func resetMultisigVesting0(ctx context.Context, store adt0.Store, tree *state.St return nil } + +func makeFakeMsg(from address.Address, to address.Address, amt abi.TokenAmount, nonce uint64) *types.Message { + return &types.Message{ + From: from, + To: to, + Value: amt, + Nonce: nonce, + } +} + +func makeFakeRct() *types.MessageReceipt { + return &types.MessageReceipt{ + ExitCode: 0, + Return: nil, + GasUsed: 0, + } +} diff --git a/chain/vm/mkactor.go b/chain/vm/mkactor.go index 072711db6..0e72b0c4b 100644 --- a/chain/vm/mkactor.go +++ b/chain/vm/mkactor.go @@ -3,6 +3,10 @@ package vm import ( "context" + "github.com/filecoin-project/go-state-types/network" + + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/lotus/chain/actors" @@ -39,6 +43,10 @@ func TryCreateAccountActor(rt *Runtime, addr address.Address) (*types.Actor, add return nil, address.Undef, err } + if addr == build.ZeroAddress && rt.NetworkVersion() >= network.Version10 { + return nil, address.Undef, aerrors.New(exitcode.ErrIllegalArgument, "cannot create the zero bls actor") + } + addrID, err := rt.state.RegisterNewAddress(addr) if err != nil { return nil, address.Undef, aerrors.Escalate(err, "registering actor address")