// Run implements sda.Simulation interface func (e *Simulation) Run(sdaConf *sda.SimulationConfig) error { log.Lvl2("Naive Tree Simulation starting with: Rounds=", e.Rounds) server := NewNtreeServer(e.Blocksize) for round := 0; round < e.Rounds; round++ { client := byzcoin.NewClient(server) err := client.StartClientSimulation(blockchain.GetBlockDir(), e.Blocksize) if err != nil { log.Error("ClientSimulation:", err) } log.Lvl1("Starting round", round) // create an empty node node := sdaConf.Overlay.NewTreeNodeInstanceFromProtoName(sdaConf.Tree, "ByzCoinNtree") // instantiate a byzcoin protocol rComplete := monitor.NewTimeMeasure("round") pi, err := server.Instantiate(node) if err != nil { return err } sdaConf.Overlay.RegisterProtocolInstance(pi) nt := pi.(*Ntree) // Register when the protocol is finished (all the nodes have finished) done := make(chan bool) nt.RegisterOnDone(func(sig *NtreeSignature) { rComplete.Record() log.Lvl3("Done") done <- true }) go func() { if err := nt.Start(); err != nil { log.Error("Couldn't start ntree protocol:", err) } }() // wait for the end <-done log.Lvl3("Round", round, "finished") } return nil }
// Run is used on the destination machines and runs a number of // rounds func (e *simulation) Run(config *sda.SimulationConfig) error { size := config.Tree.Size() log.Lvl2("Size is:", size, "rounds:", e.Rounds) for round := 0; round < e.Rounds; round++ { log.Lvl1("Starting round", round) round := monitor.NewTimeMeasure("round") p, err := config.Overlay.CreateProtocolSDA(config.Tree, "Count") if err != nil { return err } go p.Start() children := <-p.(*ProtocolCount).Count round.Record() if children != size { return errors.New("Didn't get " + strconv.Itoa(size) + " children") } } return nil }
// Run implements sda.Simulation interface func (e *Simulation) Run(sdaConf *sda.SimulationConfig) error { log.Lvl2("Simulation starting with: Rounds=", e.Rounds) server := NewByzCoinServer(e.Blocksize, e.TimeoutMs, e.Fail) pi, err := sdaConf.Overlay.CreateProtocolSDA(sdaConf.Tree, "Broadcast") if err != nil { return err } proto, _ := pi.(*manage.Broadcast) // channel to notify we are done broadDone := make(chan bool) proto.RegisterOnDone(func() { broadDone <- true }) // ignore error on purpose: Broadcast.Start() always returns nil _ = proto.Start() // wait <-broadDone for round := 0; round < e.Rounds; round++ { client := NewClient(server) err := client.StartClientSimulation(blockchain.GetBlockDir(), e.Blocksize) if err != nil { log.Error("Error in ClientSimulation:", err) return err } log.Lvl1("Starting round", round) // create an empty node tni := sdaConf.Overlay.NewTreeNodeInstanceFromProtoName(sdaConf.Tree, "ByzCoin") if err != nil { return err } // instantiate a byzcoin protocol rComplete := monitor.NewTimeMeasure("round") pi, err := server.Instantiate(tni) if err != nil { return err } sdaConf.Overlay.RegisterProtocolInstance(pi) bz := pi.(*ByzCoin) // Register callback for the generation of the signature ! bz.RegisterOnSignatureDone(func(sig *BlockSignature) { rComplete.Record() if err := verifyBlockSignature(tni.Suite(), tni.Roster().Aggregate, sig); err != nil { log.Error("Round", round, "failed:", err) } else { log.Lvl2("Round", round, "success") } }) // Register when the protocol is finished (all the nodes have finished) done := make(chan bool) bz.RegisterOnDone(func() { done <- true }) if e.Fail > 0 { go func() { err := bz.startAnnouncementPrepare() if err != nil { log.Error("Error while starting "+ "announcment prepare:", err) } }() // do not run bz.startAnnouncementCommit() } else { go func() { if err := bz.Start(); err != nil { log.Error("Couldn't start protocol", err) } }() } // wait for the end <-done log.Lvl3("Round", round, "finished") } return nil }
func (m *monitorMut) NewMeasure(id string) { m.Lock() defer m.Unlock() m.TimeMeasure = monitor.NewTimeMeasure(id) }
// Main starts the host and will setup the protocol. func main() { flag.Parse() log.SetDebugVisible(debugVisible) log.Lvl3("Flags are:", hostAddress, simul, log.DebugVisible, monitorAddress) scs, err := sda.LoadSimulationConfig(".", hostAddress) measures := make([]*monitor.CounterIOMeasure, len(scs)) if err != nil { // We probably are not needed log.Lvl2(err, hostAddress) return } if monitorAddress != "" { if err := monitor.ConnectSink(monitorAddress); err != nil { log.Error("Couldn't connect monitor to sink:", err) } } sims := make([]sda.Simulation, len(scs)) var rootSC *sda.SimulationConfig var rootSim sda.Simulation for i, sc := range scs { // Starting all hosts for that server host := sc.Host measures[i] = monitor.NewCounterIOMeasure("bandwidth", host) log.Lvl3(hostAddress, "Starting host", host.ServerIdentity.Addresses) host.Listen() host.StartProcessMessages() sim, err := sda.NewSimulation(simul, sc.Config) if err != nil { log.Fatal(err) } err = sim.Node(sc) if err != nil { log.Fatal(err) } sims[i] = sim if host.ServerIdentity.ID == sc.Tree.Root.ServerIdentity.ID { log.Lvl2(hostAddress, "is root-node, will start protocol") rootSim = sim rootSC = sc } } if rootSim != nil { // If this cothority has the root-host, it will start the simulation log.Lvl2("Starting protocol", simul, "on host", rootSC.Host.ServerIdentity.Addresses) //log.Lvl5("Tree is", rootSC.Tree.Dump()) // First count the number of available children childrenWait := monitor.NewTimeMeasure("ChildrenWait") wait := true // The timeout starts with 1 second, which is the time of response between // each level of the tree. timeout := 1000 for wait { p, err := rootSC.Overlay.CreateProtocolSDA(rootSC.Tree, "Count") if err != nil { log.Fatal(err) } proto := p.(*manage.ProtocolCount) proto.SetTimeout(timeout) proto.Start() log.Lvl1("Started counting children with timeout of", timeout) select { case count := <-proto.Count: if count == rootSC.Tree.Size() { log.Lvl1("Found all", count, "children") wait = false } else { log.Lvl1("Found only", count, "children, counting again") } } // Double the timeout and try again if not successful. timeout *= 2 } childrenWait.Record() log.Lvl1("Starting new node", simul) measureNet := monitor.NewCounterIOMeasure("bandwidth_root", rootSC.Host) err := rootSim.Run(rootSC) if err != nil { log.Fatal(err) } measureNet.Record() // Test if all ServerIdentities are used in the tree, else we'll run into // troubles with CloseAll if !rootSC.Tree.UsesList() { log.Error("The tree doesn't use all ServerIdentities from the list!\n" + "This means that the CloseAll will fail and the experiment never ends!") } closeTree := rootSC.Tree if rootSC.GetSingleHost() { // In case of "SingleHost" we need a new tree that contains every // entity only once, whereas rootSC.Tree will have the same // entity at different TreeNodes, which makes it difficult to // correctly close everything. log.Lvl2("Making new root-tree for SingleHost config") closeTree = rootSC.Roster.GenerateBinaryTree() rootSC.Overlay.RegisterTree(closeTree) } pi, err := rootSC.Overlay.CreateProtocolSDA(closeTree, "CloseAll") pi.Start() if err != nil { log.Fatal(err) } } // Wait for all hosts to be closed allClosed := make(chan bool) go func() { for i, sc := range scs { sc.Host.WaitForClose() // record the bandwidth measures[i].Record() log.Lvl3(hostAddress, "Simulation closed host", sc.Host.ServerIdentity.Addresses, "closed") } allClosed <- true }() log.Lvl3(hostAddress, scs[0].Host.ServerIdentity.First(), "is waiting for all hosts to close") <-allClosed log.Lvl2(hostAddress, "has all hosts closed") monitor.EndAndCleanup() }
// Run runs the simulation func (e *Simulation) Run(sdaConf *sda.SimulationConfig) error { doneChan := make(chan bool) doneCB := func() { doneChan <- true } // FIXME use client instead dir := blockchain.GetBlockDir() parser, err := blockchain.NewParser(dir, magicNum) if err != nil { log.Error("Error: Couldn't parse blocks in", dir) return err } transactions, err := parser.Parse(0, e.Blocksize) if err != nil { log.Error("Error while parsing transactions", err) return err } // FIXME c&p from byzcoin.go trlist := blockchain.NewTransactionList(transactions, len(transactions)) header := blockchain.NewHeader(trlist, "", "") trblock := blockchain.NewTrBlock(trlist, header) // Here we first setup the N^2 connections with a broadcast protocol pi, err := sdaConf.Overlay.CreateProtocolSDA(sdaConf.Tree, "Broadcast") if err != nil { log.Error(err) } proto := pi.(*manage.Broadcast) // channel to notify we are done broadDone := make(chan bool) proto.RegisterOnDone(func() { broadDone <- true }) // ignore error on purpose: Start always returns nil _ = proto.Start() // wait <-broadDone log.Lvl3("Simulation can start!") for round := 0; round < e.Rounds; round++ { log.Lvl1("Starting round", round) p, err := sdaConf.Overlay.CreateProtocolSDA(sdaConf.Tree, "ByzCoinPBFT") if err != nil { return err } proto := p.(*Protocol) proto.trBlock = trblock proto.onDoneCB = doneCB r := monitor.NewTimeMeasure("round_pbft") err = proto.Start() if err != nil { log.Error("Couldn't start PrePrepare") return err } // wait for finishing pbft: <-doneChan r.Record() log.Lvl2("Finished round", round) } return nil }