Skip to content

Commit c6d3ab6

Browse files
authored
Merge pull request #1219 from ainblockchain/release/v1.1.3
Release/v1.1.3
2 parents 8d21bc0 + 1f1bbbd commit c6d3ab6

24 files changed

+200
-32
lines changed

.github/workflows/github-actions.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ jobs:
2828
with:
2929
node-version: ${{ matrix.node-version }}
3030
registry-url: 'https://registry.npmjs.org'
31+
- name: node-gyp install
32+
run: yarn global add node-gyp
3133
- name: yarn install
3234
run: yarn install
3335
- name: run unittest

blockchain-configs/base/timer_flags.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,9 @@
5555
"tweak_transfer_gc_rule": {
5656
"enabled_block": 2,
5757
"has_bandage": true
58+
},
59+
"allow_up_to_6_decimal_transfer_value_only": {
60+
"enabled_block": 2,
61+
"has_bandage": true
5862
}
5963
}

blockchain-configs/mainnet-prod/timer_flags.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,9 @@
5454
"tweak_transfer_gc_rule": {
5555
"enabled_block": 2430100,
5656
"has_bandage": true
57+
},
58+
"allow_up_to_6_decimal_transfer_value_only": {
59+
"enabled_block": 3064900,
60+
"has_bandage": true
5761
}
5862
}

blockchain-configs/testnet-prod/timer_flags.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,9 @@
5858
"tweak_transfer_gc_rule": {
5959
"enabled_block": 2429500,
6060
"has_bandage": true
61+
},
62+
"allow_up_to_6_decimal_transfer_value_only": {
63+
"enabled_block": 3062600,
64+
"has_bandage": true
6165
}
6266
}

