Python 3 and a terminal — nothing installed, nothing connected.
macOS and Linux have Python; on Windows install it from python.org with
“Add python.exe to PATH” ticked, and check with
python3 --version.
Sharding is usually explained with diagrams, which is why it rarely sticks. Here you will run it: assign accounts to shards by the rule TON actually uses, measure how evenly the load lands, count how much traffic has to cross a boundary, and see why a masterchain is needed to tie the pieces together. The models are small, and every number is one you produced.
The Multi-Blockchain Design
Most blockchains are a single chain of blocks. Ethereum is one chain. Bitcoin is one chain. TON is fundamentally different — it is a blockchain of blockchains. The network consists of multiple interacting chains organized in a hierarchy, each serving a specific purpose.
This architecture is what enables TON to scale beyond what single-chain designs can achieve. Understanding it is essential to understanding TON's security model.
The Masterchain
The masterchain is TON's backbone — a single, authoritative chain that stores the network's global state:
- Validator set: The current list of validators and their stakes
- Configuration parameters: Network-wide settings (gas prices, staking rules, election parameters)
- Shard state hashes: Cryptographic commitments to the state of every shardchain
- Governance decisions: Approved proposals and parameter changes
The masterchain does not process user transactions directly. Think of it as the "constitution" of the network — it defines the rules, and all other chains follow them.
Workchains
Workchains are independent blockchains that actually process transactions and execute smart contracts. TON's design supports up to 232 workchains (over 4 billion), though currently only two exist:
Each workchain can have its own rules: different virtual machines, different address formats, different transaction formats. This makes TON extensible — a future workchain could support EVM compatibility, privacy features, or entirely new execution models.
Shardchains and Infinite Sharding
This is TON's most innovative feature. Each workchain can split into up to 260 shardchains. Each shardchain is responsible for a subset of accounts, determined by the account address prefix.
How it works:
Under normal conditions, a single shard handles all transactions for the workchain.
When a shard becomes overloaded, it automatically splits into two shards. Accounts starting with "0" go to one shard, accounts starting with "1" go to the other.
Each new shard can split again if needed. The process is recursive — the network can keep splitting until every account has its own shard if necessary.
When shards are underutilized, they merge back together. The network dynamically adjusts to actual demand.
Because the theoretical limit is 260 shards (over 1 quintillion), the network can always split further to meet demand. In practice, this means TON will never run out of throughput capacity.
Cross-Shard Communication
When a smart contract on shard A needs to interact with a contract on shard B, TON uses Instant Hypercube Routing. Messages are routed through intermediate shards using a hypercube topology, ensuring delivery in O(log N) hops where N is the number of shards.
This is fundamentally different from Ethereum, where all contracts share one global state. In TON, contracts communicate asynchronously via messages — similar to how microservices communicate in modern software architecture.
TON Virtual Machine (TVM)
TVM is the execution engine for TON smart contracts. Key characteristics:
- Stack-based: Like the JVM, TVM operates on a stack rather than registers
- Bag of Cells (BoC): All data in TON — transactions, blocks, contract state — is stored as trees of cells. Each cell holds up to 1023 bits and 4 references to other cells
- Continuation-based: TVM supports continuations, enabling complex control flow and gas management
- Deterministic: Given the same input, TVM always produces the same output across all validators
Smart contracts on TON are written in FunC (a C-like language) or Tact (a higher-level, TypeScript-like language). Both compile to TVM bytecode called Fift.
Consensus: BFT Proof-of-Stake
TON uses a Byzantine Fault Tolerant (BFT) Proof-of-Stake consensus mechanism called the Catchain protocol:
- Validator elections: Every ~18 hours, a new validator set is elected based on stake
- Minimum stake: Validators must stake a significant amount of Toncoin (currently ~300,000 TON)
- Slashing: Validators that act maliciously or go offline lose a portion of their stake
- Fault tolerance: The network remains secure as long as fewer than 1/3 of validators are Byzantine (malicious)
- Finality: Once a block is confirmed by 2/3+ of validators, it is final and cannot be reversed
Security Implications of the Architecture
Because TON contracts communicate via messages (not shared state), race conditions, message ordering attacks, and bounce handling bugs are unique vulnerability classes that don't exist on Ethereum.
- Cross-shard latency: Messages between shards take multiple blocks to deliver, creating timing windows
- Bounce handling: If a message to a contract fails, TVM sends a "bounce" message back. Contracts that don't handle bounces correctly can lose funds
- State rent: Unlike Ethereum, TON contracts must pay for storage. A contract that runs out of funds for storage is frozen and can lose state
Now Run the Sharding Rules Yourself, in Five Steps
TON’s answer to congestion is to split a chain in half whenever it gets busy, and to keep splitting. That raises three questions a diagram cannot answer: which shard is my account in, does splitting actually spread the work evenly, and what does it cost. In the next twenty-five minutes you will answer all three with numbers you generate. Every line of output below came from running these files.
Go: open a terminal in a folder you can write to, e.g.
cd ~/Desktop (Windows: cd %USERPROFILE%\Desktop).
Do: save this as shard.py and run
python3 shard.py. The rule is the whole design in one line: an account’s
shard is decided by the leading bits of its address.
import hashlib
def shard_of(account_hash: bytes, depth: int) -> str:
"""TON assigns an account to a shard by the FIRST bits of its address."""
bits = "".join(f"{b:08b}" for b in account_hash[:2])
return bits[:depth] if depth else "(one shard)"
account = hashlib.sha256(b"finkatana practice account").digest()
print("account starts:", account.hex()[:8], "=",
"".join(f"{b:08b}" for b in account[:2]))
for depth in (0, 1, 2, 3, 4):
print(f" split into {2**depth:>2} shard(s): this account lives in shard {shard_of(account, depth)}")
You should see: one account’s home becoming more specific as the chain splits:
account starts: 39f25911 = 0011100111110010
split into 1 shard(s): this account lives in shard (one shard)
split into 2 shard(s): this account lives in shard 0
split into 4 shard(s): this account lives in shard 00
split into 8 shard(s): this account lives in shard 001
split into 16 shard(s): this account lives in shard 0011
Notice what this buys: when a shard splits, nothing moves. Each account’s new home is just one bit longer than its old one, so a split is a pure bookkeeping change and anybody can work out where an account lives from its address alone, with no lookup and no directory.
If not: if every line shows the same shard, the slice
bits[:depth] is being ignored — check that depth is the
loop variable and not a fixed number.
Go: same folder. A sharding scheme that piles everyone into one shard has achieved nothing.
Do: save this as spread.py and run it. It places a hundred
thousand accounts and measures the gap between the busiest and quietest shard.
import hashlib
from collections import Counter
def shard_of(account_hash, depth):
return "".join(f"{b:08b}" for b in account_hash[:2])[:depth]
for depth in (2, 4):
counts = Counter(shard_of(hashlib.sha256(f"user-{i}".encode()).digest(), depth)
for i in range(100_000))
smallest, largest = min(counts.values()), max(counts.values())
print(f"{2**depth:>2} shards: {len(counts)} in use, "
f"smallest {smallest:,}, largest {largest:,}, "
f"imbalance {largest / smallest - 1:.1%}")
You should see: an almost perfectly even split:
4 shards: 4 in use, smallest 24,758, largest 25,350, imbalance 2.4%
16 shards: 16 in use, smallest 6,143, largest 6,371, imbalance 3.7%
The evenness is not luck — it is what a cryptographic hash is for. Because addresses are hashes, their leading bits are effectively random, so accounts fall into shards uniformly without anybody organising it. This is the property that makes “split when busy” a workable rule.
If not: if the imbalance is very large, the accounts are not being hashed
— feeding sequential numbers straight in, without sha256, produces exactly
the clustering this design avoids. That is worth doing once, to see it.
Go: same folder. Everything has a price, and here it is.
Do: save this as crossing.py and run it. It picks twenty
thousand random sender-receiver pairs and asks how often the two are in different shards.
import hashlib, random
def shard_of(account_hash, depth):
return "".join(f"{b:08b}" for b in account_hash[:2])[:depth]
random.seed(11)
users = [hashlib.sha256(f"user-{i}".encode()).digest() for i in range(1000)]
for depth in (1, 2, 4, 8):
cross = sum(shard_of(random.choice(users), depth) != shard_of(random.choice(users), depth)
for _ in range(20_000))
print(f"{2**depth:>3} shards: {cross / 20_000:.1%} of transfers cross a shard boundary "
f"(theory {1 - 1 / 2**depth:.1%})")
You should see: the measurement landing on the theory:
2 shards: 50.3% of transfers cross a shard boundary (theory 50.0%)
4 shards: 75.1% of transfers cross a shard boundary (theory 75.0%)
16 shards: 93.6% of transfers cross a shard boundary (theory 93.8%)
256 shards: 99.5% of transfers cross a shard boundary (theory 99.6%)
Past a handful of shards, essentially every transfer is cross-shard. That is why TON is built around asynchronous messages rather than the single instant transaction people expect: your transfer leaves one shard as a message and is delivered into another. It is a deliberate trade — unlimited capacity in exchange for transfers that complete in steps rather than at once, which is also why a TON transfer can be accepted on one side before it has landed on the other.
If not: if the measured figures sit far from the theory, the two
random.choice calls are being replaced by one value — sender and receiver
must be drawn separately.
Go: same folder. Sixteen chains running independently are sixteen opinions. Something has to make them one history.
Do: save this as master.py and run it.
import hashlib
def block_hash(shard, height):
return hashlib.sha256(f"{shard}:{height}".encode()).hexdigest()
shards = [f"{i:04b}" for i in range(16)]
tips = {s: block_hash(s, 900_000) for s in shards}
masterchain_block = hashlib.sha256("".join(tips[s] for s in shards).encode()).hexdigest()
print(f"shards being tracked : {len(shards)}")
print(f"masterchain block : {masterchain_block[:32]}...")
tips["0110"] = block_hash("0110", 900_001) # one shard produces a new block
rebuilt = hashlib.sha256("".join(tips[s] for s in shards).encode()).hexdigest()
print(f"after ONE shard moves: {rebuilt[:32]}...")
print("the masterchain block changed:", masterchain_block != rebuilt)
You should see: a single number standing for the state of all sixteen chains:
shards being tracked : 16
masterchain block : bebd90e52bbadc0ef4be46fe5c85d3cb...
after ONE shard moves: 1246ba94ac8e69c5ccca1bab9faa1948...
the masterchain block changed: True
That is the masterchain’s job in one line of code: it records the latest block of every shard, so one hash pins the entire network’s state. It is also why finality on TON means “referenced by a masterchain block” rather than “my shard says so”, and why the masterchain deliberately stays small and expensive — every validator must follow it, whatever else they follow.
If not: if the last line prints False, the
tips dictionary was rebuilt from scratch after the update, so the change was
thrown away — only the one shard’s entry should be replaced.
Go: same folder, using what steps 2 to 4 produced.
Do: read the three results together and answer, for yourself, where an
attacker would aim. Then confirm your reasoning by re-running crossing.py with
depth values of 6 and 10 added to the list.
python3 crossing.py
You should see: the crossing rate climbing towards 100% and never coming back down. That is the finding: as TON scales, nearly all activity becomes cross-shard, so the security of the whole network rests on the message-passing machinery and on the masterchain that orders it — not on any single shard being honest.
Two practical consequences follow, and they are why this page exists. A validator set spread thin across many shards must be reshuffled unpredictably, or an attacker could aim at one small shard’s validators instead of the whole network. And as a user, “the transaction succeeded” on the sending side is not the same as “it arrived” — for anything that matters, confirm the destination account actually received it.
If not: if adding those depths makes no difference to the output, the
for depth in (...) tuple was edited in a copy of the file rather than the one
you are running — check with ls which file you saved.
Without scrolling up: a friend says TON is faster than a single-chain network because “transactions happen in parallel”. Using step 3, what is the part of that claim they have not accounted for, and what does it mean for someone accepting payment? Answer: they have not accounted for cross-shard traffic — past a few shards, almost every transfer involves two shards and so becomes an asynchronous message rather than one atomic action. Throughput really does scale, but individual transfers complete in stages. For someone accepting payment it means the sender’s wallet showing “sent” is not proof of receipt: check the receiving account’s balance, and for large amounts wait until the masterchain has referenced the block that delivered it.
Now do it without the page: modify spread.py to place
accounts using their sequential number instead of a hash, and compare the imbalance with what
you measured in step 2. You will have demonstrated, in one edit, why addresses on this
network are hashes and not counters — and why a scheme that lets users choose their own
shard would collapse under the first popular application.
Summary
- TON is a multi-blockchain system: masterchain, workchains, and shardchains
- Infinite Sharding allows the network to dynamically scale to any transaction volume
- Cross-shard communication uses Instant Hypercube Routing
- TVM executes smart contracts using the Bag of Cells data structure
- BFT PoS consensus provides fast finality with slashing for bad actors
- The asynchronous architecture creates unique security considerations
This knowledge is essential for understanding how TON wallets, staking, and DeFi work under the hood.