Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[RnD][WIP] Emulate native bank send messages as Ethereum TXs #347

Closed
wants to merge 1 commit into from

Conversation

Yurist-85
Copy link
Contributor

Closes: #XXX

Description


For contributor use:

  • Targeted PR against correct branch (see CONTRIBUTING.md)
  • Linked to Github issue with discussion and accepted design OR link to spec that describes this work.
  • Code follows the module structure standards.
  • Wrote unit and integration tests
  • Updated relevant documentation (docs/) or specification (x/<module>/spec/)
  • Added relevant godoc comments.
  • Added a relevant changelog entry to the Unreleased section in CHANGELOG.md
  • Re-reviewed Files changed in the Github PR explorer

For admin use:

  • Added appropriate labels to PR (ex. WIP, R4R, docs, etc)
  • Reviewers assigned
  • Squashed all commits, uses message "Merge pull request #XYZ: [title]" (coding standards)

Copy link

@MalteHerrmann MalteHerrmann left a comment

Choose a reason for hiding this comment

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

Hey team, some minor comments after reviewing the proposed changes.

Comment on lines +279 to +282
// EthereumTx can't contain more than 1 message
if len(tx.GetMsgs()) > 1 {
continue
}

Choose a reason for hiding this comment

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

why add this check? it could potentially contain multiple banktypes.MsgSend right?

Comment on lines +51 to 53
if !isEth && !isBankSend {
return nil, errors.New("invalid ethereum tx")
}

Choose a reason for hiding this comment

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

probably makes sense to adjust the error message here too, could be confusing otherwise

Suggested change
if !isEth && !isBankSend {
return nil, errors.New("invalid ethereum tx")
}
if !isEth && !isBankSend {
return nil, errors.New("neither a valid ethereum tx or bank transfer")
}

Comment on lines +59 to 73
ethMsg, isEth := msg.(*evmtypes.MsgEthereumTx)
_, isBankSend := msg.(*banktypes.MsgSend)
if !isEth && !isBankSend {
continue
}

if isBankSend {
ethMsg, err = utilstx.BankSendTxAsEthereumTx(tx)
if err != nil {
b.logger.Debug("failed to convert bank send transaction into eth tx", "height", blk.Block.Height, "error", err.Error())
continue
}
}

predecessors = append(predecessors, ethMsg)

Choose a reason for hiding this comment

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

more of a nit, but a slight performance boost - if it's an MsgEthereumTx you don't need the type checking for the MsgSend. Whether to first check for the Eth transaction or the bank transfer could be decided depending on which of the two is more commonly present on your chain.

Suggested change
ethMsg, isEth := msg.(*evmtypes.MsgEthereumTx)
_, isBankSend := msg.(*banktypes.MsgSend)
if !isEth && !isBankSend {
continue
}
if isBankSend {
ethMsg, err = utilstx.BankSendTxAsEthereumTx(tx)
if err != nil {
b.logger.Debug("failed to convert bank send transaction into eth tx", "height", blk.Block.Height, "error", err.Error())
continue
}
}
predecessors = append(predecessors, ethMsg)
if ethMsg, isEth := msg.(*evmtypes.MsgEthereumTx); isEth {
predecessors = append(predecessors, ethMsg)
continue
}
if _, isBankSend := msg.(*banktypes.MsgSend); isBankSend {
ethMsg, err = utilstx.BankSendTxAsEthereumTx(tx)
if err != nil {
b.logger.Debug("failed to convert bank send transaction into eth tx", "height", blk.Block.Height, "error", err.Error())
continue
}
predecessors = append(predecessors, ethMsg)
}

Comment on lines +30 to +38
if len(tx.GetMsgs()) > 1 {
return nil, errors.New("tx has more than one message")
}

msg := tx.GetMsgs()[0]
sendMsg, ok := msg.(*banktypes.MsgSend)
if !ok {
return nil, errors.New("tx message is not a bank.MsgSend")
}

Choose a reason for hiding this comment

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

