ICAP: 互換客戶端地址協(xié)議

什么是ICAP?從以太坊Homestead指南的詞匯表中可以看出:

Interexchange Client Address Protocol, an IBAN-compatible system for referencing and transacting to client accounts aimed to streamline the process of transferring funds, worry-free between exchanges and, ultimately, making KYC and AML concerns a thing of the past.

ICAP 互換客戶端地址協(xié)議,一種IBAN兼容系統(tǒng),用于引用和處理客戶帳戶,旨在簡(jiǎn)化資金轉(zhuǎn)移流程,在交易所之間無(wú)憂無(wú)慮,并最終使KYC和AML成為過(guò)去。

這里有相關(guān)于以太坊對(duì)ICAP的介紹

在第三方賬戶之間(特別是交易所賬戶)之間轉(zhuǎn)賬資金給用戶帶來(lái)了相當(dāng)大的負(fù)擔(dān),并且由于客戶賬戶中的存款被識(shí)別的方式而容易出錯(cuò)?,F(xiàn)有的銀行業(yè)通過(guò)擁有一個(gè)被稱(chēng)為IBAN的通用代碼解決了這個(gè)問(wèn)題。該代碼合并了機(jī)構(gòu)和客戶帳戶以及錯(cuò)誤檢測(cè)機(jī)制,實(shí)際上消除了微不足道的錯(cuò)誤并為用戶提供了相當(dāng)大的便利。不幸的是,這是一個(gè)嚴(yán)格監(jiān)管和集中的服務(wù),只有大型的,完善的機(jī)構(gòu)才能使用。目前的議定書(shū)ICAP可被視為適用于以太坊系統(tǒng)中任何含有資金的機(jī)構(gòu)的分散版本。

IBAN介紹

國(guó)際銀行賬戶號(hào)碼[1] (International Bank Account Number,簡(jiǎn)稱(chēng)IBAN)是各國(guó)各銀行之間互相定立的標(biāo)識(shí)號(hào)碼,可降低國(guó)際間金融操作的失誤。它最初是由歐洲銀行標(biāo)準(zhǔn)委員會(huì)(ECBS)通過(guò),后來(lái)被采納為國(guó)際標(biāo)準(zhǔn) ISO 13616:1997。目前的標(biāo)準(zhǔn)是ISO 13616:2007,表明SWIFT代碼(ISO 9362)為正式的格式。最初開(kāi)發(fā)是為了促進(jìn)歐盟范圍內(nèi)的支付,但現(xiàn)在也已經(jīng)實(shí)施到大多數(shù)歐洲國(guó)家和其他國(guó)家,尤其是在中東加勒比海地區(qū)。IBAN最多包含34個(gè)字母和數(shù)字字符:首兩個(gè)字母是ISO 3166-1α-2國(guó)家代碼,然后兩個(gè)校驗(yàn)位,校驗(yàn)位可檢查完整性。最后一個(gè)是特定國(guó)家的基本銀行賬戶號(hào)碼(BBAN)。BBAN格式的決定是由每個(gè)國(guó)家的銀行界的約束下,它必須是一個(gè)固定長(zhǎng)度的不區(qū)分大小寫(xiě)的英數(shù)字。它包括國(guó)內(nèi)銀行賬戶號(hào)碼,銀行分行的號(hào)碼,和潛在的路由信息。

基本銀行賬戶號(hào)碼

基本銀行賬戶號(hào)碼(The Basic Bank Account Number,簡(jiǎn)稱(chēng)BBAN)的格式是由國(guó)家中央銀行或相應(yīng)機(jī)關(guān)所訂定,格式并沒(méi)有強(qiáng)制性。一國(guó)的基本銀行賬戶號(hào)碼須為固定長(zhǎng)度且由大小寫(xiě)不敏感的英數(shù)字組成。其包括本國(guó)賬戶號(hào)碼,子分支辨識(shí)碼與路徑資訊。各國(guó)皆可擁有不同的編號(hào)系統(tǒng),最多三十字。

IBAN結(jié)構(gòu)

IBAN代碼由多達(dá)34個(gè)不區(qū)分大小寫(xiě)的字母數(shù)字字符組成,其字符取值范圍為0-9和A-Z。它包含三個(gè)信息:

  • 國(guó)家代碼; 以下內(nèi)容的頂級(jí)標(biāo)識(shí)符(ISO 3166-1 alpha-2);
  • 錯(cuò)誤檢測(cè)代碼; 使用mod-97-10校驗(yàn)和協(xié)議(ISO / IEC 7064:2003);
  • 基本銀行賬號(hào)(BBAN); 該機(jī)構(gòu),分支和客戶賬戶的標(biāo)識(shí)符,其組成取決于上述國(guó)家。

