区块链测试 EOS 平台下如何测试和调试智能合约

jimi · 2018年08月26日 · 1924 次阅读

为了能够调试智能合约,需要配置本地节点。这个本地节点可以作为单独的私有链或公有链的扩展来运行。这个本地节点还需要运行在合约控制台选项上,或者通过命令行 加参数--contracts-console,或者通过 config.ini 设置contracts-console = true

当第一次创建智能合约时,建议首先在私有链上测试和调试智能合约,因为你完全控制整个区块链。这使你可以拥有无限量的 EOS 币,并且可以随时重置区块链的状态。当它已经完全准备好,并打算正式上线时,可以通过将本地nodeos连接到公有 testnet 链(或官方测试链 testnet)来完成对公有 testnet 链(或官方测试链 testnet)的调试,这样就可以在本地nodeos中查看测试链的日志。

理解了这个意思的话,对于下面的内容,就使用私有链进行调试。

如果你没有配置好自己的本地nodeos,请参考eos 开发环境安装。默认情况下,本地nodeos将只运行在私有链中,除非你修改配置文件config.ini以与公有 testnet 链(或官方测试链 testnet)的节点连接,如这里中所述。

方法

调试智能合约的主要方法是Caveman Debugging,我们利用打印功能来检查变量的值并检查合约的流程。智能合约中的打印可以通过Print C API(C和C++)来完成。C++ APIC API的封装包,所以我们通常只使用C++ API

打印

Print C API支持的可以打印的数据类型如下:

  • prints:空终止字符数组(字符串)
  • prints_l:给定大小的任意字符数组(字符串)
  • printi:64 位无符号整数
  • printi128:128 位无符号整数
  • printd:双重编码为 64 位无符号整数
  • printn:编码为 64 位无符号整数的 base32 字符串
  • printhex:二进制数据及其大小给定为十六进制

虽然Print C++ API通过重载print()函数来封装一些上面的C API,所以用户不需要确定自己使用的特定的print函数Print C++ API支持:

  • 空终止字符数组(字符串)
  • 整数(128 位无符号,64 位无符号,32 位无符号,有符号,无符号)
  • 编码为 64 位无符号整数的 Base32 字符串
  • 具有print()的结构体类型

例子

让我们以一个新的合约作为示例进行调试。

debug.hpp

C++

#include <eoslib/eos.hpp>
#include <eoslib/db.hpp>

namespace debug {
    struct foo {
        account_name from;
        account_name to;
        uint64_t amount;
        void print() const {
            eosio::print("Foo from ", eosio::name(from), " to ",eosio::name(to), " with amount ", amount, "\n");
        }
    };
}

debug.cpp

C++

#include <debug.hpp>

extern "C" {

    void apply( uint64_t code, uint64_t action ) {
        if (code == N(debug)) {
            eosio::print("Code is debug\n");
            if (action == N(foo)) {
                 eosio::print("Action is foo\n");
                debug::foo f = eosio::current_message<debug::foo>();
                if (f.amount >= 100) {
                    eosio::print("Amount is larger or equal than 100\n");
                } else {
                    eosio::print("Amount is smaller than 100\n");
                    eosio::print("Increase amount by 10\n");
                    f.amount += 10;
                    eosio::print(f);
                }
            }
        }
    }
} // extern "C"

debug.hpp

C++

{
  "structs": [{
      "name": "foo",
      "base": "",
      "fields": {
        "from": "account_name",
        "to": "account_name",
        "amount": "uint64"
      }
    }
  ],
  "actions": [{
      "action_name": "foo",
      "type": "foo"
    }
  ]
}

让我们部署完成后发送一个消息给它。假设你已经创建了调试帐户并在钱包中有它的密钥。

$ eosiocpp -o debug.wast debug.cpp
$ cleos set contract debug debug.wast debug.abi
$ cleos push message debug foo '{"from":"inita", "to":"initb", "amount":10}' --scope debug

当你检查本地节点日志时,在发送上述消息后,将看到以下几行:

Code is debug
Action is foo
Amount is smaller than 100
Increase amount by 10
Foo from inita to initb with amount 20

在那里,可以确认你的消息将进入正确的控制流,并且正确地更新该值。你可能会看到上述消息至少 2 次,这是正常的,因为每个交易都在验证、块生成和区块链应用中用到。

夹带个私货《EOS 智能合约与 DApp 开发入门》教程,如果有需要的可以体验一下:

EOS 教程

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册