This is a sample to get block information using Hyperledger Iroha's Java SDK. The contents of the code perform the following processing.
This is the code I made.
Sample.java
public static void main(String[] args) throws Exception{
URI uri = new URI(null,null, "192.168.33.10",50051,null,null,null);
IrohaAPI api = new IrohaAPI(uri);
byte[] pubByte = Hex.decodeHex("313a07e6384776ed95447710d15e59148473ccfc052a681317a72a69f2a49910");
byte[] privByte = Hex.decodeHex("f101537e319568c765b2cc89698325604991dca57b9716b58016b253506cab70");
KeyPair adminKeyPair = Ed25519Sha3.keyPairFromBytes(privByte, pubByte);
// transfer 100 usd from user_a to user_b
val tx1 = Transaction.builder("admin@test")
.transferAsset("admin@test", "test@test", "odocoin#test", "For pizza", "10")
.sign(adminKeyPair)
.build();
val tx2 = Transaction.builder("admin@test")
.transferAsset("admin@test", "test@test", "odocoin#test", "For sushi", "10")
.sign(adminKeyPair)
.build();
val tx3 = Transaction.builder("admin@test")
.transferAsset("admin@test", "test@test", "odocoin#test", "For hamburger", "10")
.sign(adminKeyPair)
.build();
List<TransactionOuterClass.Transaction> txList = new ArrayList<>();
txList.add(tx1);
txList.add(tx2);
txList.add(tx3);
val observer = TransactionStatusObserver.builder()
// executed when stateless or stateful validation is failed
.onTransactionFailed(t -> System.out.println(String.format(
"transaction %s failed with msg: %s",
t.getTxHash(),
t.getErrOrCmdName()
)))
// executed when got any exception in handlers or grpc
.onError(e -> System.out.println("Failed with exception: " + e))
// executed when we receive "committed" status
.onTransactionCommitted((t) -> System.out.println("Committed :)"))
// executed when transfer is complete (failed or succeed) and observable is closed
.onComplete(() -> System.out.println("Complete"))
.build();
// 1.Send 3 transactions at once
api.transactionListSync(txList);
Thread.sleep(10000);
val query = Query.builder("admin@test", 3).getBlock(Long.valueOf("9")).buildSigned(adminKeyPair);
QryResponses.QueryResponse response = api.query(query);
Map<FieldDescriptor, Object> map = response.getAllFields();
// 2.Get and display block information
for(Map.Entry<Descriptors.FieldDescriptor,Object> entry : map.entrySet()) {
System.out.println("Key:" + entry.getKey() + " Value:" + entry.getValue());
}
// 3.Get transaction information from the block and display it
BlockResponse block = response.getBlockResponse();
Payload payload = block.getBlock().getBlockV1().getPayload();
for(int i=0; i < payload.getTransactionsCount(); i++) {
TransactionOuterClass.Transaction tx = payload.getTransactions(i);
ReducedPayload reducePayload = tx.getPayload().getReducedPayload();
System.out.println("/********************* " + (i+1) + "Item*********************/");
System.out.println("CreatorAccountId :" + reducePayload.getCreatorAccountId());
System.out.println("CreatedTime :" + new Date(reducePayload.getCreatedTime()));
System.out.println("Quorum :" + reducePayload.getQuorum());
System.out.println("CommandCount :" + reducePayload.getCommandsCount());
for(int j=0; j < reducePayload.getCommandsCount(); j++) {
Command command = reducePayload.getCommands(j);
TransferAsset asset = command.getTransferAsset();
System.out.println("SrcAccountId :" + asset.getSrcAccountId());
System.out.println("DestAccountId :" + asset.getDestAccountId());
System.out.println("AssetId :" + asset.getAssetId());
System.out.println("Description :" + asset.getDescription());
System.out.println("Amount :" + asset.getAmount());
}
}
api.close();
}
When sending only one transaction, it seems that there are "transaction (tx)" and "transactionSync (tx)". The difference is whether to wait for it to be captured in the block. In ethereum's Java SDK, methods with "Async" will proceed without waiting for them to be included in the block. Iroha's SDK doesn't seem to wait for the method with "Sync" to be included in the block.
At the moment, it seems that only "transactionListSync" is provided as a method to send transactions in a batch.
First, let's display the contents of QryResponses that can be obtained by executing a query.
Key:iroha.protocol.QueryResponse.query_hash Value:429b50118a1d691706408045ea1ac55ed9f4138d10a15450dc70850c7869fe9e
Key:iroha.protocol.QueryResponse.block_response Value:block {
block_v1 {
payload {
transactions {
payload {
reduced_payload {
commands {
transfer_asset {
src_account_id: "admin@test"
dest_account_id: "test@test"
asset_id: "odocoin#test"
description: "For sushi"
amount: "10"
}
}
creator_account_id: "admin@test"
created_time: 1570927096936
quorum: 1
}
}
signatures {
public_key: "313A07E6384776ED95447710D15E59148473CCFC052A681317A72A69F2A49910"
signature: "924FAE8C33A4AFB9B713E443B5C6BBC5B9D26069B71C688112B8BE74DEE40192A096CA6460396D67876A684C1950E0632A4C41B0362D55FEA085706C9B305F0C"
}
}
transactions {
payload {
reduced_payload {
commands {
transfer_asset {
src_account_id: "admin@test"
dest_account_id: "test@test"
asset_id: "odocoin#test"
description: "For pizza"
amount: "10"
}
}
creator_account_id: "admin@test"
created_time: 1570927096854
quorum: 1
}
}
signatures {
public_key: "313A07E6384776ED95447710D15E59148473CCFC052A681317A72A69F2A49910"
signature: "09A3E58AEFF340B2E975049B066B445A14E9F0984D48CEDA8612E4794E51A290A5263AB3C4C3121A4B839CE29262100F349AA08262878A1C53344E1EBCDFD50C"
}
}
transactions {
payload {
reduced_payload {
commands {
transfer_asset {
src_account_id: "admin@test"
dest_account_id: "test@test"
asset_id: "odocoin#test"
description: "For hamburger"
amount: "10"
}
}
creator_account_id: "admin@test"
created_time: 1570927096938
quorum: 1
}
}
signatures {
public_key: "313A07E6384776ED95447710D15E59148473CCFC052A681317A72A69F2A49910"
signature: "1D97980C8A1CDA550CB08E1561127516ABF6A756F4C62A703ACDD1DE91FC3741A7DD4BC5E5995CEC71144622CDA685A1390FBB5C98FBAFB63260CE838F33A80D"
}
}
height: 9
prev_block_hash: "497f75888812ba4cd825322284840051c4ab0c26a1b966839510af86f7aca203"
created_time: 1570927100956
}
signatures {
public_key: "bddd58404d1315e0eb27902c5d7c8eb0602c16238f005773df406bc191308929"
signature: "0eff2986883e19325c33b2b59447e1ece486c981eeb1efcb69c61adf69e77df52228fa9e1ea5ed7aa987c3465e2c055797853e0802dcd6aea6fdf8fa201ce405"
}
}
}
As for the displayed contents, the hash value of the query and the contents of the block could be obtained. This information alone is not easy to use, so I searched for a way to obtain the information individually.
If you compare the contents of the block with the code below, it will be easier to understand how to make it.
Sample.java
BlockResponse block = response.getBlockResponse();
Payload payload = block.getBlock().getBlockV1().getPayload();
for(int i=0; i < payload.getTransactionsCount(); i++) {
TransactionOuterClass.Transaction tx = payload.getTransactions(i);
ReducedPayload reducePayload = tx.getPayload().getReducedPayload();
Information is obtained from response, but a class is prepared for each element of JSON information of the block. Therefore, it is possible to acquire data in the order of Block → Block_v1 → Payload → Transactions → Payload → reduced_payload → commands.
The sample code shows the contents of the transaction. The execution result is as follows.
/*********************1st case*********************/
CreatorAccountId :admin@test
CreatedTime :Sun Oct 13 09:38:16 JST 2019
Quorum :1
CommandCount :1
SrcAccountId :admin@test
DestAccountId :test@test
AssetId :odocoin#test
Description :For sushi
Amount :10
/*********************2nd*********************/
CreatorAccountId :admin@test
CreatedTime :Sun Oct 13 09:38:16 JST 2019
Quorum :1
CommandCount :1
SrcAccountId :admin@test
DestAccountId :test@test
AssetId :odocoin#test
Description :For pizza
Amount :10
/*********************3rd case*********************/
CreatorAccountId :admin@test
CreatedTime :Sun Oct 13 09:38:16 JST 2019
Quorum :1
CommandCount :1
SrcAccountId :admin@test
DestAccountId :test@test
AssetId :odocoin#test
Description :For hamburger
Amount :10
Personally, I got the impression that the Ethereum SDK was easier to understand regarding how to acquire transaction information and block information.
I really wanted to get the latest block information, but I don't know how to get it, so I try to specify the block number directly. It seems that we still need to find out how to use it.
Recommended Posts