Transaction Batches in Hyperledger Iroha

Sara Garifullina
Hyperledger Iroha Contributors
2 min readApr 18, 2019

Hello!

Today we would like to share Iroha use-case in which you should be very cautious — with atomic and ordered batches.

What batches of transactions are available in Iroha?

As you probably know, if you are an advanced user of Iroha, or will learn now if you are not, yet:

Atomic batch is a batch of transactions, in which all of the transactions should pass stateful validation to be committed. If any of the transactions did not pass, the whole batch will be rejected.

Ordered batch is a batch, in which the transactions will be committed in the exact order, set in the batch.

Batches are a great way to encode some business logic if, for example, you want to exchange something — an atomic batch will only work if both of the transactions are validated.

Or if you want the commands to follow in the exact order — you can use an ordered batch.

Let’s try it out

As great as the feature might be, you need to use it carefully. Iroha will store the information that it was a batch of transaction — but not the type of the batch. Let’s try to run a batch example. It will result in the following block being created:

{
"blockV1": {
"payload": {
"transactions": [
{
"payload": {
"reducedPayload": {
"commands": [
{
"transferAsset": {
"srcAccountId": "alice@test",
"destAccountId": "bob@test",
"assetId": "bitcoin#test",
"amount": "1"
}
}
],
"creatorAccountId": "alice@test",
"createdTime": "1554800002453",
"quorum": 2
},
"batch": {
"reducedHashes": [
"f813bd0590cebfaa5b2bea0bd79ef53e49a946ea4c77a55be1414906dea7a725",
"215667fc2453ddc055b07cb559c68e25ac7248d190c20784e3c152ad6992541e"
]
}

},
"signatures": [
{
"publicKey": "afbe0a34fbab84e49670a4c7b374a2841ddcd9c1abef70a8de2e513ba8d9db16",
"signature": "72f5b2adb812c55ca3577a6beb999aeb4ab558c71706c05940bf8fb47870bcf7515d300729a3ed2954d4054570ccddbb80feddf92189dd77a834dc8f0698bc0c"
},
{
"publicKey": "ba9c645853baf7718dfa39689a0faca505bf4c0d50f74d2ee4afb200aee8bc19",
"signature": "43a068d6a9d308c4685e3d1a36af412c679ff64f920a3784e6bc91c533df6ad128401c05f497429c7b31e61655bf6c13e74f88a004e63a0b6f5ab82cf4705c03"
}
]
},
{
"payload": {
"reducedPayload": {
"commands": [
{
"transferAsset": {
"srcAccountId": "bob@test",
"destAccountId": "alice@test",
"assetId": "dogecoin#test",
"amount": "2"
}
}
],
"creatorAccountId": "bob@test",
"createdTime": "1554800002453",
"quorum": 1
},
"batch": {
"reducedHashes": [
"f813bd0590cebfaa5b2bea0bd79ef53e49a946ea4c77a55be1414906dea7a725",
"215667fc2453ddc055b07cb559c68e25ac7248d190c20784e3c152ad6992541e"
]
}

},
"signatures": [
{
"publicKey": "63a873f9298e813dbe95b96ffdceae649289180dabe04841a78138c31fa8e518",
"signature": "059416bb5eb0321c5e191c709c2ff30d262e65c1a813b84717105eac5bf8ff56d9f4e59867a9ebe9619676b5efcf61715eb81786f4994170e8bb29778287f909"
},
{
"publicKey": "b3d0b7513a3cac2bc2c25158cb7bbfdb5dda518d92a8fc1070ac217118d87994",
"signature": "f7e7feae58c0c4390f9acaf8a8fb0dcbeea543e43fb2294d388ddd23f2926b1c7208dd86296facf8edf18a706cbc59087bde4cac9d92957efd2fbdf80d40bc0c"
}
]
}
],
"height": "5",
"prevBlockHash": "567d89b8f73024a7e186cfda8d7b92ba602f05735ae284ef9c41d960b8ebc4fa",
"createdTime": "1554800006546"
},
"signatures": [
{
"publicKey": "bddd58404d1315e0eb27902c5d7c8eb0602c16238f005773df406bc191308929",
"signature": "9c4eb4aa3b111a98265617942a26eb680792794c91ac068255be9c5683b5a62b80f57e8ec502504712406c0e704f1da891fb72918aaa11a5f198b7131a874100"
}
]
}
}%

As you can see — the type of the batch is not determined.

And here is what a block with single transactions will look like if we run a single transaction:

{
"blockV1": {
"payload": {
"transactions": [
{
"payload": {
"reducedPayload": {
"commands": [
{
"addSignatory": {
"accountId": "bob@test",
"publicKey": "63a873f9298e813dbe95b96ffdceae649289180dabe04841a78138c31fa8e518"
}
},
{
"setAccountQuorum": {
"accountId": "bob@test",
"quorum": 2
}
}
],
"creatorAccountId": "bob@test",
"createdTime": "1554800001380",
"quorum": 1
}
},
"signatures": [
{
"publicKey": "b3d0b7513a3cac2bc2c25158cb7bbfdb5dda518d92a8fc1070ac217118d87994",
"signature": "fc16ebeaeef97821bbf56e0d817f30b85349ba4252e1fdc0fb54b8d78e2f6c0d767c48f58ebe09238bfa049ea7c5a785a9af7ac243657cfc9df85d9f2367ec04"
}
]
}
],
"height": "4",
"prevBlockHash": "00f701ff6aed7fbdfbf2998fb403de47e4c1ab83a933fa6d18137cddebd44996",
"createdTime": "1554800002380"
},
"signatures": [
{
"publicKey": "bddd58404d1315e0eb27902c5d7c8eb0602c16238f005773df406bc191308929",
"signature": "de28b5afb1830b8834d5b4551ff7761f937cc9b53c55d25f611b0ffb1c0033b5a10b6971cc491a21d65bd5da62dc5a089050aea6c61fe48092dcef3da8c2b30c"
}
]
}
}%

How to use batches safely in production?

This means that you must validate ordered and atomic batches separately on your client side if in your use case this might be an issue.

For example, if you use a Java library, validation might look like this:

iroha.protocol.TransactionOuterClass.Transaction transaction;// …if (transaction.getPayload().getBatch().getType() == TransactionOuterClass.Transaction.Payload.BatchMeta.BatchType.ATOMIC) {// this is ATOMIC}

I hope you found this interesting!

You are welcome to subscribe to the blog for new posts like this one

🖖

--

--