本期小E将为大家带来EOCS 最低资源保障机制。

为满足普通用户日常的转账等基本需求,无需再为较少的初始资源抵押担心无法使用链上功能。EOCS可以通过链的参数来调整分配给每个用户免费的资源额度,相当于EOCS链上的最低资源保障机制。

系统合约中最低资源保障代码

 void system_contract::setmrs( int64_t cpu_us, int64_t net_bytes, int64_t ram_bytes){
require_auth(_self);
set_minimum_resource_security(ram_bytes, net_bytes, cpu_us);
}

其中privileged_api::set_minimum_resource_security是主链提供的供智能合约调用的接口,该函数参数很简单,分别为要设置的cpu,net,和ram的资源,privileged_api::get_resource_limits为获取账户资源状态的接口。函数在头文件eosiolib/privileged.h中声明。

下面为set_minimum_resource_security函数的实现

 void set_minimum_resource_security(int64_t ram_bytes, int64_t net_bytes, int64_t cpu_us) {
EOS_ASSERT(cpu_us >= , wasm_execution_error, "cpu_us must be >= 0");
EOS_ASSERT(net_bytes >= , wasm_execution_error, "net_bytes must be >= 0");
EOS_ASSERT(ram_bytes >= , wasm_execution_error, "ram_bytes must be >= 0");
auto& resource_limits = context.control.get_mutable_resource_limits_manager();
int64_t x, y, current_ram_bytes;
resource_limits.get_mrs_parameters(current_ram_bytes, x, y);
EOS_ASSERT(ram_bytes >= current_ram_bytes, wasm_execution_error,
"ram_bytes cannot be reduced, current_ram_bytes: '${current_ram_bytes}', set_ram_bytes: '${set_ram_bytes}'",
("current_ram_bytes", current_ram_bytes)("set_ram_bytes", ram_bytes));
resource_limits.set_mrs_parameters(ram_bytes, net_bytes, cpu_us);
}

函数中通过resource_limits_manager::get_mrs_parameters()和resource_limits_manager::set_mrs_parameters()分别去获取和设置最低资源保障

