Rust StarkNet插件库的使用:零知识证明与Layer2区块链开发的强大工具

Rust StarkNet插件库的使用:零知识证明与Layer2区块链开发的强大工具

starknet-rs Logo

简介

starknet-rs是一个完整的Rust语言Starknet库,提供了与Starknet Layer2区块链交互所需的各种功能。

注意:目前starknet-rs仍处于实验阶段,在第一个稳定版本发布前可能会有破坏性更改。该库目前也未经过安全审计,请谨慎使用。

功能特性

  • ✅ Sequencer网关/feeder网关客户端
  • ✅ 全节点JSON-RPC API客户端
    • ✅ HTTP传输
    • ✅ WebSocket传输(仅订阅)
  • ✅ 智能合约部署
  • ✅ 支持使用IAccount账户合约的签名器
  • ✅ Ledger硬件钱包支持

安装

在项目中添加starknet-rs依赖:

[dependencies]
starknet = "0.15.1"

或者直接从GitHub获取最新版本:

[dependencies]
starknet = { git = "https://github.com/xJonathanLEI/starknet-rs" }

示例代码

示例1:从alpha-sepolia测试网获取最新区块

use starknet::providers::{Provider, JsonRpcClient};
use url::Url;

#[tokio::main]
async fn main() {
    // 创建JSON-RPC客户端
    let provider = JsonRpcClient::new(
        Url::parse("https://alpha-sepolia.starknet.io").unwrap()
    );
    
    // 获取最新区块
    let block = provider.get_block("latest").await.unwrap();
    println!("Latest block: {:?}", block);
}

示例2:部署合约到alpha-sepolia测试网

use starknet::{
    core::types::FieldElement,
    providers::{Provider, JsonRpcClient},
    signers::{LocalWallet, SigningKey},
    contract::ContractFactory,
};
use url::Url;

#[tokio::main]
async fn main() {
    // 创建JSON-RPC客户端
    let provider = JsonRpcClient::new(
        Url::parse("https://alpha-sepolia.starknet.io").unwrap()
    );
    
    // 创建钱包签名器
    let signer = LocalWallet::from(SigningKey::from_hex("YOUR_PRIVATE_KEY").unwrap());
    
    // 合约class hash和构造函数参数
    let class_hash = FieldElement::from_hex_be("YOUR_CLASS_HASH").unwrap();
    let constructor_args = vec![FieldElement::ONE];
    
    // 创建合约工厂并部署
    let factory = ContractFactory::new(class_hash, provider, signer);
    let deployment = factory.deploy(&constructor_args).await.unwrap();
    
    println!("Contract deployed at: 0x{:x}", deployment.address);
}

示例3:在alpha-sepolia上铸造1,000 TST代币

use starknet::{
    core::types::FieldElement,
    providers::{Provider, JsonRpcClient},
    signers::{LocalWallet, SigningKey},
};
use url::Url;

#[tokio::main]
async fn main() {
    // 创建JSON-RPC客户端
    let provider = JsonRpcClient::new(
        Url::parse("https://alpha-sepolia.starknet.io").unwrap()
    );
    
    // 创建钱包签名器
    let signer = LocalWallet::from(SigningKey::from_hex("YOUR_PRIVATE_KEY").unwrap());
    
    // TST代币合约地址和ABI
    let token_address = FieldElement::from_hex_be("0xYOUR_TOKEN_ADDRESS").unwrap();
    
    // 调用mint函数
    let calldata = vec![
        FieldElement::from_hex_be("YOUR_ACCOUNT_ADDRESS").unwrap(),  // recipient
        FieldElement::from_dec_str("1000000000000000000000").unwrap(), // amount (1,000 * 10^18)
        FieldElement::ZERO  // data
    ];
    
    let result = provider
        .execute(
            token_address,
            "mint",  // function name
            &calldata,
            &signer
        )
        .await
        .unwrap();
    
    println!("Mint transaction hash: 0x{:x}", result.transaction_hash);
}

完整示例:完整的StarkNet合约交互流程

use starknet::{
    core::types::{BlockId, BlockTag, FieldElement},
    providers::{jsonrpc::HttpTransport, JsonRpcClient, Provider},
    signers::{LocalWallet, SigningKey},
};
use url::Url;

