Qtum x86 虚拟机技术文档连载(二)



本篇为Qtum x86虚拟机的第二篇技术分析连载,本篇逐渐进入实际代码操作实操阶段,想要了解什么是虚拟机Qtum x86虚拟机独特优势见

Qtum x86 虚拟机技术文档连载(一)

2018年5月23日晚,Qtum x86虚拟机及Qtum企业版的开发进展发布会于韩国首尔顺利举行。Qtum研发团队现场演示了用c语言编写的“Hello world”智能合约,从编写、编译、部署到调用的全套流程,这也是Qtum区块链(内部测试网络)上运行的首个用 C 语言编写的智能合约。


详情:

Qtum X86虚拟机及Qtum企业版原型于韩国发布

支持C/C++/Rust/Swift的Qtum X86虚拟机如何打造更丰富的智能合约生态


每周项目进展报告都有涉及 Qtum x86 技术进展,本系列文章主要为整合与实践操作指导,帮助更多的主流语言开发者加入区块链开发的大潮中来。本篇连载文章主要为“Hello World”合约的创建和调试。


Hello World

工具链设置完毕之后,我们终于可以使用一个简单的 Hello World 合约对它进行测试了。


这是一个非常简单的 Hello World 合约源代码:

#include <qtum.h>

int onCreate(){
qtumEventStringString("Hello World", "Contract creation");
return 0;
}

int main(){
qtumEventStringString("Hello World", "Execution Success!");
return 0;
}

在这里 onCreate 函数在最初使用 createcontract 或 qx86deploy 在区块链上部署智能合约时被调用。之后无论是执行 callcontract 、sendtocontract 或是其他合约调用时,都将调用 main 函数 。

qtumEventStringString 函数可在执行时生成一个新事件(event),StringString 后缀意味着事件的 “Key”和“Value” 都是一串字符。还有类似qtumEventStringInt64 这样的函数,用于指定的64位整数“Key”而不是字符串。使用 qx86cli searchevents 我们可以对该事件进行检索。

这个智能合约的编译过程稍微复杂一些。我们使用工具链docker 容器来进行实际的处理。这能简化在任何操作系统上编译 qtumx86 智能合约的过程,而不仅限于 Linux 或 OSX。

首先,我们编写一个 makefile。这个 makefile 将在 docker容器上执行,以确保所有 Qtum 工具都可用,下面是 hello world 的模板:

# files to be built
# fill this in as a template
HDRS =
C_SRC = helloworld.c
OUTPUT = helloworld.elf
LIBS =
BYTECODE = helloworld.qbit

C_OBJS = $(subst .c,.o,$(C_SRC))

#these default flags will just remove dead code and give warnings
CFLAGS += -Wall -ffunction-sections -f>LDFLAGS += -Wl,--gc-section


default: $(BYTECODE)

$(BYTECODE): $(OUTPUT)
x86testbench -assemble -raw $(OUTPUT) > $(BYTECODE)

$(OUTPUT): $(C_OBJS)
$(CC) $(LDFLAGS) -o $(OUTPUT) $(C_OBJS) $(LIBS)

$(C_OBJS): $(HDRS) $(C_SRC)
$(CC) $(CFLAGS) -c $*.c -o $@

clean:
rm -f $(C_OBJS) $(OUTPUT) $(BYTECODE)

我们把它的变量分解如下:

HDRS =

这是为了跟踪合约中的任何头文件。虽然头文件不是直接编译的,但是跟踪这些文件,可以在对头文件进行更改时重新编译代码。

C_SRC = helloworld.c

这些是要编译的C文件,可以通过在附加文件名后面加上空格分隔符将其扩展到多个文件。

OUTPUT = helloworld.elf

这是GCC编译器的输出,是一个标准的ELF文件,非常适合于后编译分析。大多数现有的逆向工程和分析工具都支持这种格式。因此,如果需要对编译器的二进制文件进行分析,那么可以使用这个文件。

LIBS =

这项操作是为了向合约中添加静态库。

BYTECODE = helloworld.qbit

这是实际用于部署在 Qtum 区块链上的字节码文件。它由 ELF 文件简化而来, 非常容易解析和使用,但由于存在较多限制,暂时没有工具支持。当使用 qx86deploy 将其部署到区块链时,将使用 Qtum RPC 命令 “createcontract” ,参数是这个文件,它被转储到十六进制字符串中。