最低资源保障定义在resource_limits_config_object类中

 class resource_limits_config_object : public chainbase::object<resource_limits_config_object_type, resource_limits_config_object> {
OBJECT_CTOR(resource_limits_config_object);
id_type id; …


// Minimal Resource Security (MRS)
int64_t mrs_cpu_us = config::default_mrs_cpu_us;// 200 microseconds
int64_t mrs_net_bytes = config::default_mrs_net_bytes;// 10 KB
int64_t mrs_ram_bytes = config::default_mrs_ram_bytes;// 0 KB };

设置了最低资源保障后可以通过privileged_api::get_resource_limits->resource_limits_manager::get_account_limits查询

//所以返回的账户资源是否加上最低资源保障根据includes_mrs_ram

 void resource_limits_manager::get_account_limits( const account_name& account, int64_t& ram_bytes, int64_t& net_weight, int64_t& cpu_weight, bool includes_mrs_ram ) const {
const auto* pending_buo = _db.find<resource_limits_object,by_owner>( boost::make_tuple(true, account) );
const auto& config = _db.get<resource_limits_config_object>(); if (pending_buo) {
ram_bytes = pending_buo->ram_bytes;
net_weight = pending_buo->net_weight;
cpu_weight = pending_buo->cpu_weight;
} else {
const auto& buo = _db.get<resource_limits_object,by_owner>( boost::make_tuple( false, account ) );
ram_bytes = buo.ram_bytes;
net_weight = buo.net_weight;
cpu_weight = buo.cpu_weight;
} if (includes_mrs_ram) {
ram_bytes += config.mrs_ram_bytes;
} }

CPU和NET通过抵押EOC获得,每个账户所能获得的资源为:系统总资源 * 抵押代币 / 总的抵押代币 + 最低资源保障

// 获取账户当前可用的虚拟CPU

 int64_t resource_limits_manager::get_account_cpu_limit( const account_name& name, bool elastic ) const {
auto arl = get_account_cpu_limit_ex(name, elastic);
return arl.available;
}

// 获取账户的虚拟CPU限制

 account_resource_limit resource_limits_manager::get_account_cpu_limit_ex( const account_name& name, bool elastic) const {

    const auto& state = _db.get<resource_limits_state_object>();
const auto& usage = _db.get<resource_usage_object, by_owner>(name);
const auto& config = _db.get<resource_limits_config_object>(); int64_t cpu_weight, x, y;
get_account_limits( name, x, y, cpu_weight ); if( cpu_weight < || state.total_cpu_weight == ) {
return { -, -, - };
} account_resource_limit arl; uint128_t window_size = config.account_cpu_usage_average_window;

   // 计算窗口期(在这里为24h)内的虚拟计算能力

 uint128_t virtual_cpu_capacity_in_window = (uint128_t)(elastic ? state.virtu   al_cpu_limit : config.cpu_limit_parameters.max) * window_size;
uint128_t user_weight = (uint128_t)cpu_weight;
uint128_t all_user_weight = (uint128_t)state.total_cpu_weight;

  // 每个账户所能获得的资源为:系统总资源 * 抵押代币 / 总的抵押代币 + 最低资源保障cpu资源

    auto max_user_use_in_window = (virtual_cpu_capacity_in_window * user_weight) / all_user_weight + config.mrs_cpu_us;
auto cpu_used_in_window=impl::integer_divide_ceil((uint128_t)usage.cpu_usage.value_ex * window_size, (uint128_t)config::rate_limiting_precision);
if( max_user_use_in_window <= cpu_used_in_window )
arl.available = ;
else
arl.available = impl::downgrade_cast<int64_t>(max_user_use_in_window - cpu_used_in_window);
arl.used = impl::downgrade_cast<int64_t>(cpu_used_in_window);
arl.max = impl::downgrade_cast<int64_t>(max_user_use_in_window);
return arl;
}

EOCS对CPU、NET和RAM资源进行统一管理,对系统可用资源和账户可用资源集中记账。

// 将交易消耗的CPU和NET资源计入账户,并且加到块消耗的CPU和NET资源内,通常在交易验证后调用

 void resource_limits_manager::add_transaction_usage(const flat_set<account_name>& accounts, uint64_t cpu_usage, uint64_t net_usage, uint32_t time_slot ) {
const auto& state = _db.get<resource_limits_state_object>();
const auto& config = _db.get<resource_limits_config_object>();
for( const auto& a : accounts ) {
const auto& usage = _db.get<resource_usage_object,by_owner>( a );
int64_t unused;
int64_t net_weight;
int64_t cpu_weight;
get_account_limits( a, unused, net_weight, cpu_weight );
_db.modify( usage, [&]( auto& bu ){
bu.net_usage.add( net_usage, time_slot, config.account_net_usage_average_window );
bu.cpu_usage.add( cpu_usage, time_slot, config.account_cpu_usage_average_window );
}); if( cpu_weight >= && state.total_cpu_weight > ) {
uint128_t window_size = config.account_cpu_usage_average_window;
auto virtual_network_capacity_in_window = (uint128_t)state.virtual_cpu_limit * window_size;
auto cpu_used_in_window = ((uint128_t)usage.cpu_usage.value_ex * window_size) / (uint128_t)config::rate_limiting_precision;
uint128_t user_weight = (uint128_t)cpu_weight;
uint128_t all_user_weight = state.total_cpu_weight;
}
}

 //此处每个账户所获得的资源需要加上最低资源保障

      auto max_user_use_in_window = (virtual_network_capacity_in_window * user_weight) / all_user_weight + config.mrs_cpu_us;
EOS_ASSERT( cpu_used_in_window <= max_user_use_in_window,
tx_cpu_usage_exceeded,
"authorizing account '${n}' has insufficient cpu resources for this transaction",
("n", name(a))
("cpu_used_in_window",cpu_used_in_window)
("max_user_use_in_window",max_user_use_in_window) );
} if( net_weight >= && state.total_net_weight > ) {
uint128_t window_size = config.account_net_usage_average_window;
auto virtual_network_capacity_in_window = (uint128_t)state.virtual_net_limit * window_size;
auto net_used_in_window = ((uint128_t)usage.net_usage.value_ex * window_size) / (uint128_t)config::rate_limiting_precision;
uint128_t user_weight = (uint128_t)net_weight;
uint128_t all_user_weight = state.total_net_weight;

      //此处每个账户所获得的资源需要加上最低资源保障

    auto max_user_use_in_window = (virtual_network_capacity_in_window * user_weight) / all_user_weight + config.mrs_net_bytes;
EOS_ASSERT( net_used_in_window <= max_user_use_in_window,
tx_net_usage_exceeded,
"authorizing account '${n}' has insufficient net resources for this transaction",
("n", name(a))
("net_used_in_window",net_used_in_window)
("max_user_use_in_window",max_user_use_in_window) ); }
} // account for this transaction in the block and do not exceed those limits either
_db.modify(state, [&](resource_limits_state_object& rls){
rls.pending_cpu_usage += cpu_usage;
rls.pending_net_usage += net_usage;
}); EOS_ASSERT( state.pending_cpu_usage <= config.cpu_limit_parameters.max, block_resource_exhausted, "Block has insufficient cpu resources" );
EOS_ASSERT( state.pending_net_usage <= config.net_limit_parameters.max, block_resource_exhausted, "Block has insufficient net resources" );
}

以上即为EOCS最低资源保障代码分析,此处稍微提一下,EOS引入了虚拟资源,实现动态调节,virtual_block_cpu_limit和virtual_block_net_limit的总资源的初始值分别为block_cpu_limit和block_net_limit,也就是说,虚拟资源一开始等于实际资源,然后随着系统忙闲不断调整,最低值等于实际资源,最高值等于实际资源的1000倍。

详细细节,大家可以下载源码仔细参阅,本期小E为大家带来的EOCS 最低资源保障机制就介绍到这里,欢迎大家关注EOCS官方微信公众号及添加EOCS小秘书共同探讨交流更多技术。

 

