Rust区块链容量计算库ckb-occupied-capacity的使用:高效管理与验证CKB链上空间占用

Rust区块链容量计算库ckb-occupied-capacity的使用:高效管理与验证CKB链上空间占用

ckb-occupied-capacity简介

ckb-occupied-capacity是Nervos CKB区块链的一个组件库,用于计算和管理CKB链上的空间占用情况。该库的最小支持Rust版本(MSRV)为1.85.0。

安装方法

在项目目录中运行以下Cargo命令:

cargo add ckb-occupied-capacity

或者在Cargo.toml中添加以下依赖项:

ckb-occupied-capacity = "0.202.0"

完整示例代码

以下是一个使用ckb-occupied-capacity计算CKB链上空间占用的完整示例:

use ckb_occupied_capacity::Capacity;
use ckb_types::{bytes::Bytes, core::Capacity as CoreCapacity};

fn main() {
    // 创建一个简单的数据示例
    let data = Bytes::from(vec![0u8; 100]);
    
    // 计算数据占用的容量
    let occupied_capacity = Capacity::bytes(data.len()).unwrap();
    
    // 转换为core::Capacity类型
    let core_capacity: CoreCapacity = occupied_capacity.into();
    
    println!("数据占用容量: {} shannons", core_capacity.as_u64());
    
    // 验证容量是否足够
    let available_capacity = CoreCapacity::shannons(200);
    if available_capacity >= core_capacity {
        println!("可用容量足够");
    } else {
        println!("可用容量不足");
    }
}

扩展示例代码

以下是一个更完整的示例,展示了如何处理不同类型的数据和容量计算:

use ckb_occupied_capacity::{Capacity, Error};
use ckb_types::{bytes::Bytes, core::Capacity as CoreCapacity, packed::Script};

fn main() -> Result<(), Error> {
    // 示例1: 计算字节数据的容量
    let data = Bytes::from(vec![1, 2, 3, 4, 5]);
    let data_capacity = Capacity::bytes(data.len())?;
    println!("5字节数据占用容量: {} shannons", data_capacity.as_u64());

    // 示例2: 计算脚本的容量
    let script = Script::default();
    let script_capacity = Capacity::bytes(script.as_bytes().len())?;
    println!("默认脚本占用容量: {} shannons", script_capacity.as_u64());

    // 示例3: 容量运算
    let total_capacity = data_capacity.safe_add(script_capacity)?;
    println!("总占用容量: {} shannons", total_capacity.as_u64());

    // 示例4: 容量验证
    let available = CoreCapacity::shannons(1000);
    if available >= total_capacity.into() {
        println!("容量验证通过");
    } else {
        println!("容量不足");
    }

    Ok(())
}

代码说明

  1. Capacity::bytes() 方法用于计算特定字节数数据占用的CKB容量
  2. 可以方便地在ckb_occupied_capacity::Capacityckb_types::core::Capacity之间转换
  3. 提供了安全的容量运算方法如safe_add,避免溢出
  4. 支持处理各种区块链数据类型如Script的容量计算
  5. 提供了完整的错误处理机制

该库遵循MIT许可证,是管理CKB链上空间占用的高效工具,特别适合需要精确计算和验证区块链存储空间的场景。


1 回复

Rust区块链容量计算库ckb-occupied-capacity使用指南

介绍

ckb-occupied-capacity是一个专门为Nervos CKB(Common Knowledge Base)区块链开发的Rust库,用于高效计算和管理链上空间(容量)占用情况。它提供了一套工具来验证交易和单元格(Cell)的容量占用,确保符合CKB网络规则。

主要功能

  • 计算交易和单元格的占用容量
  • 验证容量是否符合CKB网络要求
  • 支持各种CKB数据类型和结构
  • 提供精确的容量计算算法

安装方法

在Cargo.toml中添加依赖:

[dependencies]
ckb-occupied-capacity = "0.5.0"

基本使用方法

1. 计算单元格容量

use ckb_occupied_capacity::{Capacity, Result};

fn calculate_cell_capacity() -> Result<Capacity> {
    let data = vec![0u8; 100]; // 单元格数据
    let capacity = Capacity::bytes(data.len())?;
    Ok(capacity)
}

2. 验证交易容量

use ckb_occupied_capacity::{Capacity, Ratio};

fn verify_transaction_capacity(input_cap: u64, output_cap: u64) -> bool {
    let input_capacity = Capacity::shannons(input_cap);
    let output_capacity = Capacity::shannons(output_cap);
    
    // 确保输出不超过输入
    output_capacity <= input_capacity
}

3. 计算复杂交易容量

use ckb_types::{packed, prelude::*};
use ckb_occupied_capacity::Capacity;

fn calculate_transaction_occupied_capacity(tx: packed::Transaction) -> Result<Capacity, String> {
    let tx_size = tx.as_slice().len();
    Capacity::bytes(tx_size).map_err(|e| e.to_string())
}

高级用法

1. 计算带锁脚本的容量

use ckb_types::{packed, prelude::*};
use ckb_occupied capacity::Capacity;

