Beispiel #1
0
/*
 * Stress test the curve. If the '-num' argument is given, runs the loop
 * |num| times and prints the resulting X-coordinate. Otherwise runs the test
 * the default number of times and compares against the expected result.
 */
int setup_tests(void)
{
    const char *p;

    if (!atoi64(NUM_REPEATS, &num_repeats)) {
        TEST_error("Cannot parse " NUM_REPEATS);
        return 0;
    }
    /*
     * TODO(openssl-team): code under test/ should be able to reuse the option
     * parsing framework currently in apps/.
     */
    p = test_get_option_argument("-num");
    if (p != NULL) {
        if (!atoi64(p, &num_repeats)
                || num_repeats < 0)
            return 0;
        print_mode = 1;
    }

#ifndef OPENSSL_NO_EC
    ADD_TEST(test_curve);
#endif
    return 1;
}
Beispiel #2
0
// Convert a cobol argument to a C integer. Make allowances for different
// data types, since constants get passed as DISPLAY (NSU or NTS) and fields
// should be BINARY (NBS or NBU)
static ISC_UINT64 CvtArgToInt(const argument_entry *arg)
{
	ISC_UINT64		temp;
	char			*stemp;
	char			sign;

	switch (arg->a_type)
	{
	case 1:														// NSU
		temp = (ISC_UINT64)atoi64((char *)CobolToString(arg));
		break;
	case 2:														// NTS
		stemp = (char *)CobolToString(arg);
		sign = *(stemp + strlen(stemp) - 1);
		*(stemp + strlen(stemp) - 1) = '\0';
		if (sign == '-')
			temp = (ISC_UINT64)((ISC_INT64)atoi64(stemp) * -1);
		else
			temp = atoi64(stemp);
		break;
	case 11:													// NBS
	case 12:													// NBU
		temp = CvtCobolToInt(arg->a_address,
							 (ISC_USHORT)arg->a_length,
							 arg->a_type);
		break;
	default:
		temp = 0;
		break;
	}

	return (temp);
}
Beispiel #3
0
/*
** Return a prepared statement which, when stepped, will return in its
** first column the blob associated with segment zId.  If zId begins with
** 'r' then it is a rowid of a %_segdir entry.  Otherwise it is a
** %_segment entry.
*/
static sqlite3_stmt *prepareToGetSegment(
    sqlite3 *db,         /* The database */
    const char *zTab,    /* The FTS3/4 table name */
    const char *zId      /* ID of the segment to open */
) {
    sqlite3_stmt *pStmt;
    if( zId[0]=='r' ) {
        pStmt = prepare(db, "SELECT root FROM '%q_segdir' WHERE rowid=%lld",
                        zTab, atoi64(zId+1));
    } else {
        pStmt = prepare(db, "SELECT block FROM '%q_segments' WHERE blockid=%lld",
                        zTab, atoi64(zId));
    }
    return pStmt;
}
Beispiel #4
0
	///値の加算
	///@note Available since 2.0.0.
	bool server_type::api_hincrby(client_type * client)
	{
		auto current = client->get_time();
		auto & key = *client->get_keys()[0];
		auto & field = *client->get_fields()[0];
		auto & increment = client->get_argument(3);
		bool is_valid = true;
		int64_t intval = atoi64(increment, is_valid);
		if (!is_valid) {
			throw std::runtime_error("ERR increment is not valid integer");
		}
		auto db = writable_db(client);
		std::shared_ptr<type_hash> hash = db->get_hash(key, current);
		std::string oldval = "0";
		if (hash) {
			auto r = hash->hget(field);
			if (r.second) {
				oldval = r.first;
			}
		}
		int64_t newval = incrby(oldval, intval);
		std::string newstr = format("%"PRId64, newval);
		if (!hash) {
			hash.reset(new type_hash(current));
			hash->hset(field, newstr);
			db->replace(key, hash);
		} else {
			hash->hset(field, newstr);
			hash->update(current);
		}
		client->response_integer(newval);
		return true;
	}
Beispiel #5
0
int64_t ArgsManager::GetArg(const std::string& strArg, int64_t nDefault)
{
    LOCK(cs_args);
    if (mapArgs.count(strArg))
        return atoi64(mapArgs[strArg]);
    return nDefault;
}
Beispiel #6
0
int64_t ArgsManager::GetArg(const std::string& strArg, int64_t nDefault) const
{
    LOCK(cs_args);
    auto it = mapArgs.find(strArg);
    if (it != mapArgs.end()) return atoi64(it->second);
    return nDefault;
}
Beispiel #7
0
int64_t ArgsManager::GetArg(const std::string& strArg, int64_t nDefault) const
{
    if (IsArgNegated(strArg)) return 0;
    std::pair<bool,std::string> found_res = ArgsManagerHelper::GetArg(*this, strArg);
    if (found_res.first) return atoi64(found_res.second);
    return nDefault;
}
Beispiel #8
0
static void MutateTxVersion(CMutableTransaction& tx, const std::string& cmdVal)
{
    int64_t newVersion = atoi64(cmdVal);
    if (newVersion < 1 || newVersion > CTransaction::MAX_STANDARD_VERSION)
        throw std::runtime_error("Invalid TX version requested");

    tx.nVersion = (int) newVersion;
}
Beispiel #9
0
static void MutateTxLocktime(CMutableTransaction& tx, const std::string& cmdVal)
{
    int64_t newLocktime = atoi64(cmdVal);
    if (newLocktime < 0LL || newLocktime > 0xffffffffLL)
        throw std::runtime_error("Invalid TX locktime requested");

    tx.nLockTime = (unsigned int) newLocktime;
}
Beispiel #10
0
inline void check_header(const std::string &name, const std::string &value,
                         std::string &content_type, boost::int64_t &content_length,
                         std::string &location)
{
    if (headers_equal(name, "Content-Type"))
        content_type = value;
    else if (headers_equal(name, "Content-Length"))
        content_length = atoi64(value.c_str());
    else if (headers_equal(name, "Location"))
        location = value;
}
Beispiel #11
0
/*
** Print the content of a doclist.  The segment or segdir-root is
** identified by azExtra[0].  If the first character of azExtra[0]
** is 'r' then the remainder is the integer rowid of the %_segdir entry.
** If the first character of azExtra[0] is not 'r' then, then all of
** azExtra[0] is an integer which is the block number.  The offset
** into the segment is identified by azExtra[1].  The size of the doclist
** is azExtra[2].
**
** If the --raw option is present in azExtra, then a hex dump is provided.
** Otherwise a decoding is shown.
*/
static void showDoclist(sqlite3 *db, const char *zTab){
  const unsigned char *aData;
  sqlite3_int64 offset, nData;
  sqlite3_stmt *pStmt;

  offset = atoi64(azExtra[1]);
  nData = atoi64(azExtra[2]);
  pStmt = prepareToGetSegment(db, zTab, azExtra[0]);
  if( sqlite3_step(pStmt)!=SQLITE_ROW ){
    sqlite3_finalize(pStmt);
    return;
  }
  aData = sqlite3_column_blob(pStmt, 0);
  printf("Doclist at %s offset %lld of size %lld bytes:\n",
         azExtra[0], offset, nData);
  if( findOption("raw", 0, 0)!=0 ){
    printBlob(aData+offset, nData);
  }else{
    decodeDoclist(aData+offset, nData);
  }
  sqlite3_finalize(pStmt);
}
Beispiel #12
0
/*
 * Allocate target specific config data, and link them to table.
 * This function is called only when, flags is not READONLY and
 * therefore we can add things to pdev list. This should not a
 * problem because this routine is called only from dm_table_load_ioctl.
 * @argv[0] is name,
 * @argv[1] is physical data offset.
 */
