Skip to content

feat(nano): add transfer header format and validation#1653

Open
jansegre wants to merge 2 commits into
feat/nano/global-address-balance-statefrom
feat/nano/transfer-header
Open

feat(nano): add transfer header format and validation#1653
jansegre wants to merge 2 commits into
feat/nano/global-address-balance-statefrom
feat/nano/transfer-header

Conversation

@jansegre

@jansegre jansegre commented Apr 16, 2026

Copy link
Copy Markdown
Member

Motivation

Part of RFC#108 that introduces the TransferHeader wire format, its parser, and its stateless/stateful validation — the bridge primitive between UTXOs and the global address-balance map described in the RFC. Consensus-time execution (actually debiting/crediting the global map, nano-contract caller-funded flows, seqnum commits) is intentionally left for a follow-up; this PR only lands the header so it can be serialized, parsed, and rejected when invalid.

Acceptance Criteria

  • A new TransferHeader can be attached to a transaction, carrying addresses (authorization entries with address, seqnum, script), inputs (address_index, amount, token_index), and outputs (address, amount, token_index), serialized under header id 0x12.
  • The vertex parser recognizes all known header ids unconditionally; feature-flag enforcement moves into verification, and the per-vertex header cap grows from 2 to 3 to fit an additional header alongside nano/fee.
  • A TRANSFER_HEADER feature-activation flag and a matching ENABLE_TRANSFER_HEADER setting gate the header at verification time; the consensus reorg rule invalidates any tx that still carries a transfer header after the feature deactivates.
  • TransferHeaderVerifier enforces the RFC's structural rules: size limits on addresses/inputs/outputs, positive amounts, valid address/token indexes, regular-address-only credits, no duplicate (address, token) on either side, no same-pair on both sides, and every authorized address must be referenced by at least one input. Each InputAddress.script is evaluated against the address under opcodes V2 with sigop-count limits.
  • Balance verification reads the global address-balance trie of the best block to reject transfer inputs that exceed the current balance or use a seqnum outside the mempool window (MAX_SEQNUM_DIFF_MEMPOOL).
  • Transaction accounting is extended so transfer inputs and outputs participate in the per-token balance equation alongside UTXO and nano-contract movements; a transaction with a transfer header may have zero UTXO inputs.
  • Transaction.to_json / to_json_extended surface the transfer header (addresses, inputs, outputs, resolved token uids) and get_related_addresses includes both debited and credited addresses so indexers and wallets can track them.
  • Transfer headers on nano transactions are explicitly rejected for now, keeping the caller-funded contract flow out of scope until execution lands.
  • The DAG builder gains nc_transfer_input / nc_transfer_output attributes so tests can construct transactions with transfer headers, auto-assigning seqnums (shared with nano seqnums) and signing the header against the transaction sighash.
  • Unit tests cover header round-trip (de)serialization, full-transaction round-trip, related-addresses/json exposure, DAG builder integration, P2SH-authorized input acceptance, duplicate-output rejection, insufficient-funds rejection, and the verification service wiring.

Checklist

  • If you are requesting a merge into master, confirm this code is production-ready and can be included in future releases as soon as it gets merged

@jansegre jansegre requested review from glevco and msbrogli April 16, 2026 16:25
@jansegre jansegre self-assigned this Apr 16, 2026
@jansegre jansegre moved this from Todo to In Progress (WIP) in Hathor Network Apr 16, 2026
@codecov

codecov Bot commented Apr 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 76.27551% with 93 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.01%. Comparing base (58d1ae0) to head (791dd28).

Files with missing lines Patch % Lines
hathor/verification/transfer_header_verifier.py 60.82% 19 Missing and 19 partials ⚠️
hathor/transaction/transaction.py 56.09% 17 Missing and 1 partial ⚠️
hathor/dag_builder/vertex_exporter.py 80.00% 9 Missing and 5 partials ⚠️
hathor/consensus/consensus.py 11.11% 7 Missing and 1 partial ⚠️
...thor/transaction/vertex_parser/_transfer_header.py 87.30% 4 Missing and 4 partials ⚠️
hathor/dag_builder/builder.py 75.00% 2 Missing and 2 partials ⚠️
hathor/verification/verification_service.py 71.42% 1 Missing and 1 partial ⚠️
hathor/transaction/vertex_parser/_headers.py 94.11% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@                             Coverage Diff                             @@
##           feat/nano/global-address-balance-state    #1653       +/-   ##
===========================================================================
- Coverage                                  100.00%   85.01%   -14.99%     
===========================================================================
  Files                                           1      480      +479     
  Lines                                          25    30162    +30137     
  Branches                                        0     4526     +4526     
===========================================================================
+ Hits                                           25    25643    +25618     
- Misses                                          0     3615     +3615     
- Partials                                        0      904      +904     
Flag Coverage Δ
test-lib 85.00% <76.27%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jansegre jansegre force-pushed the feat/nano/global-address-balance-state branch 3 times, most recently from a0cf66d to 81878a5 Compare April 20, 2026 16:59
@jansegre jansegre force-pushed the feat/nano/transfer-header branch from c50cae0 to 1672ba9 Compare April 20, 2026 20:28
@jansegre jansegre force-pushed the feat/nano/global-address-balance-state branch from 81878a5 to cc941ca Compare April 23, 2026 15:33
@jansegre jansegre force-pushed the feat/nano/global-address-balance-state branch from cc941ca to 58d1ae0 Compare May 12, 2026 12:56
@jansegre jansegre force-pushed the feat/nano/transfer-header branch from 1672ba9 to 791dd28 Compare May 12, 2026 13:41
@jansegre jansegre force-pushed the feat/nano/global-address-balance-state branch from 58d1ae0 to ee7e6ff Compare May 19, 2026 14:17
@jansegre jansegre force-pushed the feat/nano/global-address-balance-state branch from ee7e6ff to 2022c13 Compare June 3, 2026 15:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress (WIP)

Development

Successfully merging this pull request may close these issues.

1 participant