Skip to content

Commit

Permalink
fixed for noble minting
Browse files Browse the repository at this point in the history
  • Loading branch information
bd21 committed Oct 25, 2023
1 parent 515b492 commit bb7cad5
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 24 deletions.
6 changes: 3 additions & 3 deletions cmd/ethereum/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ func StartListener(cfg config.Config, logger log.Logger, processingQueue chan *t

processingQueue <- parsedMsg

// It's important to wait a small amount of time between sending messages into the processing queue
// so that nonces are set correctly
time.Sleep(10 * time.Millisecond)
// It might help to wait a small amount of time between sending messages into the processing queue
// so that account sequences / nonces are set correctly
// time.Sleep(10 * time.Millisecond)
}
}
}()
Expand Down
2 changes: 1 addition & 1 deletion cmd/ethereum/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func init() {
}

func TestGetEthereumAccountNonce(t *testing.T) {
_, err := ethereum.GetEthereumAccountNonce(cfg.Networks.Destination.Ethereum.RPC, cfg.Networks.Minters[0].MinterAddress)
_, err := ethereum.GetEthereumAccountNonce(cfg.Networks.Destination.Ethereum.RPC, "0x4996f29b254c77972fff8f25e6f7797b3c9a0eb6")
require.Nil(t, err)
}

Expand Down
37 changes: 32 additions & 5 deletions cmd/noble/broadcast.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"fmt"
"io"
"net/http"
"regexp"
"strconv"
"time"

Expand Down Expand Up @@ -85,9 +86,9 @@ func Broadcast(
msg.DestDomain,
msg.SourceTxHash))

// TODO Account sequence lock is implemented but gets out of sync with remote.
// accountSequence := sequenceMap.Next(cfg.Networks.Destination.Noble.DomainId)
accountNumber, accountSequence, err := GetNobleAccountNumberSequence(cfg.Networks.Destination.Noble.API, nobleAddress)
accountSequence := sequenceMap.Next(cfg.Networks.Destination.Noble.DomainId)
accountNumber, _, err := GetNobleAccountNumberSequence(cfg.Networks.Destination.Noble.API, nobleAddress)

if err != nil {
logger.Error("unable to retrieve account number")
}
Expand Down Expand Up @@ -134,14 +135,40 @@ func Broadcast(
msg.Status = types.Complete
return rpcResponse, nil
}

// check tx response code
logger.Error(fmt.Sprintf("received non zero : %d - %s", rpcResponse.Code, rpcResponse.Log))

if err == nil && rpcResponse.Code == 32 {
// on account sequence mismatch, extract correct account sequence and retry
pattern := `expected (\d+), got (\d+)`
re := regexp.MustCompile(pattern)
match := re.FindStringSubmatch(rpcResponse.Log)

var newAccountSequence int64
if len(match) == 3 {
// Extract the numbers from the match.
newAccountSequence, _ = strconv.ParseInt(match[1], 10, 0)
} else {
// otherwise, just request the account sequence
_, newAccountSequence, err = GetNobleAccountNumberSequence(cfg.Networks.Destination.Noble.API, nobleAddress)
if err != nil {
logger.Error("unable to retrieve account number")
}
}

logger.Debug(fmt.Sprintf("error during broadcast: %s", rpcResponse.Log))
logger.Debug(fmt.Sprintf("retrying with new account sequence: %d", newAccountSequence))
sequenceMap.Put(4, newAccountSequence)

}
if err != nil {
logger.Error(fmt.Sprintf("error during broadcast: %s", err.Error()))
logger.Info(fmt.Sprintf("Retrying in %d seconds", cfg.Networks.Destination.Noble.BroadcastRetryInterval))
time.Sleep(time.Duration(cfg.Networks.Destination.Noble.BroadcastRetryInterval) * time.Second)
continue
}
// check tx response code
logger.Error(fmt.Sprintf("received non zero : %d - %s", rpcResponse.Code, rpcResponse.Log))

