diff --git a/api/api_full.go b/api/api_full.go index e7a2d289e0..1f7c38edf8 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -771,6 +771,8 @@ type FullNode interface { EthAccounts(ctx context.Context) ([]ethtypes.EthAddress, error) //perm:read // EthAddressToFilecoinAddress converts an EthAddress into an f410 Filecoin Address EthAddressToFilecoinAddress(ctx context.Context, ethAddress ethtypes.EthAddress) (address.Address, error) //perm:read + // FilecoinAddressToEthAddress converts an f410 or f0 Filecoin Address to an EthAddress + FilecoinAddressToEthAddress(ctx context.Context, filecoinAddress address.Address) (ethtypes.EthAddress, error) //perm:read // EthBlockNumber returns the height of the latest (heaviest) TipSet EthBlockNumber(ctx context.Context) (ethtypes.EthUint64, error) //perm:read // EthGetBlockTransactionCountByNumber returns the number of messages in the TipSet diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index f49e912a25..370a213a0c 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -1448,6 +1448,21 @@ func (mr *MockFullNodeMockRecorder) EthUnsubscribe(arg0, arg1 interface{}) *gomo return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthUnsubscribe", reflect.TypeOf((*MockFullNode)(nil).EthUnsubscribe), arg0, arg1) } +// FilecoinAddressToEthAddress mocks base method. +func (m *MockFullNode) FilecoinAddressToEthAddress(arg0 context.Context, arg1 address.Address) (ethtypes.EthAddress, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FilecoinAddressToEthAddress", arg0, arg1) + ret0, _ := ret[0].(ethtypes.EthAddress) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FilecoinAddressToEthAddress indicates an expected call of FilecoinAddressToEthAddress. +func (mr *MockFullNodeMockRecorder) FilecoinAddressToEthAddress(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FilecoinAddressToEthAddress", reflect.TypeOf((*MockFullNode)(nil).FilecoinAddressToEthAddress), arg0, arg1) +} + // GasEstimateFeeCap mocks base method. func (m *MockFullNode) GasEstimateFeeCap(arg0 context.Context, arg1 *types.Message, arg2 int64, arg3 types.TipSetKey) (big.Int, error) { m.ctrl.T.Helper() diff --git a/api/proxy_gen.go b/api/proxy_gen.go index baf4337359..ef257e69b4 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -310,6 +310,8 @@ type FullNodeMethods struct { EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) `perm:"write"` + FilecoinAddressToEthAddress func(p0 context.Context, p1 address.Address) (ethtypes.EthAddress, error) `perm:"read"` + GasEstimateFeeCap func(p0 context.Context, p1 *types.Message, p2 int64, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` GasEstimateGasLimit func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (int64, error) `perm:"read"` @@ -2372,6 +2374,17 @@ func (s *FullNodeStub) EthUnsubscribe(p0 context.Context, p1 ethtypes.EthSubscri return false, ErrNotSupported } +func (s *FullNodeStruct) FilecoinAddressToEthAddress(p0 context.Context, p1 address.Address) (ethtypes.EthAddress, error) { + if s.Internal.FilecoinAddressToEthAddress == nil { + return *new(ethtypes.EthAddress), ErrNotSupported + } + return s.Internal.FilecoinAddressToEthAddress(p0, p1) +} + +func (s *FullNodeStub) FilecoinAddressToEthAddress(p0 context.Context, p1 address.Address) (ethtypes.EthAddress, error) { + return *new(ethtypes.EthAddress), ErrNotSupported +} + func (s *FullNodeStruct) GasEstimateFeeCap(p0 context.Context, p1 *types.Message, p2 int64, p3 types.TipSetKey) (types.BigInt, error) { if s.Internal.GasEstimateFeeCap == nil { return *new(types.BigInt), ErrNotSupported diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index a169a93655..9ea2223dc0 100644 Binary files a/build/openrpc/full.json.gz and b/build/openrpc/full.json.gz differ diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz index f8b13575a9..f97e6877eb 100644 Binary files a/build/openrpc/gateway.json.gz and b/build/openrpc/gateway.json.gz differ diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index b1e2bec9b0..0bb354ee52 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 c711608f56..ef84185290 100644 Binary files a/build/openrpc/worker.json.gz and b/build/openrpc/worker.json.gz differ diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index a383f4946b..8e8176c23e 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -101,6 +101,8 @@ * [EthSubscribe](#EthSubscribe) * [EthUninstallFilter](#EthUninstallFilter) * [EthUnsubscribe](#EthUnsubscribe) +* [Filecoin](#Filecoin) + * [FilecoinAddressToEthAddress](#FilecoinAddressToEthAddress) * [Gas](#Gas) * [GasEstimateFeeCap](#GasEstimateFeeCap) * [GasEstimateGasLimit](#GasEstimateGasLimit) @@ -2944,6 +2946,24 @@ Inputs: Response: `true` +## Filecoin + + +### FilecoinAddressToEthAddress +FilecoinAddressToEthAddress converts an f410 or f0 Filecoin Address to an EthAddress + + +Perms: read + +Inputs: +```json +[ + "f01234" +] +``` + +Response: `"0x5cbeecf99d3fdb3f25e309cc264f240bb0664031"` + ## Gas diff --git a/gateway/node.go b/gateway/node.go index 00a83df963..90a6812b53 100644 --- a/gateway/node.go +++ b/gateway/node.go @@ -89,6 +89,7 @@ type TargetAPI interface { WalletBalance(context.Context, address.Address) (types.BigInt, error) EthAddressToFilecoinAddress(ctx context.Context, ethAddress ethtypes.EthAddress) (address.Address, error) + FilecoinAddressToEthAddress(ctx context.Context, filecoinAddress address.Address) (ethtypes.EthAddress, error) EthBlockNumber(ctx context.Context) (ethtypes.EthUint64, error) EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum ethtypes.EthUint64) (ethtypes.EthUint64, error) EthGetBlockTransactionCountByHash(ctx context.Context, blkHash ethtypes.EthHash) (ethtypes.EthUint64, error) diff --git a/itests/eth_api_test.go b/itests/eth_api_test.go index 63c6aa5a21..32949cc716 100644 --- a/itests/eth_api_test.go +++ b/itests/eth_api_test.go @@ -46,3 +46,44 @@ func TestEthAddressToFilecoinAddress(t *testing.T) { require.Equal(t, filecoinIdArr, apiFilAddr) } + +func TestFilecoinAddressToEthAddress(t *testing.T) { + // Disable EthRPC to confirm that this method does NOT need the EthEnableRPC config set to true + client, _, _ := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC(), kit.DisableEthRPC()) + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + secpDelegatedKey, err := key.GenerateKey(types.KTDelegated) + require.NoError(t, err) + + filecoinKeyAddr, err := client.WalletImport(ctx, &secpDelegatedKey.KeyInfo) + require.NoError(t, err) + + ethAddr, err := ethtypes.EthAddressFromFilecoinAddress(filecoinKeyAddr) + require.NoError(t, err) + + apiEthAddr, err := client.FilecoinAddressToEthAddress(ctx, filecoinKeyAddr) + require.NoError(t, err) + + require.Equal(t, ethAddr, apiEthAddr) + + filecoinIdArr := builtin.StorageMarketActorAddr + ethAddr, err = ethtypes.EthAddressFromFilecoinAddress(filecoinIdArr) + require.NoError(t, err) + + apiEthAddr, err = client.FilecoinAddressToEthAddress(ctx, filecoinIdArr) + require.NoError(t, err) + + require.Equal(t, ethAddr, apiEthAddr) + + secpKey, err := key.GenerateKey(types.KTSecp256k1) + require.NoError(t, err) + + filecoinSecpAddr, err := client.WalletImport(ctx, &secpKey.KeyInfo) + require.NoError(t, err) + + _, err = client.FilecoinAddressToEthAddress(ctx, filecoinSecpAddr) + + require.ErrorContains(t, err, ethtypes.ErrInvalidAddress.Error()) +} diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index 8bf8cb162e..5d4e521275 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -186,6 +186,10 @@ func (a *EthAPI) EthAddressToFilecoinAddress(ctx context.Context, ethAddress eth return ethAddress.ToFilecoinAddress() } +func (a *EthAPI) FilecoinAddressToEthAddress(ctx context.Context, filecoinAddress address.Address) (ethtypes.EthAddress, error) { + return ethtypes.EthAddressFromFilecoinAddress(filecoinAddress) +} + func (a *EthModule) countTipsetMsgs(ctx context.Context, ts *types.TipSet) (int, error) { blkMsgs, err := a.Chain.BlockMsgsForTipset(ctx, ts) if err != nil {