Ethereum: How is a transaction ID generated and when does it change? (with a new sequence ID?)
Understanding Ethereum Transaction IDs
As a developer building a non-mainstream Ethereum client, you’re probably familiar with the concept of transaction IDs (TxIDs) on the Ethereum blockchain. In this article, we’ll look at how these unique identifiers are generated and what happens to them after each block.
Transaction ID Generation
A transaction ID is an 18-byte hexadecimal string that represents a single Bitcoin transaction. The generation process involves several steps:
- Block Creation: A new block is created on the Ethereum network when a valid transaction is broadcast to the network.
- Transaction Hashing: Each transaction in the block is hashed using the “sha256” algorithm, using the hash of the block as input and the Merkle root of all transactions as additional input.
- Transaction ID generation
: The transaction hash is then used to generate a unique 18-byte hexadecimal string called the transaction ID (TxID).
The TxID is generated in two parts:
- Block hash: This is the actual hash of the block, which is a combination of the block header and other metadata.
- Merkle root: This is an additional input to the transaction hashing algorithm that helps ensure uniqueness and integrity.
TxID generation algorithm
The Ethereum community has developed a consensus algorithm called “Keccak-256” for generating transaction IDs. The algorithm requires two inputs:
- Block hash: This is the actual hash of the block.
- Merkle Root
: This is an additional input to the Merkle Root calculation.
The resulting TxID is generated using a combination of the block hash and the Merkle Root, resulting in an 18-byte hexadecimal string.
When does it change?
After each block is created on the Ethereum network, the transaction ID for that block changes. This change occurs because each new block in the chain has its own unique transaction hash and Merkle Root.
To illustrate this concept, consider the following example:
- Block 1: A new block is created with a specific block hash (e.g., “0x1234567890abcdef”).
- Transaction Hashes: Each of the 10 transactions in Block 1 has its own unique transaction hash using Keccak-256.
- Merkle Roots: The Merkle root for each of these transactions is also generated.
So when we create new blocks on the Ethereum network, they have their own unique block hashes and Merkle roots, resulting in changes in the transaction IDs associated with those blocks.
Example use case:
To demonstrate how this works, let’s look at an example using Python:
import hashlib
import json
def generate_txid(block_hash):
Hashing function for Keccak-256def hash_function(input_string):
return hashlib.sha256(input_string.encode()).hexdigest()
block_merkle_root = hash_function(str(block_hash))
transaction_hashes = []
for i in range(10):
assume 10 transactionstxid = hash_function(json.dumps(i, sort_keys=True)) + block_merkle_root
transaction_hashes.append(txid)
return json.dumps(transaction_hashes), block_merkle_root
block_hash = "0x1234567890abcdef"
txids, merkle_root = generate_txid(block_hash)
print("Transaction Hashes:", txids)
print("Merkle Root:", merkle_root)
In this example, we create a new block hash using the hash_function
function. We then use this block hash as input to the transaction hashing algorithm and store the resulting TxID along with the Merkle root.
This process ensures that every new block on the Ethereum network has its unique transaction ID and Merkle root, resulting in changes to the transaction IDs associated with those blocks.
Conclusion
Understanding how transaction IDs are generated and changed is critical to building a reliable and efficient non-conventional Ethereum client.