Skip to content

Commit ad872a6

Browse files
authored
Merge pull request #858 from ainblockchain/release/v1.0.0
Release/v1.0.0
2 parents 6009504 + bf249b8 commit ad872a6

File tree

173 files changed

+23626
-10525
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

173 files changed

+23626
-10525
lines changed

.github/workflows/github-actions.yml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,18 @@ on:
1515
jobs:
1616
build_and_test:
1717
if: ${{ github.event_name == 'pull_request' && (github.event.action == 'opened' || github.event.action == 'edited') }}
18-
runs-on: macos-latest
18+
strategy:
19+
matrix:
20+
os: [ubuntu-latest, macos-latest]
21+
node-version: [ '14.x', '16.x' ]
22+
runs-on: ${{ matrix.os }}
1923
steps:
2024
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
2125
- uses: actions/checkout@v2
2226
# Setup node environment for testing
2327
- uses: actions/setup-node@v2
2428
with:
25-
node-version: '12.x'
29+
node-version: ${{ matrix.node-version }}
2630
registry-url: 'https://registry.npmjs.org'
2731
- name: yarn install
2832
run: yarn install
@@ -78,7 +82,7 @@ jobs:
7882
project_id: ${{ secrets.PERF_TEST_PIPELINE_GCP_PROJECT_ID }}
7983
- name: send test start message to gcp
8084
run: |-
81-
gcloud compute ssh "${{ secrets.PERF_TEST_PIPELINE_GCE_INSTANCE }}" --zone "${{ secrets.PERF_TEST_PIPELINE_GCE_INSTANCE_ZONE }}" -- "cd ~/../workspace/testnet-performance-test-pipeline && nohup node start_performance_test.js ${{ secrets.PERF_TEST_PIPELINE_TEST_BRANCH }} ${{ github.event.pull_request.head.ref }} >> test_log.txt 2>&1 &" &
85+
gcloud compute ssh "${{ secrets.PERF_TEST_PIPELINE_GCE_INSTANCE }}" --zone "${{ secrets.PERF_TEST_PIPELINE_GCE_INSTANCE_ZONE }}" -- "cd ~/../workspace/testnet-performance-test-pipeline && nohup node start_performance_test.js ${{ secrets.PERF_TEST_PIPELINE_TEST_SEASON }} ${{ secrets.PERF_TEST_PIPELINE_TEST_BRANCH }} ${{ github.event.pull_request.head.ref }} >> test_log.txt 2>&1 &" &
8286
sleep 60
8387
check_deployment:
8488
if: github.event.pull_request.base.ref == 'master'
@@ -87,7 +91,7 @@ jobs:
8791
- uses: actions/checkout@v2
8892
- uses: actions/setup-node@v2
8993
with:
90-
node-version: '12.x'
94+
node-version: '16.x'
9195
registry-url: 'https://registry.npmjs.org'
9296
- name: setup key
9397
env:

README.md

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@
33
### [AI Network](https://ainetwork.ai) | [Whitepaper](https://c9ede755-23ca-410d-8a9d-e5b895cd95bb.filesusr.com/ugd/4f6eb2_482a2386addb4c3283ee6e26f8ad42e6.pdf) | [Documentation](https://docs.ainetwork.ai/)
44
Official Javascript implementation of AI Network Blockchain.
55

6+
## Install Environment (Last update at 6th of Dec 2021)
7+
### OS
8+
9+
- macOS 10.15 (macos-latest)
10+
- Ubuntu 20.04 (ubuntu-latest)
11+
12+
### Node version
13+
14+
- v16.x
15+
- v14.x
16+
617
## Tracker
718

819
Tracker server is required by new peers who wish to join the AIN network. Each peer is sent the ipaddress of 2 other nodes in the network. These nodes then gossip information through the network of all transactions and blocks.
@@ -14,7 +25,6 @@ NOTE: Tracker Server must be started first before starting any blockchain node i
1425
#### Local
1526

