Skip to content

Commit

Permalink
Filecoin messages can again be converted to Eth Txs
Browse files Browse the repository at this point in the history
  • Loading branch information
Geoff Stuart committed Jan 21, 2023
1 parent edad5f2 commit 5debd2c
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 55 deletions.
4 changes: 2 additions & 2 deletions chain/messagesigner/messagesigner.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,9 @@ func (ms *MessageSigner) dstoreKey(addr address.Address) datastore.Key {

func SigningBytes(msg *types.Message, sigType crypto.SigType) ([]byte, error) {
if sigType == crypto.SigTypeDelegated {
txArgs, err := ethtypes.EthTxArgsFromMessage(msg)
txArgs, err := ethtypes.EthTxArgsFromUnsignedEthMessage(msg)
if err != nil {
return nil, xerrors.Errorf("failed to reconstruct eth transaction: %w", err)
return nil, xerrors.Errorf("failed to convert to eth message: %w", err)
}
rlpEncodedMsg, err := txArgs.ToRlpUnsignedMsg()
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion chain/signatures.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func AuthenticateMessage(msg *types.SignedMessage, signer address.Address) error
typ := msg.Signature.Type
switch typ {
case crypto.SigTypeDelegated:
txArgs, err := ethtypes.EthTxArgsFromUnsignedMessage(&msg.Message)
txArgs, err := ethtypes.EthTxArgsFromUnsignedEthMessage(&msg.Message)
if err != nil {
return xerrors.Errorf("failed to reconstruct eth transaction: %w", err)
}
Expand Down
38 changes: 28 additions & 10 deletions chain/types/ethtypes/eth_transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,18 @@ type EthTxArgs struct {
S big.Int `json:"s"`
}

// EthTxFromSignedMessage does NOT populate:
// EthTxFromSignedEthMessage does NOT populate:
// - BlockHash
// - BlockNumber
// - TransactionIndex
// - From
func EthTxFromSignedMessage(smsg *types.SignedMessage) (EthTx, error) {
txArgs, err := EthTxArgsFromUnsignedMessage(&smsg.Message)
// - Hash
func EthTxFromSignedEthMessage(smsg *types.SignedMessage) (EthTx, error) {
if smsg.Signature.Type != typescrypto.SigTypeDelegated {
return EthTx{}, xerrors.Errorf("signature is not delegated type, is type: %d", smsg.Signature.Type)
}

txArgs, err := EthTxArgsFromUnsignedEthMessage(&smsg.Message)
if err != nil {
return EthTx{}, xerrors.Errorf("failed to convert the unsigned message: %w", err)
}
Expand All @@ -75,13 +80,7 @@ func EthTxFromSignedMessage(smsg *types.SignedMessage) (EthTx, error) {
r, s, v = EthBigIntZero, EthBigIntZero, EthBigIntZero
}

hash, err := EthHashFromCid(smsg.Cid())
if err != nil {
return EthTx{}, xerrors.Errorf("failed to calculate EthHash: %w", err)
}

return EthTx{
Hash: hash,
Nonce: EthUint64(txArgs.Nonce),
ChainID: EthUint64(txArgs.ChainID),
To: txArgs.To,
Expand All @@ -97,7 +96,26 @@ func EthTxFromSignedMessage(smsg *types.SignedMessage) (EthTx, error) {
}, nil
}

func EthTxArgsFromUnsignedMessage(msg *types.Message) (EthTxArgs, error) {
// EthTxFromNativeMessage does NOT populate:
// - BlockHash
// - BlockNumber
// - TransactionIndex
// - Hash
// - From (not valid)
// - To (not valid)
func EthTxFromNativeMessage(msg *types.Message) EthTx {
return EthTx{
Nonce: EthUint64(msg.Nonce),
ChainID: EthUint64(build.Eip155ChainId),
Value: EthBigInt(msg.Value),
Type: Eip1559TxType,
Gas: EthUint64(msg.GasLimit),
MaxFeePerGas: EthBigInt(msg.GasFeeCap),
MaxPriorityFeePerGas: EthBigInt(msg.GasPremium),
}
}

func EthTxArgsFromUnsignedEthMessage(msg *types.Message) (EthTxArgs, error) {
var (
to *EthAddress
params []byte
Expand Down
8 changes: 4 additions & 4 deletions itests/eth_account_abstraction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func TestEthAccountAbstraction(t *testing.T) {
msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK)
require.NoError(t, err)

txArgs, err := ethtypes.EthTxArgsFromUnsignedMessage(msgFromPlaceholder)
txArgs, err := ethtypes.EthTxArgsFromUnsignedEthMessage(msgFromPlaceholder)
require.NoError(t, err)

digest, err := txArgs.ToRlpUnsignedMsg()
Expand Down Expand Up @@ -106,7 +106,7 @@ func TestEthAccountAbstraction(t *testing.T) {
msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK)
require.NoError(t, err)

txArgs, err = ethtypes.EthTxArgsFromUnsignedMessage(msgFromPlaceholder)
txArgs, err = ethtypes.EthTxArgsFromUnsignedEthMessage(msgFromPlaceholder)
require.NoError(t, err)

digest, err = txArgs.ToRlpUnsignedMsg()
Expand Down Expand Up @@ -178,7 +178,7 @@ func TestEthAccountAbstractionFailure(t *testing.T) {
require.NoError(t, err)

msgFromPlaceholder.Value = abi.TokenAmount(types.MustParseFIL("1000"))
txArgs, err := ethtypes.EthTxArgsFromUnsignedMessage(msgFromPlaceholder)
txArgs, err := ethtypes.EthTxArgsFromUnsignedEthMessage(msgFromPlaceholder)
require.NoError(t, err)

digest, err := txArgs.ToRlpUnsignedMsg()
Expand Down Expand Up @@ -216,7 +216,7 @@ func TestEthAccountAbstractionFailure(t *testing.T) {
msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK)
require.NoError(t, err)

txArgs, err = ethtypes.EthTxArgsFromUnsignedMessage(msgFromPlaceholder)
txArgs, err = ethtypes.EthTxArgsFromUnsignedEthMessage(msgFromPlaceholder)
require.NoError(t, err)

digest, err = txArgs.ToRlpUnsignedMsg()
Expand Down
92 changes: 54 additions & 38 deletions node/impl/full/eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ func (a *EthModule) EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthH
if err != nil {
return ethtypes.EthBlock{}, xerrors.Errorf("error loading tipset %s: %w", ts, err)
}
return newEthBlockFromFilecoinTipSet(ctx, ts, fullTxInfo, a.Chain, a.ChainAPI, a.StateAPI)
return newEthBlockFromFilecoinTipSet(ctx, ts, fullTxInfo, a.Chain, a.StateAPI)
}

func (a *EthModule) parseBlkParam(ctx context.Context, blkParam string) (tipset *types.TipSet, err error) {
Expand Down Expand Up @@ -248,7 +248,7 @@ func (a *EthModule) EthGetBlockByNumber(ctx context.Context, blkParam string, fu
if err != nil {
return ethtypes.EthBlock{}, err
}
return newEthBlockFromFilecoinTipSet(ctx, ts, fullTxInfo, a.Chain, a.ChainAPI, a.StateAPI)
return newEthBlockFromFilecoinTipSet(ctx, ts, fullTxInfo, a.Chain, a.StateAPI)
}

func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.EthHash) (*ethtypes.EthTx, error) {
Expand All @@ -270,7 +270,7 @@ func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *ethtype
// first, try to get the cid from mined transactions
msgLookup, err := a.StateAPI.StateSearchMsg(ctx, types.EmptyTSK, c, api.LookbackNoLimit, true)
if err == nil {
tx, err := newEthTxFromFilecoinMessageLookup(ctx, msgLookup, -1, a.Chain, a.StateAPI)
tx, err := newEthTxFromMessageLookup(ctx, msgLookup, -1, a.Chain, a.StateAPI)
if err == nil {
return &tx, nil
}
Expand All @@ -286,7 +286,7 @@ func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *ethtype

for _, p := range pending {
if p.Cid() == c {
tx, err := newEthTxFromFilecoinMessage(ctx, p, a.StateAPI)
tx, err := newEthTxFromSignedMessage(ctx, p, a.StateAPI)
if err != nil {
return nil, fmt.Errorf("could not convert Filecoin message into tx: %s", err)
}
Expand Down Expand Up @@ -335,7 +335,7 @@ func (a *EthModule) EthGetMessageCidByTransactionHash(ctx context.Context, txHas
}

func (a *EthModule) EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*ethtypes.EthHash, error) {
hash, err := EthTxHashFromFilecoinMessageCid(ctx, cid, a.StateAPI)
hash, err := EthTxHashFromMessageCid(ctx, cid, a.StateAPI)
if hash == ethtypes.EmptyEthHash {
// not found
return nil, nil
Expand Down Expand Up @@ -378,7 +378,7 @@ func (a *EthModule) EthGetTransactionReceipt(ctx context.Context, txHash ethtype
return nil, nil
}

tx, err := newEthTxFromFilecoinMessageLookup(ctx, msgLookup, -1, a.Chain, a.StateAPI)
tx, err := newEthTxFromMessageLookup(ctx, msgLookup, -1, a.Chain, a.StateAPI)
if err != nil {
return nil, nil
}
Expand Down Expand Up @@ -614,7 +614,7 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint
for ts.Height() >= abi.ChainEpoch(oldestBlkHeight) {
// Unfortunately we need to rebuild the full message view so we can
// totalize gas used in the tipset.
block, err := newEthBlockFromFilecoinTipSet(ctx, ts, false, a.Chain, a.ChainAPI, a.StateAPI)
block, err := newEthBlockFromFilecoinTipSet(ctx, ts, false, a.Chain, a.StateAPI)
if err != nil {
return ethtypes.EthFeeHistory{}, fmt.Errorf("cannot create eth block: %v", err)
}
Expand Down Expand Up @@ -1246,7 +1246,7 @@ func ethFilterResultFromEvents(evs []*filter.CollectedEvent, sa StateAPI) (*etht
return nil, err
}

log.TransactionHash, err = EthTxHashFromFilecoinMessageCid(context.TODO(), ev.MsgCid, sa)
log.TransactionHash, err = EthTxHashFromMessageCid(context.TODO(), ev.MsgCid, sa)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -1288,7 +1288,7 @@ func ethFilterResultFromMessages(cs []*types.SignedMessage, sa StateAPI) (*ethty
res := &ethtypes.EthFilterResult{}

for _, c := range cs {
hash, err := EthTxHashFromSignedFilecoinMessage(context.TODO(), c, sa)
hash, err := EthTxHashFromSignedMessage(context.TODO(), c, sa)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -1389,7 +1389,7 @@ func (e *ethSubscription) start(ctx context.Context) {
case *filter.CollectedEvent:
resp.Result, err = ethFilterResultFromEvents([]*filter.CollectedEvent{vt}, e.StateAPI)
case *types.TipSet:
eb, err := newEthBlockFromFilecoinTipSet(ctx, vt, true, e.Chain, e.ChainAPI, e.StateAPI)
eb, err := newEthBlockFromFilecoinTipSet(ctx, vt, true, e.Chain, e.StateAPI)
if err != nil {
break
}
Expand Down Expand Up @@ -1423,7 +1423,7 @@ func (e *ethSubscription) stop() {
}
}

func newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTxInfo bool, cs *store.ChainStore, ca ChainAPI, sa StateAPI) (ethtypes.EthBlock, error) {
func newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTxInfo bool, cs *store.ChainStore, sa StateAPI) (ethtypes.EthBlock, error) {
parent, err := cs.LoadTipSet(ctx, ts.Parents())
if err != nil {
return ethtypes.EthBlock{}, err
Expand Down Expand Up @@ -1462,7 +1462,7 @@ func newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTx
}
gasUsed += msgLookup.Receipt.GasUsed

tx, err := newEthTxFromFilecoinMessageLookup(ctx, msgLookup, txIdx, cs, sa)
tx, err := newEthTxFromMessageLookup(ctx, msgLookup, txIdx, cs, sa)
if err != nil {
return ethtypes.EthBlock{}, nil
}
Expand Down Expand Up @@ -1522,11 +1522,11 @@ func lookupEthAddress(ctx context.Context, addr address.Address, sa StateAPI) (e
return ethtypes.EthAddressFromFilecoinAddress(idAddr)
}

func EthTxHashFromFilecoinMessageCid(ctx context.Context, c cid.Cid, sa StateAPI) (ethtypes.EthHash, error) {
func EthTxHashFromMessageCid(ctx context.Context, c cid.Cid, sa StateAPI) (ethtypes.EthHash, error) {
smsg, err := sa.Chain.GetSignedMessage(ctx, c)
if err == nil {
// This is an Eth Tx, Secp message, Or BLS message in the mpool
return EthTxHashFromSignedFilecoinMessage(ctx, smsg, sa)
return EthTxHashFromSignedMessage(ctx, smsg, sa)
}

_, err = sa.Chain.GetMessage(ctx, c)
Expand All @@ -1538,9 +1538,9 @@ func EthTxHashFromFilecoinMessageCid(ctx context.Context, c cid.Cid, sa StateAPI
return ethtypes.EmptyEthHash, nil
}

func EthTxHashFromSignedFilecoinMessage(ctx context.Context, smsg *types.SignedMessage, sa StateAPI) (ethtypes.EthHash, error) {
func EthTxHashFromSignedMessage(ctx context.Context, smsg *types.SignedMessage, sa StateAPI) (ethtypes.EthHash, error) {
if smsg.Signature.Type == crypto.SigTypeDelegated {
ethTx, err := newEthTxFromFilecoinMessage(ctx, smsg, sa)
ethTx, err := newEthTxFromSignedMessage(ctx, smsg, sa)
if err != nil {
return ethtypes.EmptyEthHash, err
}
Expand All @@ -1550,32 +1550,47 @@ func EthTxHashFromSignedFilecoinMessage(ctx context.Context, smsg *types.SignedM
return ethtypes.EthHashFromCid(smsg.Cid())
}

func newEthTxFromFilecoinMessage(ctx context.Context, smsg *types.SignedMessage, sa StateAPI) (ethtypes.EthTx, error) {
tx, err := ethtypes.EthTxFromSignedMessage(smsg)
if err != nil {
return ethtypes.EthTx{}, xerrors.Errorf("failed to convert from signed message: %w", err)
}
func newEthTxFromSignedMessage(ctx context.Context, smsg *types.SignedMessage, sa StateAPI) (ethtypes.EthTx, error) {
var tx ethtypes.EthTx
var err error

fromEthAddr, err := lookupEthAddress(ctx, smsg.Message.From, sa)
if err != nil {
return ethtypes.EthTx{}, xerrors.Errorf("failed to lookup from ethaddress: %w", err)
}
// This is an eth tx
if smsg.Signature.Type == crypto.SigTypeDelegated {
tx, err = ethtypes.EthTxFromSignedEthMessage(smsg)
if err != nil {
return ethtypes.EthTx{}, xerrors.Errorf("failed to convert from signed message: %w", err)
}

toEthAddr, err := lookupEthAddress(ctx, smsg.Message.To, sa)
if err != nil {
return ethtypes.EthTx{}, xerrors.Errorf("failed to lookup to ethaddress: %w", err)
}
tx.From, err = lookupEthAddress(ctx, smsg.Message.From, sa)
if err != nil {
return ethtypes.EthTx{}, xerrors.Errorf("failed to lookup from ethaddress: %w", err)
}

tx.From = fromEthAddr
tx.To = &toEthAddr
tx.Hash, err = tx.TxHash()
if err != nil {
return tx, err
}
} else if smsg.Signature.Type == crypto.SigTypeUnknown { // Executed BLS Filecoin message
tx = ethtypes.EthTxFromNativeMessage(smsg.VMMessage())
tx.Hash, err = ethtypes.EthHashFromCid(smsg.Message.Cid())
if err != nil {
return tx, err
}
} else { // Secp Filecoin Message or BLS Filecoin message in the mpool
tx = ethtypes.EthTxFromNativeMessage(smsg.VMMessage())
tx.Hash, err = ethtypes.EthHashFromCid(smsg.Cid())
if err != nil {
return tx, err
}
}

return tx, nil
}

// newEthTxFromFilecoinMessageLookup creates an ethereum transaction from filecoin message lookup. If a negative txIdx is passed
// into the function, it looksup the transaction index of the message in the tipset, otherwise it uses the txIdx passed into the
// newEthTxFromMessageLookup creates an ethereum transaction from filecoin message lookup. If a negative txIdx is passed
// into the function, it looks up the transaction index of the message in the tipset, otherwise it uses the txIdx passed into the
// function
func newEthTxFromFilecoinMessageLookup(ctx context.Context, msgLookup *api.MsgLookup, txIdx int, cs *store.ChainStore, sa StateAPI) (ethtypes.EthTx, error) {
func newEthTxFromMessageLookup(ctx context.Context, msgLookup *api.MsgLookup, txIdx int, cs *store.ChainStore, sa StateAPI) (ethtypes.EthTx, error) {
if msgLookup == nil {
return ethtypes.EthTx{}, fmt.Errorf("msg does not exist")
}
Expand Down Expand Up @@ -1634,7 +1649,7 @@ func newEthTxFromFilecoinMessageLookup(ctx context.Context, msgLookup *api.MsgLo
}
}

tx, err := newEthTxFromFilecoinMessage(ctx, smsg, sa)
tx, err := newEthTxFromSignedMessage(ctx, smsg, sa)
if err != nil {
return ethtypes.EthTx{}, err
}
Expand Down Expand Up @@ -1680,7 +1695,8 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
LogsBloom: ethtypes.EmptyEthBloom[:],
}

if receipt.To == nil && lookup.Receipt.ExitCode.IsSuccess() {
// V.Int will be nil for non-eth transactions, so we want to skip unmarshalling the create return.
if receipt.To == nil && lookup.Receipt.ExitCode.IsSuccess() && tx.V.Int != nil {
// Create and Create2 return the same things.
var ret eam.CreateReturn
if err := ret.UnmarshalCBOR(bytes.NewReader(lookup.Receipt.Return)); err != nil {
Expand Down Expand Up @@ -1760,7 +1776,7 @@ func (m *EthTxHashManager) Apply(ctx context.Context, from, to *types.TipSet) er
continue
}

hash, err := EthTxHashFromSignedFilecoinMessage(ctx, smsg, m.StateAPI)
hash, err := EthTxHashFromSignedMessage(ctx, smsg, m.StateAPI)
if err != nil {
return err
}
Expand Down Expand Up @@ -1797,7 +1813,7 @@ func WaitForMpoolUpdates(ctx context.Context, ch <-chan api.MpoolUpdate, manager
continue
}

ethTx, err := newEthTxFromFilecoinMessage(ctx, u.Message, manager.StateAPI)
ethTx, err := newEthTxFromSignedMessage(ctx, u.Message, manager.StateAPI)
if err != nil {
log.Errorf("error converting filecoin message to eth tx: %s", err)
}
Expand Down

0 comments on commit 5debd2c

Please sign in to comment.