Example #1
0
File: ios.go Project: dzyk/dcoin-go
func StopHTTPServer() {
	log.Debug("StopHTTPServer()")
	IosLog("StopHTTPServer 0")
	go func() { stop <- true }()
	utils.Sleep(1)
	IosLog("StopHTTPServer 1")
}
Example #2
0
func WaitStopTime() {
	var first bool
	for {
		if utils.DB == nil || utils.DB.DB == nil {
			utils.Sleep(3)
			continue
		}
		if !first {
			err := utils.DB.ExecSql(`DELETE FROM stop_daemons`)
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
			}
			first = true
		}
		dExists, err := utils.DB.Single(`SELECT stop_time FROM stop_daemons`).Int64()
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}
		log.Debug("dExtit: %d", dExists)
		if dExists > 0 {
			fmt.Println("Stop_daemons from DB!")
			for _, ch := range utils.DaemonsChans {
				fmt.Println("ch.ChBreaker<-true")
				ch.ChBreaker <- true
			}
			for _, ch := range utils.DaemonsChans {
				fmt.Println(<-ch.ChAnswer)
			}
			fmt.Println("Daemons killed")
			err := utils.DB.Close()
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
			}
			fmt.Println("DB Closed")
			err = os.Remove(*utils.Dir + "/dcoin.pid")
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
				panic(err)
			}
			fmt.Println("removed " + *utils.Dir + "/dcoin.pid")
			thrust.Exit()
			os.Exit(1)
		}
		utils.Sleep(1)
	}
}
Example #3
0
func (d *daemon) dSleep(sleep int) bool {
	for i := 0; i < sleep; i++ {
		if CheckDaemonsRestart(d.chBreaker, d.chAnswer, d.goRoutineName) {
			return true
		}
		utils.Sleep(1)
	}
	return false
}
Example #4
0
func ConfigInit() {

	// мониторим config.ini на наличие изменений
	go func() {
		for {
			log.Debug("ConfigInit monitor")
			if _, err := os.Stat(*utils.Dir + "/config.ini"); os.IsNotExist(err) {
				utils.Sleep(1)
				continue
			}
			configIni_, err := config.NewConfig("ini", *utils.Dir+"/config.ini")
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
			}
			configIni, err = configIni_.GetSection("default")
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
			}
			if len(configIni["db_type"]) > 0 {
				break
			}
			utils.Sleep(3)
		}
	}()
	globalLangReadOnly = make(map[int]map[string]string)
	for _, v := range consts.LangMap {
		data, err := static.Asset(fmt.Sprintf("static/lang/%d.ini", v))
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}
		iniconf_, err := config.NewConfigData("ini", []byte(data))
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}
		//fmt.Println(iniconf_)
		iniconf, err := iniconf_.GetSection("default")
		globalLangReadOnly[v] = make(map[string]string)
		globalLangReadOnly[v] = iniconf
	}
}
Example #5
0
func DbConnect(chBreaker chan bool, chAnswer chan string, goRoutineName string) *utils.DCDB {
	for {
		if CheckDaemonsRestart(chBreaker, chAnswer, goRoutineName) {
			return nil
		}
		if utils.DB == nil || utils.DB.DB == nil {
			utils.Sleep(1)
		} else {
			return utils.DB
		}
	}
	return nil
}
Example #6
0
func ConfigInit() {
	// мониторим config.ini на наличие изменений
	go func() {
		for {
			log.Debug("ConfigInit monitor")
			if _, err := os.Stat(*utils.Dir + "/config.ini"); os.IsNotExist(err) {
				utils.Sleep(1)
				continue
			}
			configIni_, err := config.NewConfig("ini", *utils.Dir+"/config.ini")
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
			}
			configIni, err = configIni_.GetSection("default")
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
			}
			if len(configIni["db_type"]) > 0 {
				break
			}
			utils.Sleep(3)
		}
	}()
}
Example #7
0
func (d *daemon) unlockPrintSleep(err error, sleep int) bool {
	if err != nil {
		log.Error("%v", err)
	}
	err = d.DbUnlock(d.goRoutineName)
	if err != nil {
		log.Error("%v", err)
	}
	for i := 0; i < sleep; i++ {
		if CheckDaemonsRestart(d.chBreaker, d.chAnswer, d.goRoutineName) {
			return true
		}
		utils.Sleep(1)
	}
	return false
}
Example #8
0
func BlocksCollection(chBreaker chan bool, chAnswer chan string) {
	defer func() {
		if r := recover(); r != nil {
			log.Error("daemon Recovered", r)
			panic(r)
		}
	}()

	const GoroutineName = "BlocksCollection"
	d := new(daemon)
	d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName)
	if d.DCDB == nil {
		return
	}
	d.goRoutineName = GoroutineName
	d.chAnswer = chAnswer
	d.chBreaker = chBreaker
	if utils.Mobile() {
		d.sleepTime = 300
	} else {
		d.sleepTime = 60
	}
	if !d.CheckInstall(chBreaker, chAnswer, GoroutineName) {
		return
	}
	d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName)
	if d.DCDB == nil {
		return
	}
	//var cur bool
