// postEncryptionTesting runs a series of checks on the wallet after it has // been encrypted, to make sure that locking, unlocking, and spending after // unlocking are all happening in the correct order and returning the correct // errors. func postEncryptionTesting(m modules.Miner, w *Wallet, masterKey crypto.TwofishKey) { if !w.Encrypted() { panic("wallet is not encrypted when starting postEncryptionTesting") } if w.Unlocked() { panic("wallet is unlocked when starting postEncryptionTesting") } if len(w.seeds) != 0 { panic("wallet has seeds in it when startin postEncryptionTesting") } // Try unlocking and using the wallet. err := w.Unlock(masterKey) if err != nil { panic(err) } err = w.Unlock(masterKey) if err != errAlreadyUnlocked { panic(err) } // Mine enough coins so that a balance appears (and some buffer for the // send later). for i := types.BlockHeight(0); i <= types.MaturityDelay+1; i++ { _, err := m.AddBlock() if err != nil { panic(err) } } siacoinBal, _, _ := w.ConfirmedBalance() if siacoinBal.Cmp(types.NewCurrency64(0)) <= 0 { panic("wallet balance reported as 0 after maturing some mined blocks") } err = w.Unlock(masterKey) if err != errAlreadyUnlocked { panic(err) } // Lock, unlock, and trying using the wallet some more. err = w.Lock() if err != nil { panic(err) } err = w.Lock() if err != modules.ErrLockedWallet { panic(err) } err = w.Unlock(crypto.TwofishKey{}) if err != modules.ErrBadEncryptionKey { panic(err) } err = w.Unlock(masterKey) if err != nil { panic(err) } // Verify that the secret keys have been restored by sending coins to the // void. Send more coins than are received by mining a block. _, err = w.SendSiacoins(types.CalculateCoinbase(0), types.UnlockHash{}) if err != nil { panic(err) } _, err = m.AddBlock() if err != nil { panic(err) } siacoinBal2, _, _ := w.ConfirmedBalance() if siacoinBal2.Cmp(siacoinBal) >= 0 { panic("balance did not increase") } }
// 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 }