アダプタを実装する前の準備として、fabric-sdk-javaを用いた実装例を紹介したいと思います。
やること
eclipseからプロジェクトを作成し、fabric-sdk-javaを参照しチェーンコードを実行する実行モジュールを作成します。
前回、basicというチェーンコードをデプロイしました。このbasicのコントラクト関数「InitLedger」を呼び出します。
FacricCAを有効にし、TLSを用いて接続しコードを実行します。
参考サイト
TLSを用いた実装について、大変丁寧に紹介くださっています。
実装例
ConnectionParameter.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
コントラクト呼び出し
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を用いてグローバルリソースの実装をします。