feat: use f4 eth addresses wherever possible (#9532)
Co-authored-by: Raúl Kripalani <raul@protocol.ai>
This commit is contained in:
parent
aa0e6c17b9
commit
56b238980b
@ -81,7 +81,7 @@ func NewEthTxArgsFromMessage(msg *types.Message) (EthTxArgs, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isCreate {
|
if isCreate {
|
||||||
addr, err := EthAddressFromFilecoinIDAddress(msg.To)
|
addr, err := EthAddressFromFilecoinAddress(msg.To)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return EthTxArgs{}, nil
|
return EthTxArgs{}, nil
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/filecoin-project/go-state-types/builtin"
|
"github.com/filecoin-project/go-state-types/builtin"
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
"github.com/multiformats/go-multihash"
|
"github.com/multiformats/go-multihash"
|
||||||
|
"github.com/multiformats/go-varint"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
@ -292,15 +293,41 @@ func (ea EthAddress) ToFilecoinAddress() (address.Address, error) {
|
|||||||
return addr, nil
|
return addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func EthAddressFromFilecoinIDAddress(addr address.Address) (EthAddress, error) {
|
func TryEthAddressFromFilecoinAddress(addr address.Address, allowId bool) (EthAddress, bool, error) {
|
||||||
id, err := address.IDFromAddress(addr)
|
switch addr.Protocol() {
|
||||||
if err != nil {
|
case address.ID:
|
||||||
return EthAddress{}, err
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var ethaddr EthAddress
|
return EthAddress{}, false, nil
|
||||||
ethaddr[0] = 0xff
|
}
|
||||||
binary.BigEndian.PutUint64(ethaddr[12:], id)
|
|
||||||
return ethaddr, 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)
|
||||||
|
}
|
||||||
|
return ethAddr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func EthAddressFromHex(s string) (EthAddress, error) {
|
func EthAddressFromHex(s string) (EthAddress, error) {
|
||||||
|
@ -119,7 +119,7 @@ func TestParseEthAddr(t *testing.T) {
|
|||||||
addr, err := address.NewIDAddress(id)
|
addr, err := address.NewIDAddress(id)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
eaddr, err := EthAddressFromFilecoinIDAddress(addr)
|
eaddr, err := EthAddressFromFilecoinAddress(addr)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
faddr, err := eaddr.ToFilecoinAddress()
|
faddr, err := eaddr.ToFilecoinAddress()
|
||||||
|
@ -588,6 +588,50 @@ func (a *EthModule) ethBlockFromFilecoinTipSet(ctx context.Context, ts *types.Ti
|
|||||||
return block, nil
|
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) {
|
func (a *EthModule) ethTxFromFilecoinMessageLookup(ctx context.Context, msgLookup *api.MsgLookup) (api.EthTx, error) {
|
||||||
if msgLookup == nil {
|
if msgLookup == nil {
|
||||||
return api.EthTx{}, fmt.Errorf("msg does not exist")
|
return api.EthTx{}, fmt.Errorf("msg does not exist")
|
||||||
@ -613,22 +657,12 @@ func (a *EthModule) ethTxFromFilecoinMessageLookup(ctx context.Context, msgLooku
|
|||||||
return api.EthTx{}, err
|
return api.EthTx{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
fromFilIdAddr, err := a.StateAPI.StateLookupID(ctx, msg.From, types.EmptyTSK)
|
fromEthAddr, err := a.lookupEthAddress(ctx, msg.From)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return api.EthTx{}, err
|
return api.EthTx{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
fromEthAddr, err := api.EthAddressFromFilecoinIDAddress(fromFilIdAddr)
|
toEthAddr, err := a.lookupEthAddress(ctx, msg.To)
|
||||||
if err != nil {
|
|
||||||
return api.EthTx{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
toFilAddr, err := a.StateAPI.StateLookupID(ctx, msg.To, types.EmptyTSK)
|
|
||||||
if err != nil {
|
|
||||||
return api.EthTx{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
toEthAddr, err := api.EthAddressFromFilecoinIDAddress(toFilAddr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return api.EthTx{}, err
|
return api.EthTx{}, err
|
||||||
}
|
}
|
||||||
@ -636,7 +670,8 @@ func (a *EthModule) ethTxFromFilecoinMessageLookup(ctx context.Context, msgLooku
|
|||||||
toAddr := &toEthAddr
|
toAddr := &toEthAddr
|
||||||
input := msg.Params
|
input := msg.Params
|
||||||
// Check to see if we need to decode as contract deployment.
|
// 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 {
|
switch msg.Method {
|
||||||
case builtintypes.MethodsEAM.Create:
|
case builtintypes.MethodsEAM.Create:
|
||||||
toAddr = nil
|
toAddr = nil
|
||||||
|
Loading…
Reference in New Issue
Block a user