fn calculate_cell_with_lock_script(
    lock_script: packed::Script,
    data: &[u8]
) -> Result<Capacity, String> {
    let lock_script_size = lock_script.as_slice().len();
    let total_size = lock_script_size + data.len();
    Capacity::bytes(total_size).map_err(|e| e.to_string())
}

2. 容量比例计算

use ckb_occupied_capacity::{Capacity, Ratio};

fn calculate_capacity_ratio(used: Capacity, total: Capacity) -> Ratio {
    used / total
}

实际应用示例

构建合规交易

use ckb_types::{packed, core::TransactionBuilder};
use ckb_occupied_capacity::Capacity;

fn build_valid_transaction(
    inputs: Vec<packed::CellInput>,
    outputs: Vec<packed::CellOutput>,
    outputs_data: Vec<bytes::Bytes>
) -> Result<packed::Transaction, String> {
    let tx = TransactionBuilder::default()
        .inputs(inputs)
        .outputs(outputs)
        .outputs_data(outputs_data)
        .build();
    
    // 验证输入容量是否足够
    let input_cap: Capacity = tx.input_capacities()?;
    let output_cap: Capacity = tx.output_capacities()?;
    
    if output_cap > input_cap {
        return Err("输出容量超过输入容量".to_string());
    }
    
    Ok(tx)
}

完整示例demo

以下是一个完整的CKB交易构建和容量验证示例:

use ckb_types::{
    packed::{self, CellInput, CellOutput, Script},
    prelude::*,
    bytes::Bytes,
    core::TransactionBuilder,
};
use ckb_occupied_capacity::{Capacity, Result as CapResult};

// 构建一个完整的CKB交易并进行容量验证
fn build_and_verify_transaction() -> Result<packed::Transaction, String> {
    // 1. 准备交易输入
    let input_cell = create_input_cell()?;
    
    // 2. 准备交易输出
    let output_cell = create_output_cell()?;
    
    // 3. 构建交易
    let tx = TransactionBuilder::default()
        .inputs(vec![input_cell.input])
        .outputs(vec![output_cell.output])
        .outputs_data(vec![output_cell.data])
        .build();
    
    // 4. 验证交易容量
    verify_transaction_capacity(&tx)?;
    
    Ok(tx)
}

// 创建输入单元格
fn create_input_cell() -> Result<CellInfo, String> {
    let lock_script = Script::default(); // 实际应用中替换为真实的锁脚本
    let data = Bytes::from(vec![0u8; 200]); // 单元格数据
    
    let output = CellOutput::new_builder()
        .capacity(Capacity::bytes(lock_script.as_slice().len() + data.len())?.pack())
        .lock(lock_script)
        .build();
    
    let input = CellInput::new(packed::OutPoint::default(), 0);
    
    Ok(CellInfo {
        input,
        output,
        data,
    })
}

// 创建输出单元格
fn create_output_cell() -> Result<CellInfo, String> {
    let lock_script = Script::default(); // 实际应用中替换为真实的锁脚本
    let data = Bytes::from(vec![0u8; 150]); // 单元格数据
    
    let output = CellOutput::new_builder()
        .capacity(Capacity::bytes(lock_script.as_slice().len() + data.len())?.pack())
        .lock(lock_script)
        .build();
    
    Ok(CellInfo {
        input: CellInput::default(),
        output,
        data,
    })
}

// 验证交易容量
fn verify_transaction_capacity(tx: &packed::Transaction) -> CapResult<()> {
    let inputs_cap: Capacity = tx.input_capacities()?;
    let outputs_cap: Capacity = tx.output_capacities()?;
    
    if outputs_cap > inputs_cap {
        return Err(anyhow::anyhow!("输出容量超过输入容量"));
    }
    
    // 验证每个单元格满足最小容量要求
    for (i, output) in tx.outputs().into_iter().enumerate() {
        let output_data = tx.outputs_data().get(i).unwrap_or_default();
        let occupied = Capacity::bytes(output.as_slice().len() + output_data.len())?;
        let provided = Capacity::shannons(output.capacity().unpack());
        
        if provided < occupied {
            return Err(anyhow::anyhow!("单元格{}容量不足", i));
        }
    }
    
    Ok(())
}

// 辅助结构体
struct CellInfo {
    input: CellInput,
    output: CellOutput,
    data: Bytes,
}

fn main() {
    match build_and_verify_transaction() {
        Ok(tx) => println!("交易构建成功: {:?}", tx),
        Err(e) => eprintln!("交易验证失败: {}", e),
    }
}

注意事项

  1. 容量计算必须精确到字节级别
  2. CKB的最小容量单位是Shannon (1 CKB = 100,000,000 Shannon)
  3. 所有单元格必须满足最小容量要求
  4. 交易费也需要从输入容量中扣除

性能建议

  • 对于批量计算,考虑使用缓存机制
  • 在频繁计算的场景下,可以预计算固定结构的容量
  • 使用Capacity类型而不是原始u64来避免单位混淆

这个库是开发CKB dApp和智能合约的重要工具,能确保你的应用符合CKB网络容量规则,避免交易被拒绝。

回到顶部