#[tokio::main]
async fn main() {
    // 1. 初始化JSON-RPC客户端
    let rpc_url = Url::parse("https://alpha-sepolia.starknet.io").unwrap();
    let provider = JsonRpcClient::new(HttpTransport::new(rpc_url));
    
    // 2. 创建签名器
    let private_key = "0x123456789abcdef..."; // 替换为你的私钥
    let signer = LocalWallet::from(SigningKey::from_hex(private_key).unwrap());
    
    // 3. 查询链上数据
    let latest_block = provider
        .get_block_with_txs(BlockId::Tag(BlockTag::Latest))
        .await
        .unwrap();
    println!("Latest block number: {}", latest_block.block_number);
    
    // 4. 与合约交互
    let contract_address = FieldElement::from_hex_be("0x...").unwrap(); // 替换为合约地址
    
    // 调用合约的balanceOf函数
    let calldata = vec![
        FieldElement::from_hex_be("0x...").unwrap(), // 查询的地址
    ];
    
    let balance = provider
        .call(
            starknet::core::types::FunctionCall {
                contract_address,
                entry_point_selector: FieldElement::from_hex_be(
                    "0x02e4263afad30923c891518314c3c95dbe830a168f2d698e51a6a790a5e8c4d8",
                )
                .unwrap(), // balanceOf的选择器
                calldata,
            },
            BlockId::Tag(BlockTag::Latest),
        )
        .await
        .unwrap();
    
    println!("Balance: {:?}", balance);
    
    // 5. 发送交易
    let transfer_calldata = vec![
        FieldElement::from_hex_be("0x...").unwrap(), // 接收地址
        FieldElement::from_dec_str("1000000000000000000").unwrap(), // 转账金额 (1 * 10^18)
        FieldElement::ZERO,
    ];
    
    let transfer_result = provider
        .execute(
            contract_address,
            "transfer", // 函数名
            &transfer_calldata,
            &signer,
        )
        .await
        .unwrap();
    
    println!("Transfer tx hash: 0x{:x}", transfer_result.transaction_hash);
}

使用场景

starknet-rs非常适合以下开发场景:

  1. 构建Starknet Layer2 DApps
  2. 开发零知识证明相关应用
  3. 创建智能合约部署工具
  4. 开发钱包和签名服务
  5. 构建区块链数据分析工具

许可证

starknet-rs采用双许可证:

  • Apache License 2.0
  • MIT license

开发者可以根据需要选择其中一种。


1 回复

Rust StarkNet插件库的使用:零知识证明与Layer2区块链开发的强大工具

介绍

StarkNet是一个基于零知识证明的Layer2扩容解决方案,而Rust StarkNet插件库为开发者提供了在Rust环境中与StarkNet交互的强大工具集。这个库特别适合需要在StarkNet上构建去中心化应用(DApps)、智能合约或需要零知识证明功能的开发者。

主要特性

  1. 完整的StarkNet JSON-RPC API支持
  2. 零知识证明工具集成
  3. 合约部署和交互功能
  4. 交易签名和发送
  5. 账户管理
  6. 事件监听和处理

安装方法

在Cargo.toml中添加依赖:

[dependencies]
starknet = "0.1.0"  # 请使用最新版本

基本使用方法

1. 连接到StarkNet网络

use starknet::providers::{Provider, JsonRpcProvider};
use url::Url;

async fn connect_to_starknet() {
    let provider_url = Url::parse("https://starknet-mainnet.infura.io/v3/YOUR_API_KEY").unwrap();
    let provider = JsonRpcProvider::new(provider_url);
    
    // 获取当前区块号
    let block_number = provider.block_number().await.unwrap();
    println!("Current StarkNet block number: {}", block_number);
}

2. 部署智能合约

use starknet::contract::ContractFactory;
use starknet::accounts::SingleOwnerAccount;
use starknet::signers::LocalWallet;

async fn deploy_contract() {
    let provider = JsonRpcProvider::new(/* 你的provider URL */);
    let signer = LocalWallet::from_private_key("0x123...").unwrap();
    let account = SingleOwnerAccount::new(provider, signer, "0xYourAddress".parse().unwrap());
    
    let contract_artifact = /* 加载你的合约artifact */;
    let factory = ContractFactory::new(contract_artifact, account);
    
    let deployment = factory.deploy(vec![]).unwrap();  // 传入构造函数参数
    let deployed_contract = deployment.send().await.unwrap();
    
    println!("Contract deployed at: {}", deployed_contract.address());
}

3. 与合约交互

use starknet::contract::Contract;
use starknet::core::types::FieldElement;

async fn call_contract() {
    let provider = JsonRpcProvider::new(/* 你的provider URL */);
    let contract_address = "0xContractAddress".parse().unwrap();
    let contract_abi = /* 加载你的合约ABI */;
    
    let contract = Contract::new(contract_address, contract_abi, provider);
    
    // 调用view函数
    let result: FieldElement = contract.call("get_balance", vec![]).await.unwrap();
    println!("Balance: {}", result);
    
    // 执行交易
    let signer = LocalWallet::from_private_key("0x123...").unwrap();
    let account = SingleOwnerAccount::new(provider, signer, "0xYourAddress".parse().unwrap());
    let contract = contract.with_account(account);
    
    let tx = contract.invoke("transfer", vec![recipient, amount]).await.unwrap();
    println!("Transaction hash: {}", tx.transaction_hash);
}

4. 使用零知识证明

use starknet::crypto::pedersen_hash;
use starknet::types::FieldElement;

fn zkp_example() {
    // 计算Pedersen哈希 - StarkNet中常用的哈希函数
    let a = FieldElement::from_hex_be("0x123").unwrap();
    let b = FieldElement::from_hex_be("0x456").unwrap();
    let hash = pedersen_hash(&a, &b);
    
    println!("Pedersen hash: 0x{:x}", hash);
}

高级功能

事件监听

use starknet::core::types::{BlockId, EventFilter};
use futures::StreamExt;

