您正在查看: EOS-新手问答 分类下的文章

Not producing block because I don't have the private key for EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV

有人提问 config.ini中新增加的signature-provider和private key有什么区别,该用哪个?
根据signature-provider的注释(DEPRECATED - Use signature-provider instead) Tuple of [public key, WIF private key] (may specify multiple times) (eosio::producer_plugin)private key将会废弃,被signature-provider替代。
对于两个键值的解析可查看下面producer_plugin.cpp中的plugin_initialize代码。
但是尝试直接将private key中的key替换到signature-provider 提示一下错误

1400500ms thread-0   producer_plugin.cpp:751       start_block          ] Not producing block because I don't have the private key for EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
根据查看以下代码,分析(结论在最后)

eos_source_dir\plugins\producer_plugin\producer_plugin.cpp

void producer_plugin::plugin_initialize(const boost::program_options::variables_map& options)
{ try {
   my->_options = &options;
   LOAD_VALUE_SET(options, "producer-name", my->_producers, types::account_name)

   if( options.count("private-key") )
   {
      const std::vector<std::string> key_id_to_wif_pair_strings = options["private-key"].as<std::vector<std::string>>();
      for (const std::string& key_id_to_wif_pair_string : key_id_to_wif_pair_strings)
      {
         try {
            auto key_id_to_wif_pair = dejsonify<std::pair<public_key_type, private_key_type>>(key_id_to_wif_pair_string);
            my->_signature_providers[key_id_to_wif_pair.first] = make_key_signature_provider(key_id_to_wif_pair.second);
            auto blanked_privkey = std::string(std::string(key_id_to_wif_pair.second).size(), '*' );
            wlog("\"private-key\" is DEPRECATED, use \"signature-provider=${pub}=KEY:${priv}\"", ("pub",key_id_to_wif_pair.first)("priv", blanked_privkey));
         } catch ( fc::exception& e ) {
            elog("Malformed private key pair");
         }
      }
   }

   if( options.count("signature-provider") ) {
      const std::vector<std::string> key_spec_pairs = options["signature-provider"].as<std::vector<std::string>>();
      for (const auto& key_spec_pair : key_spec_pairs) {
         try {
            auto delim = key_spec_pair.find("=");
            FC_ASSERT(delim != std::string::npos);
            auto pub_key_str = key_spec_pair.substr(0, delim);
            auto spec_str = key_spec_pair.substr(delim + 1);

            auto spec_delim = spec_str.find(":");
            FC_ASSERT(spec_delim != std::string::npos);
            auto spec_type_str = spec_str.substr(0, spec_delim);
            auto spec_data = spec_str.substr(spec_delim + 1);

            auto pubkey = public_key_type(pub_key_str);

            if (spec_type_str == "KEY") {
               my->_signature_providers[pubkey] = make_key_signature_provider(private_key_type(spec_data));
            } else if (spec_type_str == "KEOSD") {
               my->_signature_providers[pubkey] = make_keosd_signature_provider(my, spec_data, pubkey);
            }

         } catch (...) {
            elog("Malformed signature provider: \"${val}\", ignoring!", ("val", key_spec_pair));
         }
      }
   }
producer_plugin_impl::start_block_result producer_plugin_impl::start_block() {
   chain::controller& chain = app().get_plugin<chain_plugin>().chain();
   const auto& hbs = chain.head_block_state();

   //Schedule for the next second's tick regardless of chain state
   // If we would wait less than 50ms (1/10 of block_interval), wait for the whole block interval.
   fc::time_point now = fc::time_point::now();
   fc::time_point base = std::max<fc::time_point>(now, chain.head_block_time());
   int64_t min_time_to_next_block = (config::block_interval_us) - (base.time_since_epoch().count() % (config::block_interval_us) );
   fc::time_point block_time = base + fc::microseconds(min_time_to_next_block);


   if((block_time - now) < fc::microseconds(config::block_interval_us/10) ) {     // we must sleep for at least 50ms
//      ilog("Less than ${t}us to next block time, time_to_next_block_time ${bt}",
//           ("t", config::block_interval_us/10)("bt", block_time));
      block_time += fc::microseconds(config::block_interval_us);
   }

   _pending_block_mode = pending_block_mode::producing;

   // Not our turn
   const auto& scheduled_producer = hbs->get_scheduled_producer(block_time);
   auto currrent_watermark_itr = _producer_watermarks.find(scheduled_producer.producer_name);
   auto signature_provider_itr = _signature_providers.find(scheduled_producer.block_signing_key);
   auto irreversible_block_age = get_irreversible_block_age();

   // If the next block production opportunity is in the present or future, we're synced.
   if( !_production_enabled ) {
      _pending_block_mode = pending_block_mode::speculating;
   } else if( _producers.find(scheduled_producer.producer_name) == _producers.end()) {
      _pending_block_mode = pending_block_mode::speculating;
   } else if (signature_provider_itr == _signature_providers.end()) {
      elog("Not producing block because I don't have the private key for ${scheduled_key}", ("scheduled_key", scheduled_producer.block_signing_key));
      _pending_block_mode = pending_block_mode::speculating;
void producer_plugin::plugin_startup()
{ try {
   if(fc::get_logger_map().find(logger_name) != fc::get_logger_map().end()) {
      _log = fc::get_logger_map()[logger_name];
   }

   ilog("producer plugin:  plugin_startup() begin");

   chain::controller& chain = app().get_plugin<chain_plugin>().chain();
   my->_accepted_block_connection.emplace(chain.accepted_block.connect( [this]( const auto& bsp ){ my->on_block( bsp ); } ));
   my->_irreversible_block_connection.emplace(chain.irreversible_block.connect( [this]( const auto& bsp ){ my->on_irreversible_block( bsp->block ); } ));

   const auto lib_num = chain.last_irreversible_block_num();
   const auto lib = chain.fetch_block_by_number(lib_num);
   if (lib) {
      my->on_irreversible_block(lib);
   } else {
      my->_irreversible_block_time = fc::time_point::maximum();
   }

   if (!my->_producers.empty()) {
      ilog("Launching block production for ${n} producers at ${time}.", ("n", my->_producers.size())("time",fc::time_point::now()));

      if (my->_production_enabled) {
         if (chain.head_block_num() == 0) {
            new_chain_banner(chain);
         }
         //_production_skip_flags |= eosio::chain::skip_undo_history_check;
      }
   }

   my->schedule_production_loop();

eos_source_dir\libraries\chain\block_header_state.cpp

producer_key block_header_state::get_scheduled_producer( block_timestamp_type t )const {
      auto index = t.slot % (active_schedule.producers.size() * config::producer_repetitions);
      index /= config::producer_repetitions;
      return active_schedule.producers[index];
   }

eos_source_dir\libraries\chain\include\eosio\chain\controller.hpp

 void initialize_fork_db() {
      wlog( " Initializing new blockchain with genesis state                  " );
      producer_schedule_type initial_schedule{ 0, {{N(eosio), conf.genesis.initial_key}} };
 class controller {
      public:
         struct config {
            flat_set<account_name>   actor_whitelist;
            flat_set<account_name>   actor_blacklist;
            flat_set<account_name>   contract_whitelist;
            flat_set<account_name>   contract_blacklist;
            flat_set< pair<account_name, action_name> > action_blacklist;
            flat_set<public_key_type> key_blacklist;
            path                     blocks_dir             =  chain::config::default_blocks_dir_name;
            path                     state_dir              =  chain::config::default_state_dir_name;
            uint64_t                 state_size             =  chain::config::default_state_size;
            uint64_t                 reversible_cache_size  =  chain::config::default_reversible_cache_size;
            bool                     read_only              =  false;
            bool                     force_all_checks       =  false;
            bool                     contracts_console      =  false;

            genesis_state            genesis;
            wasm_interface::vm_type  wasm_runtime = chain::config::default_wasm_runtime;
         };

eos_source_dir\libraries\chain\genesis_state.cpp

struct genesis_state {
   genesis_state();
genesis_state::genesis_state() {
   initial_timestamp = fc::time_point::from_iso_string( "2018-06-01T12:00:00" );
   initial_key = fc::variant(eosio_root_key).as<public_key_type>();
}

eos_source_dir\CMakeLists.txt

if ("${EOSIO_ROOT_KEY}" STREQUAL "")
   set(EOSIO_ROOT_KEY "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV")
endif()

message( STATUS "Using '${EOSIO_ROOT_KEY}' as public key for 'eosio' account" )

结论

对于eosio账户,EOS编译时会从CMakeLists.txt取一个设置的默认公钥作为initial_key缺省值,当nodeos 没有传入--genesis-json参数时,会走默认参数,但此时并没有EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV公钥的私钥。所以报错。

解决方式有两种

  1. 编译时修改CMakeLists.txt中EOSIO_ROOT_KEY为自己的eosio 公钥
  2. nodeos运行时传入--genesis-json 自己的genesis.json路径
    对于自己的genesis.json文件中initial_key修改成与自己的eosio公钥一致

!wast.empty(): no wast file found eosio.token/eosio.token.wast

今天更新EOS到 release 1.1 重新编译后,发现执行eosio.token合约时提示

surou@surou-C-H110M-K-Pro:~/eos/contracts$ cleos set contract eosio.token eosio.token
Reading WAST/WASM from eosio.token/eosio.token.wast...
1595091ms thread-0   main.cpp:2760                 main                 ] Failed with error: Assert Exception (10)
!wast.empty(): no wast file found eosio.token/eosio.token.wast

查看目录下,确实没有生成 wast文件

surou@surou-C-H110M-K-Pro:~/eos/contracts/eosio.token$ ls
CMakeLists.txt  eosio.token.abi  eosio.token.cpp  eosio.token.hpp

手动编译生成wast

surou@surou-C-H110M-K-Pro:~/eos/contracts/eosio.token$ eosiocpp -o eosio.token.wast eosio.token.cpp 
surou@surou-C-H110M-K-Pro:~/eos/contracts/eosio.token$ ls
CMakeLists.txt  eosio.token.abi  eosio.token.cpp  eosio.token.hpp  eosio.token.wasm  eosio.token.wast

再次部署合约,已经OK

surou@surou-C-H110M-K-Pro:~/eos/contracts$ cleos set contract eosio.token eosio.token
Reading WAST/WASM from eosio.token/eosio.token.wasm...
Using already assembled WASM...
Publishing contract...
executed transaction: 45460e0ebf7c0bde0a6802adec4dd7bc457c2d4a76f1d97fc6376c88d9db0f28  8032 bytes  1079 us
#         eosio <= eosio::setcode               {"account":"eosio.token","vmtype":0,"vmversion":0,"code":"0061736d01000000017e1560037f7e7f0060057f7e...
#         eosio <= eosio::setabi                {"account":"eosio.token","abi":"0e656f73696f3a3a6162692f312e3000030663726561746500020669737375657204...
warning: transaction executed locally, but may not be confirmed by the network yet

也许是编译有什么警告或者异常没注意,或者是EOS更新什么脚本导致的,暂时未做具体跟进,下次更新版本测试后再做补充。

push_transaction Error 3050003 eosio_assert_message assertion failure

查看nodeos 抛出log

Exception Details: 3050003 eosio_assert_message_exception: eosio_assert_message assertion failure
assertion failure with message: comparison of assets with different symbols is not allowed

是因为push_transaction中的代币符号与所需代币符号不一致

测试代码如下

eos = Eos({
        httpEndpoint: 'http://192.168.1.112:8888',
        chainId: 'cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f',
        keyProvider: wif,
        verbose: true
    })
const name = 'bcskillsurou'
    const pubkey = 'EOS68mvUMCz73a5Xj2wnJxdTW1aPjmiKCeSAjVdXjTd3D3g9A38EE'
     eos.transaction(tr => {
        tr.newaccount({
          creator: 'dapp.exec1',
          name,
          owner: pubkey,
          active: pubkey
        })

        tr.buyrambytes({
          payer: 'dapp.exec1',
          receiver: name,
          bytes: 8192
        })

        tr.delegatebw({
          from: 'dapp.exec1',
          receiver: name,
          stake_net_quantity: '10.0000 EOS',
          stake_cpu_quantity: '10.0000 EOS',
          transfer: 0
        })
    }).then(console.log)
    .catch(e => {
        console.error(e);
    })

由于测试网络中内置代币符号为 SYS,所以需要将上面的 EOS修改为 SYS
还有种就是将测试网内置代币修改为EOS
修改eos_source_dir/CMakeLists.txt
CORE_SYMBOL_NAME "SYS"修改为CORE_SYMBOL_NAME "EOS"重新编译项目

Cleos Command does not exist

cd eos_source_dir/build
sudo make install

Error 3040005 (please increase the expiration time of your transaction)

确认下交易的时间与最新同步区块的时间相差不超过
config.ini 配置的 max-transaction-time设置的时间。

测试环境可以修改
max-transaction-time = 30000 或者更高