Skip to content

Commit 40547b3

Browse files
authored
Improve Block Assembly service documentation accuracy and completeness (#242)
1 parent 40cffb2 commit 40547b3

File tree

1 file changed

+78
-39
lines changed

1 file changed

+78
-39
lines changed

docs/topics/services/blockAssembly.md

Lines changed: 78 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@
99
- [2.3. Grouping Transactions into Subtrees](#23-grouping-transactions-into-subtrees)
1010
- [2.3.1 Dynamic Subtree Size Adjustment](#231-dynamic-subtree-size-adjustment)
1111
- [2.4. Creating Mining Candidates](#24-creating-mining-candidates)
12+
- [2.4.1. Mining Candidate Caching](#241-mining-candidate-caching)
1213
- [2.5. Submit Mining Solution](#25-submit-mining-solution)
1314
- [2.6. Processing Subtrees and Blocks from other Nodes and Handling Forks and Conflicts](#26-processing-subtrees-and-blocks-from-other-nodes-and-handling-forks-and-conflicts)
1415
- [2.6.1. The block received is the same as the current chaintip (i.e. the block we have already seen).](#261-the-block-received-is-the-same-as-the-current-chaintip-ie-the-block-we-have-already-seen)
1516
- [2.6.2. The block received is a new block, and it is the new chaintip.](#262-the-block-received-is-a-new-block-and-it-is-the-new-chaintip)
1617
- [2.6.3. The block received is a new block, but it represents a fork.](#263-the-block-received-is-a-new-block-but-it-represents-a-fork)
17-
- [Fork Detection and Assessment](#fork-detection-and-assessment)
18-
- [Chain Selection and Reorganization Process](#chain-selection-and-reorganization-process)
18+
- [2.6.4. Fork Detection and Assessment](#264-fork-detection-and-assessment)
19+
- [2.6.5. Chain Selection and Reorganization Process](#265-chain-selection-and-reorganization-process)
20+
- [2.7. Unmined Transaction Cleanup](#27-unmined-transaction-cleanup)
1921
- [2.8. Resetting the Block Assembly](#28-resetting-the-block-assembly)
2022
3. [Data Model](#3-data-model)
2123
4. [gRPC Protobuf Definitions](#4-grpc-protobuf-definitions)
@@ -30,7 +32,11 @@
3032

3133
## 1. Description
3234

33-
The Block Assembly Service is responsible for assembling new blocks and adding them to the blockchain. The block assembly process involves the following steps:
35+
The Block Assembly Service is responsible for assembling new blocks and adding them to the blockchain.
36+
37+
**No Mempool Design**: Unlike traditional Bitcoin nodes that maintain a mempool (memory pool) to store unconfirmed transactions, Teranode's Block Assembly service processes transactions directly through a validation and subtree assembly pipeline. Transactions are immediately validated and organized into subtrees for efficient block creation, rather than being held in an intermediate memory pool. This design enables higher throughput and more efficient resource utilization for large-scale transaction processing.
38+
39+
The block assembly process involves the following steps:
3440

3541
1. **Receiving Transactions from the TX Validator Service**:
3642

@@ -70,11 +76,17 @@ The Block Assembly Service is responsible for assembling new blocks and adding t
7076
- The node also handles the resolution of forks in the blockchain and conflicting subtrees or blocks mined by other nodes.
7177
- This involves choosing between different versions of the blockchain (in case of forks) and resolving conflicts in transactions and subtrees included in other nodes' blocks.
7278

79+
9. **Periodic Unmined Transaction Cleanup**:
80+
81+
- The service periodically removes old unmined transactions that have exceeded their retention period.
82+
- This cleanup prevents unbounded growth of the UTXO store and maintains system performance.
83+
- Parent transactions of younger unmined transactions are preserved to maintain transaction dependencies.
84+
7385
> **Note**: For information about how the Block Assembly service is initialized during daemon startup and how it interacts with other services, see the [Teranode Daemon Reference](../../references/teranodeDaemonReference.md#service-initialization-flow).
7486
7587
A high level diagram:
7688

77-
![Block_Assembly_Service_Container_Diagram.png](img%2FBlock_Assembly_Service_Container_Diagram.png)
89+
![Block_Assembly_Service_Container_Diagram.png](img/Block_Assembly_Service_Container_Diagram.png)
7890

7991
Based on its settings, the Block Assembly receives TX notifications from the validator service via direct gRPC calls.
8092

@@ -116,18 +128,30 @@ When the Block Assembly service starts, it automatically recovers unmined transa
116128

117129
**Process Overview:**
118130

119-
1. **Wait for Pending Blocks**: The service first ensures all pending blocks are processed to avoid conflicts
120-
2. **Load Unmined Transactions**: Uses the `UnminedTxIterator` to retrieve all transactions marked with the `unminedSince` flag
121-
3. **Order by Creation Time**: Transactions are sorted topologically by their `createdAt` timestamp to maintain proper dependencies
122-
4. **Re-add to Processing**: Each unmined transaction is added back to the subtree processor using `AddDirectly()`
123-
5. **Unlock Transactions**: Previously locked transactions are unlocked to allow processing
131+
1. **Wait for Pending Blocks** - The service first ensures all pending blocks are processed to avoid conflicts
132+
2. **Load Unmined Transactions** - Uses the `UnminedTxIterator` to retrieve all transactions marked with the `unminedSince` flag
133+
3. **Order by Creation Time** - Transactions are sorted topologically by their `createdAt` timestamp to maintain proper dependencies
134+
4. **Re-add to Processing** - Each unmined transaction is added back to the subtree processor using `AddDirectly()`
135+
5. **Unlock Transactions** - Previously locked transactions are unlocked to allow processing
124136

125137
This recovery mechanism ensures that:
126138

127139
- Transactions accepted but not yet mined persist across restarts
128140
- Network participants don't need to resubmit transactions after node restarts
129141
- The transaction processing pipeline maintains continuity
130142

143+
**Startup Blocking Behavior:**
144+
145+
During the unmined transaction loading phase, the Block Assembly service sets an `unminedTransactionsLoading` flag that blocks certain operations to prevent inconsistent state:
146+
147+
- **Blocked Operations**: `SubmitMiningSolution`, `ResetBlockAssembly`, and `GenerateBlocks` requests are rejected during loading
148+
- **Error Response**: Clients receive a "service not ready - unmined transactions are still being loaded" error
149+
- **Purpose**: Prevents mining solution submissions or resets while the service is reconstructing its transaction state
150+
- **Duration**: Typically completes within seconds to minutes depending on the number of unmined transactions
151+
- **Visibility**: Service readiness should be checked via health endpoints before submitting critical requests
152+
153+
This blocking behavior ensures data integrity during startup and prevents race conditions that could result in lost transactions or inconsistent block assembly state.
154+
131155
### 2.2. Receiving Transactions from the TX Validator Service
132156

133157
![block_assembly_add_tx.svg](img/plantuml/blockassembly/block_assembly_add_tx.svg)
@@ -187,20 +211,35 @@ This self-tuning mechanism helps maintain consistent processing rates and optima
187211
- The Block Assembly Server makes status announcements, using the Status Client, about the mining candidate's height and previous hash.
188212
- Finally, the Server tracks the current candidate in the JobStore within a new "job" and its TTL. This information will be retrieved at a later stage, if and when the miner submits a solution to the mining challenge for this specific mining candidate.
189213

190-
**Mining Candidate Caching:**
214+
#### 2.4.1. Mining Candidate Caching
215+
216+
The Block Assembly service implements an intelligent caching mechanism for mining candidates to optimize performance and reduce redundant computations:
217+
218+
**Cache Behavior:**
219+
220+
- Mining candidates are cached when the block height remains unchanged
221+
- The cache has a configurable timeout (via `MiningCandidateCacheTimeout` setting)
222+
- Cache is automatically invalidated when:
223+
224+
- A new block is added to the blockchain (height changes)
225+
- New subtrees become available
226+
- The cache timeout expires
227+
228+
**Performance Benefits:**
191229

192-
To optimize performance for frequent GetMiningCandidate requests, the service implements a caching mechanism:
230+
- Reduces CPU overhead for miners requesting frequent updates
231+
- Eliminates redundant subtree processing and merkle tree calculations
232+
- Improves response times for mining candidate requests
233+
- Particularly beneficial for mining pools making high-frequency requests
193234

194-
- Mining candidates are cached for a configurable timeout period (default: a few seconds)
195-
- Subsequent requests within the timeout period return the cached candidate
196-
- Cache is invalidated when:
235+
**Implementation Details:**
197236

198-
- New subtrees are completed
199-
- A new block is received from the network
200-
- The timeout expires
201-
- This reduces computation overhead for high-frequency mining requests
237+
- Uses thread-safe locking to prevent race conditions during cache updates
238+
- Implements a generation flag to serialize concurrent candidate creation requests
239+
- Cache hit/miss metrics are exposed via Prometheus for monitoring
240+
- Disabled for difficulty adjustment scenarios (when `ReduceMinDifficulty` is enabled) to ensure accurate difficulty calculations
202241

203-
The caching strategy balances freshness against performance, ensuring miners receive recent candidates without overloading the system during rapid polling.
242+
This caching mechanism is transparent to miners and significantly improves the efficiency of the mining candidate generation process during normal operations.
204243

205244
### 2.5. Submit Mining Solution
206245

@@ -328,7 +367,7 @@ In this scenario, the function needs to handle a reorganization. A blockchain re
328367

329368
It is the responsibility of the block assembly to always build on top of the longest chain of work. For clarity, it is not the Block Validation or Blockchain services's responsibility to resolve forks. The Block Assembly is notified of the ongoing chains of work, and it makes sure to build on the longest one. If the longest chain of work is different from the current local chain the block assembly was working on, a reorganization will take place.
330369

331-
#### Fork Detection and Assessment
370+
#### 2.6.4. Fork Detection and Assessment
332371

333372
The Block Assembly service implements real-time fork detection through the following mechanisms:
334373

@@ -351,13 +390,13 @@ The Block Assembly service implements real-time fork detection through the follo
351390
3. **Reorganization Size Protection**:
352391

353392
- Monitors the size of potential chain reorganizations
354-
- If a reorganization would require moving more than 5 blocks either backwards or forwards
393+
- If a reorganization would require moving more than the coinbase maturity threshold (typically 100 blocks, configured via `Settings.ChainCfgParams.CoinbaseMaturity`) either backwards or forwards
355394
- AND the current chain height is greater than 1000 blocks
356395
- Triggers a full reset of the block assembler as a safety measure against deep reorganizations
357396

358397
The `BlockAssembler` keeps the node synchronized with the network by identifying and switching to the strongest chain (the one with the most accumulated proof of work), ensuring all nodes in the network converge on the same transaction history.
359398

360-
#### Chain Selection and Reorganization Process
399+
#### 2.6.5. Chain Selection and Reorganization Process
361400

362401
During a reorganization, the `BlockAssembler` performs two key operations:
363402

@@ -377,7 +416,7 @@ The service automatically manages chain selection through:
377416
- Accepts the chain with the most accumulated proof of work
378417
- Performs a safety check on reorganization depth:
379418

380-
- If the reorganization involves more than 5 blocks in either direction
419+
- If the reorganization involves more than the coinbase maturity threshold (typically 100 blocks, configured via `Settings.ChainCfgParams.CoinbaseMaturity`) in either direction
381420
- And the current chain height is greater than 1000
382421
- The block assembler will reset rather than attempt the reorganization
383422

@@ -396,24 +435,24 @@ The following diagram illustrates how the Block Assembly service handles a chain
396435

397436
- `err = b.handleReorg(ctx, bestBlockchainBlockHeader)`:
398437

399-
- Calls the `handleReorg` method, passing the current context (`ctx`) and the new best block header from the blockchain network.
400-
- The reorg process involves rolling back to the last common ancestor block and then adding the new blocks from the network to align the `BlockAssembler`'s blockchain state with the network's state.
438+
- Calls the `handleReorg` method, passing the current context (`ctx`) and the new best block header from the blockchain network.
439+
- The reorg process involves rolling back to the last common ancestor block and then adding the new blocks from the network to align the `BlockAssembler`'s blockchain state with the network's state.
401440

402441
- **Getting Reorg Blocks**:
403442

404-
- `moveBackBlocks, moveForwardBlocks, err := b.getReorgBlocks(ctx, header)`:
443+
- `moveBackBlocks, moveForwardBlocks, err := b.getReorgBlocks(ctx, header)`:
405444

406-
- Calls `getReorgBlocks` to determine the blocks to move down (to revert) and move up (to apply) for aligning with the network's consensus chain.
407-
- `header` is the new block header that triggered the reorg.
408-
- This step involves finding the common ancestor and getting the blocks from the current chain (move down) and the new chain (move up).
445+
- Calls `getReorgBlocks` to determine the blocks to move down (to revert) and move up (to apply) for aligning with the network's consensus chain.
446+
- `header` is the new block header that triggered the reorg.
447+
- This step involves finding the common ancestor and getting the blocks from the current chain (move down) and the new chain (move up).
409448

410-
- **Performing Reorg in Subtree Processor**:
449+
- **Performing Reorg in Subtree Processor**:
411450

412-
- `b.subtreeProcessor.Reorg(moveBackBlocks, moveForwardBlocks)`:
451+
- `b.subtreeProcessor.Reorg(moveBackBlocks, moveForwardBlocks)`:
413452

414-
- Executes the actual reorg process in the `SubtreeProcessor`, responsible for managing the blockchain's data structure and state.
415-
- The function reverts the coinbase Txs associated to invalidated blocks (deleting their UTXOs).
416-
- This step involves reconciling the status of transactions from reverted and new blocks, and coming to a curated new current subtree(s) to include in the next block to mine.
453+
- Executes the actual reorg process in the `SubtreeProcessor`, responsible for managing the blockchain's data structure and state.
454+
- The function reverts the coinbase Txs associated to invalidated blocks (deleting their UTXOs).
455+
- This step involves reconciling the status of transactions from reverted and new blocks, and coming to a curated new current subtree(s) to include in the next block to mine.
417456

418457
Note: If other nodes propose blocks containing a transaction that Teranode has identified as a double-spend (based on the First-Seen rule), Teranode will only build on top of such blocks when the network has reached consensus on which transaction to accept, even if it differs from Teranode's initial first-seen assessment. For more information, please review the [Double Spend Detection documentation](../architecture/understandingDoubleSpends.md).
419458

@@ -425,10 +464,10 @@ The Block Assembly service periodically cleans up old unmined transactions to pr
425464

426465
**Cleanup Process:**
427466

428-
1. **Periodic Trigger**: A background ticker (`unminedCleanupTicker`) runs at configured intervals
429-
2. **Age-Based Selection**: Identifies unmined transactions older than the retention period using `QueryOldUnminedTransactions`
430-
3. **Parent Preservation**: Protects parent transactions of younger unmined transactions from deletion
431-
4. **Batch Deletion**: Removes eligible transactions in batches to minimize performance impact
467+
1. **Periodic Trigger** - A background ticker (`unminedCleanupTicker`) runs at configured intervals
468+
2. **Age-Based Selection** - Identifies unmined transactions older than the retention period using `QueryOldUnminedTransactions`
469+
3. **Parent Preservation** - Protects parent transactions of younger unmined transactions from deletion
470+
4. **Batch Deletion** - Removes eligible transactions in batches to minimize performance impact
432471

433472
**Configuration:**
434473

@@ -506,7 +545,7 @@ The Block Assembly service implements robust error handling across multiple laye
506545

507546
- **Conflicting Transaction Detection**: During reorgs, the service identifies and marks conflicting transactions in affected subtrees
508547
- **Transaction Recovery**: Non-conflicting transactions are automatically re-added to new subtrees
509-
- **Deep Reorg Protection**: Reorganizations affecting more than 5 blocks trigger a full service reset for safety
548+
- **Deep Reorg Protection**: Reorganizations affecting more than the coinbase maturity threshold (typically 100 blocks) trigger a full service reset for safety
510549

511550
#### UTXO Store Unavailability
512551

0 commit comments

Comments
 (0)