Beispiel #1
0
func check(host string, userId int64) *answerType {

	/*tcpAddr, err := net.ResolveTCPAddr("tcp", host)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return &answerType{userId: userId, answer: 0}
	}
	conn, err := net.DialTCP("tcp", nil, tcpAddr)*/
	conn, err := net.DialTimeout("tcp", host, 5*time.Second)

	if err != nil {
		log.Debug("%v", utils.ErrInfo(err))
		return &answerType{userId: userId, answer: 0}
	}
	defer conn.Close()

	conn.SetReadDeadline(time.Now().Add(consts.READ_TIMEOUT * time.Second))
	conn.SetWriteDeadline(time.Now().Add(consts.WRITE_TIMEOUT * time.Second))

	// вначале шлем тип данных, чтобы принимающая сторона могла понять, как именно надо обрабатывать присланные данные
	_, err = conn.Write(utils.DecToBin(5, 1))
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return &answerType{userId: userId, answer: 0}
	}

	// в 5-и байтах пишем userID, чтобы проверить, верный ли у него нодовский ключ, т.к. иначе ему нельзя слать зашифрованные данные
	_, err = conn.Write(utils.DecToBin(userId, 5))
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return &answerType{userId: userId, answer: 0}
	}

	// ответ всегда 1 байт. 0 или 1
	answer := make([]byte, 1)

	_, err = conn.Read(answer)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return &answerType{userId: userId, answer: 0}
	}

	// создадим канал для чата
	if utils.BinToDec(answer) == 1 {

	}
	log.Debug("host: %v / answer: %v / userId: %v", host, answer, userId)
	return &answerType{userId: userId, answer: utils.BinToDec(answer)}
}
Beispiel #2
0
func (t *TcpServer) Type7() {
	/* Выдаем тело указанного блока
	 * запрос шлет демон blocksCollection и queue_parser_blocks через p.GetBlocks()
	 */
	buf := make([]byte, 4)
	_, err := t.Conn.Read(buf)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
	blockId := utils.BinToDec(buf)
	block, err := t.Single("SELECT data FROM block_chain WHERE id  =  ?", blockId).Bytes()
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}

	log.Debug("blockId %x", blockId)
	log.Debug("block %x", block)
	err = utils.WriteSizeAndData(block, t.Conn)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
}
Beispiel #3
0
func (t *TcpServer) Type9() {
	/* Делаем запрос на указанную ноду, чтобы получить оттуда номер макс. блока
	 * запрос шлет демон blocksCollection
	 */
	// размер данных
	buf := make([]byte, 4)
	_, err := t.Conn.Read(buf)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
	size := utils.BinToDec(buf)
	if size < 10485760 {
		// сами данные
		binaryData := make([]byte, size)
		/*_, err = t.Conn.Read(binaryData)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}*/
		//binaryData, err = ioutil.ReadAll(t.Conn)
		_, err = io.ReadFull(t.Conn, binaryData)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		//blockId := utils.BinToDecBytesShift(&binaryData, 4)
		host, err := utils.ProtectedCheckRemoteAddrAndGetHost(&binaryData, t.Conn)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		// шлем данные указанному хосту
		conn2, err := utils.TcpConn(host)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		defer conn2.Close()
		// шлем тип данных
		_, err = conn2.Write(utils.DecToBin(10, 1))
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		// в ответ получаем номер блока
		blockIdBin := make([]byte, 4)
		_, err = conn2.Read(blockIdBin)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		// и возвращаем номер блока демону, который этот запрос прислал
		_, err = t.Conn.Write(blockIdBin)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
	}
}
Beispiel #4
0
func (t *TcpServer) Type3() {
	// размер данных
	buf := make([]byte, 4)
	_, err := t.Conn.Read(buf)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
	size := utils.BinToDec(buf)
	if size < 10485760 {
		// сами данные
		binaryData := make([]byte, size)
		//binaryData, err = ioutil.ReadAll(t.Conn)
		_, err = io.ReadFull(t.Conn, binaryData)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		/*
		 * Пересылаем тр-ию, полученную по локальной сети, конечному ноду, указанному в первых 100 байтах тр-ии
		 * от демона disseminator
		* */
		host, err := utils.ProtectedCheckRemoteAddrAndGetHost(&binaryData, t.Conn)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		// шлем данные указанному хосту
		conn2, err := utils.TcpConn(host)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		defer conn2.Close()
		// шлем тип данных
		_, err = conn2.Write(utils.DecToBin(2, 1))
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		err = utils.WriteSizeAndDataTCPConn(binaryData, conn2)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
	}
}
Beispiel #5
0
func (t *TcpServer) Type4() {
	// данные присылает демон confirmations
	buf := make([]byte, 4)
	_, err := t.Conn.Read(buf)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
	blockId := utils.BinToDec(buf)
	// используется для учета кол-ва подвержденных блоков, т.е. тех, которые есть у большинства нодов
	hash, err := t.Single("SELECT hash FROM block_chain WHERE id =  ?", blockId).String()
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		t.Conn.Write(utils.DecToBin(0, 1))
		return
	}
	_, err = t.Conn.Write([]byte(hash))
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
}
/**
 * Демон, который мониторит таблу testblock и если видит status=active,
 * то шлет блок строго тем, кто находятся на одном с нами уровне. Если пошлет
 * тем, кто не на одном уровне, то блок просто проигнорируется
 *
 */
