package commands
import (
+ "encoding/hex"
+ "io/ioutil"
"os"
"path"
"github.com/spf13/cobra"
cfg "github.com/vapor/config"
+ "github.com/vapor/crypto/ed25519/chainkd"
)
var initFilesCmd = &cobra.Command{
}
func init() {
- initFilesCmd.Flags().String("chain_id", config.ChainID, "Select [mainnet] or [testnet] or [solonet] or [vapor]")
+ initFilesCmd.Flags().String("chain_id", config.ChainID, "Select [vapor] or [solonet]")
RootCmd.AddCommand(initFilesCmd)
}
func initFiles(cmd *cobra.Command, args []string) {
configFilePath := path.Join(config.RootDir, "config.toml")
if _, err := os.Stat(configFilePath); !os.IsNotExist(err) {
- log.WithFields(log.Fields{"module": logModule, "config": configFilePath}).Info("Already exists config file.")
- return
+ log.WithFields(log.Fields{"module": logModule, "config": configFilePath}).Panic("Already exists config file.")
}
switch config.ChainID {
- case "mainnet", "testnet", "vapor":
+ case "vapor":
cfg.EnsureRoot(config.RootDir, config.ChainID)
default:
cfg.EnsureRoot(config.RootDir, "solonet")
fedFile := config.FederationFile()
if _, err := os.Stat(fedFile); !os.IsNotExist(err) {
- log.WithFields(log.Fields{"module": logModule, "config": fedFile}).Info("Already exists federation file.")
- return
+ log.WithFields(log.Fields{"module": logModule, "config": fedFile}).Panic("Already exists federation file.")
}
if err := cfg.ExportFederationFile(fedFile, config); err != nil {
- log.WithFields(log.Fields{"module": logModule, "config": fedFile, "error": err}).Info("exportFederationFile failed.")
- return
+ log.WithFields(log.Fields{"module": logModule, "config": fedFile, "error": err}).Panic("exportFederationFile failed.")
+ }
+
+ keyFilePath := path.Join(config.RootDir, config.PrivateKeyFile)
+ if _, err := os.Stat(keyFilePath); os.IsNotExist(err) {
+ xprv, err := chainkd.NewXPrv(nil)
+ if err != nil {
+ log.WithFields(log.Fields{"module": logModule, "err": err}).Panic("fail on generate private key")
+ }
+
+ xprvStr := hex.EncodeToString(xprv[:])
+ if err := ioutil.WriteFile(keyFilePath, []byte(xprvStr), 0600); err != nil {
+ log.WithFields(log.Fields{"module": logModule, "err": err}).Panic("fail on save private key")
+ }
}
log.WithFields(log.Fields{"module": logModule, "config": configFilePath}).Info("Initialized bytom")
// 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().String("p2p.node_key", config.P2P.PrivateKey, "Node key for p2p communication")
runNodeCmd.Flags().Bool("p2p.skip_upnp", config.P2P.SkipUPNP, "Skip UPNP configuration")
runNodeCmd.Flags().Bool("p2p.lan_discoverable", config.P2P.LANDiscover, "Whether the node can be discovered by nodes in the LAN")
runNodeCmd.Flags().Int("p2p.max_num_peers", config.P2P.MaxNumPeers, "Set max num peers")
package config
import (
+ "encoding/hex"
"io"
- "io/ioutil"
"os"
"os/user"
"path/filepath"
log "github.com/sirupsen/logrus"
- "github.com/vapor/crypto/ed25519"
"github.com/vapor/crypto/ed25519/chainkd"
)
// NodeKey retrieves the currently configured private key of the node, checking
// first any manually set key, falling back to the one found in the configured
// data folder. If no key can be found, a new one is generated.
-func (cfg *Config) NodeKey() (string, error) {
- // Use any specifically configured key.
- if cfg.P2P.PrivateKey != "" {
- return cfg.P2P.PrivateKey, nil
+func (cfg *Config) PrivateKey() *chainkd.XPrv {
+ if cfg.XPrv != nil {
+ return cfg.XPrv
}
- keyFile := rootify(cfg.P2P.NodeKeyFile, cfg.BaseConfig.RootDir)
- buf := make([]byte, ed25519.PrivateKeySize*2)
- fd, err := os.Open(keyFile)
- defer fd.Close()
- if err == nil {
- if _, err = io.ReadFull(fd, buf); err == nil {
- return string(buf), nil
- }
+ filePath := rootify(cfg.PrivateKeyFile, cfg.BaseConfig.RootDir)
+ fildReader, err := os.Open(filePath)
+ if err != nil {
+ log.WithField("err", err).Panic("fail on open private key file")
}
- log.WithField("err", err).Warning("key file access failed")
- _, privKey, err := ed25519.GenerateKey(nil)
- if err != nil {
- return "", err
+ defer fildReader.Close()
+ buf := make([]byte, 128)
+ if _, err = io.ReadFull(fildReader, buf); err != nil {
+ log.WithField("err", err).Panic("fail on read private key file")
}
- if err = ioutil.WriteFile(keyFile, []byte(privKey.String()), 0600); err != nil {
- return "", err
+ var xprv chainkd.XPrv
+ if _, err := hex.Decode(xprv[:], buf); err != nil {
+ log.WithField("err", err).Panic("fail on decode private key")
}
- return privKey.String(), nil
+
+ cfg.XPrv = &xprv
+ xpub := cfg.XPrv.XPub()
+ cfg.XPub = &xpub
+ return cfg.XPrv
}
//-----------------------------------------------------------------------------
// log file name
LogFile string `mapstructure:"log_file"`
- // Cipher Service Provider
- // CipherServiceProvider string `mapstructure:"csp"`
+ PrivateKeyFile string `mapstructure:"private_key_file"`
+ XPrv *chainkd.XPrv
+ XPub *chainkd.XPub
// Federation file name
FederationFileName string `mapstructure:"federation_file"`
DBBackend: "leveldb",
DBPath: "data",
KeysPath: "keystore",
+ PrivateKeyFile: "node_key.txt",
FederationFileName: "federation.json",
}
}
type P2PConfig struct {
ListenAddress string `mapstructure:"laddr"`
Seeds string `mapstructure:"seeds"`
- PrivateKey string `mapstructure:"node_key"`
- NodeKeyFile string `mapstructure:"node_key_file"`
SkipUPNP bool `mapstructure:"skip_upnp"`
LANDiscover bool `mapstructure:"lan_discoverable"`
MaxNumPeers int `mapstructure:"max_num_peers"`
func DefaultP2PConfig() *P2PConfig {
return &P2PConfig{
ListenAddress: "tcp://0.0.0.0:46656",
- NodeKeyFile: "nodekey",
SkipUPNP: false,
LANDiscover: true,
MaxNumPeers: 50,
xpub("7f23aae65ee4307c38d342699e328f21834488e18191ebd66823d220b5a58303496c9d09731784372bade78d5e9a4a6249b2cfe2e3a85464e5a4017aa5611e47"),
xpub("585e20143db413e45fbc82f03cb61f177e9916ef1df0012daa8cbf6dbb1025ce8f98e51ae319327b63505b64fdbbf6d36ef916d79e6dd67d51b0bfe76fe544c5"),
xpub("b58170b51ca61604028ba1cb412377dfc2bc6567c0afc84c83aae1c0c297d0227ccf568561df70851f4144bbf069b525129f2434133c145e35949375b22a6c9d"),
- xpub("983705ae71949c1a5d0fcf953658dd9ecc549f02c63e197b4d087ae31148097ece816bbc60d9012c316139fc550fa0f4b00beb0887f6b152f7a69bc8f392b9fa"),
- xpub("d72fb92fa13bf3e0deb39de3a47c8d6eef5584719f7877c82a4c009f78fddf924d9706d48f15b2c782ec80b6bdd621a1f7ba2a0044b0e6f92245de9436885cb9"),
- xpub("6798460919e8dc7095ee8b9f9d65033ef3da8c2334813149da5a1e52e9c6da07ba7d0e7379baaa0c8bdcb21890a54e6b7290bee077c645ee4b74b0c1ae9da59a"),
},
- Quorum: 4,
+ Quorum: 2,
}
}
}
switch runtime.GOOS {
case "darwin":
- // In order to be compatible with old data path,
- // copy the data from the old path to the new path
- oldPath := filepath.Join(home, "Library", "Vapor")
- newPath := filepath.Join(home, "Library", "Application Support", "Vapor")
- if !isFolderNotExists(oldPath) && isFolderNotExists(newPath) {
- if err := os.Rename(oldPath, newPath); err != nil {
- log.Errorf("DefaultDataDir: %v", err)
- return oldPath
- }
- }
- return newPath
+ return filepath.Join(home, "Library", "Application Support", "Vapor")
case "windows":
return filepath.Join(home, "AppData", "Roaming", "Vapor")
default:
package config
import (
- "io/ioutil"
- "os"
- "strings"
"testing"
"github.com/stretchr/testify/assert"
assert.Equal("/opt/data", cfg.DBDir())
}
-
-func TestNodeKey(t *testing.T) {
- tmpDir, err := ioutil.TempDir(".", "")
- if err != nil {
- t.Fatalf("failed to create temporary data folder: %v", err)
- }
- defer os.RemoveAll(tmpDir)
- config := DefaultConfig()
- config.BaseConfig.RootDir = tmpDir
-
- config.P2P.PrivateKey = "0fcbd0be11e35c35c41c686b7ca597bbcf8ecb78e320d01a93349c8ce9420ea4f26d0fbe651bb2c248d6727801329b589ed19e384c9e906d1da4ab2360558bc0"
- privKey, err := config.NodeKey()
- if err != nil {
- t.Fatal("test node key error:", err)
- }
-
- if strings.Compare(privKey, config.P2P.PrivateKey) != 0 {
- t.Fatal("test node key error. want:", config.P2P.PrivateKey, "got:", privKey)
- }
-
- config.P2P.PrivateKey = ""
- writePrivKey, err := config.NodeKey()
- if err != nil {
- t.Fatal("test node key error:", err)
- }
-
- readPrivKey, err := config.NodeKey()
- if err != nil {
- t.Fatal("test node key error:", err)
- }
-
- if strings.Compare(writePrivKey, readPrivKey) != 0 {
- t.Fatal("test node key error. write:", writePrivKey, "read:", readPrivKey)
- }
-}
)
func FederationProgrom(c *Config) []byte {
- pubKeys := chainkd.XPubKeys(c.Federation.Xpubs)
- fedpegScript, err := vmutil.P2SPMultiSigProgram(pubKeys, c.Federation.Quorum)
+ xpubs := c.Federation.Xpubs
+ fedpegScript, err := vmutil.P2SPMultiSigProgram(chainkd.XPubKeys(xpubs), c.Federation.Quorum)
if err != nil {
- log.Panicf("Failed generate federation scirpt for federation")
+ log.Panicf("Failed generate federation scirpt for federation: " + err.Error())
}
scriptHash := crypto.Sha256(fedpegScript)
+++ /dev/null
-package config
-
-/*func TestGenerateGenesisBlock(t *testing.T) {
- block := GenerateGenesisBlock()
- nonce := block.Nonce
- for {
- hash := block.Hash()
- if difficulty.CheckProofOfWork(&hash, consensus.InitialSeed, block.Bits) {
- break
- }
- block.Nonce++
- }
- if block.Nonce != nonce {
- t.Errorf("correct nonce is %d, but get %d", block.Nonce, nonce)
- }
-}*/
moniker = ""
`
-var mainNetConfigTmpl = `chain_id = "mainnet"
-[p2p]
-laddr = "tcp://0.0.0.0:46657"
-seeds = "45.79.213.28:46657,198.74.61.131:46657,212.111.41.245:46657,47.100.214.154:46657,47.100.109.199:46657,47.100.105.165:46657"
-`
-
-var testNetConfigTmpl = `chain_id = "wisdom"
-[p2p]
-laddr = "tcp://0.0.0.0:46656"
-seeds = "52.83.107.224:46656,52.83.251.197:46656"
-`
-
var soloNetConfigTmpl = `chain_id = "solonet"
[p2p]
laddr = "tcp://0.0.0.0:46658"
// Select network seeds to merge a new string.
func selectNetwork(network string) string {
switch network {
- case "mainnet":
- return defaultConfigTmpl + mainNetConfigTmpl
- case "testnet":
- return defaultConfigTmpl + testNetConfigTmpl
case "vapor":
return defaultConfigTmpl + vaporNetConfigTmpl
default:
+++ /dev/null
-package federation
-
-import (
- "encoding/json"
- "errors"
-
- log "github.com/sirupsen/logrus"
-
- "github.com/vapor/crypto/ed25519"
- "github.com/vapor/crypto/ed25519/chainkd"
- "github.com/vapor/protocol/vm/vmutil"
-)
-
-const fedCfgJson = `
-{
- "xpubs" : [
- "7f23aae65ee4307c38d342699e328f21834488e18191ebd66823d220b5a58303496c9d09731784372bade78d5e9a4a6249b2cfe2e3a85464e5a4017aa5611e47",
- "585e20143db413e45fbc82f03cb61f177e9916ef1df0012daa8cbf6dbb1025ce8f98e51ae319327b63505b64fdbbf6d36ef916d79e6dd67d51b0bfe76fe544c5",
- "b58170b51ca61604028ba1cb412377dfc2bc6567c0afc84c83aae1c0c297d0227ccf568561df70851f4144bbf069b525129f2434133c145e35949375b22a6c9d",
- "983705ae71949c1a5d0fcf953658dd9ecc549f02c63e197b4d087ae31148097ece816bbc60d9012c316139fc550fa0f4b00beb0887f6b152f7a69bc8f392b9fa",
- "d72fb92fa13bf3e0deb39de3a47c8d6eef5584719f7877c82a4c009f78fddf924d9706d48f15b2c782ec80b6bdd621a1f7ba2a0044b0e6f92245de9436885cb9",
- "6798460919e8dc7095ee8b9f9d65033ef3da8c2334813149da5a1e52e9c6da07ba7d0e7379baaa0c8bdcb21890a54e6b7290bee077c645ee4b74b0c1ae9da59a"
- ],
- "quorum" : 4
-}
-`
-
-type federation struct {
- XPubs []chainkd.XPub `json:"xpubs"`
- Quorum int `json:"quorum"`
- ControlProgram []byte
-}
-
-func parseFedConfig() *federation {
- fed := &federation{}
- if err := json.Unmarshal([]byte(fedCfgJson), fed); err != nil {
- log.Fatalln("invalid federation config json")
- }
-
- return fed
-}
-
-// CheckFedConfig checks the high-level rule for federation config, whereas
-// signers.Create checks the low-level rule
-func CheckFedConfig() error {
- fed := parseFedConfig()
- if len(fed.XPubs) <= 1 {
- return errors.New("federation should have more than 1 member")
- }
- if fed.Quorum < 1 {
- return errors.New("federation quorum should be >= 1")
- }
-
- return nil
-}
-
-func GetFederation() *federation {
- fed := parseFedConfig()
- PublicKeys := chainkd.XPubKeys(fed.XPubs)
- if controlProgram, err := fed.buildPegInControlProgram(PublicKeys); err == nil {
- fed.ControlProgram = controlProgram
- } else {
- log.Fatalf("fail to build peg-in script: %v", err)
- }
-
- return fed
-}
-
-func (f *federation) buildPegInControlProgram(pubkeys []ed25519.PublicKey) (program []byte, err error) {
- controlProg, err := vmutil.P2SPMultiSigProgram(pubkeys, f.Quorum)
- if err != nil {
- return nil, err
- }
-
- builder := vmutil.NewBuilder()
- builder.AddRawBytes(controlProg)
- return builder.Build()
-}
V3: binary.BigEndian.Uint64([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}),
}
-// InitialSeed is SHA3-256 of Byte[0^32]
-var InitialSeed = &bc.Hash{
- V0: uint64(11412844483649490393),
- V1: uint64(4614157290180302959),
- V2: uint64(1780246333311066183),
- V3: uint64(9357197556716379726),
-}
-
// BTMDefinitionMap is the ....
var BTMDefinitionMap = map[string]interface{}{
"name": BTMAlias,
log.WithFields(log.Fields{
"module": logModule,
+ "pubkey": config.PrivateKey().XPub(),
"fed_xpubs": config.Federation.Xpubs,
"fed_quorum": config.Federation.Quorum,
"fed_controlprogram": hex.EncodeToString(cfg.FederationProgrom(config)),
import (
"encoding/binary"
- "encoding/hex"
"encoding/json"
"fmt"
"net"
netID := binary.BigEndian.Uint64(h[:8])
blacklistDB := dbm.NewDB("trusthistory", config.DBBackend, config.DBDir())
- config.P2P.PrivateKey, err = config.NodeKey()
- if err != nil {
- return nil, err
- }
-
- bytes, err := hex.DecodeString(config.P2P.PrivateKey)
- if err != nil {
- return nil, err
- }
+ bytes := config.PrivateKey()[:]
var newKey [64]byte
copy(newKey[:], bytes)
privKey := crypto.PrivKeyEd25519(newKey)
cfg := *testCfg
cfg.P2P.ListenAddress = "127.0.1.1:0"
swPrivKey := crypto.GenPrivKeyEd25519()
- cfg.P2P.PrivateKey = swPrivKey.String()
+ //cfg.P2P.PrivateKey = swPrivKey.String()
s1 := MakeSwitch(&cfg, testDB, swPrivKey, initSwitchFunc)
s1.Start()
defer s1.Stop()
cfg := *testCfg
cfg.P2P.ListenAddress = "127.0.1.1:0"
swPrivKey := crypto.GenPrivKeyEd25519()
- cfg.P2P.PrivateKey = swPrivKey.String()
+ //cfg.P2P.PrivateKey = swPrivKey.String()
s1 := MakeSwitch(&cfg, testDB, swPrivKey, initSwitchFunc)
s1.Start()
defer s1.Stop()
cfg := *testCfg
cfg.P2P.ListenAddress = "127.0.1.1:0"
swPrivKey := crypto.GenPrivKeyEd25519()
- cfg.P2P.PrivateKey = swPrivKey.String()
+ //cfg.P2P.PrivateKey = swPrivKey.String()
s1 := MakeSwitch(&cfg, testDB, swPrivKey, initSwitchFunc)
s1.Start()
defer s1.Stop()
cfg := *testCfg
cfg.P2P.ListenAddress = "127.0.1.1:0"
swPrivKey := crypto.GenPrivKeyEd25519()
- cfg.P2P.PrivateKey = swPrivKey.String()
+ //cfg.P2P.PrivateKey = swPrivKey.String()
s1 := MakeSwitch(&cfg, testDB, swPrivKey, initSwitchFunc)
s1.Start()
defer s1.Stop()
cfg.P2P.MaxNumPeers = 2
cfg.P2P.ListenAddress = "127.0.1.1:0"
swPrivKey := crypto.GenPrivKeyEd25519()
- cfg.P2P.PrivateKey = swPrivKey.String()
+ //cfg.P2P.PrivateKey = swPrivKey.String()
s1 := MakeSwitch(&cfg, testDB, swPrivKey, initSwitchFunc)
s1.Start()
defer s1.Stop()
inpCfg := *testCfg
inpPrivKey := crypto.GenPrivKeyEd25519()
- inpCfg.P2P.PrivateKey = inpPrivKey.String()
+ //inpCfg.P2P.PrivateKey = inpPrivKey.String()
inp := &inboundPeer{PrivKey: inpPrivKey, config: &inpCfg}
addr := NewNetAddress(s1.listeners[0].(*DefaultListener).NetListener().Addr())
if err != nil {
rpCfg := *testCfg
rpPrivKey := crypto.GenPrivKeyEd25519()
- rpCfg.P2P.PrivateKey = rpPrivKey.String()
+ //rpCfg.P2P.PrivateKey = rpPrivKey.String()
rp := &remotePeer{PrivKey: rpPrivKey, Config: &rpCfg}
rp.Start()
defer rp.Stop()
inp2Cfg := *testCfg
inp2PrivKey := crypto.GenPrivKeyEd25519()
- inp2Cfg.P2P.PrivateKey = inp2PrivKey.String()
+ //inp2Cfg.P2P.PrivateKey = inp2PrivKey.String()
inp2 := &inboundPeer{PrivKey: inp2PrivKey, config: &inp2Cfg}
go inp2.dial(addr)
cfg.P2P.MaxNumPeers = 2
cfg.P2P.ListenAddress = "127.0.1.1:0"
swPrivKey := crypto.GenPrivKeyEd25519()
- cfg.P2P.PrivateKey = swPrivKey.String()
+ //cfg.P2P.PrivateKey = swPrivKey.String()
s1 := MakeSwitch(&cfg, testDB, swPrivKey, initSwitchFunc)
s1.Start()
defer s1.Stop()
inpCfg := *testCfg
inpPrivKey := crypto.GenPrivKeyEd25519()
- inpCfg.P2P.PrivateKey = inpPrivKey.String()
+ //inpCfg.P2P.PrivateKey = inpPrivKey.String()
inp := &inboundPeer{PrivKey: inpPrivKey, config: &inpCfg}
addr := NewNetAddress(s1.listeners[0].(*DefaultListener).NetListener().Addr())
if err != nil {
rpCfg := *testCfg
rpPrivKey := crypto.GenPrivKeyEd25519()
- rpCfg.P2P.PrivateKey = rpPrivKey.String()
+ //rpCfg.P2P.PrivateKey = rpPrivKey.String()
rp := &remotePeer{PrivKey: rpPrivKey, Config: &rpCfg}
rp.Start()
defer rp.Stop()
package blockproposer
import (
+ "encoding/hex"
"sync"
"time"
- "encoding/hex"
log "github.com/sirupsen/logrus"
"github.com/vapor/account"
+ "github.com/vapor/config"
"github.com/vapor/event"
"github.com/vapor/proposal"
"github.com/vapor/protocol"
bestBlockHeader := b.chain.BestBlockHeader()
bestBlockHash := bestBlockHeader.Hash()
- var pubKey []byte
- timeStart, timeEnd, err := b.chain.GetBBFT().NextLeaderTimeRange(pubKey, &bestBlockHash)
+ pubKey := config.CommonConfig.PrivateKey().XPub()
+ timeStart, timeEnd, err := b.chain.GetBBFT().NextLeaderTimeRange(pubKey[:], &bestBlockHash)
if err != nil {
- log.WithFields(log.Fields{"module": logModule, "error": err, "pubKey": hex.EncodeToString(pubKey)}).Debug("fail on get next leader time range")
+ log.WithFields(log.Fields{"module": logModule, "error": err, "pubKey": hex.EncodeToString(pubKey[:])}).Debug("fail on get next leader time range")
continue
}
timeStart = now
}
- time.Sleep(time.Millisecond * time.Duration(timeStart - now))
+ time.Sleep(time.Millisecond * time.Duration(timeStart-now))
count := 0
for now = timeStart; now < timeEnd && count < protocol.BlockNumEachNode; now = uint64(time.Now().UnixNano() / 1e6) {
"github.com/golang/groupcache/lru"
log "github.com/sirupsen/logrus"
+ "github.com/vapor/config"
"github.com/vapor/crypto/ed25519"
- "github.com/vapor/crypto/ed25519/chainkd"
"github.com/vapor/errors"
"github.com/vapor/event"
"github.com/vapor/protocol/bc"
// SignBlock signing the block if current node is consensus node
func (b *bbft) SignBlock(block *types.Block) ([]byte, error) {
- var xprv chainkd.XPrv
+ xprv := config.CommonConfig.PrivateKey()
xpub := [64]byte(xprv.XPub())
blockHash := block.Hash()
node, err := b.consensusNodeManager.getConsensusNode(&blockHash, hex.EncodeToString(xpub[:]))
"sort"
"time"
+ "github.com/vapor/config"
"github.com/vapor/errors"
"github.com/vapor/math/checked"
"github.com/vapor/protocol/bc"
}
seq := blockNode.Height / roundVoteBlockNums
+ if seq == 0 {
+ return initVoteResult(), nil
+ }
+
voteResult, err := c.store.GetVoteResult(seq)
if err != nil {
// fail to find vote result, try to construct
voteResult.Finalized = false
return nil
}
+
+func initVoteResult() map[string]*consensusNode {
+ voteResult := map[string]*consensusNode{}
+ for i, pubkey := range config.CommonConfig.Federation.Xpubs {
+ pubkeyStr := pubkey.String()
+ voteResult[pubkeyStr] = &consensusNode{pubkey: pubkeyStr, voteNum: 0, order: uint64(i)}
+ }
+ return voteResult
+}