Example #1
0
func (p *Parser) MoneyBackRequestFront() error {

	err := p.generalCheck()
	if err != nil {
		return p.ErrInfo(err)
	}

	verifyData := map[string]string{"order_id": "bigint", "seller_enc_text": "comment", "arbitrator0_enc_text": "comment", "arbitrator1_enc_text": "comment", "arbitrator2_enc_text": "comment", "arbitrator3_enc_text": "comment", "arbitrator4_enc_text": "comment"}
	err = p.CheckInputData(verifyData)
	if err != nil {
		return p.ErrInfo(err)
	}

	var txTime int64
	if p.BlockData != nil { // тр-ия пришла в блоке
		txTime = p.BlockData.Time
	} else { // голая тр-ия
		txTime = time.Now().Unix() - 30 // просто на всякий случай небольшой запас
	}

	// проверим, есть ли такой ордер, не был ли ранее запрос, точно ли покупатель наш юзер
	orderId, err := p.Single("SELECT id FROM orders WHERE id  =  ? AND status  =  'normal' AND end_time > ? AND buyer  =  ?", p.TxMaps.Int64["order_id"], txTime, p.TxUserID).Int64()
	if err != nil {
		return p.ErrInfo(err)
	}
	if orderId == 0 {
		return p.ErrInfo("orderId==0")
	}

	forSign := ""
	if p.BlockData != nil && p.BlockData.BlockId < 197115 {
		forSign = fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s", p.TxMap["type"], p.TxMap["time"], p.TxMap["user_id"], p.TxMap["order_id"], p.TxMap["arbitrator0_enc_text"], p.TxMap["arbitrator1_enc_text"], p.TxMap["arbitrator2_enc_text"], p.TxMap["arbitrator3_enc_text"], p.TxMap["arbitrator4_enc_text"], p.TxMap["seller_enc_text"])

	} else {
		encData := make(map[string]string)
		for i := 0; i < 5; i++ {
			iStr := utils.IntToStr(i)
			encData["arbitrator"+iStr+"_enc_text"] = string(utils.BinToHex(p.TxMap["arbitrator"+iStr+"_enc_text"]))
			if encData["arbitrator"+iStr+"_enc_text"] == "00" {
				encData["arbitrator"+iStr+"_enc_text"] = "0"
			}
		}
		forSign = fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s", p.TxMap["type"], p.TxMap["time"], p.TxMap["user_id"], p.TxMap["order_id"], encData["arbitrator0_enc_text"], encData["arbitrator1_enc_text"], encData["arbitrator2_enc_text"], encData["arbitrator3_enc_text"], encData["arbitrator4_enc_text"], utils.BinToHex(p.TxMap["seller_enc_text"]))
	}

	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_MONEY_BACK_REQUEST, "money_back_request", consts.LIMIT_MONEY_BACK_REQUEST_PERIOD)
	if err != nil {
		return p.ErrInfo(err)
	}
	return nil
}
Example #2
0
func (c *Controller) EDataBaseDump() (string, error) {

	if !c.NodeAdmin || c.SessRestricted != 0 {
		return "", utils.ErrInfo(errors.New("Permission denied"))
	}

	allTables, err := c.GetAllTables()
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	c.r.ParseForm()

	mainMap := make(map[string][]map[string]string)

	for _, table := range allTables {
		re := regexp.MustCompile("^e_")
		match := re.FindStringSubmatch(table)
		if len(match) > 0 {
			data, err := c.GetAll(`SELECT * FROM `+table, -1)
			if err != nil {
				return "", utils.ErrInfo(err)
			}
			for k, arr := range data {
				for name, value := range arr {
					if ok, _ := regexp.MatchString("(tx_hash)", name); ok {
						data[k][name] = string(utils.BinToHex([]byte(value)))
					}
				}
			}
			mainMap[table] = data
		}
	}

	jsonData, _ := json.Marshal(mainMap)
	log.Debug(string(jsonData))

	c.w.Header().Set("Content-Type", "text/plain")
	c.w.Header().Set("Content-Length", utils.IntToStr(len(jsonData)))
	t := time.Unix(utils.Time(), 0)
	c.w.Header().Set("Content-Disposition", `attachment; filename="dcoin_e_backup-`+t.Format(c.TimeFormat)+`.txt`)
	if _, err := c.w.Write(jsonData); err != nil {
		return "", utils.ErrInfo(errors.New("unable to write text"))
	}

	return "", nil
}
Example #3
0
func (p *Parser) MoneyBackRequest() error {

	err := p.selectiveLoggingAndUpd([]string{"status"}, []interface{}{"refund"}, "orders", []string{"id"}, []string{utils.Int64ToStr(p.TxMaps.Int64["order_id"])})
	if err != nil {
		return p.ErrInfo(err)
	}

	orderData, err := p.OneRow("SELECT seller, arbitrator0, arbitrator1, arbitrator2, arbitrator3, arbitrator4 FROM orders WHERE id  =  ?", p.TxMaps.Int64["order_id"]).Int64()
	if err != nil {
		return p.ErrInfo(err)
	}

	// проверим, не является ли мы продавцом или арбитром
	myUserId, _, myPrefix, _, err := p.GetMyUserId(orderData["seller"])
	if err != nil {
		return p.ErrInfo(err)
	}
	if orderData["seller"] == myUserId {
		err = p.ExecSql("INSERT INTO "+myPrefix+"my_comments ( type, id, comment, comment_status ) VALUES ( 'seller', ?, ?, 'encrypted' )", p.TxMaps.Int64["order_id"], utils.BinToHex(p.TxMap["seller_enc_text"]))
		if err != nil {
			return p.ErrInfo(err)
		}
	}
	for i := 0; i < 5; i++ {
		iStr := utils.IntToStr(i)
		if orderData["arbitrator"+iStr] == 0 {
			continue
		}
		myUserId, _, myPrefix, _, err := p.GetMyUserId(orderData["arbitrator"+iStr])
		if err != nil {
			return p.ErrInfo(err)
		}
		if orderData["arbitrator"+iStr] == myUserId {
			err = p.ExecSql("INSERT INTO "+myPrefix+"my_comments ( type, id, comment, comment_status ) VALUES ( 'arbitrator', ?, ?, 'encrypted' )", p.TxMaps.Int64["order_id"], utils.BinToHex(p.TxMaps.Bytes["arbitrator"+iStr+"_enc_text"]))
			if err != nil {
				return p.ErrInfo(err)
			}
		}
	}

	return nil
}
func (p *Parser) NewMaxOtherCurrencies() error {

	currencyList := make(map[string]int64)
	err := json.Unmarshal(p.TxMap["new_max_other_currencies"], &currencyList)
	if err != nil {
		return p.ErrInfo(err)
	}

	var currencyIds []int
	for k := range currencyList {
		currencyIds = append(currencyIds, utils.StrToInt(k))
	}
	sort.Ints(currencyIds)
	//sort.Sort(sort.Reverse(sort.IntSlice(keys)))

	for _, currencyId := range currencyIds {
		count := currencyList[utils.IntToStr(currencyId)]

		logData, err := p.OneRow("SELECT max_other_currencies, log_id FROM currency WHERE id  =  ?", currencyId).String()
		if err != nil {
			return p.ErrInfo(err)
		}
		logId, err := p.ExecSqlGetLastInsertId("INSERT INTO log_currency ( max_other_currencies, prev_log_id ) VALUES ( ?, ? )", "log_id", logData["max_other_currencies"], logData["log_id"])
		if err != nil {
			return p.ErrInfo(err)
		}
		err = p.ExecSql("UPDATE currency SET max_other_currencies = ?, log_id = ? WHERE id = ?", count, logId, currencyId)
		if err != nil {
			return p.ErrInfo(err)
		}
	}
	err = p.ExecSql("INSERT INTO max_other_currencies_time ( time ) VALUES ( ? )", p.BlockData.Time)
	if err != nil {
		return p.ErrInfo(err)
	}
	return nil
}
Example #5
0
func (p *Parser) MoneyBackRequestRollback() error {
	orderData, err := p.OneRow("SELECT seller, arbitrator0, arbitrator1, arbitrator2, arbitrator3, arbitrator4 FROM orders WHERE id  =  ?", p.TxMaps.Int64["order_id"]).Int64()
	if err != nil {
		return p.ErrInfo(err)
	}

	// проверим, не является ли мы продавцом или арбитром
	myUserId, _, myPrefix, _, err := p.GetMyUserId(orderData["seller"])
	if err != nil {
		return p.ErrInfo(err)
	}
	if orderData["seller"] == myUserId {
		err = p.ExecSql("DELETE FROM "+myPrefix+"my_comments WHERE type = 'seller' AND id = ?", p.TxMaps.Int64["order_id"])
		if err != nil {
			return p.ErrInfo(err)
		}
	}
	for i := 0; i < 5; i++ {
		iStr := utils.IntToStr(i)
		if orderData["arbitrator"+iStr] == 0 {
			continue
		}
		myUserId, _, myPrefix, _, err := p.GetMyUserId(orderData["arbitrator"+iStr])
		if err != nil {
			return p.ErrInfo(err)
		}
		if orderData["arbitrator"+iStr] == myUserId {
			err = p.ExecSql("DELETE FROM "+myPrefix+"my_comments WHERE type = 'arbitrator' AND id = ?", p.TxMaps.Int64["order_id"])
			if err != nil {
				return p.ErrInfo(err)
			}
		}
	}
	err = p.selectiveRollback([]string{"status"}, "orders", "id="+utils.Int64ToStr(p.TxMaps.Int64["order_id"]), false)

	return nil
}
Example #6
0
func (p *Parser) CashRequestOutFront() error {

	err := p.generalCheck()
	if err != nil {
		return p.ErrInfo(err)
	}

	verifyData := map[string]string{"to_user_id": "bigint", "currency_id": "currency_id", "amount": "amount", "comment": "comment", "hash_code": "sha256"}
	err = p.CheckInputData(verifyData)
	if err != nil {
		return p.ErrInfo(err)
	}

	// нельзя слать запрос на woc
	if p.TxMaps.Int64["currency_id"] == 1 {
		return p.ErrInfo("WOC")
	}

	// прошло ли 30 дней с момента регистрации майнера
	minerNewbie := p.checkMinerNewbie()
	if minerNewbie != nil {
		// возможно, что майнер отдал наличные за DC и у него есть общенные суммы с repaid
		// нужно дать возможность вывести ровно столько, сколько он отдал
		repaidAmount, err := p.GetRepaidAmount(p.TxMaps.Int64["currency_id"], p.TxUserID)
		// сколько уже получил наличных
		amountCashRequests, err := p.Single("SELECT sum(amount) FROM cash_requests WHERE status  =  'approved' AND currency_id  =  ? AND from_user_id  =  ?", p.TxMaps.Int64["currency_id"], p.TxUserID).Float64()
		if err != nil {
			return p.ErrInfo(err)
		}
		if amountCashRequests+p.TxMaps.Money["amount"] > repaidAmount {
			return p.ErrInfo(fmt.Sprintf("%f + %f > %f", amountCashRequests, p.TxMaps.Money["amount"], repaidAmount))
		}
	}

	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"], utils.BinToHex(p.TxMap["comment"]), p.TxMap["currency_id"], p.TxMap["hash_code"])
	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")
	}

	// проверим, существует ли такая валюта в таблице DC-валют
	if ok, err := p.CheckCurrency(p.TxMaps.Int64["currency_id"]); !ok {
		return p.ErrInfo(err)
	}

	// ===  begin проверка to_user_id

	// является ли данный юзер майнером
	err = p.checkMiner(p.TxMaps.Int64["to_user_id"])
	if err != nil {
		return p.ErrInfo(err)
	}

	maxPromisedAmount, err := p.GetMaxPromisedAmount(p.TxMaps.Int64["currency_id"])
	if err != nil {
		return p.ErrInfo(err)
	}

	repaidAmount, err := p.GetRepaidAmount(p.TxMaps.Int64["currency_id"], p.TxMaps.Int64["to_user_id"])
	if err != nil {
		return p.ErrInfo(err)
	}
	if p.TxMaps.Money["amount"]+repaidAmount > maxPromisedAmount {
		return p.ErrInfo(fmt.Sprintf("%f + %f > %f", p.TxMaps.Money["amount"], repaidAmount, maxPromisedAmount))
	}

	// не даем превысить общий лимит
	promisedAmount, err := p.Single("SELECT amount FROM promised_amount WHERE status  =  'mining' AND currency_id  =  ? AND user_id  =  ? AND del_block_id  =  0 AND del_mining_block_id  =  0", p.TxMaps.Int64["currency_id"], p.TxMaps.Int64["to_user_id"]).Float64()
	if err != nil {
		return p.ErrInfo(err)
	}
	rest := maxPromisedAmount - repaidAmount
	if rest < promisedAmount {
		promisedAmount = rest
	}

	// минимальная сумма. теоретически может делиться на min_promised_amount пока не достигнет 0.01
	if p.TxMaps.Money["amount"] < promisedAmount/float64(p.Variables.Int64["min_promised_amount"]) {
		return p.ErrInfo(fmt.Sprintf("%f < %f / %d", p.TxMaps.Money["amount"], promisedAmount, p.Variables.Int64["min_promised_amount"]))
	}
	if p.TxMaps.Money["amount"] < 0.01 {
		return p.ErrInfo("amount<0.01")
	}

	var txTime int64
	if p.BlockData != nil { // тр-ия пришла в блоке
		txTime = p.BlockData.Time
	} else {
		txTime = time.Now().Unix() - 30 // просто на всякий случай небольшой запас
	}

	// Чтобы не задалбывать получателей запроса на обмен, не даем отправить следующий запрос, пока не пройдет cash_request_time сек с момента предыдущего
	cashRequestPending, err := p.Single("SELECT status FROM cash_requests WHERE to_user_id  =  ? AND del_block_id  =  0 AND for_repaid_del_block_id  =  0 AND time > ? AND status  =  'pending'", p.TxMaps.Int64["to_user_id"], (txTime - p.Variables.Int64["cash_request_time"])).String()
	if err != nil {
		return p.ErrInfo(err)
	}
	if len(cashRequestPending) > 0 {
		return p.ErrInfo("cash_requests status not null")
	}

	// не находится ли юзер в данный момент на каникулах.
	rows, err := p.Query(p.FormatQuery("SELECT start_time, end_time FROM holidays WHERE user_id = ? AND del = 0"), p.TxMaps.Int64["to_user_id"])
	if err != nil {
		return p.ErrInfo(err)
	}
	defer rows.Close()
	for rows.Next() {
		var startTime, endTime int64
		err = rows.Scan(&startTime, &endTime)
		if err != nil {
			return p.ErrInfo(err)
		}
		var time1, time2 int64
		if p.BlockData != nil {
			time1 = p.BlockData.Time
			time2 = time1
		} else {
			// тут используем time() с запасом 1800 сек, т.к. в момент, когда тр-ия попадет в блок, каникулы уже могут начаться.
			// т.е. у голой тр-ии проверка идет жестче
			time1 = time.Now().Unix() + 1800
			time2 = time.Now().Unix()
		}
		if startTime <= time1 && endTime >= time2 {
			return p.ErrInfo("error holidays")
		}
	}
	// === end проверка to_user_id

	// ===  begin проверка отправителя
	// является ли данный юзер майнером
	err = p.checkMiner(p.TxUserID)
	if err != nil {
		return p.ErrInfo(err)
	}
	/*
	 * WalletsBuffer тут не используем т.к. попадение 2-х тр-ий данного типа в 1 блок во время генарции блока исключается в clear_incompatible_tx.
	 * там же исключается попадение данного типа с new_forex и пр.
	 * А проверка 2-го списания идет в ParseDataFull
	 * */
	if p.BlockData != nil && p.BlockData.BlockId > 173941 {
		// в блоке 173941 была попытка отправить 2 запроса на 408 и 200 dUSD, в то время как на кошельке было только 449.6
		// в итоге check_sender_money возвращало ошибку
		// есть ли нужная сумма на кошельке
		p.TxMaps.Int64["from_user_id"] = p.TxMaps.Int64["user_id"]
		for i := 0; i < 5; i++ {
			p.TxMaps.Money["arbitrator"+utils.IntToStr(i)+"_commission"] = 0
		}
		p.TxMaps.Money["commission"] = 0
		//func (p *Parser) checkSenderMoney(currencyId, fromUserId int64, amount, commission, arbitrator0_commission, arbitrator1_commission, arbitrator2_commission, arbitrator3_commission, arbitrator4_commission float64) (float64, error) {
		_, err := p.checkSenderMoney(p.TxMaps.Int64["currency_id"], p.TxMaps.Int64["from_user_id"], p.TxMaps.Money["amount"], p.TxMaps.Money["commission"], p.TxMaps.Money["arbitrator0_commission"], p.TxMaps.Money["arbitrator1_commission"], p.TxMaps.Money["arbitrator2_commission"], p.TxMaps.Money["arbitrator3_commission"], p.TxMaps.Money["arbitrator4_commission"])
		if err != nil {
			return p.ErrInfo(err)
		}
	}
	// У юзера не должно быть cash_requests со статусом pending
	err = p.CheckCashRequests(p.TxUserID)
	if err != nil {
		return p.ErrInfo(err)
	}

	err = p.limitRequest(p.Variables.Int64["limit_cash_requests_out"], "cash_requests", p.Variables.Int64["limit_cash_requests_out_period"])
	if err != nil {
		return p.ErrInfo(err)
	}
	// ===  end проверка отправителя

	return nil
}
Example #7
0
func IndexCf(w http.ResponseWriter, r *http.Request) {

	nav := ""
	if len(r.URL.RawQuery) > 0 {
		re, _ := regexp.Compile(`category\-([0-9]+)`)
		match := re.FindStringSubmatch(r.URL.RawQuery)
		if len(match) > 0 {
			nav = "dc_navigate ('cfCatalog', {'category_id':" + match[1] + "})\n"
		} else {
			re, _ := regexp.Compile(`([A-Z0-9]{7}|id-[0-9]+)\-?([0-9]+)?\-?(funders|comments|news|home|payment)?`)
			match0 := re.FindStringSubmatch(r.URL.RawQuery)
			if len(match0) > 1 {
				// $m[1] - название валюты или id валюты
				// $m[2] - id языка
				// $m[3] - тип страницы (funders|comments|news)
				addNav := ""
				re, _ := regexp.Compile(`id\-([0-9]+)`)
				match := re.FindStringSubmatch(match0[1])
				if len(match) > 1 {
					addNav += "'onlyProjectId':'" + match[1] + "',"
				} else {
					addNav += "'onlyCfCurrencyName':'" + match[1] + "',"
				}
				if len(match0) > 2 {
					addNav += "'lang_id':'" + match0[2] + "',"
				}
				if len(match0) > 3 {
					addNav += "'page':'" + match0[3] + "',"
				}
				addNav = addNav[:len(addNav)-1]
				nav = "dc_navigate ('cfPagePreview', {" + addNav + "})\n"
			}
		}
	} else {
		nav = "dc_navigate ('cfCatalog')\n"
	}

	log.Debug(nav)

	c := new(Controller)
	c.r = r
	dbInit := false
	if len(configIni["db_user"]) > 0 || (configIni["db_type"] == "sqlite") {
		dbInit = true
	}
	if dbInit {
		var err error
		c.DCDB = utils.DB
		if c.DCDB.DB == nil {
			log.Error("utils.DB == nil")
			dbInit = false
		}
		// отсутвие таблы выдаст ошибку, значит процесс инсталяции еще не пройден и надо выдать 0-й шаг
		_, err = c.DCDB.Single("SELECT progress FROM install").String()
		if err != nil {
			log.Error("%v", err)
			dbInit = false
		}

		cfUrl, err := c.GetCfUrl()
		cfLang, err := c.GetAllCfLng()

		r.ParseForm()

		c.Parameters, err = c.GetParameters()
		log.Debug("parameters=", c.Parameters)

		lang := GetLang(w, r, c.Parameters)

		analyticsDisabled, err := utils.DB.Single(`SELECT analytics_disabled FROM config`).String()
		if err != nil {
			log.Error("%v", err)
		}

		data, err := static.Asset("static/templates/index_cf.html")
		t := template.New("template")
		t, err = t.Parse(string(data))
		if err != nil {
			log.Error("%v", err)
		}
		b := new(bytes.Buffer)
		t.Execute(b, &indexCf{CfUrl: cfUrl, Lang: utils.IntToStr(lang), Nav: template.JS(nav), CfLang: cfLang, AnalyticsDisabled: analyticsDisabled})
		w.Write(b.Bytes())
	}
}
Example #8
0
func (p *Parser) VotesComplexRollback() error {

	currencyVotes := make(map[string][]float64)

	if p.BlockData.BlockId > 77951 {
		vComplex, err := makeVcomplex(p.TxMap["json_data"])
		if err != nil {
			return p.ErrInfo(err)
		}
		if p.BlockData.BlockId > 153750 && vComplex.Admin != 0 {
			err := p.selectiveRollback([]string{"admin_user_id", "time"}, "votes_admin", "user_id="+string(p.TxMap["user_id"]), false)
			if err != nil {
				return p.ErrInfo(err)
			}
		}
		// голоса за реф. %
		err = p.selectiveRollback([]string{"first", "second", "third"}, "votes_referral", "user_id="+string(p.TxMap["user_id"]), false)
		if err != nil {
			return p.ErrInfo(err)
		}

		currencyVotes = vComplex.Currency

	} else { // раньше не было рефских и выбора админа
		vComplex := make(map[string][]float64)
		err := json.Unmarshal(p.TxMap["json_data"], &vComplex)
		if err != nil {
			return p.ErrInfo(err)
		}
		currencyVotes = vComplex
	}

	// сортируем по $currency_id в обратном порядке
	var currencyIds []int
	for k := range currencyVotes {
		currencyIds = append(currencyIds, utils.StrToInt(k))
	}
	sort.Sort(sort.Reverse(sort.IntSlice(currencyIds)))

	for _, currencyId := range currencyIds {
		currencyIdStr := utils.IntToStr(currencyId)
		// miner_pct
		err := p.selectiveRollback([]string{"pct", "time"}, "votes_miner_pct", "user_id="+string(p.TxMap["user_id"])+" AND currency_id = "+currencyIdStr, false)
		if err != nil {
			return p.ErrInfo(err)
		}
		// user_pct
		err = p.selectiveRollback([]string{"pct"}, "votes_user_pct", "user_id="+string(p.TxMap["user_id"])+" AND currency_id = "+currencyIdStr, false)
		if err != nil {
			return p.ErrInfo(err)
		}
		// reduction
		err = p.selectiveRollback([]string{"pct", "time"}, "votes_reduction", "user_id="+string(p.TxMap["user_id"])+" AND currency_id = "+currencyIdStr, false)
		if err != nil {
			return p.ErrInfo(err)
		}
		// max_promised_amount
		err = p.selectiveRollback([]string{"amount"}, "votes_max_promised_amount", "user_id="+string(p.TxMap["user_id"])+" AND currency_id = "+currencyIdStr, false)
		if err != nil {
			return p.ErrInfo(err)
		}
		// max_other_currencies
		err = p.selectiveRollback([]string{"count"}, "votes_max_other_currencies", "user_id="+string(p.TxMap["user_id"])+" AND currency_id = "+currencyIdStr, false)
		if err != nil {
			return p.ErrInfo(err)
		}

		// проверим, не наш ли это user_id
		myUserId, _, myPrefix, _, err := p.GetMyUserId(p.TxUserID)
		if err != nil {
			return p.ErrInfo(err)
		}

		if p.TxUserID == myUserId {
			// отметимся, что голосовали, чтобы не пришло уведомление о необходимости голосовать раз в 2 недели
			err = p.ExecSql("DELETE FROM "+myPrefix+"my_complex_votes WHERE last_voting =?", p.BlockData.Time)
			if err != nil {
				return p.ErrInfo(err)
			}
		}
	}

	return nil
}
Example #9
0
func (c *Controller) PoolDataBaseDump() (string, error) {

	if !c.NodeAdmin || c.SessRestricted != 0 {
		return "", utils.ErrInfo(errors.New("Permission denied"))
	}

	allTables, err := c.GetAllTables()
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	c.r.ParseForm()
	dumpUserId := utils.StrToInt64(c.r.FormValue("dump_user_id"))

	mainMap := make(map[string][]map[string]string)

	if dumpUserId > 0 {
		for _, table := range consts.MyTables {
			data, err := c.GetAll(`SELECT * FROM `+table, -1)
			if err != nil {
				return "", utils.ErrInfo(err)
			}
			mainMap[table] = data
		}
	} else {
		for i := 0; i < len(c.CommunityUsers); i++ {
			for _, table := range consts.MyTables {
				table = utils.Int64ToStr(c.CommunityUsers[i]) + "_" + table
				if utils.InSliceString(table, allTables) {
					data, err := c.GetAll(`SELECT * FROM `+table, -1)
					for k, arr := range data {
						for name, value := range arr {
							if ok, _ := regexp.MatchString("(hash_code|public_key|encrypted)", name); ok {
								data[k][name] = string(utils.BinToHex([]byte(value)))
							}
						}
					}
					if err != nil {
						return "", utils.ErrInfo(err)
					}
					mainMap[table] = data
				}
			}
		}
	}

	jsonData, _ := json.Marshal(mainMap)
	log.Debug(string(jsonData))

	c.w.Header().Set("Content-Type", "text/plain")
	c.w.Header().Set("Content-Length", utils.IntToStr(len(jsonData)))
	t := time.Unix(utils.Time(), 0)
	c.w.Header().Set("Content-Disposition", `attachment; filename="dcoin_users_backup-`+t.Format(c.TimeFormat)+`.txt`)
	if _, err := c.w.Write(jsonData); err != nil {
		return "", utils.ErrInfo(errors.New("unable to write text"))
	}

	err = json.Unmarshal(jsonData, &mainMap)
	if err != nil {
		return "", utils.ErrInfo(err)
	}

	// для теста
	for table, arr := range mainMap {
		log.Debug(table)
		for i, data := range arr {
			log.Debug("%v", i)
			colNames := ""
			values := []string{}
			qq := ""
			for name, value := range data {
				colNames += name + ","
				values = append(values, value)
				if ok, _ := regexp.MatchString("(hash_code|public_key|encrypted)", name); ok {
					qq += "[hex],"
				} else {
					qq += "?,"
				}
			}
			colNames = colNames[0 : len(colNames)-1]
			qq = qq[0 : len(qq)-1]
			query := `INSERT INTO ` + table + ` (` + colNames + `) VALUES (` + qq + `)`
			log.Debug("%v", query)
			log.Debug("%v", values)
		}
	}

	return "", nil
}
Example #10
0
func (c *Controller) Assignments() (string, error) {

	var randArr []int64
	// Нельзя завершить голосование юзеров раньше чем через сутки, даже если набрано нужное кол-во голосов.
	// В голосовании нодов ждать сутки не требуется, т.к. там нельзя поставить поддельных нодов

	// Модерация новых майнеров
	// берем тех, кто прошел проверку нодов (type='node_voting')
	num, err := c.Single("SELECT count(id) FROM votes_miners WHERE votes_end  =  0 AND type  =  'user_voting'").Int64()
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	if num > 0 {
		randArr = append(randArr, 1)
	}

	// Модерация promised_amount
	// вначале получим ID валют, которые мы можем проверять.
	currency, err := c.GetList("SELECT currency_id FROM promised_amount WHERE status IN ('mining', 'repaid') AND user_id = ?", c.SessUserId).String()
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	addSql := ""
	currencyIds := strings.Join(currency, ",")
	if len(currencyIds) > 0 || c.SessUserId == 1 {
		if c.SessUserId != 1 {
			addSql = "AND currency_id IN (" + currencyIds + ")"
		}
		num, err := c.Single("SELECT count(id) FROM promised_amount WHERE status  =  'pending' AND del_block_id  =  0 " + addSql + "").Int64()
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		if num > 0 {
			randArr = append(randArr, 2)
		}
	}

	log.Debug("randArr %v", randArr)

	var AssignType int64
	if len(randArr) > 0 {
		AssignType = randArr[utils.RandInt(0, len(randArr))]
	}

	cloneHosts := make(map[int64][]string)
	var photoHosts []string
	examplePoints := make(map[string]string)
	tplName := "assignments"
	tplTitle := "assignments"

	var txType string
	var txTypeId int64
	var timeNow int64
	var myRace, myCountry, mainQuestion, newPromiseAmount, videoHost string
	var promisedAmountData, userInfo map[string]string

	switch AssignType {
	case 1:

		// ***********************************
		// задания по модерации новых майнеров
		// ***********************************
		txType = "VotesMiner"
		txTypeId = utils.TypeInt(txType)
		timeNow = utils.Time()

		userInfo, err = c.OneRow(`
				SELECT miners_data.user_id,
							 votes_miners.id as vote_id,
							 face_coords,
							 profile_coords,
							 video_type,
							 video_url_id,
							 photo_block_id,
							 photo_max_miner_id,
							 miners_keepers,
							 http_host
				FROM votes_miners
				LEFT JOIN miners_data ON miners_data.user_id = votes_miners.user_id
				LEFT JOIN `+c.MyPrefix+`my_tasks ON `+c.MyPrefix+`my_tasks.id = votes_miners.id
				WHERE 	votes_end = 0 AND
						votes_miners.type = 'user_voting' AND
						(`+c.MyPrefix+`my_tasks.time IS NULL OR (`+c.MyPrefix+`my_tasks.time < ? AND `+c.MyPrefix+`my_tasks.type  =  'miner'))
				`, utils.Time()-consts.ASSIGN_TIME).String()
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		if len(userInfo) == 0 {
			tplName = "assignments"
			break
		}

		examplePoints, err = c.GetPoints(c.Lang)
		if err != nil {
			return "", utils.ErrInfo(err)
		}

		// получим ID майнеров, у которых лежат фото нужного нам юзера
		minersIds := utils.GetMinersKeepers(userInfo["photo_block_id"], userInfo["photo_max_miner_id"], userInfo["miners_keepers"], true)
		if len(minersIds) > 0 {
			photoHosts, err = c.GetList("SELECT http_host FROM miners_data WHERE miner_id  IN (" + utils.JoinInts(minersIds, ",") + ")").String()
			if err != nil {
				return "", utils.ErrInfo(err)
			}
		}

		// отрезки майнера, которого проверяем
		relations, err := c.OneRow("SELECT * FROM faces WHERE user_id  =  ?", userInfo["user_id"]).String()
		if err != nil {
			return "", utils.ErrInfo(err)
		}

		// получим допустимые расхождения между точками и совместимость версий
		data_, err := c.OneRow("SELECT tolerances, compatibility FROM spots_compatibility").String()
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		tolerances := make(map[string]map[string]string)
		if err := json.Unmarshal([]byte(data_["tolerances"]), &tolerances); err != nil {
			return "", utils.ErrInfo(err)
		}
		var compatibility []int
		if err := json.Unmarshal([]byte(data_["compatibility"]), &compatibility); err != nil {
			return "", utils.ErrInfo(err)
		}

		// формируем кусок SQL-запроса для соотношений отрезков
		addSqlTolerances := ""
		typesArr := []string{"face", "profile"}
		for i := 0; i < len(typesArr); i++ {
			for j := 1; j <= len(tolerances[typesArr[i]]); j++ {
				currentRelations := utils.StrToFloat64(relations[typesArr[i][:1]+utils.IntToStr(j)])
				diff := utils.StrToFloat64(tolerances[typesArr[i]][utils.IntToStr(j)]) * currentRelations
				if diff == 0 {
					continue
				}
				min := currentRelations - diff
				max := currentRelations + diff
				addSqlTolerances += typesArr[i][:1] + utils.IntToStr(j) + ">" + utils.Float64ToStr(min) + " AND " + typesArr[i][:1] + utils.IntToStr(j) + " < " + utils.Float64ToStr(max) + " AND "
			}
		}
		addSqlTolerances = addSqlTolerances[:len(addSqlTolerances)-4]

		// формируем кусок SQL-запроса для совместимости версий
		addSqlCompatibility := ""
		for i := 0; i < len(compatibility); i++ {
			addSqlCompatibility += fmt.Sprintf(`%d,`, compatibility[i])
		}
		addSqlCompatibility = addSqlCompatibility[:len(addSqlCompatibility)-1]

		// получаем из БД похожие фото
		rows, err := c.Query(c.FormatQuery(`
				SELECT miners_data.user_id,
							 photo_block_id,
							 photo_max_miner_id,
							 miners_keepers
				FROM faces
				LEFT JOIN miners_data ON
						miners_data.user_id = faces.user_id
				WHERE `+addSqlTolerances+` AND
							version IN (`+addSqlCompatibility+`) AND
				             faces.status = 'used' AND
				             miners_data.user_id != ?
				LIMIT 100
				`), userInfo["user_id"])
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		defer rows.Close()
		for rows.Next() {
			var photo_block_id, photo_max_miner_id, miners_keepers string
			var user_id int64
			err = rows.Scan(&user_id, &photo_block_id, &photo_max_miner_id, &miners_keepers)
			if err != nil {
				return "", utils.ErrInfo(err)
			}
			// майнеры, у которых можно получить фото нужного нам юзера
			minersIds := utils.GetMinersKeepers(photo_block_id, photo_max_miner_id, miners_keepers, true)
			if len(minersIds) > 0 {
				photoHosts, err = c.GetList("SELECT http_host FROM miners_data WHERE miner_id  IN (" + utils.JoinInts(minersIds, ",") + ")").String()
				if err != nil {
					return "", utils.ErrInfo(err)
				}
			}
			cloneHosts[user_id] = photoHosts
		}

		data, err := c.OneRow("SELECT race, country FROM " + c.MyPrefix + "my_table").Int64()
		myRace = c.Races[data["race"]]
		myCountry = consts.Countries[int(data["country"])]

		tplName = "assignments_new_miner"
		tplTitle = "assignmentsNewMiner"

	case 2:
		promisedAmountData, err = c.OneRow(`
				SELECT id,
							 currency_id,
							 amount,
							 user_id,
							 video_type,
							 video_url_id
				FROM promised_amount
				WHERE status =  'pending' AND
							 del_block_id = 0
				` + addSql + `
		`).String()
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		promisedAmountData["currency_name"] = c.CurrencyList[utils.StrToInt64(promisedAmountData["currency_id"])]

		// проверим, не голосовали ли мы за это в последние 30 минут
		repeated, err := c.Single("SELECT id FROM "+c.MyPrefix+"my_tasks WHERE type  =  'promised_amount' AND id  =  ? AND time > ?", promisedAmountData["id"], utils.Time()-consts.ASSIGN_TIME).Int64()
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		if repeated > 0 {
			tplName = "assignments"
			tplTitle = "assignments"
			break
		}

		// если нету видео на ютубе, то получаем host юзера, где брать видео
		if promisedAmountData["video_url_id"] == "null" {
			videoHost, err = c.Single("SELECT http_host FROM miners_data WHERE user_id  =  ?", promisedAmountData["user_id"]).String()
			if err != nil {
				return "", utils.ErrInfo(err)
			}
		}

		// каждый раз обязательно проверяем, где находится юзер
		userInfo, err = c.OneRow(`
				SELECT latitude,
							 user_id,
							 longitude,
							 photo_block_id,
							 photo_max_miner_id,
							 miners_keepers,
							 http_host
				FROM miners_data
				WHERE user_id = ?
				`, promisedAmountData["user_id"]).String()
		if err != nil {
			return "", utils.ErrInfo(err)
		}

		// получим ID майнеров, у которых лежат фото нужного нам юзера
		minersIds := utils.GetMinersKeepers(userInfo["photo_block_id"], userInfo["photo_max_miner_id"], userInfo["miners_keepers"], true)
		if len(minersIds) > 0 {
			photoHosts, err = c.GetList("SELECT http_host FROM miners_data WHERE miner_id  IN (" + utils.JoinInts(minersIds, ",") + ")").String()
			if err != nil {
				return "", utils.ErrInfo(err)
			}
		}

		txType = "VotesPromisedAmount"
		txTypeId = utils.TypeInt(txType)
		timeNow = utils.Time()

		newPromiseAmount = strings.Replace(c.Lang["new_promise_amount"], "[amount]", promisedAmountData["amount"], -1)
		newPromiseAmount = strings.Replace(newPromiseAmount, "[currency]", promisedAmountData["currency_name"], -1)

		mainQuestion = strings.Replace(c.Lang["main_question"], "[amount]", promisedAmountData["amount"], -1)
		mainQuestion = strings.Replace(mainQuestion, "[currency]", promisedAmountData["currency_name"], -1)

		tplName = "assignments_promised_amount"
		tplTitle = "assignmentsPromisedAmount"

	default:
		tplName = "assignments"
		tplTitle = "assignments"
	}

	TemplateStr, err := makeTemplate(tplName, tplTitle, &AssignmentsPage{
		Alert:              c.Alert,
		Lang:               c.Lang,
		CountSignArr:       c.CountSignArr,
		ShowSignData:       c.ShowSignData,
		UserId:             c.SessUserId,
		TimeNow:            timeNow,
		TxType:             txType,
		TxTypeId:           txTypeId,
		SignData:           "",
		CurrencyList:       c.CurrencyList,
		MainQuestion:       mainQuestion,
		NewPromiseAmount:   newPromiseAmount,
		MyRace:             myRace,
		MyCountry:          myCountry,
		ExamplePoints:      examplePoints,
		VideoHost:          videoHost,
		PhotoHosts:         photoHosts,
		PromisedAmountData: promisedAmountData,
		UserInfo:           userInfo,
		CloneHosts:         cloneHosts})
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	return TemplateStr, nil
}
Example #11
0
func (p *Parser) SendDcRollback() error {
	// нужно отметить в log_time_money_orders, что тр-ия НЕ прошла в блок
	err := p.ExecSql("UPDATE log_time_money_orders SET del_block_id = 0 WHERE hex(tx_hash) = ?", p.TxHash)
	if err != nil {
		return p.ErrInfo(err)
	}

	// 6 комиссия нода-генератора блока
	if p.TxMaps.Float64["commission"] >= 0.01 {
		err = p.generalRollback("wallets", p.BlockData.UserId, "AND currency_id = "+utils.Int64ToStr(p.TxMaps.Int64["currency_id"]), false)
		if err != nil {
			return p.ErrInfo(err)
		}
		// возможно были списания по кредиту нода-генератора
		err = p.loanPaymentsRollback(p.BlockData.UserId, p.TxMaps.Int64["currency_id"])
		if err != nil {
			return p.ErrInfo(err)
		}
	}

	// 5 обновим сумму на кошельке получателю
	// возможно были списания по кредиту
	err = p.loanPaymentsRollback(p.TxMaps.Int64["to_user_id"], p.TxMaps.Int64["currency_id"])
	if err != nil {
		return p.ErrInfo(err)
	}
	err = p.generalRollback("wallets", p.TxMaps.Int64["to_user_id"], "AND currency_id = "+utils.Int64ToStr(p.TxMaps.Int64["currency_id"]), false)
	if err != nil {
		return p.ErrInfo(err)
	}

	// 4 обновим сумму на кошельке отправителя
	err = p.generalRollback("wallets", p.TxMaps.Int64["from_user_id"], "AND currency_id = "+utils.Int64ToStr(p.TxMaps.Int64["currency_id"]), false)
	if err != nil {
		return p.ErrInfo(err)
	}

	// 3
	err = p.pointsUpdateRollbackMain(p.TxMaps.Int64["to_user_id"])
	if err != nil {
		return p.ErrInfo(err)
	}

	// 2
	err = p.pointsUpdateRollbackMain(p.TxMaps.Int64["from_user_id"])
	if err != nil {
		return p.ErrInfo(err)
	}
	// 1
	err = p.pointsUpdateRollbackMain(p.BlockData.UserId)
	if err != nil {
		return p.ErrInfo(err)
	}

	// отменяем чистку буфера
	err = p.ExecSql("UPDATE wallets_buffer SET del_block_id = 0 WHERE hex(hash) = ?", p.TxHash)
	if err != nil {
		return p.ErrInfo(err)
	}

	if p.BlockData.BlockId > consts.ARBITRATION_BLOCK_START {

		// на какой период манибека согласен продавец
		arbitrationDaysRefund, err := p.Single("SELECT arbitration_days_refund FROM users WHERE user_id  =  ?", p.TxMaps.Int64["to_user_id"]).Int64()
		if err != nil {
			return p.ErrInfo(err)
		}
		if arbitrationDaysRefund > 0 {
			delOrder := false
			for i := 0; i < 5; i++ {
				iStr := utils.IntToStr(i)
				if p.TxMaps.Int64["arbitrator"+iStr] > 0 && p.TxMaps.Float64["arbitrator"+iStr+"_commission"] >= 0.01 {
					err = p.generalRollback("wallets", p.TxMaps.Int64["arbitrator"+iStr], "AND currency_id = "+utils.Int64ToStr(p.TxMaps.Int64["currency_id"]), false)
					if err != nil {
						return p.ErrInfo(err)
					}
					if !delOrder {
						err = p.ExecSql("DELETE FROM orders WHERE block_id = ? AND buyer = ? AND seller = ? AND currency_id = ? AND amount = ?", p.BlockData.BlockId, p.TxMaps.Int64["from_user_id"], p.TxMaps.Int64["to_user_id"], p.TxMaps.Int64["currency_id"], p.TxMaps.Float64["amount"])
						if err != nil {
							return p.ErrInfo(err)
						}
						err = p.rollbackAI("orders", 1)
						if err != nil {
							return p.ErrInfo(err)
						}
						delOrder = true
					}
					// возможно были списания по кредиту арбитра
					err = p.loanPaymentsRollback(p.TxMaps.Int64["arbitrator"+iStr], p.TxMaps.Int64["currency_id"])
					if err != nil {
						return p.ErrInfo(err)
					}
				}
			}
		}
	}

	err = p.mydctxRollback()
	if err != nil {
		return p.ErrInfo(err)
	}

	return nil
}
Example #12
0
/**
Обработка данных (блоков или транзакций), пришедших с гейта. Только проверка.
*/
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
}
Example #13
0
func Start(dir string, thrustWindowLoder *window.Window) {

	var err error
	IosLog("start")

	defer func() {
		if r := recover(); r != nil {
			log.Error("Recovered", r)
			panic(r)
		}
	}()

	if dir != "" {
		fmt.Println("dir", dir)
		*utils.Dir = dir
	}
	IosLog("dir:" + dir)
	fmt.Println("utils.Dir", *utils.Dir)

	fmt.Println("dcVersion:", consts.VERSION)
	log.Debug("dcVersion: %v", consts.VERSION)

	// читаем config.ini
	configIni := make(map[string]string)
	configIni_, err := config.NewConfig("ini", *utils.Dir+"/config.ini")
	if err != nil {
		IosLog("err:" + fmt.Sprintf("%s", utils.ErrInfo(err)))
		log.Error("%v", utils.ErrInfo(err))
	} else {
		configIni, err = configIni_.GetSection("default")
	}

	// убьем ранее запущенный Dcoin
	if !utils.Mobile() {
		fmt.Println("kill dcoin.pid")
		if _, err := os.Stat(*utils.Dir + "/dcoin.pid"); err == nil {
			dat, err := ioutil.ReadFile(*utils.Dir + "/dcoin.pid")
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
			}
			var pidMap map[string]string
			err = json.Unmarshal(dat, &pidMap)
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
			}
			fmt.Println("old PID ("+*utils.Dir+"/dcoin.pid"+"):", pidMap["pid"])

			utils.DB, err = utils.NewDbConnect(configIni)

			err = KillPid(pidMap["pid"])
			if nil != err {
				fmt.Println(err)
				log.Error("KillPid %v", utils.ErrInfo(err))
			}
			if fmt.Sprintf("%s", err) != "null" {
				fmt.Println(fmt.Sprintf("%s", err))
				// даем 15 сек, чтобы завершиться предыдущему процессу
				for i := 0; i < 15; i++ {
					log.Debug("waiting killer %d", i)
					if _, err := os.Stat(*utils.Dir + "/dcoin.pid"); err == nil {
						fmt.Println("waiting killer")
						utils.Sleep(1)
					} else { // если dcoin.pid нет, значит завершился
						break
					}
				}
			}
		}
	}

	// сохраним текущий pid и версию
	if !utils.Mobile() {
		pid := os.Getpid()
		PidAndVer, err := json.Marshal(map[string]string{"pid": utils.IntToStr(pid), "version": consts.VERSION})
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}
		err = ioutil.WriteFile(*utils.Dir+"/dcoin.pid", PidAndVer, 0644)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			panic(err)
		}
	}

	controllers.SessInit()
	controllers.ConfigInit()
	daemons.ConfigInit()

	go func() {
		utils.DB, err = utils.NewDbConnect(configIni)
		log.Debug("%v", utils.DB)
		IosLog("utils.DB:" + fmt.Sprintf("%v", utils.DB))
		if err != nil {
			IosLog("err:" + fmt.Sprintf("%s", utils.ErrInfo(err)))
			log.Error("%v", utils.ErrInfo(err))
			panic(err)
			os.Exit(1)
		}
	}()

	f, err := os.OpenFile(*utils.Dir+"/dclog.txt", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0777)
	if err != nil {
		IosLog("err:" + fmt.Sprintf("%s", utils.ErrInfo(err)))
		log.Error("%v", utils.ErrInfo(err))
		panic(err)
		os.Exit(1)
	}
	defer f.Close()
	IosLog("configIni:" + fmt.Sprintf("%v", configIni))
	var backend *logging.LogBackend
	switch configIni["log_output"] {
	case "file":
		backend = logging.NewLogBackend(f, "", 0)
	case "console":
		backend = logging.NewLogBackend(os.Stderr, "", 0)
	case "file_console":
		//backend = logging.NewLogBackend(io.MultiWriter(f, os.Stderr), "", 0)
	default:
		backend = logging.NewLogBackend(f, "", 0)
	}
	backendFormatter := logging.NewBackendFormatter(backend, format)
	backendLeveled := logging.AddModuleLevel(backendFormatter)

	logLevel_ := "DEBUG"
	if *utils.LogLevel == "" {
		logLevel_ = configIni["log_level"]
	} else {
		logLevel_ = *utils.LogLevel
	}

	logLevel, err := logging.LogLevel(logLevel_)
	if err != nil {
		log.Error("%v", utils.ErrInfo(err))
	}

	log.Debug("logLevel: %v", logLevel)
	backendLeveled.SetLevel(logLevel, "")
	logging.SetBackend(backendLeveled)

	rand.Seed(time.Now().UTC().UnixNano())

	// если есть OldFileName, значит работаем под именем tmp_dc и нужно перезапуститься под нормальным именем
	log.Error("OldFileName %v", *utils.OldFileName)
	if *utils.OldFileName != "" {

		// вначале нужно обновить БД в зависимости от версии
		dat, err := ioutil.ReadFile(*utils.Dir + "/dcoin.pid")
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}
		var pidMap map[string]string
		err = json.Unmarshal(dat, &pidMap)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}

		log.Debug("OldFileName %v", *utils.OldFileName)
		err = utils.CopyFileContents(*utils.Dir+`/dc.tmp`, *utils.OldFileName)
		if err != nil {
			log.Debug("%v", os.Stderr)
			log.Debug("%v", utils.ErrInfo(err))
		}
		// ждем подключения к БД
		for {
			if utils.DB == nil || utils.DB.DB == nil {
				utils.Sleep(1)
				continue
			}
			break
		}
		if len(pidMap["version"]) > 0 {
			if utils.VersionOrdinal(pidMap["version"]) < utils.VersionOrdinal("1.0.2b5") {
				log.Debug("%v", "ALTER TABLE config ADD COLUMN analytics_disabled smallint")
				err = utils.DB.ExecSql(`ALTER TABLE config ADD COLUMN analytics_disabled smallint`)
				if err != nil {
					log.Error("%v", utils.ErrInfo(err))
				}
			}
			if utils.VersionOrdinal(pidMap["version"]) < utils.VersionOrdinal("2.0.1b2") {
				log.Debug("%v", "ALTER TABLE config ADD COLUMN sqlite_db_url varchar(255)")
				err = utils.DB.ExecSql(`ALTER TABLE config ADD COLUMN sqlite_db_url varchar(255)`)
				if err != nil {
					log.Error("%v", utils.ErrInfo(err))
				}
			}
		}
		err = utils.DB.Close()
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}
		fmt.Println("DB Closed")
		err = os.Remove(*utils.Dir + "/dcoin.pid")
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}

		log.Debug("dc.tmp %v", *utils.Dir+`/dc.tmp`)
		err = exec.Command(*utils.OldFileName, "-dir", *utils.Dir).Start()
		if err != nil {
			log.Debug("%v", os.Stderr)
			log.Debug("%v", utils.ErrInfo(err))
		}
		log.Debug("OldFileName %v", *utils.OldFileName)
		os.Exit(1)
	}
	// откат БД до указанного блока
	if *utils.RollbackToBlockId > 0 {
		utils.DB, err = utils.NewDbConnect(configIni)
		parser := new(dcparser.Parser)
		parser.DCDB = utils.DB
		err = parser.RollbackToBlockId(*utils.RollbackToBlockId)
		if err != nil {
			fmt.Println(err)
			panic(err)
		}
		fmt.Print("complete")
		os.Exit(0)
	}

	log.Debug("public")
	IosLog("public")
	if _, err := os.Stat(*utils.Dir + "/public"); os.IsNotExist(err) {
		err = os.Mkdir(*utils.Dir+"/public", 0755)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
			panic(err)
			os.Exit(1)
		}
	}

	log.Debug("daemonsStart")
	IosLog("daemonsStart")

	daemons.StartDaemons()

	IosLog("MonitorDaemons")
	// мониторинг демонов
	daemonsTable := make(map[string]string)
	go func() {
		for {
			daemonNameAndTime := <-daemons.MonitorDaemonCh
			daemonsTable[daemonNameAndTime[0]] = daemonNameAndTime[1]
			if utils.Time()%10 == 0 {
				log.Debug("daemonsTable: %v\n", daemonsTable)
			}
		}
	}()

	// сигналы демонам для выхода
	IosLog("signals")
	stopdaemons.Signals()

	utils.Sleep(1)

	// мониторим сигнал из БД о том, что демонам надо завершаться
	go stopdaemons.WaitStopTime()

	BrowserHttpHost := "http://localhost:8089"
	HandleHttpHost := ""
	ListenHttpHost := ":" + *utils.ListenHttpHost
	go func() {
		// уже прошли процесс инсталяции, где юзер указал БД и был перезапуск кошелька
		if len(configIni["db_type"]) > 0 && !utils.Mobile() {
			for {
				// ждем, пока произойдет подключение к БД в другой гоурутине
				if utils.DB == nil || utils.DB.DB == nil {
					utils.Sleep(1)
					fmt.Println("wait DB")
				} else {
					break
				}
			}
			fmt.Println("GET http host")
			BrowserHttpHost, HandleHttpHost, ListenHttpHost = GetHttpHost()
			// для биржы нужен хост или каталог, поэтому нужно подключение к БД
			exhangeHttpListener(HandleHttpHost)
			// для ноды тоже нужна БД
			tcpListener()
		}
		IosLog(fmt.Sprintf("BrowserHttpHost: %v, HandleHttpHost: %v, ListenHttpHost: %v", BrowserHttpHost, HandleHttpHost, ListenHttpHost))
		fmt.Printf("BrowserHttpHost: %v, HandleHttpHost: %v, ListenHttpHost: %v\n", BrowserHttpHost, HandleHttpHost, ListenHttpHost)
		// включаем листинг веб-сервером для клиентской части
		http.HandleFunc(HandleHttpHost+"/", controllers.Index)
		http.HandleFunc(HandleHttpHost+"/content", controllers.Content)
		http.HandleFunc(HandleHttpHost+"/ajax", controllers.Ajax)
		http.HandleFunc(HandleHttpHost+"/tools", controllers.Tools)
		http.HandleFunc(HandleHttpHost+"/cf/", controllers.IndexCf)
		http.HandleFunc(HandleHttpHost+"/cf/content", controllers.ContentCf)
		http.Handle(HandleHttpHost+"/public/", noDirListing(http.FileServer(http.Dir(*utils.Dir))))
		http.Handle(HandleHttpHost+"/static/", http.FileServer(&assetfs.AssetFS{Asset: static.Asset, AssetDir: static.AssetDir, Prefix: ""}))

		log.Debug("ListenHttpHost", ListenHttpHost)

		IosLog(fmt.Sprintf("ListenHttpHost: %v", ListenHttpHost))

		fmt.Println("ListenHttpHost", ListenHttpHost)

		httpListener(ListenHttpHost, BrowserHttpHost)

		if *utils.Console == 0 && !utils.Mobile() {
			utils.Sleep(1)
			if thrustWindowLoder != nil {
				thrustWindowLoder.Close()
				thrustWindow := thrust.NewWindow(thrust.WindowOptions{
					RootUrl: BrowserHttpHost,
					Size:    commands.SizeHW{Width: 1024, Height: 600},
				})
				thrustWindow.HandleEvent("*", func(cr commands.EventResult) {
					fmt.Println("HandleEvent", cr)
				})
				thrustWindow.HandleRemote(func(er commands.EventResult, this *window.Window) {
					fmt.Println("RemoteMessage Recieved:", er.Message.Payload)
					openBrowser(er.Message.Payload)
					// Keep in mind once we have the message, lets say its json of some new type we made,
					// We can unmarshal it to that type.
					// Same goes for the other way around.
					this.SendRemoteMessage("boop")
				})
				thrustWindow.Show()
				thrustWindow.Focus()
			} else {
				openBrowser(BrowserHttpHost)
			}
		}
	}()

	// ожидает появления свежих записей в чате, затем ждет появления коннектов
	// (заносятся из демеона connections и от тех, кто сам подключился к ноде)
	go utils.ChatOutput(utils.ChatNewTx)

	log.Debug("ALL RIGHT")
	IosLog("ALL RIGHT")
	fmt.Println("ALL RIGHT")
	utils.Sleep(3600 * 24 * 90)
	log.Debug("EXIT")
}
Example #14
0
func (c *Controller) EncryptComment() (string, error) {

	var err error

	c.r.ParseForm()

	txType := c.r.FormValue("type")
	var toId int64
	var toIds []int64
	toIds_ := c.r.FormValue("to_ids")
	if len(toIds_) == 0 {
		toId = utils.StrToInt64(c.r.FormValue("to_id"))
	} else {
		var toIdsMap map[string]string
		err = json.Unmarshal([]byte(toIds_), &toIdsMap)
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		for _, uid := range toIdsMap {
			if utils.StrToInt64(uid) > 0 {
				toIds = append(toIds, utils.StrToInt64(uid))
			}
		}
	}

	comment := c.r.FormValue("comment")
	if len(comment) > 1024 {
		return "", errors.New("incorrect comment")
	}

	var toUserId int64
	if txType == "project" {
		toUserId, err = c.Single("SELECT user_id FROM cf_projects WHERE id  =  ?", toId).Int64()
		if err != nil {
			return "", utils.ErrInfo(err)
		}
	} else {
		toUserId = toId
	}

	if len(toIds) == 0 {
		toIds = []int64{toUserId}
	}

	log.Debug("toId:", toId)
	log.Debug("toIds:", toIds)
	log.Debug("toUserId:", toUserId)
	enc := make(map[string]string)
	for i := 0; i < len(toIds); i++ {
		if toIds[i] == 0 {
			enc[utils.IntToStr(i)] = "0"
			continue
		}
		// если получатель майнер, тогда шифруем нодовским ключем
		minersData, err := c.OneRow("SELECT miner_id, node_public_key FROM miners_data WHERE user_id  =  ?", toIds[i]).String()
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		var publicKey string
		if utils.StrToInt(minersData["miner_id"]) > 0 && txType != "cash_request" && txType != "bug_reporting" && txType != "project" && txType != "money_back" && txType != "restoringAccess" {
			publicKey = minersData["node_public_key"]
		} else {
			publicKey, err = c.Single("SELECT public_key_0 FROM users WHERE user_id  =  ?", toIds[i]).String()
			if err != nil {
				return "", utils.ErrInfo(err)
			}
		}

		pub, err := utils.BinToRsaPubKey([]byte(publicKey))
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		enc_, err := rsa.EncryptPKCS1v15(rand.Reader, pub, []byte(comment))
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		enc[utils.IntToStr(i)] = string(utils.BinToHex(enc_))
	}
	if len(enc) < 5 && len(enc) > 0 {
		for i := len(enc); i < 5; i++ {
			enc[utils.IntToStr(i)] = "0"
		}
	}
	log.Debug("enc:", enc)
	if txType != "arbitration_arbitrators" {
		return string(enc["0"]), nil
	} else {
		result, err := json.Marshal(enc)
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		return string(result), nil
	}
}
Example #15
0
/*
 * Каждые 2 недели собираем инфу о голосах за % и создаем тр-ию, которая
 * попадет в DC сеть только, если мы окажемся генератором блока
 * */
