From 8d355d572b3c24a8349642069a6be7a43cafcaec Mon Sep 17 00:00:00 2001 From: Silas Davis <silas@erisindustries.com> Date: Tue, 6 Dec 2016 15:47:21 +0000 Subject: [PATCH] Pull in configuration templating from eris-cm --- config/config.go | 176 +++++++++++++++++++++++ config/config_test.go | 29 ++++ config/templates.go | 318 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 523 insertions(+) create mode 100644 config/config.go create mode 100644 config/config_test.go create mode 100644 config/templates.go diff --git a/config/config.go b/config/config.go new file mode 100644 index 00000000..a37cf96f --- /dev/null +++ b/config/config.go @@ -0,0 +1,176 @@ +// Copyright 2015, 2016 Monax Industries (UK) Ltd. +// This file is part of Eris-RT + +// Eris-RT is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Eris-RT is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Eris-RT. If not, see <http://www.gnu.org/licenses/>. + +package config + +import ( + "bytes" + "fmt" + "text/template" +) + +type ConfigServiceGeneral struct { + ChainImageName string + UseDataContainer bool + ExportedPorts string + ContainerEntrypoint string +} + +// TODO: [ben] increase the configurability upon need +type ConfigChainGeneral struct { + AssertChainId string + ErisdbMajorVersion uint8 + ErisdbMinorVersion uint8 + GenesisRelativePath string +} + +type ConfigChainModule struct { + Name string + MajorVersion uint8 + MinorVersion uint8 + ModuleRelativeRoot string +} + +type ConfigTendermint struct { + Moniker string + Seeds string + FastSync bool +} + +var serviceGeneralTemplate *template.Template +var chainGeneralTemplate *template.Template +var chainConsensusTemplate *template.Template +var chainApplicationManagerTemplate *template.Template +var tendermintTemplate *template.Template + +func init() { + var err error + if serviceGeneralTemplate, err = template.New("serviceGeneral").Parse(sectionServiceGeneral); err != nil { + panic(err) + } + if chainGeneralTemplate, err = template.New("chainGeneral").Parse(sectionChainGeneral); err != nil { + panic(err) + } + if chainConsensusTemplate, err = template.New("chainConsensus").Parse(sectionChainConsensus); err != nil { + panic(err) + } + if chainApplicationManagerTemplate, err = template.New("chainApplicationManager").Parse(sectionChainApplicationManager); err != nil { + panic(err) + } + if tendermintTemplate, err = template.New("tendermint").Parse(sectionTendermint); err != nil { + panic(err) + } +} + +// NOTE: [ben] for 0.12.0-rc3 we only have a single configuration path +// with Tendermint in-process as the consensus engine and ErisMint +// in-process as the application manager, so we hard-code the few +// parameters that are already templated. +// Let's learn to walk before we can run. +func GetConfigurationFileBytes(chainId, moniker, seeds string, chainImageName string, + useDataContainer bool, exportedPortsString, containerEntrypoint string) ([]byte, error) { + + erisdbService := &ConfigServiceGeneral{ + ChainImageName: chainImageName, + UseDataContainer: useDataContainer, + ExportedPorts: exportedPortsString, + ContainerEntrypoint: containerEntrypoint, + } + erisdbChain := &ConfigChainGeneral{ + AssertChainId: chainId, + ErisdbMajorVersion: uint8(0), + ErisdbMinorVersion: uint8(12), + GenesisRelativePath: "genesis.json", + } + chainConsensusModule := &ConfigChainModule{ + Name: "tendermint", + MajorVersion: uint8(0), + MinorVersion: uint8(6), + ModuleRelativeRoot: "tendermint", + } + chainApplicationManagerModule := &ConfigChainModule{ + Name: "erismint", + MajorVersion: uint8(0), + MinorVersion: uint8(12), + ModuleRelativeRoot: "erismint", + } + tendermintModule := &ConfigTendermint{ + Moniker: moniker, + Seeds: seeds, + FastSync: false, + } + + // NOTE: [ben] according to StackOverflow appending strings with copy is + // more efficient than bytes.WriteString, but for readability and because + // this is not performance critical code we opt for bytes, which is + // still more efficient than + concatentation operator. + var buffer bytes.Buffer + + // write copyright header + buffer.WriteString(headerCopyright) + + // write section [service] + if err := serviceGeneralTemplate.Execute(&buffer, erisdbService); err != nil { + return nil, fmt.Errorf("Failed to write template service general for %s: %s", + chainId, err) + } + // write section for service dependencies; this is currently a static section + // with a fixed dependency on eris-keys + buffer.WriteString(sectionServiceDependencies) + + // write section [chain] + if err := chainGeneralTemplate.Execute(&buffer, erisdbChain); err != nil { + return nil, fmt.Errorf("Failed to write template chain general for %s: %s", + chainId, err) + } + + // write separator chain consensus + buffer.WriteString(separatorChainConsensus) + // write section [chain.consensus] + if err := chainConsensusTemplate.Execute(&buffer, chainConsensusModule); err != nil { + return nil, fmt.Errorf("Failed to write template chain consensus for %s: %s", + chainId, err) + } + + // write separator chain application manager + buffer.WriteString(separatorChainApplicationManager) + // write section [chain.consensus] + if err := chainApplicationManagerTemplate.Execute(&buffer, + chainApplicationManagerModule); err != nil { + return nil, fmt.Errorf("Failed to write template chain application manager for %s: %s", + chainId, err) + } + + // write separator servers + buffer.WriteString(separatorServerConfiguration) + // TODO: [ben] upon necessity replace this with template too + // write static section servers + buffer.WriteString(sectionServers) + + // write separator modules + buffer.WriteString(separatorModules) + + // write section module Tendermint + if err := tendermintTemplate.Execute(&buffer, tendermintModule); err != nil { + return nil, fmt.Errorf("Failed to write template tendermint for %s, moniker %s: %s", + chainId, moniker, err) + } + + // write static section erismint + buffer.WriteString(sectionErisMint) + + return buffer.Bytes(), nil +} diff --git a/config/config_test.go b/config/config_test.go new file mode 100644 index 00000000..79286f35 --- /dev/null +++ b/config/config_test.go @@ -0,0 +1,29 @@ +// Copyright 2015, 2016 Monax Industries (UK) Ltd. +// This file is part of Eris-RT + +// Eris-RT is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Eris-RT is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Eris-RT. If not, see <http://www.gnu.org/licenses/>. + +package config + +import ( + "testing" +) + +func TestConfigurationFileBytes(t *testing.T) { + // TODO: [ben] parse written bytes for comparison with expected parameters + if _, err := GetConfigurationFileBytes("simplechain", "marmot", "noseeds", "db:latest", + true, "", "eris-db"); err != nil { + t.Errorf("Error writing configuration file bytes: %s", err) + } +} diff --git a/config/templates.go b/config/templates.go new file mode 100644 index 00000000..cead77d9 --- /dev/null +++ b/config/templates.go @@ -0,0 +1,318 @@ +// Copyright 2015, 2016 Monax Industries (UK) Ltd. +// This file is part of Eris-RT + +// Eris-RT is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Eris-RT is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Eris-RT. If not, see <http://www.gnu.org/licenses/>. + +package config + +const headerCopyright = `# Copyright 2015, 2016 Eris Industries (UK) Ltd. +# This file is part of Eris-RT +# Eris-RT is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Eris-RT is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Eris-RT. If not, see <http://www.gnu.org/licenses/>. + +# This is a TOML configuration for Eris-DB chains generated by Eris-CM + +` + +const sectionServiceGeneral = `[service] +# NOTE: this section is read by Eris tooling, and ignored by eris-db. +# Image specifies the image name eris-cli needs to pull +# for running the chain. +image = "{{.ChainImageName}}" +# Define whether eris-cli needs to attach the data container +# for the chain. +data_container = {{.UseDataContainer}} +# Specify a list of ports that need to be exported on the container. +ports = {{.ExportedPorts}} +{{ if ne .ContainerEntrypoint "" }}# Entrypoint points to the default action to execute +# in the chain container. +entry_point = "{{.ContainerEntrypoint}}"{{ end }} + +` + +const sectionServiceDependencies = `[dependencies] +# NOTE: this section is read by Eris tooling, and ignored by eris-db. +# Eris-db expects these services to be available; eric-cli tooling will +# automatically set these services up for you. +# Services to boot with/required by the chain +services = [ "keys" ] + +` + +const sectionChainGeneral = `[chain] + +# ChainId is a human-readable name to identify the chain. +# This must correspond to the chain_id defined in the genesis file +# and the assertion here provides a safe-guard on misconfiguring chains. +assert_chain_id = "{{.AssertChainId}}" +# semantic major and minor version +major_version = {{.ErisdbMajorVersion}} +minor_version = {{.ErisdbMinorVersion}} +# genesis file, relative path is to eris-db working directory +genesis_file = "{{.GenesisRelativePath}}" + +` + +const separatorChainConsensus = ` +################################################################################ +## +## consensus +## +################################################################################ + +` + +const sectionChainConsensus = ` [chain.consensus] + # consensus defines the module to use for consensus and + # this will define the peer-to-peer consensus network; + # accepted values are ("noops", "tmsp",) "tendermint" + name = "{{.Name}}" + # version is the major and minor semantic version; + # the version will be asserted on + major_version = {{.MajorVersion}} + minor_version = {{.MinorVersion}} + # relative path to consensus' module root folder + relative_root = "{{.ModuleRelativeRoot}}" + + ` + +const separatorChainApplicationManager = ` +################################################################################ +## +## application manager +## +################################################################################ + +` + +const sectionChainApplicationManager = ` [chain.manager] + # application manager name defines the module to use for handling + # the transactions. Supported names are "erismint" + name = "{{.Name}}" + # version is the major and minor semantic version; + # the version will be asserted on + major_version = {{.MajorVersion}} + minor_version = {{.MinorVersion}} + # relative path to application manager root folder + relative_root = "{{.ModuleRelativeRoot}}" + + ` + +const separatorServerConfiguration = ` +################################################################################ +################################################################################ +## +## Server configurations +## +################################################################################ +################################################################################ + +` + +// TODO: [ben] map entries to structure defined in eris-db +const sectionServers = `[servers] + + [servers.bind] + address = "" + port = 1337 + + [servers.tls] + tls = false + cert_path = "" + key_path = "" + + [servers.cors] + enable = false + allow_origins = [] + allow_credentials = false + allow_methods = [] + allow_headers = [] + expose_headers = [] + max_age = 0 + + [servers.http] + json_rpc_endpoint = "/rpc" + + [servers.websocket] + endpoint = "/socketrpc" + max_sessions = 50 + read_buffer_size = 4096 + write_buffer_size = 4096 + + [servers.tendermint] + # Multiple listeners can be separated with a comma + rpc_local_address = "0.0.0.0:46657" + endpoint = "/websocket" + + [servers.logging] + console_log_level = "info" + file_log_level = "warn" + log_file = "" + + ` + +const separatorModules = ` +################################################################################ +################################################################################ +## +## Module configurations - dynamically loaded based on chain configuration +## +################################################################################ +################################################################################ + +` + +// TODO: [ben] make configurable +const sectionTmsp = ` +################################################################################ +## +## Tendermint Socket Protocol (TMSP) +## version 0.6.0 +## +## TMSP expects a tendermint consensus process to run and connect to Eris-DB +## +################################################################################ + +[tmsp] +# listener address for accepting tendermint socket protocol connections +listener = "tcp://0.0.0.0:46658" + +` + +// TODO: [ben] minimal fields have been made configurable; expand where needed +const sectionTendermint = ` +################################################################################ +## +## Tendermint +## version 0.6.0 +## +## in-process execution of Tendermint consensus engine +## +################################################################################ + +[tendermint] +# private validator file is used by tendermint to keep the status +# of the private validator, but also (currently) holds the private key +# for the private vaildator to sign with. This private key needs to be moved +# out and directly managed by eris-keys +# This file needs to be in the root directory +private_validator_file = "priv_validator.json" + + # Tendermint requires additional configuration parameters. + # Eris-DB's tendermint consensus module will load [tendermint.configuration] + # as the configuration for Tendermint. + # Eris-DB will respect the configurations set in this file where applicable, + # but reserves the option to override or block conflicting settings. + [tendermint.configuration] + # moniker is the name of the node on the tendermint p2p network + moniker = "{{.Moniker}}" + # seeds lists the peers tendermint can connect to join the network + seeds = "{{.Seeds}}" + # fast_sync allows a tendermint node to catch up faster when joining + # the network. + # NOTE: Tendermint has reported potential issues with fast_sync enabled. + # The recommended setting is for keeping it disabled. + fast_sync = {{.FastSync}} + # database backend to use for Tendermint. Supported "leveldb" and "memdb". + db_backend = "leveldb" + # logging level. Supported "error" < "warn" < "notice" < "info" < "debug" + log_level = "info" + # node local address + node_laddr = "0.0.0.0:46656" + # rpc local address + # NOTE: value is ignored when run in-process as RPC is + # handled by [servers.tendermint] + rpc_laddr = "0.0.0.0:46657" + # proxy application address - used for tmsp connections, + # and this port should not be exposed for in-process Tendermint + proxy_app = "tcp://127.0.0.1:46658" + + # Extended Tendermint configuration settings + # for reference to Tendermint see https://github.com/tendermint/tendermint/blob/master/config/tendermint/config.go + + # genesis_file = "./data/tendermint/genesis.json" + # skip_upnp = false + # addrbook_file = "./data/tendermint/addrbook.json" + # priv_validator_file = "./data/tendermint/priv_validator.json" + # db_dir = "./data/tendermint/data" + # prof_laddr = "" + # revision_file = "./data/tendermint/revision" + # cswal = "./data/tendermint/data/cswal" + # cswal_light = false + + # block_size = 10000 + # disable_data_hash = false + # timeout_propose = 3000 + # timeout_propose_delta = 500 + # timeout_prevote = 1000 + # timeout_prevote_delta = 500 + # timeout_precommit = 1000 + # timeout_precommit_delta = 500 + # timeout_commit = 1000 + # mempool_recheck = true + # mempool_recheck_empty = true + # mempool_broadcast = true + + [tendermint.configuration.p2p] + # Switch config keys + dial_timeout_seconds = 3 + handshake_timeout_seconds = 20 + max_num_peers = 20 + authenticated_encryption = true + + # MConnection config keys + send_rate = 512000 + recv_rate = 512000 + + # Fuzz params + fuzz_enable = false # use the fuzz wrapped conn + fuzz_active = false # toggle fuzzing + fuzz_mode = "drop" # eg. drop, delay + fuzz_max_delay_milliseconds = 3000 + fuzz_prob_drop_rw = 0.2 + fuzz_prob_drop_conn = 0.00 + fuzz_prob_sleep = 0.00 + +` + +const sectionErisMint = ` +################################################################################ +## +## Eris-Mint +## version 0.12.0 +## +## The original Ethereum virtual machine with IAVL merkle trees +## and tendermint/go-wire encoding +## +################################################################################ + +[erismint] +# Database backend to use for ErisMint state database. +# Supported "leveldb" and "memdb". +db_backend = "leveldb" +# tendermint host address needs to correspond to tendermints configuration +# of the rpc local address +tendermint_host = "0.0.0.0:46657" + +` -- GitLab