this assumes that only one banktypes.MsgSend can be present in a transaction - to be sure of this it would probably make sense to add a blocker for such a transaction in the ante handlers. Did you already add that?

Comment on lines +63 to +65
if len(sigs) != 1 {
return nil, errors.New("transaction with one signer has more than one signature")
}

Choose a reason for hiding this comment

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

error message could be clearer here:

Suggested change
if len(sigs) != 1 {
return nil, errors.New("transaction with one signer has more than one signature")
}
if len(sigs) != 1 {
return nil, fmt.Errorf("expected transaction with 1 signer; got %d", len(sigs))
}

Comment on lines +141 to +166
attrs := []sdk.Attribute{
sdk.NewAttribute(sdk.AttributeKeyAmount, ethTx.Value().String()),
// add event for ethereum transaction hash format
sdk.NewAttribute(evmtypes.AttributeKeyEthereumTxHash, ethMsg.Hash),
// add event for index of valid ethereum tx
sdk.NewAttribute(evmtypes.AttributeKeyTxIndex, strconv.FormatUint(0, 10)),
// add event for eth tx gas used, we can't get it from cosmos tx result when it contains multiple eth tx msgs.
sdk.NewAttribute(evmtypes.AttributeKeyTxGasUsed, strconv.FormatUint(ethMsg.GetGas(), 10)),
}

if len(ctx.TxBytes()) > 0 {
// add event for tendermint transaction hash format
hash := tmbytes.HexBytes(tmtypes.Tx(ctx.TxBytes()).Hash())
attrs = append(attrs, sdk.NewAttribute(evmtypes.AttributeKeyTxHash, hash.String()))
}

if to := ethTx.To(); to != nil {
attrs = append(attrs, sdk.NewAttribute(evmtypes.AttributeKeyRecipient, to.Hex()))
}

ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
evmtypes.EventTypeEthereumTx,
attrs...,
),
})

Choose a reason for hiding this comment

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

I'd suggest adding a corresponding integration test to check if the emitted events from a bank transfer using a Cosmos message and the resulting events from an Ethereum transfer are the same

Comment on lines +173 to +185

ethMsg, isEth := tx.GetMsgs()[res.MsgIndex].(*evmtypes.MsgEthereumTx)
_, isBankSend := tx.GetMsgs()[res.MsgIndex].(*banktypes.MsgSend)
if !isEth && !isBankSend {
return nil, errors.New("invalid ethereum tx")
}

if isBankSend {
ethMsg, err = utilstx.BankSendTxAsEthereumTx(tx)
if err != nil {
return nil, err
}
}
Copy link

@MalteHerrmann MalteHerrmann Oct 30, 2024

Choose a reason for hiding this comment

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

to avoid the code duplication it could be better to introduce a helper method

func GetEthMsgOrConvertBankSendToEthMsg(tx sdk.Tx, msg sdk.Msg) (*evmtypes.MsgEthereumTx, error) {
    if ethMsg, isEth = msg.(*evmtypes.MsgEthereumTx, error); isEth {
        return ethMsg, nil
    }

    if _, isBankSend = msg.(*banktypes.MsgSend); isBankSend {
        return utilstx.BankSendTxAsEthereumTx
    }

    return nil, fmt.Errorf("neither ethereum tx nor bank transfer; got: %T", msg)
}
Suggested change
ethMsg, isEth := tx.GetMsgs()[res.MsgIndex].(*evmtypes.MsgEthereumTx)
_, isBankSend := tx.GetMsgs()[res.MsgIndex].(*banktypes.MsgSend)
if !isEth && !isBankSend {
return nil, errors.New("invalid ethereum tx")
}
if isBankSend {
ethMsg, err = utilstx.BankSendTxAsEthereumTx(tx)
if err != nil {
return nil, err
}
}
ethMsg, err := GetEthMsgOrConvertBankSendToEthMsg(tx, tx.GetMsgs()[res.MsgIndex])
if err != nil {
return nil, err
}

Copy link
Contributor

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days-before-close if no further activity occurs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants