برنامه نویسی

ساختن یک سیستم هوایی درخت Merkle در Starknet: یک راهنمای کامل

شرح تصویر


ساختن یک سیستم هوایی درخت Merkle در Starknet: یک راهنمای کامل

بیاموزید که چگونه یک سیستم هوایی کارآمد و بهینه شده با گاز با استفاده از درختان مرکل با قراردادهای هوشمند جاوا اسکریپت و قاهره ایجاد کنید


مقدمه

AirDrops به سنگ بنای پروژه های Web3 برای توزیع نشانه ها به جوامع تبدیل شده است. با این حال ، مکانیسم های سنتی Airdrop هنگام برخورد با هزاران گیرنده می توانند بسیار گازسوز باشند. وارد کردن درختان مرکل -یک ساختار داده رمزنگاری که به ما امکان می دهد عضویت را در یک مجموعه داده بزرگ با حداقل ذخیره سازی و محاسبات در زنجیره تأیید کنیم.

در این راهنمای جامع ، ما یک سیستم کامل AirDrop مبتنی بر درخت Merkle را در Starknet می سازیم و همه چیز را از تولید اثبات خارج از زنجیره گرفته تا تأیید آنها در زنجیره ای با قراردادهای هوشمند قاهره پوشش می دهیم.

درختان مرکل چیست و چرا از آنها استفاده می کنید؟

یک درخت مرکل یک درخت باینری است که در آن:

  • هر برگ یک عنصر داده را نشان می دهد (در مورد ما ، یک گیرنده هوایی)
  • هر گره داخلی حاوی هش فرزندان خود است
  • ریشه کل مجموعه داده را نشان می دهد

مزایای آن برای AirDrops:

  • کارایی گاز: فقط به جای تمام داده های گیرنده ، فقط هش ریشه را روی زنجیره ذخیره کنید
  • مقیاس پذیری: میلیون ها گیرنده را با حداقل ردپای زنجیره ای اداره کنید
  • خلوت: داده های گیرندگان تا زمانی که ادعا کنند قابل مشاهده نیست
  • انعطاف پذیری: به روزرسانی یا اصلاح لیست های گیرنده آسان

معماری پروژه

سیستم ما از سه مؤلفه اصلی تشکیل شده است:

  1. ژنراتور جاوا اسکریپت: درختان مرکل را ایجاد می کند و اثبات ایجاد می کند
  2. قرارداد هوشمند قاهره: اثبات را تأیید می کند و ادعاهای موجود در زنجیره را کنترل می کند
  3. لایه ادغام: محاسبات خارج از زنجیره را با تأیید زنجیره متصل می کند

تنظیم محیط توسعه

ابتدا بیایید ساختار پروژه خود را تنظیم کنیم:

mkdir starknet-merkle-airdrop
cd starknet-merkle-airdrop
npm init -y
npm install starknet-merkle-tree starknet
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

خود را به روز کنید package.json:

{
  "type": "module",
  "scripts": {
    "generate-tree": "node generate-tree.js",
    "test-verification": "node test-verification.js"
  },
  "dependencies": {
    "starknet-merkle-tree": "^latest",
    "starknet": "^6.0.0"
  }
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

ساخت ژنراتور درخت مرکل خارج از زنجیره

ایجاد کردن generate-tree.js برای رسیدگی به تولید درخت و ایجاد اثبات:

import * as Merkle from "starknet-merkle-tree";
import fs from "fs";

// Define airdrop recipients with their allocation data
const airdropData = [
  ['0x7e00d496e324876bbc8531f2d9a82bf154d1a04a50218ee74cdd372f75a551a', '1000000000000000000', '0'], // 1 ETH
  ['0x53c615080d35defd55569488bc48c1a91d82f2d2ce6199463e095b4a4ead551', '2000000000000000000', '0'], // 2 ETH
  ['0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', '500000000000000000', '1'],  // 0.5 ETH
  ['0x5678901234567890abcdef1234567890abcdef1234567890abcdef1234567890', '750000000000000000', '0']   // 0.75 ETH
];

console.log('🌳 Generating Merkle tree...');

// Create tree using Poseidon hash (optimized for Starknet)
const tree = Merkle.StarknetMerkleTree.create(airdropData, Merkle.HashType.Poseidon);

console.log(`✅ Tree created with ${airdropData.length} leaves`);
console.log(`📋 Merkle Root: ${tree.root}`);

// Generate and store proofs for all recipients
const proofs = {};
const claims = [];

for (let i = 0; i  {
    fn verify_proof(
        self: @TContractState,
        proof: Array,
        leaf: felt252
    ) -> bool;
    fn verify_claim(
        self: @TContractState,
        proof: Array,
        address: ContractAddress,
        amount: u256,
        additional_data: felt252
    ) -> bool;
    fn get_merkle_root(self: @TContractState) -> felt252;
    fn set_merkle_root(ref self: TContractState, new_root: felt252);
}

#[starknet::contract]
mod MerkleVerifier {
    use super::IMerkleVerifier;
    use starknet::{ContractAddress, get_caller_address};
    use core::poseidon::poseidon_hash_span;
    use core::array::ArrayTrait;
    use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess};

    #[storage]
    struct Storage {
        merkle_root: felt252,
        owner: ContractAddress,
    }

    #[event]
    #[derive(Drop, starknet::Event)]
    enum Event {
        ProofVerified: ProofVerified,
        RootUpdated: RootUpdated,
    }

    #[derive(Drop, starknet::Event)]
    struct ProofVerified {
        #[key]
        leaf: felt252,
        verified: bool,
    }

    #[derive(Drop, starknet::Event)]
    struct RootUpdated {
        old_root: felt252,
        new_root: felt252,
    }

    #[constructor]
    fn constructor(ref self: ContractState, owner: ContractAddress, merkle_root: felt252) {
        self.owner.write(owner);
        self.merkle_root.write(merkle_root);
    }

    #[abi(embed_v0)]
    impl MerkleVerifierImpl of IMerkleVerifier {
        fn verify_proof(
            self: @ContractState,
            proof: Array,
            leaf: felt252
        ) -> bool {
            let root = self.merkle_root.read();
            self._verify_merkle_proof(proof.span(), leaf, root)
        }

        fn verify_claim(
            self: @ContractState,
            proof: Array,
            address: ContractAddress,
            amount: u256,
            additional_data: felt252
        ) -> bool {
            let leaf_hash = self._compute_leaf_hash(address, amount, additional_data);
            self.verify_proof(proof, leaf_hash)
        }

        fn get_merkle_root(self: @ContractState) -> felt252 {
            self.merkle_root.read()
        }

        fn set_merkle_root(ref self: ContractState, new_root: felt252) {
            let caller = get_caller_address();
            assert(caller == self.owner.read(), 'Only owner can update root');

            let old_root = self.merkle_root.read();
            self.merkle_root.write(new_root);

            self.emit(RootUpdated { old_root, new_root });
        }
    }

    #[generate_trait]
    impl InternalImpl of InternalTrait {
        fn _verify_merkle_proof(
            self: @ContractState,
            proof: Span,
            leaf: felt252,
            root: felt252
        ) -> bool {
            let mut computed_hash = leaf;
            let mut i = 0;

            while i  felt252 {
            // Hash format: [address, amount_low, amount_high, additional_data]
            let mut hash_data = ArrayTrait::new();
            hash_data.append(address.into());
            hash_data.append(amount.low.into());
            hash_data.append(amount.high.into());
            hash_data.append(additional_data);

            poseidon_hash_span(hash_data.span())
        }

        fn _is_left_node(self: @ContractState, a: felt252, b: felt252) -> bool {
            let a_u256: u256 = a.into();
            let b_u256: u256 = b.into();
            a_u256 < b_u256
        }
    }
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

آزمایش ادغام

ایجاد کردن test-verification.js برای آزمایش سیستم کامل ما:

import { Account, Contract, RpcProvider } from "starknet";
import fs from "fs";

async function testMerkleVerification() {
    // Load generated data
    const proofs = JSON.parse(fs.readFileSync("./proofs.json", "utf8"));
    const treeData = JSON.parse(fs.readFileSync("./merkle_tree.json", "utf8"));

    console.log("🧪 Testing Merkle verification...");
    console.log(`📋 Root: ${treeData.root}`);

    // Test data
    const testAddress = "0x7e00d496e324876bbc8531f2d9a82bf154d1a04a50218ee74cdd372f75a551a";
    const testProof = proofs[testAddress];

    if (!testProof) {
        console.error("❌ No proof found for test address");
        return;
    }

    console.log(`🎯 Testing address: ${testAddress}`);
    console.log(`💰 Amount: ${testProof.amount}`);
    console.log(`🔐 Proof: [${testProof.proof.join(', ')}]`);

    // Here you would call your deployed contract
    // const result = await contract.verify_claim(
    //     testProof.proof,
    //     testAddress,
    //     { low: testProof.amount, high: "0x0" },
    //     testProof.additionalData
    // );

    console.log("✅ Test data prepared for contract verification");
}

testMerkleVerification().catch(console.error);
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

استقرار و استفاده

مرحله 1: درخت مرکل خود را تولید کنید

npm run generate-tree
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

مرحله 2: قرارداد را مستقر کنید

هنگام استقرار قرارداد قاهره خود از هش ریشه تولید شده استفاده کنید.

مرحله 3: ادعاها را تأیید کنید

کاربران هم اکنون می توانند با ارائه اثبات خود ، از هوا استفاده کنند ، که این قرارداد در برابر ریشه ذخیره شده تأیید می کند.

ویژگی ها و مزایای اصلی

🚀 کارایی گاز

  • فقط یک زنجیره ریشه 32 بایت را ذخیره می کند
  • تأیید نیاز به محاسبات حداقل دارد
  • مقیاس به میلیون ها گیرنده بدون افزایش هزینه گاز

🔒 امنیت

  • سیستم اثبات امن رمزنگاری
  • جعل اثبات معتبر بدون داده های اصلی غیرممکن است
  • به روزرسانی های ریشه تحت کنترل مالک برای انعطاف پذیری

🎯 تجربه کاربر

  • گیرندگان فقط به اثبات خود نیاز دارند
  • نیازی به ارسال کلیه داده های گیرنده در زنجیره ای نیست
  • روند تأیید سریع

برنامه های دنیای واقعی

این سیستم درخت Merkle را می توان برای:

  • قطرات هوایی توکن: حاکمیت یا نشانه های ابزار را توزیع کنید
  • لیست های مجاز NFT: دسترسی به لیست سفید را برای مینینگ مدیریت کنید
  • سیستم های پاداش: جوایز را بر اساس مشارکت توزیع کنید
  • کنترل دسترسی: دسترسی دروازه به ویژگی ها یا محتوای انحصاری

نکات بهینه سازی

برای مجموعه داده های بزرگ

  • برای تولید درخت از پردازش دسته ای استفاده کنید
  • اجرای صفحه بندی برای توزیع اثبات
  • استفاده از IPF را برای ذخیره مجموعه های اثبات بزرگ در نظر بگیرید

برای بهینه سازی گاز

  • استفاده از poseidon hashing (بهینه سازی شده برای starknet)
  • حلقه های تأیید اثبات را به حداقل برسانید
  • در صورت امکان ادعاهای متعدد

پایان

درختان مرکل یک راه حل زیبا برای هوای مقیاس پذیر و کارآمد با گاز در استارک ارائه می دهند. با ترکیب محاسبات خارج از زنجیره با تأیید زنجیره ای ، می توانیم ضمن حفظ امنیت و به حداقل رساندن هزینه ها ، لیست های عظیم گیرنده را کنترل کنیم.

سیستمی که ما ساخته ایم ، قدرت ساختار داده های رمزنگاری را در حل چالش های blockchain در دنیای واقعی نشان می دهد. این که آیا شما یک نشانه جدید را راه اندازی می کنید یا به جامعه خود پاداش می دهید ، این اجرای درخت Merkle پایه و اساس محکمی را برای نیازهای هوایی شما فراهم می کند.

چه چیزی بعدی؟

گسترش این سیستم را با:

  • پشتیبانی چندکاره برای سناریوهای پیچیده هوایی
  • ادعای مبتنی بر زمان با تاریخ انقضا
  • مکانیسم های نمایندگی برای ادعای شخص ثالث
  • ادغام با dapps frontend برای تجربه کاربر یکپارچه

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا