Rust地址处理库cw-address-like的使用:支持类地址字符串的高效解析与验证
Rust地址处理库cw-address-like的使用:支持类地址字符串的高效解析与验证
CW Address Like
这个crate提供了一个AddressLike
trait,用于标记可以在CosmWasm中作为地址使用的类型,即String
和cosmwasm_std::Addr
。
背景
在CosmWasm中,通常有两种类型用于表示地址:
String
- 表示一个未验证的地址,用于合约API中,如消息和查询响应cosmwasm_std::Addr
- 表示一个验证过的地址,用于合约内部逻辑
当合约从消息中接收到一个地址(作为String
)时,不能简单地假设它是有效的。相反,应该使用deps.api.addr_validate
方法进行验证,该方法返回一个Addr
。然后合约可以在业务逻辑中使用这个Addr
或者将其保存在存储中。
同样,当在查询响应中返回地址时,合约也应该将Addr
转换回String
。
问题
当我们需要定义一个既用于API又用于内部逻辑的结构体或枚举时,问题就出现了。例如,考虑一个合约在其存储中保存一个"config",其中使用Addr
来表示合约所有者的地址,同时也提供一个查询方法来获取配置,该方法使用String
。
在这种情况下,开发者可能有两种做法:
第一种是定义两种类型,每种情况一种:
struct Config {
pub owner: Addr,
}
struct ConfigResponse {
pub owner: String,
}
这种方法可行,但当配置包含更多字段时会有些繁琐。
另一种方法是定义一个包含泛型的单一类型:
struct Config<T> {
pub owner: T,
}
然后在API中使用Config<String>
,在内部逻辑中使用Config<Addr>
。
这种方法的主要缺点是T
没有限制。理论上,任何类型都可以作为T
插入,不限于String
和Addr
。
如何使用
在这个crate中我们提供了一个AddressLike
trait,它简单地定义为:
pub trait AddressLike {}
impl AddressLike for Addr {}
impl AddressLike for String {}
开发者可以这样定义他们的类型:
struct Config<T: AddressLike> {
pub owner: T,
}
这样就限制了只有String
和Addr
可以用作T
。
完整示例
下面是一个完整的使用示例:
use cw_address_like::AddressLike;
use cosmwasm_std::Addr;
// 定义一个通用的配置结构体
struct Config<T: AddressLike> {
pub owner: T,
pub admin: T,
pub description: String,
}
// 用于存储的内部配置
struct StorageConfig {
config: Config<Addr>,
}
// 用于查询响应的配置
struct QueryConfig {
config: Config<String>,
}
impl StorageConfig {
pub fn new(owner: Addr, admin: Addr, description: String) -> Self {
Self {
config: Config {
owner,
admin,
description,
}
}
}
// 将存储配置转换为查询配置
pub fn to_query(&self) -> QueryConfig {
QueryConfig {
config: Config {
owner: self.config.owner.to_string(),
admin: self.config.admin.to_string(),
description: self.config.description.clone(),
}
}
}
}
// 合约消息处理示例
fn handle_message(
deps: DepsMut,
owner: String, // 从消息中接收的未验证地址
admin: String, // 从消息中接收的未验证地址
description: String,
) -> Result<Response, ContractError> {
// 验证地址
let owner_addr = deps.api.addr_validate(&owner)?;
let admin_addr = deps.api.addr_validate(&admin)?;
// 创建存储配置
let config = StorageConfig::new(owner_addr, admin_addr, description);
// 存储配置...
Ok(Response::new())
}
// 合约查询处理示例
fn handle_query(
deps: Deps,
) -> Result<QueryConfig, ContractError> {
// 从存储中读取配置
let storage_config = read_config_from_storage(deps.storage)?;
// 转换为查询配置
Ok(storage_config.to_query())
}
许可证
此crate在版本1.0.3或之前的内容发布在GNU Affero General Public License v3或更高版本下;该版本之后的内容发布在Apache-2.0许可证下。
Rust地址处理库 cw-address-like
使用指南
cw-address-like
是一个专门用于处理类地址字符串的Rust库,提供高效的解析和验证功能,特别适合区块链地址、哈希值等类地址格式的处理。
主要特性
- 轻量级高性能的地址解析
- 灵活的验证规则配置
- 支持多种编码格式(Base16, Base58, Bech32等)
- 提供标准化的地址格式化输出
安装方法
在Cargo.toml
中添加依赖:
[dependencies]
cw-address-like = "0.3.0"
基本使用方法
1. 简单验证地址
use cw_address_like::AddressLike;
fn main() {
let addr = "cosmos1hsk6jryyqjfhp5dhc55tc9jtckygx0eph6dd02";
if addr.is_address_like() {
println!("有效的类地址字符串");
} else {
println!("无效的地址格式");
}
}
2. 带前缀的地址验证
use cw_address_like::{AddressLike, Prefix};
fn main() {
let addr = "cosmos1hsk6jryyqjfhp5dhc55tc9jtckygx0eph6dd02";
let prefix = Prefix::new("cosmos");
match addr.validate_with_prefix(&prefix) {
Ok(_) => println!("地址格式和前缀都有效"),
Err(e) => println!("验证失败: {}", e),
}
}
3. 解析地址获取详细信息
use cw_address_like::AddressLike;
fn main() {
let addr = "0x71C7656EC7ab88b098defB751B7401B5f6d8976F";
if let Some(info) = addr.parse_address_like() {
println!("地址类型: {:?}", info.address_type());
println!("原始数据: {:?}", info.raw_data());
println!("格式化输出: {}", info.to_string());
}
}
高级用法
自定义验证规则
use cw_address_like::{AddressLike, ValidationOptions};
fn main() {
let options = ValidationOptions::new()
.with_min_length(20)
.with_max_length(40)
.with_allowed_chars("0123456789abcdefABCDEF");
let addr = "0x1a2b3c4d5e";
match addr.validate_with_options(&options) {
Ok(_) => println!("符合自定义验证规则"),
Err(e) => println!("验证失败: {}", e),
}
}
Bech32地址处理
use cw_address_like::{Bech32Address, Prefix};
fn main() {
let prefix = Prefix::new("cosmos");
let addr = Bech32Address::new(
"cosmos1hsk6jryyqjfhp5dhc55tc9jtckygx0eph6dd02",
&prefix
).unwrap();
println!("HRP: {}", addr.hrp());
println!("数据部分: {:?}", addr.data());
}
性能提示
对于批量地址验证,建议使用AddressLikeBatchValidator
以提高性能:
use cw_address_like::{AddressLikeBatchValidator, Prefix};
fn main() {
let prefix = Prefix::new("cosmos");
let mut validator = AddressLikeBatchValidator::new().with_prefix(&prefix);
let addresses = vec![
"cosmos1hsk6jryyqjfhp5dhc55tc9jtckygx0eph6dd02",
"cosmos1invalidaddress",
"cosmos1anothervalidone",
];
let results = validator.validate_all(&addresses);
for (addr, result) in addresses.iter().zip(results.iter()) {
println!("{}: {}", addr, if *result { "有效" } else { "无效" });
}
}
完整示例
下面是一个完整的示例,展示了如何使用cw-address-like
库进行地址的创建、验证和解析:
use cw_address_like::{
AddressLike,
Prefix,
Bech32Address,
ValidationOptions,
AddressLikeBatchValidator
};
fn main() {
// 1. 简单地址验证
let cosmos_addr = "cosmos1hsk6jryyqjfhp5dhc55tc9jtckygx0eph6dd02";
println!("验证地址 {}: {}", cosmos_addr, cosmos_addr.is_address_like());
// 2. 带前缀的地址验证
let prefix = Prefix::new("cosmos");
match cosmos_addr.validate_with_prefix(&prefix) {
Ok(_) => println!("前缀验证通过"),
Err(e) => println!("前缀验证失败: {}", e),
}
// 3. 解析以太坊地址
let eth_addr = "0x71C7656EC7ab88b098defB751B7401B5f6d8976F";
if let Some(info) = eth_addr.parse_address_like() {
println!("解析以太坊地址成功:");
println!("类型: {:?}", info.address_type());
println!("原始数据: {:?}", info.raw_data());
}
// 4. 自定义验证规则
let options = ValidationOptions::new()
.with_min_length(20)
.with_max_length(40)
.with_allowed_chars("0123456789abcdefABCDEF");
let test_addr = "0x1a2b3c4d5e";
match test_addr.validate_with_options(&options) {
Ok(_) => println!("自定义规则验证通过"),
Err(e) => println!("自定义规则验证失败: {}", e),
}
// 5. Bech32地址处理
let bech32_addr = Bech32Address::new(cosmos_addr, &prefix).unwrap();
println!("Bech32地址解析:");
println!("HRP: {}", bech32_addr.hrp());
println!("数据: {:?}", bech32_addr.data());
// 6. 批量验证
let mut validator = AddressLikeBatchValidator::new().with_prefix(&prefix);
let addresses = vec![
"cosmos1hsk6jryyqjfhp5dhc55tc9jtckygx0eph6dd02",
"cosmos1invalidaddress",
"cosmos1anothervalidone",
];
let results = validator.validate_all(&addresses);
for (addr, result) in addresses.iter().zip(results.iter()) {
println!("地址 {} 验证结果: {}", addr, if *result { "有效" } else { "无效" });
}
}
这个完整示例演示了cw-address-like
库的主要功能,包括地址验证、前缀检查、地址解析、自定义规则验证、Bech32地址处理以及批量验证等功能。