NFT环境部署-合约部署Bottle

Bottle

Bottle是开发VNT智能合约的命令行工具。
Bottle支持将c语言智能合约编译成wasm,提取abi文件,并将wasmabi压缩及编码成VNT网络合约部署所需要的智能合约文件。

Ubuntu 14.04及16.06编译

bottle代码clone到选择的目录

git clone https://github.com/vntchain/bottle

编译bottle需要go编译器,go的安装请参考go的官方文档

同时需要安装依赖包libxml2-dev,xz-utils,gcc

sudo apt-get install -y libxml2-dev xz-utils gcc

然后使用以下命令编译得到bottle

cd bottle
make bottle

最后使用以下命令运行bottle

./build/bin/bottle

其他系统

目前bottle暂不支持除上述系统之外的系统,如果希望在不支持的系统上运行bottle,请使用docker的方式

使用docker运行

编译得到docker镜像

bottle代码clone到选择的目录

git clone https://github.com/vntchain/bottle

然后使用以下命令编译得到镜像

cd bottle
make bottle-docker

通过dockerhub得到镜像

镜像拉取命令

docker pull vntchain/bottle:0.6.0

使用

编译智能合约代码

通过编译得到bottle

bottle compile -code <your contract path> -output <the path of your choosing to save the compiled contract file>

使用docker运行

docker run --rm -v <your contract directory>:/tmp vntchain/bottle:0.6.0 compile -code /tmp/<your contract file name> 

通过以上命令可以获得后缀名为compress的编译文件和后缀名为abi的abi文件,使用compress文件可以部署智能合约到VNT网络,通过abi文件可以访问VNT网络中的智能合约

智能合约代码纠错及提示

通过编译得到bottle

bottle hint -code <your contract path>

使用docker运行

docker run --rm -v <your contract directory>:/tmp vntchain/bottle:0.6.0  hint -code /tmp/<your contract file name> 

合约创建与部署

通过以下命令在空文件夹中创建智能合约与部署配置

bottle init

生成的文件结构

|____migrations
| |____1_initial_migration.js
|____contracts
| |____Migrations.c
| |____vntlib.h
| |____Erc20.c
|____bottle.js

创建完成后可以通过bottle build,bottle migrate来编译智能合约并将他们部署到VNTChain网络.

Build命令

bottle build命令需要在bottle.js所在的目录下执行,会把contracts文件夹下的智能合约文件进行编译并输出到build/contracts文件夹下

Migrate命令

bottle migrate命令需要在bottle.js所在的目录下执行,用于执行migrations文件夹下的js文件,js文件用于将contracts文件夹下的智能合约部署到VNTChain网络

Migrate文件

migrate文件是位于migrations文件夹下的js文件,一个简单的migrate文件如下所示

文件名: 4_example_migration.js

var MyContract = artifacts.require("./contracts/MyContract.c");

module.exports = function(deployer) {
  // deployment steps
  deployer.deploy(MyContract);
};

migrate文件名必须以数字为前缀,后缀为描述。数字前缀用于按顺序执行migrate文件,以及记录文件是否已被执行,已被执行的migrate文件会被再一次运行的bottle migrate命令所忽略,如果想要重新执行之前的migrate文件,请参考migrate命令的参数。后缀用于描述migrate文件,方便识别和理解文件的作用。

artifacts.require(contract_path)

migrate文件通过artifacts.require来引入需要操作的智能合约,参数是contracts文件夹内的智能合约的绝对地址或者相对地址,通过引用,将返回一个智能合约对象,智能合约对象用于智能合约部署以及访问智能合约的方法

假设在contracts文件夹下有如下智能合约文件

智能合约1: ./contracts/Contract1.c
智能合约2: ./contracts/Contract2.c

为了与以上两个智能合约交互,artifacts.require可以这样使用

var contract1 = artifacts.require("./contracts/Contract1.c");
var contract2 = artifacts.require("./contracts/Contract2.c");
module.exports

所有的migrate文件都必须通过module.exports语法导出函数,导出的函数的第一个参数为deployerdeployer对象提供了部署和访问智能合约的方法,第二个参数为networknetwork用于通过不同的网络部署智能合约,参考以下例子:

不使用network

module.exports = function(deployer) {

}

使用network

module.exports = function(deployer, network) {
  if (network == "live") {
    // Do something specific to the network named "live".
  } else {
    // Perform a different step otherwise.
  }
}

指定network通过bottle migratenetwork参数

bottle migrate --network xxx
初始化migrate智能合约

bottle需要有一个migrate智能合约才能使用bottle migrate功能,该智能合约包含特定的接口,会在第一次执行botlte migrate时部署,此后将不会更新。在使用bottle init创建新项目时,会默认创建该智能合约。

文件名: contracts/Migrations.c

#include "vntlib.h"

KEY address owner;
KEY uint32 last_completed_migration;
constructor Migrations()
{
  owner = GetSender();
}

void onlyOwner()
{
  Require(Equal(owner, GetSender()), "is not owner");
}

MUTABLE
void setCompleted(uint32 completed)
{
  onlyOwner();
  last_completed_migration = completed;
}

UNMUTABLE
uint32 get_last_completed_migration()
{
  return last_completed_migration;
}

migrate智能合约必须在第一次执行bottle migrate的时候进行部署,因此,需要创建如下的migrate文件

文件名: migrations/1_initial_migration.js

var Migrations = artifacts.require("../contracts/Migrations.c");

module.exports = function (deployer) {
  // Deploy the Migrations contract as our only task
  deployer.deploy(Migrations)
};

之后,可以增加编号前缀来创建新的migrate文件,以部署其他智能合约。

bottle init创建新项目时,会默认创建该migrate文件。

Deployer对象

migrate文件需要使用deployer对象来执行部署任务,同时可以同步编写部署任务,它们将以正确的顺序执行:

// Stage deploying A before B
deployer.deploy(A);
deployer.deploy(B);

或者,部署程序上的每个函数都可以用作Promise,按顺序依赖于上一个任务执行的部署任务:

// Deploy A, then deploy B, passing in A's newly deployed address
deployer.deploy(A).then(function() {
  return deployer.deploy(B, A.address);
});
Deployer API

deployer对象提供了方法用于简化智能合约的部署。

deployer.deploy(contract, args…, options)

参数contract为使用artifacts.require引用的智能合约对象。

参数args...为智能合约的构造函数的参数,用于初始化智能合约。

参数options用于指定fromgasoverwrite等信息,overwrite用于重新部署某个已经完成部署的智能合约,默认的options参数在bottle.js文件中配置

例子:

// Deploy a single contract without constructor arguments
deployer.deploy(A);

// Deploy a single contract with constructor arguments
deployer.deploy(A, arg1, arg2, ...);

// Don't deploy this contract if it has already been deployed
deployer.deploy(A, {overwrite: false});

// Set a maximum amount of gas and `from` address for the deployment
deployer.deploy(A, {gas: 4612388, from: "0x...."});

// External dependency example:
//
// For this example, our dependency provides an address when we're deploying to the
// live network, but not for any other networks like testing and development.
// When we're deploying to the live network we want it to use that address, but in
// testing and development we need to deploy a version of our own. Instead of writing
// a bunch of conditionals, we can simply use the `overwrite` key.
deployer.deploy(SomeDependency, {overwrite: false});
deployer.then(function() {…})

通过promise对象可以运行任意的部署步骤并调用指定的智能合约内部方法来进行交互

例子:

var ERC20 = artifacts.require("../contracts/Erc20.c")

module.exports = function (deployer, a) {
    deployer.deploy(ERC20, "1000000", "bitcoin", "BTC").then(function (instance) {
        deploy = instance;
        return deploy.GetTotalSupply()
    }).then(function (totalSupply) {
        console.log("totalSupply", totalSupply.toString());
        return deploy.GetDecimals();
    }).then(function (decimals) {
        console.log("decimals", decimals.toString());
        return deploy.GetTokenName();
    }).then(function (tokenName) {
        console.log("tokenName", tokenName);
        return deploy.GetAmount("0x122369f04f32269598789998de33e3d56e2c507a")
    }).then(function (balance) {
        console.log("balance", balance.toString());
    })
};

Bottle命令

NAME:
   bottle - the bottle command line interface

   Copyright 2018-2019 The bottle Authors

USAGE:
   bottle [global options] command [command options] [arguments11...]
   
VERSION:
   0.6.0-beta-1e52fa2f
   
COMMANDS:
   build       Build contracts
   compile     Compile contract source file
   compress    Compress wasm and abi file
   decompress  Deompress file into wasm and abi file
   hint        Contract hint
   init        Initialize dapp project
   migrate     Run migrations to deploy contracts
   help, h     Shows a list of commands or help for one command
   
PATH OPTIONS:
  --code value  Specific a contract code path
  --include     Specific the head file directory need by contract
  --output      Specific a output directory path
  --file value  Specific a compress file path to decompress
  --abi value   Specific a abi path needed by contract
  --wasm value  Specific a wasm path
  
MIGRATE OPTIONS:
  --reset          Run all migrations from the beginning, instead of running from the last completed migration
  -f value         Run contracts from a specific migration. The number refers to the prefix of the migration file (default: 0)
  -t value         Run contracts to a specific migration. The number refers to the prefix of the migration file (default: 0)
  --network value  Specify the network to use, saving artifacts specific to that network. Network name must exist in the configuration
  --verbose-rpc    Log communication between bottle and the VNTChain client
  
GLOBAL OPTIONS:
  --help, -h  show help
  

COPYRIGHT:
   Copyright 2018-2019 The bottle Authors

许可证

所有bottle仓库生成的二进制程序都采用GNU General Public License v3.0许可证, 具体请查看COPYING。

你可能感兴趣的:(区块链,区块链)