TRON TAPOS: Check a Transaction’s Reference Block

Written by

in

TRON TAPOS uses ref_block_bytes and ref_block_hash to reference a recent block. You can compare those fragments with a supplied block header offline. The two-byte number fragment does not identify a unique height by itself, and a matching fragment check does not prove that a node would accept a transaction today.

This guide shows a read-only reference-block investigation using a real Mainnet body and a fetched header, checked October 29, 2026. It is useful when an exported transaction contains unfamiliar reference fields or an application reports a reference-related error. It does not construct, repair, sign or broadcast a transaction. The Tronscan News guide collection provides the wider independent context.

TRON TAPOS map showing a two-byte number fragment and an eight-byte block ID fragment
Original field map. Byte ranges are zero-based and their end positions are excluded.

1. Separate a reference block from the containing block

A transaction’s containing block is the block in which it was included. Its reference block is an earlier chain context encoded in the raw payload. These are different roles. A receipt’s block number helps locate execution; it is not a replacement for the raw payload’s reference fields.

The official transaction protocol guide explains TAPOS as a replay-protection mechanism. It specifies a two-byte slice from the reference block number and an eight-byte slice from the block ID. Our utility checks those supplied fragments. It does not inspect a node’s recent-block store or reproduce the full admission process.

Field or record Role in this investigation Do not substitute
raw_data.ref_block_bytes Two bytes from the reference block number A complete block height
raw_data.ref_block_hash Eight bytes from the reference block ID The complete block ID or transaction hash
Receipt blockNumber Known inclusion context for our dated example Proof that this is the reference block
Fetched block header Number and block ID to compare with the fragments Proof of signatures, chain finality or contents

If you first need to locate a height, header or transaction list, use the existing TRON block-page guide. The task here begins after you have a transaction body and a proposed reference header. It adds a specific byte comparison rather than another overview of block fields.

2. Read the byte ranges without confusing hex characters

Represent the block number as eight bytes in big-endian order. Take bytes at indexes 6 and 7, written as the slice [6:8]. For the block ID, decode its 64 hexadecimal characters into 32 bytes and take indexes 8 through 15, the slice [8:16].

One byte is displayed as two hexadecimal characters. Consequently, the eight-byte block-ID fragment occupies hexadecimal character positions 16 through 31. Slicing characters at positions 8 through 15 would select four bytes from the wrong location. Decode first and use byte indexes to make the intended operation explicit.

The official block structure documentation describes TRON’s composite block ID: its first eight bytes encode the height, followed by a content-derived suffix. The check below confirms that the ID’s number prefix agrees with the supplied header number. It does not recompute the content-derived suffix from serialized header data.

A display label calling the value a “hash” does not change these byte positions. Preserve the exact field name and complete value in your working note. Do not paste an abbreviated explorer label, an address or a TxID into the block-ID input just because it is also a long hexadecimal string.

3. Choose a candidate height using dated context

The two-byte fragment repeats every 65536 heights. If you know a relevant upper context height, a useful candidate is the latest height at or below that context with the same low two bytes. This is an investigation aid, not a claim that the fragment alone proves which block was referenced.

The arithmetic is candidate = context - ((context - low_fragment) % 65536). We used the observed containing block, 87520996, as context for the retained transaction. The low fragment 76e2 is 30434 in decimal. The calculation selected candidate height 87520994.

Another height 65536 lower has the same low fragment. Another height 65536 higher does too. Without context and the ID-fragment comparison, the short number fragment leaves that ambiguity unresolved. A context from another chain or an unrelated date can therefore guide you to an irrelevant candidate.

  1. Retain the complete transaction body and source network.
  2. Identify the context height and document where it came from. Our example used a matching execution receipt’s containing block.
  3. Compute one candidate using the low-fragment arithmetic.
  4. Fetch that candidate’s header from the same network, then inspect the response content.
  5. Compare both reference fragments, preserving any disagreement and the original input files.

We used the documented GetBlock endpoint with the candidate height and a header-only response. The reference’s example host is Shasta testnet; our actual request used Mainnet at https://api.trongrid.io/wallet/getblock. A successful HTTP status is insufficient if the response contains an error or lacks the required header.

