func (p *Parser) ChangePrimaryKeyFront() error { err := p.generalCheck() if err != nil { return p.ErrInfo(err) } if !utils.CheckInputData(p.newPublicKeysHex[0], "public_key") { return p.ErrInfo("public_key") } if len(p.newPublicKeysHex[1]) > 0 && !utils.CheckInputData(p.newPublicKeysHex[1], "public_key") { return p.ErrInfo("public_key 1") } if len(p.newPublicKeysHex[2]) > 0 && !utils.CheckInputData(p.newPublicKeysHex[2], "public_key") { return p.ErrInfo("public_key 2") } forSign := fmt.Sprintf("%s,%s,%s,%s,%s,%s", p.TxMap["type"], p.TxMap["time"], p.TxMap["user_id"], p.newPublicKeysHex[0], p.newPublicKeysHex[1], p.newPublicKeysHex[2]) 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") } err = p.limitRequest(p.Variables.Int64["limit_primary_key"], "primary_key", p.Variables.Int64["limit_primary_key_period"]) if err != nil { return p.ErrInfo(err) } return nil }
func (p *Parser) ChangeCaFront() error { err := p.generalCheck() if err != nil { return p.ErrInfo(err) } if !utils.CheckInputData(p.TxMaps.String["ca1"], "ca_url") && p.TxMaps.String["ca1"] != "0" { return fmt.Errorf("incorrect ca1") } if !utils.CheckInputData(p.TxMaps.String["ca2"], "ca_url") && p.TxMaps.String["ca2"] != "0" { return fmt.Errorf("incorrect ca2") } if !utils.CheckInputData(p.TxMaps.String["ca3"], "ca_url") && p.TxMaps.String["ca3"] != "0" { return fmt.Errorf("incorrect ca3") } forSign := fmt.Sprintf("%s,%s,%s,%s,%s,%s", p.TxMap["type"], p.TxMap["time"], p.TxMap["user_id"], p.TxMap["ca1"], p.TxMap["ca2"], p.TxMap["ca3"]) 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") } err = p.limitRequest(consts.LIMIT_CHANGE_CA, "change_ca", consts.LIMIT_CHANGE_CA_PERIOD) if err != nil { return p.ErrInfo(err) } return nil }
func (c *Controller) SaveHost() (string, error) { if c.SessRestricted != 0 { return "", utils.ErrInfo(errors.New("Permission denied")) } c.r.ParseForm() http_host := c.r.FormValue("http_host") if len(http_host) > 0 && http_host[len(http_host)-1:] != "/" { http_host += "/" } tcp_host := c.r.FormValue("tcp_host") if !utils.CheckInputData(http_host, "http_host") { return `{"error":"1"}`, nil } if !utils.CheckInputData(tcp_host, "tcp_host") { return `{"error":"1"}`, nil } err := c.ExecSql("UPDATE "+c.MyPrefix+"my_table SET http_host = ?, tcp_host = ?", http_host, tcp_host) if err != nil { return "", utils.ErrInfo(err) } return `{"error":"0"}`, nil }
func (p *Parser) VotesNodeNewMinerFront() error { err := p.generalCheck() if err != nil { return p.ErrInfo(err) } // является ли данный юзер майнером err = p.checkMiner(p.TxUserID) if err != nil { return err } if !utils.CheckInputData(p.TxMap["result"], "vote") { return utils.ErrInfoFmt("incorrect vote") } // получим public_key p.nodePublicKey, err = p.GetNodePublicKey(p.TxUserID) if len(p.nodePublicKey) == 0 { return utils.ErrInfoFmt("incorrect user_id len(nodePublicKey) = 0") } if !utils.CheckInputData(p.TxMap["vote_id"], "bigint") { return utils.ErrInfoFmt("incorrect bigint") } forSign := fmt.Sprintf("%s,%s,%s,%s,%s", p.TxMap["type"], p.TxMap["time"], p.TxMap["user_id"], p.TxMap["vote_id"], p.TxMap["result"]) CheckSignResult, err := utils.CheckSign([][]byte{p.nodePublicKey}, forSign, p.TxMap["sign"], true) if err != nil { return p.ErrInfo(err) } if !CheckSignResult { return utils.ErrInfoFmt("incorrect sign") } // проверим, верно ли указан ID и не закончилось ли голосование id, err := p.Single("SELECT id FROM votes_miners WHERE id = ? AND type = 'node_voting' AND votes_end = 0", p.TxMaps.Int64["vote_id"]).Int64() if err != nil { return p.ErrInfo(err) } if id == 0 { return p.ErrInfo(fmt.Errorf("voting is over")) } // проверим, не повторное ли это голосование данного юзера num, err := p.Single("SELECT count(user_id) FROM log_votes WHERE user_id = ? AND voting_id = ? AND type = 'votes_miners'", p.TxMaps.Int64["user_id"], p.TxMaps.Int64["vote_id"]).Int64() if err != nil { return p.ErrInfo(err) } if num > 0 { return utils.ErrInfoFmt("double voting") } // нод не должен голосовать более X раз за сутки, чтобы не было доса err = p.limitRequest(p.Variables.Int64["node_voting"], "votes_nodes", p.Variables.Int64["node_voting_period"]) if err != nil { return p.ErrInfo(err) } return nil }
func (p *Parser) VotesMinerFront() error { err := p.generalCheck() if err != nil { return p.ErrInfo(err) } if !utils.CheckInputData(p.TxMap["vote_id"], "bigint") { return p.ErrInfo("incorrect vote_id") } if !utils.CheckInputData(p.TxMap["result"], "vote") { return p.ErrInfo("incorrect vote_id") } if !utils.CheckInputData(p.TxMap["comment"], "votes_comment") { return p.ErrInfo("incorrect comment") } // является ли данный юзер майнером err = p.checkMiner(p.TxUserID) if err != nil { return p.ErrInfo(err) } // проверим, верно ли указан ID и не закончилось ли голосование id, err := p.Single("SELECT id FROM votes_miners WHERE id = ? AND type = 'user_voting' AND votes_end = 0", p.TxMaps.Int64["vote_id"]).Int() if err != nil { return p.ErrInfo(err) } if id == 0 { return p.ErrInfo("voting is over") } // проверим, не повторное ли это голосование данного юзера num, err := p.Single("SELECT count(user_id) FROM log_votes WHERE user_id = ? AND voting_id = ? AND type = 'votes_miners'", p.TxMaps.Int64["user_id"], p.TxMaps.Int64["vote_id"]).Int() if err != nil { return p.ErrInfo("double voting") } if num > 0 { return p.ErrInfo("double voting") } forSign := fmt.Sprintf("%s,%s,%s,%s,%s,%s", p.TxMap["type"], p.TxMap["time"], p.TxMap["user_id"], p.TxMap["vote_id"], p.TxMap["result"], p.TxMap["comment"]) 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") } // защита от доса err = p.maxDayVotes() if err != nil { return p.ErrInfo(err) } return nil }
func (c *Controller) RewritePrimaryKeySave() (string, error) { if !c.NodeAdmin || c.SessRestricted != 0 { return "", utils.ErrInfo(errors.New("Permission denied")) } if len(c.r.FormValue("n")) > 0 { c.r.ParseForm() n := []byte(c.r.FormValue("n")) e := []byte(c.r.FormValue("e")) if !utils.CheckInputData(n, "hex") { return "", utils.ErrInfo(errors.New("incorrect n")) } if !utils.CheckInputData(e, "hex") { return "", utils.ErrInfo(errors.New("incorrect e")) } publicKey := utils.MakeAsn1(n, e) // проверим, есть ли вообще такой публичный ключ userId, err := c.Single("SELECT user_id FROM users WHERE hex(public_key_0) = ?", publicKey).Int64() if err != nil { return "", utils.ErrInfo(err) } if userId == 0 { return "", utils.ErrInfo(errors.New("incorrect public_key")) } // может быть юзер уже майнер? minerId, err := c.GetMinerId(userId) if err != nil { return "", utils.ErrInfo(err) } status := "" if minerId > 0 { status = "miner" } else { status = "user" } err = c.ExecSql(`DELETE FROM my_keys`) if err != nil { return "", utils.ErrInfo(err) } err = c.ExecSql(`INSERT INTO `+c.MyPrefix+`my_keys (public_key, status) VALUES ([hex], ?)`, publicKey, "approved") if err != nil { return "", utils.ErrInfo(err) } err = c.ExecSql(`UPDATE `+c.MyPrefix+`my_table SET user_id = ?, miner_id = ?, status = ?`, userId, minerId, status) if err != nil { return "", utils.ErrInfo(err) } } return `{"success":"success"}`, nil }
func (c *Controller) EWithdraw() (string, error) { if c.SessUserId == 0 { return "", errors.New(c.Lang["sign_up_please"]) } c.r.ParseForm() currencyId := utils.StrToInt64(c.r.FormValue("currency_id")) if !utils.CheckInputData(c.r.FormValue("amount"), "amount") { return "", fmt.Errorf("incorrect amount") } method := c.r.FormValue("method") if !utils.CheckInputData(method, "method") { return "", fmt.Errorf("incorrect method") } account := c.r.FormValue("account") if !utils.CheckInputData(account, "account") { return "", fmt.Errorf("incorrect account") } amount := utils.StrToFloat64(c.r.FormValue("amount")) curTime := utils.Time() // нужно проверить, есть ли нужная сумма на счету юзера userAmount := utils.EUserAmountAndProfit(c.SessUserId, currencyId) if userAmount < amount { return "", fmt.Errorf("%s (%f<%f)", c.Lang["not_enough_money"], userAmount, amount) } if method != "Dcoin" && currencyId < 1000 { return "", fmt.Errorf("incorrect method") } err := userLock(c.SessUserId) if err != nil { return "", utils.ErrInfo(err) } err = c.ExecSql(`UPDATE e_wallets SET amount = ?, last_update = ? WHERE user_id = ? AND currency_id = ?`, userAmount-amount, curTime, c.SessUserId, currencyId) if err != nil { return "", utils.ErrInfo(err) } var commission float64 if method == "Dcoin" { commission = utils.StrToFloat64(c.EConfig["dc_commission"]) } else if method == "Perfect-money" { commission = utils.StrToFloat64(c.EConfig["pm_commission"]) } wdAmount := utils.ClearNull(utils.Float64ToStr(amount*(1-commission/100)), 2) err = c.ExecSql(`INSERT INTO e_withdraw (open_time, user_id, currency_id, account, amount, wd_amount, method) VALUES (?, ?, ?, ?, ?, ?, ?)`, curTime, c.SessUserId, currencyId, account, amount, wdAmount, method) if err != nil { return "", utils.ErrInfo(err) } userUnlock(c.SessUserId) return utils.JsonAnswer(c.Lang["request_is_created"], "success").String(), nil }
func (c *Controller) EPages() (string, error) { var err error var title, text string if len(c.Parameters["page"]) > 0 { if !utils.CheckInputData(c.Parameters["page"], "string") { return "", utils.ErrInfo(err) } data, err := c.OneRow(`SELECT title, text from e_pages WHERE name = ? AND lang = ?`, c.Parameters["page"], c.LangInt).String() if err != nil { return "", utils.ErrInfo(err) } title = data["title"] text = data["text"] } TemplateStr, err := makeTemplate("e_pages", "ePages", &ePages{ Lang: c.Lang, Title: title, Text: text}) if err != nil { return "", utils.ErrInfo(err) } return TemplateStr, nil }
func (c *Controller) ERedirect() (string, error) { c.r.ParseForm() token := c.r.FormValue("FormToken") amount := c.r.FormValue("FormExAmount") buyCurrencyId := utils.StrToInt64(c.r.FormValue("FormDC")) if !utils.CheckInputData(token, "string") { return "", errors.New("incorrect data") } // order_id занесем когда поуступят деньги в платежной системе err := c.ExecSql(`UPDATE e_tokens SET buy_currency_id = ?, amount_fiat = ? WHERE token = ?`, buyCurrencyId, utils.StrToFloat64(c.r.FormValue("FormExAmount")), token) if err != nil { return "", utils.ErrInfo(err) } tokenId, err := c.Single(`SELECT id FROM e_tokens WHERE token = ?`, token).String() if err != nil { return "", utils.ErrInfo(err) } TemplateStr, err := makeTemplate("e_redirect", "eRedirect", &ERedirectPage{ Lang: c.Lang, EConfig: c.EConfig, TokenId: tokenId, EURL: c.EURL, MDesc: base64.StdEncoding.EncodeToString([]byte("token-" + tokenId)), Amount: amount}) if err != nil { return "", utils.ErrInfo(err) } return TemplateStr, nil }
func (p *Parser) UserAvatarFront() error { err := p.generalCheck() if err != nil { return p.ErrInfo(err) } verifyData := map[string]string{"name": "user_name"} err = p.CheckInputData(verifyData) if err != nil { return p.ErrInfo(err) } if !utils.CheckInputData(p.TxMaps.String["avatar"], "img_url") && p.TxMaps.String["avatar"] != "0" { return fmt.Errorf("incorrect avatar") } forSign := fmt.Sprintf("%s,%s,%s,%s,%s", p.TxMap["type"], p.TxMap["time"], p.TxMap["user_id"], p.TxMap["name"], p.TxMap["avatar"]) 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") } err = p.limitRequest(consts.LIMIT_USER_AVATAR, "user_avatar", consts.LIMIT_USER_AVATAR_PERIOD) if err != nil { return p.ErrInfo(err) } return nil }
func (c *Controller) CheckCfCurrency() (string, error) { if c.SessRestricted != 0 { return "", utils.ErrInfo(errors.New("Permission denied")) } c.r.ParseForm() projectCurrencyName := c.r.FormValue("project_currency_name") if !utils.CheckInputData(projectCurrencyName, "cf_currency_name") { return "", errors.New("incorrect project_currency_name") } // проверим, не занято ли имя валюты currency, err := c.Single("SELECT id FROM cf_projects WHERE project_currency_name = ? AND close_block_id = 0 AND del_block_id = 0", projectCurrencyName).Int64() if err != nil { return "", utils.ErrInfo(err) } if currency > 0 { return `{"error":"` + c.Lang["currency_name_busy"] + `"}`, nil } // проверим, не занято ли имя валюты currency, err = c.Single("SELECT id FROM cf_currency WHERE name = ?", projectCurrencyName).Int64() if err != nil { return "", utils.ErrInfo(err) } if currency > 0 { return `{"error":"` + c.Lang["currency_name_busy"] + `"}`, nil } return `{"success":"` + c.Lang["name_is_not_occupied"] + `"}`, nil }
func (p *Parser) NewUserFront() error { log.Debug("NewUserFront") err := p.generalCheck() if err != nil { return p.ErrInfo(err) } // является ли данный юзер майнером err = p.checkMiner(p.TxUserID) if err != nil { return p.ErrInfo(err) } // прошло ли 30 дней с момента регистрации майнера err = p.checkMinerNewbie() if err != nil { return p.ErrInfo(err) } // чтобы не записали слишком мелкий или слишком крупный ключ if !utils.CheckInputData(p.TxMap["public_key_hex"], "public_key") { return utils.ErrInfo(fmt.Errorf("incorrect public_key %s", p.TxMap["public_key_hex"])) } // публичный ключ должен быть без паролей if ok, _ := regexp.MatchString("DEK-Info: (.+),(.+)", string(p.TxMap["public_key"])); ok { return p.ErrInfo("incorrect public_key") } forSign := fmt.Sprintf("%s,%s,%s,%s", p.TxMap["type"], p.TxMap["time"], p.TxMap["user_id"], p.TxMap["public_key_hex"]) 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") } // один ключ не может быть у двух юзеров num, err := p.DCDB.Single("SELECT count(user_id) FROM users WHERE hex(public_key_0) = ? OR hex(public_key_1) = ? OR hex(public_key_2) = ?", p.TxMap["public_key_hex"], p.TxMap["public_key_hex"], p.TxMap["public_key_hex"]).Int() if num > 0 { return p.ErrInfo("exists public_key") } err = p.getAdminUserId() if err != nil { return p.ErrInfo(err) } if utils.BytesToInt64(p.TxMap["user_id"]) == p.AdminUserId { err = p.limitRequest(1000, "new_user", 86400) } else { err = p.limitRequest(p.Variables.Int64["limit_new_user"], "new_user", p.Variables.Int64["limit_new_user_period"]) } if err != nil { return p.ErrInfo(err) } return nil }
func (p *Parser) AbusesFront() error { err := p.generalCheck() if err != nil { return p.ErrInfo(err) } var abuses map[string]string err = json.Unmarshal(p.TxMap["abuses"], &abuses) if err != nil { return p.ErrInfo(err) } if len(abuses) > 100 { return fmt.Errorf(">100") } for userId, comment := range abuses { if !utils.CheckInputData(userId, "user_id") { return fmt.Errorf("incorrect abuses user_id") } if !utils.CheckInputData(comment, "abuse_comment") { return fmt.Errorf("incorrect abuse_comment") } // является ли данный юзер майнером err = p.checkMiner(utils.StrToInt64(userId)) if err != nil { return p.ErrInfo(err) } } forSign := fmt.Sprintf("%s,%s,%s,%s", p.TxMap["type"], p.TxMap["time"], p.TxMap["user_id"], p.TxMap["abuses"]) 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") } err = p.limitRequest(p.Variables.Int64["limit_abuses"], "abuses", p.Variables.Int64["limit_abuses_period"]) if err != nil { return p.ErrInfo(err) } return nil }
func (p *Parser) AdminSpotsFront() error { err := p.generalCheckAdmin() if err != nil { return p.ErrInfo(err) } if !utils.CheckInputData(p.TxMap["compatibility"], "compatibility") { return p.ErrInfo("incorrect compatibility") } exampleSpots := new(exampleSpotsType) if err := json.Unmarshal([]byte(p.TxMap["example_spots"]), &exampleSpots); err != nil { return p.ErrInfo("incorrect example_spots") } if exampleSpots.Face == nil || exampleSpots.Profile == nil { return p.ErrInfo("incorrect example_spots") } segments := new(exampleSpotsType) if err := json.Unmarshal([]byte(p.TxMap["segments"]), &segments); err != nil { return p.ErrInfo("incorrect segments") } if segments.Face == nil || segments.Profile == nil { return p.ErrInfo("incorrect segments") } tolerances := new(tolerancesType) if err := json.Unmarshal([]byte(p.TxMap["tolerances"]), &tolerances); err != nil { return p.ErrInfo("incorrect tolerances") } if tolerances.Face == nil || tolerances.Profile == nil { return p.ErrInfo("incorrect tolerances") } forSign := fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s", p.TxMap["type"], p.TxMap["time"], p.TxMap["user_id"], p.TxMap["example_spots"], p.TxMap["segments"], p.TxMap["tolerances"], p.TxMap["compatibility"]) 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") } return nil }
func (c *Controller) EInfo() (string, error) { c.w.Header().Set("Access-Control-Allow-Origin", "*") c.r.ParseForm() token := c.r.FormValue("token") if !utils.CheckInputData(token, "string") { return "", errors.New("incorrect token") } tokenMap, err := c.OneRow(`SELECT * FROM e_tokens WHERE token = ?`, token).String() if err != nil { return "", utils.ErrInfo(err) } wallets, err := c.GetAll(`SELECT * FROM e_wallets WHERE user_id = ?`, 100, tokenMap["user_id"]) if err != nil { return "", utils.ErrInfo(err) } orders, err := c.GetAll(`SELECT * FROM e_orders WHERE user_id = ? ORDER BY time DESC LIMIT 10`, 100, tokenMap["user_id"]) if err != nil { return "", utils.ErrInfo(err) } withdraw, err := c.GetAll(`SELECT * FROM e_withdraw WHERE user_id = ? ORDER BY open_time DESC LIMIT 10`, 100, tokenMap["user_id"]) if err != nil { return "", utils.ErrInfo(err) } m := EInfoResult{ Token: tokenMap, Wallets: wallets, Orders: orders, Withdraw: withdraw, } jsonData, err := json.Marshal(m) if err != nil { return "", utils.ErrInfo(err) } return string(jsonData), nil }
func (c *Controller) CfPagePreview() (string, error) { var err error txType := "CfComment" txTypeId := utils.TypeInt(txType) timeNow := time.Now().Unix() cfUrl, err := c.GetCfUrl() if err != nil { return "", utils.ErrInfo(err) } showHeaders := false if len(c.r.FormValue("blurb_img")) > 0 { showHeaders = true } page := c.Parameters["page"] if len(page) > 0 { if ok, _ := regexp.MatchString(`^(?i)[a-z]{0,10}$`, page); !ok { return "", errors.New("incorrect page") } } cfCurrencyName := c.Parameters["onlyCfCurrencyName"] if len(page) == 0 { page = "home" } langId := int64(utils.StrToFloat64(c.Parameters["lang_id"])) projectId := int64(utils.StrToFloat64(c.Parameters["onlyProjectId"])) log.Debug("projectId:", projectId) var blurbImg, headImg, descriptionImg, picture, videoType, videoUrlId, newsImg string imgBlank := cfUrl + "static/img/blank.png" var links [][]string if projectId > 0 || len(cfCurrencyName) > 0 { if projectId == 0 { projectId, err = c.Single("SELECT id FROM cf_projects WHERE project_currency_name = ?", cfCurrencyName).Int64() if err != nil { return "", utils.ErrInfo(err) } } data := make(map[string]string) if langId > 0 { data, err = c.OneRow("SELECT * FROM cf_projects_data WHERE project_id = ? AND lang_id = ?", projectId, langId).String() if err != nil { return "", utils.ErrInfo(err) } } else { // Если язык не указан, то просто берем первое добавленное описание data, err = c.OneRow("SELECT * FROM cf_projects_data WHERE project_id = ? ORDER BY id ASC", projectId).String() if err != nil { return "", utils.ErrInfo(err) } langId = utils.StrToInt64(data["lang_id"]) } blurbImg = data["blurb_img"] headImg = data["head_img"] descriptionImg = data["description_img"] picture = data["picture"] videoType = data["video_type"] videoUrlId = data["video_url_id"] newsImg = data["news_img"] if len(data["links"]) > 0 && data["links"] != "0" { var links_ [][]interface{} err = json.Unmarshal([]byte(data["links"]), &links_) if err != nil { log.Debug("data links:", data["links"]) return "", utils.ErrInfo(err) } for _, v := range links_ { var l []string for _, v2 := range v { str := utils.InterfaceToStr(v2) if len(str) == 0 { return "", utils.ErrInfo(errors.New("Incorrect links")) } l = append(l, str) } links = append(links, l) } } } else { log.Debug("FormValue", c.r.Form) blurbImg = c.r.FormValue("blurb_img") headImg = c.r.FormValue("head_img") descriptionImg = c.r.FormValue("description_img") picture = c.r.FormValue("blurb_img") videoType = c.r.FormValue("video_type") videoUrlId = c.r.FormValue("video_url_id") newsImg = c.r.FormValue("news_img") if !utils.CheckInputData(c.r.FormValue("project_id"), "int") { return "", errors.New("Incorrect project_id") } if !utils.CheckInputData(blurbImg, "img_url") { blurbImg = imgBlank } if !utils.CheckInputData(headImg, "img_url") { headImg = imgBlank } if !utils.CheckInputData(descriptionImg, "img_url") { descriptionImg = imgBlank } if !utils.CheckInputData(picture, "img_url") { picture = imgBlank } if !utils.CheckInputData(newsImg, "img_url") { newsImg = imgBlank } if !utils.CheckInputData(videoType, "video_type") { videoType = "" } if !utils.CheckInputData(videoUrlId, "video_url_id") { videoUrlId = "" } if len(c.Parameters["links"]) > 0 { var links_ [][]interface{} err = json.Unmarshal([]byte(c.Parameters["links"]), &links_) if err != nil { return "", utils.ErrInfo(err) } for _, v := range links_ { var l []string for _, v2 := range v { str := utils.InterfaceToStr(v2) if len(str) == 0 { return "", utils.ErrInfo(errors.New("Incorrect links")) } l = append(l, str) } links = append(links, l) } } } project, err := c.OneRow("SELECT * FROM cf_projects WHERE id = ?", projectId).String() if err != nil { return "", utils.ErrInfo(err) } // сколько дней осталось days := utils.Round((utils.StrToFloat64(project["end_time"])-float64(utils.Time()))/86400, 0) if days <= 0 { days = 0 } project["days"] = utils.Float64ToStr(days) if project["close_block_id"] != "0" || project["del_block_id"] != "0" { project["ended"] = "1" } else { project["ended"] = "0" } // дата старта t := time.Unix(utils.StrToInt64(project["start_time"]), 0) project["start_date"] = t.Format(c.TimeFormat) // в какой валюте идет сбор project["currency"] = c.CurrencyList[utils.StrToInt64(project["currency_id"])] // на каких языках есть описание // для home/news можно скрыть язык addSql := "" if page == "home" || page == "news" { addSql = " AND hide = 0 " } projectLang, err := c.GetMap(`SELECT id, lang_id FROM cf_projects_data WHERE project_id = ? `+addSql, "id", "lang_id", projectId) // сколько собрано средств projectFunding, err := c.Single("SELECT sum(amount) FROM cf_funding WHERE project_id = ? AND del_block_id = 0", projectId).Float64() if err != nil { return "", utils.ErrInfo(err) } // сколько всего фундеров projectCountFunders, err := c.Single("SELECT count(id) FROM cf_funding WHERE project_id = ? AND del_block_id = 0 GROUP BY user_id", projectId).Int64() if err != nil { return "", utils.ErrInfo(err) } // список фундеров var q string if c.ConfigIni["db_type"] == "postgresql" { q = `SELECT DISTINCT cf_funding.user_id, sum(amount) as amount, time, name, avatar FROM cf_funding LEFT JOIN users ON users.user_id = cf_funding.user_id WHERE project_id = ? AND del_block_id = 0 GROUP BY cf_funding.user_id, time, name, avatar ORDER BY time DESC LIMIT 100` } else { q = `SELECT cf_funding.user_id, sum(amount) as amount, time, name, avatar FROM cf_funding LEFT JOIN users ON users.user_id = cf_funding.user_id WHERE project_id = ? AND del_block_id = 0 GROUP BY cf_funding.user_id ORDER BY time DESC LIMIT 100` } projectFunders, err := c.GetAll(q, 100, projectId) if err != nil { return "", utils.ErrInfo(err) } for k, v := range projectFunders { t := time.Unix(utils.StrToInt64(v["time"]), 0) projectFunders[k]["time"] = t.Format(c.TimeFormat) if len(v["avatar"]) == 0 { projectFunders[k]["avatar"] = cfUrl + "static/img/noavatar.png" } if len(v["name"]) == 0 { projectFunders[k]["name"] = "Noname" } } // список комментов var projectComments []map[string]string if langId > 0 { projectComments, err = c.GetAll(` SELECT users.user_id, comment, time, name, avatar FROM cf_comments LEFT JOIN users ON users.user_id = cf_comments.user_id WHERE project_id = ? AND lang_id = ? ORDER BY time DESC LIMIT 100 `, 100, projectId, langId) if err != nil { return "", utils.ErrInfo(err) } for k, v := range projectComments { t := time.Unix(utils.StrToInt64(v["time"]), 0) projectComments[k]["time"] = t.Format(c.TimeFormat) if len(v["avatar"]) == 0 { projectComments[k]["avatar"] = cfUrl + "static/img/noavatar.png" } if len(v["name"]) == 0 { projectComments[k]["name"] = "Noname" } } } // сколько всего комментов на каждом языке if c.ConfigIni["db_type"] == "postgresql" { q = `SELECT DISTINCT lang_id, count(id) as count FROM cf_comments WHERE project_id = ? GROUP BY lang_id` } else { q = `SELECT lang_id, count(id) as count FROM cf_comments WHERE project_id = ?` } langComments, err := c.GetMap(q, "lang_id", "count", projectId) if err != nil { return "", utils.ErrInfo(err) } var projectCountComments int64 for _, v := range langComments { projectCountComments += utils.StrToInt64(v) } cfLng, err := c.GetAllCfLng() // инфа об авторе проекта authorInfo, err := c.GetCfAuthorInfo(project["user_id"], cfUrl) // возможно наш юзер фундер project["funder"] = "" if c.SessUserId > 0 { project["funder"], err = c.Single("SELECT id FROM cf_funding WHERE project_id = ? AND user_id = ? AND del_block_id = 0", projectId, c.SessUserId).String() if err != nil { return "", utils.ErrInfo(err) } } pagesArray := []string{"home", "news", "funders", "comments"} configCfPs := make(map[string][]string) if len(c.NodeConfig["cf_ps"]) > 0 { //{"1":["Credit card"],"2":["ik","MTS, Megafon, W1, Paxum"],"3":["pm","Perfect Money"]} err = json.Unmarshal([]byte(c.NodeConfig["cf_ps"]), &configCfPs) if err != nil { return "", utils.ErrInfo(err) } } // узнаем, какие платежные системы доступны данному проекту projectPs, err := c.OneRow("SELECT * FROM cf_projects_ps WHERE project_id = ?", projectId).String() if err != nil { return "", utils.ErrInfo(err) } // узнаем, не в блек-листе ли проект black, err := c.Single("SELECT project_id FROM cf_blacklist WHERE project_id = ?", projectId).Int64() if err != nil { return "", utils.ErrInfo(err) } if black > 0 { return "", errors.New("Black project") } TemplateStr, err := makeTemplate("cf_page_preview", "cfPagePreview", &CfPagePreviewPage{ Alert: c.Alert, Lang: c.Lang, CountSignArr: c.CountSignArr, ShowSignData: c.ShowSignData, UserId: c.SessUserId, TimeNow: timeNow, TxType: txType, TxTypeId: txTypeId, SignData: "", CfLng: cfLng, CurrencyList: c.CurrencyList, CfUrl: cfUrl, ShowHeaders: showHeaders, Page: page, CfCurrencyName: cfCurrencyName, LangId: langId, ProjectId: projectId, BlurbImg: blurbImg, HeadImg: headImg, DescriptionImg: descriptionImg, Picture: picture, VideoType: videoType, VideoUrlId: videoUrlId, NewsImg: newsImg, Links: links, ImgBlank: imgBlank, Project: project, ProjectLang: projectLang, ProjectFunding: projectFunding, ProjectCountFunders: projectCountFunders, ProjectFunders: projectFunders, ProjectComments: projectComments, LangComments: langComments, ProjectCountComments: projectCountComments, AuthorInfo: authorInfo, PagesArray: pagesArray, ConfigCfPs: configCfPs, ProjectPs: projectPs, Black: black}) if err != nil { return "", utils.ErrInfo(err) } return TemplateStr, nil }
func (p *Parser) NewMinerFront() error { err := p.generalCheck() if err != nil { return p.ErrInfo(err) } // получим кол-во точек для face и profile exampleSpots_, err := p.DCDB.Single("SELECT example_spots FROM spots_compatibility").String() if err != nil { return p.ErrInfo(err) } exampleSpots := new(exampleSpots) err = json.Unmarshal([]byte(exampleSpots_), &exampleSpots) if err != nil { return p.ErrInfo(err) } if !utils.CheckInputData(p.TxMap["race"], "race") { return utils.ErrInfoFmt("race") } if !utils.CheckInputData(p.TxMap["country"], "country") { return utils.ErrInfoFmt("country") } if !utils.CheckInputData(p.TxMap["latitude"], "coordinate") { return utils.ErrInfoFmt("latitude") } if !utils.CheckInputData(p.TxMap["longitude"], "coordinate") { return utils.ErrInfoFmt("longitude") } if !utils.CheckInputData(p.TxMap["http_host"], "http_host") { return utils.ErrInfoFmt("http_host") } if p.BlockData == nil || p.BlockData.BlockId > 250900 { if !utils.CheckInputData(p.TxMap["tcp_host"], "tcp_host") { return utils.ErrInfoFmt("tcp_host") } } if !utils.CheckInputData_(p.TxMap["face_coords"], "coords", utils.IntToStr(len(exampleSpots.Face)-1)) { return utils.ErrInfoFmt("face_coords") } if !utils.CheckInputData_(p.TxMap["profile_coords"], "coords", utils.IntToStr(len(exampleSpots.Profile)-1)) { return utils.ErrInfoFmt("profile_coords") } if !utils.CheckInputData(p.TxMap["face_hash"], "photo_hash") { return utils.ErrInfoFmt("face_hash") } if !utils.CheckInputData(p.TxMap["profile_hash"], "photo_hash") { return utils.ErrInfoFmt("profile_hash") } if !utils.CheckInputData(p.TxMap["video_type"], "video_type") { return utils.ErrInfoFmt("video_type") } if !utils.CheckInputData(p.TxMap["video_url_id"], "video_url_id") { return utils.ErrInfoFmt("video_url_id %s", p.TxMap["video_url_id"]) } if !utils.CheckInputData(p.TxMap["node_public_key"], "public_key") { return utils.ErrInfoFmt("node_public_key") } forSign := "" if p.BlockData != nil && p.BlockData.BlockId < 250900 { forSign = fmt.Sprintf("%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["race"], p.TxMap["country"], p.TxMap["latitude"], p.TxMap["longitude"], p.TxMap["http_host"], p.TxMap["face_hash"], p.TxMap["profile_hash"], p.TxMap["face_coords"], p.TxMap["profile_coords"], p.TxMap["video_type"], p.TxMap["video_url_id"], p.TxMap["node_public_key"]) } else { forSign = fmt.Sprintf("%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["race"], p.TxMap["country"], p.TxMap["latitude"], p.TxMap["longitude"], p.TxMap["http_host"], p.TxMap["tcp_host"], p.TxMap["face_hash"], p.TxMap["profile_hash"], p.TxMap["face_coords"], p.TxMap["profile_coords"], p.TxMap["video_type"], p.TxMap["video_url_id"], p.TxMap["node_public_key"]) } CheckSignResult, err := utils.CheckSign(p.PublicKeys, forSign, p.TxMap["sign"], false) if err != nil { return p.ErrInfo(err) } if !CheckSignResult { return utils.ErrInfoFmt("incorrect sign") } // проверим, не кончились ли попытки стать майнером у данного юзера count, err := p.CountMinerAttempt(p.TxUserID, "user_voting") if count >= p.Variables.Int64["miner_votes_attempt"] { return utils.ErrInfoFmt("miner_votes_attempt") } if err != nil { return p.ErrInfo(err) } // на всякий случай не даем начать нодовское, если идет юзерское голосование userVoting, err := p.DCDB.Single("SELECT id FROM votes_miners WHERE user_id = ? AND type = 'user_voting' AND votes_end = 0", p.TxUserID).String() if err != nil { return p.ErrInfo(err) } if len(userVoting) > 0 { return utils.ErrInfoFmt("existing $user_voting") } // проверим, не является ли юзер майнером и не разжалованный ли это бывший майнер minerStatus, err := p.DCDB.Single("SELECT status FROM miners_data WHERE user_id = ? AND status IN ('miner','passive_miner','suspended_miner')", p.TxUserID).String() if err != nil { return p.ErrInfo(err) } if len(minerStatus) > 0 { return utils.ErrInfoFmt("incorrect miner status") } // разрешен 1 запрос за сутки err = p.limitRequest(p.Variables.Int64["limit_new_miner"], "new_miner", p.Variables.Int64["limit_new_miner_period"]) if err != nil { return p.ErrInfo(err) } return nil }
func (p *Parser) NewMaxOtherCurrenciesFront() error { err := p.generalCheck() if err != nil { return p.ErrInfo(err) } // является ли данный юзер майнером err = p.checkMiner(p.TxUserID) if err != nil { return p.ErrInfo(err) } nodePublicKey, err := p.GetNodePublicKey(p.TxUserID) if err != nil { return p.ErrInfo(err) } if len(nodePublicKey) == 0 { return p.ErrInfo("incorrect user_id") } totalCountCurrencies, err := p.GetCountCurrencies() if err != nil { return p.ErrInfo(err) } // проверим, верно ли указаны ID валют currencyList := make(map[string]int64) err = json.Unmarshal(p.TxMap["new_max_other_currencies"], ¤cyList) if err != nil { return p.ErrInfo(err) } currencyIdsSql := "" var countCurrency int64 for currencyId, count := range currencyList { if !utils.CheckInputData(currencyId, "int") { return p.ErrInfo("currencyId") } currencyIdsSql += currencyId + "," countCurrency++ if count > totalCountCurrencies { return p.ErrInfo("count > totalCountCurrencies") } } currencyIdsSql = currencyIdsSql[0 : len(currencyIdsSql)-1] if countCurrency == 0 { return p.ErrInfo("countCurrency") } count, err := p.Single("SELECT count(id) FROM currency WHERE id IN (" + currencyIdsSql + ")").Int64() if err != nil { return p.ErrInfo(err) } if count != countCurrency { return p.ErrInfo("count != countCurrency") } forSign := fmt.Sprintf("%s,%s,%s,%s", p.TxMap["type"], p.TxMap["time"], p.TxMap["user_id"], p.TxMap["new_max_other_currencies"]) CheckSignResult, err := utils.CheckSign([][]byte{nodePublicKey}, forSign, p.TxMap["sign"], true) if err != nil { return p.ErrInfo(err) } if !CheckSignResult { return p.ErrInfo("incorrect sign") } // проверим, прошло ли 2 недели с момента последнего обновления pctTime, err := p.Single("SELECT max(time) FROM max_other_currencies_time").Int64() if err != nil { return p.ErrInfo(err) } if p.TxTime-pctTime <= p.Variables.Int64["new_max_other_currencies"] { return p.ErrInfo("14 day error") } // берем все голоса maxOtherCurrenciesVotes := make(map[int64][]map[int64]int64) rows, err := p.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 { return p.ErrInfo(err) } defer rows.Close() for rows.Next() { var currency_id, count, votes int64 err = rows.Scan(¤cy_id, &count, &votes) if err != nil { return p.ErrInfo(err) } maxOtherCurrenciesVotes[currency_id] = append(maxOtherCurrenciesVotes[currency_id], map[int64]int64{count: votes}) //fmt.Println("currency_id", currency_id) } //fmt.Println("maxOtherCurrenciesVotes", maxOtherCurrenciesVotes) 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) if err != nil { return p.ErrInfo(err) } if string(p.TxMap["new_max_other_currencies"]) != string(jsonData) { return p.ErrInfo("p.TxMap[new_max_other_currencies] != jsonData " + string(p.TxMap["new_max_other_currencies"]) + "!=" + string(jsonData)) } return nil }
/** Обработка данных (блоков или транзакций), пришедших с гейта. Только проверка. */ func (p *Parser) ParseDataGate(onlyTx bool) error { var err error p.dataPre() p.TxIds = []string{} p.Variables, err = p.GetAllVariables() if err != nil { return utils.ErrInfo(err) } transactionBinaryData := p.BinaryData var transactionBinaryDataFull []byte // если это транзакции (type>0), а не блок (type==0) if p.dataType > 0 { // проверим, есть ли такой тип тр-ий if len(consts.TxTypes[p.dataType]) == 0 { return p.ErrInfo("Incorrect tx type " + utils.IntToStr(p.dataType)) } log.Debug("p.dataType %v", p.dataType) transactionBinaryData = append(utils.DecToBin(int64(p.dataType), 1), transactionBinaryData...) transactionBinaryDataFull = transactionBinaryData // нет ли хэша этой тр-ии у нас в БД? err = p.CheckLogTx(transactionBinaryDataFull) if err != nil { return p.ErrInfo(err) } p.TxHash = utils.Md5(transactionBinaryData) // преобразуем бинарные данные транзакции в массив p.TxSlice, err = p.ParseTransaction(&transactionBinaryData) if err != nil { return p.ErrInfo(err) } log.Debug("p.TxSlice", p.TxSlice) if len(p.TxSlice) < 3 { return p.ErrInfo(errors.New("len(p.TxSlice) < 3")) } // время транзакции может быть немного больше, чем время на ноде. // у нода может быть просто не настроено время. // время транзакции используется только для борьбы с атаками вчерашними транзакциями. // А т.к. мы храним хэши в log_transaction за 36 часов, то боятся нечего. curTime := utils.Time() if utils.BytesToInt64(p.TxSlice[2])-consts.MAX_TX_FORW > curTime || utils.BytesToInt64(p.TxSlice[2]) < curTime-consts.MAX_TX_BACK { return p.ErrInfo(errors.New("incorrect tx time")) } // $this->transaction_array[3] могут подсунуть пустой if !utils.CheckInputData(p.TxSlice[3], "bigint") { return p.ErrInfo(errors.New("incorrect user id")) } } // если это блок if p.dataType == 0 { txCounter := make(map[int64]int64) // если есть $only_tx=true, то значит идет восстановление уже проверенного блока и заголовок не требуется if !onlyTx { err = p.ParseBlock() if err != nil { return p.ErrInfo(err) } // проверим данные, указанные в заголовке блока err = p.CheckBlockHeader() if err != nil { return p.ErrInfo(err) } } log.Debug("onlyTx", onlyTx) // если в ходе проверки тр-ий возникает ошибка, то вызываем откатчик всех занесенных тр-ий. Эта переменная для него p.fullTxBinaryData = p.BinaryData var txForRollbackTo []byte if len(p.BinaryData) > 0 { for { transactionSize := utils.DecodeLength(&p.BinaryData) if len(p.BinaryData) == 0 { return utils.ErrInfo(fmt.Errorf("empty BinaryData")) } // отчекрыжим одну транзакцию от списка транзакций transactionBinaryData := utils.BytesShift(&p.BinaryData, transactionSize) transactionBinaryDataFull = transactionBinaryData // добавляем взятую тр-ию в набор тр-ий для RollbackTo, в котором пойдем в обратном порядке txForRollbackTo = append(txForRollbackTo, utils.EncodeLengthPlusData(transactionBinaryData)...) // нет ли хэша этой тр-ии у нас в БД? err = p.CheckLogTx(transactionBinaryDataFull) if err != nil { p.RollbackTo(txForRollbackTo, true, false) return p.ErrInfo(err) } p.TxHash = utils.Md5(transactionBinaryData) p.TxSlice, err = p.ParseTransaction(&transactionBinaryData) log.Debug("p.TxSlice %s", p.TxSlice) if err != nil { p.RollbackTo(txForRollbackTo, true, false) return p.ErrInfo(err) } var userId int64 // txSlice[3] могут подсунуть пустой if len(p.TxSlice) > 3 { if !utils.CheckInputData(p.TxSlice[3], "int64") { return utils.ErrInfo(fmt.Errorf("empty user_id")) } else { userId = utils.BytesToInt64(p.TxSlice[3]) } } else { return utils.ErrInfo(fmt.Errorf("empty user_id")) } // считаем по каждому юзеру, сколько в блоке от него транзакций txCounter[userId]++ // чтобы 1 юзер не смог прислать дос-блок размером в 10гб, который заполнит своими же транзакциями if txCounter[userId] > p.Variables.Int64["max_block_user_transactions"] { p.RollbackTo(txForRollbackTo, true, false) return utils.ErrInfo(fmt.Errorf("max_block_user_transactions")) } // проверим, есть ли такой тип тр-ий _, ok := consts.TxTypes[utils.BytesToInt(p.TxSlice[1])] if !ok { return utils.ErrInfo(fmt.Errorf("nonexistent type")) } p.TxMap = map[string][]byte{} // для статы p.TxIds = append(p.TxIds, string(p.TxSlice[1])) MethodName := consts.TxTypes[utils.BytesToInt(p.TxSlice[1])] log.Debug("MethodName", MethodName+"Init") err_ := utils.CallMethod(p, MethodName+"Init") if _, ok := err_.(error); ok { log.Debug("error: %v", err) p.RollbackTo(txForRollbackTo, true, true) return utils.ErrInfo(err_.(error)) } log.Debug("MethodName", MethodName+"Front") err_ = utils.CallMethod(p, MethodName+"Front") if _, ok := err_.(error); ok { log.Debug("error: %v", err) p.RollbackTo(txForRollbackTo, true, true) return utils.ErrInfo(err_.(error)) } // пишем хэш тр-ии в лог err = p.InsertInLogTx(transactionBinaryDataFull, utils.BytesToInt64(p.TxMap["time"])) if err != nil { return utils.ErrInfo(err) } if len(p.BinaryData) == 0 { break } } } } else { // Оперативные транзакции MethodName := consts.TxTypes[p.dataType] log.Debug("MethodName", MethodName+"Init") err_ := utils.CallMethod(p, MethodName+"Init") if _, ok := err_.(error); ok { return utils.ErrInfo(err_.(error)) } log.Debug("MethodName", MethodName+"Front") err_ = utils.CallMethod(p, MethodName+"Front") if _, ok := err_.(error); ok { return utils.ErrInfo(err_.(error)) } // пишем хэш тр-ии в лог err = p.InsertInLogTx(transactionBinaryDataFull, utils.BytesToInt64(p.TxMap["time"])) if err != nil { return utils.ErrInfo(err) } } return nil }
func (p *Parser) CfProjectDataFront() error { err := p.generalCheck() if err != nil { return p.ErrInfo(err) } verifyData := map[string]string{"project_id": "int", "lang_id": "tinyint"} err = p.CheckInputData(verifyData) if err != nil { return p.ErrInfo(err) } if !utils.CheckInputData(p.TxMaps.String["blurb_img"], "img_url") && p.TxMaps.String["blurb_img"] != "0" { return fmt.Errorf("incorrect blurb_img") } if !utils.CheckInputData(p.TxMaps.String["head_img"], "img_url") && p.TxMaps.String["head_img"] != "0" { return fmt.Errorf("incorrect head_img") } if !utils.CheckInputData(p.TxMaps.String["description_img"], "img_url") && p.TxMaps.String["description_img"] != "0" { return fmt.Errorf("incorrect description_img") } if !utils.CheckInputData(p.TxMaps.String["picture"], "img_url") && p.TxMaps.String["picture"] != "0" { return fmt.Errorf("incorrect picture") } if !utils.CheckInputData(p.TxMaps.String["video_type"], "video_type") && p.TxMaps.String["video_type"] != "0" { return fmt.Errorf("incorrect blurb_img") } if !utils.CheckInputData(p.TxMaps.String["video_url_id"], "video_url_id") && p.TxMaps.String["video_url_id"] != "0" { return fmt.Errorf("incorrect video_url_id") } if !utils.CheckInputData(p.TxMaps.String["news_img"], "img_url") && p.TxMaps.String["news_img"] != "0" { return fmt.Errorf("incorrect news_img") } if !utils.CheckInputData(p.TxMaps.String["links"], "cf_links") && p.TxMaps.String["links"] != "0" { return fmt.Errorf("incorrect links") } // для подписи if p.BlockData != nil && p.BlockData.BlockId < 134261 { p.TxMap["hide"] = []byte(`0`) } else { if !utils.CheckInputData(p.TxMap["hide"], "boolean") { return fmt.Errorf("incorrect hide") } } // является ли юзер владельцем данного проекта и есть ли вообще такой проект projectUserId, err := p.Single("SELECT user_id FROM cf_projects WHERE user_id = ? AND id = ?", p.TxUserID, p.TxMaps.Int64["project_id"]).Int64() if err != nil { return p.ErrInfo(err) } if projectUserId == 0 { return fmt.Errorf("incorrect project_user_id") } var forSign string if p.BlockData != nil && p.BlockData.BlockId < 134261 { forSign = fmt.Sprintf("%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["project_id"], p.TxMap["lang_id"], p.TxMap["blurb_img"], p.TxMap["head_img"], p.TxMap["description_img"], p.TxMap["picture"], p.TxMap["video_type"], p.TxMap["video_url_id"], p.TxMap["news_img"], p.TxMap["links"]) } else { forSign = fmt.Sprintf("%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["project_id"], p.TxMap["lang_id"], p.TxMap["blurb_img"], p.TxMap["head_img"], p.TxMap["description_img"], p.TxMap["picture"], p.TxMap["video_type"], p.TxMap["video_url_id"], p.TxMap["news_img"], p.TxMap["links"], p.TxMap["hide"]) } 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") } err = p.limitRequest(consts.LIMIT_CF_PROJECT_DATA, "cf_project_data", consts.LIMIT_CF_PROJECT_DATA_PERIOD) if err != nil { return p.ErrInfo(err) } return nil }
func (c *Controller) Check_sign() (string, error) { var checkError bool c.r.ParseForm() n := []byte(c.r.FormValue("n")) e := []byte(c.r.FormValue("e")) sign := []byte(c.r.FormValue("sign")) setupPassword := c.r.FormValue("setup_password") private_key := c.r.FormValue("private_key") if !utils.CheckInputData(n, "hex") { return `{"result":"incorrect n"}`, nil } if !utils.CheckInputData(e, "hex") { return `{"result":"incorrect e"}`, nil } if !utils.CheckInputData(string(sign), "hex_sign") { return `{"result":"incorrect sign"}`, nil } allTables, err := c.DCDB.GetAllTables() if err != nil { return "{\"result\":0}", err } var hash []byte log.Debug("configIni[sign_hash] %s", configIni["sign_hash"]) log.Debug("c.r.RemoteAddr %s", c.r.RemoteAddr) log.Debug("c.r.Header.Get(User-Agent) %s", c.r.Header.Get("User-Agent")) RemoteAddr := utils.RemoteAddrFix(c.r.RemoteAddr) re := regexp.MustCompile(`(.*?):[0-9]+$`) match := re.FindStringSubmatch(RemoteAddr) if len(match) != 0 { RemoteAddr = match[1] } log.Debug("RemoteAddr %s", RemoteAddr) hash = utils.Md5(c.r.Header.Get("User-Agent") + RemoteAddr) log.Debug("hash %s", hash) if len(c.CommunityUsers) > 0 { // в цикле проверяем, кому подойдет присланная подпись for _, userId := range c.CommunityUsers { myPrefix := utils.Int64ToStr(userId) + "_" if !utils.InSliceString(myPrefix+"my_keys", allTables) { continue } // получим открытый ключ юзера publicKey, err := c.DCDB.GetMyPublicKey(myPrefix) if err != nil { return "{\"result\":0}", err } // получим данные для подписи forSign, err := c.DCDB.GetDataAuthorization(hash) log.Debug("publicKey: %x\n", publicKey) log.Debug("myPrefix: ", myPrefix) log.Debug("sign: %s\n", sign) log.Debug("hash: %s\n", hash) log.Debug("forSign: ", forSign) // проверим подпись resultCheckSign, err := utils.CheckSign([][]byte{publicKey}, forSign, utils.HexToBin(sign), true) if err != nil { continue } // если подпись верная, значит мы нашли юзера, который эту подпись смог сделать if resultCheckSign { myUserId := userId // убираем ограниченный режим c.sess.Delete("restricted") c.sess.Set("user_id", myUserId) log.Debug("c.sess.Set(user_id) %d", myUserId) public_key, err := c.DCDB.GetUserPublicKey(myUserId) if err != nil { return "{\"result\":0}", err } // паблик кей в сессии нужен чтобы выбрасывать юзера, если ключ изменился c.sess.Set("public_key", string(utils.BinToHex([]byte(public_key)))) log.Debug("string(utils.BinToHex([]byte(public_key))) %s", string(utils.BinToHex([]byte(public_key)))) adminUSerID, err := c.DCDB.GetAdminUserId() if err != nil { return "{\"result\":0}", err } if adminUSerID == myUserId { c.sess.Set("admin", 1) } return "{\"result\":1}", nil } } log.Debug("restricted test") // если дошли досюда, значит ни один ключ не подошел и даем возможность войти в ограниченном режиме publicKey := utils.MakeAsn1(n, e) userId_, err := c.DCDB.GetUserIdByPublicKey(publicKey) userId := utils.StrToInt64(userId_) if err != nil { return "{\"result\":0}", err } log.Debug("userId:", userId) // юзер с таким ключем есть в БД if userId > 0 { // получим данные для подписи forSign, err := c.DCDB.GetDataAuthorization(hash) log.Debug("forSign", forSign) log.Debug("publicKey %x\n", utils.HexToBin(publicKey)) log.Debug("sign_", string(sign)) // проверим подпись resultCheckSign, err := utils.CheckSign([][]byte{utils.HexToBin(publicKey)}, forSign, utils.HexToBin(sign), true) if err != nil { return "{\"result\":0}", err } if resultCheckSign { // если юзер смог подписать наш хэш, значит у него актуальный праймари ключ c.sess.Set("user_id", userId) log.Debug("c.sess.Set(user_id) %d", userId) // паблик кей в сессии нужен чтобы выбрасывать юзера, если ключ изменился c.sess.Set("public_key", string(publicKey)) // возможно в табле my_keys старые данные, но если эта табла есть, то нужно добавить туда ключ if utils.InSliceString(utils.Int64ToStr(userId)+"_my_keys", allTables) { curBlockId, err := c.DCDB.GetBlockId() if err != nil { return "{\"result\":0}", err } err = c.DCDB.InsertIntoMyKey(utils.Int64ToStr(userId)+"_", publicKey, utils.Int64ToStr(curBlockId)) if err != nil { return "{\"result\":0}", err } c.sess.Delete("restricted") } else { c.sess.Set("restricted", int64(1)) log.Debug("c.sess.Set(restricted) 1") } return "{\"result\":1}", nil } else { return "{\"result\":0}", nil } } } else { // получим открытый ключ юзера publicKey, err := c.DCDB.GetMyPublicKey("") if err != nil { return "{\"result\":0}", err } // Если ключ еще не успели установить if len(publicKey) == 0 { // пока не собрана цепочка блоков не даем ввести ключ infoBlock, err := c.DCDB.GetInfoBlock() if err != nil { return "{\"result\":0}", err } // если последний блок не старше 2-х часов wTime := int64(2) if c.ConfigIni["test_mode"] == "1" { wTime = 2 * 365 * 24 } log.Debug("%v/%v/%v", time.Now().Unix(), utils.StrToInt64(infoBlock["time"]), wTime) if (time.Now().Unix() - utils.StrToInt64(infoBlock["time"])) < 3600*wTime { // проверим, верный ли установочный пароль, если он, конечно, есть setupPassword_, err := c.Single("SELECT setup_password FROM config").String() if err != nil { return "{\"result\":0}", err } if len(setupPassword_) > 0 && setupPassword_ != string(utils.DSha256(setupPassword)) { log.Debug(setupPassword_, string(utils.DSha256(setupPassword)), setupPassword) return "{\"result\":0}", nil } publicKey := utils.MakeAsn1(n, e) log.Debug("new key", string(publicKey)) userId, err := c.GetUserIdByPublicKey(publicKey) if err != nil { return "{\"result\":0}", err } // получим данные для подписи forSign, err := c.DCDB.GetDataAuthorization(hash) if err != nil { return "{\"result\":0}", err } log.Debug("forSign", forSign) log.Debug("publicKey %x\n", utils.HexToBin(publicKey)) log.Debug("sign_", string(sign)) // проверим подпись resultCheckSign, err := utils.CheckSign([][]byte{utils.HexToBin(publicKey)}, forSign, utils.HexToBin(sign), true) if err != nil { return "{\"result\":0}", err } if !resultCheckSign { return "{\"result\":0}", nil } if len(userId) > 0 { err := c.InsertIntoMyKey("", publicKey, "0") if err != nil { return "{\"result\":0}", err } minerId, err := c.GetMinerId(utils.StrToInt64(userId)) if err != nil { return "{\"result\":0}", err } //myUserId, err := c.GetMyUserId("") //if myUserId > 0 { if minerId > 0 { err = c.ExecSql("UPDATE my_table SET user_id = ?, miner_id = ?, status = 'miner'", userId, minerId) if err != nil { return "{\"result\":0}", err } } else { err = c.ExecSql("UPDATE my_table SET user_id = ?, status = 'user'", userId) if err != nil { return "{\"result\":0}", err } } //} else { // c.ExecSql("INSERT INTO my_table (user_id, status) VALUES (?, 'user')", userId) //} // возможно юзер хочет сохранить свой ключ if len(private_key) > 0 { c.ExecSql("UPDATE my_keys SET private_key = ? WHERE block_id = (SELECT max(block_id) FROM my_keys)", private_key) } } else { checkError = true } } else { checkError = true } } else { log.Debug("RemoteAddr %s", RemoteAddr) hash = utils.Md5(c.r.Header.Get("User-Agent") + RemoteAddr) log.Debug("hash %s", hash) // получим данные для подписи forSign, err := c.DCDB.GetDataAuthorization(hash) log.Debug("forSign", forSign) log.Debug("publicKey %x\n", string(publicKey)) log.Debug("sign_", string(sign)) // проверим подпись resultCheckSign, err := utils.CheckSign([][]byte{publicKey}, forSign, utils.HexToBin(sign), true) if err != nil { return "{\"result\":0}", err } if !resultCheckSign { return "{\"result\":0}", nil } } if checkError { return "{\"result\":0}", nil } else { myUserId, err := c.DCDB.GetMyUserId("") if myUserId == 0 { myUserId = -1 } if err != nil { return "{\"result\":0}", err } c.sess.Delete("restricted") c.sess.Set("user_id", myUserId) // если уже пришел блок, в котором зареган ключ юзера if myUserId != -1 { public_key, err := c.DCDB.GetUserPublicKey(myUserId) if err != nil { return "{\"result\":0}", err } // паблик кей в сессии нужен чтобы выбрасывать юзера, если ключ изменился c.sess.Set("public_key", string(utils.BinToHex(public_key))) // возможно юзер хочет сохранить свой ключ if len(private_key) > 0 { c.ExecSql("UPDATE my_keys SET private_key = ? WHERE block_id = (SELECT max(block_id) FROM my_keys)", private_key) } AdminUserId, err := c.DCDB.GetAdminUserId() if err != nil { return "{\"result\":0}", err } if AdminUserId == myUserId { c.sess.Set("admin", int64(1)) } return "{\"result\":1}", nil } } } return "{\"result\":0}", nil }
func (c *Controller) MinersMap() (string, error) { if c.SessRestricted != 0 { return "", utils.ErrInfo(errors.New("Permission denied")) } c.r.ParseForm() log.Debug("min_amount:", c.r.FormValue("min_amount")) minAmount := utils.StrToFloat64(c.r.FormValue("min_amount")) log.Debug("minAmount:", minAmount) if !utils.CheckInputData(c.r.FormValue("min_amount"), "amount") { return "", errors.New("Incorrect min_amount") } currencyId := utils.StrToInt64(c.r.FormValue("currency_id")) if !utils.CheckInputData(c.r.FormValue("currency_id"), "currency_id") { return "", errors.New("Incorrect currency_id") } paymentSystemId := utils.StrToInt64(c.r.FormValue("payment_system_id")) if !utils.CheckInputData(c.r.FormValue("payment_system_id"), "int") { return "", errors.New("Incorrect payment_system_id") } maxPromisedAmounts, err := c.Single("SELECT amount FROM max_promised_amounts WHERE currency_id = ? ORDER BY time DESC", currencyId).Float64() if err != nil { return "", utils.ErrInfo(err) } addSql := "" if paymentSystemId > 0 { addSql = fmt.Sprintf(` (ps1 = %d OR ps2 = %d OR ps3 = %d OR ps4 = %d OR ps5 = %d) AND`, paymentSystemId, paymentSystemId, paymentSystemId, paymentSystemId, paymentSystemId) } rows, err := c.Query(c.FormatQuery(` SELECT amount, latitude, longitude, promised_amount.user_id FROM promised_amount LEFT JOIN miners_data ON miners_data.user_id = promised_amount.user_id WHERE promised_amount.status = 'mining' AND currency_id = ? AND `+addSql+` promised_amount.user_id != ? AND del_block_id = 0 `), currencyId, c.SessUserId) if err != nil { return "", utils.ErrInfo(err) } result := "" defer rows.Close() for rows.Next() { var amount float64 var latitude, longitude string var user_id int64 err = rows.Scan(&amount, &latitude, &longitude, &user_id) if err != nil { return "", utils.ErrInfo(err) } repaid, err := c.Single("SELECT amount FROM promised_amount WHERE status = 'repaid' AND currency_id = ? AND user_id = ? AND del_block_id = 0", currencyId, user_id).Float64() if err != nil { return "", utils.ErrInfo(err) } var returnAmount float64 if repaid+amount < maxPromisedAmounts { returnAmount = amount } else { returnAmount = maxPromisedAmounts - repaid } if returnAmount <= 0 { continue } result += fmt.Sprintf(`{"user_id": %v, "amount": %v, "longitude": %v, "latitude": %v},`, user_id, returnAmount, longitude, latitude) } if len(result) > 0 { result = result[:len(result)-1] } log.Debug(result) result = `{ "info": [` + result + `]}` return result, nil }
/** * Занесение данных из блока в БД * используется только в testblock_is_ready */ func (p *Parser) ParseDataFront() error { p.TxIds = []string{} p.dataPre() if p.dataType == 0 { // инфа о предыдущем блоке (т.е. последнем занесенном) err := p.GetInfoBlock() if err != nil { return p.ErrInfo(err) } utils.WriteSelectiveLog("DELETE FROM transactions WHERE used=1") affect, err := p.ExecSqlGetAffect("DELETE FROM transactions WHERE used = 1") if err != nil { utils.WriteSelectiveLog(err) return p.ErrInfo(err) } utils.WriteSelectiveLog("affect: " + utils.Int64ToStr(affect)) // разбор блока err = p.ParseBlock() if err != nil { return utils.ErrInfo(err) } p.Variables, err = p.GetAllVariables() if err != nil { return utils.ErrInfo(err) } //меркель рут нужен для updblockinfo() p.MrklRoot, err = utils.GetMrklroot(p.BinaryData, p.Variables, false) if err != nil { return utils.ErrInfo(err) } if len(p.BinaryData) > 0 { for { transactionSize := utils.DecodeLength(&p.BinaryData) if len(p.BinaryData) == 0 { return utils.ErrInfo(fmt.Errorf("empty BinaryData")) } // отчекрыжим одну транзакцию от списка транзакций transactionBinaryData := utils.BytesShift(&p.BinaryData, transactionSize) transactionBinaryDataFull := transactionBinaryData p.TxHash = utils.Md5(transactionBinaryData) log.Debug("p.TxHash", p.TxHash) p.TxSlice, err = p.ParseTransaction(&transactionBinaryData) log.Debug("p.TxSlice", p.TxSlice) if err != nil { return utils.ErrInfo(err) } // txSlice[3] могут подсунуть пустой if len(p.TxSlice) > 3 { if !utils.CheckInputData(p.TxSlice[3], "int64") { return utils.ErrInfo(fmt.Errorf("empty user_id")) } } else { return utils.ErrInfo(fmt.Errorf("empty user_id")) } // проверим, есть ли такой тип тр-ий _, ok := consts.TxTypes[utils.BytesToInt(p.TxSlice[1])] if !ok { return utils.ErrInfo(fmt.Errorf("nonexistent type")) } p.TxMap = map[string][]byte{} // для статы p.TxIds = append(p.TxIds, string(p.TxSlice[1])) MethodName := consts.TxTypes[utils.BytesToInt(p.TxSlice[1])] log.Debug("MethodName", MethodName+"Init") err_ := utils.CallMethod(p, MethodName+"Init") if _, ok := err_.(error); ok { log.Debug("error: %v", err) return utils.ErrInfo(err_.(error)) } log.Debug("MethodName", MethodName) err_ = utils.CallMethod(p, MethodName) if _, ok := err_.(error); ok { log.Debug("error: %v", err) return utils.ErrInfo(err_.(error)) } utils.WriteSelectiveLog("UPDATE transactions SET used=1 WHERE hex(hash) = " + string(utils.Md5(transactionBinaryDataFull))) affect, err := p.ExecSqlGetAffect("UPDATE transactions SET used=1 WHERE hex(hash) = ?", utils.Md5(transactionBinaryDataFull)) if err != nil { utils.WriteSelectiveLog(err) return utils.ErrInfo(err) } utils.WriteSelectiveLog("affect: " + utils.Int64ToStr(affect)) // даем юзеру понять, что его тр-ия попала в блок err = p.ExecSql("UPDATE transactions_status SET block_id = ? WHERE hex(hash) = ?", p.BlockData.BlockId, utils.Md5(transactionBinaryDataFull)) if err != nil { return utils.ErrInfo(err) } if len(p.BinaryData) == 0 { break } } } p.UpdBlockInfo() p.InsertIntoBlockchain() } else { return utils.ErrInfo(fmt.Errorf("incorrect type")) } return nil }
func (c *Controller) GetSellerData() (string, error) { c.r.ParseForm() getUserId := utils.StrToInt64(c.r.FormValue("user_id")) if !utils.CheckInputData(getUserId, "int") { return `{"result":"incorrect userId"}`, nil } currencyId := utils.StrToInt64(c.r.FormValue("currency_id")) if !utils.CheckInputData(currencyId, "currency_id") { return `{"result":"incorrect currency_id"}`, nil } arbitrationTrustList, err := c.GetList("SELECT arbitrator_user_id FROM arbitration_trust_list WHERE user_id = ?", getUserId).Int64() if err != nil { return "", utils.ErrInfo(err) } /* * Статистика по продавцу * */ // оборот всего sellerTurnover, err := c.Single("SELECT sum(amount) FROM orders WHERE seller = ? AND currency_id = ?", getUserId, currencyId).Float64() if err != nil { return "", utils.ErrInfo(err) } // оборот за месяц sellerTurnoverM, err := c.Single("SELECT sum(amount) FROM orders WHERE seller = ? AND time > ? AND currency_id = ?", getUserId, time.Now().Unix()-3600*24*30, currencyId).Float64() if err != nil { return "", utils.ErrInfo(err) } // Кол-во покупателей за последний месяц var q string if c.ConfigIni["db_type"] == "postgresql" { q = `SELECT count(id) FROM ( SELECT DISTINCT id FROM orders WHERE seller = ? AND time > ? AND currency_id = ? GROUP BY buyer, id ) as t1` } else { q = `SELECT count(id) FROM ( SELECT id FROM orders WHERE seller = ? AND time > ? AND currency_id = ? GROUP BY buyer ) as t1` } buyersCountM, err := c.Single(q, getUserId, currencyId, time.Now().Unix()-3600*24*30).Int64() if err != nil { return "", utils.ErrInfo(err) } // Кол-во покупателей-майнеров за последний месяц if c.ConfigIni["db_type"] == "postgresql" { q = `SELECT count(id) FROM ( SELECT DISTINCT orders.id FROM orders LEFT JOIN miners_data ON miners_data.user_id = orders.buyer WHERE seller = ? AND orders.time > ? AND orders.currency_id = ? AND miner_id > 0 GROUP BY buyer, orders.id ) as t1` } else { q = `SELECT count(id) FROM ( SELECT orders.id FROM orders LEFT JOIN miners_data ON miners_data.user_id = orders.buyer WHERE seller = ? AND orders.time > ? AND orders.currency_id = ? AND miner_id > 0 GROUP BY buyer ) as t1` } buyersMinersCountM, err := c.Single(q, getUserId, time.Now().Unix()-3600*24*30, currencyId).Int64() if err != nil { return "", utils.ErrInfo(err) } // Кол-во покупателей всего if c.ConfigIni["db_type"] == "postgresql" { q = `SELECT count(id) FROM ( SELECT DISTINCT id FROM orders WHERE seller = ? AND currency_id = ? GROUP BY buyer, id ) as t1` } else { q = `SELECT count(id) FROM ( SELECT id FROM orders WHERE seller = ? AND currency_id = ? GROUP BY buyer ) as t1` } buyersCount, err := c.Single(q, getUserId, currencyId).Int64() if err != nil { return "", utils.ErrInfo(err) } // Кол-во покупателей-майнеров всего if c.ConfigIni["db_type"] == "postgresql" { q = `SELECT count(id) FROM ( SELECT DISTINCT orders.id FROM orders LEFT JOIN miners_data ON miners_data.user_id = orders.buyer WHERE seller = ? AND orders.currency_id = ? AND miner_id > 0 GROUP BY buyer, orders.id ) as t1` } else { q = `SELECT count(id) FROM ( SELECT orders.id FROM orders LEFT JOIN miners_data ON miners_data.user_id = orders.buyer WHERE seller = ? AND orders.currency_id = ? AND miner_id > 0 GROUP BY buyer ) as t1` } buyersMinersCount, err := c.Single(q, getUserId, currencyId).Int64() if err != nil { return "", utils.ErrInfo(err) } // Заморожено для манибека holdAmount, err := c.Single(` SELECT sum(hold_back_amount) FROM orders LEFT JOIN miners_data ON miners_data.user_id = orders.buyer WHERE seller = ? AND orders.currency_id = ? AND miner_id > 0 GROUP BY buyer `, getUserId, currencyId).Float64() if err != nil { return "", utils.ErrInfo(err) } // Холдбек % на 30 дней sellerData, err := c.OneRow("SELECT seller_hold_back_pct, arbitration_days_refund FROM users WHERE user_id = ?", getUserId).String() if err != nil { return "", utils.ErrInfo(err) } sellerHoldBackPct := utils.StrToFloat64(sellerData["seller_hold_back_pct"]) arbitrationDaysRefund := utils.StrToInt64(sellerData["arbitrationDaysRefund"]) buyersCount = buyersCount - buyersMinersCount buyersCountM = buyersCountM - buyersMinersCountM rez := selleData{Trust_list: arbitrationTrustList, Seller_hold_back_pct: sellerHoldBackPct, Arbitration_days_refund: arbitrationDaysRefund, Buyers_miners_count_m: buyersMinersCountM, Buyers_miners_count: buyersMinersCount, Buyers_count: buyersCount, Buyers_count_m: buyersCountM, Seller_turnover_m: sellerTurnoverM, Seller_turnover: sellerTurnover, Hold_amount: holdAmount} log.Debug("%v", rez) log.Debug("%v", arbitrationTrustList) result, err := json.Marshal(rez) if err != nil { log.Error("%v", err) return "", utils.ErrInfo(err) } log.Debug(string(result)) return string(result), nil }
/** фронт. проверка + занесение данных из блока в таблицы и info_block */ func (p *Parser) ParseDataFull() error { p.TxIds = []string{} p.dataPre() if p.dataType != 0 { // парсим только блоки return utils.ErrInfo(fmt.Errorf("incorrect dataType")) } var err error p.Variables, err = p.GetAllVariables() if err != nil { return utils.ErrInfo(err) } //if len(p.BinaryData) > 500000 { // ioutil.WriteFile("block-"+string(utils.DSha256(p.BinaryData)), p.BinaryData, 0644) //} err = p.ParseBlock() if err != nil { return utils.ErrInfo(err) } // проверим данные, указанные в заголовке блока err = p.CheckBlockHeader() if err != nil { return utils.ErrInfo(err) } utils.WriteSelectiveLog("DELETE FROM transactions WHERE used = 1") afect, err := p.ExecSqlGetAffect("DELETE FROM transactions WHERE used = 1") if err != nil { utils.WriteSelectiveLog(err) return utils.ErrInfo(err) } utils.WriteSelectiveLog("afect: " + utils.Int64ToStr(afect)) txCounter := make(map[int64]int64) p.fullTxBinaryData = p.BinaryData var txForRollbackTo []byte if len(p.BinaryData) > 0 { for { // обработка тр-ий может занять много времени, нужно отметиться p.UpdDaemonTime(p.GoroutineName) p.halfRollback = false log.Debug("&p.BinaryData", p.BinaryData) transactionSize := utils.DecodeLength(&p.BinaryData) if len(p.BinaryData) == 0 { return utils.ErrInfo(fmt.Errorf("empty BinaryData")) } // отчекрыжим одну транзакцию от списка транзакций //log.Debug("++p.BinaryData=%x\n", p.BinaryData) //log.Debug("transactionSize", transactionSize) transactionBinaryData := utils.BytesShift(&p.BinaryData, transactionSize) transactionBinaryDataFull := transactionBinaryData //ioutil.WriteFile("/tmp/dctx", transactionBinaryDataFull, 0644) //ioutil.WriteFile("/tmp/dctxhash", utils.Md5(transactionBinaryDataFull), 0644) // добавляем взятую тр-ию в набор тр-ий для RollbackTo, в котором пойдем в обратном порядке txForRollbackTo = append(txForRollbackTo, utils.EncodeLengthPlusData(transactionBinaryData)...) //log.Debug("transactionBinaryData: %x\n", transactionBinaryData) //log.Debug("txForRollbackTo: %x\n", txForRollbackTo) err = p.CheckLogTx(transactionBinaryDataFull) if err != nil { p.RollbackTo(txForRollbackTo, true, false) return utils.ErrInfo(err) } utils.WriteSelectiveLog("UPDATE transactions SET used=1 WHERE hex(hash) = " + string(utils.Md5(transactionBinaryDataFull))) affect, err := p.ExecSqlGetAffect("UPDATE transactions SET used=1 WHERE hex(hash) = ?", utils.Md5(transactionBinaryDataFull)) if err != nil { utils.WriteSelectiveLog(err) utils.WriteSelectiveLog("RollbackTo") p.RollbackTo(txForRollbackTo, true, false) return utils.ErrInfo(err) } utils.WriteSelectiveLog("affect: " + utils.Int64ToStr(affect)) //log.Debug("transactionBinaryData", transactionBinaryData) p.TxHash = utils.Md5(transactionBinaryData) log.Debug("p.TxHash %s", p.TxHash) p.TxSlice, err = p.ParseTransaction(&transactionBinaryData) log.Debug("p.TxSlice %v", p.TxSlice) if err != nil { p.RollbackTo(txForRollbackTo, true, false) return err } if p.BlockData.BlockId > 1 { var userId int64 // txSlice[3] могут подсунуть пустой if len(p.TxSlice) > 3 { if !utils.CheckInputData(p.TxSlice[3], "int64") { return utils.ErrInfo(fmt.Errorf("empty user_id")) } else { userId = utils.BytesToInt64(p.TxSlice[3]) } } else { return utils.ErrInfo(fmt.Errorf("empty user_id")) } // считаем по каждому юзеру, сколько в блоке от него транзакций txCounter[userId]++ // чтобы 1 юзер не смог прислать дос-блок размером в 10гб, который заполнит своими же транзакциями if txCounter[userId] > p.Variables.Int64["max_block_user_transactions"] { p.RollbackTo(txForRollbackTo, true, false) return utils.ErrInfo(fmt.Errorf("max_block_user_transactions")) } } // время в транзакции не может быть больше, чем на MAX_TX_FORW сек времени блока // и время в транзакции не может быть меньше времени блока -24ч. if utils.BytesToInt64(p.TxSlice[2])-consts.MAX_TX_FORW > p.BlockData.Time || utils.BytesToInt64(p.TxSlice[2]) < p.BlockData.Time-consts.MAX_TX_BACK { p.RollbackTo(txForRollbackTo, true, false) return utils.ErrInfo(fmt.Errorf("incorrect transaction time")) } // проверим, есть ли такой тип тр-ий _, ok := consts.TxTypes[utils.BytesToInt(p.TxSlice[1])] if !ok { return utils.ErrInfo(fmt.Errorf("nonexistent type")) } p.TxMap = map[string][]byte{} // для статы p.TxIds = append(p.TxIds, string(p.TxSlice[1])) MethodName := consts.TxTypes[utils.BytesToInt(p.TxSlice[1])] log.Debug("MethodName", MethodName+"Init") err_ := utils.CallMethod(p, MethodName+"Init") if _, ok := err_.(error); ok { log.Error("error: %v", err) return utils.ErrInfo(err_.(error)) } log.Debug("MethodName", MethodName+"Front") err_ = utils.CallMethod(p, MethodName+"Front") if _, ok := err_.(error); ok { log.Error("error: %v", err_) p.RollbackTo(txForRollbackTo, true, false) return utils.ErrInfo(err_.(error)) } log.Debug("MethodName", MethodName) err_ = utils.CallMethod(p, MethodName) if _, ok := err_.(error); ok { log.Error("error: %v", err) return utils.ErrInfo(err_.(error)) } // даем юзеру понять, что его тр-ия попала в блок p.ExecSql("UPDATE transactions_status SET block_id = ? WHERE hex(hash) = ?", p.BlockData.BlockId, utils.Md5(transactionBinaryDataFull)) // Тут было time(). А значит если бы в цепочке блоков были блоки в которых были бы одинаковые хэши тр-ий, то ParseDataFull вернул бы error err = p.InsertInLogTx(transactionBinaryDataFull, utils.BytesToInt64(p.TxMap["time"])) if err != nil { return utils.ErrInfo(err) } if len(p.BinaryData) == 0 { break } } } p.UpdBlockInfo() return nil }
func (p *Parser) CfCommentFront() error { err := p.generalCheck() if err != nil { return p.ErrInfo(err) } verifyData := map[string]string{"project_id": "int", "comment": "cf_comment"} err = p.CheckInputData(verifyData) if err != nil { return p.ErrInfo(err) } if !utils.CheckInputData(p.TxMaps.Int64["lang_id"], "tinyint") || p.TxMaps.Int64["lang_id"] <= 0 { return fmt.Errorf("incorrect lang_id") } var txTime int64 if p.BlockData != nil { txTime = p.BlockData.Time } else { // голая тр-ия с запасом 30 сек на время генерации блока. Т.к. при попадинии в блок время будет уже другим txTime = time.Now().Unix() - 30 } // автор проекта может писать по 1 комменту за каждую языковую версию author, err := p.Single("SELECT id FROM cf_projects WHERE user_id = ? AND id = ?", p.TxUserID, p.TxMaps.Int64["project_id"]).Int64() if err != nil { return p.ErrInfo(err) } addSql := "" if author > 0 { addSql = " AND lang_id = " + utils.Int64ToStr(p.TxMaps.Int64["lang_id"]) } else { addSql = "" } // проверим, есть ли у данного юзера другие комменты за данный проект commentTime, err := p.Single("SELECT max(time) FROM cf_comments WHERE user_id = ? AND project_id = ? "+addSql, p.TxUserID, p.TxMaps.Int64["project_id"]).Int64() if err != nil { return p.ErrInfo(err) } // в 1 проект можно писать только 1 комммент в сутки if txTime-commentTime < consts.LIMIT_TIME_COMMENTS_CF_PROJECT { return p.ErrInfo("comment_time") } // финансировал ли данный юзер этот проект funder, err := p.Single(" SELECT id FROM cf_funding WHERE user_id = ? AND project_id = ?", p.TxUserID, p.TxMaps.Int64["project_id"]).Int64() if err != nil { return p.ErrInfo(err) } if funder == 0 { // или может быть он его автор author, err := p.Single("SELECT id FROM cf_projects WHERE user_id = ? AND id = ?", p.TxUserID, p.TxMaps.Int64["project_id"]).Int64() if err != nil { return p.ErrInfo(err) } if author == 0 { return p.ErrInfo("!funder || !author") } } forSign := fmt.Sprintf("%s,%s,%s,%s,%s,%s", p.TxMap["type"], p.TxMap["time"], p.TxMap["user_id"], p.TxMap["project_id"], p.TxMap["lang_id"], p.TxMap["comment"]) 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") } err = p.limitRequest(consts.LIMIT_CF_COMMENTS, "cf_comments", consts.LIMIT_CF_COMMENTS_PERIOD) if err != nil { return p.ErrInfo(err) } return nil }
func (p *Parser) AdminVariablesFront() error { var Variables map[string]interface{} err := json.Unmarshal(p.TxMap["variables"], &Variables) if err != nil { return p.ErrInfo(err) } var VARIABLES_COUNT int if p.BlockData != nil && p.BlockData.BlockId < 29047 { VARIABLES_COUNT = 71 } else { VARIABLES_COUNT = 72 } err = p.generalCheckAdmin() if err != nil { return p.ErrInfo(err) } if len(Variables) != VARIABLES_COUNT { return p.ErrInfo(fmt.Sprintf("incorrect variables count (%d != %d)", len(Variables), VARIABLES_COUNT)) } i := 0 for name, value := range Variables { errorText := "incorrect variable %s" // проверим допустимые значения в value. Хотя админу и можно доверять, но лучше перестраховаться. switch name { case "alert_error_time", "error_time", "promised_amount_points", "promised_amount_votes_0", "promised_amount_votes_1", "promised_amount_votes_period", "holidays_max", "limit_abuses", "limit_abuses_period", "limit_promised_amount", "limit_promised_amount_period", "limit_cash_requests_out", "limit_cash_requests_out_period", "limit_change_geolocation", "limit_change_geolocation_period", "limit_holidays", "limit_holidays_period", "limit_message_to_admin", "limit_message_to_admin_period", "limit_mining", "limit_mining_period", "limit_node_key", "limit_node_key_period", "limit_primary_key", "limit_primary_key_period", "limit_votes_miners", "limit_votes_miners_period", "limit_votes_complex", "limit_votes_complex_period", "limit_commission", "limit_commission_period", "limit_new_miner", "limit_new_miner_period", "limit_new_user", "limit_new_user_period", "max_block_size", "max_block_user_transactions", "max_day_votes", "max_tx_count", "max_tx_size", "max_user_transactions", "miners_keepers", "miner_points", "miner_votes_0", "miner_votes_1", "miner_votes_attempt", "miner_votes_period", "mining_votes_0", "mining_votes_1", "mining_votes_period", "min_miners_keepers", "node_voting", "node_voting_period", "rollback_blocks_1", "rollback_blocks_2", "limit_change_host", "limit_change_host_period", "min_miners_of_voting", "min_hold_time_promise_amount", "min_promised_amount", "points_update_time", "reduction_period", "new_pct_period", "new_max_promised_amount", "new_max_other_currencies", "cash_request_time", "limit_for_repaid_fix", "limit_for_repaid_fix_period", "miner_newbie_time": if !utils.CheckInputData(value, "bigint") { return p.ErrInfo(fmt.Errorf(errorText, name)) } i++ case "points_factor": if !utils.CheckInputData(value, "float") { return p.ErrInfo(fmt.Errorf(errorText, name)) } i++ case "system_commission": if !utils.CheckInputData(value, "system_commission") { return p.ErrInfo(fmt.Errorf(errorText, name)) } i++ case "sleep": if !utils.CheckInputData(value, "sleep_var") { return p.ErrInfo(fmt.Errorf(errorText, name)) } i++ case "default": return p.ErrInfo(fmt.Errorf(errorText, name)) } } if i != VARIABLES_COUNT { return p.ErrInfo(fmt.Sprintf("incorrect variables count (%d != %d)", i, VARIABLES_COUNT)) } forSign := fmt.Sprintf("%s,%s,%s,%s", p.TxMap["type"], p.TxMap["time"], p.TxMap["user_id"], p.TxMap["variables"]) 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") } return nil }
func (p *Parser) ChangeArbitratorConditionsFront() error { err := p.generalCheck() if err != nil { return p.ErrInfo(err) } if len(p.TxMap["conditions"]) > 3000 { return fmt.Errorf("incorrect conditions") } // может прийти [0] if p.TxMaps.String["conditions"] != "[0]" { var conditions map[string][5]string err = json.Unmarshal(p.TxMap["conditions"], &conditions) if err != nil { return p.ErrInfo(err) } if len(conditions) == 0 { return fmt.Errorf("len(conditions) == 0") } var currencyArray []string var minusCf int64 for currencyId, data := range conditions { if !utils.CheckInputData(currencyId, "bigint") { return fmt.Errorf("incorrect currencyId") } if len(data) != 5 { return fmt.Errorf("incorrect data") } minAmount := utils.StrToFloat64(data[0]) maxAmount := utils.StrToFloat64(data[1]) minCommission := utils.StrToFloat64(data[2]) maxCommission := utils.StrToFloat64(data[3]) commissionPct := utils.StrToFloat64(data[4]) if !utils.CheckInputData(data[0], "amount") || minAmount < 0.01 { return fmt.Errorf("incorrect minAmount") } if !utils.CheckInputData(data[1], "amount") { return fmt.Errorf("incorrect maxAmount") } if !utils.CheckInputData(data[2], "amount") || minCommission < 0.01 { return fmt.Errorf("incorrect minCommission") } if !utils.CheckInputData(data[3], "amount") { return fmt.Errorf("incorrect maxCommission") } if !utils.CheckInputData(data[4], "pct") || commissionPct > 10 || commissionPct < 0.01 { return fmt.Errorf("incorrect commissionPct") } if maxCommission > 0 && minCommission > maxCommission { return fmt.Errorf("minCommission > maxCommission") } if maxAmount > 0 && minAmount > maxAmount { return fmt.Errorf("minAmount > maxAmount") } // проверим, существует ли такая валюта в таблице DC-валют if ok, err := p.CheckCurrency(utils.StrToInt64(currencyId)); !ok { // если нет, то это может быть $currency_id 1000, которая определяет комиссию для всх CF-валют if currencyId != "1000" { return p.ErrInfo(err) } } if currencyId != "1000" { currencyArray = append(currencyArray, currencyId) } else { minusCf = 1 } } count, err := p.Single("SELECT count(id) FROM currency WHERE id IN (" + strings.Join(currencyArray, ",") + ")").Int64() if err != nil { return p.ErrInfo(err) } if count != int64(len(conditions))-minusCf { return p.ErrInfo("count != int64(len(conditions)) - minusCf") } } if !utils.CheckInputData(p.TxMaps.String["url"], "arbitrator_url") && p.TxMaps.String["url"] != "0" { return fmt.Errorf("incorrect url") } forSign := fmt.Sprintf("%s,%s,%s,%s,%s", p.TxMap["type"], p.TxMap["time"], p.TxMap["user_id"], p.TxMap["conditions"], p.TxMap["url"]) 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") } err = p.limitRequest(consts.LIMIT_CHANGE_ARBITRATOR_CONDITIONS, "change_arbitrator_conditions", consts.LIMIT_CHANGE_ARBITRATOR_CONDITIONS_PERIOD) if err != nil { return p.ErrInfo(err) } return 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) ChangeCommissionFront() error { err := p.generalCheck() if err != nil { return p.ErrInfo(err) } // является ли данный юзер майнером err = p.checkMiner(p.TxUserID) if err != nil { return p.ErrInfo(err) } if len(p.TxMap["commission"]) > 3000 { return p.ErrInfo("len commission") } commissionMap := make(map[string][3]float64) err = json.Unmarshal(p.TxMaps.Bytes["commission"], &commissionMap) if err != nil { return p.ErrInfo(err) } var currencyArray []int64 minusCf := 0 for currencyId_, data := range commissionMap { currencyId := utils.StrToInt64(currencyId_) if len(data) != 3 { return p.ErrInfo("len(data) !=3") } if !utils.CheckInputData(currencyId, "int") { return p.ErrInfo("currencyId") } // % от 0 до 10 if !utils.CheckInputData(utils.Float64ToStrPct(data[0]), "currency_commission") || data[0] > 10 { return p.ErrInfo("pct") } // минимальная комиссия от 0. При 0% будет = 0 if !utils.CheckInputData(utils.Float64ToStrPct(data[1]), "currency_commission") { return p.ErrInfo("currency_min_commission") } // макс. комиссия. 0 - значит, считается по % if !utils.CheckInputData(utils.Float64ToStrPct(data[2]), "currency_commission") { return p.ErrInfo("currency_max_commission") } if data[1] > data[2] && data[2] > 0 { return p.ErrInfo("currency_max_commission") } // проверим, существует ли такая валюта в таблице DC-валют if ok, err := p.CheckCurrency(currencyId); !ok { // если нет, то это может быть $currency_id 1000, которая определяет комиссию для всх CF-валют if currencyId != 1000 { return p.ErrInfo(err) } } if currencyId != 1000 { currencyArray = append(currencyArray, currencyId) } else { minusCf = 1 } } count, err := p.Single("SELECT count(id) FROM currency WHERE id IN (" + strings.Join(utils.SliceInt64ToString(currencyArray), ",") + ")").Int() if err != nil { return p.ErrInfo(err) } if count != len(commissionMap)-minusCf { return p.ErrInfo("count != len(commissionMap) - minusCf") } forSign := fmt.Sprintf("%s,%s,%s,%s", p.TxMap["type"], p.TxMap["time"], p.TxMap["user_id"], p.TxMap["commission"]) CheckSignResult, err := utils.CheckSign(p.PublicKeys, forSign, p.TxMap["sign"], false) if err != nil || !CheckSignResult { return p.ErrInfo("incorrect sign") } err = p.limitRequest(p.Variables.Int64["limit_commission"], "commission", p.Variables.Int64["limit_commission_period"]) if err != nil { return p.ErrInfo(err) } return nil }