// This file handles the creation a of cothority tree. // Basically, it takes a list of files generated by the "key" command by each // hosts and turn that into a full tree with the hostname and public key in each // node. // BuildTree takes a file formatted like this : // host pubKey // host2 pubKey // ... ... // For the moment it takes a branching factor on how to make the tree // and the name of the file where to write the config // It writes the tree + any other configs to output using toml format // with the app/config_conode.go struct func Build(hostFile string, bf int, configFile string) { // First, read the list of host and public keys hosts, pubs, err := readHostFile(hostFile) if err != nil { dbg.Fatal("Error reading the host file:", err) } // Then construct the tree tree := constructTree(hosts, pubs, bf) // then constrcut the aggregated public key K0 k0 := aggregateKeys(pubs) var b bytes.Buffer err = cliutils.WritePub64(suite, &b, k0) if err != nil { dbg.Fatal("Could not aggregate public keys in base64") } // Then write the config conf := app.ConfigConode{ Suite: suiteStr, Tree: tree, Hosts: hosts, AggPubKey: b.String(), } app.WriteTomlConfig(conf, configFile) dbg.Lvl1("Written config file with tree to", configFile) }
func init() { command := cli.Command{ Name: "check", Aliases: []string{"c"}, Usage: "Checks if a given CoNode is valid in order to be incorporated into a cothority tree", Description: "It checks the public key given and the availability of the server. It will be contacted multiple times a day during 24 hours", ArgsUsage: "Public-key-file: file where reside the public key of the host to check", Subcommands: []cli.Command{ { Name: "exit", Usage: "Asks the remote node to exit", Action: func(c *cli.Context) { if c.Args().First() == "" { dbg.Fatal("No public key file given for exit.") } CheckExit(c.Args().First()) }, }, }, Action: func(c *cli.Context) { if c.Args().First() == "" { dbg.Fatal("No public key file given for check.") } Check(c.Args().First()) }, } registerCommand(command) }
// Reads in the platform that we want to use and prepares for the tests func main() { flag.Parse() deployP = platform.NewPlatform(platform_dst) if deployP == nil { dbg.Fatal("Platform not recognized.", platform_dst) } dbg.Lvl1("Deploying to", platform_dst) simulations := flag.Args() if len(simulations) == 0 { dbg.Fatal("Please give a simulation to run") } for _, simulation := range simulations { runconfigs := platform.ReadRunFile(deployP, simulation) if len(runconfigs) == 0 { dbg.Fatal("No tests found in", simulation) } deployP.Configure() if clean { deployP.Deploy(runconfigs[0]) deployP.Cleanup() } else { logname := strings.Replace(filepath.Base(simulation), ".toml", "", 1) RunTests(logname, runconfigs) } } }
// Creates a new stamp listener one port above the // address given in nameP func NewStampListener(nameP string) *StampListener { // listen for client requests at one port higher // than the signing node var nameL string h, p, err := net.SplitHostPort(nameP) if err == nil { i, err := strconv.Atoi(p) if err != nil { dbg.Fatal(err) } nameL = net.JoinHostPort(h, strconv.Itoa(i+1)) } else { dbg.Fatal("Couldn't split host into name and port:", err) } sl, ok := SLList[nameL] if !ok { sl = &StampListener{} dbg.Lvl3("Creating new StampListener for", nameL) sl.Queue = make([][]MustReplyMessage, 2) sl.Queue[READING] = make([]MustReplyMessage, 0) sl.Queue[PROCESSING] = make([]MustReplyMessage, 0) sl.Clients = make(map[string]coconet.Conn) sl.waitClose = make(chan string) sl.NameL = nameL SLList[sl.NameL] = sl sl.ListenRequests() } else { dbg.Lvl3("Taking cached StampListener") } return sl }
func (d *Deterlab) Start(args ...string) error { // setup port forwarding for viewing log server d.started = true // Remote tunneling : the sink port is used both for the sink and for the // proxy => the proxy redirects packets to the same port the sink is // listening. // -n = stdout == /Dev/null, -N => no command stream, -T => no tty cmd := []string{"-nNTf", "-o", "StrictHostKeyChecking=no", "-o", "ExitOnForwardFailure=yes", "-R", d.ProxyRedirectionPort + ":" + d.ProxyRedirectionAddress + ":" + monitor.SinkPort, fmt.Sprintf("%s@%s", d.Login, d.Host)} exCmd := exec.Command("ssh", cmd...) if err := exCmd.Start(); err != nil { dbg.Fatal("Failed to start the ssh port forwarding:", err) } if err := exCmd.Wait(); err != nil { dbg.Fatal("ssh port forwarding exited in failure:", err) } dbg.Lvl3("Setup remote port forwarding", cmd) go func() { err := cliutils.SshRunStdout(d.Login, d.Host, "cd remote; GOMAXPROCS=8 ./users") if err != nil { dbg.Lvl3(err) } d.sshDeter <- "finished" }() return nil }
// The signer connects to the leader and then waits for a message to be // signed func GoSigner(conf *app.NaiveConfig) { // Wait for leader to be ready time.Sleep(2 * time.Second) host := net.NewTcpHost(app.RunFlags.Hostname) key := cliutils.KeyPair(suite) signer := NewPeer(host, ServRole, key.Secret, key.Public) dbg.Lvl3(signer.String(), "will contact leader", conf.Hosts[0]) l := signer.Open(conf.Hosts[0]) dbg.Lvl3(signer.String(), "is connected to leader", l.PeerName()) // make the protocol for each round for round := 0; round < conf.Rounds; round++ { // Receive message m, err := l.Receive() dbg.Lvl3(signer.String(), "round", round, "received the message to be signed from the leader") if err != nil { dbg.Fatal(signer.String(), "round", round, "received error waiting msg") } if m.MsgType != net.MessageSigningType { dbg.Fatal(app.RunFlags.Hostname, "round", round, "wanted to receive a msg to sign but..", m.MsgType.String()) } msg := m.Msg.(net.MessageSigning).Msg dbg.Lvl3(signer.String(), "round", round, "received msg:", msg[:]) // Generate signature & send s := signer.Signature(msg[:]) l.Send(*s) dbg.Lvl3(signer.String(), "round", round, "sent the signature to leader") } l.Close() dbg.Lvl3(app.RunFlags.Hostname, "Finished") }
// SynWithPeer will receive and send the public keys between the peer // If all goes well, it will add the peer to the remotePeer array // and notify to the channel synChan func (p *Peer) synWithPeer(conn net.Conn) { if conn == nil { dbg.Fatal("Connection of", p.String(), "is nil") } // First we need to SYN mutually s := Syn{ Id: p.Id, Public: p.key.Public, } err := p.suite.Write(conn, &s) if err != nil { dbg.Fatal(p.Name, "could not send SYN to", conn.RemoteAddr().String()) } // Receive the other SYN s2 := Syn{} err = p.suite.Read(conn, &s2) if err != nil { dbg.Fatal(p.Name, "could not receive SYN from", conn.RemoteAddr().String()) } if s2.Id < 0 || s2.Id >= p.info.N { dbg.Fatal(p.Name, "received wrong SYN info from", conn.RemoteAddr().String()) } if p.pubKeys[s2.Id] != nil { dbg.Fatal(p.Name, "already received a SYN for this index ") } p.pubKeys[s2.Id] = s2.Public rp := RemotePeer{Conn: conn, Id: s2.Id, Hostname: conn.RemoteAddr().String()} p.remote[s2.Id] = rp dbg.Lvl3(p.String(), "has SYN'd with peer", rp.String()) p.synChan <- s2 }
// BroadcastSIgnature will broadcast the given signature to every other peer // AND will retrieve the signature of every other peer also ! func (p *Peer) BroadcastSignature(s *poly.SchnorrSig) []*poly.SchnorrSig { arr := make([]*poly.SchnorrSig, 0, p.info.N) arr = append(arr, s) err := p.SendToAll(s) if err != nil { dbg.Fatal(p.String(), "could not sent to everyone its schnorr sig") } sigChan := make(chan *poly.SchnorrSig) fn := func(rp RemotePeer) { sch := new(poly.SchnorrSig).Init(p.suite, p.info) err := p.suite.Read(rp.Conn, sch) if err != nil { dbg.Fatal(p.String(), "could not decode schnorr sig from", rp.String()) } sigChan <- sch } // wait for every peers's schnorr sig p.ForRemotePeers(fn) n := 0 for { sig := <-sigChan arr = append(arr, sig) n += 1 if n == p.info.N-1 { dbg.Lvl3(p.String(), "received every other schnorr sig.") break } } return arr }
// ComputeSharedSecret will make the exchange of dealers between // the peers and will compute the sharedsecret at the end func (p *Peer) ComputeSharedSecret() *poly.SharedSecret { // Construct the dealer dealerKey := cliutils.KeyPair(p.suite) dealer := new(poly.Deal).ConstructDeal(&dealerKey, &p.key, p.info.T, p.info.R, p.pubKeys) // Construct the receiver receiver := poly.NewReceiver(p.suite, p.info, &p.key) // add already its own dealer _, err := receiver.AddDeal(p.Id, dealer) if err != nil { dbg.Fatal(p.String(), "could not add its own dealer >< ABORT") } // Send the dealer struct TO every one err = p.SendToAll(dealer) dbg.Lvl3(p.Name, "sent its dealer to every peers. (err =", err, ")") // Receive the dealer struct FROM every one // wait with a chan to get ALL dealers dealChan := make(chan *poly.Deal) for _, rp := range p.remote { go func(rp RemotePeer) { d := new(poly.Deal).UnmarshalInit(p.info.T, p.info.R, p.info.N, p.suite) err := p.suite.Read(rp.Conn, d) if err != nil { dbg.Fatal(p.Name, "received a strange dealer from", rp.String(), ":", err) } dealChan <- d }(rp) } // wait to get all dealers dbg.Lvl3(p.Name, "wait to receive every other peer's dealer...") n := 0 for { // get the dealer and add it d := <-dealChan dbg.Lvl3(p.Name, "collected one more dealer (count =", n, ")") // TODO: get the response back to the dealer _, err := receiver.AddDeal(p.Id, d) if err != nil { dbg.Fatal(p.Name, "has error when adding the dealer:", err) } n += 1 // we get enough dealers to compute the shared secret if n == p.info.T-1 { dbg.Lvl3(p.Name, "received every Dealers") break } } sh, err := receiver.ProduceSharedSecret() if err != nil { dbg.Fatal(p.Name, "could not produce shared secret. Abort. (err", err, ")") } dbg.Lvl3(p.Name, "produced shared secret !") return sh }
/* * Writes any structure to a toml-file * * Takes a filename and an optional directory-name. */ func WriteTomlConfig(conf interface{}, filename string, dirOpt ...string) { buf := new(bytes.Buffer) if err := toml.NewEncoder(buf).Encode(conf); err != nil { dbg.Fatal(err) } err := ioutil.WriteFile(getFullName(filename, dirOpt...), buf.Bytes(), 0660) if err != nil { dbg.Fatal(err) } }
func (l *Peer) ReceiveMessage(c net.Conn) net.MessageSigning { app, err := c.Receive() if err != nil { dbg.Fatal(l.String(), "could not receive message from", c.PeerName()) } if app.MsgType != net.MessageSigningType { dbg.Fatal(l.String(), "MS error: received", app.MsgType.String(), "from", c.PeerName()) } return app.Msg.(net.MessageSigning) }
func (l *Peer) ReceiveListBasicSignature(c net.Conn) net.ListBasicSignature { app, err := c.Receive() if err != nil { dbg.Fatal(l.String(), "could not receive listbasicsig from", c.PeerName()) } if app.MsgType != net.ListBasicSignatureType { dbg.Fatal(l.String(), "LBS error: received", app.MsgType.String(), "from", c.PeerName()) } return app.Msg.(net.ListBasicSignature) }
// Wait for the leader to receive the generated signatures from the servers func (l *Peer) ReceiveBasicSignature(c net.Conn) *net.BasicSignature { appMsg, err := c.Receive() if err != nil { dbg.Fatal(l.String(), "error decoding message from", c.PeerName()) } if appMsg.MsgType != net.BasicSignatureType { dbg.Fatal(l.String(), "Received an unknown type:", appMsg.MsgType.String()) } bs := appMsg.Msg.(net.BasicSignature) return &bs }
// Will send the message to be signed to everyone func (l *Peer) SendMessage(msg []byte, c net.Conn) { if len(msg) > msgMaxLenght { dbg.Fatal("Tried to send a too big message to sign. Abort") } ms := new(net.MessageSigning) ms.Length = len(msg) ms.Msg = msg err := c.Send(*ms) if err != nil { dbg.Fatal("Could not send message to", c.PeerName()) } }
// SchnorrSigRoot will first generate a // random shared secret, then start a new round // It will wait for the partial sig of the peers // to finally render a SchnorrSig struct func (p *Peer) SchnorrSigRoot(msg []byte) *poly.SchnorrSig { // First, gen. a random secret random := p.ComputeSharedSecret() // gen the hash out of the msg h := p.suite.Hash() h.Write(msg) // launch the new round err := p.schnorr.NewRound(random, h) if err != nil { dbg.Fatal(p.String(), "could not make a new round:", err) } // compute its own share of the signature ps := p.schnorr.RevealPartialSig() // add its own p.schnorr.AddPartialSig(ps) // no need to send to all if you are the root // p.SendToAll(ps) // then receive every partial sig sigChan := make(chan *poly.SchnorrPartialSig) fn := func(rp RemotePeer) { psig := new(poly.SchnorrPartialSig) err := p.suite.Read(rp.Conn, psig) if err != nil { dbg.Fatal(p.String(), "could not decode PartialSig of", rp.String()) } sigChan <- psig } p.ForRemotePeers(fn) // wait for all partial sig to be received n := 0 for { psig := <-sigChan err := p.schnorr.AddPartialSig(psig) if err != nil { dbg.Fatal(p.String(), "could not add the partial signature received:", err) } n += 1 if n == p.info.N-1 { dbg.Lvl3(p.String(), "received every other partial sig.") break } } sign, err := p.schnorr.Sig() if err != nil { dbg.Fatal(p.String(), "could not generate the global SchnorrSig", err) } return sign }
func main() { Current := new(Node) Magic := [4]byte{0xF9, 0xBE, 0xB4, 0xD9} Current.IP = net.IPv4(0, 1, 2, 3) Current.PublicKey = "my_cool_key" Current.Last_Block = "0" Parser, _ := BitCoSi.NewParser("/home/lefteris/hi/blocks", Magic) server := "localhost:2011" // suite = app.GetSuite("25519") dbg.Lvl2("Connecting to", server) conn := coconet.NewTCPConn(server) err := conn.Connect() if err != nil { dbg.Fatal("Error when getting the connection to the host:", err) } dbg.Lvl1("Connected to ", server) go wait_for_blocks() for i := 0; i < 10; i++ { Current.transaction_pool = Parser.Parse(i, 10+i) for len(Current.transaction_pool) > 0 { msg := &BitCoSi.BitCoSiMessage{ Type: BitCoSi.TransactionAnnouncmentType, ReqNo: 0, Treq: &BitCoSi.TransactionAnnouncment{Val: Current.transaction_pool[0]}} err = conn.PutData(msg) Current.transaction_pool = Current.transaction_pool[1:] if err != nil { dbg.Fatal("Couldn't send hash-message to server: ", err) } time.Sleep(10 * time.Millisecond) } } wait_for_Key_blocks() time.Sleep(900000 * time.Millisecond) // Asking to close the connection err = conn.PutData(&BitCoSi.BitCoSiMessage{ ReqNo: 1, Type: BitCoSi.BitCoSiClose, }) conn.Close() dbg.Lvl2("Connection closed with server") }
func wait_for_blocks() { server := "localhost:2011" suite = app.GetSuite("25519") dbg.Lvl2("Connecting to", server) conn := coconet.NewTCPConn(server) err := conn.Connect() if err != nil { dbg.Fatal("Error when getting the connection to the host:", err) } dbg.Lvl1("Connected to ", server) for i := 0; i < 1000; i++ { time.Sleep(1 * time.Second) msg := &BitCoSi.BitCoSiMessage{ Type: BitCoSi.BlockRequestType, ReqNo: 0, } err = conn.PutData(msg) if err != nil { dbg.Fatal("Couldn't send hash-message to server: ", err) } dbg.Lvl1("Sent signature request") // Wait for the signed message tsm := new(BitCoSi.BitCoSiMessage) tsm.Brep = &BitCoSi.BlockReply{} tsm.Brep.SuiteStr = suite.String() err = conn.GetData(tsm) if err != nil { dbg.Fatal("Error while receiving signature:", err) } //dbg.Lvlf1("Got signature response %+v", tsm.Brep) T := new(BitCoSi.TrBlock) T.Block = tsm.Brep.Block T.Print() dbg.Lvlf1("Response %v ", tsm.Brep.Response) } // Asking to close the connection err = conn.PutData(&BitCoSi.BitCoSiMessage{ ReqNo: 1, Type: BitCoSi.BitCoSiClose, }) conn.Close() }
// NewPeer returns a peer that can be used to set up // connections. func NewPeer(address string, conf *app.ConfigConode) *Peer { suite := app.GetSuite(conf.Suite) var err error // make sure address has a port or insert default one address, err = cliutils.VerifyPort(address, DefaultPort) if err != nil { dbg.Fatal(err) } // For retro compatibility issues, convert the base64 encoded key into hex // encoded keys.... convertTree(suite, conf.Tree) // Add our private key to the tree (compatibility issues again with graphs/ // lib) addPrivateKey(suite, address, conf) // load the configuration dbg.Lvl3("loading configuration") var hc *graphs.HostConfig opts := graphs.ConfigOptions{ConnType: "tcp", Host: address, Suite: suite} hc, err = graphs.LoadConfig(conf.Hosts, conf.Tree, suite, opts) if err != nil { dbg.Fatal(err) } // Listen to stamp-requests on port 2001 node := hc.Hosts[address] peer := &Peer{ conf: conf, Node: node, RLock: sync.Mutex{}, CloseChan: make(chan bool, 5), Hostname: address, } // Start the cothority-listener on port 2000 err = hc.Run(true, sign.MerkleTree, address) if err != nil { dbg.Fatal(err) } go func() { err := peer.Node.Listen() dbg.Lvl3("Node.listen quits with status", err) peer.CloseChan <- true peer.Close() }() return peer }
func (p *Peer) Listen() { results := strings.Split(p.Name, ":") port := ":" + results[1] ln, err := net.Listen("tcp", port) if err != nil { dbg.Fatal(p.Name, ": Error while listening on port", port, "ABORT =>", err) } for { conn, err := ln.Accept() if err != nil { dbg.Fatal(p.Name, ": Error while listening on port", port, "=>", err) } go p.synWithPeer(conn) } }
// readKeyPair will read both private and public files // and returns a keypair containing the respective private and public keys func readKeyFile(keyFile string) (config.KeyPair, string) { sec, err := cliutils.ReadPrivKey(suite, namePriv(keyFile)) if err != nil { dbg.Fatal("Could not read private key:", err) } pub, addr, err := cliutils.ReadPubKey(suite, namePub(keyFile)) if err != nil { dbg.Fatal("Could not read public key:", err) } return config.KeyPair{ Suite: suite, Secret: sec, Public: pub, }, addr }
// readHostFile will read the host file // HOSTNAME PUBLICKEY // for each line. and returns the whole set and any errror if any are found. func readHostFile(file string) ([]string, []string, error) { // open it up hostFile, err := os.Open(file) if err != nil { return nil, nil, err } // Then read it up hosts := make([]string, 0) pubs := make([]string, 0) scanner := bufio.NewScanner(hostFile) ln := 0 for scanner.Scan() { line := scanner.Text() ln += 1 spl := strings.Split(line, " ") if len(spl) != 2 { return nil, nil, errors.New(fmt.Sprintf("Hostfile misformatted at line %s", ln)) } // add it HOSTS -> PUBLIC KEY h, err := cliutils.VerifyPort(spl[0], conode.DefaultPort) if err != nil { dbg.Fatal("Error reading address in host file:", spl[0], err) } hosts = append(hosts, h) pubs = append(pubs, spl[1]) } dbg.Lvl1("Read the hosts files:", ln, "entries") return hosts, pubs, nil }
func (sn *Node) TryViewChange(view int) error { dbg.Lvl4(sn.Name(), "TRY VIEW CHANGE on", view, "with last view", sn.ViewNo) // should ideally be compare and swap sn.viewmu.Lock() if view <= sn.ViewNo { sn.viewmu.Unlock() return errors.New("trying to view change on previous/ current view") } if sn.ChangingView { sn.viewmu.Unlock() return ChangingViewError } sn.ChangingView = true sn.viewmu.Unlock() // take action if new view root if sn.Name() == sn.RootFor(view) { dbg.Fatal(sn.Name(), "Initiating view change for view:", view, "BTH") /* go func() { err := sn.StartVotingRound( &Vote{ View: view, Type: ViewChangeVT, Vcv: &ViewChangeVote{ View: view, Root: sn.Name()}}) if err != nil { dbg.Lvl2(sn.Name(), "Try view change failed:", err) } }() */ } return nil }
func (sr *StampSignature) UnmarshalJSON(dataJSON []byte) error { type Alias StampSignature suite := app.GetSuite(sr.SuiteStr) aux := &struct { BinaryBlob []byte Response abstract.Secret Challenge abstract.Secret AggCommit abstract.Point AggPublic abstract.Point *Alias }{ Response: suite.Secret(), Challenge: suite.Secret(), AggCommit: suite.Point(), AggPublic: suite.Point(), Alias: (*Alias)(sr), } if err := json.Unmarshal(dataJSON, &aux); err != nil { return err } if err := suite.Read(bytes.NewReader(aux.BinaryBlob), &sr.Response, &sr.Challenge, &sr.AggCommit, &sr.AggPublic); err != nil { dbg.Fatal("decoding signature Response / Challenge / AggCommit:", err) return err } return nil }
// Open will create a new connection between this host // and the remote host named "name". This is a TcpConn. // If anything went wrong, Conn will be nil. func (t *TcpHost) Open(name string) Conn { var conn net.Conn var err error for i := 0; i < maxRetry; i++ { conn, err = net.Dial("tcp", name) if err != nil { dbg.Lvl3(t.Name(), "(", i, "/", maxRetry, ") Error opening connection to", name) time.Sleep(waitRetry) } else { break } time.Sleep(waitRetry) } if conn == nil { dbg.Fatal(t.Name(), "could not connect to", name, ": ABORT") } c := TcpConn{ Peer: name, Conn: conn, enc: gob.NewEncoder(conn), dec: gob.NewDecoder(conn), host: t, } t.peers[name] = &c return &c }
// ConnectTo will connect to the given host and start the SYN exchange (public key + id) func (p *Peer) ConnectTo(host string) error { tick := time.NewTicker(ConnWaitRetry) count := 0 for range tick.C { // connect conn, err := net.Dial("tcp", host) if err != nil { // we have tried too many times => abort if count == ConnRetry { tick.Stop() dbg.Fatal(p.Name, "could not connect to", host, "", ConnRetry, "times. Abort.") // let's try again one more time } else { dbg.Lvl2(p.Name, "could not connect to", host, ". Retry in", ConnWaitRetry.String()) count += 1 } } // handle successful connection dbg.Lvl3(p.Name, "has connected with peer", host) tick.Stop() // start to syn with the respective peer go p.synWithPeer(conn) break } return nil }
func init() { command := cli.Command{ Name: "build", Aliases: []string{"b"}, Usage: "Builds a cothority configuration file required for CoNodes and clients", Description: "Basically it will statically generate the tree, with the respective names and public key", ArgsUsage: "HOSTFILE: file where each line is a copy of a public key node ( <address> <pubkey in b64> )", Flags: []cli.Flag{ cli.IntFlag{ Name: "bf", Value: 2, Usage: "Defines the branching factor we want in the cothority tree. Default is 2", }, cli.StringFlag{ Name: "config", Value: defaultConfigFile, Usage: "where to write the generated cothority configuration file", }, }, Action: func(c *cli.Context) { if c.Args().First() == "" { dbg.Fatal("You must provide a host file to generate the config") } Build(c.Args().First(), c.Int("bf"), c.String("config")) }, } registerCommand(command) }
func get64(str string) []byte { ret, err := base64.StdEncoding.DecodeString(str) if err != nil { dbg.Fatal("Couldn't decode", str) } return ret }
/* Reads in a configuration-file for a run. The configuration-file has the * following syntax: * Name1 = value1 * Name2 = value2 * [empty line] * n1, n2, n3, n4 * v11, v12, v13, v14 * v21, v22, v23, v24 * * The Name1...Namen are global configuration-options. * n1..nn are configuration-options for one run * Both the global and the run-configuration are copied to both * the platform and the app-configuration. */ func ReadRunFile(p Platform, filename string) []RunConfig { var runconfigs []RunConfig masterConfig := NewRunConfig() dbg.Lvl3("Reading file", filename) file, err := os.Open(filename) defer file.Close() if err != nil { dbg.Fatal("Couldn't open file", file, err) } // Decoding of the first part of the run config file // where the config wont change for the whole set of the simulation's tests scanner := bufio.NewScanner(file) for scanner.Scan() { text := scanner.Text() dbg.Lvl3("Decoding", text) // end of the first part if text == "" { break } // checking if format is good vals := strings.Split(text, "=") if len(vals) != 2 { dbg.Fatal("Simulation file:", filename, " is not properly formatted ( key = value )") } // fill in the general config masterConfig.Put(strings.TrimSpace(vals[0]), strings.TrimSpace(vals[1])) // also put it in platform toml.Decode(text, p) dbg.Lvlf3("Platform is now %+v", p) } scanner.Scan() args := strings.Split(scanner.Text(), ", ") for scanner.Scan() { rc := masterConfig.Clone() // put each individual test configs for i, value := range strings.Split(scanner.Text(), ", ") { rc.Put(strings.TrimSpace(args[i]), strings.TrimSpace(value)) } runconfigs = append(runconfigs, *rc) } return runconfigs }
// Simple ephemeral helper for compatibility issues // From base64 => hexadecimal func convertTree(suite abstract.Suite, t *graphs.Tree) { if t.PubKey != "" { point, err := cliutils.ReadPub64(suite, strings.NewReader(t.PubKey)) if err != nil { dbg.Fatal("Could not decode base64 public key") } str, err := cliutils.PubHex(suite, point) if err != nil { dbg.Fatal("Could not encode point to hexadecimal") } t.PubKey = str } for _, c := range t.Children { convertTree(suite, c) } }
// Helper functions that will return the suite used during the process from a string name func GetSuite(suite string) abstract.Suite { s, ok := suites.All()[suite] if !ok { dbg.Lvl1("Suites available:", suites.All()) dbg.Fatal("Didn't find suite", suite) } return s }