美文网首页比特股教程实时更细
Bitshares研究系列【问题集一】

Bitshares研究系列【问题集一】

作者: 聂怀远 | 来源:发表于2018-05-31 22:24 被阅读58次

    https://steemit.com/bitshares/@chaimyu/34sykz-bitshares

    1. import_key时失败帐户数据也会加入钱包,用list_my_accounts能查到数据?

    2.怎么发送operation?

    3. 没有提供api的operation怎么发送?

    4. faucet.yml配置url和port不生效

    5. python-faucet怎么输出调试日志?

    6. nathan、init0等帐号怎么生成的?

    7. bitshares的chainid是什么?

    在bitshares学习过程中,有一些零散问题整理在一块,互相之间并不一定存在关联性,计划每几个问题做一集发表。

    1. import_key时失败帐户数据也会加入钱包,用list_my_accounts能查到数据?

    例如公网引入"nathan"帐号

    Chaim:cli_wallet Chaim$ ./cli_wallet --server-rpc-endpoint=wss://bitshares.dacplay.org/ws

    Logging RPC to file: logs/rpc/rpc.log

    1125691ms th_a      main.cpp:136                  main                ] key_to_wif( committee_private_key ): 5KCBDTcyDqzsqehcb52tW5nU6pXife6V2rX9Yf7c3saYSzbDZ5W

    1125692ms th_a      main.cpp:140                  main                ] nathan_pub_key: BTS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV

    1125692ms th_a      main.cpp:141                  main                ] key_to_wif( nathan_private_key ): 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3

    Starting a new wallet with chain ID 4018d7844c78f6a6c41c6a552b898022310fc5dec06da467ee7905a8dad512c8 (from egenesis)

    1125692ms th_a      main.cpp:188                  main                ] wdata.ws_server: wss://bitshares.dacplay.org/ws

    1125918ms th_a      main.cpp:193                  main                ] wdata.ws_user:  wdata.ws_password: 

    Please use the set_password method to initialize a new wallet before continuing

    new >>> set_password 123456

    set_password 123456

    null

    locked >>> unlock 123456

    unlock 123456

    null

    unlocked >>> import_key nathan 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3

    import_key nathan 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3

    false

    unlocked >>> list_my_accounts

    list_my_accounts

    [{

        "id": "1.2.298",

        "membership_expiration_date": "1969-12-31T23:59:59",

        ...

    }

    ]

    查看import_key源码

      bool import_key(string account_name_or_id, string wif_key)

      {

          fc::optional optional_private_key = wif_to_key(wif_key);

          if (!optional_private_key)

            FC_THROW("Invalid private key");

          graphene::chain::public_key_type wif_pub_key = optional_private_key->get_public_key();

          account_object account = get_account( account_name_or_id );

          // make a list of all current public keys for the named account

          flat_set all_keys_for_account;

          std::vector active_keys = account.active.get_keys();

          std::vector owner_keys = account.owner.get_keys();

          std::copy(active_keys.begin(), active_keys.end(), std::inserter(all_keys_for_account, all_keys_for_account.end()));

          std::copy(owner_keys.begin(), owner_keys.end(), std::inserter(all_keys_for_account, all_keys_for_account.end()));

          all_keys_for_account.insert(account.options.memo_key);

          _keys[wif_pub_key] = wif_key;

          _wallet.update_account(account);

          _wallet.extra_keys[account.id].insert(wif_pub_key);

          return all_keys_for_account.find(wif_pub_key) != all_keys_for_account.end();

      }

    此函数先根据wif_key取得公钥wif_pub_key,然后取得帐户的active key和owner key并加入all_keys_for_account中,函数返回结果是看wif_pub_key是否在all_keys_for_account中。

    如果公网"nathan"帐户取的公钥是不对的,但 _wallet.update_account(account) 仍会把帐户信息加入本地钱包中。

    2.怎么发送operation?

    很多operation会提供对应的api函数,例如喂价api:

                          signed_transaction publish_asset_feed(string publishing_account, string symbol, price_feed feed, bool broadcast)

    而operation的json数据格式可以用 get_prototype_operation 取得:

    unlocked >>> get_prototype_operation asset_publish_feed_operation

    get_prototype_operation asset_publish_feed_operation

    [

      19,{

        "fee": {

          "amount": 0,

          "asset_id": "1.3.0"

        },

        "publisher": "1.2.0",

        "asset_id": "1.3.0",

        "feed": {

          "settlement_price": {

            "base": {

              "amount": 0,

              "asset_id": "1.3.0"

            },

            "quote": {

              "amount": 0,

              "asset_id": "1.3.0"

            }

          },

          "maintenance_collateral_ratio": 1750,

          "maximum_short_squeeze_ratio": 1500,

          "core_exchange_rate": {

            "base": {

              "amount": 0,

              "asset_id": "1.3.0"

            },

            "quote": {

              "amount": 0,

              "asset_id": "1.3.0"

            }

          }

        },

        "extensions": []

      }

    ]

    很多operation都会有很多参数,例如以上发布喂价,就需要指定一个json格式的参数price_feed,而这个参数格式就是operation参数中,去掉operation id,去掉api已传参数的json格式即可,所以发布喂价的这个price_feed类似如下:

    {"settlement_price": {"base": {"amount": 25,"asset_id": "1.3.1"},"quote": {"amount": 63647,"asset_id": "1.3.0"}},"maintenance_collateral_ratio": 1750,"maximum_short_squeeze_ratio":1100,"core_exchange_rate": {"base": {"amount": 25,"asset_id": "1.3.1"},"quote": {"amount": 66829,"asset_id": "1.3.0"}}}

    3. 没有提供api的operation怎么发送?

    可以手动构造operation并发送,调用流程:

    begin_builder_transaction

    add_operation_to_builder_transaction oid [opId, {operation}]

    set_fees_on_builder_transaction oid BTS

    sign_builder_transaction oid true

    operation id参见bitshares研究系列【operation的实现】

    手动构造transfer operation数据并发送交易,按如下操作:

    先查看operation格式,以下构造operation时需要使用其中部分数据

    unlocked >>> get_prototype_operation transfer_operation

    get_prototype_operation transfer_operation

    [

      0,{

        "fee": {

          "amount": 0,

          "asset_id": "1.3.0"

        },

        "from": "1.2.0",

        "to": "1.2.0",

        "amount": {

          "amount": 0,

          "asset_id": "1.3.0"

        },

        "extensions": []

      }

    ]

    unlocked >>> list_account_balances barnard18

    list_account_balances barnard18

    6.85982 BTS

    unlocked >>> begin_builder_transaction

    begin_builder_transaction

    0

    unlocked >>> add_operation_to_builder_transaction 0 [0,{"from": "1.2.861586", "to": "1.2.879822", "amount": {"amount": 100000, "asset_id": "1.3.0"}}]

    add_operation_to_builder_transaction 0 [0,{"from": "1.2.861586", "to": "1.2.879822", "amount": {"amount": 100000, "asset_id": "1.3.0"}}]

    null

    unlocked >>> set_fees_on_builder_transaction 0 BTS

    set_fees_on_builder_transaction 0 BTS

    {

      "amount": 10420,

      "asset_id": "1.3.0"

    }

    unlocked >>> sign_builder_transaction 0 true

    sign_builder_transaction 0 true

    {

      "ref_block_num": 54238,

      "ref_block_prefix": 2893069574,

      "expiration": "2018-05-08T07:47:03",

      "operations": [[

          0,{

            "fee": {

              "amount": 10420,

              "asset_id": "1.3.0"

            },

            "from": "1.2.861586",

            "to": "1.2.879822",

            "amount": {

              "amount": 100000,

              "asset_id": "1.3.0"

            },

            "extensions": []

          }

        ]

      ],

      "extensions": [],

      "signatures": [

        "1f40a75c45c544217e4af6a8ecae8e04f21d7adad7db91460284debfc52736a9797b5ee906dce9eed0ae47a4ee7c2f5f3532174fe64852c7e93a8469f09ac76b5a"

      ]

    }

    unlocked >>> list_account_balances barnard18

    list_account_balances barnard18

    5.75562 BTS

    operation需要import_key保证有私钥和权限

    4. faucet.yml配置url和port不生效

    配了也是监听localhost:3000

    => Rails 4.2.4 application starting in development on http://localhost:3000

    没具体去查原因,直接启动时指定监听地址和端口

    bash-3.2$ rails s -b 0.0.0.0 -p 3000

    5. python-faucet怎么输出调试日志?

    在用python-faucet时详细日志看不到,而运行又出现问题,查看graphene这些库都用的是logging

    在manage.py中增加以下语句:

    import logging

    logging.basicConfig(level=logging.DEBUG)

    这样就能打出所有调试信息了,同时也可以在这通过filename参数指定日志文件。

    6. nathan、init0等帐号怎么生成的?

    我们知道bitshares里有一些帐号,例如nathan、init0等,也知道这些帐号是内置的,但是怎么内置进去的呢?

    在创世区块时需要指定genesis.json文件,可以用以下方式生成一个例子文件:

    ./witness_node --create-genesis-json my-genesis.json

    文件中指定了nathan、init0等帐户的公私钥信息:

      "initial_accounts": [{

          "name": "init0",

          "owner_key": "BTS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",

          "active_key": "BTS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",

          "is_lifetime_member": true

        },

        ...

        {

          "name": "nathan",

          "owner_key": "BTS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",

          "active_key": "BTS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",

          "is_lifetime_member": false

        }

      ]

    在db_init.cpp中有初始化数据库的操作,其中对初始帐户的操作如下:

    void database::init_genesis(const genesis_state_type& genesis_state)

    {

      ...

      // Create initial accounts

      for( const auto& account : genesis_state.initial_accounts )

      {

          account_create_operation cop;

          cop.name = account.name;

          cop.registrar = GRAPHENE_TEMP_ACCOUNT;

          cop.owner = authority(1, account.owner_key, 1);

          if( account.active_key == public_key_type() )

          {

            cop.active = cop.owner;

            cop.options.memo_key = account.owner_key;

          }

          else

          {

            cop.active = authority(1, account.active_key, 1);

            cop.options.memo_key = account.active_key;

          }

          account_id_type account_id(apply_operation(genesis_eval_state, cop).get());

          if( account.is_lifetime_member )

          {

              account_upgrade_operation op;

              op.account_to_upgrade = account_id;

              op.upgrade_to_lifetime_member = true;

              apply_operation(genesis_eval_state, op);

          }

      }

      ...

    }

    7. bitshares的chainid是什么?

    使用cli_wallet等都可能需要指定chainid,而在bitshares-core修改时经常发现chainid变化了,什么原因呢?

    在genesis.json中有个初始chainid,如下:

      "initial_chain_id": "aa34045518f1469a28fa4578240d5f039afa9959c0b95ce3b39674efa691fb21",

    在application.cpp中有此函数:

          void startup()

          {

            ...

                  if( modified_genesis )

                  {

                      std::cerr << "WARNING:  GENESIS WAS MODIFIED, YOUR CHAIN ID MAY BE DIFFERENT\n";

                      genesis_str += "BOGUS";

                      genesis.initial_chain_id = fc::sha256::hash( genesis_str );

                  }

                  else

                      genesis.initial_chain_id = fc::sha256::hash( genesis_str );

            ...

          }       

    其中针对genesis.json做了hash计算并得出chainid,也就是说genesis.json改了链id就变了,这也符合实际情况,创世区块一旦创建链id就确定了。

    如果为了开发调试需要,当然可以把这个写成固定的链id,这样各方就不用变动了。

    感谢您阅读 @chaimyu 的帖子,期待您能留言交流!

    相关文章

      网友评论

      • 瓦莉拉拉:如果不把私钥存在节点中,如何自己构建一个transfer:disappointed_relieved:
      • 瓦莉拉拉:是steemit上的老鱼么:grin:
      • IT人故事会:老铁,经常看别人的分享.感谢别人的分享,感谢!关注了

      本文标题:Bitshares研究系列【问题集一】

      本文链接:https://www.haomeiwen.com/subject/jrydjftx.html