Skip to content

Commit

Permalink
Refactor relayer tests and code naming (#142)
Browse files Browse the repository at this point in the history
* Update integration tests structure
* Remove code duplication
* Use sdkmath.NewIntWithDecimal for the values with trailing zeros.
* Update github.com/sologenic/ripple dependency
* Remove unused fee test
* Rename XRPLTxObserver to XRPLToCoreumProcess
* Rename XRPLTxSubmitter to CoreumToXRPLProcess
* Fix typos
* Fix/remove TODOs
  • Loading branch information
dzmitryhil committed Feb 7, 2024
1 parent 930e842 commit 72b8b97
Show file tree
Hide file tree
Showing 41 changed files with 7,380 additions and 7,574 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/relayer-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
ci_step: [
"lint",
"test",
"integration tests coreum client",
"integration tests contract",
"integration tests processes",
"integration tests xrpl",
]
Expand All @@ -29,8 +29,8 @@ jobs:
linter-cache: false
docker-cache: false
build-contract: false
- ci_step: "integration tests coreum client"
command: "make restart-dev-env && make test-single-integration TESTS_DIR=integration-tests/coreum"
- ci_step: "integration tests contract"
command: "make restart-dev-env && make test-single-integration TESTS_DIR=integration-tests/contract"
linter-cache: false
docker-cache: true
build-contract: true
Expand Down
1 change: 0 additions & 1 deletion contract/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ pub const XRP_ISSUER: &str = "rrrrrrrrrrrrrrrrrrrrrhoLvTp";
const XRP_DEFAULT_SENDING_PRECISION: i32 = 6;
const XRP_DEFAULT_MAX_HOLDING_AMOUNT: u128 =
10u128.pow(16 - XRP_DEFAULT_SENDING_PRECISION as u32 + XRP_DECIMALS);
// TODO(keyleu): Update the value of the fee for XRP when we decide it
const XRP_DEFAULT_FEE: Uint128 = Uint128::zero();

const COREUM_CURRENCY_PREFIX: &str = "coreum";
Expand Down
2 changes: 2 additions & 0 deletions go.work.sum
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 h1:rFw4nCn9iMW+Vajsk51NtYIcwSTkXr+JGrMd36kTDJw=
github.com/alecthomas/kingpin/v2 v2.3.1 h1:ANLJcKmQm4nIaog7xdr/id6FM6zm5hHnfZrvtKPxqGg=
github.com/alecthomas/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE=
github.com/alecthomas/kingpin/v2 v2.3.2 h1:H0aULhgmSzN8xQ3nX1uxtdlTHYoPLu5AhHxWrKI6ocU=
github.com/alecthomas/kingpin/v2 v2.3.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
Expand Down Expand Up @@ -834,6 +835,7 @@ github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/xhit/go-str2duration v1.2.0 h1:BcV5u025cITWxEQKGWr1URRzrcXtu7uk8+luz3Yuhwc=
github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4=
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77 h1:ESFSdwYZvkeru3RtdrYueztKhOBCSAAzS4Gf+k0tEow=
Expand Down
274 changes: 274 additions & 0 deletions integration-tests/contract/common_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
//go:build integrationtests
// +build integrationtests

package contract_test

import (
"context"
"crypto/rand"
"strconv"
"strings"
"testing"

sdkmath "cosmossdk.io/math"
wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/google/uuid"
rippledata "github.com/rubblelabs/ripple/data"
"github.com/samber/lo"
"github.com/stretchr/testify/require"

"github.com/CoreumFoundation/coreum/v4/pkg/client"
"github.com/CoreumFoundation/coreum/v4/testutil/event"
coreumintegration "github.com/CoreumFoundation/coreum/v4/testutil/integration"
assetfttypes "github.com/CoreumFoundation/coreum/v4/x/asset/ft/types"
integrationtests "github.com/CoreumFoundation/coreumbridge-xrpl/integration-tests"
"github.com/CoreumFoundation/coreumbridge-xrpl/relayer/coreum"
)

const (
eventAttributeThresholdReached = "threshold_reached"
//nolint:lll // the signature sample doesn't require to be split
xrplTxSignature = "304502210097099E9AB2C41DA3F672004924B3557D58D101A5745C57C6336C5CF36B59E8F5022003984E50483C921E3FDF45BC7DE4E6ED9D340F0E0CAA6BB1828C647C6665A1CC"
)

func recoverTickets(
ctx context.Context,
t *testing.T,
contractClient *coreum.ContractClient,
owner sdk.AccAddress,
relayers []coreum.Relayer,
numberOfTickets uint32,
) {
bridgeXRPLAccountFirstSeqNumber := uint32(1)
_, err := contractClient.RecoverTickets(ctx, owner, bridgeXRPLAccountFirstSeqNumber, &numberOfTickets)
require.NoError(t, err)

acceptedTxEvidence := coreum.XRPLTransactionResultTicketsAllocationEvidence{
XRPLTransactionResultEvidence: coreum.XRPLTransactionResultEvidence{
TxHash: genXRPLTxHash(t),
AccountSequence: &bridgeXRPLAccountFirstSeqNumber,
TransactionResult: coreum.TransactionResultAccepted,
},
Tickets: lo.RepeatBy(int(numberOfTickets), func(index int) uint32 {
return uint32(index + 1)
}),
}

for _, relayer := range relayers {
txRes, err := contractClient.SendXRPLTicketsAllocationTransactionResultEvidence(
ctx, relayer.CoreumAddress, acceptedTxEvidence,
)
require.NoError(t, err)
thresholdReached, err := event.FindStringEventAttribute(
txRes.Events, wasmtypes.ModuleName, eventAttributeThresholdReached,
)
require.NoError(t, err)
if thresholdReached == strconv.FormatBool(true) {
break
}
}
}

func activateXRPLToken(
ctx context.Context,
t *testing.T,
contractClient *coreum.ContractClient,
relayers []coreum.Relayer,
issuer, currency string,
) {
t.Helper()

pendingOperations, err := contractClient.GetPendingOperations(ctx)
require.NoError(t, err)

var (
trustSetOperation coreum.Operation
found bool
)
for _, operation := range pendingOperations {
operationType := operation.OperationType.TrustSet
if operationType != nil && operationType.Issuer == issuer && operationType.Currency == currency {
found = true
trustSetOperation = operation
break
}
}
require.True(t, found)
require.NotNil(t, trustSetOperation.OperationType.TrustSet)

acceptedTxEvidenceTrustSet := coreum.XRPLTransactionResultTrustSetEvidence{
XRPLTransactionResultEvidence: coreum.XRPLTransactionResultEvidence{
TxHash: genXRPLTxHash(t),
TicketSequence: &trustSetOperation.TicketSequence,
TransactionResult: coreum.TransactionResultAccepted,
},
}

// send evidences from relayers
for _, relayer := range relayers {
txRes, err := contractClient.SendXRPLTrustSetTransactionResultEvidence(
ctx, relayer.CoreumAddress, acceptedTxEvidenceTrustSet,
)
require.NoError(t, err)
thresholdReached, err := event.FindStringEventAttribute(
txRes.Events, wasmtypes.ModuleName, eventAttributeThresholdReached,
)
require.NoError(t, err)
if thresholdReached == strconv.FormatBool(true) {
break
}
}

// asset token state
registeredToken, err := contractClient.GetXRPLTokenByIssuerAndCurrency(ctx, issuer, currency)
require.NoError(t, err)
require.Equal(t, coreum.TokenStateEnabled, registeredToken.State)
}

func sendFromXRPLToCoreum(
ctx context.Context,
t *testing.T,
contractClient *coreum.ContractClient,
relayers []coreum.Relayer,
issuer, currency string,
amount sdkmath.Int,
coreumRecipient sdk.AccAddress,
) {
t.Helper()

xrplToCoreumTransferEvidence := coreum.XRPLToCoreumTransferEvidence{
TxHash: genXRPLTxHash(t),
Issuer: issuer,
Currency: currency,
Amount: amount,
Recipient: coreumRecipient,
}

// send evidences from relayers
for _, relayer := range relayers {
txRes, err := contractClient.SendXRPLToCoreumTransferEvidence(
ctx, relayer.CoreumAddress, xrplToCoreumTransferEvidence,
)
require.NoError(t, err)
thresholdReached, err := event.FindStringEventAttribute(
txRes.Events, wasmtypes.ModuleName, eventAttributeThresholdReached,
)
require.NoError(t, err)
if thresholdReached == strconv.FormatBool(true) {
break
}
}
}

func sendFromCoreumToXRPL(
ctx context.Context,
t *testing.T,
contractClient *coreum.ContractClient,
relayers []coreum.Relayer,
senderCoreumAddress sdk.AccAddress,
coin sdk.Coin,
xrplRecipientAddress rippledata.Account,
) {
_, err := contractClient.SendToXRPL(ctx, senderCoreumAddress, xrplRecipientAddress.String(), coin, nil)
require.NoError(t, err)

pendingOperations, err := contractClient.GetPendingOperations(ctx)
require.NoError(t, err)
require.Len(t, pendingOperations, 1)
operation := pendingOperations[0]
operationType := operation.OperationType.CoreumToXRPLTransfer
require.NotNil(t, operationType)

acceptedTxEvidence := coreum.XRPLTransactionResultCoreumToXRPLTransferEvidence{
XRPLTransactionResultEvidence: coreum.XRPLTransactionResultEvidence{
TxHash: genXRPLTxHash(t),
TicketSequence: &operation.TicketSequence,
TransactionResult: coreum.TransactionResultAccepted,
},
}

// send evidences from relayers
for _, relayer := range relayers {
txRes, err := contractClient.SendCoreumToXRPLTransferTransactionResultEvidence(
ctx, relayer.CoreumAddress, acceptedTxEvidence,
)
require.NoError(t, err)
thresholdReached, err := event.FindStringEventAttribute(
txRes.Events, wasmtypes.ModuleName, eventAttributeThresholdReached,
)
require.NoError(t, err)
if thresholdReached == strconv.FormatBool(true) {
break
}
}
}

func genRelayers(
ctx context.Context, t *testing.T, chains integrationtests.Chains, relayersCount int,
) []coreum.Relayer {
relayers := make([]coreum.Relayer, 0)

for i := 0; i < relayersCount; i++ {
relayerXRPLSigner := chains.XRPL.GenAccount(ctx, t, 0)
relayerCoreumAddress := chains.Coreum.GenAccount()
chains.Coreum.FundAccountWithOptions(ctx, t, relayerCoreumAddress, coreumintegration.BalancesOptions{
Amount: sdkmath.NewIntWithDecimal(1, 7),
})
relayers = append(relayers, coreum.Relayer{
CoreumAddress: relayerCoreumAddress,
XRPLAddress: relayerXRPLSigner.String(),
XRPLPubKey: chains.XRPL.GetSignerPubKey(t, relayerXRPLSigner).String(),
})
}
return relayers
}

func genXRPLTxHash(t *testing.T) string {
t.Helper()

hash := rippledata.Hash256{}
_, err := rand.Read(hash[:])
require.NoError(t, err)

return strings.ToUpper(hash.String())
}

func issueAndRegisterCoreumOriginatedToken(
ctx context.Context,
t *testing.T,
contractClient *coreum.ContractClient,
coreumChain integrationtests.CoreumChain,
issuerAddress sdk.AccAddress,
ownerAddress sdk.AccAddress,
tokenDecimals uint32,
initialAmount sdkmath.Int,
sendingPrecision int32,
maxHoldingAmount sdkmath.Int,
bridgingFee sdkmath.Int,
) coreum.CoreumToken {
issueMsg := &assetfttypes.MsgIssue{
Issuer: issuerAddress.String(),
Symbol: "symbol" + uuid.NewString()[:4],
Subunit: "subunit" + uuid.NewString()[:4],
Precision: tokenDecimals, // token decimals in terms of the contract
InitialAmount: initialAmount,
}
_, err := client.BroadcastTx(
ctx,
coreumChain.ClientContext.WithFromAddress(issuerAddress),
coreumChain.TxFactory().WithSimulateAndExecute(true),
issueMsg,
)
require.NoError(t, err)
require.NoError(t, err)
coreumDenom := assetfttypes.BuildDenom(issueMsg.Subunit, issuerAddress)
_, err = contractClient.RegisterCoreumToken(
ctx, ownerAddress, coreumDenom, tokenDecimals, sendingPrecision, maxHoldingAmount, bridgingFee,
)
require.NoError(t, err)
registeredCoreumToken, err := contractClient.GetCoreumTokenByDenom(ctx, coreumDenom)
require.NoError(t, err)

return registeredCoreumToken
}
Loading

0 comments on commit 72b8b97

Please sign in to comment.