clean up ethtypes: rationalize ethtypes.EthAddressFromFilecoinAddress and conversion methods (#9992)
This commit is contained in:
parent
105a1259bc
commit
3ef32395f3
Binary file not shown.
@ -5,6 +5,7 @@ import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
mathbig "math/big"
|
||||
"strconv"
|
||||
@ -30,6 +31,8 @@ var (
|
||||
EthTopic4 = "topic4"
|
||||
)
|
||||
|
||||
var ErrInvalidAddress = errors.New("invalid Filecoin Eth address")
|
||||
|
||||
type EthUint64 uint64
|
||||
|
||||
func (e EthUint64) MarshalJSON() ([]byte, error) {
|
||||
@ -249,21 +252,32 @@ func EthAddressFromPubKey(pubk []byte) ([]byte, error) {
|
||||
}
|
||||
|
||||
func EthAddressFromFilecoinAddress(addr address.Address) (EthAddress, error) {
|
||||
ethAddr, ok, err := TryEthAddressFromFilecoinAddress(addr, true)
|
||||
switch addr.Protocol() {
|
||||
case address.ID:
|
||||
id, err := address.IDFromAddress(addr)
|
||||
if err != nil {
|
||||
return EthAddress{}, xerrors.Errorf("failed to try converting filecoin to eth addr: %w", err)
|
||||
return EthAddress{}, err
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return EthAddress{}, 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
|
||||
case address.Delegated:
|
||||
payload := addr.Payload()
|
||||
namespace, n, err := varint.FromUvarint(payload)
|
||||
if err != nil {
|
||||
return EthAddress{}, xerrors.Errorf("invalid delegated address namespace in: %s", addr)
|
||||
}
|
||||
|
||||
return ethAddr, nil
|
||||
payload = payload[n:]
|
||||
if namespace == builtintypes.EthereumAddressManagerActorID {
|
||||
return CastEthAddress(payload)
|
||||
}
|
||||
}
|
||||
return EthAddress{}, ErrInvalidAddress
|
||||
}
|
||||
|
||||
// ParseEthAddress parses an Ethereum address from a hex string.
|
||||
func ParseEthAddress(s string) (EthAddress, error) {
|
||||
handlePrefix(&s)
|
||||
b, err := decodeHexString(s, EthAddressLength)
|
||||
if err != nil {
|
||||
return EthAddress{}, err
|
||||
@ -304,9 +318,13 @@ func (ea *EthAddress) UnmarshalJSON(b []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ea EthAddress) ToFilecoinAddress() (address.Address, error) {
|
||||
func (ea EthAddress) IsMaskedID() bool {
|
||||
idmask := [12]byte{0xff}
|
||||
if bytes.Equal(ea[:12], idmask[:]) {
|
||||
return bytes.Equal(ea[:12], idmask[:])
|
||||
}
|
||||
|
||||
func (ea EthAddress) ToFilecoinAddress() (address.Address, error) {
|
||||
if ea.IsMaskedID() {
|
||||
// This is a masked ID address.
|
||||
id := binary.BigEndian.Uint64(ea[12:])
|
||||
return address.NewIDAddress(id)
|
||||
@ -322,37 +340,6 @@ func (ea EthAddress) ToFilecoinAddress() (address.Address, error) {
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
// This API assumes that if an ID address is passed in, it doesn't have an equivalent
|
||||
// delegated address
|
||||
func TryEthAddressFromFilecoinAddress(addr address.Address, allowId bool) (EthAddress, bool, error) {
|
||||
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 == builtintypes.EthereumAddressManagerActorID {
|
||||
addr, err := CastEthAddress(payload)
|
||||
return addr, err == nil, err
|
||||
}
|
||||
}
|
||||
return EthAddress{}, false, nil
|
||||
}
|
||||
|
||||
type EthHash [EthHashLength]byte
|
||||
|
||||
func (h EthHash) MarshalJSON() ([]byte, error) {
|
||||
@ -372,25 +359,22 @@ func (h *EthHash) UnmarshalJSON(b []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func handlePrefix(s *string) {
|
||||
if strings.HasPrefix(*s, "0x") || strings.HasPrefix(*s, "0X") {
|
||||
*s = (*s)[2:]
|
||||
func decodeHexString(s string, expectedLen int) ([]byte, error) {
|
||||
// Strip the leading 0x or 0X prefix since hex.DecodeString does not support it.
|
||||
if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") {
|
||||
s = s[2:]
|
||||
}
|
||||
if len(*s)%2 == 1 {
|
||||
*s = "0" + *s
|
||||
// Sometimes clients will omit a leading zero in a byte; pad so we can decode correctly.
|
||||
if len(s)%2 == 1 {
|
||||
s = "0" + s
|
||||
}
|
||||
if len(s) != expectedLen*2 {
|
||||
return []byte{}, xerrors.Errorf("expected length %d, got %d", expectedLen, len(s))
|
||||
}
|
||||
|
||||
func decodeHexString(s string, length int) ([]byte, error) {
|
||||
b, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
return []byte{}, xerrors.Errorf("cannot parse hash: %w", err)
|
||||
return []byte{}, xerrors.Errorf("cannot parse hex value: %w", err)
|
||||
}
|
||||
|
||||
if len(b) > length {
|
||||
return []byte{}, xerrors.Errorf("length of decoded bytes is longer than %d", length)
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
@ -399,7 +383,6 @@ func EthHashFromCid(c cid.Cid) (EthHash, error) {
|
||||
}
|
||||
|
||||
func ParseEthHash(s string) (EthHash, error) {
|
||||
handlePrefix(&s)
|
||||
b, err := decodeHexString(s, EthHashLength)
|
||||
if err != nil {
|
||||
return EthHash{}, err
|
||||
@ -427,30 +410,6 @@ type EthFeeHistory struct {
|
||||
Reward *[][]EthBigInt `json:"reward,omitempty"`
|
||||
}
|
||||
|
||||
type BlkNumType int64
|
||||
|
||||
const (
|
||||
BlkNumLatest BlkNumType = iota
|
||||
BlkNumPending
|
||||
BlkNumVal
|
||||
)
|
||||
|
||||
func ParseBlkNumOption(str string) (typ BlkNumType, blkNum EthUint64, err error) {
|
||||
switch str {
|
||||
case "pending":
|
||||
return BlkNumPending, 0, nil
|
||||
case "latest":
|
||||
return BlkNumLatest, 0, nil
|
||||
default:
|
||||
var num EthUint64
|
||||
err := num.UnmarshalJSON([]byte(`"` + str + `"`))
|
||||
if err != nil {
|
||||
return BlkNumVal, 0, err
|
||||
}
|
||||
return BlkNumVal, num, nil
|
||||
}
|
||||
}
|
||||
|
||||
type EthFilterID EthHash
|
||||
|
||||
// An opaque identifier generated by the Lotus node to refer to an active subscription.
|
||||
|
@ -2529,26 +2529,26 @@ Inputs:
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
92,
|
||||
190,
|
||||
236,
|
||||
1,
|
||||
35,
|
||||
69,
|
||||
103,
|
||||
63,
|
||||
37,
|
||||
227,
|
||||
9,
|
||||
204,
|
||||
38,
|
||||
79,
|
||||
36,
|
||||
11,
|
||||
176,
|
||||
102,
|
||||
64,
|
||||
49
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
]
|
||||
```
|
||||
@ -2583,26 +2583,26 @@ Inputs:
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
92,
|
||||
190,
|
||||
236,
|
||||
1,
|
||||
35,
|
||||
69,
|
||||
103,
|
||||
63,
|
||||
37,
|
||||
227,
|
||||
9,
|
||||
204,
|
||||
38,
|
||||
79,
|
||||
36,
|
||||
11,
|
||||
176,
|
||||
102,
|
||||
64,
|
||||
49
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
]
|
||||
```
|
||||
@ -2857,26 +2857,26 @@ Response:
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
92,
|
||||
190,
|
||||
236,
|
||||
1,
|
||||
35,
|
||||
69,
|
||||
103,
|
||||
63,
|
||||
37,
|
||||
227,
|
||||
9,
|
||||
204,
|
||||
38,
|
||||
79,
|
||||
36,
|
||||
11,
|
||||
176,
|
||||
102,
|
||||
64,
|
||||
49
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
```
|
||||
|
||||
@ -2914,26 +2914,26 @@ Response:
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
92,
|
||||
190,
|
||||
236,
|
||||
1,
|
||||
35,
|
||||
69,
|
||||
103,
|
||||
63,
|
||||
37,
|
||||
227,
|
||||
9,
|
||||
204,
|
||||
38,
|
||||
79,
|
||||
36,
|
||||
11,
|
||||
176,
|
||||
102,
|
||||
64,
|
||||
49
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
```
|
||||
|
||||
@ -2960,26 +2960,26 @@ Response:
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
92,
|
||||
190,
|
||||
236,
|
||||
1,
|
||||
35,
|
||||
69,
|
||||
103,
|
||||
63,
|
||||
37,
|
||||
227,
|
||||
9,
|
||||
204,
|
||||
38,
|
||||
79,
|
||||
36,
|
||||
11,
|
||||
176,
|
||||
102,
|
||||
64,
|
||||
49
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
```
|
||||
|
||||
@ -3048,26 +3048,26 @@ Response:
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
92,
|
||||
190,
|
||||
236,
|
||||
249,
|
||||
157,
|
||||
63,
|
||||
219,
|
||||
48,
|
||||
18,
|
||||
52,
|
||||
86,
|
||||
124,
|
||||
38,
|
||||
79,
|
||||
36,
|
||||
11,
|
||||
176,
|
||||
102,
|
||||
64,
|
||||
49
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"result": {}
|
||||
}
|
||||
@ -3095,26 +3095,26 @@ Inputs:
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
92,
|
||||
190,
|
||||
236,
|
||||
1,
|
||||
35,
|
||||
69,
|
||||
103,
|
||||
63,
|
||||
37,
|
||||
227,
|
||||
9,
|
||||
204,
|
||||
38,
|
||||
79,
|
||||
36,
|
||||
11,
|
||||
176,
|
||||
102,
|
||||
64,
|
||||
49
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
]
|
||||
```
|
||||
@ -3143,26 +3143,26 @@ Inputs:
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
92,
|
||||
190,
|
||||
236,
|
||||
249,
|
||||
157,
|
||||
63,
|
||||
219,
|
||||
48,
|
||||
18,
|
||||
52,
|
||||
86,
|
||||
124,
|
||||
38,
|
||||
79,
|
||||
36,
|
||||
11,
|
||||
176,
|
||||
102,
|
||||
64,
|
||||
49
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
]
|
||||
```
|
||||
|
@ -1431,30 +1431,25 @@ func newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTx
|
||||
// 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 lookupEthAddress(ctx context.Context, addr address.Address, sa StateAPI) (ethtypes.EthAddress, error) {
|
||||
// Attempt to convert directly.
|
||||
if ethAddr, ok, err := ethtypes.TryEthAddressFromFilecoinAddress(addr, false); err != nil {
|
||||
return ethtypes.EthAddress{}, err
|
||||
} else if ok {
|
||||
// BLOCK A: We are trying to get an actual Ethereum address from an f410 address.
|
||||
// Attempt to convert directly, if it's an f4 address.
|
||||
ethAddr, err := ethtypes.EthAddressFromFilecoinAddress(addr)
|
||||
if err == nil && !ethAddr.IsMaskedID() {
|
||||
return ethAddr, nil
|
||||
}
|
||||
|
||||
// Lookup on the target actor.
|
||||
actor, err := sa.StateGetActor(ctx, addr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
// Lookup on the target actor and try to get an f410 address.
|
||||
if actor, err := sa.StateGetActor(ctx, addr, types.EmptyTSK); err != nil {
|
||||
return ethtypes.EthAddress{}, err
|
||||
}
|
||||
if actor.Address != nil {
|
||||
if ethAddr, ok, err := ethtypes.TryEthAddressFromFilecoinAddress(*actor.Address, false); err != nil {
|
||||
return ethtypes.EthAddress{}, err
|
||||
} else if ok {
|
||||
} else if actor.Address != nil {
|
||||
if ethAddr, err := ethtypes.EthAddressFromFilecoinAddress(*actor.Address); err == nil && !ethAddr.IsMaskedID() {
|
||||
return ethAddr, nil
|
||||
}
|
||||
}
|
||||
|
||||
// BLOCK B: We gave up on getting an actual Ethereum address and are falling back to a Masked ID address.
|
||||
// Check if we already have an ID addr, and use it if possible.
|
||||
if ethAddr, ok, err := ethtypes.TryEthAddressFromFilecoinAddress(addr, true); err != nil {
|
||||
return ethtypes.EthAddress{}, err
|
||||
} else if ok {
|
||||
if err == nil && ethAddr.IsMaskedID() {
|
||||
return ethAddr, nil
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user