关于修改 Makefile,对于大多数简单的合约,这就足够了。对于涉及许多库等的更复杂的文件,使用它来编写自定义 makefile 可能更理想。为了真正部署此合约,你可以在本地 shell 中使用此脚本(假设你已从工具链设置中检索了 helpers.sh 脚本”)。

qx86start
qx86cli generate 600 # this will generate 600 blocks. This will start the chain and give us some coins to work with
qx86deploy helloworld.qbit
qx86cli generate 1 # generate 1 block so that we can mine our contract and ensure its processed

在这步操作之后你会看到以下输出:

Jordans-MacBook-Pro:helloworld earlz$ qx86deploy helloworld.qbit
{
"txid": "02b28cfcc7d1fdcb5963ee2ff9024a045ac6fb4d8d66683b027e47fd5973ed0b",
"sender": "qUJfCTe5LacTUBjC7djrEfoMtfZGXD7J4L",
"hash160": "75e089080145b639bf496e27cc3ed655e13377d0",
"hexaddress": "85840fafe5b51343f58259de8b48fe6b001cce57",
"address": "xLUbyAmNUTRxLt67x5gDtDxBzWpLrH92Zn"
}
Jordans-MacBook-Pro:helloworld earlz$ qx86cli generate 1
[
"300b9d8d9e5d05c22d09ff91335766e559af21ab70ee6f37daf280220eecc06d"
]


许多不同的字段将从部署命令中返回,其中很重要的一个是带有 xLUbyAmNUTRxLt67x5gDtDxBzWpLrH92Zn 值的address,所以会根据区块链上实际情况的不同而改变。txid 字段表示的是合约所属的交易ID 。

接下来你可以继续以下操作:

qx86cli searchevents


之后将会出现一组相当大的 JSON 输出。无论合约的执行是否成功,每一份合约的执行都有一份 JSON 输出。下面是 JSON 中各字段的含义:

  1. block hash——执行合约时的区块哈希

  2. tx-hash——待定

  3. tx-n——待定

  4. address——被执行的根合约地址,可能是执行createcontract 或是调用 sendtocontract 时的地址

  5. used-gas——执行合约时所花费的 gas

  6. sender-refund——退还给 sender 的 QTUM 数量


如果合约执行中出现的错误或恢复,所有在执行中发送的 QTUM 将被退还给 sender

  1. status——合约执行状态的描述字符串

  2. status-code——合约执行状态的状态码

  3. transfer-txid——待定

  4. commit-state——显示该合约执行是否已经是提交状态

  5. deltas——显示该合约执行过程中发生的所有状态变化。它会试图自动解析字符串或数字,并以更友好的方式显示

  6. deltas-raw——与 deltas 一样,但总是以原始十六进制形式显示

  7. modified-balances——显示由于该合约的执行引起余额变动的所有地址的余额

  8. spent-vins——显示所有该合约执行时消耗的 UTXO

  9. events——显示实际执行该合约时发生的事件,是一个 key-value 键值对

  10. calls——显示其他合约执行结果的递归结构。在整个合约执行过程中,每个合约调用都有一个结果。

你将在 JSON 输出的底部看到如下内容:

"modified-balances": {
},
"spent-vins": [
]
},
"events": {
"Hello World": "Contract creation"
},
"calls": [
]
}
]

可以看到 hello world 合约已经生成。


为了调用该合约以及对它进行测试(这里请将地址换成你自己的),执行以下操作:

qx86cli callcontract xLUbyAmNUTRxLt67x5gDtDxBzWpLrH92Zn 00


这将立即返回 JSON 结果。callcontract 只是在本地调用合约,并不创建区块链交易。因此,没有与 callcontract 相关的费用产生。在 JSON 结果中,你现在应该能在 events 数组中看到"Hello World": "Execution Success!"

如要在区块链上中实际交易中执行同样的操作,你可以根据以下步骤:

qx86cli sendtocontract xLUbyAmNUTRxLt67x5gDtDxBzWpLrH92Zn 00
qx86cli generate 1 #create one block to confirm the transaction

执行后,不会有 JSON 结果出现,但你可以通过 searchevents 查看。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值