diff --git a/api/api_full.go b/api/api_full.go index 8c3c64ce2b8..ddce41459ba 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -6,6 +6,8 @@ import ( "fmt" "time" + abinetwork "github.com/filecoin-project/go-state-types/network" + blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" "github.com/libp2p/go-libp2p-core/peer" @@ -584,6 +586,8 @@ type FullNode interface { StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (CirculatingSupply, error) //perm:read // StateNetworkVersion returns the network version at the given tipset StateNetworkVersion(context.Context, types.TipSetKey) (apitypes.NetworkVersion, error) //perm:read + // StateActorCids returns the CIDs of all the builtin actors for the given network version + StateActorCodeCIDs(context.Context, abinetwork.Version) (map[string]cid.Cid, error) //perm:read // StateGetRandomnessFromTickets is used to sample the chain for randomness. StateGetRandomnessFromTickets(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte, tsk types.TipSetKey) (abi.Randomness, error) //perm:read diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index e015cf038fe..928e5b80888 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -196,6 +196,7 @@ func init() { addExample(&si) addExample(retrievalmarket.DealID(5)) addExample(abi.ActorID(1000)) + addExample(map[string]cid.Cid{}) addExample(map[string][]api.SealedRef{ "98000": { api.SealedRef{ diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index 9a2bda0b4ac..d122b4b108a 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -2271,6 +2271,21 @@ func (mr *MockFullNodeMockRecorder) StateAccountKey(arg0, arg1, arg2 interface{} return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateAccountKey", reflect.TypeOf((*MockFullNode)(nil).StateAccountKey), arg0, arg1, arg2) } +// StateActorCodeCIDs mocks base method. +func (m *MockFullNode) StateActorCodeCIDs(arg0 context.Context, arg1 network.Version) (map[string]cid.Cid, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StateActorCodeCIDs", arg0, arg1) + ret0, _ := ret[0].(map[string]cid.Cid) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// StateActorCodeCIDs indicates an expected call of StateActorCodeCIDs. +func (mr *MockFullNodeMockRecorder) StateActorCodeCIDs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateActorCodeCIDs", reflect.TypeOf((*MockFullNode)(nil).StateActorCodeCIDs), arg0, arg1) +} + // StateAllMinerFaults mocks base method. func (m *MockFullNode) StateAllMinerFaults(arg0 context.Context, arg1 abi.ChainEpoch, arg2 types.TipSetKey) ([]*api.Fault, error) { m.ctrl.T.Helper() diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 671fe02aec6..42932135c70 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -338,6 +338,8 @@ type FullNodeStruct struct { StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` + StateActorCodeCIDs func(p0 context.Context, p1 abinetwork.Version) (map[string]cid.Cid, error) `perm:"read"` + StateAllMinerFaults func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) ([]*Fault, error) `perm:"read"` StateCall func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*InvocResult, error) `perm:"read"` @@ -2392,6 +2394,17 @@ func (s *FullNodeStub) StateAccountKey(p0 context.Context, p1 address.Address, p return *new(address.Address), ErrNotSupported } +func (s *FullNodeStruct) StateActorCodeCIDs(p0 context.Context, p1 abinetwork.Version) (map[string]cid.Cid, error) { + if s.Internal.StateActorCodeCIDs == nil { + return *new(map[string]cid.Cid), ErrNotSupported + } + return s.Internal.StateActorCodeCIDs(p0, p1) +} + +func (s *FullNodeStub) StateActorCodeCIDs(p0 context.Context, p1 abinetwork.Version) (map[string]cid.Cid, error) { + return *new(map[string]cid.Cid), ErrNotSupported +} + func (s *FullNodeStruct) StateAllMinerFaults(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) ([]*Fault, error) { if s.Internal.StateAllMinerFaults == nil { return *new([]*Fault), ErrNotSupported diff --git a/api/v0api/full.go b/api/v0api/full.go index 4721f4c633e..51682393482 100644 --- a/api/v0api/full.go +++ b/api/v0api/full.go @@ -3,6 +3,8 @@ package v0api import ( "context" + abinetwork "github.com/filecoin-project/go-state-types/network" + "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-bitfield" datatransfer "github.com/filecoin-project/go-data-transfer" @@ -603,6 +605,8 @@ type FullNode interface { StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (api.CirculatingSupply, error) //perm:read // StateNetworkVersion returns the network version at the given tipset StateNetworkVersion(context.Context, types.TipSetKey) (apitypes.NetworkVersion, error) //perm:read + // StateActorCids returns the CIDs of all the builtin actors for the given network version + StateActorCodeCIDs(context.Context, abinetwork.Version) (map[string]cid.Cid, error) //perm:read // StateGetRandomnessFromTickets is used to sample the chain for randomness. StateGetRandomnessFromTickets(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte, tsk types.TipSetKey) (abi.Randomness, error) //perm:read diff --git a/api/v0api/proxy_gen.go b/api/v0api/proxy_gen.go index a2a69f16309..65fe996a98e 100644 --- a/api/v0api/proxy_gen.go +++ b/api/v0api/proxy_gen.go @@ -255,6 +255,8 @@ type FullNodeStruct struct { StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` + StateActorCodeCIDs func(p0 context.Context, p1 abinetwork.Version) (map[string]cid.Cid, error) `perm:"read"` + StateAllMinerFaults func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) ([]*api.Fault, error) `perm:"read"` StateCall func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*api.InvocResult, error) `perm:"read"` @@ -1677,6 +1679,17 @@ func (s *FullNodeStub) StateAccountKey(p0 context.Context, p1 address.Address, p return *new(address.Address), ErrNotSupported } +func (s *FullNodeStruct) StateActorCodeCIDs(p0 context.Context, p1 abinetwork.Version) (map[string]cid.Cid, error) { + if s.Internal.StateActorCodeCIDs == nil { + return *new(map[string]cid.Cid), ErrNotSupported + } + return s.Internal.StateActorCodeCIDs(p0, p1) +} + +func (s *FullNodeStub) StateActorCodeCIDs(p0 context.Context, p1 abinetwork.Version) (map[string]cid.Cid, error) { + return *new(map[string]cid.Cid), ErrNotSupported +} + func (s *FullNodeStruct) StateAllMinerFaults(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) ([]*api.Fault, error) { if s.Internal.StateAllMinerFaults == nil { return *new([]*api.Fault), ErrNotSupported diff --git a/api/v0api/v0mocks/mock_full.go b/api/v0api/v0mocks/mock_full.go index ef194e9d353..9fbd5779433 100644 --- a/api/v0api/v0mocks/mock_full.go +++ b/api/v0api/v0mocks/mock_full.go @@ -2170,6 +2170,21 @@ func (mr *MockFullNodeMockRecorder) StateAccountKey(arg0, arg1, arg2 interface{} return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateAccountKey", reflect.TypeOf((*MockFullNode)(nil).StateAccountKey), arg0, arg1, arg2) } +// StateActorCodeCIDs mocks base method. +func (m *MockFullNode) StateActorCodeCIDs(arg0 context.Context, arg1 network.Version) (map[string]cid.Cid, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StateActorCodeCIDs", arg0, arg1) + ret0, _ := ret[0].(map[string]cid.Cid) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// StateActorCodeCIDs indicates an expected call of StateActorCodeCIDs. +func (mr *MockFullNodeMockRecorder) StateActorCodeCIDs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateActorCodeCIDs", reflect.TypeOf((*MockFullNode)(nil).StateActorCodeCIDs), arg0, arg1) +} + // StateAllMinerFaults mocks base method. func (m *MockFullNode) StateAllMinerFaults(arg0 context.Context, arg1 abi.ChainEpoch, arg2 types.TipSetKey) ([]*api.Fault, error) { m.ctrl.T.Helper() diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index cb79e55e20f..163f7bf7101 100644 Binary files a/build/openrpc/full.json.gz and b/build/openrpc/full.json.gz differ diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 17fba94ffa7..556acb36e16 100644 Binary files a/build/openrpc/miner.json.gz and b/build/openrpc/miner.json.gz differ diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index 90c3db8a50b..58ba9fa9df3 100644 Binary files a/build/openrpc/worker.json.gz and b/build/openrpc/worker.json.gz differ diff --git a/chain/actors/manifest.go b/chain/actors/manifest.go index a00c50217f1..452b763ea0b 100644 --- a/chain/actors/manifest.go +++ b/chain/actors/manifest.go @@ -113,7 +113,7 @@ func ReadManifest(ctx context.Context, store cbor.IpldStore, mfCid cid.Cid) (map return metadata, nil } -// GetActorCodeID looks up a builtin actor's code CID by actor version and canonical actor name name. +// GetActorCodeID looks up a builtin actor's code CID by actor version and canonical actor name. func GetActorCodeID(av Version, name string) (cid.Cid, bool) { manifestMx.RLock() defer manifestMx.RUnlock() diff --git a/cli/state.go b/cli/state.go index e9c1875829d..83df3fddecd 100644 --- a/cli/state.go +++ b/cli/state.go @@ -1927,24 +1927,15 @@ var StateSysActorCIDsCmd = &cli.Command{ } fmt.Printf("Actor Version: %d\n", actorVersion) - manifestCid, ok := actors.GetManifest(actorVersion) - if !ok { - return xerrors.Errorf("cannot get manifest CID") - } - fmt.Printf("Manifest CID: %v\n", manifestCid) - tw := tabwriter.NewWriter(os.Stdout, 2, 4, 2, ' ', 0) _, _ = fmt.Fprintln(tw, "\nActor\tCID\t") - var actorKeys = actors.GetBuiltinActorsKeys() - for _, name := range actorKeys { - sysActorCID, ok := actors.GetActorCodeID(actorVersion, name) - if !ok { - return xerrors.Errorf("error getting actor %v code id for actor version %d", name, - actorVersion) - } - _, _ = fmt.Fprintf(tw, "%v\t%v\n", name, sysActorCID) - + actorsCids, err := api.StateActorCodeCIDs(ctx, nv) + if err != nil { + return err + } + for name, cid := range actorsCids { + _, _ = fmt.Fprintf(tw, "%v\t%v\n", name, cid) } return tw.Flush() }, diff --git a/documentation/en/api-v0-methods.md b/documentation/en/api-v0-methods.md index 7060f9a811d..0781ab195f0 100644 --- a/documentation/en/api-v0-methods.md +++ b/documentation/en/api-v0-methods.md @@ -158,6 +158,7 @@ * [PaychVoucherSubmit](#PaychVoucherSubmit) * [State](#State) * [StateAccountKey](#StateAccountKey) + * [StateActorCodeCIDs](#StateActorCodeCIDs) * [StateAllMinerFaults](#StateAllMinerFaults) * [StateCall](#StateCall) * [StateChangedActors](#StateChangedActors) @@ -4639,6 +4640,21 @@ Inputs: Response: `"f01234"` +### StateActorCodeCIDs +StateActorCids returns the CIDs of all the builtin actors for the given network version + + +Perms: read + +Inputs: +```json +[ + 16 +] +``` + +Response: `{}` + ### StateAllMinerFaults StateAllMinerFaults returns all non-expired Faults that occur within lookback epochs of the given tipset diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index 325a48babb5..aa409a7c83e 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -165,6 +165,7 @@ * [PaychVoucherSubmit](#PaychVoucherSubmit) * [State](#State) * [StateAccountKey](#StateAccountKey) + * [StateActorCodeCIDs](#StateActorCodeCIDs) * [StateAllMinerFaults](#StateAllMinerFaults) * [StateCall](#StateCall) * [StateChangedActors](#StateChangedActors) @@ -5049,6 +5050,21 @@ Inputs: Response: `"f01234"` +### StateActorCodeCIDs +StateActorCids returns the CIDs of all the builtin actors for the given network version + + +Perms: read + +Inputs: +```json +[ + 16 +] +``` + +Response: `{}` + ### StateAllMinerFaults StateAllMinerFaults returns all non-expired Faults that occur within lookback epochs of the given tipset diff --git a/node/impl/full/state.go b/node/impl/full/state.go index 69fe0fea200..9f400da8056 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -7,12 +7,14 @@ import ( "fmt" "strconv" + "github.com/filecoin-project/lotus/chain/actors" + "github.com/libp2p/go-libp2p-core/peer" "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/cbor" - cid "github.com/ipfs/go-cid" + "github.com/ipfs/go-cid" "go.uber.org/fx" "golang.org/x/xerrors" @@ -1460,6 +1462,33 @@ func (m *StateModule) StateNetworkVersion(ctx context.Context, tsk types.TipSetK return m.StateManager.GetNetworkVersion(ctx, ts.Height()), nil } +func (a *StateAPI) StateActorCodeCIDs(ctx context.Context, nv network.Version) (map[string]cid.Cid, error) { + actorVersion, err := actors.VersionForNetwork(nv) + if err != nil { + return nil, xerrors.Errorf("invalid network version") + } + + cids := make(map[string]cid.Cid) + + manifestCid, ok := actors.GetManifest(actorVersion) + if !ok { + return nil, xerrors.Errorf("cannot get manifest CID") + } + + cids["manifest"] = manifestCid + + var actorKeys = actors.GetBuiltinActorsKeys() + for _, name := range actorKeys { + actorCID, ok := actors.GetActorCodeID(actorVersion, name) + if !ok { + return nil, xerrors.Errorf("didn't find actor %v code id for actor version %d", name, + actorVersion) + } + cids[name] = actorCID + } + return cids, nil +} + func (a *StateAPI) StateGetRandomnessFromTickets(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte, tsk types.TipSetKey) (abi.Randomness, error) { return a.StateManager.GetRandomnessFromTickets(ctx, personalization, randEpoch, entropy, tsk) }