diff --git a/applications/tari_base_node/src/grpc/base_node_grpc_server.rs b/applications/tari_base_node/src/grpc/base_node_grpc_server.rs index 11a962d59a..ac4f6c6a53 100644 --- a/applications/tari_base_node/src/grpc/base_node_grpc_server.rs +++ b/applications/tari_base_node/src/grpc/base_node_grpc_server.rs @@ -559,10 +559,13 @@ impl tari_rpc::base_node_server::BaseNode for BaseNodeGrpcServer { })?; if !base_node_response.is_empty() { - debug!(target: LOG_TARGET, "Sending Transaction state response to client"); let response = tari_rpc::TransactionStateResponse { result: tari_rpc::TransactionLocation::Mined.into(), }; + debug!( + target: LOG_TARGET, + "Sending Transaction state response to client {:?}", response + ); return Ok(Response::new(response)); } @@ -592,7 +595,10 @@ impl tari_rpc::base_node_server::BaseNode for BaseNodeGrpcServer { }, }; - debug!(target: LOG_TARGET, "Sending Transaction state response to client"); + debug!( + target: LOG_TARGET, + "Sending Transaction state response to client {:?}", response + ); Ok(Response::new(response)) } diff --git a/integration_tests/features/Mempool.feature b/integration_tests/features/Mempool.feature index 03b7f4b57f..a4b832debb 100644 --- a/integration_tests/features/Mempool.feature +++ b/integration_tests/features/Mempool.feature @@ -12,6 +12,7 @@ Feature: Mempool And I have 8 base nodes connected to all seed nodes When I mine a block on SENDER with coinbase CB1 When I mine 2 blocks on SENDER + Then all nodes are at height 3 When I create a transaction TX1 spending CB1 to UTX1 When I submit transaction TX1 to SENDER Then SENDER has TX1 in MEMPOOL state @@ -25,6 +26,7 @@ Feature: Mempool And I have 2 base nodes connected to all seed nodes When I mine a block on SENDER with coinbase CB1 When I mine 2 blocks on SENDER + Then all nodes are at height 3 When I create a transaction TX1 spending CB1 to UTX1 When I submit transaction TX1 to SENDER Then SENDER has TX1 in MEMPOOL state @@ -32,10 +34,11 @@ Feature: Mempool Given I have a base node NODE1 connected to all seed nodes Then NODE1 has TX1 in MEMPOOL state When I mine 1 blocks on SENDER + Then all nodes are at height 4 Then SENDER has TX1 in MINED state Then TX1 is in the MINED of all nodes - @broken + @critical Scenario: Clear out mempool Given I have 1 seed nodes And I have a base node SENDER connected to all seed nodes @@ -43,42 +46,26 @@ Feature: Mempool When I mine a block on SENDER with coinbase CB2 When I mine a block on SENDER with coinbase CB3 When I mine 4 blocks on SENDER - When I create a custom fee transaction TX1 spending CB1 to UTX1 with fee 16 - When I create a custom fee transaction TX2 spending CB2 to UTX2 with fee 20 - When I create a custom fee transaction TX3 spending CB3 to UTX3 with fee 18 + When I create a custom fee transaction TX1 spending CB1 to UTX1 with fee 1600 + When I create a custom fee transaction TX2 spending CB2 to UTX2 with fee 2000 + When I create a custom fee transaction TX3 spending CB3 to UTX3 with fee 1800 When I submit transaction TX1 to SENDER When I submit transaction TX2 to SENDER When I submit transaction TX3 to SENDER Then SENDER has TX1 in MEMPOOL state Then SENDER has TX2 in MEMPOOL state Then SENDER has TX3 in MEMPOOL state - When I mine 1 custom weight blocks on SENDER with weight 17 + # Note: The block weight should only allow one transaction to be included in the block template + When I mine 1 custom weight blocks on SENDER with weight 80 Then SENDER has TX1 in MEMPOOL state Then SENDER has TX2 in MINED state Then SENDER has TX3 in MEMPOOL state - When I mine 1 custom weight blocks on SENDER with weight 17 + # Note: The block weight should only allow one transaction to be included in the block template + When I mine 1 custom weight blocks on SENDER with weight 80 Then SENDER has TX1 in MEMPOOL state Then SENDER has TX2 in MINED state Then SENDER has TX3 in MINED state - - @critical - Scenario: Double spend - Given I have 1 seed nodes - And I have a base node SENDER connected to all seed nodes - When I mine a block on SENDER with coinbase CB1 - When I mine 4 blocks on SENDER - When I create a custom fee transaction TX1 spending CB1 to UTX1 with fee 16 - When I create a custom fee transaction TX2 spending CB1 to UTX2 with fee 20 - When I submit transaction TX1 to SENDER - When I submit transaction TX2 to SENDER - Then SENDER has TX1 in MEMPOOL state - Then SENDER has TX2 in MEMPOOL state - When I mine 1 blocks on SENDER - # a transaction that was removed from the pool will be reported as unknown as long as it is stored in the reorg pool for 5 mins - Then SENDER has TX1 in UNKNOWN state - Then SENDER has TX2 in MINED state - @long-running Scenario: Double spend eventually ends up as not stored Given I have 1 seed nodes @@ -92,7 +79,9 @@ Feature: Mempool Then SENDER has TX1 in MEMPOOL state Then SENDER has TX2 in MEMPOOL state When I mine 1 blocks on SENDER - # a transaction that was removed from the pool will be reported as unknown as long as it is stored in the reorg pool for 5 mins + # A transaction that was removed from the pool will be reported as unknown as long as it is stored in the reorg pool + # for 5 minutes + Then SENDER has TX1 in UNKNOWN state Then SENDER has TX1 in NOT_STORED state Then SENDER has TX2 in MINED state @@ -100,20 +89,28 @@ Feature: Mempool Scenario: Mempool clearing out invalid transactions after a reorg Given I have a seed node SEED_A And I have a base node NODE_A connected to seed SEED_A + And I have wallet WALLET_A connected to base node NODE_A + And I have mining node MINING_A connected to base node NODE_A and wallet WALLET_A When I mine a block on NODE_A with coinbase CB_A - When I mine 3 blocks on NODE_A + And mining node MINING_A mines 3 blocks with min difficulty 1 and max difficulty 2 + Then node SEED_A is at height 4 Given I have a seed node SEED_B And I have a base node NODE_B connected to seed SEED_B + And I have wallet WALLET_B connected to base node NODE_B + And I have mining node MINING_B connected to base node NODE_B and wallet WALLET_B When I mine a block on NODE_B with coinbase CB_B - When I mine 10 blocks on NODE_B + And mining node MINING_B mines 10 blocks with min difficulty 20 and max difficulty 9999999999 + Then node SEED_B is at height 11 When I create a custom fee transaction TXA spending CB_A to UTX1 with fee 16 When I create a custom fee transaction TXB spending CB_B to UTX1 with fee 16 When I submit transaction TXA to NODE_A When I submit transaction TXB to NODE_B Then NODE_A has TXA in MEMPOOL state Then NODE_B has TXB in MEMPOOL state - When I mine 1 blocks on NODE_A - When I mine 1 blocks on NODE_B + And mining node MINING_A mines 1 blocks with min difficulty 1 and max difficulty 2 + And mining node MINING_B mines 1 blocks with min difficulty 20 and max difficulty 9999999999 + Then node SEED_A is at height 5 + Then node SEED_B is at height 12 And I connect node NODE_A to node NODE_B Then all nodes are at height 12 Then NODE_A has TXA in NOT_STORED state diff --git a/integration_tests/features/Sync.feature b/integration_tests/features/Sync.feature index af98f62ff1..c2271468b9 100644 --- a/integration_tests/features/Sync.feature +++ b/integration_tests/features/Sync.feature @@ -70,22 +70,27 @@ Feature: Block Sync @long-running @flaky Scenario: Node should not sync from pruned node Given I have a base node NODE1 connected to all seed nodes - And I have a pruned node PNODE1 connected to node NODE1 with pruning horizon set to 5 - When I mine 40 blocks on NODE1 + And I have wallet WALLET1 connected to base node NODE1 + And I have mining node MINING1 connected to base node NODE1 and wallet WALLET1 + And I have a pruned node PNODE1 connected to node NODE1 with pruning horizon set to 6 + When mining node MINING1 mines 40 blocks with min difficulty 20 and max difficulty 9999999999 Then all nodes are at height 40 When I stop node NODE1 - Given I have a base node NODE2 connected to node PNODE1 Given I have a pruned node PNODE2 connected to node PNODE1 with pruning horizon set to 5 - When I mine 5 blocks on NODE2 - Then node NODE2 is at height 5 + Given I have a base node NODE2 + And I have wallet WALLET2 connected to base node NODE2 + And I have mining node MINING2 connected to base node NODE2 and wallet WALLET2 + When mining node MINING2 mines 5 blocks with min difficulty 1 and max difficulty 2 + And I connect node NODE2 to node PNODE1 + And I connect node NODE2 to node PNODE2 Then node PNODE2 is at height 40 + Then node NODE2 is at height 5 When I start base node NODE1 # We need for node to boot up and supply node 2 with blocks And I connect node NODE2 to node NODE1 # NODE2 may initially try to sync from PNODE1 and PNODE2, then eventually try to sync from NODE1; mining blocks # on NODE1 will make this test less flaky and force NODE2 to sync from NODE1 much quicker When I mine 10 blocks on NODE1 - Then all transactions must have succeeded Then all nodes are at height 50 Scenario Outline: Syncing node while also mining before tip sync @@ -100,7 +105,7 @@ Feature: Block Sync Then node SEED is at height When I start base node SYNCER # Try to mine much faster than block sync, but still producing a lower accumulated difficulty - And mining node MINER2 mines blocks with min difficulty 1 and max difficulty 10 + And mining node MINER2 mines blocks with min difficulty 1 and max difficulty 2 Then node SYNCER is at the same height as node SEED @critical Examples: diff --git a/integration_tests/features/TransactionInfo.feature b/integration_tests/features/TransactionInfo.feature index 13bf015b30..68d338703f 100644 --- a/integration_tests/features/TransactionInfo.feature +++ b/integration_tests/features/TransactionInfo.feature @@ -4,7 +4,6 @@ Feature: Transaction Info @long-running Scenario: Get Transaction Info Given I have a seed node NODE - # TODO: This test takes an hour if only one base node is used And I have a SHA3 miner MINER connected to all seed nodes And I have wallet WALLET_A connected to all seed nodes And I have wallet WALLET_B connected to all seed nodes diff --git a/integration_tests/features/WalletCli.feature b/integration_tests/features/WalletCli.feature index bdbd501980..0978bb96c6 100644 --- a/integration_tests/features/WalletCli.feature +++ b/integration_tests/features/WalletCli.feature @@ -76,7 +76,7 @@ Feature: Wallet CLI And I have wallet RECEIVER connected to base node BASE And I have mining node MINE connected to base node BASE and wallet SENDER And mining node MINE mines 15 blocks - Then wallets SENDER should have 12 spendable coinbase outputs + Then wallets SENDER should have EXACTLY 12 spendable coinbase outputs # TODO: Remove this wait when the wallet CLI commands involving transactions will only commence with a valid # TODO: base node connection. And I wait 30 seconds @@ -123,6 +123,7 @@ Feature: Wallet CLI Then I wait for wallet WALLET to have at least 1000000 uT And I export the utxos of wallet WALLET via command line + @flaky Scenario: As a user I want to discover-peer via command line Given I have a seed node SEED And I have a base node BASE1 connected to seed SEED diff --git a/integration_tests/features/WalletFFI.feature b/integration_tests/features/WalletFFI.feature index 6b5ee539d0..43fd2b0698 100644 --- a/integration_tests/features/WalletFFI.feature +++ b/integration_tests/features/WalletFFI.feature @@ -89,7 +89,12 @@ Feature: Wallet FFI Then I wait for ffi wallet FFI_WALLET to have at least 1000000 uT And I send 1000000 uT from ffi wallet FFI_WALLET to wallet RECEIVER at fee 20 Then ffi wallet FFI_WALLET detects AT_LEAST 2 ffi transactions to be Broadcast - And mining node MINER mines 10 blocks + # The broadcast check does not include delivery; create some holding points to ensure it was received + And mining node MINER mines 2 blocks + Then all nodes are at height 22 + And mining node MINER mines 2 blocks + Then all nodes are at height 24 + And mining node MINER mines 6 blocks Then I wait for wallet RECEIVER to have at least 1000000 uT And I have 1 received and 1 send transaction in ffi wallet FFI_WALLET And I start TXO validation on ffi wallet FFI_WALLET diff --git a/integration_tests/features/WalletMonitoring.feature b/integration_tests/features/WalletMonitoring.feature index 75e3c017df..b22e3eab0a 100644 --- a/integration_tests/features/WalletMonitoring.feature +++ b/integration_tests/features/WalletMonitoring.feature @@ -2,7 +2,7 @@ Feature: Wallet Monitoring -@flaky + @flaky Scenario: Wallets monitoring coinbase after a reorg # # Chain 1: @@ -61,17 +61,18 @@ Feature: Wallet Monitoring And I have wallet WALLET_A1 connected to seed node SEED_A And I have wallet WALLET_A2 connected to seed node SEED_A And I have mining node MINING_A connected to base node SEED_A and wallet WALLET_A1 - And mining node MINING_A mines 10 blocks + When mining node MINING_A mines 10 blocks with min difficulty 20 and max difficulty 9999999999 Then node SEED_A is at height 10 Then node NODE_A1 is at height 10 - Then wallet WALLET_A1 detects at least 7 coinbase transactions as Mined_Confirmed + Then wallet WALLET_A1 detects exactly 7 coinbase transactions as Mined_Confirmed # Use 7 of the 10 coinbase UTXOs in transactions (others require 3 confirmations) And I multi-send 7 transactions of 1000000 uT from wallet WALLET_A1 to wallet WALLET_A2 at fee 100 - When I mine 100 blocks on SEED_A - Then node SEED_A is at height 110 - Then node NODE_A1 is at height 110 + When mining node MINING_A mines 10 blocks with min difficulty 20 and max difficulty 9999999999 + Then node SEED_A is at height 20 + Then node NODE_A1 is at height 20 Then wallet WALLET_A2 detects all transactions as Mined_Confirmed Then all NORMAL transactions for wallet WALLET_A1 are valid + Then wallet WALLET_A1 detects exactly 17 coinbase transactions as Mined_Confirmed # # Chain 2: # Collects 10 coinbases into one wallet, send 7 transactions @@ -82,25 +83,28 @@ Feature: Wallet Monitoring And I have wallet WALLET_B1 connected to seed node SEED_B And I have wallet WALLET_B2 connected to seed node SEED_B And I have mining node MINING_B connected to base node SEED_B and wallet WALLET_B1 - And mining node MINING_B mines 10 blocks + When mining node MINING_B mines 10 blocks with min difficulty 1 and max difficulty 2 Then node SEED_B is at height 10 Then node NODE_B1 is at height 10 - Then wallet WALLET_B1 detects at least 7 coinbase transactions as Mined_Confirmed + Then wallet WALLET_B1 detects exactly 7 coinbase transactions as Mined_Confirmed # Use 7 of the 10 coinbase UTXOs in transactions (others require 3 confirmations) And I multi-send 7 transactions of 1000000 uT from wallet WALLET_B1 to wallet WALLET_B2 at fee 100 - When I mine 100 blocks on SEED_B - Then node SEED_B is at height 110 - Then node NODE_B1 is at height 110 + When mining node MINING_B mines 10 blocks with min difficulty 1 and max difficulty 2 + Then node SEED_B is at height 20 + Then node NODE_B1 is at height 20 Then wallet WALLET_B2 detects all transactions as Mined_Confirmed Then all NORMAL transactions for wallet WALLET_B1 are valid + Then wallet WALLET_B1 detects exactly 17 coinbase transactions as Mined_Confirmed # # Connect Chain 1 and 2 # And I have a SHA3 miner NODE_C connected to all seed nodes - Then all nodes are at height 110 + Then all nodes are at height 20 # When tip advances past required confirmations, invalid coinbases still being monitored will be cancelled. And mining node NODE_C mines 6 blocks - Then all nodes are at height 116 + Then all nodes are at height 26 + Then wallet WALLET_A1 detects exactly 20 coinbase transactions as Mined_Confirmed + Then wallet WALLET_B1 detects exactly 17 coinbase transactions as Mined_Confirmed And I list all NORMAL transactions for wallet WALLET_A1 And I list all NORMAL transactions for wallet WALLET_B1 # TODO: Uncomment this step when wallets can handle reorg @@ -124,22 +128,22 @@ Feature: Wallet Monitoring And I have mining node MINER2 connected to base node NODE2 and wallet WALLET2 When I co-mine blocks via merge mining proxy PROXY1 and mining node MINER2 - Then all nodes are on the same chain at height + Then all nodes are on the same chain tip And mining node MINER_SEED_A mines 5 blocks - Then all nodes are on the same chain at height + Then all nodes are on the same chain tip When I wait 1 seconds - Then wallets WALLET1,WALLET2 should have spendable coinbase outputs + Then wallets WALLET1,WALLET2 should have AT_LEAST spendable coinbase outputs @flaky Examples: - | numBlocks | endBlocks | - | 10 | 15 | + | numBlocks | + | 10 | - @long-running + @long-running @flaky Examples: - | numBlocks | endBlocks | - | 100 | 105 | - | 1000 | 1005 | - | 4500 | 4505 | + | numBlocks | + | 100 | + | 1000 | + | 4500 | diff --git a/integration_tests/features/WalletRoutingMechanism.feature b/integration_tests/features/WalletRoutingMechanism.feature index 8a824c5a1c..ee27a067c5 100644 --- a/integration_tests/features/WalletRoutingMechanism.feature +++ b/integration_tests/features/WalletRoutingMechanism.feature @@ -8,9 +8,8 @@ Scenario Outline: Wallets transacting via specified routing mechanism only And I have non-default wallet WALLET_A connected to all seed nodes using And I have mining node MINER connected to base node NODE and wallet WALLET_A And I have non-default wallets connected to all seed nodes using - And I have a merge mining proxy PROXY connected to NODE and WALLET_A with default config # We need to ensure the coinbase lock heights are gone and we have enough individual UTXOs; mine enough blocks - When I merge mine 20 blocks via PROXY + And mining node MINER mines 20 blocks Then all nodes are at height 20 # TODO: This wait is needed to stop base nodes from shutting down When I wait 1 seconds diff --git a/integration_tests/features/support/steps.js b/integration_tests/features/support/steps.js index b097dfdb31..31bbe9b822 100644 --- a/integration_tests/features/support/steps.js +++ b/integration_tests/features/support/steps.js @@ -28,11 +28,11 @@ const AUTOUPDATE_HASHES_TXT_SIG_URL = const AUTOUPDATE_HASHES_TXT_BAD_SIG_URL = "https://raw.githubusercontent.com/tari-project/tari/development/meta/hashes.txt.bad.sig"; -Given(/I have a seed node (.*)/, { timeout: 30 * 1000 }, async function (name) { +Given(/I have a seed node (.*)/, { timeout: 20 * 1000 }, async function (name) { return await this.createSeedNode(name); }); -Given("I have {int} seed nodes", { timeout: 30 * 1000 }, async function (n) { +Given("I have {int} seed nodes", { timeout: 20 * 1000 }, async function (n) { const promises = []; for (let i = 0; i < n; i++) { promises.push(this.createSeedNode(`SeedNode${i}`)); @@ -46,7 +46,7 @@ Then(/all transactions must have succeeded/, function () { Given( /I have a base node (.*) connected to all seed nodes/, - { timeout: 30 * 1000 }, + { timeout: 20 * 1000 }, async function (name) { await this.createAndAddNode(name, this.seedAddresses()); } @@ -54,7 +54,7 @@ Given( Given( /I have a base node (.*) connected to seed (.*)/, - { timeout: 30 * 1000 }, + { timeout: 20 * 1000 }, async function (name, seedNode) { await this.createAndAddNode(name, this.seeds[seedNode].peerAddress()); } @@ -62,7 +62,7 @@ Given( Given( /I have a base node (.*) connected to nodes (.*)/, - { timeout: 30 * 1000 }, + { timeout: 20 * 1000 }, async function (name, nodes) { const addresses = []; nodes = nodes.split(","); @@ -75,7 +75,7 @@ Given( Given( /I have a node (.*) with auto update enabled/, - { timeout: 30 * 1000 }, + { timeout: 20 * 1000 }, async function (name) { const node = await this.createNode(name, { common: { @@ -95,7 +95,7 @@ Given( Given( /I have a node (.*) with auto update configured with a bad signature/, - { timeout: 30 * 1000 }, + { timeout: 20 * 1000 }, async function (name) { const node = await this.createNode(name, { common: { @@ -151,7 +151,7 @@ Given( Given( /I have a base node (.*) connected to node (.*)/, - { timeout: 10 * 1000 }, + { timeout: 20 * 1000 }, async function (name, node) { await this.createAndAddNode(name, this.nodes[node].peerAddress()); } @@ -159,7 +159,7 @@ Given( Given( /I have a base node (\S+)$/, - { timeout: 10 * 1000 }, + { timeout: 20 * 1000 }, async function (name) { await this.createAndAddNode(name); } @@ -167,7 +167,7 @@ Given( Given( /I have a SHA3 miner (.*) connected to seed node (.*)/, - { timeout: 10 * 1000 }, + { timeout: 20 * 1000 }, async function (name, seed) { // add the base_node await this.createAndAddNode(name, this.seeds[seed].peerAddress(), this); @@ -191,7 +191,7 @@ Given( Given( /I have a SHA3 miner (.*) connected to node (.*)/, - { timeout: 10 * 1000 }, + { timeout: 20 * 1000 }, async function (name, basenode) { // add the base_node await this.createAndAddNode(name, this.nodes[basenode].peerAddress(), this); @@ -215,7 +215,7 @@ Given( Given( /I have a SHA3 miner (.*) connected to all seed nodes/, - { timeout: 10 * 1000 }, + { timeout: 20 * 1000 }, async function (name) { // add the base_node await this.createAndAddNode(name, this.seedAddresses(), this); @@ -239,7 +239,7 @@ Given( Given( /I connect node (.*) to node (.*)/, - { timeout: 40 * 1000 }, + { timeout: 20 * 1000 }, async function (nodeNameA, nodeNameB) { console.log( "Connecting (add new peer seed, shut down, then start up)", @@ -252,15 +252,6 @@ Given( nodeA.setPeerSeeds([nodeB.peerAddress()]); await this.stopNode(nodeNameA); await this.startNode(nodeNameA); - await waitFor( - async () => { - let node_a_result = (await nodeA.get_node_state()) === "LISTENING"; - let node_b_result = (await nodeB.get_node_state()) === "LISTENING"; - return node_a_result && node_b_result; - }, - true, - 30 * 1000 - ); } ); @@ -316,6 +307,7 @@ Given( Given( /I have stress-test wallet (.*) connected to the seed node (.*) with broadcast monitoring timeout (.*)/, + { timeout: 20 * 1000 }, async function (walletName, seedName, timeout) { const wallet = new WalletProcess( walletName, @@ -353,6 +345,7 @@ Given( Given( /I have wallet (.*) connected to seed node (.*)/, + { timeout: 20 * 1000 }, async function (walletName, seedName) { await this.createAndAddWallet( walletName, @@ -363,6 +356,7 @@ Given( Given( /I have wallet (.*) connected to base node (.*)/, + { timeout: 20 * 1000 }, async function (walletName, nodeName) { await this.createAndAddWallet( walletName, @@ -371,9 +365,13 @@ Given( } ); -Given(/I have wallet (.*) connected to all seed nodes/, async function (name) { - await this.createAndAddWallet(name, this.seedAddresses()); -}); +Given( + /I have wallet (.*) connected to all seed nodes/, + { timeout: 20 * 1000 }, + async function (name) { + await this.createAndAddWallet(name, this.seedAddresses()); + } +); Given( /I have non-default wallet (.*) connected to all seed nodes using (.*)/, @@ -416,6 +414,7 @@ Given( Given( /I recover wallet (.*) into wallet (.*) connected to all seed nodes/, + { timeout: 30 * 1000 }, async function (walletNameA, walletNameB) { const seedWords = this.getWallet(walletNameA).getSeedWords(); console.log( @@ -444,6 +443,7 @@ Given( Given( /I recover wallet (.*) into (\d+) wallets connected to all seed nodes/, + { timeout: 30 * 1000 }, async function (walletNameA, numwallets) { const seedWords = this.getWallet(walletNameA).getSeedWords(); for (let i = 1; i <= numwallets; i++) { @@ -474,6 +474,7 @@ Given( Then( /I wait for (\d+) wallets to have at least (\d+) uT/, + { timeout: 60 * 1000 }, async function (numwallets, amount) { for (let i = 1; i <= numwallets; i++) { const walletClient = await this.getWallet(i.toString()).connectClient(); @@ -485,7 +486,7 @@ Then( await waitFor( async () => walletClient.isBalanceAtLeast(amount), true, - 700 * 1000, + 20 * 1000, 5 * 1000, 5 ); @@ -500,6 +501,7 @@ Then( Then( /Wallet (.*) and (\d+) wallets have the same balance/, + { timeout: 120 * 1000 }, async function (wallet, numwallets) { const walletClient = await this.getWallet(wallet).connectClient(); let balance = await walletClient.getBalance(); @@ -799,7 +801,7 @@ Then("Proxy response for block header by hash is valid", function () { assert(lastResult.result.status, "OK"); }); -When(/I start base node (.*)/, { timeout: 6 * 1000 }, async function (name) { +When(/I start base node (.*)/, { timeout: 20 * 1000 }, async function (name) { await this.startNode(name); }); @@ -835,21 +837,30 @@ Then( } ); -Then(/node (.*) has a pruned height of (\d+)/, async function (name, height) { - const client = this.getClient(name); - await waitFor(async () => await client.getPrunedHeight(), height, 115 * 1000); - const currentHeight = await client.getPrunedHeight(); - console.log( - `Node ${name} has a pruned height: ${currentHeight} (should be`, - height, - `)` - ); - expect(currentHeight).to.equal(height); -}); +Then( + /node (.*) has a pruned height of (\d+)/, + { timeout: 600 * 1000 }, + async function (name, height) { + const client = this.getClient(name); + await waitFor( + async () => await client.getPrunedHeight(), + height, + 1000, + height * 5 * 1000 // 5 seconds per block + ); + const currentHeight = await client.getPrunedHeight(); + console.log( + `Node ${name} has a pruned height: ${currentHeight} (should be`, + height, + `)` + ); + expect(currentHeight).to.equal(height); + } +); Then( /node (.*) is at the same height as node (.*)/, - { timeout: 20 * 1000 }, + { timeout: 120 * 1000 }, async function (nodeA, nodeB) { var expectedHeight, currentHeight; expectedHeight = parseInt(await this.getClient(nodeB).getTipHeight()); @@ -1000,7 +1011,7 @@ Then(/node (.*) is in state (.*)/, async function (node, state) { Then( /(.*) does not have a new software update/, - { timeout: 1200 * 1000 }, + { timeout: 65 * 1000 }, async function (name) { let client = await this.getNodeOrWalletClient(name); await sleep(5000); @@ -1018,7 +1029,7 @@ Then( Then( /(.+) has a new software update/, - { timeout: 1200 * 1000 }, + { timeout: 65 * 1000 }, async function (name) { let client = await this.getNodeOrWalletClient(name); await waitFor( @@ -1035,7 +1046,7 @@ Then( Then( /all nodes are at the same height as node (.*)/, - { timeout: 1200 * 1000 }, + { timeout: 120 * 1000 }, async function (nodeB) { let expectedHeight = parseInt(await this.getClient(nodeB).getTipHeight()); console.log("Wait for all nodes to reach height of", expectedHeight); @@ -1182,26 +1193,33 @@ When(/I spend outputs (.*) via (.*)/, async function (inputs, node) { expect(this.lastResult.result).to.equal("ACCEPTED"); }); -Then(/(.*) has (.*) in (.*) state/, async function (node, txn, pool) { - const client = this.getClient(node); - const sig = this.transactions[txn].body.kernels[0].excess_sig; - this.lastResult = await waitFor( - async () => { - let tx_result = await client.transactionStateResult(sig); - console.log(`Node ${node} response is: ${tx_result}, should be: ${pool}`); - return tx_result === pool; - }, - true, - // TODO: Does it make sense to fix this timeout? - 20 * 60 * 1000 - ); - expect(this.lastResult).to.equal(true); -}); +Then( + /(.*) has (.*) in (.*) state/, + { timeout: 6 * 60 * 1000 }, // Must cater for long running transaction state changes, e.g. UNKNOWN -> NOT_STORED + async function (node, txn, pool) { + const client = this.getClient(node); + const sig = this.transactions[txn].body.kernels[0].excess_sig; + this.lastResult = await waitFor( + async () => { + let tx_result = await client.transactionStateResult(sig); + console.log( + `Node ${node} response for ${txn} is: ${tx_result}, should be: ${pool}` + ); + return tx_result === pool; + }, + true, + 6 * 60 * 1000, + 5 * 1000 + ); + expect(this.lastResult).to.equal(true); + } +); // The number is rounded down. E.g. if 1% can fail out of 17, that is 16.83 have to succeed. // It's means at least 16 have to succeed. Then( /(.*) is in the (.*) of all nodes(, where (\d+)% can fail)?/, + { timeout: 120 * 1000 }, async function (txn, pool, canFail) { const sig = this.transactions[txn].body.kernels[0].excess_sig; await this.forEachClientAsync( @@ -1209,7 +1227,7 @@ Then( await waitFor( async () => await client.transactionStateResult(sig), pool, - 20 * 60 * 1000 + 115 * 1000 ); this.lastResult = await client.transactionState(sig); console.log(`Node ${name} response is: ${this.lastResult.result}`); @@ -1276,6 +1294,7 @@ When( When( /I mine (\d+) custom weight blocks on (.*) with weight (\d+)/, + { timeout: 1200 * 1000 }, // Must allow many blocks to be mined; time out below limits each block to be mined async function (numBlocks, name, weight) { const tipHeight = await this.getClient(name).getTipHeight(); for (let i = 0; i < numBlocks; i++) { @@ -1286,7 +1305,7 @@ When( expect(autoTransactionResult).to.equal(true); // If a block cannot be mined quickly enough (or the process has frozen), timeout. await withTimeout( - 2 * 60 * 1000, + 5 * 1000, this.mineBlock(name, parseInt(weight), (candidate) => { this.addTransactionOutput( tipHeight + i + 1 + 2, @@ -1301,7 +1320,7 @@ When( When( /mining node (.*) mines (\d+) blocks with min difficulty (\d+) and max difficulty (\d+)/, - { timeout: 80 * 1000 }, + { timeout: 1200 * 1000 }, // Must allow many blocks to be mined; dynamic time out below limits actual time async function (miner, numBlocks, min, max) { const miningNode = this.getMiningNode(miner); await miningNode.init( @@ -1312,18 +1331,24 @@ When( miningNode.mineOnTipOnly, null ); - await miningNode.startNew(); + await withTimeout( + (10 + parseInt(numBlocks) * 1) * 1000, + await miningNode.startNew() + ); } ); When( /mining node (.*) mines (\d+) blocks$/, - { timeout: 20 * 1000 }, + { timeout: 1200 * 1000 }, // Must allow many blocks to be mined; dynamic time out below limits actual time async function (miner, numBlocks) { const miningNode = this.getMiningNode(miner); // Don't wait for sync before mining await miningNode.init(numBlocks, null, 1, 100000, false, null); - await miningNode.startNew(); + await withTimeout( + (10 + parseInt(numBlocks) * 1) * 1000, + await miningNode.startNew() + ); } ); @@ -1336,7 +1361,7 @@ When( When( /I mine (\d+) blocks on (.*)/, - { timeout: 40 * 1000 }, + { timeout: 1200 * 1000 }, // Must allow many blocks to be mined; time out below limits each block to be mined async function (numBlocks, name) { const tipHeight = await this.getClient(name).getTipHeight(); for (let i = 0; i < numBlocks; i++) { @@ -1346,7 +1371,7 @@ When( ); expect(autoTransactionResult).to.equal(true); await withTimeout( - 60 * 1000, + 5 * 1000, this.mineBlock(name, 0, (candidate) => { this.addTransactionOutput( tipHeight + i + 1 + 2, @@ -1361,7 +1386,7 @@ When( When( /I mine (\d+) blocks using wallet (.*) on (.*)/, - { timeout: 600 * 1000 }, + { timeout: 1200 * 1000 }, // Must allow many blocks to be mined; time out below limits each block to be mined async function (numBlocks, walletName, nodeName) { const nodeClient = this.getClient(nodeName); const walletClient = await this.getWallet(walletName).connectClient(); @@ -1372,64 +1397,32 @@ When( tipHeight + 1 + i ); expect(autoTransactionResult).to.equal(true); - await nodeClient.mineBlock(walletClient); + await withTimeout(5 * 1000, await nodeClient.mineBlock(walletClient)); } } ); -When(/I merge mine (.*) blocks via (.*)/, async function (numBlocks, mmProxy) { - for (let i = 0; i < numBlocks; i++) { - await this.mergeMineBlock(mmProxy); - } -}); - -// TODO: This step is still really flaky, rather use the co-mine with mining node step: -// Error: 13 INTERNAL: -// 'Chain storage error: The requested BlockAccumulatedData was not found via -// header_hash:55545... in the database' When( - /I co-mine (.*) blocks via merge mining proxy (.*) and base node (.*) with wallet (.*)/, - { timeout: 20 * 1000 }, - async function (numBlocks, mmProxy, node, wallet) { - let tipHeight = await this.getClient(node).getTipHeight(); - this.lastResult = tipHeight; - const baseNodeMiningPromise = - await this.baseNodeMineBlocksUntilHeightIncreasedBy( - node, - wallet, - numBlocks - ); - const mergeMiningPromise = this.mergeMineBlocksUntilHeightIncreasedBy( - mmProxy, - numBlocks - ); - await Promise.all([baseNodeMiningPromise, mergeMiningPromise]).then( - ([res1, res2]) => { - tipHeight = Math.max(res1, res2); - this.lastResult = tipHeight - this.lastResult; - console.log( - "Co-mining", - numBlocks, - "blocks concluded, tip at", - tipHeight - ); - } - ); + /I merge mine (.*) blocks via (.*)/, + { timeout: 1200 * 1000 }, // Must allow many blocks to be mined; time out below limits each block to be mined + async function (numBlocks, mmProxy) { + for (let i = 0; i < numBlocks; i++) { + await withTimeout(5 * 1000, await this.mergeMineBlock(mmProxy)); + } } ); When( /I co-mine (.*) blocks via merge mining proxy (.*) and mining node (.*)/, - { timeout: 6000 * 1000 }, + { timeout: 15000 * 1000 }, // Must allow many blocks to be mined; dynamic time out below limits actual time async function (numBlocks, mmProxy, miner) { - const sha3MiningPromise = this.sha3MineBlocksUntilHeightIncreasedBy( - miner, - numBlocks, - 105 + const sha3MiningPromise = withTimeout( + parseInt(numBlocks) * 4 * 1000, + this.sha3MineBlocksUntilHeightIncreasedBy(miner, numBlocks, 120, true) ); - const mergeMiningPromise = this.mergeMineBlocksUntilHeightIncreasedBy( - mmProxy, - numBlocks + const mergeMiningPromise = withTimeout( + parseInt(numBlocks) * 4 * 1000, + this.mergeMineBlocksUntilHeightIncreasedBy(mmProxy, numBlocks) ); await Promise.all([sha3MiningPromise, mergeMiningPromise]).then( ([res1, res2]) => { @@ -1571,7 +1564,7 @@ When("I print the world", function () { Then( /I wait for wallet (.*) to have at least (.*) uT/, - { timeout: 40 * 1000 }, + { timeout: 120 * 1000 }, async function (wallet, amount) { const walletClient = await this.getWallet(wallet).connectClient(); console.log("\n"); @@ -1582,7 +1575,7 @@ Then( await waitFor( async () => walletClient.isBalanceAtLeast(amount), true, - 700 * 1000, + 115 * 1000, 5 * 1000, 5 ); @@ -1596,7 +1589,7 @@ Then( Then( /I wait for wallet (.*) to have less than (.*) uT/, - { timeout: 6 * 1000 }, + { timeout: 120 * 1000 }, async function (wallet, amount) { let walletClient = await this.getWallet(wallet).connectClient(); console.log("\n"); @@ -1607,7 +1600,7 @@ Then( await waitFor( async () => walletClient.isBalanceLessThan(amount), true, - 700 * 1000, + 115 * 1000, 5 * 1000, 5 ); @@ -1621,6 +1614,7 @@ Then( Then( /wallet (.*) and wallet (.*) have the same balance/, + { timeout: 120 * 1000 }, async function (walletNameA, walletNameB) { const walletClientA = await this.getWallet(walletNameA).connectClient(); var balanceA = await walletClientA.getBalance(); @@ -1737,7 +1731,7 @@ async function send_tari( When( /I send (.*) uT from wallet (.*) to wallet (.*) at fee (.*)/, - { timeout: 60 * 1000 }, + { timeout: 120 * 1000 }, async function (tariAmount, source, dest, feePerGram) { const sourceWallet = this.getWallet(source); const sourceClient = await sourceWallet.connectClient(); @@ -1788,7 +1782,7 @@ When( When( /I send(.*) uT without waiting for broadcast from wallet (.*) to wallet (.*) at fee (.*)/, - { timeout: 40 * 1000 }, + { timeout: 20 * 1000 }, async function (tariAmount, source, dest, feePerGram) { const sourceWallet = this.getWallet(source); const sourceClient = await sourceWallet.connectClient(); @@ -1824,7 +1818,7 @@ When( When( /I multi-send (.*) transactions of (.*) uT from wallet (.*) to wallet (.*) at fee (.*)/, - { timeout: 10 * 1000 }, + { timeout: 120 * 1000 }, async function (number, tariAmount, source, dest, fee) { console.log("\n"); const sourceClient = await this.getWallet(source).connectClient(); @@ -2022,7 +2016,7 @@ When( When( /I transfer (.*) uT to self from wallet (.*) at fee (.*)/, - { timeout: 7 * 1000 }, + { timeout: 120 * 1000 }, async function (tariAmount, source, feePerGram) { const sourceClient = await this.getWallet(source).connectClient(); const sourceInfo = await sourceClient.identify(); @@ -2066,6 +2060,7 @@ When( When( /I transfer (.*) uT from (.*) to ([A-Za-z0-9,]+) at fee (.*)/, + { timeout: 120 * 1000 }, async function (amount, source, dests, feePerGram) { const wallet = this.getWallet(source); const client = await wallet.connectClient(); @@ -2104,7 +2099,7 @@ When( When( /I send a one-sided transaction of (.*) uT from (.*) to (.*) at fee (.*)/, - { timeout: 8 * 1000 }, + { timeout: 65 * 1000 }, async function (amount, source, dest, feePerGram) { const sourceWallet = this.getWallet(source); const sourceClient = await sourceWallet.connectClient(); @@ -2147,7 +2142,7 @@ When( When( /I cancel last transaction in wallet (.*)/, - { timeout: 25 * 5 * 1000 }, + { timeout: 20 * 1000 }, async function (walletName) { const wallet = this.getWallet(walletName); const walletClient = await wallet.connectClient(); @@ -2230,7 +2225,7 @@ Then( Then( /wallet (.*) detects all transactions are at least Pending/, - { timeout: 3800 * 1000 }, + { timeout: 1200 * 1000 }, // Must allow for many transactions; dynamic time out used below async function (walletName) { // Note: This initial step can take a long time if network conditions are not favourable // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed @@ -2265,7 +2260,7 @@ Then( await waitFor( async () => await walletClient.isTransactionAtLeastPending(txIds[i]), true, - 3700 * 1000, + (60 + txIds.length * 1) * 1000, 5 * 1000, 5 ); @@ -2279,7 +2274,7 @@ Then( Then( /all wallets detect all transactions are at least Pending/, - { timeout: 3800 * 1000 }, + { timeout: 1200 * 1000 }, // Must allow for many transactions; dynamic time out used below async function () { // Note: This initial step to register pending can take a long time if network conditions are not favourable // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed @@ -2315,7 +2310,7 @@ Then( await waitFor( async () => walletClient.isTransactionAtLeastPending(txIds[i]), true, - 3700 * 1000, + (60 + txIds.length * 1) * 1000, 5 * 1000, 5 ); @@ -2329,7 +2324,7 @@ Then( Then( /wallet (.*) detects last transaction is Pending/, - { timeout: 3800 * 1000 }, + { timeout: 120 * 1000 }, async function (walletName) { const wallet = this.getWallet(walletName); const walletClient = await wallet.connectClient(); @@ -2345,7 +2340,7 @@ Then( await waitFor( async () => walletClient.isTransactionPending(lastTxId), true, - 3700 * 1000, + 115 * 1000, 5 * 1000, 5 ); @@ -2359,7 +2354,7 @@ Then( Then( /wallet (.*) detects all transactions are at least Completed/, - { timeout: 1200 * 1000 }, + { timeout: 1200 * 1000 }, // Must allow for many transactions; dynamic time out used below async function (walletName) { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed const wallet = this.getWallet(walletName); @@ -2394,7 +2389,7 @@ Then( await waitFor( async () => walletClient.isTransactionAtLeastCompleted(txIds[i]), true, - 600 * 1000, + (60 + txIds.length * 1) * 1000, 5 * 1000, 5 ); @@ -2407,7 +2402,7 @@ Then( Then( /all wallets detect all transactions are at least Completed/, - { timeout: 1200 * 1000 }, + { timeout: 1200 * 1000 }, // Must allow for many transactions; dynamic time out used below async function () { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed for (const walletName in this.wallets) { @@ -2443,7 +2438,7 @@ Then( await waitFor( async () => walletClient.isTransactionAtLeastCompleted(txIds[i]), true, - 1100 * 1000, + (60 + txIds.length * 1) * 1000, 5 * 1000, 5 ); @@ -2457,7 +2452,7 @@ Then( Then( /wallet (.*) detects all transactions are at least Broadcast/, - { timeout: 150 * 1000 }, + { timeout: 1200 * 1000 }, // Must allow for many transactions; dynamic time out used below async function (walletName) { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed const wallet = this.getWallet(walletName); @@ -2493,7 +2488,7 @@ Then( await waitFor( async () => walletClient.isTransactionAtLeastBroadcast(txIds[i]), true, - 600 * 1000, + (60 + txIds.length * 1) * 1000, 5 * 1000, 5 ); @@ -2506,7 +2501,7 @@ Then( Then( /all wallets detect all transactions are at least Broadcast/, - { timeout: 1200 * 1000 }, + { timeout: 1200 * 1000 }, // Must allow for many transactions; dynamic time out used below async function () { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed for (const walletName in this.wallets) { @@ -2542,7 +2537,7 @@ Then( await waitFor( async () => walletClient.isTransactionAtLeastBroadcast(txIds[i]), true, - 1100 * 1000, + (60 + txIds.length * 1) * 1000, 5 * 1000, 5 ); @@ -2556,7 +2551,7 @@ Then( Then( /wallet (.*) detects all transactions are at least Mined_Unconfirmed/, - { timeout: 1200 * 1000 }, + { timeout: 1200 * 1000 }, // Must allow for many transactions; dynamic time out used below async function (walletName) { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed const wallet = this.getWallet(walletName); @@ -2590,7 +2585,7 @@ Then( await waitFor( async () => walletClient.isTransactionAtLeastMinedUnconfirmed(txIds[i]), true, - 600 * 1000, + (60 + txIds.length * 1) * 1000, 5 * 1000, 5 ); @@ -2603,7 +2598,7 @@ Then( Then( /all wallets detect all transactions are at least Mined_Unconfirmed/, - { timeout: 1200 * 1000 }, + { timeout: 1200 * 1000 }, // Must allow for many transactions; dynamic time out used below async function () { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed for (const walletName in this.wallets) { @@ -2638,7 +2633,7 @@ Then( async () => walletClient.isTransactionAtLeastMinedUnconfirmed(txIds[i]), true, - 1100 * 1000, + (60 + txIds.length * 1) * 1000, 5 * 1000, 5 ); @@ -2652,7 +2647,7 @@ Then( Then( /wallet (.*) detects all transactions as Mined_Unconfirmed/, - { timeout: 1200 * 1000 }, + { timeout: 1200 * 1000 }, // Must allow for many transactions; dynamic time out used below async function (walletName) { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed const wallet = this.getWallet(walletName); @@ -2686,7 +2681,7 @@ Then( await waitFor( async () => walletClient.isTransactionMinedUnconfirmed(txIds[i]), true, - 600 * 1000, + (60 + txIds.length * 1) * 1000, 5 * 1000, 5 ); @@ -2699,7 +2694,7 @@ Then( Then( /all wallets detect all transactions as Mined_Unconfirmed/, - { timeout: 1200 * 1000 }, + { timeout: 1200 * 1000 }, // Must allow for many transactions; dynamic time out used below async function () { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed for (const walletName in this.wallets) { @@ -2734,7 +2729,7 @@ Then( await waitFor( async () => walletClient.isTransactionMinedUnconfirmed(txIds[i]), true, - 1100 * 1000, + (60 + txIds.length * 1) * 1000, 5 * 1000, 5 ); @@ -2748,7 +2743,7 @@ Then( Then( /wallet (.*) detects all transactions as Mined_Confirmed/, - { timeout: 30 * 1000 }, + { timeout: 1200 * 1000 }, // Must allow for many transactions; dynamic time out used below async function (walletName) { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed const wallet = this.getWallet(walletName); @@ -2782,7 +2777,7 @@ Then( await waitFor( async () => walletClient.isTransactionMinedConfirmed(txIds[i]), true, - 600 * 1000, + (60 + txIds.length * 1) * 1000, 5 * 1000, 5 ); @@ -2795,6 +2790,7 @@ Then( Then( /while mining via node (.*) all transactions in wallet (.*) are found to be Mined_Confirmed/, + { timeout: 1200 * 1000 }, // Must allow for many transactions; dynamic time out used below async function (nodeName, walletName) { const wallet = this.getWallet(walletName); const walletClient = await wallet.connectClient(); @@ -2840,7 +2836,7 @@ Then( } }, true, - 600 * 1000, + (60 + txIds.length * 1) * 1000, 5 * 1000, 5 ); @@ -2853,7 +2849,7 @@ Then( Then( /while mining via SHA3 miner (.*) all transactions in wallet (.*) are found to be Mined_Confirmed/, - { timeout: 30 * 1000 }, + { timeout: 1200 * 1000 }, // Must allow for many transactions; dynamic time out used below async function (miner, walletName) { const wallet = this.getWallet(walletName); const walletClient = await wallet.connectClient(); @@ -2895,7 +2891,7 @@ Then( } }, true, - 600 * 1000, + (60 + txIds.length * 1) * 1000, 5 * 1000, 5 ); @@ -2908,7 +2904,7 @@ Then( Then( /all wallets detect all transactions as Mined_Confirmed/, - { timeout: 40 * 1000 }, + { timeout: 1200 * 1000 }, async function () { // Pending -> Completed -> Broadcast -> Mined Unconfirmed -> Mined Confirmed for (const walletName in this.wallets) { @@ -2943,7 +2939,7 @@ Then( await waitFor( async () => walletClient.isTransactionMinedConfirmed(txIds[i]), true, - 1100 * 1000, + (60 + txIds.length * 1) * 1000, 5 * 1000, 5 ); @@ -2992,26 +2988,47 @@ Then( Then( /wallet (.*) detects at least (.*) coinbase transactions as Mined_Confirmed/, - { timeout: 34 * 1000 }, + { timeout: 120 * 1000 }, async function (walletName, count) { const walletClient = await this.getWallet(walletName).connectClient(); await waitFor( async () => walletClient.areCoinbasesConfirmedAtLeast(count), true, - 600 * 1000, + 110 * 1000, 5 * 1000, 5 ); const transactions = await walletClient.getAllSpendableCoinbaseTransactions(); - expect(transactions.length >= count).to.equal(true); + expect(parseInt(transactions.length) >= parseInt(count)).to.equal(true); } ); Then( - /wallets ([A-Za-z0-9,]+) should have (.*) spendable coinbase outputs/, + /wallet (.*) detects exactly (.*) coinbase transactions as Mined_Confirmed/, + { timeout: 120 * 1000 }, + async function (walletName, count) { + const walletClient = await this.getWallet(walletName).connectClient(); + await waitFor( + async () => walletClient.areCoinbasesConfirmedAtLeast(count), + true, + 110 * 1000, + 5 * 1000, + 5 + ); + const transactions = + await walletClient.getAllSpendableCoinbaseTransactions(); + expect(parseInt(transactions.length) === parseInt(count)).to.equal(true); + } +); + +Then( + /wallets ([A-Za-z0-9,]+) should have (.*) (.*) spendable coinbase outputs/, { timeout: 610 * 1000 }, - async function (wallets, amountOfCoinBases) { + async function (wallets, comparison, amountOfCoinBases) { + const atLeast = "AT_LEAST"; + const exactly = "EXACTLY"; + expect(comparison === atLeast || comparison === exactly).to.equal(true); const walletClients = await Promise.all( wallets.split(",").map((wallet) => this.getWallet(wallet).connectClient()) ); @@ -3028,7 +3045,19 @@ Then( console.log(client.name, "count", count); spendableCoinbaseCount += count; } - return spendableCoinbaseCount.toString() === amountOfCoinBases; + if (comparison === atLeast) { + console.log( + spendableCoinbaseCount, + spendableCoinbaseCount >= parseInt(amountOfCoinBases) + ); + return spendableCoinbaseCount >= parseInt(amountOfCoinBases); + } else { + console.log( + spendableCoinbaseCount, + spendableCoinbaseCount === parseInt(amountOfCoinBases) + ); + return spendableCoinbaseCount === parseInt(amountOfCoinBases); + } }, true, 600 * 1000, @@ -3044,10 +3073,19 @@ Then( "with", spendableCoinbaseCount, "being valid and Mined_Confirmed, expected", + comparison, amountOfCoinBases, "\n" ); - expect(spendableCoinbaseCount.toString()).to.equal(amountOfCoinBases); + if (comparison === atLeast) { + expect(spendableCoinbaseCount >= parseInt(amountOfCoinBases)).to.equal( + true + ); + } else { + expect(spendableCoinbaseCount === parseInt(amountOfCoinBases)).to.equal( + true + ); + } } ); @@ -3203,7 +3241,7 @@ Then("difficulties are available", function () { When( /I coin split tari in wallet (.*) to produce (.*) UTXOs of (.*) uT each with fee_per_gram (.*) uT/, - { timeout: 7 * 1000 }, + { timeout: 4800 * 1000 }, async function (walletName, splitNum, splitValue, feePerGram) { console.log("\n"); const numberOfSplits = Math.ceil(splitNum / 499); @@ -3274,7 +3312,7 @@ When( When( /I send (.*) transactions of (.*) uT each from wallet (.*) to wallet (.*) at fee_per_gram (.*)/, - { timeout: 7 * 1000 }, + { timeout: 120 * 1000 }, async function ( numTransactions, amount, @@ -3548,6 +3586,7 @@ When( When( "I discover peer {word} on wallet {word} via command line", + { timeout: 120 * 1000 }, // Ample time should be allowed for peer discovery async function (node, name) { let wallet = this.getWallet(name); let peer = this.getNode(node).peerAddress().split("::")[0]; @@ -3559,7 +3598,7 @@ When( When( "I run whois {word} on wallet {word} via command line", - { timeout: 6 * 1000 }, + { timeout: 20 * 1000 }, async function (who, name) { await sleep(5000); let wallet = this.getWallet(name); @@ -3617,6 +3656,7 @@ When( Then( /I wait until base node (.*) has (.*) unconfirmed transactions in its mempool/, + { timeout: 120 * 1000 }, async function (baseNode, numTransactions) { const client = this.getClient(baseNode); await waitFor( @@ -3625,7 +3665,7 @@ Then( return stats.unconfirmed_txs; }, numTransactions, - 120 * 1000 + 115 * 1000 ); let stats = await client.getMempoolStats(); @@ -3678,7 +3718,7 @@ Then( When( "I have {int} base nodes with pruning horizon {int} force syncing on node {word}", - { timeout: 7 * 1000 }, + { timeout: 20 * 1000 }, async function (nodes_count, horizon, force_sync_to) { const promises = []; const force_sync_address = this.getNode(force_sync_to).peerAddress(); diff --git a/integration_tests/features/support/world.js b/integration_tests/features/support/world.js index 32e5ca6618..7a81b62154 100644 --- a/integration_tests/features/support/world.js +++ b/integration_tests/features/support/world.js @@ -160,6 +160,7 @@ class CustomWorld { const txn = new TransactionBuilder(); txn.addInput(input); + txn.changeFee(1); const txOutput = txn.addOutput(txn.getSpendableAmount()); const completedTx = txn.build(); @@ -204,10 +205,16 @@ class CustomWorld { return promise; } - sha3MineBlocksUntilHeightIncreasedBy(miner, numBlocks, minDifficulty) { + sha3MineBlocksUntilHeightIncreasedBy( + miner, + numBlocks, + minDifficulty, + mineOnTipOnly + ) { const promise = this.getMiningNode(miner).mineBlocksUntilHeightIncreasedBy( numBlocks, - minDifficulty + minDifficulty, + mineOnTipOnly ); return promise; } @@ -346,11 +353,13 @@ class CustomWorld { async stopNode(name) { const node = this.seeds[name] || this.nodes[name]; await node.stop(); + console.log("\n", name, "stopped\n"); } async startNode(name, args) { const node = this.seeds[name] || this.nodes[name]; await node.start(args); + console.log("\n", name, "started\n"); } addTransaction(pubKey, txId) { diff --git a/integration_tests/helpers/config.js b/integration_tests/helpers/config.js index d0d13ce05c..624d488578 100644 --- a/integration_tests/helpers/config.js +++ b/integration_tests/helpers/config.js @@ -101,7 +101,7 @@ function baseEnvs(peerSeeds = [], forceSyncPeers = []) { TARI_MERGE_MINING_PROXY__LOCALNET__WAIT_FOR_INITIAL_SYNC_AT_STARTUP: false, TARI_MINING_NODE__NUM_MINING_THREADS: "1", TARI_MINING_NODE__MINE_ON_TIP_ONLY: true, - TARI_MINING_NODE__VALIDATE_TIP_TIMEOUT_SEC: 2, + TARI_MINING_NODE__VALIDATE_TIP_TIMEOUT_SEC: 1, TARI_WALLET__SCAN_FOR_UTXO_INTERVAL: 5, }; if (forceSyncPeers.length > 0) { diff --git a/integration_tests/helpers/miningNodeProcess.js b/integration_tests/helpers/miningNodeProcess.js index 7a09c98767..0dd6ec0055 100644 --- a/integration_tests/helpers/miningNodeProcess.js +++ b/integration_tests/helpers/miningNodeProcess.js @@ -169,10 +169,21 @@ class MiningNodeProcess { }); } - async mineBlocksUntilHeightIncreasedBy(numBlocks, minDifficulty) { + async mineBlocksUntilHeightIncreasedBy( + numBlocks, + minDifficulty, + mineOnTipOnly + ) { const height = parseInt(await this.baseNodeClient.getTipHeight()) + parseInt(numBlocks); - await this.init(numBlocks, height, minDifficulty, 9999999999, true, 1); + await this.init( + numBlocks, + height, + minDifficulty, + 9999999999, + mineOnTipOnly, + 1 + ); await this.startNew(); await this.stop(); const tipHeight = await this.baseNodeClient.getTipHeight();