From e581aeb658411625e5c41a0b1ae3c11b82698d7b Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Fri, 2 Jun 2023 11:37:24 +0900 Subject: [PATCH 01/27] Skip password input with --kill-only option --- deploy_blockchain_genesis_gcp.sh | 36 +++++++++++++++++--------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/deploy_blockchain_genesis_gcp.sh b/deploy_blockchain_genesis_gcp.sh index dc3930277..261b1d821 100644 --- a/deploy_blockchain_genesis_gcp.sh +++ b/deploy_blockchain_genesis_gcp.sh @@ -154,23 +154,25 @@ else fi fi -# Read node ip addresses -IFS=$'\n' read -d '' -r -a IP_ADDR_LIST < ./ip_addresses/$SEASON.txt -if [[ "$ACCOUNT_INJECTION_OPTION" = "--keystore" ]]; then - # Get keystore password - printf "Enter password: " - read -s PASSWORD - printf "\n\n" - - if [[ "$SEASON" = "mainnet" ]]; then - KEYSTORE_DIR="mainnet_prod_keys" - elif [[ "$SEASON" = "spring" ]] || [[ "$SEASON" = "summer" ]]; then - KEYSTORE_DIR="testnet_prod_keys" - else - KEYSTORE_DIR="testnet_dev_staging_keys" +if ! [[ $KILL_OPTION = '--kill-only' ]]; then + # Read node ip addresses + IFS=$'\n' read -d '' -r -a IP_ADDR_LIST < ./ip_addresses/$SEASON.txt + if [[ "$ACCOUNT_INJECTION_OPTION" = "--keystore" ]]; then + # Get keystore password + printf "Enter password: " + read -s PASSWORD + printf "\n\n" + + if [[ "$SEASON" = "mainnet" ]]; then + KEYSTORE_DIR="mainnet_prod_keys" + elif [[ "$SEASON" = "spring" ]] || [[ "$SEASON" = "summer" ]]; then + KEYSTORE_DIR="testnet_prod_keys" + else + KEYSTORE_DIR="testnet_dev_staging_keys" + fi + elif [[ "$ACCOUNT_INJECTION_OPTION" = "--mnemonic" ]]; then + IFS=$'\n' read -d '' -r -a MNEMONIC_LIST < ./testnet_mnemonics/$SEASON.txt fi -elif [[ "$ACCOUNT_INJECTION_OPTION" = "--mnemonic" ]]; then - IFS=$'\n' read -d '' -r -a MNEMONIC_LIST < ./testnet_mnemonics/$SEASON.txt fi function inject_account() { @@ -314,7 +316,7 @@ if [[ $KILL_OPTION = "--skip-kill" ]]; then printf "\nSkipping process kill...\n" else # kill any processes still alive - printf "\nKilling all tracker and blockchain node jobs...\n" + printf "\nKilling tracker / blockchain node jobs...\n" # Tracker server is killed with PARENT_NODE_INDEX_BEGIN = -1 if [[ $PARENT_NODE_INDEX_BEGIN = -1 ]]; then From c8ba43fe769df279ea477655bb8a88256b14232b Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Fri, 2 Jun 2023 11:53:16 +0900 Subject: [PATCH 02/27] Get confirmation for testnet (spring, summer) --- deploy_blockchain_genesis_gcp.sh | 14 +++++++++++--- deploy_blockchain_incremental_gcp.sh | 12 ++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/deploy_blockchain_genesis_gcp.sh b/deploy_blockchain_genesis_gcp.sh index 261b1d821..3edd7d0ae 100644 --- a/deploy_blockchain_genesis_gcp.sh +++ b/deploy_blockchain_genesis_gcp.sh @@ -33,7 +33,7 @@ GCP_USER="runner" printf "GCP_USER=$GCP_USER\n" number_re='^[0-9]+$' -if ! [[ $2 =~ $number_re ]] ; then +if [[ ! $2 =~ $number_re ]] ; then printf "Invalid <# of Shards> argument: $2\n" exit fi @@ -140,11 +140,19 @@ if [[ "$SEASON" = "mainnet" ]]; then printf "\n" printf "Do you want to proceed for $SEASON? Enter [mainnet]: " read CONFIRM - printf "\n\n" + printf "\n" if [[ ! $CONFIRM = "mainnet" ]] then [[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1 # handle exits from shell or function but don't exit interactive shell fi +elif [[ "$SEASON" = "spring" ]] || [[ "$SEASON" = "summer" ]]; then + printf "\n" + printf "Do you want to proceed for $SEASON? Enter [testnet]: " + read CONFIRM + printf "\n" + if [[ ! $CONFIRM = "testnet" ]]; then + [[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1 # handle exits from shell or function but don't exit interactive shell + fi else printf "\n" read -p "Do you want to proceed for $SEASON? [y/N]: " -n 1 -r @@ -154,7 +162,7 @@ else fi fi -if ! [[ $KILL_OPTION = '--kill-only' ]]; then +if [[ ! $KILL_OPTION = '--kill-only' ]]; then # Read node ip addresses IFS=$'\n' read -d '' -r -a IP_ADDR_LIST < ./ip_addresses/$SEASON.txt if [[ "$ACCOUNT_INJECTION_OPTION" = "--keystore" ]]; then diff --git a/deploy_blockchain_incremental_gcp.sh b/deploy_blockchain_incremental_gcp.sh index d29ad593c..3a3c32efd 100644 --- a/deploy_blockchain_incremental_gcp.sh +++ b/deploy_blockchain_incremental_gcp.sh @@ -33,7 +33,7 @@ GCP_USER="runner" printf "GCP_USER=$GCP_USER\n" number_re='^[0-9]+$' -if ! [[ $2 =~ $number_re ]] ; then +if [[ ! $2 =~ $number_re ]] ; then printf "Invalid <# of Shards> argument: $2\n" exit fi @@ -126,11 +126,19 @@ if [[ "$SEASON" = "mainnet" ]]; then printf "\n" printf "Do you want to proceed for $SEASON? Enter [mainnet]: " read CONFIRM - printf "\n\n" + printf "\n" if [[ ! $CONFIRM = "mainnet" ]] then [[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1 # handle exits from shell or function but don't exit interactive shell fi +elif [[ "$SEASON" = "spring" ]] || [[ "$SEASON" = "summer" ]]; then + printf "\n" + printf "Do you want to proceed for $SEASON? Enter [testnet]: " + read CONFIRM + printf "\n" + if [[ ! $CONFIRM = "testnet" ]]; then + [[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1 # handle exits from shell or function but don't exit interactive shell + fi else printf "\n" read -p "Do you want to proceed for $SEASON? [y/N]: " -n 1 -r From 123946bc0152b6f76e8985a5a80f421d545c3094 Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Tue, 11 Jul 2023 16:47:29 +0900 Subject: [PATCH 03/27] Turn off console logging for local trackers --- start_local_blockchain.sh | 2 +- start_local_blockchain_afan_shard.sh | 4 ++-- start_local_blockchain_multi_shards.sh | 4 +++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/start_local_blockchain.sh b/start_local_blockchain.sh index 586bd4c40..363529091 100755 --- a/start_local_blockchain.sh +++ b/start_local_blockchain.sh @@ -12,7 +12,7 @@ printf "\n[[[[[ start_local_blockchain.sh ]]]]]\n\n" printf "\nStarting tracker..\n" PORT=8080 \ P2P_PORT=5000 \ - CONSOLE_LOG=true \ + CONSOLE_LOG=false \ node ./tracker-server/index.js & printf "\nDone\n\n" sleep 5 diff --git a/start_local_blockchain_afan_shard.sh b/start_local_blockchain_afan_shard.sh index 18c635013..a4dd4b59a 100755 --- a/start_local_blockchain_afan_shard.sh +++ b/start_local_blockchain_afan_shard.sh @@ -10,7 +10,7 @@ printf "\n[[[[[ start_local_blockchain_afan_shard.sh ]]]]]\n\n" printf "\nStarting parent tracker..\n" PORT=8080 \ P2P_PORT=5000 \ - CONSOLE_LOG=true \ + CONSOLE_LOG=false \ node ./tracker-server/index.js & printf "\nDone\n\n" sleep 5 @@ -60,7 +60,7 @@ printf "\nStarting afan child chain tracker..\n" BLOCKCHAIN_CONFIGS_DIR=blockchain-configs/afan-shard \ PORT=9000 \ P2P_PORT=6000 \ - CONSOLE_LOG=true \ + CONSOLE_LOG=false \ node ./tracker-server/index.js & printf "\nDone\n\n" sleep 5 diff --git a/start_local_blockchain_multi_shards.sh b/start_local_blockchain_multi_shards.sh index 26811e043..fe35ceb63 100755 --- a/start_local_blockchain_multi_shards.sh +++ b/start_local_blockchain_multi_shards.sh @@ -11,7 +11,7 @@ printf "\n[[[[[ start_local_blockchain_multi_shards.sh ]]]]]\n\n" printf "\nStarting parent tracker..\n" PORT=8080 \ P2P_PORT=5000 \ - CONSOLE_LOG=true \ + CONSOLE_LOG=false \ node ./tracker-server/index.js & printf "\nDone\n\n" sleep 5 @@ -64,6 +64,7 @@ printf "\nStarting child chain 1 tracker..\n" BLOCKCHAIN_CONFIGS_DIR=blockchain-configs/afan-shard \ PORT=9000 \ P2P_PORT=6000 \ + CONSOLE_LOG=false \ node ./tracker-server/index.js & printf "\nDone\n\n" sleep 10 @@ -131,6 +132,7 @@ printf "\nStarting child chain 2 tracker..\n" BLOCKCHAIN_CONFIGS_DIR=blockchain-configs/sim-shard \ PORT=9010 \ P2P_PORT=6010 \ + CONSOLE_LOG=false \ node ./tracker-server/index.js & printf "\nDone\n\n" sleep 10 From edcc6c6ba37c98f3697cbb2a0476242dc4c9e1f2 Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Tue, 11 Jul 2023 16:47:59 +0900 Subject: [PATCH 04/27] Delete timer flags file for testnet-dev --- .../testnet-dev/timer_flags.json | 50 ------------------- 1 file changed, 50 deletions(-) delete mode 100644 blockchain-configs/testnet-dev/timer_flags.json diff --git a/blockchain-configs/testnet-dev/timer_flags.json b/blockchain-configs/testnet-dev/timer_flags.json deleted file mode 100644 index 685b6bebc..000000000 --- a/blockchain-configs/testnet-dev/timer_flags.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "allow_lower_case_app_names_only": { - "enabled_block": 2, - "has_bandage": true - }, - "create_app_config_sanitization": { - "enabled_block": 2, - "has_bandage": true - }, - "native_service_path_length_check": { - "enabled_block": 2, - "has_bandage": true - }, - "update_max_state_tree_size_per_byte": { - "enabled_block": 2, - "has_bandage": true - }, - "staking_balance_total_sum": { - "enabled_block": 2, - "has_bandage": true - }, - "update_max_state_tree_size_per_byte2": { - "enabled_block": 2, - "has_bandage": true - }, - "update_bandwidth_budget_params": { - "enabled_block": 2, - "has_bandage": true - }, - "disable_tx_receipt_recording": { - "enabled_block": 2, - "has_bandage": false - }, - "extend_account_registration_gas_amount": { - "enabled_block": 2, - "has_bandage": false - }, - "add_app_creation_gas_amount": { - "enabled_block": 2, - "has_bandage": true - }, - "allow_non_negative_transfer_value_only": { - "enabled_block": 2, - "has_bandage": true - }, - "update_min_gc_num_siblings_deleted": { - "enabled_block": 2, - "has_bandage": true - } -} From 52416cff94bbc1b7384b88aee51492534ac758aa Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Tue, 11 Jul 2023 18:33:40 +0900 Subject: [PATCH 05/27] Charge gas amount for skipped REST function calls --- common/common-util.js | 2 +- common/result-code.js | 1 + db/functions.js | 86 ++++++++++++++++++++----------------- test/unit/functions.test.js | 2 +- 4 files changed, 49 insertions(+), 42 deletions(-) diff --git a/common/common-util.js b/common/common-util.js index 27b874fd2..f1ac71d54 100644 --- a/common/common-util.js +++ b/common/common-util.js @@ -551,7 +551,7 @@ class CommonUtil { // TODO(platfowner): Consider some code (e.g. IN_LOCKUP_PERIOD, INSUFFICIENT_BALANCE) no failure // so that their transactions are not reverted. static isFailedFuncResultCode(code) { - return code !== FunctionResultCode.SUCCESS; + return code !== FunctionResultCode.SUCCESS && code !== FunctionResultCode.SKIP; } static isAppPath(parsedPath) { diff --git a/common/result-code.js b/common/result-code.js index 14ad24d4d..5c28ba27c 100644 --- a/common/result-code.js +++ b/common/result-code.js @@ -126,6 +126,7 @@ const FailedTxPrecheckCodeSet = new Set([ // If they are altered and deployed, the full sync of the blockchain nodes can fail. const FunctionResultCode = { SUCCESS: 0, + SKIP: 20000, // Normal skip FAILURE: 20001, // Normal failure INTERNAL_ERROR: 20002, // Something went wrong but don't know why // Transfer diff --git a/db/functions.js b/db/functions.js index 7f2fde8cb..8306c738e 100644 --- a/db/functions.js +++ b/db/functions.js @@ -237,9 +237,7 @@ class Functions { } } else if (functionEntry.function_type === FunctionTypes.REST) { // NOTE: Skipped when the event source is null. - if (NodeConfigs.ENABLE_REST_FUNCTION_CALL && - eventSource !== null && - functionEntry.function_url) { + if (functionEntry.function_url) { const restFunctionUrlWhitelist = this.db.getRestFunctionsUrlWhitelist(); if (!CommonUtil.isWhitelistedUrl(functionEntry.function_url, restFunctionUrlWhitelist)) { // NOTE: Skipped when the function url is not in the whitelist. @@ -255,43 +253,51 @@ class Functions { `function_url '${functionEntry.function_url}' with:\n` + formattedParams); } - const newAuth = Object.assign( - {}, auth, { fid: functionEntry.function_id, fids: this.getFids() }); - promises.push(axios.post(functionEntry.function_url, { - fid: functionEntry.function_id, - function: functionEntry, - valuePath, - functionPath, - value, - prevValue, - params, - timestamp, - executedAt, - transaction, - blockNumber, - blockTime, - options, - eventSource, - auth: newAuth, - chainId: blockchainParams.chainId, - networkId: blockchainParams.networkId, - }, { - timeout: NodeConfigs.REST_FUNCTION_CALL_TIMEOUT_MS - }).catch((error) => { - if (DevFlags.enableRichFunctionLogging) { - logger.error( - `Failed to trigger REST function [[ ${functionEntry.function_id} ]] of ` + - `function_url '${functionEntry.function_url}' with error: \n` + - `${JSON.stringify(error)}` + - formattedParams); - } - failCount++; - return true; - })); - funcResults[functionEntry.function_id] = { - code: FunctionResultCode.SUCCESS, - bandwidth_gas_amount: blockchainParams.restFunctionCallGasAmount, - }; + if (NodeConfigs.ENABLE_REST_FUNCTION_CALL && eventSource !== null) { + const newAuth = Object.assign( + {}, auth, { fid: functionEntry.function_id, fids: this.getFids() }); + promises.push(axios.post(functionEntry.function_url, { + fid: functionEntry.function_id, + function: functionEntry, + valuePath, + functionPath, + value, + prevValue, + params, + timestamp, + executedAt, + transaction, + blockNumber, + blockTime, + options, + eventSource, + auth: newAuth, + chainId: blockchainParams.chainId, + networkId: blockchainParams.networkId, + }, { + timeout: NodeConfigs.REST_FUNCTION_CALL_TIMEOUT_MS + }).catch((error) => { + if (DevFlags.enableRichFunctionLogging) { + logger.error( + `Failed to trigger REST function [[ ${functionEntry.function_id} ]] of ` + + `function_url '${functionEntry.function_url}' with error: \n` + + `${JSON.stringify(error)}` + + formattedParams); + } + failCount++; + return true; + })); + funcResults[functionEntry.function_id] = { + code: FunctionResultCode.SUCCESS, + bandwidth_gas_amount: blockchainParams.restFunctionCallGasAmount, + }; + } else { + // Rest function trigger is skipped. + funcResults[functionEntry.function_id] = { + code: FunctionResultCode.SKIP, + bandwidth_gas_amount: blockchainParams.restFunctionCallGasAmount, + }; + } triggerCount++; } } diff --git a/test/unit/functions.test.js b/test/unit/functions.test.js index 70518f9a2..c2702ca5f 100644 --- a/test/unit/functions.test.js +++ b/test/unit/functions.test.js @@ -2723,7 +2723,7 @@ describe("Functions", () => { return triggerRes.func_promises.then((resp) => { assert.deepEqual(resp, { func_count: 1, - trigger_count: 0, + trigger_count: 1, fail_count: 0, }); }); From ff65e218414a6a364e95622c28e97f9b5db084f8 Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Wed, 12 Jul 2023 12:11:03 +0900 Subject: [PATCH 06/27] Reduce min_gc_num_siblings_deleted to 10 --- blockchain-configs/base/timer_flags.json | 4 ++++ blockchain-configs/mainnet-prod/timer_flags.json | 4 ++++ blockchain-configs/testnet-prod/timer_flags.json | 4 ++++ .../allow_non_negative_transfer_value_only.js | 2 +- .../update_min_gc_num_siblings_deleted2.js | 10 ++++++++++ 5 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 db/bandage-files/update_min_gc_num_siblings_deleted2.js diff --git a/blockchain-configs/base/timer_flags.json b/blockchain-configs/base/timer_flags.json index 61630ce74..bcba9412a 100644 --- a/blockchain-configs/base/timer_flags.json +++ b/blockchain-configs/base/timer_flags.json @@ -47,5 +47,9 @@ "update_min_gc_num_siblings_deleted": { "enabled_block": 2, "has_bandage": true + }, + "update_min_gc_num_siblings_deleted2": { + "enabled_block": 2, + "has_bandage": true } } diff --git a/blockchain-configs/mainnet-prod/timer_flags.json b/blockchain-configs/mainnet-prod/timer_flags.json index 636bf9642..f8f9ea397 100644 --- a/blockchain-configs/mainnet-prod/timer_flags.json +++ b/blockchain-configs/mainnet-prod/timer_flags.json @@ -46,5 +46,9 @@ "update_min_gc_num_siblings_deleted": { "enabled_block": 1414800, "has_bandage": true + }, + "update_min_gc_num_siblings_deleted2": { + "enabled_block": null, + "has_bandage": true } } diff --git a/blockchain-configs/testnet-prod/timer_flags.json b/blockchain-configs/testnet-prod/timer_flags.json index 1d4aa38dd..72b3f65b2 100644 --- a/blockchain-configs/testnet-prod/timer_flags.json +++ b/blockchain-configs/testnet-prod/timer_flags.json @@ -50,5 +50,9 @@ "update_min_gc_num_siblings_deleted": { "enabled_block": 1411300, "has_bandage": true + }, + "update_min_gc_num_siblings_deleted2": { + "enabled_block": null, + "has_bandage": true } } diff --git a/db/bandage-files/allow_non_negative_transfer_value_only.js b/db/bandage-files/allow_non_negative_transfer_value_only.js index 16944074d..916ed76ec 100644 --- a/db/bandage-files/allow_non_negative_transfer_value_only.js +++ b/db/bandage-files/allow_non_negative_transfer_value_only.js @@ -7,7 +7,7 @@ module.exports = { "write": "(auth.addr === $from || auth.fid === '_stake' || auth.fid === '_unstake' || auth.fid === '_pay' || auth.fid === '_claim' || auth.fid === '_hold' || auth.fid === '_release' || auth.fid === '_collectFee' || auth.fid === '_claimReward' || auth.fid === '_openCheckout' || auth.fid === '_closeCheckout' || auth.fid === '_closeCheckin') && !getValue('transfer/' + $from + '/' + $to + '/' + $key) && (util.isServAcntName($from, blockNumber) || util.isCksumAddr($from)) && (util.isServAcntName($to, blockNumber) || util.isCksumAddr($to)) && $from !== $to && util.isNumber(newData) && newData > 0 && util.getBalance($from, getValue) >= newData" } }, - // From allow_lower_case_app_names_only bandage file. + // From allow_lower_case_app_names_only.js bandage file. prevValue: { ".rule": { "write": "(auth.addr === $from || auth.fid === '_stake' || auth.fid === '_unstake' || auth.fid === '_pay' || auth.fid === '_claim' || auth.fid === '_hold' || auth.fid === '_release' || auth.fid === '_collectFee' || auth.fid === '_claimReward' || auth.fid === '_openCheckout' || auth.fid === '_closeCheckout' || auth.fid === '_closeCheckin') && !getValue('transfer/' + $from + '/' + $to + '/' + $key) && (util.isServAcntName($from, blockNumber) || util.isCksumAddr($from)) && (util.isServAcntName($to, blockNumber) || util.isCksumAddr($to)) && $from !== $to && util.isNumber(newData) && util.getBalance($from, getValue) >= newData" diff --git a/db/bandage-files/update_min_gc_num_siblings_deleted2.js b/db/bandage-files/update_min_gc_num_siblings_deleted2.js new file mode 100644 index 000000000..146cb94eb --- /dev/null +++ b/db/bandage-files/update_min_gc_num_siblings_deleted2.js @@ -0,0 +1,10 @@ +module.exports = { + data: [ + { + path: ['values', 'blockchain_params', 'resource', 'min_gc_num_siblings_deleted'], + value: 10, + // From update_min_gc_num_siblings_deleted.js bandage file. + prevValue: 20 + } + ] +}; From 44de3351ae1149471bd82bf81a119f05c8b25067 Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Wed, 12 Jul 2023 12:12:10 +0900 Subject: [PATCH 07/27] Tweak transfer gc rule --- blockchain-configs/base/timer_flags.json | 4 ++++ .../mainnet-prod/timer_flags.json | 4 ++++ .../testnet-prod/timer_flags.json | 4 ++++ db/bandage-files/tweak_transfer_gc_rule.js | 19 +++++++++++++++++++ 4 files changed, 31 insertions(+) create mode 100644 db/bandage-files/tweak_transfer_gc_rule.js diff --git a/blockchain-configs/base/timer_flags.json b/blockchain-configs/base/timer_flags.json index bcba9412a..702db6a3d 100644 --- a/blockchain-configs/base/timer_flags.json +++ b/blockchain-configs/base/timer_flags.json @@ -51,5 +51,9 @@ "update_min_gc_num_siblings_deleted2": { "enabled_block": 2, "has_bandage": true + }, + "tweak_transfer_gc_rule": { + "enabled_block": 2, + "has_bandage": true } } diff --git a/blockchain-configs/mainnet-prod/timer_flags.json b/blockchain-configs/mainnet-prod/timer_flags.json index f8f9ea397..50ca0db01 100644 --- a/blockchain-configs/mainnet-prod/timer_flags.json +++ b/blockchain-configs/mainnet-prod/timer_flags.json @@ -50,5 +50,9 @@ "update_min_gc_num_siblings_deleted2": { "enabled_block": null, "has_bandage": true + }, + "tweak_transfer_gc_rule": { + "enabled_block": null, + "has_bandage": true } } diff --git a/blockchain-configs/testnet-prod/timer_flags.json b/blockchain-configs/testnet-prod/timer_flags.json index 72b3f65b2..df69ab6e7 100644 --- a/blockchain-configs/testnet-prod/timer_flags.json +++ b/blockchain-configs/testnet-prod/timer_flags.json @@ -54,5 +54,9 @@ "update_min_gc_num_siblings_deleted2": { "enabled_block": null, "has_bandage": true + }, + "tweak_transfer_gc_rule": { + "enabled_block": null, + "has_bandage": true } } diff --git a/db/bandage-files/tweak_transfer_gc_rule.js b/db/bandage-files/tweak_transfer_gc_rule.js new file mode 100644 index 000000000..82fb4c5a6 --- /dev/null +++ b/db/bandage-files/tweak_transfer_gc_rule.js @@ -0,0 +1,19 @@ +module.exports = { + data: [ + { + path: ['rules', 'transfer', '$from', '$to', '$key', '.rule' ], + value: { + "state": { + "gc_max_siblings": 10, + "gc_num_siblings_deleted": 10 + } + }, + prevValue: { + "state": { + "gc_max_siblings": 200, + "gc_num_siblings_deleted": 100 + } + } + } + ] +}; From 45aa1d713e8a2d4e3bc657507b4a0d08a0f54559 Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Thu, 13 Jul 2023 16:33:50 +0900 Subject: [PATCH 08/27] Add ain_dryrunSignedTransaction json rpc API --- db/index.js | 4 +- json_rpc/constants.js | 1 + json_rpc/transaction.js | 102 ++++++++++++++++++++++------------------ node/index.js | 12 +++-- p2p/server.js | 11 +++-- 5 files changed, 73 insertions(+), 57 deletions(-) diff --git a/db/index.js b/db/index.js index 16f0dbdf7..4c8e79c3e 100644 --- a/db/index.js +++ b/db/index.js @@ -1948,7 +1948,9 @@ class DB { return true; } - executeTransaction(tx, skipFees = false, restoreIfFails = false, blockNumber = 0, blockTime = null, eventSource = null) { + executeTransaction( + tx, skipFees = false, restoreIfFails = false, blockNumber = 0, blockTime = null, + eventSource = null, isDryrun = false) { const LOG_HEADER = 'executeTransaction'; const precheckResult = this.precheckTransaction(tx, skipFees, blockNumber); diff --git a/json_rpc/constants.js b/json_rpc/constants.js index 73e8fd99b..0aeed83dc 100644 --- a/json_rpc/constants.js +++ b/json_rpc/constants.js @@ -1,6 +1,7 @@ const JSON_RPC_METHODS = { AIN_ADD_TO_WHITELIST_NODE_PARAM: 'ain_addToWhitelistNodeParam', AIN_CHECK_PROTOCOL_VERSION: 'ain_checkProtocolVersion', + AIN_DRYRUN_SIGNED_TRANSACTION: 'ain_dryrunSignedTransaction', AIN_EVAL_RULE: 'ain_evalRule', AIN_EVAL_OWNER: 'ain_evalOwner', AIN_GET: 'ain_get', diff --git a/json_rpc/transaction.js b/json_rpc/transaction.js index e13177f3b..efdb8435d 100644 --- a/json_rpc/transaction.js +++ b/json_rpc/transaction.js @@ -10,6 +10,55 @@ const CommonUtil = require('../common/common-util'); const Transaction = require('../tx-pool/transaction'); const { JSON_RPC_METHODS } = require('./constants'); +function executeTransactionOnNode(node, p2pServer, args, done, isDryrun) { + const beginTime = Date.now(); + const txBytesLimit = node.getBlockchainParam('resource/tx_bytes_limit'); + if (sizeof(args) > txBytesLimit) { + const latency = Date.now() - beginTime; + trafficStatsManager.addEvent(TrafficEventTypes.JSON_RPC_SET, latency); + done(null, JsonRpcUtil.addProtocolVersion({ + result: null, + code: JsonRpcApiResultCode.TX_EXCEEDS_SIZE_LIMIT, + message: `Transaction size exceeds its limit: ${txBytesLimit} bytes.` + })); + } else if (!args.tx_body || !args.signature) { + const latency = Date.now() - beginTime; + trafficStatsManager.addEvent(TrafficEventTypes.JSON_RPC_SET, latency); + done(null, JsonRpcUtil.addProtocolVersion({ + result: null, + code: JsonRpcApiResultCode.TX_MISSING_PROPERTIES, + message: 'Missing properties.' + })); + } else { + const chainId = node.getBlockchainParam('genesis/chain_id'); + const createdTx = Transaction.create(args.tx_body, args.signature, chainId); + if (!createdTx) { + const latency = Date.now() - beginTime; + trafficStatsManager.addEvent(TrafficEventTypes.JSON_RPC_SET, latency); + done(null, JsonRpcUtil.addProtocolVersion({ + result: null, + code: JsonRpcApiResultCode.TX_INVALID_FORMAT, + message: 'Invalid transaction format.' + })); + } else { + if (!NodeConfigs.LIGHTWEIGHT && + NodeConfigs.ENABLE_EARLY_TX_SIG_VERIF && + !Transaction.verifyTransaction(createdTx, chainId)) { + done(null, JsonRpcUtil.addProtocolVersion({ + result: null, + code: JsonRpcApiResultCode.TX_INVALID_SIGNATURE, + message: 'Invalid transaction signature.' + })); + } else { + const result = p2pServer.executeAndBroadcastTransaction(createdTx, isDryrun); + const latency = Date.now() - beginTime; + trafficStatsManager.addEvent(TrafficEventTypes.JSON_RPC_SET, latency); + done(null, JsonRpcUtil.addProtocolVersion({ result })); + } + } + } +} + module.exports = function getTransactionApis(node, p2pServer) { return { [JSON_RPC_METHODS.AIN_GET_PENDING_TRANSACTIONS]: function(args, done) { @@ -75,53 +124,12 @@ module.exports = function getTransactionApis(node, p2pServer) { done(null, JsonRpcUtil.addProtocolVersion({ result })); }, + [JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION]: function(args, done) { + executeTransactionOnNode(node, p2pServer, args, done, true); + }, + [JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION]: function(args, done) { - const beginTime = Date.now(); - const txBytesLimit = node.getBlockchainParam('resource/tx_bytes_limit'); - if (sizeof(args) > txBytesLimit) { - const latency = Date.now() - beginTime; - trafficStatsManager.addEvent(TrafficEventTypes.JSON_RPC_SET, latency); - done(null, JsonRpcUtil.addProtocolVersion({ - result: null, - code: JsonRpcApiResultCode.TX_EXCEEDS_SIZE_LIMIT, - message: `Transaction size exceeds its limit: ${txBytesLimit} bytes.` - })); - } else if (!args.tx_body || !args.signature) { - const latency = Date.now() - beginTime; - trafficStatsManager.addEvent(TrafficEventTypes.JSON_RPC_SET, latency); - done(null, JsonRpcUtil.addProtocolVersion({ - result: null, - code: JsonRpcApiResultCode.TX_MISSING_PROPERTIES, - message: 'Missing properties.' - })); - } else { - const chainId = node.getBlockchainParam('genesis/chain_id'); - const createdTx = Transaction.create(args.tx_body, args.signature, chainId); - if (!createdTx) { - const latency = Date.now() - beginTime; - trafficStatsManager.addEvent(TrafficEventTypes.JSON_RPC_SET, latency); - done(null, JsonRpcUtil.addProtocolVersion({ - result: null, - code: JsonRpcApiResultCode.TX_INVALID_FORMAT, - message: 'Invalid transaction format.' - })); - } else { - if (!NodeConfigs.LIGHTWEIGHT && - NodeConfigs.ENABLE_EARLY_TX_SIG_VERIF && - !Transaction.verifyTransaction(createdTx, chainId)) { - done(null, JsonRpcUtil.addProtocolVersion({ - result: null, - code: JsonRpcApiResultCode.TX_INVALID_SIGNATURE, - message: 'Invalid transaction signature.' - })); - } else { - const result = p2pServer.executeAndBroadcastTransaction(createdTx); - const latency = Date.now() - beginTime; - trafficStatsManager.addEvent(TrafficEventTypes.JSON_RPC_SET, latency); - done(null, JsonRpcUtil.addProtocolVersion({ result })); - } - } - } + executeTransactionOnNode(node, p2pServer, args, done, false); }, [JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION_BATCH]: function(args, done) { @@ -191,7 +199,7 @@ module.exports = function getTransactionApis(node, p2pServer) { } txList.push(createdTx); } - const result = p2pServer.executeAndBroadcastTransaction({tx_list: txList}); + const result = p2pServer.executeAndBroadcastTransaction({ tx_list: txList }); const latency = Date.now() - beginTime; trafficStatsManager.addEvent(TrafficEventTypes.JSON_RPC_SET, latency); done(null, JsonRpcUtil.addProtocolVersion({ result })); diff --git a/node/index.js b/node/index.js index 5312d24c1..a46a4c738 100644 --- a/node/index.js +++ b/node/index.js @@ -729,7 +729,7 @@ class BlockchainNode { * Executes a transaction and add it to the transaction pool if the execution was successful. * @param {Object} tx transaction */ - executeTransactionAndAddToPool(tx) { + executeTransactionAndAddToPool(tx, isDryrun = false) { const LOG_HEADER = 'executeTransactionAndAddToPool'; if (DevFlags.enableRichTransactionLogging) { logger.info(`[${LOG_HEADER}] EXECUTING TRANSACTION: ${JSON.stringify(tx, null, 2)}`); @@ -792,8 +792,10 @@ class BlockchainNode { `[${LOG_HEADER}] Tx pool does NOT have enough free room ` + `(${perAccountFreePoolSize}) for account: ${executableTx.address}`); } + const eventSource = isDryrun ? null : ValueChangedEventSources.USER; const result = this.db.executeTransaction( - executableTx, false, true, this.bc.lastBlockNumber() + 1, this.bc.lastBlockTimestamp(), ValueChangedEventSources.USER); + executableTx, false, true, this.bc.lastBlockNumber() + 1, this.bc.lastBlockTimestamp(), + eventSource, isDryrun); if (CommonUtil.isFailedTx(result)) { if (DevFlags.enableRichTransactionLogging) { logger.error( @@ -803,11 +805,13 @@ class BlockchainNode { // NOTE(liayoo): Transactions that don't pass the pre-checks will be rejected instantly and // will not be included in the tx pool, as they can't be included in a block // anyway, and may be used for attacks on blockchain nodes. - if (!CommonUtil.txPrecheckFailed(result)) { + if (!isDryrun && !CommonUtil.txPrecheckFailed(result)) { this.tp.addTransaction(executableTx); } } else { - this.tp.addTransaction(executableTx, true); + if (!isDryrun) { + this.tp.addTransaction(executableTx, true); + } } return result; diff --git a/p2p/server.js b/p2p/server.js index 8eaad1f0e..830a1b057 100644 --- a/p2p/server.js +++ b/p2p/server.js @@ -605,7 +605,7 @@ class P2pServer { newTxList.push(createdTx); } if (newTxList.length > 0) { - this.executeAndBroadcastTransaction({ tx_list: newTxList }, txTags); + this.executeAndBroadcastTransaction({ tx_list: newTxList }, false, txTags); } } else { const createdTx = Transaction.create(tx.tx_body, tx.signature, chainId); @@ -618,7 +618,7 @@ class P2pServer { logger.info(`[${LOG_HEADER}] Invalid signature of tx: ` + `${JSON.stringify(tx, null, 2)}`); } else { - this.executeAndBroadcastTransaction(createdTx, txTags); + this.executeAndBroadcastTransaction(createdTx, false, txTags); } } break; @@ -790,7 +790,7 @@ class P2pServer { socket.send(JSON.stringify(payload)); } - executeAndBroadcastTransaction(tx, tags = []) { + executeAndBroadcastTransaction(tx, isDryrun = false, tags = []) { const LOG_HEADER = 'executeAndBroadcastTransaction'; if (!tx) { return { @@ -818,6 +818,7 @@ class P2pServer { continue; } + // NOTE(platfowner): There is no dryrun mode for batch transactions. const result = this.node.executeTransactionAndAddToPool(subTx); resultList.push({ tx_hash: subTx.hash, @@ -834,9 +835,9 @@ class P2pServer { return resultList; } else { - const result = this.node.executeTransactionAndAddToPool(tx); + const result = this.node.executeTransactionAndAddToPool(tx, isDryrun); logger.debug(`\n TX RESULT: ` + JSON.stringify(result)); - if (!CommonUtil.isFailedTx(result)) { + if (!isDryrun && !CommonUtil.isFailedTx(result)) { this.client.broadcastTransaction(tx, tags); } From f2ca36d67bcbc545e8eaa09ccd4802f0414cabc7 Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Thu, 13 Jul 2023 19:28:21 +0900 Subject: [PATCH 09/27] Implement isDryrun = true logic --- db/index.js | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/db/index.js b/db/index.js index 4c8e79c3e..6512aea2f 100644 --- a/db/index.js +++ b/db/index.js @@ -1958,7 +1958,7 @@ class DB { logger.debug(`[${LOG_HEADER}] Pre-check failed`); return precheckResult; } - if (restoreIfFails) { + if (restoreIfFails || isDryrun) { if (!this.backupDb()) { return CommonUtil.logAndReturnTxResult( logger, @@ -1975,15 +1975,19 @@ class DB { const timestamp = txBody.timestamp; const executionResult = this.executeOperation(txBody.operation, auth, nonce, timestamp, tx, blockNumber, blockTime, eventSource); - if (CommonUtil.isFailedTx(executionResult)) { - if (restoreIfFails) { - this.restoreDb(); - } else { - this.deleteBackupStateVersion(); - return executionResult; + if (isDryrun) { + this.restoreDb(); + } else { + if (CommonUtil.isFailedTx(executionResult)) { + if (restoreIfFails) { + this.restoreDb(); + } else { + this.deleteBackupStateVersion(); + return executionResult; + } } } - if (!skipFees) { + if (!skipFees && !isDryrun) { if (DevFlags.enableGasFeeCollection) { this.collectFee(auth, tx, timestamp, blockNumber, blockTime, executionResult, eventSource); } From a921b6739c677c2b25a94554c40c0ec5abf0f348 Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Thu, 13 Jul 2023 20:15:19 +0900 Subject: [PATCH 10/27] Simplify db restoring logic --- db/index.js | 14 ++++++-------- test/unit/p2p.test.js | 4 ++-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/db/index.js b/db/index.js index 6512aea2f..2d61a8a93 100644 --- a/db/index.js +++ b/db/index.js @@ -1977,17 +1977,15 @@ class DB { this.executeOperation(txBody.operation, auth, nonce, timestamp, tx, blockNumber, blockTime, eventSource); if (isDryrun) { this.restoreDb(); - } else { + return executionResult; + } else if (restoreIfFails) { if (CommonUtil.isFailedTx(executionResult)) { - if (restoreIfFails) { - this.restoreDb(); - } else { - this.deleteBackupStateVersion(); - return executionResult; - } + this.restoreDb(); + } else { + this.deleteBackupStateVersion(); } } - if (!skipFees && !isDryrun) { + if (!skipFees) { if (DevFlags.enableGasFeeCollection) { this.collectFee(auth, tx, timestamp, blockNumber, blockTime, executionResult, eventSource); } diff --git a/test/unit/p2p.test.js b/test/unit/p2p.test.js index de7c38c93..079f58cbc 100644 --- a/test/unit/p2p.test.js +++ b/test/unit/p2p.test.js @@ -158,7 +158,7 @@ describe("P2p", () => { describe("getStateVersionStatus", () => { it("gets initial state version status", () => { const stateVersionStatus = p2pServer.getStateVersionStatus(); - expect(stateVersionStatus.numVersions).to.equal(5); + expect(stateVersionStatus.numVersions).to.equal(4); expect(stateVersionStatus.finalVersion).to.equal('FINAL:0'); }); }); @@ -219,7 +219,7 @@ describe("P2p", () => { numApps: 1, }, stateVersionStatus: { - numVersions: 5, + numVersions: 4, versionList: 'erased', finalVersion: 'FINAL:0' } From 67d703a399a47fdea9e1b530342f23ac3c760a4a Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Fri, 14 Jul 2023 11:26:14 +0900 Subject: [PATCH 11/27] Update transfer tool for dryrun --- tools/transfer/executeTransferTx.js | 105 ++++++++++++++++++++++++++++ tools/transfer/sendTransferTx.js | 79 --------------------- tools/util.js | 21 ++++-- 3 files changed, 121 insertions(+), 84 deletions(-) create mode 100644 tools/transfer/executeTransferTx.js delete mode 100644 tools/transfer/sendTransferTx.js diff --git a/tools/transfer/executeTransferTx.js b/tools/transfer/executeTransferTx.js new file mode 100644 index 000000000..da1dff28f --- /dev/null +++ b/tools/transfer/executeTransferTx.js @@ -0,0 +1,105 @@ +// A tool to transfer native AIN tokens between accounts. +const ainUtil = require('@ainblockchain/ain-util'); +const CommonUtil = require('../../common/common-util'); +const { + getAccountPrivateKey, + signAndDryrunTx, + signAndSendTx, + confirmTransaction +} = require('../util'); + +function buildTransferTxBody(fromAddr, toAddr, key, amount, timestamp) { + return { + operation: { + type: 'SET_VALUE', + ref: `/transfer/${fromAddr}/${toAddr}/${key}/value`, + value: amount, + }, + gas_price: 500, + timestamp, + nonce: -1 + } +} + +async function executeTransaction(endpointUrl, chainId, toAddr, ainAmount, account, isDryrun) { + console.log('\n*** executeTransaction():'); + const timestamp = Date.now(); + + const txBody = + buildTransferTxBody(account.address, toAddr, timestamp, ainAmount, timestamp); + console.log(`txBody: ${JSON.stringify(txBody, null, 2)}`); + + let txInfo = null; + if (isDryrun) { + txInfo = await signAndDryrunTx(endpointUrl, txBody, account.private_key, chainId); + } else { + txInfo = await signAndSendTx(endpointUrl, txBody, account.private_key, chainId); + } + console.log(`txInfo: ${JSON.stringify(txInfo, null, 2)}`); + if (!txInfo.success) { + console.log(`Transfer transaction failed.`); + process.exit(0); + } + if (!isDryrun) { + await confirmTransaction(endpointUrl, timestamp, txInfo.txHash); + } +} + +async function executeTransferTx( + endpointUrl, chainId, toAddr, ainAmount, accountType, keystoreFilepath, isDryrun) { + const privateKey = await getAccountPrivateKey(accountType, keystoreFilepath); + const account = ainUtil.privateToAccount(Buffer.from(privateKey, 'hex')); + console.log(`\nFrom-address: ${account.address}\n`); + await executeTransaction(endpointUrl, chainId, toAddr, ainAmount, account, isDryrun); +} + +async function processArguments() { + if (process.argv.length < 7 || process.argv.length > 9) { + usage(); + } + const endpointUrl = process.argv[2]; + const chainId = Number(process.argv[3]); + const toAddr = process.argv[4]; + if (!CommonUtil.isCksumAddr(toAddr)) { + console.log(`The to-address is NOT a checksum address: ${toAddr}`); + process.exit(0); + } + const ainAmount = Number(process.argv[5]); + if (!CommonUtil.isNumber(ainAmount) || ainAmount <= 0) { + console.log(`The AIN amount is NOT a valid one: ${ainAmount}`); + process.exit(0); + } + const accountType = process.argv[6]; + const keystoreFilepath = (accountType === 'keystore') ? process.argv[7] : null; + if (accountType === 'keystore' && !keystoreFilepath) { + console.error('Please specify keystore filepath.'); + usage(); + } + let dryrunOption = null; + if (accountType === 'keystore') { + if (process.argv.length === 9) { + dryrunOption = process.argv[8]; + } + } else { + if (process.argv.length === 8) { + dryrunOption = process.argv[7]; + } + } + const isDryrun = dryrunOption === '--dryrun'; + await executeTransferTx(endpointUrl, chainId, toAddr, ainAmount, accountType, keystoreFilepath, isDryrun); +} + +function usage() { + console.log('\nUsage: node executeTransferTx.js [] [--dryrun]\n'); + console.log('Example: node executeTransferTx.js http://localhost:8081 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 private_key'); + console.log('Example: node executeTransferTx.js http://localhost:8081 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 mnemonic'); + console.log('Example: node executeTransferTx.js http://localhost:8081 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json'); + console.log('Example: node executeTransferTx.js http://localhost:8081 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json --dryrun'); + console.log('Example: node executeTransferTx.js https://staging-api.ainetwork.ai 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json'); + console.log('Example: node executeTransferTx.js https://testnet-api.ainetwork.ai 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json'); + console.log('Example: node executeTransferTx.js https://mainnet-api.ainetwork.ai 1 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json\n'); + console.log('Example: node executeTransferTx.js https://mainnet-api.ainetwork.ai 1 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json --dryrun\n'); + process.exit(0) +} + +processArguments(); diff --git a/tools/transfer/sendTransferTx.js b/tools/transfer/sendTransferTx.js deleted file mode 100644 index 483d5d2ad..000000000 --- a/tools/transfer/sendTransferTx.js +++ /dev/null @@ -1,79 +0,0 @@ -// A tool to transfer native AIN tokens between accounts. -const ainUtil = require('@ainblockchain/ain-util'); -const CommonUtil = require('../../common/common-util'); -const { getAccountPrivateKey, signAndSendTx, confirmTransaction } = require('../util'); - -function buildTransferTxBody(fromAddr, toAddr, key, amount, timestamp) { - return { - operation: { - type: 'SET_VALUE', - ref: `/transfer/${fromAddr}/${toAddr}/${key}/value`, - value: amount, - }, - gas_price: 500, - timestamp, - nonce: -1 - } -} - -async function sendTransaction(endpointUrl, chainId, toAddr, ainAmount, account) { - console.log('\n*** sendTransaction():'); - const timestamp = Date.now(); - - const txBody = - buildTransferTxBody(account.address, toAddr, timestamp, ainAmount, timestamp); - console.log(`txBody: ${JSON.stringify(txBody, null, 2)}`); - - const txInfo = await signAndSendTx(endpointUrl, txBody, account.private_key, chainId); - console.log(`txInfo: ${JSON.stringify(txInfo, null, 2)}`); - if (!txInfo.success) { - console.log(`Transfer transaction failed.`); - process.exit(0); - } - await confirmTransaction(endpointUrl, timestamp, txInfo.txHash); -} - -async function sendTransferTx(endpointUrl, chainId, toAddr, ainAmount, accountType, keystoreFilepath) { - const privateKey = await getAccountPrivateKey(accountType, keystoreFilepath); - const account = ainUtil.privateToAccount(Buffer.from(privateKey, 'hex')); - console.log(`\nFrom-address: ${account.address}\n`); - await sendTransaction(endpointUrl, chainId, toAddr, ainAmount, account); -} - -async function processArguments() { - if (process.argv.length !== 7 && process.argv.length !== 8) { - usage(); - } - const endpointUrl = process.argv[2]; - const chainId = Number(process.argv[3]); - const toAddr = process.argv[4]; - if (!CommonUtil.isCksumAddr(toAddr)) { - console.log(`The to-address is NOT a checksum address: ${toAddr}`); - process.exit(0); - } - const ainAmount = Number(process.argv[5]); - if (!CommonUtil.isNumber(ainAmount) || ainAmount <= 0) { - console.log(`The AIN amount is NOT a valid one: ${ainAmount}`); - process.exit(0); - } - const accountType = process.argv[6]; - const keystoreFilepath = (accountType === 'keystore') ? process.argv[7] : null; - if (accountType === 'keystore' && !keystoreFilepath) { - console.error('Please specify keystore filepath.'); - usage(); - } - await sendTransferTx(endpointUrl, chainId, toAddr, ainAmount, accountType, keystoreFilepath); -} - -function usage() { - console.log('\nUsage: node sendTransferTx.js []\n'); - console.log('Example: node sendTransferTx.js http://localhost:8081 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 private_key'); - console.log('Example: node sendTransferTx.js http://localhost:8081 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 mnemonic'); - console.log('Example: node sendTransferTx.js http://localhost:8081 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json'); - console.log('Example: node sendTransferTx.js https://staging-api.ainetwork.ai 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json'); - console.log('Example: node sendTransferTx.js https://testnet-api.ainetwork.ai 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json'); - console.log('Example: node sendTransferTx.js https://mainnet-api.ainetwork.ai 1 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json\n'); - process.exit(0) -} - -processArguments(); diff --git a/tools/util.js b/tools/util.js index 975c11f27..3fe935968 100644 --- a/tools/util.js +++ b/tools/util.js @@ -87,18 +87,16 @@ async function keystoreToAccount(filePath) { return ainUtil.privateToAccount(ainUtil.v3KeystoreToPrivate(keystore, input.password)); } -// FIXME(minsulee2): this is duplicated function see: ./common/network-util.js -function signAndSendTx(endpointUrl, txBody, privateKey, chainId) { - console.log('\n*** signAndSendTx():'); +function signAndExecuteTx(endpointUrl, txBody, privateKey, chainId, jsonRpcMethod) { const { txHash, signedTx } = CommonUtil.signTransaction(txBody, privateKey, chainId); console.log(`signedTx: ${JSON.stringify(signedTx, null, 2)}`); console.log(`txHash: ${txHash}`); - console.log('Sending transaction...'); + console.log('Executing transaction...'); return axios.post( `${endpointUrl}/json-rpc`, { - method: JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION, + method: jsonRpcMethod, params: signedTx, jsonrpc: '2.0', id: 0 @@ -115,6 +113,18 @@ function signAndSendTx(endpointUrl, txBody, privateKey, chainId) { }); } +function signAndDryrunTx(endpointUrl, txBody, privateKey, chainId) { + console.log('\n*** signAndDryrunTx():'); + return signAndExecuteTx( + endpointUrl, txBody, privateKey, chainId, JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION); +} + +function signAndSendTx(endpointUrl, txBody, privateKey, chainId) { + console.log('\n*** signAndSendTx():'); + return signAndExecuteTx( + endpointUrl, txBody, privateKey, chainId, JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION); +} + async function sendGetTxByHashRequest(endpointUrl, txHash) { return await axios.post( `${endpointUrl}/json-rpc`, @@ -152,6 +162,7 @@ async function confirmTransaction(endpointUrl, timestamp, txHash) { module.exports = { getAccountPrivateKey, keystoreToAccount, + signAndDryrunTx, signAndSendTx, sendGetTxByHashRequest, confirmTransaction, From 13b80e8496abd24732b9ca328772d57228269485 Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Fri, 14 Jul 2023 13:03:31 +0900 Subject: [PATCH 12/27] Set gas_amount_charged and gas_cost_total for dryrun --- db/index.js | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/db/index.js b/db/index.js index 2d61a8a93..c8f925274 100644 --- a/db/index.js +++ b/db/index.js @@ -1698,8 +1698,10 @@ class DB { } } - collectFee(auth, tx, timestamp, blockNumber, blockTime, executionResult, eventSource) { - const gasPriceUnit = DB.getBlockchainParam('resource/gas_price_unit', blockNumber, this.stateRoot); + collectFee( + auth, tx, timestamp, blockNumber, blockTime, executionResult, eventSource, isDryrun) { + const gasPriceUnit = + DB.getBlockchainParam('resource/gas_price_unit', blockNumber, this.stateRoot); const gasPrice = tx.tx_body.gas_price; // Use only the service gas amount total const serviceBandwidthGasAmount = _.get(tx, 'extra.gas.bandwidth.service', 0); @@ -1735,7 +1737,9 @@ class DB { executionResult.gas_amount_charged = gasAmountChargedByTransfer; executionResult.gas_cost_total = CommonUtil.getTotalGasCost(gasPrice, executionResult.gas_amount_charged, gasPriceUnit); - if (executionResult.gas_cost_total <= 0) return; + if (isDryrun || executionResult.gas_cost_total <= 0) { + return; + } const gasFeeCollectPath = PathUtil.getGasFeeCollectPath(blockNumber, billedTo, tx.hash); const newOptions = { timestamp, @@ -1973,11 +1977,19 @@ class DB { const auth = { addr: tx.address }; const nonce = txBody.nonce; const timestamp = txBody.timestamp; - const executionResult = - this.executeOperation(txBody.operation, auth, nonce, timestamp, tx, blockNumber, blockTime, eventSource); + const executionResult = this.executeOperation( + txBody.operation, auth, nonce, timestamp, tx, blockNumber, blockTime, eventSource); + if (!skipFees) { + if (DevFlags.enableGasFeeCollection) { + this.collectFee( + auth, tx, timestamp, blockNumber, blockTime, executionResult, eventSource, isDryrun); + } + if (!isEnabledTimerFlag('disable_tx_receipt_recording', blockNumber)) { + this.recordReceipt(auth, tx, blockNumber, executionResult); + } + } if (isDryrun) { this.restoreDb(); - return executionResult; } else if (restoreIfFails) { if (CommonUtil.isFailedTx(executionResult)) { this.restoreDb(); @@ -1985,14 +1997,6 @@ class DB { this.deleteBackupStateVersion(); } } - if (!skipFees) { - if (DevFlags.enableGasFeeCollection) { - this.collectFee(auth, tx, timestamp, blockNumber, blockTime, executionResult, eventSource); - } - if (!isEnabledTimerFlag('disable_tx_receipt_recording', blockNumber)) { - this.recordReceipt(auth, tx, blockNumber, executionResult); - } - } return executionResult; } From d50e64283baa80d33ceaf3b811efffd65fdc4bdb Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Fri, 14 Jul 2023 16:53:25 +0900 Subject: [PATCH 13/27] Add test for dryrun transaction API --- test/integration/node.test.js | 866 +++++++++++++++++++++++++++++++++- 1 file changed, 853 insertions(+), 13 deletions(-) diff --git a/test/integration/node.test.js b/test/integration/node.test.js index fa7cfb2bb..f94851f63 100644 --- a/test/integration/node.test.js +++ b/test/integration/node.test.js @@ -3216,6 +3216,609 @@ describe('Blockchain Node', () => { }) }) + describe('json-rpc api: ain_dryrunSignedTransaction', () => { + const account = { + address: "0x9534bC7529961E5737a3Dd317BdEeD41AC08a52D", + private_key: "e96292ef0676287908fc3461f747f106b7b9336f183b1766f83672fbe893664d", + public_key: "1e8de35ac153fa52cb61a7e887463c205b0121be659803e9f69dddcae8dfb5a3d4c96570c5c3fafa5755b89a90eb58a2041f8da9d909b9c4b6813c3832d1254a" + }; + + // for account registration gas amount (single set) + const account2 = { + address: "0x85a620A5A46d01cc1fCF49E73ab00710d4da943E", + private_key: "b542fc2ca4a68081b3ba238888d3a8783354c3aa81711340fd69f6ff32798525", + public_key: "eb8c8577e8be18a83829c5c8a2ec2a754ef0a190e5a01139e9a24aae8f56842dfaf708da56d0f395bbfef08633237398dec96343f62ce217130d9738a76adfdf" + }; + // for account registration gas amount (multi set) + const account3 = { + address: "0x758fd59D3f8157Ae4458f8E29E2A8317be3d5974", + private_key: "63200d28b05377f983103b1ac45a379b3d424c415f8a705c7cdd6365f7e828ea", + public_key: "0760186e6d1a37107217d68e491b4a4bd89e3b6642acfcf4b320acef24d5d0de1d33bcabd2e868776879c4776937a6785e71ee963efb40c4cf09283b542006ca" + }; + // for account registration gas amount (transfer) + const account4 = { + address: "0x652a5e81Dc2B62be4b7225584A1079C29334dE27", + private_key: "98a0cc69436b5fc635184bbe16ffa97284e099e8e84c0b7ecee61b1f92db29e5", + public_key: "b6c5920098836b4ee3dd9458c706470f539e81d7370534228ffe155fff4b9af8ccdb7f6ad1eeba135c30fe4a6175ecf0d8be4bd6813a8358bc19901df47f558a" + }; + // for account registration gas amount (transfer) + const account09 = { // genesis account 09 + address: "0x09A0d53FDf1c36A131938eb379b98910e55EEfe1", + private_key: "ee0b1315d446e5318eb6eb4e9d071cd12ef42d2956d546f9acbdc3b75c469640", + public_key: "e0a9c4697a41d7ecbd7660f43c59b0df8a3e9fa31ec87687b5b4592e1ab1f66e3b2503a966ca702051f4c8e1c37c9d88cd46242750e7fc9f65dfb14980101806" + }; + + before(async () => { + const currentRule = parseOrLog(syncRequest('GET', server1 + '/get_rule?ref=/apps/test') + .body.toString('utf-8')).result[".rule"]["write"]; + const newOwners = parseOrLog(syncRequest('GET', server1 + '/get_owner?ref=/apps/test') + .body.toString('utf-8')).result[".owner"]; + const newRule = `${currentRule} || auth.addr === '${account.address}' || auth.addr === '${account2.address}' || auth.addr === '${account4.address}'`; + newOwners["owners"][account.address] = { + "branch_owner": true, + "write_owner": true, + "write_rule": true, + "write_function": true + }; + const res = parseOrLog(syncRequest('POST', server1 + '/set', {json: { + op_list: [ + // clean up old owner configs. + { + type: 'SET_OWNER', + ref: '/apps/test/test_owner/other100/path', + value: null, + }, + { + type: 'SET_OWNER', + ref: '/apps/test/test_owner/other200/path', + value: null, + }, + { + type: 'SET_OWNER', + ref: '/apps/test/test_owner/other201/path', + value: null, + }, + { + type: 'SET_OWNER', + ref: '/apps/test/test_owner/other202/path', + value: null, + }, + { + type: 'SET_OWNER', + ref: '/apps/test/test_owner/other203/path', + value: null, + }, + { + type: 'SET_RULE', + ref: '/apps/test', + value: { + ".rule": { + "write": newRule + } + } + }, + // set new owner config. + { + type: 'SET_OWNER', + ref: '/apps/test', + value: { + ".owner": newOwners + } + } + ], + timestamp: Date.now(), + nonce: -1 + }}) + .body.toString('utf-8')).result; + assert.deepEqual(CommonUtil.isFailedTx(_.get(res, 'result')), false); + if (!(await waitUntilTxFinalized(serverList, _.get(res, 'tx_hash')))) { + console.error(`Failed to check finalization of tx.`); + } + }); + + it('accepts a transaction with unordered nonce (-1)', () => { + const client = jayson.client.http(server1 + '/json-rpc'); + const txBody = { + operation: { + type: 'SET_VALUE', + ref: `/apps/test/test_value/some/path`, + value: 'some other value 1' + }, + gas_price: 0, + timestamp: Date.now(), + nonce: -1 + }; + const signature = + ainUtil.ecSignTransaction(txBody, Buffer.from(account.private_key, 'hex')); + return client.request(JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION, { + tx_body: txBody, + signature, + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION + }).then((res) => { + const result = _.get(res, 'result.result', null); + expect(result).to.not.equal(null); + assert.deepEqual(res.result, { + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION, + result: { + result: { + code: 0, + bandwidth_gas_amount: 1, + gas_amount_charged: 0, + gas_amount_total: { + bandwidth: { + app: { + test: 1 + }, + service: 0 + }, + state: { + app: { + test: 28 + }, + service: 0 + } + }, + gas_cost_total: 0 + }, + tx_hash: CommonUtil.hashSignature(signature), + } + }); + }); + }); + + it('accepts a transaction with unordered nonce (-1) and non-zero gas_price', () => { + const client = jayson.client.http(server1 + '/json-rpc'); + const txBody = { + operation: { + type: 'SET_VALUE', + ref: `/apps/test/test_value/some/path`, + value: 'some other value 1 longer' + }, + gas_price: 500, // non-zero gas price + timestamp: Date.now(), + nonce: -1 + }; + const signature = + ainUtil.ecSignTransaction(txBody, Buffer.from(account.private_key, 'hex')); + return client.request(JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION, { + tx_body: txBody, + signature, + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION + }).then((res) => { + const result = _.get(res, 'result.result', null); + expect(result).to.not.equal(null); + assert.deepEqual(res.result, { + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION, + result: { + result: { + code: 0, + bandwidth_gas_amount: 1, + gas_amount_charged: 0, + gas_amount_total: { + bandwidth: { + app: { + test: 1 + }, + service: 0 + }, + state: { + app: { + test: 42 + }, + service: 0 + } + }, + gas_cost_total: 0 + }, + tx_hash: CommonUtil.hashSignature(signature), + } + }); + }); + }); + + it('accepts a transaction with numbered nonce', () => { + const client = jayson.client.http(server1 + '/json-rpc'); + return client.request(JSON_RPC_METHODS.AIN_GET_NONCE, { + address: account.address, + from: 'pending', + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION + }) + .then((nonceRes) => { + const nonce = _.get(nonceRes, 'result.result'); + const txBody = { + operation: { + type: 'SET_VALUE', + ref: `/apps/test/test_value/some/path`, + value: 'some other value 2' + }, + gas_price: 0, + timestamp: Date.now(), + nonce, // numbered nonce + }; + const signature = + ainUtil.ecSignTransaction(txBody, Buffer.from(account.private_key, 'hex')); + return client.request(JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION, { + tx_body: txBody, + signature, + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION + }) + .then((res) => { + const result = _.get(res, 'result.result', null); + expect(result).to.not.equal(null); + assert.deepEqual(res.result, { + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION, + result: { + result: { + code: 0, + bandwidth_gas_amount: 2001, + gas_amount_charged: 0, + gas_amount_total: { + bandwidth: { + app: { + test: 2001 + }, + service: 0 + }, + state: { + app: { + test: 28 + }, + service: 0 + } + }, + gas_cost_total: 0, + }, + tx_hash: CommonUtil.hashSignature(signature), + } + }); + }); + }); + }) + + it('accepts a transaction with numbered nonce and non-zero gas price', () => { + const client = jayson.client.http(server1 + '/json-rpc'); + return client.request(JSON_RPC_METHODS.AIN_GET_NONCE, { + address: account.address, + from: 'pending', + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION + }) + .then((nonceRes) => { + const nonce = _.get(nonceRes, 'result.result'); + const txBody = { + operation: { + type: 'SET_VALUE', + ref: `/apps/test/test_value/some/path`, + value: 'some other value 2 longer' + }, + gas_price: 500, // non-zero gas price + timestamp: Date.now(), + nonce, // numbered nonce + }; + const signature = + ainUtil.ecSignTransaction(txBody, Buffer.from(account.private_key, 'hex')); + return client.request(JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION, { + tx_body: txBody, + signature, + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION + }) + .then((res) => { + const result = _.get(res, 'result.result', null); + expect(result).to.not.equal(null); + assert.deepEqual(res.result, { + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION, + result: { + result: { + code: 0, + bandwidth_gas_amount: 2001, + gas_amount_charged: 0, + gas_amount_total: { + bandwidth: { + app: { + test: 2001 + }, + service: 0 + }, + state: { + app: { + test: 42 + }, + service: 0 + } + }, + gas_cost_total: 0, + }, + tx_hash: CommonUtil.hashSignature(signature), + } + }); + }); + }); + }) + + it('accepts a transaction with account registration gas amount from nonce', () => { + // NOTE: account2 does not have balance nor nonce/timestamp. + const client = jayson.client.http(server1 + '/json-rpc'); + return client.request(JSON_RPC_METHODS.AIN_GET_NONCE, { + address: account2.address, + from: 'pending', + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION + }) + .then((nonceRes) => { + const nonce = _.get(nonceRes, 'result.result'); + const txBody = { + operation: { + type: 'SET_VALUE', + ref: `/apps/test/test_value/some/path`, + value: 'some other value 4' + }, + gas_price: 0, + timestamp: Date.now(), + nonce, // numbered nonce + }; + const signature = + ainUtil.ecSignTransaction(txBody, Buffer.from(account2.private_key, 'hex')); + return client.request(JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION, { + tx_body: txBody, + signature, + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION + }) + .then((res) => { + const result = _.get(res, 'result.result', null); + expect(result).to.not.equal(null); + assert.deepEqual(res.result, { + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION, + result: { + result: { + code: 0, + bandwidth_gas_amount: 2001, + gas_amount_charged: 0, + gas_amount_total: { + bandwidth: { + app: { + test: 2001 + }, + service: 0 + }, + state: { + app: { + test: 28 + }, + service: 0 + } + }, + gas_cost_total: 0, + }, + tx_hash: CommonUtil.hashSignature(signature), + } + }); + }); + }); + }) + + it('accepts a transaction with account registration gas amount from nonce and non-zero gas price', () => { + // NOTE: account2 does not have balance nor nonce/timestamp. + const client = jayson.client.http(server1 + '/json-rpc'); + return client.request(JSON_RPC_METHODS.AIN_GET_NONCE, { + address: account2.address, + from: 'pending', + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION + }) + .then((nonceRes) => { + const nonce = _.get(nonceRes, 'result.result'); + const txBody = { + operation: { + type: 'SET_VALUE', + ref: `/apps/test/test_value/some/path`, + value: 'some other value 4 longer' + }, + gas_price: 500, // non-zero gas price + timestamp: Date.now(), + nonce, // numbered nonce + }; + const signature = + ainUtil.ecSignTransaction(txBody, Buffer.from(account2.private_key, 'hex')); + return client.request(JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION, { + tx_body: txBody, + signature, + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION + }) + .then((res) => { + const result = _.get(res, 'result.result', null); + expect(result).to.not.equal(null); + assert.deepEqual(res.result, { + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION, + result: { + result: { + code: 0, + bandwidth_gas_amount: 2001, + gas_amount_charged: 0, + gas_amount_total: { + bandwidth: { + app: { + test: 2001 + }, + service: 0 + }, + state: { + app: { + test: 42 + }, + service: 0 + } + }, + gas_cost_total: 0, + }, + tx_hash: CommonUtil.hashSignature(signature), + } + }); + }); + }); + }) + + it('accepts a transaction with account registration gas amount from balance', () => { + // NOTE: account3 does not have balance nor nonce/timestamp. + const client = jayson.client.http(server1 + '/json-rpc'); + const txBody = { + operation: { + type: 'SET_VALUE', + ref: `/transfer/${account09.address}/${account3.address}/${Date.now()}/value`, + value: 10 + }, + gas_price: 0, + timestamp: Date.now(), + nonce: -1, // unordered nonce + }; + const signature = + ainUtil.ecSignTransaction(txBody, Buffer.from(account09.private_key, 'hex')); + return client.request(JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION, { + tx_body: txBody, + signature, + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION + }) + .then((res) => { + const result = _.get(res, 'result.result', null); + expect(result).to.not.equal(null); + assert.deepEqual(res.result, { + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION, + result: { + result: { + "bandwidth_gas_amount": 1, + "code": 0, + "func_results": { + "_transfer": { + "bandwidth_gas_amount": 2000, + "code": 0, + "op_results": { + "0": { + "path": "/accounts/0x09A0d53FDf1c36A131938eb379b98910e55EEfe1/balance", + "result": { + "bandwidth_gas_amount": 1, + "code": 0 + } + }, + "1": { + "path": "/accounts/0x758fd59D3f8157Ae4458f8E29E2A8317be3d5974/balance", + "result": { + "bandwidth_gas_amount": 1, + "code": 0 + } + } + } + } + }, + "gas_amount_charged": 3281, + "gas_amount_total": { + "bandwidth": { + "service": 2003 + }, + "state": { + "service": 1278 + } + }, + "gas_cost_total": 0 + }, + tx_hash: CommonUtil.hashSignature(signature), + } + }); + }); + }) + + it('accepts a transaction with account registration gas amount from balance and non-zero gas price', () => { + // NOTE: account3 does not have balance nor nonce/timestamp. + const client = jayson.client.http(server1 + '/json-rpc'); + const txBody = { + operation: { + type: 'SET_VALUE', + ref: `/transfer/${account09.address}/${account3.address}/${Date.now()}/value`, + value: 10 + }, + gas_price: 500, // non-zero gas price + timestamp: Date.now(), + nonce: -1, // unordered nonce + }; + const signature = + ainUtil.ecSignTransaction(txBody, Buffer.from(account09.private_key, 'hex')); + return client.request(JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION, { + tx_body: txBody, + signature, + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION + }) + .then((res) => { + const result = _.get(res, 'result.result', null); + expect(result).to.not.equal(null); + assert.deepEqual(res.result, { + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION, + result: { + result: { + "bandwidth_gas_amount": 1, + "code": 0, + "func_results": { + "_transfer": { + "bandwidth_gas_amount": 2000, + "code": 0, + "op_results": { + "0": { + "path": "/accounts/0x09A0d53FDf1c36A131938eb379b98910e55EEfe1/balance", + "result": { + "bandwidth_gas_amount": 1, + "code": 0 + } + }, + "1": { + "path": "/accounts/0x758fd59D3f8157Ae4458f8E29E2A8317be3d5974/balance", + "result": { + "bandwidth_gas_amount": 1, + "code": 0 + } + } + } + } + }, + "gas_amount_charged": 3281, + "gas_amount_total": { + "bandwidth": { + "service": 2003 + }, + "state": { + "service": 1278 + } + }, + "gas_cost_total": 1.6405 + }, + tx_hash: CommonUtil.hashSignature(signature), + } + }); + }); + }) + + it('rejects a transaction with an invalid signature.', () => { + const client = jayson.client.http(server1 + '/json-rpc'); + const txBody = { + operation: { + type: 'SET_VALUE', + ref: `/apps/test/test_value/some/path`, + value: 'some other value 3' + }, + gas_price: 0, + timestamp: Date.now(), + nonce: -1 + }; + const signature = + ainUtil.ecSignTransaction(txBody, Buffer.from(account.private_key, 'hex')); + return client.request(JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION, { + tx_body: txBody, + signature: signature + '0', // invalid signature + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION + }).then((res) => { + assert.deepEqual(res.result, { + result: null, + code: 30304, + message: 'Invalid transaction signature.', + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION + }); + }) + }); + }); + describe('json-rpc api: ain_sendSignedTransaction', () => { const account = { address: "0x9534bC7529961E5737a3Dd317BdEeD41AC08a52D", @@ -3322,7 +3925,7 @@ describe('Blockchain Node', () => { operation: { type: 'SET_VALUE', ref: `/apps/test/test_value/some/path`, - value: 'some other value' + value: 'some other value 1' }, gas_price: 0, timestamp: Date.now(), @@ -3353,7 +3956,57 @@ describe('Blockchain Node', () => { }, state: { app: { - test: 24 + test: 28 + }, + service: 0 + } + }, + gas_cost_total: 0 + }, + tx_hash: CommonUtil.hashSignature(signature), + } + }); + }) + }) + + it('accepts a transaction with unordered nonce (-1) and non-zero gas_price', () => { + const client = jayson.client.http(server1 + '/json-rpc'); + const txBody = { + operation: { + type: 'SET_VALUE', + ref: `/apps/test/test_value/some/path`, + value: 'some other value 1 longer' + }, + gas_price: 500, // non-zero gas price + timestamp: Date.now(), + nonce: -1 + }; + const signature = + ainUtil.ecSignTransaction(txBody, Buffer.from(account.private_key, 'hex')); + return client.request(JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION, { + tx_body: txBody, + signature, + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION + }).then((res) => { + const result = _.get(res, 'result.result', null); + expect(result).to.not.equal(null); + assert.deepEqual(res.result, { + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION, + result: { + result: { + code: 0, + bandwidth_gas_amount: 1, + gas_amount_charged: 0, + gas_amount_total: { + bandwidth: { + app: { + test: 1 + }, + service: 0 + }, + state: { + app: { + test: 42 }, service: 0 } @@ -3425,6 +4078,65 @@ describe('Blockchain Node', () => { }); }) + it('accepts a transaction with numbered nonce and non-zero gas price', () => { + const client = jayson.client.http(server1 + '/json-rpc'); + return client.request(JSON_RPC_METHODS.AIN_GET_NONCE, { + address: account.address, + from: 'pending', + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION + }) + .then((nonceRes) => { + const nonce = _.get(nonceRes, 'result.result'); + const txBody = { + operation: { + type: 'SET_VALUE', + ref: `/apps/test/test_value/some/path`, + value: 'some other value 2 longer' + }, + gas_price: 500, // non-zero gas price + timestamp: Date.now(), + nonce, // numbered nonce + }; + const signature = + ainUtil.ecSignTransaction(txBody, Buffer.from(account.private_key, 'hex')); + return client.request(JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION, { + tx_body: txBody, + signature, + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION + }) + .then((res) => { + const result = _.get(res, 'result.result', null); + expect(result).to.not.equal(null); + assert.deepEqual(res.result, { + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION, + result: { + result: { + code: 0, + bandwidth_gas_amount: 1, + gas_amount_charged: 0, + gas_amount_total: { + bandwidth: { + app: { + test: 1 + }, + service: 0 + }, + state: { + app: { + test: 42 + }, + service: 0 + } + }, + gas_cost_total: 0, + }, + tx_hash: CommonUtil.hashSignature(signature), + } + }); + }); + }); + }) + it('accepts a transaction with account registration gas amount from nonce', () => { // NOTE: account2 does not have balance nor nonce/timestamp. const client = jayson.client.http(server1 + '/json-rpc'); @@ -3545,6 +4257,66 @@ describe('Blockchain Node', () => { }); }) + it('accepts a transaction without account registration gas amount from nonce and non-zero gas price', () => { + // NOTE: account2 already has nonce/timestamp. + const client = jayson.client.http(server1 + '/json-rpc'); + return client.request(JSON_RPC_METHODS.AIN_GET_NONCE, { + address: account2.address, + from: 'pending', + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION + }) + .then((nonceRes) => { + const nonce = _.get(nonceRes, 'result.result'); + const txBody = { + operation: { + type: 'SET_VALUE', + ref: `/apps/test/test_value/some/path`, + value: 'some other value 4 longer' + }, + gas_price: 500, // non-zero gas price + timestamp: Date.now(), + nonce, // numbered nonce + }; + const signature = + ainUtil.ecSignTransaction(txBody, Buffer.from(account2.private_key, 'hex')); + return client.request(JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION, { + tx_body: txBody, + signature, + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION + }) + .then((res) => { + const result = _.get(res, 'result.result', null); + expect(result).to.not.equal(null); + assert.deepEqual(res.result, { + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION, + result: { + result: { + code: 0, + bandwidth_gas_amount: 1, + gas_amount_charged: 0, + gas_amount_total: { + bandwidth: { + app: { + test: 1 + }, + service: 0 + }, + state: { + app: { + test: 42 + }, + service: 0 + } + }, + gas_cost_total: 0, + }, + tx_hash: CommonUtil.hashSignature(signature), + } + }); + }); + }); + }) + it('accepts a transaction without account registration gas amount from balance', () => { // NOTE: account2 does not have balance but already has nonce/timestamp. const client = jayson.client.http(server1 + '/json-rpc'); @@ -3749,6 +4521,74 @@ describe('Blockchain Node', () => { }); }) + it('accepts a transaction without account registration gas amount from balance and non-zero gas price', () => { + // NOTE: account3 already has balance. + const client = jayson.client.http(server1 + '/json-rpc'); + const txBody = { + operation: { + type: 'SET_VALUE', + ref: `/transfer/${account09.address}/${account3.address}/${Date.now()}/value`, + value: 10 + }, + gas_price: 500, // non-zero gas price + timestamp: Date.now(), + nonce: -1, // unordered nonce + }; + const signature = + ainUtil.ecSignTransaction(txBody, Buffer.from(account09.private_key, 'hex')); + return client.request(JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION, { + tx_body: txBody, + signature, + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION + }) + .then((res) => { + const result = _.get(res, 'result.result', null); + expect(result).to.not.equal(null); + assert.deepEqual(res.result, { + protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION, + result: { + result: { + "bandwidth_gas_amount": 1, + "code": 0, + "func_results": { + "_transfer": { + "bandwidth_gas_amount": 0, + "code": 0, + "op_results": { + "0": { + "path": "/accounts/0x09A0d53FDf1c36A131938eb379b98910e55EEfe1/balance", + "result": { + "bandwidth_gas_amount": 1, + "code": 0 + } + }, + "1": { + "path": "/accounts/0x758fd59D3f8157Ae4458f8E29E2A8317be3d5974/balance", + "result": { + "bandwidth_gas_amount": 1, + "code": 0 + } + } + } + } + }, + "gas_amount_charged": 367, + "gas_amount_total": { + "bandwidth": { + "service": 3 + }, + "state": { + "service": 364 + } + }, + "gas_cost_total": 0.1835 + }, + tx_hash: CommonUtil.hashSignature(signature), + } + }); + }); + }) + it('accepts a multi-set transaction with account registration gas amount from nonce', () => { // NOTE: account4 does not have balance nor nonce/timestamp. const client = jayson.client.http(server1 + '/json-rpc'); @@ -4043,7 +4883,7 @@ describe('Blockchain Node', () => { opList.push({ type: 'SET_VALUE', ref: `/apps/test/test_value/some/path`, - value: 'some other value' + value: 'some other value 9' }); } const txBody = { @@ -4122,7 +4962,7 @@ describe('Blockchain Node', () => { operation: { type: 'SET_VALUE', ref: `/apps/test/test_value/some/path`, - value: 'some other value' + value: 'some other value 10' }, gas_price: 0, timestamp: Date.now(), @@ -4150,7 +4990,7 @@ describe('Blockchain Node', () => { operation: { type: 'SET_VALUE', ref: `/apps/test/test_value/some/path`, - value: 'some other value' + value: 'some other value 11' }, gas_price: 0, timestamp: Date.now(), @@ -4178,7 +5018,7 @@ describe('Blockchain Node', () => { operation: { type: 'SET_VALUE', ref: `/apps/test/test_value/some/path`, - value: 'some other value 3' + value: 'some other value 12' }, gas_price: 0, timestamp: Date.now(), @@ -4418,7 +5258,7 @@ describe('Blockchain Node', () => { operation: { type: 'SET_VALUE', ref: `/apps/test/test_value/some/path`, - value: 'some other value' + value: 'some other value 1' }, gas_price: 0, timestamp: Date.now(), @@ -4449,7 +5289,7 @@ describe('Blockchain Node', () => { operation: { type: 'SET_VALUE', ref: `/apps/test/test_value/some/path`, - value: 'some other value' + value: 'some other value 2' }, gas_price: 0, nonce: -1 @@ -4485,7 +5325,7 @@ describe('Blockchain Node', () => { operation: { type: 'SET_VALUE', ref: `/apps/test/test_value/some/path`, - value: 'some other value' + value: 'some other value 3' }, gas_price: 0, nonce: -1 @@ -4524,7 +5364,7 @@ describe('Blockchain Node', () => { operation: { type: 'SET_VALUE', ref: `/apps/test/test_value/some/path`, - value: 'some other value' + value: 'some other value 4' }, gas_price: 0, nonce: -1 @@ -4641,7 +5481,7 @@ describe('Blockchain Node', () => { operation: { type: 'SET_VALUE', ref: `/apps/test/test_value/some/path`, - value: 'some other value' + value: 'some other value 5' }, timestamp: Date.now(), nonce: -1 @@ -4678,7 +5518,7 @@ describe('Blockchain Node', () => { operation: { type: 'SET_VALUE', ref: `/apps/test/test_value/some/path`, - value: 'some other value' + value: 'some other value 6' }, gas_price: 0, timestamp: Date.now(), @@ -4718,7 +5558,7 @@ describe('Blockchain Node', () => { operation: { type: 'SET_VALUE', ref: `/apps/test/test_value/some/path`, - value: 'some other value 3' + value: 'some other value 7' }, gas_price: 0, timestamp: Date.now(), From c0de71f853c7170b4e05e25a7504618820e469ab Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Fri, 14 Jul 2023 18:19:21 +0900 Subject: [PATCH 14/27] Tweak some logging message's level --- p2p/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/p2p/index.js b/p2p/index.js index c56126dc8..7702049b7 100644 --- a/p2p/index.js +++ b/p2p/index.js @@ -616,7 +616,8 @@ class P2pClient { } const socket = this.assignRandomPeerForChainSync(); if (!socket) { - logger.error(`[${LOG_HEADER}] Failed to get a peer for CHAIN_SEGMENT_REQUEST`); + // NOTE(platfowner): This often occurs in the early stages of start_local_blockchain.sh. + logger.info(`[${LOG_HEADER}] Failed to get a peer for CHAIN_SEGMENT_REQUEST`); return; } const lastBlockNumber = this.server.node.bc.lastBlockNumber(); From 3368c83a4bbf35684965cf59ea9aa43725e261fb Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Fri, 14 Jul 2023 21:20:53 +0900 Subject: [PATCH 15/27] Allow isDryrun = true for batch txs in executeAndBroadcastTransaction() --- p2p/server.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/p2p/server.js b/p2p/server.js index 830a1b057..e58b97211 100644 --- a/p2p/server.js +++ b/p2p/server.js @@ -818,8 +818,7 @@ class P2pServer { continue; } - // NOTE(platfowner): There is no dryrun mode for batch transactions. - const result = this.node.executeTransactionAndAddToPool(subTx); + const result = this.node.executeTransactionAndAddToPool(subTx, isDryrun); resultList.push({ tx_hash: subTx.hash, result @@ -829,7 +828,7 @@ class P2pServer { } } logger.debug(`\n BATCH TX RESULT: ` + JSON.stringify(resultList)); - if (txListSucceeded.length > 0) { + if (!isDryrun && txListSucceeded.length > 0) { this.client.broadcastTransaction({ tx_list: txListSucceeded }, tags); } From e6bd982aaeaec961154ea6c5237fea433e8f9112 Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Sat, 15 Jul 2023 01:15:19 +0900 Subject: [PATCH 16/27] Rename: ain_dryrunSignedTransaction -> ain_sendSignedTransactionDryrun --- json_rpc/constants.js | 2 +- json_rpc/transaction.js | 2 +- test/integration/node.test.js | 20 ++++++------ ...executeTransferTx.js => sendTransferTx.js} | 32 +++++++++---------- tools/util.js | 16 +++++----- 5 files changed, 36 insertions(+), 36 deletions(-) rename tools/transfer/{executeTransferTx.js => sendTransferTx.js} (57%) diff --git a/json_rpc/constants.js b/json_rpc/constants.js index 0aeed83dc..cf193b800 100644 --- a/json_rpc/constants.js +++ b/json_rpc/constants.js @@ -1,7 +1,6 @@ const JSON_RPC_METHODS = { AIN_ADD_TO_WHITELIST_NODE_PARAM: 'ain_addToWhitelistNodeParam', AIN_CHECK_PROTOCOL_VERSION: 'ain_checkProtocolVersion', - AIN_DRYRUN_SIGNED_TRANSACTION: 'ain_dryrunSignedTransaction', AIN_EVAL_RULE: 'ain_evalRule', AIN_EVAL_OWNER: 'ain_evalOwner', AIN_GET: 'ain_get', @@ -43,6 +42,7 @@ const JSON_RPC_METHODS = { AIN_MATCH_OWNER: 'ain_matchOwner', AIN_MATCH_RULE: 'ain_matchRule', AIN_REMOVE_FROM_WHITELIST_NODE_PARAM: 'ain_removeFromWhitelistNodeParam', + AIN_SEND_SIGNED_TRANSACTION_DRYRUN: 'ain_sendSignedTransactionDryrun', AIN_SEND_SIGNED_TRANSACTION: 'ain_sendSignedTransaction', AIN_SEND_SIGNED_TRANSACTION_BATCH: 'ain_sendSignedTransactionBatch', AIN_SET_NODE_PARAM: 'ain_setNodeParam', diff --git a/json_rpc/transaction.js b/json_rpc/transaction.js index efdb8435d..1b13b0a39 100644 --- a/json_rpc/transaction.js +++ b/json_rpc/transaction.js @@ -124,7 +124,7 @@ module.exports = function getTransactionApis(node, p2pServer) { done(null, JsonRpcUtil.addProtocolVersion({ result })); }, - [JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION]: function(args, done) { + [JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION_DRYRUN]: function(args, done) { executeTransactionOnNode(node, p2pServer, args, done, true); }, diff --git a/test/integration/node.test.js b/test/integration/node.test.js index f94851f63..0dcaf266c 100644 --- a/test/integration/node.test.js +++ b/test/integration/node.test.js @@ -3216,7 +3216,7 @@ describe('Blockchain Node', () => { }) }) - describe('json-rpc api: ain_dryrunSignedTransaction', () => { + describe('json-rpc api: ain_sendSignedTransactionDryrun', () => { const account = { address: "0x9534bC7529961E5737a3Dd317BdEeD41AC08a52D", private_key: "e96292ef0676287908fc3461f747f106b7b9336f183b1766f83672fbe893664d", @@ -3330,7 +3330,7 @@ describe('Blockchain Node', () => { }; const signature = ainUtil.ecSignTransaction(txBody, Buffer.from(account.private_key, 'hex')); - return client.request(JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION, { + return client.request(JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION_DRYRUN, { tx_body: txBody, signature, protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION @@ -3380,7 +3380,7 @@ describe('Blockchain Node', () => { }; const signature = ainUtil.ecSignTransaction(txBody, Buffer.from(account.private_key, 'hex')); - return client.request(JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION, { + return client.request(JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION_DRYRUN, { tx_body: txBody, signature, protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION @@ -3437,7 +3437,7 @@ describe('Blockchain Node', () => { }; const signature = ainUtil.ecSignTransaction(txBody, Buffer.from(account.private_key, 'hex')); - return client.request(JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION, { + return client.request(JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION_DRYRUN, { tx_body: txBody, signature, protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION @@ -3496,7 +3496,7 @@ describe('Blockchain Node', () => { }; const signature = ainUtil.ecSignTransaction(txBody, Buffer.from(account.private_key, 'hex')); - return client.request(JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION, { + return client.request(JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION_DRYRUN, { tx_body: txBody, signature, protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION @@ -3556,7 +3556,7 @@ describe('Blockchain Node', () => { }; const signature = ainUtil.ecSignTransaction(txBody, Buffer.from(account2.private_key, 'hex')); - return client.request(JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION, { + return client.request(JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION_DRYRUN, { tx_body: txBody, signature, protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION @@ -3616,7 +3616,7 @@ describe('Blockchain Node', () => { }; const signature = ainUtil.ecSignTransaction(txBody, Buffer.from(account2.private_key, 'hex')); - return client.request(JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION, { + return client.request(JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION_DRYRUN, { tx_body: txBody, signature, protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION @@ -3669,7 +3669,7 @@ describe('Blockchain Node', () => { }; const signature = ainUtil.ecSignTransaction(txBody, Buffer.from(account09.private_key, 'hex')); - return client.request(JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION, { + return client.request(JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION_DRYRUN, { tx_body: txBody, signature, protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION @@ -3737,7 +3737,7 @@ describe('Blockchain Node', () => { }; const signature = ainUtil.ecSignTransaction(txBody, Buffer.from(account09.private_key, 'hex')); - return client.request(JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION, { + return client.request(JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION_DRYRUN, { tx_body: txBody, signature, protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION @@ -3804,7 +3804,7 @@ describe('Blockchain Node', () => { }; const signature = ainUtil.ecSignTransaction(txBody, Buffer.from(account.private_key, 'hex')); - return client.request(JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION, { + return client.request(JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION_DRYRUN, { tx_body: txBody, signature: signature + '0', // invalid signature protoVer: BlockchainConsts.CURRENT_PROTOCOL_VERSION diff --git a/tools/transfer/executeTransferTx.js b/tools/transfer/sendTransferTx.js similarity index 57% rename from tools/transfer/executeTransferTx.js rename to tools/transfer/sendTransferTx.js index da1dff28f..87ae51c9d 100644 --- a/tools/transfer/executeTransferTx.js +++ b/tools/transfer/sendTransferTx.js @@ -3,7 +3,7 @@ const ainUtil = require('@ainblockchain/ain-util'); const CommonUtil = require('../../common/common-util'); const { getAccountPrivateKey, - signAndDryrunTx, + signAndSendTxDryrun, signAndSendTx, confirmTransaction } = require('../util'); @@ -21,8 +21,8 @@ function buildTransferTxBody(fromAddr, toAddr, key, amount, timestamp) { } } -async function executeTransaction(endpointUrl, chainId, toAddr, ainAmount, account, isDryrun) { - console.log('\n*** executeTransaction():'); +async function sendTransaction(endpointUrl, chainId, toAddr, ainAmount, account, isDryrun) { + console.log('\n*** sendTransaction():'); const timestamp = Date.now(); const txBody = @@ -31,7 +31,7 @@ async function executeTransaction(endpointUrl, chainId, toAddr, ainAmount, accou let txInfo = null; if (isDryrun) { - txInfo = await signAndDryrunTx(endpointUrl, txBody, account.private_key, chainId); + txInfo = await signAndSendTxDryrun(endpointUrl, txBody, account.private_key, chainId); } else { txInfo = await signAndSendTx(endpointUrl, txBody, account.private_key, chainId); } @@ -45,12 +45,12 @@ async function executeTransaction(endpointUrl, chainId, toAddr, ainAmount, accou } } -async function executeTransferTx( +async function sendTransferTx( endpointUrl, chainId, toAddr, ainAmount, accountType, keystoreFilepath, isDryrun) { const privateKey = await getAccountPrivateKey(accountType, keystoreFilepath); const account = ainUtil.privateToAccount(Buffer.from(privateKey, 'hex')); console.log(`\nFrom-address: ${account.address}\n`); - await executeTransaction(endpointUrl, chainId, toAddr, ainAmount, account, isDryrun); + await sendTransaction(endpointUrl, chainId, toAddr, ainAmount, account, isDryrun); } async function processArguments() { @@ -86,19 +86,19 @@ async function processArguments() { } } const isDryrun = dryrunOption === '--dryrun'; - await executeTransferTx(endpointUrl, chainId, toAddr, ainAmount, accountType, keystoreFilepath, isDryrun); + await sendTransferTx(endpointUrl, chainId, toAddr, ainAmount, accountType, keystoreFilepath, isDryrun); } function usage() { - console.log('\nUsage: node executeTransferTx.js [] [--dryrun]\n'); - console.log('Example: node executeTransferTx.js http://localhost:8081 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 private_key'); - console.log('Example: node executeTransferTx.js http://localhost:8081 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 mnemonic'); - console.log('Example: node executeTransferTx.js http://localhost:8081 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json'); - console.log('Example: node executeTransferTx.js http://localhost:8081 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json --dryrun'); - console.log('Example: node executeTransferTx.js https://staging-api.ainetwork.ai 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json'); - console.log('Example: node executeTransferTx.js https://testnet-api.ainetwork.ai 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json'); - console.log('Example: node executeTransferTx.js https://mainnet-api.ainetwork.ai 1 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json\n'); - console.log('Example: node executeTransferTx.js https://mainnet-api.ainetwork.ai 1 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json --dryrun\n'); + console.log('\nUsage: node sendTransferTx.js [] [--dryrun]\n'); + console.log('Example: node sendTransferTx.js http://localhost:8081 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 private_key'); + console.log('Example: node sendTransferTx.js http://localhost:8081 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 mnemonic'); + console.log('Example: node sendTransferTx.js http://localhost:8081 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json'); + console.log('Example: node sendTransferTx.js http://localhost:8081 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json --dryrun'); + console.log('Example: node sendTransferTx.js https://staging-api.ainetwork.ai 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json'); + console.log('Example: node sendTransferTx.js https://testnet-api.ainetwork.ai 0 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json'); + console.log('Example: node sendTransferTx.js https://mainnet-api.ainetwork.ai 1 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json\n'); + console.log('Example: node sendTransferTx.js https://mainnet-api.ainetwork.ai 1 0x08Aed7AF9354435c38d52143EE50ac839D20696b 10 keystore keystore_from_account.json --dryrun\n'); process.exit(0) } diff --git a/tools/util.js b/tools/util.js index 3fe935968..677f4d561 100644 --- a/tools/util.js +++ b/tools/util.js @@ -87,11 +87,11 @@ async function keystoreToAccount(filePath) { return ainUtil.privateToAccount(ainUtil.v3KeystoreToPrivate(keystore, input.password)); } -function signAndExecuteTx(endpointUrl, txBody, privateKey, chainId, jsonRpcMethod) { +function signAndSendTx(endpointUrl, txBody, privateKey, chainId, jsonRpcMethod) { const { txHash, signedTx } = CommonUtil.signTransaction(txBody, privateKey, chainId); console.log(`signedTx: ${JSON.stringify(signedTx, null, 2)}`); console.log(`txHash: ${txHash}`); - console.log('Executing transaction...'); + console.log('Sending transaction...'); return axios.post( `${endpointUrl}/json-rpc`, @@ -113,15 +113,15 @@ function signAndExecuteTx(endpointUrl, txBody, privateKey, chainId, jsonRpcMetho }); } -function signAndDryrunTx(endpointUrl, txBody, privateKey, chainId) { - console.log('\n*** signAndDryrunTx():'); - return signAndExecuteTx( - endpointUrl, txBody, privateKey, chainId, JSON_RPC_METHODS.AIN_DRYRUN_SIGNED_TRANSACTION); +function signAndSendTxDryrun(endpointUrl, txBody, privateKey, chainId) { + console.log('\n*** signAndSendTxDryrun():'); + return signAndSendTx( + endpointUrl, txBody, privateKey, chainId, JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION_DRYRUN); } function signAndSendTx(endpointUrl, txBody, privateKey, chainId) { console.log('\n*** signAndSendTx():'); - return signAndExecuteTx( + return signAndSendTx( endpointUrl, txBody, privateKey, chainId, JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION); } @@ -162,7 +162,7 @@ async function confirmTransaction(endpointUrl, timestamp, txHash) { module.exports = { getAccountPrivateKey, keystoreToAccount, - signAndDryrunTx, + signAndSendTxDryrun, signAndSendTx, sendGetTxByHashRequest, confirmTransaction, From df394f0336565a56d3cf1a1872aa592e57e19a30 Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Mon, 17 Jul 2023 13:06:44 +0900 Subject: [PATCH 17/27] Add a todo for dev client api deprecation --- client/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/index.js b/client/index.js index 29bb701c4..26d6a5e55 100755 --- a/client/index.js +++ b/client/index.js @@ -673,7 +673,8 @@ app.get('/get_config', (req, res) => { /** * Dev Client SET APIs (available to whitelisted IPs, if ENABLE_DEV_CLIENT_SET_API == true) */ - +// TODO(platfowner): Deprecate Dev Client SET APIs once the related test cases are migrated to +// json rpc APIs. if (NodeConfigs.ENABLE_DEV_CLIENT_SET_API) { app.post('/set_value', (req, res, next) => { const beginTime = Date.now(); From b440201e0693649da90fddb2be707e37d17aec22 Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Mon, 17 Jul 2023 13:07:32 +0900 Subject: [PATCH 18/27] Rename a function --- json_rpc/transaction.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/json_rpc/transaction.js b/json_rpc/transaction.js index 1b13b0a39..ac8b61294 100644 --- a/json_rpc/transaction.js +++ b/json_rpc/transaction.js @@ -10,7 +10,7 @@ const CommonUtil = require('../common/common-util'); const Transaction = require('../tx-pool/transaction'); const { JSON_RPC_METHODS } = require('./constants'); -function executeTransactionOnNode(node, p2pServer, args, done, isDryrun) { +function sendTransactionOnNode(node, p2pServer, args, done, isDryrun) { const beginTime = Date.now(); const txBytesLimit = node.getBlockchainParam('resource/tx_bytes_limit'); if (sizeof(args) > txBytesLimit) { @@ -125,11 +125,11 @@ module.exports = function getTransactionApis(node, p2pServer) { }, [JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION_DRYRUN]: function(args, done) { - executeTransactionOnNode(node, p2pServer, args, done, true); + sendTransactionOnNode(node, p2pServer, args, done, true); }, [JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION]: function(args, done) { - executeTransactionOnNode(node, p2pServer, args, done, false); + sendTransactionOnNode(node, p2pServer, args, done, false); }, [JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION_BATCH]: function(args, done) { From 9f1c76c934f2f2cfa939fa32f6bae807f4081a3a Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Mon, 17 Jul 2023 13:08:05 +0900 Subject: [PATCH 19/27] Set is_dryrun = true in dryrun transaction results --- db/index.js | 3 +++ test/integration/node.test.js | 16 ++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/db/index.js b/db/index.js index c8f925274..29983cb65 100644 --- a/db/index.js +++ b/db/index.js @@ -1979,6 +1979,9 @@ class DB { const timestamp = txBody.timestamp; const executionResult = this.executeOperation( txBody.operation, auth, nonce, timestamp, tx, blockNumber, blockTime, eventSource); + if (isDryrun && executionResult) { + executionResult.is_dryrun = true; // Set is_dryrun = true + } if (!skipFees) { if (DevFlags.enableGasFeeCollection) { this.collectFee( diff --git a/test/integration/node.test.js b/test/integration/node.test.js index 0dcaf266c..8c324c975 100644 --- a/test/integration/node.test.js +++ b/test/integration/node.test.js @@ -3358,7 +3358,8 @@ describe('Blockchain Node', () => { service: 0 } }, - gas_cost_total: 0 + gas_cost_total: 0, + is_dryrun: true }, tx_hash: CommonUtil.hashSignature(signature), } @@ -3408,7 +3409,8 @@ describe('Blockchain Node', () => { service: 0 } }, - gas_cost_total: 0 + gas_cost_total: 0, + is_dryrun: true }, tx_hash: CommonUtil.hashSignature(signature), } @@ -3467,6 +3469,7 @@ describe('Blockchain Node', () => { } }, gas_cost_total: 0, + is_dryrun: true }, tx_hash: CommonUtil.hashSignature(signature), } @@ -3526,6 +3529,7 @@ describe('Blockchain Node', () => { } }, gas_cost_total: 0, + is_dryrun: true }, tx_hash: CommonUtil.hashSignature(signature), } @@ -3586,6 +3590,7 @@ describe('Blockchain Node', () => { } }, gas_cost_total: 0, + is_dryrun: true }, tx_hash: CommonUtil.hashSignature(signature), } @@ -3646,6 +3651,7 @@ describe('Blockchain Node', () => { } }, gas_cost_total: 0, + is_dryrun: true }, tx_hash: CommonUtil.hashSignature(signature), } @@ -3714,7 +3720,8 @@ describe('Blockchain Node', () => { "service": 1278 } }, - "gas_cost_total": 0 + "gas_cost_total": 0, + "is_dryrun": true }, tx_hash: CommonUtil.hashSignature(signature), } @@ -3782,7 +3789,8 @@ describe('Blockchain Node', () => { "service": 1278 } }, - "gas_cost_total": 1.6405 + "gas_cost_total": 1.6405, + "is_dryrun": true }, tx_hash: CommonUtil.hashSignature(signature), } From eb1ea88bb8270d4af52e21da6dc52fb5600d978c Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Mon, 17 Jul 2023 17:59:18 +0900 Subject: [PATCH 20/27] Guard bandage info logging with LOG_BANDAGE_INFO env variable --- common/common-util.js | 12 +++++++++--- start_node_docker.sh | 2 ++ start_node_genesis_gcp.sh | 2 ++ start_node_incremental_gcp.sh | 2 ++ 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/common/common-util.js b/common/common-util.js index f1ac71d54..df816c836 100644 --- a/common/common-util.js +++ b/common/common-util.js @@ -1057,7 +1057,9 @@ class CommonUtil { static createTimerFlagEnabledBandageMap(timerFlags) { const LOG_HEADER = 'createTimerFlagEnabledBandageMap'; const map = new Map(); - console.log(`[${LOG_HEADER}] Registering bandage files:`); + if (process.env.LOG_BANDAGE_INFO) { + console.log(`[${LOG_HEADER}] Registering bandage files:`); + } const flagNameList = Object.keys(timerFlags); for (let i = 0; i < flagNameList.length; i++) { const flagName = flagNameList[i]; @@ -1065,7 +1067,9 @@ class CommonUtil { const enabledBlockNumber = CommonUtil.getEnabledBlockNumberFromTimerFlag(flag); if (CommonUtil.isNumber(enabledBlockNumber) && flag['has_bandage'] === true) { const bandageFilePath = path.resolve(__dirname, '../db/bandage-files', `${flagName}.js`); - console.log(`[${LOG_HEADER}] [${i}] Registering ${bandageFilePath}`); + if (process.env.LOG_BANDAGE_INFO) { + console.log(`[${LOG_HEADER}] [${i}] Registering ${bandageFilePath}`); + } if (!fs.existsSync(bandageFilePath)) { throw Error(`Missing bandage file: ${bandageFilePath}`); } @@ -1074,7 +1078,9 @@ class CommonUtil { } map.get(enabledBlockNumber).push(flagName); } else { - console.log(`[${LOG_HEADER}] [${i}] Skipping for timer flag: ${flagName}`); + if (process.env.LOG_BANDAGE_INFO) { + console.log(`[${LOG_HEADER}] [${i}] Skipping for timer flag: ${flagName}`); + } } } return map; diff --git a/start_node_docker.sh b/start_node_docker.sh index 11e7073e2..e94b8b0b4 100644 --- a/start_node_docker.sh +++ b/start_node_docker.sh @@ -15,6 +15,8 @@ elif [[ $SEASON = 'exp' ]]; then elif [[ $SEASON = 'dev' ]]; then export BLOCKCHAIN_CONFIGS_DIR=blockchain-configs/testnet-dev fi +export LOG_BANDAGE_INFO=true +printf "LOG_BANDAGE_INFO=$LOG_BANDAGE_INFO\n" nohup node --max-old-space-size=55000 ./client/index.js 2>error_logs.txt & diff --git a/start_node_genesis_gcp.sh b/start_node_genesis_gcp.sh index 79af1791f..6c5cbd39f 100644 --- a/start_node_genesis_gcp.sh +++ b/start_node_genesis_gcp.sh @@ -313,6 +313,8 @@ printf "STAKE=$STAKE\n" # uncomment and set value when necessary #export TIMER_FLAG_EARLY_APPLIED_BLOCK_NUMBER=124440 # summer #printf "TIMER_FLAG_EARLY_APPLIED_BLOCK_NUMBER=$TIMER_FLAG_EARLY_APPLIED_BLOCK_NUMBER\n" +export LOG_BANDAGE_INFO=true +printf "LOG_BANDAGE_INFO=$LOG_BANDAGE_INFO\n" if [[ "$SEASON" = "sandbox" ]]; then MAX_OLD_SPACE_SIZE_MB=11000 diff --git a/start_node_incremental_gcp.sh b/start_node_incremental_gcp.sh index 1c5b472a1..db8bf3a9e 100644 --- a/start_node_incremental_gcp.sh +++ b/start_node_incremental_gcp.sh @@ -369,6 +369,8 @@ printf "\n#### [Step 7] Start new node server ####\n\n" export STAKE=100000 printf "STAKE=$STAKE\n" +export LOG_BANDAGE_INFO=true +printf "LOG_BANDAGE_INFO=$LOG_BANDAGE_INFO\n" if [[ "$SEASON" = "sandbox" ]]; then MAX_OLD_SPACE_SIZE_MB=11000 From 2a8a9dac9a04b4f2715c09ccce660fad5cea6654 Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Mon, 17 Jul 2023 21:03:58 +0900 Subject: [PATCH 21/27] Fix function name conflict --- tools/util.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/util.js b/tools/util.js index 677f4d561..972c80c46 100644 --- a/tools/util.js +++ b/tools/util.js @@ -87,7 +87,7 @@ async function keystoreToAccount(filePath) { return ainUtil.privateToAccount(ainUtil.v3KeystoreToPrivate(keystore, input.password)); } -function signAndSendTx(endpointUrl, txBody, privateKey, chainId, jsonRpcMethod) { +function signAndSendTxWithJsonRpcMethod(endpointUrl, txBody, privateKey, chainId, jsonRpcMethod) { const { txHash, signedTx } = CommonUtil.signTransaction(txBody, privateKey, chainId); console.log(`signedTx: ${JSON.stringify(signedTx, null, 2)}`); console.log(`txHash: ${txHash}`); @@ -115,13 +115,13 @@ function signAndSendTx(endpointUrl, txBody, privateKey, chainId, jsonRpcMethod) function signAndSendTxDryrun(endpointUrl, txBody, privateKey, chainId) { console.log('\n*** signAndSendTxDryrun():'); - return signAndSendTx( + return signAndSendTxWithJsonRpcMethod( endpointUrl, txBody, privateKey, chainId, JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION_DRYRUN); } function signAndSendTx(endpointUrl, txBody, privateKey, chainId) { console.log('\n*** signAndSendTx():'); - return signAndSendTx( + return signAndSendTxWithJsonRpcMethod( endpointUrl, txBody, privateKey, chainId, JSON_RPC_METHODS.AIN_SEND_SIGNED_TRANSACTION); } From f5484786af01d5af02777536bc8cc56945bf3a4a Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Tue, 18 Jul 2023 00:56:00 +0900 Subject: [PATCH 22/27] mkdir blockchain data dir always under the package root dir --- common/constants.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/common/constants.js b/common/constants.js index 163e47571..8995a68fc 100644 --- a/common/constants.js +++ b/common/constants.js @@ -116,17 +116,18 @@ function setNodeConfigs() { NodeConfigs[param] = valFromNodeParams; } } - if (!fs.existsSync(NodeConfigs.BLOCKCHAIN_DATA_DIR)) { + const blockchainDataDirPath = path.resolve(__dirname, '../', NodeConfigs.BLOCKCHAIN_DATA_DIR); + if (!fs.existsSync(blockchainDataDirPath)) { try { - fs.mkdirSync(NodeConfigs.BLOCKCHAIN_DATA_DIR, { recursive: true }); + fs.mkdirSync(blockchainDataDirPath, { recursive: true }); } catch (e) { console.log(e) } } - NodeConfigs.LOGS_DIR = path.resolve(NodeConfigs.BLOCKCHAIN_DATA_DIR, 'logs'); - NodeConfigs.CHAINS_DIR = path.resolve(NodeConfigs.BLOCKCHAIN_DATA_DIR, 'chains'); - NodeConfigs.SNAPSHOTS_ROOT_DIR = path.resolve(NodeConfigs.BLOCKCHAIN_DATA_DIR, 'snapshots'); - NodeConfigs.KEYS_ROOT_DIR = path.resolve(NodeConfigs.BLOCKCHAIN_DATA_DIR, 'keys'); + NodeConfigs.LOGS_DIR = path.resolve(blockchainDataDirPath, 'logs'); + NodeConfigs.CHAINS_DIR = path.resolve(blockchainDataDirPath, 'chains'); + NodeConfigs.SNAPSHOTS_ROOT_DIR = path.resolve(blockchainDataDirPath, 'snapshots'); + NodeConfigs.KEYS_ROOT_DIR = path.resolve(blockchainDataDirPath, 'keys'); } setNodeConfigs(); From 874b2dc90d508cbf6a7e78357c652fa0f16ce66d Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Tue, 18 Jul 2023 01:02:54 +0900 Subject: [PATCH 23/27] Log bandage info in local blockchain runs --- start_local_blockchain.sh | 3 +++ start_local_blockchain_afan_shard.sh | 6 ++++++ start_local_blockchain_multi_shards.sh | 9 +++++++++ 3 files changed, 18 insertions(+) diff --git a/start_local_blockchain.sh b/start_local_blockchain.sh index 363529091..df5efc6e1 100755 --- a/start_local_blockchain.sh +++ b/start_local_blockchain.sh @@ -23,6 +23,7 @@ UNSAFE_PRIVATE_KEY=b22c95ffc4a5c096f7d7d0487ba963ce6ac945bdc91c79b64ce209de289be P2P_PORT=5001 \ STAKE=100000 \ CONSOLE_LOG=true \ + LOG_BANDAGE_INFO=true \ ENABLE_REST_FUNCTION_CALL=true \ ENABLE_TX_SIG_VERIF_WORKAROUND=true \ ENABLE_GAS_FEE_WORKAROUND=true \ @@ -38,6 +39,7 @@ UNSAFE_PRIVATE_KEY=921cc48e48c876fc6ed1eb02a76ad520e8d16a91487f9c7e03441da8e35a0 P2P_PORT=5002 \ STAKE=100000 \ CONSOLE_LOG=true \ + LOG_BANDAGE_INFO=true \ ENABLE_REST_FUNCTION_CALL=true \ ENABLE_TX_SIG_VERIF_WORKAROUND=true \ ENABLE_GAS_FEE_WORKAROUND=true \ @@ -53,6 +55,7 @@ UNSAFE_PRIVATE_KEY=41e6e5718188ce9afd25e4b386482ac2c5272c49a622d8d217887bce21dce P2P_PORT=5003 \ STAKE=100000 \ CONSOLE_LOG=true \ + LOG_BANDAGE_INFO=true \ ENABLE_REST_FUNCTION_CALL=true \ ENABLE_TX_SIG_VERIF_WORKAROUND=true \ ENABLE_GAS_FEE_WORKAROUND=true \ diff --git a/start_local_blockchain_afan_shard.sh b/start_local_blockchain_afan_shard.sh index a4dd4b59a..449d8bbe0 100755 --- a/start_local_blockchain_afan_shard.sh +++ b/start_local_blockchain_afan_shard.sh @@ -20,6 +20,7 @@ UNSAFE_PRIVATE_KEY=b22c95ffc4a5c096f7d7d0487ba963ce6ac945bdc91c79b64ce209de289be PORT=8081 \ P2P_PORT=5001 \ CONSOLE_LOG=true \ + LOG_BANDAGE_INFO=true \ ENABLE_REST_FUNCTION_CALL=true \ ENABLE_TX_SIG_VERIF_WORKAROUND=true \ ENABLE_GAS_FEE_WORKAROUND=true \ @@ -33,6 +34,7 @@ UNSAFE_PRIVATE_KEY=921cc48e48c876fc6ed1eb02a76ad520e8d16a91487f9c7e03441da8e35a0 PORT=8082 \ P2P_PORT=5002 \ CONSOLE_LOG=true \ + LOG_BANDAGE_INFO=true \ ENABLE_REST_FUNCTION_CALL=true \ ENABLE_TX_SIG_VERIF_WORKAROUND=true \ ENABLE_GAS_FEE_WORKAROUND=true \ @@ -46,6 +48,7 @@ UNSAFE_PRIVATE_KEY=41e6e5718188ce9afd25e4b386482ac2c5272c49a622d8d217887bce21dce PORT=8083 \ P2P_PORT=5003 \ CONSOLE_LOG=true \ + LOG_BANDAGE_INFO=true \ ENABLE_REST_FUNCTION_CALL=true \ ENABLE_TX_SIG_VERIF_WORKAROUND=true \ ENABLE_GAS_FEE_WORKAROUND=true \ @@ -71,6 +74,7 @@ BLOCKCHAIN_CONFIGS_DIR=blockchain-configs/afan-shard \ P2P_PORT=6001 \ UNSAFE_PRIVATE_KEY=d8f77aa2afe2580a858a8cc97b6056e10f888c6fd07ebb58755d8422b03da816 \ CONSOLE_LOG=true \ + LOG_BANDAGE_INFO=true \ ENABLE_REST_FUNCTION_CALL=true \ ENABLE_TX_SIG_VERIF_WORKAROUND=true \ ENABLE_GAS_FEE_WORKAROUND=true \ @@ -97,6 +101,7 @@ BLOCKCHAIN_CONFIGS_DIR=blockchain-configs/afan-shard \ P2P_PORT=6002 \ UNSAFE_PRIVATE_KEY=a3409e22bc14a3d0e73697df25617b3f2eaae9b5eade77615a32abc0ad5ee0df \ CONSOLE_LOG=true \ + LOG_BANDAGE_INFO=true \ ENABLE_REST_FUNCTION_CALL=true \ ENABLE_TX_SIG_VERIF_WORKAROUND=true \ ENABLE_GAS_FEE_WORKAROUND=true \ @@ -111,6 +116,7 @@ BLOCKCHAIN_CONFIGS_DIR=blockchain-configs/afan-shard \ P2P_PORT=6003 \ UNSAFE_PRIVATE_KEY=c4611582dbb5319f08ba0907af6430a79e02b87b112aa4039d43e8765384f568 \ CONSOLE_LOG=true \ + LOG_BANDAGE_INFO=true \ ENABLE_REST_FUNCTION_CALL=true \ ENABLE_TX_SIG_VERIF_WORKAROUND=true \ ENABLE_GAS_FEE_WORKAROUND=true \ diff --git a/start_local_blockchain_multi_shards.sh b/start_local_blockchain_multi_shards.sh index fe35ceb63..22fd03fc7 100755 --- a/start_local_blockchain_multi_shards.sh +++ b/start_local_blockchain_multi_shards.sh @@ -22,6 +22,7 @@ UNSAFE_PRIVATE_KEY=b22c95ffc4a5c096f7d7d0487ba963ce6ac945bdc91c79b64ce209de289be P2P_PORT=5001 \ STAKE=100000 \ CONSOLE_LOG=true \ + LOG_BANDAGE_INFO=true \ ENABLE_REST_FUNCTION_CALL=true \ ENABLE_TX_SIG_VERIF_WORKAROUND=true \ ENABLE_GAS_FEE_WORKAROUND=true \ @@ -36,6 +37,7 @@ UNSAFE_PRIVATE_KEY=921cc48e48c876fc6ed1eb02a76ad520e8d16a91487f9c7e03441da8e35a0 P2P_PORT=5002 \ STAKE=100000 \ CONSOLE_LOG=true \ + LOG_BANDAGE_INFO=true \ ENABLE_REST_FUNCTION_CALL=true \ ENABLE_TX_SIG_VERIF_WORKAROUND=true \ ENABLE_GAS_FEE_WORKAROUND=true \ @@ -50,6 +52,7 @@ UNSAFE_PRIVATE_KEY=41e6e5718188ce9afd25e4b386482ac2c5272c49a622d8d217887bce21dce P2P_PORT=5003 \ STAKE=100000 \ CONSOLE_LOG=true \ + LOG_BANDAGE_INFO=true \ ENABLE_REST_FUNCTION_CALL=true \ ENABLE_TX_SIG_VERIF_WORKAROUND=true \ ENABLE_GAS_FEE_WORKAROUND=true \ @@ -76,6 +79,7 @@ BLOCKCHAIN_CONFIGS_DIR=blockchain-configs/afan-shard \ UNSAFE_PRIVATE_KEY=d8f77aa2afe2580a858a8cc97b6056e10f888c6fd07ebb58755d8422b03da816 \ STAKE=100000 \ CONSOLE_LOG=true \ + LOG_BANDAGE_INFO=true \ ENABLE_REST_FUNCTION_CALL=true \ ENABLE_TX_SIG_VERIF_WORKAROUND=true \ ENABLE_GAS_FEE_WORKAROUND=true \ @@ -103,6 +107,7 @@ BLOCKCHAIN_CONFIGS_DIR=blockchain-configs/afan-shard \ UNSAFE_PRIVATE_KEY=a3409e22bc14a3d0e73697df25617b3f2eaae9b5eade77615a32abc0ad5ee0df \ STAKE=100000 \ CONSOLE_LOG=true \ + LOG_BANDAGE_INFO=true \ ENABLE_REST_FUNCTION_CALL=true \ ENABLE_TX_SIG_VERIF_WORKAROUND=true \ ENABLE_GAS_FEE_WORKAROUND=true \ @@ -118,6 +123,7 @@ BLOCKCHAIN_CONFIGS_DIR=blockchain-configs/afan-shard \ UNSAFE_PRIVATE_KEY=c4611582dbb5319f08ba0907af6430a79e02b87b112aa4039d43e8765384f568 \ STAKE=100000 \ CONSOLE_LOG=true \ + LOG_BANDAGE_INFO=true \ ENABLE_REST_FUNCTION_CALL=true \ ENABLE_TX_SIG_VERIF_WORKAROUND=true \ ENABLE_GAS_FEE_WORKAROUND=true \ @@ -144,6 +150,7 @@ BLOCKCHAIN_CONFIGS_DIR=blockchain-configs/sim-shard \ UNSAFE_PRIVATE_KEY=275dac1207d58d7015b6b55dd13432337aabbb044635e447e819172daba7a69d \ STAKE=100000 \ CONSOLE_LOG=true \ + LOG_BANDAGE_INFO=true \ ENABLE_REST_FUNCTION_CALL=true \ ENABLE_TX_SIG_VERIF_WORKAROUND=true \ ENABLE_GAS_FEE_WORKAROUND=true \ @@ -171,6 +178,7 @@ BLOCKCHAIN_CONFIGS_DIR=blockchain-configs/sim-shard \ UNSAFE_PRIVATE_KEY=0d8073dc0ee25ea154762feffa601d83191d3c8f4d7a208dd5b9ce376e414cc2 \ STAKE=100000 \ CONSOLE_LOG=true \ + LOG_BANDAGE_INFO=true \ ENABLE_REST_FUNCTION_CALL=true \ ENABLE_TX_SIG_VERIF_WORKAROUND=true \ ENABLE_GAS_FEE_WORKAROUND=true \ @@ -186,6 +194,7 @@ BLOCKCHAIN_CONFIGS_DIR=blockchain-configs/sim-shard \ UNSAFE_PRIVATE_KEY=0e9b552ee38b0bc370b509b4705bae50e289acb641d9af9960e5e7604907961b \ STAKE=100000 \ CONSOLE_LOG=true \ + LOG_BANDAGE_INFO=true \ ENABLE_REST_FUNCTION_CALL=true \ ENABLE_TX_SIG_VERIF_WORKAROUND=true \ ENABLE_GAS_FEE_WORKAROUND=true \ From 6a528b2d6cf09eaa15009e5f4d254d5620131fda Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Tue, 18 Jul 2023 02:19:37 +0900 Subject: [PATCH 24/27] Fix console logging --- common/constants.js | 2 +- logger/index.js | 5 ++--- start_node_genesis_gcp.sh | 4 ++-- start_tracker_genesis_gcp.sh | 1 - 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/common/constants.js b/common/constants.js index 8995a68fc..a4106c79a 100644 --- a/common/constants.js +++ b/common/constants.js @@ -116,7 +116,7 @@ function setNodeConfigs() { NodeConfigs[param] = valFromNodeParams; } } - const blockchainDataDirPath = path.resolve(__dirname, '../', NodeConfigs.BLOCKCHAIN_DATA_DIR); + const blockchainDataDirPath = path.resolve(__dirname, '..', NodeConfigs.BLOCKCHAIN_DATA_DIR); if (!fs.existsSync(blockchainDataDirPath)) { try { fs.mkdirSync(blockchainDataDirPath, { recursive: true }); diff --git a/logger/index.js b/logger/index.js index c2a1c31df..d77894edc 100644 --- a/logger/index.js +++ b/logger/index.js @@ -23,7 +23,6 @@ if (DevFlags.enableWinstonLogger) { }); } - global.isFinished = false; class Logger { @@ -36,7 +35,7 @@ class Logger { try { logger.error(`[${this.prefix}] ${text}`); } catch (e) { - console.error(e); + console.log(e); } } } @@ -56,7 +55,7 @@ class Logger { try { logger.debug(`[${this.prefix}] ${text}`); } catch (e) { - console.debug(e); + console.log(e); } } } diff --git a/start_node_genesis_gcp.sh b/start_node_genesis_gcp.sh index 6c5cbd39f..bc8908ec0 100644 --- a/start_node_genesis_gcp.sh +++ b/start_node_genesis_gcp.sh @@ -310,11 +310,11 @@ printf "PEER_WHITELIST=$PEER_WHITELIST\n" export STAKE=100000 printf "STAKE=$STAKE\n" +export LOG_BANDAGE_INFO=true +printf "LOG_BANDAGE_INFO=$LOG_BANDAGE_INFO\n" # uncomment and set value when necessary #export TIMER_FLAG_EARLY_APPLIED_BLOCK_NUMBER=124440 # summer #printf "TIMER_FLAG_EARLY_APPLIED_BLOCK_NUMBER=$TIMER_FLAG_EARLY_APPLIED_BLOCK_NUMBER\n" -export LOG_BANDAGE_INFO=true -printf "LOG_BANDAGE_INFO=$LOG_BANDAGE_INFO\n" if [[ "$SEASON" = "sandbox" ]]; then MAX_OLD_SPACE_SIZE_MB=11000 diff --git a/start_tracker_genesis_gcp.sh b/start_tracker_genesis_gcp.sh index 1f1c24609..33ecb59bf 100644 --- a/start_tracker_genesis_gcp.sh +++ b/start_tracker_genesis_gcp.sh @@ -53,7 +53,6 @@ else eval $CODE_CMD fi - printf "\nStarting up Blockchain Tracker server..\n\n" START_CMD="nohup node --async-stack-traces tracker-server/index.js >/dev/null 2>error_logs.txt &" printf "\nSTART_CMD=$START_CMD\n" From 35325f6703129cd7534ce96a89b2a410d7057e57 Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Tue, 18 Jul 2023 11:54:54 +0900 Subject: [PATCH 25/27] Upgrade package version to v1.1.0 --- client/protocol_versions.json | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/client/protocol_versions.json b/client/protocol_versions.json index b6f87becc..6560b37d6 100644 --- a/client/protocol_versions.json +++ b/client/protocol_versions.json @@ -122,5 +122,8 @@ }, "1.0.15": { "min": "1.0.0" + }, + "1.1.0": { + "min": "1.0.0" } } \ No newline at end of file diff --git a/package.json b/package.json index a27e6ebc2..f8a6eec72 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ain-blockchain", "description": "AI Network Blockchain", - "version": "1.0.15", + "version": "1.1.0", "private": true, "license": "MIT", "author": "dev@ainetwork.ai", From 09c502361439d85410dbc290eb637dc08557d5b2 Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Tue, 18 Jul 2023 15:42:10 +0900 Subject: [PATCH 26/27] Set enabled_block for new timer flags --- blockchain-configs/testnet-prod/timer_flags.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blockchain-configs/testnet-prod/timer_flags.json b/blockchain-configs/testnet-prod/timer_flags.json index df69ab6e7..dcbf38c4a 100644 --- a/blockchain-configs/testnet-prod/timer_flags.json +++ b/blockchain-configs/testnet-prod/timer_flags.json @@ -52,11 +52,11 @@ "has_bandage": true }, "update_min_gc_num_siblings_deleted2": { - "enabled_block": null, + "enabled_block": 2429500, "has_bandage": true }, "tweak_transfer_gc_rule": { - "enabled_block": null, + "enabled_block": 2429500, "has_bandage": true } } From 9b33b8203cab776ed5d01794d0ed4662a63f6c34 Mon Sep 17 00:00:00 2001 From: Dongil Seo Date: Tue, 18 Jul 2023 16:46:48 +0900 Subject: [PATCH 27/27] Set enabled_block for new timer flags (mainnet) --- blockchain-configs/mainnet-prod/timer_flags.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blockchain-configs/mainnet-prod/timer_flags.json b/blockchain-configs/mainnet-prod/timer_flags.json index 50ca0db01..521d2da6a 100644 --- a/blockchain-configs/mainnet-prod/timer_flags.json +++ b/blockchain-configs/mainnet-prod/timer_flags.json @@ -48,11 +48,11 @@ "has_bandage": true }, "update_min_gc_num_siblings_deleted2": { - "enabled_block": null, + "enabled_block": 2430100, "has_bandage": true }, "tweak_transfer_gc_rule": { - "enabled_block": null, + "enabled_block": 2430100, "has_bandage": true } }