func (p *Parser) ParseDataLite() error { p.dataPre() if p.dataType != 0 { // парсим только блоки return utils.ErrInfo(fmt.Errorf("incorrect dataType")) } var err error p.Variables, err = p.GetAllVariables() if err != nil { return utils.ErrInfo(err) } err = p.ParseBlock() if err != nil { return utils.ErrInfo(err) } if len(p.BinaryData) > 0 { i := 0 for { transactionSize := utils.DecodeLength(&p.BinaryData) if len(p.BinaryData) == 0 { return utils.ErrInfo(fmt.Errorf("empty BinaryData")) } // отчекрыжим одну транзакцию от списка транзакций transactionBinaryData := utils.BytesShift(&p.BinaryData, transactionSize) transactionBinaryDataFull := transactionBinaryData p.TxHash = utils.Md5(transactionBinaryData) p.TxSlice, err = p.ParseTransaction(&transactionBinaryData) MethodName := consts.TxTypes[utils.BytesToInt(p.TxSlice[1])] log.Debug("MethodName", MethodName+"Init") err_ := utils.CallMethod(p, MethodName+"Init") if _, ok := err_.(error); ok { log.Debug("%v", err) return utils.ErrInfo(err_.(error)) } p.TxMap["md5hash"] = utils.Md5(transactionBinaryDataFull) p.TxMapArr = append(p.TxMapArr, p.TxMap) //p.TxMapsArr = append(p.TxMapsArr, p.TxMaps) if len(p.BinaryData) == 0 { break } i++ } } return nil }
func (c *Controller) ESignLogin() (string, error) { c.w.Header().Set("Access-Control-Allow-Origin", "*") var hash []byte loginCode := utils.RandSeq(20) RemoteAddr := utils.RemoteAddrFix(c.r.RemoteAddr) re := regexp.MustCompile(`(.*?):[0-9]+$`) match := re.FindStringSubmatch(RemoteAddr) if len(match) != 0 { RemoteAddr = match[1] } log.Debug("RemoteAddr %s", RemoteAddr) hash = utils.Md5(c.r.Header.Get("User-Agent") + RemoteAddr) log.Debug("hash %s", hash) err := c.DCDB.ExecSql(`DELETE FROM e_authorization WHERE hex(hash) = ?`, hash) if err != nil { return "", err } err = c.DCDB.ExecSql(`INSERT INTO e_authorization (hash, data) VALUES ([hex], ?)`, hash, loginCode) if err != nil { return "", err } log.Debug("loginCode %v", loginCode) return "\"" + loginCode + "\"", nil }
func (c *Controller) EGateIk() (string, error) { c.r.ParseForm() fmt.Println(c.r.Form) var ikNames []string for name, _ := range c.r.Form { if name[:2] == "ik" && name != "ik_sign" { ikNames = append(ikNames, name) } } sort.Strings(ikNames) fmt.Println(ikNames) var ikValues []string for _, names := range ikNames { ikValues = append(ikValues, c.r.FormValue(names)) } ikValues = append(ikValues, c.EConfig["ik_s_key"]) fmt.Println(ikValues) sign := strings.Join(ikValues, ":") fmt.Println(sign) sign = base64.StdEncoding.EncodeToString(utils.HexToBin(utils.Md5(sign))) fmt.Println(sign) if sign != c.r.FormValue("ik_sign") { return "", errors.New("Incorrect signature") } currencyId := int64(0) if c.r.FormValue("ik_cur") == "USD" { currencyId = 1001 } if currencyId == 0 { return "", errors.New("Incorrect currencyId") } amount := utils.StrToFloat64(c.r.FormValue("ik_am")) pmId := utils.StrToInt64(c.r.FormValue("ik_inv_id")) // проверим, не зачисляли ли мы уже это платеж existsId, err := c.Single(`SELECT id FROM e_adding_funds_ik WHERE id = ?`, pmId).Int64() if err != nil { return "", utils.ErrInfo(err) } if existsId != 0 { return "", errors.New("Incorrect ik_inv_id") } paymentInfo := c.r.FormValue("ik_desc") txTime := utils.Time() err = EPayment(paymentInfo, currencyId, txTime, amount, pmId, "ik", c.ECommission) if err != nil { return "", utils.ErrInfo(err) } return ``, nil }
func (c *Controller) SendToTheChat() (string, error) { c.r.ParseForm() message := c.r.FormValue("message") decryptMessage := c.r.FormValue("decrypt_message") sender := utils.StrToInt64(c.r.FormValue("sender")) receiver := utils.StrToInt64(c.r.FormValue("receiver")) lang := utils.StrToInt64(c.r.FormValue("lang")) room := utils.StrToInt64(c.r.FormValue("room")) // chatEncrypted == 1 status := utils.StrToInt64(c.r.FormValue("status")) signTime := utils.StrToInt64(c.r.FormValue("sign_time")) signature := []byte(c.r.FormValue("signature")) data := utils.Int64ToByte(lang) data = append(data, utils.Int64ToByte(room)...) data = append(data, utils.Int64ToByte(receiver)...) data = append(data, utils.Int64ToByte(sender)...) data = append(data, utils.Int64ToByte(status)...) data = append(data, []byte(message)...) data = append(data, utils.Int64ToByte(signTime)...) data = append(data, []byte(signature)...) hash := utils.Md5(data) err := c.CheckChatMessage(message, sender, receiver, lang, room, status, signTime, signature) if err != nil { return "", utils.ErrInfo(err) } var chatId int64 // на пуле сообщение сразу отобразится у всех if status == 1 { chatId, err = c.ExecSqlGetLastInsertId(`INSERT INTO chat (hash, time, lang, room, receiver, sender, status, enc_message, message, sign_time, signature) VALUES ([hex], ?, ?, ?, ?, ?, ?, ?, ?, ?, [hex])`, "id", hash, utils.Time(), lang, room, receiver, sender, 2, message, decryptMessage, signTime, signature) } else { chatId, err = c.ExecSqlGetLastInsertId(`INSERT INTO chat (hash, time, lang, room, receiver, sender, status, message, sign_time, signature) VALUES ([hex], ?, ?, ?, ?, ?, ?, ?, ?, [hex])`, "id", hash, utils.Time(), lang, room, receiver, sender, status, message, signTime, signature) } if err != nil { return "", utils.ErrInfo(err) } // даем команду рассыльщику, чтобы отправил всем хэш тр-ии сообщения utils.ChatNewTx <- chatId return utils.JsonAnswer("success", "success").String(), nil }
func (c *Controller) EGatePm() (string, error) { c.r.ParseForm() fmt.Println(c.r.Form) sign := strings.ToUpper(string(utils.Md5(c.r.FormValue("PAYMENT_ID") + ":" + c.r.FormValue("PAYEE_ACCOUNT") + ":" + c.r.FormValue("PAYMENT_AMOUNT") + ":" + c.r.FormValue("PAYMENT_UNITS") + ":" + c.r.FormValue("PAYMENT_BATCH_NUM") + ":" + c.r.FormValue("PAYER_ACCOUNT") + ":" + strings.ToUpper(string(utils.Md5(c.EConfig["pm_s_key"]))) + ":" + c.r.FormValue("TIMESTAMPGMT")))) txTime := utils.StrToInt64(c.r.FormValue("TIMESTAMPGMT")) if sign != c.r.FormValue("V2_HASH") { return "", errors.New("Incorrect signature") } currencyId := int64(0) if c.r.FormValue("PAYMENT_UNITS") == "USD" { currencyId = 1001 } if currencyId == 0 { return "", errors.New("Incorrect currencyId") } amount := utils.StrToFloat64(c.r.FormValue("PAYMENT_AMOUNT")) pmId := utils.StrToInt64(c.r.FormValue("PAYMENT_BATCH_NUM")) // проверим, не зачисляли ли мы уже это платеж existsId, err := c.Single(`SELECT id FROM e_adding_funds_pm WHERE id = ?`, pmId).Int64() if err != nil { return "", utils.ErrInfo(err) } if existsId != 0 { return "", errors.New("Incorrect PAYMENT_BATCH_NUM") } paymentInfo := c.r.FormValue("PAYMENT_ID") err = EPayment(paymentInfo, currencyId, txTime, amount, pmId, "pm", c.ECommission) if err != nil { return "", utils.ErrInfo(err) } return ``, nil }
func TestDisseminator(t *testing.T) { defer func() { if r := recover(); r != nil { log.Error("daemon Recovered", r) panic(r) } }() dir, err := filepath.Abs(filepath.Dir(os.Args[0])) if err != nil { t.Error(err) } fmt.Println(dir) /*configIni_, err := config.NewConfig("ini", "/home/z/IdeaProjects/src/github.com/c-darwin/dcoin-go/config.ini") if err != nil { t.Error("%v", utils.ErrInfo(err)) } configIni, err := configIni_.GetSection("default") if err != nil { t.Error("%v", utils.ErrInfo(err)) }*/ host := "pool.dcoin.club:8088" userId := int64(2) myUserId := int64(4) nodePublicKey := utils.HexToBin([]byte("30820122300d06092a864886f70d01010105000382010f003082010a0282010100b85bf8eb06d70e9f28961725ec04957d9c42db127bb788623b5063b7152bdf0df9f1af08a3cdb89f354fe86c43f9f071614b75ccee04ee9e61c749f1800870ad0ada6fc9dbcb928b2049376a06ac6754f6d2832a865e2e4bcfbd1451deb6d2c1ce6a0000701bdce2ec5c20da33ea427a58e9d9bd2807e0c712676593231410b6b0a35b392693cd62e33378987db36b4549ef5f65b172afd7cca9daed6d23e5239d966de9f31a83df4b59cb67ac5c1a816ee633cfcd3a87897b6a9053f3bd4131a403e4a20f301eea5efd31803cdf468663a605cdea96cf6b1cb698b7bb38ab5feb93b68972589d22b910520aab3b20575f2d0bc28b4960b8f912f5b15cede0af0203010001")) tx := utils.HexToBin([]byte("0c55b20550013401320131013204302e3031013001300130013001300130013001300130013082010096a9486eb64fd6ca5992e96e879e60881941d7c7bc62a0b86d60d5662b3023e1b8206105cd605791019d01ebc4c0b843284ab58efb772a159066f5a635b94c4344f09f640f244d8f68264cc1c9f83b2471547504041f8c16d8e2af77b07c5fa3799c40f267b1c7fc03326195737b3c605481e4ff37713931c28bc258a83963abf3222c287346b6ba872163b63a676ba9538f6d73fac5ee90500068541c07abddc77dff14eb3a18e47b4157228fe435c79cfa2a6189cef97fcc5f9fd58d1efa4c12f3de3db2f1993d4cd029cd3471f8a82341f75df61af247b70661ae8848afc18d28ab7654f67591f271d826f3925a4b7798653651f1e8c62854ef0bf97127f182010382010056ab8e00429fd794d2b0b64dce4cb0e36d34e59090379249990bcdc824251f907fca3e912a2e1e759dd5622b42aa86149740d72faf9743262875470b57c8c6a8333358a043ec9d8033f799578547bb04eb0f09c8e51898990f4f6760af5213ff61a95506f8b294b0ded892cfa9fcdb801887d1bb405f99ce3656818ce23de0a675cf190a5b616bea7c301f1a76e3dbbfb2c576580daf49e8f83e2286f0a62e869e49295f8bb07da0c25ac0b0a1fd3e7a82887c34f7fdda2112f334e19d7c68a130447536543752ef5a51c16ae456eaf0aadc28dbabcc27e13b7c50942704258e018f6cb898fc4a3c8a7018ee9e529b5f789973b941de7336ce7bf08b79cfeae7")) hash := utils.HexToBin(utils.Md5(tx)) toBeSent := utils.DecToBin(myUserId, 5) toBeSent = append(toBeSent, utils.DecToBin(1, 1)...) toBeSent = append(toBeSent, utils.DecToBin(utils.StrToInt64("0"), 1)...) toBeSent = append(toBeSent, []byte(hash)...) fmt.Printf("hash %x %v", hash, hash) dataType := int64(1) db := DbConnect(chBreaker, chAnswer, GoroutineName) DisseminatorType1(host, userId, string(nodePublicKey), db, toBeSent, dataType) }
func (c *Controller) GenerateNewPrimaryKey() (string, error) { c.r.ParseForm() password := c.r.FormValue("password") priv, pub := utils.GenKeys() if len(password) > 0 { log.Debug("priv:", priv) encKey, err := utils.Encrypt(utils.Md5("11"), []byte(priv)) log.Debug("priv encKey:", encKey) if err != nil { return "", utils.ErrInfo(err) } priv = base64.StdEncoding.EncodeToString(encKey) log.Debug("priv ENC:", priv) //priv = string(encKey) } json, err := json.Marshal(map[string]string{"private_key": priv, "public_key": pub, "password_hash": string(utils.DSha256(password))}) if err != nil { return "", utils.ErrInfo(err) } log.Debug("%v", json) return string(json), nil }
func ElectionsAdmin(chBreaker chan bool, chAnswer chan string) { defer func() { if r := recover(); r != nil { log.Error("daemon Recovered", r) panic(r) } }() const GoroutineName = "ElectionsAdmin" d := new(daemon) d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName) if d.DCDB == nil { return } d.goRoutineName = GoroutineName d.chAnswer = chAnswer d.chBreaker = chBreaker if utils.Mobile() { d.sleepTime = 3600 } else { d.sleepTime = 60 } if !d.CheckInstall(chBreaker, chAnswer, GoroutineName) { return } d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName) if d.DCDB == nil { return } err = d.notMinerSetSleepTime(1800) if err != nil { log.Error("%v", err) return } BEGIN: for { log.Info(GoroutineName) MonitorDaemonCh <- []string{GoroutineName, utils.Int64ToStr(utils.Time())} // проверим, не нужно ли нам выйти из цикла if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) { break BEGIN } err, restart := d.dbLock() if restart { break BEGIN } if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } blockId, err := d.GetBlockId() if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } if blockId == 0 { if d.unlockPrintSleep(utils.ErrInfo("blockId == 0"), d.sleepTime) { break BEGIN } continue BEGIN } _, _, myMinerId, _, _, _, err := d.TestBlock() if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } // а майнер ли я ? if myMinerId == 0 { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } variables, err := d.GetAllVariables() curTime := utils.Time() // проверим, прошло ли 2 недели с момента последнего обновления adminTime, err := d.Single("SELECT time FROM admin").Int64() if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } if curTime-adminTime <= variables.Int64["new_pct_period"] { if d.unlockPrintSleep(utils.ErrInfo("14 day error"), d.sleepTime) { break BEGIN } continue BEGIN } // сколько всего майнеров countMiners, err := d.Single("SELECT count(miner_id) FROM miners WHERE active = 1").Int64() if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } if countMiners < 1000 { if d.unlockPrintSleep(utils.ErrInfo("countMiners < 1000"), d.sleepTime) { break BEGIN } continue BEGIN } // берем все голоса var newAdmin int64 votes_admin, err := d.GetMap(` SELECT admin_user_id, count(user_id) as votes FROM votes_admin WHERE time > ? GROUP BY admin_user_id `, "admin_user_id", "votes", curTime-variables.Int64["new_pct_period"]) if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } for admin_user_id, votes := range votes_admin { // если более 50% майнеров проголосовали if utils.StrToInt64(votes) > countMiners/2 { newAdmin = utils.StrToInt64(admin_user_id) } } if newAdmin == 0 { if d.unlockPrintSleep(utils.ErrInfo("newAdmin == 0"), d.sleepTime) { break BEGIN } continue BEGIN } _, myUserId, _, _, _, _, err := d.TestBlock() forSign := fmt.Sprintf("%v,%v,%v,%v", utils.TypeInt("NewAdmin"), curTime, myUserId, newAdmin) binSign, err := d.GetBinSign(forSign, myUserId) if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } data := utils.DecToBin(utils.TypeInt("NewAdmin"), 1) data = append(data, utils.DecToBin(curTime, 4)...) data = append(data, utils.EncodeLengthPlusData(utils.Int64ToByte(myUserId))...) data = append(data, utils.EncodeLengthPlusData(utils.Int64ToByte(newAdmin))...) data = append(data, utils.EncodeLengthPlusData([]byte(binSign))...) err = d.InsertReplaceTxInQueue(data) if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } p := new(dcparser.Parser) p.DCDB = d.DCDB err = p.TxParser(utils.HexToBin(utils.Md5(data)), data, true) if err != nil { if d.unlockPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } d.dbUnlock() if d.dSleep(d.sleepTime) { break BEGIN } } log.Debug("break BEGIN %v", GoroutineName) }
func (c *Controller) NewUser() (string, error) { txType := "NewUser" txTypeId := utils.TypeInt(txType) timeNow := utils.Time() param := utils.ParamType{X: 176, Y: 100, Width: 100, Bg_path: "static/img/k_bg.png"} refPhotos := make(map[int64][]string) myRefsKeys := make(map[int64]map[string]string) if c.SessRestricted == 0 { join := c.MyPrefix + `my_new_users.user_id` if c.ConfigIni["db_type"] == "sqlite" || c.ConfigIni["db_type"] == "postgresql" { join = `"` + c.MyPrefix + `my_new_users".user_id` } rows, err := c.Query(c.FormatQuery(` SELECT users.user_id, private_key, log_id FROM ` + c.MyPrefix + `my_new_users LEFT JOIN users ON users.user_id = ` + join + ` WHERE status = 'approved' `)) if err != nil { return "", utils.ErrInfo(err) } defer rows.Close() for rows.Next() { var user_id, log_id int64 var private_key string err = rows.Scan(&user_id, &private_key, &log_id) if err != nil { return "", utils.ErrInfo(err) } // проверим, не сменил ли уже юзер свой ключ StrUserId := utils.Int64ToStr(user_id) if log_id != 0 { myRefsKeys[user_id] = map[string]string{"user_id": StrUserId} } else { myRefsKeys[user_id] = map[string]string{"user_id": StrUserId, "private_key": private_key} md5 := string(utils.Md5(private_key)) kPath := *utils.Dir + "/public/" + md5[0:16] kPathPng := kPath + ".png" kPathTxt := kPath + ".txt" if _, err := os.Stat(kPathPng); os.IsNotExist(err) { privKey := strings.Replace(private_key, "-----BEGIN RSA PRIVATE KEY-----", "", -1) privKey = strings.Replace(privKey, "-----END RSA PRIVATE KEY-----", "", -1) _, err = utils.KeyToImg(privKey, kPathPng, user_id, c.TimeFormat, param) if err != nil { return "", utils.ErrInfo(err) } err := ioutil.WriteFile(kPathTxt, []byte(privKey), 0644) if err != nil { return "", utils.ErrInfo(err) } /*$gd = key_to_img($private_key, $param, $row['user_id']); imagepng($gd, $k_path_png); file_put_contents($k_path_txt, trim($private_key));*/ } } } } refs := make(map[int64]map[int64]float64) // инфа по рефам юзера rows, err := c.Query(c.FormatQuery(` SELECT referral, sum(amount) as amount, currency_id FROM referral_stats WHERE user_id = ? GROUP BY currency_id, referral `), c.SessUserId) if err != nil { return "", utils.ErrInfo(err) } defer rows.Close() for rows.Next() { var referral, currency_id int64 var amount float64 err = rows.Scan(&referral, &amount, ¤cy_id) if err != nil { return "", utils.ErrInfo(err) } refs[referral] = map[int64]float64{currency_id: amount} } myRefsAmounts := make(map[int64]myRefsType) for refUserId, refData := range refs { data, err := c.OneRow("SELECT * FROM miners_data WHERE user_id = ?", refUserId).String() if err != nil { return "", utils.ErrInfo(err) } // получим ID майнеров, у которых лежат фото нужного нам юзера if len(data) == 0 { continue } minersIds := utils.GetMinersKeepers(data["photo_block_id"], data["photo_max_miner_id"], data["miners_keepers"], true) if len(minersIds) > 0 { hosts, err := c.GetList("SELECT http_host FROM miners_data WHERE miner_id IN (" + utils.JoinInts(minersIds, ",") + ")").String() if err != nil { return "", utils.ErrInfo(err) } myRefsAmounts[refUserId] = myRefsType{Amounts: refData, Hosts: hosts} refPhotos[refUserId] = hosts } } myRefs := make(map[int64]myRefsType) for refUserId, refData := range myRefsAmounts { myRefs[refUserId] = refData } for refUserId, refData := range myRefsKeys { md5 := string(utils.Md5(refData["private_key"])) myRefs[refUserId] = myRefsType{Key: refData["private_key"], KeyUrl: c.NodeConfig["pool_url"] + "public/" + md5[0:16]} } /* * Общая стата по рефам */ globalRefs := make(map[int64]globalRefsType) // берем лидеров по USD rows, err = c.Query(c.FormatQuery(` SELECT user_id, sum(amount) as amount FROM referral_stats WHERE currency_id = 72 GROUP BY user_id ORDER BY amount DESC `)) if err != nil { return "", utils.ErrInfo(err) } defer rows.Close() for rows.Next() { var user_id int64 var amount float64 err = rows.Scan(&user_id, &amount) if err != nil { return "", utils.ErrInfo(err) } // вся прибыль с рефов у данного юзера refAmounts, err := c.GetAll(` SELECT ROUND(sum(amount)) as amount, currency_id FROM referral_stats WHERE user_id = ? GROUP BY currency_id `, -1, user_id) if err != nil { return "", utils.ErrInfo(err) } data, err := c.OneRow("SELECT * FROM miners_data WHERE user_id = ?", user_id).String() if err != nil { return "", utils.ErrInfo(err) } // получим ID майнеров, у которых лежат фото нужного нам юзера minersIds := utils.GetMinersKeepers(data["photo_block_id"], data["photo_max_miner_id"], data["miners_keepers"], true) hosts, err := c.GetList("SELECT http_host FROM miners_data WHERE miner_id IN (" + utils.JoinInts(minersIds, ",") + ")").String() if err != nil { return "", utils.ErrInfo(err) } globalRefs[user_id] = globalRefsType{Amounts: refAmounts, Hosts: hosts} refPhotos[user_id] = hosts } lastTx, err := c.GetLastTx(c.SessUserId, utils.TypesToIds([]string{"NewUser"}), 1, c.TimeFormat) lastTxFormatted := "" if len(lastTx) > 0 { lastTxFormatted, _ = utils.MakeLastTx(lastTx, c.Lang) } TemplateStr, err := makeTemplate("new_user", "newUser", &newUserPage{ Alert: c.Alert, Lang: c.Lang, CountSignArr: c.CountSignArr, ShowSignData: c.ShowSignData, UserId: c.SessUserId, TimeNow: timeNow, TxType: txType, TxTypeId: txTypeId, SignData: "", LastTxFormatted: lastTxFormatted, MyRefs: myRefs, GlobalRefs: globalRefs, CurrencyList: c.CurrencyList, RefPhotos: refPhotos, PoolUrl: c.NodeConfig["pool_url"]}) if err != nil { return "", utils.ErrInfo(err) } return TemplateStr, nil }
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 (c *Controller) ECheckSign() (string, error) { c.w.Header().Set("Access-Control-Allow-Origin", "*") c.r.ParseForm() userId := utils.StrToInt64(c.r.FormValue("user_id")) sign := []byte(c.r.FormValue("sign")) if !utils.CheckInputData(string(sign), "hex_sign") { return `{"result":"incorrect sign"}`, nil } if !utils.CheckInputData(userId, "int") { return `{"result":"incorrect user_id"}`, nil } var publicKey []byte if userId == 0 { n := []byte(c.r.FormValue("n")) e := []byte(c.r.FormValue("e")) if !utils.CheckInputData(n, "hex") { return `{"result":"incorrect n"}`, nil } if !utils.CheckInputData(e, "hex") { return `{"result":"incorrect e"}`, nil } log.Debug("n %v / e %v", n, e) publicKey = utils.MakeAsn1(n, e) log.Debug("publicKey %s", publicKey) } RemoteAddr := utils.RemoteAddrFix(c.r.RemoteAddr) re := regexp.MustCompile(`(.*?):[0-9]+$`) match := re.FindStringSubmatch(RemoteAddr) if len(match) != 0 { RemoteAddr = match[1] } log.Debug("RemoteAddr %s", RemoteAddr) hash := utils.Md5(c.r.Header.Get("User-Agent") + RemoteAddr) log.Debug("hash %s", hash) forSign, err := c.Single(`SELECT data FROM e_authorization WHERE hex(hash) = ?`, hash).String() if err != nil { return "{\"result\":0}", err } if userId > 0 { publicKey_, err := c.GetUserPublicKey(userId) publicKey = []byte(publicKey_) if err != nil { return "{\"result\":0}", err } if len(publicKey_) == 0 { return "{\"result\":0}", utils.ErrInfo("len(publicKey_) == 0") } } else { userId_, err := c.GetUserIdByPublicKey(publicKey) userId = utils.StrToInt64(userId_) publicKey = utils.HexToBin(publicKey) log.Debug("userId %d", userId) if err != nil { return "{\"result\":0}", err } if userId == 0 { return "{\"result\":0}", utils.ErrInfo("userId == 0") } } log.Debug("userId %v", userId) log.Debug("publicKey %x", publicKey) log.Debug("forSign %v", forSign) log.Debug("sign %s", sign) // проверим подпись resultCheckSign, err := utils.CheckSign([][]byte{[]byte(publicKey)}, forSign, utils.HexToBin(sign), true) if err != nil { return "{\"result\":0}", err } log.Debug("resultCheckSign %v", resultCheckSign) if resultCheckSign { // если это первый запрос, то создаем запись в табле users eUserId, err := c.Single(`SELECT id FROM e_users WHERE user_id = ?`, userId).Int64() if err != nil { return "{\"result\":0}", err } if eUserId == 0 { eUserId, err = c.ExecSqlGetLastInsertId(`INSERT INTO e_users (user_id) VALUES (?)`, "id", userId) if err != nil { return "{\"result\":0}", err } } if len(c.r.FormValue("user_id")) > 0 { token := utils.RandSeq(30) err = c.ExecSql(`INSERT INTO e_tokens (token, user_id) VALUES (?, ?)`, token, eUserId) if err != nil { return "{\"result\":0}", err } log.Debug(`{"result":"1", "token":"` + token + `"}`) return `{"result":"1", "token":"` + token + `"}`, nil } else { c.sess.Set("e_user_id", eUserId) return `{"result":1}`, nil } } else { return "{\"result\":0}", nil } }
/* * Каждые 2 недели собираем инфу о голосах за % и создаем тр-ию, которая * попадет в DC сеть только, если мы окажемся генератором блока * */ func ReductionGenerator(chBreaker chan bool, chAnswer chan string) { defer func() { if r := recover(); r != nil { log.Error("daemon Recovered", r) panic(r) } }() const GoroutineName = "ReductionGenerator" d := new(daemon) d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName) if d.DCDB == nil { return } d.goRoutineName = GoroutineName d.chAnswer = chAnswer d.chBreaker = chBreaker if utils.Mobile() { d.sleepTime = 3600 } else { d.sleepTime = 60 } if !d.CheckInstall(chBreaker, chAnswer, GoroutineName) { return } d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName) if d.DCDB == nil { return } err = d.notMinerSetSleepTime(1800) if err != nil { log.Error("%v", err) return } BEGIN: for { log.Info(GoroutineName) MonitorDaemonCh <- []string{GoroutineName, utils.Int64ToStr(utils.Time())} // проверим, не нужно ли нам выйти из цикла if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) { break BEGIN } err, restart := d.dbLock() if restart { break BEGIN } if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } blockId, err := d.GetBlockId() if err != nil { if d.unlockPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } if blockId == 0 { if d.unlockPrintSleep(errors.New("blockId == 0"), d.sleepTime) { break BEGIN } continue BEGIN } _, _, myMinerId, _, _, _, err := d.TestBlock() if err != nil { if d.unlockPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } // а майнер ли я ? if myMinerId == 0 { if d.unlockPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } variables, err := d.GetAllVariables() curTime := utils.Time() var reductionType string var reductionCurrencyId int var reductionPct int64 // ===== ручное урезание денежной массы // получаем кол-во обещанных сумм у разных юзеров по каждой валюте. start_time есть только у тех, у кого статус mining/repaid promisedAmount, err := d.GetMap(` SELECT currency_id, count(user_id) as count FROM ( SELECT currency_id, user_id FROM promised_amount WHERE start_time < ? AND del_block_id = 0 AND del_mining_block_id = 0 AND status IN ('mining', 'repaid') GROUP BY user_id, currency_id ) as t1 GROUP BY currency_id`, "currency_id", "count", (curTime - variables.Int64["min_hold_time_promise_amount"])) if err != nil { if d.unlockPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } log.Info("%v", "promisedAmount", promisedAmount) // берем все голоса юзеров rows, err := d.Query(d.FormatQuery(` SELECT currency_id, pct, count(currency_id) as votes FROM votes_reduction WHERE time > ? GROUP BY currency_id, pct `), curTime-variables.Int64["reduction_period"]) if err != nil { if d.unlockPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } for rows.Next() { var votes, pct int64 var currency_id string err = rows.Scan(¤cy_id, &pct, &votes) if err != nil { rows.Close() if d.unlockPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } if len(promisedAmount[currency_id]) == 0 || promisedAmount[currency_id] == "0" { continue } // если голосов за урезание > 50% от числа всех держателей данной валюты if votes >= utils.StrToInt64(promisedAmount[currency_id])/2 { // проверим, прошло ли 2 недели с последнего урезания reductionTime, err := d.Single("SELECT max(time) FROM reduction WHERE currency_id = ? AND type = 'manual'", currency_id).Int64() if err != nil { rows.Close() if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } if curTime-reductionTime > variables.Int64["reduction_period"] { reductionCurrencyId = utils.StrToInt(currency_id) reductionPct = pct reductionType = "manual" log.Info("%v", "reductionCurrencyId", reductionCurrencyId, "reductionPct", reductionPct, "reductionType", reductionType) break } } } rows.Close() // ======= авто-урезание денежной массы из-за малого объема обещанных сумм // получаем кол-во DC на кошельках sumWallets_, err := d.GetMap("SELECT currency_id, sum(amount) as sum_amount FROM wallets GROUP BY currency_id", "currency_id", "sum_amount") if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } sumWallets := make(map[int]float64) for currencyId, amount := range sumWallets_ { sumWallets[utils.StrToInt(currencyId)] = utils.StrToFloat64(amount) } // получаем кол-во TDC на обещанных суммах, плюсуем к тому, что на кошельках sumTdc, err := d.GetMap("SELECT currency_id, sum(tdc_amount) as sum_amount FROM promised_amount GROUP BY currency_id", "currency_id", "sum_amount") if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } for currencyId, amount := range sumTdc { currencyIdInt := utils.StrToInt(currencyId) if sumWallets[currencyIdInt] == 0 { sumWallets[currencyIdInt] = utils.StrToFloat64(amount) } else { sumWallets[currencyIdInt] += utils.StrToFloat64(amount) } } log.Debug("sumWallets", sumWallets) // получаем суммы обещанных сумм sumPromisedAmount, err := d.GetMap(` SELECT currency_id, sum(amount) as sum_amount FROM promised_amount WHERE status = 'mining' AND del_block_id = 0 AND del_mining_block_id = 0 AND (cash_request_out_time = 0 OR cash_request_out_time > ?) GROUP BY currency_id `, "currency_id", "sum_amount", curTime-variables.Int64["cash_request_time"]) if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } log.Debug("sumPromisedAmount", sumPromisedAmount) if len(sumWallets) > 0 { for currencyId, sumAmount := range sumWallets { //недопустимо для WOC if currencyId == 1 { continue } reductionTime, err := d.Single("SELECT max(time) FROM reduction WHERE currency_id = ? AND type = 'auto'", currencyId).Int64() if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } log.Debug("reductionTime", reductionTime) // прошло ли 48 часов if curTime-reductionTime <= consts.AUTO_REDUCTION_PERIOD { log.Debug("curTime-reductionTime <= consts.AUTO_REDUCTION_PERIOD %d <= %d", curTime-reductionTime, consts.AUTO_REDUCTION_PERIOD) continue } // если обещанных сумм менее чем 100% от объема DC на кошельках, то запускаем урезание log.Debug("utils.StrToFloat64(sumPromisedAmount[utils.IntToStr(currencyId)]) < sumAmount*consts.AUTO_REDUCTION_PROMISED_AMOUNT_PCT %d < %d", utils.StrToFloat64(sumPromisedAmount[utils.IntToStr(currencyId)]), sumAmount*consts.AUTO_REDUCTION_PROMISED_AMOUNT_PCT) if utils.StrToFloat64(sumPromisedAmount[utils.IntToStr(currencyId)]) < sumAmount*consts.AUTO_REDUCTION_PROMISED_AMOUNT_PCT { // проверим, есть ли хотя бы 1000 юзеров, у которых на кошелках есть или была данная валюты countUsers, err := d.Single("SELECT count(user_id) FROM wallets WHERE currency_id = ?", currencyId).Int64() if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } log.Debug("countUsers>=countUsers %d >= %d", countUsers, consts.AUTO_REDUCTION_PROMISED_AMOUNT_MIN) if countUsers >= consts.AUTO_REDUCTION_PROMISED_AMOUNT_MIN { reductionCurrencyId = currencyId reductionPct = consts.AUTO_REDUCTION_PCT reductionType = "promised_amount" break } } } } if reductionCurrencyId > 0 && reductionPct > 0 { _, myUserId, _, _, _, _, err := d.TestBlock() forSign := fmt.Sprintf("%v,%v,%v,%v,%v,%v", utils.TypeInt("NewReduction"), curTime, myUserId, reductionCurrencyId, reductionPct, reductionType) log.Debug("forSign = %v", forSign) binSign, err := d.GetBinSign(forSign, myUserId) if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } data := utils.DecToBin(utils.TypeInt("NewReduction"), 1) data = append(data, utils.DecToBin(curTime, 4)...) data = append(data, utils.EncodeLengthPlusData(utils.Int64ToByte(myUserId))...) data = append(data, utils.EncodeLengthPlusData(utils.Int64ToByte(int64(reductionCurrencyId)))...) data = append(data, utils.EncodeLengthPlusData(utils.Int64ToByte(reductionPct))...) data = append(data, utils.EncodeLengthPlusData([]byte(reductionType))...) data = append(data, utils.EncodeLengthPlusData([]byte(binSign))...) err = d.InsertReplaceTxInQueue(data) if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } // и не закрывая main_lock переводим нашу тр-ию в verified=1, откатив все несовместимые тр-ии // таким образом у нас будут в блоке только актуальные голоса. // а если придет другой блок и станет verified=0, то эта тр-ия просто удалится. p := new(dcparser.Parser) p.DCDB = d.DCDB err = p.TxParser(utils.HexToBin(utils.Md5(data)), data, true) if err != nil { 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) 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 QueueParserTestblock(chBreaker chan bool, chAnswer chan string) { defer func() { if r := recover(); r != nil { log.Error("daemon Recovered", r) panic(r) } }() const GoroutineName = "QueueParserTestblock" 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 = 1800 } 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 } err, restart := d.dbLock() if restart { break BEGIN } if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } data, err := d.OneRow("SELECT * FROM queue_testblock ORDER BY head_hash ASC").String() if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue } if len(data) == 0 { if d.unlockPrintSleepInfo(utils.ErrInfo(errors.New("len(data) == 0")), d.sleepTime) { break BEGIN } continue } newBlock := []byte(data["data"]) newHeaderHash := utils.BinToHex([]byte(data["head_hash"])) tx := utils.DeleteHeader(newBlock) // сразу можно удалять данные из таблы-очереди err = d.ExecSql("DELETE FROM queue_testblock WHERE hex(head_hash) = ?", newHeaderHash) if err != nil { if d.unlockPrintSleep(utils.ErrInfo(errors.New("len(data) == 0")), d.sleepTime) { break BEGIN } continue } // прежде всего нужно проверить, а нет ли в этом блоке ошибок с несовметимыми тр-ми // при полной проверке, а не только фронтальной проблем с несовместимыми тр-ми не будет, т.к. там даные сразу пишутся в таблицы // а тут у нас данные пишутся только в log_time_ // и сами тр-ии пишем в отдельную таблу p := new(dcparser.Parser) p.DCDB = d.DCDB if len(tx) > 0 { log.Debug("len(tx): %d", len(tx)) for { log.Debug("tx: %x", tx) txSize := utils.DecodeLength(&tx) log.Debug("txSize: %d", txSize) // отделим одну транзакцию от списка транзакций txBinaryData := utils.BytesShift(&tx, txSize) log.Debug("txBinaryData: %x", txBinaryData) // проверим, нет ли несовместимых тр-ий fatalError, waitError, _, _, _, _ := p.ClearIncompatibleTx(txBinaryData, false) if len(fatalError) > 0 || len(waitError) > 0 { if d.unlockPrintSleep(utils.ErrInfo(errors.New(" len(fatalError) > 0 || len(waitError) > 0")), d.sleepTime) { break BEGIN } continue BEGIN } if len(tx) == 0 { break } } } // откатим тр-ии тестблока, но не удаляя их, т.к. далее еще можем их вернуть p.RollbackTransactionsTestblock(false) // проверим блок, который получился с данными, которые прислал другой нод p.BinaryData = newBlock err = p.ParseDataGate(false) if err != nil { log.Error("%v", err) // т.к. мы откатили наши тр-ии из transactions_testblock, то теперь нужно обработать их по новой // получим наши транзакции в 1 бинарнике, просто для удобства var myTestBlockBody []byte transactionsTestblock, err := d.GetAll("SELECT data FROM transactions_testblock ORDER BY id ASC", -1) if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } for _, data := range transactionsTestblock { myTestBlockBody = append(myTestBlockBody, []byte(data["data"])...) } if len(myTestBlockBody) > 0 { p.BinaryData = append(utils.DecToBin(0, 1), myTestBlockBody...) err = p.ParseDataGate(true) if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } } } else { // наши тр-ии уже не актуальны, т.к. мы их откатили err = d.ExecSql("DELETE FROM transactions_testblock") if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } exists, err := d.Single(`SELECT block_id FROM testblock`).Int64() if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } return } if exists > 0 { // если всё нормально, то пишем в таблу testblock новые тр-ии и новые данные по юзеру их сгенерившему err = d.ExecSql(` UPDATE testblock SET time = ?, user_id = ?, header_hash = [hex], signature = [hex], mrkl_root = [hex] `, p.BlockData.Time, p.BlockData.UserId, newHeaderHash, utils.BinToHex(p.BlockData.Sign), p.MrklRoot) if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } } // и сами тр-ии пишем в отдельную таблу if len(tx) > 0 { for { txSize := utils.DecodeLength(&tx) // отчекрыжим одну транзакцию от списка транзакций txBinaryData := utils.BytesShift(&tx, txSize) // получим тип тр-ии и юзера txType, userId, toUserId := utils.GetTxTypeAndUserId(txBinaryData) md5 := utils.Md5(txBinaryData) dataHex := utils.BinToHex(txBinaryData) err = d.ExecSql("DELETE FROM transactions_testblock") if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } err = d.ExecSql("INSERT INTO transactions_testblock (hash, data, type, user_id, third_var) VALUES ([hex], [hex], ?, ?, ?)", md5, dataHex, txType, userId, toUserId) if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } if len(tx) == 0 { break } } } // удаляем всё, где хэш больше нашего err = d.ExecSql("DELETE FROM queue_testblock WHERE hex(head_hash) > ?", newHeaderHash) if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } // возможно нужно откатить и тр-ии с verified=1 и used=0 из transactions // т.к. в transactions может быть тр-ия на удаление банкноты // и в transactions_testblock только что была залита такая же тр-ия // выходит, что блок, который будет сгенерен на основе transactions будет ошибочным // или при откате transactions будет сделан вычет из log_time_.... // и выйдет что попавшая в блок тр-я из transactions_testblock попала минуя запись log_time_.... err = p.RollbackTransactions() if err != nil { if d.dPrintSleep(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 (c *Controller) SignUpInPool() (string, error) { c.w.Header().Set("Access-Control-Allow-Origin", "*") if !c.Community { return "", utils.JsonAnswer("Not pool", "error").Error() } c.r.ParseForm() var userId int64 var codeSign string if c.SessUserId <= 0 { // запрос пришел с десктопного кошелька юзера codeSign = c.r.FormValue("code_sign") if !utils.CheckInputData(codeSign, "hex_sign") { return "", utils.JsonAnswer("Incorrect code_sign", "error").Error() } userId = utils.StrToInt64(c.r.FormValue("user_id")) if !utils.CheckInputData(userId, "int64") { return "", utils.JsonAnswer("Incorrect userId", "error").Error() } // получим данные для подписи var hash []byte RemoteAddr := utils.RemoteAddrFix(c.r.RemoteAddr) re := regexp.MustCompile(`(.*?):[0-9]+$`) match := re.FindStringSubmatch(RemoteAddr) if len(match) != 0 { RemoteAddr = match[1] } log.Debug("RemoteAddr %s", RemoteAddr) hash = utils.Md5(c.r.Header.Get("User-Agent") + RemoteAddr) log.Debug("hash %s", hash) forSign, err := c.GetDataAuthorization(hash) log.Debug("forSign: %v", forSign) publicKey, err := c.GetUserPublicKey(userId) log.Debug("publicKey: %x", publicKey) if err != nil { return "", utils.JsonAnswer(utils.ErrInfo(err), "error").Error() } // проверим подпись resultCheckSign, err := utils.CheckSign([][]byte{[]byte(publicKey)}, forSign, utils.HexToBin([]byte(codeSign)), true) if err != nil { return "", utils.JsonAnswer(utils.ErrInfo(err), "error").Error() } if !resultCheckSign { return "", utils.JsonAnswer("Incorrect codeSign", "error").Error() } } else { // запрос внутри пула userId = c.SessUserId } /*e:=c.r.FormValue("e") n:=c.r.FormValue("n") if len(e) == 0 || len(n) == 0 { result, _ := json.Marshal(map[string]string{"error": c.Lang["pool_error"]}) return "", errors.New(string(result)) }*/ email := c.r.FormValue("email") if !utils.ValidateEmail(email) { return "", utils.JsonAnswer("Incorrect email", "error").Error() } nodePrivateKey := c.r.FormValue("node_private_key") if !utils.CheckInputData(nodePrivateKey, "private_key") { return "", utils.JsonAnswer("Incorrect private_key", "error").Error() } //publicKey := utils.MakeAsn1([]byte(n), []byte(e)) log.Debug("3") // если мест в пуле нет, то просто запишем юзера в очередь pool_max_users, err := c.Single("SELECT pool_max_users FROM config").Int() if err != nil { return "", utils.JsonAnswer(utils.ErrInfo(err), "error").Error() } if len(c.CommunityUsers) >= pool_max_users { err = c.ExecSql("INSERT INTO pool_waiting_list ( email, time, user_id ) VALUES ( ?, ?, ? )", email, utils.Time(), userId) if err != nil { return "", utils.JsonAnswer(utils.ErrInfo(err), "error").Error() } return "", utils.JsonAnswer(c.Lang["pool_is_full"], "error").Error() } // регистрируем юзера в пуле // вначале убедимся, что такой user_id у нас уже не зареган community, err := c.Single("SELECT user_id FROM community WHERE user_id = ?", userId).Int64() if err != nil { return "", utils.JsonAnswer(utils.ErrInfo(err), "error").Error() } if community != 0 { return utils.JsonAnswer(c.Lang["pool_user_id_is_busy"], "success").String(), nil } err = c.ExecSql("INSERT INTO community ( user_id ) VALUES ( ? )", userId) if err != nil { return "", utils.JsonAnswer(utils.ErrInfo(err), "error").Error() } schema_ := &schema.SchemaStruct{} schema_.DCDB = c.DCDB schema_.DbType = c.ConfigIni["db_type"] schema_.PrefixUserId = int(userId) schema_.GetSchema() prefix := utils.Int64ToStr(userId) + "_" minerId, err := c.GetMinerId(userId) if err != nil { return "", utils.JsonAnswer(utils.ErrInfo(err), "error").Error() } if minerId > 0 { err = c.ExecSql("INSERT INTO "+prefix+"my_table ( user_id, miner_id, status, email ) VALUES (?, ?, ?, ?)", userId, minerId, "miner", email) if err != nil { return "", utils.JsonAnswer(utils.ErrInfo(err), "error").Error() } } else { err = c.ExecSql("INSERT INTO "+prefix+"my_table ( user_id, status, email ) VALUES (?, ?, ?)", userId, "miner", email) if err != nil { return "", utils.JsonAnswer(utils.ErrInfo(err), "error").Error() } } publicKey, err := c.GetUserPublicKey(userId) err = c.ExecSql("INSERT INTO "+prefix+"my_keys ( public_key, status ) VALUES ( [hex], 'approved' )", utils.BinToHex(publicKey)) if err != nil { return "", utils.JsonAnswer(utils.ErrInfo(err), "error").Error() } nodePublicKey, err := utils.GetPublicFromPrivate(nodePrivateKey) if err != nil { return "", utils.JsonAnswer(utils.ErrInfo(err), "error").Error() } err = c.ExecSql("INSERT INTO "+prefix+"my_node_keys ( private_key, public_key ) VALUES ( ?, [hex] )", nodePrivateKey, nodePublicKey) if err != nil { return "", utils.JsonAnswer(utils.ErrInfo(err), "error").Error() } c.sess.Delete("restricted") return utils.JsonAnswer(c.Lang["pool_sign_up_success"], "success").String(), nil }
func MaxOtherCurrenciesGenerator(chBreaker chan bool, chAnswer chan string) { defer func() { if r := recover(); r != nil { log.Error("daemon Recovered", r) panic(r) } }() const GoroutineName = "MaxOtherCurrenciesGenerator" d := new(daemon) d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName) if d.DCDB == nil { return } d.goRoutineName = GoroutineName d.chAnswer = chAnswer d.chBreaker = chBreaker if utils.Mobile() { d.sleepTime = 3600 } else { d.sleepTime = 60 } if !d.CheckInstall(chBreaker, chAnswer, GoroutineName) { return } d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName) if d.DCDB == nil { return } err = d.notMinerSetSleepTime(1800) if err != nil { log.Error("%v", err) return } BEGIN: for { log.Info(GoroutineName) MonitorDaemonCh <- []string{GoroutineName, utils.Int64ToStr(utils.Time())} // проверим, не нужно ли нам выйти из цикла if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) { break BEGIN } err, restart := d.dbLock() if restart { break BEGIN } if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } blockId, err := d.GetBlockId() if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } if blockId == 0 { if d.unlockPrintSleep(utils.ErrInfo("blockId == 0"), d.sleepTime) { break BEGIN } continue BEGIN } _, _, myMinerId, _, _, _, err := d.TestBlock() if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } // а майнер ли я ? if myMinerId == 0 { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } variables, err := d.GetAllVariables() curTime := utils.Time() totalCountCurrencies, err := d.GetCountCurrencies() if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } // проверим, прошло ли 2 недели с момента последнего обновления pctTime, err := d.Single("SELECT max(time) FROM max_other_currencies_time").Int64() if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } if curTime-pctTime <= variables.Int64["new_max_other_currencies"] { if d.unlockPrintSleep(utils.ErrInfo("14 day error"), d.sleepTime) { break BEGIN } continue BEGIN } // берем все голоса maxOtherCurrenciesVotes := make(map[int64][]map[int64]int64) rows, err := d.Query("SELECT currency_id, count, count(user_id) as votes FROM votes_max_other_currencies GROUP BY currency_id, count ORDER BY currency_id, count ASC") if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } for rows.Next() { var currency_id, count, votes int64 err = rows.Scan(¤cy_id, &count, &votes) if err != nil { rows.Close() if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } maxOtherCurrenciesVotes[currency_id] = append(maxOtherCurrenciesVotes[currency_id], map[int64]int64{count: votes}) } rows.Close() newMaxOtherCurrenciesVotes := make(map[string]int64) for currencyId, countAndVotes := range maxOtherCurrenciesVotes { newMaxOtherCurrenciesVotes[utils.Int64ToStr(currencyId)] = utils.GetMaxVote(countAndVotes, 0, totalCountCurrencies, 10) } jsonData, err := json.Marshal(newMaxOtherCurrenciesVotes) _, myUserId, _, _, _, _, err := d.TestBlock() forSign := fmt.Sprintf("%v,%v,%v,%s", utils.TypeInt("NewMaxOtherCurrencies"), curTime, myUserId, jsonData) log.Debug("forSign = %v", forSign) binSign, err := d.GetBinSign(forSign, myUserId) if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } data := utils.DecToBin(utils.TypeInt("NewMaxOtherCurrencies"), 1) data = append(data, utils.DecToBin(curTime, 4)...) data = append(data, utils.EncodeLengthPlusData(utils.Int64ToByte(myUserId))...) data = append(data, utils.EncodeLengthPlusData(jsonData)...) data = append(data, utils.EncodeLengthPlusData([]byte(binSign))...) err = d.InsertReplaceTxInQueue(data) if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } p := new(dcparser.Parser) p.DCDB = d.DCDB err = p.TxParser(utils.HexToBin(utils.Md5(data)), data, true) if err != nil { 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) }
/** фронт. проверка + занесение данных из блока в таблицы и info_block */ func (p *Parser) ParseDataFull() error { p.TxIds = []string{} p.dataPre() if p.dataType != 0 { // парсим только блоки return utils.ErrInfo(fmt.Errorf("incorrect dataType")) } var err error p.Variables, err = p.GetAllVariables() if err != nil { return utils.ErrInfo(err) } //if len(p.BinaryData) > 500000 { // ioutil.WriteFile("block-"+string(utils.DSha256(p.BinaryData)), p.BinaryData, 0644) //} err = p.ParseBlock() if err != nil { return utils.ErrInfo(err) } // проверим данные, указанные в заголовке блока err = p.CheckBlockHeader() if err != nil { return utils.ErrInfo(err) } utils.WriteSelectiveLog("DELETE FROM transactions WHERE used = 1") afect, err := p.ExecSqlGetAffect("DELETE FROM transactions WHERE used = 1") if err != nil { utils.WriteSelectiveLog(err) return utils.ErrInfo(err) } utils.WriteSelectiveLog("afect: " + utils.Int64ToStr(afect)) txCounter := make(map[int64]int64) p.fullTxBinaryData = p.BinaryData var txForRollbackTo []byte if len(p.BinaryData) > 0 { for { // обработка тр-ий может занять много времени, нужно отметиться p.UpdDaemonTime(p.GoroutineName) p.halfRollback = false log.Debug("&p.BinaryData", p.BinaryData) transactionSize := utils.DecodeLength(&p.BinaryData) if len(p.BinaryData) == 0 { return utils.ErrInfo(fmt.Errorf("empty BinaryData")) } // отчекрыжим одну транзакцию от списка транзакций //log.Debug("++p.BinaryData=%x\n", p.BinaryData) //log.Debug("transactionSize", transactionSize) transactionBinaryData := utils.BytesShift(&p.BinaryData, transactionSize) transactionBinaryDataFull := transactionBinaryData //ioutil.WriteFile("/tmp/dctx", transactionBinaryDataFull, 0644) //ioutil.WriteFile("/tmp/dctxhash", utils.Md5(transactionBinaryDataFull), 0644) // добавляем взятую тр-ию в набор тр-ий для RollbackTo, в котором пойдем в обратном порядке txForRollbackTo = append(txForRollbackTo, utils.EncodeLengthPlusData(transactionBinaryData)...) //log.Debug("transactionBinaryData: %x\n", transactionBinaryData) //log.Debug("txForRollbackTo: %x\n", txForRollbackTo) err = p.CheckLogTx(transactionBinaryDataFull) if err != nil { p.RollbackTo(txForRollbackTo, true, false) return utils.ErrInfo(err) } utils.WriteSelectiveLog("UPDATE transactions SET used=1 WHERE hex(hash) = " + string(utils.Md5(transactionBinaryDataFull))) affect, err := p.ExecSqlGetAffect("UPDATE transactions SET used=1 WHERE hex(hash) = ?", utils.Md5(transactionBinaryDataFull)) if err != nil { utils.WriteSelectiveLog(err) utils.WriteSelectiveLog("RollbackTo") p.RollbackTo(txForRollbackTo, true, false) return utils.ErrInfo(err) } utils.WriteSelectiveLog("affect: " + utils.Int64ToStr(affect)) //log.Debug("transactionBinaryData", transactionBinaryData) p.TxHash = utils.Md5(transactionBinaryData) log.Debug("p.TxHash %s", p.TxHash) p.TxSlice, err = p.ParseTransaction(&transactionBinaryData) log.Debug("p.TxSlice %v", p.TxSlice) if err != nil { p.RollbackTo(txForRollbackTo, true, false) return err } if p.BlockData.BlockId > 1 { var userId int64 // txSlice[3] могут подсунуть пустой if len(p.TxSlice) > 3 { if !utils.CheckInputData(p.TxSlice[3], "int64") { return utils.ErrInfo(fmt.Errorf("empty user_id")) } else { userId = utils.BytesToInt64(p.TxSlice[3]) } } else { return utils.ErrInfo(fmt.Errorf("empty user_id")) } // считаем по каждому юзеру, сколько в блоке от него транзакций txCounter[userId]++ // чтобы 1 юзер не смог прислать дос-блок размером в 10гб, который заполнит своими же транзакциями if txCounter[userId] > p.Variables.Int64["max_block_user_transactions"] { p.RollbackTo(txForRollbackTo, true, false) return utils.ErrInfo(fmt.Errorf("max_block_user_transactions")) } } // время в транзакции не может быть больше, чем на MAX_TX_FORW сек времени блока // и время в транзакции не может быть меньше времени блока -24ч. if utils.BytesToInt64(p.TxSlice[2])-consts.MAX_TX_FORW > p.BlockData.Time || utils.BytesToInt64(p.TxSlice[2]) < p.BlockData.Time-consts.MAX_TX_BACK { p.RollbackTo(txForRollbackTo, true, false) return utils.ErrInfo(fmt.Errorf("incorrect transaction time")) } // проверим, есть ли такой тип тр-ий _, ok := consts.TxTypes[utils.BytesToInt(p.TxSlice[1])] if !ok { return utils.ErrInfo(fmt.Errorf("nonexistent type")) } p.TxMap = map[string][]byte{} // для статы p.TxIds = append(p.TxIds, string(p.TxSlice[1])) MethodName := consts.TxTypes[utils.BytesToInt(p.TxSlice[1])] log.Debug("MethodName", MethodName+"Init") err_ := utils.CallMethod(p, MethodName+"Init") if _, ok := err_.(error); ok { log.Error("error: %v", err) return utils.ErrInfo(err_.(error)) } log.Debug("MethodName", MethodName+"Front") err_ = utils.CallMethod(p, MethodName+"Front") if _, ok := err_.(error); ok { log.Error("error: %v", err_) p.RollbackTo(txForRollbackTo, true, false) return utils.ErrInfo(err_.(error)) } log.Debug("MethodName", MethodName) err_ = utils.CallMethod(p, MethodName) if _, ok := err_.(error); ok { log.Error("error: %v", err) return utils.ErrInfo(err_.(error)) } // даем юзеру понять, что его тр-ия попала в блок p.ExecSql("UPDATE transactions_status SET block_id = ? WHERE hex(hash) = ?", p.BlockData.BlockId, utils.Md5(transactionBinaryDataFull)) // Тут было time(). А значит если бы в цепочке блоков были блоки в которых были бы одинаковые хэши тр-ий, то ParseDataFull вернул бы error err = p.InsertInLogTx(transactionBinaryDataFull, utils.BytesToInt64(p.TxMap["time"])) if err != nil { return utils.ErrInfo(err) } if len(p.BinaryData) == 0 { break } } } p.UpdBlockInfo() return nil }
func (c *Controller) CashRequestOut() (string, error) { txType := "CashRequestOut" txTypeId := utils.TypeInt(txType) timeNow := utils.Time() cashRequestsStatus := map[string]string{"my_pending": c.Lang["local_pending"], "pending": c.Lang["pending"], "approved": c.Lang["approved"], "rejected": c.Lang["rejected"]} jsonCurrencyWallets := "" var availableCurrency []int64 // список отравленных нами запросов myCashRequests, err := c.GetAll("SELECT * FROM "+c.MyPrefix+"my_cash_requests WHERE to_user_id != ?", -1, c.SessUserId) if err != nil { return "", utils.ErrInfo(err) } // получаем список кошельков, на которых есть FC rows, err := c.Query(c.FormatQuery("SELECT amount, currency_id, last_update FROM wallets WHERE user_id = ? AND currency_id < 1000"), c.SessUserId) if err != nil { return "", utils.ErrInfo(err) } defer rows.Close() for rows.Next() { var amount float64 var currency_id, last_update int64 err = rows.Scan(&amount, ¤cy_id, &last_update) if err != nil { return "", utils.ErrInfo(err) } if currency_id == 1 { continue } profit, err := c.CalcProfitGen(currency_id, amount, c.SessUserId, last_update, timeNow, "wallets") if err != nil { return "", utils.ErrInfo(err) } amount += profit jsonCurrencyWallets += fmt.Sprintf(`"%d":["%s","%v"],`, currency_id, c.CurrencyList[currency_id], amount) availableCurrency = append(availableCurrency, currency_id) } jsonCurrencyWallets = jsonCurrencyWallets[:len(jsonCurrencyWallets)-1] //jsonCurrencyWallets = "\"" log.Debug("jsonCurrencyWallets", jsonCurrencyWallets) code := utils.Md5(utils.RandSeq(50)) hashCode := utils.DSha256(code) TemplateStr, err := makeTemplate("cash_request_out", "cashRequestOut", &cashRequestOutPage{ Alert: c.Alert, Lang: c.Lang, CountSignArr: c.CountSignArr, ShowSignData: c.ShowSignData, UserId: c.SessUserId, TimeNow: timeNow, TxType: txType, TxTypeId: txTypeId, SignData: "", CurrencyList: c.CurrencyList, PaymentSystems: c.PaymentSystems, JsonCurrencyWallets: jsonCurrencyWallets, CashRequestsStatus: cashRequestsStatus, AvailableCurrency: availableCurrency, MinPromisedAmount: c.Variables.Int64["min_promised_amount"], MyCashRequests: myCashRequests, Code: string(code), HashCode: string(hashCode), MaxLength: 200}) if err != nil { return "", utils.ErrInfo(err) } return TemplateStr, nil }
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") } }
/* * Каждые 2 недели собираем инфу о голосах за % и создаем тр-ию, которая * попадет в DC сеть только, если мы окажемся генератором блока * */ func PctGenerator(chBreaker chan bool, chAnswer chan string) { defer func() { if r := recover(); r != nil { log.Error("daemon Recovered", r) panic(r) } }() const GoroutineName = "PctGenerator" d := new(daemon) d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName) if d.DCDB == nil { return } d.goRoutineName = GoroutineName d.chAnswer = chAnswer d.chBreaker = chBreaker if utils.Mobile() { d.sleepTime = 3600 } else { d.sleepTime = 60 } if !d.CheckInstall(chBreaker, chAnswer, GoroutineName) { return } d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName) if d.DCDB == nil { return } err = d.notMinerSetSleepTime(1800) if err != nil { log.Error("%v", err) return } BEGIN: for { log.Info(GoroutineName) MonitorDaemonCh <- []string{GoroutineName, utils.Int64ToStr(utils.Time())} // проверим, не нужно ли нам выйти из цикла if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) { break BEGIN } err, restart := d.dbLock() if restart { break BEGIN } if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } blockId, err := d.GetBlockId() if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } if blockId == 0 { if d.unlockPrintSleep(utils.ErrInfo("blockId == 0"), d.sleepTime) { break BEGIN } continue BEGIN } _, _, myMinerId, _, _, _, err := d.TestBlock() if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } // а майнер ли я ? if myMinerId == 0 { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } variables, err := d.GetAllVariables() curTime := utils.Time() // проверим, прошло ли 2 недели с момента последнего обновления pct pctTime, err := d.Single("SELECT max(time) FROM pct").Int64() if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } if curTime-pctTime > variables.Int64["new_pct_period"] { // берем все голоса miner_pct pctVotes := make(map[int64]map[string]map[string]int64) rows, err := d.Query("SELECT currency_id, pct, count(user_id) as votes FROM votes_miner_pct GROUP BY currency_id, pct ORDER BY currency_id, pct ASC") if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } for rows.Next() { var currency_id, votes int64 var pct string err = rows.Scan(¤cy_id, &pct, &votes) if err != nil { rows.Close() if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } log.Info("%v", "newpctcurrency_id", currency_id, "pct", pct, "votes", votes) if len(pctVotes[currency_id]) == 0 { pctVotes[currency_id] = make(map[string]map[string]int64) } if len(pctVotes[currency_id]["miner_pct"]) == 0 { pctVotes[currency_id]["miner_pct"] = make(map[string]int64) } pctVotes[currency_id]["miner_pct"][pct] = votes } rows.Close() // берем все голоса user_pct rows, err = d.Query("SELECT currency_id, pct, count(user_id) as votes FROM votes_user_pct GROUP BY currency_id, pct ORDER BY currency_id, pct ASC") if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } for rows.Next() { var currency_id, votes int64 var pct string err = rows.Scan(¤cy_id, &pct, &votes) if err != nil { rows.Close() if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } log.Info("%v", "currency_id", currency_id, "pct", pct, "votes", votes) if len(pctVotes[currency_id]) == 0 { pctVotes[currency_id] = make(map[string]map[string]int64) } if len(pctVotes[currency_id]["user_pct"]) == 0 { pctVotes[currency_id]["user_pct"] = make(map[string]int64) } pctVotes[currency_id]["user_pct"][pct] = votes } rows.Close() newPct := make(map[string]map[string]map[string]string) newPct["currency"] = make(map[string]map[string]string) var userMaxKey int64 PctArray := utils.GetPctArray() log.Info("%v", "pctVotes", pctVotes) for currencyId, data := range pctVotes { currencyIdStr := utils.Int64ToStr(currencyId) // определяем % для майнеров pctArr := utils.MakePctArray(data["miner_pct"]) log.Info("%v", "pctArrminer_pct", pctArr, currencyId) key := utils.GetMaxVote(pctArr, 0, 390, 100) log.Info("%v", "key", key) if len(newPct["currency"][currencyIdStr]) == 0 { newPct["currency"][currencyIdStr] = make(map[string]string) } newPct["currency"][currencyIdStr]["miner_pct"] = utils.GetPctValue(key) // определяем % для юзеров pctArr = utils.MakePctArray(data["user_pct"]) log.Info("%v", "pctArruser_pct", pctArr, currencyId) log.Info("%v", "newPct", newPct) pctY := utils.ArraySearch(newPct["currency"][currencyIdStr]["miner_pct"], PctArray) log.Info("%v", "newPct[currency][currencyIdStr][miner_pct]", newPct["currency"][currencyIdStr]["miner_pct"]) log.Info("%v", "PctArray", PctArray) log.Info("%v", "miner_pct $pct_y=", pctY) maxUserPctY := utils.Round(utils.StrToFloat64(pctY)/2, 2) userMaxKey = utils.FindUserPct(int(maxUserPctY)) log.Info("%v", "maxUserPctY", maxUserPctY, "userMaxKey", userMaxKey, "currencyIdStr", currencyIdStr) // отрезаем лишнее, т.к. поиск идет ровно до макимального возможного, т.е. до miner_pct/2 pctArr = utils.DelUserPct(pctArr, userMaxKey) log.Info("%v", "pctArr", pctArr) key = utils.GetMaxVote(pctArr, 0, userMaxKey, 100) log.Info("%v", "data[user_pct]", data["user_pct"]) log.Info("%v", "pctArr", pctArr) log.Info("%v", "userMaxKey", userMaxKey) log.Info("%v", "key", key) newPct["currency"][currencyIdStr]["user_pct"] = utils.GetPctValue(key) log.Info("%v", "user_pct", newPct["currency"][currencyIdStr]["user_pct"]) } newPct_ := new(newPctType) newPct_.Currency = make(map[string]map[string]string) newPct_.Currency = newPct["currency"] newPct_.Referral = make(map[string]int64) refLevels := []string{"first", "second", "third"} for i := 0; i < len(refLevels); i++ { level := refLevels[i] var votesReferral []map[int64]int64 // берем все голоса rows, err := d.Query("SELECT " + level + ", count(user_id) as votes FROM votes_referral GROUP BY " + level + " ORDER BY " + level + " ASC ") if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } for rows.Next() { var level_, votes int64 err = rows.Scan(&level_, &votes) if err != nil { rows.Close() if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } votesReferral = append(votesReferral, map[int64]int64{level_: votes}) } rows.Close() newPct_.Referral[level] = (utils.GetMaxVote(votesReferral, 0, 30, 10)) } jsonData, err := json.Marshal(newPct_) if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } _, myUserId, _, _, _, _, err := d.TestBlock() forSign := fmt.Sprintf("%v,%v,%v,%s", utils.TypeInt("NewPct"), curTime, myUserId, jsonData) log.Debug("forSign = %v", forSign) binSign, err := d.GetBinSign(forSign, myUserId) log.Debug("binSign = %x", binSign) if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } data := utils.DecToBin(utils.TypeInt("NewPct"), 1) data = append(data, utils.DecToBin(curTime, 4)...) data = append(data, utils.EncodeLengthPlusData(utils.Int64ToByte(myUserId))...) data = append(data, utils.EncodeLengthPlusData(jsonData)...) data = append(data, utils.EncodeLengthPlusData([]byte(binSign))...) err = d.InsertReplaceTxInQueue(data) if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } // и не закрывая main_lock переводим нашу тр-ию в verified=1, откатив все несовместимые тр-ии // таким образом у нас будут в блоке только актуальные голоса. // а если придет другой блок и станет verified=0, то эта тр-ия просто удалится. p := new(dcparser.Parser) p.DCDB = d.DCDB err = p.TxParser(utils.HexToBin(utils.Md5(data)), data, true) if err != nil { 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) }
/** * Занесение данных из блока в БД * используется только в testblock_is_ready */ func (p *Parser) ParseDataFront() error { p.TxIds = []string{} p.dataPre() if p.dataType == 0 { // инфа о предыдущем блоке (т.е. последнем занесенном) err := p.GetInfoBlock() if err != nil { return p.ErrInfo(err) } utils.WriteSelectiveLog("DELETE FROM transactions WHERE used=1") affect, err := p.ExecSqlGetAffect("DELETE FROM transactions WHERE used = 1") if err != nil { utils.WriteSelectiveLog(err) return p.ErrInfo(err) } utils.WriteSelectiveLog("affect: " + utils.Int64ToStr(affect)) // разбор блока err = p.ParseBlock() if err != nil { return utils.ErrInfo(err) } p.Variables, err = p.GetAllVariables() if err != nil { return utils.ErrInfo(err) } //меркель рут нужен для updblockinfo() p.MrklRoot, err = utils.GetMrklroot(p.BinaryData, p.Variables, false) if err != nil { return utils.ErrInfo(err) } if len(p.BinaryData) > 0 { for { transactionSize := utils.DecodeLength(&p.BinaryData) if len(p.BinaryData) == 0 { return utils.ErrInfo(fmt.Errorf("empty BinaryData")) } // отчекрыжим одну транзакцию от списка транзакций transactionBinaryData := utils.BytesShift(&p.BinaryData, transactionSize) transactionBinaryDataFull := transactionBinaryData p.TxHash = utils.Md5(transactionBinaryData) log.Debug("p.TxHash", p.TxHash) p.TxSlice, err = p.ParseTransaction(&transactionBinaryData) log.Debug("p.TxSlice", p.TxSlice) if err != nil { return utils.ErrInfo(err) } // txSlice[3] могут подсунуть пустой if len(p.TxSlice) > 3 { if !utils.CheckInputData(p.TxSlice[3], "int64") { return utils.ErrInfo(fmt.Errorf("empty user_id")) } } else { return utils.ErrInfo(fmt.Errorf("empty user_id")) } // проверим, есть ли такой тип тр-ий _, ok := consts.TxTypes[utils.BytesToInt(p.TxSlice[1])] if !ok { return utils.ErrInfo(fmt.Errorf("nonexistent type")) } p.TxMap = map[string][]byte{} // для статы p.TxIds = append(p.TxIds, string(p.TxSlice[1])) MethodName := consts.TxTypes[utils.BytesToInt(p.TxSlice[1])] log.Debug("MethodName", MethodName+"Init") err_ := utils.CallMethod(p, MethodName+"Init") if _, ok := err_.(error); ok { log.Debug("error: %v", err) return utils.ErrInfo(err_.(error)) } log.Debug("MethodName", MethodName) err_ = utils.CallMethod(p, MethodName) if _, ok := err_.(error); ok { log.Debug("error: %v", err) return utils.ErrInfo(err_.(error)) } utils.WriteSelectiveLog("UPDATE transactions SET used=1 WHERE hex(hash) = " + string(utils.Md5(transactionBinaryDataFull))) affect, err := p.ExecSqlGetAffect("UPDATE transactions SET used=1 WHERE hex(hash) = ?", utils.Md5(transactionBinaryDataFull)) if err != nil { utils.WriteSelectiveLog(err) return utils.ErrInfo(err) } utils.WriteSelectiveLog("affect: " + utils.Int64ToStr(affect)) // даем юзеру понять, что его тр-ия попала в блок err = p.ExecSql("UPDATE transactions_status SET block_id = ? WHERE hex(hash) = ?", p.BlockData.BlockId, utils.Md5(transactionBinaryDataFull)) if err != nil { return utils.ErrInfo(err) } if len(p.BinaryData) == 0 { break } } } p.UpdBlockInfo() p.InsertIntoBlockchain() } else { return utils.ErrInfo(fmt.Errorf("incorrect type")) } return nil }
func (c *Controller) Check_sign() (string, error) { var checkError bool c.r.ParseForm() n := []byte(c.r.FormValue("n")) e := []byte(c.r.FormValue("e")) sign := []byte(c.r.FormValue("sign")) setupPassword := c.r.FormValue("setup_password") private_key := c.r.FormValue("private_key") if !utils.CheckInputData(n, "hex") { return `{"result":"incorrect n"}`, nil } if !utils.CheckInputData(e, "hex") { return `{"result":"incorrect e"}`, nil } if !utils.CheckInputData(string(sign), "hex_sign") { return `{"result":"incorrect sign"}`, nil } allTables, err := c.DCDB.GetAllTables() if err != nil { return "{\"result\":0}", err } var hash []byte log.Debug("configIni[sign_hash] %s", configIni["sign_hash"]) log.Debug("c.r.RemoteAddr %s", c.r.RemoteAddr) log.Debug("c.r.Header.Get(User-Agent) %s", c.r.Header.Get("User-Agent")) RemoteAddr := utils.RemoteAddrFix(c.r.RemoteAddr) re := regexp.MustCompile(`(.*?):[0-9]+$`) match := re.FindStringSubmatch(RemoteAddr) if len(match) != 0 { RemoteAddr = match[1] } log.Debug("RemoteAddr %s", RemoteAddr) hash = utils.Md5(c.r.Header.Get("User-Agent") + RemoteAddr) log.Debug("hash %s", hash) if len(c.CommunityUsers) > 0 { // в цикле проверяем, кому подойдет присланная подпись for _, userId := range c.CommunityUsers { myPrefix := utils.Int64ToStr(userId) + "_" if !utils.InSliceString(myPrefix+"my_keys", allTables) { continue } // получим открытый ключ юзера publicKey, err := c.DCDB.GetMyPublicKey(myPrefix) if err != nil { return "{\"result\":0}", err } // получим данные для подписи forSign, err := c.DCDB.GetDataAuthorization(hash) log.Debug("publicKey: %x\n", publicKey) log.Debug("myPrefix: ", myPrefix) log.Debug("sign: %s\n", sign) log.Debug("hash: %s\n", hash) log.Debug("forSign: ", forSign) // проверим подпись resultCheckSign, err := utils.CheckSign([][]byte{publicKey}, forSign, utils.HexToBin(sign), true) if err != nil { continue } // если подпись верная, значит мы нашли юзера, который эту подпись смог сделать if resultCheckSign { myUserId := userId // убираем ограниченный режим c.sess.Delete("restricted") c.sess.Set("user_id", myUserId) log.Debug("c.sess.Set(user_id) %d", myUserId) public_key, err := c.DCDB.GetUserPublicKey(myUserId) if err != nil { return "{\"result\":0}", err } // паблик кей в сессии нужен чтобы выбрасывать юзера, если ключ изменился c.sess.Set("public_key", string(utils.BinToHex([]byte(public_key)))) log.Debug("string(utils.BinToHex([]byte(public_key))) %s", string(utils.BinToHex([]byte(public_key)))) adminUSerID, err := c.DCDB.GetAdminUserId() if err != nil { return "{\"result\":0}", err } if adminUSerID == myUserId { c.sess.Set("admin", 1) } return "{\"result\":1}", nil } } log.Debug("restricted test") // если дошли досюда, значит ни один ключ не подошел и даем возможность войти в ограниченном режиме publicKey := utils.MakeAsn1(n, e) userId_, err := c.DCDB.GetUserIdByPublicKey(publicKey) userId := utils.StrToInt64(userId_) if err != nil { return "{\"result\":0}", err } log.Debug("userId:", userId) // юзер с таким ключем есть в БД if userId > 0 { // получим данные для подписи forSign, err := c.DCDB.GetDataAuthorization(hash) log.Debug("forSign", forSign) log.Debug("publicKey %x\n", utils.HexToBin(publicKey)) log.Debug("sign_", string(sign)) // проверим подпись resultCheckSign, err := utils.CheckSign([][]byte{utils.HexToBin(publicKey)}, forSign, utils.HexToBin(sign), true) if err != nil { return "{\"result\":0}", err } if resultCheckSign { // если юзер смог подписать наш хэш, значит у него актуальный праймари ключ c.sess.Set("user_id", userId) log.Debug("c.sess.Set(user_id) %d", userId) // паблик кей в сессии нужен чтобы выбрасывать юзера, если ключ изменился c.sess.Set("public_key", string(publicKey)) // возможно в табле my_keys старые данные, но если эта табла есть, то нужно добавить туда ключ if utils.InSliceString(utils.Int64ToStr(userId)+"_my_keys", allTables) { curBlockId, err := c.DCDB.GetBlockId() if err != nil { return "{\"result\":0}", err } err = c.DCDB.InsertIntoMyKey(utils.Int64ToStr(userId)+"_", publicKey, utils.Int64ToStr(curBlockId)) if err != nil { return "{\"result\":0}", err } c.sess.Delete("restricted") } else { c.sess.Set("restricted", int64(1)) log.Debug("c.sess.Set(restricted) 1") } return "{\"result\":1}", nil } else { return "{\"result\":0}", nil } } } else { // получим открытый ключ юзера publicKey, err := c.DCDB.GetMyPublicKey("") if err != nil { return "{\"result\":0}", err } // Если ключ еще не успели установить if len(publicKey) == 0 { // пока не собрана цепочка блоков не даем ввести ключ infoBlock, err := c.DCDB.GetInfoBlock() if err != nil { return "{\"result\":0}", err } // если последний блок не старше 2-х часов wTime := int64(2) if c.ConfigIni["test_mode"] == "1" { wTime = 2 * 365 * 24 } log.Debug("%v/%v/%v", time.Now().Unix(), utils.StrToInt64(infoBlock["time"]), wTime) if (time.Now().Unix() - utils.StrToInt64(infoBlock["time"])) < 3600*wTime { // проверим, верный ли установочный пароль, если он, конечно, есть setupPassword_, err := c.Single("SELECT setup_password FROM config").String() if err != nil { return "{\"result\":0}", err } if len(setupPassword_) > 0 && setupPassword_ != string(utils.DSha256(setupPassword)) { log.Debug(setupPassword_, string(utils.DSha256(setupPassword)), setupPassword) return "{\"result\":0}", nil } publicKey := utils.MakeAsn1(n, e) log.Debug("new key", string(publicKey)) userId, err := c.GetUserIdByPublicKey(publicKey) if err != nil { return "{\"result\":0}", err } // получим данные для подписи forSign, err := c.DCDB.GetDataAuthorization(hash) if err != nil { return "{\"result\":0}", err } log.Debug("forSign", forSign) log.Debug("publicKey %x\n", utils.HexToBin(publicKey)) log.Debug("sign_", string(sign)) // проверим подпись resultCheckSign, err := utils.CheckSign([][]byte{utils.HexToBin(publicKey)}, forSign, utils.HexToBin(sign), true) if err != nil { return "{\"result\":0}", err } if !resultCheckSign { return "{\"result\":0}", nil } if len(userId) > 0 { err := c.InsertIntoMyKey("", publicKey, "0") if err != nil { return "{\"result\":0}", err } minerId, err := c.GetMinerId(utils.StrToInt64(userId)) if err != nil { return "{\"result\":0}", err } //myUserId, err := c.GetMyUserId("") //if myUserId > 0 { if minerId > 0 { err = c.ExecSql("UPDATE my_table SET user_id = ?, miner_id = ?, status = 'miner'", userId, minerId) if err != nil { return "{\"result\":0}", err } } else { err = c.ExecSql("UPDATE my_table SET user_id = ?, status = 'user'", userId) if err != nil { return "{\"result\":0}", err } } //} else { // c.ExecSql("INSERT INTO my_table (user_id, status) VALUES (?, 'user')", userId) //} // возможно юзер хочет сохранить свой ключ if len(private_key) > 0 { c.ExecSql("UPDATE my_keys SET private_key = ? WHERE block_id = (SELECT max(block_id) FROM my_keys)", private_key) } } else { checkError = true } } else { checkError = true } } else { log.Debug("RemoteAddr %s", RemoteAddr) hash = utils.Md5(c.r.Header.Get("User-Agent") + RemoteAddr) log.Debug("hash %s", hash) // получим данные для подписи forSign, err := c.DCDB.GetDataAuthorization(hash) log.Debug("forSign", forSign) log.Debug("publicKey %x\n", string(publicKey)) log.Debug("sign_", string(sign)) // проверим подпись resultCheckSign, err := utils.CheckSign([][]byte{publicKey}, forSign, utils.HexToBin(sign), true) if err != nil { return "{\"result\":0}", err } if !resultCheckSign { return "{\"result\":0}", nil } } if checkError { return "{\"result\":0}", nil } else { myUserId, err := c.DCDB.GetMyUserId("") if myUserId == 0 { myUserId = -1 } if err != nil { return "{\"result\":0}", err } c.sess.Delete("restricted") c.sess.Set("user_id", myUserId) // если уже пришел блок, в котором зареган ключ юзера if myUserId != -1 { public_key, err := c.DCDB.GetUserPublicKey(myUserId) if err != nil { return "{\"result\":0}", err } // паблик кей в сессии нужен чтобы выбрасывать юзера, если ключ изменился c.sess.Set("public_key", string(utils.BinToHex(public_key))) // возможно юзер хочет сохранить свой ключ if len(private_key) > 0 { c.ExecSql("UPDATE my_keys SET private_key = ? WHERE block_id = (SELECT max(block_id) FROM my_keys)", private_key) } AdminUserId, err := c.DCDB.GetAdminUserId() if err != nil { return "{\"result\":0}", err } if AdminUserId == myUserId { c.sess.Set("admin", int64(1)) } return "{\"result\":1}", nil } } } return "{\"result\":0}", nil }
/** Обработка данных (блоков или транзакций), пришедших с гейта. Только проверка. */ func (p *Parser) ParseDataGate(onlyTx bool) error { var err error p.dataPre() p.TxIds = []string{} p.Variables, err = p.GetAllVariables() if err != nil { return utils.ErrInfo(err) } transactionBinaryData := p.BinaryData var transactionBinaryDataFull []byte // если это транзакции (type>0), а не блок (type==0) if p.dataType > 0 { // проверим, есть ли такой тип тр-ий if len(consts.TxTypes[p.dataType]) == 0 { return p.ErrInfo("Incorrect tx type " + utils.IntToStr(p.dataType)) } log.Debug("p.dataType %v", p.dataType) transactionBinaryData = append(utils.DecToBin(int64(p.dataType), 1), transactionBinaryData...) transactionBinaryDataFull = transactionBinaryData // нет ли хэша этой тр-ии у нас в БД? err = p.CheckLogTx(transactionBinaryDataFull) if err != nil { return p.ErrInfo(err) } p.TxHash = utils.Md5(transactionBinaryData) // преобразуем бинарные данные транзакции в массив p.TxSlice, err = p.ParseTransaction(&transactionBinaryData) if err != nil { return p.ErrInfo(err) } log.Debug("p.TxSlice", p.TxSlice) if len(p.TxSlice) < 3 { return p.ErrInfo(errors.New("len(p.TxSlice) < 3")) } // время транзакции может быть немного больше, чем время на ноде. // у нода может быть просто не настроено время. // время транзакции используется только для борьбы с атаками вчерашними транзакциями. // А т.к. мы храним хэши в log_transaction за 36 часов, то боятся нечего. curTime := utils.Time() if utils.BytesToInt64(p.TxSlice[2])-consts.MAX_TX_FORW > curTime || utils.BytesToInt64(p.TxSlice[2]) < curTime-consts.MAX_TX_BACK { return p.ErrInfo(errors.New("incorrect tx time")) } // $this->transaction_array[3] могут подсунуть пустой if !utils.CheckInputData(p.TxSlice[3], "bigint") { return p.ErrInfo(errors.New("incorrect user id")) } } // если это блок if p.dataType == 0 { txCounter := make(map[int64]int64) // если есть $only_tx=true, то значит идет восстановление уже проверенного блока и заголовок не требуется if !onlyTx { err = p.ParseBlock() if err != nil { return p.ErrInfo(err) } // проверим данные, указанные в заголовке блока err = p.CheckBlockHeader() if err != nil { return p.ErrInfo(err) } } log.Debug("onlyTx", onlyTx) // если в ходе проверки тр-ий возникает ошибка, то вызываем откатчик всех занесенных тр-ий. Эта переменная для него p.fullTxBinaryData = p.BinaryData var txForRollbackTo []byte if len(p.BinaryData) > 0 { for { transactionSize := utils.DecodeLength(&p.BinaryData) if len(p.BinaryData) == 0 { return utils.ErrInfo(fmt.Errorf("empty BinaryData")) } // отчекрыжим одну транзакцию от списка транзакций transactionBinaryData := utils.BytesShift(&p.BinaryData, transactionSize) transactionBinaryDataFull = transactionBinaryData // добавляем взятую тр-ию в набор тр-ий для RollbackTo, в котором пойдем в обратном порядке txForRollbackTo = append(txForRollbackTo, utils.EncodeLengthPlusData(transactionBinaryData)...) // нет ли хэша этой тр-ии у нас в БД? err = p.CheckLogTx(transactionBinaryDataFull) if err != nil { p.RollbackTo(txForRollbackTo, true, false) return p.ErrInfo(err) } p.TxHash = utils.Md5(transactionBinaryData) p.TxSlice, err = p.ParseTransaction(&transactionBinaryData) log.Debug("p.TxSlice %s", p.TxSlice) if err != nil { p.RollbackTo(txForRollbackTo, true, false) return p.ErrInfo(err) } var userId int64 // txSlice[3] могут подсунуть пустой if len(p.TxSlice) > 3 { if !utils.CheckInputData(p.TxSlice[3], "int64") { return utils.ErrInfo(fmt.Errorf("empty user_id")) } else { userId = utils.BytesToInt64(p.TxSlice[3]) } } else { return utils.ErrInfo(fmt.Errorf("empty user_id")) } // считаем по каждому юзеру, сколько в блоке от него транзакций txCounter[userId]++ // чтобы 1 юзер не смог прислать дос-блок размером в 10гб, который заполнит своими же транзакциями if txCounter[userId] > p.Variables.Int64["max_block_user_transactions"] { p.RollbackTo(txForRollbackTo, true, false) return utils.ErrInfo(fmt.Errorf("max_block_user_transactions")) } // проверим, есть ли такой тип тр-ий _, ok := consts.TxTypes[utils.BytesToInt(p.TxSlice[1])] if !ok { return utils.ErrInfo(fmt.Errorf("nonexistent type")) } p.TxMap = map[string][]byte{} // для статы p.TxIds = append(p.TxIds, string(p.TxSlice[1])) MethodName := consts.TxTypes[utils.BytesToInt(p.TxSlice[1])] log.Debug("MethodName", MethodName+"Init") err_ := utils.CallMethod(p, MethodName+"Init") if _, ok := err_.(error); ok { log.Debug("error: %v", err) p.RollbackTo(txForRollbackTo, true, true) return utils.ErrInfo(err_.(error)) } log.Debug("MethodName", MethodName+"Front") err_ = utils.CallMethod(p, MethodName+"Front") if _, ok := err_.(error); ok { log.Debug("error: %v", err) p.RollbackTo(txForRollbackTo, true, true) return utils.ErrInfo(err_.(error)) } // пишем хэш тр-ии в лог err = p.InsertInLogTx(transactionBinaryDataFull, utils.BytesToInt64(p.TxMap["time"])) if err != nil { return utils.ErrInfo(err) } if len(p.BinaryData) == 0 { break } } } } else { // Оперативные транзакции MethodName := consts.TxTypes[p.dataType] log.Debug("MethodName", MethodName+"Init") err_ := utils.CallMethod(p, MethodName+"Init") if _, ok := err_.(error); ok { return utils.ErrInfo(err_.(error)) } log.Debug("MethodName", MethodName+"Front") err_ = utils.CallMethod(p, MethodName+"Front") if _, ok := err_.(error); ok { return utils.ErrInfo(err_.(error)) } // пишем хэш тр-ии в лог err = p.InsertInLogTx(transactionBinaryDataFull, utils.BytesToInt64(p.TxMap["time"])) if err != nil { return utils.ErrInfo(err) } } return nil }
func (c *Controller) DcoinKey() (string, error) { var err error c.r.ParseForm() // на IOS/Android запрос ключа идет без сессии из objective C (UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://127.0.0.1:8089/ajax?controllerName=dcoinKey&ios=1"]]];) local := false // чтобы по локалке никто не украл приватный ключ if ok, _ := regexp.MatchString(`^(\:\:)|(127\.0\.0\.1)(:[0-9]+)?$`, c.r.RemoteAddr); ok { local = true } if utils.Mobile() && c.SessUserId == 0 && !local { return "", utils.ErrInfo(errors.New("Not local request from " + c.r.RemoteAddr)) } privKey := "" if len(c.r.FormValue("first")) > 0 { privKey, err = c.Single(`SELECT private_key FROM ` + c.MyPrefix + `my_keys WHERE status='my_pending'`).String() if err != nil { return "", utils.ErrInfo(err) } } else { privKey, _ = utils.GenKeys() } paramNoPass := utils.ParamType{X: 176, Y: 100, Width: 100, Bg_path: "static/img/k_bg.png"} paramPass := utils.ParamType{X: 167, Y: 93, Width: 118, Bg_path: "static/img/k_bg_pass.png"} var param utils.ParamType var privateKey string if len(c.r.FormValue("password")) > 0 { privateKey_, err := utils.Encrypt(utils.Md5(c.r.FormValue("password")), []byte(privKey)) privateKey = base64.StdEncoding.EncodeToString(privateKey_) if err != nil { return "", utils.ErrInfo(err) } param = paramPass } else { privateKey = strings.Replace(privKey, "-----BEGIN RSA PRIVATE KEY-----", "", -1) privateKey = strings.Replace(privateKey, "-----END RSA PRIVATE KEY-----", "", -1) param = paramNoPass } ios := false if ok, _ := regexp.MatchString("(iPod|iPhone|iPad)", c.r.UserAgent()); ok { ios = true } if len(c.r.FormValue("ios")) > 0 { ios = true } if ios || utils.Android() { buffer, err := utils.KeyToImg(privateKey, "", c.SessUserId, c.TimeFormat, param) if err != nil { return "", utils.ErrInfo(err) } c.w.Header().Set("Content-Type", "image/png") c.w.Header().Set("Content-Length", utils.IntToStr(len(buffer.Bytes()))) c.w.Header().Set("Content-Disposition", `attachment; filename="Dcoin-private-key-`+utils.Int64ToStr(c.SessUserId)+`.png"`) if _, err := c.w.Write(buffer.Bytes()); err != nil { return "", utils.ErrInfo(errors.New("unable to write image")) } } else { c.w.Header().Set("Content-Type", "text/plain") c.w.Header().Set("Content-Length", utils.IntToStr(len(privateKey))) c.w.Header().Set("Content-Disposition", `attachment; filename="Dcoin-private-key-`+utils.Int64ToStr(c.SessUserId)+`.txt"`) if _, err := c.w.Write([]byte(privateKey)); err != nil { return "", utils.ErrInfo(errors.New("unable to write text")) } } return "", nil }