Skip to content

Smart Contract Demo of Long-Term Data Storage with Celestia Sovereign Rollups to provide data availability and consensus, using Ethermint & RollKit as the execution environment.

Notifications You must be signed in to change notification settings

pynchmeister/celestia-long-term-data-storage-mvp

Β 
Β 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

58 Commits
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸš€ Celestia Long-Term Data Storage MVP

Long-Term Data Storage with Celestia Rollups (Rollkit + Ethermint) + IPFS/Filecoin

This project demonstrates a minimal working example of long-term decentralized data storage using:

  • Celestia Rollups (Rollkit + Ethermint execution layer)
  • Solidity smart contracts to store IPFS/Filecoin CIDs
  • IPFS and Web3.Storage for decentralized content storage
  • React + ethers.js to form the client-side application

Users can upload files β†’ store them via IPFS/Filecoin β†’ persist the resulting CID on a Celestia rollup.
This MVP later extends into a DED Learning Session prototype where learning artifacts can be uploaded and validated through on-chain voting.


πŸ“¦ Prerequisites

Before running this project, you must have:

βœ”οΈ A Celestia Light Node

https://docs.celestia.org/nodes/light-node/

βœ”οΈ Completed the Ethermint tutorials

This provides the RPC environment used by the contracts.
https://docs.celestia.org/category/ethermint


🧱 1. Solidity Contract: Storing IPFS CIDs

A minimal contract that stores user β†’ CID mappings:

// SPDX-License-Identifier: Unlicensed
pragma solidity ^0.8.13;

contract Storage {
    mapping (address => string) public userFiles;

    function setFile(string memory file) external {
        userFiles[msg.sender] = file;
    }
}

πŸš€ 2. Deploying to Ethermint with Foundry

Deploy the contract using a standard Foundry script:

// SPDX-License-Identifier: Unlicensed
pragma solidity ^0.8.13;

import "forge-std/Script.sol";
import {Storage} from "src/Storage.sol";

contract StorageScript is Script {
    function run() public {
        vm.startBroadcast();
        new Storage();
        vm.stopBroadcast();
    }
}

Deployment demo:

Screen.Recording.2022-12-05.at.6.48.46.AM.mov

Record the deployed address for frontend integration.


🌐 3. Frontend Setup (create-eth-app + IPFS)

We bootstrap the frontend using create-eth-app:

https://github.com/paulrberg/create-eth-app

Then:

1. Install the latest IPFS JS client

2. Add the Storage.json ABI to:

packages/contracts/src/abis

3. Import it in abis.js:

import erc20Abi from "./abis/erc20.json";
import ownableAbi from "./abis/ownable.json";
import storageAbi from "./abis/Storage.json";

const abis = {
  erc20: erc20Abi,
  ownable: ownableAbi,
  storage: storageAbi,
};

export default abis;

4. Add the address to addresses.js:

const addresses = {
  storage: "0xdc64a140aa3e981100a9beca4e685f962f0cf6c9",
};

export default addresses;

πŸ”— 4. IPFS Integration

Initialize the IPFS node:

import IPFS from "ipfs";

async function initIpfs() {
  node = await IPFS.create();
  const version = await node.version();
  console.log("IPFS Node Version:", version.version);
}

Read a user's stored CID:

async function readCurrentUserFile() {
  const signer = defaultProvider.getSigner();
  const userAddress = await signer.getAddress();
  return await storageContract.userFiles(userAddress);
}

Upload + write the CID on-chain:

async function setFile(hash) {
    const withSigner = storageContract.connect(defaultProvider.getSigner());
    await withSigner.setFile(hash);
    setIpfsHash(hash);
}

async function uploadFile(file) {
    const files = [{ path: file.name + file.path, content: file }];

    for await (const result of node.add(files)) {
        await setFile(result.cid.string);
    }
}

πŸ–₯️ 5. UI Development

The UI handles:

  • File selection
  • IPFS upload
  • CID resolution
  • Smart contract interaction

See the repo for the complete frontend code.


πŸ”‘ 6. Metamask + Ethermint Network Setup

Set up a custom network for Ethermint using RPC_URL: 9545.

You can import an Anvil private key to fund transactions.

Example screenshot:

Screen Shot 2022-12-05 at 6 12 36 AM

Demo video of uploading a file and resolving its CID:

the.two.mov

πŸŽ“ 7. Extending to DED Learning Sessions

This MVP forms the basis for Decentralized Education Development (DED) Learning Sessions.

Students upload learning artifacts (videos, comments).
Arbitrators evaluate them using an on-chain voting mechanism.


πŸ“˜ Artifact Structure

struct Artifact {
    LearningSessionArtifact type;
    uint256 id;
    uint256 parentId;
    address author;
    uint256 createdAtBlock;
    uint256[] childIds;
    string CID; // IPFS/Filecoin content identifier
}

Artifact Types:

enum LearningSessionArtifact {
    VIDEO,
    COMMENT
}

Comments form a tree structure using parentId and childIds.

All content is stored as JSON in IPFS/Filecoin using Web3.Storage.


πŸ—³οΈ 8. Voting and Reputation

Arbitrators vote on artifacts:

function vote(uint256 artifactId, int8 voteValue) public { ... }
  • +1 = upvote
  • -1 = downvote
  • 0 = withdraw vote

Score retrieval:

function getArtifactScore(uint256 artifactId) public view returns (int256);

Author reputation:

function getAuthorReputation(address author) public view returns (int256);

πŸ› οΈ 9. Deploying LearningSession via Foundry

// SPDX-License-Identifier: Unlicensed
pragma solidity ^0.8.13;

import "forge-std/Script.sol";
import {LearningSession} from "src/LearningSession.sol";

contract LearningSessionScript is Script {
    function run() public {
        vm.startBroadcast();
        new LearningSession();
        vm.stopBroadcast();
    }
}

Deploy:

forge script script/LearningSession.s.sol:LearningSessionScript \
--fork-url $RPC_URL --private-key $ANVIL_KEY --broadcast

🌐 10. Interacting with Web3.Storage

File upload:

function getFiles () {
  const fileInput = document.querySelector('input[type="file"]')
  return fileInput.files
}

async function storeFiles (files) {
  const client = makeStorageClient()
  const cid = await client.put(files)
  console.log('stored files with cid:', cid)
  return cid
}

Retrieval:

async function retrieveFiles (cid) {
  const client = makeStorageClient()
  const res = await client.get(cid)

  if (!res.ok) {
    throw new Error(`failed to get ${cid} - [${res.status}] ${res.statusText}`)
  }

  const files = await res.files()
  for (const file of files) {
    console.log(`${file.cid} -- ${file.path} -- ${file.size}`)
  }
}

🧭 Navigating This Repository


πŸš€ Want to Explore or Contribute?

Open an issue or PR β€” this MVP is a foundation for research on sovereign rollups, decentralized storage, and verifiable learning systems within the Celestia ecosystem.

About

Smart Contract Demo of Long-Term Data Storage with Celestia Sovereign Rollups to provide data availability and consensus, using Ethermint & RollKit as the execution environment.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Solidity 98.7%
  • HTML 0.5%
  • TypeScript 0.3%
  • CSS 0.2%
  • JavaScript 0.2%
  • Makefile 0.1%