func TestblockDisseminator(chBreaker chan bool, chAnswer chan string) {
	defer func() {
		if r := recover(); r != nil {
			log.Error("daemon Recovered", r)
			panic(r)
		}
	}()

	const GoroutineName = "TestblockDisseminator"
	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
	}
	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
		}

		nodeConfig, err := d.GetNodeConfig()
		if len(nodeConfig["local_gate_ip"]) != 0 {
			if d.dPrintSleep("local_gate_ip", d.sleepTime) {
				break BEGIN
			}
			continue
		}

		_, _, _, _, level, levelsRange, err := d.TestBlock()
		if err != nil {
			if d.dPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue
		}
		log.Debug("level: %v", level)
		log.Debug("levelsRange: %v", levelsRange)
		// получим id майнеров, которые на нашем уровне
		nodesIds := utils.GetOurLevelNodes(level, levelsRange)
		if len(nodesIds) == 0 {
			log.Debug("len(nodesIds) == 0")
			if d.dSleep(d.sleepTime) {
				break BEGIN
			}
			continue
		}
		log.Debug("nodesIds: %v", nodesIds)

		// получим хосты майнеров, которые на нашем уровне
		hosts_, err := d.GetList("SELECT tcp_host FROM miners_data WHERE miner_id IN (" + strings.Join(utils.SliceInt64ToString(nodesIds), `,`) + ")").String()
		if err != nil {
			if d.dPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue
		}

		hosts := []string{}
		for _, host := range hosts_ {
			if !stringInSlice(host, hosts) {
				hosts = append(hosts, host)
			}
		}

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

		// шлем block_id, user_id, mrkl_root, signature
		data, err := d.OneRow("SELECT block_id, time, user_id, mrkl_root, signature FROM testblock WHERE status  =  'active' AND sent=0").String()
		if err != nil {
			if d.dPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue
		}
		if len(data) > 0 {

			err = d.ExecSql("UPDATE testblock SET sent=1")
			if err != nil {
				if d.dPrintSleep(err, d.sleepTime) {
					break BEGIN
				}
				continue
			}

			dataToBeSent := utils.DecToBin(utils.StrToInt64(data["block_id"]), 4)
			dataToBeSent = append(dataToBeSent, utils.DecToBin(data["time"], 4)...)
			dataToBeSent = append(dataToBeSent, utils.DecToBin(data["user_id"], 4)...)
			dataToBeSent = append(dataToBeSent, []byte(data["mrkl_root"])...)
			dataToBeSent = append(dataToBeSent, utils.EncodeLengthPlusData(data["signature"])...)

			for _, host := range hosts {
				go func(host string) {
					log.Debug("host: %v", host)
					conn, err := utils.TcpConn(host)
					if err != nil {
						log.Error("%v", utils.ErrInfo(err))
						return
					}
					defer conn.Close()

					// вначале шлем тип данных
					_, err = conn.Write(utils.DecToBin(6, 1))
					if err != nil {
						log.Error("%v", utils.ErrInfo(err))
						return
					}

					// в 4-х байтах пишем размер данных, которые пошлем далее
					_, err = conn.Write(utils.DecToBin(len(dataToBeSent), 4))
					if err != nil {
						log.Error("%v", utils.ErrInfo(err))
						return
					}
					// далее шлем сами данные
					log.Debug("dataToBeSent: %x", dataToBeSent)
					_, err = conn.Write(dataToBeSent)
					if err != nil {
						log.Error("%v", utils.ErrInfo(err))
						return
					}

					/*
					 * Получаем тр-ии, которые есть у юзера, в ответ выдаем те, что недостают и
					 * их порядок следования, чтобы получить валидный блок
					 */
					buf := make([]byte, 4)
					_, err = conn.Read(buf)
					if err != nil {
						log.Error("%v", utils.ErrInfo(err))
						return
					}
					dataSize := utils.BinToDec(buf)
					// и если данных менее 10мб, то получаем их
					if dataSize < 10485760 {

						data, err := d.OneRow("SELECT * FROM testblock").String()
						if err != nil {
							log.Error("%v", utils.ErrInfo(err))
							return
						}

						responseBinaryData := utils.DecToBin(utils.StrToInt64(data["block_id"]), 4)
						responseBinaryData = append(responseBinaryData, utils.DecToBin(utils.StrToInt64(data["time"]), 4)...)
						responseBinaryData = append(responseBinaryData, utils.DecToBin(utils.StrToInt64(data["user_id"]), 5)...)
						responseBinaryData = append(responseBinaryData, utils.EncodeLengthPlusData(data["signature"])...)

						addSql := ""
						if dataSize > 0 {
							binaryData := make([]byte, dataSize)
							_, err := conn.Read(binaryData)
							if err != nil {
								log.Error("%v", utils.ErrInfo(err))
								return
							}

							// разбираем присланные данные
							// получим хэши тр-ий, которые надо исключить
							for {
								if len(binaryData) < 16 {
									break
								}
								txHex := utils.BinToHex(utils.BytesShift(&binaryData, 16))
								// проверим
								addSql += string(txHex) + ","
								if len(binaryData) == 0 {
									break
								}
							}
							addSql = addSql[:len(addSql)-1]
							addSql = "WHERE id NOT IN (" + addSql + ")"
						}
						// сами тр-ии
						var transactions []byte
						transactions_testblock, err := d.GetList(`SELECT data FROM transactions_testblock ` + addSql).String()
						if err != nil {
							log.Error("%v", utils.ErrInfo(err))
							return
						}
						for _, txData := range transactions_testblock {
							transactions = append(transactions, utils.EncodeLengthPlusData(txData)...)
						}

						responseBinaryData = append(responseBinaryData, utils.EncodeLengthPlusData(transactions)...)

						// порядок тр-ий
						transactions_testblock, err = d.GetList(`SELECT hash FROM transactions_testblock ORDER BY id ASC`).String()
						if err != nil {
							log.Error("%v", utils.ErrInfo(err))
							return
						}
						for _, txHash := range transactions_testblock {
							responseBinaryData = append(responseBinaryData, []byte(txHash)...)
						}

						// в 4-х байтах пишем размер данных, которые пошлем далее
						_, err = conn.Write(utils.DecToBin(len(responseBinaryData), 4))
						if err != nil {
							log.Error("%v", utils.ErrInfo(err))
							return
						}

						// далее шлем сами данные
						_, err = conn.Write(responseBinaryData)
						if err != nil {
							log.Error("%v", utils.ErrInfo(err))
							return
						}
					}

				}(host)
			}
		}

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

}
Beispiel #7
0
func (t *TcpServer) Type8() {
	/* делаем запрос на указанную ноду, чтобы получить оттуда тело блока
	 * запрос шлет демон blocksCollection и queueParserBlocks через p.GetBlocks()
	 */
	// размер данных
	buf := make([]byte, 4)
	_, err := t.Conn.Read(buf)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
	size := utils.BinToDec(buf)
	if size < 10485760 {
		// сами данные
		binaryData := make([]byte, size)
		//binaryData, err = ioutil.ReadAll(t.Conn)
		_, err = io.ReadFull(t.Conn, binaryData)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		blockId := utils.BinToDecBytesShift(&binaryData, 4)
		host, err := utils.ProtectedCheckRemoteAddrAndGetHost(&binaryData, t.Conn)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		// шлем данные указанному хосту
		conn2, err := utils.TcpConn(host)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		defer conn2.Close()
		// шлем тип данных
		_, err = conn2.Write(utils.DecToBin(7, 1))
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		// шлем ID блока
		_, err = conn2.Write(utils.DecToBin(blockId, 4))
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		// в ответ получаем размер данных, которые нам хочет передать сервер
		buf := make([]byte, 4)
		_, err = conn2.Read(buf)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		dataSize := utils.BinToDec(buf)
		// и если данных менее 10мб, то получаем их
		if dataSize < 10485760 {
			blockBinary := make([]byte, dataSize)
			/*_, err := conn2.Read(blockBinary)
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
				return
			}*/
			//blockBinary, err = ioutil.ReadAll(conn2)
			_, err = io.ReadFull(conn2, binaryData)
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
				return
			}
			// шлем тому, кто запросил блок из демона
			_, err = t.Conn.Write(blockBinary)
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
				return
			}
		}
		return
	}
}
Beispiel #8
0
func (t *TcpServer) Type11() {

	/* Получаем данные от send_to_pool */
	log.Debug("Type11")
	// размер данных
	buf := make([]byte, 4)
	_, err := t.Conn.Read(buf)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
	size := utils.BinToDec(buf)
	log.Debug("size: %d", size)
	if size < 32<<20 {
		// сами данные
		log.Debug("read data")
		binaryData := make([]byte, size)
		//binaryData, err = ioutil.ReadAll(t.Conn)
		_, err = io.ReadFull(t.Conn, binaryData)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		//log.Debug("binaryData %x", binaryData)
		userId := utils.BinToDec(utils.BytesShift(&binaryData, 5))
		log.Debug("userId %d", userId)
		// проверим, есть ли такой юзер на пуле
		inPool, err := t.Single(`SELECT user_id FROM community WHERE user_id=?`, userId).Int64()
		if inPool <= 0 {
			log.Error("%v", utils.ErrInfo("inPool<=0"))
			_, err = t.Conn.Write(utils.DecToBin(0, 1))
			return
		}
		log.Debug("inPool %d", inPool)
		filesSign := utils.BytesShift(&binaryData, utils.DecodeLength(&binaryData))
		log.Debug("filesSign %x", filesSign)
		forSign := ""
		var files []string
		for i := 0; i < 3; i++ {
			size := utils.DecodeLength(&binaryData)
			log.Debug("size %d", size)
			data := utils.BytesShift(&binaryData, size)
			//log.Debug("data %x", data)
			fileType := utils.BinToDec(utils.BytesShift(&data, 1))
			log.Debug("fileType %d", fileType)
			var name string
			switch fileType {
			case 0:
				name = utils.Int64ToStr(userId) + "_user_face.jpg"
			case 1:
				name = utils.Int64ToStr(userId) + "_user_profile.jpg"
			case 2:
				name = utils.Int64ToStr(userId) + "_user_video.mp4"
				/*case 3:
					name = utils.Int64ToStr(userId)+"_user_video.webm"
				case 4:
					name = utils.Int64ToStr(userId)+"_user_video.ogv"*/
			}
			forSign = forSign + string(utils.DSha256((data))) + ","
			log.Debug("forSign %s", forSign)
			err = ioutil.WriteFile(os.TempDir()+"/"+name, data, 0644)
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
				return
			}
			files = append(files, name)
			log.Debug("files %d", files)
			if len(binaryData) == 0 {
				break
			}
		}

		if len(forSign) == 0 {
			log.Error("%v", utils.ErrInfo("len(forSign) == 0"))
			_, err = t.Conn.Write(utils.DecToBin(0, 1))
			return
		}
		if len(files) == 3 {
			forSign = forSign[:len(forSign)-1]
		}
		// проверим подпись
		publicKey, err := t.GetUserPublicKey(userId)
		resultCheckSign, err := utils.CheckSign([][]byte{[]byte(publicKey)}, forSign, utils.HexToBin(filesSign), true)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			_, err = t.Conn.Write(utils.DecToBin(0, 1))
			return
		}
		if resultCheckSign {
			for i := 0; i < len(files); i++ {
				utils.CopyFileContents(os.TempDir()+"/"+files[i], *utils.Dir+"/public/"+files[i])
			}
		} else {
			for i := 0; i < len(files); i++ {
				os.Remove(os.TempDir() + "/" + files[i])
			}
		}

		// и возвращаем статус
		_, err = t.Conn.Write(utils.DecToBin(1, 1))
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
	} else {
		log.Error("%v", utils.ErrInfo("size>32mb"))
	}
}
Beispiel #9
0
func (d *daemon) DisseminatorType1(host string, userId int64, node_public_key string, toBeSent []byte, dataType int64) {

	log.Debug("host %v / userId %v", host, userId)

	// шлем данные указанному хосту
	conn, err := utils.TcpConn(host)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
	defer conn.Close()

	randTestblockHash, err := d.Single("SELECT head_hash FROM queue_testblock").String()
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
	// получаем IV + ключ + зашифрованный текст
	dataToBeSent, key, iv, err := utils.EncryptData(toBeSent, []byte(node_public_key), randTestblockHash)
	log.Debug("key: %s", key)
	log.Debug("iv: %s", iv)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}

	// вначале шлем тип данных, чтобы принимающая сторона могла понять, как именно надо обрабатывать присланные данные
	n, err := conn.Write(utils.DecToBin(dataType, 1))
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
	log.Debug("n: %x", n)

	// т.к. на приеме может быть пул, то нужно дописать в начало user_id, чьим нодовским ключем шифруем
	dataToBeSent = append(utils.DecToBin(userId, 5), dataToBeSent...)
	log.Debug("dataToBeSent: %x", dataToBeSent)

	// в 4-х байтах пишем размер данных, которые пошлем далее
	size := utils.DecToBin(len(dataToBeSent), 4)
	n, err = conn.Write(size)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
	log.Debug("n: %x", n)
	n, err = conn.Write(dataToBeSent)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
	log.Debug("n: %d / size: %v / len: %d", n, utils.BinToDec(size), len(dataToBeSent))

	// в ответ получаем размер данных, которые нам хочет передать сервер
	buf := make([]byte, 4)
	n, err = conn.Read(buf)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
	log.Debug("n: %x", n)
	dataSize := utils.BinToDec(buf)
	log.Debug("dataSize %d", dataSize)
	// и если данных менее 1мб, то получаем их
	if dataSize < 1048576 {
		encBinaryTxHashes := make([]byte, dataSize)
		_, err = io.ReadFull(conn, encBinaryTxHashes)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		// разбираем полученные данные
		binaryTxHashes, err := utils.DecryptCFB(iv, encBinaryTxHashes, key)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		log.Debug("binaryTxHashes %x", binaryTxHashes)
		var binaryTx []byte
		for {
			// Разбираем список транзакций
			txHash := make([]byte, 16)
			if len(binaryTxHashes) >= 16 {
				txHash = utils.BytesShift(&binaryTxHashes, 16)
			}
			txHash = utils.BinToHex(txHash)
			log.Debug("txHash %s", txHash)
			utils.WriteSelectiveLog("SELECT data FROM transactions WHERE hex(hash) = " + string(txHash))
			tx, err := d.Single("SELECT data FROM transactions WHERE hex(hash) = ?", txHash).Bytes()
			log.Debug("tx %x", tx)
			if err != nil {
				utils.WriteSelectiveLog(err)
				log.Error("%v", utils.ErrInfo(err))
				return
			}
			utils.WriteSelectiveLog("tx: " + string(utils.BinToHex(tx)))
			if len(tx) > 0 {
				binaryTx = append(binaryTx, utils.EncodeLengthPlusData(tx)...)
			}
			if len(binaryTxHashes) == 0 {
				break
			}
		}

		log.Debug("binaryTx %x", binaryTx)
		// шифруем тр-ии. Вначале encData добавляется IV
		encData, _, err := utils.EncryptCFB(binaryTx, key, iv)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		log.Debug("encData %x", encData)

		// шлем серверу
		// в первых 4-х байтах пишем размер данных, которые пошлем далее
		size := utils.DecToBin(len(encData), 4)
		_, err = conn.Write(size)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		// далее шлем сами данные
		_, err = conn.Write(encData)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
	}
}
Beispiel #10
0
func (t *TcpServer) Type2() {
	// размер данных
	buf := make([]byte, 4)
	_, err := t.Conn.Read(buf)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
	size := utils.BinToDec(buf)
	log.Debug("size: %d", size)
	if size < 10485760 {
		// сами данные
		binaryData := make([]byte, size)
		//binaryData, err = ioutil.ReadAll(t.Conn)
		_, err = io.ReadFull(t.Conn, binaryData)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		/*
		 * Прием тр-ий от простых юзеров, а не нодов. Вызывается демоном disseminator
		 * */
		_, _, decryptedBinData, err := t.DecryptData(&binaryData)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		log.Debug("decryptedBinData: %x", decryptedBinData)
		// проверим размер
		if int64(len(binaryData)) > t.variables.Int64["max_tx_size"] {
			log.Debug("%v", utils.ErrInfo("len(txBinData) > max_tx_size"))
			return
		}
		if len(binaryData) < 5 {
			log.Debug("%v", utils.ErrInfo("len(binaryData) < 5"))
			return
		}
		decryptedBinDataFull := decryptedBinData
		txType := utils.BytesShift(&decryptedBinData, 1) // type
		txTime := utils.BytesShift(&decryptedBinData, 4) // time
		log.Debug("txType: %d", utils.BinToDec(txType))
		log.Debug("txTime: %d", utils.BinToDec(txTime))
		size := utils.DecodeLength(&decryptedBinData)
		log.Debug("size: %d", size)
		if int64(len(decryptedBinData)) < size {
			log.Debug("%v", utils.ErrInfo("len(binaryData) < size"))
			return
		}
		userId := utils.BytesToInt64(utils.BytesShift(&decryptedBinData, size))
		log.Debug("userId: %d", userId)
		highRate := 0
		if userId == 1 {
			highRate = 1
		}
		// заливаем тр-ию в БД
		err = t.ExecSql(`DELETE FROM queue_tx WHERE hex(hash) = ?`, utils.Md5(decryptedBinDataFull))
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		log.Debug("INSERT INTO queue_tx (hash, high_rate, data) (%s, %d, %s)", utils.Md5(decryptedBinDataFull), highRate, utils.BinToHex(decryptedBinDataFull))
		err = t.ExecSql(`INSERT INTO queue_tx (hash, high_rate, data) VALUES ([hex], ?, [hex])`, utils.Md5(decryptedBinDataFull), highRate, utils.BinToHex(decryptedBinDataFull))
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
	}
}
Beispiel #11
0
func (t *TcpServer) Type6() {
	/**
	- проверяем, находится ли отправитель на одном с нами уровне
	- получаем  block_id, user_id, mrkl_root, signature
	- если хэш блока меньше того, что есть у нас в табле testblock, то смотртим, есть ли такой же хэш тр-ий,
	- если отличается, то загружаем блок от отправителя
	- если не отличается, то просто обновляем хэш блока у себя
	данные присылает демон testblockDisseminator
	*/
	currentBlockId, err := t.GetBlockId()
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
	if currentBlockId == 0 {
		log.Debug("%v", utils.ErrInfo("currentBlockId == 0"))
		return
	}
	buf := make([]byte, 4)
	_, err = t.Conn.Read(buf)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
	size := utils.BinToDec(buf)
	log.Debug("size: %v", size)
	if size < 10485760 {
		binaryData := make([]byte, size)
		//binaryData, err = ioutil.ReadAll(t.Conn)
		_, err = io.ReadFull(t.Conn, binaryData)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		log.Debug("binaryData: %x", binaryData)
		newTestblockBlockId := utils.BinToDecBytesShift(&binaryData, 4)
		newTestblockTime := utils.BinToDecBytesShift(&binaryData, 4)
		newTestblockUserId := utils.BinToDecBytesShift(&binaryData, 4)
		newTestblockMrklRoot := utils.BinToHex(utils.BytesShift(&binaryData, 32))
		newTestblockSignatureHex := utils.BinToHex(utils.BytesShift(&binaryData, utils.DecodeLength(&binaryData)))
		log.Debug("newTestblockBlockId: %v", newTestblockBlockId)
		log.Debug("newTestblockTime: %v", newTestblockTime)
		log.Debug("newTestblockUserId: %v", newTestblockUserId)
		log.Debug("newTestblockMrklRoot: %s", newTestblockMrklRoot)
		log.Debug("newTestblockSignatureHex: %s", newTestblockSignatureHex)
		if !utils.CheckInputData(newTestblockBlockId, "int") {
			log.Debug("%v", utils.ErrInfo("incorrect newTestblockBlockId"))
			return
		}
		if !utils.CheckInputData(newTestblockTime, "int") {
			log.Debug("%v", utils.ErrInfo("incorrect newTestblockTime"))
			return
		}
		if !utils.CheckInputData(newTestblockUserId, "int") {
			log.Debug("%v", utils.ErrInfo("incorrect newTestblockUserId"))
			return
		}
		if !utils.CheckInputData(newTestblockMrklRoot, "sha256") {
			log.Debug("%v", utils.ErrInfo("incorrect newTestblockMrklRoot"))
			return
		}
		/*
		 * Проблема одновременных попыток локнуть. Надо попробовать без локов
		 * */
		//t.DbLockGate("6")
		exists, err := t.Single(`
				SELECT block_id
				FROM testblock
				WHERE status = 'active'
				`).Int64()
		if err != nil {
			t.PrintSleep(utils.ErrInfo(err), 0)
			return
		}
		if exists == 0 {
			t.PrintSleep(utils.ErrInfo("null testblock"), 0)
			return
		}
		//prevBlock, myUserId, myMinerId, currentUserId, level, levelsRange, err := t.TestBlock()
		prevBlock, _, _, _, level, levelsRange, err := t.TestBlock()
		if err != nil {
			t.PrintSleep(utils.ErrInfo(err), 0)
			return
		}
		nodesIds := utils.GetOurLevelNodes(level, levelsRange)
		log.Debug("nodesIds: %v ", nodesIds)
		log.Debug("prevBlock: %v ", prevBlock)
		log.Debug("level: %v ", level)
		log.Debug("levelsRange: %v ", levelsRange)
		log.Debug("newTestblockBlockId: %v ", newTestblockBlockId)
		// проверим, верный ли ID блока
		if newTestblockBlockId != prevBlock.BlockId+1 {
			t.PrintSleep(utils.ErrInfo(fmt.Sprintf("newTestblockBlockId != prevBlock.BlockId+1 %d!=%d+1", newTestblockBlockId, prevBlock.BlockId)), 1)
			return
		}
		// проверим, есть ли такой майнер
		minerId, err := t.Single("SELECT miner_id FROM miners_data WHERE user_id  =  ?", newTestblockUserId).Int64()
		if err != nil {
			t.PrintSleep(utils.ErrInfo(err), 0)
			return
		}
		if minerId == 0 {
			t.PrintSleep(utils.ErrInfo("minerId == 0"), 0)
			return
		}
		log.Debug("minerId: %v ", minerId)
		// проверим, точно ли отправитель с нашего уровня
		if !utils.InSliceInt64(minerId, nodesIds) {
			t.PrintSleep(utils.ErrInfo("!InSliceInt64(minerId, nodesIds)"), 0)
			return
		}
		// допустимая погрешность во времени генерации блока
		maxErrorTime := t.variables.Int64["error_time"]
		// получим значения для сна
		sleep, err := t.GetGenSleep(prevBlock, level)
		if err != nil {
			t.PrintSleep(utils.ErrInfo(err), 0)
			return
		}
		// исключим тех, кто сгенерил блок слишком рано
		if prevBlock.Time+sleep-newTestblockTime > maxErrorTime {
			t.PrintSleep(utils.ErrInfo("prevBlock.Time + sleep - newTestblockTime > maxErrorTime"), 0)
			return
		}
		// исключим тех, кто сгенерил блок с бегущими часами
		if newTestblockTime > utils.Time() {
			t.PrintSleep(utils.ErrInfo("newTestblockTime > Time()"), 0)
			return
		}
		// получим хэш заголовка
		newHeaderHash := utils.DSha256(fmt.Sprintf("%v,%v,%v", newTestblockUserId, newTestblockBlockId, prevBlock.HeadHash))
		myTestblock, err := t.OneRow(`
				SELECT block_id,
							user_id,
							hex(mrkl_root) as mrkl_root,
							hex(signature) as signature
				FROM testblock
				WHERE status = 'active'
				`).String()
		if len(myTestblock) > 0 {
			if err != nil {
				t.PrintSleep(utils.ErrInfo(err), 0)
				return
			}
			// получим хэш заголовка
			myHeaderHash := utils.DSha256(fmt.Sprintf("%v,%v,%v", myTestblock["user_id"], myTestblock["block_id"], prevBlock.HeadHash))
			// у кого меньше хэш, тот и круче
			hash1 := big.NewInt(0)
			hash1.SetString(string(newHeaderHash), 16)
			hash2 := big.NewInt(0)
			hash2.SetString(string(myHeaderHash), 16)
			log.Debug("%v", hash1.Cmp(hash2))
			//if HexToDecBig(newHeaderHash) > string(myHeaderHash) {
			if hash1.Cmp(hash2) == 1 {
				t.PrintSleep(utils.ErrInfo(fmt.Sprintf("newHeaderHash > myHeaderHash (%s > %s)", newHeaderHash, myHeaderHash)), 0)
				return
			}
			/* т.к. на данном этапе в большинстве случаев наш текущий блок будет заменен,
			 * то нужно парсить его, рассылать другим нодам и дождаться окончания проверки
			 */
			err = t.ExecSql("UPDATE testblock SET status = 'pending'")
			if err != nil {
				t.PrintSleep(utils.ErrInfo(err), 0)
				return
			}
		}
		// если отличается, то загружаем недостающии тр-ии от отправителя
		if string(newTestblockMrklRoot) != myTestblock["mrkl_root"] {
			log.Debug("download new tx")
			sendData := ""
			// получим все имеющиеся у нас тр-ии, которые еще не попали в блоки
			txArray, err := t.GetMap(`SELECT hex(hash) as hash, data FROM transactions`, "hash", "data")
			if err != nil {
				t.PrintSleep(utils.ErrInfo(err), 0)
				return
			}
			for hash, _ := range txArray {
				sendData += hash
			}
			err = utils.WriteSizeAndData([]byte(sendData), t.Conn)
			if err != nil {
				t.PrintSleep(utils.ErrInfo(err), 0)
				return
			}
			/*
				в ответ получаем:
				BLOCK_ID   				       4
				TIME       					       4
				USER_ID                         5
				SIGN                               от 128 до 512 байт. Подпись от TYPE, BLOCK_ID, PREV_BLOCK_HASH, TIME, USER_ID, LEVEL, MRKL_ROOT
				Размер всех тр-ий, размер 1 тр-ии, тело тр-ии.
				Хэши три-ий (порядок тр-ий)
			*/
			buf := make([]byte, 4)
			_, err = t.Conn.Read(buf)
			if err != nil {
				t.PrintSleep(utils.ErrInfo(err), 0)
				return
			}
			dataSize := utils.BinToDec(buf)
			log.Debug("dataSize %d", dataSize)
			// и если данных менее 10мб, то получаем их
			if dataSize < 10485760 {
				binaryData := make([]byte, dataSize)
				//binaryData, err = ioutil.ReadAll(t.Conn)
				_, err = io.ReadFull(t.Conn, binaryData)
				if err != nil {
					t.PrintSleep(utils.ErrInfo(err), 0)
					return
				}
				// Разбираем полученные бинарные данные
				newTestblockBlockId := utils.BinToDecBytesShift(&binaryData, 4)
				newTestblockTime := utils.BinToDecBytesShift(&binaryData, 4)
				newTestblockUserId := utils.BinToDecBytesShift(&binaryData, 5)
				newTestblockSignature := utils.BytesShift(&binaryData, utils.DecodeLength(&binaryData))
				log.Debug("newTestblockBlockId %v", newTestblockBlockId)
				log.Debug("newTestblockTime %v", newTestblockTime)
				log.Debug("newTestblockUserId %v", newTestblockUserId)
				log.Debug("newTestblockSignature %x", newTestblockSignature)
				// недостающие тр-ии
				length := utils.DecodeLength(&binaryData) // размер всех тр-ий
				txBinary := utils.BytesShift(&binaryData, length)
				for {
					// берем по одной тр-ии
					length := utils.DecodeLength(&txBinary) // размер всех тр-ий
					if length == 0 {
						break
					}
					log.Debug("length %d", length)
					tx := utils.BytesShift(&txBinary, length)
					log.Debug("tx %x", tx)
					txArray[string(utils.Md5(tx))] = string(tx)
				}
				// порядок тр-ий
				var orderHashArray []string
				for {
					orderHashArray = append(orderHashArray, string(utils.BinToHex(utils.BytesShift(&binaryData, 16))))
					if len(binaryData) == 0 {
						break
					}
				}
				// сортируем и наши и полученные транзакции
				var transactions []byte
				for _, txMd5 := range orderHashArray {
					transactions = append(transactions, utils.EncodeLengthPlusData([]byte(txArray[txMd5]))...)
				}
				// формируем блок, который далее будем тщательно проверять
				/*
					Заголовок (от 143 до 527 байт )
					TYPE (0-блок, 1-тр-я)     1
					BLOCK_ID   				       4
					TIME       					       4
					USER_ID                         5
					LEVEL                              1
					SIGN                               от 128 до 512 байт. Подпись от TYPE, BLOCK_ID, PREV_BLOCK_HASH, TIME, USER_ID, LEVEL, MRKL_ROOT
					Далее - тело блока (Тр-ии)
				*/
				newBlockIdBinary := utils.DecToBin(newTestblockBlockId, 4)
				timeBinary := utils.DecToBin(newTestblockTime, 4)
				userIdBinary := utils.DecToBin(newTestblockUserId, 5)
				levelBinary := utils.DecToBin(level, 1)
				newBlockHeader := utils.DecToBin(0, 1) // 0 - это блок
				newBlockHeader = append(newBlockHeader, newBlockIdBinary...)
				newBlockHeader = append(newBlockHeader, timeBinary...)
				newBlockHeader = append(newBlockHeader, userIdBinary...)
				newBlockHeader = append(newBlockHeader, levelBinary...) // $level пишем, чтобы при расчете времени ожидания в следующем блоке не пришлось узнавать, какой был max_miner_id
				newBlockHeader = append(newBlockHeader, utils.EncodeLengthPlusData(newTestblockSignature)...)
				newBlockHex := utils.BinToHex(append(newBlockHeader, transactions...))
				// и передаем блок для обратотки через демон queue_parser_testblock
				// т.к. есть запросы к log_time_, а их можно выполнять только по очереди
				err = t.ExecSql(`DELETE FROM queue_testblock WHERE hex(head_hash) = ?`, newHeaderHash)
				if err != nil {
					t.PrintSleep(utils.ErrInfo(err), 0)
					return
				}
				log.Debug("INSERT INTO queue_testblock  (head_hash, data)  VALUES (%s, %s)", newHeaderHash, newBlockHex)
				err = t.ExecSql(`INSERT INTO queue_testblock (head_hash, data) VALUES ([hex], [hex])`, newHeaderHash, newBlockHex)
				if err != nil {
					t.PrintSleep(utils.ErrInfo(err), 0)
					return
				}
			}
		} else {
			// если всё нормально, то пишем в таблу testblock новые данные
			exists, err := t.Single(`SELECT block_id FROM testblock`).Int64()
			if err != nil {
				t.PrintSleep(utils.ErrInfo(err), 0)
				return
			}
			if exists == 0 {
				err = t.ExecSql(`INSERT INTO testblock (block_id, time, level, user_id, header_hash, signature, mrkl_root) VALUES (?, ?, ?, ?, [hex], [hex], [hex])`,
					newTestblockBlockId, newTestblockTime, level, newTestblockUserId, string(newHeaderHash), newTestblockSignatureHex, string(newTestblockMrklRoot))
				if err != nil {
					t.PrintSleep(utils.ErrInfo(err), 0)
					return
				}
			} else {
				err = t.ExecSql(`
						UPDATE testblock
						SET   time = ?,
								user_id = ?,
								header_hash = [hex],
								signature = [hex]
						`, newTestblockTime, newTestblockUserId, string(newHeaderHash), string(newTestblockSignatureHex))
				if err != nil {
					t.PrintSleep(utils.ErrInfo(err), 0)
					return
				}
			}
		}
		err = t.ExecSql("UPDATE testblock SET status = 'active'")
		if err != nil {
			t.PrintSleep(utils.ErrInfo(err), 0)
			return
		}
		//t.DbUnlockGate("6")
	}
}
Beispiel #12
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)
		}
	}()
}
Beispiel #13
0
func (c *Controller) SendToPool() (string, error) {

	if c.SessRestricted != 0 {
		return "", utils.ErrInfo(errors.New("Permission denied"))
	}

	filesSign := c.r.FormValue("filesSign")

	poolUid := utils.StrToInt64(c.r.FormValue("poolUid"))
	data_, err := c.OneRow(`SELECT tcp_host, http_host FROM miners_data WHERE user_id = ?`, poolUid).String()
	tcpHost := data_["tcp_host"]
	httpHost := data_["http_host"]
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	conn, err := net.DialTimeout("tcp", tcpHost, 5*time.Second)
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	defer conn.Close()

	conn.SetReadDeadline(time.Now().Add(240 * time.Second))
	conn.SetWriteDeadline(time.Now().Add(240 * time.Second))

	var data []byte
	data = append(data, utils.DecToBin(c.SessUserId, 5)...)
	data = append(data, utils.EncodeLengthPlusData(filesSign)...)

	if _, err := os.Stat(*utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_face.jpg"); err == nil {
		file, err := ioutil.ReadFile(*utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_face.jpg")
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		data = append(data, utils.EncodeLengthPlusData(append(utils.DecToBin(0, 1), file...))...)
	}
	if _, err := os.Stat(*utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_profile.jpg"); err == nil {
		file, err := ioutil.ReadFile(*utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_profile.jpg")
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		data = append(data, utils.EncodeLengthPlusData(append(utils.DecToBin(1, 1), file...))...)
	}
	if _, err := os.Stat(*utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_video.mp4"); err == nil {
		file, err := ioutil.ReadFile(*utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_video.mp4")
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		data = append(data, utils.EncodeLengthPlusData(append(utils.DecToBin(2, 1), file...))...)
	}

	// тип данных
	_, err = conn.Write(utils.DecToBin(11, 1))
	if err != nil {
		return "", utils.ErrInfo(err)
	}

	// в 4-х байтах пишем размер данных, которые пошлем далее
	size := utils.DecToBin(len(data), 4)
	_, err = conn.Write(size)
	if err != nil {
		return "", utils.ErrInfo(err)
	}

	// далее шлем сами данные
	_, err = conn.Write([]byte(data))
	if err != nil {
		return "", utils.ErrInfo(err)
	}

	// в ответ получаем статус
	buf := make([]byte, 1)
	_, err = conn.Read(buf)
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	status := utils.BinToDec(buf)
	result := ""
	if status == 1 {
		result = utils.JsonAnswer("1", "success").String()
		c.ExecSql(`UPDATE `+c.MyPrefix+`my_table SET tcp_host = ?, http_host = ?`, tcpHost, httpHost)
	} else {
		result = utils.JsonAnswer("error", "error").String()
	}

	return result, nil
}
Beispiel #14
0
func (c *Controller) UploadVideo() (string, error) {

	if c.SessRestricted != 0 {
		return "", utils.ErrInfo(errors.New("Permission denied"))
	}

	var binaryVideo []byte

	c.r.ParseMultipartForm(32 << 20)
	file, _, err := c.r.FormFile("file")
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	videoBuffer := new(bytes.Buffer)
	_, err = io.Copy(videoBuffer, file)
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	defer file.Close()
	binaryVideo = videoBuffer.Bytes()
	fmt.Println(c.r.MultipartForm.File["file"][0].Filename)
	fmt.Println(c.r.MultipartForm.File["file"][0].Header.Get("Content-Type"))
	fmt.Println(c.r.MultipartForm.Value["type"][0])

	var contentType, videoType string
	if _, ok := c.r.MultipartForm.File["file"]; ok {
		contentType = c.r.MultipartForm.File["file"][0].Header.Get("Content-Type")
	}
	if _, ok := c.r.MultipartForm.Value["type"]; ok {
		videoType = c.r.MultipartForm.Value["type"][0]
	}
	end := "mp4"
	switch contentType {
	case "video/mp4", "video/quicktime":
		end = "mp4"
	case "video/ogg":
		end = "ogv"
	case "video/webm":
		end = "webm"
	case "video/3gpp":

		fmt.Println("3gpp")
		conn, err := net.DialTimeout("tcp", "3gp.dcoin.club:8099", 5*time.Second)
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		defer conn.Close()

		conn.SetReadDeadline(time.Now().Add(240 * time.Second))
		conn.SetWriteDeadline(time.Now().Add(240 * time.Second))

		// в 4-х байтах пишем размер данных, которые пошлем далее
		size := utils.DecToBin(len(videoBuffer.Bytes()), 4)
		_, err = conn.Write(size)
		if err != nil {
			return "", utils.ErrInfo(err)
		}

		// далее шлем сами данные
		_, err = conn.Write(videoBuffer.Bytes())
		if err != nil {
			return "", utils.ErrInfo(err)
		}

		// в ответ получаем размер данных, которые нам хочет передать сервер
		buf := make([]byte, 4)
		n, err := conn.Read(buf)
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		log.Debug("dataSize buf: %x / get: %v", buf, n)

		// и если данных менее 10мб, то получаем их
		dataSize := utils.BinToDec(buf)
		var binaryBlock []byte
		log.Debug("dataSize: %v", dataSize)
		if dataSize < 10485760 && dataSize > 0 {
			binaryBlock = make([]byte, dataSize)
			//binaryBlock, err = ioutil.ReadAll(conn)
			_, err = io.ReadFull(conn, binaryBlock)
			if err != nil {
				return "", utils.ErrInfo(err)
			}
			log.Debug("len(binaryBlock):", len(binaryBlock))
			binaryVideo = binaryBlock
		}
	}

	log.Debug(videoType, end)

	var name string
	if videoType == "user_video" {
		name = "public/" + utils.Int64ToStr(c.SessUserId) + "_user_video." + end
	} else {
		x := strings.Split(videoType, "-")
		if len(x) < 2 {
			if err != nil {
				return "", utils.ErrInfo(err)
			}
		}
		name = "public/" + utils.Int64ToStr(c.SessUserId) + "_promised_amount_" + x[1] + "." + end
	}
	log.Debug(*utils.Dir + "/" + name)
	err = ioutil.WriteFile(*utils.Dir+"/"+name, binaryVideo, 0644)
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	return utils.JsonAnswer(string(utils.DSha256(binaryVideo)), "success").String(), nil
}
Beispiel #15
0
func (t *TcpServer) Type1() {
	log.Debug("dataType: 1")
	// размер данных
	buf := make([]byte, 4)
	n, err := t.Conn.Read(buf)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
	size := utils.BinToDec(buf)
	log.Debug("size: %v / n: %v", size, n)
	if size < 10485760 {
		// сами данные
		binaryData := make([]byte, size)
		log.Debug("ReadAll 0")
		_, err = io.ReadFull(t.Conn, binaryData)
		log.Debug("ReadAll 1")
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		log.Debug("binaryData: %x", binaryData)
		/*
		 * принимаем зашифрованный список тр-ий от демона disseminator, которые есть у отправителя
		 * Блоки не качаем тут, т.к. может быть цепочка блоков, а их качать долго
		 * тр-ии качаем тут, т.к. они мелкие и точно скачаются за 60 сек
		 * */
		key, iv, decryptedBinData, err := t.DecryptData(&binaryData)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		log.Debug("key: %v / iv: %v", key, iv)
		/*
		 * структура данных:
		 * user_id - 5 байт
		 * type - 1 байт. 0 - блок, 1 - список тр-ий
		 * {если type==1}:
		 * <любое кол-во следующих наборов>
		 * high_rate - 1 байт
		 * tx_hash - 16 байт
		 * </>
		 * {если type==0}:
		 * block_id - 3 байта
		 * hash - 32 байт
		 * head_hash - 32 байт
		 * <любое кол-во следующих наборов>
		 * high_rate - 1 байт
		 * tx_hash - 16 байт
		 * </>
		 * */
		blockId, err := t.GetBlockId()
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		log.Debug("decryptedBinData: %x", decryptedBinData)
		// user_id отправителя, чтобы знать у кого брать данные, когда они будут скачиваться другим скриптом
		newDataUserId := utils.BinToDec(utils.BytesShift(&decryptedBinData, 5))
		log.Debug("newDataUserId: %d", newDataUserId)
		// данные могут быть отправлены юзером, который уже не майнер
		minerId, err := t.Single("SELECT miner_id FROM miners_data WHERE user_id  =  ? AND miner_id > 0", newDataUserId).Int64()
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		log.Debug("minerId: %v", minerId)
		if minerId == 0 {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		// если 0 - значит вначале идет инфа о блоке, если 1 - значит сразу идет набор хэшей тр-ий
		newDataType := utils.BinToDecBytesShift(&decryptedBinData, 1)
		log.Debug("newDataType: %d", newDataType)
		if newDataType == 0 {
			// ID блока, чтобы не скачать старый блок
			newDataBlockId := utils.BinToDecBytesShift(&decryptedBinData, 3)
			log.Debug("newDataBlockId: %d / blockId: %d", newDataBlockId, blockId)
			// нет смысла принимать старые блоки
			if newDataBlockId >= blockId {
				// Это хэш для соревнования, у кого меньше хэш
				newDataHash := utils.BinToHex(utils.BytesShift(&decryptedBinData, 32))
				// Для доп. соревнования, если head_hash равны (шалит кто-то из майнеров и позже будет за такое забанен)
				newDataHeadHash := utils.BinToHex(utils.BytesShift(&decryptedBinData, 32))
				err = t.ExecSql(`DELETE FROM queue_blocks WHERE hex(hash) = ?`, newDataHash)
				if err != nil {
					log.Error("%v", utils.ErrInfo(err))
					return
				}
				err = t.ExecSql(`
						INSERT INTO queue_blocks (
							hash,
							head_hash,
							user_id,
							block_id
						) VALUES (
							[hex],
							[hex],
							?,
							?
						)`, newDataHash, newDataHeadHash, newDataUserId, newDataBlockId)
				if err != nil {
					log.Error("%v", utils.ErrInfo(err))
					return
				}
			}
		}
		log.Debug("decryptedBinData: %x", decryptedBinData)
		var needTx []byte
		// Разбираем список транзакций
		if len(decryptedBinData) == 0 {
			log.Debug("%v", utils.ErrInfo("len(decryptedBinData) == 0"))
			return
		}
		for {
			// 1 - это админские тр-ии, 0 - обычные
			newDataHighRate := utils.BinToDecBytesShift(&decryptedBinData, 1)
			if len(decryptedBinData) < 16 {
				log.Debug("%v", utils.ErrInfo("len(decryptedBinData) < 16"))
				return
			}
			log.Debug("newDataHighRate: %v", newDataHighRate)
			newDataTxHash := utils.BinToHex(utils.BytesShift(&decryptedBinData, 16))
			if len(newDataTxHash) == 0 {
				log.Error("%v", utils.ErrInfo(err))
				return
			}
			log.Debug("newDataTxHash %s", newDataTxHash)
			// проверим, нет ли у нас такой тр-ии
			exists, err := t.Single("SELECT count(hash) FROM log_transactions WHERE hex(hash) = ?", newDataTxHash).Int64()
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
				return
			}
			if exists > 0 {
				log.Debug("exists")
				continue
			}
			needTx = append(needTx, utils.HexToBin(newDataTxHash)...)
			if len(decryptedBinData) == 0 {
				break
			}
		}
		if len(needTx) == 0 {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		log.Debug("needTx: %v", needTx)
		// шифруем данные. ключ $key сеансовый, iv тоже
		encData, _, err := utils.EncryptCFB(needTx, key, iv)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		// в 4-х байтах пишем размер данных, которые пошлем далее
		size := utils.DecToBin(len(encData), 4)
		_, err = t.Conn.Write(size)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		log.Debug("size: %v", len(encData))
		log.Debug("encData: %x", encData)
		// далее шлем сами данные
		_, err = t.Conn.Write(encData)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		// в ответ получаем размер данных, которые нам хочет передать сервер
		buf := make([]byte, 4)
		_, err = t.Conn.Read(buf)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		dataSize := utils.BinToDec(buf)
		log.Debug("dataSize %v", dataSize)
		// и если данных менее 10мб, то получаем их
		if dataSize < 10485760 {
			encBinaryTxs := make([]byte, dataSize)
			_, err = io.ReadFull(t.Conn, encBinaryTxs)
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
				return
			}
			// разбираем полученные данные
			log.Debug("encBinaryTxs %x", encBinaryTxs)
			// уберем IV из начала
			utils.BytesShift(&encBinaryTxs, 16)
			// декриптуем
			binaryTxs, err := utils.DecryptCFB(iv, encBinaryTxs, key)
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
				return
			}
			log.Debug("binaryTxs %x", binaryTxs)
			for {
				txSize := utils.DecodeLength(&binaryTxs)
				if int64(len(binaryTxs)) < txSize {
					log.Error("%v", utils.ErrInfo(err))
					return
				}
				txBinData := utils.BytesShift(&binaryTxs, txSize)
				if len(txBinData) == 0 {
					log.Error("%v", utils.ErrInfo(err))
					return
				}
				txHex := utils.BinToHex(txBinData)
				// проверим размер
				if int64(len(txBinData)) > t.variables.Int64["max_tx_size"] {
					log.Debug("%v", utils.ErrInfo("len(txBinData) > max_tx_size"))
					return
				}
				newDataHighRate := 0 // временно для тестов

				log.Debug("INSERT INTO queue_tx (hash, high_rate, data) %s, %d, %s", utils.Md5(txBinData), newDataHighRate, txHex)
				err = t.ExecSql(`INSERT INTO queue_tx (hash, high_rate, data) VALUES ([hex], ?, [hex])`, utils.Md5(txBinData), newDataHighRate, txHex)
				if len(txBinData) == 0 {
					log.Error("%v", utils.ErrInfo(err))
					return
				}
			}
		}
	}
}
Beispiel #16
0
func (t *TcpServer) HandleTcpRequest() {

	fmt.Println("NumCPU:", runtime.NumCPU(),
		" NumGoRoutine:", runtime.NumGoroutine(),
		" t.counter:", counter)

	var err error

	log.Debug("HandleTcpRequest from %v", t.Conn.RemoteAddr())
	defer t.deferClose()

	mutex.Lock()
	if counter > 20 {
		t.Conn.Close()
		mutex.Unlock()
		return
	} else {
		counter++
		fmt.Println("++", counter)
	}
	mutex.Unlock()

	t.variables, err = t.GetAllVariables()
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}

	// тип данных
	buf := make([]byte, 1)
	_, err = t.Conn.Read(buf)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
	dataType := utils.BinToDec(buf)
	log.Debug("dataType %v", dataType)
	switch dataType {
	case 1:
		t.Type1()
	case 2:
		t.Type2()
	case 3:
		t.Type3()
	case 4:
		t.Type4()
	case 5:
		t.Type5()
	case 6:
		t.Type6()
	case 7:
		t.Type7()
	case 8:
		t.Type8()
	case 9:
		t.Type9()
	case 10:
		t.Type10()
	case 11:
		t.Type11()
	case 12:
		t.Type12()
	}
	log.Debug("END")
}
Beispiel #17
0
func (t *TcpServer) Type12() {

	/* Получаем данные от send_promised_amount_to_pool */
	log.Debug("Type12")
	// размер данных
	buf := make([]byte, 4)
	_, err := t.Conn.Read(buf)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
	size := utils.BinToDec(buf)
	log.Debug("size: %d", size)
	if size < 32<<20 {
		// сами данные
		log.Debug("read data")
		binaryData := make([]byte, size)
		_, err = io.ReadFull(t.Conn, binaryData)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
		//log.Debug("binaryData %x", binaryData)
		userId := utils.BinToDec(utils.BytesShift(&binaryData, 5))
		currencyId := utils.BinToDec(utils.BytesShift(&binaryData, 1))
		log.Debug("userId %d", userId)
		log.Debug("currencyId %d", currencyId)
		// проверим, есть ли такой юзер на пуле
		inPool, err := t.Single(`SELECT user_id FROM community WHERE user_id=?`, userId).Int64()
		if inPool <= 0 {
			log.Error("%v", utils.ErrInfo("inPool<=0"))
			_, err = t.Conn.Write(utils.DecToBin(0, 1))
			return
		}
		log.Debug("inPool %d", inPool)
		filesSign := utils.BytesShift(&binaryData, utils.DecodeLength(&binaryData))
		log.Debug("filesSign %x", filesSign)
		size := utils.DecodeLength(&binaryData)
		log.Debug("size %d", size)
		data := utils.BytesShift(&binaryData, size)
		//log.Debug("data %x", data)
		fileType := utils.BinToDec(utils.BytesShift(&data, 1))
		log.Debug("fileType %d", fileType)
		fileName := utils.Int64ToStr(userId) + "_promised_amount_" + utils.Int64ToStr(currencyId) + ".mp4"
		forSign := string(utils.DSha256((data)))
		log.Debug("forSign %s", forSign)
		err = ioutil.WriteFile(os.TempDir()+"/"+fileName, data, 0644)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}

		if len(forSign) == 0 {
			log.Error("%v", utils.ErrInfo("len(forSign) == 0"))
			_, err = t.Conn.Write(utils.DecToBin(0, 1))
			return
		}
		// проверим подпись
		publicKey, err := t.GetUserPublicKey(userId)
		resultCheckSign, err := utils.CheckSign([][]byte{[]byte(publicKey)}, forSign, utils.HexToBin(filesSign), true)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			_, err = t.Conn.Write(utils.DecToBin(0, 1))
			return
		}
		if resultCheckSign {
			utils.CopyFileContents(os.TempDir()+"/"+fileName, *utils.Dir+"/public/"+fileName)
		} else {
			os.Remove(os.TempDir() + "/" + fileName)
		}

		// и возвращаем статус
		_, err = t.Conn.Write(utils.DecToBin(1, 1))
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
	} else {
		log.Error("%v", utils.ErrInfo("size>32mb"))
	}
}
func (c *Controller) SendPromisedAmountToPool() (string, error) {

	if c.SessRestricted != 0 {
		return "", utils.ErrInfo(errors.New("Permission denied"))
	}

	filesSign := c.r.FormValue("filesSign")
	currencyId := utils.StrToInt64(c.r.FormValue("currencyId"))
	tcpHost, err := c.Single(`SELECT tcp_host FROM miners_data WHERE user_id = ?`, c.SessUserId).String()
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	conn, err := net.DialTimeout("tcp", tcpHost, 5*time.Second)
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	defer conn.Close()

	conn.SetReadDeadline(time.Now().Add(240 * time.Second))
	conn.SetWriteDeadline(time.Now().Add(240 * time.Second))

	var data []byte
	data = append(data, utils.DecToBin(c.SessUserId, 5)...)
	data = append(data, utils.DecToBin(currencyId, 1)...)
	data = append(data, utils.EncodeLengthPlusData(filesSign)...)

	if _, err := os.Stat(*utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_promised_amount_" + utils.Int64ToStr(currencyId) + ".mp4"); err == nil {
		file, err := ioutil.ReadFile(*utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_promised_amount_" + utils.Int64ToStr(currencyId) + ".mp4")
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		data = append(data, utils.EncodeLengthPlusData(append(utils.DecToBin(2, 1), file...))...)
	}

	// тип данных
	_, err = conn.Write(utils.DecToBin(12, 1))
	if err != nil {
		return "", utils.ErrInfo(err)
	}

	// в 4-х байтах пишем размер данных, которые пошлем далее
	size := utils.DecToBin(len(data), 4)
	_, err = conn.Write(size)
	if err != nil {
		return "", utils.ErrInfo(err)
	}

	// далее шлем сами данные
	_, err = conn.Write([]byte(data))
	if err != nil {
		return "", utils.ErrInfo(err)
	}

	// в ответ получаем статус
	buf := make([]byte, 1)
	_, err = conn.Read(buf)
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	status := utils.BinToDec(buf)
	result := ""
	if status == 1 {
		result = utils.JsonAnswer("1", "success").String()
	} else {
		result = utils.JsonAnswer("error", "error").String()
	}

	return result, nil
}
Beispiel #19
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)
}
Beispiel #20
0
func (t *TcpServer) Type5() {
	// данные присылает демон connector
	buf := make([]byte, 5)
	_, err := t.Conn.Read(buf)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		return
	}
	userId := utils.BinToDec(buf)
	log.Debug("userId: %d", userId)
	// если работаем в режиме пула, то нужно проверить, верный ли у юзера нодовский ключ
	community, err := t.GetCommunityUsers()
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
		t.Conn.Write(utils.DecToBin(0, 1))
		return
	}
	if len(community) > 0 {
		allTables, err := t.GetAllTables()
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			t.Conn.Write(utils.DecToBin(0, 1))
			return
		}
		keyTable := utils.Int64ToStr(userId) + "_my_node_keys"
		if !utils.InSliceString(keyTable, allTables) {
			log.Error("incorrect user_id %d", userId)
			t.Conn.Write(utils.DecToBin(0, 1))
			return
		}
		myBlockId, err := t.GetMyBlockId()
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			t.Conn.Write(utils.DecToBin(0, 1))
			return
		}
		myNodeKey, err := t.Single(`
				SELECT public_key
				FROM `+keyTable+`
				WHERE block_id = (SELECT max(block_id) FROM  `+keyTable+`) AND
							 block_id < ?
				`, myBlockId).String()
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			t.Conn.Write(utils.DecToBin(0, 1))
			return
		}
		if len(myNodeKey) == 0 {
			log.Error("len(myNodeKey) userId %d", userId)
			t.Conn.Write(utils.DecToBin(0, 1))
			return
		}
		nodePublicKey, err := t.GetNodePublicKey(userId)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			t.Conn.Write(utils.DecToBin(0, 1))
			return
		}
		if myNodeKey != string(nodePublicKey) {
			log.Error("%v", utils.ErrInfo("myNodeKey != nodePublicKey"))
			t.Conn.Write(utils.DecToBin(0, 1))
			return
		}
		// всё норм, шлем 1
		_, err = t.Conn.Write(utils.DecToBin(1, 1))
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
	} else {
		// всё норм, шлем 1
		_, err = t.Conn.Write(utils.DecToBin(1, 1))
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			return
		}
	}
}