static int
dm_target_linear_init(dm_dev_t * dmv, void **target_config, char *params)
{
	dm_target_linear_config_t *tlc;
	dm_pdev_t *dmp;

	char **ap, *argv[3];

	if (params == NULL)
		return EINVAL;

	/*
	 * Parse a string, containing tokens delimited by white space,
	 * into an argument vector
	 */
	for (ap = argv; ap < &argv[2] &&
	    (*ap = strsep(&params, " \t")) != NULL;) {
		if (**ap != '\0')
			ap++;
	}

	aprint_debug("Linear target init function called %s--%s!!\n",
	    argv[0], argv[1]);

	/* XXX: temp hack */
	if (argv[0] == NULL)
		return EINVAL;

	/* Insert dmp to global pdev list */
	if ((dmp = dm_pdev_insert(argv[0])) == NULL)
		return ENOENT;

	if ((tlc = kmalloc(sizeof(dm_target_linear_config_t), M_DMLINEAR, M_WAITOK))
	    == NULL)
		return ENOMEM;

	tlc->pdev = dmp;
	tlc->offset = 0;	/* default settings */

	/* Check user input if it is not leave offset as 0. */
	tlc->offset = atoi64(argv[1]);

	*target_config = tlc;

	dmv->dev_type = DM_LINEAR_DEV;

	return 0;
}
Beispiel #13
0
bool ParseMoney(const char* pszIn, int64& nRet)
{
    string strWhole;
    int64 nCents = 0;
    const char* p = pszIn;
    while (isspace(*p))
        p++;
    for (; *p; p++)
    {
        if (*p == ',' && p > pszIn && isdigit(p[-1]) && isdigit(p[1]) && isdigit(p[2]) && isdigit(p[3]) && !isdigit(p[4]))
            continue;
        if (*p == '.')
        {
            p++;
            if (isdigit(*p))
            {
                nCents = 10 * (*p++ - '0');
                if (isdigit(*p))
                    nCents += (*p++ - '0');
            }
            break;
        }
        if (isspace(*p))
            break;
        if (!isdigit(*p))
            return false;
        strWhole.insert(strWhole.end(), *p);
    }
    for (; *p; p++)
        if (!isspace(*p))
            return false;
    if (strWhole.size() > 14)
        return false;
    if (nCents < 0 || nCents > 99)
        return false;
    int64 nWhole = atoi64(strWhole);
    int64 nPreValue = nWhole * 100 + nCents;
    int64 nValue = nPreValue * CENT;
    if (nValue / CENT != nPreValue)
        return false;
    if (nValue / COIN != nWhole)
        return false;
    nRet = nValue;
    return true;
}
Beispiel #14
0
bool ParseMoney(const char* pszIn, int64& nRet)
{
    string strWhole;
    int64 nUnits = 0;
    const char* p = pszIn;
    while (isspace(*p))
        p++;
    for (; *p; p++)
    {
        if (*p == ',' && p > pszIn && isdigit(p[-1]) && isdigit(p[1]) && isdigit(p[2]) && isdigit(p[3]) && !isdigit(p[4]))
            continue;
        if (*p == '.')
        {
            p++;
            int64 nMult = CENT*10;
            while (isdigit(*p) && (nMult > 0))
            {
                nUnits += nMult * (*p++ - '0');
                nMult /= 10;
            }
            break;
        }
        if (isspace(*p))
            break;
        if (!isdigit(*p))
            return false;
        strWhole.insert(strWhole.end(), *p);
    }
    for (; *p; p++)
        if (!isspace(*p))
            return false;
    if (strWhole.size() > 14)
        return false;
    if (nUnits < 0 || nUnits > COIN)
        return false;
    int64 nWhole = atoi64(strWhole);
    int64 nValue = nWhole*COIN + nUnits;

    nRet = nValue;
    return true;
}
bool ParseMoney(const char* pszIn, CAmount& nRet)
{
    std::string strWhole;
    int64_t nUnits = 0;
    const char* p = pszIn;
    while (isspace(*p))
        p++;
    for (; *p; p++)
    {
        if (*p == '.')
        {
            p++;
            int64_t nMult = CENT*10;
            while (isdigit(*p) && (nMult > 0))
            {
                nUnits += nMult * (*p++ - '0');
                nMult /= 10;
            }
            break;
        }
        if (isspace(*p))
            break;
        if (!isdigit(*p))
            return false;
        strWhole.insert(strWhole.end(), *p);
    }
    for (; *p; p++)
        if (!isspace(*p))
            return false;
    if (strWhole.size() > 10) // guard against 63 bit overflow
        return false;
    if (nUnits < 0 || nUnits > COIN)
        return false;
    int64_t nWhole = atoi64(strWhole);
    CAmount nValue = nWhole*COIN + nUnits;

    nRet = nValue;
    return true;
}
Beispiel #16
0
CDECL EXPORT int setvar(char *varname, char *value)
{
    VARMAP *p;

    for (p=varmap; p->name!=NULL; p++)
    {
        if (strcmp(p->name,varname)==0)
        {
            if (p->type==VT_INTEGER)
            {
                int64 v = atoi64(value);
                if (v>=(int64)p->min && v<=(int64)p->max)
                {
                    *(int64*)(p->addr) = v;
                    return 1;
                }
                else return 0;
            }
            else if (p->type==VT_DOUBLE)
            {
                double v = atof(value);
                if (v>=p->min && v<=p->max)
                {
                    *(double*)(p->addr) = v;
                    return 1;
                }
                else return 0;
            }
            else if (p->type==VT_STRING)
            {
                strncpy((char*)(p->addr),value,(unsigned)p->min-1);
                return 1;
            }
        }
    }
    return 0;
}
char *gld_loadHndl::read_object_prop(char *buffer, size_t len){
	//wchar_t wbuff[1024];
	//char tbuff[1024];
	char *rand_ptr = NULL;
	char *rand_mode_ptr = NULL;
	char *unit_ptr = NULL;
	double realval = 0.0;
	UNIT *unit=NULL;
	SAXParseException *e = NULL;
	void *addr = object_get_addr(obj, propname); /* get the & to set later */
	if(this->obj == NULL){
		sprintf(errmsg, "Null object pointer in read_object_prop(%s)", buffer);
		return errmsg;	//	no object
	}
	if(this->prop == NULL){
		if (strcmp(propname, "parent")==0){
			if (strcmp(propname, "root")==0){
				obj->parent = NULL;
			} else {
				add_unresolved(obj,PT_object,(void*)&obj->parent,oclass,buffer,"XML",42,UR_RANKS); 
			}
		} else if (strcmp(propname, "rank")==0){
			obj->rank = atoi(buffer);
		} else if (strcmp(propname, "clock")==0){
			obj->clock = atoi64(buffer);
		} else if (strcmp(propname, "latitude")==0){
			obj->latitude = load_latitude(buffer);
		} else if (strcmp(propname, "longitude")==0){
			obj->longitude = load_longitude(buffer);
		} else if (strcmp(propname, "in")==0){
			obj->in_svc = convert_to_timestamp(buffer);
		} else if (strcmp(propname, "out")==0){
			obj->out_svc = convert_to_timestamp(buffer);
		} else {
			sprintf(errmsg, "Null property pointer in read_object_prop(%s)", buffer);
			return errmsg;
		}
		return NULL;
	}
	//	determine property type
	switch(prop->ptype){
		case PT_double:
			//	scan for "random"
			if(strncmp("random.", buffer, 7) == 0){
				char temp[256];
				char *modep = NULL;
				double first = 0.0, second = 0.0;
				RANDOMTYPE rt;
				strncpy(temp, buffer, 256);
				modep = strtok(temp+7, "(");
				if(modep == NULL){
					//output_error("XML_Load: misformed random() value");
					load_state = false;
					sprintf(errmsg, "Misformed random() value in read_object_prop(%s)", buffer);
					return errmsg;
				}
				rt = random_type(modep);
				if(rt == 0){
					//output_message("XML_Load: '%s' ~ %s is not a valid random distribution", buffer, modep);
					load_state = false;
					sprintf(errmsg, "Invalid random distribution in read_object_prop(%s)", buffer);
					return errmsg;
				} else {
					first = atof(strtok(NULL, ","));
					second = atof(strtok(NULL, ")"));
					realval = random_value(rt, first, second);
				}
				if(strlen(strchr(buffer, ')')+1) > 0){ /* look for units */
					unit = unit_find(strchr(buffer, ')') + 2);
					if (unit!=NULL && prop->unit!=NULL && unit_convert_ex(unit,prop->unit,&realval)==0){
						sprintf(errmsg, "Cannot convert units from %s to %s in read_object_prop(%s)", unit->name,prop->unit->name, buffer);
						load_state = false;
						return errmsg;
					}
				}
			} else {
				unit_ptr = NULL;
				realval = strtod(buffer, &unit_ptr);
				if(unit_ptr != NULL){
					while(*unit_ptr == ' ') ++unit_ptr;
					unit = unit_find(unit_ptr);
					if(strlen(unit_ptr) > 0){
						if (unit!=NULL && prop->unit!=NULL && unit_convert_ex(unit,prop->unit,&realval)==0){
							sprintf(errmsg, "Cannot convert units from %s to %s in read_object_prop(%s)", unit->name,prop->unit->name, buffer);
							load_state = false;
							return errmsg;
						}
					}
				}
			}
			/* if((unit_ptr != NULL) && (*unit_ptr != '\0')){;} */
			if(object_set_double_by_name(obj, propname, realval) == 0){
				sprintf(errmsg, "Could not set \"%s\" to %f in read_object_prop(%s)", propname, realval, buffer);
				load_state = false;
				return errmsg;
			} else {
				return NULL; /* success */
			}
			break;
		case PT_object:
			if(add_unresolved(obj,PT_object,(void*)addr,oclass,buffer,"XML",42,UR_NONE) == NULL){
				sprintf(errmsg, "Failure with add_unresolved() in read_object_prop(%s)", buffer);
				return errmsg;
			}
			break;
		default:
			if(prop->ptype < _PT_LAST){	//	set value by name
				if (object_set_value_by_name(obj, propname, buffer)==0)	{
					//output_error("XML_Load: property %s of %s:%s could not be set to '%s'", propname, obj->oclass->name, obj->id, buffer);
					sprintf(errmsg, "Property %s of %s:%i could not be set to \"%s\" in read_object_prop()", propname, obj->oclass->name, obj->id, buffer);
					load_state = false;
					return errmsg;
				} else {
					;
				}
			} else {
				sprintf(errmsg, "Invalid property id = %i in read_object_prop(%s)", prop->ptype, buffer);
				return errmsg;
			}
	}
	return 0;
}
Beispiel #18
0
	void type_string::to_int()
	{
		if (!int_type) {
			int_value = atoi64(string_value, int_type);
		}
	}