func ReductionGenerator(chBreaker chan bool, chAnswer chan string) {
	defer func() {
		if r := recover(); r != nil {
			log.Error("daemon Recovered", r)
			panic(r)
		}
	}()

	const GoroutineName = "ReductionGenerator"
	d := new(daemon)
	d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName)
	if d.DCDB == nil {
		return
	}
	d.goRoutineName = GoroutineName
	d.chAnswer = chAnswer
	d.chBreaker = chBreaker
	if utils.Mobile() {
		d.sleepTime = 3600
	} else {
		d.sleepTime = 60
	}
	if !d.CheckInstall(chBreaker, chAnswer, GoroutineName) {
		return
	}
	d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName)
	if d.DCDB == nil {
		return
	}

	err = d.notMinerSetSleepTime(1800)
	if err != nil {
		log.Error("%v", err)
		return
	}

BEGIN:
	for {
		log.Info(GoroutineName)
		MonitorDaemonCh <- []string{GoroutineName, utils.Int64ToStr(utils.Time())}

		// проверим, не нужно ли нам выйти из цикла
		if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
			break BEGIN
		}

		err, restart := d.dbLock()
		if restart {
			break BEGIN
		}
		if err != nil {
			if d.dPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

		blockId, err := d.GetBlockId()
		if err != nil {
			if d.unlockPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		if blockId == 0 {
			if d.unlockPrintSleep(errors.New("blockId == 0"), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

		_, _, myMinerId, _, _, _, err := d.TestBlock()
		if err != nil {
			if d.unlockPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		// а майнер ли я ?
		if myMinerId == 0 {
			if d.unlockPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		variables, err := d.GetAllVariables()
		curTime := utils.Time()
		var reductionType string
		var reductionCurrencyId int
		var reductionPct int64

		// ===== ручное урезание денежной массы
		// получаем кол-во обещанных сумм у разных юзеров по каждой валюте. start_time есть только у тех, у кого статус mining/repaid
		promisedAmount, err := d.GetMap(`
				SELECT currency_id, count(user_id) as count
				FROM (
						SELECT currency_id, user_id
						FROM promised_amount
						WHERE start_time < ?  AND
									 del_block_id = 0 AND
									 del_mining_block_id = 0 AND
									 status IN ('mining', 'repaid')
						GROUP BY  user_id, currency_id
						) as t1
				GROUP BY  currency_id`, "currency_id", "count", (curTime - variables.Int64["min_hold_time_promise_amount"]))
		if err != nil {
			if d.unlockPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		log.Info("%v", "promisedAmount", promisedAmount)

		// берем все голоса юзеров
		rows, err := d.Query(d.FormatQuery(`
				SELECT currency_id,
				  		  pct,
						  count(currency_id) as votes
				FROM votes_reduction
				WHERE time > ?
				GROUP BY  currency_id, pct
				`), curTime-variables.Int64["reduction_period"])
		if err != nil {
			if d.unlockPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		for rows.Next() {
			var votes, pct int64
			var currency_id string
			err = rows.Scan(&currency_id, &pct, &votes)
			if err != nil {
				rows.Close()
				if d.unlockPrintSleep(err, d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			if len(promisedAmount[currency_id]) == 0 || promisedAmount[currency_id] == "0" {
				continue
			}
			// если голосов за урезание > 50% от числа всех держателей данной валюты
			if votes >= utils.StrToInt64(promisedAmount[currency_id])/2 {
				// проверим, прошло ли 2 недели с последнего урезания
				reductionTime, err := d.Single("SELECT max(time) FROM reduction WHERE currency_id  =  ? AND type  =  'manual'", currency_id).Int64()
				if err != nil {
					rows.Close()
					if d.dPrintSleep(err, d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				if curTime-reductionTime > variables.Int64["reduction_period"] {
					reductionCurrencyId = utils.StrToInt(currency_id)
					reductionPct = pct
					reductionType = "manual"
					log.Info("%v", "reductionCurrencyId", reductionCurrencyId, "reductionPct", reductionPct, "reductionType", reductionType)
					break
				}
			}
		}
		rows.Close()

		// =======  авто-урезание денежной массы из-за малого объема обещанных сумм

		// получаем кол-во DC на кошельках
		sumWallets_, err := d.GetMap("SELECT currency_id, sum(amount) as sum_amount FROM wallets GROUP BY currency_id", "currency_id", "sum_amount")
		if err != nil {
			if d.dPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		sumWallets := make(map[int]float64)
		for currencyId, amount := range sumWallets_ {
			sumWallets[utils.StrToInt(currencyId)] = utils.StrToFloat64(amount)
		}

		// получаем кол-во TDC на обещанных суммах, плюсуем к тому, что на кошельках
		sumTdc, err := d.GetMap("SELECT currency_id, sum(tdc_amount) as sum_amount FROM promised_amount GROUP BY currency_id", "currency_id", "sum_amount")
		if err != nil {
			if d.dPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

		for currencyId, amount := range sumTdc {
			currencyIdInt := utils.StrToInt(currencyId)
			if sumWallets[currencyIdInt] == 0 {
				sumWallets[currencyIdInt] = utils.StrToFloat64(amount)
			} else {
				sumWallets[currencyIdInt] += utils.StrToFloat64(amount)
			}
		}

		log.Debug("sumWallets", sumWallets)

		// получаем суммы обещанных сумм
		sumPromisedAmount, err := d.GetMap(`
				SELECT currency_id,
					   		sum(amount) as sum_amount
				FROM promised_amount
				WHERE status = 'mining' AND
							 del_block_id = 0 AND
							 del_mining_block_id = 0 AND
							  (cash_request_out_time = 0 OR cash_request_out_time > ?)
				GROUP BY currency_id
				`, "currency_id", "sum_amount", curTime-variables.Int64["cash_request_time"])
		if err != nil {
			if d.dPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

		log.Debug("sumPromisedAmount", sumPromisedAmount)

		if len(sumWallets) > 0 {
			for currencyId, sumAmount := range sumWallets {
				//недопустимо для WOC
				if currencyId == 1 {
					continue
				}
				reductionTime, err := d.Single("SELECT max(time) FROM reduction WHERE currency_id  =  ? AND type  =  'auto'", currencyId).Int64()
				if err != nil {
					if d.dPrintSleep(err, d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				log.Debug("reductionTime", reductionTime)
				// прошло ли 48 часов
				if curTime-reductionTime <= consts.AUTO_REDUCTION_PERIOD {
					log.Debug("curTime-reductionTime <= consts.AUTO_REDUCTION_PERIOD %d <= %d", curTime-reductionTime, consts.AUTO_REDUCTION_PERIOD)
					continue
				}

				// если обещанных сумм менее чем 100% от объема DC на кошельках, то запускаем урезание
				log.Debug("utils.StrToFloat64(sumPromisedAmount[utils.IntToStr(currencyId)]) < sumAmount*consts.AUTO_REDUCTION_PROMISED_AMOUNT_PCT %d < %d", utils.StrToFloat64(sumPromisedAmount[utils.IntToStr(currencyId)]), sumAmount*consts.AUTO_REDUCTION_PROMISED_AMOUNT_PCT)
				if utils.StrToFloat64(sumPromisedAmount[utils.IntToStr(currencyId)]) < sumAmount*consts.AUTO_REDUCTION_PROMISED_AMOUNT_PCT {

					// проверим, есть ли хотя бы 1000 юзеров, у которых на кошелках есть или была данная валюты
					countUsers, err := d.Single("SELECT count(user_id) FROM wallets WHERE currency_id  =  ?", currencyId).Int64()
					if err != nil {
						if d.dPrintSleep(err, d.sleepTime) {
							break BEGIN
						}
						continue BEGIN
					}
					log.Debug("countUsers>=countUsers %d >= %d", countUsers, consts.AUTO_REDUCTION_PROMISED_AMOUNT_MIN)
					if countUsers >= consts.AUTO_REDUCTION_PROMISED_AMOUNT_MIN {
						reductionCurrencyId = currencyId
						reductionPct = consts.AUTO_REDUCTION_PCT
						reductionType = "promised_amount"
						break
					}
				}

			}
		}
		if reductionCurrencyId > 0 && reductionPct > 0 {

			_, myUserId, _, _, _, _, err := d.TestBlock()
			forSign := fmt.Sprintf("%v,%v,%v,%v,%v,%v", utils.TypeInt("NewReduction"), curTime, myUserId, reductionCurrencyId, reductionPct, reductionType)
			log.Debug("forSign = %v", forSign)
			binSign, err := d.GetBinSign(forSign, myUserId)
			if err != nil {
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			data := utils.DecToBin(utils.TypeInt("NewReduction"), 1)
			data = append(data, utils.DecToBin(curTime, 4)...)
			data = append(data, utils.EncodeLengthPlusData(utils.Int64ToByte(myUserId))...)
			data = append(data, utils.EncodeLengthPlusData(utils.Int64ToByte(int64(reductionCurrencyId)))...)
			data = append(data, utils.EncodeLengthPlusData(utils.Int64ToByte(reductionPct))...)
			data = append(data, utils.EncodeLengthPlusData([]byte(reductionType))...)
			data = append(data, utils.EncodeLengthPlusData([]byte(binSign))...)

			err = d.InsertReplaceTxInQueue(data)
			if err != nil {
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}

			// и не закрывая main_lock переводим нашу тр-ию в verified=1, откатив все несовместимые тр-ии
			// таким образом у нас будут в блоке только актуальные голоса.
			// а если придет другой блок и станет verified=0, то эта тр-ия просто удалится.

			p := new(dcparser.Parser)
			p.DCDB = d.DCDB
			err = p.TxParser(utils.HexToBin(utils.Md5(data)), data, true)
			if err != nil {
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
		}
		d.dbUnlock()

		if d.dSleep(d.sleepTime) {
			break BEGIN
		}
	}
	log.Debug("break BEGIN %v", GoroutineName)

}
Example #16
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)
}
Example #17
0
func (p *Parser) NewForexOrderFront() error {

	err := p.generalCheck()
	if err != nil {
		return p.ErrInfo(err)
	}

	verifyData := map[string]string{"sell_currency_id": "int", "sell_rate": "sell_rate", "amount": "amount", "buy_currency_id": "int", "commission": "amount"}
	err = p.CheckInputData(verifyData)
	if err != nil {
		return p.ErrInfo(err)
	}

	if p.TxMaps.Int64["sell_currency_id"] == p.TxMaps.Int64["buy_currency_id"] {
		return p.ErrInfo("sell_currency_id == buy_currency_id")
	}
	if p.TxMaps.Float64["sell_rate"] == 0 {
		return p.ErrInfo("sell_rate=0")
	}
	if p.TxMaps.Money["amount"] == 0 {
		return p.ErrInfo("amount=0")
	}
	if p.TxMaps.Money["amount"]*p.TxMaps.Float64["sell_rate"] < 0.01 {
		return p.ErrInfo("amount * sell_rate < 0.01")
	}

	checkCurrency, err := p.CheckCurrency(p.TxMaps.Int64["sell_currency_id"])
	if err != nil || !checkCurrency {
		return p.ErrInfo("!sell_currency_id")
	}
	checkCurrency, err = p.CheckCurrency(p.TxMaps.Int64["buy_currency_id"])
	if err != nil || !checkCurrency {
		return p.ErrInfo("!buy_currency_id")
	}

	p.TxMaps.Int64["currency_id"] = p.TxMaps.Int64["sell_currency_id"]
	nodeCommission, err := p.getMyNodeCommission(p.TxMaps.Int64["currency_id"], p.TxUserID, p.TxMaps.Money["amount"])

	// проверим, удовлетворяет ли нас комиссия, которую предлагает юзер
	if p.TxMaps.Money["commission"] < nodeCommission {
		return p.ErrInfo("commission")
	}
	// есть ли нужная сумма на кошельке
	p.TxMaps.Int64["from_user_id"] = p.TxMaps.Int64["user_id"]
	for i := 0; i < 5; i++ {
		p.TxMaps.Float64["arbitrator"+utils.IntToStr(i)+"_commission"] = 0
	}
	_, err = p.checkSenderMoney(p.TxMaps.Int64["currency_id"], p.TxMaps.Int64["from_user_id"], p.TxMaps.Money["amount"], p.TxMaps.Money["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)
	}

	forSign := fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s,%s", p.TxMap["type"], p.TxMap["time"], p.TxMap["user_id"], p.TxMap["sell_currency_id"], p.TxMap["sell_rate"], p.TxMap["amount"], p.TxMap["buy_currency_id"], p.TxMap["commission"])
	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.checkSpamMoney(p.TxMaps.Int64["sell_currency_id"], p.TxMaps.Money["amount"])
	if err != nil {
		return p.ErrInfo(err)
	}

	return nil
}
Example #18
0
func Connector(chBreaker chan bool, chAnswer chan string) {
	defer func() {
		if r := recover(); r != nil {
			log.Error("daemon Recovered", r)
			panic(r)
		}
	}()

	if _, err := os.Stat(*utils.Dir + "/nodes.inc"); os.IsNotExist(err) {
		data, err := static.Asset("static/nodes.inc")
		if err != nil {
			log.Error("%v", err)
		}
		err = ioutil.WriteFile(*utils.Dir+"/nodes.inc", []byte(data), 0644)
		if err != nil {
			log.Error("%v", err)
		}
	}

	GoroutineName := "Connector"
	d := new(daemon)
	d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName)
	if d.DCDB == nil {
		return
	}
	d.goRoutineName = GoroutineName
	d.chAnswer = chAnswer
	d.chBreaker = chBreaker
	if utils.Mobile() {
		d.sleepTime = 600
	} else {
		d.sleepTime = 30
	}
	if !d.CheckInstall(chBreaker, chAnswer, GoroutineName) {
		return
	}
	d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName)
	if d.DCDB == nil {
		return
	}

	// соединения для чата иногда отваливаются, поэтому в цикле мониторим состояние
	go func() {
		for {
			if myUserIdForChat == 0 {
				utils.Sleep(1)
				continue
			}
			if len(utils.ChatOutConnections) < 5 || len(utils.ChatInConnections) < 5 {
				go d.chatConnector()
			}
			utils.Sleep(30)
		}
	}()

BEGIN:
	for {
		log.Info(GoroutineName)
		MonitorDaemonCh <- []string{GoroutineName, utils.Int64ToStr(utils.Time())}

		// проверим, не нужно ли нам выйти из цикла
		if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
			break BEGIN
		}

		nodeConfig, err := d.GetNodeConfig()
		if len(nodeConfig["local_gate_ip"]) > 0 {
			utils.Sleep(2)
			continue
		}

		var delMiners []string
		var hosts []map[string]string
		var nodeCount int64
		idArray := make(map[int]int64)
		nodesInc := make(map[string]string)

		// ровно стольким нодам мы будем слать хэши блоков и тр-ий
		var maxHosts = consts.OUT_CONNECTIONS
		if utils.StrToInt64(nodeConfig["out_connections"]) > 0 {
			maxHosts = utils.StrToInt(nodeConfig["out_connections"])
		}
		log.Info("%v", maxHosts)

		collective, err := d.GetCommunityUsers()
		if err != nil {
			log.Error("%v", err)
			return
		}
		if len(collective) == 0 {
			myUserId, err := d.GetMyUserId("")
			if err != nil {
				log.Error("%v", err)
				return
			}
			collective = append(collective, myUserId)
			myUserIdForChat = myUserId
		} else {
			myUserIdForChat, err = d.Single(`SELECT pool_admin_user_id FROM config`).Int64()
			if err != nil {
				log.Error("%v", err)
				return
			}
		}

		// в сингл-моде будет только $my_miners_ids[0]
		myMinersIds, err := d.GetMyMinersIds(collective)
		if err != nil {
			if d.dPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue
		}
		log.Info("%v", myMinersIds)
		nodesBan, err := d.GetMap(`
				SELECT tcp_host, ban_start
				FROM nodes_ban
				LEFT JOIN miners_data ON miners_data.user_id = nodes_ban.user_id
				`, "tcp_host", "ban_start")
		log.Info("%v", nodesBan)
		nodesConnections, err := d.GetAll(`
				SELECT nodes_connection.host,
							 nodes_connection.user_id,
							 ban_start,
							 miner_id
				FROM nodes_connection
				LEFT JOIN nodes_ban ON nodes_ban.user_id = nodes_connection.user_id
				LEFT JOIN miners_data ON miners_data.user_id = nodes_connection.user_id
				`, -1)
		//fmt.Println("nodesConnections", nodesConnections)
		log.Debug("nodesConnections: %v", nodesConnections)
		for _, data := range nodesConnections {

			// проверим, не нужно нам выйти, т.к. обновилась версия софта
			if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
				break BEGIN
			}

			/*// проверим соотвествие хоста и user_id
			ok, err := d.Single("SELECT user_id FROM miners_data WHERE user_id  = ? AND tcp_host  =  ?", data["user_id"], data["host"]).Int64()
			if err != nil {
				utils.Sleep(1)
				continue BEGIN
			}
			if ok == 0 {
				err = d.ExecSql("DELETE FROM nodes_connection WHERE host = ? OR user_id = ?", data["host"], data["user_id"])
				if err != nil {
					utils.Sleep(1)
					continue BEGIN
				}
			}*/

			// если нода забанена недавно
			if utils.StrToInt64(data["ban_start"]) > utils.Time()-consts.NODE_BAN_TIME {
				delMiners = append(delMiners, data["miner_id"])
				err = d.ExecSql("DELETE FROM nodes_connection WHERE host = ? OR user_id = ?", data["host"], data["user_id"])
				if err != nil {
					if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				continue
			}

			hosts = append(hosts, map[string]string{"host": data["host"], "user_id": data["user_id"]})
			nodesInc[data["host"]] = data["user_id"]
			nodeCount++
		}

		log.Debug("hosts: %v", hosts)
		/*
			ch := make(chan *answerType)
			for _, host := range hosts {
				userId := utils.StrToInt64(host["user_id"])
				go func(userId int64, host string) {
					ch_ := make(chan *answerType, 1)
					go func() {
						log.Debug("host: %v / userId: %v", host, userId)
						ch_ <- check(host, userId)
					}()
					select {
					case reachable := <-ch_:
						ch <- reachable
					case <-time.After(consts.WAIT_CONFIRMED_NODES * time.Second):
						ch <- &answerType{userId: userId, answer: 0}
					}
				}(userId, host["host"])
			}

			log.Debug("%v", "hosts", hosts)

			var newHosts []map[string]string
			var countOk int
			// если нода не отвечает, то удалем её из таблы nodes_connection
			for i := 0; i < len(hosts); i++ {
				result := <-ch
				if result.answer == 0 {
					log.Info("delete %v", result.userId)
					err = d.ExecSql("DELETE FROM nodes_connection WHERE user_id = ?", result.userId)
					if err != nil {
						if d.dPrintSleep(err, d.sleepTime) {	break BEGIN }
					}
					for _, data := range hosts {
						if utils.StrToInt64(data["user_id"]) != result.userId {
							newHosts = append(newHosts, data)
						}
					}
				} else {
					countOk++
				}
				log.Info("answer: %v", result)
			}
		*/
		var countOk int
		hosts = checkHosts(hosts, &countOk)
		log.Debug("countOk: %d / hosts: %v", countOk, hosts)
		// проверим, не нужно нам выйти, т.к. обновилась версия софта
		if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
			break BEGIN
		}
		// добьем недостающие хосты до $max_hosts
		var newHostsForCheck []map[string]string
		if len(hosts) < maxHosts {
			need := maxHosts - len(hosts)
			max, err := d.Single("SELECT max(miner_id) FROM miners").Int()
			if err != nil {
				if d.dPrintSleep(err, d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			i0 := 0
			for {
				rand := 1
				if max > 1 {
					rand = utils.RandInt(1, max+1)
				}
				idArray[rand] = 1
				i0++
				if i0 > 30 || len(idArray) >= need || len(idArray) >= max {
					break
				}
			}
			log.Info("%v", "idArray", idArray)
			// удалим себя
			for _, id := range myMinersIds {
				delete(idArray, int(id))
			}
			// Удалим забаннные хосты
			for _, id := range delMiners {
				delete(idArray, utils.StrToInt(id))
			}
			log.Info("%v", "idArray", idArray)
			ids := ""
			if len(idArray) > 0 {
				for id, _ := range idArray {
					ids += utils.IntToStr(id) + ","
				}
				ids = ids[:len(ids)-1]
				minersHosts, err := d.GetMap(`
						SELECT tcp_host, user_id
						FROM miners_data
						WHERE miner_id IN (`+ids+`)`, "tcp_host", "user_id")
				if err != nil {
					if d.dPrintSleep(err, d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				for host, userId := range minersHosts {
					if len(nodesBan[host]) > 0 {
						if utils.StrToInt64(nodesBan[host]) > utils.Time()-consts.NODE_BAN_TIME {
							continue
						}
					}
					//hosts = append(hosts, map[string]string{"host": host, "user_id": userId})
					/*err = d.ExecSql("DELETE FROM nodes_connection WHERE host = ?", host)
					if err != nil {
						if d.dPrintSleep(err, d.sleepTime) {	break BEGIN }
						continue BEGIN
					}
					log.Debug(host)*/
					newHostsForCheck = append(newHostsForCheck, map[string]string{"user_id": userId, "host": host})
					/*err = d.ExecSql("INSERT INTO nodes_connection ( host, user_id ) VALUES ( ?, ? )", host, userId)
					if err != nil {
						if d.dPrintSleep(err, d.sleepTime) {	break BEGIN }
						continue BEGIN
					}*/
				}
			}
		}

		hosts = checkHosts(newHostsForCheck, &countOk)
		log.Debug("countOk: %d / hosts: %v", countOk, hosts)
		// проверим, не нужно нам выйти, т.к. обновилась версия софта
		if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
			break BEGIN
		}
		log.Debug("%v", "hosts", hosts)
		// если хосты не набрались из miner_data, то берем из файла
		if len(hosts) < 10 {
			hostsData_, err := ioutil.ReadFile(*utils.Dir + "/nodes.inc")
			if err != nil {
				if d.dPrintSleep(err, d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			hostsData := strings.Split(string(hostsData_), "\n")
			log.Debug("%v", "hostsData_", hostsData_)
			log.Debug("%v", "hostsData", hostsData)
			max := 0
			log.Debug("maxHosts: %v", maxHosts)
			if len(hosts) > maxHosts-1 {
				max = maxHosts
			} else {
				max = len(hostsData)
			}
			log.Debug("max: %v", max)
			for i := 0; i < max; i++ {
				r := utils.RandInt(0, max)
				if len(hostsData) <= r {
					continue
				}
				hostUserId := strings.Split(hostsData[r], ";")
				if len(hostUserId) == 1 {
					continue
				}
				host, userId := hostUserId[0], hostUserId[1]
				if utils.InSliceInt64(utils.StrToInt64(userId), collective) {
					continue
				}
				if len(nodesBan[host]) > 0 {
					if utils.StrToInt64(nodesBan[host]) > utils.Time()-consts.NODE_BAN_TIME {
						continue
					}
				}
				/*
					err = d.ExecSql("DELETE FROM nodes_connection WHERE host = ?", host)
					if err != nil {
						if d.dPrintSleep(err, d.sleepTime) {	break BEGIN }
						continue BEGIN
					}
					log.Debug(host)
					/*err = d.ExecSql("INSERT INTO nodes_connection ( host, user_id ) VALUES ( ?, ? )", host, userId)
					if err != nil {
						if d.dPrintSleep(err, d.sleepTime) {	break BEGIN }
						continue BEGIN
					}*/
				newHostsForCheck = append(newHostsForCheck, map[string]string{"user_id": userId, "host": host})

				nodesInc[host] = userId

			}
		}

		hosts = checkHosts(newHostsForCheck, &countOk)
		log.Debug("countOk: %d / hosts: %v", countOk, hosts)
		// проверим, не нужно нам выйти, т.к. обновилась версия софта
		if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
			break BEGIN
		}
		for _, host := range hosts {
			err = d.ExecSql("DELETE FROM nodes_connection WHERE host = ?", host["host"])
			if err != nil {
				if d.dPrintSleep(err, d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			err = d.ExecSql("INSERT INTO nodes_connection ( host, user_id ) VALUES ( ?, ? )", host["host"], host["user_id"])
			if err != nil {
				if d.dPrintSleep(err, d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
		}
		if nodeCount > 5 {
			nodesFile := ""
			for k, v := range nodesInc {
				nodesFile += k + ";" + v + "\n"
			}
			nodesFile = nodesFile[:len(nodesFile)-1]
			err := ioutil.WriteFile(*utils.Dir+"/nodes.inc", []byte(nodesFile), 0644)
			if err != nil {
				if d.dPrintSleep(err, d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
		}

		var sleepTime int
		if countOk < 2 {
			sleepTime = 5
		} else {
			sleepTime = d.sleepTime
		}

		if d.dSleep(sleepTime) {
			break BEGIN
		}
	}
	log.Debug("break BEGIN %v", GoroutineName)
}
Example #19
0
func (p *Parser) VotesComplex() error {

	currencyVotes := make(map[string][]float64)

	if p.BlockData.BlockId > 77951 {
		vComplex, err := makeVcomplex(p.TxMap["json_data"])
		if err != nil {
			return p.ErrInfo(err)
		}
		currencyVotes = vComplex.Currency
		// голоса за реф. %
		p.selectiveLoggingAndUpd([]string{"first", "second", "third"}, []interface{}{vComplex.Referral["first"], vComplex.Referral["second"], vComplex.Referral["third"]}, "votes_referral", []string{"user_id"}, []string{string(p.TxMap["user_id"])})

		// раньше не было выборов админа
		if p.BlockData.BlockId >= 153750 && vComplex.Admin > 0 {
			p.selectiveLoggingAndUpd([]string{"admin_user_id", "time"}, []interface{}{vComplex.Admin, p.TxTime}, "votes_admin", []string{"user_id"}, []string{string(p.TxMap["user_id"])})
		}

	} else { // раньше не было рефских и выбора админа
		vComplex := make(map[string][]float64)
		err := json.Unmarshal(p.TxMap["json_data"], &vComplex)
		if err != nil {
			return p.ErrInfo(err)
		}
		currencyVotes = vComplex
	}

	var currencyIds []int
	for k := range currencyVotes {
		currencyIds = append(currencyIds, utils.StrToInt(k))
	}
	sort.Ints(currencyIds)
	//sort.Sort(sort.Reverse(sort.IntSlice(keys)))

	for _, currencyId := range currencyIds {

		data := currencyVotes[utils.IntToStr(currencyId)]
		currencyIdStr := utils.IntToStr(currencyId)
		UserIdStr := string(p.TxMap["user_id"])
		// miner_pct
		err := p.selectiveLoggingAndUpd([]string{"pct", "time"}, []interface{}{utils.Float64ToStr(data[0]), p.TxTime}, "votes_miner_pct", []string{"user_id", "currency_id"}, []string{UserIdStr, currencyIdStr})
		if err != nil {
			return p.ErrInfo(err)
		}

		// user_pct
		err = p.selectiveLoggingAndUpd([]string{"pct"}, []interface{}{utils.Float64ToStr(data[1])}, "votes_user_pct", []string{"user_id", "currency_id"}, []string{UserIdStr, currencyIdStr})
		if err != nil {
			return p.ErrInfo(err)
		}

		// max_promised_amount
		err = p.selectiveLoggingAndUpd([]string{"amount"}, []interface{}{int64(data[2])}, "votes_max_promised_amount", []string{"user_id", "currency_id"}, []string{UserIdStr, currencyIdStr})
		if err != nil {
			return p.ErrInfo(err)
		}

		// max_other_currencies
		err = p.selectiveLoggingAndUpd([]string{"count"}, []interface{}{int64(data[3])}, "votes_max_other_currencies", []string{"user_id", "currency_id"}, []string{UserIdStr, currencyIdStr})
		if err != nil {
			return p.ErrInfo(err)
		}

		// reduction
		err = p.selectiveLoggingAndUpd([]string{"pct", "time"}, []interface{}{int64(data[4]), p.TxTime}, "votes_reduction", []string{"user_id", "currency_id"}, []string{UserIdStr, currencyIdStr})
		if err != nil {
			return p.ErrInfo(err)
		}

		// проверим, не наш ли это user_id
		myUserId, myBlockId, myPrefix, _, err := p.GetMyUserId(p.TxUserID)
		if err != nil {
			return p.ErrInfo(err)
		}

		if p.TxUserID == myUserId && myBlockId <= p.BlockData.BlockId {
			// отметимся, что голосовали, чтобы не пришло уведомление о необходимости голосовать раз в 2 недели
			// может быть дубль, поэтому ошибки не проверяем
			p.ExecSql("INSERT INTO "+myPrefix+"my_complex_votes ( last_voting ) VALUES ( ? )", p.BlockData.Time)
		}
	}

	return nil
}
Example #20
0
func (c *Controller) BlockExplorer() (string, error) {

	var err error

	blockId := int64(utils.StrToFloat64(c.Parameters["blockId"]))
	start := int64(utils.StrToFloat64(c.Parameters["start"]))

	var data, sql string
	if start > 0 || (start == 0 && blockId == 0) {
		if start == 0 && blockId == 0 {
			data += "<h3>Latest Blocks</h3>"
			sql = `	SELECT data,  hash
						FROM block_chain
						ORDER BY id DESC
						LIMIT 15`
		} else {
			sql = `	SELECT data,  hash
						FROM block_chain
						ORDER BY id ASC
						LIMIT ` + utils.Int64ToStr(start-1) + `, 100`
		}
		data += `<table class="table"><tr><th>Block</th><th>Hash</th><th>Time</th><th><nobr>User id</nobr></th><th><nobr>Miner id</nobr></th><th>Level</th><th>Transactions</th></tr>`
		blocksChain, err := c.GetAll(sql, -1)
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		for _, blockData := range blocksChain {
			hash := utils.BinToHex([]byte(blockData["hash"]))
			binaryData := []byte(blockData["data"])
			parser := new(dcparser.Parser)
			parser.DCDB = c.DCDB
			parser.BinaryData = binaryData
			err = parser.ParseDataLite()
			parser.BlockData.Sign = utils.BinToHex(parser.BlockData.Sign)
			minerId, err := c.GetMinerId(parser.BlockData.UserId)
			if err != nil {
				return "", utils.ErrInfo(err)
			}
			data += fmt.Sprintf(`<tr><td><a href="#" onclick="dc_navigate('blockExplorer', {'blockId':%d})">%d</a></td><td>%s</td><td><nobr><span class='unixtime'>%d</span></nobr></td><td>%d</td><td>%d</td><td>%d</td><td>`, parser.BlockData.BlockId, parser.BlockData.BlockId, hash, parser.BlockData.Time, parser.BlockData.UserId, minerId, parser.BlockData.Level)
			data += utils.IntToStr(len(parser.TxMapArr))
			data += "</td></tr>"
		}
		data += "</table>"
	} else if blockId > 0 {
		data += `<table class="table">`
		blockChain, err := c.OneRow("SELECT data, hash, cur_0l_miner_id, max_miner_id FROM block_chain WHERE id = ?", blockId).String()
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		binToHexArray := []string{"sign", "public_key", "encrypted_message", "comment", "bin_public_keys"}
		hash := utils.BinToHex([]byte(blockChain["hash"]))
		binaryData := blockChain["data"]
		parser := new(dcparser.Parser)
		parser.DCDB = c.DCDB
		parser.BinaryData = []byte(binaryData)
		err = parser.ParseDataLite()
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		parser.BlockData.Sign = utils.BinToHex(parser.BlockData.Sign)
		previous := parser.BlockData.BlockId - 1
		next := parser.BlockData.BlockId + 1
		levelsRange := utils.GetBlockGeneratorMinerIdRange(utils.StrToInt64(blockChain["cur_0l_miner_id"]), utils.StrToInt64(blockChain["max_miner_id"]))
		minerId, err := c.GetMinerId(parser.BlockData.UserId)
		if err != nil {
			return "", utils.ErrInfo(err)
		}

		_, _, _, CurrentUserId, _, _, _ := c.TestBlock()
		maxMinerId, err := c.Single("SELECT max(miner_id) FROM miners").Int64()
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		currentMinerId, err := c.Single("SELECT miner_id FROM miners_data WHERE user_id = ?", CurrentUserId).Int64()
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		NextBlockLevelsRange := utils.GetBlockGeneratorMinerIdRange(currentMinerId, maxMinerId)

		data += fmt.Sprintf(`<tr><td><strong>Raw&nbsp;data</strong></td><td><a href='ajax?controllerName=getBlock&id=%d&download=1' target='_blank'>Download</a></td></tr>`, parser.BlockData.BlockId)
		data += fmt.Sprintf(`<tr><td><strong>Block_id</strong></td><td>%d (<a href="#" onclick="dc_navigate('blockExplorer', {'blockId':%d})">Previous</a> / <a href="#" onclick="dc_navigate('blockExplorer', {'blockId':%d})">Next</a> )</td></tr>`, parser.BlockData.BlockId, previous, next)
		data += fmt.Sprintf(`<tr><td><strong>Hash</strong></td><td>%s</td></tr>`, hash)
		data += fmt.Sprintf(`<tr><td><strong>Time</strong></td><td><span class='unixtime'>%d</span> / %d</td></tr>`, parser.BlockData.Time, parser.BlockData.Time)
		data += fmt.Sprintf(`<tr><td><strong>User_id</strong></td><td>%d</td></tr>`, parser.BlockData.UserId)
		data += fmt.Sprintf(`<tr><td><strong>Miner_Id</strong></td><td>%d</td></tr>`, minerId)
		data += fmt.Sprintf(`<tr><td><strong>Level</strong></td><td>%d (%v) next: %v</td></tr>`, parser.BlockData.Level, levelsRange, NextBlockLevelsRange)
		data += fmt.Sprintf(`<tr><td><strong>Sign</strong></td><td>%s</td></tr>`, parser.BlockData.Sign)
		if len(parser.TxMapArr) > 0 {
			data += `<tr><td><strong>Transactions</strong></td><td><div><pre style='width: 700px'>`
			for i := 0; i < len(parser.TxMapArr); i++ {
				for k, data_ := range parser.TxMapArr[i] {
					if utils.InSliceString(k, binToHexArray) {
						parser.TxMapArr[i][k] = utils.BinToHex(data_)
					}
					if k == "file" {
						parser.TxMapArr[i][k] = []byte("file size: " + utils.IntToStr(len(data_)))
					} else if k == "code" {
						parser.TxMapArr[i][k] = utils.DSha256(data_)
					} else if k == "secret" {
						parser.TxMapArr[i][k] = utils.BinToHex(data_)
					}
					data += fmt.Sprintf("%v : %s\n", k, parser.TxMapArr[i][k])
				}
				data += "\n\n"
			}

			data += "</pre></div></td></tr>"
		}
		data += "</table>"
	}

	// пока панель тут
	myNotice := make(map[string]string)
	if c.SessUserId > 0 {
		myNotice, err = c.GetMyNoticeData(c.SessUserId, c.SessUserId, c.MyPrefix, c.Lang)
		if err != nil {
			return "", utils.ErrInfo(err)
		}
	}

	TemplateStr, err := makeTemplate("block_explorer", "blockExplorer", &BlockExplorerPage{
		Lang:           c.Lang,
		CurrencyList:   c.CurrencyListCf,
		MyNotice:       myNotice,
		Data:           data,
		Start:          start,
		BlockId:        blockId,
		PoolAdmin:      c.PoolAdmin,
		SessRestricted: c.SessRestricted,
		UserId:         c.SessUserId})
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	return TemplateStr, nil
}
Example #21
0
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
}
Example #22
0
func (p *Parser) SendDc() error {
	// нужно отметить в log_time_money_orders, что тр-ия прошла в блок
	err := p.ExecSql("UPDATE log_time_money_orders SET del_block_id = ? WHERE hex(tx_hash) = ?", p.BlockData.BlockId, p.TxHash)
	if err != nil {
		return p.ErrInfo(err)
	}

	// 1 возможно нужно обновить таблицу points_status
	err = p.pointsUpdateMain(p.BlockData.UserId)
	if err != nil {
		return p.ErrInfo(err)
	}
	// 2
	err = p.pointsUpdateMain(p.TxMaps.Int64["from_user_id"])
	if err != nil {
		return p.ErrInfo(err)
	}
	// 3
	err = p.pointsUpdateMain(p.TxMaps.Int64["to_user_id"])
	if err != nil {
		return p.ErrInfo(err)
	}
	commission := p.TxMaps.Float64["commission"]

	var arbitration_days_refund int64
	var seller_hold_back_pct float64
	var arbitrators bool
	if p.BlockData.BlockId > consts.ARBITRATION_BLOCK_START {
		// на какой период манибека согласен продавец
		err := p.QueryRow(p.FormatQuery("SELECT arbitration_days_refund, seller_hold_back_pct FROM users WHERE user_id  =  ?"), p.TxMaps.Int64["to_user_id"]).Scan(&arbitration_days_refund, &seller_hold_back_pct)
		if err != nil && err != sql.ErrNoRows {
			return p.ErrInfo(err)
		}
		if arbitration_days_refund > 0 {
			for i := 0; i < 5; i++ {
				iStr := utils.IntToStr(i)
				if p.TxMaps.Int64["arbitrator"+iStr] > 0 && p.TxMaps.Float64["arbitrator"+iStr+"_commission"] >= 0.01 {
					// нужно учесть комиссию арбитра
					commission += p.TxMaps.Float64["arbitrator"+iStr+"_commission"]
					arbitrators = true
				}
			}
		}
	}
	// 4 обновим сумму на кошельке отправителя, залогировав предыдущее значение
	err = p.updateSenderWallet(p.TxMaps.Int64["from_user_id"], p.TxMaps.Int64["currency_id"], p.TxMaps.Float64["amount"], commission, "from_user", p.TxMaps.Int64["to_user_id"], p.TxMaps.Int64["to_user_id"], string(utils.BinToHex(p.TxMap["comment"])), "encrypted")
	if err != nil {
		return p.ErrInfo(err)
	}

	log.Debug("SendDC updateRecipientWallet")
	// 5 обновим сумму на кошельке получателю
	err = p.updateRecipientWallet(p.TxMaps.Int64["to_user_id"], p.TxMaps.Int64["currency_id"], p.TxMaps.Float64["amount"], "from_user", p.TxMaps.Int64["from_user_id"], p.TxMaps.String["comment"], "encrypted", true)
	if err != nil {
		return p.ErrInfo(err)
	}

	// 6 теперь начисляем комиссию майнеру, который этот блок сгенерил
	if p.TxMaps.Float64["commission"] >= 0.01 {
		err = p.updateRecipientWallet(p.BlockData.UserId, p.TxMaps.Int64["currency_id"], p.TxMaps.Float64["commission"], "node_commission", p.BlockData.BlockId, "", "encrypted", true)
		if err != nil {
			return p.ErrInfo(err)
		}
	}

	log.Debug("p.BlockData.BlockId", p.BlockData.BlockId)
	log.Debug("consts.ARBITRATION_BLOCK_START", consts.ARBITRATION_BLOCK_START)
	if p.BlockData.BlockId > consts.ARBITRATION_BLOCK_START {

		// если продавец не согласен на арбитраж, то $arbitration_days_refund будет равно 0

		log.Debug("arbitration_days_refund", arbitration_days_refund)
		log.Debug("arbitrators", arbitrators)
		if arbitration_days_refund > 0 && arbitrators {
			holdBackAmount := math.Floor(utils.Round(p.TxMaps.Float64["amount"]*(seller_hold_back_pct/100), 3)*100) / 100
			if holdBackAmount < 0.01 {
				holdBackAmount = 0.01
			}
			orderId, err := p.ExecSqlGetLastInsertId("INSERT INTO orders ( time, buyer, seller, arbitrator0, arbitrator1, arbitrator2, arbitrator3, arbitrator4, amount, hold_back_amount, currency_id, block_id, end_time ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )", "id", p.BlockData.Time, p.TxMaps.Int64["from_user_id"], p.TxMaps.Int64["to_user_id"], p.TxMaps.Int64["arbitrator0"], p.TxMaps.Int64["arbitrator1"], p.TxMaps.Int64["arbitrator2"], p.TxMaps.Int64["arbitrator3"], p.TxMaps.Int64["arbitrator4"], p.TxMaps.Float64["amount"], holdBackAmount, p.TxMaps.Int64["currency_id"], p.BlockData.BlockId, (p.BlockData.Time + arbitration_days_refund*86400))
			if err != nil {
				return p.ErrInfo(err)
			}
			// начисляем комиссию арбитрам
			for i := 0; i < 5; i++ {
				iStr := utils.IntToStr(i)
				log.Debug("arbitrator_commission "+iStr, p.TxMaps.Float64["arbitrator"+iStr+"_commission"])
				if p.TxMaps.Int64["arbitrator"+iStr] > 0 && p.TxMaps.Float64["arbitrator"+iStr+"_commission"] >= 0.01 {
					log.Debug("updateRecipientWallet")
					err = p.updateRecipientWallet(p.TxMaps.Int64["arbitrator"+iStr], p.TxMaps.Int64["currency_id"], p.TxMaps.Float64["arbitrator"+iStr+"_commission"], "arbitrator_commission", orderId, "", "encrypted", true)
					if err != nil {
						return p.ErrInfo(err)
					}
				}
			}
		}
	}
	// отмечаем данную транзакцию в буфере как отработанную и ставим в очередь на удаление
	err = p.ExecSql("UPDATE wallets_buffer SET del_block_id = ? WHERE hex(hash) = ?", p.BlockData.BlockId, p.TxHash)
	if err != nil {
		return p.ErrInfo(err)
	}

	return nil
}
Example #23
0
func (c *Controller) Upgrade3() (string, error) {

	log.Debug("Upgrade3")

	userProfile := *utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_profile.jpg"
	userFace := *utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_face.jpg"

	if _, err := os.Stat(userProfile); os.IsNotExist(err) {
		userProfile = ""
	} else {
		userProfile = "public/" + utils.Int64ToStr(c.SessUserId) + "_user_profile.jpg?r=" + utils.IntToStr(utils.RandInt(0, 99999))
	}
	if _, err := os.Stat(userFace); os.IsNotExist(err) {
		userFace = ""
	} else {
		userFace = "public/" + utils.Int64ToStr(c.SessUserId) + "_user_face.jpg?r=" + utils.IntToStr(utils.RandInt(0, 99999))
	}

	log.Debug("userProfile: %s", userProfile)
	log.Debug("userFace: %s", userFace)

	// текущий набор точек для шаблонов
	examplePoints, err := c.GetPoints(c.Lang)
	if err != nil {
		return "", utils.ErrInfo(err)
	}

	// точки, которые юзер уже отмечал
	data, err := c.OneRow("SELECT face_coords, profile_coords FROM " + c.MyPrefix + "my_table").String()
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	faceCoords := ""
	profileCoords := ""
	if len(data["face_coords"]) > 0 {
		faceCoords = data["face_coords"]
		profileCoords = data["profile_coords"]
	}

	saveAndGotoStep := strings.Replace(c.Lang["save_and_goto_step"], "[num]", "5", -1)
	upgradeMenu := utils.MakeUpgradeMenu(3)

	TemplateStr, err := makeTemplate("upgrade_3", "upgrade3", &upgrade3Page{
		Alert:           c.Alert,
		Lang:            c.Lang,
		CountSignArr:    c.CountSignArr,
		ShowSignData:    c.ShowSignData,
		SaveAndGotoStep: saveAndGotoStep,
		UpgradeMenu:     upgradeMenu,
		UserId:          c.SessUserId,
		FaceCoords:      faceCoords,
		ProfileCoords:   profileCoords,
		UserProfile:     userProfile,
		UserFace:        userFace,
		ExamplePoints:   examplePoints,
		IOS:             utils.IOS(),
		Mobile:          utils.Mobile()})
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	return TemplateStr, nil
}
Example #24
0
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
}
Example #25
0
func (c *Controller) DcoinKey() (string, error) {

	var err error
	c.r.ParseForm()
	// на IOS/Android запрос ключа идет без сессии из objective C (UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://127.0.0.1:8089/ajax?controllerName=dcoinKey&ios=1"]]];)
	local := false
	// чтобы по локалке никто не украл приватный ключ
	if ok, _ := regexp.MatchString(`^(\:\:)|(127\.0\.0\.1)(:[0-9]+)?$`, c.r.RemoteAddr); ok {
		local = true
	}
	if utils.Mobile() && c.SessUserId == 0 && !local {
		return "", utils.ErrInfo(errors.New("Not local request from " + c.r.RemoteAddr))
	}
	privKey := ""
	if len(c.r.FormValue("first")) > 0 {
		privKey, err = c.Single(`SELECT private_key FROM ` + c.MyPrefix + `my_keys WHERE status='my_pending'`).String()
		if err != nil {
			return "", utils.ErrInfo(err)
		}
	} else {
		privKey, _ = utils.GenKeys()
	}

	paramNoPass := utils.ParamType{X: 176, Y: 100, Width: 100, Bg_path: "static/img/k_bg.png"}
	paramPass := utils.ParamType{X: 167, Y: 93, Width: 118, Bg_path: "static/img/k_bg_pass.png"}

	var param utils.ParamType
	var privateKey string
	if len(c.r.FormValue("password")) > 0 {
		privateKey_, err := utils.Encrypt(utils.Md5(c.r.FormValue("password")), []byte(privKey))
		privateKey = base64.StdEncoding.EncodeToString(privateKey_)
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		param = paramPass
	} else {
		privateKey = strings.Replace(privKey, "-----BEGIN RSA PRIVATE KEY-----", "", -1)
		privateKey = strings.Replace(privateKey, "-----END RSA PRIVATE KEY-----", "", -1)
		param = paramNoPass
	}

	ios := false
	if ok, _ := regexp.MatchString("(iPod|iPhone|iPad)", c.r.UserAgent()); ok {
		ios = true
	}
	if len(c.r.FormValue("ios")) > 0 {
		ios = true
	}

	if ios || utils.Android() {
		buffer, err := utils.KeyToImg(privateKey, "", c.SessUserId, c.TimeFormat, param)
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		c.w.Header().Set("Content-Type", "image/png")
		c.w.Header().Set("Content-Length", utils.IntToStr(len(buffer.Bytes())))
		c.w.Header().Set("Content-Disposition", `attachment; filename="Dcoin-private-key-`+utils.Int64ToStr(c.SessUserId)+`.png"`)
		if _, err := c.w.Write(buffer.Bytes()); err != nil {
			return "", utils.ErrInfo(errors.New("unable to write image"))
		}
	} else {
		c.w.Header().Set("Content-Type", "text/plain")
		c.w.Header().Set("Content-Length", utils.IntToStr(len(privateKey)))
		c.w.Header().Set("Content-Disposition", `attachment; filename="Dcoin-private-key-`+utils.Int64ToStr(c.SessUserId)+`.txt"`)
		if _, err := c.w.Write([]byte(privateKey)); err != nil {
			return "", utils.ErrInfo(errors.New("unable to write text"))
		}
	}

	return "", nil
}