Building a Decentralized File Sharing System Using Python and Solidity

Building a Decentralized File Sharing System Using Python and Solidity https://celo.academy/uploads/default/optimized/2X/0/0e0e224e7a08d0b7aa150975747cb3be7b894002_2_1024x576.jpeg
none 0.0 0

In this tutorial, we’ll demonstrate how to use Python and Solidity to create a decentralized file-sharing system. We will talk about the
drawbacks of conventional file-sharing platforms and how blockchain technology can offer a safer and more effective alternative.

You will learn how to set up a development environment, use Solidity to create the smart contract and use Python to communicate with it, and upload/download files with the help of a step-by-step manual. You will have a firm grasp of how to create a decentralized file sharing system that makes use of blockchain technology by the end of this course.

Building a Decentralized File Sharing System on Celo Using Python and Solidity

Introduction​

In this Tutorial we will demonstrate how to use python and solidity to create decentralized file-sharing system on the Celo Blockchain.

we are going to cover all the steps from Designing the System Architecture to Setting Up the Development Environment, Creating Python scripts and modules to handle user interactions, authentication, and communication with the smart contracts.

Prerequisites​

To execute the task of building a decentralized file sharing system on Celo using Python and Solidity, you would need the following prior knowledge:

  • Solidity: Familiarity with the Solidity programming language is essential as you will be writing smart contracts in Solidity. Understanding Solidity syntax, data types, control structures, and contract development best practices is crucial.

  • Python: Proficiency in Python programming language is required as you will be using Python to interact with the Celo blockchain, deploy smart contracts, and write tests. You should be comfortable with Python syntax, data types, functions, and modules.

  • Blockchain Concepts: A good understanding of blockchain technology and concepts is necessary. You should grasp the fundamentals of decentralized systems, distributed ledgers, blockchain consensus mechanisms, and the basics of how smart contracts function.

  • Celo Blockchain: Familiarize yourself with the Celo blockchain, its features, and its ecosystem. Understand how Celo differs from other blockchains and its specific use cases and advantages.

  • Web3.py: Learn how to use the web3.py library, which is a Python library for interacting with the Celo blockchain. Understanding how to connect to the Celo network, send transactions, call smart contract functions, and handle events using web3.py is essential.

Requirements​

The following will be required to build a decentralized file-sharing system on the Celo Blockchain.

  • web3.py: web3.py is used again to interact with the deployed smart contract. It provides functions to call contract methods and send transactions.

  • unittest (Python Testing Framework): The unittest framework is used to write and run tests for the decentralized file sharing system.

  • celocli (Celo Command-Line Interface): celocli is a command-line interface provided by Celo that allows various operations related to the Celo blockchain, including account management and contract deployment.

  • Truffle: Testing framework for solidity

  • solc (Solidity Compiler): solc is a command-line compiler for Solidity contracts that compiles Solidity code into bytecode and ABI.

How to Build a Decentralized File Sharing System on Celo Using Python and Solidity

Step 1: Solidity Smart Contract Development

  • Design the smart contract:
    Determine the structure and functionalities your smart contract will have. For example, you can include file metadata, access control, and file retrieval.
    Here’s an example of a basic file sharing contract in Solidity:
    solidity
//solidity 

contract FileSharing {
    struct File {
        string name;
        string ipfsHash;
        address owner;
        mapping(address => bool) allowedUsers;
    }

    mapping(uint256 => File) public files;
    uint256 public fileCount;

    event FileUploaded(uint256 fileId, string name, string ipfsHash, address owner);

    function uploadFile(string memory _name, string memory _ipfsHash) external {
        uint256 fileId = fileCount++;
        files[fileId] = File(_name, _ipfsHash, msg.sender);
        emit FileUploaded(fileId, _name, _ipfsHash, msg.sender);
    }

    function allowAccess(uint256 _fileId, address _user) external {
        require(files[_fileId].owner == msg.sender, "You can only allow access to your own files");
        files[_fileId].allowedUsers[_user] = true;
    }

    function getFile(uint256 _fileId) external view returns (string memory, string memory, address) {
        File storage file = files[_fileId];
        require(file.owner == msg.sender || file.allowedUsers[msg.sender], "You don't have permission to access this file");
        return (file.name, file.ipfsHash, file.owner);
    }
}
  • Write the Solidity code:

Create a new file called “FileSharing.sol” and paste the above Solidity code into it using a code editor or the Remix IDE.

  • Test the smart contract:

Use Truffle to write unit tests for your smart contract.
Write test cases to cover different scenarios, such as uploading files, granting access, and retrieving file information.
Here’s an example using the Truffle testing framework:

//solidity

// FileSharing.test.js
const FileSharing = artifacts.require("FileSharing");

contract("FileSharing", (accounts) => {
  let fileSharing;

  before(async () => {
    fileSharing = await FileSharing.deployed();
  });

  it("should upload a file and emit an event", async () => {
    const result = await fileSharing.uploadFile("Example File", "QmHash");
    const fileId = result.logs[0].args.fileId.toNumber();
    
    assert.equal(fileId, 0, "File ID should be 0");
    
    const file = await fileSharing.files(fileId);
    assert.equal(file.name, "Example File", "File name mismatch");
    assert.equal(file.ipfsHash, "QmHash", "File IPFS hash mismatch");
    assert.equal(file.owner, accounts[0], "File owner address mismatch");
  });
  
  // Add more test cases for other contract functions
});

Step 2: Compile the smart contract:

Solidity smart contracts need to be compiled into bytecode that can be executed on the Celo Virtual Machine (VM).
There are various Solidity compilers available, such as solc (Solidity’s command-line compiler) or the Remix IDE.
Compile your smart contract by providing the Solidity code as input to the compiler.
The compiler will generate the bytecode and the Application Binary Interface (ABI) for your smart contract.
The bytecode represents the low-level machine instructions that will be executed on the Celo VM, while the ABI defines the interface for interacting with the contract.

Deploy the smart contract:

To deploy the smart contract, you need to connect to the Celo network using a Celo provider like web3.py or ethers.js which in this case we’ll be using web3.py.
Initialize a connection to the Celo network by specifying the network’s RPC endpoint. Once connected, you can create a contract instance using the compiled bytecode and ABI.
The contract instance represents the deployed smart contract on the blockchain and provides an interface to interact with its functions and data.
Deploy the contract by sending a deployment transaction, which includes the bytecode and any constructor arguments required by the contract. After the deployment transaction is mined and confirmed, the contract will have a unique address on the Celo blockchain.You can store this contract address for future interactions with the deployed contract.
Here’s the code snippet demonstrating the deployment of a smart contract using web3.py:

//python

from web3 import Web3
from solcx import compile_standard

# Connect to Celo network using the desired provider
w3 = Web3(Web3.HTTPProvider("https://<celo-network-rpc-url>"))

# Compile the smart contract
contract_source_code = """
    pragma solidity ^0.8.0;
    contract MyContract {
        // Contract code goes here...
    }
"""
compiled_contract = compile_standard(
    {
        "language": "Solidity",
        "sources": {"MyContract.sol": {"content": contract_source_code}},
        "settings": {
            "outputSelection": {"*": {"*": ["abi", "evm.bytecode"]}}
        },
    }
)

contract_bytecode = compiled_contract["contracts"]["MyContract.sol"]["MyContract"]["evm"]["bytecode"]["object"]
contract_abi = compiled_contract["contracts"]["MyContract.sol"]["MyContract"]["abi"]

# Deploy the contract
contract = w3.eth.contract(abi=contract_abi, bytecode=contract_bytecode)
deployed_contract = contract.constructor().transact()

# Wait for the contract deployment transaction to be mined
tx_receipt = w3.eth.wait_for_transaction_receipt(deployed_contract)
contract_address = tx_receipt["contractAddress"]

In the above, we compiled the Solidity contract using solcx.compile_standard and extract the bytecode and ABI from the compiled contract. We then use the contract.constructor().transact() method to send a deployment transaction to the Celo network, and we wait for the transaction to be mined using w3.eth.wait_for_transaction_receipt. Finally, we obtained the deployed contract’s address from the transaction receipt.

Remember to replace with the actual RPC endpoint of the Celo network you are connecting to. Additionally, ensure you have the necessary dependencies installed, such as web3.py and solcx.

step 3 Interact with the smart contract:

Here we are going to be using Python functions to interact with the smart contract.
Here’s an example of calling the contract’s functions:

#python 

# Upload a file
def upload_file(name, ipfs_hash):
    tx_hash = contract.functions.uploadFile(name, ipfs_hash).transact()
    w3.eth.wait_for_transaction_receipt(tx_hash)

# Allow access to a file
def allow_access(file_id, user_address):
    tx_hash = contract.functions.allowAccess(file_id, user_address).transact()
    w3.eth.wait_for_transaction_receipt(tx_hash)

# Get file information
def get_file(file_id):
    return contract.functions.getFile(file_id).call()

step 4 Testing and Deployment:

Test your decentralized file sharing system:

#Python:

import unittest from web3 
import Web3
from web3.contract import ConciseContract

class FileSharingTest(unittest.TestCase):
    def setUp(self):
        # Connect to Celo network using a provider
        self.w3 = Web3(Web3.HTTPProvider("<celo-network-rpc-url>"))

        # Load the compiled contract
        compiled_contract = compile_contract()
        contract_bytecode = compiled_contract["bytecode"]
        contract_abi = compiled_contract["abi"]

        # Deploy the contract
        self.contract = self.w3.eth.contract(abi=contract_abi, bytecode=contract_bytecode)
        self.contract_instance = self.contract.deploy(transaction={'from': self.w3.eth.default_account})

    def test_upload_file(self):
        # Perform file upload
        file_name = "test_file.txt"
        ipfs_hash = "Qm...your-ipfs-hash..."
        self.contract_instance.functions.uploadFile(file_name, ipfs_hash).transact()

        # Verify the file upload
        file_info = self.contract_instance.functions.getFile(0).call()
        self.assertEqual(file_info[0], file_name)
        self.assertEqual(file_info[1], ipfs_hash)

    def test_allow_access(self):
        # Perform access control
        user_address = "0x...user-address..."
        self.contract_instance.functions.allowAccess(0, user_address).transact()

        # Verify access control
        allowed_users = self.contract_instance.functions.getAllowedUsers(0).call()
        self.assertIn(user_address, allowed_users)

if __name__ == '__main__':
    unittest.main()

Above, we defined a test class FileSharingTest that inherits from unittest.TestCase. In the setUp method, we connect to the Celo network, compile the smart contract, and deployed it. Then, we define test methods, such as test_upload_file and test_allow_access, to verify specific functionalities of the contract. We use assertions to validate the expected results.

Run the tests by executing the Python script, and the testing framework will execute the test methods and report any failures or errors.

Deploy your decentralized file sharing system using the Celo CLI:

$ celocli account:new --from=deployer
Enter the password to unlock the account: ******
Account address: 0x...deployer-address...

$ celocli account:unlock --account=0x...deployer-address...
Enter the password to unlock the account: ******

$ celocli node:deploy <path-to-contract-file> --from=deployer
Contract deployed at address: 0x...contract-address...

Here we first created and unlocked a new account using celocli account:new and celocli account:unlock. Then, we use celocli node:deploy to deploy the compiled smart contract, specifying the contract file path and the deploying account. The deployment process will provide you with the deployed contract address.

Here is the source code for your referrence

Conclusion​

This tutorial demonstrates how to create a decentralized file-sharing system on the Celo Blockchain using Python and Solidity. It covers designing the system, setting up the development environment, writing smart contracts, and interacting with them. Prerequisites include knowledge of Solidity, Python, blockchain concepts, Celo Blockchain, and web3.py library. The tutorial includes steps for smart contract development, compilation, deployment, and interacting with the contract. It also provides an example of testing the system and deploying it using the Celo CLI.

About the Author​

Ewoma Odiri is a front-end developer with experience in Python, Next.js, Ember.js, Solidity, and web3. I adore learning new things, and I enjoy imparting my knowledge to the tech industry in order to advance it.

Connect with me on Twitter

References​

3 Likes

Approved for you to get started. You can manage the tutorial here by changing the category to Proposals > In Progress then Proposals > Review as you complete the tutorial. Thanks!

Will be reviewing this in a day or two @wadil

Please attach source code link @wadil

You can remove the Trello card links on finished projects they were only for reference :pray:

@ishan.pathak2711 source code