Beispiel #19
0
// 转换监管协议
char * PConvert::convert_lprov( const string &key, const string &seqid, const string &val , int &len, string &areacode )
{
	MapString map ;
	if ( ! parse_jkpt_value( val, map ) ) {
		OUT_ERROR( NULL, 0, NULL, "parse data %s failed", val.c_str() ) ;
		return NULL ;
	}

	string stype ;
	if ( ! get_map_string( map , "TYPE", stype ) ) {
		OUT_ERROR( NULL, 0, NULL, "get data %s type failed", val.c_str() ) ;
		return NULL ;
	}

	// 取得省域ID
	if ( ! get_map_string( map, "AREA_CODE", areacode ) ) {
		OUT_ERROR( NULL, 0, NULL, "get area code failed, %s", val.c_str() ) ;
		return NULL ;
	}

	char *buf = NULL ;
	// AREA_CODE:省代码,CARNO:车牌颜色_车牌号,ACCESS_CODE:运营商接入码,TYPE:XXX,k1:v1...
	if ( stype == "D_PLAT" ) {

		string sval ;
		// 如果为平台查岗消息处理
		if ( get_map_string( map, "PLATQUERY" , sval ) ) {
			// 查岗对象的类型(1:当前连接的下级平台,2:下级平台所属单一业户,3:下级平台所属所有业户)|查岗对象的ID|信息ID|应答内容"
			vector<string> vec ;
			if ( ! splitvector( sval, vec, "|" , 0 ) ) {
				OUT_ERROR( NULL, 0, areacode.c_str(), "split vector failed, sval %s" , sval.c_str() ) ;
				return NULL ;
			}
			// 如果拆分个数小于四个则直接返回
			if ( vec.size() < 4 ) {
				OUT_ERROR( NULL, 0, areacode.c_str(), "split vector param too less, value %s" , sval.c_str() ) ;
				return NULL ;
			}

			int dlen  = 0 ;
			char *ptr = _pEnv->GetMsgCache()->GetData( key.c_str(), dlen , false ) ;
			if ( ptr == NULL ) {
				OUT_ERROR( NULL, 0, areacode.c_str(), "get plat msg failed , key %s" , key.c_str() ) ;
				return NULL ;
			}

			string content = vec[3] ;
			CBase64 base;
			if ( base.Decode( content.c_str(), content.length() ) ) {
				content = base.GetBuffer() ;
			}
			len = sizeof(UpPlatformMsgPostQueryAck)   + content.length() + sizeof(Footer) ;
			buf = new char[len+1] ;

			// 处理平台查岗的消息
			UpPlatformMsgPostQueryAck *rsp = (UpPlatformMsgPostQueryAck *) ptr ;
			rsp->header.msg_len 			  = ntouv32( len ) ;
			rsp->up_platform_msg.data_length  = ntouv32( sizeof(UpPlatformMsgpostqueryData) + content.length() ) ;
			rsp->up_platform_post.msg_len     = ntouv32( content.length() ) ;
			rsp->up_platform_post.object_type = atoi( vec[0].c_str() ) ;
			safe_memncpy( rsp->up_platform_post.object_id, vec[1].c_str(), sizeof(rsp->up_platform_post.object_id) ) ;
			rsp->up_platform_post.info_id     = ntouv32( atoi(vec[2].c_str()) ) ;

			memcpy( buf, rsp, sizeof(UpPlatformMsgPostQueryAck) ) ;
			memcpy( buf+sizeof(UpPlatformMsgPostQueryAck) , content.c_str(), content.length() ) ;

			Footer footer ;
			memcpy( buf+sizeof(UpPlatformMsgPostQueryAck) + content.length(), &footer, sizeof(footer) ) ;

			OUT_PRINT( NULL, 0, areacode.c_str(), "platquery message %s", content.c_str() ) ;

			return buf ;
		}

		// 平台间消息
		if ( get_map_string( map, "PLATMSG", sval ) ) {
			// 从缓存中取数据, 针对平台间消息和平台查岗暂时不回收资源
			char *ptr = _pEnv->GetMsgCache()->GetData( key.c_str(), len , false ) ;
			if ( buf == NULL ) {
				OUT_ERROR( NULL, 0, areacode.c_str(), "get msg from cache failed, key %s", key.c_str() ) ;
				return NULL ;
			}

			// 重新拷贝处理
			buf = new char[len+1] ;
			memset( buf, 0, len + 1 ) ;
			memcpy( buf, ptr, len ) ;

			// 处理平台消息的ID
			UpPlatFormMsgInfoAck *ack = (UpPlatFormMsgInfoAck *) buf ;
			ack->info_id = ntouv32( atoi(sval.c_str()) ) ;

			return buf ;
		}

	} else {  // 除平台查岗处理
		string macid ;
		// 取得车牌颜色和车牌号
		if ( ! get_map_string( map, "CARNO" , macid ) ) {
			OUT_ERROR( NULL, 0, areacode.c_str(), "get carno failed, %s", val.c_str() ) ;
			return NULL ;
		}

		unsigned char carcolor = 0 ;
		string carnum ;
		// 通过MACID取得车颜色和车牌号
		if ( ! get_carinfobymacid( macid, carcolor, carnum ) ) {
			OUT_ERROR( NULL, 0, areacode.c_str(), "get car color and car num by macid failed, %d" , macid.c_str() ) ;
			return NULL ;
		}

		string sval ;
		// 如果为报警业务
		if ( stype == "D_WARN" ) {
			// 报警督办
			if ( get_map_string( map, "WARNTODO", sval ) ) {
				buf = _pEnv->GetMsgCache()->GetData( key.c_str(), len ) ;
				if ( buf == NULL ) {
					OUT_ERROR( NULL, 0, areacode.c_str(), "get msg data failed, key %s, macid %s" , key.c_str(), macid.c_str() ) ;
					return NULL ;
				}
				UpWarnMsgUrgeTodoAck *rsp = ( UpWarnMsgUrgeTodoAck *) buf ;
				rsp->result = atoi(sval.c_str()) ;
				return buf ;
			}

			// 处理上报报警
			if ( get_map_string( map, "WARNINFO" , sval ) ) {
				// 报警信息来源(1:车载终端,2:企业监控平台,3:政府监管平台,9:其它)|报警类型(详见5.3“报警类型编码表”)|报警时间(UTC时间格式)|信息ID|报警信息内容
				vector<string>  vec ;
				// 处理所有逗号分割处理
				if ( ! splitvector( sval , vec, "|" , 0 ) ) {
					OUT_ERROR( NULL, 0, areacode.c_str(), "WARNINFO split vector error, key %s, macid %s, value: %s" , key.c_str(), macid.c_str() , sval.c_str() ) ;
					return false ;
				}
				if ( vec.size() < 5 ) {
					OUT_ERROR( NULL, 0, areacode.c_str(), "WARNINFO arg too less error, key %s, macid %s, value: %s" , key.c_str(), macid.c_str() , sval.c_str() ) ;
					return false ;
				}

				int nlen = vec[4].length() ;
				len = sizeof(UpWarnMsgAdptInfoHeader) + sizeof(UpWarnMsgAdptInfoBody) + nlen + sizeof(Footer) ;

				UpWarnMsgAdptInfoHeader req ;
				req.header.msg_len  = ntouv32( len ) ;  // 修正长度不正
				req.header.msg_type = ntouv16( UP_WARN_MSG ) ;
				req.header.msg_seq  = ntouv32( _seq_gen.get_next_seq() ) ;
				req.warn_msg_header.vehicle_color = carcolor ;
				safe_memncpy( req.warn_msg_header.vehicle_no, carnum.c_str(), sizeof(req.warn_msg_header.vehicle_no) ) ;
				req.warn_msg_header.data_type   = ntouv16( UP_WARN_MSG_ADPT_INFO ) ;
				req.warn_msg_header.data_length = ntouv32( sizeof(UpWarnMsgAdptInfoBody) + nlen ) ;

				UpWarnMsgAdptInfoBody body ;
				body.warn_src    = atoi( vec[0].c_str() ) ;
				body.warn_type   = ntouv16( atoi(vec[1].c_str()) ) ;
				body.warn_time   = ntouv64( atoi64(vec[2].c_str()) ) ;
				body.info_id     = ntouv32( atoi(vec[3].c_str()) ) ;
				body.info_length = ntouv32( nlen ) ;

				int offset = 0 ;
				buf = new char[len+1] ;
				memcpy( buf+offset, &req, sizeof(req) ) ;
				offset += sizeof(req) ;

				memcpy( buf+offset, &body, sizeof(body) ) ;
				offset += sizeof(body) ;

				memcpy( buf+offset, vec[4].c_str(), nlen ) ;
				offset += nlen ;

				Footer footer ;
				memcpy( buf+offset, &footer, sizeof(footer) ) ;

				return buf ;
			}

			// 处理主动上报报警结果
			if ( get_map_string( map, "UPWARN", sval ) ) {
				// 报警信息ID|报警处理结果(0:处理中,1:已处理完毕,2:不作处理,3:将来处理)
				size_t pos = sval.find( "|" ) ;
				if ( pos == string::npos ) {
					OUT_ERROR( NULL, 0, areacode.c_str(), "upwarn result command error, value: %s" , val.c_str() ) ;
					return NULL ;
				}

				// 组装主动上报处理理结果的数据包
				UpWarnMsgAdptTodoInfo req ;
				req.header.msg_len  = ntouv32( sizeof(UpWarnMsgAdptTodoInfo) ) ;
				req.header.msg_type = ntouv16( UP_WARN_MSG ) ;
				req.header.msg_seq  = ntouv32( _seq_gen.get_next_seq() ) ;
				req.warn_msg_header.vehicle_color = carcolor ;
				safe_memncpy( req.warn_msg_header.vehicle_no, carnum.c_str(), sizeof(req.warn_msg_header.vehicle_no) ) ;
				req.warn_msg_header.data_type   = ntouv16( UP_WARN_MSG_ADPT_TODO_INFO ) ;
				req.warn_msg_header.data_length = ntouv32( sizeof(WarnMsgAdptTodoInfoBody) ) ;
				req.warn_msg_body.info_id 		= ntouv32( atoi( sval.c_str() ) ) ;
				req.warn_msg_body.result  		= atoi( sval.substr(pos+1).c_str() ) ;

				len = sizeof(req) ;
				buf = new char[len+1] ;
				memcpy( buf, &req, sizeof(req) ) ;

				return buf ;
			}
		} else if ( stype == "D_MESG" ) {
			// 如果下发申请交换车辆信息
			if ( get_map_string( map, "MONITORSTARTUP" , sval ) ) {
				// 开始时间(UTC时间格式)|结束时间(UTC时间格式)
				size_t pos = sval.find( "|" ) ;
				if ( pos == string::npos ) {
					OUT_ERROR( NULL, 0, areacode.c_str(), "down command error , value : %s" , val.c_str() ) ;
					return NULL ;
				}
				uint64 start = atoi64( sval.substr(0, pos).c_str() ) ;
				uint64 end   = atoi64( sval.substr( pos+1).c_str() ) ;

				UpExgMsgApplyForMonitorStartup req ;
				req.header.msg_len = ntouv32( sizeof(req) ) ;
				req.header.msg_seq = ntouv32( _seq_gen.get_next_seq() ) ;
				req.exg_msg_header.vehicle_color = carcolor ;
				safe_memncpy( req.exg_msg_header.vehicle_no, carnum.c_str(), sizeof(req.exg_msg_header.vehicle_no) ) ;
				req.exg_msg_header.data_length   = ntouv32( sizeof(uint64) * 2 ) ;
				req.start_time = ntouv64( start ) ;
				req.end_time   = ntouv64( end   ) ;

				len = sizeof(req) ;
				buf = new char[len+1] ;
				memcpy( buf, &req, sizeof(req) ) ;

				_pEnv->GetPasClient()->AddMacId2SeqId( UP_EXG_MSG_APPLY_FOR_MONITOR_STARTUP , macid.c_str(), seqid.c_str() ) ;

				return buf ;
			}

			// 结束车辆交换信息
			if ( get_map_string( map , "MONITOREND" , sval ) ) {

				UpExgMsgApplyForMonitorEnd  req ;
				req.header.msg_len = ntouv32( sizeof(req) ) ;
				req.header.msg_seq = ntouv32( _seq_gen.get_next_seq() ) ;
				req.exg_msg_header.vehicle_color = carcolor ;
				safe_memncpy( req.exg_msg_header.vehicle_no, carnum.c_str(), sizeof(req.exg_msg_header.vehicle_no) ) ;
				req.exg_msg_header.data_length   = ntouv32( 0 ) ;

				len = sizeof(req) ;
				buf = new char[len+1] ;
				memcpy( buf, &req, sizeof(req) ) ;

				_pEnv->GetPasClient()->AddMacId2SeqId( UP_EXG_MSG_APPLY_FOR_MONITOR_END , macid.c_str(), seqid.c_str() ) ;

				return buf ;
			}

			// 这是平台主动下发,还有一种平台自动下发情况,补发指定时间车辆信息
			if ( get_map_string( map, "HISGNSSDATA" , sval ) ) {
				// 开始时间(UTC时间格式)|结束时间(UTC时间格式)
				size_t pos = sval.find( "|" ) ;
				if ( pos == string::npos ) {
					OUT_ERROR( NULL, 0, areacode.c_str(), "down command error , value : %s" , val.c_str() ) ;
					return NULL ;
				}
				uint64 start = atoi64( sval.substr(0, pos).c_str() ) ;
				uint64 end   = atoi64( sval.substr( pos+1).c_str() ) ;

				UpExgApplyHisGnssDataReq req ;
				req.header.msg_len  = ntouv32( sizeof(req) ) ;
				req.header.msg_type = ntouv16( UP_EXG_MSG ) ;
				req.header.msg_seq  = ntouv32( _seq_gen.get_next_seq() ) ;
				req.exg_msg_header.vehicle_color = carcolor ;
				safe_memncpy( req.exg_msg_header.vehicle_no, carnum.c_str(), sizeof(req.exg_msg_header.vehicle_no) ) ;
				req.exg_msg_header.data_length   = ntouv32( sizeof(uint64) * 2 ) ;
				req.exg_msg_header.data_type	 = ntouv16( UP_EXG_MSG_APPLY_HISGNSSDATA_REQ ) ;
				req.start_time = ntouv64( start ) ;
				req.end_time   = ntouv64( end   ) ;

				len = sizeof(req) ;
				buf = new char[len+1] ;
				memcpy( buf, &req, sizeof(req) ) ;

				_pEnv->GetPasClient()->AddMacId2SeqId( UP_EXG_MSG_APPLY_HISGNSSDATA_REQ , macid.c_str(), seqid.c_str() ) ;

				return buf ;
			}

			// 处理历史数据上报
			size_t pos = val.find( "HISTORY" ) ;
			// 取得车辆的历史位数据情况
			if ( pos != string::npos ) {
				size_t end = val.find( "}" , pos+8 ) ;
				if ( end == string::npos || end < pos ){
					OUT_ERROR( NULL, 0, areacode.c_str(), "HISTORY split vector error, key %s, macid %s, value: %s" , key.c_str(), macid.c_str() , val.c_str() ) ;
					return false;
				}
				sval = val.substr( pos+8, end - pos - 8 ) ;
				vector<string>  vec ;
				// 处理所有逗号分割处理
				if ( ! splitvector( sval , vec, "|" , 0 ) ) {
					OUT_ERROR( NULL, 0, areacode.c_str(), "HISTORY split vector error, key %s, macid %s, value: %s" , key.c_str(), macid.c_str() , sval.c_str() ) ;
					return false ;
				}

				int nsize = vec.size() ;

				UpExgMsgHistoryHeader msg ;
				msg.header.msg_type = ntouv16( UP_EXG_MSG ) ;
				msg.header.msg_seq  = ntouv32( _seq_gen.get_next_seq() ) ;
				msg.exg_msg_header.vehicle_color = carcolor ;
				safe_memncpy( msg.exg_msg_header.vehicle_no, carnum.c_str(), sizeof(msg.exg_msg_header.vehicle_no) ) ;
				msg.exg_msg_header.data_type   = ntouv16(UP_EXG_MSG_HISTORY_LOCATION) ;

				DataBuffer dbuf ;

				unsigned char ncount = 0 ;
				for ( int i = 0; i < nsize; ++ i ) {
					MapString gpsmap ;
					if ( ! split2map( vec[i] , gpsmap ) ) {
						continue ;
					}
					GnssData gnssdata;
					if ( ! convert_gps_info( gpsmap, gnssdata ) ){
						continue ;
					}
					dbuf.writeBlock( &gnssdata, sizeof(GnssData) ) ;
					++ ncount ;
				}

				len = sizeof(msg) + sizeof(char) + ncount*sizeof(GnssData) + sizeof(Footer) ;
				msg.exg_msg_header.data_length = ntouv32( sizeof(char) + ncount*sizeof(GnssData) ) ;
				msg.header.msg_len			   = ntouv32( len ) ;

				buf = new char[len+1] ;

				int offset = 0 ;
				memcpy( buf, &msg, sizeof(msg) ) ;
				offset += sizeof(msg) ;

				memcpy( buf+offset , &ncount, sizeof(char) )  ;
				offset += sizeof(char) ;

				memcpy( buf+offset, dbuf.getBuffer(), dbuf.getLength() ) ;
				offset += dbuf.getLength() ;

				Footer footer ;
				memcpy( buf+offset, &footer, sizeof(footer) ) ;

				return buf ;
			}

			// 接入广州809精简版监管,提交车辆静态数据,子业务类型为DOWN_EXG_MSG_CAR_INFO
			if (get_map_string(map, "U_BASE", sval)) {
				CBase64 base64;
				if( ! base64.Decode(sval.c_str(), sval.length())) {
					OUT_ERROR( NULL, 0, areacode.c_str(), "base64 decode error, value : %s" , val.c_str() ) ;
					return NULL;
				}

				len = sizeof(DownExgMsgCarInfoHeader) + base64.GetLength() + sizeof(Footer);
				buf = new char[len + 1];

				DownExgMsgCarInfoHeader msg;
				msg.header.msg_len  = ntouv32( len ) ;
				msg.header.msg_seq  = ntouv32( _seq_gen.get_next_seq() ) ;
				msg.header.msg_type = ntouv16( UP_EXG_MSG );
				msg.exg_msg_header.vehicle_color = carcolor ;
				strncpy(msg.exg_msg_header.vehicle_no, carnum.c_str(),	sizeof(msg.exg_msg_header.vehicle_no));
				msg.exg_msg_header.data_type = ntouv16(DOWN_EXG_MSG_CAR_INFO);
				msg.exg_msg_header.data_length = ntouv32(base64.GetLength());

				int msgpos = 0;
				memcpy(buf + msgpos, &msg, sizeof(DownExgMsgCarInfoHeader));
				msgpos += sizeof(DownExgMsgCarInfoHeader);

				memcpy(buf + msgpos, base64.GetBuffer(), base64.GetLength());
				msgpos += base64.GetLength();

				Footer footer ;
				memcpy( buf + msgpos, &footer, sizeof(footer) ) ;

				return buf ;
			}
		}
	}
	return NULL ;
}
Beispiel #20
0
static UniValue getblocktemplate(const JSONRPCRequest& request)
{
    if (request.fHelp || request.params.size() > 1)
        throw std::runtime_error(
            "getblocktemplate ( TemplateRequest )\n"
            "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n"
            "It returns data needed to construct a block to work on.\n"
            "For full specification, see BIPs 22, 23, 9, and 145:\n"
            "    https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki\n"
            "    https://github.com/bitcoin/bips/blob/master/bip-0023.mediawiki\n"
            "    https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n"
            "    https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki\n"

            "\nArguments:\n"
            "1. template_request         (json object, optional) A json object in the following spec\n"
            "     {\n"
            "       \"mode\":\"template\"    (string, optional) This must be set to \"template\", \"proposal\" (see BIP 23), or omitted\n"
            "       \"capabilities\":[     (array, optional) A list of strings\n"
            "           \"support\"          (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n"
            "           ,...\n"
            "       ],\n"
            "       \"rules\":[            (array, optional) A list of strings\n"
            "           \"support\"          (string) client side supported softfork deployment\n"
            "           ,...\n"
            "       ]\n"
            "     }\n"
            "\n"

            "\nResult:\n"
            "{\n"
            "  \"version\" : n,                    (numeric) The preferred block version\n"
            "  \"rules\" : [ \"rulename\", ... ],    (array of strings) specific block rules that are to be enforced\n"
            "  \"vbavailable\" : {                 (json object) set of pending, supported versionbit (BIP 9) softfork deployments\n"
            "      \"rulename\" : bitnumber          (numeric) identifies the bit number as indicating acceptance and readiness for the named softfork rule\n"
            "      ,...\n"
            "  },\n"
            "  \"vbrequired\" : n,                 (numeric) bit mask of versionbits the server requires set in submissions\n"
            "  \"previousblockhash\" : \"xxxx\",     (string) The hash of current highest block\n"
            "  \"transactions\" : [                (array) contents of non-coinbase transactions that should be included in the next block\n"
            "      {\n"
            "         \"data\" : \"xxxx\",             (string) transaction data encoded in hexadecimal (byte-for-byte)\n"
            "         \"txid\" : \"xxxx\",             (string) transaction id encoded in little-endian hexadecimal\n"
            "         \"hash\" : \"xxxx\",             (string) hash encoded in little-endian hexadecimal (including witness data)\n"
            "         \"depends\" : [                (array) array of numbers \n"
            "             n                          (numeric) transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is\n"
            "             ,...\n"
            "         ],\n"
            "         \"fee\": n,                    (numeric) difference in value between transaction inputs and outputs (in satoshis); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n"
            "         \"sigops\" : n,                (numeric) total SigOps cost, as counted for purposes of block limits; if key is not present, sigop cost is unknown and clients MUST NOT assume it is zero\n"
            "         \"weight\" : n,                (numeric) total transaction weight, as counted for purposes of block limits\n"
            "      }\n"
            "      ,...\n"
            "  ],\n"
            "  \"coinbaseaux\" : {                 (json object) data that should be included in the coinbase's scriptSig content\n"
            "      \"flags\" : \"xx\"                  (string) key name is to be ignored, and value included in scriptSig\n"
            "  },\n"
            "  \"coinbasevalue\" : n,              (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in satoshis)\n"
            "  \"coinbasetxn\" : { ... },          (json object) information for coinbase transaction\n"
            "  \"target\" : \"xxxx\",                (string) The hash target\n"
            "  \"mintime\" : xxx,                  (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n"
            "  \"mutable\" : [                     (array of string) list of ways the block template may be changed \n"
            "     \"value\"                          (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n"
            "     ,...\n"
            "  ],\n"
            "  \"noncerange\" : \"00000000ffffffff\",(string) A range of valid nonces\n"
            "  \"sigoplimit\" : n,                 (numeric) limit of sigops in blocks\n"
            "  \"sizelimit\" : n,                  (numeric) limit of block size\n"
            "  \"weightlimit\" : n,                (numeric) limit of block weight\n"
            "  \"curtime\" : ttt,                  (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
            "  \"bits\" : \"xxxxxxxx\",              (string) compressed target of next block\n"
            "  \"height\" : n                      (numeric) The height of the next block\n"
            "}\n"

            "\nExamples:\n"
            + HelpExampleCli("getblocktemplate", "{\"rules\": [\"segwit\"]}")
            + HelpExampleRpc("getblocktemplate", "{\"rules\": [\"segwit\"]}")
         );

    LOCK(cs_main);

    std::string strMode = "template";
    UniValue lpval = NullUniValue;
    std::set<std::string> setClientRules;
    int64_t nMaxVersionPreVB = -1;
    if (!request.params[0].isNull())
    {
        const UniValue& oparam = request.params[0].get_obj();
        const UniValue& modeval = find_value(oparam, "mode");
        if (modeval.isStr())
            strMode = modeval.get_str();
        else if (modeval.isNull())
        {
            /* Do nothing */
        }
        else
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
        lpval = find_value(oparam, "longpollid");

        if (strMode == "proposal")
        {
            const UniValue& dataval = find_value(oparam, "data");
            if (!dataval.isStr())
                throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal");

            CBlock block;
            if (!DecodeHexBlk(block, dataval.get_str()))
                throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");

            uint256 hash = block.GetHash();
            const CBlockIndex* pindex = LookupBlockIndex(hash);
            if (pindex) {
                if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
                    return "duplicate";
                if (pindex->nStatus & BLOCK_FAILED_MASK)
                    return "duplicate-invalid";
                return "duplicate-inconclusive";
            }

            CBlockIndex* const pindexPrev = chainActive.Tip();
            // TestBlockValidity only supports blocks built on the current Tip
            if (block.hashPrevBlock != pindexPrev->GetBlockHash())
                return "inconclusive-not-best-prevblk";
            CValidationState state;
            TestBlockValidity(state, Params(), block, pindexPrev, false, true);
            return BIP22ValidationResult(state);
        }

        const UniValue& aClientRules = find_value(oparam, "rules");
        if (aClientRules.isArray()) {
            for (unsigned int i = 0; i < aClientRules.size(); ++i) {
                const UniValue& v = aClientRules[i];
                setClientRules.insert(v.get_str());
            }
        } else {
            // NOTE: It is important that this NOT be read if versionbits is supported
            const UniValue& uvMaxVersion = find_value(oparam, "maxversion");
            if (uvMaxVersion.isNum()) {
                nMaxVersionPreVB = uvMaxVersion.get_int64();
            }
        }
    }

    if (strMode != "template")
        throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");

    if(!g_connman)
        throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");

    if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0)
        throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Bitcoin is not connected!");

    if (IsInitialBlockDownload())
        throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Bitcoin is downloading blocks...");

    static unsigned int nTransactionsUpdatedLast;

    if (!lpval.isNull())
    {
        // Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
        uint256 hashWatchedChain;
        std::chrono::steady_clock::time_point checktxtime;
        unsigned int nTransactionsUpdatedLastLP;

        if (lpval.isStr())
        {
            // Format: <hashBestChain><nTransactionsUpdatedLast>
            std::string lpstr = lpval.get_str();

            hashWatchedChain = ParseHashV(lpstr.substr(0, 64), "longpollid");
            nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64));
        }
        else
        {
            // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
            hashWatchedChain = chainActive.Tip()->GetBlockHash();
            nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
        }

        // Release the wallet and main lock while waiting
        LEAVE_CRITICAL_SECTION(cs_main);
        {
            checktxtime = std::chrono::steady_clock::now() + std::chrono::minutes(1);

            WAIT_LOCK(g_best_block_mutex, lock);
            while (g_best_block == hashWatchedChain && IsRPCRunning())
            {
                if (g_best_block_cv.wait_until(lock, checktxtime) == std::cv_status::timeout)
                {
                    // Timeout: Check transactions for update
                    if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
                        break;
                    checktxtime += std::chrono::seconds(10);
                }
            }
        }
        ENTER_CRITICAL_SECTION(cs_main);

        if (!IsRPCRunning())
            throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
        // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
    }

    const struct VBDeploymentInfo& segwit_info = VersionBitsDeploymentInfo[Consensus::DEPLOYMENT_SEGWIT];
    // If the caller is indicating segwit support, then allow CreateNewBlock()
    // to select witness transactions, after segwit activates (otherwise
    // don't).
    bool fSupportsSegwit = setClientRules.find(segwit_info.name) != setClientRules.end();

    // Update block
    static CBlockIndex* pindexPrev;
    static int64_t nStart;
    static std::unique_ptr<CBlockTemplate> pblocktemplate;
    // Cache whether the last invocation was with segwit support, to avoid returning
    // a segwit-block to a non-segwit caller.
    static bool fLastTemplateSupportsSegwit = true;
    if (pindexPrev != chainActive.Tip() ||
        (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5) ||
        fLastTemplateSupportsSegwit != fSupportsSegwit)
    {
        // Clear pindexPrev so future calls make a new block, despite any failures from here on
        pindexPrev = nullptr;

        // Store the pindexBest used before CreateNewBlock, to avoid races
        nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
        CBlockIndex* pindexPrevNew = chainActive.Tip();
        nStart = GetTime();
        fLastTemplateSupportsSegwit = fSupportsSegwit;

        // Create new block
        CScript scriptDummy = CScript() << OP_TRUE;
        pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy, fSupportsSegwit);
        if (!pblocktemplate)
            throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");

        // Need to update only after we know CreateNewBlock succeeded
        pindexPrev = pindexPrevNew;
    }
    assert(pindexPrev);
    CBlock* pblock = &pblocktemplate->block; // pointer for convenience
    const Consensus::Params& consensusParams = Params().GetConsensus();

    // Update nTime
    UpdateTime(pblock, consensusParams, pindexPrev);
    pblock->nNonce = 0;

    // NOTE: If at some point we support pre-segwit miners post-segwit-activation, this needs to take segwit support into consideration
    const bool fPreSegWit = (ThresholdState::ACTIVE != VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache));

    UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");

    UniValue transactions(UniValue::VARR);
    std::map<uint256, int64_t> setTxIndex;
    int i = 0;
    for (const auto& it : pblock->vtx) {
        const CTransaction& tx = *it;
        uint256 txHash = tx.GetHash();
        setTxIndex[txHash] = i++;

        if (tx.IsCoinBase())
            continue;

        UniValue entry(UniValue::VOBJ);

        entry.pushKV("data", EncodeHexTx(tx));
        entry.pushKV("txid", txHash.GetHex());
        entry.pushKV("hash", tx.GetWitnessHash().GetHex());

        UniValue deps(UniValue::VARR);
        for (const CTxIn &in : tx.vin)
        {
            if (setTxIndex.count(in.prevout.hash))
                deps.push_back(setTxIndex[in.prevout.hash]);
        }
        entry.pushKV("depends", deps);

        int index_in_template = i - 1;
        entry.pushKV("fee", pblocktemplate->vTxFees[index_in_template]);
        int64_t nTxSigOps = pblocktemplate->vTxSigOpsCost[index_in_template];
        if (fPreSegWit) {
            assert(nTxSigOps % WITNESS_SCALE_FACTOR == 0);
            nTxSigOps /= WITNESS_SCALE_FACTOR;
        }
        entry.pushKV("sigops", nTxSigOps);
        entry.pushKV("weight", GetTransactionWeight(tx));

        transactions.push_back(entry);
    }

    UniValue aux(UniValue::VOBJ);
    aux.pushKV("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end()));

    arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);

    UniValue aMutable(UniValue::VARR);
    aMutable.push_back("time");
    aMutable.push_back("transactions");
    aMutable.push_back("prevblock");

    UniValue result(UniValue::VOBJ);
    result.pushKV("capabilities", aCaps);

    UniValue aRules(UniValue::VARR);
    UniValue vbavailable(UniValue::VOBJ);
    for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) {
        Consensus::DeploymentPos pos = Consensus::DeploymentPos(j);
        ThresholdState state = VersionBitsState(pindexPrev, consensusParams, pos, versionbitscache);
        switch (state) {
            case ThresholdState::DEFINED:
            case ThresholdState::FAILED:
                // Not exposed to GBT at all
                break;
            case ThresholdState::LOCKED_IN:
                // Ensure bit is set in block version
                pblock->nVersion |= VersionBitsMask(consensusParams, pos);
                // FALL THROUGH to get vbavailable set...
            case ThresholdState::STARTED:
            {
                const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
                vbavailable.pushKV(gbt_vb_name(pos), consensusParams.vDeployments[pos].bit);
                if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
                    if (!vbinfo.gbt_force) {
                        // If the client doesn't support this, don't indicate it in the [default] version
                        pblock->nVersion &= ~VersionBitsMask(consensusParams, pos);
                    }
                }
                break;
            }
            case ThresholdState::ACTIVE:
            {
                // Add to rules only
                const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
                aRules.push_back(gbt_vb_name(pos));
                if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
                    // Not supported by the client; make sure it's safe to proceed
                    if (!vbinfo.gbt_force) {
                        // If we do anything other than throw an exception here, be sure version/force isn't sent to old clients
                        throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Support for '%s' rule requires explicit client support", vbinfo.name));
                    }
                }
                break;
            }
        }
    }
    result.pushKV("version", pblock->nVersion);
    result.pushKV("rules", aRules);
    result.pushKV("vbavailable", vbavailable);
    result.pushKV("vbrequired", int(0));

    if (nMaxVersionPreVB >= 2) {
        // If VB is supported by the client, nMaxVersionPreVB is -1, so we won't get here
        // Because BIP 34 changed how the generation transaction is serialized, we can only use version/force back to v2 blocks
        // This is safe to do [otherwise-]unconditionally only because we are throwing an exception above if a non-force deployment gets activated
        // Note that this can probably also be removed entirely after the first BIP9 non-force deployment (ie, probably segwit) gets activated
        aMutable.push_back("version/force");
    }

    result.pushKV("previousblockhash", pblock->hashPrevBlock.GetHex());
    result.pushKV("transactions", transactions);
    result.pushKV("coinbaseaux", aux);
    result.pushKV("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue);
    result.pushKV("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast));
    result.pushKV("target", hashTarget.GetHex());
    result.pushKV("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1);
    result.pushKV("mutable", aMutable);
    result.pushKV("noncerange", "00000000ffffffff");
    int64_t nSigOpLimit = MAX_BLOCK_SIGOPS_COST;
    int64_t nSizeLimit = MAX_BLOCK_SERIALIZED_SIZE;
    if (fPreSegWit) {
        assert(nSigOpLimit % WITNESS_SCALE_FACTOR == 0);
        nSigOpLimit /= WITNESS_SCALE_FACTOR;
        assert(nSizeLimit % WITNESS_SCALE_FACTOR == 0);
        nSizeLimit /= WITNESS_SCALE_FACTOR;
    }
    result.pushKV("sigoplimit", nSigOpLimit);
    result.pushKV("sizelimit", nSizeLimit);
    if (!fPreSegWit) {
        result.pushKV("weightlimit", (int64_t)MAX_BLOCK_WEIGHT);
    }
    result.pushKV("curtime", pblock->GetBlockTime());
    result.pushKV("bits", strprintf("%08x", pblock->nBits));
    result.pushKV("height", (int64_t)(pindexPrev->nHeight+1));

    if (!pblocktemplate->vchCoinbaseCommitment.empty() && fSupportsSegwit) {
        result.pushKV("default_witness_commitment", HexStr(pblocktemplate->vchCoinbaseCommitment.begin(), pblocktemplate->vchCoinbaseCommitment.end()));
    }

    return result;
}
Beispiel #21
0
int64 GetArg(const std::string& strArg, int64 nDefault)
{
    if (mapArgs.count(strArg))
        return atoi64(mapArgs[strArg]);
    return nDefault;
}
Beispiel #22
0
UniValue gobject(const JSONRPCRequest& request)
{
    std::string strCommand;
    if (request.params.size() >= 1)
        strCommand = request.params[0].get_str();

    if (request.fHelp  ||
        (
#ifdef ENABLE_WALLET
         strCommand != "prepare" &&
#endif // ENABLE_WALLET
         strCommand != "vote-many" && strCommand != "vote-conf" && strCommand != "vote-name" && strCommand != "submit" && strCommand != "count" &&
         strCommand != "deserialize" && strCommand != "get" && strCommand != "getvotes" && strCommand != "getcurrentvotes" && strCommand != "list" && strCommand != "diff" &&
         strCommand != "check" ))
        throw std::runtime_error(
                "gobject \"command\"...\n"
                "Manage governance objects\n"
                "\nAvailable commands:\n"
                "  check              - Validate governance object data (proposal only)\n"
#ifdef ENABLE_WALLET
                "  prepare            - Prepare governance object by signing and creating tx\n"
#endif // ENABLE_WALLET
                "  submit             - Submit governance object to network\n"
                "  deserialize        - Deserialize governance object from hex string to JSON\n"
                "  count              - Count governance objects and votes (additional param: 'json' or 'all', default: 'json')\n"
                "  get                - Get governance object by hash\n"
                "  getvotes           - Get all votes for a governance object hash (including old votes)\n"
                "  getcurrentvotes    - Get only current (tallying) votes for a governance object hash (does not include old votes)\n"
                "  list               - List governance objects (can be filtered by signal and/or object type)\n"
                "  diff               - List differences since last diff\n"
                "  vote-name         - Vote on a governance object by masternode name (using masternode.conf setup)\n"
                "  vote-conf          - Vote on a governance object by masternode configured in syscoin.conf\n"
                "  vote-many          - Vote on a governance object by all masternodes (using masternode.conf setup)\n"
                );


    if(strCommand == "count") {
        std::string strMode{"json"};

        if (request.params.size() == 2) {
            strMode = request.params[1].get_str();
        }

        if (request.params.size() > 2 || (strMode != "json" && strMode != "all")) {
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Correct usage is 'gobject count ( \"json\"|\"all\" )'");
        }

        return strMode == "json" ? governance.ToJson() : governance.ToString();
    }
    /*
        ------ Example Governance Item ------

        gobject submit 6e622bb41bad1fb18e7f23ae96770aeb33129e18bd9efe790522488e580a0a03 0 1 1464292854 "beer-reimbursement" 5b5b22636f6e7472616374222c207b2270726f6a6563745f6e616d65223a20225c22626565722d7265696d62757273656d656e745c22222c20227061796d656e745f61646472657373223a20225c225879324c4b4a4a64655178657948726e34744744514238626a6876464564615576375c22222c2022656e645f64617465223a202231343936333030343030222c20226465736372697074696f6e5f75726c223a20225c227777772e646173687768616c652e6f72672f702f626565722d7265696d62757273656d656e745c22222c2022636f6e74726163745f75726c223a20225c22626565722d7265696d62757273656d656e742e636f6d2f3030312e7064665c22222c20227061796d656e745f616d6f756e74223a20223233342e323334323232222c2022676f7665726e616e63655f6f626a6563745f6964223a2037342c202273746172745f64617465223a202231343833323534303030227d5d5d1
    */

    // DEBUG : TEST DESERIALIZATION OF GOVERNANCE META DATA
    if(strCommand == "deserialize")
    {
        if (request.params.size() != 2) {
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Correct usage is 'gobject deserialize <data-hex>'");
        }

        std::string strHex = request.params[1].get_str();

        std::vector<unsigned char> v = ParseHex(strHex);
        std::string s(v.begin(), v.end());

        UniValue u(UniValue::VOBJ);
        u.read(s);

        return u.write().c_str();
    }

    // VALIDATE A GOVERNANCE OBJECT PRIOR TO SUBMISSION
    if(strCommand == "check")
    {
        if (request.params.size() != 2) {
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Correct usage is 'gobject check <data-hex>'");
        }

        // ASSEMBLE NEW GOVERNANCE OBJECT FROM USER PARAMETERS

        uint256 hashParent;

        int nRevision = 1;

        int64_t nTime = GetAdjustedTime();
        std::string strDataHex = request.params[1].get_str();

        CGovernanceObject govobj(hashParent, nRevision, nTime, uint256(), strDataHex);

        if(govobj.GetObjectType() == GOVERNANCE_OBJECT_PROPOSAL) {
            CProposalValidator validator(strDataHex);
            if(!validator.Validate())  {
                throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid proposal data, error messages:" + validator.GetErrorMessages());
            }
        }
        else {
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid object type, only proposals can be validated");
        }

        UniValue objResult(UniValue::VOBJ);

        objResult.push_back(Pair("Object status", "OK"));

        return objResult;
    }

#ifdef ENABLE_WALLET
    // PREPARE THE GOVERNANCE OBJECT BY CREATING A COLLATERAL TRANSACTION
    if(strCommand == "prepare")
    {
        if (!EnsureWalletIsAvailable(request.fHelp))
            return NullUniValue;

        if (request.params.size() != 5) {
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Correct usage is 'gobject prepare <parent-hash> <revision> <time> <data-hex>'");
        }

        // ASSEMBLE NEW GOVERNANCE OBJECT FROM USER PARAMETERS

        uint256 hashParent;

        // -- attach to root node (root node doesn't really exist, but has a hash of zero)
        if(request.params[1].get_str() == "0") {
            hashParent = uint256();
        } else {
            hashParent = ParseHashV(request.params[1], "fee-txid, parameter 1");
        }

        std::string strRevision = request.params[2].get_str();
        std::string strTime = request.params[3].get_str();
        int nRevision = atoi(strRevision);
        int64_t nTime = atoi64(strTime);
        std::string strDataHex = request.params[4].get_str();

        // CREATE A NEW COLLATERAL TRANSACTION FOR THIS SPECIFIC OBJECT

        CGovernanceObject govobj(hashParent, nRevision, nTime, uint256(), strDataHex);

        if(govobj.GetObjectType() == GOVERNANCE_OBJECT_PROPOSAL) {
            CProposalValidator validator(strDataHex);
            if(!validator.Validate())  {
                throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid proposal data, error messages:" + validator.GetErrorMessages());
            }
        }

        if(govobj.GetObjectType() == GOVERNANCE_OBJECT_TRIGGER) {
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Trigger objects need not be prepared (however only masternodes can create them)");
        }

        if(govobj.GetObjectType() == GOVERNANCE_OBJECT_WATCHDOG) {
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Watchdogs are deprecated");
        }
		{
			LOCK(cs_main);
			std::string strError = "";
			if (!govobj.IsValidLocally(strError, false))
				throw JSONRPCError(RPC_INTERNAL_ERROR, "Governance object is not valid - " + govobj.GetHash().ToString() + " - " + strError);
		}
        EnsureWalletIsUnlocked();

        CWalletTx wtx;
        if(!pwalletMain->GetBudgetSystemCollateralTX(wtx, govobj.GetHash(), govobj.GetMinCollateralFee(), false)) {
            throw JSONRPCError(RPC_INTERNAL_ERROR, "Error making collateral transaction for governance object. Please check your wallet balance and make sure your wallet is unlocked.");
        }

        // -- make our change address
        CReserveKey reservekey(pwalletMain);
        // -- send the tx to the network
        CValidationState state;
        if (!pwalletMain->CommitTransaction(wtx, reservekey, g_connman.get(), state, NetMsgType::TX)) {
            throw JSONRPCError(RPC_INTERNAL_ERROR, "CommitTransaction failed! Reason given: " + state.GetRejectReason());
        }

        DBG( std::cout << "gobject: prepare "
             << " GetDataAsPlainString = " << govobj.GetDataAsPlainString()
             << ", hash = " << govobj.GetHash().GetHex()
             << ", txidFee = " << wtx.GetHash().GetHex()
             << std::endl; );

        return wtx.GetHash().ToString();
    }
Beispiel #23
0
UniValue getblocktemplate(const JSONRPCRequest& request)
{
    if (request.fHelp || request.params.size() > 1)
        throw std::runtime_error(
            "getblocktemplate ( TemplateRequest )\n"
            "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n"
            "It returns data needed to construct a block to work on.\n"
            "For full specification, see BIPs 22, 23, and 9:\n"
            "    https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki\n"
            "    https://github.com/bitcoin/bips/blob/master/bip-0023.mediawiki\n"
            "    https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n"

            "\nArguments:\n"
            "1. template_request         (json object, optional) A json object in the following spec\n"
            "     {\n"
            "       \"mode\":\"template\"    (string, optional) This must be set to \"template\", \"proposal\" (see BIP 23), or omitted\n"
            "       \"capabilities\":[     (array, optional) A list of strings\n"
            "           \"support\"          (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n"
            "           ,...\n"
            "       ],\n"
            "       \"rules\":[            (array, optional) A list of strings\n"
            "           \"support\"          (string) client side supported softfork deployment\n"
            "           ,...\n"
            "       ]\n"
            "     }\n"
            "\n"

            "\nResult:\n"
            "{\n"
            "  \"capabilities\" : [ \"capability\", ... ],    (array of strings) specific client side supported features\n"
            "  \"version\" : n,                    (numeric) The preferred block version\n"
            "  \"rules\" : [ \"rulename\", ... ],    (array of strings) specific block rules that are to be enforced\n"
            "  \"vbavailable\" : {                 (json object) set of pending, supported versionbit (BIP 9) softfork deployments\n"
            "      \"rulename\" : bitnumber          (numeric) identifies the bit number as indicating acceptance and readiness for the named softfork rule\n"
            "      ,...\n"
            "  },\n"
            "  \"vbrequired\" : n,                 (numeric) bit mask of versionbits the server requires set in submissions\n"
            "  \"previousblockhash\" : \"xxxx\",     (string) The hash of current highest block\n"
            "  \"transactions\" : [                (array) contents of non-coinbase transactions that should be included in the next block\n"
            "      {\n"
            "         \"data\" : \"xxxx\",             (string) transaction data encoded in hexadecimal (byte-for-byte)\n"
            "         \"hash\" : \"xxxx\",             (string) hash/id encoded in little-endian hexadecimal\n"
            "         \"depends\" : [                (array) array of numbers \n"
            "             n                          (numeric) transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is\n"
            "             ,...\n"
            "         ],\n"
            "         \"fee\": n,                    (numeric) difference in value between transaction inputs and outputs (in duffs); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n"
            "         \"sigops\" : n,                (numeric) total number of SigOps, as counted for purposes of block limits; if key is not present, sigop count is unknown and clients MUST NOT assume there aren't any\n"
            "         \"required\" : true|false      (boolean) if provided and true, this transaction must be in the final block\n"
            "      }\n"
            "      ,...\n"
            "  ],\n"
            "  \"coinbaseaux\" : {                 (json object) data that should be included in the coinbase's scriptSig content\n"
            "      \"flags\" : \"xx\"                  (string) key name is to be ignored, and value included in scriptSig\n"
            "  },\n"
            "  \"coinbasevalue\" : n,              (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in duffs)\n"
            "  \"coinbasetxn\" : { ... },          (json object) information for coinbase transaction\n"
            "  \"target\" : \"xxxx\",                (string) The hash target\n"
            "  \"mintime\" : xxx,                  (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n"
            "  \"mutable\" : [                     (array of string) list of ways the block template may be changed \n"
            "     \"value\"                          (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n"
            "     ,...\n"
            "  ],\n"
            "  \"noncerange\" : \"00000000ffffffff\",(string) A range of valid nonces\n"
            "  \"sigoplimit\" : n,                 (numeric) limit of sigops in blocks\n"
            "  \"sizelimit\" : n,                  (numeric) limit of block size\n"
            "  \"curtime\" : ttt,                  (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
            "  \"bits\" : \"xxxxxxxx\",              (string) compressed target of next block\n"
            "  \"previousbits\" : \"xxxxxxxx\",      (string) compressed target of current highest block\n"
            "  \"height\" : n                      (numeric) The height of the next block\n"
            "  \"masternode\" : [                  (array) required masternode payments that must be included in the next block\n"
            "      {\n"
            "         \"payee\" : \"xxxx\",          (string) payee address\n"
            "         \"script\" : \"xxxx\",         (string) payee scriptPubKey\n"
            "         \"amount\": n                (numeric) required amount to pay\n"
            "      }\n"
            "  },\n"
            "  \"masternode_payments_started\" :  true|false, (boolean) true, if masternode payments started\n"
            "  \"masternode_payments_enforced\" : true|false, (boolean) true, if masternode payments are enforced\n"
            "  \"superblock\" : [                  (array) required superblock payees that must be included in the next block\n"
            "      {\n"
            "         \"payee\" : \"xxxx\",          (string) payee address\n"
            "         \"script\" : \"xxxx\",         (string) payee scriptPubKey\n"
            "         \"amount\": n                (numeric) required amount to pay\n"
            "      }\n"
            "      ,...\n"
            "  ],\n"
            "  \"superblocks_started\" : true|false, (boolean) true, if superblock payments started\n"
            "  \"superblocks_enabled\" : true|false, (boolean) true, if superblock payments are enabled\n"
            "  \"coinbase_payload\" : \"xxxxxxxx\"    (string) coinbase transaction payload data encoded in hexadecimal\n"
            "}\n"

            "\nExamples:\n"
            + HelpExampleCli("getblocktemplate", "")
            + HelpExampleRpc("getblocktemplate", "")
         );

    LOCK(cs_main);

    std::string strMode = "template";
    UniValue lpval = NullUniValue;
    std::set<std::string> setClientRules;
    int64_t nMaxVersionPreVB = -1;
    if (request.params.size() > 0)
    {
        const UniValue& oparam = request.params[0].get_obj();
        const UniValue& modeval = find_value(oparam, "mode");
        if (modeval.isStr())
            strMode = modeval.get_str();
        else if (modeval.isNull())
        {
            /* Do nothing */
        }
        else
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
        lpval = find_value(oparam, "longpollid");

        if (strMode == "proposal")
        {
            const UniValue& dataval = find_value(oparam, "data");
            if (!dataval.isStr())
                throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal");

            CBlock block;
            if (!DecodeHexBlk(block, dataval.get_str()))
                throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");

            uint256 hash = block.GetHash();
            BlockMap::iterator mi = mapBlockIndex.find(hash);
            if (mi != mapBlockIndex.end()) {
                CBlockIndex *pindex = mi->second;
                if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
                    return "duplicate";
                if (pindex->nStatus & BLOCK_FAILED_MASK)
                    return "duplicate-invalid";
                return "duplicate-inconclusive";
            }

            CBlockIndex* const pindexPrev = chainActive.Tip();
            // TestBlockValidity only supports blocks built on the current Tip
            if (block.hashPrevBlock != pindexPrev->GetBlockHash())
                return "inconclusive-not-best-prevblk";
            CValidationState state;
            TestBlockValidity(state, Params(), block, pindexPrev, false, true);
            return BIP22ValidationResult(state);
        }

        const UniValue& aClientRules = find_value(oparam, "rules");
        if (aClientRules.isArray()) {
            for (unsigned int i = 0; i < aClientRules.size(); ++i) {
                const UniValue& v = aClientRules[i];
                setClientRules.insert(v.get_str());
            }
        } else {
            // NOTE: It is important that this NOT be read if versionbits is supported
            const UniValue& uvMaxVersion = find_value(oparam, "maxversion");
            if (uvMaxVersion.isNum()) {
                nMaxVersionPreVB = uvMaxVersion.get_int64();
            }
        }
    }

    if (strMode != "template")
        throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");

    if(!g_connman)
        throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");

    if (Params().MiningRequiresPeers()) {
        if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0)
            throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Dash Core is not connected!");

        if (IsInitialBlockDownload())
            throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Dash Core is downloading blocks...");
    }

    // when enforcement is on we need information about a masternode payee or otherwise our block is going to be orphaned by the network
    std::vector<CTxOut> voutMasternodePayments;
    if (sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)
        && !masternodeSync.IsWinnersListSynced()
        && !mnpayments.GetBlockTxOuts(chainActive.Height() + 1, 0, voutMasternodePayments))
            throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Dash Core is downloading masternode winners...");

    // next bock is a superblock and we need governance info to correctly construct it
    if (sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED)
        && !masternodeSync.IsSynced()
        && CSuperblock::IsValidBlockHeight(chainActive.Height() + 1))
            throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Dash Core is syncing with network...");

    static unsigned int nTransactionsUpdatedLast;

    if (!lpval.isNull())
    {
        // Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
        uint256 hashWatchedChain;
        boost::system_time checktxtime;
        unsigned int nTransactionsUpdatedLastLP;

        if (lpval.isStr())
        {
            // Format: <hashBestChain><nTransactionsUpdatedLast>
            std::string lpstr = lpval.get_str();

            hashWatchedChain.SetHex(lpstr.substr(0, 64));
            nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64));
        }
        else
        {
            // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
            hashWatchedChain = chainActive.Tip()->GetBlockHash();
            nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
        }

        // Release the wallet and main lock while waiting
        LEAVE_CRITICAL_SECTION(cs_main);
        {
            checktxtime = boost::get_system_time() + boost::posix_time::minutes(1);

            boost::unique_lock<boost::mutex> lock(csBestBlock);
            while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
            {
                if (!cvBlockChange.timed_wait(lock, checktxtime))
                {
                    // Timeout: Check transactions for update
                    if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
                        break;
                    checktxtime += boost::posix_time::seconds(10);
                }
            }
        }
        ENTER_CRITICAL_SECTION(cs_main);

        if (!IsRPCRunning())
            throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
        // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
    }

    // Update block
    static CBlockIndex* pindexPrev;
    static int64_t nStart;
    static std::unique_ptr<CBlockTemplate> pblocktemplate;
    if (pindexPrev != chainActive.Tip() ||
        (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5))
    {
        // Clear pindexPrev so future calls make a new block, despite any failures from here on
        pindexPrev = nullptr;

        // Store the chainActive.Tip() used before CreateNewBlock, to avoid races
        nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
        CBlockIndex* pindexPrevNew = chainActive.Tip();
        nStart = GetTime();

        // Create new block
        CScript scriptDummy = CScript() << OP_TRUE;
        pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy);
        if (!pblocktemplate)
            throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");

        // Need to update only after we know CreateNewBlock succeeded
        pindexPrev = pindexPrevNew;
    }
    CBlock* pblock = &pblocktemplate->block; // pointer for convenience
    const Consensus::Params& consensusParams = Params().GetConsensus();

    // Update nTime
    UpdateTime(pblock, consensusParams, pindexPrev);
    pblock->nNonce = 0;

    UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");

    UniValue transactions(UniValue::VARR);
    std::map<uint256, int64_t> setTxIndex;
    int i = 0;
    for (const auto& it : pblock->vtx) {
        const CTransaction& tx = *it;
        uint256 txHash = tx.GetHash();
        setTxIndex[txHash] = i++;

        if (tx.IsCoinBase())
            continue;

        UniValue entry(UniValue::VOBJ);

        entry.push_back(Pair("data", EncodeHexTx(tx)));

        entry.push_back(Pair("hash", txHash.GetHex()));

        UniValue deps(UniValue::VARR);
        BOOST_FOREACH (const CTxIn &in, tx.vin)
        {
            if (setTxIndex.count(in.prevout.hash))
                deps.push_back(setTxIndex[in.prevout.hash]);
        }
        entry.push_back(Pair("depends", deps));

        int index_in_template = i - 1;
        entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template]));
        entry.push_back(Pair("sigops", pblocktemplate->vTxSigOps[index_in_template]));

        transactions.push_back(entry);
    }

    UniValue aux(UniValue::VOBJ);
    aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));

    arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);

    UniValue aMutable(UniValue::VARR);
    aMutable.push_back("time");
    aMutable.push_back("transactions");
    aMutable.push_back("prevblock");

    UniValue result(UniValue::VOBJ);
    result.push_back(Pair("capabilities", aCaps));

    UniValue aRules(UniValue::VARR);
    UniValue vbavailable(UniValue::VOBJ);
    for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) {
        Consensus::DeploymentPos pos = Consensus::DeploymentPos(j);
        ThresholdState state = VersionBitsState(pindexPrev, consensusParams, pos, versionbitscache);
        switch (state) {
            case THRESHOLD_DEFINED:
            case THRESHOLD_FAILED:
                // Not exposed to GBT at all
                break;
            case THRESHOLD_LOCKED_IN:
                // Ensure bit is set in block version
                pblock->nVersion |= VersionBitsMask(consensusParams, pos);
                // FALL THROUGH to get vbavailable set...
            case THRESHOLD_STARTED:
            {
                const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
                vbavailable.push_back(Pair(gbt_vb_name(pos), consensusParams.vDeployments[pos].bit));
                if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
                    if (!vbinfo.gbt_force) {
                        // If the client doesn't support this, don't indicate it in the [default] version
                        pblock->nVersion &= ~VersionBitsMask(consensusParams, pos);
                    }
                }
                break;
            }
            case THRESHOLD_ACTIVE:
            {
                // Add to rules only
                const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
                aRules.push_back(gbt_vb_name(pos));
                if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
                    // Not supported by the client; make sure it's safe to proceed
                    if (!vbinfo.gbt_force) {
                        // If we do anything other than throw an exception here, be sure version/force isn't sent to old clients
                        throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Support for '%s' rule requires explicit client support", vbinfo.name));
                    }
                }
                break;
            }
        }
    }
    result.push_back(Pair("version", pblock->nVersion));
    result.push_back(Pair("rules", aRules));
    result.push_back(Pair("vbavailable", vbavailable));
    result.push_back(Pair("vbrequired", int(0)));

    if (nMaxVersionPreVB >= 2) {
        // If VB is supported by the client, nMaxVersionPreVB is -1, so we won't get here
        // Because BIP 34 changed how the generation transaction is serialized, we can only use version/force back to v2 blocks
        // This is safe to do [otherwise-]unconditionally only because we are throwing an exception above if a non-force deployment gets activated
        // Note that this can probably also be removed entirely after the first BIP9 non-force deployment (ie, probably segwit) gets activated
        aMutable.push_back("version/force");
    }

    result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
    result.push_back(Pair("transactions", transactions));
    result.push_back(Pair("coinbaseaux", aux));
    result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0]->GetValueOut()));
    result.push_back(Pair("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
    result.push_back(Pair("target", hashTarget.GetHex()));
    result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
    result.push_back(Pair("mutable", aMutable));
    result.push_back(Pair("noncerange", "00000000ffffffff"));
    result.push_back(Pair("sigoplimit", (int64_t)MaxBlockSigOps(fDIP0001ActiveAtTip)));
    result.push_back(Pair("sizelimit", (int64_t)MaxBlockSize(fDIP0001ActiveAtTip)));
    result.push_back(Pair("curtime", pblock->GetBlockTime()));
    result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
    result.push_back(Pair("previousbits", strprintf("%08x", pblocktemplate->nPrevBits)));
    result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1)));

    UniValue masternodeObj(UniValue::VARR);
    for (const auto& txout : pblocktemplate->voutMasternodePayments) {
        CTxDestination address1;
        ExtractDestination(txout.scriptPubKey, address1);
        CBitcoinAddress address2(address1);

        UniValue obj(UniValue::VOBJ);
        obj.push_back(Pair("payee", address2.ToString().c_str()));
        obj.push_back(Pair("script", HexStr(txout.scriptPubKey)));
        obj.push_back(Pair("amount", txout.nValue));
        masternodeObj.push_back(obj);
    }

    result.push_back(Pair("masternode", masternodeObj));
    result.push_back(Pair("masternode_payments_started", pindexPrev->nHeight + 1 > consensusParams.nMasternodePaymentsStartBlock));
    result.push_back(Pair("masternode_payments_enforced", deterministicMNManager->IsDeterministicMNsSporkActive() || sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)));

    UniValue superblockObjArray(UniValue::VARR);
    if(pblocktemplate->voutSuperblockPayments.size()) {
        for (const auto& txout : pblocktemplate->voutSuperblockPayments) {
            UniValue entry(UniValue::VOBJ);
            CTxDestination address1;
            ExtractDestination(txout.scriptPubKey, address1);
            CBitcoinAddress address2(address1);
            entry.push_back(Pair("payee", address2.ToString().c_str()));
            entry.push_back(Pair("script", HexStr(txout.scriptPubKey)));
            entry.push_back(Pair("amount", txout.nValue));
            superblockObjArray.push_back(entry);
        }
    }
    result.push_back(Pair("superblock", superblockObjArray));
    result.push_back(Pair("superblocks_started", pindexPrev->nHeight + 1 > consensusParams.nSuperblockStartBlock));
    result.push_back(Pair("superblocks_enabled", sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED)));

    result.push_back(Pair("coinbase_payload", HexStr(pblock->vtx[0]->vExtraPayload)));

    return result;
}
Beispiel #24
0
CScript ParseScript(const std::string& s)
{
    CScript result;

    static std::map<std::string, opcodetype> mapOpNames;

    if (mapOpNames.empty())
    {
        for (unsigned int op = 0; op <= MAX_OPCODE; op++)
        {
            // Allow OP_RESERVED to get into mapOpNames
            if (op < OP_NOP && op != OP_RESERVED)
                continue;

            const char* name = GetOpName((opcodetype)op);
            if (strcmp(name, "OP_UNKNOWN") == 0)
                continue;
            std::string strName(name);
            mapOpNames[strName] = (opcodetype)op;
            // Convenience: OP_ADD and just ADD are both recognized:
            boost::algorithm::replace_first(strName, "OP_", "");
            mapOpNames[strName] = (opcodetype)op;
        }
    }

    std::vector<std::string> words;
    boost::algorithm::split(words, s, boost::algorithm::is_any_of(" \t\n"), boost::algorithm::token_compress_on);

    for (std::vector<std::string>::const_iterator w = words.begin(); w != words.end(); ++w)
    {
        if (w->empty())
        {
            // Empty string, ignore. (boost::split given '' will return one word)
        }
        else if (all(*w, boost::algorithm::is_digit()) ||
            (boost::algorithm::starts_with(*w, "-") && all(std::string(w->begin()+1, w->end()), boost::algorithm::is_digit())))
        {
            // Number
            int64_t n = atoi64(*w);
            result << n;
        }
        else if (boost::algorithm::starts_with(*w, "0x") && (w->begin()+2 != w->end()) && IsHex(std::string(w->begin()+2, w->end())))
        {
            // Raw hex data, inserted NOT pushed onto stack:
            std::vector<unsigned char> raw = ParseHex(std::string(w->begin()+2, w->end()));
            result.insert(result.end(), raw.begin(), raw.end());
        }
        else if (w->size() >= 2 && boost::algorithm::starts_with(*w, "'") && boost::algorithm::ends_with(*w, "'"))
        {
            // Single-quoted string, pushed as data. NOTE: this is poor-man's
            // parsing, spaces/tabs/newlines in single-quoted strings won't work.
            std::vector<unsigned char> value(w->begin()+1, w->end()-1);
            result << value;
        }
        else if (mapOpNames.count(*w))
        {
            // opcode, e.g. OP_ADD or ADD:
            result << mapOpNames[*w];
        }
        else
        {
            throw std::runtime_error("script parse error");
        }
    }

    return result;
}
int mp4_split_options_set(struct mp4_split_options_t* options,
                          const char* args_data,
                          unsigned int args_size)
{
  int result = 1;

  {
    const char* first = args_data;
    const char* last = first + args_size + 1;

    if(*first == '?')
    {
      ++first;
    }

    {
      char const* key = first;
      char const* val = NULL;
      int is_key = 1;
      size_t key_len = 0;

      float vbegin = 0.0f;
      float vend = 0.0f;

      while(first != last)
      {
        // the args_data is not necessarily 0 terminated, so fake it
        int ch = (first == last - 1) ? '\0' : *first;
        switch(ch)
        {
        case '=':
          val = first + 1;
          key_len = first - key;
          is_key = 0;
          break;
        case '&':
        case '\0':
          if(!is_key)
          {
            // make sure the value is zero-terminated (for strtod,atoi64)
            int val_len = first - val;
            char* valz = (char*)malloc(val_len + 1);
            memcpy(valz, val, val_len);
            valz[val_len] = '\0';

            if(!strncmp("client", key, key_len))
            {
              options->client_is_flash = starts_with(valz, "FLASH");
            } else
            if(!strncmp("start", key, key_len))
            {
              options->start = (float)(strtod(valz, NULL));
              options->start_integer = atoi64(valz);
            } else
            if(!strncmp("end", key, key_len))
            {
              options->end = (float)(strtod(valz, NULL));
            } else
            if(!strncmp("exact", key, key_len))
            {
              options->exact = 1;
            } else
            if(!strncmp("vbegin", key, key_len))
            {
              vbegin = (float)(strtod(valz, NULL));
            } else
            if(!strncmp("vend", key, key_len))
            {
              vend = (float)(strtod(valz, NULL));
            } else
            if(!strncmp("adaptive", key, key_len))
            {
              options->adaptive = 1;
            } else
            if(!strncmp("bitrate", key, key_len))
            {
              options->fragment_bitrate = (unsigned int)(atoi64(valz));
            } else
            if(!strncmp("video", key, key_len))
            {
              options->fragments = 1;
              options->fragment_type = fragment_type_video;
              options->fragment_start = atoi64(valz);
            } else
            if(!strncmp("audio", key, key_len))
            {
              options->fragments = 1;
              options->fragment_type = fragment_type_audio;
              options->fragment_start = atoi64(valz);
            } else
            if(!strncmp("format", key, key_len))
            {
              if(!strncmp("flv", val, val_len))
              {
                options->output_format = OUTPUT_FORMAT_FLV;
              } else
              if(!strncmp("ts", val, val_len))
              {
                options->output_format = OUTPUT_FORMAT_TS;
              }
            } else
            if(!strncmp("input", key, key_len))
            {
              if(!strncmp("flv", val, val_len))
              {
                options->input_format = INPUT_FORMAT_FLV;
              }
            }
            free(valz);
          }
          key = first + 1;
          val = NULL;
          is_key = 1;
          break;
        }
        ++first;
      }

      // If we have specified a begin point of the virtual video clip,
      // then adjust the start offset
      options->start += vbegin;

      // If we have specified an end, adjust it in case of a virtual video clip.
      if(options->end)
      {
        options->end += vbegin;
      }
      else
      {
        options->end = vend;
      }

      // Validate the start/end for the virtual video clip (begin).
      if(vbegin)
      {
        if(options->start < vbegin)
          result = 0;
        if(options->end && options->end < vbegin)
          result = 0;
      }
      // Validate the start/end for the virtual video clip (end).
      if(vend)
      {
        if(options->start > vend)
          result =  0;
        if(options->end && options->end > vend)
          result = 0;
      }
    }
  }

  return result;
}
/*
 * Init function called from dm_table_load_ioctl.
 *
 * Example line sent to dm from lvm tools when using striped target.
 * start length striped #stripes chunk_size device1 offset1 ... deviceN offsetN
 * 0 65536 striped 2 512 /dev/hda 0 /dev/hdb 0
 */
