在了解智能合约和传统合约之前我们先来了解合约(Contract)这个词本身,“合同(或合约),是双方当事人基于意思表示合致而成立的法律行为,为私法自治的主要表现。”在现在的日常生活中合约常常是由人或者指定的机构来代为执行的,这就是传统合约。
“智能合约(Smart contract)"这个概念由计算机科学家、加密学家尼克萨博(NickSzabo) 在1993年提出并且在1994年完成了《智能合约》论文。该论文成为了智能合约的开山之作。作为一位通过给比特币打下基础而受到广泛赞誉的密码学家,尼克萨博为智能合约下的定义:“A smart contract is a set of promises defined in digital form, including agreements on which contract participants can execute these commitments.。
传统合约其实也在演化,尤其是网购这种行为已经智能合约,所谓的"智能"就是脱离了人和机构,交由计算机去管理和执行的自动行为。 以网购为例,我们来了解智能合约的显著特征。下面假设 买家A
通过淘宝Alipay
向卖家B
买价值为100$的东西,那么计算机所执行的操作逻辑如下(LaTeX作图):
本质上是如下的单一关系(Word作图0.0)
在这其中,支付宝(Alipay)是合约状态的判定者,钱的由支付宝保管,交易受支付宝监管。支付宝是合约的判定者和执行者,双方的资产转移,查询也全部由支付宝完成。
交易的状态判定和资产转移全部交给计算机重复地自动地执行,这就是典型的智能合约
这样的智能合约有很多隐患。我们不妨将合约判定者推广到支付宝以外的各个银行,交易机构甚至是日常生活中,只要中介机构的判断一方出现问题,你并没有收到东西,但是中介机构作假说判定卖家已经完成交易,你的钱已经被转走,那就可以破坏整个交易的公平性。或者交易机构的处理不够及时也能够造成损失。
之前所提到的大佬,加密学家萨博 就认为这种仅仅依靠第三方担保的信用机制是不可靠的,
经过一番思考他认为所有的交易合同都没有必要通过第三方完成,只要合同的条款可以用编程语言来表达,让计算机自动处理就行了。这样就避免了合同执行中的尔虞我诈,还节约了大量的交易成本。
然而这个想法也只是一个雏形,在他所处的90年代还没有数字资产,也没有很强大的计算机加密手段提出。这使得他的这种思想并不能很好地实践,而仅仅是用在了构建自动售货机、自动售票机的交易模式上。他缺少四样东西:
而区块链的出现,使得萨博在90年代提出的超越时代的构想有了变为现实的能力。
我们来想想区块链的特征:
Σ(っ °Д °;)っ这,这不就是…
是的,你会发现,这些特性完美地契合了萨博在90s的构想 (๑•̀ㅂ•́)و✧。
智能合约一旦上链,就没有了像之前依赖一方信任机构时各种各样的安全风险,并且变得透明,可追溯。
同样对上述买家A
与卖家B
的交易,如果网购使用基于区块链的智能合约来完成,则你会发现缺少了Alipay
,取而代之的是各式节点,流程图如下:(在线作图0.0)
买家卖家双方,应用程序和管理员全部通过Peer节点来同步信息,Peer节点一手拿着账本(Ledger),一手拿着合约(ChainCode)。上图只是简单地描述整个过程,事实上一个Application/SDK会连接多个Peer节点和Order节点,网络图也更加复杂,并且Peer节点所持有的账本也有可能会是多项。
从上述的过程中就可以明白只要大多数的节点没有崩坏,那么交易就是安全的,而不像传统节点那样依赖中介机构一方的数据;并且由于Orderer和Peer节点定时以及定量地去检查交易的状态,使得交易的执行也是及时的。智能合约中更多地是P2P的交易,这使得很多交易可以透明,安全地完成而不需要第三方去监管。
从上述对于上链过后的智能合约的简单描述中也可以知晓ChainCode负责的是P2P用户之间已经协商好的规则,也就是合约本身的内容,这个关键的规则应该被提前写入智能合约中。那么我们来分析ChainCode应该去完成的基本内容:
在区块链的开放当中我们使用的是yaml文件,百科出门右转。
yaml =“Yet Another Markup Language” 从英文解释可以看出yaml仍然是一种标志语言。它要比json方便,同时简洁而强大。话不多说,直接上fabric中的自带yaml配置文件docker-compose-simple.yaml
(节选其中Orderer部分):
orderer:
container_name: orderer
image: hyperledger/fabric-orderer
environment:
- FABRIC_LOGGING_SPEC=debug
- ORDERER_GENERAL_LISTENADDRESS=orderer
- ORDERER_GENERAL_GENESISMETHOD=file
working_dir: /opt/gopath/src/github.com/hyperledger/fabric
ports:
- 7050:7050
:
来表示,并且可以复用-
来表示,子成员则在之后缩进那么上述文件对应的JS代码应该如下:
order:
{
container_name:'orderer'
image:'hyperledger/fabric-orderer'}
environment:['FABRIC_LOGGING_SPEC=debug',
'ORDERER_GENERAL_LISTENADDRESS=orderer',
'ORDERER_GENERAL_GENESISMETHOD=file']
working_dir: '/opt/gopath/src/github.com/hyperledger/fabric'
ports:'7050:7050'
}
在docker-compose-simple.yaml
中,我们可以看到基本的结构为
Orderer,Peer,Cli,ChainCode四个部分。
也可以打开docker-compose-base.yaml
查看记录的区块链的基础结构为
两个Org联盟Org1和Org2,各个联盟里面有包含两个Peer节点Peer1和Peer2,同时还各自包含一个Orderer。
类似的文件有很多,例如负责通信的docker-compose-base.ca
和各个connection
文件,基本上fabric里所有的关于结构的配置文件全部都是yaml完成的。在跑源码之前可以先去查看这些文件。
我们需要开三个Terminal来完成client,chaincode的测试。
yaml文件记录了区块链中的Org,Peer,Orderer以及相关结构的具体信息所以我们先
在Terminal 1
中启动 docker-compose-simple.yaml
docker-compose -f docker-compose-simple.yaml up
//结果如下:
Creating orderer ... done
Creating peer ... done
Creating cli ... done
Creating chaincode ... done
Attaching to orderer, peer, cli, chaincode
peer | 2019-05-04 10:48:34.210 UTC [viperutil] getKeysRecursively -> DEBU 001 Found map[string]interface{
} value for peer.BCCSP
orderer | 2019-05-04 10:48:33.111 UTC [localconfig] completeInitialization -> INFO 001 Kafka.Version unset, setting to 0.10.2.0
peer | 2019-05-04 10:48:34.211 UTC [viperutil] unmarshalJSON -> DEBU 002 Unmarshal JSON: value cannot be unmarshalled: invalid character 'S' looking for beginning of value
peer | 2019-05-04 10:48:34.211 UTC [viperutil] getKeysRecursively -> DEBU 003 Found real value for peer.BCCSP.Default se
记得一定要检查oderer,peer,cli,chaincode(这个对于不同的项目,结构不同,以自己的yaml中的结构为准)有没有初始化成功,因为会输出很长的文字,所以不太容易直接看是否允许成功,lz第一次的时候就是peer失败了,但是没有仔细看,结果后面一路报错QAQ。
使用docker ps
查看进程:
docker ps
//结果如下:
CONTAINER ID COMMAND CREATED STATUS PORTS NAMES
c7b0d0a23a54 hyperledger/fabric-ccenv "/bin/bash -c 'sleep…" chaincode
589f8cd7b518 hyperledger/fabric-tools "/bin/bash -c ./scri…" cli
ceeaaf3e5913 hyperledger/fabric-peer "peer node start --p…" 0.0.0.0:7051->7051/tcp, 0.0.0.0:7053->7053/tcp peer
d340752b0409 hyperledger/fabric-orderer "orderer" 0.0.0.0:7050->7050/tcp orderer
在Terminal 2
中输入 以下命令进入chaincode端口:
docker exec -it chaincode bash
进入go脚本sacc的文件夹,编译我们的go脚本:
go build
执行刚刚编译好的sacc:(看到starting up…卡着不动就是正常运行了)
CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=mycc:0 ./sacc
//结果如下:(starting up代表开始运作,之后这个端口会一直记录chaincode的状态)
2019-05-04 10:55:51.401 UTC [shim] SetupChaincodeLogging -> INFO 001 Chaincode log level not provided; defaulting to: INFO
2019-05-04 10:55:51.402 UTC [shim] SetupChaincodeLogging -> INFO 002 Chaincode (build level: ) starting up ...
这里时常会有报错:
因篇幅问题不能全部显示,请点此查看更多更全内容