Skip to content

Commit

Permalink
Integrate Teleporter message id changes (#128)
Browse files Browse the repository at this point in the history
  • Loading branch information
minghinmatthewlam authored Jan 12, 2024
1 parent 2e010ee commit fd533e4
Show file tree
Hide file tree
Showing 12 changed files with 186 additions and 118 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
github.com/ava-labs/avalanchego v1.10.17
github.com/ava-labs/coreth v0.12.9-rc.9
github.com/ava-labs/subnet-evm v0.5.10
github.com/ava-labs/teleporter v0.0.0-20231221165433-826fa59bed3c
github.com/ava-labs/teleporter v0.0.0-20240108172200-f03f526e5312
github.com/ethereum/go-ethereum v1.12.0
github.com/onsi/ginkgo/v2 v2.14.0
github.com/onsi/gomega v1.30.0
Expand Down
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ github.com/ava-labs/subnet-evm v0.5.10 h1:ed9BxoiuXRnB/qKakKzYKtZzV/gVjOB2LxuDeg
github.com/ava-labs/subnet-evm v0.5.10/go.mod h1:wln8B4siQ1Osch+elW9vW1XJGjj5PYxQETkzFyDEMjk=
github.com/ava-labs/teleporter v0.0.0-20231221165433-826fa59bed3c h1:vnMlfP4SHFoatRufgUma/eGwvVzWdwMo17ADdrh6YYQ=
github.com/ava-labs/teleporter v0.0.0-20231221165433-826fa59bed3c/go.mod h1:qeclhkPTO4R2McXNrXXca4JmiRSgQ0gJ0KtJWzQGGPE=
github.com/ava-labs/teleporter v0.0.0-20240104215757-839006a992f2 h1:gqO87g7c6Gy5ZjEzz/oQ3KgnGqvdy73hypnQ+gvmTbQ=
github.com/ava-labs/teleporter v0.0.0-20240104215757-839006a992f2/go.mod h1:qeclhkPTO4R2McXNrXXca4JmiRSgQ0gJ0KtJWzQGGPE=
github.com/ava-labs/teleporter v0.0.0-20240105220309-160c7b8bce4b h1:tBUZfmBqdAykjTcL771SZcE5iQ5kgRZ6nz9Q/VQNTK0=
github.com/ava-labs/teleporter v0.0.0-20240105220309-160c7b8bce4b/go.mod h1:qeclhkPTO4R2McXNrXXca4JmiRSgQ0gJ0KtJWzQGGPE=
github.com/ava-labs/teleporter v0.0.0-20240105221051-581342d9f521 h1:rHbDNvhen/qDQyOuFkdkQ91MjPSNOcmbrUtaTEjriH8=
github.com/ava-labs/teleporter v0.0.0-20240105221051-581342d9f521/go.mod h1:qeclhkPTO4R2McXNrXXca4JmiRSgQ0gJ0KtJWzQGGPE=
github.com/ava-labs/teleporter v0.0.0-20240108172200-f03f526e5312 h1:rG9xkvCXRU4FBi1IBIXPxnTwxRv7mM6j0PX7FQss32g=
github.com/ava-labs/teleporter v0.0.0-20240108172200-f03f526e5312/go.mod h1:qeclhkPTO4R2McXNrXXca4JmiRSgQ0gJ0KtJWzQGGPE=
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
Expand Down
30 changes: 25 additions & 5 deletions messages/mocks/mock_message_manager.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

144 changes: 63 additions & 81 deletions messages/teleporter/message_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@
package teleporter

import (
"context"
"encoding/json"
"errors"
"fmt"
"math/big"

"github.com/ava-labs/avalanchego/cache"
"github.com/ava-labs/avalanchego/ids"
Expand All @@ -16,8 +15,8 @@ import (
"github.com/ava-labs/awm-relayer/config"
"github.com/ava-labs/awm-relayer/vms"
"github.com/ava-labs/awm-relayer/vms/vmtypes"
"github.com/ava-labs/subnet-evm/accounts/abi/bind"
"github.com/ava-labs/subnet-evm/ethclient"
"github.com/ava-labs/subnet-evm/interfaces"
teleportermessenger "github.com/ava-labs/teleporter/abi-bindings/go/Teleporter/TeleporterMessenger"
gasUtils "github.com/ava-labs/teleporter/utils/gas-utils"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -125,29 +124,31 @@ func (m *messageManager) ShouldSendMessage(warpMessageInfo *vmtypes.WarpMessageI
return false, fmt.Errorf("relayer not configured to deliver to destination. destinationBlockchainID=%s", destinationBlockchainID.String())
}

teleporterMessenger := m.getTeleporterMessenger(destinationClient)
teleporterMessageID, err := m.calculateMessageID(teleporterMessenger, warpMessageInfo.WarpUnsignedMessage.SourceChainID, destinationBlockchainID, teleporterMessage.MessageNonce)
if err != nil {
return false, err
}

senderAddress := destinationClient.SenderAddress()
if !isAllowedRelayer(teleporterMessage.AllowedRelayerAddresses, senderAddress) {
m.logger.Info(
"Relayer EOA not allowed to deliver this message.",
zap.String("destinationBlockchainID", destinationBlockchainID.String()),
zap.String("warpMessageID", warpMessageInfo.WarpUnsignedMessage.ID().String()),
zap.String("teleporterMessageID", teleporterMessage.MessageID.String()),
zap.String("teleporterMessageID", teleporterMessageID.String()),
)
return false, nil
}

delivered, err := m.messageDelivered(
destinationClient,
warpMessageInfo,
teleporterMessage,
destinationBlockchainID,
)
// Check if the message has already been delivered to the destination chain
delivered, err := teleporterMessenger.MessageReceived(&bind.CallOpts{}, teleporterMessageID)
if err != nil {
m.logger.Error(
"Failed to check if message has been delivered to destination chain.",
zap.String("destinationBlockchainID", destinationBlockchainID.String()),
zap.String("warpMessageID", warpMessageInfo.WarpUnsignedMessage.ID().String()),
zap.String("teleporterMessageID", teleporterMessage.MessageID.String()),
zap.String("teleporterMessageID", teleporterMessageID.String()),
zap.Error(err),
)
return false, err
Expand All @@ -156,7 +157,7 @@ func (m *messageManager) ShouldSendMessage(warpMessageInfo *vmtypes.WarpMessageI
m.logger.Info(
"Message already delivered to destination.",
zap.String("destinationBlockchainID", destinationBlockchainID.String()),
zap.String("teleporterMessageID", teleporterMessage.MessageID.String()),
zap.String("teleporterMessageID", teleporterMessageID.String()),
)
return false, nil
}
Expand All @@ -166,64 +167,6 @@ func (m *messageManager) ShouldSendMessage(warpMessageInfo *vmtypes.WarpMessageI
return true, nil
}

// Helper to check if a message has been delivered to the destination chain
// Returns true if the message has been delivered, false if not
// On error, the boolean result should be ignored
func (m *messageManager) messageDelivered(
destinationClient vms.DestinationClient,
warpMessageInfo *vmtypes.WarpMessageInfo,
teleporterMessage *teleportermessenger.TeleporterMessage,
destinationBlockchainID ids.ID) (bool, error) {
// Check if the message has already been delivered to the destination chain
client, ok := destinationClient.Client().(ethclient.Client)
if !ok {
m.logger.Error(
"Destination client is not an Ethereum client.",
zap.String("destinationBlockchainID", destinationBlockchainID.String()),
)
return false, errors.New("destination client is not an Ethereum client")
}

data, err := teleportermessenger.PackMessageReceived(
warpMessageInfo.WarpUnsignedMessage.SourceChainID,
teleporterMessage.MessageID,
)
if err != nil {
m.logger.Error(
"Failed packing messageReceived call data.",
zap.String("destinationBlockchainID", destinationBlockchainID.String()),
zap.Error(err),
)
return false, err
}
protocolAddress := common.BytesToAddress(m.protocolAddress[:])
callMessage := interfaces.CallMsg{
To: &protocolAddress,
Data: data,
}
result, err := client.CallContract(context.Background(), callMessage, nil)
if err != nil {
m.logger.Error(
"Failed calling messageReceived method on destination chain.",
zap.String("destinationBlockchainID", destinationBlockchainID.String()),
zap.Error(err),
)
return false, err
}
// check the contract call result
delivered, err := teleportermessenger.UnpackMessageReceivedResult(result)
if err != nil {
m.logger.Error(
"Failed unpacking messageReceived result.",
zap.String("destinationBlockchainID", destinationBlockchainID.String()),
zap.Error(err),
)
return false, err
}

return delivered, nil
}

// SendMessage extracts the gasLimit and packs the call data to call the receiveCrossChainMessage method of the Teleporter contract,
// and dispatches transaction construction and broadcast to the destination client
func (m *messageManager) SendMessage(signedMessage *warp.Message, parsedVmPayload []byte, destinationBlockchainID ids.ID) error {
Expand All @@ -237,19 +180,31 @@ func (m *messageManager) SendMessage(signedMessage *warp.Message, parsedVmPayloa
return err
}

// Get the correct destination client from the global map
destinationClient, ok := m.destinationClients[destinationBlockchainID]
if !ok {
return fmt.Errorf("relayer not configured to deliver to destination. DestinationBlockchainID=%s", destinationBlockchainID)
}

teleporterMessenger := m.getTeleporterMessenger(destinationClient)
teleporterMessageID, err := m.calculateMessageID(teleporterMessenger, signedMessage.SourceChainID, destinationBlockchainID, teleporterMessage.MessageNonce)
if err != nil {
return err
}

m.logger.Info(
"Sending message to destination chain",
zap.String("destinationBlockchainID", destinationBlockchainID.String()),
zap.String("warpMessageID", signedMessage.ID().String()),
zap.String("teleporterMessageID", teleporterMessage.MessageID.String()),
zap.String("teleporterMessageID", teleporterMessageID.String()),
)
numSigners, err := signedMessage.Signature.NumSigners()
if err != nil {
m.logger.Error(
"Failed to get number of signers",
zap.String("destinationBlockchainID", destinationBlockchainID.String()),
zap.String("warpMessageID", signedMessage.ID().String()),
zap.String("teleporterMessageID", teleporterMessage.MessageID.String()),
zap.String("teleporterMessageID", teleporterMessageID.String()),
)
return err
}
Expand All @@ -259,7 +214,7 @@ func (m *messageManager) SendMessage(signedMessage *warp.Message, parsedVmPayloa
"Gas limit required overflowed uint64 max. not relaying message",
zap.String("destinationBlockchainID", destinationBlockchainID.String()),
zap.String("warpMessageID", signedMessage.ID().String()),
zap.String("teleporterMessageID", teleporterMessage.MessageID.String()),
zap.String("teleporterMessageID", teleporterMessageID.String()),
)
return err
}
Expand All @@ -270,23 +225,18 @@ func (m *messageManager) SendMessage(signedMessage *warp.Message, parsedVmPayloa
"Failed packing receiveCrossChainMessage call data",
zap.String("destinationBlockchainID", destinationBlockchainID.String()),
zap.String("warpMessageID", signedMessage.ID().String()),
zap.String("teleporterMessageID", teleporterMessage.MessageID.String()),
zap.String("teleporterMessageID", teleporterMessageID.String()),
)
return err
}

// Get the correct destination client from the global map
destinationClient, ok := m.destinationClients[destinationBlockchainID]
if !ok {
return fmt.Errorf("relayer not configured to deliver to destination. DestinationBlockchainID=%s", destinationBlockchainID)
}
err = destinationClient.SendTx(signedMessage, m.protocolAddress.Hex(), gasLimit, callData)
if err != nil {
m.logger.Error(
"Failed to send tx.",
zap.String("destinationBlockchainID", destinationBlockchainID.String()),
zap.String("warpMessageID", signedMessage.ID().String()),
zap.String("teleporterMessageID", teleporterMessage.MessageID.String()),
zap.String("teleporterMessageID", teleporterMessageID.String()),
zap.Error(err),
)
return err
Expand All @@ -295,7 +245,7 @@ func (m *messageManager) SendMessage(signedMessage *warp.Message, parsedVmPayloa
"Sent message to destination chain",
zap.String("destinationBlockchainID", destinationBlockchainID.String()),
zap.String("warpMessageID", signedMessage.ID().String()),
zap.String("teleporterMessageID", teleporterMessage.MessageID.String()),
zap.String("teleporterMessageID", teleporterMessageID.String()),
)
return nil
}
Expand Down Expand Up @@ -323,3 +273,35 @@ func (m *messageManager) parseTeleporterMessage(warpMessageID ids.ID, warpPayloa
}
return teleporterMessage, nil
}

// getTeleporterMessenger returns the Teleporter messenger instance for the destination chain.
// Panic instead of returning errors because this should never happen, and if it does, we do not
// want to log and swallow the error, since operations after this will fail too.
func (m *messageManager) getTeleporterMessenger(destinationClient vms.DestinationClient) *teleportermessenger.TeleporterMessenger {
client, ok := destinationClient.Client().(ethclient.Client)
if !ok {
panic(fmt.Sprintf("Destination client for chain %s is not an Ethereum client", destinationClient.DestinationBlockchainID().String()))
}

// Get the teleporter messenger contract
teleporterMessenger, err := teleportermessenger.NewTeleporterMessenger(common.BytesToAddress(m.protocolAddress[:]), client)
if err != nil {
panic("Failed to get teleporter messenger contract")
}
return teleporterMessenger
}

func (m *messageManager) calculateMessageID(teleporter *teleportermessenger.TeleporterMessenger, sourceBlockchainID ids.ID, destinationBlockchainID ids.ID, messageNonce *big.Int) (ids.ID, error) {
messageID, err := teleporter.CalculateMessageID(&bind.CallOpts{}, sourceBlockchainID, destinationBlockchainID, messageNonce)
if err != nil {
m.logger.Error(
"Failed to calculate message ID",
zap.String("sourceBlockchainID", sourceBlockchainID.String()),
zap.String("destinationBlockchainID", destinationBlockchainID.String()),
zap.Error(err),
)
return ids.Empty, err
}

return messageID, nil
}
Loading

0 comments on commit fd533e4

Please sign in to comment.