func KillPid(pid string) error { err := syscall.Kill(utils.StrToInt(pid), syscall.SIGTERM) if err != nil { return err } return nil }
func (p *Parser) NewMaxOtherCurrenciesRollback() error { currencyList := make(map[string]int64) err := json.Unmarshal(p.TxMap["new_max_other_currencies"], ¤cyList) if err != nil { return p.ErrInfo(err) } var currencyIds []int for k := range currencyList { currencyIds = append(currencyIds, utils.StrToInt(k)) } sort.Sort(sort.Reverse(sort.IntSlice(currencyIds))) for _, currencyId := range currencyIds { //count := currencyList[utils.IntToStr(currencyId)] logId, err := p.Single("SELECT log_id FROM currency WHERE id = ?", currencyId).Int64() if err != nil { return p.ErrInfo(err) } logData, err := p.OneRow("SELECT max_other_currencies, prev_log_id FROM log_currency WHERE log_id = ?", logId).String() if err != nil { return p.ErrInfo(err) } err = p.ExecSql("UPDATE currency SET max_other_currencies = ?, log_id = ? WHERE id = ?", logData["max_other_currencies"], logData["prev_log_id"], currencyId) if err != nil { return p.ErrInfo(err) } err = p.ExecSql("DELETE FROM log_currency WHERE log_id = ?", logId) if err != nil { return p.ErrInfo(err) } p.rollbackAI("log_currency", 1) err = p.ExecSql("DELETE FROM max_other_currencies_time WHERE time = ?", p.BlockData.Time) if err != nil { return p.ErrInfo(err) } } return nil }
func GetLang(w http.ResponseWriter, r *http.Request, parameters map[string]string) int { var lang int = 1 lang = utils.StrToInt(parameters["lang"]) if !CheckLang(lang) { if langCookie, err := r.Cookie("lang"); err == nil { lang, _ = strconv.Atoi(langCookie.Value) } } if !CheckLang(lang) { al := r.Header.Get("Accept-Language") // en-US,en;q=0.5 log.Debug("Accept-Language: %s", r.Header.Get("Accept-Language")) if len(al) >= 2 { if _, ok := consts.LangMap[al[:2]]; ok { lang = consts.LangMap[al[:2]] } } } return lang }
func (p *Parser) NewMaxOtherCurrencies() error { currencyList := make(map[string]int64) err := json.Unmarshal(p.TxMap["new_max_other_currencies"], ¤cyList) if err != nil { return p.ErrInfo(err) } var currencyIds []int for k := range currencyList { currencyIds = append(currencyIds, utils.StrToInt(k)) } sort.Ints(currencyIds) //sort.Sort(sort.Reverse(sort.IntSlice(keys))) for _, currencyId := range currencyIds { count := currencyList[utils.IntToStr(currencyId)] logData, err := p.OneRow("SELECT max_other_currencies, log_id FROM currency WHERE id = ?", currencyId).String() if err != nil { return p.ErrInfo(err) } logId, err := p.ExecSqlGetLastInsertId("INSERT INTO log_currency ( max_other_currencies, prev_log_id ) VALUES ( ?, ? )", "log_id", logData["max_other_currencies"], logData["log_id"]) if err != nil { return p.ErrInfo(err) } err = p.ExecSql("UPDATE currency SET max_other_currencies = ?, log_id = ? WHERE id = ?", count, logId, currencyId) if err != nil { return p.ErrInfo(err) } } err = p.ExecSql("INSERT INTO max_other_currencies_time ( time ) VALUES ( ? )", p.BlockData.Time) if err != nil { return p.ErrInfo(err) } return nil }
func (p *Parser) NewMiner() error { tcpHost := "" if p.BlockData != nil && p.BlockData.BlockId < 250900 { re := regexp.MustCompile(`^https?:\/\/([0-9a-z\_\.\-:]+)\/`) match := re.FindStringSubmatch(p.TxMaps.String["http_host"]) if len(match) != 0 { tcpHost = match[1] + ":8088" } } else { tcpHost = p.TxMaps.String["tcp_host"] } // получим массив майнеров, которые должны скопировать к себе 2 фото лица юзера maxMinerId, err := p.DCDB.Single("SELECT max(miner_id) FROM miners").Int64() if err != nil { return p.ErrInfo(err) } // т.к. у юзера это может быть не первая попытка стать майнером, то отменяем голосования по всем предыдущим err = p.DCDB.ExecSql("UPDATE votes_miners SET votes_end = 1, end_block_id = ? WHERE user_id = ? AND type = 'node_voting' AND end_block_id = 0 AND votes_end = 0", p.BlockData.BlockId, p.TxUserID) if err != nil { return p.ErrInfo(err) } // создаем новое голосование для нодов err = p.DCDB.ExecSql("INSERT INTO votes_miners (type, user_id, votes_start_time) VALUES ('node_voting', ?, ?)", p.TxUserID, p.BlockData.Time) if err != nil { return p.ErrInfo(err) } // переведем все координаты в отрезки. var faceCoords [][2]int err = json.Unmarshal(p.TxMap["face_coords"], &faceCoords) if err != nil { return p.ErrInfo(err) } faceCoords = append([][2]int{{0, 0}}, faceCoords...) // получим отрезки data, err := p.DCDB.OneRow("SELECT segments, version FROM spots_compatibility").String() if err != nil { return p.ErrInfo(err) } spotsVersion := data["version"] var segments map[string]map[string][]string err = json.Unmarshal([]byte(data["segments"]), &segments) if err != nil { return p.ErrInfo(err) } n := len(segments["face"]) + 1 faceRelations := make([]float64, n, n) faceRelations[0] = utils.PpLenght(faceCoords[1], faceCoords[2]) for num, spots := range segments["face"] { // 1. ширина головы // 2. глаз-нос // 3. нос-губа // 4. губа-подбородок // 5. ширина челюсти faceRelations[utils.StrToInt(num)] = utils.Round((utils.PpLenght(faceCoords[utils.StrToInt(spots[0])], faceCoords[utils.StrToInt(spots[1])]) / faceRelations[0]), 4) } faceRelations[0] = 1 // переведем все координаты в отрезки. var profileCoords [][2]int err = json.Unmarshal(p.TxMap["profile_coords"], &profileCoords) if err != nil { return p.ErrInfo(err) } profileCoords = append([][2]int{{0, 0}}, profileCoords...) n = len(segments["profile"]) + 1 profileRelations := make([]float64, n, n) profileRelations[0] = utils.PpLenght(profileCoords[1], profileCoords[2]) for num, spots := range segments["profile"] { // 1. край уха - край носа // 2. глаз - край носа // 3. подбородок - низ уха // 4. верх уха - низ уха profileRelations[utils.StrToInt(num)] = utils.Round((utils.PpLenght(profileCoords[utils.StrToInt(spots[0])], profileCoords[utils.StrToInt(spots[1])]) / profileRelations[0]), 4) } profileRelations[0] = 1 addSql := make(map[string]string) addSql["names"] = "" addSql["values"] = "" addSql["upd"] = "" for j := 1; j < len(faceRelations); j++ { addSql["names"] += fmt.Sprintf("f%v,\n", j) addSql["values"] += fmt.Sprintf("'%v',\n", faceRelations[j]) addSql["upd"] += fmt.Sprintf("f%v='%v',\n", j, faceRelations[j]) } for j := 1; j < len(profileRelations); j++ { addSql["names"] += fmt.Sprintf("p%v,\n", j) addSql["values"] += fmt.Sprintf("'%v',\n", profileRelations[j]) addSql["upd"] += fmt.Sprintf("p%v='%v',\n", j, profileRelations[j]) } addSql["names"] = addSql["names"][0 : len(addSql["names"])-2] addSql["values"] = addSql["values"][0 : len(addSql["values"])-2] addSql["upd"] = addSql["upd"][0 : len(addSql["upd"])-2] // Для откатов // проверим, есть ли в БД запись, которую нужно залогировать logData, err := p.DCDB.OneRow("SELECT * FROM faces WHERE user_id = ?", p.TxUserID).String() if err != nil { return p.ErrInfo(err) } if len(logData) > 0 { addSql1 := "" addSql2 := "" for i := 1; i <= 20; i++ { addSql1 += fmt.Sprintf("f%v, ", i) addSql2 += fmt.Sprintf("%v,", logData[fmt.Sprintf("f%v", i)]) } for i := 1; i <= 20; i++ { addSql1 += fmt.Sprintf("p%v, ", i) addSql2 += fmt.Sprintf("%v,", logData[fmt.Sprintf("p%v", i)]) } // для откатов logId, err := p.ExecSqlGetLastInsertId(` INSERT INTO log_faces ( user_id, version, status, race, country, `+addSql1+` prev_log_id, block_id ) VALUES ( `+logData["user_id"]+`, `+logData["version"]+`, '`+logData["status"]+`', `+logData["race"]+`, `+logData["country"]+`, `+addSql2+` `+logData["log_id"]+`, `+utils.Int64ToStr(p.BlockData.BlockId)+` )`, "log_id") if err != nil { return p.ErrInfo(err) } err = p.ExecSql("UPDATE faces SET "+addSql["upd"]+", version = ?, race = ?, country = ?, log_id = ? WHERE user_id = ?", spotsVersion, p.TxMaps.Int64["race"], p.TxMaps.Int64["country"], logId, p.TxUserID) if err != nil { return p.ErrInfo(err) } } else { // это первая запись в таблицу, и лог писать не с чего err = p.ExecSql(` INSERT INTO faces ( user_id, version, race, country, ` + addSql["names"] + ` ) VALUES ( ` + string(p.TxMap["user_id"]) + `, '` + spotsVersion + `', ` + string(p.TxMap["race"]) + `, ` + string(p.TxMap["country"]) + `, ` + addSql["values"] + ` )`) if err != nil { return p.ErrInfo(err) } } // проверим, есть ли в БД запись, которую надо залогировать logData, err = p.OneRow("SELECT * FROM miners_data WHERE user_id = ?", p.TxUserID).String() if err != nil { return p.ErrInfo(err) } if len(logData) > 0 { logData["node_public_key"] = string(utils.BinToHex([]byte(logData["node_public_key"]))) // для откатов logId, err := p.ExecSqlGetLastInsertId(` INSERT INTO log_miners_data ( user_id, miner_id, status, node_public_key, face_hash, profile_hash, photo_block_id, photo_max_miner_id, miners_keepers, face_coords, profile_coords, video_type, video_url_id, http_host, tcp_host, latitude, longitude, country, block_id, prev_log_id ) VALUES ( ?, ?, ?, [hex], ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) `, "log_id", logData["user_id"], logData["miner_id"], logData["status"], logData["node_public_key"], logData["face_hash"], logData["profile_hash"], logData["photo_block_id"], logData["photo_max_miner_id"], logData["miners_keepers"], logData["face_coords"], logData["profile_coords"], logData["video_type"], logData["video_url_id"], logData["http_host"], logData["tcp_host"], logData["latitude"], logData["longitude"], logData["country"], p.BlockData.BlockId, logData["log_id"]) if err != nil { return p.ErrInfo(err) } // обновляем таблу err = p.ExecSql(` UPDATE miners_data SET node_public_key = [hex], face_hash = ?, profile_hash = ?, photo_block_id = ?, photo_max_miner_id = ?, miners_keepers = ?, face_coords = ?, profile_coords = ?, video_type = ?, video_url_id = ?, latitude = ?, longitude = ?, country = ?, http_host = ?, tcp_host = ?, log_id = ? WHERE user_id = ?`, p.TxMap["node_public_key"], p.TxMaps.String["face_hash"], p.TxMaps.String["profile_hash"], p.BlockData.BlockId, maxMinerId, p.Variables.Int64["miners_keepers"], p.TxMaps.String["face_coords"], p.TxMaps.String["profile_coords"], p.TxMaps.String["video_type"], p.TxMaps.String["video_url_id"], p.TxMaps.Float64["latitude"], p.TxMaps.Float64["longitude"], p.TxMaps.Int64["country"], p.TxMaps.String["http_host"], tcpHost, logId, p.TxUserID) if err != nil { return p.ErrInfo(err) } } else { err = p.ExecSql(` INSERT INTO miners_data ( user_id, node_public_key, face_hash, profile_hash, photo_block_id, photo_max_miner_id, miners_keepers, face_coords, profile_coords, video_type, video_url_id, latitude, longitude, country, http_host, tcp_host ) VALUES (?, [hex], ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, p.TxUserID, p.TxMap["node_public_key"], p.TxMaps.String["face_hash"], p.TxMaps.String["profile_hash"], p.BlockData.BlockId, maxMinerId, p.Variables.Int64["miners_keepers"], p.TxMaps.String["face_coords"], p.TxMaps.String["profile_coords"], p.TxMaps.String["video_type"], p.TxMaps.String["video_url_id"], p.TxMaps.Float64["latitude"], p.TxMaps.Float64["longitude"], p.TxMaps.Int64["country"], p.TxMaps.String["http_host"], tcpHost) if err != nil { return p.ErrInfo(err) } } // проверим, не наш ли это user_id myUserId, myBlockId, myPrefix, _, err := p.GetMyUserId(p.TxUserID) if err != nil { return err } if p.TxUserID == myUserId && myBlockId <= p.BlockData.BlockId { err = p.DCDB.ExecSql("UPDATE "+myPrefix+"my_node_keys SET block_id = ? WHERE hex(public_key) = ?", p.BlockData.BlockId, p.TxMap["node_public_key"]) if err != nil { return p.ErrInfo(err) } } return nil }
func (c *Controller) EncryptComment() (string, error) { var err error c.r.ParseForm() txType := c.r.FormValue("type") var toId int64 var toIds []int64 toIds_ := c.r.FormValue("to_ids") if len(toIds_) == 0 { toId = utils.StrToInt64(c.r.FormValue("to_id")) } else { var toIdsMap map[string]string err = json.Unmarshal([]byte(toIds_), &toIdsMap) if err != nil { return "", utils.ErrInfo(err) } for _, uid := range toIdsMap { if utils.StrToInt64(uid) > 0 { toIds = append(toIds, utils.StrToInt64(uid)) } } } comment := c.r.FormValue("comment") if len(comment) > 1024 { return "", errors.New("incorrect comment") } var toUserId int64 if txType == "project" { toUserId, err = c.Single("SELECT user_id FROM cf_projects WHERE id = ?", toId).Int64() if err != nil { return "", utils.ErrInfo(err) } } else { toUserId = toId } if len(toIds) == 0 { toIds = []int64{toUserId} } log.Debug("toId:", toId) log.Debug("toIds:", toIds) log.Debug("toUserId:", toUserId) enc := make(map[string]string) for i := 0; i < len(toIds); i++ { if toIds[i] == 0 { enc[utils.IntToStr(i)] = "0" continue } // если получатель майнер, тогда шифруем нодовским ключем minersData, err := c.OneRow("SELECT miner_id, node_public_key FROM miners_data WHERE user_id = ?", toIds[i]).String() if err != nil { return "", utils.ErrInfo(err) } var publicKey string if utils.StrToInt(minersData["miner_id"]) > 0 && txType != "cash_request" && txType != "bug_reporting" && txType != "project" && txType != "money_back" && txType != "restoringAccess" { publicKey = minersData["node_public_key"] } else { publicKey, err = c.Single("SELECT public_key_0 FROM users WHERE user_id = ?", toIds[i]).String() if err != nil { return "", utils.ErrInfo(err) } } pub, err := utils.BinToRsaPubKey([]byte(publicKey)) if err != nil { return "", utils.ErrInfo(err) } enc_, err := rsa.EncryptPKCS1v15(rand.Reader, pub, []byte(comment)) if err != nil { return "", utils.ErrInfo(err) } enc[utils.IntToStr(i)] = string(utils.BinToHex(enc_)) } if len(enc) < 5 && len(enc) > 0 { for i := len(enc); i < 5; i++ { enc[utils.IntToStr(i)] = "0" } } log.Debug("enc:", enc) if txType != "arbitration_arbitrators" { return string(enc["0"]), nil } else { result, err := json.Marshal(enc) if err != nil { return "", utils.ErrInfo(err) } return string(result), nil } }
func (c *Controller) Home() (string, error) { log.Debug("first_select: %v", c.Parameters["first_select"]) if c.Parameters["first_select"] == "1" { c.ExecSql(`UPDATE ` + c.MyPrefix + `my_table SET first_select=1`) } var publicKey []byte var poolAdmin bool var cashRequests int64 var showMap bool if c.SessRestricted == 0 { var err error publicKey, err = c.GetMyPublicKey(c.MyPrefix) if err != nil { return "", err } publicKey = utils.BinToHex(publicKey) 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 and time > ?", c.SessUserId, utils.Time()-c.Variables.Int64["cash_request_time"]).Int64() fmt.Println("cashRequests", cashRequests) if err != nil { return "", err } show, err := c.Single("SELECT show_map FROM " + c.MyPrefix + "my_table").Int64() if err != nil { return "", err } if show > 0 { showMap = true } } if c.Community { poolAdminUserId, err := c.GetPoolAdminUserId() if err != nil { return "", err } if c.SessUserId == poolAdminUserId { poolAdmin = true } } wallets, err := c.GetBalances(c.SessUserId) if err != nil { return "", err } //var walletsByCurrency map[string]map[string]string walletsByCurrency := make(map[int]utils.DCAmounts) for _, data := range wallets { walletsByCurrency[int(data.CurrencyId)] = data } blockId, err := c.GetBlockId() if err != nil { return "", err } confirmedBlockId, err := c.GetConfirmedBlockId() if err != nil { return "", err } currencyList, err := c.GetCurrencyList(true) if err != nil { return "", err } for k, v := range currencyList { currencyList[k] = "d" + v } currencyList[1001] = "USD" // задания var assignments int64 count, err := c.Single("SELECT count(id) FROM votes_miners WHERE votes_end = 0 AND type = 'user_voting'").Int64() if err != nil { return "", err } assignments += count // вначале получим ID валют, которые мы можем проверять. currencyIds, err := c.GetList("SELECT currency_id FROM promised_amount WHERE status IN ('mining', 'repaid') AND user_id = ?", c.SessUserId).String() if len(currencyIds) > 0 || c.SessUserId == 1 { addSql := "" if c.SessUserId == 1 { addSql = "" } else { addSql = "AND currency_id IN (" + strings.Join(currencyIds, ",") + ")" } count, err := c.Single("SELECT count(id) FROM promised_amount WHERE status = 'pending' AND del_block_id = 0 " + addSql).Int64() if err != nil { return "", err } assignments += count } if c.SessRestricted == 0 { count, err := c.Single("SELECT count(id) FROM "+c.MyPrefix+"my_tasks WHERE time > ?", time.Now().Unix()-consts.ASSIGN_TIME).Int64() if err != nil { return "", err } assignments -= count if assignments < 0 { assignments = 0 } } // баллы points, err := c.Single("SELECT points FROM points WHERE user_id = ?", c.SessUserId).Int64() if err != nil { return "", err } currency_pct := make(map[int]CurrencyPct) // проценты listPct, err := c.GetMap("SELECT * FROM currency", "id", "name") for id, name := range listPct { pct, err := c.OneRow("SELECT * FROM pct WHERE currency_id = ? ORDER BY block_id DESC", id).Float64() if err != nil { return "", err } currency_pct[utils.StrToInt(id)] = CurrencyPct{Name: name, Miner: (utils.Round((math.Pow(1+pct["miner"], 3600*24*365)-1)*100, 2)), User: (utils.Round((math.Pow(1+pct["user"], 3600*24*365)-1)*100, 2)), MinerBlock: (utils.Round((math.Pow(1+pct["miner"], 120)-1)*100, 4)), UserBlock: (utils.Round((math.Pow(1+pct["user"], 120)-1)*100, 4)), MinerSec: (pct["miner"]), UserSec: (pct["user"])} } // случайне майнеры для нанесения на карту maxMinerId, err := c.Single("SELECT max(miner_id) FROM miners_data").Int64() if err != nil { return "", err } randMiners, err := c.GetList("SELECT user_id FROM miners_data WHERE status = 'miner' AND user_id > 7 AND user_id != 106 AND longitude > 0 AND miner_id IN (" + strings.Join(utils.RandSlice(1, maxMinerId, 3), ",") + ") LIMIT 3").Int64() if err != nil { return "", err } // получаем кол-во DC на кошельках sumWallets_, err := c.GetMap("SELECT currency_id, sum(amount) as sum_amount FROM wallets GROUP BY currency_id", "currency_id", "sum_amount") if err != nil { return "", err } sumWallets := make(map[int]float64) for currencyId, amount := range sumWallets_ { sumWallets[utils.StrToInt(currencyId)] = utils.StrToFloat64(amount) } // получаем кол-во TDC на обещанных суммах, плюсуем к тому, что на кошельках sumTdc, err := c.GetMap("SELECT currency_id, sum(tdc_amount) as sum_amount FROM promised_amount GROUP BY currency_id", "currency_id", "sum_amount") if err != nil { return "", err } for currencyId, amount := range sumTdc { currencyIdInt := utils.StrToInt(currencyId) if sumWallets[currencyIdInt] == 0 { sumWallets[currencyIdInt] = utils.StrToFloat64(amount) } else { sumWallets[currencyIdInt] += utils.StrToFloat64(amount) } } // получаем суммы обещанных сумм sumPromisedAmount, err := c.GetMap("SELECT currency_id, sum(amount) as sum_amount FROM promised_amount WHERE status = 'mining' AND del_block_id = 0 AND (cash_request_out_time = 0 OR cash_request_out_time > ?) GROUP BY currency_id", "currency_id", "sum_amount", time.Now().Unix()-c.Variables.Int64["cash_request_time"]) if err != nil { return "", err } _, _, promisedAmountListGen, err := c.GetPromisedAmounts(c.SessUserId, c.Variables.Int64["cash_request_time"]) calcTotal := utils.Round(100*math.Pow(1+currency_pct[72].MinerSec, 3600*24*30)-100, 0) // токен для запроса инфы с биржи var token, exchangeUrl string if c.SessRestricted == 0 { tokenAndUrl, err := c.OneRow(`SELECT token, e_host FROM ` + c.MyPrefix + `my_tokens LEFT JOIN miners_data ON miners_data.user_id = e_owner_id ORDER BY time DESC LIMIT 1`).String() if err != nil { return "", err } token = tokenAndUrl["token"] exchangeUrl = tokenAndUrl["e_host"] } 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 } // получим топ 5 бирж topExMap := make(map[int64]*topEx) var q string if c.ConfigIni["db_type"] == "postgresql" { //q = "SELECT DISTINCT e_owner_id, e_host, count(votes_exchange.user_id), result from votes_exchange LEFT JOIN miners_data ON votes_exchange.e_owner_id = miners_data.user_id WHERE e_host != '' GROUP BY e_owner_id, result, e_host" q = "SELECT DISTINCT e_owner_id, e_host, count(votes_exchange.user_id), result from miners_data LEFT JOIN votes_exchange ON votes_exchange.e_owner_id = miners_data.user_id WHERE e_host != '' AND result >= 0 GROUP BY e_owner_id, result, e_host" } else { //q = "SELECT e_owner_id, e_host, count(votes_exchange.user_id) as count, result FROM miners_data LEFT JOIN votes_exchange ON votes_exchange.e_owner_id = miners_data.user_id WHERE and e_host != '' GROUP BY votes_exchange.e_owner_id, votes_exchange.result LIMIT 10" q = "SELECT e_owner_id, e_host, count(votes_exchange.user_id) as count, result FROM miners_data LEFT JOIN votes_exchange ON votes_exchange.e_owner_id = miners_data.user_id WHERE e_host != '' AND result >= 0 GROUP BY votes_exchange.e_owner_id, votes_exchange.result LIMIT 10" } rows, err := c.Query(q) if err != nil { return "", utils.ErrInfo(err) } defer rows.Close() for rows.Next() { var user_id, count, result int64 var e_host []byte err = rows.Scan(&user_id, &e_host, &count, &result) if err != nil { return "", utils.ErrInfo(err) } if topExMap[user_id] == nil { topExMap[user_id] = new(topEx) } //if len(topExMap[user_id].Host) == 0 { // topExMap[user_id] = new(topEx) if result == 0 { topExMap[user_id].Vote1 = count } else { topExMap[user_id].Vote1 = count } topExMap[user_id].Host = string(e_host) topExMap[user_id].UserId = user_id //} } // майнер ли я? miner_, err := c.Single(`SELECT miner_id FROM miners_data WHERE user_id = ?`, c.SessUserId).Int64() if err != nil { return "", utils.ErrInfo(err) } var miner bool if miner_ > 0 { miner = true } TemplateStr, err := makeTemplate("home", "home", &homePage{ Community: c.Community, CountSignArr: c.CountSignArr, CountSign: c.CountSign, CalcTotal: calcTotal, Admin: c.Admin, CurrencyPct: currency_pct, SumWallets: sumWallets, Wallets: walletsByCurrency, PromisedAmountListGen: promisedAmountListGen, SessRestricted: c.SessRestricted, SumPromisedAmount: sumPromisedAmount, RandMiners: randMiners, Points: points, Assignments: assignments, CurrencyList: currencyList, ConfirmedBlockId: confirmedBlockId, CashRequests: cashRequests, ShowMap: showMap, BlockId: blockId, UserId: c.SessUserId, PoolAdmin: poolAdmin, Alert: c.Alert, MyNotice: c.MyNotice, Lang: c.Lang, Title: c.Lang["geolocation"], ShowSignData: c.ShowSignData, SignData: "", MyChatName: myChatName, IOS: utils.IOS(), Mobile: utils.Mobile(), TopExMap: topExMap, ChatEnabled: c.NodeConfig["chat_enabled"], Miner: miner, Token: token, ExchangeUrl: exchangeUrl}) if err != nil { return "", utils.ErrInfo(err) } return TemplateStr, 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 Content(w http.ResponseWriter, r *http.Request) { defer func() { if r := recover(); r != nil { log.Error("Content Recovered", r) fmt.Println("Content Recovered", r) } }() var err error w.Header().Set("Content-type", "text/html") sess, err := globalSessions.SessionStart(w, r) if err != nil { log.Error("%v", err) } defer sess.SessionRelease(w) sessUserId := GetSessUserId(sess) sessRestricted := GetSessRestricted(sess) sessPublicKey := GetSessPublicKey(sess) sessAdmin := GetSessAdmin(sess) log.Debug("sessUserId", sessUserId) log.Debug("sessRestricted", sessRestricted) log.Debug("sessPublicKey", sessPublicKey) log.Debug("user_id: %v", sess.Get("user_id")) c := new(Controller) c.r = r c.w = w c.sess = sess c.SessRestricted = sessRestricted c.SessUserId = sessUserId if sessAdmin == 1 { c.Admin = true } c.ContentInc = true var installProgress, configExists string var lastBlockTime int64 dbInit := false if len(configIni["db_user"]) > 0 || (configIni["db_type"] == "sqlite") { dbInit = true } if dbInit { var err error //c.DCDB, err = utils.NewDbConnect(configIni) c.DCDB = utils.DB if c.DCDB.DB == nil { log.Error("utils.DB == nil") dbInit = false } if dbInit { // отсутвие таблы выдаст ошибку, значит процесс инсталяции еще не пройден и надо выдать 0-й шаг _, err = c.DCDB.Single("SELECT progress FROM install").String() if err != nil { log.Error("%v", err) dbInit = false } } } c.dbInit = dbInit if dbInit { var err error installProgress, err = c.DCDB.Single("SELECT progress FROM install").String() if err != nil { log.Error("%v", err) } configExists, err = c.DCDB.Single("SELECT first_load_blockchain_url FROM config").String() if err != nil { log.Error("%v", err) } c.Variables, err = c.GetAllVariables() // Инфа о последнем блоке blockData, err := c.DCDB.GetLastBlockData() if err != nil { log.Error("%v", err) } //время последнего блока lastBlockTime = blockData["lastBlockTime"] log.Debug("installProgress", installProgress, "configExists", configExists, "lastBlockTime", lastBlockTime) // валюты currencyListCf, err := c.GetCurrencyList(true) if err != nil { log.Error("%v", err) } c.CurrencyListCf = currencyListCf currencyList, err := c.GetCurrencyList(false) if err != nil { log.Error("%v", err) } c.CurrencyList = currencyList confirmedBlockId, err := c.GetConfirmedBlockId() if err != nil { log.Error("%v", err) } c.ConfirmedBlockId = confirmedBlockId c.MinerId, err = c.GetMinerId(c.SessUserId) if err != nil { log.Error("%v", err) } paymentSystems, err := c.GetPaymentSystems() if err != nil { log.Error("%v", err) } c.PaymentSystems = paymentSystems } r.ParseForm() tplName := r.FormValue("tpl_name") c.Parameters, err = c.GetParameters() log.Debug("parameters=", c.Parameters) log.Debug("tpl_name=", tplName) // если в параметрах пришел язык, то установим его newLang := utils.StrToInt(c.Parameters["lang"]) if newLang > 0 { log.Debug("newLang", newLang) SetLang(w, r, newLang) } // уведомления //if utils.CheckInputData(parameters["alert"], "alert") { c.Alert = c.Parameters["alert"] //} lang := GetLang(w, r, c.Parameters) log.Debug("lang", lang) c.Lang = globalLangReadOnly[lang] c.LangInt = int64(lang) if lang == 42 { c.TimeFormat = "2006-01-02 15:04:05" } else { c.TimeFormat = "2006-02-01 15:04:05" } c.Periods = map[int64]string{86400: "1 " + c.Lang["day"], 604800: "1 " + c.Lang["week"], 31536000: "1 " + c.Lang["year"], 2592000: "1 " + c.Lang["month"], 1209600: "2 " + c.Lang["weeks"]} c.Races = map[int64]string{1: c.Lang["race_1"], 2: c.Lang["race_2"], 3: c.Lang["race_3"]} var status string var communityUsers []int64 if dbInit { communityUsers, err = c.DCDB.GetCommunityUsers() if err != nil { log.Error("%v", err) } c.CommunityUsers = communityUsers if len(communityUsers) == 0 { c.MyPrefix = "" } else { c.MyPrefix = utils.Int64ToStr(sessUserId) + "_" c.Community = true } log.Debug("c.MyPrefix %s", c.MyPrefix) // нужна мин. комиссия на пуле для перевода монет config, err := c.GetNodeConfig() if err != nil { log.Error("%v", err) } configCommission_ := make(map[string][]float64) if len(config["commission"]) > 0 { err = json.Unmarshal([]byte(config["commission"]), &configCommission_) if err != nil { log.Error("%v", err) } } configCommission := make(map[int64][]float64) for k, v := range configCommission_ { configCommission[utils.StrToInt64(k)] = v } c.NodeConfig = config c.ConfigCommission = configCommission c.NodeAdmin, err = c.NodeAdminAccess(c.SessUserId, c.SessRestricted) if err != nil { log.Error("%v", err) } status, err = c.DCDB.Single("SELECT status FROM " + c.MyPrefix + "my_table").String() if err != nil { log.Error("%v", err) } } log.Debug("dbInit", dbInit) setupPassword := c.NodeConfig["setup_password"] match, _ := regexp.MatchString("^(installStep[0-9_]+)|(blockExplorer)$", tplName) // CheckInputData - гарантирует, что tplName чист if tplName != "" && utils.CheckInputData(tplName, "tpl_name") && (sessUserId > 0 || match) { tplName = tplName } else if dbInit && installProgress == "complete" && len(configExists) == 0 { // первый запуск, еще не загружен блокчейн tplName = "updatingBlockchain" } else if dbInit && installProgress == "complete" && sessUserId > 0 { if status == "waiting_set_new_key" { tplName = "setPassword" } else if status == "waiting_accept_new_key" { tplName = "waitingAcceptNewKey" } } else if dbInit && installProgress == "complete" && !c.Community && sessUserId == 0 && status == "waiting_set_new_key" && setupPassword != "" { tplName = "setupPassword" } else if dbInit && installProgress == "complete" && sessUserId == 0 && status == "waiting_accept_new_key" { tplName = "waitingAcceptNewKey" } else if dbInit && installProgress == "complete" { tplName = "login" } else { tplName = "installStep0" // самый первый запуск } log.Debug("dbInit", dbInit, "installProgress", installProgress, "configExists", configExists) log.Debug("tplName>>>>>>>>>>>>>>>>>>>>>>", tplName) // идет загрузка блокчейна wTime := int64(2) if configIni != nil && configIni["test_mode"] == "1" { wTime = 2 * 365 * 86400 log.Debug("%v", wTime) log.Debug("%v", lastBlockTime) } if dbInit && tplName != "installStep0" && (utils.Time()-lastBlockTime > 3600*wTime) && len(configExists) > 0 { if len(communityUsers) > 0 { // исключение - админ пула poolAdminUserId, err := c.DCDB.Single("SELECT pool_admin_user_id FROM config").String() if err != nil { log.Error("%v", err) } if sessUserId != utils.StrToInt64(poolAdminUserId) { tplName = "updatingBlockchain" } } else { tplName = "updatingBlockchain" } } if tplName == "installStep0" { log.Debug("ConfigInit monitor") if _, err := os.Stat(*utils.Dir + "/config.ini"); err == nil { configIni_, err := config.NewConfig("ini", *utils.Dir+"/config.ini") if err != nil { log.Error("%v", utils.ErrInfo(err)) } configIni, err = configIni_.GetSection("default") if err != nil { log.Error("%v", utils.ErrInfo(err)) } if len(configIni["db_type"]) > 0 { tplName = "updatingBlockchain" } } } log.Debug("tplName2=", tplName) // кол-во ключей=подписей у юзера var countSign int var userId int64 // var myUserId int64 if sessUserId > 0 && dbInit && installProgress == "complete" { userId = sessUserId //myUserId = sessUserId countSign = 1 log.Debug("userId: %d", userId) pk, err := c.OneRow("SELECT hex(public_key_1) as public_key_1, hex(public_key_2) as public_key_2 FROM users WHERE user_id = ?", userId).String() if err != nil { log.Error("%v", err) } log.Debug("pk: %v", pk) if len(pk["public_key_1"]) > 0 { log.Debug("public_key_1: %x", pk["public_key_1"]) countSign = 2 } if len(pk["public_key_2"]) > 0 { log.Debug("public_key_2: %x", pk["public_key_2"]) countSign = 3 } } else { userId = 0 //myUserId = 0 } log.Debug("countSign: %v", countSign) c.UserId = userId var CountSignArr []int for i := 0; i < countSign; i++ { CountSignArr = append(CountSignArr, i) } c.CountSign = countSign c.CountSignArr = CountSignArr if tplName == "" { tplName = "login" } log.Debug("tplName::", tplName, sessUserId, installProgress) if ok, _ := regexp.MatchString(`^(?i)delAutoPayment|newAutoPayment|autoPayments|holidaysList|adminVariables|exchangeAdmin|votesExchange|chat|firstSelect|PoolAdminLogin|setupPassword|waitingAcceptNewKey|SetPassword|CfPagePreview|CfCatalog|AddCfProjectData|CfProjectChangeCategory|NewCfProject|MyCfProjects|DelCfProject|DelCfFunding|CfStart|PoolAdminControl|Credits|Home|WalletsList|Information|Notifications|Interface|MiningMenu|Upgrade5|NodeConfigControl|Upgrade7|Upgrade6|Upgrade5|Upgrade4|Upgrade3|Upgrade2|Upgrade1|Upgrade0|StatisticVoting|ProgressBar|MiningPromisedAmount|CurrencyExchangeDelete|CurrencyExchange|ChangeCreditor|ChangeCommission|CashRequestOut|ArbitrationSeller|ArbitrationBuyer|ArbitrationArbitrator|Arbitration|InstallStep2|InstallStep1|InstallStep0|DbInfo|ChangeHost|Assignments|NewUser|NewPhoto|Voting|VoteForMe|RepaymentCredit|PromisedAmountList|PromisedAmountActualization|NewPromisedAmount|Login|ForRepaidFix|DelPromisedAmount|DelCredit|ChangePromisedAmount|ChangePrimaryKey|ChangeNodeKey|ChangeAvatar|BugReporting|Abuse|UpgradeResend|UpdatingBlockchain|Statistic|RewritePrimaryKey|RestoringAccess|PoolTechWorks|Points|NewHolidays|NewCredit|MoneyBackRequest|MoneyBack|ChangeMoneyBack|ChangeKeyRequest|ChangeKeyClose|ChangeGeolocation|ChangeCountryRace|ChangeArbitratorConditions|CashRequestIn|BlockExplorer$`, tplName); !ok { w.Write([]byte("Access denied 0")) } else if len(tplName) > 0 && sessUserId > 0 && installProgress == "complete" { // если ключ юзера изменился, то выбрасываем его userPublicKey, err := c.DCDB.GetUserPublicKey(userId) if err != nil { log.Error("%v", err) } // но возможно у юзера включено сохранение приватного ключа // тогда, чтобы не получилось зацикливания, нужно проверить и my_keys myPrivateKey, err := c.GetMyPrivateKey(c.MyPrefix) if err != nil { log.Error("%v", err) } myPublicKey, err := c.GetMyPublicKey(c.MyPrefix) if err != nil { log.Error("%v", err) } countUsers, err := c.Single(`SELECT count(*) FROM users`).Int64() if err != nil { log.Error("%v", err) } if (string(utils.BinToHex(userPublicKey)) != sessPublicKey && len(myPrivateKey) == 0) || (countUsers > 0 && len(myPrivateKey) > 0 && !bytes.Equal(myPublicKey, []byte(userPublicKey))) { log.Debug("userPublicKey!=sessPublicKey %s!=%s / userId: %d", utils.BinToHex(userPublicKey), sessPublicKey, userId) log.Debug("len(myPrivateKey) = %d && %x!=%x", len(myPrivateKey), string(myPublicKey), userPublicKey) sess.Delete("user_id") sess.Delete("private_key") sess.Delete("public_key") log.Debug("window.location.href = /") if len(userPublicKey) > 0 { w.Write([]byte("<script language=\"javascript\">window.location.href = \"/\"</script>If you are not redirected automatically, follow the <a href=\"/\">/</a>")) return } else { c.sess.Delete("user_id") c.sess.Delete("public_key") c.sess.Delete("private_key") } } if tplName == "login" { tplName = "home" } if tplName == "home" && c.Parameters["first_select"] != "1" { data, err := c.OneRow(`SELECT first_select, miner_id from ` + c.MyPrefix + `my_table`).Int64() if err != nil { log.Error("%v", err) } if data["first_select"] == 0 && data["miner_id"] == 0 && c.SessRestricted == 0 { tplName = "firstSelect" } } c.TplName = tplName log.Debug("communityUsers:", communityUsers) if dbInit && len(communityUsers) > 0 { poolAdminUserId, err := c.GetPoolAdminUserId() if err != nil { log.Error("%v", err) } c.PoolAdminUserId = poolAdminUserId if c.SessUserId == poolAdminUserId { c.PoolAdmin = true } } else { c.PoolAdmin = true } if dbInit { // проверим, не идут ли тех. работы на пуле config, err := c.DCDB.OneRow("SELECT pool_admin_user_id, pool_tech_works FROM config").String() if err != nil { log.Error("%v", err) } if len(config["pool_admin_user_id"]) > 0 && utils.StrToInt64(config["pool_admin_user_id"]) != sessUserId && config["pool_tech_works"] == "1" && c.Community { tplName = "login" } // Если у юзера только 1 праймари ключ, то выдавать форму, где показываются данные для подписи и форма ввода подписи не нужно. // Только если он сам не захочет, указав это в my_table showSignData := false if sessRestricted == 0 { // у незареганных в пуле юзеров нет MyPrefix, поэтому сохранять значение show_sign_data им негде showSignData_, err := c.DCDB.Single("SELECT show_sign_data FROM " + c.MyPrefix + "my_table").String() if err != nil { log.Error("%v", err) } if showSignData_ == "1" { showSignData = true } else { showSignData = false } } if showSignData || countSign > 1 { c.ShowSignData = true } else { c.ShowSignData = false } } // писать в чат можно и при апдейте блокчейна if r.FormValue("tpl_name") == "chat" && tplName == "updatingBlockchain" { tplName = "chat" } if dbInit && tplName != "updatingBlockchain" && tplName != "setPassword" && tplName != "waitingAcceptNewKey" { html, err := CallController(c, "AlertMessage") if err != nil { log.Error("%v", err) } w.Write([]byte(html)) } w.Write([]byte("<input type='hidden' id='tpl_name' value='" + tplName + "'>")) myNotice, err := c.DCDB.GetMyNoticeData(sessRestricted, sessUserId, c.MyPrefix, globalLangReadOnly[lang]) if err != nil { log.Error("%v", err) } c.MyNotice = myNotice log.Debug("tplName==", tplName) // подсвечиваем красным номер блока, если идет процесс обновления var blockJs string blockId, err := c.GetBlockId() if err != nil { log.Error("%v", err) } if myNotice["main_status_complete"] != "1" { blockJs = "$('#block_id').html(" + utils.Int64ToStr(blockId) + ");$('#block_id').css('color', '#ff0000');" } else { blockJs = "$('#block_id').html(" + utils.Int64ToStr(blockId) + ");$('#block_id').css('color', '#428BCA');" } w.Write([]byte(`<script> $( document ).ready(function() { $('.lng_1').attr('href', '#` + tplName + `/lang=1'); $('.lng_42').attr('href', '#` + tplName + `/lang=42'); ` + blockJs + ` }); </script>`)) skipRestrictedUsers := []string{"cashRequestIn", "cashRequestOut", "upgrade", "notifications"} // тем, кто не зареган на пуле не выдаем некоторые страницы if sessRestricted == 0 || !utils.InSliceString(tplName, skipRestrictedUsers) { // вызываем контроллер в зависимости от шаблона html, err := CallController(c, tplName) if err != nil { log.Error("%v", err) } w.Write([]byte(html)) } } else if len(tplName) > 0 { log.Debug("tplName", tplName) html := "" if ok, _ := regexp.MatchString(`^(?i)blockExplorer|waitingAcceptNewKey|SetupPassword|CfCatalog|CfPagePreview|CfStart|Check_sign|CheckNode|GetBlock|GetMinerData|GetMinerDataMap|GetSellerData|Index|IndexCf|InstallStep0|InstallStep1|InstallStep2|Login|SignLogin|SynchronizationBlockchain|UpdatingBlockchain|Menu$`, tplName); !ok && c.SessUserId <= 0 { html = "Access denied 1" } else { // если сессия обнулилась в процессе навигации по админке, то вместо login шлем на /, чтобы очистилось меню if len(r.FormValue("tpl_name")) > 0 && tplName == "login" { log.Debug("window.location.href = /") w.Write([]byte("<script language=\"javascript\">window.location.href = \"/\"</script>If you are not redirected automatically, follow the <a href=\"/\">/</a>")) return } // вызываем контроллер в зависимости от шаблона html, err = CallController(c, tplName) if err != nil { log.Error("%v", err) } } w.Write([]byte(html)) } else { html, err := CallController(c, "login") if err != nil { log.Error("%v", err) } w.Write([]byte(html)) } //sess.Set("username", 11111) }
func (c *Controller) GetChatMessages() (string, error) { c.r.ParseForm() first := c.r.FormValue("first") room := utils.StrToInt64(c.r.FormValue("room")) lang := utils.StrToInt64(c.r.FormValue("lang")) if first == "1" { chatIds[c.SessUserId] = []int{} } maxId, err := c.Single(`SELECT max(id) FROM chat`).Int64() if err != nil { return "", utils.ErrInfo(err) } // удалим старое err = c.ExecSql(`DELETE FROM chat WHERE id < ?`, maxId-consts.CHAT_MAX_MESSAGES) if err != nil { return "", utils.ErrInfo(err) } ids := "" if len(chatIds[c.SessUserId]) > 0 { ids = `AND id NOT IN(` + strings.Join(utils.IntSliceToStr(chatIds[c.SessUserId]), ",") + `)` } var result string chatData, err := c.GetAll(`SELECT * FROM chat WHERE sign_time > ? AND room = ? AND lang = ? `+ids+` ORDER BY sign_time DESC LIMIT `+utils.Int64ToStr(consts.CHAT_COUNT_MESSAGES), consts.CHAT_COUNT_MESSAGES, chatMinSignTime, room, lang) if err != nil { return "", utils.ErrInfo(err) } for i := len(chatData) - 1; i >= 0; i-- { data := chatData[i] status := data["status"] message := data["message"] receiver := utils.StrToInt64(data["receiver"]) sender := utils.StrToInt64(data["sender"]) if status == "1" { // Если юзер хранит приватый ключ в БД, то сможем расшифровать прямо тут if receiver == c.SessUserId { privateKey, err := c.GetMyPrivateKey(c.MyPrefix) if err != nil { log.Error("%v", utils.ErrInfo(err)) continue } if len(privateKey) > 0 { rsaPrivateKey, err := utils.MakePrivateKey(privateKey) if err != nil { log.Error("%v", utils.ErrInfo(err)) continue } decrypted, err := rsa.DecryptPKCS1v15(rand.Reader, rsaPrivateKey, utils.HexToBin([]byte(data["message"]))) if err != nil { log.Error("%v", utils.ErrInfo(err)) continue } if len(decrypted) > 0 { err = c.ExecSql(`UPDATE chat SET enc_message = message, message = ?, status = ? WHERE id = ?`, decrypted, 2, data["id"]) if err != nil { log.Error("%v", utils.ErrInfo(err)) continue } message = string(decrypted) status = "2" } } } } name := data["sender"] ava := "/static/img/noavatar.png" // возможно у отпарвителя есть ник nameAvaBan, err := c.OneRow(`SELECT name, avatar, chat_ban FROM users WHERE user_id = ?`, sender).String() if err != nil { return "", utils.ErrInfo(err) } // возможно юзер забанен if nameAvaBan["chat_ban"] == "1" { continue } if len(nameAvaBan["name"]) > 0 { name = nameAvaBan["name"] } minerStatus, err := c.Single(`SELECT status FROM miners_data WHERE user_id = ?`, sender).String() if err != nil { return "", utils.ErrInfo(err) } if minerStatus == "miner" && len(nameAvaBan["avatar"]) > 0 { ava = nameAvaBan["avatar"] } row := "" message = template.HTMLEscapeString(message) avaHtml := `<img src="` + ava + `" onclick='setReceiver("` + name + `", "` + data["sender"] + `")'>` nameHtml := `<strong><a class="chatNick" onclick='setReceiver("` + name + `", "` + data["sender"] + `")'>` + name + `</a></strong>` if status == "2" { // успешно расшифровали row = `<tr><td>` + avaHtml + `` + nameHtml + `: <i class="fa fa-lock"></i> ` + message + `</td></tr>` } else if status == "1" && receiver == c.SessUserId { // либо нет ключа, либо какая-то ошибка row = `<tr><td>` + avaHtml + `` + nameHtml + `: <div id="comment_` + data["id"] + `" style="display: inline-block;"><input type="hidden" value="` + message + `" id="encrypt_comment_` + data["id"] + `"><a class="btn btn-default btn-lg" onclick="decrypt_comment(` + data["id"] + `, 'chat')"> <i class="fa fa-lock"></i> Decrypt</a></div></td></tr>` } else if status == "0" { row = `<tr><td>` + avaHtml + `` + nameHtml + `: ` + message + `</td></tr>` } result += row chatIds[c.SessUserId] = append(chatIds[c.SessUserId], utils.StrToInt(data["id"])) if first == "1" { if utils.StrToInt64(data["sign_time"]) < chatMinSignTime || chatMinSignTime == 0 { chatMinSignTime = utils.StrToInt64(data["sign_time"]) log.Debug("chatMinSignTime", chatMinSignTime) } } } log.Debug("chat data: %v", result) chatStatus := "ok" if len(utils.ChatInConnections) == 0 || len(utils.ChatOutConnections) == 0 { chatStatus = "bad" } resultJson, _ := json.Marshal(map[string]string{"messages": result, "chatStatus": chatStatus}) return string(resultJson), nil }
func makeTemplate(html, name string, tData interface{}) (string, error) { defer func() { if r := recover(); r != nil { log.Error("makeTemplate Recovered", r) fmt.Println(r) } }() data, err := static.Asset("static/templates/" + html + ".html") if err != nil { return "", utils.ErrInfo(err) } signatures, err := static.Asset("static/templates/signatures.html") if err != nil { return "", utils.ErrInfo(err) } alert_success, err := static.Asset("static/templates/alert_success.html") if err != nil { return "", utils.ErrInfo(err) } funcMap := template.FuncMap{ "makeCurrencyName": func(currencyId int64) string { if currencyId >= 1000 { return "" } else { return "d" } }, "div": func(a, b interface{}) float64 { return utils.InterfaceToFloat64(a) / utils.InterfaceToFloat64(b) }, "mult": func(a, b interface{}) float64 { return utils.InterfaceToFloat64(a) * utils.InterfaceToFloat64(b) }, "round": func(a interface{}, num int) float64 { return utils.Round(utils.InterfaceToFloat64(a), num) }, "len": func(s []map[string]string) int { return len(s) }, "lenMap": func(s map[string]string) int { return len(s) }, "sum": func(a, b interface{}) float64 { return utils.InterfaceToFloat64(a) + utils.InterfaceToFloat64(b) }, "minus": func(a, b interface{}) float64 { return utils.InterfaceToFloat64(a) - utils.InterfaceToFloat64(b) }, "noescape": func(s string) template.HTML { return template.HTML(s) }, "js": func(s string) template.JS { return template.JS(s) }, "join": func(s []string, sep string) string { return strings.Join(s, sep) }, "strToInt64": func(text string) int64 { return utils.StrToInt64(text) }, "strToInt": func(text string) int { return utils.StrToInt(text) }, "bin2hex": func(text string) string { return string(utils.BinToHex([]byte(text))) }, "int64ToStr": func(text int64) string { return utils.Int64ToStr(text) }, "rand": func() int { return utils.RandInt(0, 99999999) }, "append": func(args ...interface{}) string { var result string for _, value := range args { switch value.(type) { case int64: result += utils.Int64ToStr(value.(int64)) case float64: result += utils.Float64ToStr(value.(float64)) case string: result += value.(string) } } return result }, "replaceCurrency": func(text, name string) string { return strings.Replace(text, "[currency]", name, -1) }, "replaceCurrencyName": func(text, name string) string { return strings.Replace(text, "[currency]", "D"+name, -1) }, "cfCategoryLang": func(lang map[string]string, name string) string { return lang["cf_category_"+name] }, "progressBarLang": func(lang map[string]string, name string) string { return lang["progress_bar_pct_"+name] }, "checkProjectPs": func(ProjectPs map[string]string, id string) bool { if len(ProjectPs["ps"+id]) > 0 { return true } else { return false } }, "cfPageTypeLang": func(lang map[string]string, name string) string { return lang["cf_"+name] }, "notificationsLang": func(lang map[string]string, name string) string { return lang["notifications_"+name] }, } t := template.Must(template.New("template").Funcs(funcMap).Parse(string(data))) t = template.Must(t.Parse(string(alert_success))) t = template.Must(t.Parse(string(signatures))) b := new(bytes.Buffer) err = t.ExecuteTemplate(b, name, tData) if err != nil { return "", utils.ErrInfo(err) } return b.String(), nil }
func ContentE(w http.ResponseWriter, r *http.Request) { var err error if utils.DB != nil && utils.DB.DB != nil { sess, _ := globalSessions.SessionStart(w, r) defer sess.SessionRelease(w) c := new(Controller) c.r = r c.SessUserId = GetSessEUserId(sess) c.DCDB = utils.DB r.ParseForm() tplName := r.FormValue("page") c.Parameters, err = c.GetParameters() log.Debug("parameters=", c.Parameters) lang := GetLang(w, r, c.Parameters) c.Lang = globalLangReadOnly[lang] c.LangInt = int64(lang) if lang == 42 { c.TimeFormat = "2006-01-02 15:04:05" } else { c.TimeFormat = "2006-02-01 15:04:05" } // если в параметрах пришел язык, то установим его newLang := utils.StrToInt(c.Parameters["lang"]) if newLang > 0 { log.Debug("newLang", newLang) SetLang(w, r, newLang) } c.EConfig, err = c.GetMap(`SELECT * FROM e_config`, "name", "value") if err != nil { log.Error("%v", err) } c.EURL = c.EConfig["domain"] if len(c.EURL) == 0 { eHost, err := c.Single(`SELECT http_host FROM config`).String() if err != nil { log.Error("%v", err) } eHost += c.EConfig["catalog"] c.EURL = eHost } else { c.EURL = "http://" + c.EURL + "/" } html := "" if ok, _ := regexp.MatchString(`^(?i)EPages|emain|EMyOrders|EMyHistory|EMyFinance`, tplName); !ok { html = "Access denied" } else { // вызываем контроллер в зависимости от шаблона html, err = CallController(c, tplName) if err != nil { log.Error("%v", err) } } w.Write([]byte(html)) } }
func (p *Parser) VotesComplexRollback() error { currencyVotes := make(map[string][]float64) if p.BlockData.BlockId > 77951 { vComplex, err := makeVcomplex(p.TxMap["json_data"]) if err != nil { return p.ErrInfo(err) } if p.BlockData.BlockId > 153750 && vComplex.Admin != 0 { err := p.selectiveRollback([]string{"admin_user_id", "time"}, "votes_admin", "user_id="+string(p.TxMap["user_id"]), false) if err != nil { return p.ErrInfo(err) } } // голоса за реф. % err = p.selectiveRollback([]string{"first", "second", "third"}, "votes_referral", "user_id="+string(p.TxMap["user_id"]), false) if err != nil { return p.ErrInfo(err) } currencyVotes = vComplex.Currency } else { // раньше не было рефских и выбора админа vComplex := make(map[string][]float64) err := json.Unmarshal(p.TxMap["json_data"], &vComplex) if err != nil { return p.ErrInfo(err) } currencyVotes = vComplex } // сортируем по $currency_id в обратном порядке var currencyIds []int for k := range currencyVotes { currencyIds = append(currencyIds, utils.StrToInt(k)) } sort.Sort(sort.Reverse(sort.IntSlice(currencyIds))) for _, currencyId := range currencyIds { currencyIdStr := utils.IntToStr(currencyId) // miner_pct err := p.selectiveRollback([]string{"pct", "time"}, "votes_miner_pct", "user_id="+string(p.TxMap["user_id"])+" AND currency_id = "+currencyIdStr, false) if err != nil { return p.ErrInfo(err) } // user_pct err = p.selectiveRollback([]string{"pct"}, "votes_user_pct", "user_id="+string(p.TxMap["user_id"])+" AND currency_id = "+currencyIdStr, false) if err != nil { return p.ErrInfo(err) } // reduction err = p.selectiveRollback([]string{"pct", "time"}, "votes_reduction", "user_id="+string(p.TxMap["user_id"])+" AND currency_id = "+currencyIdStr, false) if err != nil { return p.ErrInfo(err) } // max_promised_amount err = p.selectiveRollback([]string{"amount"}, "votes_max_promised_amount", "user_id="+string(p.TxMap["user_id"])+" AND currency_id = "+currencyIdStr, false) if err != nil { return p.ErrInfo(err) } // max_other_currencies err = p.selectiveRollback([]string{"count"}, "votes_max_other_currencies", "user_id="+string(p.TxMap["user_id"])+" AND currency_id = "+currencyIdStr, false) if err != nil { return p.ErrInfo(err) } // проверим, не наш ли это user_id myUserId, _, myPrefix, _, err := p.GetMyUserId(p.TxUserID) if err != nil { return p.ErrInfo(err) } if p.TxUserID == myUserId { // отметимся, что голосовали, чтобы не пришло уведомление о необходимости голосовать раз в 2 недели err = p.ExecSql("DELETE FROM "+myPrefix+"my_complex_votes WHERE last_voting =?", p.BlockData.Time) if err != nil { return p.ErrInfo(err) } } } return nil }
func (p *Parser) VotesComplex() error { currencyVotes := make(map[string][]float64) if p.BlockData.BlockId > 77951 { vComplex, err := makeVcomplex(p.TxMap["json_data"]) if err != nil { return p.ErrInfo(err) } currencyVotes = vComplex.Currency // голоса за реф. % p.selectiveLoggingAndUpd([]string{"first", "second", "third"}, []interface{}{vComplex.Referral["first"], vComplex.Referral["second"], vComplex.Referral["third"]}, "votes_referral", []string{"user_id"}, []string{string(p.TxMap["user_id"])}) // раньше не было выборов админа if p.BlockData.BlockId >= 153750 && vComplex.Admin > 0 { p.selectiveLoggingAndUpd([]string{"admin_user_id", "time"}, []interface{}{vComplex.Admin, p.TxTime}, "votes_admin", []string{"user_id"}, []string{string(p.TxMap["user_id"])}) } } else { // раньше не было рефских и выбора админа vComplex := make(map[string][]float64) err := json.Unmarshal(p.TxMap["json_data"], &vComplex) if err != nil { return p.ErrInfo(err) } currencyVotes = vComplex } var currencyIds []int for k := range currencyVotes { currencyIds = append(currencyIds, utils.StrToInt(k)) } sort.Ints(currencyIds) //sort.Sort(sort.Reverse(sort.IntSlice(keys))) for _, currencyId := range currencyIds { data := currencyVotes[utils.IntToStr(currencyId)] currencyIdStr := utils.IntToStr(currencyId) UserIdStr := string(p.TxMap["user_id"]) // miner_pct err := p.selectiveLoggingAndUpd([]string{"pct", "time"}, []interface{}{utils.Float64ToStr(data[0]), p.TxTime}, "votes_miner_pct", []string{"user_id", "currency_id"}, []string{UserIdStr, currencyIdStr}) if err != nil { return p.ErrInfo(err) } // user_pct err = p.selectiveLoggingAndUpd([]string{"pct"}, []interface{}{utils.Float64ToStr(data[1])}, "votes_user_pct", []string{"user_id", "currency_id"}, []string{UserIdStr, currencyIdStr}) if err != nil { return p.ErrInfo(err) } // max_promised_amount err = p.selectiveLoggingAndUpd([]string{"amount"}, []interface{}{int64(data[2])}, "votes_max_promised_amount", []string{"user_id", "currency_id"}, []string{UserIdStr, currencyIdStr}) if err != nil { return p.ErrInfo(err) } // max_other_currencies err = p.selectiveLoggingAndUpd([]string{"count"}, []interface{}{int64(data[3])}, "votes_max_other_currencies", []string{"user_id", "currency_id"}, []string{UserIdStr, currencyIdStr}) if err != nil { return p.ErrInfo(err) } // reduction err = p.selectiveLoggingAndUpd([]string{"pct", "time"}, []interface{}{int64(data[4]), p.TxTime}, "votes_reduction", []string{"user_id", "currency_id"}, []string{UserIdStr, currencyIdStr}) if err != nil { return p.ErrInfo(err) } // проверим, не наш ли это user_id myUserId, myBlockId, myPrefix, _, err := p.GetMyUserId(p.TxUserID) if err != nil { return p.ErrInfo(err) } if p.TxUserID == myUserId && myBlockId <= p.BlockData.BlockId { // отметимся, что голосовали, чтобы не пришло уведомление о необходимости голосовать раз в 2 недели // может быть дубль, поэтому ошибки не проверяем p.ExecSql("INSERT INTO "+myPrefix+"my_complex_votes ( last_voting ) VALUES ( ? )", p.BlockData.Time) } } return nil }
func ContentCf(w http.ResponseWriter, r *http.Request) { c := new(Controller) c.r = r dbInit := false if len(configIni["db_user"]) > 0 || (configIni["db_type"] == "sqlite") { dbInit = true } if dbInit { var err error c.DCDB = utils.DB if c.DCDB.DB == nil { log.Error("utils.DB == nil") dbInit = false } // отсутвие таблы выдаст ошибку, значит процесс инсталяции еще не пройден и надо выдать 0-й шаг _, err = c.DCDB.Single("SELECT progress FROM install").String() if err != nil { log.Error("%v", err) dbInit = false } cfUrl, err := c.GetCfUrl() if len(cfUrl) == 0 { w.Write([]byte("die")) return } //c.CfUrl = cfUrl r.ParseForm() tplName := r.FormValue("tpl_name") c.Parameters, err = c.GetParameters() log.Debug("parameters=", c.Parameters) lang := GetLang(w, r, c.Parameters) c.Lang = globalLangReadOnly[lang] log.Debug("c.Lang:", c.Lang) c.LangInt = int64(lang) // если в параметрах пришел язык, то установим его newLang := utils.StrToInt(c.Parameters["lang"]) if newLang > 0 { log.Debug("newLang", newLang) SetLang(w, r, newLang) } config, err := c.GetNodeConfig() sess, _ := globalSessions.SessionStart(w, r) defer sess.SessionRelease(w) c.SessUserId = GetSessUserId(sess) if config["pool_admin_user_id"] != "0" && config["pool_admin_user_id"] != utils.Int64ToStr(c.SessUserId) && config["pool_tech_works"] != "1" { tplName = "pool_tech_works" } else if len(tplName) > 0 { if ok, _ := regexp.MatchString("^[\\w]{1,30}$", tplName); !ok { tplName = "cfCatalog" } } else { tplName = "cfCatalog" } html := "" if ok, _ := regexp.MatchString(`^(?i)CfPagePreview|CfCatalog|AddCfProjectData|CfProjectChangeCategory|NewCfProject|MyCfProjects|DelCfProject|DelCfFunding|CfStart$`, tplName); !ok { html = "Access denied" } else { // вызываем контроллер в зависимости от шаблона html, err = CallController(c, tplName) if err != nil { log.Error("%v", err) } } w.Write([]byte(html)) } }
func Shop(chBreaker chan bool, chAnswer chan string) { defer func() { if r := recover(); r != nil { log.Error("daemon Recovered", r) panic(r) } }() const GoroutineName = "Shop" 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 = 120 } 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 } myBlockId, err := d.GetMyBlockId() blockId, err := d.GetBlockId() if myBlockId > blockId { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue } currencyList, err := d.GetCurrencyList(false) if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue } // нужно знать текущий блок, который есть у большинства нодов blockId, err = d.GetConfirmedBlockId() if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue } // сколько должно быть подтверждений, т.е. кол-во блоков сверху confirmations := int64(5) // берем всех юзеров по порядку community, err := d.GetCommunityUsers() if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue } for _, userId := range community { privateKey := "" myPrefix := utils.Int64ToStr(userId) + "_" allTables, err := d.GetAllTables() if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } if !utils.InSliceString(myPrefix+"my_keys", allTables) { continue } // проверим, майнер ли minerId, err := d.GetMinerId(userId) if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } if minerId > 0 { // наш приватный ключ нода, которым будем расшифровывать комменты privateKey, err = d.GetNodePrivateKey(myPrefix) if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } } // возможно, что комменты будут зашифрованы юзерским ключем if len(privateKey) == 0 { privateKey, err = d.GetMyPrivateKey(myPrefix) if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } } // если это еще не майнер и админ ноды не указал его приватный ключ в табле my_keys, то $private_key будет пуст if len(privateKey) == 0 { continue } myData, err := d.OneRow("SELECT shop_secret_key, shop_callback_url FROM " + myPrefix + "my_table").String() if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } // Получаем инфу о входящих переводах и начисляем их на счета юзеров dq := d.GetQuotes() rows, err := d.Query(d.FormatQuery(` SELECT id, block_id, type_id, currency_id, amount, to_user_id, comment_status, comment FROM `+dq+myPrefix+`my_dc_transactions`+dq+` WHERE type = 'from_user' AND block_id < ? AND merchant_checked = 0 AND status = 'approved' ORDER BY id DESC `), blockId-confirmations) if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } for rows.Next() { var id, block_id, type_id, currency_id, to_user_id int64 var comment_status, comment string var amount float64 err = rows.Scan(&id, &block_id, &type_id, ¤cy_id, &amount, &to_user_id, &comment_status, &comment) if err != nil { rows.Close() if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } if len(myData["shop_callback_url"]) == 0 { // отметим merchant_checked=1, чтобы больше не брать эту тр-ию err = d.ExecSql("UPDATE "+myPrefix+"my_dc_transactions SET merchant_checked = 1 WHERE id = ?", id) if err != nil { rows.Close() if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } continue } // вначале нужно проверить, точно ли есть такой перевод в блоке 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 } // сравнение данных из таблы my_dc_transactions с тем, что в блоке if utils.BytesToInt64(txMap["user_id"]) == userId && utils.BytesToInt64(txMap["currency_id"]) == currency_id && utils.BytesToFloat64(txMap["amount"]) == amount && string(utils.BinToHex(txMap["comment"])) == comment && utils.BytesToInt64(txMap["to_user_id"]) == to_user_id { decryptedComment := comment // расшифруем коммент if comment_status == "encrypted" { block, _ := pem.Decode([]byte(privateKey)) 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, []byte(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 } } // возможно, что чуть раньше было reduction, а это значит, что все тр-ии, // которые мы ещё не обработали и которые были До блока с reduction нужно принимать с учетом reduction // т.к. средства на нашем счете уже урезались, а вот те, что после reduction - остались в том виде, в котором пришли lastReduction, err := d.OneRow("SELECT block_id, pct FROM reduction WHERE currency_id = ? ORDER BY block_id", currency_id).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) } // делаем запрос к callback скрипту r, _ := regexp.Compile(`(?i)\s*#\s*([0-9]+)\s*`) order := r.FindStringSubmatch(decryptedComment) orderId := 0 if len(order) > 0 { orderId = utils.StrToInt(order[1]) } txId := id sign := fmt.Sprintf("%v:%v:%v:%v:%v:%v:%v:%v", amount, currencyList[currency_id], orderId, decryptedComment, txMap["user_id"], blockId, txId, myData["shop_secret_key"]) data := url.Values{} data.Add("amount", utils.Float64ToStrPct(amount)) data.Add("currency", currencyList[currency_id]) data.Add("order_id", utils.IntToStr(orderId)) data.Add("message", decryptedComment) data.Add("user_id", string(txMap["user_id"])) data.Add("block_id", string(txMap["block_id"])) data.Add("tx_id", utils.Int64ToStr(txId)) data.Add("sign", sign) client := &http.Client{} req, err := http.NewRequest("POST", myData["shop_callback_url"], bytes.NewBufferString(data.Encode())) if err != nil { rows.Close() if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } req.Header.Add("Content-Type", "application/x-www-form-urlencoded") req.Header.Add("Content-Length", utils.IntToStr(len(data.Encode()))) resp, err := client.Do(req) if err != nil { rows.Close() if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } //contents, _ := ioutil.ReadAll(resp.Body) if resp.StatusCode == 200 { // отметим merchant_checked=1, чтобы больше не брать эту тр-ию err = d.ExecSql("UPDATE "+myPrefix+"my_dc_transactions SET merchant_checked = 1 WHERE id = ?", id) if err != nil { rows.Close() if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } } } } } rows.Close() } if d.dSleep(d.sleepTime) { break BEGIN } } log.Debug("break BEGIN %v", GoroutineName) }
func Connector(chBreaker chan bool, chAnswer chan string) { defer func() { if r := recover(); r != nil { log.Error("daemon Recovered", r) panic(r) } }() if _, err := os.Stat(*utils.Dir + "/nodes.inc"); os.IsNotExist(err) { data, err := static.Asset("static/nodes.inc") if err != nil { log.Error("%v", err) } err = ioutil.WriteFile(*utils.Dir+"/nodes.inc", []byte(data), 0644) if err != nil { log.Error("%v", err) } } GoroutineName := "Connector" d := new(daemon) d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName) if d.DCDB == nil { return } d.goRoutineName = GoroutineName d.chAnswer = chAnswer d.chBreaker = chBreaker if utils.Mobile() { d.sleepTime = 600 } else { d.sleepTime = 30 } if !d.CheckInstall(chBreaker, chAnswer, GoroutineName) { return } d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName) if d.DCDB == nil { return } // соединения для чата иногда отваливаются, поэтому в цикле мониторим состояние go func() { for { if myUserIdForChat == 0 { utils.Sleep(1) continue } if len(utils.ChatOutConnections) < 5 || len(utils.ChatInConnections) < 5 { go d.chatConnector() } utils.Sleep(30) } }() BEGIN: for { log.Info(GoroutineName) MonitorDaemonCh <- []string{GoroutineName, utils.Int64ToStr(utils.Time())} // проверим, не нужно ли нам выйти из цикла if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) { break BEGIN } nodeConfig, err := d.GetNodeConfig() if len(nodeConfig["local_gate_ip"]) > 0 { utils.Sleep(2) continue } var delMiners []string var hosts []map[string]string var nodeCount int64 idArray := make(map[int]int64) nodesInc := make(map[string]string) // ровно стольким нодам мы будем слать хэши блоков и тр-ий var maxHosts = consts.OUT_CONNECTIONS if utils.StrToInt64(nodeConfig["out_connections"]) > 0 { maxHosts = utils.StrToInt(nodeConfig["out_connections"]) } log.Info("%v", maxHosts) collective, err := d.GetCommunityUsers() if err != nil { log.Error("%v", err) return } if len(collective) == 0 { myUserId, err := d.GetMyUserId("") if err != nil { log.Error("%v", err) return } collective = append(collective, myUserId) myUserIdForChat = myUserId } else { myUserIdForChat, err = d.Single(`SELECT pool_admin_user_id FROM config`).Int64() if err != nil { log.Error("%v", err) return } } // в сингл-моде будет только $my_miners_ids[0] myMinersIds, err := d.GetMyMinersIds(collective) if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue } log.Info("%v", myMinersIds) nodesBan, err := d.GetMap(` SELECT tcp_host, ban_start FROM nodes_ban LEFT JOIN miners_data ON miners_data.user_id = nodes_ban.user_id `, "tcp_host", "ban_start") log.Info("%v", nodesBan) nodesConnections, err := d.GetAll(` SELECT nodes_connection.host, nodes_connection.user_id, ban_start, miner_id FROM nodes_connection LEFT JOIN nodes_ban ON nodes_ban.user_id = nodes_connection.user_id LEFT JOIN miners_data ON miners_data.user_id = nodes_connection.user_id `, -1) //fmt.Println("nodesConnections", nodesConnections) log.Debug("nodesConnections: %v", nodesConnections) for _, data := range nodesConnections { // проверим, не нужно нам выйти, т.к. обновилась версия софта if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) { break BEGIN } /*// проверим соотвествие хоста и user_id ok, err := d.Single("SELECT user_id FROM miners_data WHERE user_id = ? AND tcp_host = ?", data["user_id"], data["host"]).Int64() if err != nil { utils.Sleep(1) continue BEGIN } if ok == 0 { err = d.ExecSql("DELETE FROM nodes_connection WHERE host = ? OR user_id = ?", data["host"], data["user_id"]) if err != nil { utils.Sleep(1) continue BEGIN } }*/ // если нода забанена недавно if utils.StrToInt64(data["ban_start"]) > utils.Time()-consts.NODE_BAN_TIME { delMiners = append(delMiners, data["miner_id"]) err = d.ExecSql("DELETE FROM nodes_connection WHERE host = ? OR user_id = ?", data["host"], data["user_id"]) if err != nil { if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) { break BEGIN } continue BEGIN } continue } hosts = append(hosts, map[string]string{"host": data["host"], "user_id": data["user_id"]}) nodesInc[data["host"]] = data["user_id"] nodeCount++ } log.Debug("hosts: %v", hosts) /* ch := make(chan *answerType) for _, host := range hosts { userId := utils.StrToInt64(host["user_id"]) go func(userId int64, host string) { ch_ := make(chan *answerType, 1) go func() { log.Debug("host: %v / userId: %v", host, userId) ch_ <- check(host, userId) }() select { case reachable := <-ch_: ch <- reachable case <-time.After(consts.WAIT_CONFIRMED_NODES * time.Second): ch <- &answerType{userId: userId, answer: 0} } }(userId, host["host"]) } log.Debug("%v", "hosts", hosts) var newHosts []map[string]string var countOk int // если нода не отвечает, то удалем её из таблы nodes_connection for i := 0; i < len(hosts); i++ { result := <-ch if result.answer == 0 { log.Info("delete %v", result.userId) err = d.ExecSql("DELETE FROM nodes_connection WHERE user_id = ?", result.userId) if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } } for _, data := range hosts { if utils.StrToInt64(data["user_id"]) != result.userId { newHosts = append(newHosts, data) } } } else { countOk++ } log.Info("answer: %v", result) } */ var countOk int hosts = checkHosts(hosts, &countOk) log.Debug("countOk: %d / hosts: %v", countOk, hosts) // проверим, не нужно нам выйти, т.к. обновилась версия софта if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) { break BEGIN } // добьем недостающие хосты до $max_hosts var newHostsForCheck []map[string]string if len(hosts) < maxHosts { need := maxHosts - len(hosts) max, err := d.Single("SELECT max(miner_id) FROM miners").Int() if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } i0 := 0 for { rand := 1 if max > 1 { rand = utils.RandInt(1, max+1) } idArray[rand] = 1 i0++ if i0 > 30 || len(idArray) >= need || len(idArray) >= max { break } } log.Info("%v", "idArray", idArray) // удалим себя for _, id := range myMinersIds { delete(idArray, int(id)) } // Удалим забаннные хосты for _, id := range delMiners { delete(idArray, utils.StrToInt(id)) } log.Info("%v", "idArray", idArray) ids := "" if len(idArray) > 0 { for id, _ := range idArray { ids += utils.IntToStr(id) + "," } ids = ids[:len(ids)-1] minersHosts, err := d.GetMap(` SELECT tcp_host, user_id FROM miners_data WHERE miner_id IN (`+ids+`)`, "tcp_host", "user_id") if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } for host, userId := range minersHosts { if len(nodesBan[host]) > 0 { if utils.StrToInt64(nodesBan[host]) > utils.Time()-consts.NODE_BAN_TIME { continue } } //hosts = append(hosts, map[string]string{"host": host, "user_id": userId}) /*err = d.ExecSql("DELETE FROM nodes_connection WHERE host = ?", host) if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } log.Debug(host)*/ newHostsForCheck = append(newHostsForCheck, map[string]string{"user_id": userId, "host": host}) /*err = d.ExecSql("INSERT INTO nodes_connection ( host, user_id ) VALUES ( ?, ? )", host, userId) if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN }*/ } } } hosts = checkHosts(newHostsForCheck, &countOk) log.Debug("countOk: %d / hosts: %v", countOk, hosts) // проверим, не нужно нам выйти, т.к. обновилась версия софта if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) { break BEGIN } log.Debug("%v", "hosts", hosts) // если хосты не набрались из miner_data, то берем из файла if len(hosts) < 10 { hostsData_, err := ioutil.ReadFile(*utils.Dir + "/nodes.inc") if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } hostsData := strings.Split(string(hostsData_), "\n") log.Debug("%v", "hostsData_", hostsData_) log.Debug("%v", "hostsData", hostsData) max := 0 log.Debug("maxHosts: %v", maxHosts) if len(hosts) > maxHosts-1 { max = maxHosts } else { max = len(hostsData) } log.Debug("max: %v", max) for i := 0; i < max; i++ { r := utils.RandInt(0, max) if len(hostsData) <= r { continue } hostUserId := strings.Split(hostsData[r], ";") if len(hostUserId) == 1 { continue } host, userId := hostUserId[0], hostUserId[1] if utils.InSliceInt64(utils.StrToInt64(userId), collective) { continue } if len(nodesBan[host]) > 0 { if utils.StrToInt64(nodesBan[host]) > utils.Time()-consts.NODE_BAN_TIME { continue } } /* err = d.ExecSql("DELETE FROM nodes_connection WHERE host = ?", host) if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } log.Debug(host) /*err = d.ExecSql("INSERT INTO nodes_connection ( host, user_id ) VALUES ( ?, ? )", host, userId) if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN }*/ newHostsForCheck = append(newHostsForCheck, map[string]string{"user_id": userId, "host": host}) nodesInc[host] = userId } } hosts = checkHosts(newHostsForCheck, &countOk) log.Debug("countOk: %d / hosts: %v", countOk, hosts) // проверим, не нужно нам выйти, т.к. обновилась версия софта if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) { break BEGIN } for _, host := range hosts { err = d.ExecSql("DELETE FROM nodes_connection WHERE host = ?", host["host"]) if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } err = d.ExecSql("INSERT INTO nodes_connection ( host, user_id ) VALUES ( ?, ? )", host["host"], host["user_id"]) if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } } if nodeCount > 5 { nodesFile := "" for k, v := range nodesInc { nodesFile += k + ";" + v + "\n" } nodesFile = nodesFile[:len(nodesFile)-1] err := ioutil.WriteFile(*utils.Dir+"/nodes.inc", []byte(nodesFile), 0644) if err != nil { if d.dPrintSleep(err, d.sleepTime) { break BEGIN } continue BEGIN } } var sleepTime int if countOk < 2 { sleepTime = 5 } else { sleepTime = d.sleepTime } if d.dSleep(sleepTime) { break BEGIN } } log.Debug("break BEGIN %v", GoroutineName) }
func (p *Parser) VotesMinerRollback() error { userId, err := p.Single("SELECT user_id FROM votes_miners WHERE id = ?", p.TxMaps.Int64["vote_id"]).Int64() if err != nil { return p.ErrInfo(err) } // обновляем голоса err = p.ExecSql("UPDATE votes_miners SET votes_"+utils.Int64ToStr(p.TxMaps.Int64["result"])+" = votes_"+utils.Int64ToStr(p.TxMaps.Int64["result"])+" - 1, votes_end = 0 WHERE id = ?", p.TxMaps.Int64["vote_id"]) if err != nil { return p.ErrInfo(err) } // узнаем последствия данного голоса data, err := p.OneRow("SELECT miner_id, user_id, status FROM miners_data WHERE user_id = ?", userId).String() if err != nil { return p.ErrInfo(err) } // удаляем нашу запись из log_votes err = p.ExecSql("DELETE FROM log_votes WHERE user_id = ? AND voting_id = ? AND type = 'votes_miners'", p.TxMaps.Int64["user_id"], p.TxMaps.Int64["vote_id"]) if err != nil { return p.ErrInfo(err) } // сделал ли голос из юзера майнера? if utils.StrToInt(data["miner_id"]) != 0 { err = p.insOrUpdMinersRollback(utils.StrToInt64(data["miner_id"])) if err != nil { return p.ErrInfo(err) } // меняем статус err = p.ExecSql("UPDATE miners_data SET status = 'user', miner_id = 0, reg_time = 0 WHERE user_id = ?", userId) if err != nil { return p.ErrInfo(err) } // всем, кому ставили del_block_id, убираем, т.е. отменяем будущее удаление по крону err = p.ExecSql("UPDATE log_votes SET del_block_id = 0 WHERE voting_id = ? AND type = 'votes_miners' AND del_block_id = ?", p.TxMaps.Int64["vote_id"], p.BlockData.BlockId) if err != nil { return p.ErrInfo(err) } // обновлять faces не нужно, т.к. статус там и так = used // проверим, не наш ли это user_id myUserId, _, myPrefix, _, err := p.GetMyUserId(utils.StrToInt64(data["user_id"])) if err != nil { return p.ErrInfo(err) } if utils.StrToInt64(data["user_id"]) == myUserId { // обновим статус в нашей локальной табле. // sms/email не трогаем, т.к. смена из-за отката маловажна, и в большинстве случаев статус всё равно сменится. err = p.ExecSql("UPDATE " + myPrefix + "my_table SET status = 'user', miner_id = 0, host_status = 'my_pending' WHERE status != 'bad_key'") if err != nil { return p.ErrInfo(err) } } } else { // был ли данный голос решающим-отрицательным // т.к. после окончания нодовского голосования и начала юзреского статус у face всегда = used (для избежания одновременной регистрации тысяч клонов), то // смена статуса на pending означает, что юзерское голосание было завершено с отрициательным результатом err = p.ExecSql("UPDATE faces SET status = 'used' WHERE user_id = ? AND status = 'pending'", userId) if err != nil { return p.ErrInfo(err) } } // вычитаем баллы err = p.pointsRollback(p.Variables.Int64["miner_points"]) if err != nil { return p.ErrInfo(err) } return nil }