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

Test send specific receipts (Part 2) #113

Merged
merged 14 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions tests/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ var _ = ginkgo.AfterSuite(testUtils.TearDownNetwork)
var _ = ginkgo.Describe("[Teleporter integration tests]", func() {
ginkgo.It("Send a message from Subnet A to Subnet B", BasicOneWaySendGinkgo)
ginkgo.It("Add additional fee amount", AddFeeAmountGinkgo)
ginkgo.It("Send specific receipts", SendSpecificReceiptsGinkgo)
})
131 changes: 131 additions & 0 deletions tests/send_specific_receipts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package tests

import (
"context"
"math/big"

"github.com/ava-labs/subnet-evm/accounts/abi/bind"
teleportermessenger "github.com/ava-labs/teleporter/abi-bindings/go/Teleporter/TeleporterMessenger"
"github.com/ava-labs/teleporter/tests/network"
"github.com/ava-labs/teleporter/tests/utils"
"github.com/ethereum/go-ethereum/common"
. "github.com/onsi/gomega"
)

func SendSpecificReceiptsGinkgo() {
SendSpecificReceipts(&network.LocalNetwork{})
}

func SendSpecificReceipts(network network.Network) {
subnets := network.GetSubnetsInfo()
subnetAInfo := subnets[0]
subnetBInfo := subnets[1]
teleporterContractAddress := network.GetTeleporterContractAddress()
fundedAddress, fundedKey := network.GetFundedAccountInfo()
ctx := context.Background()

subnetATeleporterMessenger, err := teleportermessenger.NewTeleporterMessenger(teleporterContractAddress, subnetAInfo.ChainRPCClient)
Expect(err).Should(BeNil())
subnetBTeleporterMessenger, err := teleportermessenger.NewTeleporterMessenger(teleporterContractAddress, subnetBInfo.ChainRPCClient)
Expect(err).Should(BeNil())

// Use mock token as the fee token
mockTokenAddress, mockToken := utils.DeployMockToken(context.Background(), fundedAddress, fundedKey, subnetAInfo)
utils.ExampleERC20Approve(ctx, mockToken, teleporterContractAddress, big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(10)), subnetAInfo)

relayerFeePerMessage := big.NewInt(5)
totalAccumulatedRelayerFee := big.NewInt(10)
// Send two messages from Subnet A to Subnet B
sendCrossChainMessageInput := teleportermessenger.TeleporterMessageInput{
DestinationChainID: subnetBInfo.BlockchainID,
DestinationAddress: fundedAddress,
FeeInfo: teleportermessenger.TeleporterFeeInfo{
ContractAddress: mockTokenAddress,
Amount: relayerFeePerMessage,
},
RequiredGasLimit: big.NewInt(1),
AllowedRelayerAddresses: []common.Address{},
Message: []byte{1, 2, 3, 4},
}

// Send first message from Subnet A to Subnet B with fee amount 5
sendCrossChainMsgReceipt, messageID1 := utils.SendCrossChainMessageAndWaitForAcceptance(
ctx, subnetAInfo, subnetBInfo, sendCrossChainMessageInput, fundedAddress, fundedKey, subnetATeleporterMessenger)

// Relay message from SubnetA to SubnetB
network.RelayMessage(ctx, sendCrossChainMsgReceipt.BlockHash, sendCrossChainMsgReceipt.BlockNumber, subnetAInfo, subnetBInfo)
// Check messge delivered
delivered, err := subnetBTeleporterMessenger.MessageReceived(&bind.CallOpts{}, subnetAInfo.BlockchainID, messageID1)
Expect(err).Should(BeNil())
Expect(delivered).Should(BeTrue())

// Send second message from Subnet A to Subnet B with fee amount 5
sendCrossChainMsgReceipt, messageID2 := utils.SendCrossChainMessageAndWaitForAcceptance(
ctx, subnetAInfo, subnetBInfo, sendCrossChainMessageInput, fundedAddress, fundedKey, subnetATeleporterMessenger)

// Relay message from SubnetA to SubnetB
network.RelayMessage(ctx, sendCrossChainMsgReceipt.BlockHash, sendCrossChainMsgReceipt.BlockNumber, subnetAInfo, subnetBInfo)
// Check delivered
delivered, err = subnetBTeleporterMessenger.MessageReceived(&bind.CallOpts{}, subnetAInfo.BlockchainID, messageID2)
Expect(err).Should(BeNil())
Expect(delivered).Should(BeTrue())

// Relayer send specific receipts to get reward of relaying two messages
receipt, messageID := utils.SendSpecifiedReceiptsAndWaitForAcceptance(
ctx,
subnetAInfo.BlockchainID,
subnetBInfo,
[]*big.Int{messageID1, messageID2},
teleportermessenger.TeleporterFeeInfo{
ContractAddress: mockTokenAddress,
Amount: big.NewInt(0),
},
[]common.Address{},
fundedAddress,
fundedKey,
subnetBTeleporterMessenger,
)

// Relay message from Subnet B to Subnet A
network.RelayMessage(ctx, receipt.BlockHash, receipt.BlockNumber, subnetBInfo, subnetAInfo)
// Check delivered
delivered, err = subnetATeleporterMessenger.MessageReceived(&bind.CallOpts{}, subnetBInfo.BlockchainID, messageID)
Expect(err).Should(BeNil())
Expect(delivered).Should(BeTrue())

