This article describes how to add Peer with Hyperledger Iroha. There is also a way to add it with "iroha-cli", but this time it is added using the Java library. If you want to add it with "iroha-cli", you can get the public key and private key with the code in the article, so I think that you can easily do it by using the key information.
I'll write the conclusion first, but this procedure fails to add Peer. The Peer additional program ends normally and is also included in the block, but the communication between Peers does not work.
I'm not sure if this is an environmental issue or an Iroha issue, so I'll leave a note as a way that didn't work.
In the work of this article, four consoles are started and the work is done. Write carefully so that the console in the article is not confusing.
We will build the environment for iroha for two cars. Remittance blocks etc. should be loaded in advance on Unit 1. Unit 2 will be left with only the Genesis block.
Originally? I wonder if I will prepare a public key using OpenSSL etc. You can easily create a key by using the sample code written in the Iroha document, so this time we will create the key information in Java.
Code that only adds Peer.
import java.net.URI;
import java.security.KeyPair;
import org.testcontainers.shaded.org.apache.commons.codec.binary.Hex;
import jp.co.soramitsu.crypto.ed25519.Ed25519Sha3;
import jp.co.soramitsu.iroha.java.IrohaAPI;
import jp.co.soramitsu.iroha.java.Transaction;
import jp.co.soramitsu.iroha.java.TransactionStatusObserver;
import lombok.val;
public class AddPeer {
private static final Ed25519Sha3 crypto = new Ed25519Sha3();
private static final KeyPair peerKeypair = crypto.generateKeypair();
public static void main(String[] args) throws Exception{
// This IP is the address of iroha Unit 1
URI uri = new URI(null,null, "192.168.33.20",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);
// This IP is the IP address of iroha Unit 2
val addPeerTx = Transaction.builder("admin@test")
.addPeer("192.168.33.21:10001", peerKeypair.getPublic())
.sign(adminKeyPair)
.build();
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();
// Execute Transaction
api.transaction(addPeerTx).blockingSubscribe(observer);
api.close();
System.out.println("PubKey :" + Hex.encodeHexString(peerKeypair.getPublic().getEncoded()));
System.out.println("PrivKey:" + Hex.encodeHexString(peerKeypair.getPrivate().getEncoded()));
}
}
A block with AddPeer is created under "/ tmp / block_store" of the iroha container.
(Iroha Unit 1 iroha container operation console)
{
"blockV1": {
"payload": {
"transactions": [
{
"payload": {
"reducedPayload": {
"commands": [
{
"addPeer": {
"peer": {
"address": "192.168.33.21:10001",
"peerKey": "28CF79DEF117456ABC5413DC15F7B99B192C6D5A162ABDEF39F0BAF6C7CE0B48"
}
}
}
],
"creatorAccountId": "admin@test",
"createdTime": "1571213725207",
"quorum": 1
}
},
"signatures": [
{
"publicKey": "313A07E6384776ED95447710D15E59148473CCFC052A681317A72A69F2A49910",
"signature": "A018F697EB5F6797BD478F8CF04759F8D0ACDA48D4E1FE8B8BBE5D538E6D47A423896E689AA780DD260763ED1B97B12F9AF1EA41D7D391FB2F9C49EDB429DC0C"
}
]
}
],
"height": "16",
"prevBlockHash": "e602693381ff5ac383a2d62503d94ede87951ffdedefe9b4628a188036fd6c89",
"createdTime": "1571213727036"
},
"signatures": [
{
"publicKey": "bddd58404d1315e0eb27902c5d7c8eb0602c16238f005773df406bc191308929",
"signature": "863b38942a290640e05bbb2339ab63d94a8ab6ca3bfba1abaf673fe490f7eb46236a72cdb54d95a3c11254c440ebe3ef1110466a989e0dc4221952749b87ec0b"
}
]
}
}
The IP address embedded in the program and the created pubKey are registered as Peer information in the addPeer command.
Connect to "some-postgres" in the Docker container and take a look at the contents of the table that holds Peer information. (Iroha Unit 1 some-postgres container operation console)
root@f7d412e03bfb:/# psql -U postgres
psql (9.5.19)
Type "help" for help.
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+------------+------------+-----------------------
postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 |
template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
(3 rows)
postgres=# \d
List of relations
Schema | Name | Type | Owner
--------+-----------------------------------+----------+----------
public | account | table | postgres
public | account_has_asset | table | postgres
public | account_has_grantable_permissions | table | postgres
public | account_has_roles | table | postgres
public | account_has_signatory | table | postgres
public | asset | table | postgres
public | domain | table | postgres
public | height_by_account_set | table | postgres
public | index_by_creator_height | table | postgres
public | index_by_creator_height_id_seq | sequence | postgres
public | peer | table | postgres
public | position_by_account_asset | table | postgres
public | position_by_hash | table | postgres
public | role | table | postgres
public | role_has_permissions | table | postgres
public | signatory | table | postgres
public | tx_status_by_hash | table | postgres
(17 rows)
postgres=# select * from peer;
public_key | address
------------------------------------------------------------------+---------------------
bddd58404d1315e0eb27902c5d7c8eb0602c16238f005773df406bc191308929 | 127.0.0.1:10001
28cf79def117456abc5413dc15f7b99b192c6d5a162abdef39f0baf6c7ce0b48 | 192.168.33.21:10001
(2 rows)
The public Key and IP address set by addPeer are registered in the Peer table.
Next, check if the block information has been synchronized with Unit 2.
(Iroha Unit 2 iroha container operation console)
root@eaa7050903db:/opt/iroha_data# ls /tmp/block_store/
0000000000000001
Not synchronized. .. Let's check the log of irohad.
(Iroha Unit 1 iroha daemon log confirmation console)
root@c8d233a3c261:/opt/iroha_data# [2019-10-17 00:12:09.459123458][I][Irohad/CommandService/Processor]: handle batch
[2019-10-17 00:12:09.459140102][I][Irohad/CommandService/Processor]: propagating batch to PCS
[2019-10-17 00:12:09.459158309][I][Irohad/PeerCommunicationService]: propagate batch
[2019-10-17 00:12:09.460952243][I][Irohad/Ordering/Service]: onBatches => collection size = 1
[2019-10-17 00:12:10.400058025][W][Irohad/AsyncNetworkClient]: RPC failed: Connect Failed
[2019-10-17 00:12:10.400080412][W][Irohad/AsyncNetworkClient]: RPC failed: Connect Failed
[2019-10-17 00:12:10.400088212][W][Irohad/AsyncNetworkClient]: RPC failed: Connect Failed
[2019-10-17 00:12:10.400095314][W][Irohad/AsyncNetworkClient]: RPC failed: Connect Failed
[2019-10-17 00:12:10.400102280][W][Irohad/AsyncNetworkClient]: RPC failed: Connect Failed
It seems that the connection with Unit 2 using gRPC has failed.
Probably, but I think it is the same event. https://github.com/hyperledger/iroha/issues/191
It is managed here https://jira.hyperledger.org/browse/IR-588
Since it cannot be used as it is, I also prepared a program for deleting Peer.
import java.net.URI;
import java.security.KeyPair;
import org.testcontainers.shaded.org.apache.commons.codec.binary.Hex;
import jp.co.soramitsu.crypto.ed25519.Ed25519Sha3;
import jp.co.soramitsu.iroha.java.IrohaAPI;
import jp.co.soramitsu.iroha.java.Transaction;
import jp.co.soramitsu.iroha.java.TransactionStatusObserver;
import lombok.val;
public class RemovePeer {
public static void main(String[] args) throws Exception{
URI uri = new URI(null,null, "192.168.33.20",50051,null,null,null);
IrohaAPI api = new IrohaAPI(uri);
byte[] pubByte = Hex.decodeHex("313a07e6384776ed95447710d15e59148473ccfc052a681317a72a69f2a49910");
byte[] privByte = Hex.decodeHex("f101537e319568c765b2cc89698325604991dca57b9716b58016b253506cab70");
// ↓ Please set the public key of Peer captured in the block ↓
byte[] peerPubKey = Hex.decodeHex("28CF79DEF117456ABC5413DC15F7B99B192C6D5A162ABDEF39F0BAF6C7CE0B48");
KeyPair adminKeyPair = Ed25519Sha3.keyPairFromBytes(privByte, pubByte);
val addPeerTx = Transaction.builder("admin@test")
.removePeer (peerPubKey) // ← This just changed from addPeer to removePeer
.sign(adminKeyPair)
.build();
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();
// Execute Transaction
api.transaction(addPeerTx).blockingSubscribe(observer);
api.close();
}
}
I will do it.
transaction 6069fe1e6c2f6b7437ce145e0db552355f3d8631d16b7bc18b53894fcafec2bf failed with msg: Protobuf Transaction: [[Undefined command is found ]]
Complete
What! Undefined command is found! It seems that removePeer has not been implemented yet. When I checked the contents of Transaction by debugging, it looked like this.
reduced_payload {
commands {
remove_peer {
public_key: "28CF79DEF117456ABC5413DC15F7B99B192C6D5A162ABDEF39F0BAF6C7CE0B48"
}
}
creator_account_id: "admin@test"
created_time: 1571276110853
quorum: 1
}
I will continue to look for other ways and trace the information on the above sites. That's all for this time.
There are two points that I was interested in touching various things this time.
The first point is that Transaction is not captured in the block if the communication between Peers is not successful. Well, I think it's natural, but in actual operation, if there are two Peers, Transaction will not be imported at all if one of them goes down. In the future, I will try to increase the number of units to 3 and 4, but in order not to create a single point of failure, it seems that at least 3 units will need Peer.
The second point may not be a big problem, but it seems that all the existing block information is checked when the iroha daemon is started. (Iroha Unit 1 iroha daemon log confirmation console)
[2019-10-16 23:41:19.917112613][I][Irohad/Storage/MutableStorageImpl]: Applying block: height 1, hash 9debdb1a70db2cede2222427b849f6bf7ab20845da7c3db1837c0df25ec1c61a
[2019-10-16 23:41:19.930740040][I][Irohad/Storage/MutableStorageImpl]: Applying block: height 2, hash d2d9906eb82dd799e6cb68161208738e8383cae31bdf499b2b5f7f14d55b2ba0
[2019-10-16 23:41:19.950225041][I][Irohad/Storage/MutableStorageImpl]: Applying block: height 3, hash 686b05c2553b70cd26fdb6e9108066a33e2b09653ccb33b3b3c9f6e4f12e72d2
[2019-10-16 23:41:19.952860890][I][Irohad/Storage/MutableStorageImpl]: Applying block: height 4, hash fd8541954c9ab55229e8f6e095a7484ece7d64066e78c775359e0d8736a4ea4b
[2019-10-16 23:41:19.960015934][I][Irohad/Storage/MutableStorageImpl]: Applying block: height 5, hash cc5a4fe828811e217a5de828047b9c0d5939628d809b2265b66db1b73f9d0f98
[2019-10-16 23:41:19.972008320][I][Irohad/Storage/MutableStorageImpl]: Applying block: height 6, hash 4fa8f208d9c85b08edc3504aed35f257de943942f250639111c334724cfe6d26
[2019-10-16 23:41:19.983822479][I][Irohad/Storage/MutableStorageImpl]: Applying block: height 7, hash 471894ae7fa36f09d971be563686b2aa06ff28a9bd9a49d6e802451cb018ac1b
[2019-10-16 23:41:19.985555973][I][Irohad/Storage/MutableStorageImpl]: Applying block: height 8, hash 68ef83c09eb4bc8152dd7feaeb0e10a1fb0c71b63e6c6e66e829fd730a765f18
[2019-10-16 23:41:19.987011731][I][Irohad/Storage/MutableStorageImpl]: Applying block: height 9, hash e5dcd0505aa726d25d318af78ea41126f02c44f3647011582017140e1c7e55e5
[2019-10-16 23:41:19.988539990][I][Irohad/Storage/MutableStorageImpl]: Applying block: height 10, hash c6fb5fff4bf3c440b6846761d50d248beb75199342b8b9431e19c1e2b5e7e303
[2019-10-16 23:41:19.989874002][I][Irohad/Storage/MutableStorageImpl]: Applying block: height 11, hash 278c9c5e5a72b5513d55290f2687c623595b7825b747c525ee00135cccfb1149
[2019-10-16 23:41:19.991317395][I][Irohad/Storage/MutableStorageImpl]: Applying block: height 12, hash d33d2adabf75be7380cc6b35b84bcb4b2055f47a927cf1090c1d49853fee154b
[2019-10-16 23:41:19.992694976][I][Irohad/Storage/MutableStorageImpl]: Applying block: height 13, hash b0d19d57da0f0d0677052409e625adfea8dedbb6297edd49968d5f102de73c27
[2019-10-16 23:41:20.008512960][I][Irohad/Storage/MutableStorageImpl]: Applying block: height 14, hash 337830921603cc703cd8f95a6624b3d2d0fce090d3ddca53c69d9989620f2c44
[2019-10-16 23:41:20.022142829][I][Irohad/Storage/MutableStorageImpl]: Applying block: height 15, hash e602693381ff5ac383a2d62503d94ede87951ffdedefe9b4628a188036fd6c89
[2019-10-16 23:41:20.024153577][I][Irohad/Storage/MutableStorageImpl]: Applying block: height 16, hash d3e5c825cb9b1ca298ccf6b7b7f8a139803e6e1c9850fed65a0241f378f5125e
It seems that it takes about 0.01 seconds for a normally captured block and about 0.002 seconds for a rejected block. Of course, the processing speed will change depending on the performance of the server, but if you have to restart the daemon in actual operation, this processing may take longer than expected.
Will addPeer and removePeer work with the python library? Next, I would like to investigate this area.
Recommended Posts