美文网首页超级账本HyperLeder初见
Hyperledger Fabric架构及Java SDK实现

Hyperledger Fabric架构及Java SDK实现

作者: 小蜗牛爬楼梯 | 来源:发表于2020-06-13 18:31 被阅读0次

    Hyperledger Fabric 整理体系:

    image image

    各项解释如下:

    • APP:代表一个客户端或者SDK,作用是创建交易并获取到足够的背书之后向Orderer排序服务节点提交交易请求。(peer和orderer提供了gRPC远程访问接口,供客户端调用)
    • CA:负责对网络中所有证书进行管理,提供标准的KPI服务
    • MSP:为客户端和peer提供证书的系统抽象组件
    • Channel:通道提供了一种通讯机制,将peers和orderer连接在一起,形成一个具有保密性的通讯链路;将一个大网络分割成不同私有子网,进行数据隔离
    • Orderer:对客户端提交的交易请求进行排序,之后生成区块广播给通道内所有peer节点
    • Org1:代表联盟中的某-组织
    • Peer:表示组织中的节点;peer节点以区块的形式从orderer排序服务节点接收有序状态更新,维护状态和账本。fabric中Peer节点可划分如下:
      1. Endorsing Peer:根据指定的策略调用智能合约,对结果进行背书,返回提案相应到客户端
      2. Committing Peer:验证数据并保存到账本中
      3. Anchor Peer:跨组织通讯
      4. Leading Peer:做为组织内所有节点的代表连接到Orderer排序服务节点,将从排序服务节点接收到的批量区块广播给组织内的其他节点
    • Chaincode:链码,部署在fabric的网络节点中,独立运行在具有安全特性的受保护容器中,以gRPC协议与相应Peer节点进行通讯,提供相应的API与账本数据进行交互
    • Ledger:有排序服务构建的一个全部有序的交易哈希链块,保存在所有的Peer节点中。

    Java SDK提供了一种执行用户链码,查询块数据,在通道进行交易及模拟事件的方式。
     此模式下,区块链网络由两个组织,每个组织包含两个结点,和一个order服务;将展示怎样创建和初始化通道,安装和部署链码,和执行调用和查询操作。

    image
    基本原理

    在fabric区块链中,应用通过结点RPC协议接口访问链码。

    image

    类似于Shim API对链码通讯协议的封装,JavaSDK提供了对结点RPC协议接口封装,其入口类为HFClient;对链码的交易和查询操作则封装在channel类中。

    image
    简单实例
    • 实现User接口
       HFClient访问fabric网络身份使用User接口实现。
       一个用户的身份由它的证书来标识的,同时交易还需要证书对应的私钥,因此LocalUser的核心逻辑就是利用指定的证书和私钥PEM文件满足User接口的要求。

      image
    • 访问链码
       创建HFClient实例,然后获取通道对象,就可以查询链码或者提交链码交易。

    命令行操作: hyperledger fabric byfn up详解
    代码具体实现
    • 运行fabric-samples中fabcar,创建区块链网络
    • 新建Java工程,引入fabric-gateway-java,实现具体实现
      pom.xml
        <repositories>
            <repository>
                <id>oss-sonatype</id>
                <name>OSS Sonatype</name>
                <url>https://oss.sonatype.org/content/repositories/snapshots</url>
            </repository>
        </repositories>
    
        <dependencies>
            <dependency>
                <groupId>org.hyperledger.fabric</groupId>
                <artifactId>fabric-gateway-java</artifactId>
                <version>1.4.1-SNAPSHOT</version>
            </dependency>
        </dependencies>
    
    

    加入Admins角色:

    public class EnrollAdmin {
    
        static {
            System.setProperty("org.hyperledger.fabric.sdk.service_discovery.as_localhost", "true");
        }
    
        public static void main(String[] args) throws Exception {
    
            // Create a CA client for interacting with the CA.
            Properties props = new Properties();
            props.put("pemFile",
                "/Users/macserver/Documents/BlockChain/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem");
            props.put("allowAllHostNames", "true");
            HFCAClient caClient = HFCAClient.createNewInstance("https://localhost:7054", props);
            CryptoSuite cryptoSuite = CryptoSuiteFactory.getDefault().getCryptoSuite();
            caClient.setCryptoSuite(cryptoSuite);
    
            // Create a wallet for managing identities
            Wallet wallet = Wallet.createFileSystemWallet(Paths.get("wallet"));
    
            // Check to see if we've already enrolled the admin user.
            boolean adminExists = wallet.exists("admin");
            if (adminExists) {
                System.out.println("An identity for the admin user \"admin\" already exists in the wallet");
                return;
            }
    
            // Enroll the admin user, and import the new identity into the wallet.
            final EnrollmentRequest enrollmentRequestTLS = new EnrollmentRequest();
            enrollmentRequestTLS.addHost("localhost");
            enrollmentRequestTLS.setProfile("tls");
            Enrollment enrollment = caClient.enroll("admin", "adminpw", enrollmentRequestTLS);
            Identity user = Identity.createIdentity("Org1MSP", enrollment.getCert(), enrollment.getKey());
            wallet.put("admin", user);
            System.out.println("Successfully enrolled user \"admin\" and imported it into the wallet");
        }
    }
    
    

    加入user1角色:

    public class RegisterUser {
    
        static {
            System.setProperty("org.hyperledger.fabric.sdk.service_discovery.as_localhost", "true");
        }
    
        public static void main(String[] args) throws Exception {
    
            // Create a CA client for interacting with the CA.
            Properties props = new Properties();
            props.put("pemFile",
                "/Users/macserver/Documents/BlockChain/src/github.com/hyperledger/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem");
            props.put("allowAllHostNames", "true");
            HFCAClient caClient = HFCAClient.createNewInstance("https://localhost:7054", props);
            CryptoSuite cryptoSuite = CryptoSuiteFactory.getDefault().getCryptoSuite();
            caClient.setCryptoSuite(cryptoSuite);
    
            // Create a wallet for managing identities
            Wallet wallet = Wallet.createFileSystemWallet(Paths.get("wallet"));
    
            // Check to see if we've already enrolled the user.
            boolean userExists = wallet.exists("user1");
            if (userExists) {
                System.out.println("An identity for the user \"user1\" already exists in the wallet");
                return;
            }
    
            userExists = wallet.exists("admin");
            if (!userExists) {
                System.out.println("\"admin\" needs to be enrolled and added to the wallet first");
                return;
            }
    
            Identity adminIdentity = wallet.get("admin");
            User admin = new User() {
    
                @Override
                public String getName() {
                    return "admin";
                }
    
                @Override
                public Set<String> getRoles() {
                    return null;
                }
    
                @Override
                public String getAccount() {
                    return null;
                }
    
                @Override
                public String getAffiliation() {
                    return "org1.department1";
                }
    
                @Override
                public Enrollment getEnrollment() {
                    return new Enrollment() {
    
                        @Override
                        public PrivateKey getKey() {
                            return adminIdentity.getPrivateKey();
                        }
    
                        @Override
                        public String getCert() {
                            return adminIdentity.getCertificate();
                        }
                    };
                }
    
                @Override
                public String getMspId() {
                    return "Org1MSP";
                }
    
            };
    
            // Register the user, enroll the user, and import the new identity into the wallet.
            RegistrationRequest registrationRequest = new RegistrationRequest("user1");
            registrationRequest.setAffiliation("org1.department1");
            registrationRequest.setEnrollmentID("user1");
            String enrollmentSecret = caClient.register(registrationRequest, admin);
            Enrollment enrollment = caClient.enroll("user1", enrollmentSecret);
            Identity user = Identity.createIdentity("Org1MSP", enrollment.getCert(), enrollment.getKey());
            wallet.put("user1", user);
            System.out.println("Successfully enrolled user \"user1\" and imported it into the wallet");
        }
    
    }
    
    

    客户端:查询及添加新数据

    public class ClientApp {
    
        static {
            System.setProperty("org.hyperledger.fabric.sdk.service_discovery.as_localhost", "true");
        }
    
        public static void main(String[] args) throws Exception {
            // Load a file system based wallet for managing identities.
            Path walletPath = Paths.get("wallet");
            Wallet wallet = Wallet.createFileSystemWallet(walletPath);
    
            // load a CCP
            Path networkConfigPath = Paths.get("/Users/macserver/Documents/BlockChain/src/github.com/hyperledger/fabric-samples/fabcar", "..", "first-network", "connection-org1.yaml");
    
            Gateway.Builder builder = Gateway.createBuilder();
            builder.identity(wallet, "user1").networkConfig(networkConfigPath).discovery(true);
    
            // create a gateway connection
            try (Gateway gateway = builder.connect()) {
    
                // get the network and contract
                Network network = gateway.getNetwork("mychannel");
                Contract contract = network.getContract("fabcar");
    
                byte[] result;
    
                result = contract.evaluateTransaction("queryAllCars");
                System.out.println(new String(result));
    
                contract.submitTransaction("createCar", "CAR10", "VW", "Polo", "Grey", "Mary");
    
                result = contract.evaluateTransaction("queryCar", "CAR10");
                System.out.println(new String(result));
    
                contract.submitTransaction("changeCarOwner", "CAR10", "Archie");
    
                result = contract.evaluateTransaction("queryCar", "CAR10");
                System.out.println(new String(result));
            }
        }
    
    }
    
    
    实现方式 二

    如果跳过gateway,直接使用fabric-sdk-java,数据查询-实现代码如下:

    private static void queryAllCars() throws Exception {
            HFClient hfClient = HFClient.createNewInstance();
    
            CryptoSuite cryptoSuite = CryptoSuiteFactory.getDefault().getCryptoSuite();
            hfClient.setCryptoSuite(cryptoSuite);
    
            Enrollment enrollment = new X509Enrollment(getPrivateKey(Paths.get("wallet/user1/user1-priv")), getCertificate(certificate_user1));
            User user = new User() {
                @Override
                public String getName() {
                    return "gateway";
                }
    
                @Override
                public Set<String> getRoles() {
                    return Collections.emptySet();
                }
    
                @Override
                public String getAccount() {
                    return "";
                }
    
                @Override
                public String getAffiliation() {
                    return "";
                }
    
                @Override
                public Enrollment getEnrollment() {
                    return enrollment;
                }
    
                @Override
                public String getMspId() {
                    return "Org1MSP";
                }
            };
    
            hfClient.setUserContext(user);
    
            NetworkConfig networkConfig = NetworkConfig.fromYamlFile(new File(path + "first-network/connection-org1.yaml"));
    
            Channel channel = hfClient.newChannel("mychannel");
    
            List<String> peerNames = networkConfig.getClientOrganization().getPeerNames();
            for (String name : peerNames) {
                String url = networkConfig.getPeerUrl(name);
                Properties props = networkConfig.getPeerProperties(name);
                System.err.println("xxxxxxxxx:" + name + "..." + url);
                Peer peer = hfClient.newPeer(name, url, props);
    
                Channel.PeerOptions peerOptions = Channel.PeerOptions.createPeerOptions().setPeerRoles(EnumSet.allOf(Peer.PeerRole.class));
                channel.addPeer(peer, peerOptions);
            }
    
            channel.initialize();
    
            QueryByChaincodeRequest request = QueryByChaincodeRequest.newInstance(user);
    
            request.setChaincodeID(getChaincodeId("fabcar"));
            request.setFcn("queryAllCars");
            request.setArgs("");
    
            Collection<ProposalResponse> responses = channel.queryByChaincode(request, Collections.singletonList(channel.getPeers().iterator().next()));
            ProposalResponse response = responses.iterator().next();
            byte[] bytes = response.getChaincodeActionResponsePayload();
    
            System.err.println("xxxxxxx:" + new String(bytes));
        }
    
    
        private static String getCertificate(String certificate) {
            BufferedReader certReader = new BufferedReader(new StringReader(certificate));
            return certReader.lines().collect(Collectors.joining("\n", "", "\n"));
        }
    
        private static PrivateKey getPrivateKey(Path pemFile) {
            try {
                PEMParser parser = new PEMParser(Files.newBufferedReader(pemFile));
                Object key = parser.readObject();
                JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
                return converter.getPrivateKey((PrivateKeyInfo) key);
            } catch (IOException e) {
                System.err.println("private key 获取失败");
                return null;
            }
        }
    
        private static ChaincodeID getChaincodeId(String chaincodeId) {
            return ChaincodeID.newBuilder()
                    .setName(chaincodeId)
                    .build();
        }
    

    作者:谷雨_时
    链接:https://www.jianshu.com/p/d2c796849b42
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    相关文章

      网友评论

        本文标题:Hyperledger Fabric架构及Java SDK实现

        本文链接:https://www.haomeiwen.com/subject/ossztktx.html