Skip to content

Commit

Permalink
Merge pull request #1219 from ainblockchain/release/v1.1.3
Browse files Browse the repository at this point in the history
Release/v1.1.3
  • Loading branch information
platfowner authored Dec 12, 2023
2 parents 8d21bc0 + 1f1bbbd commit c6d3ab6
Show file tree
Hide file tree
Showing 24 changed files with 200 additions and 32 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/github-actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
registry-url: 'https://registry.npmjs.org'
- name: node-gyp install
run: yarn global add node-gyp
- name: yarn install
run: yarn install
- name: run unittest
Expand Down
4 changes: 4 additions & 0 deletions blockchain-configs/base/timer_flags.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,9 @@
"tweak_transfer_gc_rule": {
"enabled_block": 2,
"has_bandage": true
},
"allow_up_to_6_decimal_transfer_value_only": {
"enabled_block": 2,
"has_bandage": true
}
}
4 changes: 4 additions & 0 deletions blockchain-configs/mainnet-prod/timer_flags.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,9 @@
"tweak_transfer_gc_rule": {
"enabled_block": 2430100,
"has_bandage": true
},
"allow_up_to_6_decimal_transfer_value_only": {
"enabled_block": 3064900,
"has_bandage": true
}
}
4 changes: 4 additions & 0 deletions blockchain-configs/testnet-prod/timer_flags.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,9 @@
"tweak_transfer_gc_rule": {
"enabled_block": 2429500,
"has_bandage": true
},
"allow_up_to_6_decimal_transfer_value_only": {
"enabled_block": 3062600,
"has_bandage": true
}
}
8 changes: 4 additions & 4 deletions blockchain/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class Blockchain {
* the blockchain.
*
* @param {string} hash - hash or hash substring of block.
* @return {Block} Block instance corresponding to the queried block hash.
* @returns {Block} Block instance corresponding to the queried block hash.
*/
getBlockByHash(hash) {
if (!hash) return null;
Expand All @@ -108,7 +108,7 @@ class Blockchain {
* Given a block number, returns the block that corresponds to the block number.
*
* @param {integer} number - block number
* @return {Block} Block instance corresponding to the queried block number.
* @returns {Block} Block instance corresponding to the queried block number.
*/
getBlockByNumber(number) {
if (number === undefined || number === null) return null;
Expand Down Expand Up @@ -324,7 +324,7 @@ class Blockchain {
*
* @param {Number} from - The lowest block number to get (included)
* @param {Number} to - The highest block number to geet (excluded)
* @return {list} A list of blocks, up to CHAIN_SEGMENT_LENGTH blocks
* @returns {list} A list of blocks, up to CHAIN_SEGMENT_LENGTH blocks
*/
getBlockList(from, to) {
const blockList = [];
Expand Down Expand Up @@ -358,7 +358,7 @@ class Blockchain {
* starting from the `from` block number (included).
*
* @param {Number} from - The highest block number to get (included)
* @return {list} A list of blocks, up to OLD_CHAIN_SEGMENT_LENGTH blocks
* @returns {list} A list of blocks, up to OLD_CHAIN_SEGMENT_LENGTH blocks
*/
getOldBlockList(from) {
const lastBlock = this.lastBlock();
Expand Down
3 changes: 3 additions & 0 deletions client/protocol_versions.json
Original file line number Diff line number Diff line change
Expand Up @@ -131,5 +131,8 @@
},
"1.1.2": {
"min": "1.0.0"
},
"1.1.3": {
"min": "1.0.0"
}
}
13 changes: 9 additions & 4 deletions common/common-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -751,22 +751,27 @@ class CommonUtil {
* @param {Object} gasAmount gas amount
* @returns
*/
static getTotalGasCost(gasPrice, gasAmount, gasPriceUnit) {
static getTotalGasCost(gasPrice, gasAmount, gasPriceUnit, enableGasCostFlooring = true) {
if (!CommonUtil.isNumber(gasPrice)) {
gasPrice = 0; // Default gas price = 0 microain
}
if (!CommonUtil.isNumber(gasAmount)) {
gasAmount = 0; // Default gas amount = 0
}
return gasPrice * gasPriceUnit * gasAmount;
let cost = gasPrice * gasPriceUnit * gasAmount;
// NOTE(platfowner): Apply gas cost flooring up-to 6 decimals.
if (enableGasCostFlooring) {
cost = Math.floor(cost * 1000000) / 1000000; // gas cost flooring
}
return cost;
}

static getServiceGasCostTotalFromTxList(txList, resList, gasPriceUnit) {
static getServiceGasCostTotalFromTxList(txList, resList, gasPriceUnit, enableGasCostFlooring = true) {
return resList.reduce((acc, cur, index) => {
const tx = txList[index];
return CommonUtil.mergeNumericJsObjects(acc, {
gasAmountTotal: cur.gas_amount_charged,
gasCostTotal: CommonUtil.getTotalGasCost(tx.tx_body.gas_price, cur.gas_amount_charged, gasPriceUnit)
gasCostTotal: CommonUtil.getTotalGasCost(tx.tx_body.gas_price, cur.gas_amount_charged, gasPriceUnit, enableGasCostFlooring)
});
}, { gasAmountTotal: 0, gasCostTotal: 0 });
}
Expand Down
4 changes: 3 additions & 1 deletion consensus/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const {
StateVersions,
ValueChangedEventSources,
TransactionStates,
isEnabledTimerFlag,
} = require('../common/constants');
const { ConsensusErrorCode } = require('../common/result-code');
const {
Expand Down Expand Up @@ -713,8 +714,9 @@ class Consensus {
});
}
const gasPriceUnit = node.getBlockchainParam('resource/gas_price_unit', number, db.stateVersion);
const enableGasCostFlooring = isEnabledTimerFlag('allow_up_to_6_decimal_transfer_value_only', number);
const { gasAmountTotal, gasCostTotal } =
CommonUtil.getServiceGasCostTotalFromTxList(transactions, txsRes, gasPriceUnit);
CommonUtil.getServiceGasCostTotalFromTxList(transactions, txsRes, gasPriceUnit, enableGasCostFlooring);
if (gasAmountTotal !== expectedGasAmountTotal) {
throw new ConsensusError({
code: ConsensusErrorCode.INVALID_GAS_AMOUNT_TOTAL,
Expand Down
18 changes: 18 additions & 0 deletions db/bandage-files/allow_up_to_6_decimal_transfer_value_only.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = {
data: [
{
path: ['rules', 'transfer', '$from', '$to', '$key', 'value' ],
value: {
'.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) && newData > 0 && util.countDecimals(newData) <= 6 && util.getBalance($from, getValue) >= newData"
}
},
// From allow_non_negative_transfer_value_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) && newData > 0 && util.getBalance($from, getValue) >= newData"
}
}
}
]
};
7 changes: 4 additions & 3 deletions db/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1702,6 +1702,7 @@ class DB {
auth, tx, timestamp, blockNumber, blockTime, executionResult, eventSource, isDryrun) {
const gasPriceUnit =
DB.getBlockchainParam('resource/gas_price_unit', blockNumber, this.stateRoot);
const enableGasCostFlooring = isEnabledTimerFlag('allow_up_to_6_decimal_transfer_value_only', blockNumber);
const gasPrice = tx.tx_body.gas_price;
// Use only the service gas amount total
const serviceBandwidthGasAmount = _.get(tx, 'extra.gas.bandwidth.service', 0);
Expand All @@ -1711,7 +1712,7 @@ class DB {
if (gasAmountChargedByTransfer <= 0 || gasPrice === 0) { // No fees to collect
executionResult.gas_amount_charged = gasAmountChargedByTransfer;
executionResult.gas_cost_total =
CommonUtil.getTotalGasCost(gasPrice, gasAmountChargedByTransfer, gasPriceUnit);
CommonUtil.getTotalGasCost(gasPrice, gasAmountChargedByTransfer, gasPriceUnit, enableGasCostFlooring);
return;
}
const billing = tx.tx_body.billing;
Expand All @@ -1724,7 +1725,7 @@ class DB {
}
}
let balance = this.getBalance(billedTo);
const gasCost = CommonUtil.getTotalGasCost(gasPrice, gasAmountChargedByTransfer, gasPriceUnit);
const gasCost = CommonUtil.getTotalGasCost(gasPrice, gasAmountChargedByTransfer, gasPriceUnit, enableGasCostFlooring);
if (!isDryrun && balance < gasCost) {
Object.assign(executionResult, {
code: TxResultCode.FEE_BALANCE_TOO_LOW,
Expand All @@ -1736,7 +1737,7 @@ class DB {
}
executionResult.gas_amount_charged = gasAmountChargedByTransfer;
executionResult.gas_cost_total =
CommonUtil.getTotalGasCost(gasPrice, executionResult.gas_amount_charged, gasPriceUnit);
CommonUtil.getTotalGasCost(gasPrice, executionResult.gas_amount_charged, gasPriceUnit, enableGasCostFlooring);
if (isDryrun || executionResult.gas_cost_total <= 0) {
return;
}
Expand Down
14 changes: 14 additions & 0 deletions db/rule-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,20 @@ class RuleUtil {
return this.isString(str) ? str : '';
}

countDecimals(value) {
const decimalExponentRegex = /^-{0,1}(\d*\.{0,1}\d*)e-(\d+)$/gm;

if (Math.floor(value) === value) {
return 0;
}
const valueString = value.toString();
const matches = decimalExponentRegex.exec(valueString);
if (matches) {
return Number(matches[2]) + this.countDecimals(Number(matches[1]));
}
return valueString.split('.')[1].length || 0;
}

toBool(value) {
return this.isBool(value) ? value : value === 'true';
}
Expand Down
2 changes: 1 addition & 1 deletion deploy_blockchain_genesis_gcp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ JSON_RPC_NODE_INDEX_LE=4
REST_FUNC_NODE_INDEX_GE=0
REST_FUNC_NODE_INDEX_LE=2
# Event-Handler-enabled blockchain nodes
EVENT_HANDLER_NODE_INDEX_GE=3
EVENT_HANDLER_NODE_INDEX_GE=0
EVENT_HANDLER_NODE_INDEX_LE=4

printf "\n"
Expand Down
2 changes: 1 addition & 1 deletion deploy_blockchain_incremental_gcp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ JSON_RPC_NODE_INDEX_LE=4
REST_FUNC_NODE_INDEX_GE=0
REST_FUNC_NODE_INDEX_LE=2
# Event-Handler-enabled blockchain nodes
EVENT_HANDLER_NODE_INDEX_GE=3
EVENT_HANDLER_NODE_INDEX_GE=0
EVENT_HANDLER_NODE_INDEX_LE=4

printf "\n"
Expand Down
4 changes: 2 additions & 2 deletions json_rpc/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ const { JSON_RPC_METHODS } = require('./constants');
* @param {EventHandler} eventHandler Instance of the EventHandler class.
* @param {string} minProtocolVersion Minimum compatible protocol version.
* @param {string} maxProtocolVersion Maximum compatible protocol version.
* @return {dict} A closure of functions compatible with the jayson library for
* servicing JSON-RPC requests.
* @returns {dict} A closure of functions compatible with the jayson library for
* servicing JSON-RPC requests.
*/
module.exports = function getApis(node, p2pServer, minProtocolVersion, maxProtocolVersion) {
// Minimally required APIs
Expand Down
6 changes: 4 additions & 2 deletions node/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const {
TrafficEventTypes,
trafficStatsManager,
ValueChangedEventSources,
isEnabledTimerFlag,
} = require('../common/constants');
const { TxResultCode } = require('../common/result-code');
const { ValidatorOffenseTypes } = require('../consensus/constants');
Expand Down Expand Up @@ -683,7 +684,7 @@ class BlockchainNode {
*
* @param {dict} operation - Database write operation to be converted to transaction
* not
* @return {Transaction} Instance of the transaction class
* @returns {Transaction} Instance of the transaction class
*/
createTransaction(txBody) {
const LOG_HEADER = 'createTransaction';
Expand Down Expand Up @@ -949,8 +950,9 @@ class BlockchainNode {
}
const gasPriceUnit =
this.getBlockchainParam('resource/gas_price_unit', blockNumber, baseDb.stateVersion);
const enableGasCostFlooring = isEnabledTimerFlag('allow_up_to_6_decimal_transfer_value_only', blockNumber);
const { gasAmountTotal, gasCostTotal } =
CommonUtil.getServiceGasCostTotalFromTxList(transactions, resList, gasPriceUnit);
CommonUtil.getServiceGasCostTotalFromTxList(transactions, resList, gasPriceUnit, enableGasCostFlooring);
const receipts = CommonUtil.txResultsToReceipts(resList);
return { transactions, receipts, gasAmountTotal, gasCostTotal };
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ain-blockchain",
"description": "AI Network Blockchain",
"version": "1.1.2",
"version": "1.1.3",
"private": true,
"license": "MIT",
"author": "[email protected]",
Expand Down
4 changes: 2 additions & 2 deletions start_node_genesis_gcp.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/bin/bash

# NOTE(minsulee2): Since exit really exits terminals, those are replaced to return 1.
if [[ $# -lt 4 ]] || [[ $# -gt 12 ]]; then
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"
if [[ $# -lt 4 ]] || [[ $# -gt 13 ]]; then
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"
printf "Example: bash start_node_genesis_gcp.sh spring gcp_user 0 0 --keystore --no-keep-code --full-sync --no-chown-data\n"
printf "\n"
return 1
Expand Down
4 changes: 2 additions & 2 deletions start_node_incremental_gcp.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash

if [[ $# -lt 4 ]] || [[ $# -gt 12 ]]; then
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"
if [[ $# -lt 4 ]] || [[ $# -gt 13 ]]; then
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"
printf "Example: bash start_node_incremental_gcp.sh spring gcp_user 0 0 --keystore --no-keep-code --full-sync --no-chown-data\n"
printf "\n"
exit
Expand Down
18 changes: 17 additions & 1 deletion test/integration/consensus.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -405,13 +405,29 @@ describe('Consensus', () => {
});
});

it('cannot claim with an amount of more than 6 decimals', async () => {
const claimTx = parseOrLog(syncRequest('POST', server1 + '/set_value', {json: {
ref: `/gas_fee/claim/${server1Addr}/0`,
value: {
amount: 0.0000001 // an amount of 7 decimals
}
}}).body.toString('utf-8')).result;
if (!(await waitUntilTxFinalized(serverList, claimTx.tx_hash))) {
console.error(`Failed to check finalization of tx.`);
}
expect(claimTx.result.code).to.equal(10104);
expect(claimTx.result.func_results._claimReward.code).to.equal(20001);
expect(claimTx.result.func_results._claimReward.op_results['0'].result.code).to.equal(12103);
});

it('can claim unclaimed rewards', async () => {
const unclaimed = parseOrLog(syncRequest('GET',
server1 + `/get_value?ref=/consensus/rewards/${server1Addr}/unclaimed&is_final=true`).body.toString('utf-8')).result;
const unclaimedFloored = Math.floor(unclaimed * 1000000) / 1000000;
const claimTx = parseOrLog(syncRequest('POST', server1 + '/set_value', {json: {
ref: `/gas_fee/claim/${server1Addr}/1`,
value: {
amount: unclaimed
amount: unclaimedFloored
},
timestamp: 1629377509815
}}).body.toString('utf-8')).result;
Expand Down
Loading

0 comments on commit c6d3ab6

Please sign in to comment.