Skip to content

Commit 5ccc257

Browse files
authored
Merge pull request #202 from ainblockchain/release/v0.6.0
Release/v0.6.0
2 parents 8c6ed0b + 583ea20 commit 5ccc257

Some content is hidden

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

63 files changed

+4509
-2204
lines changed

.eslintrc.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@
1515
"error",
1616
{ "code": 100 }
1717
],
18-
"object-curly-spacing": [
19-
"error",
20-
"never"
21-
],
18+
"object-curly-spacing": "off",
2219
"comma-dangle": [
2320
"error",
2421
"only-multiline"
Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,58 @@
1-
# This is a basic workflow to help you get started with Actions
1+
name: AIN-blockchain CI/CD
22

3-
name: CI
4-
5-
# Controls when the action will run. Triggers the workflow on push or pull request
6-
# events but only for the master branch
73
on:
4+
push:
5+
branches:
6+
- 'develop'
7+
- 'release/*'
8+
- 'master'
89
pull_request:
9-
types: [opened, edited]
10-
11-
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
10+
branches:
11+
- 'develop'
12+
- 'release/*'
13+
- 'master'
1214
jobs:
13-
# This workflow contains a single job called "build"
14-
build-and-test:
15-
# The type of runner that the job will run on
15+
build_and_test:
16+
if: ${{ github.event_name == 'pull_request' && github.event.action == 'opened' }}
1617
runs-on: ubuntu-latest
17-
18-
# Steps represent a sequence of tasks that will be executed as part of the job
1918
steps:
2019
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
2120
- uses: actions/checkout@v2
2221
# Setup node environment for testing
2322
- uses: actions/setup-node@v1
2423
with:
25-
node-version: '10.x'
24+
node-version: '12.16'
2625
registry-url: 'https://registry.npmjs.org'
26+
- name: test
27+
run: echo ${{github.event_name}}
2728
- name: npm install
2829
run: npm install
2930
- name: run unittest
3031
run: npm run test_unit
3132
- name: run integration test
33+
if: github.event.pull_request.base.ref == 'master' # integration test only run when master merging
3234
run: npm run test_integration
35+
check_protocol_version:
36+
if: ${{ github.event_name == 'push' }}
37+
runs-on: ubuntu-latest
38+
steps:
39+
- uses: actions/checkout@v2
40+
- name: test
41+
if: github.event_name == 'push'
42+
run: echo ${{github.event_name}}
43+
- name: get current version
44+
run: echo "VERSION=$(cat package.json | jq -r '.version')" >> $GITHUB_ENV
45+
- name: get min/max versions
46+
run: |
47+
echo "MIN_VERSION=$(cat client/protocol_versions.json | jq -r --arg var "$VERSION" '.[$var].min')" >> $GITHUB_ENV
48+
echo "MAX_VERSION=$(cat client/protocol_versions.json | jq -r --arg var "$VERSION" '.[$var].max')" >> $GITHUB_ENV
49+
- name: send results
50+
env:
51+
SLACK_WEBHOOK_TOKEN: ${{ secrets.SLACK_WEBHOOK_TOKEN }}
52+
run: |
53+
curl -X POST https://hooks.slack.com/services/$SLACK_WEBHOOK_TOKEN \
54+
-H "Content-Type: application/json" \
55+
-d '{"username": "ain-blockchain",
56+
"channel": "blockchain-testnet-deploy",
57+
"text": "New PR has just been merged(${{ github.ref }}, ${{ github.sha }}).\nCurrent version: '"$VERSION"', compatible with min('"$MIN_VERSION"'), max('"$MAX_VERSION"')",
58+
"icon_emoji": ":gem:"}'

