Reading — step 1 of 5
Read
The .torrent Metainfo File
A .torrent file is one bencoded dictionary, start to finish. Open one in a hex editor and you will see d8:announce... — the same four types you just built a codec for.
Top-level keys:
{
'announce': 'http://tracker.example.com:6969/announce',
'announce-list': [['http://t1/announce'], ['http://t2/announce']], # optional, BEP 12
'creation date': 1700000000, # optional
'created by': 'qBittorrent v4.5', # optional
'comment': 'Optional description', # optional
'info': { ... }
}
Everything except info is advisory: where to find a tracker, who made the file, a human-readable note. The info dict is the identity of the torrent.
Single-file torrent:
{
'name': 'debian.iso',
'length': 734003200, # total bytes
'piece length': 262144, # bytes per piece (a power of two)
'pieces': <20-byte SHA-1 per piece, concatenated>
}
Multi-file torrent:
{
'name': 'My Album', # root directory name
'piece length': 262144,
'pieces': <same as above>,
'files': [
{'length': 4500000, 'path': ['track01.flac']},
{'length': 100, 'path': ['art', 'cover.jpg']}, # nested: art/cover.jpg
]
}
Multi-file mode is signaled by files replacing length. There is no per-file pieces: the files are conceptually concatenated into one byte stream and pieces are cut across file boundaries.
pieces: the ground truth
pieces is a single binary string of exactly 20 * N bytes — the SHA-1 digest of piece 0, then piece 1, and so on. Its length tells you the piece count. This field is why bencoded strings had to be binary-safe: raw digests contain every byte value, including e, :, and NUL.
The infohash
The infohash is the SHA-1 of the bencoded info value — those exact bytes, not of the whole .torrent file. That choice is deliberate: two .torrent files with different trackers or comments but the same info dict describe the same content, hash to the same infohash, and join the same swarm. From here on, every layer of the protocol — tracker announce, peer handshake, DHT lookup — identifies the torrent only by these 20 bytes.
The re-encoding trap
The infohash is defined over the bytes as they appear in the file. Real clients therefore record the start and end offsets of the info value while decoding, and hash that original byte slice. Decoding to objects and re-encoding with your own bencoder gives the same bytes only if your encoder is perfectly canonical — one unsorted key, one integer formatted differently, and you have computed the hash of a torrent that does not exist. A wrong infohash means the tracker has never heard of your swarm and every peer drops your handshake: the failure mode is total silence, which makes this the most frustrating bug to diagnose in a whole client.
Your exercise
Read a bencoded info dict from each input line and print its SHA-1 as 40 lowercase hex characters. Mistakes the grader catches:
- Hashing the newline. Strip the trailing
\nbefore hashing: ford6:lengthi100e4:name3:abcethe grader expects0fc554e5c155c0287a342f2aafd857f18d48101d— one extra byte produces a completely different digest. - Wrong byte decoding. Encode the line with
latin-1, which maps code points 0–255 back to single bytes one-to-one. UTF-8 would expand any byte above 0x7F into two bytes and corrupt the hash. (The tests are ASCII, where the two agree — the habit matters for real torrents.) - Missing the degenerate case. An empty dict is still valid input:
demust print600ccd1b71569232d01d110bc63e906beab04d8c. If your loop rejects "too short" lines, the hidden test fails.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…