舉例來(lái)說(shuō),從維基百科可以得知,英國(guó)的IBAN格式定義為:

國(guó)家 格式 說(shuō)明
英國(guó)???? GBkk bbbb ssss sscc cccc cc b = 銀行代碼 s = 銀行分類(lèi)代碼 c = 賬號(hào)

GBkk bbbb ssss sscc cccc cc 格式解讀為:

[國(guó)家代碼:GB][錯(cuò)誤校驗(yàn)碼:kk][基本銀行賬號(hào):bbbb ssss sscc cccc cc]

對(duì)于英國(guó)來(lái)說(shuō),BBAN由以下部分組成:

  • 機(jī)構(gòu)標(biāo)識(shí)符,4個(gè)字符的字母,例如 MIDL 代表匯豐銀行。
  • 分類(lèi)代碼(機(jī)構(gòu)內(nèi)的分行標(biāo)識(shí)符),一個(gè)6位十進(jìn)制數(shù)字,例如402702匯豐銀行的Lancaster分行。
  • 帳號(hào)(分支機(jī)構(gòu)內(nèi)的客戶標(biāo)識(shí)符),一個(gè)8位十進(jìn)制數(shù)字。

以太坊ICAP設(shè)計(jì)

以太坊引入了新的IBAN國(guó)家代碼:XE,X前綴為擴(kuò)展的意思,E表示為以太坊(Ethereum),制定為非法定貨幣(例如XBOX, XEOS)。以太坊在IBAN基礎(chǔ)上設(shè)計(jì)了ICAP,其設(shè)計(jì)思路與IBAN兼容。目的是為了方便各大公鏈之間轉(zhuǎn)賬?它有三種BBAN代碼類(lèi)型:直接類(lèi)型,基本類(lèi)型和間接類(lèi)型。

直接類(lèi)型

此代碼的直接BBAN為30個(gè)字符,將包含一個(gè)字段:

  • 帳戶標(biāo)識(shí)符,30個(gè)字母數(shù)字(<155位)。這將被解釋為表示160位以太坊地址的最低有效位的大端編碼的36進(jìn)制整數(shù)。因此,這些以太坊地址通常以零字節(jié)開(kāi)始。

例如XE 73 38O073KYGTWWZN0F2WZ0R8PX5ZPPZS,它的對(duì)應(yīng)的地址00c5496aee77c1ba1f0854206a26dda82a81d6d8。

基本類(lèi)型

與直接編碼相同,但代碼為31個(gè)字符(與IBAN不兼容)并組成相同的單個(gè)字段:

  • 帳戶標(biāo)識(shí)符,31個(gè)字符字母數(shù)字(<161位)。這將被解釋為一個(gè)代表160位以太坊地址的大端編碼的36進(jìn)制整數(shù)。

間接類(lèi)型

該代碼的BBAN在間接時(shí)將為16個(gè)字符,并將包含三個(gè)字段:

  • 資產(chǎn)標(biāo)識(shí)符,3個(gè)字符的字母數(shù)字(<16位);
  • 機(jī)構(gòu)標(biāo)識(shí)符,4個(gè)字符的字母數(shù)字(<21位);
  • 機(jī)構(gòu)客戶標(biāo)識(shí)符,9個(gè)字符的字母數(shù)字(<47位);

包括四個(gè)首字符,這導(dǎo)致最終的客戶帳戶地址長(zhǎng)度為20個(gè)字符,格式為:

XE81ETHXREGGAVOFYORK

分成:

  • XE 以太坊的國(guó)家代碼;
  • 81 校驗(yàn)和;
  • ETH 客戶賬戶中的資產(chǎn)標(biāo)識(shí)符 - 在這種情況下,“ETH”是唯一有效的資產(chǎn)標(biāo)識(shí)符,因?yàn)橐蕴坏幕A(chǔ)注冊(cè)管理機(jī)構(gòu)合同僅支持該資產(chǎn);
  • XREG 賬戶的機(jī)構(gòu)代碼 - 在這種情況下,以太坊的基礎(chǔ)注冊(cè)管理機(jī)構(gòu)合同;
  • GAVOFYORK 該機(jī)構(gòu)內(nèi)的客戶標(biāo)識(shí)符 - 在這種情況下,直接支付且無(wú)任何主要地址的額外數(shù)據(jù)與以太坊基礎(chǔ)注冊(cè)合同中的名稱(chēng)“GAVOFYORK”相關(guān)聯(lián);

