Skip to content
This repository has been archived by the owner on Jun 11, 2024. It is now read-only.

Commit

Permalink
Add second sidechain to interop examples (#8345)
Browse files Browse the repository at this point in the history
* 🌱 Add second sidechain example

* 💅🏻Rename sidechain one to pos-sidechain-example-one

* ⚙️ Add configurations for multiple side/mainchain nodes

* 🌱 Add support for cross chain transfers on example apps

* 🌱 Add cross chain transfer scripts

* ♻️ Update interoperability genesis assets and bump sdk version

* ♻️ Bump version of SDK and update genesis-block

* 🌱 Add second sidechain example

* 💅🏻Rename sidechain one to pos-sidechain-example-one

* ⚙️ Add configurations for multiple side/mainchain nodes

* ⬆️ Bump sdk version and update genesis-blocks

* ♻️ Resolve merge conflicts and update genesis block

* 🌱 Add recovery plugin script

* ♻️ Update recover LSK script

* Add scripts and updated README

* ♻️ Store storeValue with each inclusionProof

* ⬆️ Bump sdk version

* 🌱 Add second sidechain example

* 💅🏻Rename sidechain one to pos-sidechain-example-one

* ⚙️ Add configurations for multiple side/mainchain nodes

* 🌱 Add cross chain transfer scripts

* ♻️ Update interoperability genesis assets and bump sdk version

* 🌱 Add second sidechain example

* 💅🏻Rename sidechain one to pos-sidechain-example-one

* ⚙️ Add configurations for multiple side/mainchain nodes

* Move mainchain registration to common file

* Fix typo

* ♻️ Update genesisBlock

* ♻️ Update genesisBlock

* 🌱 Add genesis-assets for 103 validators

* 💅🏻Update readme

---------

Co-authored-by: Franco NG <[email protected]>
Co-authored-by: Khalid Hameed <[email protected]>
  • Loading branch information
3 people authored Apr 24, 2023
1 parent 97cc901 commit c49607a
Show file tree
Hide file tree
Showing 153 changed files with 13,698 additions and 531 deletions.
134 changes: 86 additions & 48 deletions examples/interop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,33 @@

This folder contains example applications for mainchain and sidechain with POS consensus algorithm.

- pos-mainchain-fast

Genesis Configuration:

- pos-mainchain-fast

```js
blockTime: 5;
bftBatchSize: 5;
chainID: 04000000;
```

Below configuration added for Chain Connector Plugin in `config/default/config.json`

```json
"plugins": {
"chainConnector": {
"receivingChainID": "04000001",
"encryptedPrivateKey": "kdf=argon2id&cipher=aes-256-gcm&version=1&ciphertext=47f00a1502fb1b4fe4db2427a805636e7b3d82be7b8b8c5aa8e0325fbe777dba8bea9daa1ef3d6b81784866229277fb2935dbd977ad40f3451081c1ef3fbc03ee044779241d99257bdcce2bd646cc7c9ceeb1952de88baf5fa7fe597cf20744ed8cdbbbc16fa3ff9a712272b61882d7fb7ed9b267ea1a12970352ba8a8dcded5&mac=f7a7a7b6c2c47e2305f4dc5019a0511b9645ef6c68a5b1f7de324ca995c1c869&salt=6483dd1e9c6b00f0b9e8968b0f852bd6&iv=eb182b56fc868be3ac2a5de6&tag=0f8572a9a25b6d344ee50f53e7af9a11&iterations=1&parallelism=4&memorySize=2024",
"password": "lisk",
"ccuFee": "1000000000",
"receivingChainIPCPath": "~/.lisk/pos-sidechain-fast"
}
}
chainID: '04000000';
name: 'lisk_mainchain';
```

- pos-sidechain-fast

Genesis Configuration:
- pos-sidechain-example-one

```js
blockTime: 5;
bftBatchSize: 5;
chainID: 04000001;
chainID: '04000001';
name: 'sidechain_example_one';
```

Below configuration added for Chain Connector Plugin in `config/default/config.json`

```json
"plugins": {
"chainConnector": {
"receivingChainID": "04000000",
"encryptedPrivateKey": "kdf=argon2id&cipher=aes-256-gcm&version=1&ciphertext=ab4354c56527e236f4a4b1abed94519b2db8f2f5568f995f679466f597a7a0f4a124358a19a84b84328c8a6e8cc0c96f2234bbc279f9554723e4c21d73aa03ad0ca010110b76ca0680c3f43d2b66c574eb03ed306b8944d40db706a06a14931723ac1df7d613fe654d941c7c25e64cd9e8727e13314346b3bb519c9839338d9e&mac=9348ac2fcc1bc870cacef541cb00838e4f70b8c61239721286cb9a5d67c627c8&salt=ead34f6a3ae8f821396881e033dde523&iv=364dddf45dd0fee2f5971ae2&tag=d347e6e4b057e3bd5692904c595fd5a2&iterations=1&parallelism=4&memorySize=2024",
"password": "lisk",
"ccuFee": "1000000000",
"receivingChainIPCPath": "~/.lisk/pos-mainchain-fast"
}
}
- pos-sidechain-example-two

```js
blockTime: 5;
bftBatchSize: 5;
chainID: '04000002';
name: 'sidechain_example_two';
```

### How to run?
Expand All @@ -59,40 +40,97 @@ Install and build `pos-mainchain-fast`
- `cd pos-mainchain-fast`
- `yarn && yarn build`

Install and build `pos-sidechain-fast`
Install and build `pos-sidechain-example-one`

- `cd pos-sidechain-example-one`
- `yarn && yarn build`

Install and build `pos-sidechain-example-two`

- `cd pos-sidechain-fast`
- `cd pos-sidechain-example-two`
- `yarn && yarn build`

#### Run apps using pm2

Install [pm2](https://pm2.keymetrics.io/) if not installed using `npm install pm2 -g`

Run below commands to start mainchain and sidechain applications
Run 2 instances mainchain node

- `cd pos-mainchain-fast`
- `pm2 start config/mainchain_node_one.sh`
- `pm2 start config/mainchain_node_two.sh`

Run below commands to start sidechain applications

- Come back to interop folder after above step `cd ..`
- Run `pm2 start run_sidechains.json`

- `pm2 interop/pos-mainchain-fast/src/pm2.json`
- `pm2 interop/pos-sidechain-fast/src/pm2.json`
Above steps will run 2 mainchain nodes of the same network with chainID `04000000` and 1 sidechain node of each network (2 nodes in total for sidechains) with chainID `04000001` and `04000002` respectively.

Interact with applications using `pm2`

- `pm2 ls` to list all the applications with their status
- `pm2 logs 0` or `pm2 logs mainchain-pos` to see the logs of individual apps.
- `pm2 start 0` or `pm2 start mainchain-pos` to start an application
- `pm2 stop 0` or `pm2 stop mainchain-pos` to stop an application
- `pm2 logs 0` or `pm2 logs mainchain_node_one` to see the logs of individual apps.
- `pm2 start 0` or `pm2 start mainchain_node_one` to start an application
- `pm2 stop 0` or `pm2 stop mainchain_node_one` to stop an application
- `pm2 start all` to start all the applications
- `pm2 stop all` to stop all the applications

#### Register chains

- Run `ts-node /pos-mainchain-fast/config/scripts/sidechain_registration.ts` to register sidechain on mainchain node
- Run `ts-node /pos-sidechain-fast/config/scripts/mainchain_registration.ts`
to register mainchain on sidechain node
- Run `ts-node pos-mainchain-fast/config/scripts/sidechain_registration.ts` to register all the sidechains on the mainchain node.
- Run `ts-node pos-sidechain-example-one/config/scripts/mainchain_registration.ts` to register sidechain `sidechain_example_one` on mainchain.
- Run `ts-node pos-sidechain-example-two/config/scripts/mainchain_registration.ts` to register sidechain `sidechain_example_two` on mainchain.

Check chain status
#### Check chain status

- Run `./bin/run endpoint:invoke 'interoperability_getChainAccount' '{"chainID": "04000000" }'` to check chain status of mainchain account on sidechain. It should show lastCertificate with height 0 and status 0.
- Run `./bin/run endpoint:invoke 'interoperability_getChainAccount' '{"chainID": "04000001" }'` to check chain status of sidechain account on mainchain. It should show lastCertificate with height 0 and status 0.
- Run `./bin/run endpoint:invoke 'interoperability_getChainAccount' '{"chainID": "04000000" }'` to check chain status of mainchain account on sidechain. It should show lastCertificate with height 0 and status 0 if no CCU was sent yet.
- Run `./bin/run endpoint:invoke 'interoperability_getChainAccount' '{"chainID": "04000001" }'` to check chain status of sidechain account on mainchain. It should show lastCertificate with height 0 and status 0 if no CCU was sent yet.

Now observe logs, intially it will log `No valid CCU can be generated for the height: ${newBlockHeader.height}` until first finalized height is reached.
Now observe logs, initially it will log `No valid CCU can be generated for the height: ${newBlockHeader.height}` until first finalized height is reached.

When the finalized height is reached, check chain status as described above and it should update lastCertificate height > 0 and status to 1 which means the CCU was sent successfully and chain is active now.

#### Cross Chain transfers

##### Transfer from mainchain to sidechain one

- Run `ts-node pos-mainchain-fast/config/scripts/transfer_lsk_sidechain_one.ts` from `interop` folder.
- Check balance for `lskxz85sur2yo22dmcxybe39uvh2fg7s2ezxq4ny9` using `token_getBalances` RPC on sidechain one.

##### Transfer from mainchain to sidechain two

- Run `ts-node pos-mainchain-fast/config/scripts/transfer_lsk_sidechain_two.ts` from `interop` folder.
- Check balance for `lskx5uqu2zzybdwrqswd8c6b5v5aj77yytn4k6mv6` using `token_getBalances` RPC on sidechain two.

##### Transfer sidechain one to mainchain

- Run `ts-node pos-sidechain-example-one/config/scripts/transfer_lsk_mainchain.ts` from `interop` folder.
- Check balance for `lskzjzeam6szx4a65sxgavr98m9h4kctcx85nvy7h` using `token_getBalances` RPC on mainchain.

##### Transfer sidechain two to sidechain one

- Run `ts-node pos-sidechain-example-one/config/scripts/transfer_sidechain_one.ts` from `interop` folder.
- Check balance for `lskxvesvwgxpdnhp4rdukmsx42teehpxkeod7xv7f` using `token_getBalances` RPC on sidechain one.

##### Transfer sidechain one to sidechain two

- Run `ts-node pos-sidechain-example-one/config/scripts/transfer_sidechain_two.ts` from `interop` folder.
- Check balance for `lskx5uqu2zzybdwrqswd8c6b5v5aj77yytn4k6mv6` using `token_getBalances` RPC on sidechain one.

### Helper Scripts

#### start_example

- It build 4 chains, starts with pm2, and register chains
- If you want to restart everything from scratch, run `./start_example --reset`

#### monitor

- Calls 4 chain's getAllChainAccounts at the same time, at 5s interval

#### Other options

There are `genesis_assets_103_validators.json` file under config folder of each app. You can also use this genesis-assets if you want to run an application for 103 validators. In order to do so follow these steps:

- Update genesis block using command: `./bin/run genesis-block:create --output config/default/ --assets-file config/default/genesis_assets_103_validators.json`
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import { codec, cryptography, apiClient, Transaction } from 'lisk-sdk';
import { keys as sidechainValidatorsKeys } from '../../config/default/dev-validators.json';
import {
registrationSignatureMessageSchema,
mainchainRegParams as mainchainRegParamsSchema,
MESSAGE_TAG_CHAIN_REG,
MODULE_NAME_INTEROPERABILITY,
} from 'lisk-framework';
import { keys as sidechainDevValidators } from '../default/dev-validators.json';
import { COMMAND_NAME_MAINCHAIN_REG } from 'lisk-framework/dist-node/modules/interoperability/constants';

(async () => {
export const registerMainchain = async (
num: string,
sidechainDevValidators: any[],
sidechainValidatorsKeys: any[],
) => {
const { bls, address } = cryptography;

const mainchainClient = await apiClient.createIPCClient('~/.lisk/pos-mainchain-fast');
const sidechainClient = await apiClient.createIPCClient('~/.lisk/pos-sidechain-fast');
const mainchainClient = await apiClient.createIPCClient(`~/.lisk/mainchain-node-${num}`);
const sidechainClient = await apiClient.createIPCClient(`~/.lisk/pos-sidechain-example-${num}`);

const mainchainNodeInfo = await mainchainClient.invoke('system_getNodeInfo');
const sidechainNodeInfo = await sidechainClient.invoke('system_getNodeInfo');

// Get active validators from mainchain
const {
validators: mainchainActiveValidators,
Expand All @@ -24,7 +30,7 @@ import { keys as sidechainDevValidators } from '../default/dev-validators.json';

const paramsJSON = {
ownChainID: sidechainNodeInfo.chainID,
ownName: 'lisk_sidechain',
ownName: `sidechain_example_${num}`,
mainchainValidators: (mainchainActiveValidators as { blsKey: string; bftWeight: string }[])
.map(v => ({ blsKey: v.blsKey, bftWeight: v.bftWeight }))
.sort((a, b) => Buffer.from(a.blsKey, 'hex').compare(Buffer.from(b.blsKey, 'hex'))),
Expand All @@ -43,14 +49,14 @@ import { keys as sidechainDevValidators } from '../default/dev-validators.json';

const message = codec.encode(registrationSignatureMessageSchema, params);

// Get active validators from sidechainchain
const { validators: sidehcainActiveValidators } = await sidechainClient.invoke(
// Get active validators from sidechainChain
const { validators: sidechainActiveValidators } = await sidechainClient.invoke(
'consensus_getBFTParameters',
{ height: sidechainNodeInfo.height },
);

const activeValidatorsWithPrivateKey: { blsPublicKey: Buffer; blsPrivateKey: Buffer }[] = [];
for (const v of sidehcainActiveValidators as { blsKey: string; bftWeight: string }[]) {
for (const v of sidechainActiveValidators as { blsKey: string; bftWeight: string }[]) {
const validatorInfo = sidechainValidatorsKeys.find(
configValidator => configValidator.plain.blsKey === v.blsKey,
);
Expand All @@ -62,7 +68,7 @@ import { keys as sidechainDevValidators } from '../default/dev-validators.json';
}
}
console.log('Total activeValidatorsWithPrivateKey:', activeValidatorsWithPrivateKey.length);
// Sort active validators from sidechainchain
// Sort active validators from sidechainChain
activeValidatorsWithPrivateKey.sort((a, b) => a.blsPublicKey.compare(b.blsPublicKey));

const sidechainValidatorsSignatures: { publicKey: Buffer; signature: Buffer }[] = [];
Expand All @@ -86,28 +92,28 @@ import { keys as sidechainDevValidators } from '../default/dev-validators.json';
sidechainValidatorsSignatures,
);

const relayerkeyInfo = sidechainDevValidators[0];
const relayerKeyInfo = sidechainDevValidators[0];
const { nonce } = await sidechainClient.invoke<{ nonce: string }>('auth_getAuthAccount', {
address: address.getLisk32AddressFromPublicKey(Buffer.from(relayerkeyInfo.publicKey, 'hex')),
address: address.getLisk32AddressFromPublicKey(Buffer.from(relayerKeyInfo.publicKey, 'hex')),
});
const mainchainRegmainchainRegParams = {
const mainchainRegParams = {
...paramsJSON,
signature: signature.toString('hex'),
aggregationBits: aggregationBits.toString('hex'),
};
const tx = new Transaction({
module: 'interoperability',
command: 'registerMainchain',
module: MODULE_NAME_INTEROPERABILITY,
command: COMMAND_NAME_MAINCHAIN_REG,
fee: BigInt(2000000000),
params: codec.encodeJSON(mainchainRegParamsSchema, mainchainRegmainchainRegParams),
params: codec.encodeJSON(mainchainRegParamsSchema, mainchainRegParams),
nonce: BigInt(nonce),
senderPublicKey: Buffer.from(relayerkeyInfo.publicKey, 'hex'),
senderPublicKey: Buffer.from(relayerKeyInfo.publicKey, 'hex'),
signatures: [],
});

tx.sign(
Buffer.from(sidechainNodeInfo.chainID as string, 'hex'),
Buffer.from(relayerkeyInfo.privateKey, 'hex'),
Buffer.from(relayerKeyInfo.privateKey, 'hex'),
);

const result = await sidechainClient.invoke<{
Expand All @@ -117,6 +123,5 @@ import { keys as sidechainDevValidators } from '../default/dev-validators.json';
});

console.log('Sent mainchain registration transaction. Result from transaction pool is: ', result);

process.exit(0);
})();
};
75 changes: 75 additions & 0 deletions examples/interop/monitor
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/bin/sh

if ! command -v jq &> /dev/null
then
echo "jq Not installed in this computer."
echo "Please go to https://stedolan.github.io/jq/"
exit
fi

while [ true ]
do
now=$(date +"%T")
echo "Captured At: $now"

#mainchain 1
RESULT=$(curl --location -s 'http://127.0.0.1:7881/rpc' \
--header 'Content-Type: text/plain' \
--data '{
"jsonrpc": "2.0",
"id": 1,
"method": "interoperability_getAllChainAccounts",
"params": {
"chainID": "00000000"
}
}')
echo "- Mainchain_1:"
echo "$(echo $RESULT | jq '.result.chains[0].name') : Height: $(echo $RESULT | jq '.result.chains[0].lastCertificate.height') | Status: $(echo $RESULT | jq '.result.chains[0].status')"
echo "$(echo $RESULT | jq '.result.chains[1].name') : Height: $(echo $RESULT | jq '.result.chains[0].lastCertificate.height') | Status: $(echo $RESULT | jq '.result.chains[1].status')"

#mainchain 2
RESULT=$(curl --location -s 'http://127.0.0.1:7882/rpc' \
--header 'Content-Type: text/plain' \
--data '{
"jsonrpc": "2.0",
"id": 1,
"method": "interoperability_getAllChainAccounts",
"params": {
"chainID": "00000000"
}
}')
echo "- Mainchain_2:"
echo "$(echo $RESULT | jq '.result.chains[0].name') : Height: $(echo $RESULT | jq '.result.chains[0].lastCertificate.height') | Status: $(echo $RESULT | jq '.result.chains[0].status')"
echo "$(echo $RESULT | jq '.result.chains[1].name') : Height: $(echo $RESULT | jq '.result.chains[0].lastCertificate.height') | Status: $(echo $RESULT | jq '.result.chains[1].status')"

#sidechain 1
RESULT=$(curl --location -s 'http://127.0.0.1:7885/rpc' \
--header 'Content-Type: text/plain' \
--data '{
"jsonrpc": "2.0",
"id": 1,
"method": "interoperability_getAllChainAccounts",
"params": {
"chainID": "00000000"
}
}')
echo "- Sidechain_1:"
echo "$(echo $RESULT | jq '.result.chains[0].name') : Height: $(echo $RESULT | jq '.result.chains[0].lastCertificate.height') | Status: $(echo $RESULT | jq '.result.chains[0].status')"

#sidechain 2
RESULT=$(curl --location -s 'http://127.0.0.1:7886/rpc' \
--header 'Content-Type: text/plain' \
--data '{
"jsonrpc": "2.0",
"id": 1,
"method": "interoperability_getAllChainAccounts",
"params": {
"chainID": "00000000"
}
}')
echo "- Sidechain 2:"
echo "$(echo $RESULT | jq '.result.chains[0].name') : Height: $(echo $RESULT | jq '.result.chains[0].lastCertificate.height') | Status: $(echo $RESULT | jq '.result.chains[0].status')"

echo "====================================="
sleep 5;
done
Loading

0 comments on commit c49607a

Please sign in to comment.