Skip to content

Commit

Permalink
feat(address): add blake160-ed public key as address identifier
Browse files Browse the repository at this point in the history
  • Loading branch information
Keith-CY committed May 23, 2019
1 parent e3e83a1 commit b7bee1c
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 30 deletions.
17 changes: 15 additions & 2 deletions packages/ckb-sdk-address/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ In a nutshell, the address format is similar to [BIP-0173](https://github.com/bi

Detailed methods could be found in `@nervosnetwork/ckb-sdk-utils`

## Address options
## Address configuration

> The meanings of the options will be explained in the RFC.
> The meanings of the configuration will be explained in the RFC.
1. Prefix

Expand All @@ -30,6 +30,18 @@ Detailed methods could be found in `@nervosnetwork/ckb-sdk-utils`

- 'P2PH'

## Address Value

The `address.value` is the address string generated by the private key and address configuration you passed to the constructor.

## Address Idenfitier

The `address.identifier` represents the identity of the address object. It derives from the public key, and used to generate the human readable address value.

`address.identifier` is calculated by `blake160(publicKey)`, which picks the first 20 bytes of `blake2b(publicKey)`.

And `address.identifier` is used to generate `address.value` in `bech32(address.identifier, ...AddressConfiguration)`.

## Installation

Install the package with [yarn](https://yarnpkg.com/):
Expand All @@ -53,4 +65,5 @@ const privateKey = 'your private key'

const address = new Address(privateKey, { prefix: 'ckt' })
console.log(address.value)
console.log(address.identifier)
```
9 changes: 9 additions & 0 deletions packages/ckb-sdk-address/__tests__/ckb-sdk-address.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,13 @@ describe('ckb-sdk-address', () => {
})
expect(address.value).toBe(fixture.address)
})

it('generate idenfitier with default configuration', () => {
const fixture = {
privateKey: 'e79f3207ea4980b7fed79956d5934249ceac4751a4fae01a0f7c4a96884bc4e',
idenfitier: '2f663ae60e00153d223657c685a15604255b168b',
}
const address = new Address(fixture.privateKey)
expect(address.idenfitier).toBe(fixture.idenfitier)
})
})
20 changes: 12 additions & 8 deletions packages/ckb-sdk-address/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
import ECPair, { Options } from '@nervosnetwork/ckb-sdk-utils/lib/ecpair'
import { hexToBytes, AddressPrefix, AddressType, AddressBinIdx, pubkeyToAddress } from '@nervosnetwork/ckb-sdk-utils'
import ECPair from '@nervosnetwork/ckb-sdk-utils/lib/ecpair'
import * as utils from '@nervosnetwork/ckb-sdk-utils'
import { AddressOptions } from '@nervosnetwork/ckb-sdk-utils/lib/address'

const { hexToBytes, pubkeyToAddress, blake160, AddressPrefix, AddressType, AddressBinIdx } = utils

class Address extends ECPair {
public value = ''

public idenfitier = ''

public constructor(
sk: Uint8Array | string,
{
addressAlgorithm = pubkeyToAddress,
prefix = AddressPrefix.Testnet,
type = AddressType.BinIdx,
binIdx = AddressBinIdx.P2PH,
}: Options &
Partial<{
}: Partial<
{
addressAlgorithm: Function
prefix: AddressPrefix
type: AddressType
binIdx: AddressBinIdx
}> = {
} & AddressOptions
> = {
addressAlgorithm: pubkeyToAddress,
prefix: AddressPrefix.Testnet,
type: AddressType.BinIdx,
Expand All @@ -30,6 +33,7 @@ class Address extends ECPair {
type,
binIdx,
})
this.idenfitier = blake160(this.publicKey as string, 'hex') as string
}
}

Expand Down
26 changes: 13 additions & 13 deletions packages/ckb-sdk-utils/__tests__/ckb-utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,54 +138,54 @@ describe('scriptToHash', () => {
})

describe('address', () => {
it('to address payload', () => {
it('identifier to address payload', () => {
const fixture = {
blake160Pubkey: '36c329ed630d6ce750712a477543672adab57f4c',
identifier: '36c329ed630d6ce750712a477543672adab57f4c',
payload: '015032504836c329ed630d6ce750712a477543672adab57f4c',
}
const payload = bytesToHex(toAddressPayload(fixture.blake160Pubkey))
const payload = bytesToHex(toAddressPayload(fixture.identifier))
expect(payload).toBe(fixture.payload)
})

it('pubkey blake160 to address with prefix of ckt', () => {
it('identifier to address with prefix of ckt', () => {
const fixture = {
str: '36c329ed630d6ce750712a477543672adab57f4c',
identifier: '36c329ed630d6ce750712a477543672adab57f4c',
prefix: 'ckt',
address: 'ckt1q9gry5zgxmpjnmtrp4kww5r39frh2sm89tdt2l6v234ygf',
}
const address = bech32Address(fixture.str, {
const address = bech32Address(fixture.identifier, {
prefix: fixture.prefix,
})
expect(address).toBe(fixture.address)
})

it('pubkey blake160 to address with prefix of ckb', () => {
it('identifier to address with prefix of ckb', () => {
const fixture = {
str: '36c329ed630d6ce750712a477543672adab57f4c',
identifier: '36c329ed630d6ce750712a477543672adab57f4c',
prefix: 'ckb',
address: 'ckb1q9gry5zgxmpjnmtrp4kww5r39frh2sm89tdt2l6vqdd7em',
}
const address = bech32Address(fixture.str, {
const address = bech32Address(fixture.identifier, {
prefix: fixture.prefix,
})
expect(address).toBe(fixture.address)
})

it('bech32Address with empty options', () => {
const fixture = {
str: '36c329ed630d6ce750712a477543672adab57f4c',
identifier: '36c329ed630d6ce750712a477543672adab57f4c',
address: 'ckt1q9gry5zgxmpjnmtrp4kww5r39frh2sm89tdt2l6v234ygf',
}
const address = bech32Address(fixture.str, {})
const address = bech32Address(fixture.identifier, {})
expect(address).toBe(fixture.address)
})

it('bech32Address with default options which should be prefix: ckb, type: binIndx, binIdx: P2PH', () => {
const fixture = {
str: '36c329ed630d6ce750712a477543672adab57f4c',
identifier: '36c329ed630d6ce750712a477543672adab57f4c',
address: 'ckt1q9gry5zgxmpjnmtrp4kww5r39frh2sm89tdt2l6v234ygf',
}
const address = bech32Address(fixture.str)
const address = bech32Address(fixture.identifier)
expect(address).toBe(fixture.address)
})

Expand Down
16 changes: 9 additions & 7 deletions packages/ckb-sdk-utils/src/address/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,26 @@ export const defaultAddressOptions = {
* @see https://github.com/nervosnetwork/ckb/wiki/Common-Address-Format
*/
export const toAddressPayload = (
blake160Pubkey: string | Uint8Array,
identifier: string | Uint8Array,
type: AddressType = AddressType.BinIdx,
params: AddressBinIdx = AddressBinIdx.P2PH
): Uint8Array => {
if (typeof blake160Pubkey === 'string') {
return new Uint8Array([...hexToBytes(type), ...utf8ToBytes(params), ...hexToBytes(blake160Pubkey)])
if (typeof identifier === 'string') {
return new Uint8Array([...hexToBytes(type), ...utf8ToBytes(params), ...hexToBytes(identifier)])
}
return new Uint8Array([...hexToBytes(type), ...utf8ToBytes(params), ...blake160Pubkey])
return new Uint8Array([...hexToBytes(type), ...utf8ToBytes(params), ...identifier])
}

export const toAddressIdentifier = toAddressPayload

export const bech32Address = (
data: Uint8Array | string,
{
prefix = AddressPrefix.Testnet,
type = AddressType.BinIdx,
binIdx = AddressBinIdx.P2PH,
}: AddressOptions = defaultAddressOptions
) => bech32.encode(prefix, bech32.toWords(toAddressPayload(data, type, binIdx)))
) => bech32.encode(prefix, bech32.toWords(toAddressIdentifier(data, type, binIdx)))

export const pubkeyToAddress = (
pubkey: Uint8Array | string,
Expand All @@ -58,8 +60,8 @@ export const pubkeyToAddress = (
binIdx = AddressBinIdx.P2PH,
}: AddressOptions = defaultAddressOptions
) => {
const blake160Pubkey = blake160(pubkey)
return bech32Address(blake160Pubkey, {
const identifier = blake160(pubkey)
return bech32Address(identifier, {
prefix,
type,
binIdx,
Expand Down

0 comments on commit b7bee1c

Please sign in to comment.