ethereum/EIPs-55 Mixed-case checksum address encoding

eip title author type category status created
55
Mixed-case checksum address encoding
Vitalik Buterin
Standards Track
ERC
Final
2016-01-14

Specification(python)

from ethereum import utils

def checksum_encode(addr): # Takes a 20-byte binary address as input
    o = ''
    v = utils.big_endian_to_int(utils.sha3(addr.hex()))
    for i, c in enumerate(addr.hex()):
        if c in '0123456789'://就是若是address在i位置上的值是數字的話,就不作任何改變
            o += c
        else: //可是若是是字符的話,就要另進行判斷,(2**(255 - 4*i))這個的二進制的結果就是從後向前數的255 - 4*i個位置上的值爲1,便是爲了實現從前日後數爲4*i位置的數字
            o += c.upper() if (v & (2**(255 - 4*i))) else c.lower()//255的緣由是hash的v有32bytes,即32*8=256,從0開始
//因此意思是若是小寫十六進制地址的散列v的第4*i位也是1,則以大寫形式打印,不然以小寫形式打印。
return '0x'+o def test(addrstr): assert(addrstr == checksum_encode(bytes.fromhex(addrstr[2:]))) test('0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed') test('0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359') test('0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB') test('0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb')

注意:v = utils.big_endian_to_int(utils.sha3(addr.hex()))python

所謂的大端模式(Big-endian),是指數據的高字節,保存在內存的低地址中,而數據的低字節,保存在內存的高地址中,這樣的存儲模式有點兒相似於把數據看成字符串順序處理:地址由小向大增長,而數據從高位往低位放;好比1234,若是是數字的話應該從低位開始讀4321(即小端模式);可是這裏爲大端模式,因此讀法就是1234。這是爲了順序處理addr的hash值git

In English, convert the address to hex, but if the ith digit is a letter (ie. it's one of abcdef) print it in uppercase if the 4*ith bit of the hash of the lowercase hexadecimal address is 1 otherwise print it in lowercase.github

Rationale

Benefits:swift

  • Backwards compatible with many hex parsers that accept mixed case, allowing it to be easily introduced over time
  • Keeps the length at 40 characters。 address長度爲40個字符
  • On average there will be 15 check bits per address, and the net probability that a randomly generated address if mistyped will accidentally pass a check is 0.0247%. This is a ~50x improvement over ICAP, but not as good as a 4-byte check code.  上面bit的轉換效率沒有字節的轉化效率快,因此下面實現的是半字節(16進制一字符4bits)形式的轉換方法:

例子:dom

const createKeccakHash = require('keccak');

function toChecksumAddress (address) {
  address = address.toLowerCase().replace('0x', '');
  console.log(address);
  var hash = createKeccakHash('keccak256').update(address).digest('hex');//update就是輸入要加密的值,digest就是將加密好的hash值以16進制的形式輸出
  console.log(hash);//5cfac663f45837b409c4d3dc1cef5f4759734f4989dd53a31b1265734c0b28f4,64個
  var ret = '0x';

  for (var i = 0; i < address.length; i++) {//因此只用獲得hash的前40個字符
    if (parseInt(hash[i], 16) >= 8) {//即將16進制的hash[i]轉化成10進制的數值後與8進行比較,若是在i位置的hash的值大於或等於8,相應位置的address的值就換成大寫,不然就仍是小寫
      ret += address[i].toUpperCase();//其實就是根據獲得的hash值來相應將address轉換成大小寫皆有的形式
      console.log('if');
      console.log(ret);
    } else {
      ret += address[i];
      console.log('else');
      console.log(ret);
    }
  }

  return ret;
}

var addr = '0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359';//去掉0x是40個
console.log(toChecksumAddress(addr));

這裏的例子address是16進制的,固然,若是the hex address encoded as ASCII,那麼就寫成:ide

var hash = createKeccakHash('keccak256').update(Buffer.from(address.toLowerCase(), 'ascii')).digest()

 

 

Adoption

Wallet displays checksummed addresses rejects invalid mixed-case rejects too short rejects too long
Etherwall 2.0.1 Yes Yes Yes Yes
Jaxx 1.2.17 No Yes Yes Yes
MetaMask 3.7.8 Yes Yes Yes Yes
Mist 0.8.10 Yes Yes Yes Yes
MyEtherWallet v3.9.4 Yes Yes Yes Yes
Parity 1.6.6-beta (UI) Yes Yes Yes Yes

Exchange support for mixed-case address checksums, as of 2017-05-27:

Exchange displays checksummed deposit addresses rejects invalid mixed-case rejects too short rejects too long
Bitfinex No Yes Yes Yes
Coinbase Yes No Yes Yes
GDAX Yes Yes Yes Yes
Kraken No No Yes Yes
Poloniex No No Yes Yes
Shapeshift No No Yes Yes

 

References

  1. EIP 55 issue and discussion https://github.com/ethereum/eips/issues/55
  2. Python implementation in ethereum-utils
  3. Ethereumjs-util implementation https://github.com/ethereumjs/ethereumjs-util/blob/75f529458bc7dc84f85fd0446d0fac92d991c262/index.js#L452-L466
/**
 * Returns a checksummed address
 * @param {String} address
 * @return {String}
 */
exports.toChecksumAddress = function (address) {
  address = exports.stripHexPrefix(address).toLowerCase()
  var hash = exports.sha3(address).toString('hex')
  var ret = '0x'

  for (var i = 0; i < address.length; i++) {
    if (parseInt(hash[i], 16) >= 8) {
      ret += address[i].toUpperCase()
    } else {
      ret += address[i]
    }
  }

  return ret
}

  4.Swift implementation in EthereumKitui

相關文章
相關標籤/搜索