// convenience method for creating two switches connected to each other. func makeSwitchPair(t testing.TB, initSwitch func(*Switch) *Switch) (*Switch, *Switch) { s1PrivKey := acm.GenPrivKeyEd25519() s2PrivKey := acm.GenPrivKeyEd25519() // Create two switches that will be interconnected. s1 := initSwitch(NewSwitch()) s1.SetNodeInfo(&types.NodeInfo{ PubKey: s1PrivKey.PubKey().(acm.PubKeyEd25519), Moniker: "switch1", ChainID: "testing", Version: "123.123.123", }) s1.SetNodePrivKey(s1PrivKey) s2 := initSwitch(NewSwitch()) s2.SetNodeInfo(&types.NodeInfo{ PubKey: s2PrivKey.PubKey().(acm.PubKeyEd25519), Moniker: "switch2", ChainID: "testing", Version: "123.123.123", }) s2.SetNodePrivKey(s2PrivKey) // Start switches and reactors s1.Start() s2.Start() // Create a listener for s1 l := NewDefaultListener("tcp", ":8001") // Dial the listener & add the connection to s2. lAddr := l.ExternalAddress() connOut, err := lAddr.Dial() if err != nil { t.Fatalf("Could not connect to listener address %v", lAddr) } else { t.Logf("Created a connection to listener address %v", lAddr) } connIn, ok := <-l.Connections() if !ok { t.Fatalf("Could not get inbound connection from listener") } go s1.AddPeerWithConnection(connIn, false) // AddPeer is blocking, requires handshake. s2.AddPeerWithConnection(connOut, true) // Wait for things to happen, peers to get added... time.Sleep(100 * time.Millisecond) // Close the server, no longer needed. l.Stop() return s1, s2 }
func makeSecretConnPair(tb testing.TB) (fooSecConn, barSecConn *SecretConnection) { fooConn, barConn := makeDummyConnPair() fooPrvKey := acm.GenPrivKeyEd25519() fooPubKey := fooPrvKey.PubKey().(acm.PubKeyEd25519) barPrvKey := acm.GenPrivKeyEd25519() barPubKey := barPrvKey.PubKey().(acm.PubKeyEd25519) Parallel( func() { var err error fooSecConn, err = MakeSecretConnection(fooConn, fooPrvKey) if err != nil { tb.Errorf("Failed to establish SecretConnection for foo: %v", err) return } remotePubBytes := fooSecConn.RemotePubKey() if !bytes.Equal(remotePubBytes[:], barPubKey[:]) { tb.Errorf("Unexpected fooSecConn.RemotePubKey. Expected %v, got %v", barPubKey, fooSecConn.RemotePubKey()) } }, func() { var err error barSecConn, err = MakeSecretConnection(barConn, barPrvKey) if barSecConn == nil { tb.Errorf("Failed to establish SecretConnection for bar: %v", err) return } remotePubBytes := barSecConn.RemotePubKey() if !bytes.Equal(remotePubBytes[:], fooPubKey[:]) { tb.Errorf("Unexpected barSecConn.RemotePubKey. Expected %v, got %v", fooPubKey, barSecConn.RemotePubKey()) } }) return }
func TestSecretConnectionReadWrite(t *testing.T) { fooConn, barConn := makeDummyConnPair() fooWrites, barWrites := []string{}, []string{} fooReads, barReads := []string{}, []string{} // Pre-generate the things to write (for foo & bar) for i := 0; i < 100; i++ { fooWrites = append(fooWrites, RandStr((RandInt()%(dataMaxSize*5))+1)) barWrites = append(barWrites, RandStr((RandInt()%(dataMaxSize*5))+1)) } // A helper that will run with (fooConn, fooWrites, fooReads) and vice versa genNodeRunner := func(nodeConn dummyConn, nodeWrites []string, nodeReads *[]string) func() { return func() { // Node handskae nodePrvKey := acm.GenPrivKeyEd25519() nodeSecretConn, err := MakeSecretConnection(nodeConn, nodePrvKey) if err != nil { t.Errorf("Failed to establish SecretConnection for node: %v", err) return } // In parallel, handle reads and writes Parallel( func() { // Node writes for _, nodeWrite := range nodeWrites { n, err := nodeSecretConn.Write([]byte(nodeWrite)) if err != nil { t.Errorf("Failed to write to nodeSecretConn: %v", err) return } if n != len(nodeWrite) { t.Errorf("Failed to write all bytes. Expected %v, wrote %v", len(nodeWrite), n) return } } nodeConn.PipeWriter.Close() }, func() { // Node reads readBuffer := make([]byte, dataMaxSize) for { n, err := nodeSecretConn.Read(readBuffer) if err == io.EOF { return } else if err != nil { t.Errorf("Failed to read from nodeSecretConn: %v", err) return } *nodeReads = append(*nodeReads, string(readBuffer[:n])) } nodeConn.PipeReader.Close() }) } } // Run foo & bar in parallel Parallel( genNodeRunner(fooConn, fooWrites, &fooReads), genNodeRunner(barConn, barWrites, &barReads), ) // A helper to ensure that the writes and reads match. // Additionally, small writes (<= dataMaxSize) must be atomically read. compareWritesReads := func(writes []string, reads []string) { for { // Pop next write & corresponding reads var read, write string = "", writes[0] var readCount = 0 for _, readChunk := range reads { read += readChunk readCount += 1 if len(write) <= len(read) { break } if len(write) <= dataMaxSize { break // atomicity of small writes } } // Compare if write != read { t.Errorf("Expected to read %X, got %X", write, read) } // Iterate writes = writes[1:] reads = reads[readCount:] if len(writes) == 0 { break } } } compareWritesReads(fooWrites, barReads) compareWritesReads(barWrites, fooReads) }
func NewNode() *Node { // Get BlockStore blockStoreDB := dbm.GetDB("blockstore") blockStore := bc.NewBlockStore(blockStoreDB) // Get State stateDB := dbm.GetDB("state") state := sm.LoadState(stateDB) var genDoc *stypes.GenesisDoc if state == nil { genDoc, state = sm.MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file")) state.Save() // write the gendoc to db buf, n, err := new(bytes.Buffer), new(int64), new(error) wire.WriteJSON(genDoc, buf, n, err) stateDB.Set(stypes.GenDocKey, buf.Bytes()) if *err != nil { Exit(Fmt("Unable to write gendoc to db: %v", err)) } } else { genDocBytes := stateDB.Get(stypes.GenDocKey) err := new(error) wire.ReadJSONPtr(&genDoc, genDocBytes, err) if *err != nil { Exit(Fmt("Unable to read gendoc from db: %v", err)) } } // add the chainid to the global config config.Set("chain_id", state.ChainID) // Get PrivValidator privValidatorFile := config.GetString("priv_validator_file") privValidator := types.LoadOrGenPrivValidator(privValidatorFile) // Generate node PrivKey privKey := acm.GenPrivKeyEd25519() // Make event switch eventSwitch := events.NewEventSwitch() _, err := eventSwitch.Start() if err != nil { Exit(Fmt("Failed to start switch: %v", err)) } // Make PEXReactor book := p2p.NewAddrBook(config.GetString("addrbook_file")) pexReactor := p2p.NewPEXReactor(book) // Make BlockchainReactor bcReactor := bc.NewBlockchainReactor(state.Copy(), blockStore, config.GetBool("fast_sync")) // Make MempoolReactor mempool := mempl.NewMempool(state.Copy()) mempoolReactor := mempl.NewMempoolReactor(mempool) // Make ConsensusReactor consensusState := consensus.NewConsensusState(state.Copy(), blockStore, mempoolReactor) consensusReactor := consensus.NewConsensusReactor(consensusState, blockStore, config.GetBool("fast_sync")) if privValidator != nil { consensusReactor.SetPrivValidator(privValidator) } // Make p2p network switch sw := p2p.NewSwitch() sw.AddReactor("PEX", pexReactor) sw.AddReactor("MEMPOOL", mempoolReactor) sw.AddReactor("BLOCKCHAIN", bcReactor) sw.AddReactor("CONSENSUS", consensusReactor) // add the event switch to all services // they should all satisfy events.Eventable SetFireable(eventSwitch, pexReactor, bcReactor, mempoolReactor, consensusReactor) // run the profile server profileHost := config.GetString("prof_laddr") if profileHost != "" { go func() { log.Warn("Profile server", "error", http.ListenAndServe(profileHost, nil)) }() } // set vm log level vm.SetDebug(config.GetBool("vm_log")) return &Node{ sw: sw, evsw: eventSwitch, book: book, blockStore: blockStore, pexReactor: pexReactor, bcReactor: bcReactor, mempoolReactor: mempoolReactor, consensusState: consensusState, consensusReactor: consensusReactor, privValidator: privValidator, genDoc: genDoc, privKey: privKey, } }