github.com/Finschia/finschia-proxy/v2@v2.0.1/cli_test/cli_test.go (about) 1 //go:build cli_test 2 3 package clitest 4 5 import ( 6 "encoding/base64" 7 "encoding/hex" 8 "errors" 9 "fmt" 10 "os" 11 "path" 12 "path/filepath" 13 "strconv" 14 "strings" 15 "testing" 16 "time" 17 18 "github.com/Finschia/finschia-sdk/client/flags" 19 "github.com/Finschia/finschia-sdk/crypto/keys/ed25519" 20 sdk "github.com/Finschia/finschia-sdk/types" 21 "github.com/Finschia/finschia-sdk/types/tx" 22 gov "github.com/Finschia/finschia-sdk/x/gov/types" 23 minttypes "github.com/Finschia/finschia-sdk/x/mint/types" 24 osttypes "github.com/Finschia/ostracon/types" 25 "github.com/stretchr/testify/require" 26 27 "github.com/Finschia/finschia-proxy/v2/app" 28 ) 29 30 func TestFnsadKeysAddMultisig(t *testing.T) { 31 t.Parallel() 32 f := InitFixtures(t) 33 defer f.Cleanup() 34 35 // key names order does not matter 36 f.KeysAdd("msig1", "--multisig-threshold=2", 37 fmt.Sprintf("--multisig=%s,%s", keyBar, keyBaz)) 38 39 // err : trying to save same pubkey 40 msig1Addr := f.KeysShow("msig1").Address 41 f.KeysDelete("msig1") 42 43 f.KeysAdd("msig2", "--multisig-threshold=2", 44 fmt.Sprintf("--multisig=%s,%s", keyBaz, keyBar)) 45 require.Equal(t, msig1Addr, f.KeysShow("msig2").Address) 46 47 f.KeysAdd("msig3", "--multisig-threshold=2", 48 fmt.Sprintf("--multisig=%s,%s", keyBar, keyBaz), 49 "--nosort") 50 f.KeysAdd("msig4", "--multisig-threshold=2", 51 fmt.Sprintf("--multisig=%s,%s", keyBaz, keyBar), 52 "--nosort") 53 require.NotEqual(t, f.KeysShow("msig3").Address, f.KeysShow("msig4").Address) 54 } 55 56 func TestFnsadMinimumFees(t *testing.T) { 57 t.Parallel() 58 f := InitFixtures(t) 59 defer f.Cleanup() 60 61 // start fnsad server with minimum fees 62 minGasPrice, err := sdk.NewDecFromStr("0.000006") 63 require.NoError(t, err) 64 65 fees := fmt.Sprintf( 66 "%s,%s", 67 sdk.NewDecCoinFromDec(feeDenom, minGasPrice), 68 sdk.NewDecCoinFromDec(fee2Denom, minGasPrice), 69 ) 70 71 n := f.FnsadStart(fees) 72 defer n.Cleanup() 73 74 barAddr := f.KeyAddress(keyBar) 75 76 // Send a transaction that will get rejected 77 out, err := f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(fee2Denom, 10), "-y") 78 require.NoError(t, err) 79 require.Contains(t, out.String(), "insufficient fees") 80 81 err = n.WaitForNextBlock() 82 require.NoError(t, err) 83 84 // Ensure tx w/ correct fees pass 85 txFees := fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(feeDenom, 2)) 86 _, err = f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(fee2Denom, 10), txFees, "-y") 87 require.NoError(t, err) 88 89 err = n.WaitForNextBlock() 90 require.NoError(t, err) 91 92 // Ensure tx w/ improper fees fails 93 txFees = fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(feeDenom, 1)) 94 out, err = f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(fooDenom, 10), txFees, "-y") 95 require.NoError(t, err) 96 require.Contains(t, out.String(), "insufficient fees") 97 } 98 99 func TestFnsadGasPrices(t *testing.T) { 100 t.Parallel() 101 f := InitFixtures(t) 102 defer f.Cleanup() 103 104 // start fnsad server with minimum fees 105 minGasPrice, err := sdk.NewDecFromStr("0.000006") 106 require.NoError(t, err) 107 108 n := f.FnsadStart(sdk.NewDecCoinFromDec(feeDenom, minGasPrice).String()) 109 defer n.Cleanup() 110 111 barAddr := f.KeyAddress(keyBar) 112 113 // insufficient gas prices (tx fails) 114 badGasPrice, err := sdk.NewDecFromStr("0.000003") 115 require.NoError(t, err) 116 117 out, err := f.TxSend( 118 keyFoo, barAddr, sdk.NewInt64Coin(fooDenom, 50), 119 fmt.Sprintf("--gas-prices=%s", sdk.NewDecCoinFromDec(feeDenom, badGasPrice)), "-y") 120 require.NoError(t, err) 121 require.Contains(t, out.String(), "insufficient fees") 122 123 // wait for a block confirmation 124 require.NoError(t, n.WaitForNextBlock()) 125 126 // sufficient gas prices (tx passes) 127 _, err = f.TxSend( 128 keyFoo, barAddr, sdk.NewInt64Coin(fooDenom, 50), 129 fmt.Sprintf("--gas-prices=%s", sdk.NewDecCoinFromDec(feeDenom, minGasPrice)), "-y") 130 require.NoError(t, err) 131 132 // wait for a block confirmation 133 require.NoError(t, n.WaitForNextBlock()) 134 } 135 136 func TestFnsadFeesDeduction(t *testing.T) { 137 t.Parallel() 138 f := InitFixtures(t) 139 defer f.Cleanup() 140 141 // start fnsad server with minimum fees 142 minGasPrice, err := sdk.NewDecFromStr("0.000006") 143 require.NoError(t, err) 144 145 n := f.FnsadStart(sdk.NewDecCoinFromDec(feeDenom, minGasPrice).String()) 146 defer n.Cleanup() 147 148 // Save key addresses for later use 149 fooAddr := f.KeyAddress(keyFoo) 150 barAddr := f.KeyAddress(keyBar) 151 152 fooBal := f.QueryBalances(fooAddr) 153 fooAmt := fooBal.GetBalances().AmountOf(fooDenom) 154 155 // test simulation 156 // _, err = f.TxSend( 157 // fooAddr.String(), barAddr, sdk.NewInt64Coin(fooDenom, 1000), 158 // fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(feeDenom, 2)), "--dry-run") 159 // require.NoError(t, err) 160 161 // Wait for a block 162 err = n.WaitForNextBlock() 163 require.NoError(t, err) 164 165 // ensure state didn't change 166 fooBal = f.QueryBalances(fooAddr) 167 require.Equal(t, fooAmt.Int64(), fooBal.GetBalances().AmountOf(fooDenom).Int64()) 168 169 // insufficient funds (coins + fees) tx fails 170 largeCoins := sdk.TokensFromConsensusPower(10000000, sdk.DefaultPowerReduction) 171 out, err := f.TxSend( 172 keyFoo, barAddr, sdk.NewCoin(fooDenom, largeCoins), 173 fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(feeDenom, 2)), "-y") 174 require.NoError(t, err) 175 176 // Wait for a block 177 err = n.WaitForNextBlock() 178 require.NoError(t, err) 179 180 resp := UnmarshalTxResponse(t, out.Bytes()) 181 out2 := f.QueryTx(resp.TxHash) 182 require.Contains(t, out2.String(), "insufficient funds") 183 184 // ensure state didn't change 185 fooBal = f.QueryBalances(fooAddr) 186 require.Equal(t, fooAmt.Int64(), fooBal.GetBalances().AmountOf(fooDenom).Int64()) 187 188 // test success (transfer = coins + fees) 189 _, err = f.TxSend( 190 keyFoo, barAddr, sdk.NewInt64Coin(fooDenom, 500), 191 fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(feeDenom, 2)), "-y") 192 require.NoError(t, err) 193 } 194 195 func TestFnsadSend(t *testing.T) { 196 t.Parallel() 197 f := InitFixtures(t) 198 defer f.Cleanup() 199 200 // start fnsad server 201 n := f.FnsadStart(minGasPrice.String()) 202 defer n.Cleanup() 203 204 // Save key addresses for later use 205 fooAddr := f.KeyAddress(keyFoo) 206 barAddr := f.KeyAddress(keyBar) 207 208 fooBal := f.QueryBalances(fooAddr) 209 210 fmt.Println(fooBal) 211 212 startTokens := sdk.TokensFromConsensusPower(50, sdk.DefaultPowerReduction) 213 fmt.Println(startTokens.Uint64()) 214 require.Equal(t, startTokens, fooBal.GetBalances().AmountOf(denom)) 215 216 // Send some tokens from one account to the other 217 sendTokens := sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction) 218 _, err := f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "-y") 219 require.NoError(t, err) 220 221 err = n.WaitForNextBlock() 222 require.NoError(t, err) 223 224 // Ensure account balances match expected 225 barBal := f.QueryBalances(barAddr) 226 require.Equal(t, sendTokens, barBal.GetBalances().AmountOf(denom)) 227 fooBal = f.QueryBalances(fooAddr) 228 require.Equal(t, startTokens.Sub(sendTokens), fooBal.GetBalances().AmountOf(denom)) 229 230 // Test --dry-run 231 // _, err = f.TxSend(fooAddr.String(), barAddr, sdk.NewCoin(denom, sendTokens), "--dry-run") 232 // require.NoError(t, err) 233 234 // Test --generate-only 235 out, err := f.TxSend( 236 fooAddr.String(), barAddr, sdk.NewCoin(denom, sendTokens), "--generate-only=true", 237 ) 238 require.NoError(t, err) 239 msg := UnmarshalTx(t, out.Bytes()) 240 require.NotZero(t, msg.GetAuthInfo().GetFee().GetGasLimit()) 241 require.Len(t, msg.GetMsgs(), 1) 242 require.Len(t, msg.GetSignatures(), 0) 243 244 // Check state didn't change 245 fooBal = f.QueryBalances(fooAddr) 246 require.Equal(t, startTokens.Sub(sendTokens), fooBal.GetBalances().AmountOf(denom)) 247 248 // test autosequencing 249 _, err = f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "-y") 250 require.NoError(t, err) 251 252 err = n.WaitForNextBlock() 253 require.NoError(t, err) 254 255 // Ensure account balances match expected 256 barBal = f.QueryBalances(barAddr) 257 require.Equal(t, sendTokens.MulRaw(2), barBal.GetBalances().AmountOf(denom)) 258 fooBal = f.QueryBalances(fooAddr) 259 require.Equal(t, startTokens.Sub(sendTokens.MulRaw(2)), fooBal.GetBalances().AmountOf(denom)) 260 261 // test memo 262 _, err = f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), fmt.Sprintf("--%s=%s", flags.FlagNote, "testnote"), "-y") 263 require.NoError(t, err) 264 265 err = n.WaitForNextBlock() 266 require.NoError(t, err) 267 268 // Ensure account balances match expected 269 barBal = f.QueryBalances(barAddr) 270 require.Equal(t, sendTokens.MulRaw(3), barBal.GetBalances().AmountOf(denom)) 271 fooBal = f.QueryBalances(fooAddr) 272 require.Equal(t, startTokens.Sub(sendTokens.MulRaw(3)), fooBal.GetBalances().AmountOf(denom)) 273 } 274 275 func TestFnsadGasAuto(t *testing.T) { 276 t.Parallel() 277 f := InitFixtures(t) 278 defer f.Cleanup() 279 280 // start fnsad server 281 n := f.FnsadStart(minGasPrice.String()) 282 defer n.Cleanup() 283 284 fooAddr := f.KeyAddress(keyFoo) 285 barAddr := f.KeyAddress(keyBar) 286 287 fooBal := f.QueryBalances(fooAddr) 288 startTokens := sdk.TokensFromConsensusPower(50, sdk.DefaultPowerReduction) 289 require.Equal(t, startTokens, fooBal.GetBalances().AmountOf(denom)) 290 291 // Test failure with auto gas disabled and very little gas set by hand 292 sendTokens := sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction) 293 out, err := f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "--gas=10", "-y") 294 require.NoError(t, err) 295 require.Contains(t, out.String(), "out of gas in location") 296 297 // Check state didn't change 298 fooBal = f.QueryBalances(fooAddr) 299 require.Equal(t, startTokens, fooBal.GetBalances().AmountOf(denom)) 300 301 // Test failure with negative gas 302 _, err = f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "--gas=-100", "-y") 303 require.NoError(t, err) 304 305 // Check state didn't change 306 fooBal = f.QueryBalances(fooAddr) 307 require.Equal(t, startTokens, fooBal.GetBalances().AmountOf(denom)) 308 309 // Test failure with 0 gas 310 out, err = f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "--gas=0", "-y") 311 require.NoError(t, err) 312 require.Contains(t, out.String(), "out of gas in location") 313 314 // Check state didn't change 315 fooBal = f.QueryBalances(fooAddr) 316 require.Equal(t, startTokens, fooBal.GetBalances().AmountOf(denom)) 317 318 // Enable auto gas 319 out, err = f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "--gas=auto", "-y") 320 require.NoError(t, err) 321 cdc, _ := app.MakeCodecs() 322 sendResp := sdk.TxResponse{} 323 err = cdc.UnmarshalJSON(out.Bytes(), &sendResp) 324 require.Nil(t, err) 325 require.True(t, sendResp.GasWanted >= sendResp.GasUsed) 326 327 err = n.WaitForNextBlock() 328 require.NoError(t, err) 329 330 // Check state has changed accordingly 331 fooBal = f.QueryBalances(fooAddr) 332 require.Equal(t, startTokens.Sub(sendTokens), fooBal.GetBalances().AmountOf(denom)) 333 } 334 335 func TestFnsadCreateValidator(t *testing.T) { 336 t.Parallel() 337 f := InitFixtures(t) 338 defer f.Cleanup() 339 340 // start fnsad server 341 n := f.FnsadStart(minGasPrice.String()) 342 defer n.Cleanup() 343 344 barAddr := f.KeyAddress(keyBar) 345 barVal := sdk.ValAddress(barAddr) 346 347 cdc, _ := app.MakeCodecs() 348 pubKeyJSON, err := cdc.MarshalInterfaceJSON(ed25519.GenPrivKey().PubKey()) 349 require.NoError(t, err) 350 consPubKey := string(pubKeyJSON) 351 352 sendTokens := sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction) 353 _, err = f.TxSend(keyFoo, barAddr, sdk.NewCoin(denom, sendTokens), "-y") 354 require.NoError(t, err) 355 356 err = n.WaitForNextBlock() 357 require.NoError(t, err) 358 359 barBal := f.QueryBalances(barAddr) 360 require.Equal(t, sendTokens, barBal.GetBalances().AmountOf(denom)) 361 362 // Generate a create validator transaction and ensure correctness 363 out, err := f.TxStakingCreateValidator(barAddr.String(), consPubKey, sdk.NewInt64Coin(denom, 2), "--generate-only") 364 365 require.NoError(t, err) 366 fmt.Println(out.String()) 367 msg := UnmarshalTx(t, out.Bytes()) 368 require.NotZero(t, msg.GetAuthInfo().GetFee().GetGasLimit()) 369 require.Equal(t, len(msg.GetMsgs()), 1) 370 require.Equal(t, 0, len(msg.GetSignatures())) 371 372 // Test --dry-run 373 newValTokens := sdk.TokensFromConsensusPower(2, sdk.DefaultPowerReduction) 374 // _, err = f.TxStakingCreateValidator(barAddr.String(), consPubKey, sdk.NewCoin(denom, newValTokens), "--dry-run") 375 // require.NoError(t, err) 376 377 // grant bar to create validator 378 member := f.KeyAddress(keyFoo) 379 _, err = f.TxFoundationGrantCreateValidator([]sdk.AccAddress{member}, barAddr, "-y") 380 require.NoError(t, err) 381 382 err = n.WaitForNextBlock() 383 require.NoError(t, err) 384 385 // Create the validator 386 _, err = f.TxStakingCreateValidator(keyBar, consPubKey, sdk.NewCoin(denom, newValTokens), "-y") 387 require.NoError(t, err) 388 389 err = n.WaitForNextBlock() 390 require.NoError(t, err) 391 392 // Ensure funds were deducted properly 393 barBal = f.QueryBalances(barAddr) 394 require.Equal(t, sendTokens.Sub(newValTokens), barBal.GetBalances().AmountOf(denom)) 395 396 // Ensure that validator state is as expected 397 validator := f.QueryStakingValidator(barVal) 398 require.Equal(t, validator.OperatorAddress, barVal.String()) 399 require.True(sdk.IntEq(t, newValTokens, validator.Tokens)) 400 401 // Query delegations to the validator 402 validatorDelegations := f.QueryStakingDelegationsTo(barVal) 403 require.Len(t, validatorDelegations.DelegationResponses, 1) 404 require.NotZero(t, validatorDelegations.GetDelegationResponses()[0].GetDelegation().GetShares()) 405 406 // unbond a single share 407 unbondAmt := sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(1, sdk.DefaultPowerReduction)) 408 _, err = f.TxStakingUnbond(keyBar, unbondAmt.String(), barVal, "-y") 409 require.NoError(t, err) 410 411 err = n.WaitForNextBlock() 412 require.NoError(t, err) 413 414 // Ensure bonded staking is correct 415 remainingTokens := newValTokens.Sub(unbondAmt.Amount) 416 validator = f.QueryStakingValidator(barVal) 417 require.Equal(t, remainingTokens, validator.Tokens) 418 419 // Get unbonding delegations from the validator 420 validatorUbds := f.QueryStakingUnbondingDelegationsFrom(barVal) 421 require.Len(t, validatorUbds.GetUnbondingResponses(), 1) 422 require.Len(t, validatorUbds.GetUnbondingResponses()[0].Entries, 1) 423 require.Equal(t, remainingTokens.String(), validatorUbds.GetUnbondingResponses()[0].Entries[0].Balance.String()) 424 } 425 426 func TestFnsadQuerySupply(t *testing.T) { 427 t.Parallel() 428 f := InitFixtures(t) 429 defer f.Cleanup() 430 431 // start fnsad server 432 n := f.FnsadStart(minGasPrice.String()) 433 defer n.Cleanup() 434 435 totalSupplyOf := f.QueryTotalSupplyOf(fooDenom) 436 437 require.True(sdk.IntEq(t, TotalCoins.AmountOf(fooDenom), totalSupplyOf.Amount)) 438 } 439 440 func TestFnsadSubmitProposal(t *testing.T) { 441 t.Parallel() 442 f := InitFixtures(t) 443 defer f.Cleanup() 444 445 // start fnsad server 446 n := f.FnsadStart(minGasPrice.String()) 447 defer n.Cleanup() 448 449 f.QueryGovParamDeposit() 450 f.QueryGovParamVoting() 451 f.QueryGovParamTallying() 452 453 fooAddr := f.KeyAddress(keyFoo) 454 455 fooBal := f.QueryBalances(fooAddr) 456 startTokens := sdk.TokensFromConsensusPower(50, sdk.DefaultPowerReduction) 457 require.Equal(t, startTokens, fooBal.GetBalances().AmountOf(sdk.DefaultBondDenom)) 458 459 proposalsQuery := f.QueryGovProposals() 460 require.Empty(t, proposalsQuery) 461 462 // Test submit generate only for submit proposal 463 proposalTokens := sdk.TokensFromConsensusPower(5, sdk.DefaultPowerReduction) 464 out, err := f.TxGovSubmitProposal( 465 fooAddr.String(), "Text", "Test", "test", sdk.NewCoin(denom, proposalTokens), "--generate-only", "-y") 466 require.NoError(t, err) 467 msg := UnmarshalTx(t, out.Bytes()) 468 require.NotZero(t, msg.GetAuthInfo().GetFee().GetGasLimit()) 469 require.Equal(t, len(msg.GetMsgs()), 1) 470 require.Equal(t, 0, len(msg.GetSignatures())) 471 472 // Test --dry-run 473 // _, err = f.TxGovSubmitProposal(fooAddr.String(), "Text", "Test", "test", sdk.NewCoin(denom, proposalTokens), "--dry-run") 474 // require.NoError(t, err) 475 476 // Create the proposal 477 _, err = f.TxGovSubmitProposal(keyFoo, "Text", "Test", "test", sdk.NewCoin(denom, proposalTokens), "-y") 478 require.NoError(t, err) 479 480 err = n.WaitForNextBlock() 481 require.NoError(t, err) 482 483 // Ensure transaction tags can be queried 484 searchResult := f.QueryTxs(1, 50, fmt.Sprintf("--events='message.action=%s&message.sender=%s'", sdk.MsgTypeURL(&gov.MsgSubmitProposal{}), fooAddr)) 485 require.Len(t, searchResult.Txs, 1) 486 487 // Ensure deposit was deducted 488 fooBal = f.QueryBalances(fooAddr) 489 require.Equal(t, startTokens.Sub(proposalTokens), fooBal.GetBalances().AmountOf(denom)) 490 491 // Ensure propsal is directly queryable 492 proposal1 := f.QueryGovProposal(1) 493 require.Equal(t, uint64(1), proposal1.ProposalId) 494 require.Equal(t, gov.StatusDepositPeriod, proposal1.Status) 495 496 // Ensure query proposals returns properly 497 proposalsQuery = f.QueryGovProposals() 498 require.Equal(t, uint64(1), proposalsQuery.GetProposals()[0].ProposalId) 499 500 // Query the deposits on the proposal 501 deposit := f.QueryGovDeposit(1, fooAddr) 502 require.Equal(t, proposalTokens, deposit.Amount.AmountOf(denom)) 503 504 // Test deposit generate only 505 depositTokens := sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction) 506 out, err = f.TxGovDeposit(1, fooAddr.String(), sdk.NewCoin(denom, depositTokens), "--generate-only") 507 require.NoError(t, err) 508 msg = UnmarshalTx(t, out.Bytes()) 509 require.NotZero(t, msg.GetAuthInfo().GetFee().GetGasLimit()) 510 require.Equal(t, len(msg.GetMsgs()), 1) 511 require.Equal(t, 0, len(msg.GetSignatures())) 512 513 // Run the deposit transaction 514 _, err = f.TxGovDeposit(1, keyFoo, sdk.NewCoin(denom, depositTokens), "-y") 515 require.NoError(t, err) 516 517 err = n.WaitForNextBlock() 518 require.NoError(t, err) 519 520 // test query deposit 521 deposits := f.QueryGovDeposits(1) 522 require.Len(t, deposits.GetDeposits(), 1) 523 require.Equal(t, proposalTokens.Add(depositTokens), deposits.GetDeposits()[0].Amount.AmountOf(denom)) 524 525 // Ensure querying the deposit returns the proper amount 526 deposit = f.QueryGovDeposit(1, fooAddr) 527 require.Equal(t, proposalTokens.Add(depositTokens), deposit.Amount.AmountOf(denom)) 528 529 // Ensure tags are set on the transaction 530 searchResult = f.QueryTxs(1, 50, fmt.Sprintf("--events='message.action=%s&message.sender=%s'", sdk.MsgTypeURL(&gov.MsgDeposit{}), fooAddr)) 531 require.Len(t, searchResult.Txs, 1) 532 533 // Ensure account has expected amount of funds 534 fooBal = f.QueryBalances(fooAddr) 535 require.Equal(t, startTokens.Sub(proposalTokens.Add(depositTokens)), fooBal.GetBalances().AmountOf(denom)) 536 537 // Fetch the proposal and ensure it is now in the voting period 538 proposal1 = f.QueryGovProposal(1) 539 require.Equal(t, uint64(1), proposal1.ProposalId) 540 require.Equal(t, gov.StatusVotingPeriod, proposal1.Status) 541 542 // Test vote generate only 543 out, err = f.TxGovVote(1, gov.OptionYes, fooAddr.String(), "--generate-only") 544 require.NoError(t, err) 545 msg = UnmarshalTx(t, out.Bytes()) 546 require.NotZero(t, msg.GetAuthInfo().GetFee().GetGasLimit()) 547 require.Equal(t, len(msg.GetMsgs()), 1) 548 require.Equal(t, 0, len(msg.GetSignatures())) 549 550 // Vote on the proposal 551 _, err = f.TxGovVote(1, gov.OptionYes, keyFoo, "-y") 552 require.NoError(t, err) 553 554 err = n.WaitForNextBlock() 555 require.NoError(t, err) 556 557 // Query the vote 558 vote := f.QueryGovVote(1, fooAddr) 559 require.Equal(t, uint64(1), vote.ProposalId) 560 require.Equal(t, 1, len(vote.Options)) 561 require.Equal(t, gov.OptionYes, vote.Options[0].Option) 562 563 // Query the votes 564 votes := f.QueryGovVotes(1) 565 require.Len(t, votes.GetVotes(), 1) 566 require.Equal(t, uint64(1), votes.GetVotes()[0].ProposalId) 567 require.Equal(t, 1, len(votes.GetVotes()[0].Options)) 568 require.Equal(t, gov.OptionYes, votes.GetVotes()[0].Options[0].Option) 569 570 // Ensure tags are applied to voting transaction properly 571 searchResult = f.QueryTxs(1, 50, fmt.Sprintf("--events='message.action=%s&message.sender=%s'", sdk.MsgTypeURL(&gov.MsgVote{}), fooAddr)) 572 require.Len(t, searchResult.Txs, 1) 573 574 // Ensure no proposals in deposit period 575 proposalsQuery = f.QueryGovProposals("--status=DepositPeriod") 576 require.Empty(t, proposalsQuery) 577 578 // Ensure the proposal returns as in the voting period 579 proposalsQuery = f.QueryGovProposals("--status=VotingPeriod") 580 require.Equal(t, uint64(1), proposalsQuery.GetProposals()[0].ProposalId) 581 582 // submit a second test proposal 583 _, err = f.TxGovSubmitProposal(keyFoo, "Text", "Apples", "test", sdk.NewCoin(denom, proposalTokens), "-y") 584 require.NoError(t, err) 585 586 err = n.WaitForNextBlock() 587 require.NoError(t, err) 588 589 // Test limit on proposals query 590 proposalsQuery = f.QueryGovProposals("--limit=2") 591 require.Equal(t, uint64(2), proposalsQuery.GetProposals()[1].ProposalId) 592 } 593 594 func TestFnsadSubmitParamChangeProposal(t *testing.T) { 595 t.Parallel() 596 f := InitFixtures(t) 597 defer f.Cleanup() 598 599 n := f.FnsadStart(minGasPrice.String()) 600 defer n.Cleanup() 601 602 fooAddr := f.KeyAddress(keyFoo) 603 fooBal := f.QueryBalances(fooAddr) 604 startTokens := sdk.TokensFromConsensusPower(50, sdk.DefaultPowerReduction) 605 require.Equal(t, startTokens, fooBal.GetBalances().AmountOf(sdk.DefaultBondDenom)) 606 607 // write proposal to file 608 proposalTokens := sdk.TokensFromConsensusPower(5, sdk.DefaultPowerReduction) 609 610 proposal := fmt.Sprintf(`{ 611 "title": "Param Change", 612 "description": "Update max validators", 613 "type": "Text", 614 "deposit": "%sstake" 615 }`, proposalTokens.String()) 616 617 proposalFile := WriteToNewTempFile(t, proposal) 618 619 // create the param change proposal 620 out, err := f.TxGovSubmitParamChangeProposal(keyFoo, proposalFile.Name(), "-y") 621 fmt.Println(out.String()) 622 require.NoError(t, err) 623 624 err = n.WaitForNextBlock() 625 require.NoError(t, err) 626 627 // ensure transaction tags can be queried 628 txsPage := f.QueryTxs(1, 50, fmt.Sprintf("--events='message.action=%s&message.sender=%s'", sdk.MsgTypeURL(&gov.MsgSubmitProposal{}), fooAddr)) 629 require.Len(t, txsPage.Txs, 1) 630 631 // ensure deposit was deducted 632 fooBal = f.QueryBalances(fooAddr) 633 require.Equal(t, startTokens.Sub(proposalTokens).String(), fooBal.GetBalances().AmountOf(sdk.DefaultBondDenom).String()) 634 635 // ensure proposal is directly queryable 636 proposal1 := f.QueryGovProposal(1) 637 require.Equal(t, uint64(1), proposal1.ProposalId) 638 require.Equal(t, gov.StatusDepositPeriod, proposal1.Status) 639 640 // ensure correct query proposals result 641 proposalsQuery := f.QueryGovProposals() 642 require.Equal(t, uint64(1), proposalsQuery.GetProposals()[0].ProposalId) 643 644 // ensure the correct deposit amount on the proposal 645 deposit := f.QueryGovDeposit(1, fooAddr) 646 require.Equal(t, proposalTokens, deposit.Amount.AmountOf(denom)) 647 } 648 649 func TestFnsadSubmitCommunityPoolSpendProposal(t *testing.T) { 650 t.Skip("Due to removing mint module") 651 t.Parallel() 652 f := InitFixtures(t) 653 defer f.Cleanup() 654 655 // create some inflation 656 var cdc, amino = app.MakeCodecs() 657 genesisState := f.GenesisState() 658 inflationMin := sdk.MustNewDecFromStr("10000.0") 659 var mintData minttypes.GenesisState 660 err := cdc.UnmarshalJSON(genesisState[minttypes.ModuleName], &mintData) 661 require.NoError(t, err) 662 663 mintData.Minter.Inflation = inflationMin 664 mintData.Params.InflationMin = inflationMin 665 mintData.Params.InflationMax = sdk.MustNewDecFromStr("15000.0") 666 mintDataBz, err := cdc.MarshalJSON(&mintData) 667 require.NoError(t, err) 668 genesisState[minttypes.ModuleName] = mintDataBz 669 670 genFile := filepath.Join(f.Home, "config", "genesis.json") 671 genDoc, err := osttypes.GenesisDocFromFile(genFile) 672 require.NoError(t, err) 673 genDoc.AppState, err = amino.MarshalJSON(genesisState) 674 require.NoError(t, err) 675 require.NoError(t, genDoc.SaveAs(genFile)) 676 677 n := f.FnsadStart("") 678 defer n.Cleanup() 679 680 fooAddr := f.KeyAddress(keyFoo) 681 fooBal := f.QueryBalances(fooAddr) 682 startTokens := sdk.TokensFromConsensusPower(50, sdk.DefaultPowerReduction) 683 require.Equal(t, startTokens, fooBal.GetBalances().AmountOf(sdk.DefaultBondDenom)) 684 685 err = n.WaitForNextBlock() 686 require.NoError(t, err) 687 688 // write proposal to file 689 proposalTokens := sdk.TokensFromConsensusPower(5, sdk.DefaultPowerReduction) 690 691 proposal := fmt.Sprintf(`{ 692 "title": "Community Pool Spend", 693 "description": "Spend from community pool", 694 "type": "Text" 695 "deposit": "%s%s" 696 } 697 `, sdk.DefaultBondDenom, proposalTokens.String()) 698 699 proposalFile := WriteToNewTempFile(t, proposal) 700 701 // create the param change proposal 702 _, err = f.TxGovSubmitCommunityPoolSpendProposal(keyFoo, proposalFile.Name(), sdk.NewCoin(denom, proposalTokens), "-y") 703 require.NoError(t, err) 704 705 err = n.WaitForNextBlock() 706 require.NoError(t, err) 707 708 // ensure transaction tags can be queried 709 txsPage := f.QueryTxs(1, 50, fmt.Sprintf("--events='message.action=%s&message.sender=%s'", sdk.MsgTypeURL(&gov.MsgSubmitProposal{}), fooAddr)) 710 require.Len(t, txsPage.Txs, 1) 711 712 // ensure deposit was deducted 713 fooBal = f.QueryBalances(fooAddr) 714 require.Equal(t, startTokens.Sub(proposalTokens).String(), fooBal.GetBalances().AmountOf(sdk.DefaultBondDenom).String()) 715 716 // ensure proposal is directly queryable 717 proposal1 := f.QueryGovProposal(1) 718 require.Equal(t, uint64(1), proposal1.ProposalId) 719 require.Equal(t, gov.StatusDepositPeriod, proposal1.Status) 720 721 // ensure correct query proposals result 722 proposalsQuery := f.QueryGovProposals() 723 require.Equal(t, uint64(1), proposalsQuery.GetProposals()[0].ProposalId) 724 725 // ensure the correct deposit amount on the proposal 726 deposit := f.QueryGovDeposit(1, fooAddr) 727 require.Equal(t, proposalTokens, deposit.Amount.AmountOf(denom)) 728 } 729 730 func TestFnsadQueryTxPagination(t *testing.T) { 731 t.Parallel() 732 f := InitFixtures(t) 733 defer f.Cleanup() 734 735 // start fnsad server 736 n := f.FnsadStart(minGasPrice.String()) 737 defer n.Cleanup() 738 739 fooAddr := f.KeyAddress(keyFoo) 740 barAddr := f.KeyAddress(keyBar) 741 742 accFoo := f.QueryAccount(fooAddr) 743 seq := accFoo.GetSequence() 744 745 for i := 1; i <= 4; i++ { 746 _, err := f.TxSend(keyFoo, barAddr, sdk.NewInt64Coin(fooDenom, int64(i)), fmt.Sprintf("--sequence=%d", seq), "-y") 747 require.NoError(t, err) 748 seq++ 749 } 750 err := n.WaitForNextBlock() 751 require.NoError(t, err) 752 753 // perPage = 15, 2 pages 754 txsPage1 := f.QueryTxs(1, 2, fmt.Sprintf("--events='message.sender=%s'", fooAddr)) 755 require.Len(t, txsPage1.Txs, 2) 756 require.Equal(t, txsPage1.Count, uint64(2)) 757 txsPage2 := f.QueryTxs(2, 2, fmt.Sprintf("--events='message.sender=%s'", fooAddr)) 758 require.Len(t, txsPage2.Txs, 2) 759 require.NotEqual(t, txsPage1.Txs, txsPage2.Txs) 760 761 // perPage = 16, 2 pages 762 txsPage1 = f.QueryTxs(1, 3, fmt.Sprintf("--events='message.sender=%s'", fooAddr)) 763 require.Len(t, txsPage1.Txs, 3) 764 txsPage2 = f.QueryTxs(2, 3, fmt.Sprintf("--events='message.sender=%s'", fooAddr)) 765 require.Len(t, txsPage2.Txs, 1) 766 require.NotEqual(t, txsPage1.Txs, txsPage2.Txs) 767 768 // perPage = 50 769 txsPageFull := f.QueryTxs(1, 50, fmt.Sprintf("--events='message.sender=%s'", fooAddr)) 770 require.Len(t, txsPageFull.Txs, 4) 771 require.Equal(t, txsPageFull.Txs, append(txsPage1.Txs, txsPage2.Txs...)) 772 773 // perPage = 0 774 f.QueryTxsInvalid(errors.New("page must greater than 0"), 0, 50, fmt.Sprintf("--events='message.sender=%s'", fooAddr)) 775 776 // limit = 0 777 f.QueryTxsInvalid(errors.New("limit must greater than 0"), 1, 0, fmt.Sprintf("--events='message.sender=%s'", fooAddr)) 778 779 // no events 780 f.QueryTxsInvalid(errors.New("required flag(s) \"events\" not set"), 1, 30) 781 } 782 783 func TestFnsadValidateSignatures(t *testing.T) { 784 t.Skip("no flag validate-signatures") 785 t.Parallel() 786 f := InitFixtures(t) 787 defer f.Cleanup() 788 789 // start fnsad server 790 n := f.FnsadStart("") 791 defer n.Cleanup() 792 793 fooAddr := f.KeyAddress(keyFoo) 794 barAddr := f.KeyAddress(keyBar) 795 796 // generate sendTx with default gas 797 out, err := f.TxSend(fooAddr.String(), barAddr, sdk.NewInt64Coin(denom, 10), "--generate-only") 798 require.NoError(t, err) 799 800 // write unsigned tx to file 801 unsignedTxFile := WriteToNewTempFile(t, out.String()) 802 defer os.Remove(unsignedTxFile.Name()) 803 804 // validate we can successfully sign 805 out, err = f.TxSign(keyFoo, unsignedTxFile.Name()) 806 require.NoError(t, err) 807 stdTx := UnmarshalTx(t, out.Bytes()) 808 require.Equal(t, len(stdTx.GetMsgs()), 1) 809 require.Equal(t, 1, len(stdTx.GetSignatures())) 810 require.Equal(t, fooAddr.String(), stdTx.GetSigners()[0].String()) 811 812 // write signed tx to file 813 signedTxFile := WriteToNewTempFile(t, out.String()) 814 defer os.Remove(signedTxFile.Name()) 815 816 // validate signatures 817 _, err = f.TxSign(keyFoo, signedTxFile.Name(), "--validate-signatures") 818 require.NoError(t, err) 819 820 // modify the transaction 821 stdTx.Body.Memo = "MODIFIED-ORIGINAL-TX-BAD" 822 bz := MarshalTx(t, stdTx) 823 modSignedTxFile := WriteToNewTempFile(t, string(bz)) 824 defer os.Remove(modSignedTxFile.Name()) 825 826 // validate signature validation failure due to different transaction sig bytes 827 _, err = f.TxSign(keyFoo, modSignedTxFile.Name(), "--validate-signatures") 828 require.Error(t, err) 829 } 830 831 func TestFnsadSendGenerateSignAndBroadcast(t *testing.T) { 832 t.Parallel() 833 f := InitFixtures(t) 834 defer f.Cleanup() 835 836 // start fnsad server 837 n := f.FnsadStart(minGasPrice.String()) 838 defer n.Cleanup() 839 840 fooAddr := f.KeyAddress(keyFoo) 841 barAddr := f.KeyAddress(keyBar) 842 843 // Test generate sendTx with default gas 844 sendTokens := sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction) 845 out, err := f.TxSend(fooAddr.String(), barAddr, sdk.NewCoin(denom, sendTokens), "--generate-only") 846 require.NoError(t, err) 847 msg := UnmarshalTx(t, out.Bytes()) 848 require.Equal(t, msg.GetAuthInfo().GetFee().GetGasLimit(), uint64(flags.DefaultGasLimit)) 849 require.Equal(t, len(msg.GetMsgs()), 1) 850 require.Equal(t, 0, len(msg.GetSignatures())) 851 852 // Test generate sendTx with --gas=$amount 853 out, err = f.TxSend(fooAddr.String(), barAddr, sdk.NewCoin(denom, sendTokens), "--gas=100", "--generate-only") 854 require.NoError(t, err) 855 msg = UnmarshalTx(t, out.Bytes()) 856 require.Equal(t, msg.GetAuthInfo().GetFee().GetGasLimit(), uint64(100)) 857 require.Equal(t, len(msg.GetMsgs()), 1) 858 require.Equal(t, 0, len(msg.GetSignatures())) 859 860 // Test generate sendTx, estimate gas 861 out, err = f.TxSend(fooAddr.String(), barAddr, sdk.NewCoin(denom, sendTokens), "--generate-only") 862 require.NoError(t, err) 863 msg = UnmarshalTx(t, out.Bytes()) 864 require.True(t, msg.GetAuthInfo().GetFee().GetGasLimit() > 0) 865 require.Equal(t, len(msg.GetMsgs()), 1) 866 867 // Write the output to disk 868 unsignedTxFile := WriteToNewTempFile(t, out.String()) 869 defer os.Remove(unsignedTxFile.Name()) 870 871 // Test sign 872 out, err = f.TxSign(keyFoo, unsignedTxFile.Name()) 873 require.NoError(t, err) 874 msg = UnmarshalTx(t, out.Bytes()) 875 require.Equal(t, len(msg.GetMsgs()), 1) 876 require.Equal(t, 1, len(msg.GetSignatures())) 877 require.Equal(t, fooAddr.String(), msg.GetSigners()[0].String()) 878 879 // Write the output to disk 880 signedTxFile := WriteToNewTempFile(t, out.String()) 881 defer os.Remove(signedTxFile.Name()) 882 883 // Ensure foo has right amount of funds 884 fooBal := f.QueryBalances(fooAddr) 885 startTokens := sdk.TokensFromConsensusPower(50, sdk.DefaultPowerReduction) 886 require.Equal(t, startTokens, fooBal.GetBalances().AmountOf(denom)) 887 888 // Test broadcast 889 _, err = f.TxBroadcast(signedTxFile.Name()) 890 require.NoError(t, err) 891 892 err = n.WaitForNextBlock() 893 require.NoError(t, err) 894 895 // Ensure account state 896 barBal := f.QueryBalances(barAddr) 897 fooBal = f.QueryBalances(fooAddr) 898 require.Equal(t, sendTokens, barBal.GetBalances().AmountOf(denom)) 899 require.Equal(t, startTokens.Sub(sendTokens), fooBal.GetBalances().AmountOf(denom)) 900 } 901 902 func TestFnsadMultisignInsufficientCosigners(t *testing.T) { 903 t.Parallel() 904 f := InitFixtures(t) 905 defer f.Cleanup() 906 907 // start fnsad server with minimum fees 908 n := f.FnsadStart(minGasPrice.String()) 909 defer n.Cleanup() 910 911 fooBarBazAddr := f.KeyAddress(keyFooBarBaz) 912 barAddr := f.KeyAddress(keyBar) 913 914 // Send some tokens from one account to the other 915 _, err := f.TxSend(keyFoo, fooBarBazAddr, sdk.NewInt64Coin(denom, 10), "-y") 916 require.NoError(t, err) 917 918 err = n.WaitForNextBlock() 919 require.NoError(t, err) 920 921 // Test generate sendTx with multisig 922 out, err := f.TxSend(fooBarBazAddr.String(), barAddr, sdk.NewInt64Coin(denom, 5), "--generate-only") 923 require.NoError(t, err) 924 925 // Write the output to disk 926 unsignedTxFile := WriteToNewTempFile(t, out.String()) 927 defer os.Remove(unsignedTxFile.Name()) 928 929 // Sign with foo's key 930 out, err = f.TxSign(keyFoo, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String(), "-y") 931 require.NoError(t, err) 932 933 // Write the output to disk 934 fooSignatureFile := WriteToNewTempFile(t, out.String()) 935 defer os.Remove(fooSignatureFile.Name()) 936 937 // Multisign, not enough signatures 938 out, err = f.TxMultisign(unsignedTxFile.Name(), keyFooBarBaz, []string{fooSignatureFile.Name()}) 939 require.NoError(t, err) 940 941 // Write the output to disk 942 signedTxFile := WriteToNewTempFile(t, out.String()) 943 defer os.Remove(signedTxFile.Name()) 944 945 // Validate the multisignature 946 _, err = f.TxSign(keyFooBarBaz, signedTxFile.Name(), "--validate-signatures") 947 require.Error(t, err) 948 949 // Broadcast the transaction 950 out, err = f.TxBroadcast(signedTxFile.Name()) 951 require.NoError(t, err) 952 require.NotNil(t, out) 953 require.Contains(t, out.String(), "signature verification failed") 954 } 955 956 func TestFnsadEncode(t *testing.T) { 957 t.Parallel() 958 f := InitFixtures(t) 959 defer f.Cleanup() 960 961 // start fnsad server 962 n := f.FnsadStart(minGasPrice.String()) 963 defer n.Cleanup() 964 965 cdc, _ := app.MakeCodecs() 966 967 // Build a testing transaction and write it to disk 968 barAddr := f.KeyAddress(keyBar) 969 keyAddr := f.KeyAddress(keyFoo) 970 971 sendTokens := sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction) 972 out, err := f.TxSend(keyAddr.String(), barAddr, sdk.NewCoin(denom, sendTokens), "--generate-only", fmt.Sprintf("--%s=%s", flags.FlagNote, "deadbeef")) 973 require.NoError(t, err) 974 975 // Write it to disk 976 jsonTxFile := WriteToNewTempFile(t, out.String()) 977 defer os.Remove(jsonTxFile.Name()) 978 979 // Run the encode command, and trim the extras from the stdout capture 980 base64Encoded, err := f.TxEncode(jsonTxFile.Name()) 981 require.NoError(t, err) 982 trimmedBase64 := strings.Trim(base64Encoded.String(), "\"\n") 983 // Decode the base64 984 decodedBytes, err := base64.StdEncoding.DecodeString(trimmedBase64) 985 require.Nil(t, err) 986 987 // Check that the transaction decodes as expected 988 var decodedTx tx.Tx 989 require.Nil(t, cdc.Unmarshal(decodedBytes, &decodedTx)) 990 require.Equal(t, "deadbeef", decodedTx.GetBody().GetMemo()) 991 } 992 993 func TestFnsadMultisignSortSignatures(t *testing.T) { 994 t.Parallel() 995 f := InitFixtures(t) 996 defer f.Cleanup() 997 998 // start fnsad server with minimum fees 999 n := f.FnsadStart(minGasPrice.String()) 1000 defer n.Cleanup() 1001 1002 fooBarBazAddr := f.KeyAddress(keyFooBarBaz) 1003 barAddr := f.KeyAddress(keyBar) 1004 1005 // Send some tokens from one account to the other 1006 _, err := f.TxSend(keyFoo, fooBarBazAddr, sdk.NewInt64Coin(denom, 10), "-y") 1007 require.NoError(t, err) 1008 1009 err = n.WaitForNextBlock() 1010 require.NoError(t, err) 1011 1012 // Ensure account balances match expected 1013 fooBarBazBal := f.QueryBalances(fooBarBazAddr) 1014 require.Equal(t, int64(10), fooBarBazBal.GetBalances().AmountOf(denom).Int64()) 1015 1016 // Test generate sendTx with multisig 1017 out, err := f.TxSend(fooBarBazAddr.String(), barAddr, sdk.NewInt64Coin(denom, 5), "--generate-only") 1018 require.NoError(t, err) 1019 1020 // Write the output to disk 1021 unsignedTxFile := WriteToNewTempFile(t, out.String()) 1022 defer os.Remove(unsignedTxFile.Name()) 1023 1024 // Sign with foo's key 1025 out, err = f.TxSign(keyFoo, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String()) 1026 require.NoError(t, err) 1027 1028 // Write the output to disk 1029 fooSignatureFile := WriteToNewTempFile(t, out.String()) 1030 defer os.Remove(fooSignatureFile.Name()) 1031 1032 // Sign with baz's key 1033 out, err = f.TxSign(keyBaz, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String()) 1034 require.NoError(t, err) 1035 1036 // Write the output to disk 1037 bazSignatureFile := WriteToNewTempFile(t, out.String()) 1038 defer os.Remove(bazSignatureFile.Name()) 1039 1040 // Multisign, keys in different order 1041 out, err = f.TxMultisign(unsignedTxFile.Name(), keyFooBarBaz, []string{ 1042 bazSignatureFile.Name(), fooSignatureFile.Name()}) 1043 require.NoError(t, err) 1044 1045 // Write the output to disk 1046 signedTxFile := WriteToNewTempFile(t, out.String()) 1047 defer os.Remove(signedTxFile.Name()) 1048 1049 // Broadcast the transaction 1050 _, err = f.TxBroadcast(signedTxFile.Name()) 1051 require.NoError(t, err) 1052 } 1053 1054 func TestFnsadMultisign(t *testing.T) { 1055 t.Parallel() 1056 f := InitFixtures(t) 1057 defer f.Cleanup() 1058 1059 // start fnsad server with minimum fees 1060 n := f.FnsadStart(minGasPrice.String()) 1061 defer n.Cleanup() 1062 1063 fooBarBazAddr := f.KeyAddress(keyFooBarBaz) 1064 bazAddr := f.KeyAddress(keyBaz) 1065 1066 // Send some tokens from one account to the other 1067 _, err := f.TxSend(keyFoo, fooBarBazAddr, sdk.NewInt64Coin(denom, 10), "-y") 1068 require.NoError(t, err) 1069 1070 err = n.WaitForNextBlock() 1071 require.NoError(t, err) 1072 1073 // Ensure account balances match expected 1074 fooBarBazBal := f.QueryBalances(fooBarBazAddr) 1075 require.Equal(t, int64(10), fooBarBazBal.GetBalances().AmountOf(denom).Int64()) 1076 1077 // Test generate sendTx with multisig 1078 out, err := f.TxSend(fooBarBazAddr.String(), bazAddr, sdk.NewInt64Coin(denom, 10), "--generate-only") 1079 require.NoError(t, err) 1080 1081 // Write the output to disk 1082 unsignedTxFile := WriteToNewTempFile(t, out.String()) 1083 defer os.Remove(unsignedTxFile.Name()) 1084 1085 // Sign with foo's key 1086 out, err = f.TxSign(keyFoo, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String(), "-y") 1087 require.NoError(t, err) 1088 1089 // Write the output to disk 1090 fooSignatureFile := WriteToNewTempFile(t, out.String()) 1091 defer os.Remove(fooSignatureFile.Name()) 1092 1093 // Sign with bar's key 1094 out, err = f.TxSign(keyBar, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String(), "-y") 1095 require.NoError(t, err) 1096 1097 // Write the output to disk 1098 barSignatureFile := WriteToNewTempFile(t, out.String()) 1099 defer os.Remove(barSignatureFile.Name()) 1100 1101 // Multisign 1102 out, err = f.TxMultisign(unsignedTxFile.Name(), keyFooBarBaz, []string{ 1103 fooSignatureFile.Name(), barSignatureFile.Name()}) 1104 require.NoError(t, err) 1105 1106 // Write the output to disk 1107 signedTxFile := WriteToNewTempFile(t, out.String()) 1108 defer os.Remove(signedTxFile.Name()) 1109 1110 // Broadcast the transaction 1111 _, err = f.TxBroadcast(signedTxFile.Name()) 1112 require.NoError(t, err) 1113 } 1114 1115 func TestFnsadCollectGentxs(t *testing.T) { 1116 t.Parallel() 1117 var customMaxBytes, customMaxGas int64 = 99999999, 1234567 1118 f := NewFixtures(t, getHomeDir(t)) 1119 1120 // Initialize temporary directories 1121 gentxDir, err := os.MkdirTemp("", "") 1122 gentxDoc := filepath.Join(gentxDir, "gentx.json") 1123 require.NoError(t, err) 1124 1125 defer f.Cleanup(gentxDir) 1126 1127 // Initialize keys 1128 f.KeysAdd(keyFoo) 1129 1130 // Run init 1131 f.FnsadInit(keyFoo) 1132 1133 // Customize genesis.json 1134 genFile := f.GenesisFile() 1135 genDoc, err := osttypes.GenesisDocFromFile(genFile) 1136 require.NoError(t, err) 1137 genDoc.ConsensusParams.Block.MaxBytes = customMaxBytes 1138 genDoc.ConsensusParams.Block.MaxGas = customMaxGas 1139 err = genDoc.SaveAs(genFile) 1140 require.NoError(t, err) 1141 1142 // Add account to genesis.json 1143 f.AddGenesisAccount(f.KeyAddress(keyFoo), startCoins) 1144 1145 // Write gentx file 1146 f.GenTx(keyFoo, fmt.Sprintf("--output-document=%s", gentxDoc)) 1147 1148 // Collect gentxs from a custom directory 1149 f.CollectGenTxs(fmt.Sprintf("--gentx-dir=%s", gentxDir)) 1150 1151 genDoc, err = osttypes.GenesisDocFromFile(genFile) 1152 require.NoError(t, err) 1153 require.Equal(t, genDoc.ConsensusParams.Block.MaxBytes, customMaxBytes) 1154 require.Equal(t, genDoc.ConsensusParams.Block.MaxGas, customMaxGas) 1155 } 1156 1157 func TestValidateGenesis(t *testing.T) { 1158 t.Parallel() 1159 f := InitFixtures(t) 1160 defer f.Cleanup() 1161 1162 // start fnsad server 1163 n := f.FnsadStart(minGasPrice.String()) 1164 defer n.Cleanup() 1165 1166 f.ValidateGenesis(filepath.Join(f.Home, "config", "genesis.json")) 1167 } 1168 1169 func TestFnsadIncrementSequenceDecorator(t *testing.T) { 1170 t.Parallel() 1171 f := InitFixtures(t) 1172 defer f.Cleanup() 1173 1174 // start fnsad server 1175 n := f.FnsadStart(minGasPrice.String()) 1176 defer n.Cleanup() 1177 1178 fooAddr := f.KeyAddress(keyFoo) 1179 barAddr := f.KeyAddress(keyBar) 1180 1181 sendTokens := sdk.TokensFromConsensusPower(1, sdk.DefaultPowerReduction) 1182 1183 time.Sleep(3 * time.Second) 1184 1185 fooAcc := f.QueryAccount(fooAddr) 1186 1187 // Prepare signed Tx 1188 signedTxFiles := make([]*os.File, 0) 1189 for idx := 0; idx < 3; idx++ { 1190 // Test generate sendTx, estimate gas 1191 out, err := f.TxSend(fooAddr.String(), barAddr, sdk.NewCoin(denom, sendTokens), "--generate-only") 1192 require.NoError(t, err) 1193 1194 // Write the output to disk 1195 unsignedTxFile := WriteToNewTempFile(t, out.String()) 1196 defer os.Remove(unsignedTxFile.Name()) 1197 1198 // Test sign 1199 out, err = f.TxSign(keyFoo, unsignedTxFile.Name(), "--offline", fmt.Sprintf("--%s=%d", flags.FlagAccountNumber, fooAcc.AccountNumber), "--sequence", strconv.Itoa(int(fooAcc.Sequence)+idx)) 1200 require.NoError(t, err) 1201 1202 // Write the output to disk 1203 signedTxFile := WriteToNewTempFile(t, out.String()) 1204 signedTxFiles = append(signedTxFiles, signedTxFile) 1205 defer os.Remove(signedTxFile.Name()) 1206 } 1207 // Wait for a new block 1208 err := n.WaitForNextBlock() 1209 require.NoError(t, err) 1210 1211 txHashes := make([]string, 0) 1212 // Broadcast the signed Txs 1213 for _, signedTxFile := range signedTxFiles { 1214 // Test broadcast 1215 out, err := f.TxBroadcast(signedTxFile.Name(), "--broadcast-mode", "sync") 1216 require.NoError(t, err) 1217 sendResp := UnmarshalTxResponse(t, out.Bytes()) 1218 txHashes = append(txHashes, sendResp.TxHash) 1219 } 1220 1221 // Wait for a new block 1222 err = n.WaitForNextBlock() 1223 require.NoError(t, err) 1224 1225 // All Txs are in one block 1226 height := f.QueryTx(txHashes[0]).Height 1227 for _, txHash := range txHashes { 1228 require.Equal(t, height, f.QueryTx(txHash).Height) 1229 } 1230 } 1231 1232 func TestFnsadWasmContract(t *testing.T) { 1233 t.Parallel() 1234 f := InitFixtures(t) 1235 defer f.Cleanup() 1236 1237 // start fnsad server with minimum fees 1238 n := f.FnsadStart(minGasPrice.String()) 1239 defer n.Cleanup() 1240 1241 fooAddr := f.KeyAddress(keyFoo) 1242 1243 flagFromFoo := fmt.Sprintf("--from=%s", fooAddr) 1244 flagGas := "--gas=auto" 1245 flagGasAdjustment := "--gas-adjustment=1.2" 1246 workDir, err := os.Getwd() 1247 require.NoError(t, err) 1248 dirContract := path.Join(workDir, "contracts", "queue") 1249 hashFile := path.Join(dirContract, "hash.txt") 1250 wasmQueue := path.Join(dirContract, "contract.wasm") 1251 codeID := uint64(1) 1252 amountSend := uint64(10) 1253 denomSend := fooDenom 1254 1255 var contractAddress string 1256 count := 0 1257 initValue := 0 1258 enqueueValue := 2 1259 1260 // make tmpDir 1261 tmpDir, err := os.MkdirTemp("", "") 1262 require.NoError(t, err) 1263 defer func() { 1264 require.NoError(t, os.RemoveAll(tmpDir)) 1265 }() 1266 err = os.Chdir(tmpDir) 1267 require.NoError(t, err) 1268 1269 // validate that there are no code in the chain 1270 { 1271 listCode := f.QueryListCodeWasm() 1272 require.Len(t, listCode.CodeInfos, 0) 1273 } 1274 1275 // store the contract queue 1276 { 1277 _, err := f.TxStoreWasm(wasmQueue, flagFromFoo, flagGasAdjustment, flagGas, "-y") 1278 require.NoError(t, err) 1279 // Wait for a new block 1280 err = n.WaitForNextBlock() 1281 require.NoError(t, err) 1282 } 1283 1284 // validate the code is stored 1285 { 1286 queryCodesResponse := f.QueryListCodeWasm() 1287 require.Len(t, queryCodesResponse.CodeInfos, 1) 1288 1289 // validate the hash is the same 1290 expectedRow, err := os.ReadFile(hashFile) 1291 require.NoError(t, err) 1292 expected, err := hex.DecodeString(string(expectedRow[:64])) 1293 require.NoError(t, err) 1294 actual := queryCodesResponse.CodeInfos[0].DataHash.Bytes() 1295 require.Equal(t, expected, actual) 1296 } 1297 1298 // validate getCode get the exact same wasm 1299 { 1300 outputPath := fmt.Sprintf("contract-%s.wasm", strconv.FormatUint(codeID, 10)) 1301 f.QueryCodeWasm(codeID) 1302 fLocal, err := os.Open(wasmQueue) 1303 require.NoError(t, err) 1304 fChain, err := os.Open(outputPath) 1305 require.NoError(t, err) 1306 1307 // 2000000 is enough length 1308 dataLocal := make([]byte, 2000000) 1309 dataChain := make([]byte, 2000000) 1310 _, err = fLocal.Read(dataLocal) 1311 require.NoError(t, err) 1312 _, err = fChain.Read(dataChain) 1313 require.NoError(t, err) 1314 require.Equal(t, dataLocal, dataChain) 1315 } 1316 1317 // validate that there are no contract using the code (id=1) 1318 { 1319 listContract := f.QueryListContractByCodeWasm(codeID) 1320 require.Len(t, listContract.Contracts, 0) 1321 } 1322 1323 // instantiate a contract with the code queue 1324 { 1325 msgJSON := "{}" 1326 flagLabel := "--label=queue-test" 1327 flagAmount := fmt.Sprintf("--amount=%d%s", amountSend, denomSend) 1328 _, err := f.TxInstantiateWasm(codeID, msgJSON, flagFromFoo, flagGasAdjustment, flagGas, flagLabel, flagAmount, flagFromFoo, "-y", "--no-admin") 1329 require.NoError(t, err) 1330 // Wait for a new block 1331 err = n.WaitForNextBlock() 1332 require.NoError(t, err) 1333 } 1334 1335 // validate there is only one contract using codeID=1 and get contractAddress 1336 { 1337 listContract := f.QueryListContractByCodeWasm(codeID) 1338 require.Len(t, listContract.Contracts, 1) 1339 contractAddress = listContract.Contracts[0] 1340 } 1341 1342 // check queue count and sum 1343 { 1344 res := f.QueryContractStateSmartWasm(contractAddress, "{\"count\":{}}") 1345 require.Equal(t, fmt.Sprintf("{\"data\":{\"count\":%d}}", count), strings.TrimRight(res, "\n")) 1346 1347 res = f.QueryContractStateSmartWasm(contractAddress, "{\"sum\":{}}") 1348 require.Equal(t, fmt.Sprintf("{\"data\":{\"sum\":%d}}", initValue), strings.TrimRight(res, "\n")) 1349 } 1350 1351 // execute contract(enqueue function) 1352 { 1353 msgJSON := fmt.Sprintf("{\"enqueue\":{\"value\":%d}}", enqueueValue) 1354 _, err := f.TxExecuteWasm(contractAddress, msgJSON, flagFromFoo, flagGasAdjustment, flagGas, "-y") 1355 require.NoError(t, err) 1356 // Wait for a new block 1357 err = n.WaitForNextBlock() 1358 require.NoError(t, err) 1359 count++ 1360 } 1361 1362 // check queue count and sum 1363 { 1364 res := f.QueryContractStateSmartWasm(contractAddress, "{\"count\":{}}") 1365 require.Equal(t, fmt.Sprintf("{\"data\":{\"count\":%d}}", count), strings.TrimRight(res, "\n")) 1366 1367 res = f.QueryContractStateSmartWasm(contractAddress, "{\"sum\":{}}") 1368 require.Equal(t, fmt.Sprintf("{\"data\":{\"sum\":%d}}", initValue+enqueueValue), strings.TrimRight(res, "\n")) 1369 } 1370 }