Skip to content

Commit

Permalink
Update EIP with new test vectors and better algorithm descriptions (e…
Browse files Browse the repository at this point in the history
  • Loading branch information
Arachnid authored Oct 24, 2019
1 parent 60bad6b commit e44c9e6
Showing 1 changed file with 61 additions and 33 deletions.
94 changes: 61 additions & 33 deletions EIPS/eip-2304.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,51 +59,65 @@ This function emits an `AddressChanged` event with the new address; see also the

In general, the native binary representation of the address should be used, without any checksum commonly used in the text representation.

A table of encodings for common blockchains is provided, followed by a more detailed description of each format. In the table, 'Format' describes the encoding used to represent the bytes in text format, 'Decoded' describes the result of decoding this format, and 'On ENS' describes how this should be stored in ENS as bytes.
A table of encodings for common blockchains is provided, followed by a more detailed description of each format. In the table, 'encodings' lists the address encodings supported by that chain, along with any relevant parameters. Details of those address encodings are described in the following sections.

| Cryptocurrency | Format | Decoded | On ENS |
| --- | --- | --- | --- |
| Ethereum | hex-checksum | `<20 byte hash>` | `<20 byte hash>` |
| Bitcoin | base58check | `0x00 <20 byte hash>` | `0x76a914 <20 byte hash> 0x88ac` |
| Bitcoin | base58check | `0x05 <20 byte hash>` | `0xa914 <20 byte hash> 0x87` |
| Bitcoin | bech32 | `<witness version> <witness program>` | `<OP_n> <PUSH_m> <witness program>` |
| Binance | bech32 | `<public key hash>` | `<public key hash>` |
| Cryptocurrency | Coin Type | Encoding |
| --- | --- | --- |
| Bitcoin | 0 | P2PKH(0x00), P2SH(0x05), SegWit('bc') |
| Litecoin | 2 | P2PKH(0x30), P2SH(0x32), P2SH(0x05), SegWit('ltc') |
| Dogecoin | 3 | P2PKH(0x1e), P2SH(0x16) |
| Monacoin | 22 | P2PKH(0x32), P2SH(0x05) |
| Ethereum | 60 | ChecksummedHex |
| Ethereum Classic | 61 | ChecksummedHex |
| Rootstock | 137 | ChecksummedHex(30) |
| Ripple | 144 | Ripple |
| Bitcoin Cash | 145 | P2PKH(0x00), P2SH(0x05), CashAddr |
| Binance | 714 | Bech32('bnb') |

#### Ethereum
#### P2PKH(version)

To translate a text format Ethereum address into binary format, simply remove the '0x' prefix and hex decode it. `0x314159265dD8dbb310642f98f50C066173C1259b` is hex-decoded and stored as the 20 bytes `314159265dd8dbb310642f98f50c066173c1259b`.
Pay to Public Key Hash addresses are [base58check](https://en.bitcoin.it/wiki/Base58Check_encoding) encoded. After decoding, the first byte is a version byte. For example, the Bitcoin address `1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa` base58check decodes to the 21 bytes `0062e907b15cbf27d5425399ebf6f0fb50ebb88f18`.

Before decoding, the [EIP 55](https://eips.ethereum.org/EIPS/eip-55) address checksum must be checked. Addresses with invalid checksums that are not all uppercase or all lowercase MUST be rejected with an error. Implementations may choose whether to accept non-checksummed addresses, but the authors recommend at least providing a warning to users in this situation.
P2PKH addresses have a version byte, followed by a 20 byte pubkey hash. Their canonical encoding is their scriptPubkey encoding (specified [here](https://en.bitcoin.it/wiki/Transaction#Types_of_Transaction)) is `OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG`.

When encoding an address from binary to text, an [EIP 55](https://eips.ethereum.org/EIPS/eip-55) checksum MUST be used - so the correct encoding of the above address is `0x314159265dD8dbb310642f98f50C066173C1259b`.
The above example address is thus encoded as the 25 bytes `76a91462e907b15cbf27d5425399ebf6f0fb50ebb88f1888ac`.

#### Bitcoin
##### P2SH(version)

Bitcoin addresses are encoded as the scriptPubkey for the address. Common Bitcoin addressing formats are encoded and decoded as follows:
P2SH addresses are base58check encoded in the same manner as P2PKH addresses.
P2SH addresses have a version, followed by a 20 byte script hash. Their scriptPubkey encoding (specified [here](https://en.bitcoin.it/wiki/Transaction#Pay-to-Script-Hash)) is `OP_HASH160 <scriptHash> OP_EQUAL`. A Bitcoin address of `3Ai1JZ8pdJb2ksieUV8FsxSNVJCpoPi8W6` decodes to the 21 bytes `0562e907b15cbf27d5425399ebf6f0fb50ebb88f18` and is encoded as the 23 bytes `a91462e907b15cbf27d5425399ebf6f0fb50ebb88f1887`.

##### P2PKH and P2SH
##### SegWit(hrp)

Pay to Public Key Hash and Pay To Script Hash addresses are [base58check](https://en.bitcoin.it/wiki/Base58Check_encoding) encoded. After decoding, the first byte is a version byte. For example, the Bitcoin address `1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa` base58check decodes to the 21 bytes `0062e907b15cbf27d5425399ebf6f0fb50ebb88f18`.
SegWit addresses are encoded with [bech32](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki). Bech32 addresses consist of a human-readable part - 'bc' for Bitcoin mainnet - and a machine readable part. For SegWit addresses, this decodes to a 'witness version', between 0 and 15, and a 'witness program', as defined in [BIP141](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki).

P2PKH addresses have a version byte of 0, followed by a 20 byte pubkey hash. Their scriptPubkey encoding (specified [here](https://en.bitcoin.it/wiki/Transaction#Types_of_Transaction)) is `OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG`.
The scriptPubkey encoding for a bech32 address, as defined in BIP141, is `OP_n`, where `n` is the witness version, followed by a push of the witness program. Note this warning from BIP173:

The above example address is thus encoded as the 25 bytes `76a91462e907b15cbf27d5425399ebf6f0fb50ebb88f1888ac`.
> Implementations should take special care when converting the address to a scriptPubkey, where witness version n is stored as OP_n. OP_0 is encoded as 0x00, but OP_1 through OP_16 are encoded as 0x51 though 0x60 (81 to 96 in decimal). If a bech32 address is converted to an incorrect scriptPubKey the result will likely be either unspendable or insecure.
P2SH addresses have a version byte of 5, followed by a 20 byte script hash. Their scriptPubkey encoding (specified [here](https://en.bitcoin.it/wiki/Transaction#Pay-to-Script-Hash)) is `OP_HASH160 <scriptHash> OP_EQUAL`. A Bitcoin address of `3Ai1JZ8pdJb2ksieUV8FsxSNVJCpoPi8W6` decodes to the 21 bytes `0562e907b15cbf27d5425399ebf6f0fb50ebb88f18` and is encoded as the 23 bytes `a91462e907b15cbf27d5425399ebf6f0fb50ebb88f1887`.
For example, the Bitcoin SegWit address `BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4` decodes to a version of `0` and a witness script of `751e76e8199196d454941c45d1b3a323f1433bd6`, and then encodes to a scriptPubkey of `0014751e76e8199196d454941c45d1b3a323f1433bd6`.

##### SegWit addresses
#### ChecksummedHex(chainId?)

SegWit addresses are encoded with [bech32](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki). Bech32 addresses consist of a human-readable part - 'bc' for Bitcoin mainnet - and a machine readable part. This decodes to a 'witness version', between 0 and 15, and a 'witness program', as defined in [BIP141](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki).
To translate a text format checksummed hex address into binary format, simply remove the '0x' prefix and hex decode it. `0x314159265dD8dbb310642f98f50C066173C1259b` is hex-decoded and stored as the 20 bytes `314159265dd8dbb310642f98f50c066173c1259b`.

The scriptPubkey encoding for a bech32 address, as defined in BIP141, is `OP_n`, where `n` is the witness version, followed by a push of the witness program. Note this warning from BIP173:
A checksum format is specified by [EIP 55](https://eips.ethereum.org/EIPS/eip-55), and extended by [RSKIP60](https://github.com/rsksmart/RSKIPs/blob/master/IPs/RSKIP60.md), which specifies a means of including the chain ID in the checksum. The checksum on a text format address must be checked. Addresses with invalid checksums that are not all uppercase or all lowercase MUST be rejected with an error. Implementations may choose whether to accept non-checksummed addresses, but the authors recommend at least providing a warning to users in this situation.

> Implementations should take special care when converting the address to a scriptPubkey, where witness version n is stored as OP_n. OP_0 is encoded as 0x00, but OP_1 through OP_16 are encoded as 0x51 though 0x60 (81 to 96 in decimal). If a bech32 address is converted to an incorrect scriptPubKey the result will likely be either unspendable or insecure.
When encoding an address from binary to text, an EIP55/RSKIP60 checksum MUST be used - so the correct encoding of the above address for Ethereum is `0x314159265dD8dbb310642f98f50C066173C1259b`.

#### Ripple

Ripple addresses are encoded using a version of base58check with an alternative alphabet, described [here](https://xrpl.org/base58-encodings.html). Two types of ripple addresses are supported, 'r-addresses', and 'X-addresss'. r-addresses consist of a version byte followed by a 20 byte hash, while X-addresses consist of a version byte, a 20 byte hash, and a tag, specified [here](https://github.com/xrp-community/standards-drafts/issues/6).

Both address types should be stored in ENS by performing ripple's version of base58check decoding and storing them directly (including version byte). For example, the ripple address `rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn` decodes to and is stored as `004b4e9c06f24296074f7bc48f92a97916c6dc5ea9`, while the address `X7qvLs7gSnNoKvZzNWUT2e8st17QPY64PPe7zriLNuJszeg` decodes to and is stored as `05444b4e9c06f24296074f7bc48f92a97916c6dc5ea9000000000000000000`.

For example, the SegWit address `BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4` decodes to a version of `0` and a witness script of `751e76e8199196d454941c45d1b3a323f1433bd6`, and then encodes to a scriptPubkey of `0014751e76e8199196d454941c45d1b3a323f1433bd6`.
#### CashAddr

#### Binance Chain (BNB)
Bitcoin Cash defines a new address format called 'CashAddr', specified [here](https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/cashaddr.md). This uses a variant of bech32 encoding to encode and decode (non-segwit) Bitcoin Cash addresses, using a prefix of 'bitcoincash:'. A CashAddr should be decoded using this bech32 variant, then converted and stored based on its type (P2PKH or P2SH) as described in the relevant sections above.

Binance addresses are encoded in bech32, with the human-readable prefix 'bnb'. The encoded data is simply the address, which can be converted to binary and stored directly.
#### Bech32

[Bech32](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki) addresses consist of a human-readable part - for example, 'bnb' for Binance - and a machine readable part. The encoded data is simply the address, which can be converted to binary and stored directly.

For example, the BNB address `bnb1grpf0955h0ykzq3ar5nmum7y6gdfl6lxfn46h2` decodes to the binary representation `40c2979694bbc961023d1d27be6fc4d21a9febe6`, which is stored directly in ENS.

Expand Down Expand Up @@ -180,13 +194,27 @@ If the resolver supports the `addr(bytes32)` interface defined in EIP137, the re

The table below specifies test vectors for valid address encodings for each cryptocurrency described above.

| Cryptocurrency | Text | Onchain (hex) |
| --- | --- | --- |
| Ethereum | `0x314159265dD8dbb310642f98f50C066173C1259b` | `314159265dd8dbb310642f98f50c066173c1259b` |
| Bitcoin | `1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa` | `76a91462e907b15cbf27d5425399ebf6f0fb50ebb88f1888ac` |
| Bitcoin | `3Ai1JZ8pdJb2ksieUV8FsxSNVJCpoPi8W6` | `a91462e907b15cbf27d5425399ebf6f0fb50ebb88f1887` |
| Bitcoin | `BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4` | `0014751e76e8199196d454941c45d1b3a323f1433bd6` |
| Binance | `bnb1grpf0955h0ykzq3ar5nmum7y6gdfl6lxfn46h2` | `40c2979694bbc961023d1d27be6fc4d21a9febe6` |
| Cryptocurrency | Coin Type | Text | Onchain (hex) |
| --- | --- | --- | --- |
| Bitcoin | 0 | `1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa` | `76a91462e907b15cbf27d5425399ebf6f0fb50ebb88f1888ac` |
| | | `3Ai1JZ8pdJb2ksieUV8FsxSNVJCpoPi8W6` | `a91462e907b15cbf27d5425399ebf6f0fb50ebb88f1887` |
| | | `BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4` | `0014751e76e8199196d454941c45d1b3a323f1433bd6` |
| Litecoin | 2 | `LaMT348PWRnrqeeWArpwQPbuanpXDZGEUz` | `76a914a5f4d12ce3685781b227c1f39548ddef429e978388ac` |
| | | `MQMcJhpWHYVeQArcZR3sBgyPZxxRtnH441` | `a914b48297bff5dadecc5f36145cec6a5f20d57c8f9b87` |
| | | `ltc1qdp7p2rpx4a2f80h7a4crvppczgg4egmv5c78w8` | `0014687c150c26af5493befeed7036043812115ca36c` |
| Dogecoin | 3 | `DBXu2kgc3xtvCUWFcxFE3r9hEYgmuaaCyD` | `76a9144620b70031f0e9437e374a2100934fba4911046088ac` |
| | | `AF8ekvSf6eiSBRspJjnfzK6d1EM6pnPq3G` | `a914f8f5d99a9fc21aa676e74d15e7b8134557615bda87` |
| Monacoin | 22 | `MHxgS2XMXjeJ4if2PRRbWYcdwZPWfdwaDT` | `76a9146e5bb7226a337fe8307b4192ae5c3fab9fa9edf588ac` |
| Ethereum | 60 | `0x314159265dD8dbb310642f98f50C066173C1259b` | `314159265dd8dbb310642f98f50c066173c1259b` |
| Ethereum Classic | 61 | `0x314159265dD8dbb310642f98f50C066173C1259b` | `314159265dd8dbb310642f98f50c066173c1259b` |
| Rootstock | 137 | `0x5aaEB6053f3e94c9b9a09f33669435E7ef1bEAeD` | `5aaeb6053f3e94c9b9a09f33669435e7ef1beaed` |
| Ripple | 144 | `rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn` | `004b4e9c06f24296074f7bc48f92a97916c6dc5ea9` |
| | | `X7qvLs7gSnNoKvZzNWUT2e8st17QPY64PPe7zriLNuJszeg` | `05444b4e9c06f24296074f7bc48f92a97916c6dc5ea9000000000000000000` |
| Bitcoin Cash | 145 | `1BpEi6DfDAUFd7GtittLSdBeYJvcoaVggu` | `76a91476a04053bda0a88bda5177b86a15c3b29f55987388ac` |
| | | `bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a` | `76a91476a04053bda0a88bda5177b86a15c3b29f55987388ac` |
| | | `3CWFddi6m4ndiGyKqzYvsFYagqDLPVMTzC` | `a91476a04053bda0a88bda5177b86a15c3b29f55987387` |
| | | `bitcoincash:ppm2qsznhks23z7629mms6s4cwef74vcwvn0h829pq` | `a91476a04053bda0a88bda5177b86a15c3b29f55987387` |
| Binance | 714 | `bnb1grpf0955h0ykzq3ar5nmum7y6gdfl6lxfn46h2` | `40c2979694bbc961023d1d27be6fc4d21a9febe6` |

## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).

0 comments on commit e44c9e6

Please sign in to comment.