Merge pull request #3174 from filecoin-project/keyko-io-fix/genesis-multisig

Keyko io fix/genesis multisig
This commit is contained in:
Whyrusleeping 2020-08-19 13:56:36 -07:00 committed by GitHub
commit 6117afe0be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 232 additions and 105 deletions

View File

@ -92,10 +92,8 @@ func (m mybs) Get(c cid.Cid) (block.Block, error) {
return b, nil return b, nil
} }
var rootkey, _ = address.NewIDAddress(80)
var rootkeyMultisig = genesis.MultisigMeta{ var rootkeyMultisig = genesis.MultisigMeta{
Signers: []address.Address{rootkey}, Signers: []address.Address{remAccTestKey},
Threshold: 1, Threshold: 1,
VestingDuration: 0, VestingDuration: 0,
VestingStart: 0, VestingStart: 0,
@ -108,12 +106,13 @@ var DefaultVerifregRootkeyActor = genesis.Actor{
} }
var remAccTestKey, _ = address.NewFromString("t1ceb34gnsc6qk5dt6n7xg6ycwzasjhbxm3iylkiy") var remAccTestKey, _ = address.NewFromString("t1ceb34gnsc6qk5dt6n7xg6ycwzasjhbxm3iylkiy")
var remAccMeta = genesis.AccountMeta{ var remAccMeta = genesis.MultisigMeta{
Owner: remAccTestKey, Signers: []address.Address{remAccTestKey},
Threshold: 1,
} }
var DefaultRemainderAccountActor = genesis.Actor{ var DefaultRemainderAccountActor = genesis.Actor{
Type: genesis.TAccount, Type: genesis.TMultisig,
Balance: big.NewInt(0), Balance: big.NewInt(0),
Meta: remAccMeta.ActorMeta(), Meta: remAccMeta.ActorMeta(),
} }

View File

@ -135,7 +135,7 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
// Create init actor // 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 { if err != nil {
return nil, nil, xerrors.Errorf("setup init actor: %w", err) return nil, nil, xerrors.Errorf("setup init actor: %w", err)
} }
@ -202,19 +202,28 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
} }
// Create accounts // Create accounts
for id, info := range template.Accounts { for _, info := range template.Accounts {
if info.Type != genesis.TAccount && info.Type != genesis.TMultisig {
return nil, nil, xerrors.New("unsupported account type") 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)
} }
ida, err := address.NewIDAddress(uint64(AccountStart + id)) case genesis.TMultisig:
ida, err := address.NewIDAddress(uint64(idStart))
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
idStart++
if err = createAccount(ctx, bs, cst, state, ida, info); err != nil { if err := createMultisigAccount(ctx, bs, cst, state, ida, info, keyIDs); err != nil {
return nil, nil, err return nil, nil, err
} }
default:
return nil, nil, xerrors.New("unsupported account type")
}
} }
@ -223,8 +232,8 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
return nil, nil, err return nil, nil, err
} }
if err = createAccount(ctx, bs, cst, state, vregroot, template.VerifregRootKey); err != nil { if err = createMultisigAccount(ctx, bs, cst, state, vregroot, template.VerifregRootKey, keyIDs); err != nil {
return nil, nil, err return nil, nil, xerrors.Errorf("failed to set up verified registry signer: %w", err)
} }
// Setup the first verifier as ID-address 81 // Setup the first verifier as ID-address 81
@ -288,23 +297,14 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
return nil, nil, err return nil, nil, err
} }
if err := createAccount(ctx, bs, cst, state, remAccKey, template.RemainderAccount); err != nil { if err := createMultisigAccount(ctx, bs, cst, state, remAccKey, template.RemainderAccount, keyIDs); err != nil {
return nil, nil, err return nil, nil, xerrors.Errorf("failed to set up remainder account: %w", 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)
} }
return state, keyIDs, nil 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 { func createAccountActor(ctx context.Context, cst cbor.IpldStore, state *state.StateTree, info genesis.Actor, keyIDs map[address.Address]address.Address) error {
if info.Type == genesis.TAccount {
var ainfo genesis.AccountMeta var ainfo genesis.AccountMeta
if err := json.Unmarshal(info.Meta, &ainfo); err != nil { if err := json.Unmarshal(info.Meta, &ainfo); err != nil {
return xerrors.Errorf("unmarshaling account meta: %w", err) return xerrors.Errorf("unmarshaling account meta: %w", err)
@ -313,6 +313,12 @@ func createAccount(ctx context.Context, bs bstore.Blockstore, cst cbor.IpldStore
if err != nil { if err != nil {
return err return err
} }
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{ err = state.SetActor(ida, &types.Actor{
Code: builtin.AccountActorCodeID, Code: builtin.AccountActorCodeID,
Balance: info.Balance, Balance: info.Balance,
@ -322,7 +328,12 @@ func createAccount(ctx context.Context, bs bstore.Blockstore, cst cbor.IpldStore
return xerrors.Errorf("setting account from actmap: %w", err) return xerrors.Errorf("setting account from actmap: %w", err)
} }
return nil return nil
} else if info.Type == genesis.TMultisig { }
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 var ainfo genesis.MultisigMeta
if err := json.Unmarshal(info.Meta, &ainfo); err != nil { if err := json.Unmarshal(info.Meta, &ainfo); err != nil {
return xerrors.Errorf("unmarshaling account meta: %w", err) return xerrors.Errorf("unmarshaling account meta: %w", err)
@ -332,8 +343,38 @@ func createAccount(ctx context.Context, bs bstore.Blockstore, cst cbor.IpldStore
return xerrors.Errorf("failed to create empty map: %v", err) 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{ st, err := cst.Put(ctx, &multisig.State{
Signers: ainfo.Signers, Signers: signers,
NumApprovalsThreshold: uint64(ainfo.Threshold), NumApprovalsThreshold: uint64(ainfo.Threshold),
StartEpoch: abi.ChainEpoch(ainfo.VestingStart), StartEpoch: abi.ChainEpoch(ainfo.VestingStart),
UnlockDuration: abi.ChainEpoch(ainfo.VestingDuration), UnlockDuration: abi.ChainEpoch(ainfo.VestingDuration),
@ -354,9 +395,6 @@ func createAccount(ctx context.Context, bs bstore.Blockstore, cst cbor.IpldStore
return nil return nil
} }
return fmt.Errorf("failed to create account")
}
func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot cid.Cid, template genesis.Template, keyIDs map[address.Address]address.Address) (cid.Cid, error) { func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot cid.Cid, template genesis.Template, keyIDs map[address.Address]address.Address) (cid.Cid, error) {
verifNeeds := make(map[address.Address]abi.PaddedPieceSize) verifNeeds := make(map[address.Address]abi.PaddedPieceSize)
var sum abi.PaddedPieceSize var sum abi.PaddedPieceSize
@ -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) 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 amt := s.Deal.PieceSize
verifNeeds[keyIDs[s.Deal.Client]] += amt verifNeeds[keyIDs[s.Deal.Client]] += amt
sum += amt sum += amt

View File

@ -137,7 +137,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
params := mustEnc(&minerInfos[i].maddr) params := mustEnc(&minerInfos[i].maddr)
_, err := doExecValue(ctx, vm, builtin.StorageMarketActorAddr, m.Worker, m.MarketBalance, builtin.MethodsMarket.AddBalance, params) _, err := doExecValue(ctx, vm, builtin.StorageMarketActorAddr, m.Worker, m.MarketBalance, builtin.MethodsMarket.AddBalance, params)
if err != nil { 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)) ret, err := doExecValue(ctx, vm, builtin.StorageMarketActorAddr, m.Worker, big.Zero(), builtin.MethodsMarket.PublishStorageDeals, mustEnc(params))
if err != nil { 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 var ids market.PublishStorageDealsReturn
if err := ids.UnmarshalCBOR(bytes.NewReader(ret)); err != nil { if err := ids.UnmarshalCBOR(bytes.NewReader(ret)); err != nil {

View File

@ -20,9 +20,9 @@ import (
bstore "github.com/filecoin-project/lotus/lib/blockstore" 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 { 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 var ias init_.State
@ -33,55 +33,105 @@ func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesi
amap := adt.MakeEmptyMap(store) amap := adt.MakeEmptyMap(store)
keyToId := map[address.Address]address.Address{} keyToId := map[address.Address]address.Address{}
counter := int64(AccountStart)
for i, a := range initialActors { for _, a := range initialActors {
if a.Type == genesis.TMultisig { 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 continue
} }
if a.Type != genesis.TAccount { 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 var ainfo genesis.AccountMeta
if err := json.Unmarshal(a.Meta, &ainfo); err != nil { 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 { 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 var err error
keyToId[ainfo.Owner], err = address.NewIDAddress(uint64(value)) keyToId[ainfo.Owner], err = address.NewIDAddress(uint64(value))
if err != nil { if err != nil {
return nil, nil, err return 0, nil, nil, err
} }
} }
if rootVerifier.Type == genesis.TAccount { if rootVerifier.Type == genesis.TAccount {
var ainfo genesis.AccountMeta var ainfo genesis.AccountMeta
if err := json.Unmarshal(rootVerifier.Meta, &ainfo); err != nil { 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) value := cbg.CborInt(80)
if err := amap.Put(adt.AddrKey(ainfo.Owner), &value); err != nil { 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() amapaddr, err := amap.Root()
if err != nil { if err != nil {
return nil, nil, err return 0, nil, nil, err
} }
ias.AddressMap = amapaddr ias.AddressMap = amapaddr
statecid, err := store.Put(store.Context(), &ias) statecid, err := store.Put(store.Context(), &ias)
if err != nil { if err != nil {
return nil, nil, err return 0, nil, nil, err
} }
act := &types.Actor{ act := &types.Actor{
@ -89,5 +139,5 @@ func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesi
Head: statecid, Head: statecid,
} }
return act, keyToId, nil return counter, act, keyToId, nil
} }

View File

@ -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) { 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) act, err := vm.StateTree().GetActor(from)
if err != nil { 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{ ret, err := vm.ApplyImplicitMessage(ctx, &types.Message{

View File

@ -12,6 +12,7 @@ import (
"text/tabwriter" "text/tabwriter"
"github.com/filecoin-project/specs-actors/actors/abi" "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/specs-actors/actors/util/adt"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
@ -231,10 +232,10 @@ var msigInspectCmd = &cli.Command{
}) })
w := tabwriter.NewWriter(os.Stdout, 8, 4, 0, ' ', 0) 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 { for _, txid := range txids {
tx := pending[txid] 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 { if err := w.Flush(); err != nil {
return xerrors.Errorf("flushing output: %+v", err) return xerrors.Errorf("flushing output: %+v", err)
@ -355,6 +356,15 @@ var msigProposeCmd = &cli.Command{
from = defaddr 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) msgCid, err := api.MsigPropose(ctx, msig, dest, types.BigInt(value), from, method, params)
if err != nil { if err != nil {
return err return err

View File

@ -562,10 +562,30 @@ var stateGetActorCmd = &cli.Command{
return err 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("Address:\t%s\n", addr)
fmt.Printf("Balance:\t%s\n", types.FIL(a.Balance)) fmt.Printf("Balance:\t%s\n", types.FIL(a.Balance))
fmt.Printf("Nonce:\t\t%d\n", a.Nonce) 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) fmt.Printf("Head:\t\t%s\n", a.Head)
return nil return nil

View File

@ -114,6 +114,7 @@ func PreSeal(maddr address.Address, spt abi.RegisteredSealProof, offset abi.Sect
} }
miner := &genesis.Miner{ miner := &genesis.Miner{
ID: maddr,
Owner: minerAddr.Address, Owner: minerAddr.Address,
Worker: minerAddr.Address, Worker: minerAddr.Address,
MarketBalance: big.Zero(), MarketBalance: big.Zero(),

View File

@ -26,6 +26,7 @@ type PreSeal struct {
} }
type Miner struct { type Miner struct {
ID address.Address
Owner address.Address Owner address.Address
Worker address.Address Worker address.Address
PeerId peer.ID //nolint:golint PeerId peer.ID //nolint:golint

View File

@ -1092,6 +1092,12 @@ func (a *StateAPI) StateVerifiedClientStatus(ctx context.Context, addr address.A
return nil, err 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) store := a.StateManager.ChainStore().Store(ctx)
var st verifreg.State var st verifreg.State
@ -1105,7 +1111,7 @@ func (a *StateAPI) StateVerifiedClientStatus(ctx context.Context, addr address.A
} }
var dcap verifreg.DataCap 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 return nil, err
} else if !found { } else if !found {
return nil, nil return nil, nil

View File

@ -25,6 +25,7 @@ func PreSeal(ssize abi.SectorSize, maddr address.Address, sectors int) (*genesis
} }
genm := &genesis.Miner{ genm := &genesis.Miner{
ID: maddr,
Owner: k.Address, Owner: k.Address,
Worker: k.Address, Worker: k.Address,
MarketBalance: big.NewInt(0), MarketBalance: big.NewInt(0),