乐趣区

关于区块链:中移链合约常用开发介绍四工程树目录

01

目标

本文档介绍了工程化开发智能合约我的项目的工程树目录,介绍了各个文件夹及文件的含意和用处。本文档将沿用之前文章中实现的地址簿合约内容,以初始化我的项目为例开展介绍,适宜刚接触合约开发的开发人员用来理解智能合约我的项目,帮忙其疾速理解以及上手智能合约。

02

智能合约介绍

区块链作为一种分布式可信计算平台,去中心化是其最实质的特色。每笔交易的记录不可篡改地存储在区块链上。智能合约中定义能够在区块链上执行的动作 action 和交易 transaction 的代码。能够在区块链上执行,并将合约执行状态作为该区块链实例不可变历史的一部分。

因而,开发人员能够依赖该区块链作为可信计算环境,其中智能合约的输出、执行和后果都是独立的,不受内部影响。

03

术语解释

WebAssembly(WASM)
用于执行可移植二进制代码格局的虚拟机,托管在 nodeos 中。

应用程序二进制接口(ABI)
定义如何将数据编组进出 WebAssembly 虚拟机的接口。

CMake
CMake 是一个跨平台的装置(编译)工具,能够用简略的语句来形容所有平台的装置(编译过程)。它可能输入各种各样的 makefile 或者 project 文件,能测试编译器所反对的 C ++ 个性,组态档取名为 CMakeLists.txt。相熟某个集成开发环境(IDE)的开发者能够通过 CMake 用规范的形式建构软件。

04

目录树详解

(一)综述
在中移链合约罕用开发介绍(二)多索引表的应用一文中,介绍了如何在智能合约中编写代码应用多索引表,实现一个能够增删改查的地址簿合约。该合约通过一个 addressbook.cpp 文件实现了所有代码,并不合乎工程化开发的要求。

在本文中,咱们将以工程化开发的形式重写这一合约,不便介绍各目录的含意和用处。

首先仍旧是应用 eosio-init 命令创立 addressbook 我的项目。

eosio-init --path=. --project=addressbook

首次被创立的我的项目构造如下:

├── CMakeLists.txt c++ 编译形容文件
├── README.txt 引导文件
├── include
│   └── addressbook.hpp 我的项目头文件,蕴含表构造定义和接口定义
├── ricardian
│   └── addressbook.contracts.md 李嘉图合约,合约的数字文档
└── src
    ├── CMakeLists.txt c++ 编译形容文件
    └── addressbook.cpp 我的项目源文件,蕴含接口实现

(二)头文件目录 include
智能合约以 C ++ 程序出现,文件夹也大多遵循 C ++ 我的项目的命名习惯。其中 include 文件夹用于寄存头文件,即后缀为.hpp 的文件,可称为头文件目录。

头文件中编写了合约动作(函数)的申明、表格(构造体)等。

在 addressbook 我的项目中,合约的构造函数、两个动作 upsert 和 erase 的申明、多索引表 people,都应写在 addressbook.hpp 文件中并搁置于头文件目录 include.

addressbook.hpp 内容如下:

#include <eosio/eosio.hpp>

using namespace eosio;

class [[eosio::contract("addressbook")]] addressbook : public eosio::contract {

public:

  addressbook(name receiver, name code,  datastream<const char*> ds): 
  contract(receiver, code, ds) {}


  ACTION upsert(name user, std::string first_name, std::string last_name, uint64_t age, std::string street, std::string city, std::string state);

  ACTION erase(name user);

private:
  TABLE person {
    name key;
    std::string first_name;
    std::string last_name;
    uint64_t age;
    std::string street;
    std::string city;
    std::string state;

    uint64_t primary_key() const { return key.value;}
    uint64_t get_secondary_1() const { return age;}

  };

  using address_index = eosio::multi_index<"people"_n, person, indexed_by<"byage"_n, const_mem_fun<person, uint64_t, &person::get_secondary_1>>>;

};