logger.Info(fmt.Sprintf("Retrying in %d seconds", cfg.Networks.Destination.Noble.BroadcastRetryInterval))
time.Sleep(time.Duration(cfg.Networks.Destination.Noble.BroadcastRetryInterval) * time.Second)
}
Expand Down
2 changes: 2 additions & 0 deletions cmd/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ func filterInvalidDestinationCallers(cfg config.Config, logger log.Logger, msg *
if err != nil {
result = true
}

//transformedDestinationCaller :=
if !bytes.Equal(msg.DestinationCaller, zeroByteArr) &&
bech32DestinationCaller != cfg.Networks.Minters[msg.DestDomain].MinterAddress {
result = true
Expand Down
65 changes: 50 additions & 15 deletions integration/noble_multi_send_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package integration_testing

import (
"encoding/hex"
"fmt"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
"github.com/cosmos/cosmos-sdk/types/bech32"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
Expand All @@ -10,28 +12,60 @@ import (
"github.com/ethereum/go-ethereum/ethclient"
"github.com/strangelove-ventures/noble-cctp-relayer/cmd"
eth "github.com/strangelove-ventures/noble-cctp-relayer/cmd/ethereum"
"github.com/strangelove-ventures/noble-cctp-relayer/cmd/noble"
"github.com/strangelove-ventures/noble-cctp-relayer/types"
"github.com/stretchr/testify/require"
"math/big"
"testing"
"time"
)

// TestNobleMultiSend broadcasts N messages on Ethereum, and then tries to receive them all at once on Noble.
// The point of this test is to verify that account sequences on Noble are synced correctly.
// A success means that all messages went through (i.e. no retries are attempted).
// TestNobleMultiSend broadcasts N depositForBurnWithCaller messages on Ethereum, and then tries to receive them all at once on Noble.
// We require a destination caller in this test so the deployed relayer doesn't pick it up.
//
// The point of this test is to verify that the Noble minter's account sequence is synced.
// A successful test means that all messages went through without retries (which are set to zero).
// We verify this result by checking the account balance at the end of the test.
func TestNobleMultiSend(t *testing.T) {
setupTest()

nobleMultiSendCfg := Parse("../.ignore/noble_multi_send.yaml")

// the caller account functions both as the destination caller and minter
var callerPrivKey = nobleMultiSendCfg.Networks.Noble.PrivateKey
keyBz, err := hex.DecodeString(callerPrivKey)
require.Nil(t, err)
privKey := secp256k1.PrivKey{Key: keyBz}
caller, err := bech32.ConvertAndEncode("noble", privKey.PubKey().Address())
require.Nil(t, err)

for i, minter := range cfg.Networks.Minters {
switch i {
case 4:
minter.MinterAddress = caller
minter.MinterPrivateKey = callerPrivKey
cfg.Networks.Minters[4] = minter
}
}

_, nextMinterSequence, err := noble.GetNobleAccountNumberSequence(
cfg.Networks.Destination.Noble.API,
cfg.Networks.Minters[4].MinterAddress)

require.Nil(t, err)

sequenceMap = types.NewSequenceMap()
sequenceMap.Put(uint32(4), nextMinterSequence)

// number of depositForBurn txns to send
n := 5
n := 7

// start up relayer
cfg.Networks.Source.Ethereum.StartBlock = getEthereumLatestBlockHeight(t)
cfg.Networks.Source.Ethereum.LookbackPeriod = 20
cfg.Networks.Destination.Noble.BroadcastRetries = 0
cfg.Networks.Source.Ethereum.LookbackPeriod = 5
cfg.Networks.Destination.Noble.BroadcastRetries = 0 // don't rely on retries to broadcast txns

fmt.Println(fmt.Sprintf("Building %d Ethereum depositForBurnWithMetadata txn..."), n)
fmt.Println(fmt.Sprintf("Building %d Ethereum depositForBurnWithMetadata txns...", n))

_, _, cosmosAddress := testdata.KeyTestPubAddr()
nobleAddress, _ := bech32.ConvertAndEncode("noble", cosmosAddress)
Expand All @@ -56,26 +90,32 @@ func TestNobleMultiSend(t *testing.T) {
mintRecipientPadded := append([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, cosmosAddress...)
require.Nil(t, err)

_, callerRaw, _ := bech32.DecodeAndConvert(caller)
destinationCallerPadded := append([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, callerRaw...)
require.Nil(t, err)

erc20, err := NewERC20(common.HexToAddress(UsdcAddress), client)
_, err = erc20.Approve(auth, common.HexToAddress(TokenMessengerWithMetadataAddress), big.NewInt(99999))
require.Nil(t, err)
var burnAmount = big.NewInt(1)

for i := 0; i < n; i++ {
tx, err := tokenMessenger.DepositForBurn(
tx, err := tokenMessenger.DepositForBurnWithCaller(
auth,
burnAmount,
4,
[32]byte(mintRecipientPadded),
common.HexToAddress(UsdcAddress),
[32]byte(destinationCallerPadded),
)
if err != nil {
logger.Error("Failed to update value: %v", err)
}

time.Sleep(1 * time.Second)

fmt.Printf("Update pending: https://goerli.etherscan.io/tx/%s\n", tx.Hash().String())

// todo sleep between burns?
}

fmt.Println("Waiting 90 seconds for attestations...")
Expand All @@ -90,14 +130,9 @@ func TestNobleMultiSend(t *testing.T) {
fmt.Println("Checking noble wallet...")
for i := 0; i < 250; i++ {
if originalNobleBalance+burnAmount.Uint64()*uint64(n) == getNobleBalance(nobleAddress) {
fmt.Println("Successfully minted at https://testnet.mintscan.io/noble-testnet/account/" + nobleAddress)
fmt.Println(fmt.Sprintf("Successfully minted %d times at https://testnet.mintscan.io/noble-testnet/account/%s", n, nobleAddress))
return
}
time.Sleep(1 * time.Second)
}
// verify noble balance
require.Equal(t, originalNobleBalance+burnAmount.Uint64()*uint64(n), getNobleBalance(nobleAddress))

// check logs

}

0 comments on commit bb7cad5

Please sign in to comment.