基于以太坊搭建私有链并部署智能合约
前言
最近有些懒了,好久没更新博客,前阵子研究以太坊智能合约,当时记录了些东西,不过是保存的草稿,这两天翻后台的时候才发现并发布了出来(o(╯□╰)o),以下内容可以作为以太坊的入门开发教程,有需要的伙伴可以瞧瞧(评论功能已开放,欢迎留言),后面我会开源几个DApp到时候分享出来,有时间的话会再写几篇相关文章抛转引玉。
如果你完全没听说过以太坊,那你需要先去搜索了解下它具体是什么\有什么用,网络wiki上有很详细标准的介绍,我就不阐述了。言归正传,为何需要搭建一个以太坊私有链呢?
因为在以太坊公有链上发起交易、部署智能合约等都需要消耗以太坊代币(ETH),而以太坊本身也是一个平台,我们可以直接在上面开发、部署分布式应用,搭建一个私有链既可以不用同步公有链庞大的数据,也不用花钱买代币,可以很好地满足智能合约的开发和测试要求,而且开发好的智能合约将来也可以很容易地切换接口部署到以太坊公有链上。
前期准备
以太坊客户端
以太坊客户端用于接入以太坊网络,进行账户管理、交易、挖矿、智能合约相关的操作。目前有多种语言实现的客户端,常用的有 Go 语言实现的 go-ethereum 客户端Geth
,支持接入以太坊网络并成为一个完整节点,也可作为一个 HTTP-RPC 服务器对外提供 JSON-RPC 接口。
其他的客户端有:- Parity:Rust 语言实现
- cpp-ethereum:C++ 语言实现
- ethereumjs-lib:JavaScript 语言实现
- Ethereum(J):Java 语言实现
- ethereumH:Haskell 语言实现
- pyethapp: Python 语言实现
- ruby-ethereum:Ruby 语言实现
智能合约编译器
以太坊支持两种智能合约的编程语言:Solidity
和Serpent
。Serpent 语言面临一些安全问题,现在已经不推荐使用了。Solidity 语法类似 JavaScript,它的编译器 solc 可以把智能合约源码编译成以太坊虚拟机 EVM 可以执行的二进制码。
现在以太坊提供更方便的在线 IDE —— Remix https://remix.ethereum.org 使用 Remix,免去了安装 solc 和编译过程,它可以直接提供部署合约所需的二进制码和 ABI。以太坊钱包
以太坊提供了图形界面的钱包 Ethereum Wallet 和 Mist Dapp 浏览器。钱包的功能是 Mist 的一个子集,可用于管理账户和交易;Mist 在钱包基础上,还能操作智能合约。为了演示合约部署过程,本文使用了 Geth console 操作,没有用到 Mist,当然,使用 Mist 会更简单。
安装环境
没有特别要求,可以去Geth官网下载操作系统对应的版本,本文演示环境为阿里云下Ubuntu 16.04 x64 2核4G
的主机。
安装以太坊客户端
为了方便,我们直接从Geth官网下载已经编译完成的二进制文件
wget https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.7.3-4bb3c89d.tar.gz
tar -zxvf geth-linux-amd64-1.7.3-4bb3c89d.tar.gz
编辑/etc/profile
,配置环境变量
export PATH=$PATH:/root/geth/
通过source /etc/profile
使得配置生效,可执行 geth version
查看版本,成功返回的结果如下
root@blockchain-node-sh:~# geth version
Geth
Version: 1.7.3-stable
Git Commit: 4bb3c89d44e372e6a9ab85a8be0c9345265c763a
Architecture: amd64
Protocol Versions: [63 62]
Network Id: 1
Go Version: go1.9.2
Operating System: linux
GOPATH=
GOROOT=/usr/local/go
私有链搭建
一、配置「创世纪块」
新建一个mychain
的目录,在其中创建一个 genesis.json
文件,内容如下
{
"config": {
"chainID": 1024,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"alloc": {},
"coinbase": "0x0000000000000000000000000000000000000000",
"difficulty": "0x100",
"extraData": "",
"gasLimit": "0x2fe9a0",
"nonce": "0xfeadbeefdeedceef",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp": "0x00"
}
其中,chainID
指定了独立的区块链网络 ID。网络 ID 在连接到其他节点的时候会用到,以太坊公网的网络 ID 是 1,为了不与公有链网络冲突,运行私有链节点的时候要指定自己的网络 ID。不同 ID 网络的节点无法相互连接。配置文件还对当前挖矿难度 difficulty
、区块 Gas 消耗限制 gasLimit
等参数进行了设置。
在 Geth 1.6+ 中,以太坊提供了一个生成创世块的向导工具:puppeth。并且提供了更适合在私有链中使用的 Clique PoA 共识算法。puppeth 的使用,可以参照《利用puppeth搭建POA共识的以太坊私链网络》
二、初始化「写入创世区块」
准备好创世区块配置文件后,需要初始化区块链,将上面的创世区块信息写入到区块链中。首先要新建一个目录用来存放区块链数据,我们在 ~/mychain
目录下新建 data
目录,创建完后目录结构应该是这样的:
root@blockchain-node-sh:~/mychain# tree -c
.
├── genesis.json
└── data
1 directory, 1 file
接下来进入 mychain
执行初始化命令
cd mychain
geth --datadir data init genesis.json
初始化区块链之后,会将「创世块」写入区块中,看到以下结果说明初始化成功了
root@blockchain-node-sh:~/mychain# geth --datadir data init genesis.json
WARN [02-06|11:15:02] No etherbase set and no accounts found as default
INFO [02-06|11:15:02] Allocated cache and file handles database=/root/mychain/data/geth/chaindata cache=16 handles=16
INFO [02-06|11:15:02] Writing custom genesis block
INFO [02-06|11:15:02] Successfully wrote genesis state database=chaindata hash=a9f2f3…9bfc24
INFO [02-06|11:15:02] Allocated cache and file handles database=/root/mychain/data/geth/lightchaindata cache=16 handles=16
INFO [02-06|11:15:02] Writing custom genesis block
INFO [02-06|11:15:02] Successfully wrote genesis state database=lightchaindata hash=a9f2f3…9bfc24
初始化成功后,会在数据目录 data
中生成 geth
和 keystore
两个文件夹,此时目录结构如下
root@blockchain-node-sh:~/mychain# tree -c
.
├── genesis.json
└── data
├── geth
│ ├── chaindata
│ │ ├── 000001.log
│ │ ├── CURRENT
│ │ ├── LOCK
│ │ ├── LOG
│ │ └── MANIFEST-000000
│ └── lightchaindata
│ ├── 000001.log
│ ├── CURRENT
│ ├── LOCK
│ ├── LOG
│ └── MANIFEST-000000
└── keystore
5 directories, 11 files
其中 geth/chaindata
中存放的是区块数据,keystore
中存放的是账户数据。
三、启动私有链节点
初始化完成后,私有链的配置就已经完成了,在终端中输入以下命令即可启动节点:
geth --identity "MyChain" --rpc --rpcport "8545" --datadir data --port "30303" console
上面命令的主体是 geth console,表示启动节点并进入交互式控制台,各选项含义如下:
- identity:指定节点 ID
- rpc:表示开启 HTTP-RPC 服务
- rpcport:指定 HTTP-RPC 服务监听端口号(默认为 8545)
- datadir:指定区块链数据的存储位置
- port:指定和其他节点连接所用的端口号(默认为 30303)
运行上面的命令后,就启动了区块链节点并进入了该节点的控制台:
···
INFO [02-06|11:21:27] HTTP endpoint opened: http://127.0.0.1:8545
INFO [02-06|11:21:27] IPC endpoint opened: /root/mychain/data/geth.ipc
Welcome to the Geth JavaScript console!
instance: Geth/MyChain/v1.7.3-stable-4bb3c89d/linux-amd64/go1.9.2
modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
>
>
这是一个交互式的 JavaScript 执行环境,在这里面可以执行 JavaScript 代码,其中 >
是命令提示符。在这个环境里也内置了一些用来操作以太坊的 JavaScript 对象,可以直接使用这些对象。这些对象主要包括:
- eth:包含一些跟操作区块链相关的方法;
- net:包含一些查看p2p网络状态的方法;
- admin:包含一些与管理节点相关的方法;
- miner:包含启动&停止挖矿的一些方法;
- personal:主要包含一些管理账户的方法;
- txpool:包含一些查看交易内存池的方法;
- web3:包含了以上对象,还包含一些单位换算的方法。
具体的用法可以前往参阅官网文档
控制台操作
进入以太坊 Javascript Console 后,就可以使用里面的内置对象做一些操作,这些内置对象提供的功能很丰富,比如查看区块和交易、创建账户、挖矿、发送交易、部署智能合约等。
常用命令有:
- personal.newAccount():创建账户;
- personal.unlockAccount():解锁账户;
- eth.accounts:枚举系统中的账户;
- eth.getBalance():查看账户余额,返回值的单位是 Wei(Wei 是以太坊中最小货币面额单位,类似比特币中的聪,1 ether = 10^18 Wei);
- eth.blockNumber:列出区块总数;
- eth.getTransaction():获取交易;
- eth.getBlock():获取区块;
- miner.start():开始挖矿;
- miner.stop():停止挖矿;
- web3.fromWei():Wei 换算成以太币;
- web3.toWei():以太币换算成 Wei;
- txpool.status:交易池中的状态;
- admin.addPeer():连接到其他节点;
这些命令支持 Tab 键自动补全。
一、创建账户 personal.newAccount()
> personal.newAccount()
Passphrase:
Repeat passphrase:
"0x2b8e32e869ec17b120b8b866a7852b2d593c4a05"
输入两遍密码后会生成一个账户地址
再创建一个
> personal.newAccount()
Passphrase:
Repeat passphrase:
"0x7ff4850044c42e9895c9b5e966293d29cae7fa23"
查看刚刚创建的两个账户地址
> eth.accounts
["0x2b8e32e869ec17b120b8b866a7852b2d593c4a05", "0x7ff4850044c42e9895c9b5e966293d29cae7fa23"]
二、查看账户余额 eth.getBalance()
> eth.getBalance(eth.accounts[0])
0
> eth.getBalance(eth.accounts[1])
0
三、启动&停止挖矿
启动挖矿
miner.start(8)
其中 start 的参数表示挖矿使用的线程数。第一次启动挖矿会先生成挖矿所需的 DAG 文件,这个过程有点慢,等进度达到 100% 后,就会开始挖矿,此时屏幕会被挖矿信息刷屏。
停止挖矿
miner.stop()
挖到一个区块会奖励5个以太币,挖矿所得的奖励会进入矿工的账户,这个账户叫做 coinbase,默认情况下 coinbase 是本地账户中的第一个账户,可以通过 miner.setEtherbase()
将其他账户设置成 coinbase。
四、发送交易
在开启挖矿一阵子之后,可以查看到账户中已经有挖出块的奖励了
> eth.getBalance(eth.accounts[0])
8.845e+21
> web3.fromWei(eth.getBalance(eth.accounts[0]),'ether')
8845
> eth.getBalance(eth.accounts[1])
0
现在从「账户0」给「账户1」转账,要先解锁「账户0」,才能发起交易
> personal.unlockAccount(eth.accounts[0])
Unlock account 0x2b8e32e869ec17b120b8b866a7852b2d593c4a05
Passphrase:
true
发送一笔交易,「账户0」 -> 「账户1」
> amount = web3.toWei(500,'ether')
"500000000000000000000"
> eth.sendTransaction({from:eth.accounts[0], to:eth.accounts[1], value:amount})
INFO [02-07|10:30:24] Submitted transaction fullhash=0xe2d74696c4186c1fa0e09c439dd81e89142c67cddeacd833cff90cce76496246 recipient=0x7Ff4850044c42E9895C9B5e966293d29Cae7FA23
"0xe2d74696c4186c1fa0e09c439dd81e89142c67cddeacd833cff90cce76496246"
此时如果没有挖矿,用 txpool.status
命令可以看到本地交易池中有一个待确认的交易,可以使用 eth.getBlock("pending", true).transactions
查看当前待确认交易。
> txpool.status
{
pending: 1,
queued: 0
}
> eth.getBlock("pending", true).transactions
[{
blockHash: "0xda45c4ee7de84396f4ba562c666306ea97e4a7445fc36ffbb6a36c10c0fbf610",
blockNumber: 1770,
from: "0x2b8e32e869ec17b120b8b866a7852b2d593c4a05",
gas: 90000,
gasPrice: 18000000000,
hash: "0xe2d74696c4186c1fa0e09c439dd81e89142c67cddeacd833cff90cce76496246",
input: "0x",
nonce: 0,
r: "0xdadeb2f45f55e62c4d8068d4c167a98f246cc2c70ea654ef67a593aa77530081",
s: "0x4ea040b97103fab958da4a760ae3f90b3c905def471699551a8b5f712f51f4f4",
to: "0x7ff4850044c42e9895c9b5e966293d29cae7fa23",
transactionIndex: 0,
v: "0x824",
value: 500000000000000000000
}]
使用 miner.start() 命令开始挖矿
> miner.start(1);admin.sleepBlocks(1);miner.stop();
新区块挖出后,挖矿结束,查看「账户1」的余额,已经收到了「账户0」的以太币
> web3.fromWei(eth.getBalance(eth.accounts[1]),'ether')
500
五、查看交易和区块
查看当前区块总数
> eth.blockNumber
1770
根据上面交易返回的Hash
查看交易详情
> eth.getTransaction("0xe2d74696c4186c1fa0e09c439dd81e89142c67cddeacd833cff90cce76496246")
{
blockHash: "0xd58ac4d3434e8f485b1d4a8a741bebbfe3360e3b01c1f6380b9b1a8c1edbba7c",
blockNumber: 1770,
from: "0x2b8e32e869ec17b120b8b866a7852b2d593c4a05",
gas: 90000,
gasPrice: 18000000000,
hash: "0xe2d74696c4186c1fa0e09c439dd81e89142c67cddeacd833cff90cce76496246",
input: "0x",
nonce: 0,
r: "0xdadeb2f45f55e62c4d8068d4c167a98f246cc2c70ea654ef67a593aa77530081",
s: "0x4ea040b97103fab958da4a760ae3f90b3c905def471699551a8b5f712f51f4f4",
to: "0x7ff4850044c42e9895c9b5e966293d29cae7fa23",
transactionIndex: 0,
v: "0x824",
value: 500000000000000000000
}
通过区块号查看区块
eth.getBlock(1770)
{
difficulty: 259239,
extraData: "0xd783010703846765746887676f312e392e32856c696e7578",
gasLimit: 4712388,
gasUsed: 21000,
hash: "0xd58ac4d3434e8f485b1d4a8a741bebbfe3360e3b01c1f6380b9b1a8c1edbba7c",
logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
miner: "0x2b8e32e869ec17b120b8b866a7852b2d593c4a05",
mixHash: "0x56f43f7f8f3191177ce39d859bf470b79b09845bbce025483be8290802c0b0f9",
nonce: "0x0888dfc33def060a",
number: 1770,
parentHash: "0xc0529ca39530fc4a759e839272aba82f028f7243d28441334cca8549cb3d06ae",
receiptsRoot: "0x5cd1205318b43d21a6ad398c5ac833fb47705990d07c34988915f10201a893e4",
sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
size: 654,
stateRoot: "0xa3f08a91d5f3a4bf16b2f5b722ac9030ba7feb9e2dd885d4e24e74d5aa79e843",
timestamp: 1517971336,
totalDifficulty: 355546930,
transactions: ["0xe2d74696c4186c1fa0e09c439dd81e89142c67cddeacd833cff90cce76496246"],
transactionsRoot: "0xc0f7643b406ad1aff74e9165a9e1db82295841a6921adf426d96ecc8cb4cbbee",
uncles: []
}
六、节点互连
以上均是单节点操作,而实际一个健壮的区块链网络是由大量的节点构成,通过 admin.addPeer()
方法可以连接到其他节点,相同节点要指定相同的chainID。
在本地电脑安装好Geth
环境后,需要指定相同的「创世块」genesis.json
文件和相同的ChainID
假设上面我们搭建的那个节点为「节点一」,在本机电脑上搭建的为「节点二」
在「节点一」执行 admin.nodeInfo.enode
可以获取 enode
信息
> admin.nodeInfo.enode
"enode://0ceafcae30c783ddcbb3d0ad8a5dd5a061bfb96efc94a7bf7a4e431a80e52e662cdb5fe717c9de45342d0f75264d3799386ccc7da214c2118946391ce907ccaa@[::]:30303"
在「节点二」的 console 中执行 admin.addPeer()
,就可以连接到「节点一」
> admin.addPeer("enode://0ceafcae30c783ddcbb3d0ad8a5dd5a061bfb96efc94a7bf7a4e431a80e52e662cdb5fe717c9de45342d0f75264d3799386ccc7da214c2118946391ce907ccaa@106.14.170.6:30303")
true
注意:「节点一」生成的enode中[::]
需要换成相应的IP地址,且要注意防火墙是否开放相应端口。
连接成功后,「节点二」就会开始同步「节点一」的区块,同步完成后,任意一个节点开始挖矿,其他节点会自动同步区块,向任意一个节点发送交易,其他节点也会收到该笔交易。
通过 admin.peers
可以查看连接到的其他节点信息,通过 net.peerCount
可以查看已连接到的节点数量。
除了上面的方法,也可以在启动节点的时候指定 --bootnodes
选项连接到其他节点。
智能合约操作
一、创建和编译智能合约
有多种方式来新建和编译智能合约,这里介绍两种常见的便捷方式:
Remix,是一个Solidity开发语言的Ide,它是一款运行在浏览器端的在线solidity ide,也是官方推荐使用的ide,无需在本地安装搭建环境,可以方便快捷地在线编写、编译、部署智能合约。
通过npm来安装solc,
npm i -g solc
环境安装成功后,接下来新建一个 Solidity 智能合约文件,命名为 testContract.sol
,该合约包含一个方法 multiply()
,将输入的两个数相乘后输出:
pragma solidity ^0.4.0;
contract TestContract
{
function multiply(uint a, uint b) public pure returns (uint)
{
return a * b;
}
}
编译智能合约,获得编译后的 EVM 十六进制码:
$ solcjs --bin testContract.sol
$ cat testContract_sol_TestContract.bin
6060604052341561000f57600080fd5b60ba8061001d6000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063165c4a16146044575b600080fd5b3415604e57600080fd5b606b60048080359060200190919080359060200190919050506081565b6040518082815260200191505060405180910390f35b60008183029050929150505600a165627a7a7230582089c979bfe42c5794d1b92af4acc41048cb266a1be566c9e3699e58a3cb6e9d800029
再用 solc 获取智能合约的 JSON ABI(Application Binary Interface),其中指定了合约接口,包括可调用的合约方法、变量、事件等:
$ cat testContract_sol_TestContract.abi
[{"constant":true,"inputs":[{"name":"a","type":"uint256"},{"name":"b","type":"uint256"}],"name":"multiply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"}]
回到 Geth 的控制台,用变量 code
和 abi
来记录上面两个值,注意在 code
前加上 0x
前缀:
> code = "0x6060604052341561000f57600080fd5b60ba8061001d6000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063165c4a16146044575b600080fd5b3415604e57600080fd5b606b60048080359060200190919080359060200190919050506081565b6040518082815260200191505060405180910390f35b60008183029050929150505600a165627a7a7230582089c979bfe42c5794d1b92af4acc41048cb266a1be566c9e3699e58a3cb6e9d800029"
> abi = [{"constant":true,"inputs":[{"name":"a","type":"uint256"},{"name":"b","type":"uint256"}],"name":"multiply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"}]
二、部署智能合约
这里使用「账户0」来部署合约,首先解锁账户:
> personal.unlockAccount(eth.accounts[0])
Unlock account 0x132acf5dbb300cc8ccc03ee05d3e1e90409908fb
Passphrase:
true
发送部署合约的交易:
> myContract = eth.contract(abi)
...
> contract = myContract.new({from:eth.accounts[0],data:code,gas:1000000})
INFO [02-24|10:21:43] Submitted contract creation fullhash=0x099a297160a071e3040bee1514c681bfc8cc1b002df60fc5975a2639634eed21 contract=0xA818D8384D86f1e0d9Cd355A279110b2ccA44DEC
{
abi: [{
constant: true,
inputs: [{...}, {...}],
name: "multiply",
outputs: [{...}],
payable: false,
stateMutability: "pure",
type: "function"
}],
address: undefined,
transactionHash: "0x099a297160a071e3040bee1514c681bfc8cc1b002df60fc5975a2639634eed21"
}
此时如果没有挖矿,用 txpool.status
命令可以看到本地交易池中有一个待确认的交易
> txpool.status
{
pending: 1,
queued: 0
}
> eth.getBlock("pending", true).transactions
[{
blockHash: "0xae0c63885ea0f9a8fda46e4568606eddb453a386c27213195a5b9649d0088aa2",
blockNumber: 1989,
from: "0x132acf5dbb300cc8ccc03ee05d3e1e90409908fb",
gas: 1000000,
gasPrice: 18000000000,
hash: "0x099a297160a071e3040bee1514c681bfc8cc1b002df60fc5975a2639634eed21",
input: "0x6060604052341561000f57600080fd5b60ba8061001d6000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063165c4a16146044575b600080fd5b3415604e57600080fd5b606b60048080359060200190919080359060200190919050506081565b6040518082815260200191505060405180910390f35b60008183029050929150505600a165627a7a7230582089c979bfe42c5794d1b92af4acc41048cb266a1be566c9e3699e58a3cb6e9d800029",
nonce: 9,
r: "0xe4c6ae4d28dedda6b7145dcd1fabc4016535180adecb34a0abb984bed9d8ee31",
s: "0x4abc769013e775b97acf023a9f22fd672fdac23e48692127302d09efcfbd0b94",
to: null,
transactionIndex: 0,
v: "0x823",
value: 0
}]
使用 miner.start()
命令开始挖矿,一段时间后交易会被确认,随新区块进入区块链。
三、调用智能合约
使用以下命令发送交易,sendTransaction
方法的前几个参数应该与合约中 multiply
方法的输入参数对应。这种情况下,交易会通过挖矿记录到区块链中(注意:部署和「修改合约内数据」的调用本质都是发起一个交易):
> contract.multiply.sendTransaction(2, 4, {from:eth.accounts[0]})
INFO [02-24|10:27:01] Submitted transaction fullhash=0xa066b8dfe2f78296e6dd25518c3cf68b2489bcc571679f4bdfe92a4705ea2405 recipient=0xA818D8384D86f1e0d9Cd355A279110b2ccA44DEC
"0xa066b8dfe2f78296e6dd25518c3cf68b2489bcc571679f4bdfe92a4705ea2405"
如果只是本地运行该方法查看返回结果,可以采用如下方式(本地调用查询,不涉及修改合约内部数据,不需要广播至区块链,不会消耗手续费):
> contract.multiply.call(2, 4)
8
以上就是在以太坊上开发部署智能合约的简单示例。
附言
目前并非所有场景都需要使用区块链技术,从网络节点设计层面来看,当前技术水平的区块链网络为达到更高的安全性、更好的信任效果,会消耗更多资源,在使各方信任成本降低的同时,也导致全网网络运营总成本偏高,区块链技术应用场景应该遵循如下四个原则:
第一,多信任主体:区块链是信任机器,应用环境最好是相互之间没有天然信任关系(如不同企业主体之间),需要通过区块链来搭建信任。反之,如果双方是强信任关系,或已有完善的制度保障,使用区块链的必要性就不大。
第二,多方协作:如果该场景协作方多,对账成本高,区块链底层的共享账本之上搭建的智能合约能够降低对账成本,从而提升效率。
第三,中低频交易:区块链目前的并发性和扩展性还不足以应用于大规模高频交易,比如股票交易所。
第四,商业逻辑完备:区块链节点之间一定要有完备的商业逻辑,形成多赢局面,参与者才有动力使用整条区块链。
相关术语说明
- ABI(Application Binary Interface)应用二进制接口,其中指定了合约接口,包括可调用的合约方法、变量、事件等。
- DApp(Decentralized App)去中心化的应用程序,基于智能合约的应用称为去中心化的应用程序。
- EVM(Ethereum Virtual Machine),以太坊虚拟机,以太坊智能合约的运行环境。
- Gas(消耗的)汽油,在以太坊上发起交易、部署合约和调用合约都要消耗一定量的以太币,这些消耗的以太币称为 Gas。
- Geth 以太坊客户端 go-ethereum,使用 Go 语言编写,是最常用的以太坊客户端之一。
- Solidity 以太坊智能合约的一种编程语言,类似 JavaScript。
- Remix IDE 在线地址,基于浏览器的 Solidity 集成开发环境,在浏览器中编写和调试智能合约。
参考资料
- 《区块链——原理、设计与应用》杨保华、陈昌编著,机械工业出版
- 以太坊学习笔记:私有链搭建操作指南
- 利用puppeth搭建POA共识的以太坊私链网络
- 区块链技术指南
- Solidity 官方文档
- Go 官方文档
- 其他
学习了!
厉害,连你也去捣鼓区块链了。。
哈哈,比较感兴趣,就随便折腾折腾了