Hyperledger Fabric Java智能合约实现

  运行环境:ubuntu18.04    docker基础环境

环境变量设置
export FABRIC_PATH=/路径/fabric-samples
export FABRIC_CFG_PATH=${FABRIC_PATH}/config/
export MSP_PATH=${FABRIC_PATH}/test-network/organizations
export CORE_PEER_TLS_ENABLED=true
export PATH=${FABRIC_PATH}/bin:$PATH

maven集成fabric-chaincode-shim,实现区块链智能合约

一、pom.xml 添加依赖
    
        
            central
            http://maven.aliyun.com/nexus/content/groups/public/
            
                true
            
            
                false
            
        
        
            jitpack.io
            https://www.jitpack.io
        
        
            artifactory
            https://hyperledger.jfrog.io/hyperledger/fabric-maven
        
    
    
        
            org.hyperledger.fabric-chaincode-java
            fabric-chaincode-shim
            2.3.0
        

        
            com.alibaba
            fastjson
            1.2.38
        
    
    
        
            
                maven-compiler-plugin
                3.1
                
                    1.8
                    1.8
                
            
            
                org.apache.maven.plugins
                maven-shade-plugin
                3.1.0
                
                    
                        package
                        
                            shade
                        
                        
                            chaincode
                            
                                
                                    org.hyperledger.fabric.contract.ContractRouter
                                
                            
                            
                                
                                    
                                    *:*
                                    
                                        META-INF/*.SF
                                        META-INF/*.DSA
                                        META-INF/*.RSA
                                    
                                
                            
                        
                    
                
            
        
    
二、实现智能合约代码
import com.alibaba.fastjson.JSON;

import java.util.Objects;

/**
 * 用户帐户对象
 */

public class User {
    private String userId;
    private String name;
    private double money;

    public User(final String userId, final String name, final double money) {
        this.userId = userId;
        this.name = name;
        this.money = money;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    public String getName() {
        return name;
    }

    public double getMoney() {
        return money;
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if ((obj == null) || (getClass() != obj.getClass())) {
            return false;
        }
        User other = (User) obj;
        return Objects.deepEquals(
                new String[] {getUserId(), getName()},
                    new String[] {other.getUserId(), other.getName()})
                &&
                Objects.deepEquals(
                        new double[] {getMoney()},
                        new double[] {other.getMoney()});
    }

    @Override
    public int hashCode() {
        return Objects.hash(getUserId(), getName(), getMoney());
    }

    @Override
    public String toString() {
        return JSON.toJSONString(this);
    }

}
import com.alibaba.fastjson.JSON;
import org.hyperledger.fabric.contract.Context;
import org.hyperledger.fabric.contract.ContractInterface;
import org.hyperledger.fabric.contract.annotation.*;
import org.hyperledger.fabric.shim.ChaincodeException;
import org.hyperledger.fabric.shim.ChaincodeStub;
import org.hyperledger.fabric.shim.ledger.KeyModification;
import org.hyperledger.fabric.shim.ledger.KeyValue;
import org.hyperledger.fabric.shim.ledger.QueryResultsIterator;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 智能合约-用户账本
 */
@Contract(name = "UserChainCode")
@Default
public class UserChainCode implements ContractInterface {

    public UserChainCode() {

    }

    /**
     * 初始化3条记录
     */
    @Transaction(intent = Transaction.TYPE.SUBMIT)
    public void init(final Context ctx) {
        addUser(ctx, "1", "mixm",100D);
        addUser(ctx, "2", "admin",200D);
        addUser(ctx, "3", "user",300D);
    }

    /**
     * 获取该id的所有变更记录
     */
    @Transaction(intent = Transaction.TYPE.EVALUATE)
    public String getHistory(final Context ctx, final String userId) {
        Map userHistory = new HashMap<>();
        ChaincodeStub stub = ctx.getStub();
        QueryResultsIterator iterator = stub.getHistoryForKey(userId);
        for (KeyModification result: iterator) {
            userHistory.put(result.getTxId(), result.getStringValue());
        }
        return JSON.toJSONString(userHistory);
    }

    /**
     * 新增用户
     */
    @Transaction(intent = Transaction.TYPE.SUBMIT)
    public String addUser(final Context ctx, final String userId, final String name, final double money) {
        ChaincodeStub stub = ctx.getStub();
        User user = new User(userId, name, money);
        String userJson = JSON.toJSONString(user);
        stub.putStringState(userId, userJson);
        return stub.getTxId();
    }