(三)源文件目录 src
src 是 source 的缩写,在目录中是源文件的意思。src 文件夹用于寄存源文件,即后缀为.cpp 的文件,可称为源文件目录。

1、源文件
源文件中编写了合约动作(函数)的实现。

在 addressbook 我的项目中,合约的两个动作 upsert 和 erase 的实现,都写在 addressbook.cpp 文件中并搁置于源文件目录 src.

addressbook.cpp 内容如下:

#include <addressbook.hpp>

ACTION addressbook::upsert(name user, std::string first_name, std::string last_name, uint64_t age, std::string street, std::string city, std::string state) {require_auth( user);
   address_index addresses(get_first_receiver(),get_first_receiver().value);
   auto iterator = addresses.find(user.value);
   if(iterator == addresses.end() )
   {addresses.emplace(user, [&](auto& row) {
      row.key = user;
      row.first_name = first_name;
      row.last_name = last_name;
      row.age = age;
      row.street = street;
      row.city = city;
      row.state = state;
     });
   }
   else {addresses.modify(iterator, user, [&](auto& row) {
       row.key = user;
       row.first_name = first_name;
       row.last_name = last_name;
       row.age = age;
       row.street = street;
       row.city = city;
       row.state = state;
     });
   }
}

ACTION addressbook::erase(name user) {require_auth(user);

   address_index addresses(get_self(), get_first_receiver().value);

   auto iterator = addresses.find(user.value);
   check(iterator != addresses.end(), "Record does not exist");
   addresses.erase(iterator);
}

2、CMakeLists.txt
CMake 通过 CMakeLists.txt 配置我的项目的构建零碎,配合应用 cmake 命令行工具生成构建零碎并执行编译、测试,相比于手动编写构建零碎要高效许多。

由 eosio-init 主动生成的 CMakeLists.txt 文件内容如下:

project(addressbook)

set(EOSIO_WASM_OLD_BEHAVIOR "Off")
find_package(eosio.cdt)

add_contract(addressbook addressbook addressbook.cpp)
target_include_directories(addressbook PUBLIC ${CMAKE_SOURCE_DIR}/../include )
target_ricardian_directory(addressbook ${CMAKE_SOURCE_DIR}/../ricardian )

project 我的项目名
add_contract 用于构建智能合约并生成 ABI
第一个参数是合约名称;
第二个参数是 cmake 指标名称;
其余是构建合约所需的 CPP 文件(如本例中的 addressbook.cpp)。
target_include_directories 用于将头文件所在的目录增加到特定的 cmake 指标,指向 include 文件夹
target_ricardian_directory 用于将李嘉图合约所在的目录增加到特定的 cmake 指标,指向 ricardian 文件夹
(四)李嘉图合约目录 ricardian
在基于 EOSIO 的区块链环境中,李嘉图合约是一个随同智能合约的数字文档,定义了智能合约与其用户之间交互的条款和条件,以人类可读的文本编写,而后对其进行加密签订和验证。对于人和程序来说,它都很容易浏览,并有助于为智能合约和其用户之间的交互中可能呈现的任何状况提供清晰的了解。
本例中存在 upsert 和 erase 两个动作,能够按如下编写 addressbook.contracts.md 文件:

<h1 class="contract">upsert</h1>
---
spec-version: 0.0.1
title: Upsert
summary: This action will either insert or update an entry in the address book. If an entry exists with the same name as the specified user parameter, the record is updated with the first_name, last_name, street, city, and state parameters. If a record does not exist, a new record is created. The data is stored in the multi index table. The ram costs are paid by the smart contract.
icon:

<h1 class="contract">erase</h1>
---
spec-version: 0.0.1
title: Erase
summary: This action will remove an entry from the address book if an entry in the multi index table exists with the specified name.
icon:

形容了每个动作的具体解释。
(五)CMakeLists.txt 文件
根目录下主动生成的 CMakeLists.txt 文件内容如下:

include(ExternalProject)
# if no cdt root is given use default path
if(EOSIO_CDT_ROOT STREQUAL "" OR NOT EOSIO_CDT_ROOT)
   find_package(eosio.cdt)
endif()

ExternalProject_Add(
   addressbook_project
   SOURCE_DIR ${CMAKE_SOURCE_DIR}/src
   BINARY_DIR ${CMAKE_BINARY_DIR}/addressbook
   CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${EOSIO_CDT_ROOT}/lib/cmake/eosio.cdt/EosioWasmToolchain.cmake
   UPDATE_COMMAND ""PATCH_COMMAND""
   TEST_COMMAND ""INSTALL_COMMAND""
   BUILD_ALWAYS 1
)

文件中蕴含对 eosio.cdt 的导入,以及我的项目源文件、资源文件目录的导航。
(六)README.txt 文件
— addressbook Project —

--- addressbook Project ---

 - How to Build -
   - cd to 'build' directory
   - run the command 'cmake ..'
   - run the command 'make'

 - After build -
   - The built smart contract is under the 'addressbook' directory in the 'build' directory
   - You can then do a 'set contract' action with 'cleos' and point in to the './build/addressbook' directory

 - Additions to CMake should be done to the CMakeLists.txt in the './src' directory and not in the top level CMakeLists.txt

该文档的初始化内容中形容了如何编译并部署合约我的项目,依据理论的开发状况,能够在 README.txt 文件中对我的项目的构造、次要性能、应用办法进行形容,供参加开发或应用我的项目代码的人参考。

05

开发中的操作

(一)编译部署
在终端中应用如下命令:

cd ~/biosboot/genesis/addressbook
cd build/
cmake ..
make

失去的最终后果后有如下提醒,则为编译胜利:

[100%] Linking CXX executable addressbook.wasm
[100%] Built target addressbook
[77%] No install step for 'addressbook_project'
[88%] No test step for 'addressbook_project'
[100%] Completed 'addressbook_project'
[100%] Built target addressbook_project

此时,bulid 文件夹中已生成该合约的.wasm 和.abi 文件,应用 cleos set contract 部署合约:

cleos set contract addressbook /home/xxx/biosboot/genesis/addressbook/build/addressbook -p addressbook@active
Reading WASM from /home/xxx/biosboot/genesis/addressbook/build/addressbook/addressbook.wasm...
Skipping set abi because the new abi is the same as the existing abi
Publishing contract...
executed transaction: 19d0acfa59ba196c4d355c95c7fd420f0e2343967540cff6ef4c5aa73c25cc33  17672 bytes  3566 us
#         eosio <= eosio::setcode               {"account":"addressbook","vmtype":0,"vmversion":0,"code":"0061736d01000000019a022a60000060037f7f7f01...
<4>warn  2023-01-18T07:16:08.250 cleos     main.cpp:615                  print_rwarning: transaction executed locally, but may not be confirmed by the network yet

(二)增加源文件
如果我的项目中申明的办法增多,且附属不同品种的性能,可能会用到多个源文件。将同类型或独特实现一类性能的办法实现编写在同一个源文件当中。
当我的项目有多个源文件时,该当依照如下办法进行增加:
将.cpp 文件放入 src 文件夹中
批改 src 文件夹中的 CMakeLists.txt 文件,在 add_contract 后减少新的.cpp 文件。
例如:

add_contract(addressbook addressbook addressbook.cpp xxx.cpp)

(三)增加头文件
如果我的项目中申明的办法增多,且附属不同品种的性能,或者引入了独自的工具办法,可能会用到多个头文件。
当我的项目有多个头文件时,只须要将.hpp 文件放入 include 文件夹中即可。src 文件夹中的 CMakeLists.txt 中有如下语句:

target_include_directories(addressbook PUBLIC ${CMAKE_SOURCE_DIR}/../include )

该语句会将 include 文件夹中的所有文件作为头文件资源。

电脑拜访 DDC 网络门户
ddc.bsnbase.com
-END-

退出移动版