URI表示形式

iban:XE7338O073KYGTWWZN0F2WZ0R8PX5ZPPZS

具體實(shí)現(xiàn):以太坊地址轉(zhuǎn)換成ICAP格式

轉(zhuǎn)換函數(shù)

//ConvertAddressToICAP 將以太坊地址轉(zhuǎn)換為ICAP格式的地址
func ConvertAddressToICAP(a common.Address) (string, error) {
    enc := base36Encode(a.Big())
    if len(enc) < 30 {
        enc = join(strings.Repeat("0", 30-len(enc)), enc)
    }
    // 以太坊國(guó)家代碼XE + 校驗(yàn)碼 + 賬號(hào)
    icap := join("XE", checkDigits(enc), enc)
    return icap, nil
}

36進(jìn)制編碼

其規(guī)則如同十進(jìn)制數(shù)轉(zhuǎn)十六進(jìn)制數(shù),其算法如下:

十六進(jìn)制數(shù)取值范圍表示s="0123456789ABCDEF"。其字符串?dāng)?shù)組下標(biāo)范圍為0-15,其中對(duì)應(yīng)的下標(biāo):A=11,B=12… F=15。

記余數(shù)數(shù)組a,

  1. 把10進(jìn)制數(shù)除以16,獲取整數(shù)商和余數(shù),記下余數(shù)和整數(shù)商,并把余數(shù)放入余數(shù)數(shù)組a;
  2. 整數(shù)商不為0時(shí),再次執(zhí)行第一個(gè)步驟,整數(shù)商為0時(shí)停止,并記錄下此時(shí)的余數(shù);
  3. 倒排余數(shù)數(shù)組a,同時(shí)影射每個(gè)位置值到s字符串?dāng)?shù)組下標(biāo)對(duì)應(yīng)的值。

例如:十進(jìn)制數(shù)505,500/16 得31余9,將9放入余數(shù)數(shù)組a,由于31不為0,再次用31/16 得1余15,將15放入a,1不為0,再次用1/16 得0余1,將1放入a,倒排a,得[s[1],s[15],s[9]] = ['1', 'F', '9'] = "0x1F9" = 505。

36進(jìn)制編碼也是采用了如上算法,只是s="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"。

var (
    Base36Chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    Big36 = big.NewInt(36)
)
func base36Encode(i *big.Int) string {
    var chars []rune
    x := new(big.Int)
    for {
        x.Mod(i, Big36)
        chars = append(chars, rune(Base36Chars[x.Uint64()]))
        i.Div(i, Big36)
        if i.Cmp(Big0) == 0 {
            break
        }
    }
    // reverse slice
    for i, j := 0, len(chars)-1; i < j; i, j = i+1, j-1 {
        chars[i], chars[j] = chars[j], chars[i]
    }
    return string(chars)
}

校驗(yàn)碼

校驗(yàn)碼使用了mod-97-10校驗(yàn)和協(xié)議 (ISO / IEC 7064:2003),查看ISO具體協(xié)議需要8,800瑞士法郎。

舉例,對(duì)于字符串794,其算法步驟為:

步驟1:追加兩個(gè)零占據(jù)校驗(yàn)字符位置:79400;
步驟2:除以97,得到商818和整數(shù)余數(shù)54;
步驟3:將校驗(yàn)字符值確定為(97 + 1) - 54 = 44并將其附加到原始字符串以給出79444。

為了檢查,將字符串除以97; 如果提醒是1,則校驗(yàn)通過(guò)。

計(jì)算國(guó)際銀行帳號(hào)(IBAN)的校驗(yàn)位(xx yyy zzzzzzzz kk)

  • 余數(shù)不等于0的計(jì)算。

不包括支票號(hào)碼的銀行賬號(hào):06 000 01234567。

a:06 000 01234567 00
b:060000123456700:97 = 618557973780余數(shù)= 40
c:(97 + 1) - 40 = 58結(jié)果:06 000 01234567 58

校驗(yàn)和:06000123456758:97 = 618557973781其余= 1

  • 無(wú)余數(shù)計(jì)算或余數(shù)等于0。

不包括支票號(hào)碼的銀行賬號(hào):06 000 01234586。

a:06 000 01234586 00
b:060000123458600:97 = 618557973800其余= 00
c:(97 + 1) - 00 = 98結(jié)果:06 000 01234586 98。

校驗(yàn)和:06000123458698:97 = 618557973801余數(shù)= 1。

