为什么使用 <T::Lookup as StaticLookup>::Source 而不是普通的 T::AccountId?
Why use <T::Lookup as StaticLookup>::Source instead of plain T::AccountId?
根据此 PR,所有可调度调用都应使用 <T::Lookup as StaticLookup>::Source
而不是 T::AccountId
。为什么用查询处理转账比用用户的账户来处理转账更好? Substrate 中的查找是如何工作的,是否有 StaticLookup
的替代方法?
最后,除了 IdentityLookup
还有其他类型吗?您会如何使用它们?
type Lookup = IdentityLookup<AccountId>;
StaticLookup 是对地址的抽象,可以将多个不同的地址类型转换为基础 AccountId。
想象一个仅使用 AccountId 的外部函数。与该功能交互的唯一方法是为链上帐户提供原始 AccountId。
相反,使用 StaticLookup,您可以提供任何兼容的地址格式,并且会有额外的逻辑用于将该地址转换为基础帐户。
想象一下:
enum Address {
AccountId([u8; 32]), // 32 byte account id
String(Vec<u8>), // arbitrary string
}
这是一个实际示例,说明您将如何允许人们在您的链上使用名称服务。例如你可以这样做:
transfer(b"shawntabrizi", 100 UNIT)
除了:
transfer(5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY, 100 UNIT)
StaticLookup 将包含任何适当的代码以将已知格式转换为您需要的最终 AccountId。
想象一下下面的代码:
struct NameServiceLookup;
impl StaticLookup for NameServiceLookup {
type Source = Address;
type Target = AccountId;
fn lookup(a: Address) -> Result<AccountId, LookupError> {
match a {
Address::AccountId(id) => Ok(id),
Address::String(string) => {
string_to_account_id(string).ok_or(LookupError)
},
}
}
fn unlookup(a: [u8; 32]) -> Address {
Address::AccountId(a)
}
}
在这里你可以看到我们有特殊的逻辑来处理地址,如果它是一个 AccountId 或一个字符串。这就是 StaticLookup
最终会提供的。
IdentityLookup
的实现是一个简单的直通,returns正好是输入输出。因此,当您没有任何此类花哨的逻辑并希望直接使所有 StaticLookup
与 AccountId
完全相同时,这就是您想要使用的:
pub struct IdentityLookup<T>(PhantomData<T>);
impl<T: Codec + Clone + PartialEq + Debug> StaticLookup for IdentityLookup<T> {
type Source = T;
type Target = T;
fn lookup(x: T) -> Result<T, LookupError> { Ok(x) }
fn unlookup(x: T) -> T { x }
}
根据此 PR,所有可调度调用都应使用 <T::Lookup as StaticLookup>::Source
而不是 T::AccountId
。为什么用查询处理转账比用用户的账户来处理转账更好? Substrate 中的查找是如何工作的,是否有 StaticLookup
的替代方法?
最后,除了 IdentityLookup
还有其他类型吗?您会如何使用它们?
type Lookup = IdentityLookup<AccountId>;
StaticLookup 是对地址的抽象,可以将多个不同的地址类型转换为基础 AccountId。
想象一个仅使用 AccountId 的外部函数。与该功能交互的唯一方法是为链上帐户提供原始 AccountId。
相反,使用 StaticLookup,您可以提供任何兼容的地址格式,并且会有额外的逻辑用于将该地址转换为基础帐户。
想象一下:
enum Address {
AccountId([u8; 32]), // 32 byte account id
String(Vec<u8>), // arbitrary string
}
这是一个实际示例,说明您将如何允许人们在您的链上使用名称服务。例如你可以这样做:
transfer(b"shawntabrizi", 100 UNIT)
除了:
transfer(5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY, 100 UNIT)
StaticLookup 将包含任何适当的代码以将已知格式转换为您需要的最终 AccountId。
想象一下下面的代码:
struct NameServiceLookup;
impl StaticLookup for NameServiceLookup {
type Source = Address;
type Target = AccountId;
fn lookup(a: Address) -> Result<AccountId, LookupError> {
match a {
Address::AccountId(id) => Ok(id),
Address::String(string) => {
string_to_account_id(string).ok_or(LookupError)
},
}
}
fn unlookup(a: [u8; 32]) -> Address {
Address::AccountId(a)
}
}
在这里你可以看到我们有特殊的逻辑来处理地址,如果它是一个 AccountId 或一个字符串。这就是 StaticLookup
最终会提供的。
IdentityLookup
的实现是一个简单的直通,returns正好是输入输出。因此,当您没有任何此类花哨的逻辑并希望直接使所有 StaticLookup
与 AccountId
完全相同时,这就是您想要使用的:
pub struct IdentityLookup<T>(PhantomData<T>);
impl<T: Codec + Clone + PartialEq + Debug> StaticLookup for IdentityLookup<T> {
type Source = T;
type Target = T;
fn lookup(x: T) -> Result<T, LookupError> { Ok(x) }
fn unlookup(x: T) -> T { x }
}