Skip to content
This repository was archived by the owner on Aug 29, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ The Provenance Blockchain Manager is an application for automated startup of nod
## Usage
In order to execute wizard, run:
```sh
forge
forge interactive
```
* You will be prompted on what you want PBPM to do. Selecting to bootstrap a node will allow you to select mainnet, testnet, or localnet.
* You will be prompted on what you want Forge to do. Selecting to bootstrap a node will allow you to select mainnet, testnet, or localnet.

* Selecting any of the listed 3 would clone the [Provenance Repository](https://github.com/provenance-io/provenance) if it doesn't already exist, then the version information would be gathered either from the user in the case of localnet, or from mainnet/testnet information on github.

Expand All @@ -19,17 +19,18 @@ forge

To get you started with a couple commands:

Initialize and possibly start a mainnet node without wizard:
Initialize and start a localnet node with default values:
```sh
forge -ba WITH_CLEVELDB=no -n mainnet
```
Initialize and possibly start a localnet:
```sh
forge -rv v1.7.5 -ba WITH_CLEVELDB=no -n localnet -m aMoniker -cid theChainId
forge node start
```
For a list of all commands:
```sh
forge --help
```
You can also drill into the individual commands for more help and additional commands:
```sh
forge node --help
```

## Version Info
* Python 3.6
17 changes: 7 additions & 10 deletions forgepb/__main__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import os
import sys

# Development mode.
if os.getenv("DEBUG"):
print("DEBUG is set, injecting '.' into sys.path for local module lookup")
sys.path.insert(0, '.')

from forgepb.command_line import start
from command_line import root_cmd

if __name__ == '__main__':
start()
try:
root_cmd()
exit(0)
except Exception as e:
print(e)
exit(1)
113 changes: 72 additions & 41 deletions forgepb/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@
def build(environment, network, config, provenance_branch=None, version=None, args=[], moniker=None, chain_id=None, start_node=None):
root_path = config['saveDir'] + "forge"
provenance_path = config['saveDir'] + "forge" + "/provenance"
if not os.path.exists(provenance_path):
print("Cloning Repository for binary construction, this can take a few seconds...")
git.Repo.clone_from(global_.PROVENANCE_REPO, provenance_path)
# Get version and checkout to proper provenance tag
if not version and not provenance_branch:
version = utils.get_version_info(network, environment, provenance_path)
elif not provenance_branch and version:
if version and version not in utils.get_versions(provenance_path):
print("The version entered doesn't exist in provenance. Please run 'forge -lsv' to list all versions")
if version and version not in utils.get_versions():
print(
"The version entered doesn't exist in provenance. Please run 'forge -lsv' to list all versions")
exit()
repo = git.Repo(provenance_path)
repo.git.reset('--hard')
Expand All @@ -30,16 +34,15 @@ def build(environment, network, config, provenance_branch=None, version=None, ar
repo.git.checkout("-f", version)
elif provenance_branch:
version = provenance_branch
branches = utils.get_remote_branches()
repo = git.Repo(provenance_path)
repo.git.reset('--hard')
repo.git.checkout('main')
repo.remotes.origin.pull()
print(branches)
try:
branches = [branch.name for branch in repo.remote().refs]
if provenance_branch in branches:
repo.git.checkout(provenance_branch)
else:
print("The entered branch, {}, does not exist.".format(provenance_branch))
print("The entered branch, {}, does not exist.".format(
provenance_branch))
exit()
except git.exc.GitCommandError:
repo.git.checkout("-f", provenance_branch)
Expand All @@ -61,7 +64,7 @@ def build(environment, network, config, provenance_branch=None, version=None, ar
copyfile(go_path, "{}/bin/provenanced".format(build_path))
st = os.stat(build_path + "/bin/provenanced")
os.chmod(build_path + "/bin/provenanced", st.st_mode | stat.S_IEXEC)

# Collect moniker and chain id if they aren't given
if not moniker or not chain_id:
version_data = utils.collect_moniker_chain_id(version, config)
Expand All @@ -81,14 +84,18 @@ def build(environment, network, config, provenance_branch=None, version=None, ar
utils.save_config(config)

validator_info = populate_genesis(build_path, moniker, chain_id)
utils.persist_localnet_information(build_path, config, version, validator_info)

run_command = "{}/bin/provenanced start --home {}".format(build_path, build_path).split(" ")
log_path = '{}/logs/{}.txt'.format(build_path, str(datetime.datetime.now()).replace(' ', '-'))
utils.persist_localnet_information(
build_path, config, version, validator_info)

run_command = "{}/bin/provenanced start --home {}".format(
build_path, build_path).split(" ")
log_path = '{}/logs/{}.txt'.format(build_path,
str(datetime.datetime.now()).replace(' ', '-'))
if(start_node):
spawnDaemon(run_command, version, network, config, log_path)
else:
utils.take_start_node_input(run_command, version, network, config, log_path)
utils.take_start_node_input(
run_command, version, network, config, log_path)

# Handle mainnet and testnet node construction
else:
Expand Down Expand Up @@ -117,55 +124,76 @@ def build(environment, network, config, provenance_branch=None, version=None, ar
while not genesis_complete:
try:
if os.path.exists(build_path + "/config/genesis.json"):
download_genesis = input("The genesis file already exists, would you like to overwrite the existing file?[y]/n:\n")
download_genesis = input(
"The genesis file already exists, would you like to overwrite the existing file?[y]/n:\n")
if not download_genesis or download_genesis.lower() == 'y':
print("Downloading genesis file...")
genesis_json_res = requests.get(global_.GENESIS_JSON_URL.format(network, environment)).text
open(build_path + "/config/genesis.json", 'w').write(genesis_json_res)
genesis_json_res = requests.get(
global_.GENESIS_JSON_URL.format(network, environment)).text
open(build_path + "/config/genesis.json",
'w').write(genesis_json_res)
genesis_complete = True
else:
genesis_json_res = requests.get(global_.GENESIS_JSON_URL.format(network, environment)).text
open(build_path + "/config/genesis.json", 'w').write(genesis_json_res)
genesis_json_res = requests.get(
global_.GENESIS_JSON_URL.format(network, environment)).text
open(build_path + "/config/genesis.json",
'w').write(genesis_json_res)
genesis_complete = True
except ValueError as e:
print(e)
continue


# Take seed information for testnet and mainnet
if network == "testnet":
seed_info = global_.TESTNET_SEEDS
else:
seed_info = global_.MAINNET_SEEDS

if network not in config:
config[network] = {}
config[network]['version'] = version
utils.save_config(config)

run_command = "{}/bin/provenanced start {} --home {}".format(build_path, seed_info, build_path).split(" ")
log_path = '{}/logs/{}.txt'.format(build_path, str(datetime.datetime.now()).replace(' ', '-'))
run_command = "{}/bin/provenanced start {} --home {}".format(
build_path, seed_info, build_path).split(" ")
log_path = '{}/logs/{}.txt'.format(build_path,
str(datetime.datetime.now()).replace(' ', '-'))

if(start_node):
spawnDaemon(run_command, version, network, config, log_path)
else:
utils.take_start_node_input(run_command, version, network, config, log_path)
utils.take_start_node_input(
run_command, version, network, config, log_path)

# Localnet generate genesis and gentx


def populate_genesis(build_path, moniker, chain_id):
command1 = "{}/bin/provenanced --home {} init {} --chain-id {};".format(build_path, build_path, moniker, chain_id)
command2 = "{}/bin/provenanced --home {} keys add validator --keyring-backend test 2>&1;".format(build_path, build_path, build_path)
command3 = "{}/bin/provenanced --home {} add-genesis-root-name validator pio --keyring-backend test 2>&- || echo pio root name already exists, skipping...;".format(build_path, build_path)
command3 += "{}/bin/provenanced --home {} add-genesis-root-name validator pb --restrict=false --keyring-backend test 2>&- || echo pb root name already exists, skipping...;".format(build_path, build_path)
command3 += "{}/bin/provenanced --home {} add-genesis-root-name validator io --restrict --keyring-backend test 2>&- || echo io root name already exists, skipping...;".format(build_path, build_path)
command3 += "{}/bin/provenanced --home {} add-genesis-root-name validator provenance --keyring-backend test 2>&- || echo validator root name already exists, skipping...;".format(build_path, build_path)
command3 += "{}/bin/provenanced --home {} add-genesis-account validator 100000000000000000000nhash --keyring-backend test 2>&-;".format(build_path, build_path)
command3 += "{}/bin/provenanced --home {} gentx validator 1000000000000000nhash --keyring-backend test --chain-id={} 2>&- || echo gentx file already exists, skipping;".format(build_path, build_path, chain_id)
command3 += "{}/bin/provenanced --home {} add-genesis-marker 100000000000000000000nhash --manager validator --access mint,burn,admin,withdraw,deposit --activate --keyring-backend test 2>&- || echo existing address, skipping;".format(build_path, build_path)
command3 += "{}/bin/provenanced --home {} collect-gentxs".format(build_path, build_path)
validator_check_command = "{}/bin/provenanced --home {} keys show validator".format(build_path, build_path)
command1 = "{}/bin/provenanced --home {} init {} --chain-id {};".format(
build_path, build_path, moniker, chain_id)
command2 = "{}/bin/provenanced --home {} keys add validator --keyring-backend test 2>&1;".format(
build_path, build_path, build_path)
command3 = "{}/bin/provenanced --home {} add-genesis-root-name validator pio --keyring-backend test 2>&- || echo pio root name already exists, skipping...;".format(
build_path, build_path)
command3 += "{}/bin/provenanced --home {} add-genesis-root-name validator pb --restrict=false --keyring-backend test 2>&- || echo pb root name already exists, skipping...;".format(
build_path, build_path)
command3 += "{}/bin/provenanced --home {} add-genesis-root-name validator io --restrict --keyring-backend test 2>&- || echo io root name already exists, skipping...;".format(
build_path, build_path)
command3 += "{}/bin/provenanced --home {} add-genesis-root-name validator provenance --keyring-backend test 2>&- || echo validator root name already exists, skipping...;".format(
build_path, build_path)
command3 += "{}/bin/provenanced --home {} add-genesis-account validator 100000000000000000000nhash --keyring-backend test 2>&-;".format(
build_path, build_path)
command3 += "{}/bin/provenanced --home {} gentx validator 1000000000000000nhash --keyring-backend test --chain-id={} 2>&- || echo gentx file already exists, skipping;".format(
build_path, build_path, chain_id)
command3 += "{}/bin/provenanced --home {} add-genesis-marker 100000000000000000000nhash --manager validator --access mint,burn,admin,withdraw,deposit --activate --keyring-backend test 2>&- || echo existing address, skipping;".format(
build_path, build_path)
command3 += "{}/bin/provenanced --home {} collect-gentxs".format(
build_path, build_path)
validator_check_command = "{}/bin/provenanced --home {} keys show validator".format(
build_path, build_path)
os.system(command1)
validator_check_process = subprocess.Popen(validator_check_command, shell=True, stdout=subprocess.PIPE)
validator_check_process = subprocess.Popen(
validator_check_command, shell=True, stdout=subprocess.PIPE)
validator_check_process.wait()
validators_out, err = validator_check_process.communicate()
if validators_out.decode('utf-8').startswith('- name:'):
Expand All @@ -177,9 +205,10 @@ def populate_genesis(build_path, moniker, chain_id):
os.system(command3)
return out.decode('utf-8')


def spawnDaemon(node_command, version, network, config, log_path):
try:
pid = os.fork()
try:
pid = os.fork()
if pid > 0:
return
except OSError as e:
Expand All @@ -190,19 +219,21 @@ def spawnDaemon(node_command, version, network, config, log_path):
try:
pid = os.fork()
if pid > 0:
exit()
return
except OSError as e:
print("fork #1 failed: {} ({})".format(e.errno, e.strerror))

start_node(node_command, version, network, config, log_path)

os._exit(os.EX_OK)


def start_node(node_command, version, network, config, log_path):
log = open(log_path, 'w+')
print('Running {}'.format(node_command))
print('Running {}'.format(''.join(node_command)))
print('You can view the logs here: {}'.format(log_path))
process = subprocess.Popen(node_command, shell=False, stdout=log, stderr=log)
process = subprocess.Popen(
node_command, shell=False, stdout=log, stderr=log)
if network == 'localnet':
config[network][version]['run-command'] = node_command
config[network][version]['log-path'] = log_path
Expand All @@ -216,4 +247,4 @@ def start_node(node_command, version, network, config, log_path):
"network": network
}
utils.save_config(config)
process.wait()
process.wait()
30 changes: 30 additions & 0 deletions forgepb/cmd/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import click

from cmd.node import *
from cmd.config import *
from cmd.provenance import *


@click.group("node", help="Interact with nodes")
def node_cmd(): pass


@click.group("config")
def config_cmd(): pass

@click.group("provenance", help="Retrieve information on provenance")
def provenance_cmd(): pass


# Hook up sub commands for node management.
node_cmd.add_command(node_stop_cmd)
node_cmd.add_command(node_start_cmd)
node_cmd.add_command(node_status_cmd)
node_cmd.add_command(node_init_cmd)
node_cmd.add_command(list_mnemonic_cmd)

config_cmd.add_command(list_config_cmd)
config_cmd.add_command(change_save_loc_cmd)

provenance_cmd.add_command(list_tags_cmd)
provenance_cmd.add_command(list_branches_cmd)
67 changes: 67 additions & 0 deletions forgepb/cmd/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import json
import os
import click

from forgepb import utils, builder, forge, config_handler, global_


@click.command(
'list',
help='List config information about localnet nodes that have been initialized'
)
@click.option(
"-t",
"--tag",
"tag",
default=None,
help="Release tag used to specify the localnet config to display")
@click.option(
'-b',
'--provenance-branch',
'provenance_branch',
type=click.STRING,
help='Provenance branch used to specify the localnet config to display')
def list_config_cmd(tag, provenance_branch):
# get config or set location of config to be made
if not os.path.exists(global_.CONFIG_PATH + "/config.json"):
config = config_handler.set_build_location()
else:
config = utils.load_config()
provenance_path = config['saveDir'] + "forge" + "/provenance"
# Retrieve the config information if it exists, else display a message saying that it couldn't be found
try:
if tag:
if tag not in utils.get_versions():
print(
"The version entered doesn't exist in provenance. Please run 'forge -lsv' to list all versions")
else:
print(json.dumps(config['localnet'][tag], indent=4))
elif provenance_branch:
if provenance_branch not in utils.get_remote_branches():
print(
"The version entered doesn't exist in provenance. Please run 'forge -lsv' to list all versions")
else:
print(json.dumps(config['localnet']
[provenance_branch], indent=4))
else:
print(json.dumps(config['localnet'], indent=4))
except KeyError:
print("No nodes found.")
except:
print("No nodes have been initialized.")


@click.command(
'save_location',
help='Change the save location of forge'
)
@click.option(
'-p',
'--path',
'path',
type=click.STRING,
help='Existing path that forge will save initialized nodes into'
)
def change_save_loc_cmd(path):
config_handler.check_save_location(path)
return
Loading