diff --git a/client/node_client.go b/client/node_client.go index eb03fd77fb22300419bba16696e8e06f96e17c13..adc450cd7baac490f6b93d1cf1f64920ce0dbbd6 100644 --- a/client/node_client.go +++ b/client/node_client.go @@ -87,7 +87,7 @@ func init() { // broadcast to blockchain node func (burrowNodeClient *burrowNodeClient) Broadcast(tx txs.Tx) (*txs.Receipt, error) { - client := rpcclient.NewClientURI(burrowNodeClient.broadcastRPC) + client := rpcclient.NewURIClient(burrowNodeClient.broadcastRPC) receipt, err := tendermint_client.BroadcastTx(client, tx) if err != nil { return nil, err @@ -134,7 +134,7 @@ func (burrowNodeClient *burrowNodeClient) DeriveWebsocketClient() (nodeWsClient // Status returns the ChainId (GenesisHash), validator's PublicKey, latest block hash // the block height and the latest block time. func (burrowNodeClient *burrowNodeClient) Status() (GenesisHash []byte, ValidatorPublicKey []byte, LatestBlockHash []byte, LatestBlockHeight int, LatestBlockTime int64, err error) { - client := rpcclient.NewClientJSONRPC(burrowNodeClient.broadcastRPC) + client := rpcclient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) res, err := tendermint_client.Status(client) if err != nil { err = fmt.Errorf("Error connecting to node (%s) to get status: %s", @@ -152,7 +152,7 @@ func (burrowNodeClient *burrowNodeClient) Status() (GenesisHash []byte, Validato } func (burrowNodeClient *burrowNodeClient) ChainId() (ChainName, ChainId string, GenesisHash []byte, err error) { - client := rpcclient.NewClientJSONRPC(burrowNodeClient.broadcastRPC) + client := rpcclient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) chainIdResult, err := tendermint_client.ChainId(client) if err != nil { err = fmt.Errorf("Error connecting to node (%s) to get chain id: %s", @@ -170,7 +170,7 @@ func (burrowNodeClient *burrowNodeClient) ChainId() (ChainName, ChainId string, // QueryContract executes the contract code at address with the given data // NOTE: there is no check on the caller; func (burrowNodeClient *burrowNodeClient) QueryContract(callerAddress, calleeAddress, data []byte) (ret []byte, gasUsed int64, err error) { - client := rpcclient.NewClientJSONRPC(burrowNodeClient.broadcastRPC) + client := rpcclient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) callResult, err := tendermint_client.Call(client, callerAddress, calleeAddress, data) if err != nil { err = fmt.Errorf("Error connnecting to node (%s) to query contract at (%X) with data (%X)", @@ -182,7 +182,7 @@ func (burrowNodeClient *burrowNodeClient) QueryContract(callerAddress, calleeAdd // QueryContractCode executes the contract code at address with the given data but with provided code func (burrowNodeClient *burrowNodeClient) QueryContractCode(address, code, data []byte) (ret []byte, gasUsed int64, err error) { - client := rpcclient.NewClientJSONRPC(burrowNodeClient.broadcastRPC) + client := rpcclient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) // TODO: [ben] Call and CallCode have an inconsistent signature; it makes sense for both to only // have a single address that is the contract to query. callResult, err := tendermint_client.CallCode(client, address, code, data) @@ -196,7 +196,7 @@ func (burrowNodeClient *burrowNodeClient) QueryContractCode(address, code, data // GetAccount returns a copy of the account func (burrowNodeClient *burrowNodeClient) GetAccount(address []byte) (*acc.Account, error) { - client := rpcclient.NewClientJSONRPC(burrowNodeClient.broadcastRPC) + client := rpcclient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) account, err := tendermint_client.GetAccount(client, address) if err != nil { err = fmt.Errorf("Error connecting to node (%s) to fetch account (%X): %s", @@ -213,7 +213,7 @@ func (burrowNodeClient *burrowNodeClient) GetAccount(address []byte) (*acc.Accou // DumpStorage returns the full storage for an account. func (burrowNodeClient *burrowNodeClient) DumpStorage(address []byte) (storage *core_types.Storage, err error) { - client := rpcclient.NewClientJSONRPC(burrowNodeClient.broadcastRPC) + client := rpcclient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) resultStorage, err := tendermint_client.DumpStorage(client, address) if err != nil { err = fmt.Errorf("Error connecting to node (%s) to get storage for account (%X): %s", @@ -231,7 +231,7 @@ func (burrowNodeClient *burrowNodeClient) DumpStorage(address []byte) (storage * // Name registry func (burrowNodeClient *burrowNodeClient) GetName(name string) (owner []byte, data string, expirationBlock int, err error) { - client := rpcclient.NewClientJSONRPC(burrowNodeClient.broadcastRPC) + client := rpcclient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) entryResult, err := tendermint_client.GetName(client, name) if err != nil { err = fmt.Errorf("Error connecting to node (%s) to get name registrar entry for name (%s)", @@ -249,7 +249,7 @@ func (burrowNodeClient *burrowNodeClient) GetName(name string) (owner []byte, da func (burrowNodeClient *burrowNodeClient) ListValidators() (blockHeight int, bondedValidators []consensus_types.Validator, unbondingValidators []consensus_types.Validator, err error) { - client := rpcclient.NewClientJSONRPC(burrowNodeClient.broadcastRPC) + client := rpcclient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) validatorsResult, err := tendermint_client.ListValidators(client) if err != nil { err = fmt.Errorf("Error connecting to node (%s) to get validators", diff --git a/cmd/serve.go b/cmd/serve.go index c4373db68d71c555667b91aa3ea38a78890421a6..89666e830e2483dc8594e11cec1e69b5b72c0e8c 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -28,6 +28,7 @@ import ( vm "github.com/hyperledger/burrow/manager/burrow-mint/evm" "github.com/hyperledger/burrow/util" + "github.com/hyperledger/burrow/config" "github.com/spf13/cobra" ) @@ -95,6 +96,11 @@ func NewCoreFromDo(do *definitions.Do) (*core.Core, error) { do.GenesisFile = path.Join(do.WorkDir, do.Config.GetString("chain.genesis_file")) + err := config.AssertConfigCompatibleWithRuntime(do.Config) + if err != nil { + return nil, err + } + if do.Config.GetString("chain.genesis_file") == "" { return nil, fmt.Errorf("The config value chain.genesis_file is empty, " + "but should be set to the location of the genesis.json file.") @@ -175,7 +181,7 @@ func ServeRunner(do *definitions.Do) func(*cobra.Command, []string) { } if !do.DisableRpc { - serverConfig, err := core.LoadServerConfig(do) + serverConfig, err := core.LoadServerConfigFromDo(do) if err != nil { util.Fatalf("Failed to load server configuration: %s.", err) } @@ -192,6 +198,8 @@ func ServeRunner(do *definitions.Do) func(*cobra.Command, []string) { util.Fatalf("Failed to start Tendermint gateway") } <-serverProcess.StopEventChannel() + // Attempt graceful shutdown + newCore.Stop() } else { signals := make(chan os.Signal, 1) signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM) diff --git a/config/config.go b/config/config.go index 8d002743fc0c474c50d2c655f2bee568ec7bbb03..32f1e59b6bf3fe30a9bd450683297d616c81ff2a 100644 --- a/config/config.go +++ b/config/config.go @@ -19,7 +19,10 @@ import ( "fmt" "text/template" + tendermint_version "github.com/hyperledger/burrow/consensus/tendermint/version" lconfig "github.com/hyperledger/burrow/logging/config" + "github.com/hyperledger/burrow/version" + "github.com/spf13/viper" ) type ConfigServiceGeneral struct { @@ -89,22 +92,28 @@ func GetConfigurationFileBytes(chainId, moniker, seeds string, chainImageName st ExportedPorts: exportedPortsString, ContainerEntrypoint: containerEntrypoint, } + + // We want to encode in the config file which Burrow version generated the config + burrowVersion := version.GetBurrowVersion() burrowChain := &ConfigChainGeneral{ AssertChainId: chainId, - BurrowMajorVersion: uint8(0), - BurrowMinorVersion: uint8(17), + BurrowMajorVersion: burrowVersion.MajorVersion, + BurrowMinorVersion: burrowVersion.MinorVersion, GenesisRelativePath: "genesis.json", } + + tendermintVersion := tendermint_version.GetTendermintVersion() chainConsensusModule := &ConfigChainModule{ Name: "tendermint", - MajorVersion: uint8(0), - MinorVersion: uint8(8), + MajorVersion: tendermintVersion.MajorVersion, + MinorVersion: tendermintVersion.MinorVersion, ModuleRelativeRoot: "tendermint", } + chainApplicationManagerModule := &ConfigChainModule{ Name: "burrowmint", - MajorVersion: uint8(0), - MinorVersion: uint8(17), + MajorVersion: burrowVersion.MajorVersion, + MinorVersion: burrowVersion.MinorVersion, ModuleRelativeRoot: "burrowmint", } tendermintModule := &ConfigTendermint{ @@ -178,6 +187,19 @@ func GetConfigurationFileBytes(chainId, moniker, seeds string, chainImageName st return buffer.Bytes(), nil } +func AssertConfigCompatibleWithRuntime(conf *viper.Viper) error { + burrowVersion := version.GetBurrowVersion() + majorVersion := uint8(conf.GetInt(fmt.Sprintf("chain.%s", majorVersionKey))) + minorVersion := uint8(conf.GetInt(fmt.Sprintf("chain.%s", majorVersionKey))) + if burrowVersion.MajorVersion != majorVersion || + burrowVersion.MinorVersion != minorVersion { + fmt.Errorf("Runtime Burrow version %s is not compatible with "+ + "configuration file version: major=%s, minor=%s", + burrowVersion.GetVersionString(), majorVersion, minorVersion) + } + return nil +} + func GetExampleConfigFileBytes() ([]byte, error) { return GetConfigurationFileBytes( "simplechain", diff --git a/config/config_test.go b/config/config_test.go index 67da505fd3d9346eac7fb575cf747d9bebcfb598..a49d808491b63518d227fc4aa854e7695372df27 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -15,19 +15,14 @@ package config import ( - "bytes" "testing" - "github.com/spf13/viper" "github.com/stretchr/testify/assert" ) func TestGeneratedConfigIsUsable(t *testing.T) { bs, err := GetExampleConfigFileBytes() assert.NoError(t, err, "Should be able to create example config") - buf := bytes.NewBuffer(bs) - conf := viper.New() - viper.SetConfigType("toml") - err = conf.ReadConfig(buf) + _, err = ReadViperConfig(bs) assert.NoError(t, err, "Should be able to read example config into Viper") } diff --git a/config/templates.go b/config/templates.go index f8d340369ddb2e16e91b17b1d36de3499f3fb257..7005ae7ff08956977bea57d3bb109de8302ab951 100644 --- a/config/templates.go +++ b/config/templates.go @@ -14,6 +14,8 @@ package config +import "fmt" + const headerCopyright = `# Copyright 2017 Monax Industries Limited # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -56,20 +58,22 @@ const sectionServiceDependencies = `[dependencies] services = [ "keys" ] ` +const majorVersionKey = "major_version" +const minorVersionKey = "minor_version" -const sectionChainGeneral = `[chain] +var sectionChainGeneral string = fmt.Sprintf(`[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 = {{.BurrowMajorVersion}} -minor_version = {{.BurrowMinorVersion}} +%s = {{.BurrowMajorVersion}} +%s = {{.BurrowMinorVersion}} # genesis file, relative path is to burrow working directory genesis_file = "{{.GenesisRelativePath}}" -` +`, majorVersionKey, minorVersionKey) const separatorChainConsensus = ` ################################################################################ @@ -180,7 +184,6 @@ const sectionTendermint = ` ################################################################################ ## ## Tendermint -## version 0.8 ## ## in-process execution of Tendermint consensus engine ## @@ -235,7 +238,7 @@ private_validator_file = "priv_validator.json" # db_dir = "./data/tendermint/data" # prof_laddr = "" # revision_file = "./data/tendermint/revision" - # cs_wal_dir = "./data/tendermint/data/cswal" + # cs_wal_file = "./data/tendermint/data/cs.wal/wal" # cs_wal_light = false # filter_peers = false @@ -281,7 +284,6 @@ const sectionBurrowMint = ` ################################################################################ ## ## Burrow-Mint -## version 0.17 ## ## The original Ethereum virtual machine with IAVL merkle trees ## and tendermint/go-wire encoding diff --git a/config/viper.go b/config/viper.go index 1b4c96b6caae6d840c26b2667ee499a1be1b643e..c8f308f5368f0ed9070ad6fc77270eb306cf32c2 100644 --- a/config/viper.go +++ b/config/viper.go @@ -17,6 +17,8 @@ package config import ( "fmt" + "bytes" + "github.com/spf13/viper" ) @@ -42,3 +44,15 @@ func ViperSubConfig(conf *viper.Viper, configSubtreePath string) (subConfig *vip } return subConfig, err } + +// Read in TOML Viper config from bytes +func ReadViperConfig(configBytes []byte) (*viper.Viper, error) { + buf := bytes.NewBuffer(configBytes) + conf := viper.New() + viper.SetConfigType("toml") + err := conf.ReadConfig(buf) + if err != nil { + return nil, err + } + return conf, nil +} diff --git a/consensus/config.go b/consensus/config.go index 1c197b6fc45d75ee50a378fa8f8bc8604b67d0f9..e207213dbdd22a53182f28aebf07ea11465050a6 100644 --- a/consensus/config.go +++ b/consensus/config.go @@ -15,8 +15,7 @@ package consensus import ( - // noops "github.com/hyperledger/burrow/consensus/noops" - tendermint "github.com/hyperledger/burrow/consensus/tendermint" + tendermint_version "github.com/hyperledger/burrow/consensus/tendermint/version" ) //------------------------------------------------------------------------------ @@ -29,7 +28,7 @@ func AssertValidConsensusModule(name, minorVersionString string) bool { // over iterations return true case "tendermint": - return minorVersionString == tendermint.GetTendermintVersion().GetMinorVersionString() + return minorVersionString == tendermint_version.GetTendermintVersion().GetMinorVersionString() case "bigchaindb": // TODO: [ben] implement BigchainDB as consensus engine return false diff --git a/consensus/consensus.go b/consensus/consensus.go index f94dffb2ef64dc6907257c796dc0844b4861232f..d821f551476146abdedcf461a591c4e3c5605cb0 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -24,10 +24,18 @@ import ( func LoadConsensusEngineInPipe(moduleConfig *config.ModuleConfig, pipe definitions.Pipe) error { + + // Check interface-level compatibility + if !pipe.GetApplication().CompatibleConsensus(&tendermint.Tendermint{}) { + return fmt.Errorf("Manager Application %s it no compatible with "+ + "%s consensus", moduleConfig.Name, pipe.GetApplication()) + } + switch moduleConfig.Name { case "tendermint": + tmint, err := tendermint.NewTendermint(moduleConfig, pipe.GetApplication(), - pipe.Logger().With()) + pipe.Logger()) if err != nil { return fmt.Errorf("Failed to load Tendermint node: %v", err) } diff --git a/consensus/tendermint/config.go b/consensus/tendermint/config.go index 0ea0a1d546cbcb8e261de919fa03be5c3637ab66..b73a0b4f71ac424ba14b83320f3e8681015fd4c6 100644 --- a/consensus/tendermint/config.go +++ b/consensus/tendermint/config.go @@ -77,7 +77,7 @@ func (tmintConfig *TendermintConfig) AssertTendermintDefaults(chainId, workDir, tmintConfig.SetDefault("rpc_laddr", "") tmintConfig.SetDefault("prof_laddr", "") tmintConfig.SetDefault("revision_file", path.Join(workDir, "revision")) - tmintConfig.SetDefault("cs_wal_dir", path.Join(dataDir, "cs.wal")) + tmintConfig.SetDefault("cs_wal_file", path.Join(dataDir, "cs.wal/wal")) tmintConfig.SetDefault("cs_wal_light", false) tmintConfig.SetDefault("filter_peers", false) diff --git a/consensus/tendermint/tendermint.go b/consensus/tendermint/tendermint.go index 7029fe0406909ed72941a0027f46c1683ee27c8f..4f793389e5ae4a1e56d3e714a85482cd3beba3c6 100644 --- a/consensus/tendermint/tendermint.go +++ b/consensus/tendermint/tendermint.go @@ -19,6 +19,7 @@ import ( "path" "strings" + tendermint_version "github.com/hyperledger/burrow/consensus/tendermint/version" abci_types "github.com/tendermint/abci/types" crypto "github.com/tendermint/go-crypto" p2p "github.com/tendermint/go-p2p" @@ -32,6 +33,8 @@ import ( config "github.com/hyperledger/burrow/config" manager_types "github.com/hyperledger/burrow/manager/types" // files "github.com/hyperledger/burrow/files" + "errors" + blockchain_types "github.com/hyperledger/burrow/blockchain/types" consensus_types "github.com/hyperledger/burrow/consensus/types" "github.com/hyperledger/burrow/logging" @@ -56,9 +59,9 @@ func NewTendermint(moduleConfig *config.ModuleConfig, application manager_types.Application, logger logging_types.InfoTraceLogger) (*Tendermint, error) { // re-assert proper configuration for module - if moduleConfig.Version != GetTendermintVersion().GetMinorVersionString() { + if moduleConfig.Version != tendermint_version.GetTendermintVersion().GetMinorVersionString() { return nil, fmt.Errorf("Version string %s did not match %s", - moduleConfig.Version, GetTendermintVersion().GetMinorVersionString()) + moduleConfig.Version, tendermint_version.GetTendermintVersion().GetMinorVersionString()) } // loading the module has ensured the working and data directory // for tendermint have been created, but the config files needs @@ -122,15 +125,16 @@ func NewTendermint(moduleConfig *config.ModuleConfig, newNode := node.NewNode(tmintConfig, privateValidator, proxy.NewLocalClientCreator(application)) - listener := p2p.NewDefaultListener("tcp", tmintConfig.GetString("node_laddr"), - tmintConfig.GetBool("skip_upnp")) - - newNode.AddListener(listener) // TODO: [ben] delay starting the node to a different function, to hand // control over events to Core - if err := newNode.Start(); err != nil { + if started, err := newNode.Start(); !started { newNode.Stop() - return nil, fmt.Errorf("Failed to start Tendermint consensus node: %v", err) + if err != nil { + return nil, fmt.Errorf("Failed to start Tendermint consensus node: %v", err) + } + return nil, errors.New("Failed to start Tendermint consensus node, " + + "probably because it is already started, see logs") + } logging.InfoMsg(logger, "Tendermint consensus node started", "nodeAddress", tmintConfig.GetString("node_laddr"), @@ -269,6 +273,11 @@ func (tendermint *Tendermint) PeerConsensusStates() map[string]string { return peerConsensusStates } +// Allow for graceful shutdown of node. Returns whether the node was stopped. +func (tendermint *Tendermint) Stop() bool { + return tendermint.tmintNode.Stop() +} + //------------------------------------------------------------------------------ // Helper functions diff --git a/consensus/tendermint/version.go b/consensus/tendermint/version/version.go similarity index 95% rename from consensus/tendermint/version.go rename to consensus/tendermint/version/version.go index 7a20ac5c1b5b7bc037d6591ea82164f9b9f3e9a8..6b630784b9cb46b4a7c50348a1e4bdcde91e369d 100644 --- a/consensus/tendermint/version.go +++ b/consensus/tendermint/version/version.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package tendermint +package version import ( "strconv" @@ -28,9 +28,9 @@ const ( // Major version component of the current release tendermintVersionMajorConst uint8 = 0 // Minor version component of the current release - tendermintVersionMinorConst uint8 = 8 + tendermintVersionMinorConst uint8 = 9 // Patch version component of the current release - tendermintVersionPatchConst uint8 = 0 + tendermintVersionPatchConst uint8 = 2 ) var ( diff --git a/consensus/tendermint/version_test.go b/consensus/tendermint/version/version_test.go similarity index 99% rename from consensus/tendermint/version_test.go rename to consensus/tendermint/version/version_test.go index bfbbe3e762bde36304cf59379b04c94d13cff4ae..f5eb9cd0b775b7aa725c42c67e3bd86f2f6b68a2 100644 --- a/consensus/tendermint/version_test.go +++ b/consensus/tendermint/version/version_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package tendermint +package version import ( "fmt" diff --git a/consensus/types/consensus_engine.go b/consensus/types/consensus_engine.go index 26754db313609f0b5c30cf7ba6e8b622f18733e1..b1677d7a53fe8ef14181738ae17f93ff59748d22 100644 --- a/consensus/types/consensus_engine.go +++ b/consensus/types/consensus_engine.go @@ -48,4 +48,7 @@ type ConsensusEngine interface { // TODO: Consider creating a real type for PeerRoundState, but at the looks // quite coupled to tendermint PeerConsensusStates() map[string]string + + // Allow for graceful shutdown of node. Returns whether the node was stopped. + Stop() bool } diff --git a/core/config.go b/core/config.go index 0bc07bf8ce5aa185fa83adbcdd5fe2a8dd16abc0..1b9b79dbca5b14af924f1645ea149c5194e0b1a2 100644 --- a/core/config.go +++ b/core/config.go @@ -98,10 +98,15 @@ func LoadModuleConfig(conf *viper.Viper, rootWorkDir, rootDataDir, }, nil } -// LoadServerModuleConfig wraps specifically for the servers run by core -func LoadServerConfig(do *definitions.Do) (*server.ServerConfig, error) { +// Load the ServerConfig from commandline Do object +func LoadServerConfigFromDo(do *definitions.Do) (*server.ServerConfig, error) { // load configuration subtree for servers - subConfig, err := config.ViperSubConfig(do.Config, "servers") + return LoadServerConfig(do.ChainId, do.Config) +} + +// Load the ServerConfig from root Viper config, fixing the ChainId +func LoadServerConfig(chainId string, rootConfig *viper.Viper) (*server.ServerConfig, error) { + subConfig, err := config.ViperSubConfig(rootConfig, "servers") if err != nil { return nil, err } @@ -109,7 +114,7 @@ func LoadServerConfig(do *definitions.Do) (*server.ServerConfig, error) { if err != nil { return nil, err } - serverConfig.ChainId = do.ChainId + serverConfig.ChainId = chainId return serverConfig, err } diff --git a/core/core.go b/core/core.go index b6f515e0f8af69208aa708f569634975929b151a..3dad6ff078e9142123b83b59c46779d766ca9feb 100644 --- a/core/core.go +++ b/core/core.go @@ -119,3 +119,8 @@ func (core *Core) NewGatewayTendermint(config *server.ServerConfig) ( return rpc_tendermint.NewTendermintWebsocketServer(config, core.tendermintPipe, core.evsw) } + +// Stop the core allowing for a graceful shutdown of component in order. +func (core *Core) Stop() bool { + return core.pipe.GetConsensusEngine().Stop() +} diff --git a/genesis/maker.go b/genesis/maker.go index f30ef3cbd23762ea269475e7ba38d8e328f2903d..bfabb4fbc3671a9f0d6f1157dc28339634ad0d4c 100644 --- a/genesis/maker.go +++ b/genesis/maker.go @@ -46,22 +46,22 @@ func NewGenesisValidator(amount int64, name string, unbondToAddress []byte, case "ed25519": // TODO: [ben] functionality and checks need to be inherit in the type if len(publicKeyBytes) != PublicKeyEd25519ByteLength { - return nil, fmt.Errorf("Invalid length provided for ed25519 public key (len %v)", - len(publicKeyBytes)) + return nil, fmt.Errorf("Invalid length provided for ed25519 public key (%v bytes provided but expected %v bytes)", + len(publicKeyBytes), PublicKeyEd25519ByteLength) } // ed25519 has type byte 0x01 typedPublicKeyBytes = make([]byte, PublicKeyEd25519ByteLength+1) // prepend type byte to public key - typedPublicKeyBytes = append([]byte{crypto.PubKeyTypeEd25519}, publicKeyBytes...) + typedPublicKeyBytes = append([]byte{crypto.TypeEd25519}, publicKeyBytes...) case "secp256k1": if len(publicKeyBytes) != PublicKeySecp256k1ByteLength { - return nil, fmt.Errorf("Invalid length provided for secp256k1 public key (len %v)", - len(publicKeyBytes)) + return nil, fmt.Errorf("Invalid length provided for secp256k1 public key (%v bytes provided but expected %v bytes)", + len(publicKeyBytes), PublicKeySecp256k1ByteLength) } // secp256k1 has type byte 0x02 typedPublicKeyBytes = make([]byte, PublicKeySecp256k1ByteLength+1) // prepend type byte to public key - typedPublicKeyBytes = append([]byte{crypto.PubKeyTypeSecp256k1}, publicKeyBytes...) + typedPublicKeyBytes = append([]byte{crypto.TypeSecp256k1}, publicKeyBytes...) default: return nil, fmt.Errorf("Unsupported key type (%s)", keyType) } diff --git a/glide.lock b/glide.lock index 303601c905a60a2161e377ce2f06f15280c3ad9a..a53f4588b335dad4e7f2f03a87a25404f4f4456b 100644 --- a/glide.lock +++ b/glide.lock @@ -1,12 +1,12 @@ -hash: 310aa7c7435ad7dd1c3eb6772a42065b5f506e38e195107bdbfb1584833add9a -updated: 2017-02-21T01:43:41.814044634Z +hash: 4ad3a252504d2e316e39e6987952988b84692479a44ef29aeb1063add4c129c7 +updated: 2017-04-27T11:38:47.830251548+01:00 imports: - name: github.com/Azure/go-ansiterm version: 388960b655244e76e24c75f48631564eaefade62 subpackages: - winterm - name: github.com/btcsuite/btcd - version: 153dca5c1e4b5d1ea1523592495e5bedfa503391 + version: 4b348c1d33373d672edd83fc576892d0e46686d2 subpackages: - btcec - name: github.com/btcsuite/fastsha256 @@ -20,19 +20,19 @@ imports: - name: github.com/bugsnag/panicwrap version: d6191e27ad06236eaad65d79e49a08b03b9f8029 - name: github.com/BurntSushi/toml - version: 99064174e013895bbd9b025c31100bd1d9b590ca + version: b26d9c308763d68093482582cea63d69be07a0f0 - name: github.com/davecgh/go-spew - version: 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d + version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 + subpackages: + - spew - name: github.com/eapache/channels version: 47238d5aae8c0fefd518ef2bee46290909cf8263 - name: github.com/eapache/queue version: 44cc805cf13205b55f69e14bcb69867d1ae92f98 - name: github.com/ebuchman/fail-test - version: c1eddaa09da2b4017351245b0d43234955276798 + version: 95f809107225be108efcf10a3509e4ea6ceef3c4 - name: github.com/fsnotify/fsnotify version: 30411dbcefb7a1da7e84f75530ad3abe4011b4f8 -- name: github.com/Graylog2/go-gelf - version: 5bfd5bbbfe86489017c268bf86539fcec7e28d8e - name: github.com/gin-gonic/gin version: f931d1ea80ae95a6fc739213cdd9399bd2967fb6 subpackages: @@ -47,15 +47,18 @@ imports: - name: github.com/go-stack/stack version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 - name: github.com/gogo/protobuf - version: f9114dace7bd920b32f943b3c73fafbcbab2bf31 + version: 100ba4e885062801d56799d78530b73b178a78f3 - name: github.com/golang/protobuf - version: 8ee79997227bf9b34611aee7946ae64735e6fd93 + version: 2bba0603135d7d7f5cb73b2125beeda19c09f4ef subpackages: - proto + - ptypes/any - name: github.com/golang/snappy - version: d9eb7a3d35ec988b8585d4a0068e462c27d28380 + version: 553a641470496b2327abcac10b36396bd98e45c9 - name: github.com/gorilla/websocket - version: 17634340a83afe0cab595e40fbc63f6ffa1d8915 + version: 3ab3a8b8831546bd18fd182c20687ca853b2bb13 +- name: github.com/Graylog2/go-gelf + version: 5bfd5bbbfe86489017c268bf86539fcec7e28d8e - name: github.com/hashicorp/hcl version: da486364306ed66c218be9b7953e19173447c18b subpackages: @@ -82,37 +85,37 @@ imports: - name: github.com/Masterminds/glide version: 869001d1571ce5f03fd0078bff188b9d3f272807 - name: github.com/mattn/go-colorable - version: d228849504861217f796da67fae4f6e347643f15 + version: ded68f7a9561c023e790de24279db7ebf473ea80 - name: github.com/mattn/go-isatty - version: 30a891c33c7cde7b02a981314b4228ec99380cca + version: fc9e8d8ef48496124e79ae0df75490096eccf6fe - name: github.com/mitchellh/mapstructure version: db1efb556f84b25a0a13a04aad883943538ad2e0 - name: github.com/naoina/toml version: 751171607256bb66e64c9f0220c00662420c38e9 +- name: github.com/pkg/errors + version: 645ef00459ed84a119197bfb8d8205042c6df63d - name: github.com/pmezard/go-difflib version: d8ed2627bdf02c080bf22230dbb337003b7aba2d - subpackages: - - difflib - name: github.com/Sirupsen/logrus version: d26492970760ca5d33129d2d799e34be5c4782eb - name: github.com/spf13/cast version: 27b586b42e29bec072fe7379259cc719e1289da6 - name: github.com/spf13/cobra - version: bc81c21bd0d8be5ba2d6630a505d79d4467566e7 + version: 10f6b9d7e1631a54ad07c5c0fb71c28a1abfd3c2 - name: github.com/spf13/jwalterweatherman version: 33c24e77fb80341fe7130ee7c594256ff08ccc46 - name: github.com/spf13/pflag - version: 25f8b5b07aece3207895bf19f7ab517eb3b22a40 + version: 2300d0f8576fe575f71aaa5b9bbe4e1b0dc2eb51 - name: github.com/spf13/viper version: c1ccc378a054ea8d4e38d8c67f6938d4760b53dd - name: github.com/streadway/simpleuuid version: 6617b501e485b77e61b98cd533aefff9e258b5a7 - name: github.com/stretchr/testify - version: d77da356e56a7428ad25149ca77381849a6a5232 + version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 subpackages: - assert - name: github.com/syndtr/goleveldb - version: 23851d93a2292dcc56e71a18ec9e0624d84a0f65 + version: 8c81ea47d4c41a385645e133e15510fc6a2a74b4 subpackages: - leveldb - leveldb/cache @@ -127,12 +130,11 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/abci - version: 699d45bc678865b004b90213bf88a950f420973b + version: 56e13d87f4e3ec1ea756957d6b23caa6ebcf0998 subpackages: - client - example/counter - example/dummy - - example/nil - server - types - name: github.com/tendermint/ed25519 @@ -143,21 +145,23 @@ imports: - name: github.com/tendermint/flowcontrol version: 84d9671090430e8ec80e35b339907e0579b999eb - name: github.com/tendermint/go-autofile - version: 0416e0aa9c68205aa44844096f9f151ada9d0405 + version: 48b17de82914e1ec2f134ce823ba426337d2c518 - name: github.com/tendermint/go-clist version: 3baa390bbaf7634251c42ad69a8682e7e3990552 - name: github.com/tendermint/go-common - version: e289af53b6bf6af28da129d9ef64389a4cf7987f + version: f9e3db037330c8a8d61d3966de8473eaf01154fa subpackages: - test - name: github.com/tendermint/go-config - version: e64b424499acd0eb9856b88e10c0dff41628c0d6 + version: 620dcbbd7d587cf3599dedbf329b64311b0c307a - name: github.com/tendermint/go-crypto - version: 4b11d62bdb324027ea01554e5767b71174680ba0 + version: 0ca2c6fdb0706001ca4c4b9b80c9f428e8cf39da +- name: github.com/tendermint/go-data + version: e7fcc6d081ec8518912fcdc103188275f83a3ee5 - name: github.com/tendermint/go-db - version: 72f6dacd22a686cdf7fcd60286503e3aceda77ba + version: 9643f60bc2578693844aacf380a7c32e4c029fee - name: github.com/tendermint/go-events - version: fddee66d90305fccb6f6d84d16c34fa65ea5b7f6 + version: f8ffbfb2be3483e9e7927495590a727f51c0c11f - name: github.com/tendermint/go-flowrate version: a20c98e61957faa93b4014fbd902f20ab9317a6a subpackages: @@ -165,25 +169,31 @@ imports: - name: github.com/tendermint/go-logger version: cefb3a45c0bf3c493a04e9bcd9b1540528be59f2 - name: github.com/tendermint/go-merkle - version: 7a86b4486f2cd84ac885c5bbc609fdee2905f5d1 + version: 714d4d04557fd068a7c2a1748241ce8428015a96 - name: github.com/tendermint/go-p2p - version: 3d98f675f30dc4796546b8b890f895926152fa8d + version: e8f33a47846708269d373f9c8080613d6c4f66b2 subpackages: - upnp - name: github.com/tendermint/go-rpc - version: fcea0cda21f64889be00a0f4b6d13266b1a76ee7 + version: 2c8df0ee6b60d8ac33662df13a4e358c679e02bf subpackages: - client - server - types - name: github.com/tendermint/go-wire - version: 2f3b7aafe21c80b19b6ee3210ecb3e3d07c7a471 + version: c1c9a57ab8038448ddea1714c0698f8051e5748c - name: github.com/tendermint/log15 version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 subpackages: - term +- name: github.com/tendermint/merkleeyes + version: 9fb76efa5aebe773a598f97e68e75fe53d520e70 + subpackages: + - app + - client + - testutil - name: github.com/tendermint/tendermint - version: 764091dfbb035f1b28da4b067526e04c6a849966 + version: f6e28c497510dcd266353649a45d6f962fd5001c subpackages: - blockchain - consensus @@ -198,7 +208,7 @@ imports: - name: github.com/tommy351/gin-cors version: dc91dec6313ae4db53481bf3b29cf6b94bf80357 - name: golang.org/x/crypto - version: 7c6cc321c680f03b9ef0764448e780704f486b51 + version: 96846453c37f0876340a66a47f3f75b1f3a6cd2d subpackages: - curve25519 - nacl/box @@ -209,7 +219,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: 60c41d1de8da134c05b7b40154a9a82bf5b7edb9 + version: c8c74377599bd978aee1cf3b9b63a8634051cec2 subpackages: - context - http2 @@ -217,27 +227,33 @@ imports: - idna - internal/timeseries - name: golang.org/x/sys - version: d75a52659825e75fff6158388dddc6a5b04f9ba5 + version: ea9bcade75cb975a0b9738936568ab388b845617 subpackages: - unix - name: golang.org/x/text - version: 44f4f658a783b0cee41fe0a23b8fc91d9c120558 + version: 19e3104b43db45fca0303f489a9536087b184802 subpackages: - secure/bidirule - transform - unicode/bidi - unicode/norm +- name: google.golang.org/genproto + version: 411e09b969b1170a9f0c467558eb4c4c110d9c77 + subpackages: + - googleapis/rpc/status - name: google.golang.org/grpc - version: 50955793b0183f9de69bd78e2ec251cf20aab121 + version: 6914ab1e338c92da4218a23d27fcd03d0ad78d46 subpackages: - codes - credentials - grpclog - internal + - keepalive - metadata - naming - peer - stats + - status - tap - transport - name: gopkg.in/fatih/set.v0 diff --git a/glide.yaml b/glide.yaml index 43dd7879a00769a4e33011634df7600943cb8630..cb5cf944ec45eed78f58c29376ce050e8b4f65ef 100644 --- a/glide.yaml +++ b/glide.yaml @@ -6,8 +6,6 @@ import: - package: github.com/gorilla/websocket - package: github.com/naoina/toml - package: github.com/stretchr/testify -- package: github.com/tendermint/tendermint - version: ~0.8.0 - package: github.com/tendermint/ed25519 - package: github.com/tommy351/gin-cors - package: golang.org/x/crypto @@ -33,3 +31,5 @@ import: - package: github.com/Masterminds/glide version: ~0.12.3 - package: github.com/Graylog2/go-gelf +- package: github.com/tendermint/tendermint + version: ~0.9.2 diff --git a/manager/burrow-mint/burrow-mint.go b/manager/burrow-mint/burrow-mint.go index b54f9f3de5a174c2ff7c86daafbae5e9f585c94b..d3255452a3585f2da307dce4b65226e6767a2231 100644 --- a/manager/burrow-mint/burrow-mint.go +++ b/manager/burrow-mint/burrow-mint.go @@ -24,9 +24,9 @@ import ( tendermint_events "github.com/tendermint/go-events" wire "github.com/tendermint/go-wire" + consensus_types "github.com/hyperledger/burrow/consensus/types" "github.com/hyperledger/burrow/logging" logging_types "github.com/hyperledger/burrow/logging/types" - sm "github.com/hyperledger/burrow/manager/burrow-mint/state" manager_types "github.com/hyperledger/burrow/manager/types" "github.com/hyperledger/burrow/txs" @@ -51,13 +51,22 @@ type BurrowMint struct { logger logging_types.InfoTraceLogger } +// Currently we just wrap ConsensusEngine but this interface can give us +// arbitrary control over the type of ConsensusEngine at such a point that we +// support others. For example it can demand a 'marker' function: +// func IsBurrowMint_0.XX.XX_CompatibleConsensusEngine() +type BurrowMintCompatibleConsensusEngine interface { + consensus_types.ConsensusEngine +} + // NOTE [ben] Compiler check to ensure BurrowMint successfully implements // burrow/manager/types.Application var _ manager_types.Application = (*BurrowMint)(nil) -// NOTE: [ben] also automatically implements abci.Application, -// undesired but unharmful -// var _ abci.Application = (*BurrowMint)(nil) +func (app *BurrowMint) CompatibleConsensus(consensusEngine consensus_types.ConsensusEngine) bool { + _, ok := consensusEngine.(BurrowMintCompatibleConsensusEngine) + return ok +} func (app *BurrowMint) GetState() *sm.State { app.mtx.Lock() @@ -177,6 +186,31 @@ func (app *BurrowMint) Commit() (res abci.Result) { return abci.NewResultOK(appHash, "Success") } -func (app *BurrowMint) Query(query []byte) (res abci.Result) { - return abci.NewResultOK(nil, "Success") +func (app *BurrowMint) Query(query abci.RequestQuery) (res abci.ResponseQuery) { + return abci.ResponseQuery{ + Code: abci.CodeType_OK, + Log: "success", + } +} + +// BlockchainAware interface + +// Initialise the blockchain +// validators: genesis validators from tendermint core +func (app *BurrowMint) InitChain(validators []*abci.Validator) { + // Could verify agreement on initial validator set here +} + +// Signals the beginning of a block +func (app *BurrowMint) BeginBlock(hash []byte, header *abci.Header) { + +} + +// Signals the end of a blockchain, return value can be used to modify validator +// set and voting power distribution see our BlockchainAware interface +func (app *BurrowMint) EndBlock(height uint64) (respEndblock abci.ResponseEndBlock) { + // TODO: [Silas] Bondage + // TODO: [Silas] this might be a better place for us to dispatch new block + // events particularly if we want to separate ourselves from go-events + return } diff --git a/manager/burrow-mint/pipe.go b/manager/burrow-mint/pipe.go index 3830bd0e88b3f8ff7b6684cefb50c8408734fb21..77efde509bd5dcfcfa0c73a64de6f838c521d614 100644 --- a/manager/burrow-mint/pipe.go +++ b/manager/burrow-mint/pipe.go @@ -297,7 +297,7 @@ func (pipe *burrowMintPipe) Status() (*rpc_tm_types.ResultStatus, error) { ) if latestHeight != 0 { latestBlockMeta = pipe.blockchain.BlockMeta(latestHeight) - latestBlockHash = latestBlockMeta.Hash + latestBlockHash = latestBlockMeta.Header.Hash() latestBlockTime = latestBlockMeta.Header.Time.UnixNano() } return &rpc_tm_types.ResultStatus{ diff --git a/manager/burrow-mint/version.go b/manager/burrow-mint/version.go index 93d7a36e96d6937d47756738f8a8be3ffe572409..888de79cbca1c81d032954b4c9fc78bf34237bdc 100644 --- a/manager/burrow-mint/version.go +++ b/manager/burrow-mint/version.go @@ -34,7 +34,7 @@ const ( // Define the compatible consensus engines this application manager // is compatible and has been tested with. var compatibleConsensus = [...]string{ - "tendermint-0.8", + "tendermint-0.9", } func GetBurrowMintVersion() *version.VersionIdentifier { diff --git a/manager/types/application.go b/manager/types/application.go index d2eda8f38318e28b993f490a857548bfad091d84..2025742bbd5cee5b62b95f348478d382f0acab31 100644 --- a/manager/types/application.go +++ b/manager/types/application.go @@ -18,7 +18,8 @@ import ( // TODO: [ben] this is currently only used for abci result type; but should // be removed as abci dependencies shouldn't feature in the application // manager - abci_types "github.com/tendermint/abci/types" + consensus_types "github.com/hyperledger/burrow/consensus/types" + abci "github.com/tendermint/abci/types" ) // NOTE: [ben] this interface is likely to be changed. Currently it is taken @@ -29,7 +30,7 @@ type Application interface { // Info returns application information as a string // NOTE: [ben] likely to move - Info() (info abci_types.ResponseInfo) + Info() (info abci.ResponseInfo) // Set application option (e.g. mode=mempool, mode=consensus) // NOTE: [ben] taken from tendermint, but it is unclear what the use is, @@ -48,7 +49,7 @@ type Application interface { // TODO: implementation notes: // 1. at this point the transaction should already be strongly typed // 2. - DeliverTx(tx []byte) abci_types.Result + DeliverTx(tx []byte) abci.Result // Check Transaction validates a transaction before being allowed into the // consensus' engine memory pool. This is the original defintion and @@ -59,7 +60,7 @@ type Application interface { // TODO: implementation notes: // 1. at this point the transaction should already be strongly typed // 2. - CheckTx(tx []byte) abci_types.Result + CheckTx(tx []byte) abci.Result // Commit returns the root hash of the current application state // NOTE: [ben] Because the concept of the block has been erased here @@ -67,30 +68,37 @@ type Application interface { // the opposit the principle of explicit stateless functions. // This will be amended when we introduce the concept of (streaming) // blocks in the pipe. - Commit() abci_types.Result + Commit() abci.Result // Query for state. This query request is not passed over the p2p network - // and is called from Tendermint rpc directly up to the application. + // and is called from Tenderpmint rpc directly up to the application. // NOTE: [ben] burrow will give preference to queries from the local client // directly over the burrow rpc. // We will support this for Tendermint compatibility. - Query(query []byte) abci_types.Result -} + Query(reqQuery abci.RequestQuery) abci.ResponseQuery -// Tendermint has a separate interface for reintroduction of blocks -type BlockchainAware interface { + // Tendermint acbi_types.Application extends our base definition of an + // Application with a parenthetical (begin/end) streaming block interface // Initialise the blockchain - // validators: genesis validators from tendermint core - InitChain(validators []*abci_types.Validator) + // When Tendermint initialises the genesis validators from tendermint core + // are passed in as validators + InitChain(validators []*abci.Validator) - // Signals the beginning of a block; - // NOTE: [ben] currently not supported by tendermint - BeginBlock(height uint64) + // Signals the beginning of communicating a block (all transactions have been + // closed into the block already + BeginBlock(hash []byte, header *abci.Header) // Signals the end of a blockchain - // validators: changed validators from app to Tendermint - // NOTE: [ben] currently not supported by tendermint - // not yet well defined what the change set contains. - EndBlock(height uint64) (validators []*abci_types.Validator) + // ResponseEndBlock wraps a slice of Validators with the Diff field. A Validator + // is a public key and a voting power. Returning a Validator within this slice + // asks Tendermint to set that validator's voting power to the Power provided. + // Note: although the field is named 'Diff' the intention is that it declares + // the what the new voting power should be (for validators specified, + // those omitted are left alone) it is not an relative increment to + // be added (or subtracted) from voting power. + EndBlock(height uint64) abci.ResponseEndBlock + + // Is this the passed ConsensusEngine compatible with this manager + CompatibleConsensus(consensusEngine consensus_types.ConsensusEngine) bool } diff --git a/rpc/tendermint/client/client.go b/rpc/tendermint/client/client.go index d8ca980094524562d9e70a8d13b6e7e19c6cd6bf..fe9f8ca55e774e61098074c89a94b9f2e2b957e5 100644 --- a/rpc/tendermint/client/client.go +++ b/rpc/tendermint/client/client.go @@ -22,36 +22,39 @@ import ( core_types "github.com/hyperledger/burrow/core/types" rpc_types "github.com/hyperledger/burrow/rpc/tendermint/core/types" "github.com/hyperledger/burrow/txs" - rpcclient "github.com/tendermint/go-rpc/client" "github.com/tendermint/go-wire" ) -func Status(client rpcclient.Client) (*rpc_types.ResultStatus, error) { - res, err := performCall(client, "status") +type RPCClient interface { + Call(method string, params map[string]interface{}, result interface{}) (interface{}, error) +} + +func Status(client RPCClient) (*rpc_types.ResultStatus, error) { + res, err := call(client, "status") if err != nil { return nil, err } return res.(*rpc_types.ResultStatus), nil } -func ChainId(client rpcclient.Client) (*rpc_types.ResultChainId, error) { - res, err := performCall(client, "chain_id") +func ChainId(client RPCClient) (*rpc_types.ResultChainId, error) { + res, err := call(client, "chain_id") if err != nil { return nil, err } return res.(*rpc_types.ResultChainId), nil } -func GenPrivAccount(client rpcclient.Client) (*acm.PrivAccount, error) { - res, err := performCall(client, "unsafe/gen_priv_account") +func GenPrivAccount(client RPCClient) (*acm.PrivAccount, error) { + res, err := call(client, "unsafe/gen_priv_account") if err != nil { return nil, err } return res.(*rpc_types.ResultGenPrivAccount).PrivAccount, nil } -func GetAccount(client rpcclient.Client, address []byte) (*acm.Account, error) { - res, err := performCall(client, "get_account", +func GetAccount(client RPCClient, address []byte) (*acm.Account, error) { + res, err := call(client, "get_account", "address", address) if err != nil { return nil, err @@ -59,9 +62,9 @@ func GetAccount(client rpcclient.Client, address []byte) (*acm.Account, error) { return res.(*rpc_types.ResultGetAccount).Account, nil } -func SignTx(client rpcclient.Client, tx txs.Tx, +func SignTx(client RPCClient, tx txs.Tx, privAccounts []*acm.PrivAccount) (txs.Tx, error) { - res, err := performCall(client, "unsafe/sign_tx", + res, err := call(client, "unsafe/sign_tx", "tx", wrappedTx{tx}, "privAccounts", privAccounts) if err != nil { @@ -70,9 +73,9 @@ func SignTx(client rpcclient.Client, tx txs.Tx, return res.(*rpc_types.ResultSignTx).Tx, nil } -func BroadcastTx(client rpcclient.Client, +func BroadcastTx(client RPCClient, tx txs.Tx) (txs.Receipt, error) { - res, err := performCall(client, "broadcast_tx", + res, err := call(client, "broadcast_tx", "tx", wrappedTx{tx}) if err != nil { return txs.Receipt{}, err @@ -84,9 +87,9 @@ func BroadcastTx(client rpcclient.Client, } -func DumpStorage(client rpcclient.Client, +func DumpStorage(client RPCClient, address []byte) (*rpc_types.ResultDumpStorage, error) { - res, err := performCall(client, "dump_storage", + res, err := call(client, "dump_storage", "address", address) if err != nil { return nil, err @@ -94,8 +97,8 @@ func DumpStorage(client rpcclient.Client, return res.(*rpc_types.ResultDumpStorage), err } -func GetStorage(client rpcclient.Client, address, key []byte) ([]byte, error) { - res, err := performCall(client, "get_storage", +func GetStorage(client RPCClient, address, key []byte) ([]byte, error) { + res, err := call(client, "get_storage", "address", address, "key", key) if err != nil { @@ -104,9 +107,9 @@ func GetStorage(client rpcclient.Client, address, key []byte) ([]byte, error) { return res.(*rpc_types.ResultGetStorage).Value, nil } -func CallCode(client rpcclient.Client, fromAddress, code, +func CallCode(client RPCClient, fromAddress, code, data []byte) (*rpc_types.ResultCall, error) { - res, err := performCall(client, "call_code", + res, err := call(client, "call_code", "fromAddress", fromAddress, "code", code, "data", data) @@ -116,9 +119,9 @@ func CallCode(client rpcclient.Client, fromAddress, code, return res.(*rpc_types.ResultCall), err } -func Call(client rpcclient.Client, fromAddress, toAddress, +func Call(client RPCClient, fromAddress, toAddress, data []byte) (*rpc_types.ResultCall, error) { - res, err := performCall(client, "call", + res, err := call(client, "call", "fromAddress", fromAddress, "toAddress", toAddress, "data", data) @@ -128,8 +131,8 @@ func Call(client rpcclient.Client, fromAddress, toAddress, return res.(*rpc_types.ResultCall), err } -func GetName(client rpcclient.Client, name string) (*core_types.NameRegEntry, error) { - res, err := performCall(client, "get_name", +func GetName(client RPCClient, name string) (*core_types.NameRegEntry, error) { + res, err := call(client, "get_name", "name", name) if err != nil { return nil, err @@ -137,9 +140,9 @@ func GetName(client rpcclient.Client, name string) (*core_types.NameRegEntry, er return res.(*rpc_types.ResultGetName).Entry, nil } -func BlockchainInfo(client rpcclient.Client, minHeight, +func BlockchainInfo(client RPCClient, minHeight, maxHeight int) (*rpc_types.ResultBlockchainInfo, error) { - res, err := performCall(client, "blockchain", + res, err := call(client, "blockchain", "minHeight", minHeight, "maxHeight", maxHeight) if err != nil { @@ -148,8 +151,8 @@ func BlockchainInfo(client rpcclient.Client, minHeight, return res.(*rpc_types.ResultBlockchainInfo), err } -func GetBlock(client rpcclient.Client, height int) (*rpc_types.ResultGetBlock, error) { - res, err := performCall(client, "get_block", +func GetBlock(client RPCClient, height int) (*rpc_types.ResultGetBlock, error) { + res, err := call(client, "get_block", "height", height) if err != nil { return nil, err @@ -157,69 +160,57 @@ func GetBlock(client rpcclient.Client, height int) (*rpc_types.ResultGetBlock, e return res.(*rpc_types.ResultGetBlock), err } -func ListUnconfirmedTxs(client rpcclient.Client) (*rpc_types.ResultListUnconfirmedTxs, error) { - res, err := performCall(client, "list_unconfirmed_txs") +func ListUnconfirmedTxs(client RPCClient) (*rpc_types.ResultListUnconfirmedTxs, error) { + res, err := call(client, "list_unconfirmed_txs") if err != nil { return nil, err } return res.(*rpc_types.ResultListUnconfirmedTxs), err } -func ListValidators(client rpcclient.Client) (*rpc_types.ResultListValidators, error) { - res, err := performCall(client, "list_validators") +func ListValidators(client RPCClient) (*rpc_types.ResultListValidators, error) { + res, err := call(client, "list_validators") if err != nil { return nil, err } return res.(*rpc_types.ResultListValidators), err } -func DumpConsensusState(client rpcclient.Client) (*rpc_types.ResultDumpConsensusState, error) { - res, err := performCall(client, "dump_consensus_state") +func DumpConsensusState(client RPCClient) (*rpc_types.ResultDumpConsensusState, error) { + res, err := call(client, "dump_consensus_state") if err != nil { return nil, err } return res.(*rpc_types.ResultDumpConsensusState), err } -func performCall(client rpcclient.Client, method string, +func call(client RPCClient, method string, paramKeyVals ...interface{}) (res rpc_types.BurrowResult, err error) { - paramsMap, paramsSlice, err := mapAndValues(paramKeyVals...) + pMap, err := paramsMap(paramKeyVals...) if err != nil { return } - switch cli := client.(type) { - case *rpcclient.ClientJSONRPC: - _, err = cli.Call(method, paramsSlice, &res) - case *rpcclient.ClientURI: - _, err = cli.Call(method, paramsMap, &res) - default: - panic(fmt.Errorf("peformCall called against an unknown rpcclient.Client %v", - cli)) - } + _, err = client.Call(method, pMap, &res) return - } -func mapAndValues(orderedKeyVals ...interface{}) (map[string]interface{}, - []interface{}, error) { +func paramsMap(orderedKeyVals ...interface{}) (map[string]interface{}, error) { if len(orderedKeyVals)%2 != 0 { - return nil, nil, fmt.Errorf("mapAndValues requires a even length list of"+ + return nil, fmt.Errorf("mapAndValues requires a even length list of"+ " keys and values but got: %v (length %v)", orderedKeyVals, len(orderedKeyVals)) } paramsMap := make(map[string]interface{}) - paramsSlice := make([]interface{}, len(orderedKeyVals)/2) for i := 0; i < len(orderedKeyVals); i += 2 { key, ok := orderedKeyVals[i].(string) if !ok { - return nil, nil, errors.New("mapAndValues requires every even element" + + return nil, errors.New("mapAndValues requires every even element" + " of orderedKeyVals to be a string key") } val := orderedKeyVals[i+1] paramsMap[key] = val - paramsSlice[i/2] = val } - return paramsMap, paramsSlice, nil + return paramsMap, nil } type wrappedTx struct { diff --git a/rpc/tendermint/client/client_test.go b/rpc/tendermint/client/client_test.go index 105a9d2b92fddd75508c9eadbe209859fbf88b44..673be6c1c60275cfb595c79079f719f976bb3fbe 100644 --- a/rpc/tendermint/client/client_test.go +++ b/rpc/tendermint/client/client_test.go @@ -20,29 +20,27 @@ import ( "github.com/stretchr/testify/assert" ) -func TestMapsAndValues(t *testing.T) { +func TestParamsMap(t *testing.T) { type aStruct struct { Baz int } - dict, vals, err := mapAndValues("Foo", aStruct{5}, + dict, err := paramsMap("Foo", aStruct{5}, "Bar", "Nibbles") assert.Equal(t, map[string]interface{}{ "Foo": aStruct{5}, "Bar": "Nibbles", }, dict) - assert.Equal(t, []interface{}{aStruct{5}, "Nibbles"}, vals) // Empty map - dict, vals, err = mapAndValues() + dict, err = paramsMap() assert.Equal(t, map[string]interface{}{}, dict) - assert.Equal(t, []interface{}{}, vals) assert.NoError(t, err, "Empty mapsAndValues call should be fine") // Invalid maps assert.NoError(t, err, "Empty mapsAndValues call should be fine") - _, _, err = mapAndValues("Foo", 4, "Bar") + _, err = paramsMap("Foo", 4, "Bar") assert.Error(t, err, "Should be an error to get an odd number of arguments") - _, _, err = mapAndValues("Foo", 4, 4, "Bar") + _, err = paramsMap("Foo", 4, 4, "Bar") assert.Error(t, err, "Should be an error to provide non-string keys") } diff --git a/rpc/tendermint/test/common.go b/rpc/tendermint/test/common.go index ff618906ca09d88167e6ee883219caff0326cecf..13d4aca450e1c974e7a6ef23d7450a5e71ef6a25 100644 --- a/rpc/tendermint/test/common.go +++ b/rpc/tendermint/test/common.go @@ -25,7 +25,7 @@ import ( // Needs to be referenced by a *_test.go file to be picked up func TestWrapper(runner func() int) int { - fmt.Println("Running with integration TestWrapper (rpc/tendermint/test/common.go)...") + fmt.Println("Running with integration TestWrapper (rpc/tendermint/test/common.go)...\n") ffs := fixtures.NewFileFixtures("burrow") defer ffs.RemoveAll() diff --git a/rpc/tendermint/test/config.go b/rpc/tendermint/test/config.go deleted file mode 100644 index ed080f3d4bf32ecbc8b54d683c36ec3ea3b53c99..0000000000000000000000000000000000000000 --- a/rpc/tendermint/test/config.go +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright 2017 Monax Industries Limited -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package test - -var defaultConfig = `# Copyright 2017 Monax Industries Limited -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License.. - -# This is a TOML configuration for burrow chains - -[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 = "MyChainId" -# semantic major and minor version -major_version = 0 -minor_version = 17 -# genesis file, relative path is to burrow working directory -genesis_file = "genesis.json" - - -############################################################################### -## -## consensus -## -############################################################################### - - [chain.consensus] - # consensus defines the module to use for consensus and - # this will define the peer-to-peer consensus network; - # accepted values are "noops", "abci", "tendermint" - name = "tendermint" - # version is the major and minor semantic version; - # the version will be asserted on - major_version = 0 - minor_version = 8 - # relative path to consensus' module root folder - relative_root = "tendermint" - -############################################################################### -## -## application manager -## -############################################################################### - - [chain.manager] - # application manager name defines the module to use for handling - name = "burrowmint" - # version is the major and minor semantic version; - # the version will be asserted on - major_version = 0 - minor_version = 17 - # relative path to application manager root folder - relative_root = "burrowmint" - -################################################################################ -################################################################################ -## -## Server configurations -## -################################################################################ -################################################################################ - -[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:36657" - endpoint = "/websocket" - -################################################################################ -################################################################################ -## -## Module configurations - dynamically loaded based on chain configuration -## -################################################################################ -################################################################################ - - -################################################################################ -## -## Tendermint Socket Protocol (abci) -## -## abci expects a tendermint consensus process to run and connect to burrow -## -################################################################################ - -[abci] -# listener address for accepting tendermint socket protocol connections -listener = "tcp://0.0.0.0:46658" - -################################################################################ -##yeah we had partial support for that with TMSP -## Tendermint -## -## 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 monax-keys -# This file needs to be in the root directory -private_validator_file = "priv_validator.json" - - # Tendermint requires additional configuration parameters. - # burrow's tendermint consensus module will load [tendermint.configuration] - # as the configuration for Tendermint. - # burrow 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 = "anonymous_marmot" - # seeds lists the peers tendermint can connect to join the network - 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 = false - db_backend = "leveldb" - 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 = "" - # proxy application address - used for abci 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" - # cs_wal_dir = "./data/tendermint/data/cswal" - # cs_wal_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 - -################################################################################ -## -## burrow-mint -## version 0.17.0 -## -## The original Ethereum virtual machine with IAVL merkle trees -## and tendermint/go-wire encoding -## -################################################################################ - -[burrowmint] -# Database backend to use for BurrowMint state database. -db_backend = "leveldb" -` diff --git a/rpc/tendermint/test/genesis.go b/rpc/tendermint/test/genesis.go deleted file mode 100644 index 9ca0e6e83c0575b733b841f0af44402adc83d19d..0000000000000000000000000000000000000000 --- a/rpc/tendermint/test/genesis.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2017 Monax Industries Limited -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package test - -// priv keys generated deterministically eg rpc/tests/shared.go -var defaultGenesis = `{ - "chain_id" : "MyChainId", - "accounts": [ - { - "address": "E9B5D87313356465FAE33C406CE2C2979DE60BCB", - "amount": 200000000 - }, - { - "address": "DFE4AFFA4CEE17CD01CB9E061D77C3ECED29BD88", - "amount": 200000000 - }, - { - "address": "F60D30722E7B497FA532FB3207C3FB29C31B1992", - "amount": 200000000 - }, - { - "address": "336CB40A5EB92E496E19B74FDFF2BA017C877FD6", - "amount": 200000000 - }, - { - "address": "D218F0F439BF0384F6F5EF8D0F8B398D941BD1DC", - "amount": 200000000 - } - ], - "validators": [ - { - "pub_key": [1, "583779C3BFA3F6C7E23C7D830A9C3D023A216B55079AD38BFED1207B94A19548"], - "amount": 1000000, - "unbond_to": [ - { - "address": "E9B5D87313356465FAE33C406CE2C2979DE60BCB", - "amount": 100000 - } - ] - } - ] -}` diff --git a/rpc/tendermint/test/rpc_client_test.go b/rpc/tendermint/test/rpc_client_test.go index f7f89827ca4625abaf60ae65eeee8707971aadcf..3f7da59afb790e358e2d0dda423ae7e2291067cc 100644 --- a/rpc/tendermint/test/rpc_client_test.go +++ b/rpc/tendermint/test/rpc_client_test.go @@ -26,12 +26,11 @@ import ( "golang.org/x/crypto/ripemd160" consensus_types "github.com/hyperledger/burrow/consensus/types" - edbcli "github.com/hyperledger/burrow/rpc/tendermint/client" + burrow_client "github.com/hyperledger/burrow/rpc/tendermint/client" "github.com/hyperledger/burrow/txs" "github.com/hyperledger/burrow/word256" "github.com/stretchr/testify/assert" - rpcclient "github.com/tendermint/go-rpc/client" _ "github.com/tendermint/tendermint/config/tendermint_test" ) @@ -42,7 +41,7 @@ import ( // due to weirdness with go-wire's interface registration, and those global // registrations not being available within a *_test.go runtime context. func testWithAllClients(t *testing.T, - testFunction func(*testing.T, string, rpcclient.Client)) { + testFunction func(*testing.T, string, burrow_client.RPCClient)) { for clientName, client := range clients { testFunction(t, clientName, client) } @@ -50,8 +49,8 @@ func testWithAllClients(t *testing.T, //-------------------------------------------------------------------------------- func TestStatus(t *testing.T) { - testWithAllClients(t, func(t *testing.T, clientName string, client rpcclient.Client) { - resp, err := edbcli.Status(client) + testWithAllClients(t, func(t *testing.T, clientName string, client burrow_client.RPCClient) { + resp, err := burrow_client.Status(client) assert.NoError(t, err) fmt.Println(resp) if resp.NodeInfo.Network != chainID { @@ -63,12 +62,11 @@ func TestStatus(t *testing.T) { func TestBroadcastTx(t *testing.T) { wsc := newWSClient() - testWithAllClients(t, func(t *testing.T, clientName string, client rpcclient.Client) { + testWithAllClients(t, func(t *testing.T, clientName string, client burrow_client.RPCClient) { // Avoid duplicate Tx in mempool amt := hashString(clientName) % 1000 - toAddr := user[1].Address + toAddr := users[1].Address tx := makeDefaultSendTxSigned(t, client, toAddr, amt) - //receipt := broadcastTx(t, client, tx) receipt, err := broadcastTxAndWaitForBlock(t, client, wsc, tx) assert.NoError(t, err) if receipt.CreatesContract > 0 { @@ -97,14 +95,14 @@ func TestGetAccount(t *testing.T) { if testing.Short() { t.Skip("skipping test in short mode.") } - testWithAllClients(t, func(t *testing.T, clientName string, client rpcclient.Client) { - acc := getAccount(t, client, user[0].Address) + testWithAllClients(t, func(t *testing.T, clientName string, client burrow_client.RPCClient) { + acc := getAccount(t, client, users[0].Address) if acc == nil { t.Fatal("Account was nil") } - if bytes.Compare(acc.Address, user[0].Address) != 0 { + if bytes.Compare(acc.Address, users[0].Address) != 0 { t.Fatalf("Failed to get correct account. Got %x, expected %x", acc.Address, - user[0].Address) + users[0].Address) } }) } @@ -114,12 +112,14 @@ func TestGetStorage(t *testing.T) { t.Skip("skipping test in short mode.") } wsc := newWSClient() - testWithAllClients(t, func(t *testing.T, clientName string, client rpcclient.Client) { + defer func() { + wsc.Stop() + }() + testWithAllClients(t, func(t *testing.T, clientName string, client burrow_client.RPCClient) { eid := txs.EventStringNewBlock() subscribe(t, wsc, eid) defer func() { unsubscribe(t, wsc, eid) - wsc.Stop() }() amt, gasLim, fee := int64(1100), int64(1000), int64(1000) @@ -151,13 +151,13 @@ func TestCallCode(t *testing.T) { t.Skip("skipping test in short mode.") } - testWithAllClients(t, func(t *testing.T, clientName string, client rpcclient.Client) { + testWithAllClients(t, func(t *testing.T, clientName string, client burrow_client.RPCClient) { // add two integers and return the result code := []byte{0x60, 0x5, 0x60, 0x6, 0x1, 0x60, 0x0, 0x52, 0x60, 0x20, 0x60, 0x0, 0xf3} data := []byte{} expected := []byte{0xb} - callCode(t, client, user[0].PubKey.Address(), code, data, expected) + callCode(t, client, users[0].PubKey.Address(), code, data, expected) // pass two ints as calldata, add, and return the result code = []byte{0x60, 0x0, 0x35, 0x60, 0x20, 0x35, 0x1, 0x60, 0x0, 0x52, 0x60, @@ -165,7 +165,7 @@ func TestCallCode(t *testing.T) { data = append(word256.LeftPadWord256([]byte{0x5}).Bytes(), word256.LeftPadWord256([]byte{0x6}).Bytes()...) expected = []byte{0xb} - callCode(t, client, user[0].PubKey.Address(), code, data, expected) + callCode(t, client, users[0].PubKey.Address(), code, data, expected) }) } @@ -174,12 +174,14 @@ func TestCallContract(t *testing.T) { t.Skip("skipping test in short mode.") } wsc := newWSClient() - testWithAllClients(t, func(t *testing.T, clientName string, client rpcclient.Client) { + defer func() { + wsc.Stop() + }() + testWithAllClients(t, func(t *testing.T, clientName string, client burrow_client.RPCClient) { eid := txs.EventStringNewBlock() subscribe(t, wsc, eid) defer func() { unsubscribe(t, wsc, eid) - wsc.Stop() }() // create the contract @@ -202,7 +204,7 @@ func TestCallContract(t *testing.T) { // run a call through the contract data := []byte{} expected := []byte{0xb} - callContract(t, client, user[0].PubKey.Address(), contractAddr, data, expected) + callContract(t, client, users[0].PubKey.Address(), contractAddr, data, expected) }) } @@ -211,7 +213,7 @@ func TestNameReg(t *testing.T) { t.Skip("skipping test in short mode.") } wsc := newWSClient() - testWithAllClients(t, func(t *testing.T, clientName string, client rpcclient.Client) { + testWithAllClients(t, func(t *testing.T, clientName string, client burrow_client.RPCClient) { txs.MinNameRegistrationPeriod = 1 @@ -243,7 +245,7 @@ func TestNameReg(t *testing.T) { entry := getNameRegEntry(t, client, name) assert.Equal(t, data, entry.Data) - assert.Equal(t, user[0].Address, entry.Owner) + assert.Equal(t, users[0].Address, entry.Owner) // update the data as the owner, make sure still there numDesiredBlocks = int64(5) @@ -260,9 +262,9 @@ func TestNameReg(t *testing.T) { assert.Equal(t, updatedData, entry.Data) // try to update as non owner, should fail - tx = txs.NewNameTxWithNonce(user[1].PubKey, name, "never mind", amt, fee, - getNonce(t, client, user[1].Address)+1) - tx.Sign(chainID, user[1]) + tx = txs.NewNameTxWithNonce(users[1].PubKey, name, "never mind", amt, fee, + getNonce(t, client, users[1].Address)+1) + tx.Sign(chainID, users[1]) _, err := broadcastTxAndWaitForBlock(t, client, wsc, tx) assert.Error(t, err, "Expected error when updating someone else's unexpired"+ @@ -277,28 +279,28 @@ func TestNameReg(t *testing.T) { //now the entry should be expired, so we can update as non owner const data2 = "this is not my beautiful house" - tx = txs.NewNameTxWithNonce(user[1].PubKey, name, data2, amt, fee, - getNonce(t, client, user[1].Address)+1) - tx.Sign(chainID, user[1]) + tx = txs.NewNameTxWithNonce(users[1].PubKey, name, data2, amt, fee, + getNonce(t, client, users[1].Address)+1) + tx.Sign(chainID, users[1]) _, err = broadcastTxAndWaitForBlock(t, client, wsc, tx) assert.NoError(t, err, "Should be able to update a previously expired name"+ " registry entry as a different address") mempoolCount = 0 entry = getNameRegEntry(t, client, name) assert.Equal(t, data2, entry.Data) - assert.Equal(t, user[1].Address, entry.Owner) + assert.Equal(t, users[1].Address, entry.Owner) }) } func TestBlockchainInfo(t *testing.T) { wsc := newWSClient() - testWithAllClients(t, func(t *testing.T, clientName string, client rpcclient.Client) { + testWithAllClients(t, func(t *testing.T, clientName string, client burrow_client.RPCClient) { // wait a mimimal number of blocks to ensure that the later query for block // headers has a non-trivial length nBlocks := 4 waitNBlocks(t, wsc, nBlocks) - resp, err := edbcli.BlockchainInfo(client, 0, 0) + resp, err := burrow_client.BlockchainInfo(client, 0, 0) if err != nil { t.Fatalf("Failed to get blockchain info: %v", err) } @@ -310,18 +312,18 @@ func TestBlockchainInfo(t *testing.T) { "Should see at least 4 BlockMetas after waiting for 4 blocks") // For the maximum number (default to 20) of retrieved block headers, // check that they correctly chain to each other. - lastBlockHash := resp.BlockMetas[nMetaBlocks-1].Hash + lastBlockHash := resp.BlockMetas[nMetaBlocks-1].Header.Hash() for i := nMetaBlocks - 2; i >= 0; i-- { // the blockhash in header of height h should be identical to the hash // in the LastBlockID of the header of block height h+1. assert.Equal(t, lastBlockHash, resp.BlockMetas[i].Header.LastBlockID.Hash, "Blockchain should be a hash tree!") - lastBlockHash = resp.BlockMetas[i].Hash + lastBlockHash = resp.BlockMetas[i].Header.Hash() } // Now retrieve only two blockheaders (h=1, and h=2) and check that we got // two results. - resp, err = edbcli.BlockchainInfo(client, 1, 2) + resp, err = burrow_client.BlockchainInfo(client, 1, 2) assert.NoError(t, err) assert.Equal(t, 2, len(resp.BlockMetas), "Should see 2 BlockMetas after extracting 2 blocks") @@ -333,7 +335,7 @@ func TestListUnconfirmedTxs(t *testing.T) { t.Skip("skipping test in short mode.") } wsc := newWSClient() - testWithAllClients(t, func(t *testing.T, clientName string, client rpcclient.Client) { + testWithAllClients(t, func(t *testing.T, clientName string, client burrow_client.RPCClient) { amt, gasLim, fee := int64(1100), int64(1000), int64(1000) code := []byte{0x60, 0x5, 0x60, 0x1, 0x55} // Call with nil address will create a contract @@ -349,7 +351,7 @@ func TestListUnconfirmedTxs(t *testing.T) { go func() { for { - resp, err := edbcli.ListUnconfirmedTxs(client) + resp, err := burrow_client.ListUnconfirmedTxs(client) assert.NoError(t, err) if resp.N > 0 { txChan <- resp.Txs @@ -375,9 +377,9 @@ func TestListUnconfirmedTxs(t *testing.T) { func TestGetBlock(t *testing.T) { wsc := newWSClient() - testWithAllClients(t, func(t *testing.T, clientName string, client rpcclient.Client) { + testWithAllClients(t, func(t *testing.T, clientName string, client burrow_client.RPCClient) { waitNBlocks(t, wsc, 3) - resp, err := edbcli.GetBlock(client, 2) + resp, err := burrow_client.GetBlock(client, 2) assert.NoError(t, err) assert.Equal(t, 2, resp.Block.Height) assert.Equal(t, 2, resp.BlockMeta.Header.Height) @@ -386,9 +388,9 @@ func TestGetBlock(t *testing.T) { func TestListValidators(t *testing.T) { wsc := newWSClient() - testWithAllClients(t, func(t *testing.T, clientName string, client rpcclient.Client) { + testWithAllClients(t, func(t *testing.T, clientName string, client burrow_client.RPCClient) { waitNBlocks(t, wsc, 3) - resp, err := edbcli.ListValidators(client) + resp, err := burrow_client.ListValidators(client) assert.NoError(t, err) assert.Len(t, resp.BondedValidators, 1) validator := resp.BondedValidators[0].(*consensus_types.TendermintValidator) @@ -398,9 +400,9 @@ func TestListValidators(t *testing.T) { func TestDumpConsensusState(t *testing.T) { wsc := newWSClient() - testWithAllClients(t, func(t *testing.T, clientName string, client rpcclient.Client) { + testWithAllClients(t, func(t *testing.T, clientName string, client burrow_client.RPCClient) { waitNBlocks(t, wsc, 3) - resp, err := edbcli.DumpConsensusState(client) + resp, err := burrow_client.DumpConsensusState(client) assert.NoError(t, err) startTime := resp.ConsensusState.StartTime // TODO: uncomment lines involving commitTime when diff --git a/rpc/tendermint/test/shared.go b/rpc/tendermint/test/shared.go index 40cc976d49d4dfdc96fa5b86a3b10ac27f61d1a5..5205e69368d4173a7122796ba396e16eab9a475c 100644 --- a/rpc/tendermint/test/shared.go +++ b/rpc/tendermint/test/shared.go @@ -16,15 +16,21 @@ package test import ( "bytes" + "errors" + "fmt" "hash/fnv" "path" "strconv" "testing" acm "github.com/hyperledger/burrow/account" + "github.com/hyperledger/burrow/config" "github.com/hyperledger/burrow/core" core_types "github.com/hyperledger/burrow/core/types" + genesis "github.com/hyperledger/burrow/genesis" "github.com/hyperledger/burrow/logging/lifecycle" + ptypes "github.com/hyperledger/burrow/permission/types" + "github.com/hyperledger/burrow/rpc/tendermint/client" edbcli "github.com/hyperledger/burrow/rpc/tendermint/client" rpc_core "github.com/hyperledger/burrow/rpc/tendermint/core" rpc_types "github.com/hyperledger/burrow/rpc/tendermint/core/types" @@ -32,37 +38,52 @@ import ( "github.com/hyperledger/burrow/test/fixtures" "github.com/hyperledger/burrow/txs" "github.com/hyperledger/burrow/word256" - - genesis "github.com/hyperledger/burrow/genesis" "github.com/spf13/viper" "github.com/tendermint/go-crypto" rpcclient "github.com/tendermint/go-rpc/client" "github.com/tendermint/tendermint/types" ) +const chainID = "RPC_Test_Chain" + // global variables for use across all tests var ( - config = server.DefaultServerConfig() + serverConfig *server.ServerConfig rootWorkDir string mempoolCount = 0 - chainID string websocketAddr string genesisDoc *genesis.GenesisDoc websocketEndpoint string - user = makeUsers(5) // make keys - jsonRpcClient rpcclient.Client - httpClient rpcclient.Client - clients map[string]rpcclient.Client + users = makeUsers(5) // make keys + jsonRpcClient client.RPCClient + httpClient client.RPCClient + clients map[string]client.RPCClient testCore *core.Core ) // initialize config and create new node func initGlobalVariables(ffs *fixtures.FileFixtures) error { - testConfigFile := ffs.AddFile("config.toml", defaultConfig) + configBytes, err := config.GetConfigurationFileBytes(chainID, + "test_single_node", + "", + "burrow", + true, + "46657", + "burrow serve") + if err != nil { + return err + } + + genesisBytes, err := genesisFileBytesFromUsers(chainID, users) + if err != nil { + return err + } + + testConfigFile := ffs.AddFile("config.toml", string(configBytes)) rootWorkDir = ffs.AddDir("rootWorkDir") rootDataDir := ffs.AddDir("rootDataDir") - genesisFile := ffs.AddFile("rootWorkDir/genesis.json", defaultGenesis) - genesisDoc = genesis.GenesisDocFromJSON([]byte(defaultGenesis)) + genesisFile := ffs.AddFile("rootWorkDir/genesis.json", string(genesisBytes)) + genesisDoc = genesis.GenesisDocFromJSON(genesisBytes) if ffs.Error != nil { return ffs.Error @@ -70,14 +91,19 @@ func initGlobalVariables(ffs *fixtures.FileFixtures) error { testConfig := viper.New() testConfig.SetConfigFile(testConfigFile) - err := testConfig.ReadInConfig() + err = testConfig.ReadInConfig() if err != nil { return err } - chainID = testConfig.GetString("chain.assert_chain_id") - rpcAddr := config.Tendermint.RpcLocalAddress + sconf, err := core.LoadServerConfig(chainID, testConfig) + if err != nil { + return err + } + serverConfig = sconf + + rpcAddr := serverConfig.Tendermint.RpcLocalAddress websocketAddr = rpcAddr websocketEndpoint = "/websocket" @@ -108,31 +134,65 @@ func initGlobalVariables(ffs *fixtures.FileFixtures) error { return err } - jsonRpcClient = rpcclient.NewClientJSONRPC(rpcAddr) - httpClient = rpcclient.NewClientURI(rpcAddr) + jsonRpcClient = rpcclient.NewJSONRPCClient(rpcAddr) + httpClient = rpcclient.NewURIClient(rpcAddr) - clients = map[string]rpcclient.Client{ + clients = map[string]client.RPCClient{ "JSONRPC": jsonRpcClient, "HTTP": httpClient, } return nil } -// deterministic account generation, synced with genesis file in config/tendermint_test/config.go +// Deterministic account generation helper. Pass number of accounts to make func makeUsers(n int) []*acm.PrivAccount { accounts := []*acm.PrivAccount{} for i := 0; i < n; i++ { - secret := ("mysecret" + strconv.Itoa(i)) + secret := "mysecret" + strconv.Itoa(i) user := acm.GenPrivAccountFromSecret(secret) accounts = append(accounts, user) } return accounts } +func genesisFileBytesFromUsers(chainName string, accounts []*acm.PrivAccount) ([]byte, error) { + if len(accounts) < 1 { + return nil, errors.New("Please pass in at least 1 account to be the validator") + } + genesisValidators := make([]*genesis.GenesisValidator, 1) + genesisAccounts := make([]*genesis.GenesisAccount, len(accounts)) + genesisValidators[0] = genesisValidatorFromPrivAccount(accounts[0]) + + for i, acc := range accounts { + genesisAccounts[i] = genesisAccountFromPrivAccount(acc) + } + + return genesis.GenerateGenesisFileBytes(chainName, genesisAccounts, genesisValidators) +} + +func genesisValidatorFromPrivAccount(account *acm.PrivAccount) *genesis.GenesisValidator { + return &genesis.GenesisValidator{ + Amount: 1000000, + Name: fmt.Sprintf("full-account_%X", account.Address), + PubKey: account.PubKey, + UnbondTo: []genesis.BasicAccount{ + { + Address: account.Address, + Amount: 100, + }, + }, + } +} + +func genesisAccountFromPrivAccount(account *acm.PrivAccount) *genesis.GenesisAccount { + return genesis.NewGenesisAccount(account.Address, 100000, + fmt.Sprintf("account_%X", account.Address), &ptypes.DefaultAccountPermissions) +} + func newNode(ready chan error, tmServer chan *rpc_core.TendermintWebsocketServer) { // Run the 'tendermint' rpc server - server, err := testCore.NewGatewayTendermint(config) + server, err := testCore.NewGatewayTendermint(serverConfig) ready <- err tmServer <- server } @@ -140,9 +200,9 @@ func newNode(ready chan error, func saveNewPriv() { // Save new priv_validator file. priv := &types.PrivValidator{ - Address: user[0].Address, - PubKey: crypto.PubKeyEd25519(user[0].PubKey.(crypto.PubKeyEd25519)), - PrivKey: crypto.PrivKeyEd25519(user[0].PrivKey.(crypto.PrivKeyEd25519)), + Address: users[0].Address, + PubKey: crypto.PubKeyEd25519(users[0].PubKey.(crypto.PubKeyEd25519)), + PrivKey: crypto.PrivKeyEd25519(users[0].PrivKey.(crypto.PrivKeyEd25519)), } priv.SetFile(path.Join(rootWorkDir, "priv_validator.json")) priv.Save() @@ -151,36 +211,36 @@ func saveNewPriv() { //------------------------------------------------------------------------------- // some default transaction functions -func makeDefaultSendTx(t *testing.T, client rpcclient.Client, addr []byte, +func makeDefaultSendTx(t *testing.T, client client.RPCClient, addr []byte, amt int64) *txs.SendTx { - nonce := getNonce(t, client, user[0].Address) + nonce := getNonce(t, client, users[0].Address) tx := txs.NewSendTx() - tx.AddInputWithNonce(user[0].PubKey, amt, nonce+1) + tx.AddInputWithNonce(users[0].PubKey, amt, nonce+1) tx.AddOutput(addr, amt) return tx } -func makeDefaultSendTxSigned(t *testing.T, client rpcclient.Client, addr []byte, +func makeDefaultSendTxSigned(t *testing.T, client client.RPCClient, addr []byte, amt int64) *txs.SendTx { tx := makeDefaultSendTx(t, client, addr, amt) - tx.SignInput(chainID, 0, user[0]) + tx.SignInput(chainID, 0, users[0]) return tx } -func makeDefaultCallTx(t *testing.T, client rpcclient.Client, addr, code []byte, amt, gasLim, +func makeDefaultCallTx(t *testing.T, client client.RPCClient, addr, code []byte, amt, gasLim, fee int64) *txs.CallTx { - nonce := getNonce(t, client, user[0].Address) - tx := txs.NewCallTxWithNonce(user[0].PubKey, addr, code, amt, gasLim, fee, + nonce := getNonce(t, client, users[0].Address) + tx := txs.NewCallTxWithNonce(users[0].PubKey, addr, code, amt, gasLim, fee, nonce+1) - tx.Sign(chainID, user[0]) + tx.Sign(chainID, users[0]) return tx } -func makeDefaultNameTx(t *testing.T, client rpcclient.Client, name, value string, amt, +func makeDefaultNameTx(t *testing.T, client client.RPCClient, name, value string, amt, fee int64) *txs.NameTx { - nonce := getNonce(t, client, user[0].Address) - tx := txs.NewNameTxWithNonce(user[0].PubKey, name, value, amt, fee, nonce+1) - tx.Sign(chainID, user[0]) + nonce := getNonce(t, client, users[0].Address) + tx := txs.NewNameTxWithNonce(users[0].PubKey, name, value, amt, fee, nonce+1) + tx.Sign(chainID, users[0]) return tx } @@ -188,7 +248,7 @@ func makeDefaultNameTx(t *testing.T, client rpcclient.Client, name, value string // rpc call wrappers (fail on err) // get an account's nonce -func getNonce(t *testing.T, client rpcclient.Client, addr []byte) int { +func getNonce(t *testing.T, client client.RPCClient, addr []byte) int { ac, err := edbcli.GetAccount(client, addr) if err != nil { t.Fatal(err) @@ -200,7 +260,7 @@ func getNonce(t *testing.T, client rpcclient.Client, addr []byte) int { } // get the account -func getAccount(t *testing.T, client rpcclient.Client, addr []byte) *acm.Account { +func getAccount(t *testing.T, client client.RPCClient, addr []byte) *acm.Account { ac, err := edbcli.GetAccount(client, addr) if err != nil { t.Fatal(err) @@ -209,7 +269,7 @@ func getAccount(t *testing.T, client rpcclient.Client, addr []byte) *acm.Account } // sign transaction -func signTx(t *testing.T, client rpcclient.Client, tx txs.Tx, +func signTx(t *testing.T, client client.RPCClient, tx txs.Tx, privAcc *acm.PrivAccount) txs.Tx { signedTx, err := edbcli.SignTx(client, tx, []*acm.PrivAccount{privAcc}) if err != nil { @@ -219,7 +279,7 @@ func signTx(t *testing.T, client rpcclient.Client, tx txs.Tx, } // broadcast transaction -func broadcastTx(t *testing.T, client rpcclient.Client, tx txs.Tx) txs.Receipt { +func broadcastTx(t *testing.T, client client.RPCClient, tx txs.Tx) txs.Receipt { rec, err := edbcli.BroadcastTx(client, tx) if err != nil { t.Fatal(err) @@ -238,7 +298,7 @@ func dumpStorage(t *testing.T, addr []byte) *rpc_types.ResultDumpStorage { return resp } -func getStorage(t *testing.T, client rpcclient.Client, addr, key []byte) []byte { +func getStorage(t *testing.T, client client.RPCClient, addr, key []byte) []byte { resp, err := edbcli.GetStorage(client, addr, key) if err != nil { t.Fatal(err) @@ -246,7 +306,7 @@ func getStorage(t *testing.T, client rpcclient.Client, addr, key []byte) []byte return resp } -func callCode(t *testing.T, client rpcclient.Client, fromAddress, code, data, +func callCode(t *testing.T, client client.RPCClient, fromAddress, code, data, expected []byte) { resp, err := edbcli.CallCode(client, fromAddress, code, data) if err != nil { @@ -259,7 +319,7 @@ func callCode(t *testing.T, client rpcclient.Client, fromAddress, code, data, } } -func callContract(t *testing.T, client rpcclient.Client, fromAddress, toAddress, +func callContract(t *testing.T, client client.RPCClient, fromAddress, toAddress, data, expected []byte) { resp, err := edbcli.Call(client, fromAddress, toAddress, data) if err != nil { @@ -273,7 +333,7 @@ func callContract(t *testing.T, client rpcclient.Client, fromAddress, toAddress, } // get the namereg entry -func getNameRegEntry(t *testing.T, client rpcclient.Client, name string) *core_types.NameRegEntry { +func getNameRegEntry(t *testing.T, client client.RPCClient, name string) *core_types.NameRegEntry { entry, err := edbcli.GetName(client, name) if err != nil { t.Fatal(err) diff --git a/rpc/tendermint/test/websocket_client_test.go b/rpc/tendermint/test/websocket_client_test.go index 046f13ea44c0d239fcd89655d6cb4c55c6bfca4d..6523290cf08e4fdd225554db299b3a741e96e357 100644 --- a/rpc/tendermint/test/websocket_client_test.go +++ b/rpc/tendermint/test/websocket_client_test.go @@ -93,9 +93,9 @@ func TestWSBlockchainGrowth(t *testing.T) { // send a transaction and validate the events from listening for both sender and receiver func TestWSSend(t *testing.T) { wsc := newWSClient() - toAddr := user[1].Address + toAddr := users[1].Address amt := int64(100) - eidInput := txs.EventStringAccInput(user[0].Address) + eidInput := txs.EventStringAccInput(users[0].Address) eidOutput := txs.EventStringAccOutput(toAddr) subIdInput := subscribeAndGetSubscriptionId(t, wsc, eidInput) subIdOutput := subscribeAndGetSubscriptionId(t, wsc, eidOutput) @@ -119,14 +119,14 @@ func TestWSDoubleFire(t *testing.T) { t.Skip("skipping test in short mode.") } wsc := newWSClient() - eid := txs.EventStringAccInput(user[0].Address) + eid := txs.EventStringAccInput(users[0].Address) subId := subscribeAndGetSubscriptionId(t, wsc, eid) defer func() { unsubscribe(t, wsc, subId) wsc.Stop() }() amt := int64(100) - toAddr := user[1].Address + toAddr := users[1].Address // broadcast the transaction, wait to hear about it waitForEvent(t, wsc, eid, func() { tx := makeDefaultSendTxSigned(t, jsonRpcClient, toAddr, amt) @@ -150,7 +150,7 @@ func TestWSCallWait(t *testing.T) { t.Skip("skipping test in short mode.") } wsc := newWSClient() - eid1 := txs.EventStringAccInput(user[0].Address) + eid1 := txs.EventStringAccInput(users[0].Address) subId1 := subscribeAndGetSubscriptionId(t, wsc, eid1) defer func() { unsubscribe(t, wsc, subId1) @@ -252,7 +252,7 @@ func TestWSCallCall(t *testing.T) { tx := makeDefaultCallTx(t, jsonRpcClient, contractAddr2, nil, amt, gasLim, fee) broadcastTx(t, jsonRpcClient, tx) *txid = txs.TxHash(chainID, tx) - }, unmarshalValidateCall(user[0].Address, returnVal, txid)) + }, unmarshalValidateCall(users[0].Address, returnVal, txid)) } func TestSubscribe(t *testing.T) { diff --git a/rpc/tendermint/test/websocket_helpers.go b/rpc/tendermint/test/websocket_helpers.go index 6cb6a2a4f22b343e7b6b11186ac1ebe540602d2a..acade844555176695120d5cde11a410b149760d3 100644 --- a/rpc/tendermint/test/websocket_helpers.go +++ b/rpc/tendermint/test/websocket_helpers.go @@ -20,13 +20,13 @@ import ( "testing" "time" + burrow_client "github.com/hyperledger/burrow/rpc/tendermint/client" ctypes "github.com/hyperledger/burrow/rpc/tendermint/core/types" "github.com/hyperledger/burrow/txs" - tm_types "github.com/tendermint/tendermint/types" - edbcli "github.com/hyperledger/burrow/rpc/tendermint/client" rpcclient "github.com/tendermint/go-rpc/client" "github.com/tendermint/go-wire" + tm_types "github.com/tendermint/tendermint/types" ) const ( @@ -81,13 +81,13 @@ func unsubscribe(t *testing.T, wsc *rpcclient.WSClient, subscriptionId string) { } // broadcast transaction and wait for new block -func broadcastTxAndWaitForBlock(t *testing.T, client rpcclient.Client, wsc *rpcclient.WSClient, - tx txs.Tx) (txs.Receipt, error) { +func broadcastTxAndWaitForBlock(t *testing.T, client burrow_client.RPCClient, + wsc *rpcclient.WSClient, tx txs.Tx) (txs.Receipt, error) { var rec txs.Receipt var err error runThenWaitForBlock(t, wsc, nextBlockPredicateFn(), func() { - rec, err = edbcli.BroadcastTx(client, tx) + rec, err = burrow_client.BroadcastTx(client, tx) mempoolCount += 1 }) return rec, err @@ -231,14 +231,14 @@ func unmarshalValidateSend(amt int64, return true, fmt.Errorf(data.Exception) } tx := data.Tx.(*txs.SendTx) - if !bytes.Equal(tx.Inputs[0].Address, user[0].Address) { - return true, fmt.Errorf("Senders do not match up! Got %x, expected %x", tx.Inputs[0].Address, user[0].Address) + if !bytes.Equal(tx.Inputs[0].Address, users[0].Address) { + return true, fmt.Errorf("Senders do not match up! Got %x, expected %x", tx.Inputs[0].Address, users[0].Address) } if tx.Inputs[0].Amount != amt { return true, fmt.Errorf("Amt does not match up! Got %d, expected %d", tx.Inputs[0].Amount, amt) } if !bytes.Equal(tx.Outputs[0].Address, toAddr) { - return true, fmt.Errorf("Receivers do not match up! Got %x, expected %x", tx.Outputs[0].Address, user[0].Address) + return true, fmt.Errorf("Receivers do not match up! Got %x, expected %x", tx.Outputs[0].Address, users[0].Address) } return true, nil } @@ -252,9 +252,9 @@ func unmarshalValidateTx(amt int64, return true, fmt.Errorf(data.Exception) } tx := data.Tx.(*txs.CallTx) - if !bytes.Equal(tx.Input.Address, user[0].Address) { + if !bytes.Equal(tx.Input.Address, users[0].Address) { return true, fmt.Errorf("Senders do not match up! Got %x, expected %x", - tx.Input.Address, user[0].Address) + tx.Input.Address, users[0].Address) } if tx.Input.Amount != amt { return true, fmt.Errorf("Amt does not match up! Got %d, expected %d", diff --git a/rpc/v0/rest_server_pipe_test.go b/rpc/v0/rest_server_pipe_test.go index d949c79ebcde608b2bc91b314b5689d0074f5bef..eea240bacccc369191352837beabe6e7e52f432e 100644 --- a/rpc/v0/rest_server_pipe_test.go +++ b/rpc/v0/rest_server_pipe_test.go @@ -237,6 +237,10 @@ func (cons *consensusEngine) PeerConsensusStates() map[string]string { return map[string]string{} } +func (cons *consensusEngine) Stop() bool { + return true +} + // Events type eventer struct { testData *TestData diff --git a/rpc/v0/rest_server_test.go b/rpc/v0/rest_server_test.go index b336d3f8e6fc873884a58bdbca76b76b0480b85c..757993201a2189172be193e72410bd4cfd5ee0e7 100644 --- a/rpc/v0/rest_server_test.go +++ b/rpc/v0/rest_server_test.go @@ -32,9 +32,9 @@ import ( "github.com/hyperledger/burrow/txs" "github.com/gin-gonic/gin" - "github.com/hyperledger/burrow/rpc/v0/shared" "github.com/hyperledger/burrow/logging/lifecycle" logging_types "github.com/hyperledger/burrow/logging/types" + "github.com/hyperledger/burrow/rpc/v0/shared" "github.com/stretchr/testify/suite" "github.com/tendermint/log15" ) diff --git a/version/version.go b/version/version.go index 2df0d9965c4a6ce353e8eaca6ceac078bd1603c2..449d562b15c56cc51c36208032f031397628594d 100644 --- a/version/version.go +++ b/version/version.go @@ -35,38 +35,42 @@ const ( versionPatch = 0 ) -var version *VersionIdentifier +var burrowVersion *VersionIdentifier func init() { - version = New(clientIdentifier, versionMajor, versionMinor, versionPatch) + burrowVersion = New(clientIdentifier, versionMajor, versionMinor, versionPatch) +} + +func GetBurrowVersion() *VersionIdentifier { + return burrowVersion } //------------------------------------------------------------------------------ // versioning globally for burrow and scoped for modules type VersionIdentifier struct { - clientIdentifier string - versionMajor uint8 - versionMinor uint8 - versionPatch uint8 + ClientIdentifier string + MajorVersion uint8 + MinorVersion uint8 + PatchVersion uint8 } func New(client string, major, minor, patch uint8) *VersionIdentifier { - v := new(VersionIdentifier) - v.clientIdentifier = client - v.versionMajor = major - v.versionMinor = minor - v.versionPatch = patch - return v + return &VersionIdentifier{ + ClientIdentifier: client, + MajorVersion: major, + MinorVersion: minor, + PatchVersion: patch, + } } // GetVersionString returns `client-major.minor.patch` for burrow // without a receiver, or for the version called on. // MakeVersionString builds the same version string with provided parameters. -func GetVersionString() string { return version.GetVersionString() } +func GetVersionString() string { return burrowVersion.GetVersionString() } func (v *VersionIdentifier) GetVersionString() string { - return fmt.Sprintf("%s-%d.%d.%d", v.clientIdentifier, v.versionMajor, - v.versionMinor, v.versionPatch) + return fmt.Sprintf("%s-%d.%d.%d", v.ClientIdentifier, v.MajorVersion, + v.MinorVersion, v.PatchVersion) } // note: the arguments are passed in as int (rather than uint8) @@ -82,10 +86,10 @@ func MakeVersionString(client string, major, minor, patch int) string { // without a receiver, or for the version called on. // MakeMinorVersionString builds the same version string with // provided parameters. -func GetMinorVersionString() string { return version.GetVersionString() } +func GetMinorVersionString() string { return burrowVersion.GetVersionString() } func (v *VersionIdentifier) GetMinorVersionString() string { - return fmt.Sprintf("%s-%d.%d", v.clientIdentifier, v.versionMajor, - v.versionMinor) + return fmt.Sprintf("%s-%d.%d", v.ClientIdentifier, v.MajorVersion, + v.MinorVersion) } // note: similar remark applies here on the use of `int` over `uint8` @@ -97,12 +101,12 @@ func MakeMinorVersionString(client string, major, minor, patch int) string { // GetVersion returns a tuple of client, major, minor, and patch as types, // either for burrow without a receiver or the called version structure. func GetVersion() (client string, major, minor, patch uint8) { - return version.GetVersion() + return burrowVersion.GetVersion() } func (version *VersionIdentifier) GetVersion() ( client string, major, minor, patch uint8) { - return version.clientIdentifier, version.versionMajor, version.versionMinor, - version.versionPatch + return version.ClientIdentifier, version.MajorVersion, version.MinorVersion, + version.PatchVersion } //------------------------------------------------------------------------------ @@ -111,14 +115,14 @@ func (version *VersionIdentifier) GetVersion() ( // MatchesMinorVersion matches the client identifier, major and minor version // number of the reference version identifier to be equal with the receivers. func MatchesMinorVersion(referenceVersion *VersionIdentifier) bool { - return version.MatchesMinorVersion(referenceVersion) + return burrowVersion.MatchesMinorVersion(referenceVersion) } func (version *VersionIdentifier) MatchesMinorVersion( referenceVersion *VersionIdentifier) bool { referenceClient, referenceMajor, referenceMinor, _ := referenceVersion.GetVersion() - return version.clientIdentifier == referenceClient && - version.versionMajor == referenceMajor && - version.versionMinor == referenceMinor + return version.ClientIdentifier == referenceClient && + version.MajorVersion == referenceMajor && + version.MinorVersion == referenceMinor } //------------------------------------------------------------------------------