Skip to content

Commit

Permalink
integrate Teleporter message id changes
Browse files Browse the repository at this point in the history
fix unit tests

update mock files
  • Loading branch information
Matthew Lam committed Jan 8, 2024
1 parent 01b3aef commit 2ecf959
Show file tree
Hide file tree
Showing 12 changed files with 208 additions and 114 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.13.2
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.

162 changes: 85 additions & 77 deletions messages/teleporter/message_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
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 +16,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 +125,41 @@ func (m *messageManager) ShouldSendMessage(warpMessageInfo *vmtypes.WarpMessageI
return false, fmt.Errorf("relayer not configured to deliver to destination. destinationBlockchainID=%s", destinationBlockchainID.String())
}

teleporter, err := m.getTeleporterMessenger(destinationClient)
if err != nil {
m.logger.Error(
"Failed to get teleporter messenger contract.",
zap.String("destinationBlockchainID", destinationBlockchainID.String()),
zap.String("warpMessageID", warpMessageInfo.WarpUnsignedMessage.ID().String()),
zap.String("messageNonce", teleporterMessage.MessageNonce.String()),
zap.Error(err),
)
return false, err
}
teleporterMessageID, err := m.calculateMessageID(teleporter, 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 := teleporter.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 +168,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,90 +178,54 @@ 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,
)
// 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 {
teleporterMessage, err := m.parseTeleporterMessage(signedMessage.ID(), parsedVmPayload)
if err != nil {
m.logger.Error(
"Failed packing messageReceived call data.",
"Failed get teleporter message.",
zap.String("destinationBlockchainID", destinationBlockchainID.String()),
zap.Error(err),
zap.String("warpMessageID", signedMessage.ID().String()),
)
return false, err
}
protocolAddress := common.BytesToAddress(m.protocolAddress[:])
callMessage := interfaces.CallMsg{
To: &protocolAddress,
Data: data,
return err
}
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

// 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)
}
// check the contract call result
delivered, err := teleportermessenger.UnpackMessageReceivedResult(result)

teleporter, err := m.getTeleporterMessenger(destinationClient)
if err != nil {
m.logger.Error(
"Failed unpacking messageReceived result.",
"Failed to get teleporter messenger contract.",
zap.String("destinationBlockchainID", destinationBlockchainID.String()),
zap.String("warpMessageID", signedMessage.ID().String()),
zap.String("messageNonce", teleporterMessage.MessageNonce.String()),
zap.Error(err),
)
return false, err
return 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 {
teleporterMessage, err := m.parseTeleporterMessage(signedMessage.ID(), parsedVmPayload)
teleporterMessageID, err := m.calculateMessageID(teleporter, signedMessage.SourceChainID, destinationBlockchainID, teleporterMessage.MessageNonce)
if err != nil {
m.logger.Error(
"Failed get teleporter message.",
zap.String("destinationBlockchainID", destinationBlockchainID.String()),
zap.String("warpMessageID", signedMessage.ID().String()),
)
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 +235,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 +246,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 +266,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 +294,40 @@ func (m *messageManager) parseTeleporterMessage(warpMessageID ids.ID, warpPayloa
}
return teleporterMessage, nil
}

func (m *messageManager) getTeleporterMessenger(destinationClient vms.DestinationClient) (*teleportermessenger.TeleporterMessenger, error) {
client, ok := destinationClient.Client().(ethclient.Client)
if !ok {
m.logger.Error(
"Destination client is not an Ethereum client.",
zap.String("destinationBlockchainID", destinationClient.DestinationBlockchainID().String()),
)
return nil, errors.New("destination client is not an Ethereum client")
}

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

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 2ecf959

Please sign in to comment.