nervosnetwork / rfcs

This repository contains proposals, standards and documentations related to Nervos Network.
https://nervos.org
MIT License
268 stars 160 forks source link

Example steps to generate address from public key in C #362

Open mdhash opened 2 years ago

mdhash commented 2 years ago

I am trying to implement Nervos address generation from public key in C. While following the steps mentioned in RFC, I am unable to generate the correct address. Are there any detailed examples showcasing intermediate values, so I can debug my logic?

I referenced this python demo and js sdk to verify the logic.

Example:

Address format - testnet short address

PK: 038ab113db7fc7af23b104a839c5c2e33e4b6b791d0589c3030f1eb7b819c17b82
args: adf33350760d7d939935c48751886ad55506c741

Desired address(generated from sdk): ckt1qyq2muen2pmq6lvnny6ufp633p4d24gxcaqswv6xlr

How do I generate the address mentioned ^? Since I am implementing it in C, I cannot use libraries from other languages. Is there any demo C implementation logic for the same?

Also are there any recommended C libraries for steps in generating address? (PK -> blake160(PK) -> payload -> address )

TIA

quake commented 2 years ago

first, you need to calculate the hash of the public key, we are using blake2b with a personalization string ( https://github.com/nervosnetwork/ckb/wiki/ckbhash ), this is the python demo code:

def ckbhash():
    return hashlib.blake2b(digest_size=32, person=b'ckb-default-hash')

hasher = ckbhash()
hasher.update(bytes.fromhex('038ab113db7fc7af23b104a839c5c2e33e4b6b791d0589c3030f1eb7b819c17b82'))
hasher.hexdigest()

=> 'adf33350760d7d939935c48751886ad55506c7410d77eafc51fac0f047969c40'

the first 20 bytes of the hash (adf33350760d7d939935c48751886ad55506c741) will be used as the script args, we call it blake160(PK), then you can use it to generate the payload. according to the rfc, the desired address format is Deprecated Short Payload Format, the payload is composed of the following data:

payload = 0x01 | code_hash_index | args
=>
payload = 0x01 | 0x00 | 0xadf33350760d7d939935c48751886ad55506c741

=> 0100adf33350760d7d939935c48751886ad55506c741

now you can use bech32 lib to encode the payload with the hrp ckt, the result is:

ckt1qyq2muen2pmq6lvnny6ufp633p4d24gxcaqswv6xlr

here is an online tool to verify the bech32 result ( https://slowli.github.io/bech32-buffer/ )

image

And I am sorry to say that there is no C sdk at the moment, but the main computational process here is blake2b and bech32/bech32m, and I think there are already some open source C libs (especially in the bitcoin related lib) that can be used. If you have any questions, please comment on the issue.

mdhash commented 2 years ago

thanks for the above info. Also can you let me know the derivation path from mnemonic to attain the desired public key for above operations.

quake commented 2 years ago

we follow the bip44, you may find registered nervos ckb coin type here: https://github.com/satoshilabs/slips/blob/master/slip-0044.md , the code is 309, and the derivation path is m/44'/309'/0'/