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 (c *Controller) WalletsListCfProject() (string, error) { var err error c.r.ParseForm() projectId := utils.StrToInt64(c.r.FormValue("project_id")) if projectId == 0 { return "", errors.New("projectId == 0") } cfProject, err := c.OneRow("SELECT id, amount, currency_id, end_time FROM cf_projects WHERE del_block_id = 0 AND id = ?", projectId).String() if err != nil { return "", utils.ErrInfo(err) } //id, endTime, langId int64, amount float64, levelUp string CfProjectData, err := c.GetCfProjectData(projectId, utils.StrToInt64(cfProject["end_time"]), c.LangInt, utils.StrToFloat64(cfProject["amount"]), "") for k, v := range CfProjectData { cfProject[k] = v } // сколько у нас есть DC данной валюты wallet, err := c.OneRow("SELECT amount, currency_id, last_update FROM wallets WHERE user_id = ? AND currency_id = ?", c.SessUserId, cfProject["currency_id"]).String() if err != nil { return "", utils.ErrInfo(err) } if len(wallet) > 0 { amount := utils.StrToMoney(wallet["amount"]) profit, err := c.CalcProfitGen(utils.StrToInt64(wallet["currency_id"]), amount, c.SessUserId, utils.StrToInt64(wallet["last_update"]), time.Now().Unix(), "wallet") if err != nil { return "", utils.ErrInfo(err) } amount += profit amount = math.Floor(utils.Round(amount, 3)*100) / 100 forexOrdersAmount, err := c.Single("SELECT sum(amount) FROM forex_orders WHERE user_id = ? AND sell_currency_id = ? AND del_block_id = 0", c.SessUserId, wallet["currency_id"]).Float64() if err != nil { return "", utils.ErrInfo(err) } amount -= forexOrdersAmount cfProject["wallet_amount"] = utils.Float64ToStrPct(amount) } else { cfProject["wallet_amount"] = "0" } cfProject["currency"] = c.CurrencyList[utils.StrToInt64(cfProject["currency_id"])] newmap := make(map[string]interface{}) for k, v := range cfProject { newmap[k] = v } // наличие описаний newmap["lang"], err = c.GetMap("SELECT id, lang_id FROM cf_projects_data WHERE project_id = ?", "id", "lang_id", projectId) if err != nil { return "", utils.ErrInfo(err) } result, err := json.Marshal(newmap) if err != nil { return "", utils.ErrInfo(err) } return string(result), 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 }