Пример #1
0
func (p *Parser) RepaymentCreditRollback() error {
	creditData, err := p.OneRow("SELECT to_user_id, currency_id FROM credits WHERE id  =  ?", p.TxMaps.Int64["credit_id"]).Int64()
	if err != nil {
		return p.ErrInfo(err)
	}

	err = p.generalRollback("wallets", p.TxUserID, "AND currency_id = "+utils.Int64ToStr(creditData["currency_id"]), false)
	if err != nil {
		return p.ErrInfo(err)
	}

	err = p.generalRollback("wallets", creditData["to_user_id"], "AND currency_id = "+utils.Int64ToStr(creditData["currency_id"]), false)
	if err != nil {
		return p.ErrInfo(err)
	}

	err = p.selectiveRollback([]string{"amount", "tx_hash", "tx_block_id"}, "credits", "id="+utils.Int64ToStr(p.TxMaps.Int64["credit_id"]), false)
	if err != nil {
		return p.ErrInfo(err)
	}

	// возможно нужно обновить таблицу points_status
	err = p.pointsUpdateMain(creditData["to_user_id"])
	if err != nil {
		return p.ErrInfo(err)
	}

	// возможно нужно обновить таблицу points_status
	err = p.pointsUpdateMain(p.TxUserID)
	if err != nil {
		return p.ErrInfo(err)
	}

	return nil
}
Пример #2
0
func (p *Parser) NewPromisedAmount() error {
	addSqlNames := ""
	addSqlValues := ""
	if p.BlockData.BlockId > 27134 {
		paymentSystemsIds := strings.Split(string(p.TxMaps.String["payment_systems_ids"]), ",")
		for i, v := range paymentSystemsIds {
			addSqlNames += fmt.Sprintf("ps%d,", (i + 1))
			addSqlValues += fmt.Sprintf("%s,", v)
		}
	}

	//добавляем promised_amount в БД
	err := p.ExecSql(`
				INSERT INTO promised_amount (
						user_id,
						amount,
						currency_id,
						` + addSqlNames + `
						video_type,
						video_url_id,
						votes_start_time
					)
					VALUES (
						` + utils.Int64ToStr(p.TxMaps.Int64["user_id"]) + `,
						` + utils.Float64ToStr(p.TxMaps.Money["amount"]) + `,
						` + utils.Int64ToStr(p.TxMaps.Int64["currency_id"]) + `,
						` + addSqlValues + `
						'` + p.TxMaps.String["video_type"] + `',
						'` + p.TxMaps.String["video_url_id"] + `',
						` + utils.Int64ToStr(p.BlockData.Time) + `
					)`)
	if err != nil {
		return p.ErrInfo(err)
	}

	// проверим, не наш ли это user_id
	myUserId, myBlockId, myPrefix, _, err := p.GetMyUserId(p.TxMaps.Int64["user_id"])
	if err != nil {
		return err
	}
	if p.TxUserID == myUserId && myBlockId <= p.BlockData.BlockId {
		// Удалим, т.к. попало в блок
		err = p.ExecSql("DELETE FROM "+myPrefix+"my_promised_amount WHERE amount = ? AND currency_id = ?", p.TxMaps.Money["amount"], p.TxMaps.Int64["currency_id"])
		if err != nil {
			return p.ErrInfo(err)
		}
	}

	return nil
}
Пример #3
0
func (c *Controller) Chat() (string, error) {

	myChatName := utils.Int64ToStr(c.SessUserId)
	// возможно у отпарвителя есть ник
	name, err := c.Single(`SELECT name FROM users WHERE user_id = ?`, c.SessUserId).String()
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	if len(name) > 0 {
		myChatName = name
	}

	TemplateStr, err := makeTemplate("chat", "chat", &chatPage{
		Community:    c.Community,
		CountSignArr: c.CountSignArr,
		CountSign:    c.CountSign,
		Lang:         c.Lang,
		ShowSignData: c.ShowSignData,
		SignData:     "",
		MyChatName:   myChatName,
		UserId:       c.SessUserId,
		IOS:          utils.IOS(),
		Mobile:       utils.Mobile()})
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	return TemplateStr, nil
}
Пример #4
0
func makeVcomplex(json_data []byte) (*vComplex, error) {
	vComplex := new(vComplex)
	err := json.Unmarshal(json_data, &vComplex)
	if err != nil {
		vComplex_ := new(vComplex_)
		err = json.Unmarshal(json_data, &vComplex_)
		if err != nil {
			vComplex__ := new(vComplex__)
			err = json.Unmarshal(json_data, &vComplex__)
			if err != nil {
				return vComplex, err
			}
			vComplex.Referral = vComplex__.Referral
			vComplex.Currency = vComplex__.Currency
			vComplex.Admin = utils.StrToInt64(vComplex__.Admin)
		} else {
			vComplex.Referral = make(map[string]string)
			for k, v := range vComplex_.Referral {
				vComplex.Referral[k] = utils.Int64ToStr(v)
			}
			vComplex.Currency = vComplex_.Currency
			vComplex.Admin = vComplex_.Admin
		}
	}
	return vComplex, nil
}
Пример #5
0
func (a *AvailablekeyStruct) checkAvailableKey(key string) (int64, string, error) {
	publicKeyAsn, err := utils.GetPublicFromPrivate(key)
	if err != nil {
		log.Debug("%v", err)
		return 0, "", utils.ErrInfo(err)
	}
	log.Debug("publicKeyAsn: %s", publicKeyAsn)
	userId, err := a.Single("SELECT user_id FROM users WHERE hex(public_key_0) = ?", publicKeyAsn).Int64()
	if err != nil {
		return 0, "", utils.ErrInfo(err)
	}
	log.Debug("userId: %s", userId)
	if userId == 0 {
		return 0, "", errors.New("null userId")
	}
	allTables, err := a.GetAllTables()
	if err != nil {
		return 0, "", utils.ErrInfo(err)
	}
	// может другой юзер уже начал смену ключа. актуально для пула
	if utils.InSliceString(utils.Int64ToStr(userId)+"_my_table", allTables) {
		return 0, "", errors.New("exists _my_table")
	}
	return userId, string(publicKeyAsn), nil
}
Пример #6
0
func (c *Controller) NewPhoto() (string, error) {

	c.r.ParseForm()

	userId := int64(utils.StrToFloat64(c.r.FormValue("user_id")))

	data, err := c.OneRow("SELECT photo_block_id, photo_max_miner_id, miners_keepers FROM miners_data WHERE user_id = ?", userId).String()
	if err != nil {
		return "", utils.ErrInfo(err)
	}

	// получим ID майнеров, у которых лежат фото нужного нам юзера
	minersIds := utils.GetMinersKeepers(data["photo_block_id"], data["photo_max_miner_id"], data["miners_keepers"], true)

	// берем 1 случайный из 10-и ID майнеров
	k := utils.RandInt(0, len(minersIds))
	minerId := minersIds[k]
	host, err := c.Single("SELECT http_host FROM miners_data WHERE miner_id  =  ?", minerId).String()
	if err != nil {
		return "", utils.ErrInfo(err)
	}

	result, err := json.Marshal(map[string]string{"face": host + "public/face_" + utils.Int64ToStr(userId) + ".jpg", "profile": host + "public/profile_" + utils.Int64ToStr(userId) + ".jpg"})
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	return string(result), nil
}
Пример #7
0
func (c *Controller) CfCatalog() (string, error) {

	var err error
	log.Debug("CfCatalog")

	categoryId := utils.Int64ToStr(int64(utils.StrToFloat64(c.Parameters["category_id"])))
	log.Debug("categoryId", categoryId)
	var curCategory string
	addSql := ""
	if categoryId != "0" {
		addSql = `AND category_id = ` + categoryId
		curCategory = c.Lang["cf_category_"+categoryId]
	}

	cfUrl := ""

	projects := make(map[string]map[string]string)
	cfProjects, err := c.GetAll(`
			SELECT cf_projects.id, lang_id, blurb_img, country, city, currency_id, end_time, amount
			FROM cf_projects
			LEFT JOIN cf_projects_data ON  cf_projects_data.project_id = cf_projects.id
			WHERE del_block_id = 0 AND
						 end_time > ? AND
						 lang_id = ?
						`+addSql+`
			ORDER BY funders DESC
			LIMIT 100
			`, 100, utils.Time(), c.LangInt)
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	for _, data := range cfProjects {
		CfProjectData, err := c.GetCfProjectData(utils.StrToInt64(data["id"]), utils.StrToInt64(data["end_time"]), c.LangInt, utils.StrToFloat64(data["amount"]), cfUrl)
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		for k, v := range CfProjectData {
			data[k] = v
		}
		projects[data["id"]] = data
	}

	cfCategory := utils.MakeCfCategories(c.Lang)

	TemplateStr, err := makeTemplate("cf_catalog", "cfCatalog", &cfCatalogPage{
		Lang:         c.Lang,
		CfCategory:   cfCategory,
		CurrencyList: c.CurrencyList,
		CurCategory:  curCategory,
		Projects:     projects,
		UserId:       c.SessUserId,
		CategoryId:   categoryId,
		CfUrl:        cfUrl})
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	return TemplateStr, nil
}
Пример #8
0
func (c *Controller) Upgrade1() (string, error) {

	log.Debug("Upgrade1")

	userFace := ""
	/*userProfile := ""

	path := "public/"+utils.Int64ToStr(c.SessUserId)+"_user_profile.jpg"
	if _, err := os.Stat(path); err == nil {
		userProfile = path
	}*/

	path := *utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_face.jpg"
	if _, err := os.Stat(path); err == nil {
		userFace = "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_face.jpg"
	}

	step := "1"
	nextStep := "2"
	photoType := "face"
	photo := userFace

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

	TemplateStr, err := makeTemplate("upgrade_1_and_2", "upgrade1And2", &upgrade1Page{
		Alert:           c.Alert,
		Lang:            c.Lang,
		CountSignArr:    c.CountSignArr,
		ShowSignData:    c.ShowSignData,
		SaveAndGotoStep: saveAndGotoStep,
		UpgradeMenu:     upgradeMenu,
		UserId:          c.SessUserId,
		PhotoType:       photoType,
		Photo:           photo,
		Step:            step,
		NextStep:        nextStep,
		IOS:             utils.IOS(),
		Mobile:          utils.Mobile()})
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	return TemplateStr, nil
}
Пример #9
0
func (p *Parser) VotesPromisedAmountRollback() error {

	// вычитаем баллы
	p.pointsRollback(p.Variables.Int64["promised_amount_points"])

	// удаляем логирование, чтобы юзер {$this->tx_data['user_id']} не смог повторно проголосовать
	err := p.ExecSql("DELETE FROM log_votes WHERE user_id = ? AND voting_id = ? AND type = 'promised_amount'", p.TxMaps.Int64["user_id"], p.TxMaps.Int64["promised_amount_id"])
	if err != nil {
		return p.ErrInfo(err)
	}

	// обновляем голоса
	err = p.ExecSql("UPDATE promised_amount SET votes_"+utils.Int64ToStr(p.TxMaps.Int64["result"])+" = votes_"+utils.Int64ToStr(p.TxMaps.Int64["result"])+" - 1 WHERE id = ?", p.TxMaps.Int64["promised_amount_id"])
	if err != nil {
		return p.ErrInfo(err)
	}
	data, err := p.OneRow("SELECT status, user_id, log_id FROM promised_amount WHERE id  =  ?", p.TxMaps.Int64["promised_amount_id"]).String()
	if err != nil {
		return p.ErrInfo(err)
	}

	// если статус mining или rejected, значит голос был решающим
	if data["status"] == "mining" || data["status"] == "rejected" {

		// восстановим из лога
		logData, err := p.OneRow("SELECT status, start_time, tdc_amount_update, prev_log_id FROM log_promised_amount WHERE log_id  =  ?", data["log_id"]).String()
		if err != nil {
			return p.ErrInfo(err)
		}
		err = p.ExecSql("UPDATE promised_amount SET status = ?, start_time = ?, tdc_amount_update = ?, log_id = ? WHERE id = ?", logData["status"], logData["start_time"], logData["tdc_amount_update"], logData["prev_log_id"], p.TxMaps.Int64["promised_amount_id"])
		if err != nil {
			return p.ErrInfo(err)
		}
		// подчищаем _log
		err = p.ExecSql("DELETE FROM log_promised_amount WHERE log_id = ?", data["log_id"])
		if err != nil {
			return p.ErrInfo(err)
		}
		p.rollbackAI("log_promised_amount", 1)

		// был ли добавлен woc
		woc, err := p.Single("SELECT id FROM promised_amount WHERE currency_id  =  1 AND woc_block_id  =  ? AND user_id  =  ?", p.BlockData.BlockId, data["user_id"]).Int64()
		if err != nil {
			return p.ErrInfo(err)
		}
		if woc > 0 {
			err = p.ExecSql("DELETE FROM promised_amount WHERE id = ?", woc)
			if err != nil {
				return p.ErrInfo(err)
			}
			p.rollbackAI("promised_amount", 1)
		}
	}

	return nil
}
Пример #10
0
func (c *Controller) ChangeHost() (string, error) {

	txType := "ChangeHost"
	txTypeId := utils.TypeInt(txType)
	timeNow := utils.Time()

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

	data, err := c.OneRow("SELECT http_host, tcp_host, host_status FROM " + c.MyPrefix + "my_table").String()
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	data2, err := c.OneRow("SELECT http_host, tcp_host, e_host FROM miners_data WHERE user_id = ?", c.SessUserId).String()
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	if len(data["http_host"]) == 0 {
		data["http_host"] = data2["http_host"]
	}
	if len(data["tcp_host"]) == 0 {
		data["tcp_host"] = data2["tcp_host"]
	}
	if len(data["e_host"]) == 0 {
		data["e_host"] = data2["e_host"]
	}
	if data["e_host"] == "" {
		data["e_host"] = "0"
	}

	statusArray := map[string]string{"my_pending": c.Lang["local_pending"], "approved": c.Lang["status_approved"]}
	data["host_status"] = statusArray[data["host_status"]]

	limitsText := strings.Replace(c.Lang["change_host_limits_text"], "[limit]", utils.Int64ToStr(c.Variables.Int64["limit_change_host"]), -1)
	limitsText = strings.Replace(limitsText, "[period]", c.Periods[c.Variables.Int64["limit_change_host_period"]], -1)

	TemplateStr, err := makeTemplate("change_host", "changeHost", &changeHostPage{
		Alert:        c.Alert,
		UserId:       c.SessUserId,
		CountSignArr: c.CountSignArr,
		Data:         data,
		TimeNow:      timeNow,
		TxType:       txType,
		TxTypeId:     txTypeId,
		LimitsText:   limitsText,
		ShowSignData: c.ShowSignData,
		Community:    c.Community,
		SignData:     "",
		Lang:         c.Lang})
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	return TemplateStr, nil
}
Пример #11
0
func (p *Parser) ChangeArbitratorConditionsRollback() error {
	err := p.selectiveRollback([]string{"url"}, "users", "user_id="+utils.Int64ToStr(p.TxUserID), false)
	if err != nil {
		return p.ErrInfo(err)
	}
	err = p.generalRollback("arbitrator_conditions", p.TxUserID, "", false)
	if err != nil {
		return p.ErrInfo(err)
	}
	return nil
}
Пример #12
0
func (p *Parser) NewUserRollback() error {
	// если работаем в режиме пула, то ищем тех, у кого записан такой ключ
	community, err := p.DCDB.GetCommunityUsers()
	if err != nil {
		return p.ErrInfo(err)
	}
	if len(community) > 0 {
		for _, userId := range community {
			myPrefix := utils.Int64ToStr(userId) + "_"
			// проверим, не наш ли это public_key, чтобы записать полученный user_id в my_table
			myPublicKey, err := p.DCDB.Single("SELECT public_key FROM "+myPrefix+"my_keys WHERE hex(public_key) = ?", p.TxMap["public_key_hex"]).String()
			if err != nil {
				return p.ErrInfo(err)
			}
			if myPublicKey != "" {
				// теперь у нас полноценный юзерский акк, и его можно апргрейдить до майнерского
				err = p.DCDB.ExecSql("UPDATE " + myPrefix + "my_table SET user_id = 0, status = 'my_pending', notification_status = 0")
				if err != nil {
					return p.ErrInfo(err)
				}
				err = p.DCDB.ExecSql("UPDATE "+myPrefix+"my_keys SET block_id = 0 WHERE block_id = ?", p.BlockData.BlockId)
				if err != nil {
					return p.ErrInfo(err)
				}
			}
		}
	} else {
		// проверим, не наш ли это public_key
		myPublicKey, err := p.DCDB.Single("SELECT public_key FROM my_keys WHERE hex(public_key) = ?", p.TxMap["public_key_hex"]).String()
		if err != nil {
			return p.ErrInfo(err)
		}
		if myPublicKey != "" {
			err = p.DCDB.ExecSql("UPDATE my_table SET user_id = 0, status = 'my_pending', notification_status = 0")
			if err != nil {
				return p.ErrInfo(err)
			}
			err = p.DCDB.ExecSql("UPDATE my_keys SET block_id = 0 WHERE block_id = ?", p.BlockData.BlockId)
			if err != nil {
				return p.ErrInfo(err)
			}
		}
	}
	err = p.DCDB.ExecSql("DELETE FROM users WHERE hex(public_key_0) = ?", p.TxMap["public_key_hex"])
	if err != nil {
		return p.ErrInfo(err)
	}
	err = p.rollbackAI("users", 1)
	if err != nil {
		return p.ErrInfo(err)
	}
	return nil
}
Пример #13
0
func UnbanNodes(chBreaker chan bool, chAnswer chan string) {
	defer func() {
		if r := recover(); r != nil {
			log.Error("daemon Recovered", r)
			panic(r)
		}
	}()

	GoroutineName := "UnbanNodes"
	d := new(daemon)
	d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName)
	if d.DCDB == nil {
		return
	}
	d.goRoutineName = GoroutineName
	d.chAnswer = chAnswer
	d.chBreaker = chBreaker
	d.sleepTime = 3600
	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
		}

		err = d.ExecSql("DELETE FROM nodes_ban")
		if err != nil {
			if d.dPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

		if d.dSleep(d.sleepTime) {
			break BEGIN
		}
	}
	log.Debug("break BEGIN %v", GoroutineName)
}
Пример #14
0
func (c *Controller) DeleteVideo() (string, error) {

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

	if c.r.FormValue("type") == "mp4" {
		err := os.Remove(*utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_video.mp4")
		if err != nil {
			return "", utils.ErrInfo(err)
		}
	} else if c.r.FormValue("type") == "webm_ogg" {
		err := os.Remove(*utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_video.ogv")
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		err = os.Remove(*utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_video.webm")
		if err != nil {
			return "", utils.ErrInfo(err)
		}
	}

	return ``, nil
}
Пример #15
0
func (c *Controller) CropPhoto() (string, error) {

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

	c.r.ParseForm()
	photo := strings.Split(c.r.FormValue("photo"), ",")
	if len(photo) != 2 {
		return "", errors.New("Incorrect photo")
	}
	binary, err := base64.StdEncoding.DecodeString(photo[1])
	if err != nil {
		return "", err
	}
	img, _, err := image.Decode(bytes.NewReader(binary))
	if err != nil {
		return "", err
	}
	path := ""
	if c.r.FormValue("type") == "face" {
		path = *utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_face.jpg"
	} else {
		path = *utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_profile.jpg"
	}
	out, err := os.Create(path)
	if err != nil {
		return "", err
	}
	err = jpeg.Encode(out, img, &jpeg.Options{85})
	if err != nil {
		return "", err
	}

	return `{"success":"ok"}`, nil
}
Пример #16
0
func (c *Controller) Upgrade4() (string, error) {

	log.Debug("Upgrade4")

	videoUrl := ""

	// есть ли загруженное видео.
	data, err := c.OneRow("SELECT video_url_id, video_type FROM " + c.MyPrefix + "my_table").String()
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	switch data["video_type"] {
	case "youtube":
		videoUrl = "http://www.youtube.com/embed/" + data["video_url_id"]
	case "vimeo":
		videoUrl = "http://www.vimeo.com/embed/" + data["video_url_id"]
	case "youku":
		videoUrl = "http://www.youku.com/embed/" + data["video_url_id"]
	}

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

	var userVideoMp4 string
	path := *utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_video.mp4"
	if _, err := os.Stat(path); err == nil {
		userVideoMp4 = "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_video.mp4"
	}
	var userVideoWebm string
	path = *utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_video.webm"
	if _, err := os.Stat(path); err == nil {
		userVideoWebm = "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_video.webm"
	}
	var userVideoOgg string
	path = *utils.Dir + "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_video.ogg"
	if _, err := os.Stat(path); err == nil {
		userVideoOgg = "/public/" + utils.Int64ToStr(c.SessUserId) + "_user_video.ogg"
	}

	TemplateStr, err := makeTemplate("upgrade_4", "upgrade4", &upgrade4Page{
		Alert:           c.Alert,
		Lang:            c.Lang,
		SaveAndGotoStep: saveAndGotoStep,
		UpgradeMenu:     upgradeMenu,
		VideoUrl:        videoUrl,
		UserVideoMp4:    userVideoMp4,
		UserVideoWebm:   userVideoWebm,
		UserVideoOgg:    userVideoOgg,
		Mobile:          utils.Mobile(),
		UserId:          c.SessUserId})
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	return TemplateStr, nil
}
Пример #17
0
func (db *DCDB) MakeFrontTest(transactionArray []string, time int64, dataForSign string, txType string, userId int64) error {
	var err error
	nodeArr := []string{"new_admin", "votes_node_new_miner"}
	MY_PREFIX := utils.Int64ToStr(userId) + "_"
	var binSign []byte
	if utils.InSliceString(txType, nodeArr) {
		k, err := db.GetNodePrivateKey(MY_PREFIX)
		privateKey, err := MakePrivateKey(k)
		if err != nil {
			return ErrInfo(err)
		}
		binSign, err = rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA1, utils.HashSha1(dataForSign))
	} else {
		k, err := db.GetPrivateKey(MY_PREFIX)
		privateKey, err := MakePrivateKey(k)
		if err != nil {
			return ErrInfo(err)
		}
		binSign, err = rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA1, utils.HashSha1(dataForSign))
		binSign = EncodeLengthPlusData(binSign)
	}
	transactionArray = append(transactionArray, binSign)

	parser := new(Parser)
	parser.DCDB = db
	parser.GoroutineName = "test"
	parser.TxSlice = transactionArray
	parser.BlockData = &utils.BlockData{BlockId: 190006, Time: time, UserId: userId}
	parser.TxHash = "111111111111111"

	err0 := utils.CallMethod(parser, txType+"Init")
	if i, ok := err0.(error); ok {
		fmt.Println(err0.(error), i)
		return err0.(error)
	}
	err0 := utils.CallMethod(parser, txType+"Front")
	if i, ok := err0.(error); ok {
		fmt.Println(err0.(error), i)
		return err0.(error)
	}
	err0 := utils.CallMethod(parser, txType+"RollbackFront")
	if i, ok := err0.(error); ok {
		fmt.Println(err0.(error), i)
		return err0.(error)
	}
	return nil
}
Пример #18
0
func (c *Controller) ChangeGeolocation() (string, error) {

	var err error

	txType := "ChangeGeolocation"
	txTypeId := utils.TypeInt(txType)
	timeNow := utils.Time()

	myGeolocationStr, err := c.Single(`SELECT geolocation FROM ` + c.MyPrefix + `my_table`).String()
	if len(myGeolocationStr) == 0 {
		myGeolocationStr = "39.94887, -75.15005"
	}
	x := strings.Split(myGeolocationStr, ", ")
	myGeolocation := make(map[string]string)
	myGeolocation["lat"] = x[0]
	myGeolocation["lon"] = x[1]

	myCountry, err := c.Single("SELECT country FROM miners_data WHERE user_id = ?", c.SessUserId).Int()
	if err != nil {
		return "", utils.ErrInfo(err)
	}

	limitsText := strings.Replace(c.Lang["geolocation_limits_text"], "[limit]", utils.Int64ToStr(c.Variables.Int64["limit_change_geolocation"]), -1)
	limitsText = strings.Replace(limitsText, "[period]", c.Periods[c.Variables.Int64["limit_change_geolocation_period"]], -1)

	TemplateStr, err := makeTemplate("change_geolocation", "changeGeolocation", &changeGeolocationPage{
		Alert:         c.Alert,
		Lang:          c.Lang,
		TxTypeId:      txTypeId,
		TimeNow:       timeNow,
		UserId:        c.SessUserId,
		CountSignArr:  c.CountSignArr,
		ShowSignData:  c.ShowSignData,
		SignData:      "",
		LimitsText:    limitsText,
		MyCountry:     myCountry,
		Countries:     consts.Countries,
		MyGeolocation: myGeolocation})
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	return TemplateStr, nil
}
Пример #19
0
func (c *Controller) MyNoticeData() (string, error) {

	if !c.dbInit {
		return "", utils.ErrInfo(errors.New("Permission denied"))
	}

	c.r.ParseForm()

	myNotice, err := c.GetMyNoticeData(c.SessRestricted, c.SessUserId, c.MyPrefix, c.Lang)
	if err != nil {
		return "", utils.ErrInfo(err)
	}

	var cashRequests int64
	if c.SessRestricted == 0 {
		myUserId, err := c.GetMyUserId(c.MyPrefix)
		if err != nil {
			return "", utils.ErrInfo(err)
		}
		cashRequests, err = c.Single("SELECT count(id) FROM cash_requests WHERE to_user_id  =  ? AND status  =  'pending' AND for_repaid_del_block_id  =  0 AND del_block_id  =  0", myUserId).Int64()
		if cashRequests > 0 {
			cashRequests = 1
		}
		if err != nil {
			return "", utils.ErrInfo(err)
		}
	}

	result, err := json.Marshal(map[string]string{
		"main_status":          myNotice["main_status"],
		"main_status_complete": myNotice["main_status_complete"],
		"account_status":       myNotice["account_status"],
		"cur_block_id":         myNotice["cur_block_id"],
		"connections":          myNotice["connections"],
		"time_last_block":      myNotice["time_last_block"],
		"time_last_block_int":  myNotice["time_last_block_int"],
		"inbox":                utils.Int64ToStr(cashRequests)})
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	return string(result), nil
}
Пример #20
0
func (c *Controller) GetBlock() (string, error) {

	c.r.ParseForm()

	BlockId := int64(utils.StrToFloat64(c.r.FormValue("id")))
	if BlockId == 0 {
		return `{"error": "nil id"}`, nil
	}

	if len(c.r.FormValue("download")) > 0 {
		c.w.Header().Set("Content-type", "application/octet-stream")
		c.w.Header().Set("Content-Disposition", "attachment; filename=\""+utils.Int64ToStr(BlockId)+".binary\"")
	}

	block, err := c.Single("SELECT data FROM block_chain WHERE id  =  ?", BlockId).String()
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	return block, nil
}
Пример #21
0
func (c *Controller) PromisedAmountList() (string, error) {

	txType := "PromisedAmount"
	txTypeId := utils.TypeInt(txType)
	timeNow := time.Now().Unix()

	last_tx, err := c.GetLastTx(c.SessUserId, utils.TypesToIds([]string{"NewPromisedAmount", "ChangePromisedAmount", "DelPromisedAmount", "ForRepaidFix", "ActualizationPromisedAmounts", "Mining"}), 3, c.TimeFormat)
	lastTxFormatted := ""
	if len(last_tx) > 0 {
		lastTxFormatted, _ = utils.MakeLastTx(last_tx, c.Lang)
	}

	limitsText := strings.Replace(c.Lang["change_commission_limits_text"], "[limit]", utils.Int64ToStr(c.Variables.Int64["limit_promised_amount"]), -1)
	limitsText = strings.Replace(limitsText, "[period]", c.Periods[c.Variables.Int64["limit_promised_amount_period"]], -1)

	actualizationPromisedAmounts, promisedAmountListAccepted, _, err := c.GetPromisedAmounts(c.SessUserId, c.Variables.Int64["cash_request_time"])
	if err != nil {
		return "", utils.ErrInfo(err)
	}

	TemplateStr, err := makeTemplate("promised_amount_list", "promisedAmountList", &promisedAmountListPage{
		Alert:                        c.Alert,
		Lang:                         c.Lang,
		CountSignArr:                 c.CountSignArr,
		ShowSignData:                 c.ShowSignData,
		UserId:                       c.SessUserId,
		TimeNow:                      timeNow,
		TxType:                       txType,
		TxTypeId:                     txTypeId,
		SignData:                     "",
		LastTxFormatted:              lastTxFormatted,
		CurrencyList:                 c.CurrencyList,
		PromisedAmountListAccepted:   promisedAmountListAccepted,
		ActualizationPromisedAmounts: actualizationPromisedAmounts,
		LimitsText:                   limitsText})
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	return TemplateStr, nil
}
Пример #22
0
func (p *Parser) DelCfProjectRollback() error {

	project_currency_id, err := p.Single("SELECT currency_id FROM cf_projects WHERE id  =  ?", p.TxMaps.Int64["project_id"]).Int64()
	if err != nil {
		return p.ErrInfo(err)
	}

	// проходимся по всем фундерам и возращаем на их кошельки деньги
	rows, err := p.Query(p.FormatQuery("SELECT user_id FROM cf_funding WHERE project_id = ? AND del_block_id = 0 ORDER BY id DESC"), p.TxMaps.Int64["project_id"])
	if err != nil {
		return p.ErrInfo(err)
	}
	defer rows.Close()
	for rows.Next() {
		var user_id int64
		err = rows.Scan(&user_id)
		if err != nil {
			return p.ErrInfo(err)
		}
		// откат возврата
		err = p.generalRollback("wallets", user_id, "AND currency_id = "+utils.Int64ToStr(project_currency_id), false)
		if err != nil {
			return p.ErrInfo(err)
		}
		// возможно были списания по кредиту
		err = p.loanPaymentsRollback(user_id, project_currency_id)
		if err != nil {
			return p.ErrInfo(err)
		}
	}

	err = p.ExecSql("UPDATE cf_projects SET del_block_id = 0 WHERE id = ?", p.TxMaps.Int64["project_id"])
	if err != nil {
		return p.ErrInfo(err)
	}
	return nil
}
Пример #23
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
}
Пример #24
0
func (c *Controller) AlertFromAdmin() (string, error) {

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

	alertMessage := ""
	alert, err := utils.GetHttpTextAnswer("http://dcoin.club/alert.json")
	if len(alert) > 0 {
		alertData := new(alertType)
		err = json.Unmarshal([]byte(alert), &alertData)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}

		messageJson, err := json.Marshal(alertData.Message)
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}

		pub, err := utils.BinToRsaPubKey(utils.HexToBin(consts.ALERT_KEY))
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}
		err = rsa.VerifyPKCS1v15(pub, crypto.SHA1, utils.HashSha1(string(messageJson)), []byte(utils.HexToBin(alertData.Signature)))
		if err != nil {
			log.Error("%v", utils.ErrInfo(err))
		}

		if version.Compare(alertData.Message["version"], consts.VERSION, ">") {
			alertMessage = alertData.Message[utils.Int64ToStr(c.LangInt)]
			return utils.JsonAnswer(alertMessage, "success").String(), nil
		}
	}
	return ``, nil
}
Пример #25
0
func (c *Controller) HolidaysList() (string, error) {

	var err error

	var myHolidaysPending []map[string]string
	if c.SessRestricted == 0 {
		// те, что еще не попали в Dc-сеть
		myHolidaysPending, err = c.GetAll(`SELECT * FROM `+c.MyPrefix+`my_holidays ORDER BY id DESC`, -1)
	}

	myHolidaysAccepted, err := c.GetAll(`SELECT * FROM holidays WHERE user_id = ?`, -1, c.SessUserId)

	limitsText := strings.Replace(c.Lang["limits_text"], "[limit]", utils.Int64ToStr(c.Variables.Int64["limit_holidays"]), -1)
	limitsText = strings.Replace(limitsText, "[period]", c.Periods[c.Variables.Int64["limit_holidays_period"]], -1)

	last_tx, err := c.GetLastTx(c.SessUserId, utils.TypesToIds([]string{"NewHolidays"}), 3, c.TimeFormat)
	lastTxFormatted := ""
	if len(last_tx) > 0 {
		lastTxFormatted, _ = utils.MakeLastTx(last_tx, c.Lang)
	}

	TemplateStr, err := makeTemplate("holidays_list", "holidaysList", &holidaysListPage{
		Alert:              c.Alert,
		Lang:               c.Lang,
		CountSignArr:       c.CountSignArr,
		ShowSignData:       c.ShowSignData,
		SignData:           "",
		LastTxFormatted:    lastTxFormatted,
		LimitsText:         limitsText,
		MyHolidaysPending:  myHolidaysPending,
		MyHolidaysAccepted: myHolidaysAccepted})
	if err != nil {
		return "", utils.ErrInfo(err)
	}
	return TemplateStr, nil
}
Пример #26
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
}
Пример #27
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
}
func MaxOtherCurrenciesGenerator(chBreaker chan bool, chAnswer chan string) {
	defer func() {
		if r := recover(); r != nil {
			log.Error("daemon Recovered", r)
			panic(r)
		}
	}()

	const GoroutineName = "MaxOtherCurrenciesGenerator"
	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(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		if blockId == 0 {
			if d.unlockPrintSleep(utils.ErrInfo("blockId == 0"), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

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

		totalCountCurrencies, err := d.GetCountCurrencies()
		if err != nil {
			if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		// проверим, прошло ли 2 недели с момента последнего обновления
		pctTime, err := d.Single("SELECT max(time) FROM max_other_currencies_time").Int64()
		if err != nil {
			if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		if curTime-pctTime <= variables.Int64["new_max_other_currencies"] {
			if d.unlockPrintSleep(utils.ErrInfo("14 day error"), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

		// берем все голоса
		maxOtherCurrenciesVotes := make(map[int64][]map[int64]int64)
		rows, err := d.Query("SELECT currency_id, count, count(user_id) as votes FROM votes_max_other_currencies GROUP BY currency_id, count ORDER BY currency_id, count ASC")
		if err != nil {
			if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		for rows.Next() {
			var currency_id, count, votes int64
			err = rows.Scan(&currency_id, &count, &votes)
			if err != nil {
				rows.Close()
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			maxOtherCurrenciesVotes[currency_id] = append(maxOtherCurrenciesVotes[currency_id], map[int64]int64{count: votes})
		}
		rows.Close()

		newMaxOtherCurrenciesVotes := make(map[string]int64)
		for currencyId, countAndVotes := range maxOtherCurrenciesVotes {
			newMaxOtherCurrenciesVotes[utils.Int64ToStr(currencyId)] = utils.GetMaxVote(countAndVotes, 0, totalCountCurrencies, 10)
		}

		jsonData, err := json.Marshal(newMaxOtherCurrenciesVotes)

		_, myUserId, _, _, _, _, err := d.TestBlock()
		forSign := fmt.Sprintf("%v,%v,%v,%s", utils.TypeInt("NewMaxOtherCurrencies"), curTime, myUserId, jsonData)
		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("NewMaxOtherCurrencies"), 1)
		data = append(data, utils.DecToBin(curTime, 4)...)
		data = append(data, utils.EncodeLengthPlusData(utils.Int64ToByte(myUserId))...)
		data = append(data, utils.EncodeLengthPlusData(jsonData)...)
		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
		}

		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)
}
Пример #29
0
func Exchange(chBreaker chan bool, chAnswer chan string) {

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

	const GoroutineName = "Exchange"
	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
	}

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

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

		blockId, err := d.GetConfirmedBlockId()
		if err != nil {
			if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

		var myPrefix string
		community, err := d.GetCommunityUsers()
		if len(community) > 0 {
			adminUserId, err := d.GetPoolAdminUserId()
			if err != nil {
				if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			myPrefix = utils.Int64ToStr(adminUserId) + "_"
		} else {
			myPrefix = ""
		}

		eConfig, err := d.GetMap(`SELECT * FROM e_config`, "name", "value")
		if err != nil {
			if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		confirmations := utils.StrToInt64(eConfig["confirmations"])
		mainDcAccount := utils.StrToInt64(eConfig["main_dc_account"])

		// все валюты, с которыми работаем
		currencyList, err := utils.EGetCurrencyList()
		if err != nil {
			if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

		// ++++++++++++ reduction ++++++++++++

		// максимальный номер блока для процентов. Чтобы брать только новые
		maxReductionBlock, err := d.Single(`SELECT max(block_id) FROM e_reduction`).Int64()
		if err != nil {
			if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

		// если есть свежая reduction, то нужно остановить торги
		reduction, err := d.Single(`SELECT block_id FROM reduction WHERE block_id > ? and pct > 0`, maxReductionBlock).Int64()
		if err != nil {
			if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		if reduction > 0 {
			err = d.ExecSql(`INSERT INTO e_reduction_lock (time) VALUES (?)`, utils.Time())
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
			}
		}

		// если уже прошло 10 блоков с момента обнаружения reduction, то производим сокращение объема монет
		rows, err := d.Query(d.FormatQuery(`SELECT pct, currency_id, time, block_id FROM reduction WHERE block_id > ? AND
	block_id < ?`), maxReductionBlock, blockId-confirmations)
		if err != nil {
			if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		for rows.Next() {
			var pct float64
			var currencyId, rTime, blockId int64
			err = rows.Scan(&pct, &currencyId, &rTime, &blockId)
			if err != nil {
				rows.Close()
				if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			//	$k = (100-$row['pct'])/100;
			k := (100 - pct) / 100
			// уменьшаем все средства на счетах
			err = d.ExecSql(`UPDATE e_wallets SET amount = amount * ? WHERE currency_id = ?`, k, currencyId)

			// уменьшаем все средства на вывод
			err = d.ExecSql(`UPDATE e_withdraw SET amount = amount * ? WHERE currency_id = ? AND close_time = 0`, k, currencyId)

			// уменьшаем все ордеры на продажу
			err = d.ExecSql(`UPDATE e_orders SET amount = amount * ?, begin_amount = begin_amount * ? WHERE sell_currency_id = ?`, k, k, currencyId)

			err = d.ExecSql(`INSERT INTO e_reduction (
					time,
					block_id,
					currency_id,
					pct
				)
				VALUES (
					?,
					?,
					?,
					?
				)`, rTime, blockId, currencyId, pct)
			if err != nil {
				rows.Close()
				if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
		}
		rows.Close()

		// ++++++++++++ DC ++++++++++++
		/*
		 * Важно! отключать в кроне при обнулении данных в БД
		 *
		 * 1. Получаем инфу о входящих переводах и начисляем их на счета юзеров
		 * 2. Обновляем проценты
		 * 3. Чистим кол-во отправленных смс-ок
		 * */
		nodePrivateKey, err := d.GetNodePrivateKey(myPrefix)
		if err != nil {
			if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		/*
		 * Получаем инфу о входящих переводах и начисляем их на счета юзеров
		 * */

		// если всё остановлено из-за найденного блока с reduction, то входящие переводы не обрабатываем
		reductionLock, err := utils.EGetReductionLock()
		if err != nil {
			if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		if reductionLock > 0 {
			if d.dPrintSleep(utils.ErrInfo("reductionLock"), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

		rows, err = d.Query(d.FormatQuery(`
				SELECT amount, id, block_id, type_id, currency_id, to_user_id, time, comment, comment_status
				FROM my_dc_transactions
				WHERE type = 'from_user' AND
					  block_id < ? AND
					  exchange_checked = 0 AND
					  status = 'approved' AND
					  to_user_id = ?
				ORDER BY id DESC`), blockId-confirmations, mainDcAccount)
		if err != nil {
			if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		for rows.Next() {
			var amount float64
			var id, blockId, typeId, currencyId, toUserId, txTime int64
			var comment, commentStatus string
			err = rows.Scan(&amount, &id, &blockId, &typeId, &currencyId, &toUserId, &txTime, &comment, &commentStatus)
			if err != nil {
				rows.Close()
				if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			// отметим exchange_checked=1, чтобы больше не брать эту тр-ию
			err = d.ExecSql(`UPDATE my_dc_transactions SET exchange_checked = 1 WHERE id = ?`, id)
			if err != nil {
				rows.Close()
				if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}

			// вначале нужно проверить, точно ли есть такой перевод в блоке
			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
				}
				log.Debug("md5hash %s", txMap["md5hash"])

				// если что-то случится с таблой my_dc_transactions, то все ввода на биржу будут зачислены по новой
				// поэтому нужно проверять e_adding_funds
				exists, err := d.Single(`SELECT id FROM e_adding_funds WHERE hex(tx_hash) = ?`, string(txMap["md5hash"])).Int64()
				if err != nil {
					rows.Close()
					if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				log.Debug("exists %d", exists)
				if exists != 0 {
					continue
				}

				log.Debug("user_id = %d / typeId = %d / currency_id = %d / currencyId = %d / amount = %f / amount = %f / comment = %s / comment = %s / to_user_id = %d / toUserId = %d ", utils.BytesToInt64(txMap["user_id"]), typeId, utils.BytesToInt64(txMap["currency_id"]), currencyId, utils.BytesToFloat64(txMap["amount"]), amount, string(utils.BinToHex(txMap["comment"])), comment, utils.BytesToInt64(txMap["to_user_id"]), toUserId)
				// сравнение данных из таблы my_dc_transactions с тем, что в блоке
				if utils.BytesToInt64(txMap["user_id"]) == typeId && utils.BytesToInt64(txMap["currency_id"]) == currencyId && utils.BytesToFloat64(txMap["amount"]) == amount && string(utils.BinToHex(txMap["comment"])) == comment && utils.BytesToInt64(txMap["to_user_id"]) == toUserId {

					decryptedComment := comment
					if commentStatus == "encrypted" {
						// расшифруем коммент
						block, _ := pem.Decode([]byte(nodePrivateKey))
						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, utils.HexToBin(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
						}
					}

					// возможно юзер сделал перевод в той валюте, которая у нас на бирже еще не торгуется
					if len(currencyList[currencyId]) == 0 {
						log.Error("currencyId %d not trading", currencyId)
						continue
					}

					// возможно, что чуть раньше было reduction, а это значит, что все тр-ии,
					// которые мы ещё не обработали и которые были До блока с reduction нужно принимать с учетом reduction
					// т.к. средства на нашем счете уже урезались, а  вот те, что после reduction - остались в том виде, в котором пришли
					lastReduction, err := d.OneRow("SELECT block_id, pct FROM reduction WHERE currency_id  = ? ORDER BY block_id", currencyId).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)
					}

					// начисляем средства на счет того, чей id указан в комменте
					r, _ := regexp.Compile(`(?i)\s*#\s*([0-9]+)\s*`)
					user := r.FindStringSubmatch(decryptedComment)
					if len(user) == 0 {
						log.Error("len(user) == 0")
						continue
					}
					log.Debug("user %s", user[1])
					// user_id с биржевой таблы
					uid := utils.StrToInt64(user[1])
					userAmountAndProfit := utils.EUserAmountAndProfit(uid, currencyId)
					newAmount_ := userAmountAndProfit + amount

					utils.UpdEWallet(uid, currencyId, utils.Time(), newAmount_, true)

					// для отчетности запишем в историю
					err = d.ExecSql(`
						INSERT INTO e_adding_funds (
							user_id,
							currency_id,
							time,
							amount,
							tx_hash
						)
						VALUES (
							?,
							?,
							?,
							?,
							?
						)`, uid, currencyId, txTime, amount, string(txMap["md5hash"]))
					if err != nil {
						rows.Close()
						if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
							break BEGIN
						}
						continue BEGIN
					}
				}
			}
		}
		rows.Close()

		/*
		 * Обновляем проценты
		 * */
		// максимальный номер блока для процентов. Чтобы брать только новые
		maxPctBlock, err := d.Single(`SELECT max(block_id) FROM e_user_pct`).Int64()

		log.Debug(`SELECT time, block_id, currency_id, user FROM pct WHERE  block_id < ` + utils.Int64ToStr(blockId-confirmations) + ` AND block_id > ` + utils.Int64ToStr(maxPctBlock))
		rows, err = d.Query(d.FormatQuery(`SELECT time, block_id, currency_id, user FROM pct WHERE  block_id < ? AND block_id > ?`), blockId-confirmations, maxPctBlock)
		if err != nil {
			if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		for rows.Next() {
			var pct float64
			var pTime, blockId, currencyId int64
			err = rows.Scan(&pTime, &blockId, &currencyId, &pct)
			if err != nil {
				rows.Close()
				if d.dPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			d.ExecSql(`
				INSERT INTO e_user_pct (
					time,
					block_id,
					currency_id,
					pct
				)
				VALUES (
					?,
					?,
					?,
					?
				)`, pTime, blockId, currencyId, pct)
		}
		rows.Close()

		if d.dSleep(d.sleepTime) {
			break BEGIN
		}
	}
	log.Debug("break BEGIN %v", GoroutineName)
}
Пример #30
0
func BlocksCollection(chBreaker chan bool, chAnswer chan string) {
	defer func() {
		if r := recover(); r != nil {
			log.Error("daemon Recovered", r)
			panic(r)
		}
	}()

	const GoroutineName = "BlocksCollection"
	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 = 300
	} else {
		d.sleepTime = 60
	}
	if !d.CheckInstall(chBreaker, chAnswer, GoroutineName) {
		return
	}
	d.DCDB = DbConnect(chBreaker, chAnswer, GoroutineName)
	if d.DCDB == nil {
		return
	}
	//var cur bool
BEGIN:
	for {
		log.Info(GoroutineName)
		MonitorDaemonCh <- []string{GoroutineName, utils.Int64ToStr(utils.Time())}

		// проверим, не нужно ли нам выйти из цикла
		if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
			break BEGIN
		}
		log.Debug("0")
		config, err := d.GetNodeConfig()
		if err != nil {
			if d.dPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		log.Debug("1")

		err, restart := d.dbLock()
		if restart {
			log.Debug("restart true")
			break BEGIN
		}
		if err != nil {
			log.Debug("restart err %v", err)
			if d.dPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}
		log.Debug("2")

		// если это первый запуск во время инсталяции
		currentBlockId, err := d.GetBlockId()
		if err != nil {
			if d.unlockPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

		log.Info("config", config)
		log.Info("currentBlockId", currentBlockId)

		// на время тестов
		/*if !cur {
		    currentBlockId = 0
		    cur = true
		}*/
		parser := new(dcparser.Parser)
		parser.DCDB = d.DCDB
		parser.GoroutineName = GoroutineName
		if currentBlockId == 0 || *utils.StartBlockId > 0 {
			/*
			   IsNotExistBlockChain := false
			   if _, err := os.Stat(*utils.Dir+"/public/blockchain"); os.IsNotExist(err) {
			       IsNotExistBlockChain = true
			   }*/
			if config["first_load_blockchain"] == "file" /* && IsNotExistBlockChain*/ {

				log.Info("first_load_blockchain=file")
				nodeConfig, err := d.GetNodeConfig()
				blockchain_url := nodeConfig["first_load_blockchain_url"]
				if len(blockchain_url) == 0 {
					blockchain_url = consts.BLOCKCHAIN_URL
				}
				log.Debug("blockchain_url: %s", blockchain_url)
				// возможно сервер отдаст блокчейн не с первой попытки
				var blockchainSize int64
				for i := 0; i < 10; i++ {
					log.Debug("blockchain_url: %s, i: %d", blockchain_url, i)
					blockchainSize, err = utils.DownloadToFile(blockchain_url, *utils.Dir+"/public/blockchain", 3600, chBreaker, chAnswer, GoroutineName)
					if err != nil {
						log.Error("%v", utils.ErrInfo(err))
					}
					if blockchainSize > consts.BLOCKCHAIN_SIZE {
						break
					}
				}
				log.Debug("blockchain dw ok")
				if err != nil || blockchainSize < consts.BLOCKCHAIN_SIZE {
					if err != nil {
						log.Error("%v", utils.ErrInfo(err))
					} else {
						log.Info(fmt.Sprintf("%v < %v", blockchainSize, consts.BLOCKCHAIN_SIZE))
					}
					if d.unlockPrintSleep(err, d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}

				first := true
				/*// блокчейн мог быть загружен ранее. проверим его размер


				  stat, err := file.Stat()
				  if err != nil {
				      if d.unlockPrintSleep(err, d.sleepTime) {	break BEGIN }
				      file.Close()
				      continue BEGIN
				  }
				  if stat.Size() < consts.BLOCKCHAIN_SIZE {
				      d.unlockPrintSleep(fmt.Errorf("%v < %v", stat.Size(), consts.BLOCKCHAIN_SIZE), 1)
				      file.Close()
				      continue BEGIN
				  }*/

				log.Debug("GO!")
				file, err := os.Open(*utils.Dir + "/public/blockchain")
				if err != nil {
					if d.unlockPrintSleep(err, d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				err = d.ExecSql(`UPDATE config SET current_load_blockchain = 'file'`)
				if err != nil {
					if d.unlockPrintSleep(err, d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}

				for {
					// проверим, не нужно ли нам выйти из цикла
					if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
						d.unlockPrintSleep(fmt.Errorf("DaemonsRestart"), 0)
						break BEGIN
					}
					b1 := make([]byte, 5)
					file.Read(b1)
					dataSize := utils.BinToDec(b1)
					log.Debug("dataSize", dataSize)
					if dataSize > 0 {

						data := make([]byte, dataSize)
						file.Read(data)
						//log.Debug("data %x\n", data)
						blockId := utils.BinToDec(data[0:5])
						if *utils.EndBlockId > 0 && blockId == *utils.EndBlockId {
							if d.dPrintSleep(err, d.sleepTime) {
								break BEGIN
							}
							file.Close()
							continue BEGIN
						}
						log.Info("blockId", blockId)
						data2 := data[5:]
						length := utils.DecodeLength(&data2)
						log.Debug("length", length)
						//log.Debug("data2 %x\n", data2)
						blockBin := utils.BytesShift(&data2, length)
						//log.Debug("blockBin %x\n", blockBin)

						if *utils.StartBlockId == 0 || (*utils.StartBlockId > 0 && blockId > *utils.StartBlockId) {

							// парсинг блока
							parser.BinaryData = blockBin

							if first {
								parser.CurrentVersion = consts.VERSION
								first = false
							}
							err = parser.ParseDataFull()
							if err != nil {
								if d.dPrintSleep(err, d.sleepTime) {
									break BEGIN
								}
								file.Close()
								continue BEGIN
							}
							err = parser.InsertIntoBlockchain()
							if err != nil {
								if d.dPrintSleep(err, d.sleepTime) {
									break BEGIN
								}
								file.Close()
								continue BEGIN
							}

							// отметимся, чтобы не спровоцировать очистку таблиц
							err = parser.UpdMainLock()
							if err != nil {
								if d.dPrintSleep(err, d.sleepTime) {
									break BEGIN
								}
								file.Close()
								continue BEGIN
							}
							if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
								if d.dPrintSleep(err, d.sleepTime) {
									break BEGIN
								}
								file.Close()
								continue BEGIN
							}
						}
						// ненужный тут размер в конце блока данных
						data = make([]byte, 5)
						file.Read(data)
					} else {
						if d.unlockPrintSleep(err, d.sleepTime) {
							break BEGIN
						}
						continue BEGIN
					}
					// utils.Sleep(1)
				}
				file.Close()
			} else {

				newBlock, err := static.Asset("static/1block.bin")
				if err != nil {
					if d.dPrintSleep(err, d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				parser.BinaryData = newBlock
				parser.CurrentVersion = consts.VERSION

				err = parser.ParseDataFull()
				if err != nil {
					if d.dPrintSleep(err, d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				err = parser.InsertIntoBlockchain()

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

			utils.Sleep(1)
			d.dbUnlock()
			continue BEGIN
		}
		d.dbUnlock()

		err = d.ExecSql(`UPDATE config SET current_load_blockchain = 'nodes'`)
		if err != nil {
			if d.unlockPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

		myConfig, err := d.OneRow("SELECT local_gate_ip, static_node_user_id FROM config").String()
		if err != nil {
			if d.dPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue
		}
		var hosts []map[string]string
		var nodeHost string
		var dataTypeMaxBlockId, dataTypeBlockBody int64
		if len(myConfig["local_gate_ip"]) > 0 {
			hosts = append(hosts, map[string]string{"host": myConfig["local_gate_ip"], "user_id": myConfig["static_node_user_id"]})
			nodeHost, err = d.Single("SELECT tcp_host FROM miners_data WHERE user_id  =  ?", myConfig["static_node_user_id"]).String()
			if err != nil {
				if d.dPrintSleep(err, d.sleepTime) {
					break BEGIN
				}
				continue
			}
			dataTypeMaxBlockId = 9
			dataTypeBlockBody = 8
			//getBlockScriptName = "ajax?controllerName=protectedGetBlock";
			//addNodeHost = "&nodeHost="+nodeHost;
		} else {
			// получим список нодов, с кем установлено рукопожатие
			hosts, err = d.GetAll("SELECT * FROM nodes_connection", -1)
			if err != nil {
				if d.dPrintSleep(err, d.sleepTime) {
					break BEGIN
				}
				continue
			}
			dataTypeMaxBlockId = 10
			dataTypeBlockBody = 7
			//getBlockScriptName = "ajax?controllerName=getBlock";
			//addNodeHost = "";
		}

		log.Info("%v", hosts)

		if len(hosts) == 0 {
			if d.dPrintSleep(err, 1) {
				break BEGIN
			}
			continue
		}

		maxBlockId := int64(1)
		maxBlockIdHost := ""
		var maxBlockIdUserId int64
		// получим максимальный номер блока
		for i := 0; i < len(hosts); i++ {
			if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
				break BEGIN
			}
			conn, err := utils.TcpConn(hosts[i]["host"])
			if err != nil {
				if d.dPrintSleep(err, 1) {
					break BEGIN
				}
				continue
			}
			// шлем тип данных
			_, err = conn.Write(utils.DecToBin(dataTypeMaxBlockId, 1))
			if err != nil {
				conn.Close()
				if d.dPrintSleep(err, 1) {
					break BEGIN
				}
				continue
			}
			if len(nodeHost) > 0 { // защищенный режим
				err = utils.WriteSizeAndData([]byte(nodeHost), conn)
				if err != nil {
					conn.Close()
					if d.dPrintSleep(err, d.sleepTime) {
						break BEGIN
					}
					continue
				}
			}
			// в ответ получаем номер блока
			blockIdBin := make([]byte, 4)
			_, err = conn.Read(blockIdBin)
			if err != nil {
				conn.Close()
				if d.dPrintSleep(err, 1) {
					break BEGIN
				}
				continue
			}
			conn.Close()
			id := utils.BinToDec(blockIdBin)
			if id > maxBlockId || i == 0 {
				maxBlockId = id
				maxBlockIdHost = hosts[i]["host"]
				maxBlockIdUserId = utils.StrToInt64(hosts[i]["user_id"])
			}
			if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
				utils.Sleep(1)
				break BEGIN
			}
		}

		// получим наш текущий имеющийся номер блока
		// ждем, пока разлочится и лочим сами, чтобы не попасть в тот момент, когда данные из блока уже занесены в БД, а info_block еще не успел обновиться
		err, restart = d.dbLock()
		if restart {
			break BEGIN
		}
		if err != nil {
			if d.dPrintSleep(err, d.sleepTime) {
				break BEGIN
			}
			continue BEGIN
		}

		currentBlockId, err = d.Single("SELECT block_id FROM info_block").Int64()
		if err != nil {
			if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
				break BEGIN
			}
			continue
		}
		log.Info("currentBlockId", currentBlockId, "maxBlockId", maxBlockId)
		if maxBlockId <= currentBlockId {
			if d.unlockPrintSleep(utils.ErrInfo(errors.New("maxBlockId <= currentBlockId")), d.sleepTime) {
				break BEGIN
			}
			continue
		}

		fmt.Printf("\nnode: %s\n", maxBlockIdHost)

		// в цикле собираем блоки, пока не дойдем до максимального
		for blockId := currentBlockId + 1; blockId < maxBlockId+1; blockId++ {
			d.UpdMainLock()
			if CheckDaemonsRestart(chBreaker, chAnswer, GoroutineName) {
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				break BEGIN
			}
			variables, err := d.GetAllVariables()
			if err != nil {
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			// качаем тело блока с хоста maxBlockIdHost
			binaryBlock, err := utils.GetBlockBody(maxBlockIdHost, blockId, dataTypeBlockBody, nodeHost)

			if len(binaryBlock) == 0 {
				// баним на 1 час хост, который дал нам пустой блок, хотя должен был дать все до максимального
				// для тестов убрал, потом вставить.
				//nodes_ban ($db, $max_block_id_user_id, substr($binary_block, 0, 512)."\n".__FILE__.', '.__LINE__.', '. __FUNCTION__.', '.__CLASS__.', '. __METHOD__);
				//p.NodesBan(maxBlockIdUserId, "len(binaryBlock) == 0")
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			binaryBlockFull := binaryBlock
			utils.BytesShift(&binaryBlock, 1) // уберем 1-й байт - тип (блок/тр-я)
			// распарсим заголовок блока
			blockData := utils.ParseBlockHeader(&binaryBlock)
			log.Info("blockData: %v, blockId: %v", blockData, blockId)

			// если существуют глючная цепочка, тот тут мы её проигнорируем
			badBlocks_, err := d.Single("SELECT bad_blocks FROM config").Bytes()
			if err != nil {
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}
			badBlocks := make(map[int64]string)
			if len(badBlocks_) > 0 {
				err = json.Unmarshal(badBlocks_, &badBlocks)
				if err != nil {
					if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
			}
			if badBlocks[blockData.BlockId] == string(utils.BinToHex(blockData.Sign)) {
				d.NodesBan(maxBlockIdUserId, fmt.Sprintf("bad_block = %v => %v", blockData.BlockId, badBlocks[blockData.BlockId]))
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}

			// размер блока не может быть более чем max_block_size
			if currentBlockId > 1 {
				if int64(len(binaryBlock)) > variables.Int64["max_block_size"] {
					d.NodesBan(maxBlockIdUserId, fmt.Sprintf(`len(binaryBlock) > variables.Int64["max_block_size"]  %v > %v`, len(binaryBlock), variables.Int64["max_block_size"]))
					if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
			}

			if blockData.BlockId != blockId {
				d.NodesBan(maxBlockIdUserId, fmt.Sprintf(`blockData.BlockId != blockId  %v > %v`, blockData.BlockId, blockId))
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}

			// нам нужен хэш предыдущего блока, чтобы проверить подпись
			prevBlockHash := ""
			if blockId > 1 {
				prevBlockHash, err = d.Single("SELECT hash FROM block_chain WHERE id = ?", blockId-1).String()
				if err != nil {
					if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				prevBlockHash = string(utils.BinToHex([]byte(prevBlockHash)))
			} else {
				prevBlockHash = "0"
			}
			first := false
			if blockId == 1 {
				first = true
			}
			// нам нужен меркель-рут текущего блока
			mrklRoot, err := utils.GetMrklroot(binaryBlock, variables, first)
			if err != nil {
				d.NodesBan(maxBlockIdUserId, fmt.Sprintf(`%v`, err))
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}

			// публичный ключ того, кто этот блок сгенерил
			nodePublicKey, err := d.GetNodePublicKey(blockData.UserId)
			if err != nil {
				if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
					break BEGIN
				}
				continue BEGIN
			}

			// SIGN от 128 байта до 512 байт. Подпись от TYPE, BLOCK_ID, PREV_BLOCK_HASH, TIME, USER_ID, LEVEL, MRKL_ROOT
			forSign := fmt.Sprintf("0,%v,%v,%v,%v,%v,%s", blockData.BlockId, prevBlockHash, blockData.Time, blockData.UserId, blockData.Level, mrklRoot)

			// проверяем подпись
			if !first {
				_, err = utils.CheckSign([][]byte{nodePublicKey}, forSign, blockData.Sign, true)
			}

			// качаем предыдущие блоки до тех пор, пока отличается хэш предыдущего.
			// другими словами, пока подпись с prevBlockHash будет неверной, т.е. пока что-то есть в $error
			if err != nil {
				log.Error("%v", utils.ErrInfo(err))
				if blockId < 1 {
					if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				// нужно привести данные в нашей БД в соответствие с данными у того, у кого качаем более свежий блок
				//func (p *Parser) GetOldBlocks (userId, blockId int64, host string, hostUserId int64, goroutineName, getBlockScriptName, addNodeHost string) error {
				err := parser.GetOldBlocks(blockData.UserId, blockId-1, maxBlockIdHost, maxBlockIdUserId, GoroutineName, dataTypeBlockBody, nodeHost)
				if err != nil {
					log.Error("%v", err)
					d.NodesBan(maxBlockIdUserId, fmt.Sprintf(`blockId: %v / %v`, blockId, err))
					if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}

			} else {

				log.Info("plug found blockId=%v\n", blockId)

				// получим наши транзакции в 1 бинарнике, просто для удобства
				var transactions []byte
				utils.WriteSelectiveLog("SELECT data FROM transactions WHERE verified = 1 AND used = 0")
				rows, err := d.Query("SELECT data FROM transactions WHERE verified = 1 AND used = 0")
				if err != nil {
					utils.WriteSelectiveLog(err)
					if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				for rows.Next() {
					var data []byte
					err = rows.Scan(&data)
					utils.WriteSelectiveLog(utils.BinToHex(data))
					if err != nil {
						rows.Close()
						if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
							break BEGIN
						}
						continue BEGIN
					}
					transactions = append(transactions, utils.EncodeLengthPlusData(data)...)
				}
				rows.Close()
				if len(transactions) > 0 {
					// отмечаем, что эти тр-ии теперь нужно проверять по новой
					utils.WriteSelectiveLog("UPDATE transactions SET verified = 0 WHERE verified = 1 AND used = 0")
					affect, err := d.ExecSqlGetAffect("UPDATE transactions SET verified = 0 WHERE verified = 1 AND used = 0")
					if err != nil {
						utils.WriteSelectiveLog(err)
						if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
							break BEGIN
						}
						continue BEGIN
					}
					utils.WriteSelectiveLog("affect: " + utils.Int64ToStr(affect))
					// откатываем по фронту все свежие тр-ии
					parser.BinaryData = transactions
					err = parser.ParseDataRollbackFront(false)
					if err != nil {
						utils.Sleep(1)
						continue BEGIN
					}
				}

				err = parser.RollbackTransactionsTestblock(true)
				if err != nil {
					if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
				err = d.ExecSql("DELETE FROM testblock")
				if err != nil {
					if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
			}

			// теперь у нас в таблицах всё тоже самое, что у нода, у которого качаем блок
			// и можем этот блок проверить и занести в нашу БД
			parser.BinaryData = binaryBlockFull
			err = parser.ParseDataFull()
			if err == nil {
				err = parser.InsertIntoBlockchain()
				if err != nil {
					if d.unlockPrintSleep(utils.ErrInfo(err), d.sleepTime) {
						break BEGIN
					}
					continue BEGIN
				}
			}
			// начинаем всё с начала уже с другими нодами. Но у нас уже могут быть новые блоки до $block_id, взятые от нода, которого с в итоге мы баним
			if err != nil {
				d.NodesBan(maxBlockIdUserId, fmt.Sprintf(`blockId: %v / %v`, blockId, err))
				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)
}