什麼是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 互換用戶端地址協議,一種IBAN相容系統,用於引用和處理客戶帳戶,旨在簡化資金轉移流程,在證券交易所之間無憂無慮,並最終使KYC和AML成為過去。
這裡有相關於以太坊對ICAP的介紹:
在第三方賬戶之間(特別是證券交易所賬戶)之間轉賬資金給使用者帶來了相當大的負擔,並且由於客戶賬戶中的存款被識別的方式而容易出錯。現有的銀行業通過擁有一個被稱為
IBAN的通用代碼解決了這個問題。該代碼合并了機構和客戶帳戶以及錯誤偵測機制,實際上消除了微不足道的錯誤並為使用者提供了相當大的便利。不幸的是,這是一個嚴格監管和集中的服務,只有大型的,完善的機構才能使用。目前的議定書ICAP可被視為適用於以太坊系統中任何含有資金的機構的分散版本。
IBAN介紹
國際銀行賬戶號碼~[1]~ (International Bank Account Number,簡稱IBAN)是各國各銀行之間互相定立的標識號碼,可降低國際間金融操作的失誤。它最初是由歐洲銀行標準委員會(ECBS)通過,後來被採納為國際標準 ISO 13616:1997。目前的標準是ISO 13616:2007,表明SWIFT代碼(ISO 9362)為正式的格式。最初開發是為了促進歐盟範圍內的支付,但現在也已經實施到大多數歐洲國家和其他國家,尤其是在中東和加勒比海地區。IBAN最多包含34個字母和數字字元:首兩個字母是ISO 3166-1α-2國家代碼,然後兩個校正位,校正位可檢查完整性。最後一個是特定國家的基本銀行賬戶號碼(BBAN)。BBAN格式的決定是由每個國家的銀行界的約束下,它必須是一個固定長度的不區分大小寫英數字。它包括國內銀行賬戶號碼,銀行分行的號碼,和潛在的路由資訊。
基本銀行賬戶號碼
基本銀行賬戶號碼(The Basic Bank Account Number,簡稱BBAN)的格式是由國家中央銀行或相應機關所訂定,格式並沒有強制性。一國的基本銀行賬戶號碼須為固定長度且由大小寫不敏感的英數字組成。其包括本國賬戶號碼,子分支辨識碼與路徑資訊。各國皆可擁有不同的編號系統,最多三十字。
IBAN結構
IBAN代碼由多達34個不區分大小寫字母數字字元組成,其字元取值範圍為0-9和A-Z。它包含三個資訊:
- 國家代碼; 以下內容的頂級標識符(ISO 3166-1 alpha-2);
- 錯誤偵測代碼; 使用mod-97-10校正和協議(ISO / IEC 7064:2003);
- 基本銀行帳號(BBAN); 該機構,分支和客戶賬戶的標識符,其組成取決於上述國家。
舉例來說,從維基百科可以得知,英國的IBAN格式定義為:
國家 |
格式 |
說明 |
英國 |
GBkk bbbb ssss sscc cccc cc |
b = 銀行代碼 s = 銀行分類代碼 c = 帳號 |
該 GBkk bbbb ssss sscc cccc cc
格式解讀為:
[國家代碼:GB][錯誤校正碼:kk][基本銀行帳號:bbbb ssss sscc cccc cc]
對於英國來說,BBAN由以下部分組成:
- 機構標識符,4個字元的字母,例如
MIDL
代表滙豐銀行。
- 分類代碼(機構內的分行標識符),一個6位十進位數字,例如
402702
滙豐銀行的Lancaster分行。
- 帳號(分公司內的客戶標識符),一個8位十進位數字。
以太坊ICAP設計
以太坊引入了新的IBAN國家代碼:XE,X首碼為擴充的意思,E表示為以太坊(Ethereum),制定為非法定貨幣(例如XBOX, XEOS)。以太坊在IBAN基礎上設計了ICAP,其設計思路與IBAN相容。目的是為了方便各大公鏈之間轉賬?它有三種BBAN代碼類型:直接類型,基本類型和間接類型。
直接類型
此代碼的直接BBAN為30個字元,將包含一個欄位:
- 帳戶標識符,30個字母數字(<155位)。這將被解釋為表示160位以太坊地址的最低有效位的大端編碼的36進位整數。因此,這些以太坊地址通常以零位元組開始。
例如XE 73 38O073KYGTWWZN0F2WZ0R8PX5ZPPZS,它的對應的地址00c5496aee77c1ba1f0854206a26dda82a81d6d8
。
基本類型
與直接編碼相同,但代碼為31個字元(與IBAN不相容)並組成相同的單個欄位:
- 帳戶標識符,31個字元字母數字(<161位)。這將被解釋為一個代表160位以太坊地址的大端編碼的36進位整數。
間接類型
該代碼的BBAN在間接時將為16個字元,並將包含三個欄位:
- 資產標識符,3個字元的字母數字(<16位);
- 機構標識符,4個字元的字母數字(<21位);
- 機構客戶標識符,9個字元的字母數字(<47位);
包括四個首字元,這導致最終的客戶帳戶地址長度為20個字元,格式為:
XE81ETHXREGGAVOFYORK
分成:
XE
以太坊的國家代碼;
81
校正和;
ETH
客戶賬戶中的資產標識符 - 在這種情況下,“ETH”是唯一有效資產標識符,因為以太坊的基礎註冊管理機構合約僅支援該資產;
XREG
賬戶的機構代碼 - 在這種情況下,以太坊的基礎註冊管理機構合約;
GAVOFYORK
該機構內的客戶標識符 - 在這種情況下,直接支付且無任何主要地址的額外資料與以太坊基礎註冊合約中的名稱“GAVOFYORK”相關聯;
URI表示形式
iban:XE7338O073KYGTWWZN0F2WZ0R8PX5ZPPZS
具體實現:以太坊地址轉換成ICAP格式
轉換函式
//ConvertAddressToICAP 將以太坊地址轉換為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) } // 以太坊國家代碼XE + 校正碼 + 帳號 icap := join("XE", checkDigits(enc), enc) return icap, nil}
36進位編碼
其規則如同十進位數轉十六進位數,其演算法如下:
十六進位數取值範圍表示s="0123456789ABCDEF"。其字串數組下標範圍為0-15,其中對應的下標:A=11,B=12… F=15。
記餘數數組a,
- 把10進位數除以16,擷取整數商和餘數,記下餘數和整數商,並把餘數放入餘數數組a;
- 整數商不為0時,再次執行第一個步驟,整數商為0時停止,並記錄下此時的餘數;
- 倒排餘數數組a,同時影射每個位置值到s字串數組下標對應的值。
例如:十進位數505,500/16 得31餘9,將9放入餘數數組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進位編碼也是採用了如上演算法,只是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)}
校正碼
校正碼使用了mod-97-10校正和協議 (ISO / IEC 7064:2003),查看ISO具體協議需要8,800瑞士法郎。
舉例,對於字串794,其演算法步驟為:
步驟1:追加兩個零佔據校正字元位置:79400;
步驟2:除以97,得到商818和整數餘數54;
步驟3:將校正字元值確定為(97 + 1) - 54 = 44並將其附加到原始字串以給出79444。
為了檢查,將字串除以97; 如果提醒是1,則校正通過。
計算國際銀行帳號(IBAN)的校正位(xx yyy zzzzzzzz kk)
不包括支票號碼的銀行帳號:06 000 01234567。
a:06 000 01234567 00
b:060000123456700:97 = 618557973780餘數= 40
c:(97 + 1) - 40 = 58結果:06 000 01234567 58
校正和:06000123456758:97 = 618557973781其餘= 1
不包括支票號碼的銀行帳號:06 000 01234586。
a:06 000 01234586 00
b:060000123458600:97 = 618557973800其餘= 00
c:(97 + 1) - 00 = 98結果:06 000 01234586 98。
校正和:06000123458698:97 = 618557973801餘數= 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 = 35func 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碼錶中分別對應10進位值為65,66... //字元A-Z的36進位字串索引分別是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}
具體實現:ICAP格式轉換成以太坊地址
校正
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}
轉換
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錢包二維碼使用了ICAP格式,掃碼之後出現的格式為:
iban:XE86G29C8IV34UOJMYWHGDSGME33YKEC3QO?account=100&type=ETH
其中XE86G29C8IV34UOJMYWHGDSGME33YKEC3QO
是轉賬的地址,account
是轉賬的數額,type
是轉賬的類型,這裡代錶轉ETH。
BOX將相容imToken格式。
完整的程式碼片段可以在這裡找到:https://gist.github.com/alpha...
參考
1.) Wikipedia: International Bank Account Number
2.) ICAP: Inter exchange Client Address Protocol
3.) Open source: BOX a business wallet solution