#big-integer #near #near-protocol #type #state #big-int #compatible

near-bigint

兼容 NEAR 协议状态 trie 序列化和 serde 序列化的大整数类型

2 个稳定版本

1.0.1 2022 年 12 月 1 日

#5#near-protocol

Download history 29/week @ 2024-03-30 8/week @ 2024-04-06

66 每月下载次数
用于 3 crates

MIT 许可证

14KB
133

near-bigint

Rust 库,用于 NEAR 协议智能合约开发中的大整数类型。

使用场景

NEAR 区块链中的智能合约受原生 rust 数据类型的限制。这意味着开发者可以使用 u128 类型表示最多 128 位的整数。

然而,在处理区块链金融应用时,可能需要表示更大的数字。例如,以太坊生态系统中的 solidity 语言支持原生 256 位,如果天真地将 solidity 应用程序转换为 NEAR,很容易导致整数溢出错误。

解决此问题的常用方法是将实现大整数算术的知名 rust 包作为依赖项,以实现更大整数类型,例如 uint

这些库运行良好,并允许开发者在 NEAR 智能合约应用程序中安全地使用大整数算术,但它们缺少在 NEAR 环境中工作所需的便捷性。这些所需功能包括

  1. Borsh 序列化和反序列化 -> 允许直接将值存储到区块链的状态中,而无需将其转换为二进制表示
  2. Serde 序列化和反序列化 -> 允许将值作为调用智能合约中公共方法时的函数参数传递
  3. StorageKey 序列化 -> 允许将值用作区块链 trie 中的键

我们选择在 uint 库之上实现这些功能,该库被 NEAR 的顶级项目(如 ref.finance)使用。除了实现上述功能外,我们还添加了更便捷的 API

  1. 将大整数格式转换为 u128,如果数字不合适则 panic
  2. 将大整数格式转换为小端或大端字节
  3. 为大整数初始化生成空缓冲区值

如何使用

有两种方法可以使用此库

  1. 导入预构建的类型
  2. 导入宏以构建任何大小的 Big Integer 类型

该库默认导出 256、384、512、640、768、896 和 1024 位大整数类型。

use near_bigint::{U256, U384, U512, /* ... */};

如果您需要一个不同位大小的类型,可以使用construct_near_bigint宏来构建。这允许您构建任何大小为64位倍数的类型。

use near_bigint::construct_near_bigint;

/// You need to declare a name for the type you're creating - U{bit size} is recommended
/// You also need to declare the intended bit size (as a multiple of 64)
/// construct_near_bigint!(pub struct {type name}({multiple of 64 bitsize}););

construct_near_bigint!(pub struct U2048(32););
construct_near_bigint!(pub struct U192(3););

let u2048_var = U2048::from_dec_str("100").unwrap();
let u192_var = U192::from_dec_str("100").unwrap();

API和示例

使用此库构建的所有类型都继承自uint库的API。这可以在其文档中找到,此处不再重复。

所有近大整数类型都是borsh可序列化和反序列化的,这意味着您可以直接将它们存储到合约的状态中

use near_sdk::{env, near_bindgen, PanicOnDefault, AccountId, BorshStorageKey, Promise};
use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::collections::{LookupSet};
use near_bigint::U256;

#[near_bindgen]
#[derive(PanicOnDefault, BorshDeserialize, BorshSerialize)]
pub struct Contract {
  pub owner: AccountId,
  pub guardian: LookupSet<AccountId>,
  pub deposit_value: U256,
  pub deposited_valeus: LookupSet<U256>,
}

类型也可以作为serde可序列化和反序列化的,这意味着它们可以用作公共方法中的参数或返回类型。然后,最终用户必须在他们的前端应用程序中将值作为字符串传递(与near_sdk::json_types::{U128, U64}的工作方式相同)。

use near_sdk::{env, near_bindgen, PanicOnDefault, AccountId, BorshStorageKey, Promise};
use near_bigint::U256;
use crate::Contract;

#[near_bindgen]
impl Contract {

    pub fn public_method(&mut self, number: U256) {
        self.deposit_value = number;
    }

}

最后,类型也可以用作trie中的存储键

use near_sdk::{env, near_bindgen, PanicOnDefault, AccountId, BorshStorageKey, Promise};
use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::collections::{LookupMap};
use near_bigint::U256;

#[near_bindgen]
#[derive(PanicOnDefault, BorshDeserialize, BorshSerialize)]
pub struct Contract {
  pub owner: AccountId,
  /// Bigint used as storage key here
  pub map: LookupMap<U256, AccountId>,
}

#[near_bindgen]
impl Contract {
  #[init]
  pub fn new(
    owner: AccountId,
    initial_key: U256
  ) -> Self {
    assert!(!env::state_exists(), "Already initialized");
    assert!(
      env::is_valid_account_id(owner.as_bytes()),
      "Invalid owner account"
    );

    /// Bigint used as storage key here
    let mut map = LookupMap::new(initial_key);

    /// Bigint used as storage key here
    map.insert(&U256::from_dec_str("0").unwrap(), &owner);

    Self {
      owner,
      map,
    };
  }
}

还实现了一些实用工具来提高效率

use near_bigint::U256;

let sample_var = U256::from_dec_str("5165164138").unwrap();

/// Convert to big endian bytes
let big_endian: [u8; 256] = sample_var.to_be_bytes();

/// Convert to little endian bytes
let little_endian: [u8; 256] = sample_var.to_le_bytes();

/// Get bytes equivalent to 0 value
let 0_bytes: [u8; 256] = U256::empty_buffer();

/// Convert to u128 (panics in case big number overflows 128 bits)
let 128_bits: u128 = sample_var.as_u128(); 

支持的near-sdk版本

near-bigint建立在near-sdk 4.0.0之上,并将定期更新以反映near-sdk的更新。以前的near-sdk版本与此库不兼容。

依赖项

约5.5MB
约107K SLoC