예제 #1
0
// 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
}
예제 #2
0
// 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
}
예제 #3
0
// 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
}
예제 #4
0
func (m *monitorMut) NewMeasure(id string) {
	m.Lock()
	defer m.Unlock()
	m.TimeMeasure = monitor.NewTimeMeasure(id)
}
예제 #5
0
// 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()
}
예제 #6
0
// 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
}