Beispiel #1
0
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, &currency_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
}
Beispiel #3
0
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
}