HIP-1127: Transaction Cleanup
Author | Michael Heinrichs, Michael Tinker |
---|---|
Working Group | Richard Bair, Jasper Potts |
Requested By | Richard Bair <@rbair> |
Status | Last Call ⓘ |
Needs Hedera Approval | Yes ⓘ |
Needs Hiero Review | Yes ⓘ |
Review period ends ⓘ | Wed, 16 Jul 2025 07:00:00 +0000 |
Type | Standards Track ⓘ |
Category | Service ⓘ |
Created | 2025-02-17 |
Updated | 2025-07-02 |
Requires | 1056 |
Table of Contents
Abstract
The Transaction
protobuf message in the legacy record stream supports two ways to represent a transaction.
- The
Transaction.signedTransactionBytes
field. - Deprecated The
Transaction.bodyBytes
andTransaction.sigMap
fields combination.
The definition of the transaction hash differs between the two representations. For (1), the transaction
hash is the SHA-384 hash of the raw bytes in the signedTransactionBytes
field. But for (2), the transaction
hash is the SHA-384 hash of the protobuf serialization of the entire Transaction
message; where this
serialization must be done using ascending protobuf field order.
This HIP defines a single transaction representation for the block stream and preserves existing hash-based look-ups, so no client code changes are required.
This HIP does not propose any changes to the Hiero API (HAPI) or to the existing record stream. The
consensus node will do all needed conversions from and to legacy Transaction
messages for the foreseeable
future.
Motivation
Unnecessary nesting in the Transaction
message bloats the block stream and increases the serialization
work done by consumers. The SignedTransaction
message is a better, cleaner candidate for representing
transactions in the block stream. This message is,
message SignedTransaction {
/**
* A byte array containing a serialized `TransactionBody`.
* <p>
* This content is what the signatures in `sigMap` MUST sign.
*/
bytes bodyBytes = 1;
/**
* A set of cryptographic signatures.
* <p>
* This set MUST contain all signatures required to authenticate
* and authorize the transaction.<br/>
* This set MAY contain additional signatures.
*/
SignatureMap sigMap = 2;
}
Rationale
We could specify the block stream’s representation with a TransactionBody body
field instead of the
serialized bodyBytes
. But we feel it is important to make the block stream definition explicitly encode
the signed bytes, as this is such a fundamental part of the protocol.
We could also extend HAPI to let clients submit SignedTransaction
s instead of Transaction
s.
This would be nice, but does not offer a compelling return on investment at the current stage of the project.
User stories
- As a transaction sender, I want to be able to send transactions using both
Transaction
representations so that I am not forced to rewrite the calling code (which may be impossible). - As a record stream/block stream consumer, I want a simple way to parse transactions and extract data.
- As a transaction signer, I want to be sure that my signatures can always be validated, even if transactions are modified to follow the normalized format.
- As a user of APIs that take transaction hashes as input, I want block stream consumers to preserve the
current transaction hash definitions for both
Transaction
representations.
Specification
The protobuf definition of the Transaction
object will not change. The SignedTransaction
message will
get one new field, a boolean that is true iff the transaction was originally submitted using the deprecated
bodyBytes
and sigMap
combination,
message SignedTransaction {
...
/**
* If false then the hash of this transaction is the SHA-384 hash of the
* serialization of this SignedTransaction message as it arrived on the wire.
* <p>
* If true then the hash of this transaction is the SHA-384 hash of the
* ascending field order serialization of the Transaction whose `bodyBytes`
* and sigMap fields are deserialized from the contents of this message.
*/
boolean use_legacy_transaction_hash_algorithm = 3;
}
Modification of incoming transactions
When a node receives a Transaction
using the signedTransactionBytes
field, it will submit those
signedTransactionBytes
contents directly into consensus gossip.
When a node receives a Transaction
using the bodyBytes
and sigMap
combination, it will repackage
those two fields inside a SignedTransaction
along with use_legacy_transaction_hash_algorithm=true
,
and submit the serialization of the repackaged message to consensus gossip.
Changes in record stream and block stream
Nothing will change in the record stream. The oneof item
in the block stream’s BlockItem
message
will replace its EventTransaction
choice with a SignedTransaction
choice,
message BlockItem {
...
oneof item {
...
/**
* A single logical transaction in the block stream.
* <p>
* If this item is not followed by a `state_changes` item
* before the appearance of the next `signed_transaction`,
* it MUST be taken as purely informational; that is, as a
* "synthetic" transaction whose only purpose is to increase
* the legibility of the block stream semantics to consumers
* that do not themselves simulate consensus node logic.
*/
proto.SignedTransaction signed_transaction = 4;
...
}
}
Backwards Compatibility
A user can always find the original serialized bytes of their submitted Transaction
in the record
stream, even if they used the deprecated bodyBytes
and sigMap
combination. The block stream
will not preserve this property for deprecated submissions.
But it will still let a user find their deprecated transactions by TransactionID
or hash in the
stream. So this is only a minor inconvenience, not a fundamentally breaking change.
Security Implications
This change has no known security implications.
How to Teach This
The block stream standardizes to a single transaction representation, the SignedTransaction
.
Users that look up transactions by hash can continue to do this as they do today.
Rejected Ideas
- Keep
EventTransaction
in the block stream. (The parsing and wrapper overhead was deemed excessive.) - Use any of the other fields as the standard format.
- Introduce a new transaction type.
Copyright/license
This document is licensed under the Apache License, Version 2.0 – see LICENSE or (https://www.apache.org/licenses/LICENSE-2.0)
Citation
Please cite this document as: