diff --git a/chain/gen/gen.go b/chain/gen/gen.go index f9bf90bfd..e34bb586b 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -92,10 +92,8 @@ func (m mybs) Get(c cid.Cid) (block.Block, error) { return b, nil } -var rootkey, _ = address.NewIDAddress(80) - var rootkeyMultisig = genesis.MultisigMeta{ - Signers: []address.Address{rootkey}, + Signers: []address.Address{remAccTestKey}, Threshold: 1, VestingDuration: 0, VestingStart: 0, @@ -108,12 +106,13 @@ var DefaultVerifregRootkeyActor = genesis.Actor{ } var remAccTestKey, _ = address.NewFromString("t1ceb34gnsc6qk5dt6n7xg6ycwzasjhbxm3iylkiy") -var remAccMeta = genesis.AccountMeta{ - Owner: remAccTestKey, +var remAccMeta = genesis.MultisigMeta{ + Signers: []address.Address{remAccTestKey}, + Threshold: 1, } var DefaultRemainderAccountActor = genesis.Actor{ - Type: genesis.TAccount, + Type: genesis.TMultisig, Balance: big.NewInt(0), Meta: remAccMeta.ActorMeta(), } diff --git a/chain/gen/genesis/genesis.go b/chain/gen/genesis/genesis.go index d779c5820..a6a320b97 100644 --- a/chain/gen/genesis/genesis.go +++ b/chain/gen/genesis/genesis.go @@ -135,7 +135,7 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge // Create init actor - initact, keyIDs, err := SetupInitActor(bs, template.NetworkName, template.Accounts, template.VerifregRootKey) + idStart, initact, keyIDs, err := SetupInitActor(bs, template.NetworkName, template.Accounts, template.VerifregRootKey) if err != nil { return nil, nil, xerrors.Errorf("setup init actor: %w", err) } @@ -202,20 +202,29 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge } // Create accounts - for id, info := range template.Accounts { - if info.Type != genesis.TAccount && info.Type != genesis.TMultisig { + for _, info := range template.Accounts { + + switch info.Type { + case genesis.TAccount: + if err := createAccountActor(ctx, cst, state, info, keyIDs); err != nil { + return nil, nil, xerrors.Errorf("failed to create account actor: %w", err) + } + + case genesis.TMultisig: + + ida, err := address.NewIDAddress(uint64(idStart)) + if err != nil { + return nil, nil, err + } + idStart++ + + if err := createMultisigAccount(ctx, bs, cst, state, ida, info, keyIDs); err != nil { + return nil, nil, err + } + default: return nil, nil, xerrors.New("unsupported account type") } - ida, err := address.NewIDAddress(uint64(AccountStart + id)) - if err != nil { - return nil, nil, err - } - - if err = createAccount(ctx, bs, cst, state, ida, info); err != nil { - return nil, nil, err - } - } vregroot, err := address.NewIDAddress(80) @@ -223,8 +232,8 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge return nil, nil, err } - if err = createAccount(ctx, bs, cst, state, vregroot, template.VerifregRootKey); err != nil { - return nil, nil, err + if err = createMultisigAccount(ctx, bs, cst, state, vregroot, template.VerifregRootKey, keyIDs); err != nil { + return nil, nil, xerrors.Errorf("failed to set up verified registry signer: %w", err) } // Setup the first verifier as ID-address 81 @@ -288,73 +297,102 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge return nil, nil, err } - if err := createAccount(ctx, bs, cst, state, remAccKey, template.RemainderAccount); err != nil { - return nil, nil, err - } - err = state.SetActor(remAccKey, &types.Actor{ - Code: builtin.AccountActorCodeID, - Balance: remainingFil, - Head: emptyobject, - }) - if err != nil { - return nil, nil, xerrors.Errorf("set burnt funds account actor: %w", err) + if err := createMultisigAccount(ctx, bs, cst, state, remAccKey, template.RemainderAccount, keyIDs); err != nil { + return nil, nil, xerrors.Errorf("failed to set up remainder account: %w", err) } return state, keyIDs, nil } -func createAccount(ctx context.Context, bs bstore.Blockstore, cst cbor.IpldStore, state *state.StateTree, ida address.Address, info genesis.Actor) error { - if info.Type == genesis.TAccount { - var ainfo genesis.AccountMeta - if err := json.Unmarshal(info.Meta, &ainfo); err != nil { - return xerrors.Errorf("unmarshaling account meta: %w", err) - } - st, err := cst.Put(ctx, &account.State{Address: ainfo.Owner}) - if err != nil { - return err - } - err = state.SetActor(ida, &types.Actor{ - Code: builtin.AccountActorCodeID, - Balance: info.Balance, - Head: st, - }) - if err != nil { - return xerrors.Errorf("setting account from actmap: %w", err) - } - return nil - } else if info.Type == genesis.TMultisig { - var ainfo genesis.MultisigMeta - if err := json.Unmarshal(info.Meta, &ainfo); err != nil { - return xerrors.Errorf("unmarshaling account meta: %w", err) - } - pending, err := adt.MakeEmptyMap(adt.WrapStore(ctx, cst)).Root() - if err != nil { - return xerrors.Errorf("failed to create empty map: %v", err) - } - - st, err := cst.Put(ctx, &multisig.State{ - Signers: ainfo.Signers, - NumApprovalsThreshold: uint64(ainfo.Threshold), - StartEpoch: abi.ChainEpoch(ainfo.VestingStart), - UnlockDuration: abi.ChainEpoch(ainfo.VestingDuration), - PendingTxns: pending, - InitialBalance: info.Balance, - }) - if err != nil { - return err - } - err = state.SetActor(ida, &types.Actor{ - Code: builtin.MultisigActorCodeID, - Balance: info.Balance, - Head: st, - }) - if err != nil { - return xerrors.Errorf("setting account from actmap: %w", err) - } - return nil +func createAccountActor(ctx context.Context, cst cbor.IpldStore, state *state.StateTree, info genesis.Actor, keyIDs map[address.Address]address.Address) error { + var ainfo genesis.AccountMeta + if err := json.Unmarshal(info.Meta, &ainfo); err != nil { + return xerrors.Errorf("unmarshaling account meta: %w", err) + } + st, err := cst.Put(ctx, &account.State{Address: ainfo.Owner}) + if err != nil { + return err } - return fmt.Errorf("failed to create account") + ida, ok := keyIDs[ainfo.Owner] + if !ok { + return fmt.Errorf("no registered ID for account actor: %s", ainfo.Owner) + } + + err = state.SetActor(ida, &types.Actor{ + Code: builtin.AccountActorCodeID, + Balance: info.Balance, + Head: st, + }) + if err != nil { + return xerrors.Errorf("setting account from actmap: %w", err) + } + return nil +} + +func createMultisigAccount(ctx context.Context, bs bstore.Blockstore, cst cbor.IpldStore, state *state.StateTree, ida address.Address, info genesis.Actor, keyIDs map[address.Address]address.Address) error { + if info.Type != genesis.TMultisig { + return fmt.Errorf("can only call createMultisigAccount with multisig Actor info") + } + var ainfo genesis.MultisigMeta + if err := json.Unmarshal(info.Meta, &ainfo); err != nil { + return xerrors.Errorf("unmarshaling account meta: %w", err) + } + pending, err := adt.MakeEmptyMap(adt.WrapStore(ctx, cst)).Root() + if err != nil { + return xerrors.Errorf("failed to create empty map: %v", err) + } + + var signers []address.Address + + for _, e := range ainfo.Signers { + idAddress, ok := keyIDs[e] + if !ok { + return fmt.Errorf("no registered key ID for signer: %s", e) + } + + // Check if actor already exists + _, err := state.GetActor(e) + if err == nil { + signers = append(signers, idAddress) + continue + } + + st, err := cst.Put(ctx, &account.State{Address: e}) + if err != nil { + return err + } + err = state.SetActor(idAddress, &types.Actor{ + Code: builtin.AccountActorCodeID, + Balance: types.NewInt(0), + Head: st, + }) + if err != nil { + return xerrors.Errorf("setting account from actmap: %w", err) + } + signers = append(signers, idAddress) + } + + st, err := cst.Put(ctx, &multisig.State{ + Signers: signers, + NumApprovalsThreshold: uint64(ainfo.Threshold), + StartEpoch: abi.ChainEpoch(ainfo.VestingStart), + UnlockDuration: abi.ChainEpoch(ainfo.VestingDuration), + PendingTxns: pending, + InitialBalance: info.Balance, + }) + if err != nil { + return err + } + err = state.SetActor(ida, &types.Actor{ + Code: builtin.MultisigActorCodeID, + Balance: info.Balance, + Head: st, + }) + if err != nil { + return xerrors.Errorf("setting account from actmap: %w", err) + } + return nil } func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot cid.Cid, template genesis.Template, keyIDs map[address.Address]address.Address) (cid.Cid, error) { @@ -375,11 +413,12 @@ func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot ci return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err) } - for _, m := range template.Miners { + for mi, m := range template.Miners { + for si, s := range m.Sectors { + if s.Deal.Provider != m.ID { + return cid.Undef, xerrors.Errorf("Sector %d in miner %d in template had mismatch in provider and miner ID: %s != %s", si, mi, s.Deal.Provider, m.ID) + } - // Add the miner to the market actor's balance table - _, err = doExec(ctx, vm, builtin.StorageMarketActorAddr, m.Owner, builtin.MethodsMarket.AddBalance, mustEnc(adt.Empty)) - for _, s := range m.Sectors { amt := s.Deal.PieceSize verifNeeds[keyIDs[s.Deal.Client]] += amt sum += amt diff --git a/chain/gen/genesis/miners.go b/chain/gen/genesis/miners.go index cc649c84c..04c121d41 100644 --- a/chain/gen/genesis/miners.go +++ b/chain/gen/genesis/miners.go @@ -137,7 +137,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid params := mustEnc(&minerInfos[i].maddr) _, err := doExecValue(ctx, vm, builtin.StorageMarketActorAddr, m.Worker, m.MarketBalance, builtin.MethodsMarket.AddBalance, params) if err != nil { - return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err) + return cid.Undef, xerrors.Errorf("failed to create genesis miner (add balance): %w", err) } } @@ -149,7 +149,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid ret, err := doExecValue(ctx, vm, builtin.StorageMarketActorAddr, m.Worker, big.Zero(), builtin.MethodsMarket.PublishStorageDeals, mustEnc(params)) if err != nil { - return xerrors.Errorf("failed to create genesis miner: %w", err) + return xerrors.Errorf("failed to create genesis miner (publish deals): %w", err) } var ids market.PublishStorageDealsReturn if err := ids.UnmarshalCBOR(bytes.NewReader(ret)); err != nil { diff --git a/chain/gen/genesis/t01_init.go b/chain/gen/genesis/t01_init.go index c3708329b..1686102fe 100644 --- a/chain/gen/genesis/t01_init.go +++ b/chain/gen/genesis/t01_init.go @@ -20,9 +20,9 @@ import ( bstore "github.com/filecoin-project/lotus/lib/blockstore" ) -func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesis.Actor, rootVerifier genesis.Actor) (*types.Actor, map[address.Address]address.Address, error) { +func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesis.Actor, rootVerifier genesis.Actor) (int64, *types.Actor, map[address.Address]address.Address, error) { if len(initialActors) > MaxAccounts { - return nil, nil, xerrors.New("too many initial actors") + return 0, nil, nil, xerrors.New("too many initial actors") } var ias init_.State @@ -33,55 +33,105 @@ func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesi amap := adt.MakeEmptyMap(store) keyToId := map[address.Address]address.Address{} + counter := int64(AccountStart) - for i, a := range initialActors { + for _, a := range initialActors { if a.Type == genesis.TMultisig { + var ainfo genesis.MultisigMeta + if err := json.Unmarshal(a.Meta, &ainfo); err != nil { + return 0, nil, nil, xerrors.Errorf("unmarshaling account meta: %w", err) + } + for _, e := range ainfo.Signers { + + if _, ok := keyToId[e]; ok { + continue + } + + fmt.Printf("init set %s t0%d\n", e, counter) + + value := cbg.CborInt(counter) + if err := amap.Put(adt.AddrKey(e), &value); err != nil { + return 0, nil, nil, err + } + counter = counter + 1 + var err error + keyToId[e], err = address.NewIDAddress(uint64(value)) + if err != nil { + return 0, nil, nil, err + } + + } + // Need to add actors for all multisigs too continue } if a.Type != genesis.TAccount { - return nil, nil, xerrors.Errorf("unsupported account type: %s", a.Type) // TODO: Support msig (skip here) + return 0, nil, nil, xerrors.Errorf("unsupported account type: %s", a.Type) } var ainfo genesis.AccountMeta if err := json.Unmarshal(a.Meta, &ainfo); err != nil { - return nil, nil, xerrors.Errorf("unmarshaling account meta: %w", err) + return 0, nil, nil, xerrors.Errorf("unmarshaling account meta: %w", err) } - fmt.Printf("init set %s t0%d\n", ainfo.Owner, AccountStart+int64(i)) + fmt.Printf("init set %s t0%d\n", ainfo.Owner, counter) - value := cbg.CborInt(AccountStart + int64(i)) + value := cbg.CborInt(counter) if err := amap.Put(adt.AddrKey(ainfo.Owner), &value); err != nil { - return nil, nil, err + return 0, nil, nil, err } + counter = counter + 1 var err error keyToId[ainfo.Owner], err = address.NewIDAddress(uint64(value)) if err != nil { - return nil, nil, err + return 0, nil, nil, err } } if rootVerifier.Type == genesis.TAccount { var ainfo genesis.AccountMeta if err := json.Unmarshal(rootVerifier.Meta, &ainfo); err != nil { - return nil, nil, xerrors.Errorf("unmarshaling account meta: %w", err) + return 0, nil, nil, xerrors.Errorf("unmarshaling account meta: %w", err) } value := cbg.CborInt(80) if err := amap.Put(adt.AddrKey(ainfo.Owner), &value); err != nil { - return nil, nil, err + return 0, nil, nil, err + } + } else if rootVerifier.Type == genesis.TMultisig { + var ainfo genesis.MultisigMeta + if err := json.Unmarshal(rootVerifier.Meta, &ainfo); err != nil { + return 0, nil, nil, xerrors.Errorf("unmarshaling account meta: %w", err) + } + for _, e := range ainfo.Signers { + if _, ok := keyToId[e]; ok { + continue + } + fmt.Printf("init set %s t0%d\n", e, counter) + + value := cbg.CborInt(counter) + if err := amap.Put(adt.AddrKey(e), &value); err != nil { + return 0, nil, nil, err + } + counter = counter + 1 + var err error + keyToId[e], err = address.NewIDAddress(uint64(value)) + if err != nil { + return 0, nil, nil, err + } + } } amapaddr, err := amap.Root() if err != nil { - return nil, nil, err + return 0, nil, nil, err } ias.AddressMap = amapaddr statecid, err := store.Put(store.Context(), &ias) if err != nil { - return nil, nil, err + return 0, nil, nil, err } act := &types.Actor{ @@ -89,5 +139,5 @@ func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesi Head: statecid, } - return act, keyToId, nil + return counter, act, keyToId, nil } diff --git a/chain/gen/genesis/util.go b/chain/gen/genesis/util.go index 15ada30cb..e78f6a0d2 100644 --- a/chain/gen/genesis/util.go +++ b/chain/gen/genesis/util.go @@ -28,7 +28,7 @@ func doExec(ctx context.Context, vm *vm.VM, to, from address.Address, method abi func doExecValue(ctx context.Context, vm *vm.VM, to, from address.Address, value types.BigInt, method abi.MethodNum, params []byte) ([]byte, error) { act, err := vm.StateTree().GetActor(from) if err != nil { - return nil, xerrors.Errorf("doExec failed to get from actor: %w", err) + return nil, xerrors.Errorf("doExec failed to get from actor (%s): %w", from, err) } ret, err := vm.ApplyImplicitMessage(ctx, &types.Message{ diff --git a/cli/multisig.go b/cli/multisig.go index e2ff4e5a7..57f6c2c03 100644 --- a/cli/multisig.go +++ b/cli/multisig.go @@ -12,6 +12,7 @@ import ( "text/tabwriter" "github.com/filecoin-project/specs-actors/actors/abi" + "github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/go-address" @@ -231,10 +232,10 @@ var msigInspectCmd = &cli.Command{ }) w := tabwriter.NewWriter(os.Stdout, 8, 4, 0, ' ', 0) - fmt.Fprintf(w, "ID\tState\tTo\tValue\tMethod\tParams\n") + fmt.Fprintf(w, "ID\tState\tApprovals\tTo\tValue\tMethod\tParams\n") for _, txid := range txids { tx := pending[txid] - fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%d\t%x\n", txid, state(tx), tx.To, types.FIL(tx.Value), tx.Method, tx.Params) + fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%d\t%x\n", txid, state(tx), len(tx.Approved), tx.To, types.FIL(tx.Value), tx.Method, tx.Params) } if err := w.Flush(); err != nil { return xerrors.Errorf("flushing output: %+v", err) @@ -355,6 +356,15 @@ var msigProposeCmd = &cli.Command{ from = defaddr } + act, err := api.StateGetActor(ctx, msig, types.EmptyTSK) + if err != nil { + return fmt.Errorf("failed to look up multisig %s: %w", msig, err) + } + + if act.Code != builtin.MultisigActorCodeID { + return fmt.Errorf("actor %s is not a multisig actor", msig) + } + msgCid, err := api.MsigPropose(ctx, msig, dest, types.BigInt(value), from, method, params) if err != nil { return err diff --git a/cli/state.go b/cli/state.go index 5e9952685..c8daade15 100644 --- a/cli/state.go +++ b/cli/state.go @@ -562,10 +562,30 @@ var stateGetActorCmd = &cli.Command{ return err } + var strtype string + switch a.Code { + case builtin.AccountActorCodeID: + strtype = "account" + case builtin.MultisigActorCodeID: + strtype = "multisig" + case builtin.CronActorCodeID: + strtype = "cron" + case builtin.InitActorCodeID: + strtype = "init" + case builtin.StorageMinerActorCodeID: + strtype = "miner" + case builtin.StorageMarketActorCodeID: + strtype = "market" + case builtin.StoragePowerActorCodeID: + strtype = "power" + default: + strtype = "unknown" + } + fmt.Printf("Address:\t%s\n", addr) fmt.Printf("Balance:\t%s\n", types.FIL(a.Balance)) fmt.Printf("Nonce:\t\t%d\n", a.Nonce) - fmt.Printf("Code:\t\t%s\n", a.Code) + fmt.Printf("Code:\t\t%s (%s)\n", a.Code, strtype) fmt.Printf("Head:\t\t%s\n", a.Head) return nil diff --git a/cmd/lotus-seed/seed/seed.go b/cmd/lotus-seed/seed/seed.go index 5b4a1fbac..f892709f6 100644 --- a/cmd/lotus-seed/seed/seed.go +++ b/cmd/lotus-seed/seed/seed.go @@ -114,6 +114,7 @@ func PreSeal(maddr address.Address, spt abi.RegisteredSealProof, offset abi.Sect } miner := &genesis.Miner{ + ID: maddr, Owner: minerAddr.Address, Worker: minerAddr.Address, MarketBalance: big.Zero(), diff --git a/genesis/types.go b/genesis/types.go index 468a09067..13349def2 100644 --- a/genesis/types.go +++ b/genesis/types.go @@ -26,6 +26,7 @@ type PreSeal struct { } type Miner struct { + ID address.Address Owner address.Address Worker address.Address PeerId peer.ID //nolint:golint diff --git a/node/impl/full/state.go b/node/impl/full/state.go index ceea2e813..f5421e2ba 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -1092,6 +1092,12 @@ func (a *StateAPI) StateVerifiedClientStatus(ctx context.Context, addr address.A return nil, err } + aid, err := a.StateLookupID(ctx, addr, tsk) + if err != nil { + log.Warnf("lookup failure %v", err) + return nil, err + } + store := a.StateManager.ChainStore().Store(ctx) var st verifreg.State @@ -1105,7 +1111,7 @@ func (a *StateAPI) StateVerifiedClientStatus(ctx context.Context, addr address.A } var dcap verifreg.DataCap - if found, err := vh.Get(adt.AddrKey(addr), &dcap); err != nil { + if found, err := vh.Get(adt.AddrKey(aid), &dcap); err != nil { return nil, err } else if !found { return nil, nil diff --git a/storage/mockstorage/preseal.go b/storage/mockstorage/preseal.go index 50810a4b2..fd4d0d69b 100644 --- a/storage/mockstorage/preseal.go +++ b/storage/mockstorage/preseal.go @@ -25,6 +25,7 @@ func PreSeal(ssize abi.SectorSize, maddr address.Address, sectors int) (*genesis } genm := &genesis.Miner{ + ID: maddr, Owner: k.Address, Worker: k.Address, MarketBalance: big.NewInt(0),