Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

Bytom DAPP 开发流程

zmhg799417
402 0 0
从目前已经发布的DAPP来看,DAPP架构大致可以分成3种类型:插件钱包模式、全节点钱包模式和兼容模式。% O* m& a6 y" k$ A' p  [1 m
插件钱包模式是借助封装了钱包的浏览器插件通过RPC协议与区块链节点通信,插件在运行时会将Web3框架注入到DAPP前端页面中,然后DApp通过Web3来与区块链节点通信。全节点钱包模式需要项目方同步并持有一个区块链节点,并对外提供一个浏览器环境与用户进行交互。兼容模式可以在插件钱包和全节点钱包下同时使用,即上述两种方式可以自由切换,安全性能相对较高。5 c' p7 g$ F4 }7 }- |+ O1 q+ B. D

3 n1 b4 ?2 O1 _+ ]" L8 O接下来介绍的比原链DAPP的架构模式跟账户模型DAPP的插件钱包模式有些相似,都是由DAPP前端、插件钱包和合约程序共同组成,其中插件钱包需要连接去中心化的区块链服务器blockcenter,该服务器主要是为了管理插件钱包的相关信息。此外,比原链是UTXO模型的区块链系统,合约程序存在于无状态的UTXO中,如果要实现这样一个具体的DAPP,就需要在前端和后端多做一些逻辑的处理。( z$ f' ^7 I" i0 K% `+ \, @
1. 编写、编译并实例化智能合约. l% k4 x: e2 \" G8 R9 E& w
编写智能合约
' `+ m0 J# x( S& w+ K  b+ N9 H比原链的虚拟机是图灵完备的,理论上可以实现任意图灵计算机能实现的操作。而Equity作为比原链的智能合约语言,使用Equity语言可以实现许多典型的金融模型案例,但是为了解决停机问题,比原链也设置了手续费的上限,因此用户在设计合约的时候做一下权衡。
! W8 Z" M& h7 m! O8 f合约模板结构如下:
; ?6 U- x7 D. y; r6 ocontract contract_name(...) locks valueAmount of valueAsset {
, H4 U! X5 f8 q2 N( {  clause clause_name(...) {
8 g! N/ q; M6 A9 @    ...! j. O: g: ?" ~+ r9 W
    lock/unlock ...
+ b, D; F- d, R7 }9 J6 E  }) X; y) e0 h7 H+ X" K( T) J
  ...
