Skip to content

Re-implement BIP68#547

Merged
ctnguyen merged 4 commits into
mainfrom
revert-546-bugfix/revert-bip68
Mar 31, 2026
Merged

Re-implement BIP68#547
ctnguyen merged 4 commits into
mainfrom
revert-546-bugfix/revert-bip68

Conversation

@ctnguyen

@ctnguyen ctnguyen commented Mar 3, 2026

Copy link
Copy Markdown
Collaborator

Reverts #546

Re-implements #514

@oskarszoon oskarszoon changed the title Revert "Revert BIP68 temporarily" Re-implement BIP68 Mar 3, 2026
@github-actions

github-actions Bot commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

🤖 Claude Code Review

Status: Complete

This PR re-implements BIP68 (relative lock-time via sequence numbers) after reverting PR 546. The implementation includes comprehensive unit and E2E tests.

Observations:

  1. MTP Approximation (Acknowledged): The code uses stored_mtp(blockHeight-1) during block validation (Validator.go:1239), which inline comments acknowledge as a 1-block-shifted approximation. E2E accept tests pass against real BSV nodes, and reject tests are skipped due to model.NewBlockFromMsgBlock limitations. A previous inline comment thread discusses this - appears intentional given timing constraints.

  2. CodeQL Warning (Line 408): Conversion of uint32 blockHeight to int32 without overflow check. While BSV block heights will not exceed 2^31-1 in practice for decades, this violates defensive coding principles and triggers static analysis warnings.

  3. Test Coverage: Strong coverage with unit tests (TxValidator_bip68_test.go: 559 lines) and E2E tests (bip68_test.go: 866 lines). Reject tests are appropriately skipped with clear explanations about model limitations.

  4. Architecture: Clean separation between ValidateTransaction and ValidateBIP68, avoiding unnecessary MTP lookups for invalid transactions. Follows project conventions.

The existing inline comment threads adequately cover the main architectural considerations. Human reviewers should verify the MTP approximation strategy and CodeQL findings.

