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

相关文章
相关标签/搜索