func NetStart(s *state.State) { enablenetPtr := flag.Bool("enablenet", true, "Enable or disable networking") listenToPtr := flag.Int("node", 0, "Node Number the simulator will set as the focus") cntPtr := flag.Int("count", 1, "The number of nodes to generate") netPtr := flag.String("net", "tree", "The default algorithm to build the network connections") fnetPtr := flag.String("fnet", "", "Read the given file to build the network connections") dropPtr := flag.Int("drop", 0, "Number of messages to drop out of every thousand") journalPtr := flag.String("journal", "", "Rerun a Journal of messages") journalingPtr := flag.Bool("journaling", false, "Write a journal of all messages recieved. Default is off.") followerPtr := flag.Bool("follower", false, "If true, force node to be a follower. Only used when replaying a journal.") leaderPtr := flag.Bool("leader", true, "If true, force node to be a leader. Only used when replaying a journal.") dbPtr := flag.String("db", "", "Override the Database in the Config file and use this Database implementation") cloneDBPtr := flag.String("clonedb", "", "Override the main node and use this database for the clones in a Network.") portOverridePtr := flag.Int("port", 0, "Address to serve WSAPI on") networkNamePtr := flag.String("network", "", "Network to join: MAIN, TEST or LOCAL") networkPortOverridePtr := flag.Int("networkPort", 0, "Address for p2p network to listen on.") peersPtr := flag.String("peers", "", "Array of peer addresses. ") blkTimePtr := flag.Int("blktime", 0, "Seconds per block. Production is 600.") runtimeLogPtr := flag.Bool("runtimeLog", false, "If true, maintain runtime logs of messages passed.") netdebugPtr := flag.Int("netdebug", 0, "0-5: 0 = quiet, >0 = increasing levels of logging") exclusivePtr := flag.Bool("exclusive", false, "If true, we only dial out to special/trusted peers.") prefixNodePtr := flag.String("prefix", "", "Prefix the Factom Node Names with this value; used to create leaderless networks.") rotatePtr := flag.Bool("rotate", false, "If true, responsiblity is owned by one leader, and rotated over the leaders.") timeOffsetPtr := flag.Int("timedelta", 0, "Maximum timeDelta in milliseconds to offset each node. Simulates deltas in system clocks over a network.") keepMismatchPtr := flag.Bool("keepmismatch", false, "If true, do not discard DBStates even when a majority of DBSignatures have a different hash") startDelayPtr := flag.Int("startdelay", 10, "Delay to start processing messages, in seconds") deadlinePtr := flag.Int("deadline", 1000, "Timeout Delay in milliseconds used on Reads and Writes to the network comm") customNetPtr := flag.String("customnet", "", "This string specifies a custom blockchain network ID.") rpcUserflag := flag.String("rpcuser", "", "Username to protect factomd local API with simple HTTP authentication") rpcPasswordflag := flag.String("rpcpass", "", "Password to protect factomd local API. Ignored if rpcuser is blank") factomdTLSflag := flag.Bool("tls", false, "Set to true to require encrypted connections to factomd API and Control Panel") //to get tls, run as "factomd -tls=true" factomdLocationsflag := flag.String("selfaddr", "", "comma seperated IPAddresses and DNS names of this factomd to use when creating a cert file") flag.Parse() enableNet := *enablenetPtr listenTo := *listenToPtr cnt := *cntPtr net := *netPtr fnet := *fnetPtr droprate := *dropPtr journal := *journalPtr journaling := *journalingPtr follower := *followerPtr leader := *leaderPtr db := *dbPtr cloneDB := *cloneDBPtr portOverride := *portOverridePtr peers := *peersPtr networkName := *networkNamePtr networkPortOverride := *networkPortOverridePtr blkTime := *blkTimePtr runtimeLog := *runtimeLogPtr netdebug := *netdebugPtr exclusive := *exclusivePtr prefix := *prefixNodePtr rotate := *rotatePtr timeOffset := *timeOffsetPtr keepMismatch := *keepMismatchPtr startDelay := int64(*startDelayPtr) deadline := *deadlinePtr customNet := primitives.Sha([]byte(*customNetPtr)).Bytes()[:4] rpcUser := *rpcUserflag rpcPassword := *rpcPasswordflag factomdTLS := *factomdTLSflag factomdLocations := *factomdLocationsflag // Must add the prefix before loading the configuration. s.AddPrefix(prefix) FactomConfigFilename := util.GetConfigFilename("m2") fmt.Println(fmt.Sprintf("factom config: %s", FactomConfigFilename)) s.LoadConfig(FactomConfigFilename, networkName) s.OneLeader = rotate s.TimeOffset = primitives.NewTimestampFromMilliseconds(uint64(timeOffset)) s.StartDelayLimit = startDelay * 1000 s.Journaling = journaling if 999 < portOverride { // The command line flag exists and seems reasonable. s.SetPort(portOverride) } if blkTime != 0 { s.DirectoryBlockInSeconds = blkTime } else { blkTime = s.DirectoryBlockInSeconds } if follower { leader = false } if leader { follower = false } if !follower && !leader { panic("Not a leader or a follower") } if journal != "" { cnt = 1 } if rpcUser != "" { s.RpcUser = rpcUser } if rpcPassword != "" { s.RpcPass = rpcPassword } if factomdTLS == true { s.FactomdTLSEnable = true } if factomdLocations != "" { if len(s.FactomdLocations) > 0 { s.FactomdLocations += "," } s.FactomdLocations += factomdLocations } fmt.Println(">>>>>>>>>>>>>>>>") fmt.Println(">>>>>>>>>>>>>>>> Net Sim Start!") fmt.Println(">>>>>>>>>>>>>>>>") fmt.Println(">>>>>>>>>>>>>>>> Listening to Node", listenTo) fmt.Println(">>>>>>>>>>>>>>>>") AddInterruptHandler(func() { fmt.Print("<Break>\n") fmt.Print("Gracefully shutting down the server...\n") for _, fnode := range fnodes { fmt.Print("Shutting Down: ", fnode.State.FactomNodeName, "\r\n") fnode.State.ShutdownChan <- 0 } if enableNet { p2pNetwork.NetworkStop() // NODE_TALK_FIX p2pProxy.stopProxy() } fmt.Print("Waiting...\r\n") time.Sleep(3 * time.Second) os.Exit(0) }) if journal != "" { if s.DBType != "Map" { fmt.Println("Journal is ALWAYS a Map database") s.DBType = "Map" } } if follower { s.NodeMode = "FULL" leadID := primitives.Sha([]byte(s.Prefix + "FNode0")) if s.IdentityChainID.IsSameAs(leadID) { s.SetIdentityChainID(primitives.Sha([]byte(time.Now().String()))) // Make sure this node is NOT a leader } } s.KeepMismatch = keepMismatch if len(db) > 0 { s.DBType = db } else { db = s.DBType } if len(cloneDB) > 0 { s.CloneDBType = cloneDB } else { s.CloneDBType = db } pnet := net if len(fnet) > 0 { pnet = fnet net = "file" } go StartProfiler() s.AddPrefix(prefix) s.SetOut(false) s.Init() s.SetDropRate(droprate) mLog.init(runtimeLog, cnt) setupFirstAuthority(s) os.Stderr.WriteString(fmt.Sprintf("%20s %s\n", "FNode 0 Salt", s.Salt.String()[:16])) os.Stderr.WriteString(fmt.Sprintf("%20s %v\n", "enablenet", enableNet)) os.Stderr.WriteString(fmt.Sprintf("%20s %d\n", "node", listenTo)) os.Stderr.WriteString(fmt.Sprintf("%20s %s\n", "prefix", prefix)) os.Stderr.WriteString(fmt.Sprintf("%20s %d\n", "node count", cnt)) os.Stderr.WriteString(fmt.Sprintf("%20s \"%s\"\n", "net spec", pnet)) os.Stderr.WriteString(fmt.Sprintf("%20s %d\n", "Msgs droped", droprate)) os.Stderr.WriteString(fmt.Sprintf("%20s \"%s\"\n", "journal", journal)) os.Stderr.WriteString(fmt.Sprintf("%20s \"%s\"\n", "database", db)) os.Stderr.WriteString(fmt.Sprintf("%20s \"%s\"\n", "database for clones", cloneDB)) os.Stderr.WriteString(fmt.Sprintf("%20s \"%d\"\n", "port", s.PortNumber)) os.Stderr.WriteString(fmt.Sprintf("%20s \"%s\"\n", "peers", peers)) os.Stderr.WriteString(fmt.Sprintf("%20s \"%d\"\n", "netdebug", netdebug)) os.Stderr.WriteString(fmt.Sprintf("%20s \"%t\"\n", "exclusive", exclusive)) os.Stderr.WriteString(fmt.Sprintf("%20s %d\n", "block time", blkTime)) os.Stderr.WriteString(fmt.Sprintf("%20s %v\n", "runtimeLog", runtimeLog)) os.Stderr.WriteString(fmt.Sprintf("%20s %v\n", "rotate", rotate)) os.Stderr.WriteString(fmt.Sprintf("%20s %v\n", "timeOffset", timeOffset)) os.Stderr.WriteString(fmt.Sprintf("%20s %v\n", "keepMismatch", keepMismatch)) os.Stderr.WriteString(fmt.Sprintf("%20s %v\n", "startDelay", startDelay)) os.Stderr.WriteString(fmt.Sprintf("%20s %v\n", "Network", s.Network)) os.Stderr.WriteString(fmt.Sprintf("%20s %x\n", "customnet", customNet)) os.Stderr.WriteString(fmt.Sprintf("%20s %v\n", "deadline (ms)", deadline)) os.Stderr.WriteString(fmt.Sprintf("%20s %v\n", "tls", s.FactomdTLSEnable)) os.Stderr.WriteString(fmt.Sprintf("%20s %v\n", "selfaddr", s.FactomdLocations)) os.Stderr.WriteString(fmt.Sprintf("%20s \"%s\"\n", "rpcuser", s.RpcUser)) if "" == s.RpcPass { os.Stderr.WriteString(fmt.Sprintf("%20s %s\n", "rpcpass", "is blank")) } else { os.Stderr.WriteString(fmt.Sprintf("%20s %s\n", "rpcpass", "is set")) } //************************************************ // Actually setup the Network //************************************************ // Make cnt Factom nodes for i := 0; i < cnt; i++ { makeServer(s) // We clone s to make all of our servers } // Modify Identities of new nodes if len(fnodes) > 1 && len(s.Prefix) == 0 { modifyLoadIdentities() // We clone s to make all of our servers } for i := range fnodes { fnodes[i].State.CreateBlankFactomIdentity(fnodes[i].State.IdentityChainID) } // Start the P2P netowork var networkID p2p.NetworkID var seedURL, networkPort, specialPeers string switch s.Network { case "MAIN", "main": networkID = p2p.MainNet seedURL = s.MainSeedURL networkPort = s.MainNetworkPort specialPeers = s.MainSpecialPeers case "TEST", "test": networkID = p2p.TestNet seedURL = s.TestSeedURL networkPort = s.TestNetworkPort specialPeers = s.TestSpecialPeers case "LOCAL", "local": networkID = p2p.LocalNet seedURL = s.LocalSeedURL networkPort = s.LocalNetworkPort specialPeers = s.LocalSpecialPeers case "CUSTOM", "custom": if bytes.Compare(customNet, []byte("\xe3\xb0\xc4\x42")) == 0 { panic("Please specify a custom network with -customnet=<something unique here>") } s.CustomNetworkID = customNet networkID = p2p.NetworkID(binary.BigEndian.Uint32(customNet)) for i := range fnodes { fnodes[i].State.CustomNetworkID = customNet } seedURL = s.LocalSeedURL networkPort = s.LocalNetworkPort specialPeers = s.LocalSpecialPeers default: panic("Invalid Network choice in Config File or command line. Choose MAIN, TEST, LOCAL, or CUSTOM") } connectionMetricsChannel := make(chan interface{}, p2p.StandardChannelSize) p2p.NetworkDeadline = time.Duration(deadline) * time.Millisecond if enableNet { if 0 < networkPortOverride { networkPort = fmt.Sprintf("%d", networkPortOverride) } ci := p2p.ControllerInit{ Port: networkPort, PeersFile: s.PeersFile, Network: networkID, Exclusive: exclusive, SeedURL: seedURL, SpecialPeers: specialPeers, ConnectionMetricsChannel: connectionMetricsChannel, } p2pNetwork = new(p2p.Controller).Init(ci) p2pNetwork.StartNetwork() // Setup the proxy (Which translates from network parcels to factom messages, handling addressing for directed messages) p2pProxy = new(P2PProxy).Init(fnodes[0].State.FactomNodeName, "P2P Network").(*P2PProxy) p2pProxy.FromNetwork = p2pNetwork.FromNetwork p2pProxy.ToNetwork = p2pNetwork.ToNetwork fnodes[0].Peers = append(fnodes[0].Peers, p2pProxy) p2pProxy.SetDebugMode(netdebug) if 0 < netdebug { go p2pProxy.PeriodicStatusReport(fnodes) p2pNetwork.StartLogging(uint8(netdebug)) } else { p2pNetwork.StartLogging(uint8(0)) } p2pProxy.StartProxy() // Command line peers lets us manually set special peers p2pNetwork.DialSpecialPeersString(peers) } switch net { case "file": file, err := os.Open(fnet) if err != nil { panic(fmt.Sprintf("File network.txt failed to open: %s", err.Error())) } else if file == nil { panic(fmt.Sprint("File network.txt failed to open, and we got a file of <nil>")) } scanner := bufio.NewScanner(file) for scanner.Scan() { var a, b int var s string fmt.Sscanf(scanner.Text(), "%d %s %d", &a, &s, &b) if s == "--" { AddSimPeer(fnodes, a, b) } } case "square": side := int(math.Sqrt(float64(cnt))) for i := 0; i < side; i++ { AddSimPeer(fnodes, i*side, (i+1)*side-1) AddSimPeer(fnodes, i, side*(side-1)+i) for j := 0; j < side; j++ { if j < side-1 { AddSimPeer(fnodes, i*side+j, i*side+j+1) } AddSimPeer(fnodes, i*side+j, ((i+1)*side)+j) } } case "long": fmt.Println("Using long Network") for i := 1; i < cnt; i++ { AddSimPeer(fnodes, i-1, i) } // Make long into a circle case "loops": fmt.Println("Using loops Network") for i := 1; i < cnt; i++ { AddSimPeer(fnodes, i-1, i) } for i := 0; (i+17)*2 < cnt; i += 17 { AddSimPeer(fnodes, i%cnt, (i+5)%cnt) } for i := 0; (i+13)*2 < cnt; i += 13 { AddSimPeer(fnodes, i%cnt, (i+7)%cnt) } case "alot": n := len(fnodes) for i := 0; i < n; i++ { AddSimPeer(fnodes, i, (i+1)%n) AddSimPeer(fnodes, i, (i+5)%n) AddSimPeer(fnodes, i, (i+7)%n) } case "alot+": n := len(fnodes) for i := 0; i < n; i++ { AddSimPeer(fnodes, i, (i+1)%n) AddSimPeer(fnodes, i, (i+5)%n) AddSimPeer(fnodes, i, (i+7)%n) AddSimPeer(fnodes, i, (i+13)%n) } case "tree": index := 0 row := 1 treeloop: for i := 0; true; i++ { for j := 0; j <= i; j++ { AddSimPeer(fnodes, index, row) AddSimPeer(fnodes, index, row+1) row++ index++ if index >= len(fnodes) { break treeloop } } row += 1 } case "circles": circleSize := 7 index := 0 for { AddSimPeer(fnodes, index, index+circleSize-1) for i := index; i < index+circleSize-1; i++ { AddSimPeer(fnodes, i, i+1) } index += circleSize AddSimPeer(fnodes, index, index-circleSize/3) AddSimPeer(fnodes, index+2, index-circleSize-circleSize*2/3-1) AddSimPeer(fnodes, index+3, index-(2*circleSize)-circleSize*2/3) AddSimPeer(fnodes, index+5, index-(3*circleSize)-circleSize*2/3+1) if index >= len(fnodes) { break } } default: fmt.Println("Didn't understand network type. Known types: mesh, long, circles, tree, loops. Using a Long Network") for i := 1; i < cnt; i++ { AddSimPeer(fnodes, i-1, i) } } if journal != "" { go LoadJournal(s, journal) startServers(false) } else { startServers(true) } // Start the webserver go wsapi.Start(fnodes[0].State) go controlPanel.ServeControlPanel(fnodes[0].State.ControlPanelChannel, fnodes[0].State, connectionMetricsChannel, p2pNetwork, Build) // Listen for commands: SimControl(listenTo) }
func SimControl(listenTo int) { var _ = time.Sleep var summary int var watchPL int var watchMessages int var rotate int var wsapiNode int var faulting bool for { l := make([]byte, 100) var err error // When running as a detatched process, this routine becomes a very tight loop and starves other goroutines. // So, we will sleep before letting it check to see if Stdin has been reconnected if _, err = os.Stdin.Read(l); err != nil { time.Sleep(2 * time.Second) continue } // This splits up the command at anycodepoint that is not a letter, number of punctuation, so usually by spaces. parseFunc := func(c rune) bool { return !unicode.IsLetter(c) && !unicode.IsNumber(c) && !unicode.IsPunct(c) } // cmd is not a list of the parameters, much like command line args show up in args[] cmd := strings.FieldsFunc(string(l), parseFunc) if 0 == len(cmd) { cmd = []string{"h"} } b := string(cmd[0]) v, err := strconv.Atoi(string(b)) if err == nil && v >= 0 && v < len(fnodes) && fnodes[listenTo].State != nil { listenTo = v os.Stderr.WriteString(fmt.Sprintf("Switching to Node %d\n", listenTo)) // Update which node will be displayed on the controlPanel page connectionMetricsChannel := make(chan interface{}, p2p.StandardChannelSize) go controlPanel.ServeControlPanel(fnodes[listenTo].State.ControlPanelChannel, fnodes[listenTo].State, connectionMetricsChannel, p2pNetwork, Build) } else { // fmt.Printf("Parsing command, found %d elements. The first element is: %+v / %s \n Full command: %+v\n", len(cmd), b[0], string(b), cmd) switch { case '!' == b[0]: if listenTo < 0 || listenTo > len(fnodes) { break } s := fnodes[listenTo].State os.Stderr.WriteString("Reset Node: " + s.FactomNodeName + "\n") s.Reset() case 'g' == b[0]: if len(b) > 1 { if b[1] == 'c' { copyOver(fnodes[listenTo].State) break } } if listenTo < 0 || listenTo > len(fnodes) { break } wsapiNode = listenTo wsapi.SetState(fnodes[wsapiNode].State) if nextAuthority == -1 { err := fundWallet(fnodes[wsapiNode].State, 2e7) if err != nil { os.Stderr.WriteString(fmt.Sprintf("Error in funding the wallet, %s\n", err.Error())) break } setUpAuthorites(fnodes[wsapiNode].State, true) os.Stderr.WriteString(fmt.Sprintf("%d Authorities added to the stack and funds are in wallet\n", len(authStack))) } if len(b) == 1 { os.Stderr.WriteString(fmt.Sprint("Authorities are ready to be made. 'gN' where N is the number to be made.\n")) } if len(b) > 1 { count, err := strconv.Atoi(b[1:]) if err != nil { os.Stderr.WriteString(fmt.Sprintf("Error in input bN, %s\n", err.Error())) } else { if count > 100 { os.Stderr.WriteString(fmt.Sprint("You can only pop a max of 100 off the stack at a time.")) count = 100 } err := fundWallet(fnodes[wsapiNode].State, uint64(count*5e7)) if err != nil { os.Stderr.WriteString(fmt.Sprintf("Error in funding the wallet, %s\n", err.Error())) break } auths, skipped, err := authorityToBlockchain(count, fnodes[wsapiNode].State) if err != nil { os.Stderr.WriteString(fmt.Sprintf("Error making authorites, %s\n", err.Error())) } os.Stderr.WriteString(fmt.Sprintf("=== %d Identities added to blockchain, %d remain in stack, %d skipped (Added by someone else) ===\n", len(auths), len(authStack), skipped)) for _, ele := range auths { fmt.Println(ele.ChainID.String()) } } } case '/' == b[0]: sortByID = !sortByID if sortByID { os.Stderr.WriteString("Sort Status by Chain IDs\n") } else { os.Stderr.WriteString("Sort Status by Node Name\n") } case 'w' == b[0]: if listenTo >= 0 && listenTo < len(fnodes) { wsapiNode = listenTo wsapi.SetState(fnodes[wsapiNode].State) os.Stderr.WriteString(fmt.Sprintf("--Listen to %s --\n", fnodes[wsapiNode].State.FactomNodeName)) } case 's' == b[0]: if len(b) > 1 { ht, err := strconv.Atoi(string(b[1:])) if err != nil { os.Stderr.WriteString("type snnn where nnn is the number of status messages to print\n") break } if listenTo < 0 || listenTo > len(fnodes) { os.Stderr.WriteString("Select a node first\n") break } f := fnodes[listenTo] fmt.Println("-----------------------------", f.State.FactomNodeName, "--------------------------------------", string(b)) l := len(f.State.StatusStrs) if l < ht { ht = l } for i := 0; i < ht; i++ { os.Stderr.WriteString(f.State.StatusStrs[l-1] + "\n") l-- } break } summary++ if summary%2 == 1 { os.Stderr.WriteString("--Print Summary On--\n") go printSummary(&summary, summary, &listenTo, &wsapiNode) } else { os.Stderr.WriteString("--Print Summary Off--\n") } case 'p' == b[0]: if len(b) > 1 { ht, err := strconv.Atoi(string(b[1:])) if err != nil { os.Stderr.WriteString("Dump Process List with pn where n = blockheight, i.e. 'p10'") break } if listenTo < 0 || listenTo > len(fnodes) { os.Stderr.WriteString("Select a node first") break } f := fnodes[listenTo] pl := f.State.ProcessLists.Get(uint32(ht)) if pl == nil { os.Stderr.WriteString("No Process List found") } else { fmt.Println("-----------------------------", f.State.FactomNodeName, "--------------------------------------", string(b)) fmt.Println(pl.String()) } break } watchPL++ if watchPL%2 == 1 { os.Stderr.WriteString("--Print Process Lists On--\n") go printProcessList(&watchPL, watchPL, &listenTo) } else { os.Stderr.WriteString("--Print Process Lists Off--\n") } case 'r' == b[0]: rotate++ if rotate%2 == 1 { os.Stderr.WriteString("--Rotate the WSAPI around the nodes--\n") go rotateWSAPI(&rotate, rotate, &wsapiNode) } else { os.Stderr.WriteString("--Stop Rotation of the WSAPI around the nodes. Now --\n") wsapi.SetState(fnodes[wsapiNode].State) } case 'a' == b[0]: mLog.all = false for _, fnode := range fnodes { fnode.State.SetOut(false) } if listenTo < 0 || listenTo > len(fnodes) { fmt.Println("Select a node first") break } f := fnodes[listenTo] fmt.Println("-----------------------------", f.State.FactomNodeName, "--------------------------------------", string(b[:len(b)])) if len(b) < 2 { break } ht, err := strconv.Atoi(string(b[1:])) if err != nil { fmt.Println(err, "Dump Adminblock block with an where n = blockheight, i.e. 'a10'") } else { msg, err := f.State.LoadDBState(uint32(ht)) if err == nil && msg != nil { dsmsg := msg.(*messages.DBStateMsg) ABlock := dsmsg.AdminBlock fmt.Println(ABlock.String()) } else { pl := f.State.ProcessLists.Get(uint32(ht)) if pl == nil || pl.AdminBlock == nil { fmt.Println("Could not find this Admin block") } else { fmt.Printf(pl.AdminBlock.String()) } } } case 'e' == b[0]: mLog.all = false for _, fnode := range fnodes { fnode.State.SetOut(false) } if listenTo < 0 || listenTo > len(fnodes) { fmt.Println("Select a node first") break } f := fnodes[listenTo] fmt.Println("-----------------------------", f.State.FactomNodeName, "--------------------------------------", string(b[:len(b)])) if len(b) < 2 { break } ht, err := strconv.Atoi(string(b[1:])) if err != nil { fmt.Println(err, "Dump Entry Credit block with fn where n = blockheight, i.e. 'e10'") } else { msg, err := f.State.LoadDBState(uint32(ht)) if err == nil && msg != nil { dsmsg := msg.(*messages.DBStateMsg) ECBlock := dsmsg.EntryCreditBlock fmt.Printf(ECBlock.String()) } else { pl := f.State.ProcessLists.Get(uint32(ht)) if pl == nil || pl.EntryCreditBlock == nil { fmt.Println("Could not find this Entry Credit Block") } else { fmt.Printf(pl.EntryCreditBlock.String()) } } } case 'f' == b[0]: mLog.all = false for _, fnode := range fnodes { fnode.State.SetOut(false) } if listenTo < 0 || listenTo > len(fnodes) { fmt.Println("Select a node first") break } f := fnodes[listenTo] fmt.Println("-----------------------------", f.State.FactomNodeName, "--------------------------------------", string(b[:len(b)])) if len(b) < 2 { break } ht, err := strconv.Atoi(string(b[1:])) if err != nil { fmt.Println(err, "Dump Factoid block with fn where n = blockheight, i.e. 'f10'") } else { msg, err := f.State.LoadDBState(uint32(ht)) if err == nil && msg != nil { dsmsg := msg.(*messages.DBStateMsg) FBlock := dsmsg.FactoidBlock fmt.Printf(FBlock.String()) } else { dbstate := f.State.DBStates.Get(ht) if dbstate == nil || dbstate.FactoidBlock == nil { fmt.Println("Could not find this Factoid block") } else { fmt.Printf(dbstate.FactoidBlock.String()) } } } case 'd' == b[0]: mLog.all = false for _, fnode := range fnodes { fnode.State.SetOut(false) } if listenTo < 0 || listenTo > len(fnodes) { fmt.Println("Select a node first") break } f := fnodes[listenTo] fmt.Println("-----------------------------", f.State.FactomNodeName, "--------------------------------------", string(b[:len(b)])) if len(b) < 2 { break } ht, err := strconv.Atoi(string(b[1:])) if err != nil { fmt.Println(err, "Dump Directory block with dn where n = blockheight, i.e. 'd10'") } else { msg, err := f.State.LoadDBState(uint32(ht)) if err == nil && msg != nil { dsmsg := msg.(*messages.DBStateMsg) DBlock := dsmsg.DirectoryBlock fmt.Printf(DBlock.String()) } else { pl := f.State.ProcessLists.Get(uint32(ht)) if pl == nil || pl.DirectoryBlock == nil { fmt.Println("Could not find this directory block") } else { fmt.Printf(pl.DirectoryBlock.String()) } } } case 'v' == b[0]: if verboseFaultOutput { verboseFaultOutput = false os.Stderr.WriteString("Vnnn Set full fault timeout to the given number of seconds. Helps debugging.\n") } else { verboseFaultOutput = true os.Stderr.WriteString("--VerboseFaultOutput On--\n") } case 'V' == b[0]: if len(b) == 1 { os.Stderr.WriteString("Vnnn -- Set the timeout for faulting a server to nnn seconds\n") os.Stderr.WriteString("Vt -- Start an automated Faulting Test, or stop a running Faulting Test\n") os.Stderr.WriteString("VL -- Display all the authority sets in the Status update\n") os.Stderr.WriteString("Vr -- Reset all nodes in the simulation\n") break } if b[1] == 't' { faulting = !faulting if faulting { os.Stderr.WriteString("Start Faulting Test\n") go faultTest(&faulting) } else { os.Stderr.WriteString("Stop Faulting Test\n") } break } // Reset Everything if b[1] == 'r' { os.Stderr.WriteString("Reset all nodes in the simulation!\n") for _, f := range fnodes { f.State.Reset() } break } if b[1] == 'l' || b[1] == 'L' { if verboseAuthoritySet { verboseAuthoritySet = false os.Stderr.WriteString("--VerboseAuthoritySet Off--\n") } else { verboseAuthoritySet = true os.Stderr.WriteString("--VerboseAuthoritySet On--\n") } break } if b[1] == 'd' || b[1] == 'D' { if verboseAuthorityDeltas { verboseAuthorityDeltas = false os.Stderr.WriteString("--VerboseAuthorityDeltas Off--\n") } else { verboseAuthorityDeltas = true os.Stderr.WriteString("--VerboseAuthorityDeltas On--\n") } break } nnn, err := strconv.Atoi(string(b[1:])) if err != nil || nnn < 0 || nnn > 99 { os.Stderr.WriteString("Specifiy a FaultTimeout between 0 and 100\n") break } for _, fn := range fnodes { fn.State.FaultTimeout = nnn os.Stderr.WriteString(fmt.Sprintf("Setting FaultTimeout of %10s to %d\n", fn.State.FactomNodeName, nnn)) } case 'k' == b[0]: mLog.all = false for _, fnode := range fnodes { fnode.State.SetOut(false) } if listenTo < 0 || listenTo > len(fnodes) { fmt.Println("Select a node first") break } f := fnodes[listenTo] fmt.Println("-----------------------------", f.State.FactomNodeName, "--------------------------------------", string(b)) if len(b) < 2 { fmt.Println("No Parms found.") break } parms := strings.Split(string(b[1:]), ".") if len(parms) >= 2 { os.Stderr.WriteString("Print Entry String with: k<db #>.<entry #>\n") } db, err1 := strconv.Atoi(string(parms[0])) entry, err2 := strconv.Atoi(string(parms[1])) if err1 != nil || err2 != nil { os.Stderr.WriteString("Bad Parameters") } else { msg, err := f.State.LoadDBState(uint32(db)) if err == nil && msg != nil { dsmsg := msg.(*messages.DBStateMsg) DBlock := dsmsg.DirectoryBlock entries := DBlock.GetDBEntries() if entry < len(entries) && entry >= 0 { fmt.Println(fmt.Sprintf("Looking for EB with KeyMR %x", entries[entry].GetKeyMR().Bytes())) eb1, _ := f.State.DB.FetchEBlockHead(entries[entry].GetChainID()) if eb1 != nil { fmt.Println("Chain Head:") fmt.Println(eb1.String()) } eb2, _ := f.State.DB.FetchEBlock(entries[entry].GetKeyMR()) if eb2 != nil { fmt.Println("Entry Block:") fmt.Println(eb2.String()) } else { fmt.Println("No Entry Block Found") } } } else { fmt.Println("Error: ", err, msg) } } case 'x' == b[0]: if listenTo >= 0 && listenTo < len(fnodes) { f := fnodes[listenTo] v := f.State.GetNetStateOff() if v { os.Stderr.WriteString("Bring " + f.State.FactomNodeName + " Back onto the network\n") } else { os.Stderr.WriteString("Take " + f.State.FactomNodeName + " off the network\n") } f.State.SetNetStateOff(!v) } case 'y' == b[0]: if listenTo >= 0 && listenTo < len(fnodes) { f := fnodes[listenTo] fmt.Println("Holding:") for k := range f.State.Holding { fmt.Println(f.State.Holding[k].String()) } } case 'm' == b[0]: watchMessages++ if watchMessages%2 == 1 { os.Stderr.WriteString("--Print Messages On--\n") go printMessages(&watchMessages, watchMessages, &listenTo) } else { os.Stderr.WriteString("--Print Messages Off--\n") } case 'z' == b[0]: // Add Audit server, Remove server, and Add Leader fall through to 'n', switch to next node. if len(b) > 1 && b[1] == 'a' { msg := messages.NewRemoveServerMsg(fnodes[listenTo].State, fnodes[listenTo].State.IdentityChainID, 1) fnodes[listenTo].State.InMsgQueue() <- msg os.Stderr.WriteString(fmt.Sprintln("Attempting to remove", fnodes[listenTo].State.GetFactomNodeName(), "as a server")) } else { msg := messages.NewRemoveServerMsg(fnodes[listenTo].State, fnodes[listenTo].State.IdentityChainID, 0) fnodes[listenTo].State.InMsgQueue() <- msg os.Stderr.WriteString(fmt.Sprintln("Attempting to remove", fnodes[listenTo].State.GetFactomNodeName(), "as a server")) } fallthrough case 'o' == b[0]: // Add Audit server and Add Leader fall through to 'n', switch to next node. if b[0] == 'o' { // (Don't do anything if just passing along the remove server) if len(b) > 1 && b[1] == 'n' { index := 0 for index < len(authKeyLibrary) { if authKeyLibrary[index].Taken == false { authKeyLibrary[index].Taken = true fnodes[listenTo].State.IdentityChainID = authKeyLibrary[index].ChainID key, pKey, _ := authKeyLookup(fnodes[listenTo].State.IdentityChainID) fnodes[listenTo].State.LocalServerPrivKey = key fnodes[listenTo].State.SimSetNewKeys(pKey) os.Stderr.WriteString(fmt.Sprintf("Identity of " + fnodes[listenTo].State.GetFactomNodeName() + " changed to [" + authKeyLibrary[index].ChainID.String()[:10] + "]\n")) break } index++ } } msg := messages.NewAddServerMsg(fnodes[listenTo].State, 1) fnodes[listenTo].State.InMsgQueue() <- msg os.Stderr.WriteString(fmt.Sprintln("Attempting to make", fnodes[listenTo].State.GetFactomNodeName(), "a Audit Server")) } fallthrough case 'l' == b[0]: // Add Audit server, Remove server, and Add Leader fall through to 'n', switch to next node. if b[0] == 'l' { // (Don't do anything if just passing along the audit server) feds := fnodes[listenTo].State.LeaderPL.FedServers exists := false for _, fed := range feds { if fed.GetChainID().IsSameAs(fnodes[listenTo].State.IdentityChainID) { exists = true } } if len(b) > 1 && b[1] == 't' && fnodes[listenTo].State.IdentityChainID.String()[:6] != "888888" && !exists { index := 0 for index < len(authKeyLibrary) { if authKeyLibrary[index].Taken == false { authKeyLibrary[index].Taken = true fnodes[listenTo].State.IdentityChainID = authKeyLibrary[index].ChainID key, pKey, _ := authKeyLookup(fnodes[listenTo].State.IdentityChainID) fnodes[listenTo].State.LocalServerPrivKey = key fnodes[listenTo].State.SimSetNewKeys(pKey) os.Stderr.WriteString(fmt.Sprintf("Identity of " + fnodes[listenTo].State.GetFactomNodeName() + " changed to [" + authKeyLibrary[index].ChainID.String()[:10] + "]\n")) break } index++ } if index >= len(authKeyLibrary) { os.Stderr.WriteString(fmt.Sprint("Did not make a leader, ran out of identities. Type 'g1' for one more identity.\n")) break } } msg := messages.NewAddServerMsg(fnodes[listenTo].State, 0) fnodes[listenTo].State.InMsgQueue() <- msg os.Stderr.WriteString(fmt.Sprintln("Attempting to make", fnodes[listenTo].State.GetFactomNodeName(), "a Leader")) } fallthrough case 'n' == b[0]: fnodes[listenTo].State.SetOut(false) listenTo++ if listenTo >= len(fnodes) { listenTo = 0 } fnodes[listenTo].State.SetOut(true) os.Stderr.WriteString(fmt.Sprint("\r\nSwitching to Node ", listenTo, "\r\n")) case 'c' == b[0]: c := !fnodes[0].State.DebugConsensus for _, n := range fnodes { n.State.DebugConsensus = fnodes[0].State.DebugConsensus } if c { os.Stderr.WriteString(fmt.Sprint("\r\nTrace Consensus\n")) } else { os.Stderr.WriteString(fmt.Sprint("\r\nTurn off Consensus Trace \n")) } for _, f := range fnodes { f.State.DebugConsensus = c } case 'i' == b[0]: show := 0 amt := -1 if len(b) > 1 && (b[1] == 'H' || b[1] == 'h') { os.Stderr.WriteString("------------------------ Identity Commands --------------------------------\n") os.Stderr.WriteString("iH -Show this help\n") os.Stderr.WriteString("gN -Adds 'N' identities to your identity pool from the identity stack. Cannot add \n") os.Stderr.WriteString(" identities that another instance of Factomd has added to their identity pool.\n") os.Stderr.WriteString(" Each Factomd instance has its own identity pool it can use (t), but everyone\n") os.Stderr.WriteString(" will share the identities in the identity stack. This stack is fixed and will\n") os.Stderr.WriteString(" be the same each time Factomd launches. It may grow in the future. Used for testing\n") os.Stderr.WriteString("tN -Attaches Nth identity in pool(0 indexed) to current node. If that identity is taken, \n") os.Stderr.WriteString(" will grab the next available identity in the local identity pool. Can also just type \n") os.Stderr.WriteString(" 't' and it will grab the next available identity.\n") os.Stderr.WriteString("tm -Shows the current node's identity information. \n") os.Stderr.WriteString("tc -Changes the current node's signing key. \n") os.Stderr.WriteString("t[CHAINID] -Attaches the identity associated with the root chainID given to current node \n") os.Stderr.WriteString("u Shows the authorities being monitored for change.\n") os.Stderr.WriteString("i Shows the identities being monitored for change.\n") os.Stderr.WriteString("i[t/m/b/a][N] Shows only the Chains, Mhash, block signing key, or anchor key up to the Nth identity\n") os.Stderr.WriteString("isN Shows only Nth identity\n") os.Stderr.WriteString("-------------------------------------------------------------------------------\n\n") } else { if len(b) > 1 { if b[1] == 't' { show = 1 } else if b[1] == 'm' { show = 2 } else if b[1] == 'b' { show = 3 } else if b[1] == 'a' { show = 4 } if len(b) > 2 { amt, err = strconv.Atoi(b[2:]) if b[1] == 's' { show = 5 } else if err == nil { } else { show = 0 amt = -1 } } } if amt == -1 { os.Stderr.WriteString(fmt.Sprintf("=== Identity List === Total: %d Displaying: All\n", len(fnodes[listenTo].State.Identities))) } else if show == 5 { os.Stderr.WriteString(fmt.Sprintf("=== Identity List === Total: %d Displaying Only: %d\n", len(fnodes[listenTo].State.Identities), amt)) } else { os.Stderr.WriteString(fmt.Sprintf("=== Identity List === Total: %d Displaying: %d\n", len(fnodes[listenTo].State.Identities), amt)) } for c, i := range fnodes[listenTo].State.Identities { if amt != -1 && c == amt+1 { break } stat := returnStatString(i.Status) if show == 5 { if c != amt { } else { os.Stderr.WriteString(fmt.Sprint("-----------------------------------Identity: ", amt, "---------------------------------------\n")) } } else { os.Stderr.WriteString(fmt.Sprint("-----------------------------------Identity: ", c, "---------------------------------------\n")) } if show == 0 || show == 5 { if show == 0 || c == amt { os.Stderr.WriteString(fmt.Sprint("Server Status: ", stat, "\n")) os.Stderr.WriteString(fmt.Sprint("Identity Chain: ", i.IdentityChainID, "\n")) os.Stderr.WriteString(fmt.Sprint("Management Chain: ", i.ManagementChainID, "\n")) os.Stderr.WriteString(fmt.Sprint("Matryoshka Hash: ", i.MatryoshkaHash, "\n")) os.Stderr.WriteString(fmt.Sprint("Key 1: ", i.Key1, "\n")) os.Stderr.WriteString(fmt.Sprint("Key 2: ", i.Key2, "\n")) os.Stderr.WriteString(fmt.Sprint("Key 3: ", i.Key3, "\n")) os.Stderr.WriteString(fmt.Sprint("Key 4: ", i.Key4, "\n")) os.Stderr.WriteString(fmt.Sprint("Signing Key: ", i.SigningKey, "\n")) for _, a := range i.AnchorKeys { os.Stderr.WriteString(fmt.Sprintf("Anchor Key: {'%s' L%x T%x K:%x}\n", a.BlockChain, a.KeyLevel, a.KeyType, a.SigningKey)) } } } else if show == 1 { os.Stderr.WriteString(fmt.Sprint("Server Salt: ", fnodes[c].State.Salt.String()[:16], "\n")) os.Stderr.WriteString(fmt.Sprint("Server Status: ", stat, "\n")) os.Stderr.WriteString(fmt.Sprint("Identity Chain: ", i.IdentityChainID, "\n")) os.Stderr.WriteString(fmt.Sprint("Management Chain: ", i.ManagementChainID, "\n")) } else if show == 2 { os.Stderr.WriteString(fmt.Sprint("Server Salt: ", fnodes[c].State.Salt.String()[:16], "\n")) os.Stderr.WriteString(fmt.Sprint("Server Status: ", stat, "\n")) os.Stderr.WriteString(fmt.Sprint("Identity Chain: ", i.IdentityChainID, "\n")) os.Stderr.WriteString(fmt.Sprint("Matryoshka Hash: ", i.MatryoshkaHash, "\n")) } else if show == 3 { os.Stderr.WriteString(fmt.Sprint("Server Salt: ", fnodes[c].State.Salt.String()[:16], "\n")) os.Stderr.WriteString(fmt.Sprint("Server Status: ", stat, "\n")) os.Stderr.WriteString(fmt.Sprint("Identity Chain: ", i.IdentityChainID, "\n")) os.Stderr.WriteString(fmt.Sprint("Signing Key: ", i.SigningKey, "\n")) } else if show == 4 { os.Stderr.WriteString(fmt.Sprint("Server Salt: ", fnodes[c].State.Salt.String()[:16], "\n")) os.Stderr.WriteString(fmt.Sprint("Server Status: ", stat, "\n")) os.Stderr.WriteString(fmt.Sprint("Identity Chain: ", i.IdentityChainID, "\n")) for _, a := range i.AnchorKeys { os.Stderr.WriteString(fmt.Sprintf("Anchor Key: {'%s' L%x T%x K:%x}\n", a.BlockChain, a.KeyLevel, a.KeyType, a.SigningKey)) } } } } case 't' == b[0]: if len(b) == 2 && b[1] == 'm' { _, _, auth := authKeyLookup(fnodes[listenTo].State.IdentityChainID) if auth == nil { break } fullSk := []byte{0x4d, 0xb6, 0xc9} fullSk = append(fullSk[:], auth.Sk1[:32]...) shadSk := shad(fullSk) fullSk = append(fullSk[:], shadSk[:4]...) os.Stderr.WriteString(fmt.Sprint("Identity of Current Node Information\n")) os.Stderr.WriteString(fmt.Sprintf("Server Salt: %s\n", fnodes[listenTo].State.Salt.String()[:16])) os.Stderr.WriteString(fmt.Sprintf("Root Chain ID: %s\n", fnodes[listenTo].State.IdentityChainID.String())) os.Stderr.WriteString(fmt.Sprintf("Sub Chain ID : %s\n", auth.ManageChain)) os.Stderr.WriteString(fmt.Sprintf("Sk1 Key (hex): %x\n", fullSk)) os.Stderr.WriteString(fmt.Sprintf("Signing Key (hex): %s\n", fnodes[listenTo].State.SimGetSigKey())) p := fnodes[listenTo].State.GetServerPrivateKey() str := hex.EncodeToString((p.Key)[:32]) os.Stderr.WriteString(fmt.Sprintf("Private Key (hex): %s\n", str)) break } else if len(b) == 2 && b[1] == 'c' { _, _, auth := authKeyLookup(fnodes[listenTo].State.IdentityChainID) if auth == nil { break } wsapiNode = listenTo wsapi.SetState(fnodes[wsapiNode].State) err := fundWallet(fnodes[listenTo].State, 1e8) if err != nil { os.Stderr.WriteString(fmt.Sprintf("Error in funding the wallet, %s\n", err.Error())) break } newKey, err := changeSigningKey(fnodes[listenTo].State.IdentityChainID, fnodes[listenTo].State) if err != nil { os.Stderr.WriteString(fmt.Sprintf("Error: %s\n", err.Error())) break } fnodes[listenTo].State.LocalServerPrivKey = newKey.PrivateKeyString() fnodes[listenTo].State.SetPendingSigningKey(newKey) os.Stderr.WriteString(fmt.Sprintf("New public key for [%s]: %s\n", fnodes[listenTo].State.IdentityChainID.String()[:8], newKey.Pub.String())) break } index := 0 if len(b) == 65 { hash, err := fnodes[listenTo].State.IdentityChainID.HexToHash(b[1:]) if err != nil { os.Stderr.WriteString(fmt.Sprintf("Error: %s\n", err.Error())) } else { fnodes[listenTo].State.IdentityChainID = hash key, pKey, _ := authKeyLookup(fnodes[listenTo].State.IdentityChainID) if len(key) == 64 { fnodes[listenTo].State.LocalServerPrivKey = key fnodes[listenTo].State.SimSetNewKeys(pKey) } os.Stderr.WriteString(fmt.Sprintf("Identity of " + fnodes[listenTo].State.GetFactomNodeName() + " changed to [" + hash.String()[:10] + "]\n")) } break } else if len(authKeyLibrary) == 0 { os.Stderr.WriteString(fmt.Sprint("There are no available identities in this node. Type 'g1' to claim another identity\n")) break } else if len(b) > 1 { index, err = strconv.Atoi(string(b[1:])) if err != nil { os.Stderr.WriteString(fmt.Sprint("Incorrect input. bN where N is a number\n")) break } } if index >= len(authKeyLibrary) { os.Stderr.WriteString(fmt.Sprintf("Identity index out of bounds, only %d in the list.\n", len(authKeyLibrary))) break } if authKeyLibrary[index].Taken == true { os.Stderr.WriteString(fmt.Sprintf("Identity %d already taken, taking next available identity in list\n", index)) } for index < len(authKeyLibrary) { if authKeyLibrary[index].Taken == false { authKeyLibrary[index].Taken = true fnodes[listenTo].State.IdentityChainID = authKeyLibrary[index].ChainID key, pKey, _ := authKeyLookup(fnodes[listenTo].State.IdentityChainID) fnodes[listenTo].State.LocalServerPrivKey = key fnodes[listenTo].State.SimSetNewKeys(pKey) os.Stderr.WriteString(fmt.Sprintf("Identity of " + fnodes[listenTo].State.GetFactomNodeName() + " changed to [" + authKeyLibrary[index].ChainID.String()[:10] + "]\n")) break } index++ } if index >= len(authKeyLibrary) { os.Stderr.WriteString(fmt.Sprint("There are no more available identities in this node. Type 'g1' to claim another identity\n")) } case 'u' == b[0]: os.Stderr.WriteString(fmt.Sprintf("=== Authority List === Total: %d Displaying: All\n", len(fnodes[listenTo].State.Authorities))) for _, i := range fnodes[listenTo].State.Authorities { os.Stderr.WriteString("-------------------------------------------------------------------------------\n") var stat string switch i.Status { case 0: stat = "Unassigned" case 1: stat = "Federated Server" case 2: stat = "Audit Server" case 3: stat = "Full" case 4: stat = "Pending Federated Server" case 5: stat = "Pending Audit Server" case 6: stat = "Pending Full" case 7: stat = "Pending" } os.Stderr.WriteString(fmt.Sprint("Server Status: ", stat, "\n")) os.Stderr.WriteString(fmt.Sprint("Identity Chain: ", i.AuthorityChainID, "\n")) os.Stderr.WriteString(fmt.Sprint("Management Chain: ", i.ManagementChainID, "\n")) os.Stderr.WriteString(fmt.Sprint("Matryoshka Hash: ", i.MatryoshkaHash, "\n")) os.Stderr.WriteString(fmt.Sprint("Signing Key: ", i.SigningKey.String(), "\n")) for _, a := range i.AnchorKeys { os.Stderr.WriteString(fmt.Sprintf("Anchor Key: {'%s' L%x T%x K:%x}\n", a.BlockChain, a.KeyLevel, a.KeyType, a.SigningKey)) } } case 'q' == b[0]: eHashes := fnodes[listenTo].State.GetPendingEntries() os.Stderr.WriteString("Pending Entry Hash\n") os.Stderr.WriteString("------------------\n") for _, eh := range eHashes { os.Stderr.WriteString(fmt.Sprint(eh.String(), "\n")) } case 'j' == b[0]: fpl := fnodes[listenTo].State.GetPendingTransactions() fmt.Println(fpl) case 'S' == b[0]: nnn, err := strconv.Atoi(string(b[1:])) if err != nil || nnn < 0 || nnn > 999 { os.Stderr.WriteString("Specifiy a drop amount between 0 and 1000\n") break } for _, fn := range fnodes { fn.State.DropRate = nnn os.Stderr.WriteString(fmt.Sprintf("Setting drop rate of %10s to %2d.%01d\n", fn.State.FactomNodeName, nnn/10, nnn%10)) } case 'O' == b[0]: if listenTo < 0 || listenTo > len(fnodes) { os.Stderr.WriteString("No Factom Node selected\n") break } nnn, err := strconv.Atoi(string(b[1:])) if err != nil || nnn < 0 || nnn > 999 { os.Stderr.WriteString("Specifiy a drop amount between 0 and 1000\n") break } fnodes[listenTo].State.DropRate = nnn os.Stderr.WriteString(fmt.Sprintf("Setting drop rate of %10s to %2d.%01d percent\n", fnodes[listenTo].State.FactomNodeName, nnn/10, nnn%10)) case 'F' == b[0]: nn, err := strconv.Atoi(string(b[1:])) nnn := int64(nn) if err != nil || nnn < 0 || nnn > 99999 { os.Stderr.WriteString("Specifiy a delay amount in milliseconds less than 100 seconds\n") break } for _, fn := range fnodes { fn.State.Delay = nnn os.Stderr.WriteString(fmt.Sprintf("Setting Delay on communications from %10s to %2d.%03d Seconds\n", fn.State.FactomNodeName, nnn/1000, nnn%1000)) } for _, f := range fnodes { for _, p := range f.Peers { sim, ok := p.(*SimPeer) if ok { sim.Delay = nnn } } } case 'D' == b[0]: if listenTo < 0 || listenTo > len(fnodes) { os.Stderr.WriteString("No Factom Node selected\n") break } nn, err := strconv.Atoi(string(b[1:])) nnn := int64(nn) if err != nil || nnn < 0 || nnn > 99999 { os.Stderr.WriteString("Specifiy a delay amount in milliseconds less than 100 seconds\n") break } for _, f := range fnodes { for _, p := range f.Peers { sim, ok := p.(*SimPeer) if ok { if sim.FromName == fnodes[listenTo].State.FactomNodeName { sim.Delay = nnn } } } } fnodes[listenTo].State.Delay = nnn os.Stderr.WriteString(fmt.Sprintf("Setting Delay on communications from %10s to %2d.%03d Seconds\n", fnodes[listenTo].State.FactomNodeName, nnn/1000, nnn%1000)) case 'h' == b[0]: os.Stderr.WriteString("-------------------------------------------------------------------------------\n") os.Stderr.WriteString("Vtest Run the fault test. Faults 1 to n/2-1 servers. Waits for next block + 60 sec. Repeats.\n") os.Stderr.WriteString("nnn For some number nnn < the number of nodes: Set focus on that node\n") os.Stderr.WriteString("n increment (with wrap) the node under focus. i.e. if on 1, focus is set to 2\n") os.Stderr.WriteString("Vtest Run the fault test. Faults 1 to n/2-1 servers. Waits for next block + 60 sec. Repeats.\n") os.Stderr.WriteString("aN Show Admin block N. Indicate node eg:\"a5\" to shows blocks for that node.\n") os.Stderr.WriteString("eN Show Entry Credit Block N. Indicate node eg:\"f5\" to shows blocks for that node.\n") os.Stderr.WriteString("fN Show Factoid block N. Indicate node eg:\"f5\" to shows blocks for that node.\n") os.Stderr.WriteString("dN Show Directory block N. Indicate node eg:\"d5\" to shows blocks for that node.\n") os.Stderr.WriteString("kN.M Show Entry Block and Chain Head. N is the directory block, and M is the Entry in that block.\n") os.Stderr.WriteString(" So K3.6 gets the directory block at height 3, and prints the entry at index 6.\n") os.Stderr.WriteString("y Dump what is in the Holding Map. Can crash, but oh well.\n") os.Stderr.WriteString("m Show Messages as they are passed through the simulator.\n") os.Stderr.WriteString("c Trace the Consensus Process\n") os.Stderr.WriteString("s Show the state of all nodes as their state changes in the simulator.\n") os.Stderr.WriteString("p Show the process lists and directory block states as they change.\n") os.Stderr.WriteString("n Change the focus to the next node.\n") os.Stderr.WriteString("l Make focused node the Leader.\n") os.Stderr.WriteString("lt Attach the next available identity to node and make focused node the Leader.\n") os.Stderr.WriteString("z Attempt to remove focused node as a federated server\n") os.Stderr.WriteString("za Attempt to remove focused node as a audit server\n") os.Stderr.WriteString("o Make focused an audit server.\n") os.Stderr.WriteString("x Take the given node out of the netork or bring an offline node back in.\n") os.Stderr.WriteString("w Point the WSAPI to send API calls to the current node.\n") os.Stderr.WriteString("iH To learn about identity control through simulator.\n") os.Stderr.WriteString("gN Adds 'N' identities to your identity pool. (Cannot add identities already taken)\n") os.Stderr.WriteString("tN Attaches Nth identity in pool to current node. Can also just press 't' to grab the next\n") os.Stderr.WriteString("i Shows the identities being monitored for change.\n") os.Stderr.WriteString("u Shows the current Authorities (federated or audit servers)\n") os.Stderr.WriteString("v Verbose Fault Debug Output\n") os.Stderr.WriteString("Vnnn Set full fault timeout to the given number of seconds. Helps debugging.\n") os.Stderr.WriteString("Vtest Run the fault test. Faults 1 to n/2-1 servers. Waits for next block + 60 sec. Repeats.\n") os.Stderr.WriteString("Vreset Reset all fnodes in the simulation.\n") os.Stderr.WriteString("! Reset the current node with the focus (i.e. the 'f' by it)\n") os.Stderr.WriteString("Snnn Set Drop Rate to nnn on everyone\n") os.Stderr.WriteString("Onnn Set Drop Rate to nnn on this node\n") os.Stderr.WriteString("Dnnn Set the Delay on messages from the current node to nnn milliseconds\n") os.Stderr.WriteString("Fnnn Set the Delay on messages from all nodes to nnn milliseconds\n") os.Stderr.WriteString("/ Toggle the sort order between ChainID and Factom Node Name\n") //os.Stderr.WriteString("i[m/b/a][N] Shows only the Mhash, block signing key, or anchor key up to the Nth identity\n") //os.Stderr.WriteString("isN Shows only Nth identity\n") os.Stderr.WriteString("h or <enter> Show help\n") os.Stderr.WriteString("\n") os.Stderr.WriteString("Commands are case sensitive.\n") os.Stderr.WriteString("-------------------------------------------------------------------------------\n\n") default: } } } }