Hyperledger Fabric SDKを用いた実装

アダプタを実装する前の準備として、fabric-sdk-javaを用いた実装例を紹介したいと思います。

## やること
eclipseからプロジェクトを作成し、fabric-sdk-javaを参照しチェーンコードを実行する実行モジュールを作成します。
前回、basicというチェーンコードをデプロイしました。このbasicのコントラクト関数「InitLedger」を呼び出します。
FacricCAを有効にし、TLSを用いて接続しコードを実行します。

## 参考サイト
TLSを用いた実装について、大変丁寧に紹介くださっています。

https://blog.csdn.net/qq_27348837/article/details/95489720

## 実装例
### ConnectionParameter.java
各定数の宣言
接続先、接続先名称、証明書情報を定義します。
```java
public class ConnectionParameter {
	public static final String baseUrl ="localhost";
	public static final String grpc="grpcs://";

	public static final String CA_ORG1_URL = "https://" + baseUrl + ":7054";
	public static final String CA_ORG2_URL = "https://" + baseUrl + ":8054";

	public static final String ORG1_MSP = "Org1MSP";
	public static final String ORG1 = "org1";

	public static final String ORG2_MSP = "Org2MSP";
	public static final String ORG2 = "org2";

	public static final String CA1NAME = "ca-org1";
	public static final String CA2NAME = "ca-org2";

	public static final String ADMIN = "admin";
	public static final String ADMIN_PASSWORD = "adminpw";

	public static final String USER1 = "user1";
	public static final String USER1_PASSWORD = "user1pw";

	public static final String CHANNEL_CONFIG_PATH = "config/channel.tx";

	public static final String BASE_NETWORK_PATH = "C:\\Users\\zkani\\Documents\\6_DataSpider\\04_Hyperledger_fabric\\fabric\\myFabric\\fabric-samples\\test-network\\organizations";
	public static final String ORG1_USR_BASE_PATH = BASE_NETWORK_PATH + File.separator + "peerOrganizations" + File.separator
			+ "org1.example.com" + File.separator + "users" + File.separator + "Admin@org1.example.com"
			+ File.separator + "msp";

	public static final String ORG2_USR_BASE_PATH = BASE_NETWORK_PATH+ File.separator + "peerOrganizations" + File.separator
			+ "org2.example.com" + File.separator + "users" + File.separator + "Admin@org2.example.com"
			+ File.separator + "msp";

	public static final String CA1_TLSFILE = BASE_NETWORK_PATH + File.separator + "peerOrganizations" + File.separator
			+"org1.example.com"+File.separator+ "ca"+ File.separator+"ca.org1.example.com-cert.pem";

	public static final String ORG1_PER1_CAFILE= BASE_NETWORK_PATH + File.separator + "peerOrganizations" + File.separator
			+ "org1.example.com" + File.separator + "tlsca" + File.separator + "tlsca.org1.example.com-cert.pem";
	public static final String ORG2_PER1_CAFILE=BASE_NETWORK_PATH + File.separator + "peerOrganizations" + File.separator
			+ "org2.example.com" + File.separator + "tlsca" + File.separator + "tlsca.org2.example.com-cert.pem";
	public static final String ORDER_CAFILE=BASE_NETWORK_PATH + File.separator + "ordererOrganizations" + File.separator
			+ "example.com" + File.separator + "tlsca" + File.separator + "tlsca.example.com-cert.pem";

	public static final String ORG1_USR_ADMIN_PK = ORG1_USR_BASE_PATH + File.separator + "keystore";
	public static final String ORG1_USR_ADMIN_CERT = ORG1_USR_BASE_PATH + File.separator + "admincerts";

	public static final String ORG2_USR_ADMIN_PK = ORG2_USR_BASE_PATH + File.separator + "keystore";
	public static final String ORG2_USR_ADMIN_CERT = ORG2_USR_BASE_PATH + File.separator + "admincerts";
	public static final String ORDERER_URL = grpc+ baseUrl + ":7050";

	public static final String ORDERER_NAME = "orderer.example.com";

	public static final String CHANNEL_NAME = "mychannel";

	public static final String ORG1_PEER_0 = "peer0.org1.example.com";

	public static final String ORG1_PEER_0_URL = grpc + baseUrl+ ":7051";

	public static final String ORG1_PEER_1 = "peer1.org1.example.com";

	public static final String ORG1_PEER_1_URL = grpc + baseUrl+ ":8051";

    public static final String ORG2_PEER_0 = "peer0.org2.example.com";

	public static final String ORG2_PEER_0_URL =grpc + baseUrl+ ":9051";

	public static final String ORG2_PEER_1 = "peer1.org2.example.com";

	public static final String ORG2_PEER_1_URL = grpc + baseUrl+ ":10051";

	public static final String CHAINCODE_ROOT_DIR = "chaincode";

	public static final String CHAINCODE_1_NAME = "basic";

	public static final String CHAINCODE_1_PATH = "github.com/fabcar";

	public static final String CHAINCODE_1_VERSION = "1";
}
```

