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)} }
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 } }
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 } } }
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 } } }
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) }
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 } }
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")) } }
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 } } }
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 } } }
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") } }
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) } }() }
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 }
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 }
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 } } } } }
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") }
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 }
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) }
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 } } }