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 }
func (p *Parser) ParseDataLite() error { p.dataPre() if p.dataType != 0 { // парсим только блоки return utils.ErrInfo(fmt.Errorf("incorrect dataType")) } var err error p.Variables, err = p.GetAllVariables() if err != nil { return utils.ErrInfo(err) } err = p.ParseBlock() if err != nil { return utils.ErrInfo(err) } if len(p.BinaryData) > 0 { i := 0 for { transactionSize := utils.DecodeLength(&p.BinaryData) if len(p.BinaryData) == 0 { return utils.ErrInfo(fmt.Errorf("empty BinaryData")) } // отчекрыжим одну транзакцию от списка транзакций transactionBinaryData := utils.BytesShift(&p.BinaryData, transactionSize) transactionBinaryDataFull := transactionBinaryData p.TxHash = utils.Md5(transactionBinaryData) p.TxSlice, err = p.ParseTransaction(&transactionBinaryData) 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("%v", err) return utils.ErrInfo(err_.(error)) } p.TxMap["md5hash"] = utils.Md5(transactionBinaryDataFull) p.TxMapArr = append(p.TxMapArr, p.TxMap) //p.TxMapsArr = append(p.TxMapsArr, p.TxMaps) if len(p.BinaryData) == 0 { break } i++ } } return nil }
/** Обработка данных (блоков или транзакций), пришедших с гейта. Только проверка. */ func (p *Parser) ParseDataGate(onlyTx bool) error { var err error p.dataPre() p.TxIds = []string{} p.Variables, err = p.GetAllVariables() if err != nil { return utils.ErrInfo(err) } transactionBinaryData := p.BinaryData var transactionBinaryDataFull []byte // если это транзакции (type>0), а не блок (type==0) if p.dataType > 0 { // проверим, есть ли такой тип тр-ий if len(consts.TxTypes[p.dataType]) == 0 { return p.ErrInfo("Incorrect tx type " + utils.IntToStr(p.dataType)) } log.Debug("p.dataType %v", p.dataType) transactionBinaryData = append(utils.DecToBin(int64(p.dataType), 1), transactionBinaryData...) transactionBinaryDataFull = transactionBinaryData // нет ли хэша этой тр-ии у нас в БД? err = p.CheckLogTx(transactionBinaryDataFull) if err != nil { return p.ErrInfo(err) } p.TxHash = utils.Md5(transactionBinaryData) // преобразуем бинарные данные транзакции в массив p.TxSlice, err = p.ParseTransaction(&transactionBinaryData) if err != nil { return p.ErrInfo(err) } log.Debug("p.TxSlice", p.TxSlice) if len(p.TxSlice) < 3 { return p.ErrInfo(errors.New("len(p.TxSlice) < 3")) } // время транзакции может быть немного больше, чем время на ноде. // у нода может быть просто не настроено время. // время транзакции используется только для борьбы с атаками вчерашними транзакциями. // А т.к. мы храним хэши в log_transaction за 36 часов, то боятся нечего. curTime := utils.Time() if utils.BytesToInt64(p.TxSlice[2])-consts.MAX_TX_FORW > curTime || utils.BytesToInt64(p.TxSlice[2]) < curTime-consts.MAX_TX_BACK { return p.ErrInfo(errors.New("incorrect tx time")) } // $this->transaction_array[3] могут подсунуть пустой if !utils.CheckInputData(p.TxSlice[3], "bigint") { return p.ErrInfo(errors.New("incorrect user id")) } } // если это блок if p.dataType == 0 { txCounter := make(map[int64]int64) // если есть $only_tx=true, то значит идет восстановление уже проверенного блока и заголовок не требуется if !onlyTx { err = p.ParseBlock() if err != nil { return p.ErrInfo(err) } // проверим данные, указанные в заголовке блока err = p.CheckBlockHeader() if err != nil { return p.ErrInfo(err) } } log.Debug("onlyTx", onlyTx) // если в ходе проверки тр-ий возникает ошибка, то вызываем откатчик всех занесенных тр-ий. Эта переменная для него p.fullTxBinaryData = p.BinaryData var txForRollbackTo []byte if len(p.BinaryData) > 0 { for { transactionSize := utils.DecodeLength(&p.BinaryData) if len(p.BinaryData) == 0 { return utils.ErrInfo(fmt.Errorf("empty BinaryData")) } // отчекрыжим одну транзакцию от списка транзакций transactionBinaryData := utils.BytesShift(&p.BinaryData, transactionSize) transactionBinaryDataFull = transactionBinaryData // добавляем взятую тр-ию в набор тр-ий для RollbackTo, в котором пойдем в обратном порядке txForRollbackTo = append(txForRollbackTo, utils.EncodeLengthPlusData(transactionBinaryData)...) // нет ли хэша этой тр-ии у нас в БД? err = p.CheckLogTx(transactionBinaryDataFull) if err != nil { p.RollbackTo(txForRollbackTo, true, false) return p.ErrInfo(err) } p.TxHash = utils.Md5(transactionBinaryData) p.TxSlice, err = p.ParseTransaction(&transactionBinaryData) log.Debug("p.TxSlice %s", p.TxSlice) if err != nil { p.RollbackTo(txForRollbackTo, true, false) return p.ErrInfo(err) } var userId int64 // txSlice[3] могут подсунуть пустой if len(p.TxSlice) > 3 { if !utils.CheckInputData(p.TxSlice[3], "int64") { return utils.ErrInfo(fmt.Errorf("empty user_id")) } else { userId = utils.BytesToInt64(p.TxSlice[3]) } } else { return utils.ErrInfo(fmt.Errorf("empty user_id")) } // считаем по каждому юзеру, сколько в блоке от него транзакций txCounter[userId]++ // чтобы 1 юзер не смог прислать дос-блок размером в 10гб, который заполнит своими же транзакциями if txCounter[userId] > p.Variables.Int64["max_block_user_transactions"] { p.RollbackTo(txForRollbackTo, true, false) return utils.ErrInfo(fmt.Errorf("max_block_user_transactions")) } // проверим, есть ли такой тип тр-ий _, ok := consts.TxTypes[utils.BytesToInt(p.TxSlice[1])] if !ok { return utils.ErrInfo(fmt.Errorf("nonexistent type")) } p.TxMap = map[string][]byte{} // для статы p.TxIds = append(p.TxIds, string(p.TxSlice[1])) MethodName := consts.TxTypes[utils.BytesToInt(p.TxSlice[1])] log.Debug("MethodName", MethodName+"Init") err_ := utils.CallMethod(p, MethodName+"Init") if _, ok := err_.(error); ok { log.Debug("error: %v", err) p.RollbackTo(txForRollbackTo, true, true) return utils.ErrInfo(err_.(error)) } log.Debug("MethodName", MethodName+"Front") err_ = utils.CallMethod(p, MethodName+"Front") if _, ok := err_.(error); ok { log.Debug("error: %v", err) p.RollbackTo(txForRollbackTo, true, true) return utils.ErrInfo(err_.(error)) } // пишем хэш тр-ии в лог err = p.InsertInLogTx(transactionBinaryDataFull, utils.BytesToInt64(p.TxMap["time"])) if err != nil { return utils.ErrInfo(err) } if len(p.BinaryData) == 0 { break } } } } else { // Оперативные транзакции MethodName := consts.TxTypes[p.dataType] log.Debug("MethodName", MethodName+"Init") err_ := utils.CallMethod(p, MethodName+"Init") if _, ok := err_.(error); ok { return utils.ErrInfo(err_.(error)) } log.Debug("MethodName", MethodName+"Front") err_ = utils.CallMethod(p, MethodName+"Front") if _, ok := err_.(error); ok { return utils.ErrInfo(err_.(error)) } // пишем хэш тр-ии в лог err = p.InsertInLogTx(transactionBinaryDataFull, utils.BytesToInt64(p.TxMap["time"])) if err != nil { return utils.ErrInfo(err) } } return nil }
/** * Занесение данных из блока в БД * используется только в testblock_is_ready */ func (p *Parser) ParseDataFront() error { p.TxIds = []string{} p.dataPre() if p.dataType == 0 { // инфа о предыдущем блоке (т.е. последнем занесенном) err := p.GetInfoBlock() if err != nil { return p.ErrInfo(err) } utils.WriteSelectiveLog("DELETE FROM transactions WHERE used=1") affect, err := p.ExecSqlGetAffect("DELETE FROM transactions WHERE used = 1") if err != nil { utils.WriteSelectiveLog(err) return p.ErrInfo(err) } utils.WriteSelectiveLog("affect: " + utils.Int64ToStr(affect)) // разбор блока err = p.ParseBlock() if err != nil { return utils.ErrInfo(err) } p.Variables, err = p.GetAllVariables() if err != nil { return utils.ErrInfo(err) } //меркель рут нужен для updblockinfo() p.MrklRoot, err = utils.GetMrklroot(p.BinaryData, p.Variables, false) if err != nil { return utils.ErrInfo(err) } if len(p.BinaryData) > 0 { for { transactionSize := utils.DecodeLength(&p.BinaryData) if len(p.BinaryData) == 0 { return utils.ErrInfo(fmt.Errorf("empty BinaryData")) } // отчекрыжим одну транзакцию от списка транзакций transactionBinaryData := utils.BytesShift(&p.BinaryData, transactionSize) transactionBinaryDataFull := transactionBinaryData p.TxHash = utils.Md5(transactionBinaryData) log.Debug("p.TxHash", p.TxHash) p.TxSlice, err = p.ParseTransaction(&transactionBinaryData) log.Debug("p.TxSlice", p.TxSlice) if err != nil { return utils.ErrInfo(err) } // txSlice[3] могут подсунуть пустой if len(p.TxSlice) > 3 { if !utils.CheckInputData(p.TxSlice[3], "int64") { return utils.ErrInfo(fmt.Errorf("empty user_id")) } } else { return utils.ErrInfo(fmt.Errorf("empty user_id")) } // проверим, есть ли такой тип тр-ий _, ok := consts.TxTypes[utils.BytesToInt(p.TxSlice[1])] if !ok { return utils.ErrInfo(fmt.Errorf("nonexistent type")) } p.TxMap = map[string][]byte{} // для статы p.TxIds = append(p.TxIds, string(p.TxSlice[1])) MethodName := consts.TxTypes[utils.BytesToInt(p.TxSlice[1])] log.Debug("MethodName", MethodName+"Init") err_ := utils.CallMethod(p, MethodName+"Init") if _, ok := err_.(error); ok { log.Debug("error: %v", err) return utils.ErrInfo(err_.(error)) } log.Debug("MethodName", MethodName) err_ = utils.CallMethod(p, MethodName) if _, ok := err_.(error); ok { log.Debug("error: %v", err) return utils.ErrInfo(err_.(error)) } utils.WriteSelectiveLog("UPDATE transactions SET used=1 WHERE hex(hash) = " + string(utils.Md5(transactionBinaryDataFull))) affect, err := p.ExecSqlGetAffect("UPDATE transactions SET used=1 WHERE hex(hash) = ?", utils.Md5(transactionBinaryDataFull)) if err != nil { utils.WriteSelectiveLog(err) return utils.ErrInfo(err) } utils.WriteSelectiveLog("affect: " + utils.Int64ToStr(affect)) // даем юзеру понять, что его тр-ия попала в блок err = p.ExecSql("UPDATE transactions_status SET block_id = ? WHERE hex(hash) = ?", p.BlockData.BlockId, utils.Md5(transactionBinaryDataFull)) if err != nil { return utils.ErrInfo(err) } if len(p.BinaryData) == 0 { break } } } p.UpdBlockInfo() p.InsertIntoBlockchain() } else { return utils.ErrInfo(fmt.Errorf("incorrect type")) } return nil }
/** фронт. проверка + занесение данных из блока в таблицы и info_block */ func (p *Parser) ParseDataFull() error { p.TxIds = []string{} p.dataPre() if p.dataType != 0 { // парсим только блоки return utils.ErrInfo(fmt.Errorf("incorrect dataType")) } var err error p.Variables, err = p.GetAllVariables() if err != nil { return utils.ErrInfo(err) } //if len(p.BinaryData) > 500000 { // ioutil.WriteFile("block-"+string(utils.DSha256(p.BinaryData)), p.BinaryData, 0644) //} err = p.ParseBlock() if err != nil { return utils.ErrInfo(err) } // проверим данные, указанные в заголовке блока err = p.CheckBlockHeader() if err != nil { return utils.ErrInfo(err) } utils.WriteSelectiveLog("DELETE FROM transactions WHERE used = 1") afect, err := p.ExecSqlGetAffect("DELETE FROM transactions WHERE used = 1") if err != nil { utils.WriteSelectiveLog(err) return utils.ErrInfo(err) } utils.WriteSelectiveLog("afect: " + utils.Int64ToStr(afect)) txCounter := make(map[int64]int64) p.fullTxBinaryData = p.BinaryData var txForRollbackTo []byte if len(p.BinaryData) > 0 { for { // обработка тр-ий может занять много времени, нужно отметиться p.UpdDaemonTime(p.GoroutineName) p.halfRollback = false log.Debug("&p.BinaryData", p.BinaryData) transactionSize := utils.DecodeLength(&p.BinaryData) if len(p.BinaryData) == 0 { return utils.ErrInfo(fmt.Errorf("empty BinaryData")) } // отчекрыжим одну транзакцию от списка транзакций //log.Debug("++p.BinaryData=%x\n", p.BinaryData) //log.Debug("transactionSize", transactionSize) transactionBinaryData := utils.BytesShift(&p.BinaryData, transactionSize) transactionBinaryDataFull := transactionBinaryData //ioutil.WriteFile("/tmp/dctx", transactionBinaryDataFull, 0644) //ioutil.WriteFile("/tmp/dctxhash", utils.Md5(transactionBinaryDataFull), 0644) // добавляем взятую тр-ию в набор тр-ий для RollbackTo, в котором пойдем в обратном порядке txForRollbackTo = append(txForRollbackTo, utils.EncodeLengthPlusData(transactionBinaryData)...) //log.Debug("transactionBinaryData: %x\n", transactionBinaryData) //log.Debug("txForRollbackTo: %x\n", txForRollbackTo) err = p.CheckLogTx(transactionBinaryDataFull) if err != nil { p.RollbackTo(txForRollbackTo, true, false) return utils.ErrInfo(err) } utils.WriteSelectiveLog("UPDATE transactions SET used=1 WHERE hex(hash) = " + string(utils.Md5(transactionBinaryDataFull))) affect, err := p.ExecSqlGetAffect("UPDATE transactions SET used=1 WHERE hex(hash) = ?", utils.Md5(transactionBinaryDataFull)) if err != nil { utils.WriteSelectiveLog(err) utils.WriteSelectiveLog("RollbackTo") p.RollbackTo(txForRollbackTo, true, false) return utils.ErrInfo(err) } utils.WriteSelectiveLog("affect: " + utils.Int64ToStr(affect)) //log.Debug("transactionBinaryData", transactionBinaryData) p.TxHash = utils.Md5(transactionBinaryData) log.Debug("p.TxHash %s", p.TxHash) p.TxSlice, err = p.ParseTransaction(&transactionBinaryData) log.Debug("p.TxSlice %v", p.TxSlice) if err != nil { p.RollbackTo(txForRollbackTo, true, false) return err } if p.BlockData.BlockId > 1 { var userId int64 // txSlice[3] могут подсунуть пустой if len(p.TxSlice) > 3 { if !utils.CheckInputData(p.TxSlice[3], "int64") { return utils.ErrInfo(fmt.Errorf("empty user_id")) } else { userId = utils.BytesToInt64(p.TxSlice[3]) } } else { return utils.ErrInfo(fmt.Errorf("empty user_id")) } // считаем по каждому юзеру, сколько в блоке от него транзакций txCounter[userId]++ // чтобы 1 юзер не смог прислать дос-блок размером в 10гб, который заполнит своими же транзакциями if txCounter[userId] > p.Variables.Int64["max_block_user_transactions"] { p.RollbackTo(txForRollbackTo, true, false) return utils.ErrInfo(fmt.Errorf("max_block_user_transactions")) } } // время в транзакции не может быть больше, чем на MAX_TX_FORW сек времени блока // и время в транзакции не может быть меньше времени блока -24ч. if utils.BytesToInt64(p.TxSlice[2])-consts.MAX_TX_FORW > p.BlockData.Time || utils.BytesToInt64(p.TxSlice[2]) < p.BlockData.Time-consts.MAX_TX_BACK { p.RollbackTo(txForRollbackTo, true, false) return utils.ErrInfo(fmt.Errorf("incorrect transaction time")) } // проверим, есть ли такой тип тр-ий _, ok := consts.TxTypes[utils.BytesToInt(p.TxSlice[1])] if !ok { return utils.ErrInfo(fmt.Errorf("nonexistent type")) } p.TxMap = map[string][]byte{} // для статы p.TxIds = append(p.TxIds, string(p.TxSlice[1])) MethodName := consts.TxTypes[utils.BytesToInt(p.TxSlice[1])] log.Debug("MethodName", MethodName+"Init") err_ := utils.CallMethod(p, MethodName+"Init") if _, ok := err_.(error); ok { log.Error("error: %v", err) return utils.ErrInfo(err_.(error)) } log.Debug("MethodName", MethodName+"Front") err_ = utils.CallMethod(p, MethodName+"Front") if _, ok := err_.(error); ok { log.Error("error: %v", err_) p.RollbackTo(txForRollbackTo, true, false) return utils.ErrInfo(err_.(error)) } log.Debug("MethodName", MethodName) err_ = utils.CallMethod(p, MethodName) if _, ok := err_.(error); ok { log.Error("error: %v", err) return utils.ErrInfo(err_.(error)) } // даем юзеру понять, что его тр-ия попала в блок p.ExecSql("UPDATE transactions_status SET block_id = ? WHERE hex(hash) = ?", p.BlockData.BlockId, utils.Md5(transactionBinaryDataFull)) // Тут было time(). А значит если бы в цепочке блоков были блоки в которых были бы одинаковые хэши тр-ий, то ParseDataFull вернул бы error err = p.InsertInLogTx(transactionBinaryDataFull, utils.BytesToInt64(p.TxMap["time"])) if err != nil { return utils.ErrInfo(err) } if len(p.BinaryData) == 0 { break } } } p.UpdBlockInfo() return nil }
func MakeTest(txSlice [][]byte, blockData *utils.BlockData, txType string, testType string) error { db := DbConn() parser := new(dcparser.Parser) parser.DCDB = db parser.TxSlice = txSlice parser.BlockData = blockData parser.TxHash = []byte("111111111111111") parser.Variables, _ = db.GetAllVariables() // делаем снимок БД в виде хэшей до начала тестов hashesStart, err := AllHashes(db) if err != nil { return err } //fmt.Println("dcparser."+txType+"Init") err0 := utils.CallMethod(parser, txType+"Init") if i, ok := err0.(error); ok { fmt.Println(err0.(error), i) return err0.(error) } if testType == "work_and_rollback" { err0 = utils.CallMethod(parser, txType) if i, ok := err0.(error); ok { fmt.Println(err0.(error), i) return err0.(error) } //fmt.Println("-------------------") // узнаем, какие таблицы были затронуты в результате выполнения основного метода hashesMiddle, err := AllHashes(db) if err != nil { return utils.ErrInfo(err) } var tables []string //fmt.Println("hashesMiddle", hashesMiddle) //fmt.Println("hashesStart", hashesStart) for table, hash := range hashesMiddle { if hash != hashesStart[table] { tables = append(tables, table) } } fmt.Println("tables", tables) // rollback err0 := utils.CallMethod(parser, txType+"Rollback") if i, ok := err0.(error); ok { fmt.Println(err0.(error), i) return err0.(error) } // сраниим хэши, которые были до начала и те, что получились после роллбэка hashesEnd, err := AllHashes(db) if err != nil { return utils.ErrInfo(err) } for table, hash := range hashesEnd { if hash != hashesStart[table] { fmt.Println("ERROR in table ", table) } } } else if (len(os.Args) > 1 && os.Args[1] == "w") || testType == "work" { err0 = utils.CallMethod(parser, txType) if i, ok := err0.(error); ok { fmt.Println(err0.(error), i) return err0.(error) } } else if (len(os.Args) > 1 && os.Args[1] == "r") || testType == "rollback" { err0 = utils.CallMethod(parser, txType+"Rollback") if i, ok := err0.(error); ok { fmt.Println(err0.(error), i) return err0.(error) } } return nil }
func MakeFrontTest(transactionArray [][]byte, time int64, dataForSign string, txType string, userId int64, MY_PREFIX string, blockId int64) error { db := DbConn() priv, pub := genKeys() nodeArr := []string{"new_admin", "votes_node_new_miner", "NewPct"} var binSign []byte if utils.InSliceString(txType, nodeArr) { err := db.ExecSql("UPDATE my_node_keys SET private_key = ?", priv) if err != nil { return utils.ErrInfo(err) } err = db.ExecSql("UPDATE miners_data SET node_public_key = [hex] WHERE user_id = ?", pub, userId) if err != nil { return utils.ErrInfo(err) } k, err := db.GetNodePrivateKey(MY_PREFIX) if err != nil { return utils.ErrInfo(err) } fmt.Println("k", k) privateKey, err := utils.MakePrivateKey(k) if err != nil { return utils.ErrInfo(err) } //fmt.Println("privateKey.PublicKey", privateKey.PublicKey) //fmt.Println("privateKey.D", privateKey.D) //fmt.Printf("privateKey.N %x\n", privateKey.N) //fmt.Println("privateKey.Public", privateKey.Public()) binSign, err = rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA1, utils.HashSha1(dataForSign)) //nodePublicKey, err := db.GetNodePublicKey(userId) //fmt.Println("nodePublicKey", nodePublicKey) //if err != nil { // return utils.ErrInfo(err) //} //CheckSignResult, err := utils.CheckSign([][]byte{nodePublicKey}, dataForSign, binSign, true); //fmt.Printf("binSign: %x\n", binSign) //fmt.Println("err", err) //fmt.Println("CheckSignResult", CheckSignResult) } else { err := db.ExecSql("UPDATE my_keys SET private_key = ?", priv) if err != nil { return utils.ErrInfo(err) } err = db.ExecSql("UPDATE users SET public_key_0 = [hex]", pub) if err != nil { return utils.ErrInfo(err) } k, err := db.GetPrivateKey(MY_PREFIX) privateKey, err := utils.MakePrivateKey(k) if err != nil { return utils.ErrInfo(err) } binSign, err = rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA1, utils.HashSha1(dataForSign)) binSign = utils.EncodeLengthPlusData(binSign) } //fmt.Println("HashSha1", utils.HashSha1(dataForSign)) //fmt.Printf("binSign %x\n", binSign) //fmt.Println("dataForSign", dataForSign) transactionArray = append(transactionArray, binSign) parser := new(dcparser.Parser) parser.DCDB = db parser.GoroutineName = "test" parser.TxSlice = transactionArray parser.BlockData = &utils.BlockData{BlockId: blockId, Time: time, UserId: userId} parser.TxHash = []byte("111111111111111") parser.Variables, _ = parser.DCDB.GetAllVariables() 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 }