BEGIN:
	for {
		log.Info(GoroutineName)
		MonitorDaemonCh <- []string{GoroutineName, utils.Int64ToStr(utils.Time())}

		// проверим, не нужно ли нам выйти из цикла
		if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
			break BEGIN
		}
		log.Debug("0")
		config, err := d.GetNodeConfig()
		if err != nil {
			if d.dPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		log.Debug("1")

		err, restart := d.dbLock()
		if restart {
			log.Debug("restart true")
			break BEGIN
		}
		if err != nil {
			log.Debug("restart err %v", err)
			if d.dPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		log.Debug("2")

		// если это первый запуск во время инсталяции
		currentBlockId, err := d.GetBlockId()
		if err != nil {
			if d.unlockPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

		log.Info("config", config)
		log.Info("currentBlockId", currentBlockId)

		// на время тестов
		/*if !cur {
		    currentBlockId = 0
		    cur = true
		}*/
		parser := new(dcparser.Parser)
		parser.DCDB = d.DCDB
		parser.GoroutineName = GoroutineName
		if currentBlockId == 0 || *utils.StartBlockId > 0 {
			/*
			   IsNotExistBlockChain := false
			   if _, err := os.Stat(*utils.Dir+"/public/blockchain"); os.IsNotExist(err) {
			       IsNotExistBlockChain = true
			   }*/
			if config["first_load_blockchain"] == "file" /* && IsNotExistBlockChain*/ {

				log.Info("first_load_blockchain=file")
				nodeConfig, err := d.GetNodeConfig()
				blockchain_url := nodeConfig["first_load_blockchain_url"]
				if len(blockchain_url) == 0 {
					blockchain_url = consts.BLOCKCHAIN_URL
				}
				log.Debug("blockchain_url: %s", blockchain_url)
				// возможно сервер отдаст блокчейн не с первой попытки
				var blockchainSize int64
				for i := 0; i < 10; i++ {
					log.Debug("blockchain_url: %s, i: %d", blockchain_url, i)
					blockchainSize, err = utils.DownloadToFile(blockchain_url, *utils.Dir+"/public/blockchain", 3600, chBreaker, chAnswer, GoroutineName)
					if err != nil {
						log.Error("%v", utils.ErrInfo(err))
					}
					if blockchainSize > consts.BLOCKCHAIN_SIZE {
						break
					}
				}
				log.Debug("blockchain dw ok")
				if err != nil || blockchainSize < consts.BLOCKCHAIN_SIZE {
					if err != nil {
						log.Error("%v", utils.ErrInfo(err))
					} else {
						log.Info(fmt.Sprintf("%v < %v", blockchainSize, consts.BLOCKCHAIN_SIZE))
					}
					if d.unlockPrintSleep(err, d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}

				first := true
				/*// блокчейн мог быть загружен ранее. проверим его размер


				  stat, err := file.Stat()
				  if err != nil {
				      if d.unlockPrintSleep(err, d.sleepTime) {	break BEGIN }
				      file.Close()
				      continue BEGIN
				  }
				  if stat.Size() < consts.BLOCKCHAIN_SIZE {
				      d.unlockPrintSleep(fmt.Errorf("%v < %v", stat.Size(), consts.BLOCKCHAIN_SIZE), 1)
				      file.Close()
				      continue BEGIN
				  }*/

				log.Debug("GO!")
				file, err := os.Open(*utils.Dir + "/public/blockchain")
				if err != nil {
					if d.unlockPrintSleep(err, d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				err = d.ExecSql(`UPDATE config SET current_load_blockchain = 'file'`)
				if err != nil {
					if d.unlockPrintSleep(err, d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}

				for {
					// проверим, не нужно ли нам выйти из цикла
					if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
						d.unlockPrintSleep(fmt.Errorf("DaemonsRestart"), 0)
						break BEGIN
					}
					b1 := make([]byte, 5)
					file.Read(b1)
					dataSize := utils.BinToDec(b1)
					log.Debug("dataSize", dataSize)
					if dataSize > 0 {

						data := make([]byte, dataSize)
						file.Read(data)
						//log.Debug("data %x\n", data)
						blockId := utils.BinToDec(data[0:5])
						if *utils.EndBlockId > 0 && blockId == *utils.EndBlockId {
							if d.dPrintSleep(err, d.sleepTime) {
								break BEGIN
							}
							file.Close()
							continue BEGIN
						}
						log.Info("blockId", blockId)
						data2 := data[5:]
						length := utils.DecodeLength(&data2)
						log.Debug("length", length)
						//log.Debug("data2 %x\n", data2)
						blockBin := utils.BytesShift(&data2, length)
						//log.Debug("blockBin %x\n", blockBin)

						if *utils.StartBlockId == 0 || (*utils.StartBlockId > 0 && blockId > *utils.StartBlockId) {

							// парсинг блока
							parser.BinaryData = blockBin

							if first {
								parser.CurrentVersion = consts.VERSION
								first = false
							}
							err = parser.ParseDataFull()
							if err != nil {
								if d.dPrintSleep(err, d.sleepTime) {
									break BEGIN
								}
								file.Close()
								continue BEGIN
							}
							err = parser.InsertIntoBlockchain()
							if err != nil {
								if d.dPrintSleep(err, d.sleepTime) {
									break BEGIN
								}
								file.Close()
								continue BEGIN
							}

							// отметимся, чтобы не спровоцировать очистку таблиц
							err = parser.UpdMainLock()
							if err != nil {
								if d.dPrintSleep(err, d.sleepTime) {
									break BEGIN
								}
								file.Close()
								continue BEGIN
							}
							if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
								if d.dPrintSleep(err, d.sleepTime) {
									break BEGIN
								}
								file.Close()
								continue BEGIN
							}
						}
						// ненужный тут размер в конце блока данных
						data = make([]byte, 5)
						file.Read(data)
					} else {
						if d.unlockPrintSleep(err, d.sleepTime) {
							break BEGIN
						}
						continue BEGIN
					}
					// utils.Sleep(1)
				}
				file.Close()
			} else {

				newBlock, err := static.Asset("static/1block.bin")
				if err != nil {
					if d.dPrintSleep(err, d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				parser.BinaryData = newBlock
				parser.CurrentVersion = consts.VERSION

				err = parser.ParseDataFull()
				if err != nil {
					if d.dPrintSleep(err, d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				err = parser.InsertIntoBlockchain()

				if err != nil {
					if d.dPrintSleep(err, d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
			}

			utils.Sleep(1)
			d.dbUnlock()
			continue BEGIN
		}
		d.dbUnlock()

		err = d.ExecSql(`UPDATE config SET current_load_blockchain = 'nodes'`)
		if err != nil {
			if d.unlockPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

		myConfig, err := d.OneRow("SELECT local_gate_ip, static_node_user_id FROM config").String()
		if err != nil {
			if d.dPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue
		}
		var hosts []map[string]string
		var nodeHost string
		var dataTypeMaxBlockId, dataTypeBlockBody int64
		if len(myConfig["local_gate_ip"]) > 0 {
			hosts = append(hosts, map[string]string{"host": myConfig["local_gate_ip"], "user_id": myConfig["static_node_user_id"]})
			nodeHost, err = d.Single("SELECT tcp_host FROM miners_data WHERE user_id  =  ?", myConfig["static_node_user_id"]).String()
			if err != nil {
				if d.dPrintSleep(err, d.sleepTime) {
					break BEGIN
				}
				continue
			}
			dataTypeMaxBlockId = 9
			dataTypeBlockBody = 8
			//getBlockScriptName = "ajax?controllerName=protectedGetBlock";
			//addNodeHost = "&nodeHost="+nodeHost;
		} else {
			// получим список нодов, с кем установлено рукопожатие
			hosts, err = d.GetAll("SELECT * FROM nodes_connection", -1)
			if err != nil {
				if d.dPrintSleep(err, d.sleepTime) {
					break BEGIN
				}
				continue
			}
			dataTypeMaxBlockId = 10
			dataTypeBlockBody = 7
			//getBlockScriptName = "ajax?controllerName=getBlock";
			//addNodeHost = "";
		}

		log.Info("%v", hosts)

		if len(hosts) == 0 {
			if d.dPrintSleep(err, 1) {
				break BEGIN
			}
			continue
		}

		maxBlockId := int64(1)
		maxBlockIdHost := ""
		var maxBlockIdUserId int64
		// получим максимальный номер блока
		for i := 0; i < len(hosts); i++ {
			if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
				break BEGIN
			}
			conn, err := utils.TcpConn(hosts[i]["host"])
			if err != nil {
				if d.dPrintSleep(err, 1) {
					break BEGIN
				}
				continue
			}
			// шлем тип данных
			_, err = conn.Write(utils.DecToBin(dataTypeMaxBlockId, 1))
			if err != nil {
				conn.Close()
				if d.dPrintSleep(err, 1) {
					break BEGIN
				}
				continue
			}
			if len(nodeHost) > 0 { // защищенный режим
				err = utils.WriteSizeAndData([]byte(nodeHost), conn)
				if err != nil {
					conn.Close()
					if d.dPrintSleep(err, d.sleepTime) {
						break BEGIN
					}
					continue
				}
			}
			// в ответ получаем номер блока
			blockIdBin := make([]byte, 4)
			_, err = conn.Read(blockIdBin)
			if err != nil {
				conn.Close()
				if d.dPrintSleep(err, 1) {
					break BEGIN
				}
				continue
			}
			conn.Close()
			id := utils.BinToDec(blockIdBin)
			if id > maxBlockId || i == 0 {
				maxBlockId = id
				maxBlockIdHost = hosts[i]["host"]
				maxBlockIdUserId = utils.StrToInt64(hosts[i]["user_id"])
			}
			if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
				utils.Sleep(1)
				break BEGIN
			}
		}

		// получим наш текущий имеющийся номер блока
		// ждем, пока разлочится и лочим сами, чтобы не попасть в тот момент, когда данные из блока уже занесены в БД, а info_block еще не успел обновиться
		err, restart = d.dbLock()
		if restart {
			break BEGIN
		}
		if err != nil {
			if d.dPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

		currentBlockId, err = d.Single("SELECT block_id FROM info_block").Int64()
		if err != nil {
			if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue
		}
		log.Info("currentBlockId", currentBlockId, "maxBlockId", maxBlockId)
		if maxBlockId <= currentBlockId {
			if d.unlockPrintSleep(utils.ErrInfo(errors.New("maxBlockId <= currentBlockId")), d.sleepTime) {
				break BEGIN
			}
			continue
		}

		fmt.Printf("\nnode: %s\n", maxBlockIdHost)

		// в цикле собираем блоки, пока не дойдем до максимального
		for blockId := currentBlockId + 1; blockId < maxBlockId+1; blockId++ {
			d.UpdMainLock()
			if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				break BEGIN
			}
			variables, err := d.GetAllVariables()
			if err != nil {
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			// качаем тело блока с хоста maxBlockIdHost
			binaryBlock, err := utils.GetBlockBody(maxBlockIdHost, blockId, dataTypeBlockBody, nodeHost)

			if len(binaryBlock) == 0 {
				// баним на 1 час хост, который дал нам пустой блок, хотя должен был дать все до максимального
				// для тестов убрал, потом вставить.
				//nodes_ban ($db, $max_block_id_user_id, substr($binary_block, 0, 512)."\n".__FILE__.', '.__LINE__.', '. __FUNCTION__.', '.__CLASS__.', '. __METHOD__);
				//p.NodesBan(maxBlockIdUserId, "len(binaryBlock) == 0")
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			binaryBlockFull := binaryBlock
			utils.BytesShift(&binaryBlock, 1) // уберем 1-й байт - тип (блок/тр-я)
			// распарсим заголовок блока
			blockData := utils.ParseBlockHeader(&binaryBlock)
			log.Info("blockData: %v, blockId: %v", blockData, blockId)

			// если существуют глючная цепочка, тот тут мы её проигнорируем
			badBlocks_, err := d.Single("SELECT bad_blocks FROM config").Bytes()
			if err != nil {
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			badBlocks := make(map[int64]string)
			if len(badBlocks_) > 0 {
				err = json.Unmarshal(badBlocks_, &badBlocks)
				if err != nil {
					if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
			}
			if badBlocks[blockData.BlockId] == string(utils.BinToHex(blockData.Sign)) {
				d.NodesBan(maxBlockIdUserId, fmt.Sprintf("bad_block = %v => %v", blockData.BlockId, badBlocks[blockData.BlockId]))
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}

			// размер блока не может быть более чем max_block_size
			if currentBlockId > 1 {
				if int64(len(binaryBlock)) > variables.Int64["max_block_size"] {
					d.NodesBan(maxBlockIdUserId, fmt.Sprintf(`len(binaryBlock) > variables.Int64["max_block_size"]  %v > %v`, len(binaryBlock), variables.Int64["max_block_size"]))
					if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
			}

			if blockData.BlockId != blockId {
				d.NodesBan(maxBlockIdUserId, fmt.Sprintf(`blockData.BlockId != blockId  %v > %v`, blockData.BlockId, blockId))
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}

			// нам нужен хэш предыдущего блока, чтобы проверить подпись
			prevBlockHash := ""
			if blockId > 1 {
				prevBlockHash, err = d.Single("SELECT hash FROM block_chain WHERE id = ?", blockId-1).String()
				if err != nil {
					if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				prevBlockHash = string(utils.BinToHex([]byte(prevBlockHash)))
			} else {
				prevBlockHash = "0"
			}
			first := false
			if blockId == 1 {
				first = true
			}
			// нам нужен меркель-рут текущего блока
			mrklRoot, err := utils.GetMrklroot(binaryBlock, variables, first)
			if err != nil {
				d.NodesBan(maxBlockIdUserId, fmt.Sprintf(`%v`, err))
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}

			// публичный ключ того, кто этот блок сгенерил
			nodePublicKey, err := d.GetNodePublicKey(blockData.UserId)
			if err != nil {
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}

			// SIGN от 128 байта до 512 байт. Подпись от TYPE, BLOCK_ID, PREV_BLOCK_HASH, TIME, USER_ID, LEVEL, MRKL_ROOT
			forSign := fmt.Sprintf("0,%v,%v,%v,%v,%v,%s", blockData.BlockId, prevBlockHash, blockData.Time, blockData.UserId, blockData.Level, mrklRoot)

			// проверяем подпись
			if !first {
				_, err = utils.CheckSign([][]byte{nodePublicKey}, forSign, blockData.Sign, true)
			}

			// качаем предыдущие блоки до тех пор, пока отличается хэш предыдущего.
			// другими словами, пока подпись с prevBlockHash будет неверной, т.е. пока что-то есть в $error
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
				if blockId < 1 {
					if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				// нужно привести данные в нашей БД в соответствие с данными у того, у кого качаем более свежий блок
				//func (p *Parser) GetOldBlocks (userId, blockId int64, host string, hostUserId int64, goroutineName, getBlockScriptName, addNodeHost string) error {
				err := parser.GetOldBlocks(blockData.UserId, blockId-1, maxBlockIdHost, maxBlockIdUserId, GoroutineName, dataTypeBlockBody, nodeHost)
				if err != nil {
					log.Error("%v", err)
					d.NodesBan(maxBlockIdUserId, fmt.Sprintf(`blockId: %v / %v`, blockId, err))
					if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}

			} else {

				log.Info("plug found blockId=%v\n", blockId)

				// получим наши транзакции в 1 бинарнике, просто для удобства
				var transactions []byte
				utils.WriteSelectiveLog("SELECT data FROM transactions WHERE verified = 1 AND used = 0")
				rows, err := d.Query("SELECT data FROM transactions WHERE verified = 1 AND used = 0")
				if err != nil {
					utils.WriteSelectiveLog(err)
					if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				for rows.Next() {
					var data []byte
					err = rows.Scan(&data)
					utils.WriteSelectiveLog(utils.BinToHex(data))
					if err != nil {
						rows.Close()
						if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
							break BEGIN
						}
						continue BEGIN
					}
					transactions = append(transactions, utils.EncodeLengthPlusData(data)...)
				}
				rows.Close()
				if len(transactions) > 0 {
					// отмечаем, что эти тр-ии теперь нужно проверять по новой
					utils.WriteSelectiveLog("UPDATE transactions SET verified = 0 WHERE verified = 1 AND used = 0")
					affect, err := d.ExecSqlGetAffect("UPDATE transactions SET verified = 0 WHERE verified = 1 AND used = 0")
					if err != nil {
						utils.WriteSelectiveLog(err)
						if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
							break BEGIN
						}
						continue BEGIN
					}
					utils.WriteSelectiveLog("affect: " + utils.Int64ToStr(affect))
					// откатываем по фронту все свежие тр-ии
					parser.BinaryData = transactions
					err = parser.ParseDataRollbackFront(false)
					if err != nil {
						utils.Sleep(1)
						continue BEGIN
					}
				}

				err = parser.RollbackTransactionsTestblock(true)
				if err != nil {
					if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				err = d.ExecSql("DELETE FROM testblock")
				if err != nil {
					if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
			}

			// теперь у нас в таблицах всё тоже самое, что у нода, у которого качаем блок
			// и можем этот блок проверить и занести в нашу БД
			parser.BinaryData = binaryBlockFull
			err = parser.ParseDataFull()
			if err == nil {
				err = parser.InsertIntoBlockchain()
				if err != nil {
					if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
			}
			// начинаем всё с начала уже с другими нодами. Но у нас уже могут быть новые блоки до $block_id, взятые от нода, которого с в итоге мы баним
			if err != nil {
				d.NodesBan(maxBlockIdUserId, fmt.Sprintf(`blockId: %v / %v`, blockId, err))
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
		}

		d.dbUnlock()

		if d.dSleep(d.sleepTime) {
			break BEGIN
		}
	}

	log.Debug("break BEGIN %v", GoroutineName)
}
Example #9
0
func tcpListener() {
	db := utils.DB
	log.Debug("tcp")
	go func() {
		if db == nil || db.DB == nil {
			for {
				db = utils.DB
				if db != nil && db.DB != nil {
					break
				} else {
					utils.Sleep(3)
				}
			}
		}
		tcpHost := db.GetTcpHost()
		log.Debug("tcpHost: %v", tcpHost)
		// включаем листинг TCP-сервером и обработку входящих запросов
		l, err := net.Listen("tcp", tcpHost)
		if err != nil {
			log.Error("Error listening: %v", err)
			panic(err)
			//os.Exit(1)
		}
		//defer l.Close()
		go func() {
			for {
				conn, err := l.Accept()
				if err != nil {
					log.Error("Error accepting: %v", err)
					utils.Sleep(1)
					//panic(err)
					//os.Exit(1)
				} else {
					go func(conn net.Conn) {
						t := new(tcpserver.TcpServer)
						t.DCDB = db
						t.Conn = conn
						t.HandleTcpRequest()
					}(conn)
				}
			}
		}()
	}()

	// Листенинг для чата
	go func() {
		listener, err := net.Listen("tcp", ":"+consts.CHAT_PORT)
		if err != nil {
			log.Error("Error listening: %v", err)
			panic(err)
		}
		defer listener.Close()

		for {
			conn, _ := listener.Accept()
			log.Debug("main conn %v\n", conn)
			log.Debug("conn.RemoteAddr() %v\n", conn.RemoteAddr().String())

			go func(conn net.Conn) {
				buf := make([]byte, 4)
				_, err := conn.Read(buf)
				if err != nil {
					log.Debug("%v", err)
					return
				}
				// получим user_id в первых 4-х байтах
				userId := utils.BinToDec(buf)

				// и тип канала
				buf = make([]byte, 1)
				_, err = conn.Read(buf)
				if err != nil {
					log.Debug("%v", err)
					return
				}
				chType := utils.BinToDec(buf)
				log.Debug("userId %v chType %v", userId, chType)

				// мониторит входящие
				if chType == 0 {
					fmt.Println("chType 0", conn.RemoteAddr(), utils.Time())
					utils.ChatMutex.Lock()
					utils.ChatInConnections[userId] = 1
					utils.ChatMutex.Unlock()
					go utils.ChatInput(conn, userId)
				}
				// создаем канал, через который будем рассылать тр-ии чата
				if chType == 1 {
					re := regexp.MustCompile(`(.*?):[0-9]+$`)
					match := re.FindStringSubmatch(conn.RemoteAddr().String())
					if len(match) != 0 {
						fmt.Println("chType 1", conn.RemoteAddr(), utils.Time())
						// проверим, нет ли уже созданного канала для такого хоста
						if _, ok := utils.ChatOutConnections[userId]; !ok {
							fmt.Println("ADD", userId, conn.RemoteAddr(), utils.Time())
							connChan := make(chan *utils.ChatData, 100)
							utils.ChatMutex.Lock()
							utils.ChatOutConnections[userId] = &utils.ChatOutConnectionsType{MessIds: []int64{}, ConnectionChan: connChan}
							utils.ChatMutex.Unlock()
							fmt.Println("utils.ChatOutConnections", utils.ChatOutConnections)
							utils.ChatTxDisseminator(conn, userId, connChan)
						} else {
							fmt.Println("SKIP", userId, conn.RemoteAddr(), utils.Time())
							conn.Close()
						}
					}
				}
			}(conn)
		}
	}()
}
Example #10
0
func NodeVoting(chBreaker chan bool, chAnswer chan string) {
	defer func() {
		if r := recover(); r != nil {
			log.Error("daemon Recovered", r)
			panic(r)
		}
	}()

	const GoroutineName = "NodeVoting"
	d := new(daemon)
	d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName)
	if d.DCDB == nil {
		return
	}
	d.goRoutineName = GoroutineName
	d.chAnswer = chAnswer
	d.chBreaker = chBreaker
	if utils.Mobile() {
		d.sleepTime = 3600
	} else {
		d.sleepTime = 60
	}
	if !d.CheckInstall(chBreaker, chAnswer, GoroutineName) {
		return
	}
	d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName)
	if d.DCDB == nil {
		return
	}

	err = d.notMinerSetSleepTime(1800)
	if err != nil {
		log.Error("%v", err)
		return
	}

BEGIN:
	for {
		log.Info(GoroutineName)
		MonitorDaemonCh <- []string{GoroutineName, utils.Int64ToStr(utils.Time())}

		// проверим, не нужно ли нам выйти из цикла
		if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
			break BEGIN
		}

		err, restart := d.dbLock()
		if restart {
			break BEGIN
		}
		if err != nil {
			if d.dPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

		// берем данные, которые находятся на голосовании нодов
		rows, err := d.Query(d.FormatQuery(`
				SELECT miners_data.user_id,
							 http_host as host,
							 face_hash,
							 profile_hash,
							 photo_block_id,
							 photo_max_miner_id,
							 miners_keepers,
							 id as vote_id,
							 miner_id
				FROM votes_miners
				LEFT JOIN miners_data
						 ON votes_miners.user_id = miners_data.user_id
				WHERE cron_checked_time < ? AND
							 votes_end = 0 AND
							 type = 'node_voting'
				`), utils.Time()-consts.CRON_CHECKED_TIME_SEC)
		if err != nil {
			if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		if ok := rows.Next(); ok {
			var vote_id, miner_id int64
			var user_id, host, row_face_hash, row_profile_hash, photo_block_id, photo_max_miner_id, miners_keepers string
			err = rows.Scan(&user_id, &host, &row_face_hash, &row_profile_hash, &photo_block_id, &photo_max_miner_id, &miners_keepers, &vote_id, &miner_id)
			if err != nil {
				rows.Close()
				if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}

			// проверим, не нужно нам выйти, т.к. обновилась версия софта
			if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
				rows.Close()
				utils.Sleep(1)
				break
			}
			minersIds := utils.GetMinersKeepers(photo_block_id, photo_max_miner_id, miners_keepers, true)
			myUsersIds, err := d.GetMyUsersIds(true, true)
			myMinersIds, err := d.GetMyMinersIds(myUsersIds)

			// нет ли нас среди тех, кто должен скачать фото к себе и проголосовать
			var intersectMyMiners []int64
			for _, id := range minersIds {
				if utils.InSliceInt64(int64(id), myMinersIds) {
					intersectMyMiners = append(intersectMyMiners, int64(id))
				}
			}
			var vote int64
			if len(intersectMyMiners) > 0 {
				var downloadError bool
				var faceHash, profileHash string
				var faceFile, profileFile []byte
				// копируем фото  к себе
				profilePath := *utils.Dir + "/public/profile_" + user_id + ".jpg"
				_, err = utils.DownloadToFile(host+"/public/"+user_id+"_user_profile.jpg", profilePath, 60, chBreaker, chAnswer, GoroutineName)
				if err != nil {
					log.Error("%s", utils.ErrInfo(err))
					downloadError = true
				}
				facePath := *utils.Dir + "/public/face_" + user_id + ".jpg"
				_, err = utils.DownloadToFile(host+"/public/"+user_id+"_user_face.jpg", facePath, 60, chBreaker, chAnswer, GoroutineName)
				if err != nil {
					log.Error("%s", utils.ErrInfo(err))
					downloadError = true
				}
				if !downloadError {
					// хэши скопированных фото
					profileFile, err = ioutil.ReadFile(profilePath)
					if err != nil {
						rows.Close()
						if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
							break BEGIN
						}
						continue BEGIN
					}
					profileHash = string(utils.DSha256(profileFile))
					log.Info("%v", "profileHash", profileHash)
					faceFile, err = ioutil.ReadFile(facePath)
					if err != nil {
						rows.Close()
						if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
							break BEGIN
						}
						continue BEGIN
					}
					faceHash = string(utils.DSha256(faceFile))
					log.Info("%v", "faceHash", faceHash)
				}
				// проверяем хэш. Если сходится, то голосуем за, если нет - против и размер не должен быть более 200 Kb.
				if profileHash == row_profile_hash && faceHash == row_face_hash && len(profileFile) < 204800 && len(faceFile) < 204800 {
					vote = 1
				} else {
					log.Error("%s %s %s %s %d %d", profileHash, row_face_hash, faceHash, row_profile_hash, len(profileFile), len(faceFile))
					vote = 0 // если хэш не сходится, то удаляем только что скаченное фото
					os.Remove(profilePath)
					os.Remove(facePath)
				}

				// проходимся по всем нашим майнерам, если это пул и по одному, если это сингл-мод
				for _, myMinerId := range intersectMyMiners {

					myUserId, err := d.Single("SELECT user_id FROM miners_data WHERE miner_id  =  ?", myMinerId).Int64()
					if err != nil {
						rows.Close()
						if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
							break BEGIN
						}
						continue BEGIN
					}

					curTime := utils.Time()

					forSign := fmt.Sprintf("%v,%v,%v,%v,%v", utils.TypeInt("VotesNodeNewMiner"), curTime, myUserId, vote_id, vote)
					binSign, err := d.GetBinSign(forSign, myUserId)
					if err != nil {
						rows.Close()
						if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
							break BEGIN
						}
						continue BEGIN
					}
					data := utils.DecToBin(utils.TypeInt("VotesNodeNewMiner"), 1)
					data = append(data, utils.DecToBin(curTime, 4)...)
					data = append(data, utils.EncodeLengthPlusData(utils.Int64ToByte(myUserId))...)
					data = append(data, utils.EncodeLengthPlusData(utils.Int64ToByte(vote_id))...)
					data = append(data, utils.EncodeLengthPlusData(utils.Int64ToByte(vote))...)
					data = append(data, utils.EncodeLengthPlusData([]byte(binSign))...)

					err = d.InsertReplaceTxInQueue(data)
					if err != nil {
						rows.Close()
						if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
							break BEGIN
						}
						continue BEGIN
					}

				}
			}

			// отмечаем, чтобы больше не брать эту строку
			err = d.ExecSql("UPDATE votes_miners SET cron_checked_time = ? WHERE id = ?", utils.Time(), vote_id)
			if err != nil {
				rows.Close()
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
		}
		rows.Close()
		d.dbUnlock()

		if d.dSleep(d.sleepTime) {
			break BEGIN
		}
	}
	log.Debug("break BEGIN %v", GoroutineName)

}
Example #11
0
func Connector(chBreaker chan bool, chAnswer chan string) {
	defer func() {
		if r := recover(); r != nil {
			log.Error("daemon Recovered", r)
			panic(r)
		}
	}()

	if _, err := os.Stat(*utils.Dir + "/nodes.inc"); os.IsNotExist(err) {
		data, err := static.Asset("static/nodes.inc")
		if err != nil {
			log.Error("%v", err)
		}
		err = ioutil.WriteFile(*utils.Dir+"/nodes.inc", []byte(data), 0644)
		if err != nil {
			log.Error("%v", err)
		}
	}

	GoroutineName := "Connector"
	d := new(daemon)
	d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName)
	if d.DCDB == nil {
		return
	}
	d.goRoutineName = GoroutineName
	d.chAnswer = chAnswer
	d.chBreaker = chBreaker
	if utils.Mobile() {
		d.sleepTime = 600
	} else {
		d.sleepTime = 30
	}
	if !d.CheckInstall(chBreaker, chAnswer, GoroutineName) {
		return
	}
	d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName)
	if d.DCDB == nil {
		return
	}

	// соединения для чата иногда отваливаются, поэтому в цикле мониторим состояние
	go func() {
		for {
			if myUserIdForChat == 0 {
				utils.Sleep(1)
				continue
			}
			if len(utils.ChatOutConnections) < 5 || len(utils.ChatInConnections) < 5 {
				go d.chatConnector()
			}
			utils.Sleep(30)
		}
	}()

BEGIN:
	for {
		log.Info(GoroutineName)
		MonitorDaemonCh <- []string{GoroutineName, utils.Int64ToStr(utils.Time())}

		// проверим, не нужно ли нам выйти из цикла
		if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
			break BEGIN
		}

		nodeConfig, err := d.GetNodeConfig()
		if len(nodeConfig["local_gate_ip"]) > 0 {
			utils.Sleep(2)
			continue
		}

		var delMiners []string
		var hosts []map[string]string
		var nodeCount int64
		idArray := make(map[int]int64)
		nodesInc := make(map[string]string)

		// ровно стольким нодам мы будем слать хэши блоков и тр-ий
		var maxHosts = consts.OUT_CONNECTIONS
		if utils.StrToInt64(nodeConfig["out_connections"]) > 0 {
			maxHosts = utils.StrToInt(nodeConfig["out_connections"])
		}
		log.Info("%v", maxHosts)

		collective, err := d.GetCommunityUsers()
		if err != nil {
			log.Error("%v", err)
			return
		}
		if len(collective) == 0 {
			myUserId, err := d.GetMyUserId("")
			if err != nil {
				log.Error("%v", err)
				return
			}
			collective = append(collective, myUserId)
			myUserIdForChat = myUserId
		} else {
			myUserIdForChat, err = d.Single(`SELECT pool_admin_user_id FROM config`).Int64()
			if err != nil {
				log.Error("%v", err)
				return
			}
		}

		// в сингл-моде будет только $my_miners_ids[0]
		myMinersIds, err := d.GetMyMinersIds(collective)
		if err != nil {
			if d.dPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue
		}
		log.Info("%v", myMinersIds)
		nodesBan, err := d.GetMap(`
				SELECT tcp_host, ban_start
				FROM nodes_ban
				LEFT JOIN miners_data ON miners_data.user_id = nodes_ban.user_id
				`, "tcp_host", "ban_start")
		log.Info("%v", nodesBan)
		nodesConnections, err := d.GetAll(`
				SELECT nodes_connection.host,
							 nodes_connection.user_id,
							 ban_start,
							 miner_id
				FROM nodes_connection
				LEFT JOIN nodes_ban ON nodes_ban.user_id = nodes_connection.user_id
				LEFT JOIN miners_data ON miners_data.user_id = nodes_connection.user_id
				`, -1)
		//fmt.Println("nodesConnections", nodesConnections)
		log.Debug("nodesConnections: %v", nodesConnections)
		for _, data := range nodesConnections {

			// проверим, не нужно нам выйти, т.к. обновилась версия софта
			if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
				break BEGIN
			}

			/*// проверим соотвествие хоста и user_id
			ok, err := d.Single("SELECT user_id FROM miners_data WHERE user_id  = ? AND tcp_host  =  ?", data["user_id"], data["host"]).Int64()
			if err != nil {
				utils.Sleep(1)
				continue BEGIN
			}
			if ok == 0 {
				err = d.ExecSql("DELETE FROM nodes_connection WHERE host = ? OR user_id = ?", data["host"], data["user_id"])
				if err != nil {
					utils.Sleep(1)
					continue BEGIN
				}
			}*/

			// если нода забанена недавно
			if utils.StrToInt64(data["ban_start"]) > utils.Time()-consts.NODE_BAN_TIME {
				delMiners = append(delMiners, data["miner_id"])
				err = d.ExecSql("DELETE FROM nodes_connection WHERE host = ? OR user_id = ?", data["host"], data["user_id"])
				if err != nil {
					if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				continue
			}

			hosts = append(hosts, map[string]string{"host": data["host"], "user_id": data["user_id"]})
			nodesInc[data["host"]] = data["user_id"]
			nodeCount++
		}

		log.Debug("hosts: %v", hosts)
		/*
			ch := make(chan *answerType)
			for _, host := range hosts {
				userId := utils.StrToInt64(host["user_id"])
				go func(userId int64, host string) {
					ch_ := make(chan *answerType, 1)
					go func() {
						log.Debug("host: %v / userId: %v", host, userId)
						ch_ <- check(host, userId)
					}()
					select {
					case reachable := <-ch_:
						ch <- reachable
					case <-time.After(consts.WAIT_CONFIRMED_NODES * time.Second):
						ch <- &answerType{userId: userId, answer: 0}
					}
				}(userId, host["host"])
			}

			log.Debug("%v", "hosts", hosts)

			var newHosts []map[string]string
			var countOk int
			// если нода не отвечает, то удалем её из таблы nodes_connection
			for i := 0; i < len(hosts); i++ {
				result := <-ch
				if result.answer == 0 {
					log.Info("delete %v", result.userId)
					err = d.ExecSql("DELETE FROM nodes_connection WHERE user_id = ?", result.userId)
					if err != nil {
						if d.dPrintSleep(err, d.sleepTime) {	break BEGIN }
					}
					for _, data := range hosts {
						if utils.StrToInt64(data["user_id"]) != result.userId {
							newHosts = append(newHosts, data)
						}
					}
				} else {
					countOk++
				}
				log.Info("answer: %v", result)
			}
		*/
		var countOk int
		hosts = checkHosts(hosts, &countOk)
		log.Debug("countOk: %d / hosts: %v", countOk, hosts)
		// проверим, не нужно нам выйти, т.к. обновилась версия софта
		if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
			break BEGIN
		}
		// добьем недостающие хосты до $max_hosts
		var newHostsForCheck []map[string]string
		if len(hosts) < maxHosts {
			need := maxHosts - len(hosts)
			max, err := d.Single("SELECT max(miner_id) FROM miners").Int()
			if err != nil {
				if d.dPrintSleep(err, d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			i0 := 0
			for {
				rand := 1
				if max > 1 {
					rand = utils.RandInt(1, max+1)
				}
				idArray[rand] = 1
				i0++
				if i0 > 30 || len(idArray) >= need || len(idArray) >= max {
					break
				}
			}
			log.Info("%v", "idArray", idArray)
			// удалим себя
			for _, id := range myMinersIds {
				delete(idArray, int(id))
			}
			// Удалим забаннные хосты
			for _, id := range delMiners {
				delete(idArray, utils.StrToInt(id))
			}
			log.Info("%v", "idArray", idArray)
			ids := ""
			if len(idArray) > 0 {
				for id, _ := range idArray {
					ids += utils.IntToStr(id) + ","
				}
				ids = ids[:len(ids)-1]
				minersHosts, err := d.GetMap(`
						SELECT tcp_host, user_id
						FROM miners_data
						WHERE miner_id IN (`+ids+`)`, "tcp_host", "user_id")
				if err != nil {
					if d.dPrintSleep(err, d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				for host, userId := range minersHosts {
					if len(nodesBan[host]) > 0 {
						if utils.StrToInt64(nodesBan[host]) > utils.Time()-consts.NODE_BAN_TIME {
							continue
						}
					}
					//hosts = append(hosts, map[string]string{"host": host, "user_id": userId})
					/*err = d.ExecSql("DELETE FROM nodes_connection WHERE host = ?", host)
					if err != nil {
						if d.dPrintSleep(err, d.sleepTime) {	break BEGIN }
						continue BEGIN
					}
					log.Debug(host)*/
					newHostsForCheck = append(newHostsForCheck, map[string]string{"user_id": userId, "host": host})
					/*err = d.ExecSql("INSERT INTO nodes_connection ( host, user_id ) VALUES ( ?, ? )", host, userId)
					if err != nil {
						if d.dPrintSleep(err, d.sleepTime) {	break BEGIN }
						continue BEGIN
					}*/
				}
			}
		}

		hosts = checkHosts(newHostsForCheck, &countOk)
		log.Debug("countOk: %d / hosts: %v", countOk, hosts)
		// проверим, не нужно нам выйти, т.к. обновилась версия софта
		if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
			break BEGIN
		}
		log.Debug("%v", "hosts", hosts)
		// если хосты не набрались из miner_data, то берем из файла
		if len(hosts) < 10 {
			hostsData_, err := ioutil.ReadFile(*utils.Dir + "/nodes.inc")
			if err != nil {
				if d.dPrintSleep(err, d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			hostsData := strings.Split(string(hostsData_), "\n")
			log.Debug("%v", "hostsData_", hostsData_)
			log.Debug("%v", "hostsData", hostsData)
			max := 0
			log.Debug("maxHosts: %v", maxHosts)
			if len(hosts) > maxHosts-1 {
				max = maxHosts
			} else {
				max = len(hostsData)
			}
			log.Debug("max: %v", max)
			for i := 0; i < max; i++ {
				r := utils.RandInt(0, max)
				if len(hostsData) <= r {
					continue
				}
				hostUserId := strings.Split(hostsData[r], ";")
				if len(hostUserId) == 1 {
					continue
				}
				host, userId := hostUserId[0], hostUserId[1]
				if utils.InSliceInt64(utils.StrToInt64(userId), collective) {
					continue
				}
				if len(nodesBan[host]) > 0 {
					if utils.StrToInt64(nodesBan[host]) > utils.Time()-consts.NODE_BAN_TIME {
						continue
					}
				}
				/*
					err = d.ExecSql("DELETE FROM nodes_connection WHERE host = ?", host)
					if err != nil {
						if d.dPrintSleep(err, d.sleepTime) {	break BEGIN }
						continue BEGIN
					}
					log.Debug(host)
					/*err = d.ExecSql("INSERT INTO nodes_connection ( host, user_id ) VALUES ( ?, ? )", host, userId)
					if err != nil {
						if d.dPrintSleep(err, d.sleepTime) {	break BEGIN }
						continue BEGIN
					}*/
				newHostsForCheck = append(newHostsForCheck, map[string]string{"user_id": userId, "host": host})

				nodesInc[host] = userId

			}
		}

		hosts = checkHosts(newHostsForCheck, &countOk)
		log.Debug("countOk: %d / hosts: %v", countOk, hosts)
		// проверим, не нужно нам выйти, т.к. обновилась версия софта
		if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
			break BEGIN
		}
		for _, host := range hosts {
			err = d.ExecSql("DELETE FROM nodes_connection WHERE host = ?", host["host"])
			if err != nil {
				if d.dPrintSleep(err, d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			err = d.ExecSql("INSERT INTO nodes_connection ( host, user_id ) VALUES ( ?, ? )", host["host"], host["user_id"])
			if err != nil {
				if d.dPrintSleep(err, d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
		}
		if nodeCount > 5 {
			nodesFile := ""
			for k, v := range nodesInc {
				nodesFile += k + ";" + v + "\n"
			}
			nodesFile = nodesFile[:len(nodesFile)-1]
			err := ioutil.WriteFile(*utils.Dir+"/nodes.inc", []byte(nodesFile), 0644)
			if err != nil {
				if d.dPrintSleep(err, d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
		}

		var sleepTime int
		if countOk < 2 {
			sleepTime = 5
		} else {
			sleepTime = d.sleepTime
		}

		if d.dSleep(sleepTime) {
			break BEGIN
		}
	}
	log.Debug("break BEGIN %v", GoroutineName)
}
Example #12
0
func (a *AvailablekeyStruct) GetAvailableKey() (int64, string, error) {

	community, err := a.GetCommunityUsers()
	if err != nil {
		return 0, "", utils.ErrInfo(err)
	}
	// запрещено менять ключ таким методом если в my_table уже есть статус
	if len(community) == 0 {
		status, err := a.Single("SELECT status FROM my_table").String()
		if err != nil {
			return 0, "", utils.ErrInfo(err)
		}
		if status != "my_pending" {
			return 0, "", utils.ErrInfo(errors.New("my_table not null"))
		}
	}

	var keys []string
	for i := 0; i < 10; i++ {
		keysStr, err := utils.GetHttpTextAnswer("http://dcoin.club/keys")
		if err != nil {
			return 0, "", utils.ErrInfo(err)
		}
		//keysStr = strings.Replace(keysStr, "\n", "", -1)
		r, _ := regexp.Compile("(?s)-----BEGIN RSA PRIVATE KEY-----(.*?)-----END RSA PRIVATE KEY-----")
		keys = r.FindAllString(keysStr, -1)
		for i := range keys {
			j := rand.Intn(i + 1)
			keys[i], keys[j] = keys[j], keys[i]
		}
		if len(keys) > 0 {
			break
		} else {
			utils.Sleep(5)
		}
	}

	for _, key := range keys {
		userId, pubKey, err := a.checkAvailableKey(key)
		if err != nil {
			log.Error("%s", utils.ErrInfo(err)) // тут ошибка - это нормально
		}
		log.Debug("checkAvailableKey userId: %v", userId)
		if userId > 0 {
			// запишем приватный ключ в БД, чтобы можно было подписать тр-ию на смену ключа
			myPref := ""

			log.Debug("schema_ 0")
			if len(community) > 0 {
				schema_ := &schema.SchemaStruct{}
				schema_.DCDB = a.DCDB
				schema_.DbType = a.ConfigIni["db_type"]
				schema_.PrefixUserId = int(userId)
				schema_.GetSchema()
				myPref = utils.Int64ToStr(userId) + "_"
				err = a.ExecSql("INSERT INTO "+myPref+"my_table (user_id, status, email) VALUES (?, ?, ?)", userId, "waiting_set_new_key", a.Email)
				if err != nil {
					return 0, "", utils.ErrInfo(err)
				}
				err = a.ExecSql("INSERT INTO community ( user_id ) VALUES ( ? )", userId)
				if err != nil {
					return 0, "", utils.ErrInfo(err)
				}
			} else {
				err = a.ExecSql("UPDATE my_table SET user_id = ?, status = ?", userId, "waiting_set_new_key")
				if err != nil {
					return 0, "", utils.ErrInfo(err)
				}
			}
			log.Debug("schema_ 1")

			// пишем приватный в my_keys т.к. им будем подписывать тр-ию на смену ключа
			err = a.ExecSql("INSERT INTO "+myPref+"my_keys (private_key, public_key, status, block_id) VALUES (?, [hex], ?, ?)", key, pubKey, "approved", 1)
			if err != nil {
				return 0, "", utils.ErrInfo(err)
			}
			log.Debug("GenKeys 0")
			newPrivKey, newPubKey := utils.GenKeys()
			log.Debug("GenKeys 1")
			// сразу генерируем новый ключ и пишем приватный временно в my_keys, чтобы можно было выдавать юзеру для скачивания
			err = a.ExecSql("INSERT INTO "+myPref+"my_keys (private_key, public_key, status) VALUES (?, ?, ?)", newPrivKey, utils.HexToBin([]byte(newPubKey)), "my_pending")
			if err != nil {
				return 0, "", utils.ErrInfo(err)
			}
			log.Debug("return userId %d", userId)
			return userId, pubKey, nil
		}
	}
	return 0, "", nil
}
Example #13
0
func Start(dir string, thrustWindowLoder *window.Window) {

	var err error
	IosLog("start")

	defer func() {
		if r := recover(); r != nil {
			log.Error("Recovered", r)
			panic(r)
		}
	}()

	if dir != "" {
		fmt.Println("dir", dir)
		*utils.Dir = dir
	}
	IosLog("dir:" + dir)
	fmt.Println("utils.Dir", *utils.Dir)

	fmt.Println("dcVersion:", consts.VERSION)
	log.Debug("dcVersion: %v", consts.VERSION)

	// читаем config.ini
	configIni := make(map[string]string)
	configIni_, err := config.NewConfig("ini", *utils.Dir+"/config.ini")
	if err != nil {
		IosLog("err:" + fmt.Sprintf("%s", utils.ErrInfo(err)))
		log.Error("%v", utils.ErrInfo(err))
	} else {
		configIni, err = configIni_.GetSection("default")
	}

	// убьем ранее запущенный Dcoin
	if !utils.Mobile() {
		fmt.Println("kill dcoin.pid")
		if _, err := os.Stat(*utils.Dir + "/dcoin.pid"); err == nil {
			dat, err := ioutil.ReadFile(*utils.Dir + "/dcoin.pid")
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
			}
			var pidMap map[string]string
			err = json.Unmarshal(dat, &pidMap)
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
			}
			fmt.Println("old PID ("+*utils.Dir+"/dcoin.pid"+"):", pidMap["pid"])

			utils.DB, err = utils.NewDbConnect(configIni)

			err = KillPid(pidMap["pid"])
			if nil != err {
				fmt.Println(err)
				log.Error("KillPid %v", utils.ErrInfo(err))
			}
			if fmt.Sprintf("%s", err) != "null" {
				fmt.Println(fmt.Sprintf("%s", err))
				// даем 15 сек, чтобы завершиться предыдущему процессу
				for i := 0; i < 15; i++ {
					log.Debug("waiting killer %d", i)
					if _, err := os.Stat(*utils.Dir + "/dcoin.pid"); err == nil {
						fmt.Println("waiting killer")
						utils.Sleep(1)
					} else { // если dcoin.pid нет, значит завершился
						break
					}
				}
			}
		}
	}

	// сохраним текущий pid и версию
	if !utils.Mobile() {
		pid := os.Getpid()
		PidAndVer, err := json.Marshal(map[string]string{"pid": utils.IntToStr(pid), "version": consts.VERSION})
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}
		err = ioutil.WriteFile(*utils.Dir+"/dcoin.pid", PidAndVer, 0644)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			panic(err)
		}
	}

	controllers.SessInit()
	controllers.ConfigInit()
	daemons.ConfigInit()

	go func() {
		utils.DB, err = utils.NewDbConnect(configIni)
		log.Debug("%v", utils.DB)
		IosLog("utils.DB:" + fmt.Sprintf("%v", utils.DB))
		if err != nil {
			IosLog("err:" + fmt.Sprintf("%s", utils.ErrInfo(err)))
			log.Error("%v", utils.ErrInfo(err))
			panic(err)
			os.Exit(1)
		}
	}()

	f, err := os.OpenFile(*utils.Dir+"/dclog.txt", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0777)
	if err != nil {
		IosLog("err:" + fmt.Sprintf("%s", utils.ErrInfo(err)))
		log.Error("%v", utils.ErrInfo(err))
		panic(err)
		os.Exit(1)
	}
	defer f.Close()
	IosLog("configIni:" + fmt.Sprintf("%v", configIni))
	var backend *logging.LogBackend
	switch configIni["log_output"] {
	case "file":
		backend = logging.NewLogBackend(f, "", 0)
	case "console":
		backend = logging.NewLogBackend(os.Stderr, "", 0)
	case "file_console":
		//backend = logging.NewLogBackend(io.MultiWriter(f, os.Stderr), "", 0)
	default:
		backend = logging.NewLogBackend(f, "", 0)
	}
	backendFormatter := logging.NewBackendFormatter(backend, format)
	backendLeveled := logging.AddModuleLevel(backendFormatter)

	logLevel_ := "DEBUG"
	if *utils.LogLevel == "" {
		logLevel_ = configIni["log_level"]
	} else {
		logLevel_ = *utils.LogLevel
	}

	logLevel, err := logging.LogLevel(logLevel_)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
	}

	log.Debug("logLevel: %v", logLevel)
	backendLeveled.SetLevel(logLevel, "")
	logging.SetBackend(backendLeveled)

	rand.Seed(time.Now().UTC().UnixNano())

	// если есть OldFileName, значит работаем под именем tmp_dc и нужно перезапуститься под нормальным именем
	log.Error("OldFileName %v", *utils.OldFileName)
	if *utils.OldFileName != "" {

		// вначале нужно обновить БД в зависимости от версии
		dat, err := ioutil.ReadFile(*utils.Dir + "/dcoin.pid")
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}
		var pidMap map[string]string
		err = json.Unmarshal(dat, &pidMap)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}

		log.Debug("OldFileName %v", *utils.OldFileName)
		err = utils.CopyFileContents(*utils.Dir+`/dc.tmp`, *utils.OldFileName)
		if err != nil {
			log.Debug("%v", os.Stderr)
			log.Debug("%v", utils.ErrInfo(err))
		}
		// ждем подключения к БД
		for {
			if utils.DB == nil || utils.DB.DB == nil {
				utils.Sleep(1)
				continue
			}
			break
		}
		if len(pidMap["version"]) > 0 {
			if utils.VersionOrdinal(pidMap["version"]) < utils.VersionOrdinal("1.0.2b5") {
				log.Debug("%v", "ALTER TABLE config ADD COLUMN analytics_disabled smallint")
				err = utils.DB.ExecSql(`ALTER TABLE config ADD COLUMN analytics_disabled smallint`)
				if err != nil {
					log.Error("%v", utils.ErrInfo(err))
				}
			}
			if utils.VersionOrdinal(pidMap["version"]) < utils.VersionOrdinal("2.0.1b2") {
				log.Debug("%v", "ALTER TABLE config ADD COLUMN sqlite_db_url varchar(255)")
				err = utils.DB.ExecSql(`ALTER TABLE config ADD COLUMN sqlite_db_url varchar(255)`)
				if err != nil {
					log.Error("%v", utils.ErrInfo(err))
				}
			}
		}
		err = utils.DB.Close()
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}
		fmt.Println("DB Closed")
		err = os.Remove(*utils.Dir + "/dcoin.pid")
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}

		log.Debug("dc.tmp %v", *utils.Dir+`/dc.tmp`)
		err = exec.Command(*utils.OldFileName, "-dir", *utils.Dir).Start()
		if err != nil {
			log.Debug("%v", os.Stderr)
			log.Debug("%v", utils.ErrInfo(err))
		}
		log.Debug("OldFileName %v", *utils.OldFileName)
		os.Exit(1)
	}
	// откат БД до указанного блока
	if *utils.RollbackToBlockId > 0 {
		utils.DB, err = utils.NewDbConnect(configIni)
		parser := new(dcparser.Parser)
		parser.DCDB = utils.DB
		err = parser.RollbackToBlockId(*utils.RollbackToBlockId)
		if err != nil {
			fmt.Println(err)
			panic(err)
		}
		fmt.Print("complete")
		os.Exit(0)
	}

	log.Debug("public")
	IosLog("public")
	if _, err := os.Stat(*utils.Dir + "/public"); os.IsNotExist(err) {
		err = os.Mkdir(*utils.Dir+"/public", 0755)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			panic(err)
			os.Exit(1)
		}
	}

	log.Debug("daemonsStart")
	IosLog("daemonsStart")

	daemons.StartDaemons()

	IosLog("MonitorDaemons")
	// мониторинг демонов
	daemonsTable := make(map[string]string)
	go func() {
		for {
			daemonNameAndTime := <-daemons.MonitorDaemonCh
			daemonsTable[daemonNameAndTime[0]] = daemonNameAndTime[1]
			if utils.Time()%10 == 0 {
				log.Debug("daemonsTable: %v\n", daemonsTable)
			}
		}
	}()

	// сигналы демонам для выхода
	IosLog("signals")
	stopdaemons.Signals()

	utils.Sleep(1)

	// мониторим сигнал из БД о том, что демонам надо завершаться
	go stopdaemons.WaitStopTime()

	BrowserHttpHost := "http://localhost:8089"
	HandleHttpHost := ""
	ListenHttpHost := ":" + *utils.ListenHttpHost
	go func() {
		// уже прошли процесс инсталяции, где юзер указал БД и был перезапуск кошелька
		if len(configIni["db_type"]) > 0 && !utils.Mobile() {
			for {
				// ждем, пока произойдет подключение к БД в другой гоурутине
				if utils.DB == nil || utils.DB.DB == nil {
					utils.Sleep(1)
					fmt.Println("wait DB")
				} else {
					break
				}
			}
			fmt.Println("GET http host")
			BrowserHttpHost, HandleHttpHost, ListenHttpHost = GetHttpHost()
			// для биржы нужен хост или каталог, поэтому нужно подключение к БД
			exhangeHttpListener(HandleHttpHost)
			// для ноды тоже нужна БД
			tcpListener()
		}
		IosLog(fmt.Sprintf("BrowserHttpHost: %v, HandleHttpHost: %v, ListenHttpHost: %v", BrowserHttpHost, HandleHttpHost, ListenHttpHost))
		fmt.Printf("BrowserHttpHost: %v, HandleHttpHost: %v, ListenHttpHost: %v\n", BrowserHttpHost, HandleHttpHost, ListenHttpHost)
		// включаем листинг веб-сервером для клиентской части
		http.HandleFunc(HandleHttpHost+"/", controllers.Index)
		http.HandleFunc(HandleHttpHost+"/content", controllers.Content)
		http.HandleFunc(HandleHttpHost+"/ajax", controllers.Ajax)
		http.HandleFunc(HandleHttpHost+"/tools", controllers.Tools)
		http.HandleFunc(HandleHttpHost+"/cf/", controllers.IndexCf)
		http.HandleFunc(HandleHttpHost+"/cf/content", controllers.ContentCf)
		http.Handle(HandleHttpHost+"/public/", noDirListing(http.FileServer(http.Dir(*utils.Dir))))
		http.Handle(HandleHttpHost+"/static/", http.FileServer(&assetfs.AssetFS{Asset: static.Asset, AssetDir: static.AssetDir, Prefix: ""}))

		log.Debug("ListenHttpHost", ListenHttpHost)

		IosLog(fmt.Sprintf("ListenHttpHost: %v", ListenHttpHost))

		fmt.Println("ListenHttpHost", ListenHttpHost)

		httpListener(ListenHttpHost, BrowserHttpHost)

		if *utils.Console == 0 && !utils.Mobile() {
			utils.Sleep(1)
			if thrustWindowLoder != nil {
				thrustWindowLoder.Close()
				thrustWindow := thrust.NewWindow(thrust.WindowOptions{
					RootUrl: BrowserHttpHost,
					Size:    commands.SizeHW{Width: 1024, Height: 600},
				})
				thrustWindow.HandleEvent("*", func(cr commands.EventResult) {
					fmt.Println("HandleEvent", cr)
				})
				thrustWindow.HandleRemote(func(er commands.EventResult, this *window.Window) {
					fmt.Println("RemoteMessage Recieved:", er.Message.Payload)
					openBrowser(er.Message.Payload)
					// Keep in mind once we have the message, lets say its json of some new type we made,
					// We can unmarshal it to that type.
					// Same goes for the other way around.
					this.SendRemoteMessage("boop")
				})
				thrustWindow.Show()
				thrustWindow.Focus()
			} else {
				openBrowser(BrowserHttpHost)
			}
		}
	}()

	// ожидает появления свежих записей в чате, затем ждет появления коннектов
	// (заносятся из демеона connections и от тех, кто сам подключился к ноде)
	go utils.ChatOutput(utils.ChatNewTx)

	log.Debug("ALL RIGHT")
	IosLog("ALL RIGHT")
	fmt.Println("ALL RIGHT")
	utils.Sleep(3600 * 24 * 90)
	log.Debug("EXIT")
}
Example #14
0
func TestblockIsReady(chBreaker chan bool, chAnswer chan string) {
	defer func() {
		if r := recover(); r != nil {
			log.Error("daemon Recovered", r)
			panic(r)
		}
	}()

	const GoroutineName = "TestblockIsReady"
	d := new(daemon)
	d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName)
	if d.DCDB == nil {
		return
	}
	d.goRoutineName = GoroutineName
	d.chAnswer = chAnswer
	d.chBreaker = chBreaker
	if utils.Mobile() {
		d.sleepTime = 3600
	} else {
		d.sleepTime = 1
	}
	if !d.CheckInstall(chBreaker, chAnswer, GoroutineName) {
		return
	}

	err = d.notMinerSetSleepTime(1800)
	if err != nil {
		log.Error("%v", err)
		return
	}

BEGIN:
	for {
		log.Info(GoroutineName)
		MonitorDaemonCh <- []string{GoroutineName, utils.Int64ToStr(utils.Time())}

		// проверим, не нужно ли нам выйти из цикла
		if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
			break BEGIN
		}

		LocalGateIp, err := d.GetMyLocalGateIp()
		if err != nil {
			if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue
		}
		if len(LocalGateIp) > 0 {
			if d.dPrintSleep(utils.ErrInfo(errors.New("len(LocalGateIp) > 0")), d.sleepTime) {
				break BEGIN
			}
			continue
		}

		// сколько нужно спать
		prevBlock, myUserId, myMinerId, currentUserId, level, levelsRange, err := d.TestBlock()
		if err != nil {
			if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue
		}
		log.Info("%v", prevBlock, myUserId, myMinerId, currentUserId, level, levelsRange)

		if myMinerId == 0 {
			log.Debug("myMinerId == 0")
			if d.dSleep(d.sleepTime) {
				break BEGIN
			}
			continue
		}

		sleepData, err := d.GetSleepData()
		sleep := d.GetIsReadySleep(prevBlock.Level, sleepData["is_ready"])
		prevHeadHash := prevBlock.HeadHash

		// Если случится откат или придет новый блок, то testblock станет неактуален
		startSleep := utils.Time()
		for i := 0; i < int(sleep); i++ {
			err, restart := d.dbLock()
			if restart {
				break BEGIN
			}
			if err != nil {
				if d.dPrintSleep(err, d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}

			newHeadHash, err := d.Single("SELECT head_hash FROM info_block").String()
			if err != nil {
				if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue
			}
			d.dbUnlock()
			newHeadHash = string(utils.BinToHex([]byte(newHeadHash)))
			if newHeadHash != prevHeadHash {
				if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			log.Info("%v", "i", i, "time", utils.Time())
			if utils.Time()-startSleep > sleep {
				break
			}
			utils.Sleep(1) // спим 1 сек. общее время = $sleep
		}

		/*
			Заголовок
			TYPE (0-блок, 1-тр-я)       FF (256)
			BLOCK_ID   				       FF FF FF FF (4 294 967 295)
			TIME       					       FF FF FF FF (4 294 967 295)
			USER_ID                          FF FF FF FF FF (1 099 511 627 775)
			LEVEL                              FF (256)
			SIGN                               от 128 байта до 512 байт. Подпись от TYPE, BLOCK_ID, PREV_BLOCK_HASH, TIME, USER_ID, LEVEL, MRKL_ROOT
			Далее - тело блока (Тр-ии)
		*/

		// блокируем изменения данных в тестблоке
		// также, нужно блокировать main, т.к. изменение в info_block и block_chain ведут к изменению подписи в testblock
		err, restart := d.dbLock()
		if restart {
			break BEGIN
		}
		if err != nil {
			if d.dPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		// за промежуток в main_unlock и main_lock мог прийти новый блок
		prevBlock, myUserId, myMinerId, currentUserId, level, levelsRange, err = d.TestBlock()
		if err != nil {
			if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue
		}
		log.Info("%v", prevBlock, myUserId, myMinerId, currentUserId, level, levelsRange)

		// на всякий случай убедимся, что блок не изменился
		if prevBlock.HeadHash != prevHeadHash {
			if d.unlockPrintSleep(utils.ErrInfo(errors.New("prevBlock.HeadHash != prevHeadHash")), d.sleepTime) {
				break BEGIN
			}
			continue
		}

		// составим блок. заголовок + тело + подпись
		testBlockData, err := d.OneRow("SELECT * FROM testblock WHERE status  =  'active'").String()
		if err != nil {
			if d.unlockPrintSleep(utils.ErrInfo(errors.New("prevBlock.HeadHash != prevHeadHash")), d.sleepTime) {
				break BEGIN
			}
			continue
		}
		log.Debug("testBlockData: %v", testBlockData)
		if len(testBlockData) == 0 {
			if d.unlockPrintSleep(utils.ErrInfo(errors.New("null $testblock_data")), d.sleepTime) {
				break BEGIN
			}
			continue
		}
		// получим транзакции
		var testBlockDataTx []byte
		transactionsTestBlock, err := d.GetList("SELECT data FROM transactions_testblock ORDER BY id ASC").String()
		if err != nil {
			if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		for _, data := range transactionsTestBlock {
			testBlockDataTx = append(testBlockDataTx, utils.EncodeLengthPlusData([]byte(data))...)
		}

		// в промежутке межде тем, как блок был сгенерирован и запуском данного скрипта может измениться текущий блок
		// поэтому нужно проверять подпись блока из тестблока
		prevBlockHash, err := d.Single("SELECT hash FROM info_block").Bytes()
		if err != nil {
			if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		prevBlockHash = utils.BinToHex(prevBlockHash)
		nodePublicKey, err := d.GetNodePublicKey(utils.StrToInt64(testBlockData["user_id"]))
		if err != nil {
			if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		forSign := fmt.Sprintf("0,%v,%s,%v,%v,%v,%s", testBlockData["block_id"], prevBlockHash, testBlockData["time"], testBlockData["user_id"], testBlockData["level"], utils.BinToHex([]byte(testBlockData["mrkl_root"])))
		log.Debug("forSign %v", forSign)
		log.Debug("signature %x", testBlockData["signature"])

		p := new(dcparser.Parser)
		p.DCDB = d.DCDB
		// проверяем подпись
		_, err = utils.CheckSign([][]byte{nodePublicKey}, forSign, []byte(testBlockData["signature"]), true)
		if err != nil {
			log.Error("incorrect signature %v")
			p.RollbackTransactionsTestblock(true)
			err = d.ExecSql("DELETE FROM testblock")
			if err != nil {
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		// БАГ
		if utils.StrToInt64(testBlockData["block_id"]) == prevBlock.BlockId {
			log.Error("testBlockData block_id =  prevBlock.BlockId (%v=%v)", testBlockData["block_id"], prevBlock.BlockId)

			err = p.RollbackTransactionsTestblock(true)
			if err != nil {
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			err = d.ExecSql("DELETE FROM testblock")
			if err != nil {
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

		// готовим заголовок
		newBlockIdBinary := utils.DecToBin(utils.StrToInt64(testBlockData["block_id"]), 4)
		timeBinary := utils.DecToBin(utils.StrToInt64(testBlockData["time"]), 4)
		userIdBinary := utils.DecToBin(utils.StrToInt64(testBlockData["user_id"]), 5)
		levelBinary := utils.DecToBin(utils.StrToInt64(testBlockData["level"]), 1)
		//prevBlockHashBinary := prevBlock.Hash
		//merkleRootBinary := testBlockData["mrklRoot"];

		// заголовок
		blockHeader := utils.DecToBin(0, 1)
		blockHeader = append(blockHeader, newBlockIdBinary...)
		blockHeader = append(blockHeader, timeBinary...)
		blockHeader = append(blockHeader, userIdBinary...)
		blockHeader = append(blockHeader, levelBinary...)
		blockHeader = append(blockHeader, utils.EncodeLengthPlusData([]byte(testBlockData["signature"]))...)

		// сам блок
		block := append(blockHeader, testBlockDataTx...)
		log.Debug("block %x", block)

		// теперь нужно разнести блок по таблицам и после этого мы будем его слать всем нодам скриптом disseminator.php
		p.BinaryData = block
		err = p.ParseDataFront()
		if err != nil {
			if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

		// и можно удалять данные о тестблоке, т.к. они перешел в нормальный блок
		err = d.ExecSql("DELETE FROM transactions_testblock")
		if err != nil {
			if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		err = d.ExecSql("DELETE FROM testblock")
		if err != nil {
			if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

		// между testblock_generator и testbock_is_ready
		p.RollbackTransactionsTestblock(false)

		d.dbUnlock()

		if d.dSleep(d.sleepTime) {
			break BEGIN
		}
	}
	log.Debug("break BEGIN %v", GoroutineName)
}
Example #15
0
// Шаг 1 - выбор либо стандартных настроек (sqlite и блокчейн с сервера) либо расширенных - pg/mysql и загрузка с нодов
func (c *Controller) InstallStep1() (string, error) {

	c.r.ParseForm()
	installType := c.r.FormValue("type")
	url := c.r.FormValue("url")
	setupPassword := c.r.FormValue("setup_password")
	userId := utils.StrToInt64(c.r.FormValue("user_id"))
	firstLoad := c.r.FormValue("first_load")
	dbType := c.r.FormValue("db_type")
	dbHost := c.r.FormValue("host")
	dbPort := c.r.FormValue("port")
	dbName := c.r.FormValue("db_name")
	dbUsername := c.r.FormValue("username")
	dbPassword := c.r.FormValue("password")
	sqliteDbUrl := c.r.FormValue("sqlite_db_url")
	keyPassword := c.r.FormValue("key_password")

	if installType == "standard" {
		dbType = "sqlite"
	} else {
		if len(url) == 0 {
			url = consts.BLOCKCHAIN_URL
		}
	}

	if _, err := os.Stat(*utils.Dir + "/config.ini"); os.IsNotExist(err) {
		ioutil.WriteFile(*utils.Dir+"/config.ini", []byte(``), 0644)
	}
	confIni, err := config.NewConfig("ini", *utils.Dir+"/config.ini")
	//confIni.Set("sql_log", "1")
	confIni.Set("error_log", "1")
	confIni.Set("log_level", "DEBUG")
	confIni.Set("log", "0")
	confIni.Set("log_block_id_begin", "0")
	confIni.Set("log_block_id_end", "0")
	confIni.Set("bad_tx_log", "1")
	confIni.Set("nodes_ban_exit", "0")
	confIni.Set("log_tables", "")
	confIni.Set("log_fns", "")
	confIni.Set("sign_hash", "ip")
	if len(sqliteDbUrl) > 0 && dbType == "sqlite" {
		utils.SqliteDbUrl = sqliteDbUrl
	}

	if dbType == "sqlite" {
		confIni.Set("db_type", "sqlite")
		confIni.Set("db_user", "")
		confIni.Set("db_host", "")
		confIni.Set("db_port", "")
		confIni.Set("db_password", "")
		confIni.Set("db_name", "")
	} else if dbType == "postgresql" || dbType == "mysql" {
		confIni.Set("db_type", dbType)
		confIni.Set("db_user", dbUsername)
		confIni.Set("db_host", dbHost)
		confIni.Set("db_port", dbPort)
		confIni.Set("db_password", dbPassword)
		confIni.Set("db_name", dbName)
	}

	err = confIni.SaveConfigFile(*utils.Dir + "/config.ini")
	if err != nil {
		return "", err
	}

	log.Debug("sqliteDbUrl: %s", sqliteDbUrl)

	go func() {

		configIni, err = confIni.GetSection("default")

		if dbType == "sqlite" && len(sqliteDbUrl) > 0 {
			if utils.DB != nil && utils.DB.DB != nil {
				utils.DB.Close()
				log.Debug("DB CLOSE")
			}
			for i := 0; i < 5; i++ {
				log.Debug("sqliteDbUrl %v", sqliteDbUrl)
				_, err := utils.DownloadToFile(sqliteDbUrl, *utils.Dir+"/litedb.db", 3600, nil, nil, "install")
				if err != nil {
					log.Error("%v", utils.ErrInfo(err))
				}
				if err == nil {
					break
				}
			}
			if err != nil {
				panic(err)
				os.Exit(1)
			}
			utils.DB, err = utils.NewDbConnect(configIni)
			log.Debug("DB OPEN")
			log.Debug("%v", utils.DB)
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
				panic(err)
				os.Exit(1)
			}
		} else {
			utils.DB, err = utils.NewDbConnect(configIni)
		}

		c.DCDB = utils.DB
		if c.DCDB.DB == nil {
			err = fmt.Errorf("utils.DB == nil")
			log.Error("%v", utils.ErrInfo(err))
			panic(err)
			os.Exit(1)
		}

		if dbType != "sqlite" || len(sqliteDbUrl) == 0 {
			schema_ := &schema.SchemaStruct{}
			schema_.DCDB = c.DCDB
			schema_.DbType = dbType
			schema_.PrefixUserId = 0
			schema_.GetSchema()

			err = c.DCDB.ExecSql(`INSERT INTO admin (user_id) VALUES (1)`)
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
				panic(err)
				os.Exit(1)
			}
		}

		//if len(userId)>0 {
		err = c.DCDB.ExecSql("INSERT INTO my_table (user_id, key_password) VALUES (?, ?)", userId, keyPassword)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			panic(err)
			os.Exit(1)
		}
		//}
		log.Debug("setupPassword: (%s) / (%s)", setupPassword, utils.DSha256(setupPassword))
		if len(setupPassword) > 0 {
			setupPassword = string(utils.DSha256(setupPassword))
		}
		err = c.DCDB.ExecSql("INSERT INTO config (sqlite_db_url, first_load_blockchain, first_load_blockchain_url, setup_password, auto_reload, chat_enabled) VALUES (?, ?, ?, ?, ?, ?)", sqliteDbUrl, firstLoad, url, setupPassword, 259200, 1)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			panic(err)
			os.Exit(1)
		}

		count, err := c.Single(`SELECT count(*) FROM payment_systems`).Int64()
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			panic(err)
			os.Exit(1)
		}
		if count == 0 {
			err = c.DCDB.ExecSql("INSERT INTO payment_systems (name)VALUES ('Adyen'),('Alipay'),('Amazon Payments'),('AsiaPay'),('Atos'),('Authorize.Net'),('BIPS'),('BPAY'),('Braintree'),('CentUp'),('Chargify'),('Citibank'),('ClickandBuy'),('Creditcall'),('CyberSource'),('DataCash'),('DigiCash'),('Digital River'),('Dwolla'),('ecoPayz'),('Edy'),('Elavon'),('Euronet Worldwide'),('eWAY'),('Flooz'),('Fortumo'),('Google'),('GoCardless'),('Heartland Payment Systems'),('HSBC'),('iKobo'),('iZettle'),('IP Payments'),('Klarna'),('Live Gamer'),('Mobilpenge'),('ModusLink'),('MPP Global Solutions'),('Neteller'),('Nochex'),('Ogone'),('Paymate'),('PayPal'),('Payoneer'),('PayPoint'),('Paysafecard'),('PayXpert'),('Payza'),('Peppercoin'),('Playspan'),('Popmoney'),('Realex Payments'),('Recurly'),('RBK Money'),('Sage Group'),('Serve'),('Skrill (Moneybookers)'),('Stripe'),('Square, Inc.'),('TFI Markets'),('TIMWE'),('Use My Services (UMS)'),('Ukash'),('V.me by Visa'),('VeriFone'),('Vindicia'),('WebMoney'),('WePay'),('Wirecard'),('Western Union'),('WorldPay'),('Yandex money'),('Qiwi'),('OK Pay'),('Bitcoin'),('Perfect Money')")
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
				panic(err)
				os.Exit(1)
			}
		}
		count, err = c.Single(`SELECT count(*) FROM my_notifications`).Int64()
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			panic(err)
			os.Exit(1)
		}
		if count == 0 {
			err = c.DCDB.ExecSql(`INSERT INTO my_notifications (name, email, sms, mobile) VALUES ('admin_messages',1,1,1),('change_in_status',1,0,0),('dc_came_from',1,0,1),('dc_sent',1,0,0),('incoming_cash_requests',1,1,1),('new_version',1,1,1),('node_time',0,0,0),('system_error',1,1,0),('update_email',1,0,0),('update_primary_key',1,0,0),('update_sms_request',1,0,0),('voting_results',1,0,0),('voting_time',1,0,0)`)
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
				panic(err)
				os.Exit(1)
			}
		}

		err = c.DCDB.ExecSql(`INSERT INTO cf_lang (id, name) VALUES
		(1, 'English (US)'),
		(2, 'Afrikaans'),
		(3, 'Kiswahili'),
		(4, 'Türkçe'),
		(5, '‏עברית‏'),
		(6, '‏العربية‏'),
		(7, 'Español'),
		(8, 'Français (Canada)'),
		(9, 'Guarani'),
		(10, 'Português (Brasil)'),
		(11, 'Azərbaycan dili'),
		(12, 'Bahasa Indonesia'),
		(13, 'Bahasa Melayu'),
		(14, 'Basa Jawa'),
		(15, 'Bisaya'),
		(16, 'Filipino'),
		(17, 'Tiếng Việt'),
		(18, 'Հայերեն'),
		(19, '‏اردو‏'),
		(20, 'हिन्दी'),
		(21, 'বাংলা'),
		(22, 'ਪੰਜਾਬੀ'),
		(23, 'தமிழ்'),
		(24, 'తెలుగు'),
		(25, 'ಕನ್ನಡ'),
		(26, 'മലയാളം'),
		(27, 'සිංහල'),
		(28, 'ภาษาไทย'),
		(29, '한국어'),
		(30, '中文(台灣)'),
		(31, '中文(简体)'),
		(32, '中文(香港)'),
		(33, '日本語'),
		(35, 'Čeština'),
		(36, 'Magyar'),
		(37, 'Polski'),
		(38, 'Română'),
		(39, 'Slovenčina'),
		(40, 'Slovenščina'),
		(41, 'Български'),
		(42, 'Русский'),
		(43, 'Українська'),
		(45, 'Bosanski'),
		(46, 'Català'),
		(47, 'Cymraeg'),
		(48, 'Dansk'),
		(49, 'Deutsch'),
		(50, 'Eesti'),
		(51, 'English (UK)'),
		(52, 'Español (España)'),
		(53, 'Euskara'),
		(54, 'Français (France)'),
		(55, 'Galego'),
		(56, 'Hrvatski'),
		(57, 'Italiano'),
		(58, 'Latviešu'),
		(59, 'Lietuvių'),
		(60, 'Nederlands'),
		(61, 'Norsk (bokmål)'),
		(62, 'Português (Portugal)'),
		(63, 'Shqip'),
		(64, 'Suomi'),
		(65, 'Svenska'),
		(66, 'Ελληνικά'),
		(67, 'Македонски'),
		(68, 'Српски');`)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			panic(err)
			os.Exit(1)
		}

		err = c.DCDB.ExecSql(`INSERT INTO install (progress) VALUES ('complete')`)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			panic(err)
			os.Exit(1)
		}

	}()

	utils.Sleep(3) // даем время обновиться config.ini, чтобы в content выдался не installStep0, а updatingBlockchain
	TemplateStr, err := makeTemplate("install_step_1", "installStep1", &installStep1Struct{
		Lang: c.Lang})
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	return TemplateStr, nil
}
Example #16
0
func ClearDb(ChAnswer chan string, goroutineName string) error {

	// остановим демонов, иначе будет паника, когда таблы обнулятся
	fmt.Println("ClearDb() Stop_daemons from DB!")
	for _, ch := range utils.DaemonsChans {
		fmt.Println("ch.ChBreaker<-true")
		ch.ChBreaker <- true
	}
	if len(goroutineName) > 0 {
		ChAnswer <- goroutineName
	}
	for _, ch := range utils.DaemonsChans {
		fmt.Println(<-ch.ChAnswer)
	}

	fmt.Println("ClearDb() Stop_daemons from DB OK")

	// на всякий случай пометим, что работаем
	err = utils.DB.ExecSql("UPDATE main_lock SET script_name = 'cleaning_db'")
	if err != nil {
		return utils.ErrInfo(err)
	}
	err = utils.DB.ExecSql("UPDATE config SET pool_tech_works = 1")
	if err != nil {
		return utils.ErrInfo(err)
	}
	allTables, err := utils.DB.GetAllTables()
	if err != nil {
		return utils.ErrInfo(err)
	}
	for _, table := range allTables {
		log.Debug("table: %s", table)
		if ok, _ := regexp.MatchString(`^[0-9_]*my_|^e_|install|^config|daemons|payment_systems|community|cf_lang|main_lock`, table); !ok {
			log.Debug("DELETE FROM %s", table)
			err = utils.DB.ExecSql("DELETE FROM " + table)
			if err != nil {
				return utils.ErrInfo(err)
			}
			if table == "cf_currency" {
				if utils.DB.ConfigIni["db_type"] == "sqlite" {
					err = utils.DB.SetAI("cf_currency", 999)
				} else {
					err = utils.DB.SetAI("cf_currency", 1000)
				}
				if err != nil {
					return utils.ErrInfo(err)
				}
			} else if table == "admin" {
				err = utils.DB.ExecSql("INSERT INTO admin (user_id) VALUES (1)")
				if err != nil {
					return utils.ErrInfo(err)
				}
			} else {
				log.Debug("SET AI %s", table)
				if utils.DB.ConfigIni["db_type"] == "sqlite" {
					err = utils.DB.SetAI(table, 0)
				} else {
					err = utils.DB.SetAI(table, 1)
				}
				// только логируем, т.к. тут ошибка - это норм
				if err != nil {
					log.Error("%v", err)
				}
			}
		}
	}

	err = utils.DB.ExecSql("DELETE FROM main_lock")
	if err != nil {
		return utils.ErrInfo(err)
	}

	// запустим демонов
	StartDaemons()
	stopdaemons.Signals()
	utils.Sleep(1)
	// мониторим сигнал из БД о том, что демонам надо завершаться
	go stopdaemons.WaitStopTime()
	return nil
}