Candidate height calculation using context 87520996 and low fragment 76e2 to select 87520994
Original candidate worksheet from the dated observation. Context supplies information that the short fragment cannot.

4. Run the offline TRON TAPOS fragment check

Save your complete body as body.json, the proposed header response as reference-block.json and the code below as check_reference.py. With Python available, run python check_reference.py body.json reference-block.json 87520996 for our example’s context. Substitute your own documented context when investigating another transaction.

import json
import re
import sys


def exact_hex(value, byte_count, name):
    if not isinstance(value, str) or not re.fullmatch('[0-9a-fA-F]{' + str(byte_count * 2) + '}', value):
        raise ValueError(name + ' must be unprefixed hexadecimal of the expected length')
    return bytes.fromhex(value)


def height(value, name):
    if type(value) is not int or not 0 <= value <= 9223372036854775807:
        raise ValueError(name + ' must be a nonnegative signed-int64 height')
    return value


def candidate_height(ref_bytes, context_height):
    low = int.from_bytes(exact_hex(ref_bytes, 2, 'ref_block_bytes'), 'big')
    context = height(context_height, 'context height')
    candidate = context - ((context - low) % 65536)
    if candidate < 0:
        raise ValueError('No nonnegative candidate at or below this context')
    return candidate


def check_reference(body, block, context_height):
    if not isinstance(body, dict) or not isinstance(block, dict):
        raise ValueError('Expected transaction-body and block objects')
    raw = body.get('raw_data')
    if not isinstance(raw, dict):
        raise ValueError('Missing transaction raw_data object')
    ref_bytes = exact_hex(raw.get('ref_block_bytes'), 2, 'ref_block_bytes')
    ref_hash = exact_hex(raw.get('ref_block_hash'), 8, 'ref_block_hash')
    header = block.get('block_header', {}).get('raw_data', {})
    number = height(header.get('number'), 'block number')
    block_id = exact_hex(block.get('blockID'), 32, 'blockID')
    if int.from_bytes(block_id[:8], 'big') != number:
        raise ValueError('Block ID height prefix disagrees with header number')
    number_bytes = number.to_bytes(8, 'big')
    return {
        'supplied_block_number': number,
        'context_height': height(context_height, 'context height'),
        'latest_congruent_candidate': candidate_height(raw['ref_block_bytes'], context_height),
        'number_fragment_matches': number_bytes[6:8] == ref_bytes,
        'id_fragment_matches': block_id[8:16] == ref_hash,
        'extracted_number_fragment': number_bytes[6:8].hex(),
        'extracted_id_fragment': block_id[8:16].hex(),
        'scope': 'Fragment consistency only; no signature, block-content or node-admission validation'
    }


if __name__ == '__main__':
    if len(sys.argv) != 4:
        raise SystemExit('Usage: check_reference.py body.json reference-block.json context-height')
    with open(sys.argv[1], encoding='utf-8') as source:
        body = json.load(source)
    with open(sys.argv[2], encoding='utf-8') as source:
        block = json.load(source)
    print(json.dumps(check_reference(body, block, int(sys.argv[3])), indent=2))

The program validates exact fragment lengths, hexadecimal shape and a nonnegative signed-int64 height. It rejects Boolean values as heights even though Python can otherwise treat them like integers. It also rejects a header whose number disagrees with the composite ID’s number prefix.

The output intentionally reports two separate Boolean comparisons. Inspect both. A matching number fragment with a different ID fragment does not pass the same check as two matches. The printed candidate is also separate from the supplied block number, so a reader can see when the file being checked is not the latest congruent candidate for the chosen context.

No network request occurs inside this script. It cannot establish whether a provider is currently synchronized or whether an old reference is still available to a validating node. A program that prints two matching fragments has performed the stated local comparison, not a simulated transaction submission.

5. Reproduce the saved Mainnet result