Comment thread services/validator/Validator.go Outdated
// covers [blockHeight-12, blockHeight-2] — a 1-block-shifted approximation.
blockMTPHeight := blockHeight
if blockHeight > 0 {
blockMTPHeight = blockHeight - 1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical: MTP off-by-one error breaks BIP68 consensus

The code uses blockHeight - 1 to fetch MTP for block validation, but this is incorrect and breaks consensus with BSV nodes.

What BSV C++ does:
For block N validation, uses block.GetPrev()->GetMedianTimePast() = median([N-11, N-1])

What this code does:
Fetches stored_mtp(blockHeight-1) = median([N-12, N-2]) - off by one block

Impact:
Time-based BIP68 sequence locks will be validated against the wrong MTP, causing consensus divergence and potential chain splits.

Fix:
Calculate MTP as median([N-11, N-1]) during validation, not from pre-stored values.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for flagging this. After analyzing the code and tests:

Current Behavior:
The code at line 1211 does use blockHeight - 1, which the inline comment at line 1208 acknowledges creates a "1-block-shifted approximation."

Why E2E Tests Pass:
The E2E test TestBIP68_TimeBased_Accept validates against real BSV nodes successfully. However, TestBIP68_TimeBased_Reject is skipped (line 385 in bip68_test.go) with the note: "model.NewBlockFromMsgBlock only populates the coinbase subtree, so ValidateBlock never sees non-coinbase txs."

This suggests BIP68 may only be enforced during mempool validation (not block validation during IBD). During mempool validation, block N has already been persisted, making stored_mtp(blockHeight) available.

Recommendation:
Before treating this as critical, please verify:

  1. Is BIP68 enforced during block validation in the current codebase?
  2. If only during mempool validation, does the correct MTP become available?

Note: Line 1196 also has a documentation error claiming BSV uses median of [H-10, H] (including H), which contradicts BIP113 spec and other docs stating [H-11, H-1].

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue resolved in current code

The previous concern about blockHeight - 1 has been addressed. The code now correctly uses blockMTPHeight := blockHeight and fetches v.mtpStore[blockMTPHeight].

However, documentation error at line 1237: The comment incorrectly states BSV uses "median of [H-10, H] (includes H itself)". Per BIP113, MTP always uses the previous 11 blocks excluding the current block. The correct range is [H-11, H-1].

Comment thread services/validator/TxValidator.go Fixed
@ctnguyen ctnguyen force-pushed the revert-546-bugfix/revert-bip68 branch 3 times, most recently from 9d1ce4d to 5ce231d Compare March 3, 2026 14:04
@github-actions

github-actions Bot commented Mar 4, 2026

Copy link
Copy Markdown
Contributor

🤖 Claude Code Review

Status: Complete

Summary

This PR re-implements BIP68 (relative locktime) after reverting #546. The implementation adds:

  • Median Time Past (MTP) calculation and storage in the blockchain database
  • BIP68 sequence lock validation in the validator service
  • Comprehensive unit tests and E2E tests with real BSV node validation

Key Changes

MTP Storage (stores/blockchain/sql/StoreBlock.go:411)

  • Calculates and stores median_time_past for each block as median of previous 11 block timestamps
  • Schema migration adds median_time_past column to blocks table
  • Pre-computes MTP at persistence time for performance

MTP Retrieval (services/blockchain/median_time_past.go)

  • GetMedianTimePastForHeights - fetches MTPs for specific heights
  • GetMedianTimePastRange - efficient range fetching for bulk pre-loading
  • Handles edge case where block N is not yet persisted during validation by computing MTP on-the-fly

BIP68 Validation (services/validator/)

  • Two-phase validation: standard checks first, then BIP68 (avoids MTP lookups for invalid txs)
  • sequenceLocks implements height-based and time-based relative locktimes
  • Pre-loads MTP store at validator startup to avoid gRPC calls during concurrent validation
  • Correctly enforces CSV activation height

Test Coverage

  • 17 unit tests in TxValidator_bip68_test.go covering all BIP68 scenarios
  • E2E test (test/e2e/daemon/ready/bip68_test.go) validates against real BSV node

Review Findings

No issues found in current code. The implementation appears correct and well-tested.

Note on Existing Inline Comments

Several older inline comments on Validator.go reference code from earlier iterations of this PR that has since been corrected:

  • The MTP off-by-one issue has been fixed - code now uses blockMTPHeight := blockHeight (line 1264)
  • MTP calculation correctly implements median([H-11, H-1]) per BIP113
  • All comments and implementation are now accurate

These inline comments can be safely dismissed as they no longer apply to the current code.

Minor Observations

  1. Database migration - Schema adds median_time_past with DEFAULT 0 for existing blocks. Acceptable as BIP68 only applies from CSVHeight onwards.

  2. Performance - Pre-loading strategy (EnsureMTPLoaded) effectively avoids per-transaction RPC overhead during block validation.

  3. Test quality - E2E test validates against real BSV node, providing strong confidence in consensus compatibility.

Recommendation

Approve for merge. Implementation is well-designed, thoroughly tested, and correctly implements BIP68 relative locktimes.

@ctnguyen ctnguyen force-pushed the revert-546-bugfix/revert-bip68 branch from 4edf4e8 to 9a4169b Compare March 6, 2026 09:44
Comment thread services/validator/Validator.go Outdated
// Build utxoMTPs and blockMTP from the pre-loaded mtpStore (populated by EnsureMTPLoaded).
//
// Teranode stores MTP(H) = median of block timestamps [H-11, H-1].
// BSV's GetMedianTimePast() at block H = median of [H-10, H] (includes H itself),

@github-actions github-actions Bot Mar 6, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation error confirmed - comment is incorrect

The comment at line 1237 incorrectly states BSV GetMedianTimePast() includes block H itself in the median calculation [H-10, H].

This is wrong. Per BIP113 and BSV implementation, MTP of block H = median of previous 11 blocks only: [H-11, H-1]. Block H itself is never included.

The implementation is correct (uses stored_mtp(blockHeight) = median [blockHeight-11, blockHeight-1]), but this comment should be corrected.

@ctnguyen ctnguyen force-pushed the revert-546-bugfix/revert-bip68 branch from 9a4169b to 603ecfe Compare March 6, 2026 09:55
@github-actions

github-actions Bot commented Mar 6, 2026

Copy link
Copy Markdown
Contributor

🤖 Claude Code Review

Status: Complete


Current Review:

This PR re-implements BIP68 (relative lock-time via sequence numbers) after reverting #546. The implementation is well-structured with comprehensive tests and follows Bitcoin SV consensus rules.

Issue Found:

  • Documentation error at services/validator/Validator.go:1237 - comment incorrectly describes MTP calculation (see inline comment)

Implementation Quality:

  • Core logic is correct and matches BSV consensus
  • MTP values pre-loaded efficiently via EnsureMTPLoaded
  • Proper separation of BIP68 validation (Phase 2) from main validation
  • Strong test coverage including unit tests and E2E tests
  • Handles edge cases (version < 2, disable flag, pre-CSV blocks)

History:

  • ✅ Fixed: Previous off-by-one concern resolved - code now correctly uses blockMTPHeight = blockHeight

@ctnguyen ctnguyen force-pushed the revert-546-bugfix/revert-bip68 branch from 603ecfe to 878029e Compare March 6, 2026 10:24
@ctnguyen ctnguyen force-pushed the revert-546-bugfix/revert-bip68 branch from 878029e to 2c47434 Compare March 12, 2026 14:17

@oskarszoon oskarszoon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please dont merge until I've done some performance testing on Testnet

@ctnguyen ctnguyen force-pushed the revert-546-bugfix/revert-bip68 branch from 2c47434 to ec8d0bb Compare March 13, 2026 12:37
@ctnguyen ctnguyen requested a review from oskarszoon March 15, 2026 12:30
@ctnguyen ctnguyen force-pushed the revert-546-bugfix/revert-bip68 branch from ec8d0bb to 6ffee13 Compare March 31, 2026 08:35
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
50.0% Coverage on New Code (required ≥ 80%)
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@github-actions

Copy link
Copy Markdown
Contributor

Benchmark Comparison Report

Baseline: main (unknown)

Current: PR-547 (a13dda6)

Summary

  • Regressions: 0
  • Improvements: 0
  • Unchanged: 151
  • Significance level: p < 0.05
All benchmark results (sec/op)
Benchmark Baseline Current Change p-value
_NewBlockFromBytes-4 1.404µ 1.562µ ~ 0.100
SplitSyncedParentMap_SetIfNotExists/256_buckets-4 61.78n 61.73n ~ 1.000
SplitSyncedParentMap_SetIfNotExists/16_buckets-4 61.73n 61.70n ~ 1.000
SplitSyncedParentMap_SetIfNotExists/1_bucket-4 61.80n 61.75n ~ 0.500
SplitSyncedParentMap_ConcurrentSetIfNotExists/256_buckets... 30.69n 31.05n ~ 0.100
SplitSyncedParentMap_ConcurrentSetIfNotExists/16_buckets_... 52.42n 51.42n ~ 0.100
SplitSyncedParentMap_ConcurrentSetIfNotExists/1_bucket_pa... 106.7n 108.6n ~ 0.400
MiningCandidate_Stringify_Short-4 259.3n 269.1n ~ 0.100
MiningCandidate_Stringify_Long-4 1.876µ 1.852µ ~ 0.100
MiningSolution_Stringify-4 944.0n 944.3n ~ 0.600
BlockInfo_MarshalJSON-4 1.794µ 1.759µ ~ 0.100
NewFromBytes-4 131.4n 156.4n ~ 0.700
Mine_EasyDifficulty-4 58.17µ 58.42µ ~ 0.400
Mine_WithAddress-4 4.638µ 4.692µ ~ 0.100
BlockAssembler_AddTx-4 0.03139n 0.03028n ~ 1.000
AddNode-4 12.25 11.96 ~ 0.700
AddNodeWithMap-4 12.38 12.19 ~ 0.700
DirectSubtreeAdd/4_per_subtree-4 74.85n 77.13n ~ 0.700
DirectSubtreeAdd/64_per_subtree-4 41.22n 41.43n ~ 0.700
DirectSubtreeAdd/256_per_subtree-4 40.41n 39.88n ~ 0.100
DirectSubtreeAdd/1024_per_subtree-4 38.80n 38.59n ~ 0.400
DirectSubtreeAdd/2048_per_subtree-4 38.37n 38.10n ~ 0.300
SubtreeProcessorAdd/4_per_subtree-4 360.9n 342.4n ~ 0.100
SubtreeProcessorAdd/64_per_subtree-4 360.5n 344.3n ~ 0.100
SubtreeProcessorAdd/256_per_subtree-4 358.4n 345.3n ~ 0.700
SubtreeProcessorAdd/1024_per_subtree-4 355.3n 346.1n ~ 0.700
SubtreeProcessorAdd/2048_per_subtree-4 360.0n 353.5n ~ 0.100
SubtreeProcessorRotate/4_per_subtree-4 364.3n 352.8n ~ 0.100
SubtreeProcessorRotate/64_per_subtree-4 357.9n 349.0n ~ 0.100
SubtreeProcessorRotate/256_per_subtree-4 354.7n 350.7n ~ 0.100
SubtreeProcessorRotate/1024_per_subtree-4 352.7n 345.0n ~ 0.100
SubtreeNodeAddOnly/4_per_subtree-4 94.39n 92.53n ~ 0.700
SubtreeNodeAddOnly/64_per_subtree-4 67.36n 67.55n ~ 0.400
SubtreeNodeAddOnly/256_per_subtree-4 66.36n 66.12n ~ 0.400
SubtreeNodeAddOnly/1024_per_subtree-4 65.67n 65.38n ~ 0.600
SubtreeCreationOnly/4_per_subtree-4 161.6n 156.3n ~ 0.200
SubtreeCreationOnly/64_per_subtree-4 703.2n 721.3n ~ 1.000
SubtreeCreationOnly/256_per_subtree-4 2.548µ 2.648µ ~ 0.100
SubtreeCreationOnly/1024_per_subtree-4 9.212µ 9.028µ ~ 0.400
SubtreeCreationOnly/2048_per_subtree-4 17.51µ 17.33µ ~ 1.000
SubtreeProcessorOverheadBreakdown/64_per_subtree-4 354.4n 346.6n ~ 0.100
SubtreeProcessorOverheadBreakdown/1024_per_subtree-4 351.0n 348.5n ~ 0.700
ParallelGetAndSetIfNotExists/1k_nodes-4 1.013m 1.005m ~ 0.400
ParallelGetAndSetIfNotExists/10k_nodes-4 2.311m 2.327m ~ 0.700
ParallelGetAndSetIfNotExists/50k_nodes-4 10.69m 10.65m ~ 0.700
ParallelGetAndSetIfNotExists/100k_nodes-4 21.15m 20.92m ~ 0.700
SequentialGetAndSetIfNotExists/1k_nodes-4 789.9µ 796.2µ ~ 1.000
SequentialGetAndSetIfNotExists/10k_nodes-4 3.523m 3.519m ~ 1.000
SequentialGetAndSetIfNotExists/50k_nodes-4 13.09m 13.07m ~ 0.700
SequentialGetAndSetIfNotExists/100k_nodes-4 24.98m 25.24m ~ 1.000
ProcessOwnBlockSubtreeNodesParallel/1k_nodes-4 1.078m 1.077m ~ 1.000
ProcessOwnBlockSubtreeNodesParallel/10k_nodes-4 5.213m 5.195m ~ 0.400
ProcessOwnBlockSubtreeNodesParallel/100k_nodes-4 24.14m 24.25m ~ 0.200
ProcessOwnBlockSubtreeNodesSequential/1k_nodes-4 867.6µ 861.7µ ~ 0.100
ProcessOwnBlockSubtreeNodesSequential/10k_nodes-4 7.093m 7.065m ~ 1.000
ProcessOwnBlockSubtreeNodesSequential/100k_nodes-4 50.31m 50.67m ~ 0.700
DiskTxMap_SetIfNotExists-4 4.223µ 3.981µ ~ 0.100
DiskTxMap_SetIfNotExists_Parallel-4 3.799µ 3.894µ ~ 0.700
DiskTxMap_ExistenceOnly-4 326.9n 310.4n ~ 0.100
Queue-4 199.0n 197.9n ~ 0.100
AtomicPointer-4 8.142n 8.125n ~ 0.200
ReorgOptimizations/DedupFilterPipeline/Old/10K-4 825.7µ 777.8µ ~ 0.100
ReorgOptimizations/DedupFilterPipeline/New/10K-4 779.8µ 764.3µ ~ 0.100
ReorgOptimizations/AllMarkFalse/Old/10K-4 124.6µ 118.6µ ~ 0.200
ReorgOptimizations/AllMarkFalse/New/10K-4 58.62µ 58.26µ ~ 0.100
ReorgOptimizations/HashSlicePool/Old/10K-4 65.20µ 72.29µ ~ 0.200
ReorgOptimizations/HashSlicePool/New/10K-4 11.79µ 11.79µ ~ 0.500
ReorgOptimizations/NodeFlags/Old/10K-4 5.576µ 6.042µ ~ 0.700
ReorgOptimizations/NodeFlags/New/10K-4 1.864µ 1.828µ ~ 0.600
ReorgOptimizations/DedupFilterPipeline/Old/100K-4 11.66m 10.44m ~ 0.100
ReorgOptimizations/DedupFilterPipeline/New/100K-4 11.13m 10.66m ~ 0.100
ReorgOptimizations/AllMarkFalse/Old/100K-4 1.219m 1.158m ~ 0.100
ReorgOptimizations/AllMarkFalse/New/100K-4 734.1µ 725.2µ ~ 0.700
ReorgOptimizations/HashSlicePool/Old/100K-4 595.8µ 606.6µ ~ 0.100
ReorgOptimizations/HashSlicePool/New/100K-4 299.2µ 317.9µ ~ 0.100
ReorgOptimizations/NodeFlags/Old/100K-4 56.54µ 56.71µ ~ 1.000
ReorgOptimizations/NodeFlags/New/100K-4 18.97µ 19.31µ ~ 0.700
TxMapSetIfNotExists-4 53.35n 50.90n ~ 0.100
TxMapSetIfNotExistsDuplicate-4 44.02n 43.39n ~ 0.100
ChannelSendReceive-4 707.4n 708.0n ~ 0.800
CalcBlockWork-4 494.8n 494.1n ~ 1.000
CalculateWork-4 676.8n 692.8n ~ 0.400
BuildBlockLocatorString_Helpers/Size_10-4 1.453µ 1.399µ ~ 1.000
BuildBlockLocatorString_Helpers/Size_100-4 12.30µ 12.33µ ~ 1.000
BuildBlockLocatorString_Helpers/Size_1000-4 121.5µ 124.2µ ~ 0.700
CatchupWithHeaderCache-4 104.3m 104.2m ~ 0.700
_BufferPoolAllocation/16KB-4 3.375µ 3.316µ ~ 0.100
_BufferPoolAllocation/32KB-4 8.651µ 7.370µ ~ 0.400
_BufferPoolAllocation/64KB-4 14.66µ 14.72µ ~ 0.700
_BufferPoolAllocation/128KB-4 28.74µ 27.77µ ~ 0.100
_BufferPoolAllocation/512KB-4 113.6µ 113.3µ ~ 1.000
_BufferPoolConcurrent/32KB-4 19.23µ 19.19µ ~ 0.700
_BufferPoolConcurrent/64KB-4 30.78µ 30.17µ ~ 0.200
_BufferPoolConcurrent/512KB-4 146.0µ 135.4µ ~ 0.100
_SubtreeDeserializationWithBufferSizes/16KB-4 626.1µ 611.6µ ~ 0.400
_SubtreeDeserializationWithBufferSizes/32KB-4 620.9µ 620.7µ ~ 0.700
_SubtreeDeserializationWithBufferSizes/64KB-4 623.2µ 620.5µ ~ 0.700
_SubtreeDeserializationWithBufferSizes/128KB-4 622.0µ 613.6µ ~ 0.100
_SubtreeDeserializationWithBufferSizes/512KB-4 638.9µ 636.5µ ~ 1.000
_SubtreeDataDeserializationWithBufferSizes/16KB-4 35.38m 35.36m ~ 0.700
_SubtreeDataDeserializationWithBufferSizes/32KB-4 35.35m 35.26m ~ 1.000
_SubtreeDataDeserializationWithBufferSizes/64KB-4 35.43m 35.41m ~ 1.000
_SubtreeDataDeserializationWithBufferSizes/128KB-4 35.31m 35.44m ~ 0.400
_SubtreeDataDeserializationWithBufferSizes/512KB-4 34.90m 35.15m ~ 0.200
_PooledVsNonPooled/Pooled-4 735.8n 735.3n ~ 0.400
_PooledVsNonPooled/NonPooled-4 7.122µ 7.020µ ~ 0.100
_MemoryFootprint/Current_512KB_32concurrent-4 6.634µ 6.424µ ~ 0.100
_MemoryFootprint/Proposed_32KB_32concurrent-4 10.863µ 9.535µ ~ 0.100
_MemoryFootprint/Alternative_64KB_32concurrent-4 9.664µ 9.171µ ~ 0.100
_prepareTxsPerLevel-4 415.9m 414.3m ~ 1.000
_prepareTxsPerLevelOrdered-4 3.597m 3.862m ~ 0.100
_prepareTxsPerLevel_Comparison/Original-4 423.7m 420.5m ~ 0.400
_prepareTxsPerLevel_Comparison/Optimized-4 3.850m 3.707m ~ 0.200
SubtreeProcessor/100_tx_64_per_subtree-4 82.86m 82.29m ~ 0.400
SubtreeProcessor/500_tx_64_per_subtree-4 403.9m 397.1m ~ 0.400
SubtreeProcessor/500_tx_256_per_subtree-4 441.3m 409.3m ~ 0.100
SubtreeProcessor/1k_tx_64_per_subtree-4 791.6m 795.2m ~ 0.700
SubtreeProcessor/1k_tx_256_per_subtree-4 812.8m 817.7m ~ 0.400
StreamingProcessorPhases/FilterValidated/100_tx-4 2.843m 2.877m ~ 0.100
StreamingProcessorPhases/ClassifyProcess/100_tx-4 248.0µ 248.3µ ~ 1.000
StreamingProcessorPhases/FilterValidated/500_tx-4 13.95m 13.96m ~ 1.000
StreamingProcessorPhases/ClassifyProcess/500_tx-4 618.2µ 609.8µ ~ 0.700
StreamingProcessorPhases/FilterValidated/1k_tx-4 27.88m 28.13m ~ 0.700
StreamingProcessorPhases/ClassifyProcess/1k_tx-4 1.083m 1.067m ~ 0.700
SubtreeSizes/10k_tx_4_per_subtree-4 1.334m 1.342m ~ 0.100
SubtreeSizes/10k_tx_16_per_subtree-4 319.8µ 323.9µ ~ 0.100
SubtreeSizes/10k_tx_64_per_subtree-4 74.88µ 76.96µ ~ 0.100
SubtreeSizes/10k_tx_256_per_subtree-4 18.55µ 19.35µ ~ 0.100
SubtreeSizes/10k_tx_512_per_subtree-4 9.177µ 9.448µ ~ 0.100
SubtreeSizes/10k_tx_1024_per_subtree-4 4.592µ 4.710µ ~ 0.100
SubtreeSizes/10k_tx_2k_per_subtree-4 2.345µ 2.352µ ~ 0.500
BlockSizeScaling/10k_tx_64_per_subtree-4 72.98µ 75.68µ ~ 0.100
BlockSizeScaling/10k_tx_256_per_subtree-4 18.36µ 18.72µ ~ 0.100
BlockSizeScaling/10k_tx_1024_per_subtree-4 4.524µ 4.684µ ~ 0.100
BlockSizeScaling/50k_tx_64_per_subtree-4 395.3µ 398.3µ ~ 0.400
BlockSizeScaling/50k_tx_256_per_subtree-4 91.37µ 95.05µ ~ 0.100
BlockSizeScaling/50k_tx_1024_per_subtree-4 22.45µ 23.35µ ~ 0.100
SubtreeAllocations/small_subtrees_exists_check-4 156.7µ 162.8µ ~ 0.100
SubtreeAllocations/small_subtrees_data_fetch-4 159.6µ 167.5µ ~ 0.100
SubtreeAllocations/small_subtrees_full_validation-4 312.3µ 323.8µ ~ 0.100
SubtreeAllocations/medium_subtrees_exists_check-4 8.944µ 9.369µ ~ 0.100
SubtreeAllocations/medium_subtrees_data_fetch-4 9.326µ 9.590µ ~ 0.100
SubtreeAllocations/medium_subtrees_full_validation-4 18.23µ 18.98µ ~ 0.100
SubtreeAllocations/large_subtrees_exists_check-4 2.144µ 2.235µ ~ 0.100
SubtreeAllocations/large_subtrees_data_fetch-4 2.298µ 2.335µ ~ 0.100
SubtreeAllocations/large_subtrees_full_validation-4 4.541µ 4.704µ ~ 0.100
GetUtxoHashes-4 253.5n 257.8n ~ 0.100
GetUtxoHashes_ManyOutputs-4 42.83µ 45.69µ ~ 0.100
_NewMetaDataFromBytes-4 235.2n 234.1n ~ 0.700
_Bytes-4 616.8n 607.3n ~ 0.100
_MetaBytes-4 556.5n 554.5n ~ 0.400

Threshold: >10% with p < 0.05 | Generated: 2026-03-31 08:52 UTC

@ctnguyen ctnguyen merged commit 3a51130 into main Mar 31, 2026
29 checks passed
@ctnguyen ctnguyen deleted the revert-546-bugfix/revert-bip68 branch March 31, 2026 10:04
galt-tr pushed a commit to galt-tr/teranode that referenced this pull request Apr 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants