Check out Part 1 if you haven’t.
Compression tricks
Basic compression
Although this is not necessarily related to sharding, it's commonly used in Ethereum rollups to gain more capacity because DA sharding is not yet implemented in/before the time of writing, hence the name "rollups." If transactions are smaller, rollups can fit in more transactions into an L1 block.
To understand how this works, we must have a basic idea of a simple transaction; then, we will look at how each property can be compressed.
Nonce (~3 bytes): Entropy so that transactions have different signatures. This can be omitted entirely because we can get the current nonce directly from the state, which reduces 3 bytes.
Gas price (~8 bytes): How much a person would pay for 1 gas. We can make the user pay within a fixed range of gas prices, e.g., a choice of 16 consecutive powers of two, or it can be omitted entirely, and gas will be paid to block proposers using other sources like a state channel, which would get to 0-0.5 bytes.
Gas (3 bytes): Max amount of gas to use. We can either use the same trick above or remove it entirely using a fixed-size gas, which would get to 0-0.5 bytes also.
To (21 bytes): Receiver's address. We can make an account manager to reduce the receiver's address. An address will be registered with an index, and a reasonable index size would be somewhere 4 bytes which we can ensure that we would not be able to max out for several lifetimes.
Value (~9 bytes): Amount to transact. We can use scientific notations for this, resulting in approximately 3 bytes.
Signature (~68 bytes): Signature of the transaction. We can use BLS signature aggregation for this. The basic idea is that you can aggregate multiple signatures into only one signature. The cost is fixed to only one signature, which takes approximately 0.5 bytes per transaction.
From (0 bytes): Sender's address. Initially, we can omit the sender's address because it can be recovered from the signature. Still, we need it to verify the aggregated signature in this case. So that's 4 bytes added.
(Taken from Vitalik's blog on rollups).
Overall, we have reduced a transaction with ~112 bytes to around ~12 bytes - almost a ten-time improvement in transaction capacity!
In many cases, with ZK rollups, some transaction fields can be removed entirely because they have already been proven through the ZK proof, e.g. signatures.
Digging deeper
However, these compression techniques are rather basic. What happens if a rollup supports smart contracts? The size of a transaction may not come from the properties we have mentioned, but instead from the calldata - the data passed into the functions of smart contracts.
There isn't a one-fits-all approach, but there are some ways we could tackle this. Many transactions may contain data that is similar to others, so it's possible to store just one instance of the data and refer back to it later using only a few bytes. For example, there might be a popular NFT contract that a lot of people are calling, and the transactions all share the same contract address and calldata that has similar properties. In this case, one could store a single transaction body and then use a few bytes as a reference for subsequent transactions instead of storing the entire data repeatedly.
Additionally, traditional compression algorithms could be used on batches, considering how many duplicated bytes calldata might have. Effectively, they can also do the same thing that we have mentioned above.
Going layer 3?
A wild thought would be to stack rollups on top of each other. While this may sound like an excellent idea, it just doesn't work because, in the end, data availability is the same, and no improvement in capacity is being added. However, we can build state channels and plasma chains on top of rollups.
Cryptographic tricks
Cryptographic tricks refer to all sorts of cryptography usage in optimizing the blockchain. Here are some of the most popular use cases.
ZK proof
There are three essential aspects in a blockchain: verification, execution, and data storage; vaguely, succinct ZK proof schemes like SNARKs or STARKs can improve efficiency in verification and execution, which results in more capacity gained.
Data storage commitment
How would we deal with data storage, then? First, we will split it into two types of data storage, chain-related storage and application storage. Chain-related storage can only be optimized through the sharding tricks mentioned above, state data sharding through rollups, and then do data availability sharding. But in the case of application storage, we have a slightly different approach.
The idea is similar to what I have mentioned about DA sharding; you keep some cryptographic commitment on-chain, store data off-chain, and can then request the data from a p2p network like IPFS or a similar DHT protocol and verify it with the commitment stored. The only problem with this is that data is voluntarily stored. If your app has a large userbase or a model that makes people host data behind the scenes, it will work, but otherwise, it wouldn't. A further approach would be to have a protocol similar to Sia, which pays hosts to store data, uses the same data sampling trick for proof of storage, punishes hosts if they don't store data, and incentivizes at download time in an *optimistic* way - paying accordingly to the data received so that they would provide data at any time.
Optimizations
All of the things I have mentioned earlier are pretty abstract and general, in practice, protocol designs play a huge role in scalability. How you deal with the runtime environment, data serialization, message gossiping, trie construction, stuff like segwit, parallel utxo transactions, etc can vastly reduce cost and improve overall transaction throughput. Optimization tricks to reduce data cost, disk io cost, pruning, etc from blockchain clients are also just as essential.
Evade blockchain usage
Try to avoid blockchain usage as much as you can if you don't need to use a blockchain. Tasks like messaging or large data transfers should never be done on-chain; you should use a simple p2p network which is even more decentralized and infinitely faster.
Better smart contract languages/compilers
Bad smart contract languages/compilers indirectly affect several blockchain networks' proper performance.
First, let's talk about contract execution. A lousy contract language design/compiler would produce unnecessary opcodes, meaning more execution is needed. For example, a contract written in Huff or Vyper (with their current official compilers) might be twice or three times more gas efficient than one written in Solidity (using the solc compiler). We don't even need to shard another chain or use another rollup in the first place for more efficiency if developers use those languages rather than Solidity.
Second, let's talk about contract code storage. Again, a bad contract language design/compiler would produce unnecessary opcodes, and that not only contributes to worse execution efficiency but also data storage cost for those contracts. In the long run, these code will be immutable bloat for the entire network. Imagine having 10% or 20% of the chain be useless code, forever.
People may not realize the damages a foul smart contract language may bring. Sure, it hurts apps' performance individually, but the problem is more complicated when a language is mass-adopted. A mass-adopted smart contract language with 3x more opcodes and 3x lower gas efficiency directly contributes to the network being three times less scalable than it could have been. We don't need to make three sharded chains; we need better smart contract language designs and compilers!
This solution does not help with scaling blockchains directly, as it does not add in any extra execution or data storage capacity, but rather helps recover the performance that they have lost due to unoptimized use of smart contracts and helps reduce chain bloat.
Misconceptions
Here is a quick recap of the misconceptions we have covered:
We can not just scale a blockchain by changing block size or block time.
We can not do sharding by naively spawning new, unconnected chains/sidechains.
Proof-of-stake improves scalability
A common misconception that most modern blockchain networks lie to users and investors about is that Proof-of-stake-based consensus is more scalable than Proof-of-work-based consensus or other consensus mechanisms. This is false since consensus protocols don't bring any extra transaction execution or data storage capabilities to the network; pos-based consensus protocols exist only as an energy-efficient way to achieve consensus compared to PoW mining. Most centralized blockchain networks with low block time and high block size will use PoS as an excuse for their performant but centralized network.
Compression tricks can be used on the L1 without rollups
A common misconception is that you can use the compression tricks to fit in more transactions in the L1 (layer one) block without using rollups/sharded chains at all, however, this is false.
If your computer can execute 100 transactions per block, it doesn’t mean your computer can execute 1000 transactions just because they are 10 times smaller. Transaction execution does not only mean storing the transactions; it also includes… running the transactions themselves. The size is the same, but you need 10 times the computational power to run 10 times more transactions, and you would also need more power to decompress the transactions. Therefore, compression on the L1 is simply not enough even though it would make the L1 blocks lighter.
Rollups are different because each in 10 rollups can execute 100 transactions independently. In the end, a rollup is just as decentralized as a normal L1, but you have 10 times more transaction throughput with all of these rollups combined.
Conclusion
I believe understanding blockchain fundamentals and possible blockchain scaling solutions is crucial for participants in this industry because not only can we have a better view of what the future of blockchain technology might look like, but we can also understand what's right and wrong, what's possible and what's limited so that people would not fall for projects that might exploit users' misconceptions for their goods, so there you go, thanks for reading!