blockchain/index.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class Blockchain {
8989
* the blockchain.
9090
*
9191
* @param {string} hash - hash or hash substring of block.
92-
* @return {Block} Block instance corresponding to the queried block hash.
92+
* @returns {Block} Block instance corresponding to the queried block hash.
9393
*/
9494
getBlockByHash(hash) {
9595
if (!hash) return null;
@@ -108,7 +108,7 @@ class Blockchain {
108108
* Given a block number, returns the block that corresponds to the block number.
109109
*
110110
* @param {integer} number - block number
111-
* @return {Block} Block instance corresponding to the queried block number.
111+
* @returns {Block} Block instance corresponding to the queried block number.
112112
*/
113113
getBlockByNumber(number) {
114114
if (number === undefined || number === null) return null;
@@ -324,7 +324,7 @@ class Blockchain {
324324
*
325325
* @param {Number} from - The lowest block number to get (included)
326326
* @param {Number} to - The highest block number to geet (excluded)
327-
* @return {list} A list of blocks, up to CHAIN_SEGMENT_LENGTH blocks
327+
* @returns {list} A list of blocks, up to CHAIN_SEGMENT_LENGTH blocks
328328
*/
329329
getBlockList(from, to) {
330330
const blockList = [];
@@ -358,7 +358,7 @@ class Blockchain {
358358
* starting from the `from` block number (included).
359359
*
360360
* @param {Number} from - The highest block number to get (included)
361-
* @return {list} A list of blocks, up to OLD_CHAIN_SEGMENT_LENGTH blocks
361+
* @returns {list} A list of blocks, up to OLD_CHAIN_SEGMENT_LENGTH blocks
362362
*/
363363
getOldBlockList(from) {
364364
const lastBlock = this.lastBlock();

client/protocol_versions.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,5 +131,8 @@
131131
},
132132
"1.1.2": {
133133
"min": "1.0.0"
134+
},
135+
"1.1.3": {
136+
"min": "1.0.0"
134137
}
135138
}

common/common-util.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -751,22 +751,27 @@ class CommonUtil {
751751
* @param {Object} gasAmount gas amount
752752
* @returns
753753
*/
754-
static getTotalGasCost(gasPrice, gasAmount, gasPriceUnit) {
754+
static getTotalGasCost(gasPrice, gasAmount, gasPriceUnit, enableGasCostFlooring = true) {
755755
if (!CommonUtil.isNumber(gasPrice)) {
756756
gasPrice = 0; // Default gas price = 0 microain
757757
}
758758
if (!CommonUtil.isNumber(gasAmount)) {
759759
gasAmount = 0; // Default gas amount = 0
760760
}
761-
return gasPrice * gasPriceUnit * gasAmount;
761+
let cost = gasPrice * gasPriceUnit * gasAmount;
762+
// NOTE(platfowner): Apply gas cost flooring up-to 6 decimals.
763+
if (enableGasCostFlooring) {
764+
cost = Math.floor(cost * 1000000) / 1000000; // gas cost flooring
765+
}
766+
return cost;
762767
}
763768

764-
static getServiceGasCostTotalFromTxList(txList, resList, gasPriceUnit) {
769+
static getServiceGasCostTotalFromTxList(txList, resList, gasPriceUnit, enableGasCostFlooring = true) {
765770
return resList.reduce((acc, cur, index) => {
766771
const tx = txList[index];
767772
return CommonUtil.mergeNumericJsObjects(acc, {
768773
gasAmountTotal: cur.gas_amount_charged,
769-
gasCostTotal: CommonUtil.getTotalGasCost(tx.tx_body.gas_price, cur.gas_amount_charged, gasPriceUnit)
774+
gasCostTotal: CommonUtil.getTotalGasCost(tx.tx_body.gas_price, cur.gas_amount_charged, gasPriceUnit, enableGasCostFlooring)
770775
});
771776
}, { gasAmountTotal: 0, gasCostTotal: 0 });
772777
}

consensus/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const {
1818
StateVersions,
1919
ValueChangedEventSources,
2020
TransactionStates,
21+
isEnabledTimerFlag,
2122
} = require('../common/constants');
2223
const { ConsensusErrorCode } = require('../common/result-code');
2324
const {
@@ -713,8 +714,9 @@ class Consensus {
713714
});
714715
}
715716
const gasPriceUnit = node.getBlockchainParam('resource/gas_price_unit', number, db.stateVersion);
717+
const enableGasCostFlooring = isEnabledTimerFlag('allow_up_to_6_decimal_transfer_value_only', number);
716718
const { gasAmountTotal, gasCostTotal } =
717-
CommonUtil.getServiceGasCostTotalFromTxList(transactions, txsRes, gasPriceUnit);
719+
CommonUtil.getServiceGasCostTotalFromTxList(transactions, txsRes, gasPriceUnit, enableGasCostFlooring);
718720
if (gasAmountTotal !== expectedGasAmountTotal) {
719721
throw new ConsensusError({
720722
code: ConsensusErrorCode.INVALID_GAS_AMOUNT_TOTAL,
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module.exports = {
2+
data: [
3+
{
4+
path: ['rules', 'transfer', '$from', '$to', '$key', 'value' ],
5+
value: {
6+
'.rule': {
7+
"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.countDecimals(newData) <= 6 && util.getBalance($from, getValue) >= newData"
8+
}
9+
},
10+
// From allow_non_negative_transfer_value_only.js bandage file.
11+
prevValue: {
12+
".rule": {
13+
"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"
14+
}
15+
}
16+
}
17+
]
18+
};

db/index.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,6 +1702,7 @@ class DB {
17021702
auth, tx, timestamp, blockNumber, blockTime, executionResult, eventSource, isDryrun) {
17031703
const gasPriceUnit =
17041704
DB.getBlockchainParam('resource/gas_price_unit', blockNumber, this.stateRoot);
1705+
const enableGasCostFlooring = isEnabledTimerFlag('allow_up_to_6_decimal_transfer_value_only', blockNumber);
17051706
const gasPrice = tx.tx_body.gas_price;
17061707
// Use only the service gas amount total
17071708
const serviceBandwidthGasAmount = _.get(tx, 'extra.gas.bandwidth.service', 0);
@@ -1711,7 +1712,7 @@ class DB {
17111712
if (gasAmountChargedByTransfer <= 0 || gasPrice === 0) { // No fees to collect
17121713
executionResult.gas_amount_charged = gasAmountChargedByTransfer;
17131714
executionResult.gas_cost_total =
1714-
CommonUtil.getTotalGasCost(gasPrice, gasAmountChargedByTransfer, gasPriceUnit);
1715+
CommonUtil.getTotalGasCost(gasPrice, gasAmountChargedByTransfer, gasPriceUnit, enableGasCostFlooring);
17151716
return;
17161717
}
17171718
const billing = tx.tx_body.billing;
@@ -1724,7 +1725,7 @@ class DB {
17241725
}
17251726
}
17261727
let balance = this.getBalance(billedTo);
1727-
const gasCost = CommonUtil.getTotalGasCost(gasPrice, gasAmountChargedByTransfer, gasPriceUnit);
1728+
const gasCost = CommonUtil.getTotalGasCost(gasPrice, gasAmountChargedByTransfer, gasPriceUnit, enableGasCostFlooring);
17281729
if (!isDryrun && balance < gasCost) {
17291730
Object.assign(executionResult, {
17301731
code: TxResultCode.FEE_BALANCE_TOO_LOW,
@@ -1736,7 +1737,7 @@ class DB {
17361737
}
17371738
executionResult.gas_amount_charged = gasAmountChargedByTransfer;
17381739
executionResult.gas_cost_total =
1739-
CommonUtil.getTotalGasCost(gasPrice, executionResult.gas_amount_charged, gasPriceUnit);
1740+
CommonUtil.getTotalGasCost(gasPrice, executionResult.gas_amount_charged, gasPriceUnit, enableGasCostFlooring);
17401741
if (isDryrun || executionResult.gas_cost_total <= 0) {
17411742
return;
17421743
}

db/rule-util.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,20 @@ class RuleUtil {
122122
return this.isString(str) ? str : '';
123123
}
124124

125+
countDecimals(value) {
126+
const decimalExponentRegex = /^-{0,1}(\d*\.{0,1}\d*)e-(\d+)$/gm;
127+
128+
if (Math.floor(value) === value) {
129+
return 0;
130+
}
131+
const valueString = value.toString();
132+
const matches = decimalExponentRegex.exec(valueString);
133+
if (matches) {
134+
return Number(matches[2]) + this.countDecimals(Number(matches[1]));
135+
}
136+
return valueString.split('.')[1].length || 0;
137+
}
138+
125139
toBool(value) {
126140
return this.isBool(value) ? value : value === 'true';
127141
}

deploy_blockchain_genesis_gcp.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ JSON_RPC_NODE_INDEX_LE=4
119119
REST_FUNC_NODE_INDEX_GE=0
120120
REST_FUNC_NODE_INDEX_LE=2
121121
# Event-Handler-enabled blockchain nodes
122-
EVENT_HANDLER_NODE_INDEX_GE=3
122+
EVENT_HANDLER_NODE_INDEX_GE=0
123123
EVENT_HANDLER_NODE_INDEX_LE=4
124124

125125
printf "\n"

deploy_blockchain_incremental_gcp.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ JSON_RPC_NODE_INDEX_LE=4
105105
REST_FUNC_NODE_INDEX_GE=0
106106
REST_FUNC_NODE_INDEX_LE=2
107107
# Event-Handler-enabled blockchain nodes
108-
EVENT_HANDLER_NODE_INDEX_GE=3
108+
EVENT_HANDLER_NODE_INDEX_GE=0
109109
EVENT_HANDLER_NODE_INDEX_LE=4
110110

111111
printf "\n"

json_rpc/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ const { JSON_RPC_METHODS } = require('./constants');
2222
* @param {EventHandler} eventHandler Instance of the EventHandler class.
2323
* @param {string} minProtocolVersion Minimum compatible protocol version.
2424
* @param {string} maxProtocolVersion Maximum compatible protocol version.
25-
* @return {dict} A closure of functions compatible with the jayson library for
26-
* servicing JSON-RPC requests.
25+
* @returns {dict} A closure of functions compatible with the jayson library for
26+
* servicing JSON-RPC requests.
2727
*/
2828
module.exports = function getApis(node, p2pServer, minProtocolVersion, maxProtocolVersion) {
2929
// Minimally required APIs

node/index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const {
2323
TrafficEventTypes,
2424
trafficStatsManager,
2525
ValueChangedEventSources,
26+
isEnabledTimerFlag,
2627
} = require('../common/constants');
2728
const { TxResultCode } = require('../common/result-code');
2829
const { ValidatorOffenseTypes } = require('../consensus/constants');
@@ -683,7 +684,7 @@ class BlockchainNode {
683684
*
684685
* @param {dict} operation - Database write operation to be converted to transaction
685686
* not
686-
* @return {Transaction} Instance of the transaction class
687+
* @returns {Transaction} Instance of the transaction class
687688
*/
688689
createTransaction(txBody) {
689690
const LOG_HEADER = 'createTransaction';
@@ -949,8 +950,9 @@ class BlockchainNode {
949950
}
950951
const gasPriceUnit =
951952
this.getBlockchainParam('resource/gas_price_unit', blockNumber, baseDb.stateVersion);
953+
const enableGasCostFlooring = isEnabledTimerFlag('allow_up_to_6_decimal_transfer_value_only', blockNumber);
952954
const { gasAmountTotal, gasCostTotal } =
953-
CommonUtil.getServiceGasCostTotalFromTxList(transactions, resList, gasPriceUnit);
955+
CommonUtil.getServiceGasCostTotalFromTxList(transactions, resList, gasPriceUnit, enableGasCostFlooring);
954956
const receipts = CommonUtil.txResultsToReceipts(resList);
955957
return { transactions, receipts, gasAmountTotal, gasCostTotal };
956958
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "ain-blockchain",
33
"description": "AI Network Blockchain",
4-
"version": "1.1.2",
4+
"version": "1.1.3",
55
"private": true,
66
"license": "MIT",
77
"author": "[email protected]",

start_node_genesis_gcp.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#!/bin/bash
22

33
# NOTE(minsulee2): Since exit really exits terminals, those are replaced to return 1.
4-
if [[ $# -lt 4 ]] || [[ $# -gt 12 ]]; then
5-
printf "Usage: bash start_node_genesis_gcp.sh [dev|staging|sandbox|exp|spring|summer|mainnet] <GCP Username> <Shard Index> <Node Index> [--keystore|--mnemonic|--private-key] [--keep-code|--no-keep-code] [--keep-data|--no-keep-data] [--full-sync|--fast-sync] [--chown-data|--no-chown-data] [--json-rpc] [--update-front-db] [--rest-func]\n"
4+
if [[ $# -lt 4 ]] || [[ $# -gt 13 ]]; then
5+
printf "Usage: bash start_node_genesis_gcp.sh [dev|staging|sandbox|exp|spring|summer|mainnet] <GCP Username> <Shard Index> <Node Index> [--keystore|--mnemonic|--private-key] [--keep-code|--no-keep-code] [--keep-data|--no-keep-data] [--full-sync|--fast-sync] [--chown-data|--no-chown-data] [--json-rpc] [--update-front-db] [--rest-func] [--event-handler]\n"
66
printf "Example: bash start_node_genesis_gcp.sh spring gcp_user 0 0 --keystore --no-keep-code --full-sync --no-chown-data\n"
77
printf "\n"
88
return 1

start_node_incremental_gcp.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/bin/bash
22

3-
if [[ $# -lt 4 ]] || [[ $# -gt 12 ]]; then
4-
printf "Usage: bash start_node_incremental_gcp.sh [dev|staging|sandbox|exp|spring|summer|mainnet] <GCP Username> <Shard Index> <Node Index> [--keystore|--mnemonic|--private-key] [--keep-code|--no-keep-code] [--keep-data|--no-keep-data] [--full-sync|--fast-sync] [--chown-data|--no-chown-data] [--json-rpc] [--update-front-db] [--rest-func]\n"
3+
if [[ $# -lt 4 ]] || [[ $# -gt 13 ]]; then
4+
printf "Usage: bash start_node_incremental_gcp.sh [dev|staging|sandbox|exp|spring|summer|mainnet] <GCP Username> <Shard Index> <Node Index> [--keystore|--mnemonic|--private-key] [--keep-code|--no-keep-code] [--keep-data|--no-keep-data] [--full-sync|--fast-sync] [--chown-data|--no-chown-data] [--json-rpc] [--update-front-db] [--rest-func] [--event-handler]\n"
55
printf "Example: bash start_node_incremental_gcp.sh spring gcp_user 0 0 --keystore --no-keep-code --full-sync --no-chown-data\n"
66
printf "\n"
77
exit

test/integration/consensus.test.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,13 +405,29 @@ describe('Consensus', () => {
405405
});
406406
});
407407

408+
it('cannot claim with an amount of more than 6 decimals', async () => {
409+
const claimTx = parseOrLog(syncRequest('POST', server1 + '/set_value', {json: {
410+
ref: `/gas_fee/claim/${server1Addr}/0`,
411+
value: {
412+
amount: 0.0000001 // an amount of 7 decimals
413+
}
414+
}}).body.toString('utf-8')).result;
415+
if (!(await waitUntilTxFinalized(serverList, claimTx.tx_hash))) {
416+
console.error(`Failed to check finalization of tx.`);
417+
}
418+
expect(claimTx.result.code).to.equal(10104);
419+
expect(claimTx.result.func_results._claimReward.code).to.equal(20001);
420+
expect(claimTx.result.func_results._claimReward.op_results['0'].result.code).to.equal(12103);
421+
});
422+
408423
it('can claim unclaimed rewards', async () => {
409424
const unclaimed = parseOrLog(syncRequest('GET',
410425
server1 + `/get_value?ref=/consensus/rewards/${server1Addr}/unclaimed&is_final=true`).body.toString('utf-8')).result;
426+
const unclaimedFloored = Math.floor(unclaimed * 1000000) / 1000000;
411427
const claimTx = parseOrLog(syncRequest('POST', server1 + '/set_value', {json: {
412428
ref: `/gas_fee/claim/${server1Addr}/1`,
413429
value: {
414-
amount: unclaimed
430+
amount: unclaimedFloored
415431
},
416432
timestamp: 1629377509815
417433
}}).body.toString('utf-8')).result;

0 commit comments

Comments
 (0)