static int
dm_target_stripe_init(dm_dev_t *dmv, void **target_config, char *params)
{
	dm_target_stripe_config_t *tsc;
	int n;
	char *ap;

	if (params == NULL)
		return EINVAL;

	/*
	 * nstripes
	 */
	ap = strsep(&params, " \t");
	if (ap == NULL)
		return EINVAL;
	n = (int)atoi64(ap);
	if (n < 0 || n > MAX_STRIPES) {
		kprintf("dm: Error %d stripes not supported (%d max)\n",
			n, MAX_STRIPES);
		return ENOTSUP;
	}

	tsc = kmalloc(sizeof(dm_target_stripe_config_t),
		      M_DMSTRIPE, M_WAITOK | M_ZERO);
	tsc->stripe_num = n;

	ap = strsep(&params, " \t");
	if (ap == NULL)
		return EINVAL;
	tsc->stripe_chunksize = atoi64(ap);
	if (tsc->stripe_chunksize < 1 ||
	    tsc->stripe_chunksize * DEV_BSIZE > MAXPHYS) {
		kprintf("dm: Error unsupported chunk size %jdKB\n",
			(intmax_t)tsc->stripe_chunksize * DEV_BSIZE / 1024);
		dm_target_stripe_destroy_config(tsc);
		return EINVAL;
	}

	/*
	 * Parse the devices
	 */

	kprintf("dm: Stripe %d devices chunk size %dKB\n",
		(int)tsc->stripe_num,
		(int)tsc->stripe_chunksize
	);

	for (n = 0; n < tsc->stripe_num; ++n) {
		ap = strsep(&params, " \t");
		if (ap == NULL)
			break;
		tsc->stripe_devs[n].pdev = dm_pdev_insert(ap);
		if (tsc->stripe_devs[n].pdev == NULL)
			break;
		ap = strsep(&params, " \t");
		if (ap == NULL)
			break;
		tsc->stripe_devs[n].offset = atoi64(ap);
	}
	if (n != tsc->stripe_num) {
		dm_target_stripe_destroy_config(tsc);
		return (ENOENT);
	}

	*target_config = tsc;

	dmv->dev_type = DM_STRIPE_DEV;

	return 0;
}