SECTION 1: LEARNING OBJECTIVES
By the end of this lesson, you will be able to:
-
Define decentralised storage and its role in blockchain ecosystems.
-
Explain content-addressed storage and its advantages over location-addressed storage.
-
Understand the architecture of IPFS and its core components.
-
Describe incentive layers (Filecoin, Arweave, Storj).
-
Differentiate between on-chain and off-chain data storage strategies.
-
Identify use cases for decentralised storage in digital finance.
-
Implement a basic content-addressed storage simulation in Python.
-
Develop a framework for selecting decentralised storage solutions.
SECTION 2: WHAT IS DECENTRALISED STORAGE?
2.1 Definition
Decentralised storage refers to a system where data is stored across a distributed network of nodes rather than in a centralised data centre. Unlike traditional cloud storage (AWS S3, Google Cloud), decentralised storage eliminates single points of failure, reduces censorship risk, and gives users control over their data.
2.2 Content-Addressed vs Location-Addressed Storage
The fundamental shift in decentralised storage is moving from location-addressed to content-addressed storage:
Location-Addressed Storage (Traditional):
-
Data is found by where it is stored (e.g.,
https://server.com/file.pdf) -
The server is a single point of failure
-
Links break if the server moves or shuts down
-
Example: HTTP, FTP
Content-Addressed Storage (Decentralised):
-
Data is found by what it is (its cryptographic hash)
-
The hash uniquely identifies the content
-
Any node can serve the content
-
Links are permanent and verifiable
-
Example: IPFS (
ipfs://Qm...), Arweave
┌─────────────────────────────────────────────────────────────────────────────┐ │ CONTENT ADDRESSING │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ Traditional HTTP: │ │ https://website.com/images/photo.jpg │ │ └─────────────┘ └─────────────┘ │ │ Location File name │ │ (Server address) (Name, not content) │ │ │ │ Decentralised Content-Addressing: │ │ ipfs://QmZ4tDu... / │ │ └──────────┘ │ │ Cryptographic Hash │ │ (Identifies content, not location) │ │ │ │ Advantages: │ │ • Immutable - content changes = different hash │ │ • Verifiable - users can verify integrity │ │ • Permanent - hash always points to same content │ │ • Decentralised - any node can serve the content │ │ │ └─────────────────────────────────────────────────────────────────────────────┘
SECTION 3: IPFS (INTERPLANETARY FILE SYSTEM)
3.1 Architecture
IPFS is a peer-to-peer protocol for storing and sharing content-addressed data. Its architecture consists of several key components:
1. Identity Layer:
Each node in the IPFS network has a unique peer identity (PeerID) derived from its public key. This enables secure communication and authentication between nodes.
2. Network Layer:
IPFS nodes communicate using libp2p, a modular networking stack that supports multiple transport protocols (TCP, WebSocket, QUIC). It handles peer discovery, connection management, and secure communication.
3. Routing Layer:
IPFS uses a Distributed Hash Table (DHT) to find which nodes are storing specific content. When a node requests a file, the DHT helps locate peers that have the content.
4. Exchange Layer:
The Bitswap protocol manages the exchange of data blocks between nodes. It uses a strategy to prioritise fetching the most valuable or requested blocks first.
5. Merkle DAG Layer:
IPFS structures data using a Merkle Directed Acyclic Graph (DAG). Each block is addressed by its hash, and blocks can link to other blocks, forming a directed graph. This enables:
-
Deduplication (same content stored once)
-
Versioning (different versions have different hashes)
-
Efficient retrieval (only fetch needed blocks)
6. Naming Layer (IPNS):
IPNS provides mutable names for content. While IPFS addresses are immutable (hash-based), IPNS allows users to publish a name that can point to different content over time, enabling content updates.
3.2 IPFS Components
| Component | Purpose | Description |
|---|---|---|
| CID (Content Identifier) | Content addressing | Hash-based identifier (e.g., Qm...) |
| Merkle DAG | Data structuring | Linked data blocks with hash verification |
| DHT | Discovery | Finds nodes storing content |
| Bitswap | Data exchange | Block trading between nodes |
| IPNS | Mutable naming | Human-readable, updatable names |
| Filecoin | Incentive layer | Economic incentives for storage |
3.3 IPFS Use Cases in Digital Finance
| Use Case | Description | Benefit |
|---|---|---|
| DeFi Data Storage | Store historical transaction data | Permanent, verifiable records |
| NFT Storage | Store NFT metadata and assets | Decentralised, permanent |
| Tokenised Assets | Store asset documentation | Verifiable provenance |
| KYC Documents | Store encrypted identity documents | User-controlled privacy |
| Smart Contract Code | Store off-chain code references | Verification of code |
| Research Data | Store financial models and analytics | Reproducibility |
SECTION 4: INCENTIVISED STORAGE LAYERS
4.1 Filecoin
Filecoin is a decentralised storage network that adds economic incentives on top of IPFS.
Key Concepts:
-
Storage Miners: Nodes that provide storage space and earn Filecoin (FIL) tokens.
-
Retrieval Miners: Nodes that provide fast retrieval of content.
-
Proof-of-Storage: Cryptographic proofs that miners are actually storing data.
-
Proof-of-Replication (PoRep): Proves data has been stored uniquely.
-
Proof-of-Spacetime (PoSt): Proves data is continuously stored over time.
-
How It Works:
-
Client wants to store data.
-
Client and storage miner agree on a deal (price, duration).
-
Data is stored, and the miner provides proofs.
-
Client pays Filecoin to the miner.
-
If data is lost, the miner is penalised.
Storage Process:
Client → Deal with Miner → Data Transfer → PoRep → PoSt (ongoing) → Payment
Current Metrics:
-
Network Storage Capacity: 20+ EiB (exabytes)
-
Active Miners: 3,000+
-
Deal Volume: Growing rapidly
4.2 Arweave
Arweave offers permanent, one-time payment storage.
Key Concepts:
-
Permaweb: A permanent, decentralised web built on Arweave.
-
Storage Endowment: Users pay once, and the endowment pays miners over time.
-
Proof of Access (PoA): Miners must prove they can access historical data.
Unique Features:
-
One-time payment for permanent storage
-
Designed for long-term data archival
-
Growing ecosystem of “permaweb” applications
4.3 Storj
Storj is a decentralised cloud storage platform with S3-compatible APIs.
Key Concepts:
-
Storage Nodes: Nodes providing storage space.
-
Satellite Nodes: Coordinate storage and retrieval.
-
Tardigrade: Enterprise-grade decentralised storage.
Features:
-
S3-compatible API (easy migration)
-
Encryption by default
-
Focus on performance and reliability
4.4 Comparison of Incentivised Storage
| Feature | Filecoin | Arweave | Storj |
|---|---|---|---|
| Payment Model | Ongoing (deals) | One-time (permanent) | Ongoing |
| Storage Model | Contract-based | Permanent | Contract-based |
| Blockchain | Native (Filecoin) | Native (Arweave) | Ethereum + own |
| Retrieval Speed | Moderate | Moderate | Fast |
| S3 Compatible | No | No | Yes |
| Best For | General storage, DeFi | Permanent archival | Enterprise migration |
SECTION 5: STORAGE STRATEGIES FOR BLOCKCHAIN APPLICATIONS
5.1 On-Chain vs Off-Chain Storage
┌─────────────────────────────────────────────────────────────────────────────┐ │ ON-CHAIN VS OFF-CHAIN STORAGE │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ ON-CHAIN STORAGE │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ • Data stored in blockchain state │ │ │ │ • Expensive (gas costs) │ │ │ │ • Limited capacity │ │ │ │ • Immutable, verifiable │ │ │ │ • Best for: Small data, critical state, consensus data │ │ │ │ • Examples: Account balances, smart contract code, governance data │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ OFF-CHAIN STORAGE │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ • Data stored outside blockchain │ │ │ │ • Inexpensive │ │ │ │ • Unlimited capacity │ │ │ │ • Verifiable via cryptographic hashes │ │ │ │ • Best for: Large files, metadata, historical data │ │ │ │ • Examples: NFT assets, KYC documents, app data │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ HYBRID APPROACH │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ • Store hash on-chain, data off-chain │ │ │ │ • Best of both worlds │ │ │ │ • Verification via hash │ │ │ │ • Example: ERC-721 NFT stores metadata URI on-chain │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘
5.2 Storage Architecture Patterns
| Pattern | Description | Use Case |
|---|---|---|
| Hash-on-Chain | Store CID on-chain, data off-chain | NFTs, document verification |
| Full On-Chain | All data stored on-chain | Simple DApps, governance |
| Off-Chain Reference | Data stored off-chain with on-chain pointer | Large applications |
| Distributed Storage | Data distributed across storage network | Decentralised apps |
| Hybrid | Critical data on-chain, rest off-chain | Most DeFi protocols |
SECTION 6: IMPLEMENTATION IN PYTHON
# =================================================================== # MODULE 4, LESSON 3: DECENTRALISED STORAGE # =================================================================== import hashlib import json import time import base64 from typing import Dict, List, Optional, Any import pandas as pd import matplotlib.pyplot as plt import numpy as np import warnings warnings.filterwarnings('ignore') print("="*70) print("DECENTRALISED STORAGE") print("="*70) # ---------------------------------------------------------------- # PART A: CONTENT-ADDRESSED STORAGE SIMULATION # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART A: Content-Addressed Storage Simulation") print("-"*60) class ContentAddressableStorage: """ Simulated content-addressed storage system. """ def __init__(self): self.storage: Dict[str, bytes] = {} self.pinned: set = set() self.metrics = { 'total_objects': 0, 'total_bytes': 0, 'pinned_objects': 0, 'retrieval_requests': 0 } def add_content(self, data: bytes) -> str: """ Store content and return its content address (CID). """ # Calculate content hash content_hash = hashlib.sha256(data).hexdigest() cid = f"Qm{content_hash[:44]}" # Simplified CID format # Store content self.storage[cid] = data self.metrics['total_objects'] += 1 self.metrics['total_bytes'] += len(data) print(f"Stored content with CID: {cid}") print(f" Size: {len(data)} bytes") return cid def get_content(self, cid: str) -> Optional[bytes]: """ Retrieve content by CID. """ self.metrics['retrieval_requests'] += 1 if cid in self.storage: print(f"Retrieved content: {cid}") return self.storage[cid] else: print(f"Content not found: {cid}") return None def pin_content(self, cid: str) -> bool: """ Pin content to keep it permanently. """ if cid in self.storage: self.pinned.add(cid) self.metrics['pinned_objects'] += 1 print(f"Pinned content: {cid}") return True return False def get_metrics(self) -> Dict: return { 'total_objects': self.metrics['total_objects'], 'total_bytes': self.metrics['total_bytes'], 'pinned_objects': self.metrics['pinned_objects'], 'retrieval_requests': self.metrics['retrieval_requests'] } # Create storage system storage = ContentAddressableStorage() print("Content-Addressable Storage Simulation:") # Store data documents = [ b"Hello, Blockchain! This is a sample document.", b"Smart contract code: function transfer(address to, uint amount)", b"NFT metadata: {'name': 'Digital Art', 'artist': 'Alice'}", b"Financial report: Q4 2024 earnings" ] print("\nStoring content...") cids = [] for doc in documents: cid = storage.add_content(doc) cids.append(cid) # Retrieve content print("\nRetrieving content...") for cid in cids[:2]: content = storage.get_content(cid) if content: print(f" Content preview: {content[:50]}...") # Pin content print("\nPinning content...") storage.pin_content(cids[0]) # Metrics metrics = storage.get_metrics() print(f"\nStorage Metrics:") print(f" Total Objects: {metrics['total_objects']}") print(f" Total Bytes: {metrics['total_bytes']}") print(f" Pinned Objects: {metrics['pinned_objects']}") print(f" Retrieval Requests: {metrics['retrieval_requests']}") # ---------------------------------------------------------------- # PART B: ON-CHAIN VS OFF-CHAIN STORAGE COMPARISON # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART B: On-Chain vs Off-Chain Storage Comparison") print("-"*60) comparison_data = { 'Feature': [ 'Cost per MB', 'Storage Limit', 'Data Availability', 'Verification', 'Immutability', 'Retrieval Speed', 'Privacy', 'Best For' ], 'On-Chain': [ 'Very High (~$10,000)', 'Very Low (~KB)', 'Always Available', 'Native', 'Permanent', 'Fast (if stored)', 'Public (by default)', 'Critical state' ], 'Off-Chain (IPFS)': [ 'Low (~$0.01)', 'Very High (PB+)', 'Pinning-dependent', 'Hash-based', 'Permanent (if pinned)', 'Moderate', 'Controlled (encryption)', 'Large files' ], 'Incentivised (Filecoin)': [ 'Medium (~$0.001-0.01)', 'Very High (EB)', 'Guaranteed (contract)', 'Proof-based', 'Permanent (contract)', 'Variable', 'Controlled', 'Enterprise storage' ] } comparison_df = pd.DataFrame(comparison_data) print(comparison_df.to_string(index=False)) # ---------------------------------------------------------------- # PART C: STORAGE METRICS VISUALISATION # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART C: Storage Metrics Visualisation") print("-"*60) # Simulate storage cost comparison platforms = ['IPFS (Pinning)', 'Filecoin', 'Arweave', 'Storj', 'AWS S3'] cost_per_gb = [0.05, 0.03, 0.10, 0.02, 0.25] storage_capacity = [50, 100, 30, 40, 80] # relative index retrieval_speed = [3, 2, 1, 4, 5] # relative index (higher = faster) decentralisation = [5, 5, 4, 3, 1] # relative index (higher = more decentralised) fig, axes = plt.subplots(1, 2, figsize=(14, 5)) ax1 = axes[0] x = np.arange(len(platforms)) width = 0.35 ax1.bar(x - width/2, cost_per_gb, width, label='Cost per GB ($)', color='orange', alpha=0.7) ax1.bar(x + width/2, [d/10 for d in decentralisation], width, label='Decentralisation (scaled)', color='blue', alpha=0.7) ax1.set_xticks(x) ax1.set_xticklabels(platforms, rotation=45, ha='right') ax1.set_title('Storage Solutions: Cost vs Decentralisation') ax1.legend() ax1.grid(True, alpha=0.3) ax2 = axes[1] ax2.scatter(retrieval_speed, cost_per_gb, s=200, c=decentralisation, cmap='viridis', alpha=0.8) for i, platform in enumerate(platforms): ax2.annotate(platform, (retrieval_speed[i], cost_per_gb[i]), xytext=(5, 5), textcoords='offset points', fontsize=8) ax2.set_xlabel('Retrieval Speed (relative)') ax2.set_ylabel('Cost per GB ($)') ax2.set_title('Storage Solutions: Speed vs Cost') ax2.grid(True, alpha=0.3) plt.tight_layout() plt.savefig('decentralised_storage_comparison.png', dpi=300, bbox_inches='tight') plt.show() print("Storage comparison chart saved as 'decentralised_storage_comparison.png'") # ---------------------------------------------------------------- # PART D: SUMMARY AND RECOMMENDATIONS # ---------------------------------------------------------------- print("\n" + "="*70) print("PART D: Summary and Recommendations") print("="*70) print(""" Decentralised Storage – Key Takeaways: 1. Content-addressed storage uses cryptographic hashes instead of locations. 2. IPFS provides a decentralised P2P storage network with content addressing. 3. Key IPFS components: CID, Merkle DAG, DHT, Bitswap, IPNS. 4. Filecoin adds economic incentives with proof-of-storage mechanisms. 5. Arweave offers permanent storage with one-time payment. 6. Storj provides S3-compatible decentralised storage. 7. Storage strategies: on-chain (critical), off-chain (large data), hybrid (hash + data). Storage Selection Framework: - For permanent data: Arweave (one-time payment). - For general storage: Filecoin (cost-effective, provable). - For enterprise migration: Storj (S3 compatible). - For development: IPFS pinning services (Infura, Pinata). - For critical state: On-chain storage. - For NFT assets: IPFS + Filecoin (provenance + persistence). """) print("="*70) print("END OF LESSON 3 – MODULE 4") print("="*70)