EOCS 最低资源保障机制的更多相关文章

  1. atitit.资源释放机制--attilax总结

    atitit.资源释放机制--attilax总结 1. .全手工, 1 2. 引用计数, 1 2.1. 成本也显而易见. 1 2.2. 循环引用的问题, 2 2.3. 引用计数方式事实上也有经典的卡顿 ...

  2. 【原】Storm 消息处理保障机制

    Storm入门教程 1. Storm基础 Storm Storm主要特点 Storm基本概念 Storm调度器 Storm配置 Guaranteeing Message Processing(消息处理 ...

  3. Android源代码分析-资源载入机制

    转载请注明出处:http://blog.csdn.net/singwhatiwanna/article/details/23387079 (来自singwhatiwanna的csdn博客) 前言 我们 ...

  4. MySQL 持久化保障机制-redo 日志

    我们在 聊一聊 MySQL 中的事务及其实现原理 中提到了 redo 日志,redo 日志是用来保证 MySQL 持久化功能的,需要注意的是 redo 日志是 InnoDB 引擎特有的功能. 为什么 ...

  5. Yarn的资源隔离机制

    源调度和资源隔离是YARN作为一个资源管理系统,最重要和最基础的两个功能.资源调度由ResourceManager完成,而资源隔离由各个NodeManager实现,在文章“Hadoop YARN中内存 ...

  6. Tornado 的安全性保障机制Cookie XSRF跨站请求伪造阻断 &用户验证机制

    6.1 Cookie 对于RequestHandler,除了在第二章中讲到的之外,还提供了操作cookie的方法. 设置/获取 注意:Cookie 在浏览器调试时, 只有在第一次访问该网站的时候获取到 ...

  7. hadoop作业调度策略

    一个Mapreduce作业是通过JobClient向master的JobTasker提交的(JobTasker一直在等待JobClient通过RPC协议提交作业),JobTasker接到JobClie ...

  8. MapReduce多用户任务调度器——容量调度器(Capacity Scheduler)原理和源码研究

    前言:为了研究需要,将Capacity Scheduler和Fair Scheduler的原理和代码进行学习,用两篇文章作为记录.如有理解错误之处,欢迎批评指正. 容量调度器(Capacity Sch ...

  9. 大数据基础总结---MapReduce和YARN技术原理

    Map Reduce和YARN技术原理 学习目标 熟悉MapReduce和YARN是什么 掌握MapReduce使用的场景及其原理 掌握MapReduce和YARN功能与架构 熟悉YARN的新特性 M ...

随机推荐

  1. SkiaSharp图像处理

    SkiaSharp图像处理 .NET Core使用skiasharp文字头像生成方案(基于docker发布)   一.问题背景 目前.NET Core下面针对于图像处理的库微软并没有集成,在.NET ...

  2. 记录学习antd design pro dva的过程,主要记错, 多图预警,如有理解偏差,忘指出,多谢!

    首要问题: 如何增加菜单项 答案: 在router.config中添加路由,在locales语言国际化增加选项 问题1: 答案1: 问题2: 这个要修改state,正确写法 存在的疑惑:为什么不能直接 ...

  3. [Alpha阶段]第十次Scrum Meeting

    Scrum Meeting博客目录 [Alpha阶段]第十次Scrum Meeting 基本信息 名称 时间 地点 时长 第十次Scrum Meeting 19/04/15 大运村寝室6楼 35min ...

  4. js循环获取table中的值

    <script type="text/javascript"> function getTdValue() { var tableId = document.getEl ...

  5. JS学习笔记:(一)浏览器页面渲染机制

    浏览器的内核主要分为渲染引擎和JS引擎.目前市面上常见的浏览器内核可以分为这四种:Trident(IE).Gecko(火狐).Blink(Chrome.Opera).Webkit(Safari).这里 ...

  6. kettle变量(var变量)

    设置变量/set varibale 1.定义变量(子转换): 原始数据 设置获取变量:点击获取字段,自动获取变量名称和字段名称 引用变量: 输出: kettle.properties 文件存储在.ke ...

  7. Python——模块——fnmatch(文件名对比)

    一.模块作用 fnmatch 模块主要用于文件名的比较,使用 Unix shell 使用的 glob 样式模式. 二.简单匹配 fnmatch() 将单个文件名与模式进行比较并返回布尔值,来看它们是否 ...

  8. request+response+jsp+el+jstl

    response: 1.设置响应行的状态码: response.setStatus(int sc); 2.设置response缓冲区的编码:response.setCharacterEncoding( ...

  9. Xilinx FPGA 移位寄存器IP延时问题

    软件版本:Vivado2016.1 在使用移位寄存器IP时,对于不同延时拍数的使能延时可能会有问题. (1)32深度的可变长度移位寄存器,IP生成界面如下图所示. (2)128深度的可变长度移位寄存器 ...

  10. docker添加阿里云专属镜像

    阿里云镜像地址:https://link.zhihu.com/?target=https%3A//cr.console.aliyun.com/%23/accelerator 根据提示开启容器镜像服务, ...