// Check the reward amount. The reward amount should be 10
amount, err := subnetATeleporterMessenger.CheckRelayerRewardAmount(&bind.CallOpts{}, fundedAddress, mockTokenAddress)
Expect(err).Should(BeNil())
Expect(amount).Should(Equal(totalAccumulatedRelayerFee))

Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add an additional step of sending an arbitrary message from Subnet B -> Subnet A? This message will also include the receipts that were explicitly sent in the above steps. We should check that the relayer reward amount is unchanged, even after the receipt is delivered again.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure. Then, will it cover Test receiving a receipt multiple times has no effect case?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yup it will! I pointed it out for completeness here, but that will also cover that test case.

// Send message from Subnet B to Subnet A to trigger the "regular" method of delivering receipts.
// The next message from B->A will contain the same receipts that were manually sent in the above steps,
// but they should not be processed again on Subnet A.
sendCrossChainMessageInput = teleportermessenger.TeleporterMessageInput{
DestinationChainID: subnetAInfo.BlockchainID,
DestinationAddress: fundedAddress,
FeeInfo: teleportermessenger.TeleporterFeeInfo{
ContractAddress: mockTokenAddress,
Amount: big.NewInt(0),
},
RequiredGasLimit: big.NewInt(1),
AllowedRelayerAddresses: []common.Address{},
Message: []byte{1, 2, 3, 4},
}

// This message will also have the same receipt as the previous message
receipt, messageID = utils.SendCrossChainMessageAndWaitForAcceptance(
ctx, subnetBInfo, subnetAInfo, sendCrossChainMessageInput, fundedAddress, fundedKey, subnetBTeleporterMessenger)

// Relay message from Subnet B to Subnet A
network.RelayMessage(ctx, receipt.BlockHash, receipt.BlockNumber, subnetBInfo, subnetAInfo)
// Check delivered
delivered, err = subnetATeleporterMessenger.MessageReceived(&bind.CallOpts{}, subnetBInfo.BlockchainID, messageID)
Expect(err).Should(BeNil())
Expect(delivered).Should(BeTrue())

// Check the reward amount remains the same
amount, err = subnetATeleporterMessenger.CheckRelayerRewardAmount(&bind.CallOpts{}, fundedAddress, mockTokenAddress)
Expect(err).Should(BeNil())
Expect(amount).Should(Equal(totalAccumulatedRelayerFee))
}
37 changes: 35 additions & 2 deletions tests/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"strconv"
"strings"

"github.com/ava-labs/avalanchego/ids"
avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp"
"github.com/ava-labs/subnet-evm/accounts/abi/bind"
"github.com/ava-labs/subnet-evm/core/types"
Expand Down Expand Up @@ -127,6 +128,38 @@ func SendAddFeeAmountAndWaitForAcceptance(
return receipt
}

func SendSpecifiedReceiptsAndWaitForAcceptance(
ctx context.Context,
originChainID ids.ID,
source SubnetTestInfo,
messageIDs []*big.Int,
feeInfo teleportermessenger.TeleporterFeeInfo,
allowedRelayerAddresses []common.Address,
fundedAddress common.Address,
fundedKey *ecdsa.PrivateKey,
transactor *teleportermessenger.TeleporterMessenger,
) (*types.Receipt, *big.Int) {
opts := CreateTransactorOpts(ctx, source, fundedAddress, fundedKey)

txn, err := transactor.SendSpecifiedReceipts(opts, originChainID, messageIDs, feeInfo, allowedRelayerAddresses)
Expect(err).Should(BeNil())

receipt, err := bind.WaitMined(ctx, source.ChainRPCClient, txn)
Expect(err).Should(BeNil())
Expect(receipt.Status).Should(Equal(types.ReceiptStatusSuccessful))

// Check the transaction logs for the SendCrossChainMessage event emitted by the Teleporter contract
event, err := GetSendEventFromLogs(receipt.Logs, transactor)
Expect(err).Should(BeNil())
Expect(event.DestinationChainID[:]).Should(Equal(originChainID[:]))

log.Info("Sending SendSpecifiedReceipts transaction",
"originChainID", originChainID,
"txHash", txn.Hash())

return receipt, event.Message.MessageID
}

func HttpToWebsocketURI(uri string, blockchainID string) string {
return fmt.Sprintf("ws://%s/ext/bc/%s/ws", strings.TrimPrefix(uri, "http://"), blockchainID)
}
Expand Down Expand Up @@ -263,7 +296,7 @@ func CreateNativeTransferTransaction(
recipient common.Address,
amount *big.Int,
) *types.Transaction {
gasFeeCap, gasTipCap, nonce := calculateTxParams(ctx, network.ChainRPCClient, fundedAddress)
gasFeeCap, gasTipCap, nonce := calculateTxParams(ctx, network.ChainRPCClient, fromAddress)

tx := types.NewTx(&types.DynamicFeeTx{
ChainID: network.ChainIDInt,
Expand All @@ -275,7 +308,7 @@ func CreateNativeTransferTransaction(
Value: amount,
})

return signTransaction(tx, fundedKey, network.ChainIDInt)
return signTransaction(tx, fromKey, network.ChainIDInt)
}

//
Expand Down
Loading