README.md

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ docker pull ainblockchain/tracker-server
6262
```
6363
- Run with Docker image
6464
```
65-
docker run -e HOSTING_ENV="gcp" --network="host" -d ainblockchain/tracker-server:latest
65+
docker run --network="host" -d ainblockchain/tracker-server:latest
6666
```
6767
-->
6868

@@ -92,21 +92,20 @@ yarn install
9292
```
9393
- Run blockchain nodes
9494
```
95-
NUM_VALIDATORS=4 ACCOUNT_INDEX=0 HOSTING_ENV=local DEBUG=false node client/index.js
96-
NUM_VALIDATORS=4 ACCOUNT_INDEX=1 HOSTING_ENV=local DEBUG=false node client/index.js
97-
NUM_VALIDATORS=4 ACCOUNT_INDEX=2 HOSTING_ENV=local DEBUG=false node client/index.js
98-
NUM_VALIDATORS=4 ACCOUNT_INDEX=3 HOSTING_ENV=local DEBUG=false node client/index.js
95+
ACCOUNT_INDEX=0 DEBUG=false STAKE=250 node client/index.js
96+
ACCOUNT_INDEX=1 DEBUG=false STAKE=250 node client/index.js
97+
ACCOUNT_INDEX=2 DEBUG=false STAKE=250 node client/index.js
9998
```
100-
The environment variable `NUM_VALIDATORS` has default value `5`.
10199
You can override default port numbering system by setting `PORT` and `P2P_PORT` environment variables.
102100
Before starting node jobs, remove existing blockchain files and logs if necessary:
103101
```
104102
rm -rf blockchain/blockchains logger/logs
105103
```
106-
The default size of the validator whitelist is 5. Set NUM_VALIDATORS environment variable when running the first node if you'd like to run different number of validator nodes than 5.
107-
The genesis configs directory used is `blockchain` by default and it can be altered using `GENESIS_CONFIGS_DIR` env variable. For example, afan shard cluster can use the following command line:
104+
The default minimum size of the validator whitelist is 3. Change MIN_NUM_VALIDATORS parameter in
105+
the genesis-configs/base/genesis.json to change this value. You may also need to modify the GENESIS_WHITELIST and GENESIS_VALIDATORS accordingly.
106+
The genesis configs directory used is `genesis-configs/base` by default and it can be altered using `GENESIS_CONFIGS_DIR` env variable. For example, afan shard cluster can use the following command line:
108107
```
109-
GENESIS_CONFIGS_DIR=blockchain/afan_shard NUM_VALIDATORS=1 ACCOUNT_INDEX=0 HOSTING_ENV=local DEBUG=false node client/index.js
108+
GENESIS_CONFIGS_DIR=genesis-configs/afan-shard ACCOUNT_INDEX=0 DEBUG=false STAKE=250 node client/index.js
110109
```
111110

112111
### How to run tests
@@ -153,7 +152,7 @@ docker pull ainblockchain/blockchain-database
153152
```
154153
- Run with Docker image
155154
```
156-
docker run -e ACCOUNT_INDEX=0 -e HOSTING_ENV="gcp" -e TRACKER_WS_ADDR="ws://<ip_address_of_tracker_server>:5000" --network="host" -d ainblockchain/ain-blockchain:latest
155+
docker run -e ACCOUNT_INDEX=0 --network="host" -d ainblockchain/ain-blockchain:latest
157156
```
158157
159158
#### Enter Docker container and inspect blockchain files

blockchain/block.js

Lines changed: 79 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const DB = require('../db');
1010
const {
1111
PredefinedDbPaths,
1212
GenesisAccounts,
13-
GenesisWhitelist,
13+
GENESIS_VALIDATORS,
1414
GenesisValues,
1515
GenesisFunctions,
1616
GenesisRules,
@@ -25,21 +25,20 @@ class Block {
2525
constructor(lastHash, lastVotes, transactions, number, epoch, timestamp,
2626
stateProofHash, proposer, validators) {
2727
this.last_votes = lastVotes;
28-
this.transactions = transactions;
28+
this.transactions = Block.sanitizeTransactions(transactions);
2929
// Block's header
3030
this.last_hash = lastHash;
3131
this.last_votes_hash = ChainUtil.hashString(stringify(lastVotes));
32-
this.transactions_hash = ChainUtil.hashString(stringify(transactions));
32+
this.transactions_hash = ChainUtil.hashString(stringify(this.transactions));
3333
this.number = number;
3434
this.epoch = epoch;
3535
this.timestamp = timestamp;
36-
// TODO(lia): change this to snake case
37-
this.stateProofHash = stateProofHash;
36+
this.state_proof_hash = stateProofHash;
3837
this.proposer = proposer;
3938
this.validators = validators;
40-
this.size = sizeof(this.transactions);
4139
// Hash of block's header
4240
this.hash = Block.hash(this);
41+
this.size = Block.getSize(this);
4342
}
4443

4544
get header() {
@@ -50,10 +49,16 @@ class Block {
5049
number: this.number,
5150
epoch: this.epoch,
5251
timestamp: this.timestamp,
53-
stateProofHash: this.stateProofHash,
52+
state_proof_hash: this.state_proof_hash,
5453
proposer: this.proposer,
5554
validators: this.validators,
56-
size: this.size
55+
};
56+
}
57+
58+
get body() {
59+
return {
60+
last_votes: this.last_votes,
61+
transactions: this.transactions,
5762
};
5863
}
5964

@@ -66,7 +71,7 @@ class Block {
6671
number: ${this.number}
6772
epoch: ${this.epoch}
6873
timestamp: ${this.timestamp}
69-
stateProofHash: ${this.stateProofHash}
74+
state_proof_hash: ${this.state_proof_hash}
7075
proposer: ${this.proposer}
7176
validators: ${this.validators}
7277
size: ${this.size}
@@ -76,11 +81,29 @@ class Block {
7681
transactions: ${stringify(this.transactions)}`;
7782
}
7883