4 Y# T+ }) F  j- ]' t}( v( @5 f. d$ H/ e5 Z
Equity语法结构简单,语句意思明确,有开发经验的童鞋一看基本能明白合约的意思。编写智能合约可以参考Equity合约介绍,文档中对Equity语言的语法和编译方法都做了详细的介绍。此外,文档还对一些典型的模板合约进行了介绍,开发者可以自己需求进行参考。# u( I7 k# R/ o3 P
编译并实例化合约
$ s) Z- y, d/ T* c5 f编译合约目前支持两种方式,一种是使用Equity编译工具,另一种是调用比原链中编译合约的RPC接口compile; 而合约实例化是为了将合约脚本按照用户设定的参数进行锁定,编译并实例化合约可以参考编译并实例化合约的上半部分说明,该文档不仅介绍了合约的参数构造说明,还对编译合约的步骤进行详细说明。而编译器以及相关工具位于Equity编译器中,是使用go语言开发的,用户可以下载源代码并编译使用。5 S) R1 s# O' Z/ Z: e9 w6 M0 J
工具编译和实例化示例如下:5 H) t# b5 _8 h; ~
// compile
7 r$ o5 j! M6 t) C! J./equity [contract_name] --bin
6 F% m5 f& O- d4 O$ n// instance9 _8 o+ [4 Y( P2 k% _
./equity [contract_name] --instance [arguments ...]
& E! [0 W* d: Q5 m; Y2. 部署合约5 ?8 u+ ]! ], f% j, K- N
部署合约即发送合约交易,调用比原链的build-transaction接口将指定数量的资产发送到合约program中,只需将输出output中接收方control_program设置为指定合约即可。用户可以参考合约交易说明中的锁定合约章节,交易的构造按照文档中介绍进行参考即可。如果合约交易发送成功,并且交易已经成功上链,便可以通过调用API接口list-unspent-outputs来查找该合约的UTXO。
, O9 d+ o8 k( t; ~- Q部署合约交易模板大致如下:
! X9 u6 D4 X1 ]* h3 r7 Q6 V{
. t( b: J3 A" |  "actions": [
% R4 b; y, d1 }+ ~2 e2 E( E    // inputs
4 R8 q) a* E1 O* m    {. x5 U/ y) l, X
        // btm fee
2 Z7 V# p  F7 L# `; j    },
; Y/ p8 o; T+ D# x( ^: ~    {
; i1 s( Y( n9 i" W0 Z! E        amount, asset, spend_account' z* [2 }- c: g, U
        // spend user asset7 m& `; w1 ?6 K0 Y
    },
7 F! T& _! n2 s) i1 y    // outputs. j0 o* D$ {' \( \: ]' l$ {
    {; s' f$ `: T; J; t
        amount, asset, contract_program8 A' {2 s  A7 ^# d, ~
        // receive contract program with instantiated result
7 N( X% |# t6 f# Q5 P2 g9 k    }: F( Z# W: N$ a9 z3 T
  ],
# b8 w. E/ H. B  ...3 @; _& Z8 ~5 [+ e: B# K) X
}
7 B# N) s% p5 _7 m3 }3. 搭建DAPP架构0 a! I+ l  ~- @
Bytom的blockcenter服务器是官方开发的去中心化插件钱包服务器,开发者可以按照相关API接口来调用即可。比原链的DAPP总体框架模型如下:
: ]! m; d0 O5 s% d
8 k/ a" Z, ~% b7 j- }DAPP前端
  C. D$ p0 Q( N' K3 R' N' P" f+ h搭建DAPP前端主要包含两个方面:一个是前端与插件钱包的交互,另一个是前端的逻辑处理、以及与缓冲服务器的交互。插件钱包是与区块链节点服务器通信的窗口,一个DAPP为了跟区块链节点进行通信,需要通过借助插件来与后台服务器节点进行交互。比原的插件钱包除了与后台服务器进行交互之外,还包含一些本地业务逻辑处理的接口API,具体内容可以参考一下DAPP开发者向导。由于比原链是基于UTXO模型的区块链系统,交易是由多输入和多输出构成的结构,并且交易输入或输出的位置也需要按照顺序来排列,因此开发DAPP需要前端处理一些构建交易的逻辑。除此之外,合约中的lock-unlock语句中涉及到数量的计算需要根据抽象语法树来进行预计算,计算的结果将用于构建交易,而verify、if-else等其他语句类型也需要进行相关的预校验,从而防止用户在执行合约的时候报错。: ]4 ?$ @( A2 y: H( z( R, P+ O$ L5 q
从功能层面来说,前端主要包含页面的设计、插件的调用、合约交易逻辑的处理、缓冲服务器的交互等。接下来对这几个重要的部分展开说明:' x# M! g3 L( m/ U  z( T; j

) |9 N. Q5 \6 O  o5 d1)前端页面的设计主要是网页界面的设计,这个部分开发者可以自己选择页面模式3 M* X7 B% N+ i3 O- ^( w
4 E* }* G+ W7 K( `, g5 ]) T- P
2)插件钱包已经进行了结构化的封装,并且提供了外部接口给DAPP开发者调用,开发者只需要将插件的参数按照规则进行填充,具体请参考DAPP开发者向导7 @, U+ \4 l2 ?5 F. A$ j) S; H
+ g4 S# I" e" }3 ^! [" K
3)比原链的合约交易是多输入多输出的交易结构,前端需要进行一些预判断逻辑的处理,然后再选择合适的合约交易模板结构。
( t) ^8 I& Y0 F7 x3 G8 ~1 Q; u# _8 x+ X  E' @; N
4)DAPP的插件连接的是去中心化的bycoin服务器,该服务器从比原节点服务器上同步的所有区块信息和交易信息,该部分主要是在插件钱包层进行了高度的封装,用户只需按照接口调用即可。除此之外,需要开发者搭建一个缓冲服务器,不仅可以在管理合约UTXO层面做一些性能方面的处理,而且还可以为DAPP做一些数据存储。开发者可以根据实际需求来开发一些RPC请求接口,然后在前端页面设置相关条件来触发这些API的调用。
, D# h, ~; ?/ r4 K. K+ A% s0 b6 H! x9 z! K  A0 G- |! i4 i

; j! T5 v) h% ]+ \! v' c' }- J前端逻辑处理流程大致如下:! f! s1 S. _5 u4 J
7 f8 C+ a) s7 X: n0 m4 e1 N# g
调用插件,比原的chrome插件源码位于Bytom-JS-SDK,开发比原DAPP时调用插件的说明可以参考Dapp Developer Guide,其网络配置如下:
+ S  }7 F8 F* d. lwindow.addEventListener('load', async function() {& l9 R- X3 `  x& E% G! X
  if (typeof window.bytom !== 'undefined') {  L% C8 r% O* a! v1 P9 T3 P$ G
    let networks = {
5 @' N" U9 _. |5 Q9 F/ V        solonet: ... // solonet bycoin url
; E3 U8 J9 ~( w# M        testnet: ... // testnet bycoin url
' s% F. c, f6 l7 V        mainnet: ... // mainnet bycoin url 0 \+ s, \/ A% H7 k
    };$ u: d6 @+ r5 W7 z8 r3 K: N
    ...1 a! O0 S0 G# ^9 A
    startApp();/ ~6 a: M5 w  e& N/ I6 N6 {
});
3 {$ h6 c- ]2 w$ D6 G% o' t, X" j5 u* h, w) V
配置合约参数,可以采用文件配置的方式,该步骤是为了让前端得到需要用到的一些已经固定化的合约参数,其前端配置文件为configure.json.js,其示例模型如下:
2 q6 \: ~6 Y% v4 u4 K: s1 c1 G7 Lvar config = {
6 a0 J. V8 e0 w# D/ o! E    "solonet": {
$ E! B5 [6 p: x  l. I: N: H/ x9 y        ...         // contract arguments
! i; H  p( F+ C7 G        "gas": 0.4  // btm fee
5 `3 v. K+ W2 O) a5 n    },) D3 b+ g! r8 A' X: d5 w
    "testnet":{
: A! ]8 V7 T1 f        ...
9 X1 Z' n7 D3 Z# [    },9 B: N: x8 V8 ~$ R" B- u2 f) S
    "mainnet":{
( u/ _" S& G8 [; O* I% Q; A        ...
- A  ]  W7 l1 e! K$ g$ m# k; K/ U    }+ u- O1 d2 b& c4 j( U, n2 {
}( ?8 {8 {- \$ _" }# E0 T
0 y- y0 z, l6 Y4 X9 d# x
前端预计算处理,如果合约中包含lock-unlock语句,并且Amount是一个数值表达式,那么前端来提取计算表达式并进行相应的预计算。此外,前端还需要预判下所有可验证的verify语句,从而判定交易是否可行,因为一旦前端对这些验证失败,合约将必然验证失败。此外,如果define或assign语句涉及的变量,前端也需预计算这些变量的值。" M2 A  p0 I5 H# w' _: K2 f

  `8 H4 j( n- S5 k; L0 V构建合约交易模板,由于解锁合约是解锁lock语句条件,构造交易需要根据lock语句或unlock语句来进行变换。解锁合约交易是由inputs和outputs构成,交易的第一个input输入一般都是是固定的,即合约UTXO的hash值,除此之外,其他输入输出都需要根据DAPP中的实际合约来进行变更,其模型大致如下:
8 ?, Y5 i% o4 p& k( wconst input = []8 o9 I1 i. Z/ k9 H+ o
input.push(spendUTXOAction(utxohash)). r" t9 q! g2 I" n# D/ q
... // other input2 A. |' h8 E3 w$ j7 A
const output = []& `+ r- Y  R: U3 c* H7 N' j
output.push(controlProgramAction(amount, asset, program))
$ x9 M3 Q, X7 @+ w* E3 b... // other output1 p0 _! U& B6 \( k/ W

: r. ^& z% t/ b3 ?9 R; ]9 Q启动前端服务
; @+ g5 t, E8 B& U  Q编译前端命令如下:
  ?% X; g; e2 V9 \% |9 f$ unpm run build0 Z. e) h, R( y& Z
启动之前需要先启动bufferserver缓冲服务器,然后再启动前端服务,其前端启动命令如下:3 n7 W/ N3 K- y) F/ s" a
npm start
2 u2 H8 P4 g, x* U
& L3 d; h; W, y, C9 y' p% s: y& r8 }' \$ z
DAPP缓冲服务器( [1 B2 g1 s9 L* O$ t. Q
缓冲服务器主要是为了在管理合约UTXO层面做一些效率方面的处理,包括了对bycoin服务器是如何同步请求的,此外对DAPP的相关交易记录也进行了存储。bycoin服务器是比原链的去中心化钱包服务器,缓冲服务器的UTXO跟它是同步更新的,比原官方插件钱包默认连接的就是该服务器。尽管bycoin服务器的也对比原链的所有UTXO进行了管理,但是由于UTXO数量比较大,如果直接在该层面处理会导致DAPP性能不佳,所以建议用户自己构建自己的缓冲服务器做进一步优化处理。此外,DAPP开发者也可以搭建了自己的去中心化钱包服务器,并且自己开发相关的插件。8 r6 R; r/ h+ P( y) M
缓冲服务器架构可以参考一下bufferserver案例的源代码,其编译和启动步骤如下:
/ H6 h2 Y  Q$ }# r" k! ?  k0 i8 p. D2 F' Z/ N9 w; d
编译bufferserver源代码& Q' f. W" r# N; j
按照README安装部署服务需要的软件包Mysql和Redis,然后下载源代码并编译:  w9 c+ V, J# R. g0 S, B
make all* X  B% L1 I$ _2 \: v1 n2 o
编译完成之后,在target目录下会生成可执行文件api和updater。
( V, i; N4 F! w1 k6 N* ]
3 S1 }  @- {) w% }/ }启动服务
6 T) {) C- }( `- T$ x6 [使用root用户创建数据库和数据表,其命令如下:
$ Y7 @2 O' }2 t  ^2 b/ Ymysql -u root -p ( q1 k. Q" R! N
修改配置文件config_local.json,配置说明参考README的config配置参数详解。
+ w& O. o; l9 n* S启动api和updater服务器,其中api是提供JSON RPC请求的服务进程,updater是提供同步blockcenter和区块链浏览器数据请求的服务进程。3 k" {# x" `8 M  p5 _
./target/api config_local.json
( l/ C9 H+ i9 O' q! ^: f./target/updater config_local.json% v; A6 I: t" Y% O# z
启动缓冲服务器之后,便可以启动前端服务,然后打开DAPP的网页URL即可使用。5 P2 \& `  x3 @6 f0 e9 H
附:缓冲服务器的JSON RPC接口可以参考wiki接口说明。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

zmhg799417 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    16