Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat: use f4 eth addresses wherever possible #9532

Merged
merged 2 commits into from
Oct 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/eth_transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func NewEthTxArgsFromMessage(msg *types.Message) (EthTxArgs, error) {
}
}
if isCreate {
addr, err := EthAddressFromFilecoinIDAddress(msg.To)
addr, err := EthAddressFromFilecoinAddress(msg.To)
if err != nil {
return EthTxArgs{}, nil
}
Expand Down
43 changes: 35 additions & 8 deletions api/eth_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/ipfs/go-cid"
"github.com/multiformats/go-multihash"
"github.com/multiformats/go-varint"
"golang.org/x/xerrors"

"github.com/filecoin-project/go-address"
Expand Down Expand Up @@ -289,15 +290,41 @@ func (ea EthAddress) ToFilecoinAddress() (address.Address, error) {
return addr, nil
}

func EthAddressFromFilecoinIDAddress(addr address.Address) (EthAddress, error) {
id, err := address.IDFromAddress(addr)
if err != nil {
return EthAddress{}, err
func TryEthAddressFromFilecoinAddress(addr address.Address, allowId bool) (EthAddress, bool, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when would we want to not allow ID?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we want to check if we have an eth address (take a look at how we use this)

switch addr.Protocol() {
case address.ID:
if !allowId {
return EthAddress{}, false, nil
}
id, err := address.IDFromAddress(addr)
if err != nil {
return EthAddress{}, false, err
}
var ethaddr EthAddress
ethaddr[0] = 0xff
binary.BigEndian.PutUint64(ethaddr[12:], id)
return ethaddr, true, nil
case address.Delegated:
payload := addr.Payload()
namespace, n, err := varint.FromUvarint(payload)
if err != nil {
return EthAddress{}, false, xerrors.Errorf("invalid delegated address namespace in: %s", addr)
}
payload = payload[n:]
if namespace == builtin.EthereumAddressManagerActorID {
addr, err := EthAddressFromBytes(payload)
return addr, err == nil, err
}
}
return EthAddress{}, false, nil
}

func EthAddressFromFilecoinAddress(addr address.Address) (EthAddress, error) {
ethAddr, ok, err := TryEthAddressFromFilecoinAddress(addr, true)
if !ok && err == nil {
err = xerrors.Errorf("failed to convert filecoin address %s to an equivalent eth address", addr)
}
var ethaddr EthAddress
ethaddr[0] = 0xff
binary.BigEndian.PutUint64(ethaddr[12:], id)
return ethaddr, nil
return ethAddr, err
}

func EthAddressFromHex(s string) (EthAddress, error) {
Expand Down
2 changes: 1 addition & 1 deletion api/eth_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ func TestParseEthAddr(t *testing.T) {
addr, err := address.NewIDAddress(id)
require.Nil(t, err)

eaddr, err := EthAddressFromFilecoinIDAddress(addr)
eaddr, err := EthAddressFromFilecoinAddress(addr)
require.Nil(t, err)

faddr, err := eaddr.ToFilecoinAddress()
Expand Down
61 changes: 48 additions & 13 deletions node/impl/full/eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,50 @@ func (a *EthModule) ethBlockFromFilecoinTipSet(ctx context.Context, ts *types.Ti
return block, nil
}

// lookupEthAddress makes its best effort at finding the Ethereum address for a
// Filecoin address. It does the following:
//
// 1. If the supplied address is an f410 address, we return its payload as the EthAddress.
// 2. Otherwise (f0, f1, f2, f3), we look up the actor on the state tree. If it has a predictable address, we return it if it's f410 address.
// 3. Otherwise, we fall back to returning a masked ID Ethereum address. If the supplied address is an f0 address, we
// use that ID to form the masked ID address.
// 4. Otherwise, we fetch the actor's ID from the state tree and form the masked ID with it.
func (a *EthModule) lookupEthAddress(ctx context.Context, addr address.Address) (api.EthAddress, error) {
// Attempt to convert directly.
if ethAddr, ok, err := api.TryEthAddressFromFilecoinAddress(addr, false); err != nil {
return api.EthAddress{}, err
} else if ok {
return ethAddr, nil
}

// Lookup on the target actor.
actor, err := a.StateAPI.StateGetActor(ctx, addr, types.EmptyTSK)
if err != nil {
return api.EthAddress{}, err
}
if actor.Address != nil {
if ethAddr, ok, err := api.TryEthAddressFromFilecoinAddress(*actor.Address, false); err != nil {
return api.EthAddress{}, err
} else if ok {
return ethAddr, nil
}
}

// Check if we already have an ID addr, and use it if possible.
if ethAddr, ok, err := api.TryEthAddressFromFilecoinAddress(addr, true); err != nil {
return api.EthAddress{}, err
} else if ok {
return ethAddr, nil
}

// Otherwise, resolve the ID addr.
idAddr, err := a.StateAPI.StateLookupID(ctx, addr, types.EmptyTSK)
if err != nil {
return api.EthAddress{}, err
}
return api.EthAddressFromFilecoinAddress(idAddr)
}

func (a *EthModule) ethTxFromFilecoinMessageLookup(ctx context.Context, msgLookup *api.MsgLookup) (api.EthTx, error) {
if msgLookup == nil {
return api.EthTx{}, fmt.Errorf("msg does not exist")
Expand All @@ -613,30 +657,21 @@ func (a *EthModule) ethTxFromFilecoinMessageLookup(ctx context.Context, msgLooku
return api.EthTx{}, err
}

fromFilIdAddr, err := a.StateAPI.StateLookupID(ctx, msg.From, types.EmptyTSK)
if err != nil {
return api.EthTx{}, err
}

fromEthAddr, err := api.EthAddressFromFilecoinIDAddress(fromFilIdAddr)
if err != nil {
return api.EthTx{}, err
}

toFilAddr, err := a.StateAPI.StateLookupID(ctx, msg.To, types.EmptyTSK)
fromEthAddr, err := a.lookupEthAddress(ctx, msg.From)
if err != nil {
return api.EthTx{}, err
}

toEthAddr, err := api.EthAddressFromFilecoinIDAddress(toFilAddr)
toEthAddr, err := a.lookupEthAddress(ctx, msg.To)
if err != nil {
return api.EthTx{}, err
}

toAddr := &toEthAddr
input := msg.Params
// Check to see if we need to decode as contract deployment.
if toFilAddr == builtintypes.EthereumAddressManagerActorAddr {
// We don't need to resolve the to address, because there's only one form (an ID).
if msg.To == builtintypes.EthereumAddressManagerActorAddr {
switch msg.Method {
case builtintypes.MethodsEAM.Create:
toAddr = nil
Expand Down