Refactor: Unify EthTx to FilecoinMessage methods v2 (#10095)
* Refactor: Unify EthTx to FilecoinMessage methods * Filecoin messages can again be converted to Eth Txs * All BLS messages should calculated tx hash with unsigned message * Refactor newEthTxReceipt * fill in from and to for non-eth transactions * Hoist nil check out of newEthTxFromMessageLookup --------- Co-authored-by: Aayush <arajasek94@gmail.com> Co-authored-by: Raúl Kripalani <raul@protocol.ai>
This commit is contained in:
parent
6518122a2d
commit
af72e6f6ac
@ -202,7 +202,7 @@ func (ms *MessageSigner) dstoreKey(addr address.Address) datastore.Key {
|
|||||||
|
|
||||||
func SigningBytes(msg *types.Message, sigType crypto.SigType) ([]byte, error) {
|
func SigningBytes(msg *types.Message, sigType crypto.SigType) ([]byte, error) {
|
||||||
if sigType == crypto.SigTypeDelegated {
|
if sigType == crypto.SigTypeDelegated {
|
||||||
txArgs, err := ethtypes.EthTxArgsFromMessage(msg)
|
txArgs, err := ethtypes.EthTxArgsFromUnsignedEthMessage(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to reconstruct eth transaction: %w", err)
|
return nil, xerrors.Errorf("failed to reconstruct eth transaction: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ func AuthenticateMessage(msg *types.SignedMessage, signer address.Address) error
|
|||||||
typ := msg.Signature.Type
|
typ := msg.Signature.Type
|
||||||
switch typ {
|
switch typ {
|
||||||
case crypto.SigTypeDelegated:
|
case crypto.SigTypeDelegated:
|
||||||
txArgs, err := ethtypes.EthTxArgsFromMessage(&msg.Message)
|
txArgs, err := ethtypes.EthTxArgsFromUnsignedEthMessage(&msg.Message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("failed to reconstruct eth transaction: %w", err)
|
return xerrors.Errorf("failed to reconstruct eth transaction: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,44 @@ type EthTxArgs struct {
|
|||||||
S big.Int `json:"s"`
|
S big.Int `json:"s"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func EthTxArgsFromMessage(msg *types.Message) (EthTxArgs, error) {
|
// EthTxFromSignedEthMessage does NOT populate:
|
||||||
|
// - BlockHash
|
||||||
|
// - BlockNumber
|
||||||
|
// - TransactionIndex
|
||||||
|
// - From
|
||||||
|
// - 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, s, v, err := RecoverSignature(smsg.Signature)
|
||||||
|
if err != nil {
|
||||||
|
return EthTx{}, xerrors.Errorf("failed to recover signature: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return EthTx{
|
||||||
|
Nonce: EthUint64(txArgs.Nonce),
|
||||||
|
ChainID: EthUint64(txArgs.ChainID),
|
||||||
|
To: txArgs.To,
|
||||||
|
Value: EthBigInt(txArgs.Value),
|
||||||
|
Type: Eip1559TxType,
|
||||||
|
Gas: EthUint64(txArgs.GasLimit),
|
||||||
|
MaxFeePerGas: EthBigInt(txArgs.MaxFeePerGas),
|
||||||
|
MaxPriorityFeePerGas: EthBigInt(txArgs.MaxPriorityFeePerGas),
|
||||||
|
V: v,
|
||||||
|
R: r,
|
||||||
|
S: s,
|
||||||
|
Input: txArgs.Input,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func EthTxArgsFromUnsignedEthMessage(msg *types.Message) (EthTxArgs, error) {
|
||||||
var (
|
var (
|
||||||
to *EthAddress
|
to *EthAddress
|
||||||
params []byte
|
params []byte
|
||||||
|
@ -72,7 +72,7 @@ func TestEthAccountAbstraction(t *testing.T) {
|
|||||||
msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK)
|
msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
txArgs, err := ethtypes.EthTxArgsFromMessage(msgFromPlaceholder)
|
txArgs, err := ethtypes.EthTxArgsFromUnsignedEthMessage(msgFromPlaceholder)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
digest, err := txArgs.ToRlpUnsignedMsg()
|
digest, err := txArgs.ToRlpUnsignedMsg()
|
||||||
@ -108,7 +108,7 @@ func TestEthAccountAbstraction(t *testing.T) {
|
|||||||
msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK)
|
msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
txArgs, err = ethtypes.EthTxArgsFromMessage(msgFromPlaceholder)
|
txArgs, err = ethtypes.EthTxArgsFromUnsignedEthMessage(msgFromPlaceholder)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
digest, err = txArgs.ToRlpUnsignedMsg()
|
digest, err = txArgs.ToRlpUnsignedMsg()
|
||||||
@ -180,7 +180,7 @@ func TestEthAccountAbstractionFailure(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
msgFromPlaceholder.Value = abi.TokenAmount(types.MustParseFIL("1000"))
|
msgFromPlaceholder.Value = abi.TokenAmount(types.MustParseFIL("1000"))
|
||||||
txArgs, err := ethtypes.EthTxArgsFromMessage(msgFromPlaceholder)
|
txArgs, err := ethtypes.EthTxArgsFromUnsignedEthMessage(msgFromPlaceholder)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
digest, err := txArgs.ToRlpUnsignedMsg()
|
digest, err := txArgs.ToRlpUnsignedMsg()
|
||||||
@ -218,7 +218,7 @@ func TestEthAccountAbstractionFailure(t *testing.T) {
|
|||||||
msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK)
|
msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
txArgs, err = ethtypes.EthTxArgsFromMessage(msgFromPlaceholder)
|
txArgs, err = ethtypes.EthTxArgsFromUnsignedEthMessage(msgFromPlaceholder)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
digest, err = txArgs.ToRlpUnsignedMsg()
|
digest, err = txArgs.ToRlpUnsignedMsg()
|
||||||
|
@ -212,7 +212,7 @@ func (a *EthModule) EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthH
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return ethtypes.EthBlock{}, xerrors.Errorf("error loading tipset %s: %w", ts, err)
|
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) {
|
func (a *EthModule) parseBlkParam(ctx context.Context, blkParam string) (tipset *types.TipSet, err error) {
|
||||||
@ -249,7 +249,7 @@ func (a *EthModule) EthGetBlockByNumber(ctx context.Context, blkParam string, fu
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return ethtypes.EthBlock{}, err
|
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) {
|
func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.EthHash) (*ethtypes.EthTx, error) {
|
||||||
@ -270,8 +270,8 @@ func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *ethtype
|
|||||||
|
|
||||||
// first, try to get the cid from mined transactions
|
// first, try to get the cid from mined transactions
|
||||||
msgLookup, err := a.StateAPI.StateSearchMsg(ctx, types.EmptyTSK, c, api.LookbackNoLimit, true)
|
msgLookup, err := a.StateAPI.StateSearchMsg(ctx, types.EmptyTSK, c, api.LookbackNoLimit, true)
|
||||||
if err == nil {
|
if err == nil && msgLookup != nil {
|
||||||
tx, err := newEthTxFromFilecoinMessageLookup(ctx, msgLookup, -1, a.Chain, a.StateAPI)
|
tx, err := newEthTxFromMessageLookup(ctx, msgLookup, -1, a.Chain, a.StateAPI)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return &tx, nil
|
return &tx, nil
|
||||||
}
|
}
|
||||||
@ -287,7 +287,7 @@ func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *ethtype
|
|||||||
|
|
||||||
for _, p := range pending {
|
for _, p := range pending {
|
||||||
if p.Cid() == c {
|
if p.Cid() == c {
|
||||||
tx, err := NewEthTxFromFilecoinMessage(ctx, p, a.StateAPI)
|
tx, err := newEthTxFromSignedMessage(ctx, p, a.StateAPI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not convert Filecoin message into tx: %s", err)
|
return nil, fmt.Errorf("could not convert Filecoin message into tx: %s", err)
|
||||||
}
|
}
|
||||||
@ -336,7 +336,7 @@ func (a *EthModule) EthGetMessageCidByTransactionHash(ctx context.Context, txHas
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *EthModule) EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*ethtypes.EthHash, error) {
|
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 {
|
if hash == ethtypes.EmptyEthHash {
|
||||||
// not found
|
// not found
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -379,7 +379,7 @@ func (a *EthModule) EthGetTransactionReceipt(ctx context.Context, txHash ethtype
|
|||||||
return nil, nil
|
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 {
|
if err != nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@ -605,7 +605,7 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint
|
|||||||
for ts.Height() >= abi.ChainEpoch(oldestBlkHeight) {
|
for ts.Height() >= abi.ChainEpoch(oldestBlkHeight) {
|
||||||
// Unfortunately we need to rebuild the full message view so we can
|
// Unfortunately we need to rebuild the full message view so we can
|
||||||
// totalize gas used in the tipset.
|
// 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 {
|
if err != nil {
|
||||||
return ethtypes.EthFeeHistory{}, fmt.Errorf("cannot create eth block: %v", err)
|
return ethtypes.EthFeeHistory{}, fmt.Errorf("cannot create eth block: %v", err)
|
||||||
}
|
}
|
||||||
@ -1233,7 +1233,7 @@ func ethFilterResultFromEvents(evs []*filter.CollectedEvent, sa StateAPI) (*etht
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.TransactionHash, err = EthTxHashFromFilecoinMessageCid(context.TODO(), ev.MsgCid, sa)
|
log.TransactionHash, err = EthTxHashFromMessageCid(context.TODO(), ev.MsgCid, sa)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -1275,7 +1275,7 @@ func ethFilterResultFromMessages(cs []*types.SignedMessage, sa StateAPI) (*ethty
|
|||||||
res := ðtypes.EthFilterResult{}
|
res := ðtypes.EthFilterResult{}
|
||||||
|
|
||||||
for _, c := range cs {
|
for _, c := range cs {
|
||||||
hash, err := EthTxHashFromSignedFilecoinMessage(context.TODO(), c, sa)
|
hash, err := EthTxHashFromSignedMessage(context.TODO(), c, sa)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -1376,7 +1376,7 @@ func (e *ethSubscription) start(ctx context.Context) {
|
|||||||
case *filter.CollectedEvent:
|
case *filter.CollectedEvent:
|
||||||
resp.Result, err = ethFilterResultFromEvents([]*filter.CollectedEvent{vt}, e.StateAPI)
|
resp.Result, err = ethFilterResultFromEvents([]*filter.CollectedEvent{vt}, e.StateAPI)
|
||||||
case *types.TipSet:
|
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 {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -1410,7 +1410,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())
|
parent, err := cs.LoadTipSet(ctx, ts.Parents())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ethtypes.EthBlock{}, err
|
return ethtypes.EthBlock{}, err
|
||||||
@ -1449,7 +1449,7 @@ func newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTx
|
|||||||
}
|
}
|
||||||
gasUsed += msgLookup.Receipt.GasUsed
|
gasUsed += msgLookup.Receipt.GasUsed
|
||||||
|
|
||||||
tx, err := newEthTxFromFilecoinMessageLookup(ctx, msgLookup, txIdx, cs, sa)
|
tx, err := newEthTxFromMessageLookup(ctx, msgLookup, txIdx, cs, sa)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ethtypes.EthBlock{}, nil
|
return ethtypes.EthBlock{}, nil
|
||||||
}
|
}
|
||||||
@ -1509,11 +1509,11 @@ func lookupEthAddress(ctx context.Context, addr address.Address, sa StateAPI) (e
|
|||||||
return ethtypes.EthAddressFromFilecoinAddress(idAddr)
|
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)
|
smsg, err := sa.Chain.GetSignedMessage(ctx, c)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// This is an Eth Tx, Secp message, Or BLS message in the mpool
|
// 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)
|
_, err = sa.Chain.GetMessage(ctx, c)
|
||||||
@ -1525,93 +1525,44 @@ func EthTxHashFromFilecoinMessageCid(ctx context.Context, c cid.Cid, sa StateAPI
|
|||||||
return ethtypes.EmptyEthHash, nil
|
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 {
|
if smsg.Signature.Type == crypto.SigTypeDelegated {
|
||||||
ethTx, err := NewEthTxFromFilecoinMessage(ctx, smsg, sa)
|
ethTx, err := newEthTxFromSignedMessage(ctx, smsg, sa)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ethtypes.EmptyEthHash, err
|
return ethtypes.EmptyEthHash, err
|
||||||
}
|
}
|
||||||
return ethTx.Hash, nil
|
return ethTx.Hash, nil
|
||||||
|
} else if smsg.Signature.Type == crypto.SigTypeSecp256k1 {
|
||||||
|
return ethtypes.EthHashFromCid(smsg.Cid())
|
||||||
|
} else { // BLS message
|
||||||
|
return ethtypes.EthHashFromCid(smsg.Message.Cid())
|
||||||
}
|
}
|
||||||
|
|
||||||
return ethtypes.EthHashFromCid(smsg.Cid())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEthTxFromFilecoinMessage(ctx context.Context, smsg *types.SignedMessage, sa StateAPI) (ethtypes.EthTx, error) {
|
func newEthTxFromSignedMessage(ctx context.Context, smsg *types.SignedMessage, sa StateAPI) (ethtypes.EthTx, error) {
|
||||||
// Ignore errors here so we can still parse non-eth messages
|
var tx ethtypes.EthTx
|
||||||
fromEthAddr, _ := lookupEthAddress(ctx, smsg.Message.From, sa)
|
|
||||||
toEthAddr, _ := lookupEthAddress(ctx, smsg.Message.To, sa)
|
|
||||||
|
|
||||||
toAddr := &toEthAddr
|
|
||||||
input := smsg.Message.Params
|
|
||||||
var err error
|
var err error
|
||||||
// Check to see if we need to decode as contract deployment.
|
|
||||||
// We don't need to resolve the to address, because there's only one form (an ID).
|
|
||||||
if smsg.Message.To == builtintypes.EthereumAddressManagerActorAddr {
|
|
||||||
switch smsg.Message.Method {
|
|
||||||
case builtintypes.MethodsEAM.Create:
|
|
||||||
toAddr = nil
|
|
||||||
var params eam.CreateParams
|
|
||||||
err = params.UnmarshalCBOR(bytes.NewReader(smsg.Message.Params))
|
|
||||||
input = params.Initcode
|
|
||||||
case builtintypes.MethodsEAM.Create2:
|
|
||||||
toAddr = nil
|
|
||||||
var params eam.Create2Params
|
|
||||||
err = params.UnmarshalCBOR(bytes.NewReader(smsg.Message.Params))
|
|
||||||
input = params.Initcode
|
|
||||||
case builtintypes.MethodsEAM.CreateExternal:
|
|
||||||
toAddr = nil
|
|
||||||
var params abi.CborBytes
|
|
||||||
err = params.UnmarshalCBOR(bytes.NewReader(smsg.Message.Params))
|
|
||||||
input = []byte(params)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return ethtypes.EthTx{}, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Otherwise, try to decode as a cbor byte array.
|
|
||||||
// TODO: Actually check if this is an ethereum call. This code will work for demo purposes, but is not correct.
|
|
||||||
if toAddr != nil {
|
|
||||||
if decodedParams, err := cbg.ReadByteArray(bytes.NewReader(smsg.Message.Params), uint64(len(smsg.Message.Params))); err == nil {
|
|
||||||
input = decodedParams
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r, s, v, err := ethtypes.RecoverSignature(smsg.Signature)
|
|
||||||
if err != nil {
|
|
||||||
// we don't want to return error if the message is not an Eth tx
|
|
||||||
r, s, v = ethtypes.EthBigIntZero, ethtypes.EthBigIntZero, ethtypes.EthBigIntZero
|
|
||||||
}
|
|
||||||
|
|
||||||
tx := ethtypes.EthTx{
|
|
||||||
Nonce: ethtypes.EthUint64(smsg.Message.Nonce),
|
|
||||||
ChainID: ethtypes.EthUint64(build.Eip155ChainId),
|
|
||||||
From: fromEthAddr,
|
|
||||||
To: toAddr,
|
|
||||||
Value: ethtypes.EthBigInt(smsg.Message.Value),
|
|
||||||
Type: ethtypes.EthUint64(2),
|
|
||||||
Input: input,
|
|
||||||
Gas: ethtypes.EthUint64(smsg.Message.GasLimit),
|
|
||||||
MaxFeePerGas: ethtypes.EthBigInt(smsg.Message.GasFeeCap),
|
|
||||||
MaxPriorityFeePerGas: ethtypes.EthBigInt(smsg.Message.GasPremium),
|
|
||||||
V: v,
|
|
||||||
R: r,
|
|
||||||
S: s,
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is an eth tx
|
// This is an eth tx
|
||||||
if smsg.Signature.Type == crypto.SigTypeDelegated {
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
tx.Hash, err = tx.TxHash()
|
tx.Hash, err = tx.TxHash()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return tx, err
|
return ethtypes.EthTx{}, err
|
||||||
}
|
}
|
||||||
} else if smsg.Signature.Type == crypto.SigTypeUnknown { // BLS Filecoin message
|
} else if smsg.Signature.Type == crypto.SigTypeSecp256k1 { // Secp Filecoin Message
|
||||||
tx.Hash, err = ethtypes.EthHashFromCid(smsg.Message.Cid())
|
tx = ethTxFromNativeMessage(ctx, smsg.VMMessage(), sa)
|
||||||
|
tx.Hash, err = ethtypes.EthHashFromCid(smsg.Cid())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return tx, err
|
return tx, err
|
||||||
}
|
}
|
||||||
} else { // Secp Filecoin Message
|
} else { // BLS Filecoin message
|
||||||
tx.Hash, err = ethtypes.EthHashFromCid(smsg.Cid())
|
tx = ethTxFromNativeMessage(ctx, smsg.VMMessage(), sa)
|
||||||
|
tx.Hash, err = ethtypes.EthHashFromCid(smsg.Message.Cid())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return tx, err
|
return tx, err
|
||||||
}
|
}
|
||||||
@ -1620,14 +1571,32 @@ func NewEthTxFromFilecoinMessage(ctx context.Context, smsg *types.SignedMessage,
|
|||||||
return tx, nil
|
return tx, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// newEthTxFromFilecoinMessageLookup creates an ethereum transaction from filecoin message lookup. If a negative txIdx is passed
|
// ethTxFromNativeMessage does NOT populate:
|
||||||
// into the function, it looksup the transaction index of the message in the tipset, otherwise it uses the txIdx passed into the
|
// - BlockHash
|
||||||
// function
|
// - BlockNumber
|
||||||
func newEthTxFromFilecoinMessageLookup(ctx context.Context, msgLookup *api.MsgLookup, txIdx int, cs *store.ChainStore, sa StateAPI) (ethtypes.EthTx, error) {
|
// - TransactionIndex
|
||||||
if msgLookup == nil {
|
// - Hash
|
||||||
return ethtypes.EthTx{}, fmt.Errorf("msg does not exist")
|
func ethTxFromNativeMessage(ctx context.Context, msg *types.Message, sa StateAPI) ethtypes.EthTx {
|
||||||
|
// We don't care if we error here, conversion is best effort for non-eth transactions
|
||||||
|
from, _ := lookupEthAddress(ctx, msg.From, sa)
|
||||||
|
to, _ := lookupEthAddress(ctx, msg.To, sa)
|
||||||
|
return ethtypes.EthTx{
|
||||||
|
To: &to,
|
||||||
|
From: from,
|
||||||
|
Nonce: ethtypes.EthUint64(msg.Nonce),
|
||||||
|
ChainID: ethtypes.EthUint64(build.Eip155ChainId),
|
||||||
|
Value: ethtypes.EthBigInt(msg.Value),
|
||||||
|
Type: ethtypes.Eip1559TxType,
|
||||||
|
Gas: ethtypes.EthUint64(msg.GasLimit),
|
||||||
|
MaxFeePerGas: ethtypes.EthBigInt(msg.GasFeeCap),
|
||||||
|
MaxPriorityFeePerGas: ethtypes.EthBigInt(msg.GasPremium),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 newEthTxFromMessageLookup(ctx context.Context, msgLookup *api.MsgLookup, txIdx int, cs *store.ChainStore, sa StateAPI) (ethtypes.EthTx, error) {
|
||||||
ts, err := cs.LoadTipSet(ctx, msgLookup.TipSet)
|
ts, err := cs.LoadTipSet(ctx, msgLookup.TipSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ethtypes.EthTx{}, err
|
return ethtypes.EthTx{}, err
|
||||||
@ -1676,13 +1645,13 @@ func newEthTxFromFilecoinMessageLookup(ctx context.Context, msgLookup *api.MsgLo
|
|||||||
smsg = &types.SignedMessage{
|
smsg = &types.SignedMessage{
|
||||||
Message: *msg,
|
Message: *msg,
|
||||||
Signature: crypto.Signature{
|
Signature: crypto.Signature{
|
||||||
Type: crypto.SigTypeUnknown,
|
Type: crypto.SigTypeBLS,
|
||||||
Data: nil,
|
Data: nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tx, err := NewEthTxFromFilecoinMessage(ctx, smsg, sa)
|
tx, err := newEthTxFromSignedMessage(ctx, smsg, sa)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ethtypes.EthTx{}, err
|
return ethtypes.EthTx{}, err
|
||||||
}
|
}
|
||||||
@ -1728,16 +1697,6 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
|
|||||||
LogsBloom: ethtypes.EmptyEthBloom[:],
|
LogsBloom: ethtypes.EmptyEthBloom[:],
|
||||||
}
|
}
|
||||||
|
|
||||||
if receipt.To == nil && lookup.Receipt.ExitCode.IsSuccess() {
|
|
||||||
// Create and Create2 return the same things.
|
|
||||||
var ret eam.CreateReturn
|
|
||||||
if err := ret.UnmarshalCBOR(bytes.NewReader(lookup.Receipt.Return)); err != nil {
|
|
||||||
return api.EthTxReceipt{}, xerrors.Errorf("failed to parse contract creation result: %w", err)
|
|
||||||
}
|
|
||||||
addr := ethtypes.EthAddress(ret.EthAddress)
|
|
||||||
receipt.ContractAddress = &addr
|
|
||||||
}
|
|
||||||
|
|
||||||
if lookup.Receipt.ExitCode.IsSuccess() {
|
if lookup.Receipt.ExitCode.IsSuccess() {
|
||||||
receipt.Status = 1
|
receipt.Status = 1
|
||||||
}
|
}
|
||||||
@ -1745,6 +1704,24 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
|
|||||||
receipt.Status = 0
|
receipt.Status = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
receipt.GasUsed = ethtypes.EthUint64(lookup.Receipt.GasUsed)
|
||||||
|
|
||||||
|
// TODO: handle CumulativeGasUsed
|
||||||
|
receipt.CumulativeGasUsed = ethtypes.EmptyEthInt
|
||||||
|
|
||||||
|
effectiveGasPrice := big.Div(replay.GasCost.TotalCost, big.NewInt(lookup.Receipt.GasUsed))
|
||||||
|
receipt.EffectiveGasPrice = ethtypes.EthBigInt(effectiveGasPrice)
|
||||||
|
|
||||||
|
if receipt.To == nil && lookup.Receipt.ExitCode.IsSuccess() {
|
||||||
|
// Create and Create2 return the same things.
|
||||||
|
var ret eam.CreateExternalReturn
|
||||||
|
if err := ret.UnmarshalCBOR(bytes.NewReader(lookup.Receipt.Return)); err != nil {
|
||||||
|
return api.EthTxReceipt{}, xerrors.Errorf("failed to parse contract creation result: %w", err)
|
||||||
|
}
|
||||||
|
addr := ethtypes.EthAddress(ret.EthAddress)
|
||||||
|
receipt.ContractAddress = &addr
|
||||||
|
}
|
||||||
|
|
||||||
if len(events) > 0 {
|
if len(events) > 0 {
|
||||||
// TODO return a dummy non-zero bloom to signal that there are logs
|
// TODO return a dummy non-zero bloom to signal that there are logs
|
||||||
// need to figure out how worth it is to populate with a real bloom
|
// need to figure out how worth it is to populate with a real bloom
|
||||||
@ -1788,14 +1765,6 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
receipt.GasUsed = ethtypes.EthUint64(lookup.Receipt.GasUsed)
|
|
||||||
|
|
||||||
// TODO: handle CumulativeGasUsed
|
|
||||||
receipt.CumulativeGasUsed = ethtypes.EmptyEthInt
|
|
||||||
|
|
||||||
effectiveGasPrice := big.Div(replay.GasCost.TotalCost, big.NewInt(lookup.Receipt.GasUsed))
|
|
||||||
receipt.EffectiveGasPrice = ethtypes.EthBigInt(effectiveGasPrice)
|
|
||||||
|
|
||||||
return receipt, nil
|
return receipt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1811,7 +1780,7 @@ func (m *EthTxHashManager) Apply(ctx context.Context, from, to *types.TipSet) er
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
hash, err := EthTxHashFromSignedFilecoinMessage(ctx, smsg, m.StateAPI)
|
hash, err := EthTxHashFromSignedMessage(ctx, smsg, m.StateAPI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1848,7 +1817,7 @@ func WaitForMpoolUpdates(ctx context.Context, ch <-chan api.MpoolUpdate, manager
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
ethTx, err := NewEthTxFromFilecoinMessage(ctx, u.Message, manager.StateAPI)
|
ethTx, err := newEthTxFromSignedMessage(ctx, u.Message, manager.StateAPI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("error converting filecoin message to eth tx: %s", err)
|
log.Errorf("error converting filecoin message to eth tx: %s", err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user