Our retained body belongs to transaction 530fe4aa80f9427cb25a469abc5ebb08230db6dff8adcb97ce0ec895d3ad4a8e, collected earlier on October 29 at 01:11:35 UTC. We fetched the proposed reference header at 02:18:30 UTC. Keeping both timestamps makes clear that the header lookup was a later read, not a simultaneous capture of a node’s admission state.

The returned block ID was 00000000053776e274e28fe22589696c8d912059a8f221d37e4c0516adc5f61d. Its height prefix represented 87520994. The extracted number fragment was 76e2 and the extracted ID fragment was 74e28fe22589696c. Both matched the transaction body’s supplied reference fields.

Observed item Result Scope
Known containing block 87520996 Context from the earlier receipt
Candidate and fetched header number 87520994 Selected by the documented arithmetic, then queried
Number fragment 76e2 matched Two-byte consistency
ID fragment 74e28fe22589696c matched Eight-byte consistency
Height distance in this observation 2 blocks Not a universal reference distance
Paid action or broadcast None Read-only source retrieval and local code

The two-block distance is specific to this retained example. It is not a rule that every reference equals the containing block minus two. The header and body files are retained in our editorial working record; a local source archive is not a hosted download offered to readers.

You can reproduce the number slice without using a blockchain application. The eight-byte representation of 87520994 is 00000000053776e2. Split it into pairs: 00 00 00 00 05 37 76 e2. The final two byte pairs are 76 e2. Joining those pairs produces the body’s four-character value 76e2.

For the block ID, the first sixteen hexadecimal characters are that same eight-byte number prefix. The next sixteen characters are 74e28fe22589696c, which represent the eight bytes selected by [8:16]. The remaining characters belong to the rest of the composite ID and are not included in the transaction’s short reference fragment.

Manual view of the example Hexadecimal text Meaning
Number prefix, bytes 0 through 7 00000000053776e2 Complete eight-byte encoded height
Number fragment, bytes 6 and 7 76e2 Two low bytes used in the reference
ID fragment, bytes 8 through 15 74e28fe22589696c Eight bytes compared with ref_block_hash
Remaining ID bytes Retain in the full source value Not covered by the short-fragment comparison

A useful self-check is to count characters before converting to bytes. Four hex characters should decode to two bytes, sixteen to eight bytes, and sixty-four to thirty-two bytes. If your adapted tool reports different lengths, inspect its input conversion before interpreting any match. Do not append zeros or remove a prefix in an undocumented preprocessing step to make the displayed values line up.

The printed object is also designed to prevent an ambiguous success label. Read number_fragment_matches and id_fragment_matches separately. Both must be true for the narrow two-fragment consistency statement used here. The script prints JSON but does not return an exit code that summarizes the two Booleans; a process ending normally is not itself proof of a match. An automated consumer must inspect the named fields and handle validation errors explicitly.

For a support note, report the actual outcome as one of three categories: malformed input rejected, valid-shaped input with a fragment mismatch, or two matching fragments. Attach the complete public TxID and proposed block ID, the source network, collection times and the chosen context. A phrase such as “TAPOS failed” leaves too many possibilities unresolved. This classification shows whether the immediate problem is an unusable export, disagreement between supplied records or a question beyond this local comparison.

6. Exercise the ambiguity and failure paths

We tested the real pair and altered local copies. Changing the eight-byte reference fragment while retaining the real header produces an ID-fragment mismatch. Changing the low-number fragment produces a number-fragment mismatch. These fixtures were not valid new transactions and were never broadcast.

Controlled case Expected outcome
Real body and candidate header Both fragments match
Uppercase hexadecimal representation Same decoded-byte result
Changed reference ID fragment ID fragment reports false
Changed number fragment Number fragment reports false
Header number disagrees with ID prefix Reject input
Missing, prefixed, odd or non-hex fragment Reject input
Negative or Boolean context height Reject input
Context increased by 65536 Candidate increases by 65536, showing repeat ambiguity

For the wraparound fixture, we changed only the context supplied to the arithmetic. We did not retrieve or assert the contents of the higher candidate block. The exercise demonstrates why a short fragment is insufficient; it does not create evidence of another matching real reference block.

