#!/bin/bash
rm -rf ~/.bitcoin/
bin/bitcoind -regtest \
-rpcthreads=1 \
-rpcworkqueue=1 \
-par=1 \
-listen=0 \
-dnsseed=0 \
-disablewallet=0 \
-torcontrol=0 \
-fallbackfee=0.00001 \
-maxtxfee=1.0
./bitcoin-cli -regtest createwallet "mywallet"
./bitcoin-cli -regtest getnewaddress
./bitcoin-cli -regtest getnewaddress
./bitcoin-cli -regtest getnewaddress
./bitcoin-cli -regtest generatetoaddress 101 bcrt1qufg9udk2sn4vc7l93f5lfcm56wy99v6avv7vu5
./bitcoin-cli -regtest sendtoaddress "bcrt1q9rk2aq9zwfnkehmvj87d4gt07ugyyh7ycl05ms" 10.00
./bitcoin-cli -regtest generatetoaddress 1 bcrt1qufg9udk2sn4vc7l93f5lfcm56wy99v6avv7vu5
./bitcoin-cli -regtest listunspent 0 9999 '["bcrt1q9rk2aq9zwfnkehmvj87d4gt07ugyyh7ycl05ms"]'
./bitcoin-cli -regtest createrawtransaction '[{"txid":"0d987d29d94fe59a669e8bedbc98ec1c01264fe2bce3ccbe1324ee48d22754ac","vout":1}]' '{"bcrt1qdh6w03tqysmqph8drafmm4445y9ucg0xjvgns4":3.00,"bcrt1q9rk2aq9zwfnkehmvj87d4gt07ugyyh7ycl05ms":6.99999}'
./bitcoin-cli -regtest signrawtransactionwithwallet 0200000001ac5427d248ee2413becce3bce24f26011cec98bced8b9e669ae54fd9297d980d0100000000fdffffff0200a3e111000000001600146df4e7c560243600dced1f53bdd6b5a10bcc21e61823b9290000000016001428ecae80a272676cdf6c91fcdaa16ff710425fc400000000 | jq -r '.hex'
./bitcoin-cli -regtest sendrawtransaction 02000000000101ac5427d248ee2413becce3bce24f26011cec98bced8b9e669ae54fd9297d980d0100000000fdffffff0200a3e111000000001600146df4e7c560243600dced1f53bdd6b5a10bcc21e61823b9290000000016001428ecae80a272676cdf6c91fcdaa16ff710425fc402473044022029f4a04e4c3e745c390530b8ef73159cc40a887e7baea965e0b5ce6947fa16ff022064d16e5d517de7419b90c3d010529658d62155abba8f33fb4e096b79f53b0dae0121027fbffeaf8cca5b9ea0bc22bfa6fa19634e630415ff80b3b3cebedb638c96364700000000
sleep 1
./bitcoin-cli -regtest generatetoaddress 1 bcrt1qufg9udk2sn4vc7l93f5lfcm56wy99v6avv7vu5
sleep 1
./bitcoin-cli -regtest listunspent 0 9999 '["bcrt1q9rk2aq9zwfnkehmvj87d4gt07ugyyh7ycl05ms"]'
HD钱包的后续推导原理
根据nChild 以及根私钥 以及根链码 计算相应的tweak
chind1 => tweak1
chind2 => tweak2
由于根私钥 以及根链码固定 可以推导出一群密钥对
...
nodejs demo1===============
const crypto = require('crypto');
// 🔥 码链
const chainCodeHex = "60950c195139ac379fab69cf8d7f9e3ab2fe59a693ba7d4b450c11a505857afd";
const headerHex = "03";
const dataHex = "ef1bc1cbd4b009f6c8c78589d8d90f618d3a870ae8ef2452b24e40f1f5366e3c";
const nChild = 0;
// 1. 转为 Buffer
const chainCode = Buffer.from(chainCodeHex, 'hex');
const header = Buffer.from(headerHex, 'hex');
const data = Buffer.from(dataHex, 'hex');
// 2. 索引转 4字节大端
const num = Buffer.alloc(4);
num.writeUInt32BE(nChild, 0);
// 3. 严格按顺序拼接:header + data + num
const msg = Buffer.concat([header, data, num]);
// 4. 计算 HMAC-SHA512
const output = crypto.createHmac('sha512', chainCode).update(msg).digest();
// 5. 打印结果
console.log("=== 计算结果 ===");
console.log("output[64]:", output.toString('hex'));
console.log("tweak (前32):", output.slice(0,32).toString('hex'));
console.log("ccChild(后32):", output.slice(32,64).toString('hex'));
=======
=== 计算结果 ===
output[64]: dc4ad75be3f28028cfb769dd90ca87751324aefda805ebad58d8d72198befbb2a5602f2520d79042c4b5728fb7e658ecaec3901c983f454947ba78cd79ec5df4
tweak (前32): dc4ad75be3f28028cfb769dd90ca87751324aefda805ebad58d8d72198befbb2
ccChild(后32): a5602f2520d79042c4b5728fb7e658ecaec3901c983f454947ba78cd79ec5df4
===============
根私钥 "287344f3107dba43c398e0920628af27c39972a7f20e35f78ef87af0df644c84";
tweak "dd1e73d0a7c33b985a661d561c0b40621738d6acb4bd36ab50c969b2ca83784c";
算法符合阿贝尔群规范
这里约定根私钥Rp 子私钥np 子公钥 nP 子微调值ntweak
则子私钥可以自行计算 np = Rp + ntweak .
子公钥nP = np * G = Rp * G + ntweak * G

子私钥计算demo2 =========================
priKey + tweak = 子私钥
// secp256k1 椭圆曲线阶(固定常数)
const n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141n;
// 两个十六进制数priKey tweak
const a_hex = "287344f3107dba43c398e0920628af27c39972a7f20e35f78ef87af0df644c84";
const b_hex = "dd1e73d0a7c33b985a661d561c0b40621738d6acb4bd36ab50c969b2ca83784c";
// 转为大整数
const a = BigInt(`0x${a_hex}`);
const b = BigInt(`0x${b_hex}`);
// 核心计算:(a + b) mod n
const result = (a + b) % n;
// 转为 64 位十六进制字符串
const result_hex = result.toString(16).padStart(64, '0');
// 输出
console.log("父私钥 + tweak = 子私钥");
console.log("结果:", result_hex);
===========================
子私钥: 0591b8c3b840f5dc1dfefde82233ef8b20236c6df782cc671fef8616d9b1838f
计算出的公钥: 027fbffeaf8cca5b9ea0bc22bfa6fa19634e630415ff80b3b3cebedb638c963647
==========