// New returns a ready-to-go miner that is not mining. func New(cs modules.ConsensusSet, tpool modules.TransactionPool, w modules.Wallet, persistDir string) (*Miner, error) { // Create the miner and its dependencies. if cs == nil { return nil, errors.New("miner cannot use a nil state") } if tpool == nil { return nil, errors.New("miner cannot use a nil transaction pool") } if w == nil { return nil, errors.New("miner cannot use a nil wallet") } // Grab some starting block variables. currentBlock := cs.GenesisBlock().ID() currentTarget, exists1 := cs.ChildTarget(currentBlock) earliestTimestamp, exists2 := cs.EarliestChildTimestamp(currentBlock) if build.DEBUG { if !exists1 { panic("could not get child target") } if !exists2 { panic("could not get child earliest timestamp") } } addr, _, err := w.CoinAddress(false) // false indicates that the address should not be visible to the user. if err != nil { return nil, err } // Assemble the miner. m := &Miner{ cs: cs, tpool: tpool, wallet: w, parent: currentBlock, target: currentTarget, earliestTimestamp: earliestTimestamp, address: addr, blockMem: make(map[types.BlockHeader]types.Block), headerMem: make([]types.BlockHeader, headerForWorkMemory), persistDir: persistDir, mu: sync.New(modules.SafeMutexDelay, 1), } err = m.initPersist() if err != nil { return nil, err } m.tpool.TransactionPoolSubscribe(m) return m, 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 }
// New returns an initialized Host. func New(cs *consensus.State, hdb modules.HostDB, tpool modules.TransactionPool, wallet modules.Wallet, addr string, saveDir string) (*Host, error) { if cs == nil { return nil, errors.New("host cannot use a nil state") } if hdb == nil { return nil, errors.New("host cannot use a nil hostdb") } if tpool == nil { return nil, errors.New("host cannot use a nil tpool") } if wallet == nil { return nil, errors.New("host cannot use a nil wallet") } coinAddr, _, err := wallet.CoinAddress(false) // false indicates that the address should not be visible to the user. if err != nil { return nil, err } h := &Host{ cs: cs, hostdb: hdb, tpool: tpool, wallet: wallet, // default host settings HostSettings: modules.HostSettings{ TotalStorage: 10e9, // 10 GB MaxFilesize: 1e9, // 1 GB MaxDuration: 144 * 60, // 60 days WindowSize: 288, // 48 hours Price: types.NewCurrency64(100e12), // 0.1 siacoin / mb / week Collateral: types.NewCurrency64(0), UnlockHash: coinAddr, }, saveDir: saveDir, obligationsByID: make(map[types.FileContractID]contractObligation), obligationsByHeight: make(map[types.BlockHeight][]contractObligation), mu: sync.New(modules.SafeMutexDelay, 1), } h.spaceRemaining = h.TotalStorage // Create listener and set address. h.listener, err = net.Listen("tcp", addr) if err != nil { return nil, err } _, port, _ := net.SplitHostPort(h.listener.Addr().String()) h.myAddr = modules.NetAddress(net.JoinHostPort(modules.ExternalIP, port)) err = os.MkdirAll(saveDir, 0700) if err != nil { return nil, err } err = h.load() if err != nil && !os.IsNotExist(err) { return nil, err } // spawn listener go h.listen() h.cs.ConsensusSetSubscribe(h) return h, nil }