func checkDigits(s string) string {
    expanded, _ := iso13616Expand(strings.Join([]string{s, "XE00"}, ""))
    num, _ := new(big.Int).SetString(expanded, 10)
    //mod-97-10
    num.Sub(Big98, num.Mod(num, Big97))

    checkDigits := num.String()
    // zero padd checksum
    if len(checkDigits) == 1 {
        checkDigits = join("0", checkDigits)
    }
    return checkDigits
}

// not base-36, but expansion to decimal literal: A = 10, B = 11, ... Z = 35
func iso13616Expand(s string) (string, error) {
    var parts []string
    if !validBase36(s) {
        return "", errICAPEncoding
    }
    for _, c := range s {
        i := uint64(c)
        if i >= 65 {
            //字符A-Z在ASCII碼表中分別對(duì)應(yīng)10進(jìn)制值為65,66...
            //字符A-Z的36進(jìn)制字符串索引分別是A=10,B=11...
            //字符的碼表值-字符的索引值=55
            //字符碼表值-55=字符的索引值
            parts = append(parts, strconv.FormatUint(uint64(c)-55, 10))
        } else {
            parts = append(parts, string(c))
        }
    }
    return join(parts...), nil
}

具體實(shí)現(xiàn):ICAP格式轉(zhuǎn)換成以太坊地址

校驗(yàn)

func validCheckSum(s string) error {
    s = join(s[4:], s[:4])
    expanded, err := iso13616Expand(s)
    if err != nil {
        return err
    }
    checkSumNum, _ := new(big.Int).SetString(expanded, 10)
    if checkSumNum.Mod(checkSumNum, Big97).Cmp(Big1) != 0 {
        return errICAPChecksum
    }
    return nil
}

轉(zhuǎn)換

func parseICAP(s string) (common.Address, error) {
    if !strings.HasPrefix(s, "XE") {
        return common.Address{}, errICAPCountryCode
    }
    if err := validCheckSum(s); err != nil {
        return common.Address{}, err
    }
    // checksum is ISO13616, Ethereum address is base-36
    bigAddr, _ := new(big.Int).SetString(s[4:], 36)
    return common.BigToAddress(bigAddr), nil
}

用途

imToken錢(qián)包二維碼使用了ICAP格式,掃碼之后出現(xiàn)的格式為:

iban:XE86G29C8IV34UOJMYWHGDSGME33YKEC3QO?account=100&type=ETH

其中XE86G29C8IV34UOJMYWHGDSGME33YKEC3QO是轉(zhuǎn)賬的地址,account是轉(zhuǎn)賬的數(shù)額,type是轉(zhuǎn)賬的類(lèi)型,這里代表轉(zhuǎn)ETH。

BOX將兼容imToken格式。

完整的代碼片段可以在這里找到:https://gist.github.com/alphaqiu/646d45fc5c2b1f42d8529d55b52f58d2

參考

1.) Wikipedia: International Bank Account Number

2.) ICAP: Inter exchange Client Address Protocol

3.) Open source: BOX a business wallet solution

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 以太坊(Ethereum ):下一代智能合約和去中心化應(yīng)用平臺(tái) 翻譯:巨蟹 、少平 譯者注:中文讀者可以到以太坊愛(ài)...
    車(chē)圣閱讀 3,928評(píng)論 1 7
  • 【中文版】以太坊白皮書(shū) 翻譯:少平、 Seven當(dāng)中本聰在 2009 年 1 月啟動(dòng)比特幣區(qū)塊鏈時(shí),他同時(shí)向世界引...
    __Seven__閱讀 4,453評(píng)論 0 10
  • 大漠長(zhǎng)風(fēng)呼嘯,晴空萬(wàn)里甚好。 此刻縱馬意逍遙,方顯童心年少。 北坡水草茂,南山地勢(shì)高。 登頂漫山遙望,江山如此多嬌...
    羊古閱讀 182評(píng)論 0 1
  • 近日被朋友啦進(jìn)去了一個(gè)所謂的金融圈,交流了下心得,一交流下一跳。 所謂金融就是貸款中介。貸款一般收費(fèi)百分之10到2...
    創(chuàng)業(yè)y閱讀 1,117評(píng)論 0 0
  • 日子過(guò)的很是艱難啊,17年18年19年20年,還有幾年,還得熬幾年,今晚又失眠了,翻來(lái)覆去兩個(gè)小時(shí)了,想睡但是睡不...
    高妞妞_e4ed閱讀 264評(píng)論 0 0

友情鏈接更多精彩內(nèi)容