Skip to content

Commit

Permalink
Merge pull request #38 from cffls/master
Browse files Browse the repository at this point in the history
Support config file
  • Loading branch information
cffls authored Jun 8, 2022
2 parents 42d8a25 + 6acfce2 commit 23bc117
Show file tree
Hide file tree
Showing 17 changed files with 289 additions and 57 deletions.
29 changes: 19 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,24 @@ git clone https://github.com/maticnetwork/matic-cli.git
npm i
mkdir devnet
cd devnet
../bin/matic-cli setup devnet
```

**-----**
**To setup multi-node local network (via docker)**
**-----**
Setup a local network interactively

```bash
../bin/matic-cli setup devnet -i
```

Alternatively, setup a local network with a template configuration file

```bash
../bin/matic-cli setup devnet -c ../configs/devnet/docker-setup-config.yaml
```

You can find more details about configuration options [here](configs/README.md).


#### To setup multi-node local network (via docker)

It will ask you several questions (default values are provided):

Expand Down Expand Up @@ -108,9 +120,8 @@ Logs

Logs will be at `logs/` folder

**-----**
**To setup multi-node remote network**
**-----**

#### To setup multi-node remote network

It will ask you several questions:

Expand Down Expand Up @@ -162,9 +173,7 @@ bash bor-setup.sh
bash bor-start.sh
```

**-----**
**Clean Setup**
**-----**
#### Clean Setup

Remove the devnet folder and you can start the process once again

Expand Down
68 changes: 68 additions & 0 deletions configs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Configurations

`matic-cli` can boostrap a local network with a configuration file. The file could be in yaml or json format.

## Usage

```bash
matic-cli setup devnet -c path/to/config.yaml
```

## Option details with examples

```yaml
# The root target directory where everything related to the network will be created
# If not specified, current directory where the CLI is run will be used.
targetDirectory: /absolute/path/to/target/directory

# Default stake for each validator (in matic)
defaultStake: 10000

# Default amount of fee to topup heimdall validator
defaultFee: 2000

# ChainID of bor
borChainId: "15001"

# ChainID of heimdall
heimdallChainId: heimdall-15001

# Branch of bor to use. Repository: https://github.com/maticnetwork/bor
borBranch: v0.2.16

# Docker build context for bor. When specified, borBranch will be ignore.
# e.g. https://github.com/maticnetwork/bor.git#v0.3.0-dev
borDockerBuildContext: ""

# Branch of Heimdall to use. Repository: https://github.com/maticnetwork/heimdall
heimdallBranch: v0.2.9

# Docker build context for heimdall. When specified, heimdallBranch will be ignore.
# e.g. https://github.com/maticnetwork/heimdall.git#v0.3.0-dev
heimdallDockerBuildContext: ""

# Branch of contract to use. Repostiory: https://github.com/maticnetwork/contracts
contractsBranch: arpit/v0.3.1-backport

# Number of validators to create
numOfValidators: 2

# Number of non-validators (sentry node) to create
numOfNonValidators: 0

# URL to Ethereum RPC
ethURL: http://ganache:9545

# Devnet type, choose from [docker, remote]
devnetType: docker

# IPs of hosts where bor will run. Only effective when devnetType is remote.
devnetBorHosts:
- 172.20.1.100
- 172.20.1.101

# IPs of hosts where heimdall will run. Only effective when devnetType is remote.
devnetHeimdallHosts:
- 172.20.1.100
- 172.20.1.101
```
11 changes: 11 additions & 0 deletions configs/devnet/docker-setup-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
defaultStake: 10000
defaultFee: 2000
borChainId: "15001"
heimdallChainId: heimdall-15001
borBranch: v0.2.16
heimdallBranch: v0.2.9
contractsBranch: arpit/v0.3.1-backport
numOfValidators: 2
numOfNonValidators: 0
ethURL: http://ganache:9545
devnetType: docker
17 changes: 17 additions & 0 deletions configs/devnet/remote-setup-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
defaultStake: 10000
defaultFee: 2000
borChainId: "15001"
heimdallChainId: heimdall-15001
borBranch: v0.2.16
heimdallBranch: v0.2.9
contractsBranch: arpit/v0.3.1-backport
numOfValidators: 2
numOfNonValidators: 0
ethURL: http://172.20.1.100:9545
devnetType: remote
devnetBorHosts:
- 172.20.1.100
- 172.20.1.101
devnetHeimdallHosts:
- 172.20.1.100
- 172.20.1.101
7 changes: 6 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
"nunjucks": "^3.2.1",
"pkg-install": "^0.2.0",
"truffle-privatekey-provider": "1.0.0",
"web3": "^1.2.6"
"web3": "^1.2.6",
"yaml": "^1.10.2"
},
"files": [
"bin/",
Expand Down
3 changes: 3 additions & 0 deletions src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import setupPrograms from './setup'
const setupCmd = program
.version(pkg.version)
.command('setup')
.option('-i, --interactive', 'enable interactive setup')
.option('-c, --config [string]', 'path to configuration file', 'config.json')
.option('-d, --directory [string]', 'path to target output directory', process.cwd())

// add all setup programs as sub commands
setupPrograms.forEach((p) => {
Expand Down
10 changes: 10 additions & 0 deletions src/lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,13 @@ export function privateKeyToPublicKey(pk) {
export function compressedPublicKey(pk) {
return '0x' + ethCrypto.publicKey.compress(pk.replace('0x', ''))
}

export function errorMissingConfigs(configNames) {
if (configNames && configNames.length > 0) {
console.error('Missing the following config attributes: \n')
configNames.forEach((name) => {
console.error(name)
})
process.exit(1)
}
}
8 changes: 6 additions & 2 deletions src/setup/bor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,11 +167,15 @@ async function setupBor(config) {
return true
}

export default async function () {
export default async function (command) {
await printDependencyInstructions()

// configuration
const config = await loadConfig({ targetDirectory: process.cwd() })
await loadConfig({
targetDirectory: command.parent.directory,
fileName: command.parent.config,
interactive: command.parent.interactive
})
await config.loadChainIds()
await config.loadAccounts()

Expand Down
22 changes: 20 additions & 2 deletions src/setup/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import path from 'path'
import execa from 'execa'
import chalk from 'chalk'
import { toBuffer, privateToPublic, bufferToHex } from 'ethereumjs-util'
import YAML from 'yaml'

import { getKeystoreDetails, getChainIds } from './helper'
import { getAccountFromPrivateKey } from '../lib/utils'
Expand Down Expand Up @@ -102,8 +103,17 @@ export async function loadConfig(options = {}) {
const configFile = path.join(targetDirectory, fileName)

const hasConfigFile = await fs.exists(configFile)
let _options = {}
if (hasConfigFile) {
const _options = require(configFile) // get options from config
if (configFile.endsWith('.json')) {
_options = require(configFile) // get options from config
} else if (configFile.endsWith('.yaml') || configFile.endsWith('.yml')) {
const file = fs.readFileSync(configFile, 'utf8')
_options = YAML.parse(file)
} else {
console.error('Unable to recognize file format for file: ', configFile)
process.exit(1)
}
options = {
...options,
..._options
Expand All @@ -125,6 +135,14 @@ export async function loadConfig(options = {}) {

export async function saveConfig(config) {
const configFile = path.join(config.targetDirectory, config.fileName || defaultConfigFileName)
const data = JSON.stringify(config, null, 2)
let data = {}
if (configFile.endsWith('.json')) {
data = JSON.stringify(config, null, 2)
} else if (configFile.endsWith('.yml') || configFile.endsWith('.yaml')) {
data = YAML.stringify(config)
} else {
console.error('Unable to recognize file format for file: ', configFile)
process.exit(1)
}
return fs.writeFileSync(configFile, data, { mode: 0o755 })
}
43 changes: 33 additions & 10 deletions src/setup/devnet/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { Bor } from '../bor'
import { Ganache } from '../ganache'
import { Genesis } from '../genesis'
import { printDependencyInstructions, getDefaultBranch } from '../helper'
import { getNewPrivateKey, getKeystoreFile, processTemplateFiles, getAccountFromPrivateKey } from '../../lib/utils'
import { getNewPrivateKey, getKeystoreFile, processTemplateFiles, getAccountFromPrivateKey, errorMissingConfigs } from '../../lib/utils'
import { loadConfig } from '../config'
import fileReplacer from '../../lib/file-replacer'

Expand Down Expand Up @@ -527,11 +527,15 @@ export async function getHosts(n) {
})
}

export default async function () {
export default async function (command) {
await printDependencyInstructions()

// configuration
const config = await loadConfig()
const config = await loadConfig({
targetDirectory: command.parent.directory,
fileName: command.parent.config,
interactive: command.parent.interactive
})
await config.loadChainIds()

// load branch
Expand Down Expand Up @@ -578,22 +582,41 @@ export default async function () {
})
}

if (!config.interactive) {
errorMissingConfigs(questions.map((q) => {return q.name}))
}

answers = await inquirer.prompt(questions)
config.set(answers)

// set devent hosts
let devnetBorHosts = []
let devnetHeimdallHosts = []
let devnetBorHosts = config.devnetBorHosts || []
let devnetHeimdallHosts = config.devnetHeimdallHosts || []
const totalValidators = config.numOfValidators + config.numOfNonValidators
if (config.devnetType === 'docker') {
[...Array(totalValidators).keys()].forEach((i) => {
devnetBorHosts.push(`172.20.1.${i + 100}`)
devnetHeimdallHosts.push(`heimdall${i}`)
if (devnetBorHosts.length < totalValidators) {
devnetBorHosts.push(`172.20.1.${i + 100}`)
}
if (devnetHeimdallHosts.length < totalValidators) {
devnetHeimdallHosts.push(`heimdall${i}`)
}
})
} else {
const hosts = await getHosts(totalValidators)
devnetBorHosts = hosts
devnetHeimdallHosts = hosts
let missing = ['devnetBorHosts', 'devnetHeimdallHosts'].filter(
(c) => {
if (c in config && config[c].length != totalValidators && !config.interactive) {
console.error(`Wrong number of hosts provided in ${c}, got ${config[c].length}, expect ${totalValidators}.`)
process.exit(1)
}
return !(c in config) || (config[c].length != totalValidators)
}
)
if (missing.length > 0) {
const hosts = await getHosts(totalValidators)
devnetBorHosts = hosts
devnetHeimdallHosts = hosts
}
}
config.set({ devnetBorHosts, devnetHeimdallHosts })

Expand Down
23 changes: 23 additions & 0 deletions src/setup/devnet/templates/docker/docker-compose.yml.njk
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,18 @@ services:
- devnet-network

heimdall{{ node }}:
{% if obj.config.heimdallDockerBuildContext|length %}
{% if node == 0 %}
build:
context: {{ obj.config.heimdallDockerBuildContext }}j
dockerfile: Dockerfile
image: local/heimdall
{% else %}
image: local/heimdall
{% endif %}
{% else %}
image: "maticnetwork/heimdall:{{ obj.config.heimdallBranch }}"
{% endif %}
container_name: heimdall{{ node }}
depends_on:
- rabbit{{ node }}
Expand All @@ -42,7 +53,19 @@ services:
{% endif %}

bor{{ node }}:
{% if obj.config.borDockerBuildContext|length %}
{% if node == 0 %}
build:
context: {{ obj.config.borDockerBuildContext }}
dockerfile: Dockerfile
image: local/bor
{% else %}
image: local/bor
{% endif %}
{% else %}
image: "maticnetwork/bor:{{ obj.config.borBranch }}"
{% endif %}

container_name: bor{{ node }}
# depends_on:
# - heimdall{{ node }}
Expand Down
Loading

0 comments on commit 23bc117

Please sign in to comment.