func (p *Parser) RepaymentCreditRollback() error { creditData, err := p.OneRow("SELECT to_user_id, currency_id FROM credits WHERE id = ?", p.TxMaps.Int64["credit_id"]).Int64() if err != nil { return p.ErrInfo(err) } err = p.generalRollback("wallets", p.TxUserID, "AND currency_id = "+utils.Int64ToStr(creditData["currency_id"]), false) if err != nil { return p.ErrInfo(err) } err = p.generalRollback("wallets", creditData["to_user_id"], "AND currency_id = "+utils.Int64ToStr(creditData["currency_id"]), false) if err != nil { return p.ErrInfo(err) } err = p.selectiveRollback([]string{"amount", "tx_hash", "tx_block_id"}, "credits", "id="+utils.Int64ToStr(p.TxMaps.Int64["credit_id"]), false) if err != nil { return p.ErrInfo(err) } // возможно нужно обновить таблицу points_status err = p.pointsUpdateMain(creditData["to_user_id"]) if err != nil { return p.ErrInfo(err) } // возможно нужно обновить таблицу points_status err = p.pointsUpdateMain(p.TxUserID) if err != nil { return p.ErrInfo(err) } return nil }
func (p *Parser) NewPromisedAmount() error { addSqlNames := "" addSqlValues := "" if p.BlockData.BlockId > 27134 { paymentSystemsIds := strings.Split(string(p.TxMaps.String["payment_systems_ids"]), ",") for i, v := range paymentSystemsIds { addSqlNames += fmt.Sprintf("ps%d,", (i + 1)) addSqlValues += fmt.Sprintf("%s,", v) } } //добавляем promised_amount в БД err := p.ExecSql(` INSERT INTO promised_amount ( user_id, amount, currency_id, ` + addSqlNames + ` video_type, video_url_id, votes_start_time ) VALUES ( ` + utils.Int64ToStr(p.TxMaps.Int64["user_id"]) + `, ` + utils.Float64ToStr(p.TxMaps.Money["amount"]) + `, ` + utils.Int64ToStr(p.TxMaps.Int64["currency_id"]) + `, ` + addSqlValues + ` '` + p.TxMaps.String["video_type"] + `', '` + p.TxMaps.String["video_url_id"] + `', ` + utils.Int64ToStr(p.BlockData.Time) + ` )`) if err != nil { return p.ErrInfo(err) } // проверим, не наш ли это user_id myUserId, myBlockId, myPrefix, _, err := p.GetMyUserId(p.TxMaps.Int64["user_id"]) if err != nil { return err } if p.TxUserID == myUserId && myBlockId <= p.BlockData.BlockId { // Удалим, т.к. попало в блок err = p.ExecSql("DELETE FROM "+myPrefix+"my_promised_amount WHERE amount = ? AND currency_id = ?", p.TxMaps.Money["amount"], p.TxMaps.Int64["currency_id"]) if err != nil { return p.ErrInfo(err) } } return nil }
func (c *Controller) Chat() (string, error) { myChatName := utils.Int64ToStr(c.SessUserId) // возможно у отпарвителя есть ник name, err := c.Single(`SELECT name FROM users WHERE user_id = ?`, c.SessUserId).String() if err != nil { return "", utils.ErrInfo(err) } if len(name) > 0 { myChatName = name } TemplateStr, err := makeTemplate("chat", "chat", &chatPage{ Community: c.Community, CountSignArr: c.CountSignArr, CountSign: c.CountSign, Lang: c.Lang, ShowSignData: c.ShowSignData, SignData: "", MyChatName: myChatName, UserId: c.SessUserId, IOS: utils.IOS(), Mobile: utils.Mobile()}) if err != nil { return "", utils.ErrInfo(err) } return TemplateStr, nil }
func makeVcomplex(json_data []byte) (*vComplex, error) { vComplex := new(vComplex) err := json.Unmarshal(json_data, &vComplex) if err != nil { vComplex_ := new(vComplex_) err = json.Unmarshal(json_data, &vComplex_) if err != nil { vComplex__ := new(vComplex__) err = json.Unmarshal(json_data, &vComplex__) if err != nil { return vComplex, err } vComplex.Referral = vComplex__.Referral vComplex.Currency = vComplex__.Currency vComplex.Admin = utils.StrToInt64(vComplex__.Admin) } else { vComplex.Referral = make(map[string]string) for k, v := range vComplex_.Referral { vComplex.Referral[k] = utils.Int64ToStr(v) } vComplex.Currency = vComplex_.Currency vComplex.Admin = vComplex_.Admin } } return vComplex, nil }
func (a *AvailablekeyStruct) checkAvailableKey(key string) (int64, string, error) { publicKeyAsn, err := utils.GetPublicFromPrivate(key) if err != nil { log.Debug("%v", err) return 0, "", utils.ErrInfo(err) } log.Debug("publicKeyAsn: %s", publicKeyAsn) userId, err := a.Single("SELECT user_id FROM users WHERE hex(public_key_0) = ?", publicKeyAsn).Int64() if err != nil { return 0, "", utils.ErrInfo(err) } log.Debug("userId: %s", userId) if userId == 0 { return 0, "", errors.New("null userId") } allTables, err := a.GetAllTables() if err != nil { return 0, "", utils.ErrInfo(err) } // может другой юзер уже начал смену ключа. актуально для пула if utils.InSliceString(utils.Int64ToStr(userId)+"_my_table", allTables) { return 0, "", errors.New("exists _my_table") } return userId, string(publicKeyAsn), nil }
func (c *Controller) NewPhoto() (string, error) { c.r.ParseForm() userId := int64(utils.StrToFloat64(c.r.FormValue("user_id"))) data, err := c.OneRow("SELECT photo_block_id, photo_max_miner_id, miners_keepers FROM miners_data WHERE user_id = ?", userId).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) // берем 1 случайный из 10-и ID майнеров k := utils.RandInt(0, len(minersIds)) minerId := minersIds[k] host, err := c.Single("SELECT http_host FROM miners_data WHERE miner_id = ?", minerId).String() if err != nil { return "", utils.ErrInfo(err) } result, err := json.Marshal(map[string]string{"face": host + "public/face_" + utils.Int64ToStr(userId) + ".jpg", "profile": host + "public/profile_" + utils.Int64ToStr(userId) + ".jpg"}) if err != nil { return "", utils.ErrInfo(err) } return string(result), nil }
func (c *Controller) CfCatalog() (string, error) { var err error log.Debug("CfCatalog") categoryId := utils.Int64ToStr(int64(utils.StrToFloat64(c.Parameters["category_id"]))) log.Debug("categoryId", categoryId) var curCategory string addSql := "" if categoryId != "0" { addSql = `AND category_id = ` + categoryId curCategory = c.Lang["cf_category_"+categoryId] } cfUrl := "" projects := make(map[string]map[string]string) cfProjects, err := c.GetAll(` SELECT cf_projects.id, lang_id, blurb_img, country, city, currency_id, end_time, amount FROM cf_projects LEFT JOIN cf_projects_data ON cf_projects_data.project_id = cf_projects.id WHERE del_block_id = 0 AND end_time > ? AND lang_id = ? `+addSql+` ORDER BY funders DESC LIMIT 100 `, 100, utils.Time(), c.LangInt) if err != nil { return "", utils.ErrInfo(err) } for _, data := range cfProjects { CfProjectData, err := c.GetCfProjectData(utils.StrToInt64(data["id"]), utils.StrToInt64(data["end_time"]), c.LangInt, utils.StrToFloat64(data["amount"]), cfUrl) if err != nil { return "", utils.ErrInfo(err) } for k, v := range CfProjectData { data[k] = v } projects[data["id"]] = data } cfCategory := utils.MakeCfCategories(c.Lang) TemplateStr, err := makeTemplate("cf_catalog", "cfCatalog", &cfCatalogPage{ Lang: c.Lang, CfCategory: cfCategory, CurrencyList: c.CurrencyList, CurCategory: curCategory, Projects: projects, UserId: c.SessUserId, CategoryId: categoryId, CfUrl: cfUrl}) if err != nil { return "", utils.ErrInfo(err) } return TemplateStr, nil }
func (c *Controller) Upgrade1() (string, error) { log.Debug("Upgrade1") userFace := "" /*userProfile := "" path := "public/"+utils.Int64ToStr(c.SessUserId)+"_user_profile.jpg" if _, err := os.Stat(path); err == nil { userProfile = path }*/ path := *utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_face.jpg" if _, err := os.Stat(path); err == nil { userFace = "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_face.jpg" } step := "1" nextStep := "2" photoType := "face" photo := userFace saveAndGotoStep := strings.Replace(c.Lang["save_and_goto_step"], "[num]", "3", -1) upgradeMenu := utils.MakeUpgradeMenu(1) TemplateStr, err := makeTemplate("upgrade_1_and_2", "upgrade1And2", &upgrade1Page{ Alert: c.Alert, Lang: c.Lang, CountSignArr: c.CountSignArr, ShowSignData: c.ShowSignData, SaveAndGotoStep: saveAndGotoStep, UpgradeMenu: upgradeMenu, UserId: c.SessUserId, PhotoType: photoType, Photo: photo, Step: step, NextStep: nextStep, IOS: utils.IOS(), Mobile: utils.Mobile()}) if err != nil { return "", utils.ErrInfo(err) } return TemplateStr, nil }
func (p *Parser) VotesPromisedAmountRollback() error { // вычитаем баллы p.pointsRollback(p.Variables.Int64["promised_amount_points"]) // удаляем логирование, чтобы юзер {$this->tx_data['user_id']} не смог повторно проголосовать err := p.ExecSql("DELETE FROM log_votes WHERE user_id = ? AND voting_id = ? AND type = 'promised_amount'", p.TxMaps.Int64["user_id"], p.TxMaps.Int64["promised_amount_id"]) if err != nil { return p.ErrInfo(err) } // обновляем голоса err = p.ExecSql("UPDATE promised_amount SET votes_"+utils.Int64ToStr(p.TxMaps.Int64["result"])+" = votes_"+utils.Int64ToStr(p.TxMaps.Int64["result"])+" - 1 WHERE id = ?", p.TxMaps.Int64["promised_amount_id"]) if err != nil { return p.ErrInfo(err) } data, err := p.OneRow("SELECT status, user_id, log_id FROM promised_amount WHERE id = ?", p.TxMaps.Int64["promised_amount_id"]).String() if err != nil { return p.ErrInfo(err) } // если статус mining или rejected, значит голос был решающим if data["status"] == "mining" || data["status"] == "rejected" { // восстановим из лога logData, err := p.OneRow("SELECT status, start_time, tdc_amount_update, prev_log_id FROM log_promised_amount WHERE log_id = ?", data["log_id"]).String() if err != nil { return p.ErrInfo(err) } err = p.ExecSql("UPDATE promised_amount SET status = ?, start_time = ?, tdc_amount_update = ?, log_id = ? WHERE id = ?", logData["status"], logData["start_time"], logData["tdc_amount_update"], logData["prev_log_id"], p.TxMaps.Int64["promised_amount_id"]) if err != nil { return p.ErrInfo(err) } // подчищаем _log err = p.ExecSql("DELETE FROM log_promised_amount WHERE log_id = ?", data["log_id"]) if err != nil { return p.ErrInfo(err) } p.rollbackAI("log_promised_amount", 1) // был ли добавлен woc woc, err := p.Single("SELECT id FROM promised_amount WHERE currency_id = 1 AND woc_block_id = ? AND user_id = ?", p.BlockData.BlockId, data["user_id"]).Int64() if err != nil { return p.ErrInfo(err) } if woc > 0 { err = p.ExecSql("DELETE FROM promised_amount WHERE id = ?", woc) if err != nil { return p.ErrInfo(err) } p.rollbackAI("promised_amount", 1) } } return nil }
func (c *Controller) ChangeHost() (string, error) { txType := "ChangeHost" txTypeId := utils.TypeInt(txType) timeNow := utils.Time() if !c.PoolAdmin || c.SessRestricted != 0 { return "", utils.ErrInfo(errors.New("access denied")) } data, err := c.OneRow("SELECT http_host, tcp_host, host_status FROM " + c.MyPrefix + "my_table").String() if err != nil { return "", utils.ErrInfo(err) } data2, err := c.OneRow("SELECT http_host, tcp_host, e_host FROM miners_data WHERE user_id = ?", c.SessUserId).String() if err != nil { return "", utils.ErrInfo(err) } if len(data["http_host"]) == 0 { data["http_host"] = data2["http_host"] } if len(data["tcp_host"]) == 0 { data["tcp_host"] = data2["tcp_host"] } if len(data["e_host"]) == 0 { data["e_host"] = data2["e_host"] } if data["e_host"] == "" { data["e_host"] = "0" } statusArray := map[string]string{"my_pending": c.Lang["local_pending"], "approved": c.Lang["status_approved"]} data["host_status"] = statusArray[data["host_status"]] limitsText := strings.Replace(c.Lang["change_host_limits_text"], "[limit]", utils.Int64ToStr(c.Variables.Int64["limit_change_host"]), -1) limitsText = strings.Replace(limitsText, "[period]", c.Periods[c.Variables.Int64["limit_change_host_period"]], -1) TemplateStr, err := makeTemplate("change_host", "changeHost", &changeHostPage{ Alert: c.Alert, UserId: c.SessUserId, CountSignArr: c.CountSignArr, Data: data, TimeNow: timeNow, TxType: txType, TxTypeId: txTypeId, LimitsText: limitsText, ShowSignData: c.ShowSignData, Community: c.Community, SignData: "", Lang: c.Lang}) if err != nil { return "", utils.ErrInfo(err) } return TemplateStr, nil }
func (p *Parser) ChangeArbitratorConditionsRollback() error { err := p.selectiveRollback([]string{"url"}, "users", "user_id="+utils.Int64ToStr(p.TxUserID), false) if err != nil { return p.ErrInfo(err) } err = p.generalRollback("arbitrator_conditions", p.TxUserID, "", false) if err != nil { return p.ErrInfo(err) } return nil }
func (p *Parser) NewUserRollback() error { // если работаем в режиме пула, то ищем тех, у кого записан такой ключ community, err := p.DCDB.GetCommunityUsers() if err != nil { return p.ErrInfo(err) } if len(community) > 0 { for _, userId := range community { myPrefix := utils.Int64ToStr(userId) + "_" // проверим, не наш ли это public_key, чтобы записать полученный user_id в my_table myPublicKey, err := p.DCDB.Single("SELECT public_key FROM "+myPrefix+"my_keys WHERE hex(public_key) = ?", p.TxMap["public_key_hex"]).String() if err != nil { return p.ErrInfo(err) } if myPublicKey != "" { // теперь у нас полноценный юзерский акк, и его можно апргрейдить до майнерского err = p.DCDB.ExecSql("UPDATE " + myPrefix + "my_table SET user_id = 0, status = 'my_pending', notification_status = 0") if err != nil { return p.ErrInfo(err) } err = p.DCDB.ExecSql("UPDATE "+myPrefix+"my_keys SET block_id = 0 WHERE block_id = ?", p.BlockData.BlockId) if err != nil { return p.ErrInfo(err) } } } } else { // проверим, не наш ли это public_key myPublicKey, err := p.DCDB.Single("SELECT public_key FROM my_keys WHERE hex(public_key) = ?", p.TxMap["public_key_hex"]).String() if err != nil { return p.ErrInfo(err) } if myPublicKey != "" { err = p.DCDB.ExecSql("UPDATE my_table SET user_id = 0, status = 'my_pending', notification_status = 0") if err != nil { return p.ErrInfo(err) } err = p.DCDB.ExecSql("UPDATE my_keys SET block_id = 0 WHERE block_id = ?", p.BlockData.BlockId) if err != nil { return p.ErrInfo(err) } } } err = p.DCDB.ExecSql("DELETE FROM users WHERE hex(public_key_0) = ?", p.TxMap["public_key_hex"]) if err != nil { return p.ErrInfo(err) } err = p.rollbackAI("users", 1) if err != nil { return p.ErrInfo(err) } return nil }
func UnbanNodes(chBreaker chan bool, chAnswer chan string) { defer func() { if r := recover(); r != nil { log.Error("daemon Recovered", r) panic(r) } }() GoroutineName := "UnbanNodes" d := new(daemon) d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName) if d.DCDB == nil { return } d.goRoutineName = GoroutineName d.chAnswer = chAnswer d.chBreaker = chBreaker d.sleepTime = 3600 if !d.CheckInstall(chBreaker, chAnswer, GoroutineName) { return } d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName) if d.DCDB == nil { return } BEGIN: for { log.Info(GoroutineName) MonitorDaemonCh <- []string{GoroutineName, utils.Int64ToStr(utils.Time())} // проверим, не нужно ли нам выйти из цикла if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) { break BEGIN } err = d.ExecSql("DELETE FROM nodes_ban") if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } if d.dSleep(d.sleepTime) { break BEGIN } } log.Debug("break BEGIN %v", GoroutineName) }
func (c *Controller) DeleteVideo() (string, error) { if !c.NodeAdmin || c.SessRestricted != 0 { return "", utils.ErrInfo(errors.New("Permission denied")) } if c.r.FormValue("type") == "mp4" { err := os.Remove(*utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_video.mp4") if err != nil { return "", utils.ErrInfo(err) } } else if c.r.FormValue("type") == "webm_ogg" { err := os.Remove(*utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_video.ogv") if err != nil { return "", utils.ErrInfo(err) } err = os.Remove(*utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_video.webm") if err != nil { return "", utils.ErrInfo(err) } } return ``, nil }
func (c *Controller) CropPhoto() (string, error) { if c.SessRestricted != 0 { return "", utils.ErrInfo(errors.New("Permission denied")) } c.r.ParseForm() photo := strings.Split(c.r.FormValue("photo"), ",") if len(photo) != 2 { return "", errors.New("Incorrect photo") } binary, err := base64.StdEncoding.DecodeString(photo[1]) if err != nil { return "", err } img, _, err := image.Decode(bytes.NewReader(binary)) if err != nil { return "", err } path := "" if c.r.FormValue("type") == "face" { path = *utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_face.jpg" } else { path = *utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_profile.jpg" } out, err := os.Create(path) if err != nil { return "", err } err = jpeg.Encode(out, img, &jpeg.Options{85}) if err != nil { return "", err } return `{"success":"ok"}`, nil }
func (c *Controller) Upgrade4() (string, error) { log.Debug("Upgrade4") videoUrl := "" // есть ли загруженное видео. data, err := c.OneRow("SELECT video_url_id, video_type FROM " + c.MyPrefix + "my_table").String() if err != nil { return "", utils.ErrInfo(err) } switch data["video_type"] { case "youtube": videoUrl = "http://www.youtube.com/embed/" + data["video_url_id"] case "vimeo": videoUrl = "http://www.vimeo.com/embed/" + data["video_url_id"] case "youku": videoUrl = "http://www.youku.com/embed/" + data["video_url_id"] } saveAndGotoStep := strings.Replace(c.Lang["save_and_goto_step"], "[num]", "6", -1) upgradeMenu := utils.MakeUpgradeMenu(4) var userVideoMp4 string path := *utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_video.mp4" if _, err := os.Stat(path); err == nil { userVideoMp4 = "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_video.mp4" } var userVideoWebm string path = *utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_video.webm" if _, err := os.Stat(path); err == nil { userVideoWebm = "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_video.webm" } var userVideoOgg string path = *utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_video.ogg" if _, err := os.Stat(path); err == nil { userVideoOgg = "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_video.ogg" } TemplateStr, err := makeTemplate("upgrade_4", "upgrade4", &upgrade4Page{ Alert: c.Alert, Lang: c.Lang, SaveAndGotoStep: saveAndGotoStep, UpgradeMenu: upgradeMenu, VideoUrl: videoUrl, UserVideoMp4: userVideoMp4, UserVideoWebm: userVideoWebm, UserVideoOgg: userVideoOgg, Mobile: utils.Mobile(), UserId: c.SessUserId}) if err != nil { return "", utils.ErrInfo(err) } return TemplateStr, nil }
func (db *DCDB) MakeFrontTest(transactionArray []string, time int64, dataForSign string, txType string, userId int64) error { var err error nodeArr := []string{"new_admin", "votes_node_new_miner"} MY_PREFIX := utils.Int64ToStr(userId) + "_" var binSign []byte if utils.InSliceString(txType, nodeArr) { k, err := db.GetNodePrivateKey(MY_PREFIX) privateKey, err := MakePrivateKey(k) if err != nil { return ErrInfo(err) } binSign, err = rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA1, utils.HashSha1(dataForSign)) } else { k, err := db.GetPrivateKey(MY_PREFIX) privateKey, err := MakePrivateKey(k) if err != nil { return ErrInfo(err) } binSign, err = rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA1, utils.HashSha1(dataForSign)) binSign = EncodeLengthPlusData(binSign) } transactionArray = append(transactionArray, binSign) parser := new(Parser) parser.DCDB = db parser.GoroutineName = "test" parser.TxSlice = transactionArray parser.BlockData = &utils.BlockData{BlockId: 190006, Time: time, UserId: userId} parser.TxHash = "111111111111111" err0 := utils.CallMethod(parser, txType+"Init") if i, ok := err0.(error); ok { fmt.Println(err0.(error), i) return err0.(error) } err0 := utils.CallMethod(parser, txType+"Front") if i, ok := err0.(error); ok { fmt.Println(err0.(error), i) return err0.(error) } err0 := utils.CallMethod(parser, txType+"RollbackFront") if i, ok := err0.(error); ok { fmt.Println(err0.(error), i) return err0.(error) } return nil }
func (c *Controller) ChangeGeolocation() (string, error) { var err error txType := "ChangeGeolocation" txTypeId := utils.TypeInt(txType) timeNow := utils.Time() myGeolocationStr, err := c.Single(`SELECT geolocation FROM ` + c.MyPrefix + `my_table`).String() if len(myGeolocationStr) == 0 { myGeolocationStr = "39.94887, -75.15005" } x := strings.Split(myGeolocationStr, ", ") myGeolocation := make(map[string]string) myGeolocation["lat"] = x[0] myGeolocation["lon"] = x[1] myCountry, err := c.Single("SELECT country FROM miners_data WHERE user_id = ?", c.SessUserId).Int() if err != nil { return "", utils.ErrInfo(err) } limitsText := strings.Replace(c.Lang["geolocation_limits_text"], "[limit]", utils.Int64ToStr(c.Variables.Int64["limit_change_geolocation"]), -1) limitsText = strings.Replace(limitsText, "[period]", c.Periods[c.Variables.Int64["limit_change_geolocation_period"]], -1) TemplateStr, err := makeTemplate("change_geolocation", "changeGeolocation", &changeGeolocationPage{ Alert: c.Alert, Lang: c.Lang, TxTypeId: txTypeId, TimeNow: timeNow, UserId: c.SessUserId, CountSignArr: c.CountSignArr, ShowSignData: c.ShowSignData, SignData: "", LimitsText: limitsText, MyCountry: myCountry, Countries: consts.Countries, MyGeolocation: myGeolocation}) if err != nil { return "", utils.ErrInfo(err) } return TemplateStr, nil }
func (c *Controller) MyNoticeData() (string, error) { if !c.dbInit { return "", utils.ErrInfo(errors.New("Permission denied")) } c.r.ParseForm() myNotice, err := c.GetMyNoticeData(c.SessRestricted, c.SessUserId, c.MyPrefix, c.Lang) if err != nil { return "", utils.ErrInfo(err) } var cashRequests int64 if c.SessRestricted == 0 { myUserId, err := c.GetMyUserId(c.MyPrefix) if err != nil { return "", utils.ErrInfo(err) } cashRequests, err = c.Single("SELECT count(id) FROM cash_requests WHERE to_user_id = ? AND status = 'pending' AND for_repaid_del_block_id = 0 AND del_block_id = 0", myUserId).Int64() if cashRequests > 0 { cashRequests = 1 } if err != nil { return "", utils.ErrInfo(err) } } result, err := json.Marshal(map[string]string{ "main_status": myNotice["main_status"], "main_status_complete": myNotice["main_status_complete"], "account_status": myNotice["account_status"], "cur_block_id": myNotice["cur_block_id"], "connections": myNotice["connections"], "time_last_block": myNotice["time_last_block"], "time_last_block_int": myNotice["time_last_block_int"], "inbox": utils.Int64ToStr(cashRequests)}) if err != nil { return "", utils.ErrInfo(err) } return string(result), nil }
func (c *Controller) GetBlock() (string, error) { c.r.ParseForm() BlockId := int64(utils.StrToFloat64(c.r.FormValue("id"))) if BlockId == 0 { return `{"error": "nil id"}`, nil } if len(c.r.FormValue("download")) > 0 { c.w.Header().Set("Content-type", "application/octet-stream") c.w.Header().Set("Content-Disposition", "attachment; filename=\""+utils.Int64ToStr(BlockId)+".binary\"") } block, err := c.Single("SELECT data FROM block_chain WHERE id = ?", BlockId).String() if err != nil { return "", utils.ErrInfo(err) } return block, nil }
func (c *Controller) PromisedAmountList() (string, error) { txType := "PromisedAmount" txTypeId := utils.TypeInt(txType) timeNow := time.Now().Unix() last_tx, err := c.GetLastTx(c.SessUserId, utils.TypesToIds([]string{"NewPromisedAmount", "ChangePromisedAmount", "DelPromisedAmount", "ForRepaidFix", "ActualizationPromisedAmounts", "Mining"}), 3, c.TimeFormat) lastTxFormatted := "" if len(last_tx) > 0 { lastTxFormatted, _ = utils.MakeLastTx(last_tx, c.Lang) } limitsText := strings.Replace(c.Lang["change_commission_limits_text"], "[limit]", utils.Int64ToStr(c.Variables.Int64["limit_promised_amount"]), -1) limitsText = strings.Replace(limitsText, "[period]", c.Periods[c.Variables.Int64["limit_promised_amount_period"]], -1) actualizationPromisedAmounts, promisedAmountListAccepted, _, err := c.GetPromisedAmounts(c.SessUserId, c.Variables.Int64["cash_request_time"]) if err != nil { return "", utils.ErrInfo(err) } TemplateStr, err := makeTemplate("promised_amount_list", "promisedAmountList", &promisedAmountListPage{ Alert: c.Alert, Lang: c.Lang, CountSignArr: c.CountSignArr, ShowSignData: c.ShowSignData, UserId: c.SessUserId, TimeNow: timeNow, TxType: txType, TxTypeId: txTypeId, SignData: "", LastTxFormatted: lastTxFormatted, CurrencyList: c.CurrencyList, PromisedAmountListAccepted: promisedAmountListAccepted, ActualizationPromisedAmounts: actualizationPromisedAmounts, LimitsText: limitsText}) if err != nil { return "", utils.ErrInfo(err) } return TemplateStr, nil }
func (p *Parser) DelCfProjectRollback() error { project_currency_id, err := p.Single("SELECT currency_id FROM cf_projects WHERE id = ?", p.TxMaps.Int64["project_id"]).Int64() if err != nil { return p.ErrInfo(err) } // проходимся по всем фундерам и возращаем на их кошельки деньги rows, err := p.Query(p.FormatQuery("SELECT user_id FROM cf_funding WHERE project_id = ? AND del_block_id = 0 ORDER BY id DESC"), p.TxMaps.Int64["project_id"]) if err != nil { return p.ErrInfo(err) } defer rows.Close() for rows.Next() { var user_id int64 err = rows.Scan(&user_id) if err != nil { return p.ErrInfo(err) } // откат возврата err = p.generalRollback("wallets", user_id, "AND currency_id = "+utils.Int64ToStr(project_currency_id), false) if err != nil { return p.ErrInfo(err) } // возможно были списания по кредиту err = p.loanPaymentsRollback(user_id, project_currency_id) if err != nil { return p.ErrInfo(err) } } err = p.ExecSql("UPDATE cf_projects SET del_block_id = 0 WHERE id = ?", p.TxMaps.Int64["project_id"]) if err != nil { return p.ErrInfo(err) } return nil }
func (p *Parser) MoneyBackRequestRollback() error { orderData, err := p.OneRow("SELECT seller, arbitrator0, arbitrator1, arbitrator2, arbitrator3, arbitrator4 FROM orders WHERE id = ?", p.TxMaps.Int64["order_id"]).Int64() if err != nil { return p.ErrInfo(err) } // проверим, не является ли мы продавцом или арбитром myUserId, _, myPrefix, _, err := p.GetMyUserId(orderData["seller"]) if err != nil { return p.ErrInfo(err) } if orderData["seller"] == myUserId { err = p.ExecSql("DELETE FROM "+myPrefix+"my_comments WHERE type = 'seller' AND id = ?", p.TxMaps.Int64["order_id"]) if err != nil { return p.ErrInfo(err) } } for i := 0; i < 5; i++ { iStr := utils.IntToStr(i) if orderData["arbitrator"+iStr] == 0 { continue } myUserId, _, myPrefix, _, err := p.GetMyUserId(orderData["arbitrator"+iStr]) if err != nil { return p.ErrInfo(err) } if orderData["arbitrator"+iStr] == myUserId { err = p.ExecSql("DELETE FROM "+myPrefix+"my_comments WHERE type = 'arbitrator' AND id = ?", p.TxMaps.Int64["order_id"]) if err != nil { return p.ErrInfo(err) } } } err = p.selectiveRollback([]string{"status"}, "orders", "id="+utils.Int64ToStr(p.TxMaps.Int64["order_id"]), false) return nil }
func (c *Controller) AlertFromAdmin() (string, error) { if c.SessRestricted != 0 { return "", utils.ErrInfo(errors.New("Permission denied")) } alertMessage := "" alert, err := utils.GetHttpTextAnswer("http://dcoin.club/alert.json") if len(alert) > 0 { alertData := new(alertType) err = json.Unmarshal([]byte(alert), &alertData) if err != nil { log.Error("%v", utils.ErrInfo(err)) } messageJson, err := json.Marshal(alertData.Message) if err != nil { log.Error("%v", utils.ErrInfo(err)) } pub, err := utils.BinToRsaPubKey(utils.HexToBin(consts.ALERT_KEY)) if err != nil { log.Error("%v", utils.ErrInfo(err)) } err = rsa.VerifyPKCS1v15(pub, crypto.SHA1, utils.HashSha1(string(messageJson)), []byte(utils.HexToBin(alertData.Signature))) if err != nil { log.Error("%v", utils.ErrInfo(err)) } if version.Compare(alertData.Message["version"], consts.VERSION, ">") { alertMessage = alertData.Message[utils.Int64ToStr(c.LangInt)] return utils.JsonAnswer(alertMessage, "success").String(), nil } } return ``, nil }
func (c *Controller) HolidaysList() (string, error) { var err error var myHolidaysPending []map[string]string if c.SessRestricted == 0 { // те, что еще не попали в Dc-сеть myHolidaysPending, err = c.GetAll(`SELECT * FROM `+c.MyPrefix+`my_holidays ORDER BY id DESC`, -1) } myHolidaysAccepted, err := c.GetAll(`SELECT * FROM holidays WHERE user_id = ?`, -1, c.SessUserId) limitsText := strings.Replace(c.Lang["limits_text"], "[limit]", utils.Int64ToStr(c.Variables.Int64["limit_holidays"]), -1) limitsText = strings.Replace(limitsText, "[period]", c.Periods[c.Variables.Int64["limit_holidays_period"]], -1) last_tx, err := c.GetLastTx(c.SessUserId, utils.TypesToIds([]string{"NewHolidays"}), 3, c.TimeFormat) lastTxFormatted := "" if len(last_tx) > 0 { lastTxFormatted, _ = utils.MakeLastTx(last_tx, c.Lang) } TemplateStr, err := makeTemplate("holidays_list", "holidaysList", &holidaysListPage{ Alert: c.Alert, Lang: c.Lang, CountSignArr: c.CountSignArr, ShowSignData: c.ShowSignData, SignData: "", LastTxFormatted: lastTxFormatted, LimitsText: limitsText, MyHolidaysPending: myHolidaysPending, MyHolidaysAccepted: myHolidaysAccepted}) if err != nil { return "", utils.ErrInfo(err) } return TemplateStr, nil }
func (p *Parser) SendDcFront() error { err := p.generalCheck() if err != nil { return p.ErrInfo(err) } verifyData := map[string]string{"from_user_id": "bigint", "to_user_id": "bigint", "currency_id": "bigint", "amount": "amount", "commission": "amount", "comment": "comment"} err = p.CheckInputData(verifyData) if err != nil { return p.ErrInfo(err) } if p.TxMaps.Float64["amount"] < 0.01 { // 0.01 - минимальная сумма return p.ErrInfo("amount") } // проверим, существует ли такая валюта в таблиуе DC-валют checkCurrency, err := p.CheckCurrency(p.TxMaps.Int64["currency_id"]) if !checkCurrency { // если нет, то проверяем список CF-валют checkCurrency, err := p.CheckCurrencyCF(p.TxMaps.Int64["currency_id"]) if err != nil { return p.ErrInfo(err) } if !checkCurrency { return p.ErrInfo("currency_id") } } nodeCommission, err := p.getMyNodeCommission(p.TxMaps.Int64["currency_id"], p.TxUserID, p.TxMaps.Float64["amount"]) if err != nil { return p.ErrInfo(err) } // проверим, удовлетворяет ли нас комиссия, которую предлагает юзер if p.TxMaps.Float64["commission"] < nodeCommission { return p.ErrInfo(fmt.Sprintf("commission %v<%v", p.TxMaps.Float64["commission"], nodeCommission)) } if p.BlockData != nil && p.BlockData.BlockId <= consts.ARBITRATION_BLOCK_START { for i := 0; i < 5; i++ { p.TxMaps.Float64["arbitrator"+utils.IntToStr(i)+"_commission"] = 0 // для check_sender_money } forSign := fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s,%s", p.TxMap["type"], p.TxMap["time"], p.TxMap["user_id"], p.TxMap["to_user_id"], p.TxMap["amount"], p.TxMap["commission"], utils.BinToHex(p.TxMap["comment"]), p.TxMap["currency_id"]) CheckSignResult, err := utils.CheckSign(p.PublicKeys, forSign, p.TxMap["sign"], false) if err != nil { return p.ErrInfo(err) } if !CheckSignResult { return p.ErrInfo("incorrect sign") } } else { dupArray := make(map[int64]int64) for i := 0; i < 5; i++ { arbitrator__commission := "arbitrator" + utils.IntToStr(i) + "_commission" arbitrator_ := "arbitrator" + utils.IntToStr(i) if !utils.CheckInputData(p.TxMap[arbitrator__commission], "amount") { return p.ErrInfo("arbitrator_commission") } if !utils.CheckInputData(p.TxMap[arbitrator_], "bigint") { return p.ErrInfo("arbitrator") } // если указал ID арбитра, то должна быть комиссия для него if p.TxMaps.Int64[arbitrator_] > 0 && p.TxMaps.Float64[arbitrator__commission] < 0.01 { return p.ErrInfo("arbitrator_commission") } // на всяк случай не даем арбитрам возможность быть арбитрами самим себе if p.TxMaps.Int64[arbitrator_] == p.TxUserID { return p.ErrInfo("arbitrator = user_id") } if p.TxMaps.Int64[arbitrator_] > 0 { dupArray[utils.BytesToInt64(p.TxMap[arbitrator_])]++ if dupArray[utils.BytesToInt64(p.TxMap[arbitrator_])] > 1 { return p.ErrInfo("doubles") } } if p.TxMaps.Int64[arbitrator_] > 0 { arbitrator := p.TxMap[arbitrator_] // проверим, является ли арбитром указанный user_id arbitratorConditionsJson, err := p.Single("SELECT conditions FROM arbitrator_conditions WHERE user_id = ?", utils.BytesToInt64(arbitrator)).Bytes() if err != nil { return p.ErrInfo(err) } arbitratorConditionsMap := make(map[string][5]string) err = json.Unmarshal(arbitratorConditionsJson, &arbitratorConditionsMap) // арбитр к этому моменту мог передумать и убрать свои условия, уйдя из арбитров для новых сделок поставив [0] что вызовет тут ошибку if err != nil { log.Debug("arbitratorConditionsJson", arbitratorConditionsJson) return p.ErrInfo(err) } // проверим, работает ли выбранный арбитр с валютой данной сделки var checkCurrency int64 if p.TxMaps.Int64["currency_id"] > 1000 { checkCurrency = 1000 } else { checkCurrency = p.TxMaps.Int64["currency_id"] } if len(arbitratorConditionsMap[utils.Int64ToStr(checkCurrency)]) == 0 { return p.ErrInfo("len(arbitratorConditionsMap[checkCurrency]) == 0") } // указан ли этот арбитр в списке доверенных у продавца sellerArbitrator, err := p.Single("SELECT user_id FROM arbitration_trust_list WHERE user_id = ? AND arbitrator_user_id = ?", p.TxMaps.Int64["to_user_id"], utils.BytesToInt64(arbitrator)).Int64() if err != nil { return p.ErrInfo(err) } if sellerArbitrator == 0 { return p.ErrInfo("sellerArbitrator == 0") } // указан ли этот арбитр в списке доверенных у покупателя buyerArbitrator, err := p.Single("SELECT user_id FROM arbitration_trust_list WHERE user_id = ? AND arbitrator_user_id = ?", p.TxMaps.Int64["from_user_id"], utils.BytesToInt64(arbitrator)).Int64() if err != nil { return p.ErrInfo(err) } if buyerArbitrator == 0 { return p.ErrInfo("buyerArbitrator == 0") } // согласен ли продавец на манибек arbitrationDaysRefund, err := p.Single("SELECT arbitration_days_refund FROM users WHERE user_id = ?", p.TxMaps.Int64["to_user_id"]).Int64() if err != nil { return p.ErrInfo(err) } if arbitrationDaysRefund == 0 { return p.ErrInfo("buyerArbitrator == 0") } // готов ли арбитр рассматривать такую сумму сделки currencyIdStr := utils.Int64ToStr(p.TxMaps.Int64["currency_id"]) if p.TxMaps.Float64["amount"] < utils.StrToFloat64(arbitratorConditionsMap[currencyIdStr][0]) || (p.TxMaps.Float64["amount"] > utils.StrToFloat64(arbitratorConditionsMap[currencyIdStr][1]) && utils.StrToFloat64(arbitratorConditionsMap[currencyIdStr][1]) > 0) { return p.ErrInfo("amount") } // мин. комиссия, на которую согласен арбитр minArbitratorCommission := utils.StrToFloat64(arbitratorConditionsMap[currencyIdStr][4]) / 100 * p.TxMaps.Float64["amount"] if minArbitratorCommission > utils.StrToFloat64(arbitratorConditionsMap[currencyIdStr][3]) && utils.StrToFloat64(arbitratorConditionsMap[currencyIdStr][3]) > 0 { minArbitratorCommission = utils.StrToFloat64(arbitratorConditionsMap[currencyIdStr][3]) } if minArbitratorCommission < utils.StrToFloat64(arbitratorConditionsMap[currencyIdStr][2]) { minArbitratorCommission = utils.StrToFloat64(arbitratorConditionsMap[currencyIdStr][2]) } if utils.BytesToFloat64(p.TxMap[arbitrator__commission]) < minArbitratorCommission { return p.ErrInfo(" < minArbitratorCommission") } } } forSign := fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s", p.TxMap["type"], p.TxMap["time"], p.TxMap["user_id"], p.TxMap["to_user_id"], p.TxMap["amount"], p.TxMap["commission"], p.TxMap["arbitrator0"], p.TxMap["arbitrator1"], p.TxMap["arbitrator2"], p.TxMap["arbitrator3"], p.TxMap["arbitrator4"], p.TxMap["arbitrator0_commission"], p.TxMap["arbitrator1_commission"], p.TxMap["arbitrator2_commission"], p.TxMap["arbitrator3_commission"], p.TxMap["arbitrator4_commission"], utils.BinToHex(p.TxMap["comment"]), p.TxMap["currency_id"]) CheckSignResult, err := utils.CheckSign(p.PublicKeys, forSign, p.TxMap["sign"], false) if err != nil { return p.ErrInfo(err) } if !CheckSignResult { return p.ErrInfo("incorrect sign") } } /* wallets_buffer сделан не для защиты от двойной траты, а для того, чтобы нода, которая генерит блок не записала двойное списание в свой блок, который будет отправлен другим нодам и будет ими отвергнут. Для тр-ий типа new_forex_order используется простой запрет на запись в блок тр-ии new_forex_order+new_forex_order или new_forex_order+send_dc и пр. защита от двойного списания на основе даннных из блока, полученного из сети заключается в постепенной обработке тр-ий путем проверки front_ и занесения данных в БД (ParseDataFull). */ amountAndCommission, err := p.checkSenderMoney(p.TxMaps.Int64["currency_id"], p.TxMaps.Int64["from_user_id"], p.TxMaps.Float64["amount"], p.TxMaps.Float64["commission"], p.TxMaps.Float64["arbitrator0_commission"], p.TxMaps.Float64["arbitrator1_commission"], p.TxMaps.Float64["arbitrator2_commission"], p.TxMaps.Float64["arbitrator3_commission"], p.TxMaps.Float64["arbitrator4_commission"]) if err != nil { return p.ErrInfo(err) } // существует ли юзер-получатель err = p.CheckUser(p.TxMaps.Int64["to_user_id"]) if err != nil { return p.ErrInfo(err) } err = p.checkSpamMoney(p.TxMaps.Int64["currency_id"], p.TxMaps.Float64["amount"]) if err != nil { return p.ErrInfo(err) } // вычитаем из wallets_buffer // amount_and_commission взято из check_sender_money() err = p.updateWalletsBuffer(amountAndCommission, p.TxMaps.Int64["currency_id"]) if err != nil { return p.ErrInfo(err) } return nil }
func (p *Parser) SendDcRollback() error { // нужно отметить в log_time_money_orders, что тр-ия НЕ прошла в блок err := p.ExecSql("UPDATE log_time_money_orders SET del_block_id = 0 WHERE hex(tx_hash) = ?", p.TxHash) if err != nil { return p.ErrInfo(err) } // 6 комиссия нода-генератора блока if p.TxMaps.Float64["commission"] >= 0.01 { err = p.generalRollback("wallets", p.BlockData.UserId, "AND currency_id = "+utils.Int64ToStr(p.TxMaps.Int64["currency_id"]), false) if err != nil { return p.ErrInfo(err) } // возможно были списания по кредиту нода-генератора err = p.loanPaymentsRollback(p.BlockData.UserId, p.TxMaps.Int64["currency_id"]) if err != nil { return p.ErrInfo(err) } } // 5 обновим сумму на кошельке получателю // возможно были списания по кредиту err = p.loanPaymentsRollback(p.TxMaps.Int64["to_user_id"], p.TxMaps.Int64["currency_id"]) if err != nil { return p.ErrInfo(err) } err = p.generalRollback("wallets", p.TxMaps.Int64["to_user_id"], "AND currency_id = "+utils.Int64ToStr(p.TxMaps.Int64["currency_id"]), false) if err != nil { return p.ErrInfo(err) } // 4 обновим сумму на кошельке отправителя err = p.generalRollback("wallets", p.TxMaps.Int64["from_user_id"], "AND currency_id = "+utils.Int64ToStr(p.TxMaps.Int64["currency_id"]), false) if err != nil { return p.ErrInfo(err) } // 3 err = p.pointsUpdateRollbackMain(p.TxMaps.Int64["to_user_id"]) if err != nil { return p.ErrInfo(err) } // 2 err = p.pointsUpdateRollbackMain(p.TxMaps.Int64["from_user_id"]) if err != nil { return p.ErrInfo(err) } // 1 err = p.pointsUpdateRollbackMain(p.BlockData.UserId) if err != nil { return p.ErrInfo(err) } // отменяем чистку буфера err = p.ExecSql("UPDATE wallets_buffer SET del_block_id = 0 WHERE hex(hash) = ?", p.TxHash) if err != nil { return p.ErrInfo(err) } if p.BlockData.BlockId > consts.ARBITRATION_BLOCK_START { // на какой период манибека согласен продавец arbitrationDaysRefund, err := p.Single("SELECT arbitration_days_refund FROM users WHERE user_id = ?", p.TxMaps.Int64["to_user_id"]).Int64() if err != nil { return p.ErrInfo(err) } if arbitrationDaysRefund > 0 { delOrder := false for i := 0; i < 5; i++ { iStr := utils.IntToStr(i) if p.TxMaps.Int64["arbitrator"+iStr] > 0 && p.TxMaps.Float64["arbitrator"+iStr+"_commission"] >= 0.01 { err = p.generalRollback("wallets", p.TxMaps.Int64["arbitrator"+iStr], "AND currency_id = "+utils.Int64ToStr(p.TxMaps.Int64["currency_id"]), false) if err != nil { return p.ErrInfo(err) } if !delOrder { err = p.ExecSql("DELETE FROM orders WHERE block_id = ? AND buyer = ? AND seller = ? AND currency_id = ? AND amount = ?", p.BlockData.BlockId, p.TxMaps.Int64["from_user_id"], p.TxMaps.Int64["to_user_id"], p.TxMaps.Int64["currency_id"], p.TxMaps.Float64["amount"]) if err != nil { return p.ErrInfo(err) } err = p.rollbackAI("orders", 1) if err != nil { return p.ErrInfo(err) } delOrder = true } // возможно были списания по кредиту арбитра err = p.loanPaymentsRollback(p.TxMaps.Int64["arbitrator"+iStr], p.TxMaps.Int64["currency_id"]) if err != nil { return p.ErrInfo(err) } } } } } err = p.mydctxRollback() if err != nil { return p.ErrInfo(err) } return 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) }
func Exchange(chBreaker chan bool, chAnswer chan string) { defer func() { if r := recover(); r != nil { log.Error("daemon Recovered", r) panic(r) } }() const GoroutineName = "Exchange" 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 } BEGIN: for { log.Info(GoroutineName) MonitorDaemonCh <- []string{GoroutineName, utils.Int64ToStr(utils.Time())} // проверим, не нужно ли нам выйти из цикла if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) { break BEGIN } blockId, err := d.GetConfirmedBlockId() if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } var myPrefix string community, err := d.GetCommunityUsers() if len(community) > 0 { adminUserId, err := d.GetPoolAdminUserId() if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } myPrefix = utils.Int64ToStr(adminUserId) + "_" } else { myPrefix = "" } eConfig, err := d.GetMap(`SELECT * FROM e_config`, "name", "value") if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } confirmations := utils.StrToInt64(eConfig["confirmations"]) mainDcAccount := utils.StrToInt64(eConfig["main_dc_account"]) // все валюты, с которыми работаем currencyList, err := utils.EGetCurrencyList() if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } // ++++++++++++ reduction ++++++++++++ // максимальный номер блока для процентов. Чтобы брать только новые maxReductionBlock, err := d.Single(`SELECT max(block_id) FROM e_reduction`).Int64() if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } // если есть свежая reduction, то нужно остановить торги reduction, err := d.Single(`SELECT block_id FROM reduction WHERE block_id > ? and pct > 0`, maxReductionBlock).Int64() if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } if reduction > 0 { err = d.ExecSql(`INSERT INTO e_reduction_lock (time) VALUES (?)`, utils.Time()) if err != nil { log.Error("%v", utils.ErrInfo(err)) } } // если уже прошло 10 блоков с момента обнаружения reduction, то производим сокращение объема монет rows, err := d.Query(d.FormatQuery(`SELECT pct, currency_id, time, block_id FROM reduction WHERE block_id > ? AND block_id < ?`), maxReductionBlock, blockId-confirmations) if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } for rows.Next() { var pct float64 var currencyId, rTime, blockId int64 err = rows.Scan(&pct, ¤cyId, &rTime, &blockId) if err != nil { rows.Close() if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } // $k = (100-$row['pct'])/100; k := (100 - pct) / 100 // уменьшаем все средства на счетах err = d.ExecSql(`UPDATE e_wallets SET amount = amount * ? WHERE currency_id = ?`, k, currencyId) // уменьшаем все средства на вывод err = d.ExecSql(`UPDATE e_withdraw SET amount = amount * ? WHERE currency_id = ? AND close_time = 0`, k, currencyId) // уменьшаем все ордеры на продажу err = d.ExecSql(`UPDATE e_orders SET amount = amount * ?, begin_amount = begin_amount * ? WHERE sell_currency_id = ?`, k, k, currencyId) err = d.ExecSql(`INSERT INTO e_reduction ( time, block_id, currency_id, pct ) VALUES ( ?, ?, ?, ? )`, rTime, blockId, currencyId, pct) if err != nil { rows.Close() if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } } rows.Close() // ++++++++++++ DC ++++++++++++ /* * Важно! отключать в кроне при обнулении данных в БД * * 1. Получаем инфу о входящих переводах и начисляем их на счета юзеров * 2. Обновляем проценты * 3. Чистим кол-во отправленных смс-ок * */ nodePrivateKey, err := d.GetNodePrivateKey(myPrefix) if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } /* * Получаем инфу о входящих переводах и начисляем их на счета юзеров * */ // если всё остановлено из-за найденного блока с reduction, то входящие переводы не обрабатываем reductionLock, err := utils.EGetReductionLock() if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } if reductionLock > 0 { if d.dPrintSleep(utils.ErrInfo("reductionLock"), d.sleepTime) { break BEGIN } continue BEGIN } rows, err = d.Query(d.FormatQuery(` SELECT amount, id, block_id, type_id, currency_id, to_user_id, time, comment, comment_status FROM my_dc_transactions WHERE type = 'from_user' AND block_id < ? AND exchange_checked = 0 AND status = 'approved' AND to_user_id = ? ORDER BY id DESC`), blockId-confirmations, mainDcAccount) if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } for rows.Next() { var amount float64 var id, blockId, typeId, currencyId, toUserId, txTime int64 var comment, commentStatus string err = rows.Scan(&amount, &id, &blockId, &typeId, ¤cyId, &toUserId, &txTime, &comment, &commentStatus) if err != nil { rows.Close() if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } // отметим exchange_checked=1, чтобы больше не брать эту тр-ию err = d.ExecSql(`UPDATE my_dc_transactions SET exchange_checked = 1 WHERE id = ?`, id) if err != nil { rows.Close() if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } // вначале нужно проверить, точно ли есть такой перевод в блоке binaryData, err := d.Single(`SELECT data FROM block_chain WHERE id = ?`, blockId).Bytes() if err != nil { rows.Close() if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } p := new(dcparser.Parser) p.DCDB = d.DCDB p.BinaryData = binaryData p.ParseDataLite() for _, txMap := range p.TxMapArr { // пропускаем все ненужные тр-ии if utils.BytesToInt64(txMap["type"]) != utils.TypeInt("SendDc") { continue } log.Debug("md5hash %s", txMap["md5hash"]) // если что-то случится с таблой my_dc_transactions, то все ввода на биржу будут зачислены по новой // поэтому нужно проверять e_adding_funds exists, err := d.Single(`SELECT id FROM e_adding_funds WHERE hex(tx_hash) = ?`, string(txMap["md5hash"])).Int64() if err != nil { rows.Close() if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } log.Debug("exists %d", exists) if exists != 0 { continue } log.Debug("user_id = %d / typeId = %d / currency_id = %d / currencyId = %d / amount = %f / amount = %f / comment = %s / comment = %s / to_user_id = %d / toUserId = %d ", utils.BytesToInt64(txMap["user_id"]), typeId, utils.BytesToInt64(txMap["currency_id"]), currencyId, utils.BytesToFloat64(txMap["amount"]), amount, string(utils.BinToHex(txMap["comment"])), comment, utils.BytesToInt64(txMap["to_user_id"]), toUserId) // сравнение данных из таблы my_dc_transactions с тем, что в блоке if utils.BytesToInt64(txMap["user_id"]) == typeId && utils.BytesToInt64(txMap["currency_id"]) == currencyId && utils.BytesToFloat64(txMap["amount"]) == amount && string(utils.BinToHex(txMap["comment"])) == comment && utils.BytesToInt64(txMap["to_user_id"]) == toUserId { decryptedComment := comment if commentStatus == "encrypted" { // расшифруем коммент block, _ := pem.Decode([]byte(nodePrivateKey)) if block == nil || block.Type != "RSA PRIVATE KEY" { rows.Close() if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } private_key, err := x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil { rows.Close() if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } decryptedComment_, err := rsa.DecryptPKCS1v15(rand.Reader, private_key, utils.HexToBin(comment)) if err != nil { rows.Close() if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } decryptedComment = string(decryptedComment_) // запишем расшифрованный коммент, чтобы потом можно было найти перевод в ручном режиме err = d.ExecSql("UPDATE "+myPrefix+"my_dc_transactions SET comment = ?, comment_status = 'decrypted' WHERE id = ?", decryptedComment, id) if err != nil { rows.Close() if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } } // возможно юзер сделал перевод в той валюте, которая у нас на бирже еще не торгуется if len(currencyList[currencyId]) == 0 { log.Error("currencyId %d not trading", currencyId) continue } // возможно, что чуть раньше было reduction, а это значит, что все тр-ии, // которые мы ещё не обработали и которые были До блока с reduction нужно принимать с учетом reduction // т.к. средства на нашем счете уже урезались, а вот те, что после reduction - остались в том виде, в котором пришли lastReduction, err := d.OneRow("SELECT block_id, pct FROM reduction WHERE currency_id = ? ORDER BY block_id", currencyId).Int64() if err != nil { rows.Close() if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } if blockId <= lastReduction["block_id"] { // сумму с учетом reduction k0 := (100 - lastReduction["pct"]) / 100 amount = amount * float64(k0) } // начисляем средства на счет того, чей id указан в комменте r, _ := regexp.Compile(`(?i)\s*#\s*([0-9]+)\s*`) user := r.FindStringSubmatch(decryptedComment) if len(user) == 0 { log.Error("len(user) == 0") continue } log.Debug("user %s", user[1]) // user_id с биржевой таблы uid := utils.StrToInt64(user[1]) userAmountAndProfit := utils.EUserAmountAndProfit(uid, currencyId) newAmount_ := userAmountAndProfit + amount utils.UpdEWallet(uid, currencyId, utils.Time(), newAmount_, true) // для отчетности запишем в историю err = d.ExecSql(` INSERT INTO e_adding_funds ( user_id, currency_id, time, amount, tx_hash ) VALUES ( ?, ?, ?, ?, ? )`, uid, currencyId, txTime, amount, string(txMap["md5hash"])) if err != nil { rows.Close() if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } } } } rows.Close() /* * Обновляем проценты * */ // максимальный номер блока для процентов. Чтобы брать только новые maxPctBlock, err := d.Single(`SELECT max(block_id) FROM e_user_pct`).Int64() log.Debug(`SELECT time, block_id, currency_id, user FROM pct WHERE block_id < ` + utils.Int64ToStr(blockId-confirmations) + ` AND block_id > ` + utils.Int64ToStr(maxPctBlock)) rows, err = d.Query(d.FormatQuery(`SELECT time, block_id, currency_id, user FROM pct WHERE block_id < ? AND block_id > ?`), blockId-confirmations, maxPctBlock) if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } for rows.Next() { var pct float64 var pTime, blockId, currencyId int64 err = rows.Scan(&pTime, &blockId, ¤cyId, &pct) if err != nil { rows.Close() if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } d.ExecSql(` INSERT INTO e_user_pct ( time, block_id, currency_id, pct ) VALUES ( ?, ?, ?, ? )`, pTime, blockId, currencyId, pct) } rows.Close() if d.dSleep(d.sleepTime) { break BEGIN } } log.Debug("break BEGIN %v", GoroutineName) }
func BlocksCollection(chBreaker chan bool, chAnswer chan string) { defer func() { if r := recover(); r != nil { log.Error("daemon Recovered", r) panic(r) } }() const GoroutineName = "BlocksCollection" d := new(daemon) d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName) if d.DCDB == nil { return } d.goRoutineName = GoroutineName d.chAnswer = chAnswer d.chBreaker = chBreaker if utils.Mobile() { d.sleepTime = 300 } else { d.sleepTime = 60 } if !d.CheckInstall(chBreaker, chAnswer, GoroutineName) { return } d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName) if d.DCDB == nil { return } //var cur bool BEGIN: for { log.Info(GoroutineName) MonitorDaemonCh <- []string{GoroutineName, utils.Int64ToStr(utils.Time())} // проверим, не нужно ли нам выйти из цикла if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) { break BEGIN } log.Debug("0") config, err := d.GetNodeConfig() if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } log.Debug("1") err, restart := d.dbLock() if restart { log.Debug("restart true") break BEGIN } if err != nil { log.Debug("restart err %v", err) if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } log.Debug("2") // если это первый запуск во время инсталяции currentBlockId, err := d.GetBlockId() if err != nil { if d.unlockPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } log.Info("config", config) log.Info("currentBlockId", currentBlockId) // на время тестов /*if !cur { currentBlockId = 0 cur = true }*/ parser := new(dcparser.Parser) parser.DCDB = d.DCDB parser.GoroutineName = GoroutineName if currentBlockId == 0 || *utils.StartBlockId > 0 { /* IsNotExistBlockChain := false if _, err := os.Stat(*utils.Dir+"/public/blockchain"); os.IsNotExist(err) { IsNotExistBlockChain = true }*/ if config["first_load_blockchain"] == "file" /* && IsNotExistBlockChain*/ { log.Info("first_load_blockchain=file") nodeConfig, err := d.GetNodeConfig() blockchain_url := nodeConfig["first_load_blockchain_url"] if len(blockchain_url) == 0 { blockchain_url = consts.BLOCKCHAIN_URL } log.Debug("blockchain_url: %s", blockchain_url) // возможно сервер отдаст блокчейн не с первой попытки var blockchainSize int64 for i := 0; i < 10; i++ { log.Debug("blockchain_url: %s, i: %d", blockchain_url, i) blockchainSize, err = utils.DownloadToFile(blockchain_url, *utils.Dir+"/public/blockchain", 3600, chBreaker, chAnswer, GoroutineName) if err != nil { log.Error("%v", utils.ErrInfo(err)) } if blockchainSize > consts.BLOCKCHAIN_SIZE { break } } log.Debug("blockchain dw ok") if err != nil || blockchainSize < consts.BLOCKCHAIN_SIZE { if err != nil { log.Error("%v", utils.ErrInfo(err)) } else { log.Info(fmt.Sprintf("%v < %v", blockchainSize, consts.BLOCKCHAIN_SIZE)) } if d.unlockPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } first := true /*// блокчейн мог быть загружен ранее. проверим его размер stat, err := file.Stat() if err != nil { if d.unlockPrintSleep(err, d.sleepTime) { break BEGIN } file.Close() continue BEGIN } if stat.Size() < consts.BLOCKCHAIN_SIZE { d.unlockPrintSleep(fmt.Errorf("%v < %v", stat.Size(), consts.BLOCKCHAIN_SIZE), 1) file.Close() continue BEGIN }*/ log.Debug("GO!") file, err := os.Open(*utils.Dir + "/public/blockchain") if err != nil { if d.unlockPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } err = d.ExecSql(`UPDATE config SET current_load_blockchain = 'file'`) if err != nil { if d.unlockPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } for { // проверим, не нужно ли нам выйти из цикла if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) { d.unlockPrintSleep(fmt.Errorf("DaemonsRestart"), 0) break BEGIN } b1 := make([]byte, 5) file.Read(b1) dataSize := utils.BinToDec(b1) log.Debug("dataSize", dataSize) if dataSize > 0 { data := make([]byte, dataSize) file.Read(data) //log.Debug("data %x\n", data) blockId := utils.BinToDec(data[0:5]) if *utils.EndBlockId > 0 && blockId == *utils.EndBlockId { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } file.Close() continue BEGIN } log.Info("blockId", blockId) data2 := data[5:] length := utils.DecodeLength(&data2) log.Debug("length", length) //log.Debug("data2 %x\n", data2) blockBin := utils.BytesShift(&data2, length) //log.Debug("blockBin %x\n", blockBin) if *utils.StartBlockId == 0 || (*utils.StartBlockId > 0 && blockId > *utils.StartBlockId) { // парсинг блока parser.BinaryData = blockBin if first { parser.CurrentVersion = consts.VERSION first = false } err = parser.ParseDataFull() if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } file.Close() continue BEGIN } err = parser.InsertIntoBlockchain() if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } file.Close() continue BEGIN } // отметимся, чтобы не спровоцировать очистку таблиц err = parser.UpdMainLock() if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } file.Close() continue BEGIN } if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } file.Close() continue BEGIN } } // ненужный тут размер в конце блока данных data = make([]byte, 5) file.Read(data) } else { if d.unlockPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } // utils.Sleep(1) } file.Close() } else { newBlock, err := static.Asset("static/1block.bin") if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } parser.BinaryData = newBlock parser.CurrentVersion = consts.VERSION err = parser.ParseDataFull() if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } err = parser.InsertIntoBlockchain() if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } } utils.Sleep(1) d.dbUnlock() continue BEGIN } d.dbUnlock() err = d.ExecSql(`UPDATE config SET current_load_blockchain = 'nodes'`) if err != nil { if d.unlockPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } myConfig, err := d.OneRow("SELECT local_gate_ip, static_node_user_id FROM config").String() if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue } var hosts []map[string]string var nodeHost string var dataTypeMaxBlockId, dataTypeBlockBody int64 if len(myConfig["local_gate_ip"]) > 0 { hosts = append(hosts, map[string]string{"host": myConfig["local_gate_ip"], "user_id": myConfig["static_node_user_id"]}) nodeHost, err = d.Single("SELECT tcp_host FROM miners_data WHERE user_id = ?", myConfig["static_node_user_id"]).String() if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue } dataTypeMaxBlockId = 9 dataTypeBlockBody = 8 //getBlockScriptName = "ajax?controllerName=protectedGetBlock"; //addNodeHost = "&nodeHost="+nodeHost; } else { // получим список нодов, с кем установлено рукопожатие hosts, err = d.GetAll("SELECT * FROM nodes_connection", -1) if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue } dataTypeMaxBlockId = 10 dataTypeBlockBody = 7 //getBlockScriptName = "ajax?controllerName=getBlock"; //addNodeHost = ""; } log.Info("%v", hosts) if len(hosts) == 0 { if d.dPrintSleep(err, 1) { break BEGIN } continue } maxBlockId := int64(1) maxBlockIdHost := "" var maxBlockIdUserId int64 // получим максимальный номер блока for i := 0; i < len(hosts); i++ { if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) { break BEGIN } conn, err := utils.TcpConn(hosts[i]["host"]) if err != nil { if d.dPrintSleep(err, 1) { break BEGIN } continue } // шлем тип данных _, err = conn.Write(utils.DecToBin(dataTypeMaxBlockId, 1)) if err != nil { conn.Close() if d.dPrintSleep(err, 1) { break BEGIN } continue } if len(nodeHost) > 0 { // защищенный режим err = utils.WriteSizeAndData([]byte(nodeHost), conn) if err != nil { conn.Close() if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue } } // в ответ получаем номер блока blockIdBin := make([]byte, 4) _, err = conn.Read(blockIdBin) if err != nil { conn.Close() if d.dPrintSleep(err, 1) { break BEGIN } continue } conn.Close() id := utils.BinToDec(blockIdBin) if id > maxBlockId || i == 0 { maxBlockId = id maxBlockIdHost = hosts[i]["host"] maxBlockIdUserId = utils.StrToInt64(hosts[i]["user_id"]) } if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) { utils.Sleep(1) break BEGIN } } // получим наш текущий имеющийся номер блока // ждем, пока разлочится и лочим сами, чтобы не попасть в тот момент, когда данные из блока уже занесены в БД, а info_block еще не успел обновиться err, restart = d.dbLock() if restart { break BEGIN } if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } currentBlockId, err = d.Single("SELECT block_id FROM info_block").Int64() if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue } log.Info("currentBlockId", currentBlockId, "maxBlockId", maxBlockId) if maxBlockId <= currentBlockId { if d.unlockPrintSleep(utils.ErrInfo(errors.New("maxBlockId <= currentBlockId")), d.sleepTime) { break BEGIN } continue } fmt.Printf("\nnode: %s\n", maxBlockIdHost) // в цикле собираем блоки, пока не дойдем до максимального for blockId := currentBlockId + 1; blockId < maxBlockId+1; blockId++ { d.UpdMainLock() if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } break BEGIN } variables, err := d.GetAllVariables() if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } // качаем тело блока с хоста maxBlockIdHost binaryBlock, err := utils.GetBlockBody(maxBlockIdHost, blockId, dataTypeBlockBody, nodeHost) if len(binaryBlock) == 0 { // баним на 1 час хост, который дал нам пустой блок, хотя должен был дать все до максимального // для тестов убрал, потом вставить. //nodes_ban ($db, $max_block_id_user_id, substr($binary_block, 0, 512)."\n".__FILE__.', '.__LINE__.', '. __FUNCTION__.', '.__CLASS__.', '. __METHOD__); //p.NodesBan(maxBlockIdUserId, "len(binaryBlock) == 0") if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } binaryBlockFull := binaryBlock utils.BytesShift(&binaryBlock, 1) // уберем 1-й байт - тип (блок/тр-я) // распарсим заголовок блока blockData := utils.ParseBlockHeader(&binaryBlock) log.Info("blockData: %v, blockId: %v", blockData, blockId) // если существуют глючная цепочка, тот тут мы её проигнорируем badBlocks_, err := d.Single("SELECT bad_blocks FROM config").Bytes() if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } badBlocks := make(map[int64]string) if len(badBlocks_) > 0 { err = json.Unmarshal(badBlocks_, &badBlocks) if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } } if badBlocks[blockData.BlockId] == string(utils.BinToHex(blockData.Sign)) { d.NodesBan(maxBlockIdUserId, fmt.Sprintf("bad_block = %v => %v", blockData.BlockId, badBlocks[blockData.BlockId])) if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } // размер блока не может быть более чем max_block_size if currentBlockId > 1 { if int64(len(binaryBlock)) > variables.Int64["max_block_size"] { d.NodesBan(maxBlockIdUserId, fmt.Sprintf(`len(binaryBlock) > variables.Int64["max_block_size"] %v > %v`, len(binaryBlock), variables.Int64["max_block_size"])) if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } } if blockData.BlockId != blockId { d.NodesBan(maxBlockIdUserId, fmt.Sprintf(`blockData.BlockId != blockId %v > %v`, blockData.BlockId, blockId)) if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } // нам нужен хэш предыдущего блока, чтобы проверить подпись prevBlockHash := "" if blockId > 1 { prevBlockHash, err = d.Single("SELECT hash FROM block_chain WHERE id = ?", blockId-1).String() if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } prevBlockHash = string(utils.BinToHex([]byte(prevBlockHash))) } else { prevBlockHash = "0" } first := false if blockId == 1 { first = true } // нам нужен меркель-рут текущего блока mrklRoot, err := utils.GetMrklroot(binaryBlock, variables, first) if err != nil { d.NodesBan(maxBlockIdUserId, fmt.Sprintf(`%v`, err)) if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } // публичный ключ того, кто этот блок сгенерил nodePublicKey, err := d.GetNodePublicKey(blockData.UserId) if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } // SIGN от 128 байта до 512 байт. Подпись от TYPE, BLOCK_ID, PREV_BLOCK_HASH, TIME, USER_ID, LEVEL, MRKL_ROOT forSign := fmt.Sprintf("0,%v,%v,%v,%v,%v,%s", blockData.BlockId, prevBlockHash, blockData.Time, blockData.UserId, blockData.Level, mrklRoot) // проверяем подпись if !first { _, err = utils.CheckSign([][]byte{nodePublicKey}, forSign, blockData.Sign, true) } // качаем предыдущие блоки до тех пор, пока отличается хэш предыдущего. // другими словами, пока подпись с prevBlockHash будет неверной, т.е. пока что-то есть в $error if err != nil { log.Error("%v", utils.ErrInfo(err)) if blockId < 1 { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } // нужно привести данные в нашей БД в соответствие с данными у того, у кого качаем более свежий блок //func (p *Parser) GetOldBlocks (userId, blockId int64, host string, hostUserId int64, goroutineName, getBlockScriptName, addNodeHost string) error { err := parser.GetOldBlocks(blockData.UserId, blockId-1, maxBlockIdHost, maxBlockIdUserId, GoroutineName, dataTypeBlockBody, nodeHost) if err != nil { log.Error("%v", err) d.NodesBan(maxBlockIdUserId, fmt.Sprintf(`blockId: %v / %v`, blockId, err)) if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } } else { log.Info("plug found blockId=%v\n", blockId) // получим наши транзакции в 1 бинарнике, просто для удобства var transactions []byte utils.WriteSelectiveLog("SELECT data FROM transactions WHERE verified = 1 AND used = 0") rows, err := d.Query("SELECT data FROM transactions WHERE verified = 1 AND used = 0") if err != nil { utils.WriteSelectiveLog(err) if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } for rows.Next() { var data []byte err = rows.Scan(&data) utils.WriteSelectiveLog(utils.BinToHex(data)) if err != nil { rows.Close() if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } transactions = append(transactions, utils.EncodeLengthPlusData(data)...) } rows.Close() if len(transactions) > 0 { // отмечаем, что эти тр-ии теперь нужно проверять по новой utils.WriteSelectiveLog("UPDATE transactions SET verified = 0 WHERE verified = 1 AND used = 0") affect, err := d.ExecSqlGetAffect("UPDATE transactions SET verified = 0 WHERE verified = 1 AND used = 0") if err != nil { utils.WriteSelectiveLog(err) if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } utils.WriteSelectiveLog("affect: " + utils.Int64ToStr(affect)) // откатываем по фронту все свежие тр-ии parser.BinaryData = transactions err = parser.ParseDataRollbackFront(false) if err != nil { utils.Sleep(1) continue BEGIN } } err = parser.RollbackTransactionsTestblock(true) if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } err = d.ExecSql("DELETE FROM testblock") if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } } // теперь у нас в таблицах всё тоже самое, что у нода, у которого качаем блок // и можем этот блок проверить и занести в нашу БД parser.BinaryData = binaryBlockFull err = parser.ParseDataFull() if err == nil { err = parser.InsertIntoBlockchain() if err != nil { if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } } // начинаем всё с начала уже с другими нодами. Но у нас уже могут быть новые блоки до $block_id, взятые от нода, которого с в итоге мы баним if err != nil { d.NodesBan(maxBlockIdUserId, fmt.Sprintf(`blockId: %v / %v`, blockId, err)) if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } } d.dbUnlock() if d.dSleep(d.sleepTime) { break BEGIN } } log.Debug("break BEGIN %v", GoroutineName) }