``` bash
$ cd $GOPATH/src/github.com/bytom
$ make install
-$ cd ./cmd/bytom
+$ cd ./cmd/bytomd
$ go build
```
When successfully building the project, the `bytom` and `bytomcli` binary should be present in `cmd/bytom/bytom` and `cmd/bytomcli/bytomcli`, respectively. The next step is to initialize the node:
```bash
-$ cd ./cmd/bytom
-$ ./bytom init --home ./.bytom
+$ cd ./cmd/bytomd
+$ ./bytomd init --home ./.bytom
```
After that, you'll see `.bytom` generated in current directory, then launch the single node:
``` bash
-$ ./bytom node --home ./.bytom
+$ ./bytomd node --home ./.bytom
```
#### Asset issuance test
--- /dev/null
+package flags
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/pkg/errors"
+
+ cfg "github.com/bytom/config"
+ "github.com/tendermint/tmlibs/log"
+)
+
+const (
+ defaultLogLevelKey = "*"
+)
+
+// ParseLogLevel parses complex log level - comma-separated
+// list of module:level pairs with an optional *:level pair (* means
+// all other modules).
+//
+func ParseLogLevel(lvl string, logger log.Logger) (log.Logger, error) {
+ if lvl == "" {
+ return nil, errors.New("Empty log level")
+ }
+
+ l := lvl
+
+ // prefix simple one word levels (e.g. "info") with "*"
+ if !strings.Contains(l, ":") {
+ l = defaultLogLevelKey + ":" + l
+ }
+
+ options := make([]log.Option, 0)
+
+ isDefaultLogLevelSet := false
+ var option log.Option
+ var err error
+
+ list := strings.Split(l, ",")
+ for _, item := range list {
+ moduleAndLevel := strings.Split(item, ":")
+
+ if len(moduleAndLevel) != 2 {
+ return nil, fmt.Errorf("Expected list in a form of \"module:level\" pairs, given pair %s, list %s", item, list)
+ }
+
+ module := moduleAndLevel[0]
+ level := moduleAndLevel[1]
+
+ if module == defaultLogLevelKey {
+ option, err = log.AllowLevel(level)
+ if err != nil {
+ return nil, errors.Wrap(err, fmt.Sprintf("Failed to parse default log level (pair %s, list %s)", item, l))
+ }
+ options = append(options, option)
+ isDefaultLogLevelSet = true
+ } else {
+ switch level {
+ case "debug":
+ option = log.AllowDebugWith("module", module)
+ case "info":
+ option = log.AllowInfoWith("module", module)
+ case "error":
+ option = log.AllowErrorWith("module", module)
+ case "none":
+ option = log.AllowNoneWith("module", module)
+ default:
+ return nil, fmt.Errorf("Expected either \"info\", \"debug\", \"error\" or \"none\" log level, given %s (pair %s, list %s)", level, item, list)
+ }
+ options = append(options, option)
+
+ }
+ }
+
+ // if "*" is not provided, set default global level
+ if !isDefaultLogLevelSet {
+ option, err = log.AllowLevel(cfg.DefaultLogLevel())
+ if err != nil {
+ return nil, err
+ }
+ options = append(options, option)
+ }
+
+ return log.NewFilter(logger, options...), nil
+}
--- /dev/null
+package commands
+
+import (
+ "os"
+
+ "github.com/spf13/cobra"
+
+ "github.com/bytom/types"
+ cmn "github.com/tendermint/tmlibs/common"
+)
+
+var initFilesCmd = &cobra.Command {
+ Use: "init",
+ Short: "Initialize blockchain",
+ Run: initFiles,
+}
+
+func init() {
+ RootCmd.AddCommand(initFilesCmd)
+}
+
+func initFiles(cmd *cobra.Command, args []string) {
+ genFile := config.GenesisFile()
+
+ if _, err := os.Stat(genFile); os.IsNotExist(err) {
+ genDoc := types.GenesisDoc{
+ ChainID: cmn.Fmt("bytom"),
+ PrivateKey: "27F82582AEFAE7AB151CFB01C48BB6C1A0DA78F9BDDA979A9F70A84D074EB07D3B3069C422E19688B45CBFAE7BB009FC0FA1B1EA86593519318B7214853803C8",
+ }
+ genDoc.SaveAs(genFile)
+ }
+
+ logger.Info("Initialized bytom", "genesis", config.GenesisFile())
+}
--- /dev/null
+package commands
+
+import (
+ "os"
+
+ "github.com/spf13/cobra"
+ "github.com/spf13/viper"
+
+ tmflags "github.com/bytom/cmd/bytomd/commands/flags"
+ cfg "github.com/bytom/config"
+ "github.com/tendermint/tmlibs/log"
+)
+
+var (
+ config = cfg.DefaultConfig()
+ logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "main")
+)
+
+func init() {
+ RootCmd.PersistentFlags().String("log_level", config.LogLevel, "Log level")
+}
+
+var RootCmd = &cobra.Command{
+ Use: "bytom",
+ Short: "Multiple asset management.",
+ PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
+ err := viper.Unmarshal(config)
+ if err != nil {
+ return err
+ }
+ config.SetRoot(config.RootDir)
+ cfg.EnsureRoot(config.RootDir)
+ logger, err = tmflags.ParseLogLevel(config.LogLevel, logger)
+ if err != nil {
+ return err
+ }
+ return nil
+ },
+}
--- /dev/null
+package commands
+
+import (
+ "fmt"
+ "io/ioutil"
+
+ "github.com/spf13/cobra"
+
+ "github.com/bytom/node"
+ "github.com/bytom/types"
+ cmn "github.com/tendermint/tmlibs/common"
+)
+
+var runNodeCmd = &cobra.Command{
+ Use: "node",
+ Short: "Run the p2p node",
+ RunE: runNode,
+}
+
+func init() {
+ // p2p flags
+ runNodeCmd.Flags().String("p2p.laddr", config.P2P.ListenAddress, "Node listen address. (0.0.0.0:0 means any interface, any port)")
+ runNodeCmd.Flags().String("p2p.seeds", config.P2P.Seeds, "Comma delimited host:port seed nodes")
+ runNodeCmd.Flags().Bool("p2p.skip_upnp", config.P2P.SkipUPNP, "Skip UPNP configuration")
+ runNodeCmd.Flags().Bool("p2p.pex", config.P2P.PexReactor, "Enable Peer-Exchange (dev feature)")
+
+ RootCmd.AddCommand(runNodeCmd)
+}
+
+func runNode(cmd *cobra.Command, args []string) error {
+ genDocFile := config.GenesisFile()
+ if cmn.FileExists(genDocFile) {
+ jsonBlob, err := ioutil.ReadFile(genDocFile)
+ if err != nil {
+ return fmt.Errorf("Couldn't read GenesisDoc file: %v", err)
+ }
+ genDoc, err := types.GenesisDocFromJSON(jsonBlob)
+ if err != nil {
+ return fmt.Errorf("Error reading GenesisDoc: %v", err)
+ }
+ if genDoc.ChainID == "" {
+ return fmt.Errorf("Genesis doc %v must include non-empty chain_id", genDocFile)
+ }
+ config.ChainID = genDoc.ChainID
+ config.PrivateKey = genDoc.PrivateKey
+ config.Time = genDoc.GenesisTime
+ } else {
+ return fmt.Errorf("not find genesis.json")
+ }
+
+ // Create & start node
+ n := node.NewNodeDefault(config, logger.With("module", "node_p2p"))
+ if _, err := n.Start(); err != nil {
+ return fmt.Errorf("Failed to start node: %v", err)
+ } else {
+ logger.Info("Started node", "nodeInfo", n.Switch().NodeInfo())
+ }
+
+ // Trap signal, run forever.
+ n.RunForever()
+
+ return nil
+}
--- /dev/null
+package commands
+
+import (
+ "fmt"
+
+ "github.com/spf13/cobra"
+
+ "github.com/bytom/version"
+)
+
+var versionCmd = &cobra.Command{
+ Use: "version",
+ Short: "Show version info",
+ Run: func(cmd *cobra.Command, args []string) {
+ fmt.Println(version.Version)
+ },
+}
+
+func init() {
+ RootCmd.AddCommand(versionCmd)
+}
--- /dev/null
+package main
+
+import (
+ "os"
+
+ "github.com/bytom/cmd/bytomd/commands"
+ "github.com/tendermint/tmlibs/cli"
+)
+
+func main() {
+ cmd := cli.PrepareBaseCmd(commands.RootCmd, "TM", os.ExpandEnv("./.bytomd"))
+ cmd.Execute()
+}