Skip to content
Piece Verification
step 1/5

Reading — step 1 of 5

Read

~3 min readPeer Wire Protocol

Piece Verification

A BitTorrent download runs on a simple trust model: trust nothing a peer sends; trust only the metainfo. The pieces field gives you one 20-byte SHA-1 per piece, fixed when the torrent was created. Every piece you assemble gets hashed and compared before a single byte counts as downloaded:

python

Without this check, one misbehaving peer poisons your download — and you find out when the finished ISO fails its checksum, hours later, with no idea which of 40 peers to blame.

Blocks arrive; pieces get verified

You request pieces in 16 KiB blocks, and blocks arrive out of order, from different peers, sometimes twice (endgame duplicates overlap). So the unit of bookkeeping is byte coverage, not "how many blocks came in":

  • Keep a buffer per in-flight piece; write each block at its offset.
  • Track which byte ranges are covered. Only when every byte of the piece is covered may you hash — SHA-1 offers no per-block verification; you either have the whole piece or you know nothing yet. (Fixing that requires per-block Merkle hashes, which is exactly what BitTorrent v2 added.)
  • Counting blocks breaks on duplicates: receiving block 0 twice is not a complete two-block piece.

The last piece is shorter

piece length divides the total only by luck. The piece count is ceil(total / piece_length), and the last piece holds the remainder:

python

Demand piece_length bytes of coverage on the final piece and it sits at "incomplete" forever — the single most common bug in this exercise.

Check completeness BEFORE hashing

An incomplete buffer still hashes — to the wrong value, because the unfilled bytes are zero. Hash first and you report "corrupt" for a piece that is merely "not done yet". The two verdicts demand opposite reactions: incomplete → keep waiting for blocks; mismatch → discard the whole piece and re-request every block, preferably from different peers (real clients remember who contributed to failed pieces and ban repeat offenders).

On success: write the piece at offset piece_length * index in the concatenated file space (for multi-file torrents, map that offset onto the files list), set your bitfield bit, and broadcast have <index> to every connected peer. As for choosing piece length in the first place: it is picked at creation time so the piece count stays in the low thousands — that keeps pieces (20 bytes per piece) and thus the .torrent file small. 256 KiB to 4 MiB is typical today.

Your exercise

Implement INIT / BLOCK / VERIFY / BITFIELD. Mistakes the grader catches:

  1. Fixed-size last piece. Test 3 is INIT 16 40 ... — three pieces of 16, 16, and 8 bytes. If piece 2 waits for 16 bytes of coverage, you print INCOMPLETE where the grader expects OK.
  2. Echo discipline. INIT and every BLOCK print OK too. The first test expects seven OK lines and then e0; drop one echo and every later line misaligns — the grader diffs your full stdout.
  3. BITFIELD is packed hex, not a bit string. Three pieces, all verified → bits 111, padded MSB-first to 11100000 → print e0. Printing 111 (or uppercase E0) fails, and an all-unverified 3-piece torrent must print 00.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…