// startDaemonCmd uses the config parameters to start siad. func startDaemon() error { // Establish multithreading. runtime.GOMAXPROCS(runtime.NumCPU()) // Create all of the modules. gateway, err := gateway.New(config.Siad.RPCaddr, filepath.Join(config.Siad.SiaDir, modules.GatewayDir)) if err != nil { return err } state, err := consensus.New(gateway, filepath.Join(config.Siad.SiaDir, modules.ConsensusDir)) if err != nil { return err } hostdb, err := hostdb.New(state, gateway) if err != nil { return err } explorer, err := explorer.New(state, filepath.Join(config.Siad.SiaDir, modules.ExplorerDir)) if err != nil { return err } srv, err := api.NewServer(config.Siad.APIaddr, state, gateway, nil, hostdb, nil, nil, nil, nil, explorer) if err != nil { return err } // Bootstrap to the network. if !config.Siad.NoBootstrap { for i := range modules.BootstrapPeers { go gateway.Connect(modules.BootstrapPeers[i]) } } // Send a struct down the started channel, so the testing package knows // that daemon startup has completed. A gofunc is used with the hope that // srv.Serve() will start running before the value is sent down the // channel. go func() { started <- struct{}{} }() // Start serving api requests. err = srv.Serve() if err != nil { return err } return nil }
// assembleExplorerServerTester creates all the explorer dependencies and // explorer module without creating any directories. The user agent requirement // is disabled. func assembleExplorerServerTester(testdir string) (*serverTester, error) { // assembleExplorerServerTester should not get called during short tests, // as it takes a long time to run. if testing.Short() { panic("assembleServerTester called during short tests") } // Create the modules. g, err := gateway.New("localhost:0", false, filepath.Join(testdir, modules.GatewayDir)) if err != nil { return nil, err } cs, err := consensus.New(g, false, filepath.Join(testdir, modules.ConsensusDir)) if err != nil { return nil, err } e, err := explorer.New(cs, filepath.Join(testdir, modules.ExplorerDir)) if err != nil { return nil, err } srv, err := NewServer("localhost:0", "", "", cs, e, g, nil, nil, nil, nil, nil) if err != nil { return nil, err } // Assemble the serverTester. st := &serverTester{ cs: cs, explorer: e, gateway: g, server: srv, dir: testdir, } // TODO: A more reasonable way of listening for server errors. go func() { listenErr := srv.Serve() if listenErr != nil { panic(listenErr) } }() return st, nil }
// assembleExplorerServerTester creates all the explorer dependencies and // explorer module without creating any directories. The user agent requirement // is disabled. func assembleExplorerServerTester(testdir string) (*serverTester, error) { // Create the modules. g, err := gateway.New(":0", filepath.Join(testdir, modules.GatewayDir)) if err != nil { return nil, err } cs, err := consensus.New(g, filepath.Join(testdir, modules.ConsensusDir)) if err != nil { return nil, err } e, err := explorer.New(cs, filepath.Join(testdir, modules.ExplorerDir)) if err != nil { return nil, err } srv, err := NewServer(":0", "", cs, e, g, nil, nil, nil, nil, nil) if err != nil { return nil, err } // Assemble the serverTester. st := &serverTester{ cs: cs, explorer: e, gateway: g, server: srv, dir: testdir, } // TODO: A more reasonable way of listening for server errors. go func() { listenErr := srv.Serve() if listenErr != nil { panic(listenErr) } }() return st, nil }
// assembleServerTester creates a bunch of modules and assembles them into a // server tester, without creating any directories or mining any blocks. func assembleServerTester(key crypto.TwofishKey, testdir string) (*serverTester, error) { // Create the modules. g, err := gateway.New(":0", filepath.Join(testdir, modules.GatewayDir)) if err != nil { return nil, err } cs, err := consensus.New(g, filepath.Join(testdir, modules.ConsensusDir)) if err != nil { return nil, err } tp, err := transactionpool.New(cs, g) if err != nil { return nil, err } w, err := wallet.New(cs, tp, filepath.Join(testdir, modules.WalletDir)) if err != nil { return nil, err } if !w.Encrypted() { _, err = w.Encrypt(key) if err != nil { return nil, err } } err = w.Unlock(key) if err != nil { return nil, err } m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.MinerDir)) if err != nil { return nil, err } h, err := host.New(cs, tp, w, ":0", filepath.Join(testdir, modules.HostDir)) if err != nil { return nil, err } r, err := renter.New(cs, w, tp, filepath.Join(testdir, modules.RenterDir)) if err != nil { return nil, err } e, err := explorer.New(cs, filepath.Join(testdir, modules.ExplorerDir)) if err != nil { return nil, err } srv, err := NewServer(":0", "Sia-Agent", cs, e, g, h, m, r, tp, w) if err != nil { return nil, err } // Assemble the serverTester. st := &serverTester{ cs: cs, gateway: g, host: h, miner: m, renter: r, tpool: tp, explorer: e, wallet: w, walletKey: key, server: srv, dir: testdir, } // TODO: A more reasonable way of listening for server errors. go func() { listenErr := srv.Serve() if listenErr != nil { panic(listenErr) } }() return st, nil }
// createServerTester creates a server tester object that is ready for testing, // including money in the wallet and all modules initalized. func createServerTester(name string) (*serverTester, error) { // Create the testing directory and assign the api port. testdir := build.TempDir("api", name) APIAddr := ":" + strconv.Itoa(APIPort) APIPort++ // Create the modules. g, err := gateway.New(":0", filepath.Join(testdir, modules.GatewayDir)) if err != nil { return nil, err } cs, err := consensus.New(g, filepath.Join(testdir, modules.ConsensusDir)) if err != nil { return nil, err } tp, err := transactionpool.New(cs, g) if err != nil { return nil, err } w, err := wallet.New(cs, tp, filepath.Join(testdir, modules.WalletDir)) if err != nil { return nil, err } key, err := crypto.GenerateTwofishKey() if err != nil { return nil, err } _, err = w.Encrypt(key) if err != nil { return nil, err } err = w.Unlock(key) if err != nil { return nil, err } m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.MinerDir)) if err != nil { return nil, err } hdb, err := hostdb.New(cs, g) if err != nil { return nil, err } h, err := host.New(cs, hdb, tp, w, ":0", filepath.Join(testdir, modules.HostDir)) if err != nil { return nil, err } r, err := renter.New(cs, hdb, w, filepath.Join(testdir, modules.RenterDir)) if err != nil { return nil, err } exp, err := explorer.New(cs, filepath.Join(testdir, modules.ExplorerDir)) if err != nil { return nil, err } srv, err := NewServer(APIAddr, cs, g, h, hdb, m, r, tp, w, exp) if err != nil { return nil, err } // Assemble the serverTester. st := &serverTester{ cs: cs, gateway: g, host: h, hostdb: hdb, miner: m, renter: r, tpool: tp, exp: exp, wallet: w, walletKey: key, server: srv, } // TODO: A more reasonable way of listening for server errors. go func() { listenErr := srv.Serve() if listenErr != nil { panic(listenErr) } }() // Mine blocks until the wallet has confirmed money. for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ { _, err := st.miner.AddBlock() if err != nil { return nil, err } } return st, nil }
// startDaemonCmd uses the config parameters to start siad. func startDaemon(config Config) (err error) { // Prompt user for API password. var password string if config.Siad.AuthenticateAPI { password, err = speakeasy.Ask("Enter API password: "******"" { return errors.New("password cannot be blank") } passwordConfirm, err := speakeasy.Ask("Confirm API password: "******"passwords don't match") } } // Print a startup message. fmt.Println("Loading...") loadStart := time.Now() // Create all of the modules. i := 0 var g modules.Gateway if strings.Contains(config.Siad.Modules, "g") { i++ fmt.Printf("(%d/%d) Loading gateway...\n", i, len(config.Siad.Modules)) g, err = gateway.New(config.Siad.RPCaddr, filepath.Join(config.Siad.SiaDir, modules.GatewayDir)) if err != nil { return err } } var cs modules.ConsensusSet if strings.Contains(config.Siad.Modules, "c") { i++ fmt.Printf("(%d/%d) Loading consensus...\n", i, len(config.Siad.Modules)) cs, err = consensus.New(g, filepath.Join(config.Siad.SiaDir, modules.ConsensusDir)) if err != nil { return err } } var e modules.Explorer if strings.Contains(config.Siad.Modules, "e") { i++ fmt.Printf("(%d/%d) Loading explorer...\n", i, len(config.Siad.Modules)) e, err = explorer.New(cs, filepath.Join(config.Siad.SiaDir, modules.ExplorerDir)) if err != nil { return err } } var tpool modules.TransactionPool if strings.Contains(config.Siad.Modules, "t") { i++ fmt.Printf("(%d/%d) Loading transaction pool...\n", i, len(config.Siad.Modules)) tpool, err = transactionpool.New(cs, g, filepath.Join(config.Siad.SiaDir, modules.TransactionPoolDir)) if err != nil { return err } } var w modules.Wallet if strings.Contains(config.Siad.Modules, "w") { i++ fmt.Printf("(%d/%d) Loading wallet...\n", i, len(config.Siad.Modules)) w, err = wallet.New(cs, tpool, filepath.Join(config.Siad.SiaDir, modules.WalletDir)) if err != nil { return err } } var m modules.Miner if strings.Contains(config.Siad.Modules, "m") { i++ fmt.Printf("(%d/%d) Loading miner...\n", i, len(config.Siad.Modules)) m, err = miner.New(cs, tpool, w, filepath.Join(config.Siad.SiaDir, modules.MinerDir)) if err != nil { return err } } var h modules.Host if strings.Contains(config.Siad.Modules, "h") { i++ fmt.Printf("(%d/%d) Loading host...\n", i, len(config.Siad.Modules)) h, err = host.New(cs, tpool, w, config.Siad.HostAddr, filepath.Join(config.Siad.SiaDir, modules.HostDir)) if err != nil { return err } } var r modules.Renter if strings.Contains(config.Siad.Modules, "r") { i++ fmt.Printf("(%d/%d) Loading renter...\n", i, len(config.Siad.Modules)) r, err = renter.New(cs, w, tpool, filepath.Join(config.Siad.SiaDir, modules.RenterDir)) if err != nil { return err } } srv, err := api.NewServer( config.Siad.APIaddr, config.Siad.RequiredUserAgent, password, cs, e, g, h, m, r, tpool, w, ) if err != nil { return err } // Bootstrap to the network. if !config.Siad.NoBootstrap && g != nil { // connect to 3 random bootstrap nodes perm, err := crypto.Perm(len(modules.BootstrapPeers)) if err != nil { return err } for _, i := range perm[:3] { go g.Connect(modules.BootstrapPeers[i]) } } // Print a 'startup complete' message. startupTime := time.Since(loadStart) fmt.Println("Finished loading in", startupTime.Seconds(), "seconds") // Start serving api requests. err = srv.Serve() if err != nil { return err } return nil }
// startDaemonCmd uses the config parameters to start siad. func startDaemon(config Config) error { // Print a startup message. fmt.Println("Loading...") loadStart := time.Now() // Create all of the modules. gateway, err := gateway.New(config.Siad.RPCaddr, filepath.Join(config.Siad.SiaDir, modules.GatewayDir)) if err != nil { return err } cs, err := consensus.New(gateway, filepath.Join(config.Siad.SiaDir, modules.ConsensusDir)) if err != nil { return err } var e *explorer.Explorer if config.Siad.Explorer { e, err = explorer.New(cs, filepath.Join(config.Siad.SiaDir, modules.ExplorerDir)) if err != nil { return err } } tpool, err := transactionpool.New(cs, gateway) if err != nil { return err } wallet, err := wallet.New(cs, tpool, filepath.Join(config.Siad.SiaDir, modules.WalletDir)) if err != nil { return err } miner, err := miner.New(cs, tpool, wallet, filepath.Join(config.Siad.SiaDir, modules.MinerDir)) if err != nil { return err } host, err := host.New(cs, tpool, wallet, config.Siad.HostAddr, filepath.Join(config.Siad.SiaDir, modules.HostDir)) if err != nil { return err } renter, err := renter.New(cs, wallet, tpool, filepath.Join(config.Siad.SiaDir, modules.RenterDir)) if err != nil { return err } srv, err := api.NewServer( config.Siad.APIaddr, config.Siad.RequiredUserAgent, cs, e, gateway, host, miner, renter, tpool, wallet, ) if err != nil { return err } // Bootstrap to the network. if !config.Siad.NoBootstrap { // connect to 3 random bootstrap nodes perm, err := crypto.Perm(len(modules.BootstrapPeers)) if err != nil { return err } for _, i := range perm[:3] { go gateway.Connect(modules.BootstrapPeers[i]) } } // Print a 'startup complete' message. startupTime := time.Since(loadStart) fmt.Println("Finished loading in", startupTime.Seconds(), "seconds") // Start serving api requests. err = srv.Serve() if err != nil { return err } return nil }
// startDaemon uses the config parameters to initialize Sia modules and start // siad. func startDaemon(config Config) (err error) { // Prompt user for API password. if config.Siad.AuthenticateAPI { config.APIPassword, err = speakeasy.Ask("Enter API password: "******"" { return errors.New("password cannot be blank") } } // Process the config variables after they are parsed by cobra. config, err = processConfig(config) if err != nil { return err } // Print a startup message. fmt.Println("Loading...") loadStart := time.Now() // Create the server and start serving daemon routes immediately. fmt.Printf("(0/%d) Loading siad...\n", len(config.Siad.Modules)) srv, err := NewServer(config.Siad.APIaddr, config.Siad.RequiredUserAgent, config.APIPassword) if err != nil { return err } servErrs := make(chan error) go func() { servErrs <- srv.Serve() }() // Initialize the Sia modules i := 0 var g modules.Gateway if strings.Contains(config.Siad.Modules, "g") { i++ fmt.Printf("(%d/%d) Loading gateway...\n", i, len(config.Siad.Modules)) g, err = gateway.New(config.Siad.RPCaddr, !config.Siad.NoBootstrap, filepath.Join(config.Siad.SiaDir, modules.GatewayDir)) if err != nil { return err } defer g.Close() } var cs modules.ConsensusSet if strings.Contains(config.Siad.Modules, "c") { i++ fmt.Printf("(%d/%d) Loading consensus...\n", i, len(config.Siad.Modules)) cs, err = consensus.New(g, !config.Siad.NoBootstrap, filepath.Join(config.Siad.SiaDir, modules.ConsensusDir)) if err != nil { return err } defer cs.Close() } var e modules.Explorer if strings.Contains(config.Siad.Modules, "e") { i++ fmt.Printf("(%d/%d) Loading explorer...\n", i, len(config.Siad.Modules)) e, err = explorer.New(cs, filepath.Join(config.Siad.SiaDir, modules.ExplorerDir)) if err != nil { return err } defer e.Close() } var tpool modules.TransactionPool if strings.Contains(config.Siad.Modules, "t") { i++ fmt.Printf("(%d/%d) Loading transaction pool...\n", i, len(config.Siad.Modules)) tpool, err = transactionpool.New(cs, g, filepath.Join(config.Siad.SiaDir, modules.TransactionPoolDir)) if err != nil { return err } defer tpool.Close() } var w modules.Wallet if strings.Contains(config.Siad.Modules, "w") { i++ fmt.Printf("(%d/%d) Loading wallet...\n", i, len(config.Siad.Modules)) w, err = wallet.New(cs, tpool, filepath.Join(config.Siad.SiaDir, modules.WalletDir)) if err != nil { return err } defer w.Close() } var m modules.Miner if strings.Contains(config.Siad.Modules, "m") { i++ fmt.Printf("(%d/%d) Loading miner...\n", i, len(config.Siad.Modules)) m, err = miner.New(cs, tpool, w, filepath.Join(config.Siad.SiaDir, modules.MinerDir)) if err != nil { return err } defer m.Close() } var h modules.Host if strings.Contains(config.Siad.Modules, "h") { i++ fmt.Printf("(%d/%d) Loading host...\n", i, len(config.Siad.Modules)) h, err = host.New(cs, tpool, w, config.Siad.HostAddr, filepath.Join(config.Siad.SiaDir, modules.HostDir)) if err != nil { return err } defer h.Close() } var r modules.Renter if strings.Contains(config.Siad.Modules, "r") { i++ fmt.Printf("(%d/%d) Loading renter...\n", i, len(config.Siad.Modules)) r, err = renter.New(cs, w, tpool, filepath.Join(config.Siad.SiaDir, modules.RenterDir)) if err != nil { return err } defer r.Close() } // Create the Sia API a := api.New( config.Siad.RequiredUserAgent, config.APIPassword, cs, e, g, h, m, r, tpool, w, ) // connect the API to the server srv.mux.Handle("/", a) // stop the server if a kill signal is caught sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, os.Interrupt, os.Kill) go func() { <-sigChan fmt.Println("\rCaught stop signal, quitting...") srv.Close() }() // Print a 'startup complete' message. startupTime := time.Since(loadStart) fmt.Println("Finished loading in", startupTime.Seconds(), "seconds") err = <-servErrs if err != nil { build.Critical(err) } return nil }