P2WPKH地址生成示例

P2WPKH地址生成示例

参考:

https://blog.csdn.net/QQ604666459/article/details/82147516

P2WPKH地址生成流程如下:

0. 拥有一个私钥

9a9a6539856be209b8ea2adbd155c0919646d108515b60b7b13d6a79f1ae5174

1. 计算该私钥的压缩公钥

0340a609475afa1f9a784cad0db5d5ba7dbaab2147a5d7b9bbde4d1334a0e40a5e

2. 计算压缩公钥的Hash-160值,即(SHA-256 + RIPEMD-160)

154de7cabbb5822075e92c57a27ca3ef3e8be50c

3. 生成压缩公钥的脚本,即在步骤2结果值前添加操作码OP_0和Hash-160的结果长度(0x14)

0014154de7cabbb5822075e92c57a27ca3ef3e8be50c

4. 计算步骤3脚本的Hash-160值

c596906f342478ca56707f7bb1bda659cb3cef98

5. 在步骤4的结果前,添加版本号(主网为0x05,测试网为0xC4)

05c596906f342478ca56707f7bb1bda659cb3cef98

6. 计算步骤5结果值的校验码

a63b7898

7. 将校验码添加到扩展的步骤5的结果后,然后,进行Base-58编码,即得到比特币的付款地址

3KhmQic5wmCxDN5hHDr4TnGQu3S5LcKXTV

8. 验证脚本为OP_HASH160 OP_EQUAL

a914c596906f342478ca56707f7bb1bda659cb3cef9887

Node(v10.5.0)实现源码:

const crypto = require(`crypto`);
const bs58 = require(`bs58`);
const ecdh = crypto.createECDH('secp256k1');
const OP_0 = Buffer.from([0x00]);
const len_hash160 = Buffer.from([0x14]);
const OP_HASH160 = Buffer.from([0xA9]);
const OP_EQUAL = Buffer.from([0x87]);

// 0. 拥有一个私钥
const privateKey = Buffer.from(`9a9a6539856be209b8ea2adbd155c0919646d108515b60b7b13d6a79f1ae5174`,`hex`);
console.log(`0 - Private key: ${privateKey.toString(`hex`)}`);
// 1. 计算该私钥的压缩公钥
ecdh.setPrivateKey(privateKey);
const cPublicKey = Buffer.from(ecdh.getPublicKey(`hex`, `compressed`), `hex`);
console.log(`1 - Compressed public key: ${cPublicKey.toString(`hex`)}`);
// 2. 计算压缩公钥的Hash-160值,即(SHA-256 + RIPEMD-160const CPubKeySHA256 = crypto.createHash(`sha256`).update(cPublicKey).digest();
const CPubKeyHash160 = crypto.createHash(`rmd160`).update(CPubKeySHA256).digest();
console.log(`2 - CPubKey Hash-160: ${CPubKeyHash160.toString(`hex`)}`);
// 3. 生成压缩公钥的脚本,即在步骤2结果值前添加操作码OP_0和Hash-160的结果长度0x14
const ScriptPubKey = Buffer.concat([OP_0, len_hash160, CPubKeyHash160]);
console.log(`3 - Script public key: ${ScriptPubKey.toString(`hex`)}`);
// 4. 计算步骤3脚本的Hash-160const ScriptPubKeySHA256 = crypto.createHash(`sha256`).update(ScriptPubKey).digest();
const ScriptPubKeyHash160 = crypto.createHash(`rmd160`).update(ScriptPubKeySHA256).digest();
console.log(`4 - ScriptPubKey Hash-160: ${ScriptPubKeyHash160.toString(`hex`)}`);
// 5. 在步骤4的结果前,添加版本号(主网为0x05,测试网为0xC4const version = Buffer.from([0x05]);
const extendedHash160 = Buffer.concat([version, ScriptPubKeyHash160]);
console.log(`5 - Extended Hash-160: ${extendedHash160.toString(`hex`)}`);
// 6. 计算步骤5结果值的校验码
const sha1 = crypto.createHash(`sha256`).update(extendedHash160).digest();
const sha2 = crypto.createHash(`sha256`).update(sha1).digest();
const checksum = Buffer.alloc(4);
sha2.copy(checksum, 0, 0, checksum.length);
console.log(`6 - Checksum: ${checksum.toString(`hex`)}`);
// 7. 将校验码添加到扩展的步骤5的结果后,然后,进行Base-58编码,即得到比特币的付款地址
const bitaddress = Buffer.concat([extendedHash160, checksum]);
const address = bs58.encode(bitaddress);
console.log(`7 - Address: ${address}`);
// 8. 验证脚本为OP_HASH160  OP_EQUAL
const scriptPubKey = Buffer.concat([OP_HASH160, len_hash160, ScriptPubKeyHash160, OP_EQUAL]);
console.log(`8 - ScritpPubkey: ${scriptPubKey.toString(`hex`)}`);

你可能感兴趣的:(Bitcoin)