For a protocol-level conclusion, also consider the trustworthiness and chain view of the source. A supplier can fabricate mutually consistent fields. This utility checks selected relationships among supplied values and explicitly leaves signature validation, full block-content hashing and consensus outside its scope.

TAPOS test matrix separating fragment mismatches, invalid input and repeating low-number fragments
Original test matrix. Synthetic changes exercise the program; they do not describe new on-chain records.

7. Diagnose a reference error without editing signed data

If a fragment differs, first check network, complete values, byte positions and the candidate context. Preserve the original exports. A mismatch may arise from the wrong header or a copying problem; this comparison alone does not identify a malicious source or prove a chain fork.

If both fragments match but an application reports an admission error, this utility has reached its boundary. The node’s relevant chain state, reference availability and other transaction checks need separate evidence. Record the exact error response and time. A later successful header lookup does not prove that the same node had the relevant reference when it handled an earlier request.

Do not change reference fields in a signed body and assume its authorization remains intact. Raw payload fields participate in the transaction’s signing digest. The offline TxID recomputation guide explains the byte-to-identifier comparison; it is also not a signing or repair service.

Keep reference freshness and expiration separate in the investigation. The transaction expiration guide compares deadline fields and time context. A fragment match does not establish that the deadline has not passed, and a future deadline does not prove that the reference is acceptable.

Also compare supplied_block_number with latest_congruent_candidate in the output. The program displays both instead of silently changing your file selection. If they differ, investigate why the supplied header and chosen context do not identify the same candidate. The number-fragment Boolean can still be true for heights separated by 65536; the additional height comparison makes that distinction visible.

For example, the synthetic context-wrap test continues to check the same real saved header while proposing a higher candidate from the altered context. The fragment comparisons remain properties of that supplied header. The candidate field changes because the arithmetic was given a different upper context. That is not contradictory output: the fields answer different questions. Do not collapse them into a single “valid transaction” badge. Keep the context-selection reasoning with the output so another reviewer can understand which candidate you intended to fetch.

8. Preserve an evidence note another reader can repeat

Keep the transaction body, full proposed block ID, header number, network, source endpoint, collection timestamps, chosen context and printed comparison together. A screenshot of shortened fragments can help explain the screen, but complete machine-readable values are necessary to reproduce the slices.

Separate the observed statement from the conclusion you have not tested. Our observed statement is that two supplied reference fragments matched the corresponding slices in the fetched candidate header. We did not independently validate the block’s producing signature, recompute its content-derived suffix, inspect a recent-block store or submit the historical transaction.

If an input is unavailable because a provider limits requests or cannot return historical data, record that limitation. Do not substitute a current header and report a failure against the old transaction. A new source or a later retrieval should have its own provenance note so readers can see which view produced the result.

Reference-check evidence boundary distinguishing local fragment matches from node admission and finality
Original scope worksheet. Fragment consistency is one check within a larger transaction investigation.

Frequently asked questions

Is ref_block_hash the complete block ID?

No. In this workflow it is an eight-byte fragment extracted from specified block-ID byte positions. Preserve the full candidate ID separately and do not search with a shortened fragment as if it uniquely named a block.

Can ref_block_bytes identify a unique block height?

No. Two bytes repeat every 65536 values. A dated context selects a candidate for investigation; the header comparison adds evidence without turning the short number fragment into a unique identifier.

Does a fragment match prove the transaction is still valid?

No. The script does not check current node admission, reference availability, expiration, signatures or consensus. A historical comparison is not a promise of successful broadcast today.

Should the reference block equal the containing block?

Do not assume that. They have different roles. Our dated example referenced height 87520994 while its receipt identified containing block 87520996; that distance is an observation, not a universal formula.

Does the procedure require wallet access?

No. It reads public response files and performs local byte comparisons. It does not request private keys, wallet connections or signatures, and it cannot modify an on-chain transaction.

Checked October 29, 2026 by the Tronscan News editorial team. AI assisted drafting; local checks and synthetic failures were executed using retained public source files. Independent publication, not official TRONSCAN support. Report a correction through this page’s comments with the affected step and public source details; exclude account credentials and signing secrets.

Rate this post

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *