以下从开发(包括完整测试)的角度梳理每一步的关键点:


搭建区块链

这一步就不细说了,根据现在的开源文档,完全对应配置化就可以了,然后直接一撸到底,具体参见文档:

https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/getstart/index.html

对应的节点起来以后,通过ps -ef | grep fisco 来验证对应目录的节点是否正常启动。


合约的创建与部署

先写一个简单的合约,如下,一个Demo,用来更新合约中的一个balance值,返回对应的地址:

pragma solidity ^0.4.4;

contract Demo{
    uint balance;
    function update(uint amount) returns (address, uint){
        balance += amount;
        return (msg.sender, balance);
    }
}

接着我们通过物料包中的指引,把这个合约放到contract目录下,然后执行部署合约命令把合约部署到区块链上:


[app@VM_100_48_centos tool]$ babel-node deploy.js Demo
RPC=http://0.0.0.0:21334
Ouputpath=./output/
deploy.js  ........................Start........................
Soc File :Demo
Democomplie success!
send transaction success: 0xb3f4275c9ef27ca927d279c33a9991061693504849da14841f5cfbc2f81d259e
Democontract address 0xaed8b4409cd8635bc5dd1315b871e8749e228943
Demo deploy success!
cns add operation => cns_name = Demo
         cns_name =>Demo
         contract =>Demo
         version  =>
         address  =>0xaed8b4409cd8635bc5dd1315b871e8749e228943
         abi      =>[{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"update","outputs":[{"name":"","type":"address"},{"name":"","type":"uint256"}],"payable":false,"type":"function"}]


看到输出为以上格式表示已经部署成功,其中记录下红色的部分,为合约地址,后续的我们项目中需要通过调用这个地址来执行对应的合约。


合约生成对应的Java代码

在对应的dist/bin目录下,我们会看到对应的compile.sh 文件,是用来编译成Java代码,具体执行操作为 sh compile.sh {package},例如生成的合约对象需要放到我的项目中的package路径为:cn.webank.blockchain, 则在对应目录执行: sh compile.sh cn.webank.blockchain,在同级目录下的output文件夹下会看到所有的contract目录的合约文件生成了对应的Java代码,其中就有我们的Demo.java文件。复制到对应的项目即可


如何通过项目直接调用合约

之前区块链节点启动以后,我们可以从其中的web3sdk目录中找到几个文件,对应挪到项目中,主要为:

applicationContext.xml  

ca.crt

client.keystore

其中第一个问SpringContext文件,后两个为证书,由于物料包引用的是Spring2.5的写法,太老了,我们可以从Context文件中抽取我们需要的数据,如果是Springboot项目,对应的Bean文件直接通过在@Configuration文件中注入就好。


对于测试文件来说,整合下放到Test文件中,最终的结果如下:


@Slf4j
DemoTest {

    Demo demo@Before
    setUp() Exception {

        String contractAddress = Web3j web3j = Web3j.build(getChannelEthereumService())Credentials credentials = GenCredential.create()BigInteger gasPrice = BigInteger()BigInteger gasLimited = BigInteger()demo = Demo.load(contractAddressweb3jcredentialsgasPricegasLimited)log.info()}

    Web3jService getChannelEthereumService() Exception {
        ChannelEthereumService channelEthereumService = ChannelEthereumService()channelEthereumService.setChannelService(getChannelService())channelEthereumService.setTimeout()channelEthereumService}

    Service getChannelService() Exception {
        Service service = Service()service.setOrgID()service.setConnectSeconds()service.setConnectSleepPerMillis()ConcurrentHashMap keyID2connections = ConcurrentHashMap<>()ChannelConnections channelConnections = ChannelConnections()channelConnections.setCaCertPath()channelConnections.setClientKeystorePath()channelConnections.setKeystorePassWord()channelConnections.setClientCertPassWord()List list = ArrayList<>()list.add()list.add()channelConnections.setConnectionsStr(list)keyID2connections.put(channelConnections)service.setAllChannelConnections(keyID2connections)service.run()service}

    @Test
    testUpdateBalance() ExecutionExceptionInterruptedException {

        Uint256 balance = Uint256()TransactionReceipt receipt = demo.update(balance).get()Assert.assertNotNull(receipt)}
}



如何通过前置系统测试

有时候为了让客户和区块链节点隔离开,减少上链成本,可能通过前置项目隐藏具体的区块链细节,前置系统的测试方案如下。


和普通的接口测试/场景测试没有区别,如果要做到自动化测试,可以参考另一篇自动化测试的方案,开发添加稍许注解参数即可:

https://blog.51cto.com/14054453/2314500