84+
static sanitizeTransactions(transactions) {
85+
const sanitized = [];
86+
transactions.forEach((tx) => {
87+
sanitized.push({
88+
tx_body: Transaction.sanitizeTxBody(tx.tx_body),
89+
signature: tx.signature,
90+
hash: tx.hash,
91+
address: tx.address
92+
});
93+
});
94+
return sanitized;
95+
}
96+
7997
static hash(block) {
8098
if (!(block instanceof Block)) block = Block.parse(block);
8199
return ChainUtil.hashString(stringify(block.header));
82100
}
83101

102+
static getSize(block) {
103+
if (!(block instanceof Block)) block = Block.parse(block);
104+
return sizeof({...block.header, ...block.body});
105+
}
106+
84107
static create(lastHash, lastVotes, transactions, number, epoch,
85108
stateProofHash, proposer, validators) {
86109
return new Block(lastHash, lastVotes, transactions, number, epoch, Date.now(),
@@ -102,35 +125,42 @@ class Block {
102125
if (blockInfo instanceof Block) return blockInfo;
103126
return new Block(blockInfo.last_hash, blockInfo.last_votes,
104127
blockInfo.transactions, blockInfo.number, blockInfo.epoch, blockInfo.timestamp,
105-
blockInfo.stateProofHash, blockInfo.proposer, blockInfo.validators);
128+
blockInfo.state_proof_hash, blockInfo.proposer, blockInfo.validators);
106129
}
107130

108131
static hasRequiredFields(block) {
109132
return (block && block.last_hash !== undefined && block.last_votes !== undefined &&
110133
block.transactions !== undefined && block.number !== undefined &&
111134
block.epoch !== undefined && block.timestamp !== undefined &&
112-
block.stateProofHash !== undefined && block.proposer !== undefined &&
135+
block.state_proof_hash !== undefined && block.proposer !== undefined &&
113136
block.validators !== undefined);
114137
}
115138

116139
static validateHashes(block) {
140+
const LOG_HEADER = 'validateHashes';
141+
117142
if (block.hash !== Block.hash(block)) {
118-
logger.error(`Block hash is incorrect for block ${block.hash}`);
143+
logger.error(`[${LOG_HEADER}] Block hash is incorrect for block ${block.hash}`);
119144
return false;
120145
}
121146
if (block.transactions_hash !== ChainUtil.hashString(stringify(block.transactions))) {
122-
logger.error(`Transactions or transactions_hash is incorrect for block ${block.hash}`);
147+
logger.error(
148+
`[${LOG_HEADER}] Transactions or transactions_hash is incorrect for block ${block.hash}`);
123149
return false;
124150
}
125151
if (block.last_votes_hash !== ChainUtil.hashString(stringify(block.last_votes))) {
126-
logger.error(`Last votes or last_votes_hash is incorrect for block ${block.hash}`);
152+
logger.error(
153+
`[${LOG_HEADER}] Last votes or last_votes_hash is incorrect for block ${block.hash}`);
127154
return false;
128155
}
129-
logger.info(`Hash check successfully done`);
156+
logger.info(
157+
`[${LOG_HEADER}] Hash check successfully done for block: ${block.number} / ${block.epoch}`);
130158
return true;
131159
}
132160

133161
static validateProposedBlock(block) {
162+
const LOG_HEADER = 'validateProposedBlock';
163+
134164
if (!Block.validateHashes(block)) return false;
135165
const nonceTracker = {};
136166
let tx;
@@ -144,15 +174,15 @@ class Block {
144174
continue;
145175
}
146176
if (tx.tx_body.nonce != nonceTracker[tx.address] + 1) {
147-
logger.error(`Invalid noncing for ${tx.address} ` +
177+
logger.error(`[${LOG_HEADER}] Invalid noncing for ${tx.address} ` +
148178
`Expected ${nonceTracker[tx.address] + 1} ` +
149179
`Received ${tx.tx_body.nonce}`);
150180
return false;
151181
}
152182
nonceTracker[tx.address] = tx.tx_body.nonce;
153183
}
154184

155-
logger.info(`Valid block of number ${block.number}`);
185+
logger.info(`[${LOG_HEADER}] Validated block: ${block.number} / ${block.epoch}`);
156186
return true;
157187
}
158188

@@ -229,6 +259,34 @@ class Block {
229259
return Transaction.signTxBody(secondTxBody, privateKey);
230260
}
231261

262+
static buildGenesisStakingTxs(timestamp) {
263+
const _ = require('lodash');
264+
const txs = [];
265+
Object.entries(GENESIS_VALIDATORS).forEach(([address, amount], index) => {
266+
const privateKey = _.get(GenesisAccounts,
267+
`${AccountProperties.OTHERS}.${index}.${AccountProperties.PRIVATE_KEY}`);
268+
if (!privateKey) {
269+
throw Error(`GenesisAccounts missing values: ${JSON.stringify(GenesisAccounts)}, ${address}`);
270+
}
271+
const txBody = {
272+
nonce: -1,
273+
timestamp,
274+
operation: {
275+
type: 'SET_VALUE',
276+
ref: ChainUtil.formatPath([
277+
PredefinedDbPaths.DEPOSIT_CONSENSUS,
278+
address,
279+
1,
280+
PredefinedDbPaths.DEPOSIT_VALUE
281+
]),
282+
value: amount
283+
}
284+
};
285+
txs.push(Transaction.signTxBody(txBody, privateKey));
286+
});
287+
return txs;
288+
}
289+
232290
static getGenesisBlockData(genesisTime) {
233291
const ownerAddress = ChainUtil.getJsObject(
234292
GenesisAccounts, [AccountProperties.OWNER, AccountProperties.ADDRESS]);
@@ -237,8 +295,10 @@ class Block {
237295

238296
const firstTx = this.buildDbSetupTx(genesisTime, ownerPrivateKey);
239297
const secondTx = this.buildAccountsSetupTx(ownerAddress, genesisTime, ownerPrivateKey);
298+
// TODO(lia): Change the logic to staking & signing by the current node
299+
const stakingTxs = this.buildGenesisStakingTxs(genesisTime);
240300

241-
return [firstTx, secondTx];
301+
return [firstTx, secondTx, ...stakingTxs];
242302
}
243303

244304
static getGenesisStateProofHash() {
@@ -270,7 +330,7 @@ class Block {
270330
const number = 0;
271331
const epoch = 0;
272332
const proposer = ownerAddress;
273-
const validators = GenesisWhitelist;
333+
const validators = GENESIS_VALIDATORS;
274334
const stateProofHash = Block.getGenesisStateProofHash();
275335
return new Block(lastHash, lastVotes, transactions, number, epoch, genesisTime,
276336
stateProofHash, proposer, validators);

0 commit comments

Comments
 (0)