Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -748,14 +748,37 @@ Upgrading from v0.16.0 changes nothing for them; upgrading from an earlier relea
invalid transaction is; the retryable error is returned only when nothing is
proven. A block that used to retry indefinitely may now be rejected on the first
attempt. This includes a walk over the `utxostore_conflictingChildrenMaxNodes`
budget that already reached a mined member: raising the setting no longer
changes that verdict. The fresh-path change also reaches `ValidateSubtreeInternal`,
budget that already reached a mined counter-conflicting transaction (a
conflicting transaction, a counter-spender or a counter-spender's descendant;
the conflicting transactions' own descendants are only checked for frozen
outputs): raising the setting no longer changes that verdict. The fresh-path change also reaches `ValidateSubtreeInternal`,
so `CheckSubtreeFromBlock` and live peer subtrees return a proven conflict as
`TX_INVALID` too. On the live path, `subtreeMessageHandler` now logs it at error
level ("error processing kafka message") where it logged a "Context canceled,
skipping" warning, so operators will see new error-level log lines for such
subtrees. Nothing to configure. (bsv-blockchain/teranode#2052)

- **Conflict-check failures in subtree validation are no longer reported as
context cancellations.** Two follow-ups to the entry above, both in subtree
validation's conflict check:
- On the fresh path (`CheckBlockSubtrees` on a new subtree, `CheckSubtreeFromBlock`,
live peer subtrees), a store fault, the `utxostore_conflictingChildrenMaxNodes`
walk limit, a frozen output, an input out of range and the fail-fast
missing-tx threshold are no longer wrapped as a context cancellation. Each is
still retried and never charged to a peer. What changes is how they show up:
on the live path `subtreeMessageHandler` logs them at error level ("error
processing kafka message") where it logged a "Context canceled, skipping"
warning, and a catch-up run that ends on the walk limit, a frozen output or an
out-of-range input records `local_processing_fault` instead of
`local_context_cancelled` as its last error type. A missing record, a
cancelled check, and a record the store could not decode keep the old
classification.
- On the fresh path a proven conflict is rejected with `TX_INVALID` even when
the check's context is cancelled while it runs, as the cached path and
blessing a missing transaction already did. Before, it was retried.

Nothing to configure. (bsv-blockchain/teranode#2066)

### Not breaking, but worth knowing

- **Peer subtrees announced during a catchup are validated afterwards instead of
Expand Down
2 changes: 1 addition & 1 deletion docs/references/settings/stores/utxo_settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
| MaxMinedBatchSize | int | 1024 | utxostore_maxMinedBatchSize | Max mined transaction batch size |
| BlockHeightRetentionAdjustment | int32 | 0 | utxostore_blockHeightRetentionAdjustment | **CRITICAL** - Retention adjustment |
| DisableDAHCleaner | bool | false | utxostore_disableDAHCleaner | **CRITICAL** - DAH cleaner process control |
| ConflictingChildrenMaxNodes | int | 100000 | utxostore_conflictingChildrenMaxNodes | Fail-closed node budget per root of a conflicting-descendant walk (<=0 = unlimited). Subtree validation walks a block's conflicting transactions as one batch from N roots (the transactions and their counter-spenders) and allows N × this budget: the old aggregate bound of N separate walks. Worst case, the visited set reaches N × this budget entries, and a single runaway cone fails after N × this budget reads rather than this budget. A walk that stops on the budget still rejects the block with `TX_INVALID` if it already reached a transaction mined on the candidate chain; otherwise the block fails with `UTXO_WALK_LIMIT_EXCEEDED` and is retried |
| ConflictingChildrenMaxNodes | int | 100000 | utxostore_conflictingChildrenMaxNodes | Fail-closed node budget per root of a conflicting-descendant walk (<=0 = unlimited). Subtree validation walks a block's conflicting transactions as one batch from N roots (the transactions and their counter-spenders) and allows N × this budget: the old aggregate bound of N separate walks. Worst case, the visited set reaches N × this budget entries, and a single runaway cone fails after N × this budget reads rather than this budget. A walk that stops on the budget still rejects the block with `TX_INVALID` if it already reached a counter-conflicting transaction (a conflicting transaction, a counter-spender or a counter-spender's descendant) mined on the candidate chain; the conflicting transactions' own descendants are only checked for frozen outputs. Otherwise the block fails with `UTXO_WALK_LIMIT_EXCEEDED` and is retried |

### PostgreSQL Connection Pool (PostgresPool)

Expand Down
14 changes: 13 additions & 1 deletion services/blockvalidation/BlockValidation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,13 @@ func (m *MockSubtreeValidationClient) CheckBlockSubtrees(ctx context.Context, bl
// proper test isolation. Each configure func adjusts the settings the stores and
// the subtree validation server are built with.
func setup(t *testing.T, configure ...func(*settings.Settings)) (utxostore.Store, subtreevalidation.Interface, blockchain.ClientI, blob.Store, blob.Store, func()) {
return setupWithSubtreeValidationStore(t, nil, configure...)
}

// setupWithSubtreeValidationStore is setup, with the subtree validation server
// reading the UTXO store through wrap, when wrap is not nil. The returned store
// is the unwrapped one.
func setupWithSubtreeValidationStore(t *testing.T, wrap func(utxostore.Store) utxostore.Store, configure ...func(*settings.Settings)) (utxostore.Store, subtreevalidation.Interface, blockchain.ClientI, blob.Store, blob.Store, func()) {
// we only need the httpClient, utxoStore and validatorClient when blessing a transaction
httpmock.ActivateNonDefault(util.HTTPClient())
httpmock.RegisterResponder(
Expand Down Expand Up @@ -351,7 +358,12 @@ func setup(t *testing.T, configure ...func(*settings.Settings)) (utxostore.Store

nilConsumer := &kafka.KafkaConsumerGroup{}

subtreeValidationServer, err := subtreevalidation.New(context.Background(), ulogger.TestLogger{}, tSettings, subtreeStore, txStore, utxoStore, validatorClient, blockchainClient, nilConsumer, nilConsumer, nil, nil)
subtreeValidationStore := utxostore.Store(utxoStore)
if wrap != nil {
subtreeValidationStore = wrap(utxoStore)
}

subtreeValidationServer, err := subtreevalidation.New(context.Background(), ulogger.TestLogger{}, tSettings, subtreeStore, txStore, subtreeValidationStore, validatorClient, blockchainClient, nilConsumer, nilConsumer, nil, nil)
if err != nil {
panic(err)
}
Expand Down
Loading
Loading