    /**
     * 查询某个用户
     */
    @Transaction(intent = Transaction.TYPE.EVALUATE)
    public User getUser(final Context ctx, final String userId) {
        ChaincodeStub stub = ctx.getStub();
        String userJSON = stub.getStringState(userId);
        if (userJSON == null || userJSON.isEmpty()) {
            String errorMessage = String.format("User %s does not exist", userId);
            throw new ChaincodeException(errorMessage);
        }
        return JSON.parseObject(userJSON, User.class);
    }

    /**
     * 查询所有用户
     */
    @Transaction(intent = Transaction.TYPE.EVALUATE)
    public String queryAll(final Context ctx) {
        ChaincodeStub stub = ctx.getStub();
        List userList = new ArrayList<>();
        QueryResultsIterator results = stub.getStateByRange("", "");
        for (KeyValue result: results) {
            User user = JSON.parseObject(result.getStringValue(), User.class);
            System.out.println(user);
            userList.add(user);
        }
        return JSON.toJSONString(userList);
    }

    /**
     * 转账
     * @param sourceId 源用户id
     * @param targetId 目标用户id
     * @param money 金额
     */
    @Transaction(intent = Transaction.TYPE.SUBMIT)
    public String transfer(final Context ctx, final String sourceId, final String targetId, final double money) {
        ChaincodeStub stub = ctx.getStub();
        User sourceUser = getUser(ctx, sourceId);
        User targetUser = getUser(ctx, targetId);
        if (sourceUser.getMoney() < money) {
            String errorMessage = String.format("The balance of user %s is insufficient", sourceId);
            throw new ChaincodeException(errorMessage);
        }
        User newSourceUser = new User(sourceUser.getUserId(), sourceUser.getName(), sourceUser.getMoney() - money);
        User newTargetUser = new User(targetUser.getUserId(), targetUser.getName(), targetUser.getMoney() + money);
        stub.putStringState(sourceId, JSON.toJSONString(newSourceUser));
        stub.putStringState(targetId, JSON.toJSONString(newTargetUser));
        return stub.getTxId();
    }
}

  • 打包合约源码
peer lifecycle chaincode package UserChainCode.tar.gz --path /工程目录/UserChainCode --lang java --label UserChainCode
三、安装合约
  • 设置peer0.org1环境:
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${MSP_PATH}/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${MSP_PATH}/peerOrganizations/org1.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=localhost:7051

  安装合约:

peer lifecycle chaincode install UserChainCode.tar.gz

  成功返回值:

[2022-06-16 02:01:41.891 PDT [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response: 
2022-06-16 02:01:41.891 PDT [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: UserChainCode:c8afcba20a3e5e70b1ca183a983d856e984908f02bc0244f4be0755940745271
  •   设置peer0.org2环境:
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${MSP_PATH}/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${MSP_PATH}/peerOrganizations/org2.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=localhost:9051

  安装合约:

peer lifecycle chaincode install UserChainCode.tar.gz
  • 查看安装的合约清单:
peer lifecycle chaincode queryinstalled
四、合约审核

当合约安装后,需经过机构的审批达成一致后才允许使用。
package-id通过合约清单查询

  • peer0.org1审核合约

  环境变量设置

export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${MSP_PATH}/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${MSP_PATH}/peerOrganizations/org1.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=localhost:7051

  审批合约

peer lifecycle chaincode approveformyorg \
  -o localhost:7050 \
  --ordererTLSHostnameOverride orderer.example.com \
  --tls \
  --cafile ${MSP_PATH}/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
  --channelID mychannel \
  --name UserChainCode \
  --version 1.0 \
  --package-id UserChainCode:c8afcba20a3e5e70b1ca183a983d856e984908f02bc0244f4be0755940745271 \
  --sequence 1

  成功返回值:

2022-06-16 02:17:23.850 PDT [chaincodeCmd] ClientWait -> INFO 001 txid [f657a862e0f08e14429c31c660b1db798ee4099f21006b67f26e939c22510c9b] committed with status (VALID) at localhost:7051
  • peer0.org2审核合约
      设置环境:
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${MSP_PATH}/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${MSP_PATH}/peerOrganizations/org2.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=localhost:9051

  审批合约

peer lifecycle chaincode approveformyorg \
  -o localhost:7050 \
  --ordererTLSHostnameOverride orderer.example.com \
  --tls \
  --cafile ${MSP_PATH}/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
  --channelID mychannel \
  --name UserChainCode \
  --version 1.0 \
  --package-id UserChainCode:c8afcba20a3e5e70b1ca183a983d856e984908f02bc0244f4be0755940745271 \
  --sequence 1

  成功返回值:

2022-06-16 02:13:17.149 PDT [chaincodeCmd] ClientWait -> INFO 001 txid [c7824a195ab4734421a452546334b10ed1e3043de947bd43e02afce692fa32b9] committed with status (VALID) at localhost:9051
  • 检查合约的审批情况
peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name UserChainCode --version 1.0 --sequence 1 --output json

  成功返回值:

{
    "approvals": {
        "Org1MSP": true,
        "Org2MSP": true
    }
}
五、提交合约
  • 向通道提交合约
peer lifecycle chaincode commit \
  -o localhost:7050 \
  --ordererTLSHostnameOverride orderer.example.com \
  --tls \
  --cafile ${MSP_PATH}/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
  --channelID mychannel \
  --name UserChainCode \
  --peerAddresses localhost:7051 \
  --tlsRootCertFiles ${MSP_PATH}/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt \
  --peerAddresses localhost:9051 \
  --tlsRootCertFiles ${MSP_PATH}/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
  --version 1.0 \
  --sequence 1

  成功返回:

2022-06-16 02:24:00.916 PDT [chaincodeCmd] ClientWait -> INFO 001 txid [a98706144cb7a982924935d175d3d9469a1ba384918fa3b2317796ab5c9fc45b] committed with status (VALID) at localhost:9051
2022-06-16 02:24:00.922 PDT [chaincodeCmd] ClientWait -> INFO 002 txid [a98706144cb7a982924935d175d3d9469a1ba384918fa3b2317796ab5c9fc45b] committed with status (VALID) at localhost:7051
  • 查看通道上已提交合约
peer lifecycle chaincode querycommitted --channelID mychannel --name UserChainCode --output json

  成功返回:

{
    "sequence": 1,
    "version": "1.0",
    "endorsement_plugin": "escc",
    "validation_plugin": "vscc",
    "validation_parameter": "EiAvQ2hhbm5lbC9BcHBsaWNhdGlvbi9FbmRvcnNlbWVudA==",
    "collections": {},
    "approvals": {
        "Org1MSP": true,
        "Org2MSP": true
    }
}
六、测试合约
  • 初始化账本
peer chaincode invoke -o localhost:7050 \
  --ordererTLSHostnameOverride orderer.example.com \
  --tls \
  --cafile ${MSP_PATH}/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
  -C mychannel \
  -n UserChainCode \
  --peerAddresses localhost:7051 \
  --tlsRootCertFiles ${MSP_PATH}/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt \
  --peerAddresses localhost:9051 \
  --tlsRootCertFiles ${MSP_PATH}/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
  -c '{"function":"init","Args":[]}'

  成功返回:

2022-06-16 02:32:17.327 PDT [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200
  • 查询数据

  设置为peer0.org1环境

export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${MSP_PATH}/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${MSP_PATH}/peerOrganizations/org1.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=localhost:7051

  查询所有数据

peer chaincode query -C mychannel -n UserChainCode -c '{"Args":["queryAll"]}'

  成功返回:

[{"money":100.0,"name":"mixm","userId":"1"},{"money":200.0,"name":"admin","userId":"2"},{"money":300.0,"name":"user","userId":"3"}]

  单个查询

peer chaincode query -C mychannel -n UserChainCode -c '{"Args":["getUser", "1"]}'

  成功返回:

  • 新增数据
peer chaincode invoke -o localhost:7050 \
  --ordererTLSHostnameOverride orderer.example.com \
  --tls \
  --cafile ${MSP_PATH}/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
  -C mychannel \
  -n UserChainCode \
  --peerAddresses localhost:7051 \
  --tlsRootCertFiles ${MSP_PATH}/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt \
  --peerAddresses localhost:9051 \
  --tlsRootCertFiles ${MSP_PATH}/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
  -c '{"function":"addUser","Args":["4","test","400"]}'

  成功返回:

2022-06-16 04:45:33.799 PDT [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200 payload:"3fec668b3342100ca362fc342d240cc5bc6fb1e52cced55233b4a984f4d13c3a"
  • 转账
peer chaincode invoke -o localhost:7050 \
  --ordererTLSHostnameOverride orderer.example.com \
  --tls \
  --cafile ${MSP_PATH}/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
  -C mychannel \
  -n UserChainCode \
  --peerAddresses localhost:7051 \
  --tlsRootCertFiles ${MSP_PATH}/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt \
  --peerAddresses localhost:9051 \
  --tlsRootCertFiles ${MSP_PATH}/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
  -c '{"function":"transfer","Args":["4","1","400"]}'

  成功返回:

2022-06-16 04:48:05.651 PDT [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200 payload:"5bfd15030101eb1fd538ffd622d8a66c79d237fabeaaa67342ee8ba04dc1dccc"

你可能感兴趣的:(Hyperledger Fabric Java智能合约实现)