// Initialize Factoid Block Chain from database func initFctChain() { //Initialize the Admin Chain ID fchain = new(common.FctChain) fchain.ChainID = new(common.Hash) fchain.ChainID.SetBytes(fct.FACTOID_CHAINID) // get all aBlocks from db fBlocks, _ := db.FetchAllFBlocks() sort.Sort(util.ByFBlockIDAccending(fBlocks)) // double check the block ids for i := 0; i < len(fBlocks); i = i + 1 { if uint32(i) != fBlocks[i].GetDBHeight() { panic(errors.New("BlockID does not equal index for chain:" + fchain.ChainID.String() + " block:" + fmt.Sprintf("%v", fBlocks[i].GetDBHeight()))) } else { FactoshisPerCredit = fBlocks[i].GetExchRate() common.FactoidState.SetFactoshisPerEC(FactoshisPerCredit) // initialize the FactoidState in sequence err := common.FactoidState.AddTransactionBlock(fBlocks[i]) if err != nil { panic("Failed to rebuild factoid state: " + err.Error()) } } } //Create an empty block and append to the chain if len(fBlocks) == 0 || dchain.NextDBHeight == 0 { common.FactoidState.SetFactoshisPerEC(FactoshisPerCredit) fchain.NextBlockHeight = 0 // func GetGenesisFBlock(ftime uint64, ExRate uint64, addressCnt int, Factoids uint64 ) IFBlock { //fchain.NextBlock = block.GetGenesisFBlock(0, FactoshisPerCredit, 10, 200000000000) fchain.NextBlock = block.GetGenesisFBlock() fmt.Println(fchain.NextBlock) gb := fchain.NextBlock // If a client, this block is going to get downloaded and added. Don't do it twice. if nodeMode == common.SERVER_NODE { err := common.FactoidState.AddTransactionBlock(gb) if err != nil { panic(err) } } } else { fchain.NextBlockHeight = dchain.NextDBHeight common.FactoidState.ProcessEndOfBlock2(dchain.NextDBHeight) fchain.NextBlock = common.FactoidState.GetCurrentBlock() } exportFctChain(fchain) }
// build Genesis blocks func buildGenesisBlocks() error { //Set the timestamp for the genesis block t, err := time.Parse(time.RFC3339, common.GENESIS_BLK_TIMESTAMP) if err != nil { panic("Not able to parse the genesis block time stamp") } dchain.NextBlock.Header.Timestamp = uint32(t.Unix() / 60) // Allocate the first two dbentries for ECBlock and Factoid block dchain.AddDBEntry(&common.DBEntry{}) // AdminBlock dchain.AddDBEntry(&common.DBEntry{}) // ECBlock dchain.AddDBEntry(&common.DBEntry{}) // Factoid block // Entry Credit Chain cBlock := newEntryCreditBlock(ecchain) procLog.Debugf("buildGenesisBlocks: cBlock=%s\n", spew.Sdump(cBlock)) dchain.AddECBlockToDBEntry(cBlock) exportECChain(ecchain) // Admin chain aBlock := newAdminBlock(achain) procLog.Debugf("buildGenesisBlocks: aBlock=%s\n", spew.Sdump(aBlock)) dchain.AddABlockToDBEntry(aBlock) exportAChain(achain) // factoid Genesis Address //fchain.NextBlock = block.GetGenesisFBlock(0, FactoshisPerCredit, 10, 200000000000) fchain.NextBlock = block.GetGenesisFBlock() FBlock := newFactoidBlock(fchain) dchain.AddFBlockToDBEntry(FBlock) exportFctChain(fchain) // Directory Block chain procLog.Debug("in buildGenesisBlocks") dbBlock := newDirectoryBlock(dchain) // Check block hash if genesis block if dbBlock.DBHash.String() != common.GENESIS_DIR_BLOCK_HASH { //Panic for Milestone 1 panic("\nGenesis block hash expected: " + common.GENESIS_DIR_BLOCK_HASH + "\nGenesis block hash found: " + dbBlock.DBHash.String() + "\n") } exportDChain(dchain) // place an anchor into btc placeAnchor(dbBlock) return nil }
func (fs *FactoidState) LoadState() error { var hashes []fct.IHash cblk := fs.GetTransactionBlock(fct.FACTOID_CHAINID_HASH) // If there is no head for the Factoids in the database, we have an // uninitialized database. We need to add the Genesis Block. TODO if cblk == nil { cp.CP.AddUpdate( "Creating Factoid Genesis Block", // tag "info", // Category "Creating the Factoid Genesis Block", // Title "", // Msg 60) // Expire //gb := block.GetGenesisFBlock(fs.GetTimeMilli(), 1000000,10,200000000000) gb := block.GetGenesisFBlock() fs.PutTransactionBlock(gb.GetHash(), gb) fs.PutTransactionBlock(fct.FACTOID_CHAINID_HASH, gb) err := fs.AddTransactionBlock(gb) if err != nil { fct.Prtln("Failed to build initial state.\n", err) return err } fs.ProcessEndOfBlock() return nil } blk := cblk // First run back from the head back to the genesis block, collecting hashes. for { if blk == nil { return fmt.Errorf("Block not found or not formated properly") } h := blk.GetHash() for _, hash := range hashes { if bytes.Compare(hash.Bytes(), h.Bytes()) == 0 { return fmt.Errorf("Corrupted database; same hash found twice") } } hashes = append(hashes, h) if bytes.Compare(blk.GetPrevKeyMR().Bytes(), fct.ZERO_HASH) == 0 { break } tblk := fs.GetTransactionBlock(blk.GetPrevKeyMR()) if tblk == nil { return fmt.Errorf("Failed to find the block at height: %d", blk.GetDBHeight()-1) } if !bytes.Equal(tblk.GetHash().Bytes(), blk.GetPrevKeyMR().Bytes()) { return fmt.Errorf("Hash Failure! Database must be rebuilt") } blk = tblk time.Sleep(time.Second / 100) cp.CP.AddUpdate( "loadState", "status", // Category "Loading State", fmt.Sprintf("Scanning backwards. Block: %d", blk.GetDBHeight()), 0) } // Now run forward, and build our accounting for i := len(hashes) - 1; i >= 0; i-- { blk = fs.GetTransactionBlock(hashes[i]) if blk == nil { return fmt.Errorf("Should never happen. Block not found in the Database\n"+ "No block found for: %s", hashes[i].String()) } err := fs.AddTransactionBlock(blk) // updates accounting for this block if err != nil { fct.Prtln("Failed to rebuild state.\n", err) return err } time.Sleep(time.Second / 100) cp.CP.AddUpdate( "loadState", "status", // Category "Loading State", fmt.Sprintf("Loading and Processing. Block: %d", blk.GetDBHeight()), 0) } fs.dbheight = blk.GetDBHeight() fs.ProcessEndOfBlock() return nil }