1627
- Clone this repository and install yarn packages
17-
- Highly recommend to use node version >= 12
1828
```
1929
git clone https://github.com/ainblockchain/ain-blockchain.git
2030
cd ain-blockchain/tracker-server/
@@ -89,17 +99,16 @@ Operates a single peer node instance of the AIN blockchain. A single blockchain
8999
#### Local
90100

91101
- Clone this repository and install yarn packages
92-
- Highly recommend to use node version >= 12
93102
```
94103
git clone https://github.com/ainblockchain/ain-blockchain.git
95104
cd ain-blockchain/
96105
yarn install
97106
```
98107
- Run blockchain nodes
99108
```
100-
ACCOUNT_INDEX=0 PEER_CANDIDATE_JSON_RPC_URL='' DEBUG=false STAKE=100000 CONSOLE_LOG=true ENABLE_DEV_CLIENT_SET_API=true ENABLE_GAS_FEE_WORKAROUND=true node client/index.js
101-
ACCOUNT_INDEX=1 DEBUG=false STAKE=100000 CONSOLE_LOG=true ENABLE_DEV_CLIENT_SET_API=true ENABLE_GAS_FEE_WORKAROUND=true node client/index.js
102-
ACCOUNT_INDEX=2 DEBUG=false STAKE=100000 CONSOLE_LOG=true ENABLE_DEV_CLIENT_SET_API=true ENABLE_GAS_FEE_WORKAROUND=true node client/index.js
109+
ACCOUNT_INJECTION_OPTION=keystore KEYSTORE_FILE_PATH=/path/to/keystore DEBUG=false STAKE=100000 CONSOLE_LOG=true ENABLE_GAS_FEE_WORKAROUND=true node client/index.js
110+
ACCOUNT_INJECTION_OPTION=keystore KEYSTORE_FILE_PATH=/path/to/keystore DEBUG=false STAKE=100000 CONSOLE_LOG=true ENABLE_GAS_FEE_WORKAROUND=true node client/index.js
111+
ACCOUNT_INJECTION_OPTION=keystore KEYSTORE_FILE_PATH=/path/to/keystore DEBUG=false STAKE=100000 CONSOLE_LOG=true ENABLE_GAS_FEE_WORKAROUND=true node client/index.js
103112
```
104113
You can override default port numbering system by setting `PORT` and `P2P_PORT` environment variables.
105114
Before starting node jobs, remove existing blockchain files and logs if necessary:
@@ -112,7 +121,7 @@ The default minimum size of the validator whitelist is 3. Change MIN_NUM_VALIDAT
112121
the blockchain-configs/base/genesis.json to change this value. You may also need to modify the GENESIS_WHITELIST and GENESIS_VALIDATORS accordingly.
113122
The genesis configs directory used is `blockchain-configs/base` by default and it can be altered using `BLOCKCHAIN_CONFIGS_DIR` env variable. For example, afan shard cluster can use the following command line:
114123
```
115-
BLOCKCHAIN_CONFIGS_DIR=blockchain-configs/afan-shard MIN_NUM_VALIDATORS=1 ACCOUNT_INDEX=0 DEBUG=false STAKE=100000 CONSOLE_LOG=true ENABLE_DEV_CLIENT_SET_API=true ENABLE_GAS_FEE_WORKAROUND=true node client/index.js
124+
BLOCKCHAIN_CONFIGS_DIR=blockchain-configs/afan-shard MIN_NUM_VALIDATORS=1 ACCOUNT_INJECTION_OPTION=keystore KEYSTORE_FILE_PATH=/path/to/keystore DEBUG=false STAKE=100000 CONSOLE_LOG=true ENABLE_GAS_FEE_WORKAROUND=true node client/index.js
116125
```
117126

118127
#### On Google Cloud Platform (GCP)
@@ -152,7 +161,7 @@ docker pull ainblockchain/blockchain-database
152161
```
153162
- Run with Docker image
154163
```
155-
docker run -e ACCOUNT_INDEX=0 --network="host" -d ainblockchain/ain-blockchain:latest
164+
docker run -e ACCOUNT_INJECTION_OPTION=keystore KEYSTORE_FILE_PATH=/path/to/keystore --network="host" -d ainblockchain/ain-blockchain:latest
156165
```
157166
158167
#### Enter Docker container and inspect blockchain files
@@ -172,8 +181,6 @@ cat logger/logs/8080/<log_file>
172181

173182
### How to run tests
174183

