Merge pull request #8486 from filecoin-project/gstuart/robust-address-endpoint
Feat: API: Implement StateLookupRobustAddress
This commit is contained in:
commit
a3a3fefb1c
@ -874,6 +874,11 @@ workflows:
|
|||||||
suite: itest-get_messages_in_ts
|
suite: itest-get_messages_in_ts
|
||||||
target: "./itests/get_messages_in_ts_test.go"
|
target: "./itests/get_messages_in_ts_test.go"
|
||||||
|
|
||||||
|
- test:
|
||||||
|
name: test-itest-lookup_robust_address
|
||||||
|
suite: itest-lookup_robust_address
|
||||||
|
target: "./itests/lookup_robust_address_test.go"
|
||||||
|
|
||||||
- test:
|
- test:
|
||||||
name: test-itest-mempool
|
name: test-itest-mempool
|
||||||
suite: itest-mempool
|
suite: itest-mempool
|
||||||
|
@ -522,8 +522,10 @@ type FullNode interface {
|
|||||||
StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*MarketDeal, error) //perm:read
|
StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*MarketDeal, error) //perm:read
|
||||||
// StateLookupID retrieves the ID address of the given address
|
// StateLookupID retrieves the ID address of the given address
|
||||||
StateLookupID(context.Context, address.Address, types.TipSetKey) (address.Address, error) //perm:read
|
StateLookupID(context.Context, address.Address, types.TipSetKey) (address.Address, error) //perm:read
|
||||||
// StateAccountKey returns the public key address of the given ID address
|
// StateAccountKey returns the public key address of the given ID address for secp and bls accounts
|
||||||
StateAccountKey(context.Context, address.Address, types.TipSetKey) (address.Address, error) //perm:read
|
StateAccountKey(context.Context, address.Address, types.TipSetKey) (address.Address, error) //perm:read
|
||||||
|
// StateLookupRobustAddress returns the public key address of the given ID address for non-account addresses (multisig, miners etc)
|
||||||
|
StateLookupRobustAddress(context.Context, address.Address, types.TipSetKey) (address.Address, error) //perm:read
|
||||||
// StateChangedActors returns all the actors whose states change between the two given state CIDs
|
// StateChangedActors returns all the actors whose states change between the two given state CIDs
|
||||||
// TODO: Should this take tipset keys instead?
|
// TODO: Should this take tipset keys instead?
|
||||||
StateChangedActors(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error) //perm:read
|
StateChangedActors(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error) //perm:read
|
||||||
|
@ -2496,6 +2496,21 @@ func (mr *MockFullNodeMockRecorder) StateLookupID(arg0, arg1, arg2 interface{})
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateLookupID", reflect.TypeOf((*MockFullNode)(nil).StateLookupID), arg0, arg1, arg2)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateLookupID", reflect.TypeOf((*MockFullNode)(nil).StateLookupID), arg0, arg1, arg2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StateLookupRobustAddress mocks base method.
|
||||||
|
func (m *MockFullNode) StateLookupRobustAddress(arg0 context.Context, arg1 address.Address, arg2 types.TipSetKey) (address.Address, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "StateLookupRobustAddress", arg0, arg1, arg2)
|
||||||
|
ret0, _ := ret[0].(address.Address)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// StateLookupRobustAddress indicates an expected call of StateLookupRobustAddress.
|
||||||
|
func (mr *MockFullNodeMockRecorder) StateLookupRobustAddress(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateLookupRobustAddress", reflect.TypeOf((*MockFullNode)(nil).StateLookupRobustAddress), arg0, arg1, arg2)
|
||||||
|
}
|
||||||
|
|
||||||
// StateMarketBalance mocks base method.
|
// StateMarketBalance mocks base method.
|
||||||
func (m *MockFullNode) StateMarketBalance(arg0 context.Context, arg1 address.Address, arg2 types.TipSetKey) (api.MarketBalance, error) {
|
func (m *MockFullNode) StateMarketBalance(arg0 context.Context, arg1 address.Address, arg2 types.TipSetKey) (api.MarketBalance, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
@ -364,6 +364,8 @@ type FullNodeStruct struct {
|
|||||||
|
|
||||||
StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"`
|
StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"`
|
||||||
|
|
||||||
|
StateLookupRobustAddress func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"`
|
||||||
|
|
||||||
StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MarketBalance, error) `perm:"read"`
|
StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MarketBalance, error) `perm:"read"`
|
||||||
|
|
||||||
StateMarketDeals func(p0 context.Context, p1 types.TipSetKey) (map[string]MarketDeal, error) `perm:"read"`
|
StateMarketDeals func(p0 context.Context, p1 types.TipSetKey) (map[string]MarketDeal, error) `perm:"read"`
|
||||||
@ -2528,6 +2530,17 @@ func (s *FullNodeStub) StateLookupID(p0 context.Context, p1 address.Address, p2
|
|||||||
return *new(address.Address), ErrNotSupported
|
return *new(address.Address), ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *FullNodeStruct) StateLookupRobustAddress(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) {
|
||||||
|
if s.Internal.StateLookupRobustAddress == nil {
|
||||||
|
return *new(address.Address), ErrNotSupported
|
||||||
|
}
|
||||||
|
return s.Internal.StateLookupRobustAddress(p0, p1, p2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *FullNodeStub) StateLookupRobustAddress(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) {
|
||||||
|
return *new(address.Address), ErrNotSupported
|
||||||
|
}
|
||||||
|
|
||||||
func (s *FullNodeStruct) StateMarketBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MarketBalance, error) {
|
func (s *FullNodeStruct) StateMarketBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MarketBalance, error) {
|
||||||
if s.Internal.StateMarketBalance == nil {
|
if s.Internal.StateMarketBalance == nil {
|
||||||
return *new(MarketBalance), ErrNotSupported
|
return *new(MarketBalance), ErrNotSupported
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -4,6 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/v7/actors/migration/nv15"
|
"github.com/filecoin-project/specs-actors/v7/actors/migration/nv15"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/rand"
|
"github.com/filecoin-project/lotus/chain/rand"
|
||||||
@ -22,6 +24,7 @@ import (
|
|||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
|
_init "github.com/filecoin-project/lotus/chain/actors/builtin/init"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||||
"github.com/filecoin-project/lotus/chain/state"
|
"github.com/filecoin-project/lotus/chain/state"
|
||||||
@ -318,6 +321,48 @@ func (sm *StateManager) LookupID(ctx context.Context, addr address.Address, ts *
|
|||||||
return state.LookupID(addr)
|
return state.LookupID(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sm *StateManager) LookupRobustAddress(ctx context.Context, idAddr address.Address, ts *types.TipSet) (address.Address, error) {
|
||||||
|
idAddrDecoded, err := address.IDFromAddress(idAddr)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, xerrors.Errorf("failed to decode provided address as id addr: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cst := cbor.NewCborStore(sm.cs.StateBlockstore())
|
||||||
|
wrapStore := adt.WrapStore(ctx, cst)
|
||||||
|
|
||||||
|
stateTree, err := state.LoadStateTree(cst, sm.parentState(ts))
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, xerrors.Errorf("load state tree: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
initActor, err := stateTree.GetActor(_init.Address)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, xerrors.Errorf("load init actor: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
initState, err := _init.Load(wrapStore, initActor)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, xerrors.Errorf("load init state: %w", err)
|
||||||
|
}
|
||||||
|
robustAddr := address.Undef
|
||||||
|
|
||||||
|
err = initState.ForEachActor(func(id abi.ActorID, addr address.Address) error {
|
||||||
|
if uint64(id) == idAddrDecoded {
|
||||||
|
robustAddr = addr
|
||||||
|
// Hacky way to early return from ForEach
|
||||||
|
return xerrors.New("robust address found")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if robustAddr == address.Undef {
|
||||||
|
if err == nil {
|
||||||
|
return address.Undef, xerrors.Errorf("Address %s not found", idAddr.String())
|
||||||
|
}
|
||||||
|
return address.Undef, xerrors.Errorf("finding address: %w", err)
|
||||||
|
}
|
||||||
|
return robustAddr, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (sm *StateManager) ValidateChain(ctx context.Context, ts *types.TipSet) error {
|
func (sm *StateManager) ValidateChain(ctx context.Context, ts *types.TipSet) error {
|
||||||
tschain := []*types.TipSet{ts}
|
tschain := []*types.TipSet{ts}
|
||||||
for ts.Height() != 0 {
|
for ts.Height() != 0 {
|
||||||
|
@ -181,6 +181,7 @@
|
|||||||
* [StateListMessages](#StateListMessages)
|
* [StateListMessages](#StateListMessages)
|
||||||
* [StateListMiners](#StateListMiners)
|
* [StateListMiners](#StateListMiners)
|
||||||
* [StateLookupID](#StateLookupID)
|
* [StateLookupID](#StateLookupID)
|
||||||
|
* [StateLookupRobustAddress](#StateLookupRobustAddress)
|
||||||
* [StateMarketBalance](#StateMarketBalance)
|
* [StateMarketBalance](#StateMarketBalance)
|
||||||
* [StateMarketDeals](#StateMarketDeals)
|
* [StateMarketDeals](#StateMarketDeals)
|
||||||
* [StateMarketParticipants](#StateMarketParticipants)
|
* [StateMarketParticipants](#StateMarketParticipants)
|
||||||
@ -5037,7 +5038,7 @@ A nil TipSetKey can be provided as a param, this will cause the heaviest tipset
|
|||||||
|
|
||||||
|
|
||||||
### StateAccountKey
|
### StateAccountKey
|
||||||
StateAccountKey returns the public key address of the given ID address
|
StateAccountKey returns the public key address of the given ID address for secp and bls accounts
|
||||||
|
|
||||||
|
|
||||||
Perms: read
|
Perms: read
|
||||||
@ -5783,6 +5784,29 @@ Response:
|
|||||||
StateLookupID retrieves the ID address of the given address
|
StateLookupID retrieves the ID address of the given address
|
||||||
|
|
||||||
|
|
||||||
|
Perms: read
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
"f01234",
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
Response: `"f01234"`
|
||||||
|
|
||||||
|
### StateLookupRobustAddress
|
||||||
|
StateLookupRobustAddress returns the public key address of the given ID address for non-account addresses (multisig, miners etc)
|
||||||
|
|
||||||
|
|
||||||
Perms: read
|
Perms: read
|
||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
|
32
itests/lookup_robust_address_test.go
Normal file
32
itests/lookup_robust_address_test.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package itests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-state-types/network"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
"github.com/filecoin-project/lotus/itests/kit"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStateLookupRobustAddress(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
kit.QuietMiningLogs()
|
||||||
|
|
||||||
|
client, miner, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.GenesisNetworkVersion(network.Version15))
|
||||||
|
ens.InterconnectAll().BeginMining(10 * time.Millisecond)
|
||||||
|
|
||||||
|
addr, err := miner.ActorAddress(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Look up the robust address
|
||||||
|
robAddr, err := client.StateLookupRobustAddress(ctx, addr, types.EmptyTSK)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Check the id address for the given robust address and make sure it matches
|
||||||
|
idAddr, err := client.StateLookupID(ctx, robAddr, types.EmptyTSK)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, addr, idAddr)
|
||||||
|
}
|
@ -449,6 +449,15 @@ func (m *StateModule) StateLookupID(ctx context.Context, addr address.Address, t
|
|||||||
return m.StateManager.LookupID(ctx, addr, ts)
|
return m.StateManager.LookupID(ctx, addr, ts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *StateAPI) StateLookupRobustAddress(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
||||||
|
ts, err := a.Chain.GetTipSetFromKey(ctx, tsk)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.StateManager.LookupRobustAddress(ctx, addr, ts)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *StateModule) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
func (m *StateModule) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
||||||
ts, err := m.Chain.GetTipSetFromKey(ctx, tsk)
|
ts, err := m.Chain.GetTipSetFromKey(ctx, tsk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user