diff --git a/go.mod b/go.mod index fc7624fbb9..2528ebf5b9 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/0chain/errors v1.0.3 - github.com/0chain/gosdk v1.8.18-0.20230823135357-61db9486f4c0 + github.com/0chain/gosdk v1.10.1-0.20231027034008-e99291168a4f github.com/go-resty/resty/v2 v2.7.0 github.com/herumi/bls-go-binary v1.31.0 github.com/shopspring/decimal v1.3.1 @@ -23,12 +23,13 @@ require ( github.com/google/uuid v1.3.0 // indirect github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/lithammer/shortuuid/v3 v3.0.7 // indirect + github.com/remeh/sizedwaitgroup v1.0.0 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.9.0 // indirect go.uber.org/zap v1.24.0 // indirect ) -require github.com/aws/aws-sdk-go v1.44.289 +require github.com/aws/aws-sdk-go v1.44.331 require ( github.com/0chain/common v0.0.6-0.20230127095721-8df4d1d72565 // indirect @@ -85,7 +86,7 @@ require ( github.com/yusufpapurcu/wmi v1.2.3 // indirect go.dedis.ch/fixbuf v1.0.3 // indirect go.dedis.ch/kyber/v3 v3.1.0 // indirect - golang.org/x/net v0.7.0 // indirect + golang.org/x/net v0.8.0 // indirect golang.org/x/sync v0.2.0 // indirect golang.org/x/sys v0.8.0 // indirect golang.org/x/text v0.9.0 // indirect diff --git a/go.sum b/go.sum index ef7f17cb69..279f9906ef 100644 --- a/go.sum +++ b/go.sum @@ -40,8 +40,8 @@ github.com/0chain/common v0.0.6-0.20230127095721-8df4d1d72565 h1:z+DtCR8mBsjPnEs github.com/0chain/common v0.0.6-0.20230127095721-8df4d1d72565/go.mod h1:UyDC8Qyl5z9lGkCnf9RHJPMektnFX8XtCJZHXCCVj8E= github.com/0chain/errors v1.0.3 h1:QQZPFxTfnMcRdt32DXbzRQIfGWmBsKoEdszKQDb0rRM= github.com/0chain/errors v1.0.3/go.mod h1:xymD6nVgrbgttWwkpSCfLLEJbFO6iHGQwk/yeSuYkIc= -github.com/0chain/gosdk v1.8.18-0.20230823135357-61db9486f4c0 h1:XhLlPJKQxohZAS1+H2MHxy/e5I9Pw+Iyi+KaC5NHPl8= -github.com/0chain/gosdk v1.8.18-0.20230823135357-61db9486f4c0/go.mod h1:3NKNYzmnMIYqZwwwOgZwMmTW1DT1ZUAmKyVPmYQOiT4= +github.com/0chain/gosdk v1.10.1-0.20231027034008-e99291168a4f h1:Eb2rYn3dqhrv0Kuyi9R0Pmi2FuFEVZoYEufW9XXFLkE= +github.com/0chain/gosdk v1.10.1-0.20231027034008-e99291168a4f/go.mod h1:d3YLgnSKvEtZ6I9taIQotb6xcMvUKvd01JnkXS+O1jk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Luzifer/go-openssl/v3 v3.1.0 h1:QqKqo6kYXGGUsvtUoCpRZm8lHw+jDfhbzr36gVj+/gw= @@ -59,8 +59,8 @@ github.com/antchfx/xmlquery v1.3.17/go.mod h1:Afkq4JIeXut75taLSuI31ISJ/zeq+3jG7T github.com/antchfx/xpath v1.2.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= github.com/antchfx/xpath v1.2.4 h1:dW1HB/JxKvGtJ9WyVGJ0sIoEcqftV3SqIstujI+B9XY= github.com/antchfx/xpath v1.2.4/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= -github.com/aws/aws-sdk-go v1.44.289 h1:5CVEjiHFvdiVlKPBzv0rjG4zH/21W/onT18R5AH/qx0= -github.com/aws/aws-sdk-go v1.44.289/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.331 h1:hEwdOTv6973uegCUY2EY8jyyq0OUg9INc0HOzcu2bjw= +github.com/aws/aws-sdk-go v1.44.331/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= @@ -172,8 +172,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -223,7 +223,7 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/herumi/bls-go-binary v1.31.0 h1:L1goQ2tMtGgpXCg5AwHAdJQpLs/pfnWWEc3Wog6OhmI= github.com/herumi/bls-go-binary v1.31.0/go.mod h1:O4Vp1AfR4raRGwFeQpr9X/PQtncEicMoOe6BQt1oX0Y= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= -github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= +github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -295,6 +295,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= +github.com/remeh/sizedwaitgroup v1.0.0 h1:VNGGFwNo/R5+MJBf6yrsr110p0m4/OX4S3DCy7Kyl5E= +github.com/remeh/sizedwaitgroup v1.0.0/go.mod h1:3j2R4OIe/SeS6YDhICBy22RWjJC5eNCJ1V+9+NVNYlo= github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -472,8 +474,9 @@ golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= diff --git a/tests/cli_tests/zwalletcli_zcnbridge_add_and_rm_authorizer_test.go b/tests/cli_tests/zwalletcli_zcnbridge_add_and_rm_authorizer_test.go new file mode 100644 index 0000000000..539c3dcc15 --- /dev/null +++ b/tests/cli_tests/zwalletcli_zcnbridge_add_and_rm_authorizer_test.go @@ -0,0 +1,141 @@ +package cli_tests + +import ( + "fmt" + "strings" + "testing" + "time" + + "github.com/0chain/system_test/internal/api/util/test" + cliutils "github.com/0chain/system_test/internal/cli/util" + "github.com/stretchr/testify/require" +) + +func TestZCNBridgeAuthorizerRegisterAndDelete(testSetup *testing.T) { // nolint:gocyclo // team preference is to have codes all within test. + t := test.NewSystemTest(testSetup) + output, err := createWallet(t, configPath) + require.NoError(t, err, "Unexpected create wallet failure", strings.Join(output, "\n")) + + t.RunSequentially("Register authorizer to DEX smartcontract", func(t *test.SystemTest) { + output, err = scRegisterAuthorizer(t, "0xEa36456C79caD6Dd941Fe552285594C7217Fe258", true) + require.NoError(t, err, "error trying to register authorizer to DEX sc: %s", strings.Join(output, "\n")) + t.Log("register authorizer DEX SC successfully") + }) + + t.RunSequentially("Remove authorizer from DEX smartcontract", func(t *test.SystemTest) { + output, err = scRemoveAuthorizer(t, "0xEa36456C79caD6Dd941Fe552285594C7217Fe258", true) + require.NoError(t, err, strings.Join(output, "\n")) + t.Log("remove authorizer DEX SC successfully") + }) +} + +func TestZCNAuthorizerRegisterAndDelete(testSetup *testing.T) { + t := test.NewSystemTest(testSetup) + output, err := createWallet(t, configPath) + require.NoError(t, err, "Unexpected create wallet failure", strings.Join(output, "\n")) + + w, err := getWallet(t, configPath) + require.NoError(t, err) + + var ( + publicKey = w.ClientPublicKey + clientID = w.ClientID + authURL = "http://systemtest.network/authorizer01" + ) + // faucet pour to sc owner wallet + output, err = executeFaucetWithTokensForWallet(t, "wallets/sc_owner", configPath, defaultInitFaucetTokens) + require.NoError(t, err, "Unexpected faucet execution failure", strings.Join(output, "\n")) + + t.RunSequentially("Register authorizer to zcnsc smartcontract", func(t *test.SystemTest) { + output, err := registerAuthorizer(t, clientID, publicKey, authURL, true) + require.NoError(t, err, "error trying to register authorizer to zcnsc: %s", strings.Join(output, "\n")) + t.Log("register authorizer zcnsc successfully") + }) + + t.RunSequentially("Remove authorizer from zcnsc smartcontract", func(t *test.SystemTest) { + output, err := removeAuthorizer(t, clientID, true) + require.NoError(t, err, strings.Join(output, "\n")) + t.Log("remove authorizer zcnsc successfully") + }) +} + +func scRegisterAuthorizer(t *test.SystemTest, authAddress string, retry bool) ([]string, error) { + t.Logf("Register authorizer to SC...") + cmd := fmt.Sprintf( + "./zwallet auth-sc-register "+ + "--ethereum_address=%s "+ + "--silent "+ + "--path %s "+ + "--configDir ./config "+ + "--wallet %s", + authAddress, + configDir, + escapedTestName(t)+"_wallet.json", + ) + + if retry { + return cliutils.RunCommand(t, cmd, 3, time.Second*2) + } else { + return cliutils.RunCommandWithoutRetry(cmd) + } +} + +func scRemoveAuthorizer(t *test.SystemTest, authAddress string, retry bool) ([]string, error) { + t.Logf("Remove authorizer to SC ...") + cmd := fmt.Sprintf( + "./zwallet auth-sc-delete --ethereum_address=%s "+ + "--silent "+ + "--path %s "+ + "--configDir ./config "+ + "--wallet %s", + authAddress, + configDir, + escapedTestName(t)+"_wallet.json", + ) + + if retry { + return cliutils.RunCommand(t, cmd, 3, time.Second*2) + } else { + return cliutils.RunCommandWithoutRetry(cmd) + } +} + +func registerAuthorizer(t *test.SystemTest, clientID, publicKey, authURL string, retry bool) ([]string, error) { + t.Log("Register authorizer to zcnsc ...") + + cmd := fmt.Sprintf(` + ./zwallet auth-register --silent + --configDir ./config + --path %s + --wallet wallets/sc_owner_wallet.json + --client_id %s + --client_key %s + --url %s + --min_stake 1 + --max_stake 10 + --service_charge 0.1 + --num_delegates 5`, + configDir, clientID, publicKey, authURL) + + if retry { + return cliutils.RunCommand(t, cmd, 3, time.Second*2) + } else { + return cliutils.RunCommandWithoutRetry(cmd) + } +} + +func removeAuthorizer(t *test.SystemTest, clientID string, retry bool) ([]string, error) { + t.Log("Remove authorizer from zcnsc ...") + + cmd := fmt.Sprintf(` + ./zwallet bridge-auth-delete --silent + --configDir ./config + --wallet wallets/sc_owner_wallet.json + --id %s`, clientID) + + if retry { + return cliutils.RunCommand(t, cmd, 3, time.Second*2) + } else { + return cliutils.RunCommandWithoutRetry(cmd) + } +} diff --git a/tests/cli_tests/zwalletcli_zcnbridge_auth_replace_burn_mint_test.go b/tests/cli_tests/zwalletcli_zcnbridge_auth_replace_burn_mint_test.go new file mode 100644 index 0000000000..bf1651c8bd --- /dev/null +++ b/tests/cli_tests/zwalletcli_zcnbridge_auth_replace_burn_mint_test.go @@ -0,0 +1,190 @@ +package cli_tests + +import ( + "fmt" + "regexp" + "strings" + "testing" + "time" + + "github.com/0chain/system_test/internal/api/util/test" + cliutils "github.com/0chain/system_test/internal/cli/util" + "github.com/stretchr/testify/require" +) + +func TestReplaceAuthorizerBurnZCNAndMintWZCN(testSetup *testing.T) { + t := test.NewSystemTest(testSetup) + + authsIDKeys := map[string]string{ + "d6e9b3222434faa043c683d1a939d6a0fa2818c4d56e794974d64a32005330d3": "b41d6232f11e0feefe895483688410216b3b1101e5db55044b22f0342fc18718b96b3124c9373dd116c50bd9b60512f28930a0e5771e58ecdc7d5bc2b570111a", + "7b07c0489e2f35d7c13160f4da2866b4aa69aa4e8d2b2cd9c4fc002693dca5d7": "aa6b6a16ae362189008cd4e7b4573174460965ab8d9c18515f0142cee4d8ba0708584cfbb8074120586998157ccb808954cde6c68443f22aab0b5ca72175c79d", + "896c171639937a647f9e91d5ba676be580f6d2b7e0d708e4fe6ea36610a13ffd": "aa894f74724dbb774deafda1de89b1d2853e1849c148c632ef7c9877338d5d129c9ccca3fe6a4581af2b07bbfb1225da4f674b1f76b49bc2187dc761896dff87", + } + + // create local wallet and faucet + output, err := createWallet(t, configPath) + require.NoError(t, err, "Unexpected create wallet failure", strings.Join(output, "\n")) + + // We should have 3 authorizers in total when the network is deployed. + // Test steps: + // - Remove one authorizer, and do the burn ZCN and mint WZCN test flow. + // Expected result: The test should pass. + // + // - Remove another authorizer, and add back the first removed authorizer, do the burn and mint test flow. + // Expect result: The test should pass. + // + // Ideally we should check the outputs to see the mint requests burn tickets to the right authorizers. + // but that's trivial and we have done the manual test to confirm the correct authorizers are used. + auths := getAuthorizers(t, false) + + require.Len(t, auths, 3, "There should be 3 authorizers in the network") + + // Remove 1 authorizer from zcnsc smartcontract + removeAuth := auths[0] + output, err = removeAuthorizer(t, removeAuth.ID, false) + require.NoError(t, err, "Unexpected remove authorizer failure", strings.Join(output, "\n")) + t.Logf("remove authorizer: %s zcnsc successfully", removeAuth.ID) + + // confirm burn zcn and mint wzcn could work with the existing 2 authorizers + burnZCNMintWZCN(t) + + // remove another authorizer + auth2 := auths[1] + output, err = removeAuthorizer(t, auth2.ID, false) + require.NoError(t, err, "Unexpected remove authorizer failure", strings.Join(output, "\n")) + t.Logf("remove authorizer: %s zcnsc successfully", auth2.ID) + + // add back the authorizer removed previously, the auths[0] + addAuth := auths[0] + output, err = registerAuthorizer(t, addAuth.ID, authsIDKeys[addAuth.ID], addAuth.URL, false) + require.NoError(t, err, "Unexpected register authorizer failure", strings.Join(output, "\n")) + + // wait until the new one is registered + var ( + // 6 * 30 seconds = 2 minute, the authorizer send health check every 60 seconds + maxRetry = 6 + reged bool + ) + for i := 0; i < maxRetry; i++ { + newAuths := getAuthorizers(t, false) + if len(newAuths) == 2 { + reged = true + break + } + t.Logf("retry list authorizers after 30 seconds, current num: %d", len(newAuths)) + time.Sleep(30 * time.Second) + } + + require.True(t, reged, "The new authorizer is not registered") + + // confirm burn zcn and mint wzcn could work + burnZCNMintWZCN(t) + + // add back the second removed authorizer + addAuth2 := auths[1] + output, err = registerAuthorizer(t, addAuth2.ID, authsIDKeys[addAuth2.ID], addAuth2.URL, false) + require.NoError(t, err, "Unexpected register authorizer failure", strings.Join(output, "\n")) + + // TODO: test burn-wzcn and mint zcn, but thats require the grapnode and dex_subgraph setup for + // tenderly fork. So leave it for now. We have done the manual test to confirm the flow could work. +} + +func burnZCNMintWZCN(t *test.SystemTest) { + // Burn zcn + output, err := burnZCN(t, "1", false) + require.NoError(t, err, "Unexpected burn zcn failure", strings.Join(output, "\n")) + t.Log("burn output:", strings.Join(output, "\n")) + + // Mint wzcn + output, err = mintWZCN(t, false) + require.NoError(t, err, "Unexpected mint wzcn failure", strings.Join(output, "\n")) + t.Log("mint output:", strings.Join(output, "\n")) +} + +func burnZCN(t *test.SystemTest, amount string, retry bool) ([]string, error) { + t.Log("Burn zcn ...") + cmd := fmt.Sprintf(` + ./zwallet bridge-burn-zcn --silent + --configDir ./config + --path %s + --wallet %s + --token %s`, + configDir, + escapedTestName(t)+"_wallet.json", + amount) + + if retry { + return cliutils.RunCommand(t, cmd, 6, time.Second*10) + } else { + return cliutils.RunCommandWithoutRetry(cmd) + } +} + +func mintWZCN(t *test.SystemTest, retry bool) ([]string, error) { + t.Log("Mint wzcn ...") + cmd := fmt.Sprintf(` + ./zwallet bridge-mint-wzcn --silent + --configDir ./config + --path %s + --wallet %s`, + configDir, + escapedTestName(t)+"_wallet.json") + + if retry { + return cliutils.RunCommand(t, cmd, 6, time.Second*10) + } else { + return cliutils.RunCommandWithoutRetry(cmd) + } +} + +type authorizerNode struct { + ID string + URL string +} + +func getAuthorizers(t *test.SystemTest, retry bool) []authorizerNode { + // get all authorizers + output, err := getAuthorizersCmd(t, false) + require.NoError(t, err) + + // Define the regular expression to match the line with "id": "the authorizer id" + re := regexp.MustCompile(`"id"\s*:\s*"(.*?)"|"url"\s*:\s*"(.*?)"`) + + // Find all matches + matches := re.FindAllStringSubmatch(strings.Join(output, "\n"), -1) + + // Extract the URLs from the matches + ids := make([]string, 0, len(matches)) + urls := make([]string, 0, len(matches)) + for _, match := range matches { + if match[1] != "" { + ids = append(ids, match[1]) + } else { + urls = append(urls, match[2]) + } + } + + auths := make([]authorizerNode, len(ids)) + for i := 0; i < len(ids); i++ { + auths[i] = authorizerNode{ + ID: ids[i], + URL: urls[i], + } + } + return auths +} + +func getAuthorizersCmd(t *test.SystemTest, retry bool) ([]string, error) { + t.Log("Get authorizers from zcnsc ...") + + cmd := fmt.Sprintf(` + ./zwallet bridge-list-auth --silent + --configDir ./config + --wallet %s`, escapedTestName(t)+"_wallet.json") + + if retry { + return cliutils.RunCommand(t, cmd, 6, time.Second*10) + } else { + return cliutils.RunCommandWithoutRetry(cmd) + } +}