async fn listen_to_events() {
    let provider = JsonRpcProvider::new(/* 你的provider URL */);
    let contract_address = "0xContractAddress".parse().unwrap();
    
    let filter = EventFilter {
        from_block: BlockId::Number(1000),
        to_block: BlockId::Latest,
        address: Some(contract_address),
        keys: Some(vec![vec!["0xEventKey"].parse().unwrap()]]),
    };
    
    let mut event_stream = provider.get_events(filter).unwrap();
    while let Some(event) = event_stream.next().await {
        println!("New event: {:?}", event);
    }
}

批量交易

use starknet::account::Execution;

async fn batch_transactions() {
    let provider = /* 初始化provider */;
    let account = /* 初始化account */;
    
    let contract = Contract::new(/* 合约地址 */, /* ABI */, &account);
    
    let execution = account
        .execute(vec![
            Execution::new("contract_method1", vec!["0x1".parse().unwrap()]),
            Execution::new("contract_method2", vec!["0x2".parse().unwrap()]),
        ])
        .unwrap();
    
    let result = execution.send().await.unwrap();
    println!("Batch transaction hash: {}", result.transaction_hash);
}

最佳实践

  1. 错误处理:始终正确处理可能出现的错误,StarkNet操作可能会因为网络问题或合约状态而失败
  2. Gas估算:在执行交易前估算gas,避免交易失败
  3. 测试网先行:先在测试网测试你的代码,再部署到主网
  4. 缓存结果:对频繁查询的数据考虑实现缓存机制
  5. 事件驱动:利用事件监听而不是轮询来构建响应式应用

完整示例代码

// 完整StarkNet交互示例
use starknet::{
    providers::{JsonRpcProvider, Provider},
    contract::{Contract, ContractFactory},
    accounts::SingleOwnerAccount,
    signers::LocalWallet,
    core::types::{FieldElement, BlockId, EventFilter},
    crypto::pedersen_hash,
};
use url::Url;
use futures::StreamExt;

#[tokio::main]
async fn main() {
    // 1. 连接到StarkNet网络
    let provider_url = Url::parse("https://starknet-mainnet.infura.io/v3/YOUR_API_KEY").unwrap();
    let provider = JsonRpcProvider::new(provider_url);
    
    // 获取网络状态
    let block_number = provider.block_number().await.unwrap();
    println!("Current StarkNet block number: {}", block_number);
    
    // 2. 部署合约示例
    let signer = LocalWallet::from_private_key("0x123...").unwrap();
    let account = SingleOwnerAccount::new(
        provider.clone(), 
        signer, 
        "0xYourAddress".parse().unwrap()
    );
    
    // 假设这是你的合约artifact
    let contract_artifact = load_contract_artifact();
    let factory = ContractFactory::new(contract_artifact, account.clone());
    
    match factory.deploy(vec![]).unwrap().send().await {
        Ok(deployed_contract) => {
            println!("Contract deployed at: {}", deployed_contract.address());
            
            // 3. 与合约交互
            let contract = Contract::new(
                deployed_contract.address(),
                load_contract_abi(),
                account.clone()
            );
            
            // 调用view函数
            if let Ok(balance) = contract.call("get_balance", vec![]).await {
                println!("Contract balance: {}", balance);
            }
            
            // 执行交易
            let recipient = FieldElement::from_hex_be("0xabc").unwrap();
            let amount = FieldElement::from_dec_str("100").unwrap();
            
            if let Ok(tx) = contract.invoke("transfer", vec![recipient, amount]).await {
                println!("Transfer transaction hash: {}", tx.transaction_hash);
            }
            
            // 4. 使用零知识证明功能
            let a = FieldElement::from_hex_be("0x123").unwrap();
            let b = FieldElement::from_hex_be("0x456").unwrap();
            println!("Pedersen hash: 0x{:x}", pedersen_hash(&a, &b));
            
            // 5. 监听事件
            let filter = EventFilter {
                from_block: BlockId::Number(block_number),
                to_block: BlockId::Latest,
                address: Some(deployed_contract.address()),
                keys: Some(vec![vec!["0xEventKey".parse().unwrap()]]),
            };
            
            tokio::spawn(async move {
                let mut events = provider.get_events(filter).unwrap();
                while let Some(event) = events.next().await {
                    println!("New contract event: {:?}", event);
                }
            });
            
            // 6. 批量交易示例
            let execution = account.execute(vec![
                Execution::new("method1", vec!["0x1".parse().unwrap()]),
                Execution::new("method2", vec!["0x2".parse().unwrap()]),
            ]).unwrap();
            
            if let Ok(result) = execution.send().await {
                println!("Batch execution hash: {}", result.transaction_hash);
            }
        }
        Err(e) => eprintln!("Contract deployment failed: {:?}", e),
    }
}

// 辅助函数 - 实际项目中需要实现
fn load_contract_artifact() -> serde_json::Value {
    unimplemented!()
}

fn load_contract_abi() -> starknet::core::abi::Abi {
    unimplemented!()
}

这个完整示例展示了如何使用Rust StarkNet插件库进行完整的区块链交互流程,包括网络连接、合约部署、交互、事件监听和批量交易等功能。

回到顶部