From 5b4ff610c75a2dd3a549aea2adc6af8cedd9580e Mon Sep 17 00:00:00 2001 From: Federico Mastellone Date: Wed, 13 Nov 2024 20:28:43 +0000 Subject: [PATCH] retry --- nix/workbench/service/voting.nix | 158 ++++++++++++++++--------------- 1 file changed, 82 insertions(+), 76 deletions(-) diff --git a/nix/workbench/service/voting.nix b/nix/workbench/service/voting.nix index b28e0117dce..3b3a47b9598 100644 --- a/nix/workbench/service/voting.nix +++ b/nix/workbench/service/voting.nix @@ -82,20 +82,21 @@ let outs_per_transaction = 100; # 193 produced too many timeouts. # Sleeps. - # Used when splitting funds to wait for them to arrive, a pretty high number! - # Any UTxO is considered a success in this phase. - wait_any_utxo_tries = 24; - wait_any_utxo_sleep = 10; # 4 minutes in 10s steps. - # Used when sending funds if they need to be batched, it waits for the - # expected UTxO to arrive to the change-address. More than this is a failure! - wait_utxo_id_tries = 24; - wait_utxo_id_sleep = 10; # 4 minutes in 10s steps. + # Used when splitting funds to wait for funds to arrive, as this initial funds + # are sent from a different process (not genesis) this works as a flag! + wait_any_utxo_tries = 30; + wait_any_utxo_sleep = 10; # 5 minutes in 10s steps. + # Used when splitting funds, it waits for the expected UTxO to arrive to the + # change-address and re-submits the transaction if necessary! + funds_submit_tries = 3; + wait_utxo_id_tries = 18; + wait_utxo_id_sleep = 10; # 3 minutes in 10s steps. # Used when waiting for the recently created proposal. wait_proposal_id_tries = 30; wait_proposal_id_sleep = 10; # 5 minutes # Use to wait for all proposals to be available before we start voting. # As nodes will end their splitting phases at different times, this parameters - # works as a formation lap before race start =). + # work as a formation lap before race start =). wait_proposals_count_tries = 150; wait_proposals_count_sleep = 10; # 25 minutes in 10s steps. @@ -242,6 +243,63 @@ function get_address_utxo_expected_value { fi } +################################################################################ +# Function to submit the funds-splitting tx and retry if needed. +# Not to be run during the benchmarking phase: lots of queries! +################################################################################ +function funds_submit_retry { + + # Function arguments. + local node_str=$1 # node name / folder to find the socket to use. + local tx_signed=$2 # tx to send and maybe re-send. + local addr=$3 # Address to wait for (UTxO id must be cached). + + # Only defined in functions that use it. + local socket_path + socket_path="$(get_socket_path "''${node_str}")" + + local utxo_id + utxo_id="$(get_address_utxo_expected_id "''${node_str}" "''${addr}")" + + local contains_addr="false" + local submit_tries=${toString funds_submit_tries} + while test "''${contains_addr}" = "false" + do + if test "''${submit_tries}" -le 0 + then + # Time's up! + ${coreutils}/bin/echo "funds_submit_retry: Timeout waiting for: ''${addr} - ''${utxo_id}" + exit 1 + else + # (Re)Submit transaction ignoring errors. + ${cardano-cli}/bin/cardano-cli conway transaction submit \ + --testnet-magic ${toString testnetMagic} \ + --socket-path "''${socket_path}" \ + --tx-file "''${tx_signed}" \ + || true + submit_tries="$((submit_tries - 1))" + # Some loops to see if the expected UTxO of this address appears. + local utxo_tries=${toString wait_utxo_id_tries} + while test "''${contains_addr}" = "false" && test "''${utxo_tries}" -gt 0 + do + contains_addr="$( \ + ${cardano-cli}/bin/cardano-cli conway query utxo \ + --testnet-magic ${toString testnetMagic} \ + --socket-path "''${socket_path}" \ + --address "''${addr}" \ + --output-json \ + | ${jq}/bin/jq --raw-output \ + --argjson utxo_id "\"''${utxo_id}\"" \ + 'keys | any(. == $utxo_id) // false' \ + )" + ${coreutils}/bin/sleep ${toString wait_utxo_id_sleep} + utxo_tries="$((utxo_tries - 1))" + done + fi + done + +} + ################################################################################ # Evenly split the first UTxO of this key to the addresses in the array! # Does it in batchs so we don't exceed "maxTxSize" of 16384. @@ -347,17 +405,15 @@ function funds_from_to { fi else # Not the first batch. - # The input comes from the last transaction submitted. Wait for it!!! + # The input comes from the last transaction submitted. + # No need to wait for it because the submission function does this! tx_in="$(get_address_utxo_expected_id "''${node_str}" "''${funds_addr}")" - ${coreutils}/bin/echo "funds_from_to: Wait for funds: $(${coreutils}/bin/date --rfc-3339=seconds)" - wait_utxo_id "''${node_str}" "''${funds_addr}" "''${tx_in}" >/dev/null - ${coreutils}/bin/echo "funds_from_to: Funds available: $(${coreutils}/bin/date --rfc-3339=seconds)" # Treasury donation happens only once. treasury_donation_args_array=() fi # Some debugging! - ${coreutils}/bin/echo "funds_from_to: ''${utxo_vkey} (''${funds_addr}): --tx-in ''${tx_in}" # Remove from output ''${txOuts_args_array[*]} + ${coreutils}/bin/echo "funds_from_to: ''${utxo_vkey} (''${funds_addr}): --tx-in ''${tx_in}" # Send this batch to each node! # Build transaction. @@ -376,14 +432,10 @@ function funds_from_to { --signing-key-file "''${utxo_skey}" \ --tx-body-file "''${tx_filename}.raw" \ --out-file "''${tx_filename}.signed" - # Submit transaction. - ${cardano-cli}/bin/cardano-cli conway transaction submit \ - --testnet-magic ${toString testnetMagic} \ - --socket-path "''${socket_path}" \ - --tx-file "''${tx_filename}.signed" # Store outs/addresses next UTxO, including the change address. - # Without the change address we can't wait for the funds if a next batch! + # Without the change address we can't wait for the funds after submission + # or calculate the next input to use if an extra batch is needed! txOuts_addrs_array+=("''${funds_addr}") for addr_cache in "''${txOuts_addrs_array[@]}" do @@ -393,6 +445,12 @@ function funds_from_to { "''${addr_cache}" done + # Submit transaction and wait for settlement. + funds_submit_retry \ + "''${node_str}" \ + "''${tx_filename}.signed" \ + "''${funds_addr}" + # Reset variables for next batch iteration. txOuts_args_array=() txOuts_addrs_array=() batch="$((batch + ${toString outs_per_transaction}))" @@ -445,50 +503,6 @@ function wait_any_utxo { done } -################################################################################ -# Waits until an specific UTxO of this address appears (errors on timeout). -# Not to be run during the benchmarking phase: lots of queries! -################################################################################ -function wait_utxo_id { - - # Function arguments. - local node_str=$1 # node name / folder to find the socket to use. - local addr=$2 - local utxo_id=$3 - - # Only defined in functions that use it. - local socket_path - socket_path="$(get_socket_path "''${node_str}")" - - local contains_addr="false" - local tries=${toString wait_utxo_id_tries} - while test "''${contains_addr}" = "false" - do - if test "''${tries}" -le 0 - then - # Time's up! - ${coreutils}/bin/echo "wait_utxo_id: Timeout waiting for: ''${addr} - ''${utxo_id}" - exit 1 - else - contains_addr="$( \ - ${cardano-cli}/bin/cardano-cli conway query utxo \ - --testnet-magic ${toString testnetMagic} \ - --socket-path "''${socket_path}" \ - --address "''${addr}" \ - --output-json \ - | ${jq}/bin/jq --raw-output \ - --argjson utxo_id "\"''${utxo_id}\"" \ - 'keys | any(. == $utxo_id) // false' \ - )" - if ! test "''${tries}" = ${toString wait_utxo_id_tries} - then - ${coreutils}/bin/sleep ${toString wait_utxo_id_sleep} - fi - tries="$((tries - 1))" - fi - done -} - ################################################################################ # Waits until an specific proposal appears or fails. # Not to be run during the benchmarking phase: lots of queries! @@ -723,16 +737,13 @@ function governance_funds_genesis { ${coreutils}/bin/echo "governance_funds_genesis: Splitting to: ''${producer_name} - ''${producer_i} - 0 - (''${producer_addr})" done - # Split! + # Split (no need to wait for the funds or re-submit, function takes care)! funds_from_to \ "''${node_str}" \ "''${utxo_vkey}" "''${utxo_skey}" \ "''${constitution_reminder}" \ ${toString treasury_donation} \ "''${producers_addrs_array[@]}" - - # Wait for the funds of the last producer to arrive. - wait_any_utxo "''${node_str}" "''${producers_addrs_array[-1]}" } ################################################################################ @@ -786,7 +797,7 @@ function governance_funds_producer { ${coreutils}/bin/echo "governance_funds_producer: Splitting to: ''${producer_name} - ''${producer_i} - ''${prop_i} - ''${producer_prop_addr}" done - # Split! + # Split (no need to wait for the funds or re-submit, function takes care)! funds_from_to \ "''${node_str}" \ "''${producer_vkey}" "''${producer_skey}" \ @@ -794,9 +805,6 @@ function governance_funds_producer { 0 \ "''${producer_prop_addr_array[@]}" - # Wait for the funds of the last producer-drep to arrive. - wait_any_utxo "''${node_str}" "''${producer_prop_addr_array[-1]}" - ############################ # Proposals -> DReps split # ############################ @@ -825,16 +833,14 @@ function governance_funds_producer { ${coreutils}/bin/echo "governance_funds_producer: Splitting to: ''${producer_name} - ''${producer_i} - ''${prop_i} - ''${actual_drep} - ''${producer_drep_addr}" done - # Split! + # Split (no need to wait for the funds or re-submit, function takes care)! funds_from_to \ "''${node_str}" \ "''${producer_prop_vkey}" "''${producer_prop_skey}" \ "''${dreps_reminder}" \ 0 \ "''${producer_dreps_addrs_array[@]}" - - # Wait for the funds of the last producer-prop-drep to arrive. - wait_any_utxo "''${node_str}" "''${producer_dreps_addrs_array[-1]}" + done }