您正在查看: Surou 发布的文章

EOS 合约使用 current_time_point (eosio.cdt v1.6)

From eosio.cdt v1.6 onwards
You have to #include <eosio/system.hpp> and then you can use:

eosio::current_time_point
eosio::current_block_time
to cast from time_point to uint32_t u can use like:
eosio::current_time_point().sec_since_epoch();

参考

https://github.com/EOSIO/eosio.cdt/issues/470

git 提示 fatal: Authentication failed for 'http://***********‘’得解决方法

首先用 git config --list 查看一下

user.name=surou
user.email=652511569@qq.com

如果不对,用命令设置一下

git config --global user.name "xxxx"
git config --global user.email  "xxxx"

如果还不行,执行一下命令,重新输入用户名密码就可以了:

git config --system --unset credential.helper

如果是Windows平台提示权限不足,就去git 安装目录右键管理员权限运行git-bash.exe,然后再切换到仓库目录再次执行。

工作量证明(PoW)与EOSIO一起使用

https://www.eospow.org/
https://github.com/NedAmarril/eosiopowcoin

EOS 工作量证明硬币(POW)[1]将PoW(工作量证明)采矿时间表和调整比特币(BTC)[2] 的难度应用于EOSIO [3]令牌。

每10分钟铸造50个战俘,持续约4年,然后将一半铸造成一半。一直重复,直到有2100万个POW,与BTC完全一样。

EOS CPU和NET资源用于通过将EOS转移到eosiopowcoin来挖掘POW。每次您将EOS发送到eosiopowcoin合约账户时,该EOS的确切金额加上eosiopowcoin账户中总POW供应量的0.0025%将会被转回给您。

POW是一个完全分散的,不信任的开源项目,无需开发人员分配。每个单独的战俘都已经或将要被开采。没有给予战俘免费或预先开采。使用setupminer 操作后,任何人都可以挖掘POW 。战俘的铸造将持续到供应达到2100万为止。没有人可以阻止POW的铸造,开采或分销。合同是无钥匙的。

推送交易上链“假”失败的处理方案

解决问题

对于通过Rpc推送交易上链,因超时等因素导致无返回交易id或者失败,实际交易已上链。

解决方案

在推送交易时附加一个action,action可以填一个与此次推送任务对应的唯一值mark,并把当前链的块高度记下

void addmark( const name& owner, const string& mark )
{
   require_auth( owner );
}

然后mongo会把这个action数据以及对应的交易Id 洗出来

bool
mongo_db_plugin_impl::add_action_trace( mongocxx::bulk_write& bulk_action_traces, const chain::action_trace& atrace,
                                        const chain::transaction_trace_ptr& t,
                                        bool executed, const std::chrono::milliseconds& now,
                                        bool& write_ttrace )
{
   using namespace bsoncxx::types;
   using bsoncxx::builder::basic::kvp;

   const auto block_time = std::chrono::duration_cast<std::chrono::milliseconds>(
               std::chrono::microseconds{atrace.block_time.to_time_point().time_since_epoch().count()} );

   if( executed && atrace.receipt->receiver == chain::config::system_account_name ) {
      update_account( atrace, now, block_time );
   }
   .....
   else if(atrace.act.name == name("addmark")) {
      add_trx_marks( atrace, now, block_time );
   }
void mongo_db_plugin_impl::add_trx_marks( const chain::action_trace& atrace, const std::chrono::milliseconds& now, const std::chrono::milliseconds& block_time ) {
   using namespace bsoncxx::types;
   using bsoncxx::builder::basic::kvp;
   using bsoncxx::builder::basic::make_document;

   auto addma = fc::raw::unpack<mongo_db_plugin::addmark>(atrace.act.data);

   auto doc = make_document( 
                           kvp( "mark", addma.mark),
                           kvp( "trx_id", atrace.trx_id.str()),
                           kvp( "owner", addma.owner.to_string()),
                           kvp( "contract",atrace.receipt.receiver.to_string()),
                           kvp( "block_time", b_date{block_time}),
                           kvp( "block_timestamp", block_time.count()),
                           kvp( "createdAt", b_date{now} ));

   try {
      if( !_trx_marks.insert_one(doc.view())) {
         EOS_ASSERT( false, chain::mongo_db_insert_fail, "Failed to insert _trx_marks ${name} : ${mark}", ("name", addma.owner.to_string())("mark", addma.mark) );
      }
   } catch (...) {
      handle_mongo_exception( "_trx_marks", __LINE__ );
   }
}

测试查询记录

也就是如果推送没返回交易id,可以尝试查洗出的这个表,如果有的话,使用对应的交易id做数据补全。

{
    "_id" : ObjectId("5df34b721e722d468e02260f"),
    "mark" : "944c1698dc62c1817cc02c68207c47bf85dfc7e830839d2ab7267899bb04ada9",
    "trx_id" : "0e65b2b921019604b7928fdea11fe4e02e10550fe50fe767cbb84043b245e5ee",
    "owner" : "bcskillsurou",
    "contract" : "eosio.token",
    "block_time" : ISODate("2019-12-13T08:27:30.000Z"),
    "block_timestamp" : NumberLong(1576225650000),
    "createdAt" : ISODate("2019-12-13T08:27:30.028Z")
}

如果超过一段时间,且判断mongo中块高度增长正常,且超过前面记下的块高度一段距离(以防意外的话,就是超过当前最新区块与不可逆块的差)【防止mongo同步问题】,也没记录的话,就可以判定失败了。

mongo 同步节点出错,导致数据脏后得处理

讨论前提

方案讨论的前提是在,本地有一份低于mongo数据库块高度得链数据备份
如果没有得话,此文章无效,只能清数据库,整体重放了。所以体现了,定期备份得重要性!

方案实施

查询mongo 数据,确认最后写入得块高度
blocks表,查看最后插入记录得 block_num 块号。
然后查询下其余各表

  • block_states
  • action_traces
  • transaction_traces

将该块号下得所有记录按照交易id,块号都删掉。
因为不能保证最后一个块得数据是写入完整得。
其他的表,插入时有更新判断,不会造成重复,所以无需删除,如果有自行新加得表,自行处理。

启动同步节点

使用之前得低于mongo块高度得链数据备份,启动同步节点
添加--mongodb-block-start参数,指定从哪个块开始,才解析块数据写入mongo.
假设此时mongo删去最后一块后,块高度为1000,那执行开始位置为 1000 + 1

nodeos --mongodb-block-start 1001

开始启动后,节点开始同步,等到1001块时,开始mongo插件开始解析块数据,并写入mongo

附加

由于mongo插件缺少判断,导致提前插入数据,修改如下
https://github.com/EOSIO/eos/blob/3c553db73864ea19458512b4669cf9942dc59f57/plugins/mongo_db_plugin/mongo_db_plugin.cpp#L705

void mongo_db_plugin_impl::process_applied_transaction( const chain::transaction_trace_ptr& t ) {
   try {
      // always call since we need to capture setabi on accounts even if not storing transaction traces
      if( start_block_reached ) { // 新加判断
           _process_applied_transaction( t );
       }
   } catch (fc::exception& e) {
      elog("FC Exception while processing applied transaction trace: ${e}", ("e", e.to_detail_string()));
   } catch (std::exception& e) {
      elog("STD Exception while processing applied transaction trace: ${e}", ("e", e.what()));
   } catch (...) {
      elog("Unknown exception while processing applied transaction trace");
   }
}