github.com/NebulousLabs/Sia@v1.3.7/modules/consensus/persist.go (about)

     1  package consensus
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"os"
     7  	"path/filepath"
     8  
     9  	"github.com/NebulousLabs/Sia/build"
    10  	"github.com/NebulousLabs/Sia/modules"
    11  	"github.com/NebulousLabs/Sia/persist"
    12  
    13  	"github.com/coreos/bbolt"
    14  )
    15  
    16  const (
    17  	// DatabaseFilename contains the filename of the database that will be used
    18  	// when managing consensus.
    19  	DatabaseFilename = modules.ConsensusDir + ".db"
    20  	logFile          = modules.ConsensusDir + ".log"
    21  )
    22  
    23  // loadDB pulls all the blocks that have been saved to disk into memory, using
    24  // them to fill out the ConsensusSet.
    25  func (cs *ConsensusSet) loadDB() error {
    26  	// Open the database - a new bolt database will be created if none exists.
    27  	err := cs.openDB(filepath.Join(cs.persistDir, DatabaseFilename))
    28  	if err != nil {
    29  		return err
    30  	}
    31  
    32  	// Walk through initialization for Sia.
    33  	return cs.db.Update(func(tx *bolt.Tx) error {
    34  		// Check if the database has been initialized.
    35  		err = cs.initDB(tx)
    36  		if err != nil {
    37  			return err
    38  		}
    39  
    40  		// Check the initialization of the oak difficulty adjustment fields, and
    41  		// create them if they do not exist. This is separate from 'initDB'
    42  		// because older consensus databases will have completed the 'initDB'
    43  		// process but will not have the oak difficulty adjustment fields, so a
    44  		// scan will be needed to add and update them.
    45  		err = cs.initOak(tx)
    46  		if err != nil {
    47  			return err
    48  		}
    49  
    50  		// Check that the genesis block is correct - typically only incorrect
    51  		// in the event of developer binaries vs. release binaires.
    52  		genesisID, err := getPath(tx, 0)
    53  		if build.DEBUG && err != nil {
    54  			panic(err)
    55  		}
    56  		if genesisID != cs.blockRoot.Block.ID() {
    57  			return errors.New("Blockchain has wrong genesis block, exiting.")
    58  		}
    59  		return nil
    60  	})
    61  }
    62  
    63  // initPersist initializes the persistence structures of the consensus set, in
    64  // particular loading the database and preparing to manage subscribers.
    65  func (cs *ConsensusSet) initPersist() error {
    66  	// Create the consensus directory.
    67  	err := os.MkdirAll(cs.persistDir, 0700)
    68  	if err != nil {
    69  		return err
    70  	}
    71  
    72  	// Initialize the logger.
    73  	cs.log, err = persist.NewFileLogger(filepath.Join(cs.persistDir, logFile))
    74  	if err != nil {
    75  		return err
    76  	}
    77  	// Set up closing the logger.
    78  	cs.tg.AfterStop(func() {
    79  		err := cs.log.Close()
    80  		if err != nil {
    81  			// State of the logger is unknown, a println will suffice.
    82  			fmt.Println("Error shutting down consensus set logger:", err)
    83  		}
    84  	})
    85  
    86  	// Try to load an existing database from disk - a new one will be created
    87  	// if one does not exist.
    88  	err = cs.loadDB()
    89  	if err != nil {
    90  		return err
    91  	}
    92  	// Set up the closing of the database.
    93  	cs.tg.AfterStop(func() {
    94  		err := cs.db.Close()
    95  		if err != nil {
    96  			cs.log.Println("ERROR: Unable to close consensus set database at shutdown:", err)
    97  		}
    98  	})
    99  	return nil
   100  }