175-
Please check your node version before running the below tests. Tests has passed node version 12.*
176-
177184
How to run unit test and integration test all around.
178185
```
179186
yarn run test_unit

block-pool/index.js

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -271,10 +271,10 @@ class BlockPool {
271271
});
272272
this.tryUpdateNotarized(blockHash);
273273
}
274-
logger.info(
274+
logger.debug(
275275
`[${LOG_HEADER}] Block added to the block pool: ${block.number} / ${block.epoch}`);
276276
} else {
277-
logger.info(
277+
logger.debug(
278278
`[${LOG_HEADER}] Block already in the block pool: ${block.number} / ${block.epoch}`);
279279
}
280280
}
@@ -289,10 +289,10 @@ class BlockPool {
289289
if (CommonUtil.isEmpty(blockInfo.block)) {
290290
this.hashToInvalidBlockInfo[blockHash].block = block;
291291
this.hashToInvalidBlockInfo[blockHash].proposal = proposalTx;
292-
logger.info(
292+
logger.debug(
293293
`[${LOG_HEADER}] Invalid block added to the block pool: ${block.number} / ${block.epoch}`);
294294
} else {
295-
logger.info(
295+
logger.debug(
296296
`[${LOG_HEADER}] Invalid block already in the block pool: ${block.number} / ${block.epoch}`);
297297
}
298298
}
@@ -361,9 +361,11 @@ class BlockPool {
361361
addSeenVote(voteTx) {
362362
const LOG_HEADER = 'addSeenVote';
363363
const blockHash = ConsensusUtil.getBlockHashFromConsensusTx(voteTx);
364+
const blockNumber = ConsensusUtil.getBlockNumberFromConsensusTx(voteTx);
364365
const stake = ConsensusUtil.getStakeFromVoteTx(voteTx);
365366
logger.debug(`[${LOG_HEADER}] voteTx: ${JSON.stringify(voteTx, null, 2)}, ` +
366-
`blockHash: ${blockHash}, stake: ${stake}`);
367+
`blockHash: ${blockHash}, blockNumber: ${blockNumber}, stake: ${stake}`);
368+
this.addToNumberToBlockSet({ number: blockNumber, hash: blockHash });
367369
if (ConsensusUtil.isProposalTx(voteTx)) {
368370
this.addProposal(voteTx, blockHash);
369371
} else if (ConsensusUtil.isAgainstVoteTx(voteTx)) {
@@ -435,6 +437,9 @@ class BlockPool {
435437
logger.info(`[${LOG_HEADER}] Current block is unavailable`);
436438
return;
437439
}
440+
if (currentBlockInfo.notarized) {
441+
return;
442+
}
438443
if (currentBlockInfo.block.number === 0) {
439444
this.hashToBlockInfo[currentBlockInfo.block.hash].notarized = true;
440445
this.updateLongestNotarizedChains(this.hashToBlockInfo[currentBlockInfo.block.hash]);
@@ -468,6 +473,20 @@ class BlockPool {
468473
}
469474

470475
cleanUpForBlockHash(blockHash) {
476+
const block = _get(this.hashToBlockInfo[blockHash], 'block', null);
477+
const blockProposal = _get(this.hashToBlockInfo[blockHash], 'proposal', null);
478+
const blockConsensusTxs = _get(this.hashToBlockInfo[blockHash], 'votes', []);
479+
if (blockProposal) {
480+
blockConsensusTxs.push(blockProposal);
481+
}
482+
const invalidBlock = _get(this.hashToInvalidBlockInfo[blockHash], 'block', null);
483+
const invalidBlockProposal = _get(this.hashToInvalidBlockInfo[blockHash], 'proposal', null);
484+
const invalidBlockConsensusTxs = _get(this.hashToInvalidBlockInfo[blockHash], 'votes', []);
485+
if (invalidBlockProposal) {
486+
invalidBlockConsensusTxs.push(invalidBlockProposal);
487+
}
488+
this.node.tp.cleanUpConsensusTxs(block, blockConsensusTxs);
489+
this.node.tp.cleanUpConsensusTxs(invalidBlock, invalidBlockConsensusTxs);
471490
delete this.hashToBlockInfo[blockHash];
472491
delete this.hashToInvalidBlockInfo[blockHash];
473492
delete this.hashToNextBlockSet[blockHash];
@@ -481,13 +500,14 @@ class BlockPool {
481500
// Remove everything that came before lastBlock.
482501
cleanUpAfterFinalization(lastBlock, recordedInvalidBlocks) {
483502
const targetNumber = lastBlock.number;
503+
const maxInvalidBlocksOnMem = this.node.getBlockchainParam('consensus/max_invalid_blocks_on_mem');
484504
for (const blockNumber of Object.keys(this.numberToBlockSet)) {
485-
if (blockNumber < targetNumber) {
505+
const number = Number(blockNumber);
506+
if (number < targetNumber) {
486507
const blockHashList = this.numberToBlockSet[blockNumber];
487508
for (const blockHash of blockHashList) {
488509
if (this.hashToInvalidBlockInfo[blockHash]) {
489-
if (recordedInvalidBlocks.has(blockHash) ||
490-
blockNumber < targetNumber - ConsensusConsts.MAX_CONSENSUS_LOGS_IN_STATES) {
510+
if (recordedInvalidBlocks.has(blockHash) || number < targetNumber - maxInvalidBlocksOnMem) {
491511
this.cleanUpForBlockHash(blockHash);
492512
this.numberToBlockSet[blockNumber].delete(blockHash);
493513
}
@@ -502,7 +522,7 @@ class BlockPool {
502522
}
503523
}
504524
for (const epoch of Object.keys(this.epochToBlock)) {
505-
if (epoch < lastBlock.epoch) {
525+
if (Number(epoch) < lastBlock.epoch) {
506526
const blockHash = this.epochToBlock[epoch];
507527
this.cleanUpForBlockHash(blockHash);
508528
delete this.epochToBlock[epoch];
@@ -521,6 +541,7 @@ class BlockPool {
521541
*/
522542
getValidLastVotes(lastBlock, blockNumber, blockTime, tempDb) {
523543
const LOG_HEADER = 'getValidLastVotes';
544+
const chainId = this.node.getBlockchainParam('genesis/chain_id');
524545
const lastBlockInfo = this.hashToBlockInfo[lastBlock.hash];
525546
logger.debug(`[${LOG_HEADER}] lastBlockInfo: ${JSON.stringify(lastBlockInfo, null, 2)}`);
526547
// FIXME(minsulee2 or liayoo): When I am behind and a newly coming node is ahead of me,
@@ -537,7 +558,7 @@ class BlockPool {
537558
let tallied = 0;
538559
for (const vote of lastVotes) {
539560
if (CommonUtil.isFailedTx(tempDb.executeTransaction(
540-
Transaction.toExecutable(vote), true, true, 0, blockTime))) {
561+
Transaction.toExecutable(vote, chainId), true, true, 0, blockTime))) {
541562
logger.debug(`[${LOG_HEADER}] failed to execute last vote: ${JSON.stringify(vote, null, 2)}`);
542563
} else {
543564
tallied += _get(lastBlock.validators, `${vote.address}.stake`, 0);
@@ -566,6 +587,7 @@ class BlockPool {
566587
const LOG_HEADER = 'getOffensesAndEvidence';
567588
const totalAtStake = ConsensusUtil.getTotalAtStake(validators);
568589
const blockNumber = baseDb.blockNumberSnapshot;
590+
const chainId = this.node.getBlockchainParam('genesis/chain_id');
569591
let backupDb = this.node.createTempDb(
570592
baseDb.stateVersion, `${StateVersions.SNAP}:${blockNumber}`, blockNumber);
571593
const majority = totalAtStake * ConsensusConsts.MAJORITY;
@@ -589,7 +611,8 @@ class BlockPool {
589611
for (const vote of blockInfo.votes) {
590612
const stake = _get(validators, `${vote.address}.stake`, 0);
591613
if (stake > 0) {
592-
const res = baseDb.executeTransaction(Transaction.toExecutable(vote), true, true, 0, blockTime);
614+
const res = baseDb.executeTransaction(
615+
Transaction.toExecutable(vote, chainId), true, true, 0, blockTime);
593616
if (CommonUtil.isFailedTx(res)) {
594617
logger.debug(`[${LOG_HEADER}] Failed to execute evidence vote:\n${JSON.stringify(vote, null, 2)}\n${JSON.stringify(res, null, 2)})`);
595618
} else {
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
{
2+
"_description": "Blockchain params for a 1-node network. Mostly used for unit tests.",
3+
"token": {
4+
"name": "AI Network",
5+
"symbol": "AIN",
6+
"total_supply": 700000000,
7+
"bridge": {
8+
"ETH": {
9+
"3": {
10+
"0xB16c0C80a81f73204d454426fC413CAe455525A7": {
11+
"token_pool": "0x20ADd3d38405ebA6338CB9e57a0510DEB8f8e000",
12+
"min_checkout_per_request": 10000,
13+
"max_checkout_per_request": 100000,
14+
"max_checkout_per_day": 1000000,
15+
"checkout_fee_rate": 0.001,
16+
"token_exchange_rate": 1,
17+
"token_exchange_scheme": "FIXED"
18+
}
19+
}
20+
}
21+
}
22+
},
23+
"consensus": {
24+
"min_stake_for_proposer": 10000000,
25+
"max_stake_for_proposer": 10000000,
26+
"min_num_validators": 1,
27+
"max_num_validators": 1,
28+
"genesis_proposer_whitelist": {
29+
"0x00ADEc28B6a845a085e03591bE7550dd68673C1C": true
30+
},
31+
"genesis_validator_whitelist": {
32+
"0x00ADEc28B6a845a085e03591bE7550dd68673C1C": true
33+
},
34+
"genesis_validators": {
35+
"0x00ADEc28B6a845a085e03591bE7550dd68673C1C": {
36+
"stake": 10000000,
37+
"proposal_right": true
38+
}
39+
},
40+
"health_threshold_epoch": 10,
41+
"stake_lockup_extension": 2592000000,
42+
"max_invalid_blocks_on_mem": 100
43+
},
44+
"genesis": {
45+
"genesis_addr": "0xAAAf6f50A0304F12119D218b94bea8082642515B",
46+
"genesis_timestamp": 1571819318272,
47+
"num_genesis_accounts": 10,
48+
"epoch_ms": 1000,
49+
"chain_id": 0,
50+
"network_id": 0
51+
},
52+
"resource": {
53+
"state_tree_height_limit": 30,
54+
"state_tree_bytes_limit": 20000000,
55+
"state_label_length_limit": 150,
56+
"bandwidth_budget_per_block": 10000,
57+
"service_state_budget_ratio": 0.5,
58+
"apps_state_budget_ratio": 0.495,
59+
"free_state_budget_ratio": 0.005,
60+
"max_state_tree_size_per_byte": 0.01,
61+
"state_gas_coefficient": 1,
62+
"unit_write_gas_amount": 1,
63+
"account_registration_gas_amount": 2000,
64+
"rest_function_call_gas_amount": 100,
65+
"gas_price_unit": 0.000001,
66+
"service_bandwidth_budget_ratio": 0.5,
67+
"apps_bandwidth_budget_ratio": 0.495,
68+
"free_bandwidth_budget_ratio": 0.005,
69+
"min_staking_for_app_tx": 0,
70+
"min_balance_for_service_tx": 0,
71+
"max_function_urls_per_developer": 3,
72+
"default_developers_url_whitelist": {
73+
"0": "https://*.ainetwork.ai",
74+
"1": "https://*.ainize.ai",
75+
"2": "https://*.afan.ai",
76+
"3": "http://localhost:3000"
77+
},
78+
"tx_bytes_limit": 10000,
79+
"batch_tx_list_size_limit": 50,
80+
"set_op_list_size_limit": 1500,
81+
"min_gc_num_siblings_deleted": 100
82+
},
83+
"reward": {
84+
"type": "FIXED",
85+
"annual_rate": 0.08
86+
},
87+
"sharding": {
88+
"shard_owner": "",
89+
"shard_reporter": "",
90+
"sharding_protocol": "NONE",
91+
"sharding_path": "/",
92+
"parent_chain_poc": "",
93+
"reporting_period": 0,
94+
"max_shard_report": 100,
95+
"num_shard_report_deleted": 100
96+
}
97+
}
4.37 KB
Binary file not shown.

0 commit comments

Comments
 (0)