diff --git a/cmd/tendermint/main.go b/cmd/tendermint/main.go index 6ccbc4d11..81c55f321 100644 --- a/cmd/tendermint/main.go +++ b/cmd/tendermint/main.go @@ -8,6 +8,7 @@ import ( cfg "github.com/tendermint/go-config" tmcfg "github.com/tendermint/tendermint/config/tendermint" "github.com/tendermint/tendermint/node" + "github.com/tendermint/tendermint/version" ) func main() { @@ -45,7 +46,7 @@ Commands: case "unsafe_reset_priv_validator": reset_priv_validator() case "version": - fmt.Println(node.Version) + fmt.Println(version.Version) default: Exit(Fmt("Unknown command %v\n", args[0])) } diff --git a/consensus/state.go b/consensus/state.go index 721f71574..d139d04b4 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -1097,6 +1097,7 @@ func (cs *ConsensusState) tryFinalizeCommit(height int) { return } if !cs.ProposalBlock.HashesTo(hash) { + // TODO: this happens every time if we're not a validator (ugly logs) log.Warn("Attempt to finalize failed. We don't have the commit block.") return } diff --git a/node/node.go b/node/node.go index ab06d48c9..bda20084e 100644 --- a/node/node.go +++ b/node/node.go @@ -3,7 +3,6 @@ package node import ( "bytes" "io/ioutil" - "math/rand" "net" "net/http" "strings" @@ -22,9 +21,10 @@ import ( "github.com/tendermint/tendermint/consensus" mempl "github.com/tendermint/tendermint/mempool" "github.com/tendermint/tendermint/proxy" - "github.com/tendermint/tendermint/rpc/core" + rpccore "github.com/tendermint/tendermint/rpc/core" sm "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/types" + "github.com/tendermint/tendermint/version" "github.com/tendermint/tmsp/example/golang" ) @@ -145,47 +145,21 @@ func (n *Node) AddListener(l p2p.Listener) { n.sw.AddListener(l) } -// Dial a list of seeds in random order -// Spawns a go routine for each dial -func (n *Node) DialSeed() { - // permute the list, dial them in random order. - seeds := strings.Split(config.GetString("seeds"), ",") - perm := rand.Perm(len(seeds)) - for i := 0; i < len(perm); i++ { - go func(i int) { - time.Sleep(time.Duration(rand.Int63n(3000)) * time.Millisecond) - j := perm[i] - addr := p2p.NewNetAddressString(seeds[j]) - n.dialSeed(addr) - }(i) - } -} - -func (n *Node) dialSeed(addr *p2p.NetAddress) { - peer, err := n.sw.DialPeerWithAddress(addr) - if err != nil { - log.Error("Error dialing seed", "error", err) - return - } else { - log.Notice("Connected to seed", "peer", peer) - } -} - func (n *Node) StartRPC() (net.Listener, error) { - core.SetBlockStore(n.blockStore) - core.SetConsensusState(n.consensusState) - core.SetConsensusReactor(n.consensusReactor) - core.SetMempoolReactor(n.mempoolReactor) - core.SetSwitch(n.sw) - core.SetPrivValidator(n.privValidator) - core.SetGenesisDoc(n.genesisDoc) + rpccore.SetBlockStore(n.blockStore) + rpccore.SetConsensusState(n.consensusState) + rpccore.SetConsensusReactor(n.consensusReactor) + rpccore.SetMempoolReactor(n.mempoolReactor) + rpccore.SetSwitch(n.sw) + rpccore.SetPrivValidator(n.privValidator) + rpccore.SetGenesisDoc(n.genesisDoc) listenAddr := config.GetString("rpc_laddr") mux := http.NewServeMux() - wm := rpcserver.NewWebsocketManager(core.Routes, n.evsw) + wm := rpcserver.NewWebsocketManager(rpccore.Routes, n.evsw) mux.HandleFunc("/websocket", wm.WebsocketHandler) - rpcserver.RegisterRPCFuncs(mux, core.Routes) + rpcserver.RegisterRPCFuncs(mux, rpccore.Routes) return rpcserver.StartHTTPServer(listenAddr, mux) } @@ -215,11 +189,11 @@ func makeNodeInfo(sw *p2p.Switch, privKey crypto.PrivKeyEd25519) *p2p.NodeInfo { PubKey: privKey.PubKey().(crypto.PubKeyEd25519), Moniker: config.GetString("moniker"), Network: config.GetString("chain_id"), - Version: Version, + Version: version.Version, Other: []string{ - Fmt("p2p_version=%v", p2p.Version), - Fmt("rpc_version=%v", rpc.Version), Fmt("wire_version=%v", wire.Version), + Fmt("p2p_version=%v", p2p.Version), + Fmt("rpc_version=%v/%v", rpc.Version, rpccore.Version), }, } @@ -291,7 +265,8 @@ func RunNode() { // If seedNode is provided by config, dial out. if config.GetString("seeds") != "" { - n.DialSeed() + seeds := strings.Split(config.GetString("seeds"), ",") + n.sw.DialSeeds(seeds) } // Run the RPC server. diff --git a/node/version.go b/node/version.go deleted file mode 100644 index 6b981175a..000000000 --- a/node/version.go +++ /dev/null @@ -1,6 +0,0 @@ -package node - -// Major: alpha -// Minor: encrypted p2p! -// Patch: New block pool logic -const Version = "0.5.2" diff --git a/rpc/core/net.go b/rpc/core/net.go index 76c75c98b..3cf1fd9e3 100644 --- a/rpc/core/net.go +++ b/rpc/core/net.go @@ -1,6 +1,8 @@ package core import ( + "fmt" + ctypes "github.com/tendermint/tendermint/rpc/core/types" ) @@ -29,6 +31,19 @@ func NetInfo() (*ctypes.ResultNetInfo, error) { //----------------------------------------------------------------------------- +// Dial given list of seeds if we have no outbound peers +func DialSeeds(seeds []string) (*ctypes.ResultDialSeeds, error) { + outbound, _, _ := p2pSwitch.NumPeers() + if outbound != 0 { + return nil, fmt.Errorf("Already have some outbound peers") + } + // starts go routines to dial each seed after random delays + p2pSwitch.DialSeeds(seeds) + return &ctypes.ResultDialSeeds{}, nil +} + +//----------------------------------------------------------------------------- + func Genesis() (*ctypes.ResultGenesis, error) { return &ctypes.ResultGenesis{genDoc}, nil } diff --git a/rpc/core/routes.go b/rpc/core/routes.go index 8e9c252d0..4a8d38008 100644 --- a/rpc/core/routes.go +++ b/rpc/core/routes.go @@ -12,6 +12,7 @@ var Routes = map[string]*rpc.RPCFunc{ "unsubscribe": rpc.NewWSRPCFunc(UnsubscribeResult, "event"), "status": rpc.NewRPCFunc(StatusResult, ""), "net_info": rpc.NewRPCFunc(NetInfoResult, ""), + "dial_seeds": rpc.NewRPCFunc(DialSeedsResult, "seeds"), "blockchain": rpc.NewRPCFunc(BlockchainInfoResult, "minHeight,maxHeight"), "genesis": rpc.NewRPCFunc(GenesisResult, ""), "get_block": rpc.NewRPCFunc(GetBlockResult, "height"), @@ -54,6 +55,14 @@ func NetInfoResult() (ctypes.TMResult, error) { } } +func DialSeedsResult(seeds []string) (ctypes.TMResult, error) { + if r, err := DialSeeds(seeds); err != nil { + return nil, err + } else { + return r, nil + } +} + func BlockchainInfoResult(min, max int) (ctypes.TMResult, error) { if r, err := BlockchainInfo(min, max); err != nil { return nil, err diff --git a/rpc/core/types/responses.go b/rpc/core/types/responses.go index 09b7a7029..e6fa6e06d 100644 --- a/rpc/core/types/responses.go +++ b/rpc/core/types/responses.go @@ -37,6 +37,9 @@ type ResultNetInfo struct { Peers []Peer `json:"peers"` } +type ResultDialSeeds struct { +} + type Peer struct { p2p.NodeInfo `json:"node_info"` IsOutbound bool `json:"is_outbound"` @@ -76,18 +79,28 @@ type ResultEvent struct { // response & result types const ( - ResultTypeGenesis = byte(0x01) - ResultTypeBlockchainInfo = byte(0x02) - ResultTypeGetBlock = byte(0x03) - ResultTypeStatus = byte(0x04) - ResultTypeNetInfo = byte(0x05) - ResultTypeListValidators = byte(0x06) - ResultTypeDumpConsensusState = byte(0x07) - ResultTypeBroadcastTx = byte(0x08) - ResultTypeListUnconfirmedTxs = byte(0x09) - ResultTypeSubscribe = byte(0x0A) - ResultTypeUnsubscribe = byte(0x0B) - ResultTypeEvent = byte(0x0C) + // 0x0 bytes are for the blockchain + ResultTypeGenesis = byte(0x01) + ResultTypeBlockchainInfo = byte(0x02) + ResultTypeGetBlock = byte(0x03) + + // 0x2 bytes are for the network + ResultTypeStatus = byte(0x20) + ResultTypeNetInfo = byte(0x21) + ResultTypeDialSeeds = byte(0x22) + + // 0x4 bytes are for the consensus + ResultTypeListValidators = byte(0x40) + ResultTypeDumpConsensusState = byte(0x41) + + // 0x6 bytes are for txs / the application + ResultTypeBroadcastTx = byte(0x60) + ResultTypeListUnconfirmedTxs = byte(0x61) + + // 0x8 bytes are for events + ResultTypeSubscribe = byte(0x80) + ResultTypeUnsubscribe = byte(0x81) + ResultTypeEvent = byte(0x82) ) type TMResult interface { @@ -102,6 +115,7 @@ var _ = wire.RegisterInterface( wire.ConcreteType{&ResultGetBlock{}, ResultTypeGetBlock}, wire.ConcreteType{&ResultStatus{}, ResultTypeStatus}, wire.ConcreteType{&ResultNetInfo{}, ResultTypeNetInfo}, + wire.ConcreteType{&ResultDialSeeds{}, ResultTypeDialSeeds}, wire.ConcreteType{&ResultListValidators{}, ResultTypeListValidators}, wire.ConcreteType{&ResultDumpConsensusState{}, ResultTypeDumpConsensusState}, wire.ConcreteType{&ResultBroadcastTx{}, ResultTypeBroadcastTx},