### FabricExample.java
コントラクト呼び出し
```java

	public static void invokeUserChaincode() {

		List<ProposalResponse> transactionRecord = new LinkedList<>();

		try {
			/* ユーザ情報初期化 */
			Utility.cleanUp();

            /* org1への接続情報をセット */
    		File ca1Tls = new File (ConnectionParameter.CA1_TLSFILE);
            String certficateData = new String (IOUtils.toByteArray(new FileInputStream(ca1Tls)),"UTF-8");
            Properties caClientProperties = new Properties();
            caClientProperties.put("pemBytes", certficateData.getBytes());
            caClientProperties.setProperty("pemFile", ca1Tls.getAbsolutePath());
            caClientProperties.setProperty("allowAllHostNames", "true");
            FabricCAClient caclient=new  FabricCAClient(ConnectionParameter.CA1NAME, ConnectionParameter.CA_ORG1_URL, caClientProperties);

            /* チェーンコード呼出ユーザの情報をセット */
			UserParameter userParameter = new UserParameter();
			userParameter.setName(ConnectionParameter.USER1);
			userParameter.setAffiliation(ConnectionParameter.ORG1);
			userParameter.setMspId(ConnectionParameter.ORG1_MSP);
            caclient.setAdminUserParameter(userParameter);
            userParameter =  caclient.enrollAdminUserTLS(ConnectionParameter.USER1, ConnectionParameter.USER1_PASSWORD);

			FabricClient fabClient = new FabricClient(userParameter);

			ChannelClient channelClient = fabClient.createChannelClient(ConnectionParameter.CHANNEL_NAME);

			Channel channel = channelClient.getChannel();

            /* チャネルに属するPeerを設定します */
			Properties org1Properties = Utility.gete2ePro("peer",ConnectionParameter.ORG1_PEER_0);
			Peer peer0 = fabClient.getInstance().newPeer(ConnectionParameter.ORG1_PEER_0, ConnectionParameter.ORG1_PEER_0_URL, org1Properties);

			Properties org2Properties = Utility.gete2ePro("peer",ConnectionParameter.ORG2_PEER_0);
			Peer peer1 = fabClient.getInstance().newPeer(ConnectionParameter.ORG2_PEER_0, ConnectionParameter.ORG2_PEER_0_URL, org2Properties);

			Properties orderProperties = Utility.gete2ePro("orderer",ConnectionParameter.ORDERER_NAME);
			Orderer orderer = fabClient.getInstance().newOrderer(ConnectionParameter.ORDERER_NAME, ConnectionParameter.ORDERER_URL, orderProperties);

			channel.addPeer(peer0);
			channel.addPeer(peer1);
			channel.addOrderer(orderer);
			channel.initialize();

            /* コントラクト呼び出し */
			TransactionProposalRequest proposalRequest = fabClient.getInstance().newTransactionProposalRequest();
			ChaincodeID chaincode = ChaincodeID.newBuilder().setName(ConnectionParameter.CHAINCODE_1_NAME).build();
			proposalRequest.setChaincodeID(chaincode);
			proposalRequest.setFcn("InitLedger");
			proposalRequest.setProposalWaitTime(3000);

			Collection<ProposalResponse> responses = channelClient.sendTransactionProposal(proposalRequest);
            /* 設定したPeer分繰り返しtransactionRecordに登録します */
			for (ProposalResponse response: responses) {
				if (response.getStatus() == ProposalResponse.Status.SUCCESS) {
					transactionRecord.add(response);
				}
			}
			channel.sendTransaction(transactionRecord);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

```

## 実装時のポイント
当該ネットワークにおいて、peerのアドレスを2つまたいでいます。それぞれのpeerを登録し、双方に伝搬させる仕組みが必要です。
sendTransactionProposal呼び出し後、それぞれのpeerに対して繰り返し処理を行うように実装します。
台帳にブロードキャストしないsendTransactionProposalメソッドを呼び出し、そのレスポンスをブロードキャスト（sendTransaction呼び出し）します。

## 次回は
DataSpiderSDKを用いてグローバルリソースの実装をします。