为什么使用 <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正好是输入输出。因此,当您没有任何此类花哨的逻辑并希望直接使所有 StaticLookupAccountId 完全相同时,这就是您想要使用的:

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 }
}