diff --git a/config/module.go b/config/module.go index 1590af2015cd7ba752b055c13a7bc7c454a77f89..5fd4be77c982cffdfc7b456ce16fb85467349239 100644 --- a/config/module.go +++ b/config/module.go @@ -22,12 +22,13 @@ import ( ) type ModuleConfig struct { - Module string - Name string - Version string - WorkDir string - DataDir string - RootDir string - ChainId string - Config *viper.Viper + Module string + Name string + Version string + WorkDir string + DataDir string + RootDir string + ChainId string + GenesisFile string + Config *viper.Viper } diff --git a/consensus/consensus.go b/consensus/consensus.go index cc81aa48c618f4c70e8e88caf7ded09b3a5a655e..2c5a48d6b68d9935d9f3abcfa7eb86587d1e7025 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -19,7 +19,8 @@ package consensus import ( config "github.com/eris-ltd/eris-db/config" - tendermint "github.com/eris-ltd/eris-db/consensus/tendermint" + definitions "github.com/eris-ltd/eris-db/definitions" + tendermint "github.com/eris-ltd/eris-db/consensus/tendermint" ) type ConsensusEngine struct { @@ -30,8 +31,17 @@ type ConsensusEngine struct { } +func LoadConsensusEngineInPipe(moduleConfig *config.ModuleConfig, + pipe definitions.Pipe) error { + switch moduleConfig.Name { + case "tendermint" : + tendermint.NewTendermintNode(moduleConfig, nil) + } + return nil +} + func NewConsensusEngine(moduleConfig *config.ModuleConfig) { - tendermint.NewTendermintNode(moduleConfig) + } type Communicator interface { diff --git a/consensus/tendermint/tendermint.go b/consensus/tendermint/tendermint.go index e6d2881164e1961ec466c2d6615e89b1755bb0c1..98ea8c53495f1f1ba79b2080b64c1ffa817ed5c1 100644 --- a/consensus/tendermint/tendermint.go +++ b/consensus/tendermint/tendermint.go @@ -24,7 +24,8 @@ import ( node "github.com/tendermint/tendermint/node" - config "github.com/eris-ltd/eris-db/config" + config "github.com/eris-ltd/eris-db/config" + manager_types "github.com/eris-ltd/eris-db/manager/types" // files "github.com/eris-ltd/eris-db/files" ) @@ -32,7 +33,8 @@ type TendermintNode struct { tmintNode *node.Node } -func NewTendermintNode(moduleConfig *config.ModuleConfig) (*TendermintConfig, error) { +func NewTendermintNode(moduleConfig *config.ModuleConfig, + applicaton *manager_types.Application) (*TendermintNode, error) { // re-assert proper configuration for module if moduleConfig.Version != GetTendermintVersion().GetMinorVersionString() { return nil, fmt.Errorf("Version string %s did not match %s", @@ -45,7 +47,8 @@ func NewTendermintNode(moduleConfig *config.ModuleConfig) (*TendermintConfig, er // subtree. To shield in go-routine, or PR to viper. tendermintConfigViper := moduleConfig.Config.Sub("configuration") if tendermintConfigViper == nil { - return nil, fmt.Errorf("Failed to extract Tendermint configuration subtree.") + return nil, + fmt.Errorf("Failed to extract Tendermint configuration subtree.") } // wrap a copy of the viper config in a tendermint/go-config interface tmintConfig := GetTendermintConfig(tendermintConfigViper) @@ -53,7 +56,9 @@ func NewTendermintNode(moduleConfig *config.ModuleConfig) (*TendermintConfig, er tmintConfig.AssertTendermintDefaults(moduleConfig.ChainId, moduleConfig.WorkDir, moduleConfig.DataDir, moduleConfig.RootDir) - // newNode := node.NewNode() + + + // newNode := node.NewNode(tmintConfig, ) // newNode := node.NewNode() // return &TendermintNode{ diff --git a/core/core.go b/core/core.go index 495addb58b08fbafd127afc72cb5bdadd5589041..179c64ff21027a9caa286aa2f6d77cd0d8afc7de 100644 --- a/core/core.go +++ b/core/core.go @@ -17,29 +17,40 @@ package core import ( + "fmt" + // TODO: [ben] swap out go-events with eris-db/event (currently unused) events "github.com/tendermint/go-events" - config "github.com/eris-ltd/eris-db/config" - consensus "github.com/eris-ltd/eris-db/consensus" - // manager "github.com/eris-ltd/eris-db/manager" + config "github.com/eris-ltd/eris-db/config" + consensus "github.com/eris-ltd/eris-db/consensus" + definitions "github.com/eris-ltd/eris-db/definitions" + manager "github.com/eris-ltd/eris-db/manager" ) // Core is the high-level structure type Core struct { chainId string evsw *events.EventSwitch - // pipe Pipe + pipe definitions.Pipe } -func NewCore(chainId string, consensusConfig *config.ModuleConfig, - managerConfig *config.ModuleConfig) *Core { +func NewCore(chainId, genesisFile string, consensusConfig *config.ModuleConfig, + managerConfig *config.ModuleConfig) (*Core, error) { // start new event switch, TODO: [ben] replace with eris-db/event evsw := events.NewEventSwitch() evsw.Start() - consensus.NewConsensusEngine(consensusConfig) + // start a new application pipe that will load an application manager + pipe, err := manager.NewApplicationPipe(managerConfig, evsw, + consensusConfig.Version, genesisFile) + if err != nil { + return nil, fmt.Errorf("PLACEHOLDER") + } + // pass the + consensus.LoadConsensusEngineInPipe(consensusConfig, pipe) + // create state // from genesis @@ -49,7 +60,7 @@ func NewCore(chainId string, consensusConfig *config.ModuleConfig, // create new Pipe // give app // create servers - return &Core{} + return &Core{}, fmt.Errorf("PLACEHOLDER") } //------------------------------------------------------------------------------ diff --git a/definitions/do.go b/definitions/do.go index 0410a456cf1b2fb1aef086397f92faac61700030..5836716e2292d5efa9d11ddcdc42d634396bc56f 100644 --- a/definitions/do.go +++ b/definitions/do.go @@ -41,6 +41,7 @@ type Do struct { // Capital configuration options explicitly extracted from the Viper config ChainId string // has to be set to non-empty string, // uniquely identifying the chain. + GenesisFile string // ChainType string // CSV string // AccountTypes []string @@ -58,6 +59,7 @@ func NowDo() *Do { do.WorkDir = "" do.DataDir = "" do.ChainId = "" + do.GenesisFile = "" do.Config = viper.New() return do } diff --git a/core/pipe.go b/definitions/pipe.go similarity index 98% rename from core/pipe.go rename to definitions/pipe.go index ebd0b272e235c411c3cd7ba3949b0a199615defa..cfd02e713d0c7f94854effbac4ffd2a01e8da1fd 100644 --- a/core/pipe.go +++ b/definitions/pipe.go @@ -14,11 +14,7 @@ // 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 core - -import ( - types "github.com/eris-ltd/eris-db/core/types" -) +package definitions // TODO: [ben] This respects the old Pipe interface from Eris-DB. // This made sense as a wrapper around the old Tendermint, but now @@ -34,6 +30,7 @@ import ( account "github.com/eris-ltd/eris-db/account" transaction "github.com/eris-ltd/eris-db/txs" + types "github.com/eris-ltd/eris-db/core/types" ) type Pipe interface { diff --git a/manager/eris-mint/pipe.go b/manager/eris-mint/pipe.go index 30a3081923bcf650b056843f21abc944258cd79e..edfe31635f29dace310c5cd058120d3733f92a7d 100644 --- a/manager/eris-mint/pipe.go +++ b/manager/eris-mint/pipe.go @@ -20,8 +20,11 @@ import ( "bytes" "fmt" - db "github.com/tendermint/go-db" - wire "github.com/tendermint/go-wire" + db "github.com/tendermint/go-db" + events "github.com/tendermint/go-events" + wire "github.com/tendermint/go-wire" + + log "github.com/eris-ltd/eris-logger" config "github.com/eris-ltd/eris-db/config" state "github.com/eris-ltd/eris-db/manager/eris-mint/state" @@ -30,25 +33,48 @@ import ( type ErisMintPipe struct { erisMintState *state.State + eventSwitch *events.EventSwitch + erisMint *ErisMint } func NewErisMintPipe(moduleConfig *config.ModuleConfig, - genesisFile string) (*ErisMintPipe, error) { + genesisFile string, eventSwitch *events.EventSwitch) (*ErisMintPipe, error) { startedState, err := startState(moduleConfig.DataDir, - moduleConfig.Config.GetString("db_backend"), genesisFile) + moduleConfig.Config.GetString("db_backend"), genesisFile, + moduleConfig.ChainId) if err != nil { return nil, fmt.Errorf("Failed to start state: %v", err) } - return &ErisMintPipe{ + // assert ChainId matches genesis ChainId + + // start the application + erisMint := NewErisMint(startedState, eventSwitch) + + // NOTE: [ben] Set Host opens an RPC pipe to Tendermint; this is a remnant + // of the old Eris-DB / Tendermint and should be + tendermintHost := moduleConfig.Config.GetString("tendermint_host") + log.Debug("Starting ErisMint RPC client to Tendermint host on %s", + tendermintHost) + erisMint.SetHostAddress(tendermintHost) + + return &ErisMintPipe { erisMintState: startedState, + eventSwitch: eventSwitch, + erisMint: erisMint, }, nil } //------------------------------------------------------------------------------ // Start state -func startState(dataDir, backend, genesisFile string) (*state.State, error) { +// Start state tries to load the existing state in the data directory; +// if an existing database can be loaded, it will validate that the +// chainId in the genesis of that loaded state matches the asserted chainId. +// If no state can be loaded, the JSON genesis file will be loaded into the +// state database as the zero state. +func startState(dataDir, backend, genesisFile, chainId string) (*state.State, + error) { // avoid Tendermints PanicSanity and return a clean error if backend != db.DBBackendMemDB && backend != db.DBBackendLevelDB { @@ -69,12 +95,17 @@ func startState(dataDir, backend, genesisFile string) (*state.State, error) { return nil, fmt.Errorf("Unable to write genesisDoc to db: %v", err) } } else { - genDocBytes := stateDB.Get(state_types.GenDocKey) + loadedGenesisDocBytes := stateDB.Get(state_types.GenDocKey) err := new(error) - wire.ReadJSONPtr(&genesisDoc, genDocBytes, err) + wire.ReadJSONPtr(&genesisDoc, loadedGenesisDocBytes, err) if *err != nil { - return nil, fmt.Errorf("Unable to read genesisDoc from db: %v", err) + return nil, fmt.Errorf("Unable to read genesisDoc from db on startState: %v", err) } + // assert loaded genesis doc has the same chainId as the provided chainId + if genesisDoc.ChainID != chainId { + return nil, fmt.Errorf("ChainId (%s) loaded from genesis document in existing database does not match configuration chainId (%s).", + genesisDoc.ChainID, chainId) + } } return newState, nil diff --git a/manager/eris-mint/state/state.go b/manager/eris-mint/state/state.go index a3937a5c302b73cae7f257368b077e20f96915ea..f22beb3ee67663c07d39186b9f88f168a9cee11f 100644 --- a/manager/eris-mint/state/state.go +++ b/manager/eris-mint/state/state.go @@ -2,6 +2,7 @@ package state import ( "bytes" + "fmt" "io" "io/ioutil" "time" @@ -151,6 +152,17 @@ func (s *State) ComputeBlockStateHash(block *types.Block) error { } */ +func (s *State) GetGenesisDoc() (*GenesisDoc, error) { + var genesisDoc *GenesisDoc + loadedGenesisDocBytes := s.DB.Get(GenDocKey) + err := new(error) + wire.ReadJSONPtr(&genesisDoc, loadedGenesisDocBytes, err) + if *err != nil { + return nil, fmt.Errorf("Unable to read genesisDoc from db on Get: %v", err) + } + return genesisDoc, nil +} + func (s *State) SetDB(db dbm.DB) { s.DB = db } diff --git a/manager/manager.go b/manager/manager.go index 3aab6d88df722b9ec950040c029c2d54dc208a77..fa79d82784690427c420ea15e172e64edd090167 100644 --- a/manager/manager.go +++ b/manager/manager.go @@ -19,35 +19,30 @@ package manager import ( "fmt" - config "github.com/eris-ltd/eris-db/config" - erismint "github.com/eris-ltd/eris-db/manager/eris-mint" - types "github.com/eris-ltd/eris-db/manager/types" + events "github.com/tendermint/go-events" + + config "github.com/eris-ltd/eris-db/config" + definitions "github.com/eris-ltd/eris-db/definitions" + erismint "github.com/eris-ltd/eris-db/manager/eris-mint" + // types "github.com/eris-ltd/eris-db/manager/types" ) -// NewApplication returns an initialised application interface +// NewApplicationPipe returns an initialised Pipe interface // based on the loaded module configuration file. // NOTE: [ben] Currently we only have a single `generic` definition // of an application. It is feasible this will be insufficient to support // different types of applications later down the line. -func NewApplication(moduleConfig *config.ModuleConfig, - consensusMinorVersion string) (types.Application, - error) { +func NewApplicationPipe(moduleConfig *config.ModuleConfig, + evsw *events.EventSwitch, consensusMinorVersion, + genesisFile string) (definitions.Pipe, error) { switch moduleConfig.Name { case "erismint" : if err := erismint.AssertCompatibleConsensus(consensusMinorVersion); err != nil { return nil, err } - - return newErisMintPH(moduleConfig) + erismint.NewErisMintPipe(moduleConfig, genesisFile, evsw) + // TODO: ErisMintPipe does not yet implement definitions.Pipe } return nil, fmt.Errorf("PLACEHOLDER") } - -//------------------------------------------------------------------------------ -// Eris-Mint - -func newErisMintPH(moduleConfig *config.ModuleConfig) (*erismint.ErisMint, - error) { - return nil, fmt.Errorf("PLACEHOLDER") -} diff --git a/server_config.toml b/server_config.toml index 3227f7b9bbb99c44ec7c6a142de06ad94b3c7daf..511b25f1d0512418c08a7333a57c083948db91cd 100644 --- a/server_config.toml +++ b/server_config.toml @@ -125,7 +125,7 @@ listener = "tcp://0.0.0.0:46658" # database backend to use for Tendermint. Supported `leveldb` and `memdb`. db_backend = "leveldb" # logging level. Suppored `debug`, `notice`, `info` [ben: incomplete, see Tendermint] - log_level = "notice" + log_level = "info" # node local address node_laddr = "0.0.0.0:46656" # rpc local address @@ -174,3 +174,6 @@ listener = "tcp://0.0.0.0:46658" # 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"