Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 59x 66x 25x 41x 25x 16x 1x 15x 2x 13x 2x 11x 2x 2x 60x 59x 59x 59x 59x 59x 59x 59x 59x 59x 57x 2x 55x 2x 53x 27x 27x 3x 24x 24x 26x 26x 26x 26x 44x 44x 44x 44x 44x 44x 69x 69x 69x 69x 69x 69x 69x 49x 49x 20x 69x 69x | import { BufferReader, BufferWriter } from "@node-lightning/bufio"; import { BitcoinErrorCode } from "./BitcoinErrorCode"; import { BitcoinError } from "./BitcoinError"; import { HdKeyType } from "./HdKeyType"; import { Network } from "./Network"; import { HdPrivateKey } from "./HdPrivateKey"; import { Base58Check } from "./Base58Check"; import { PrivateKey } from "./PrivateKey"; import { PublicKey } from "./PublicKey"; import { HdPublicKey } from "./HdPublicKey"; export class HdKeyCodec { public static decodeVersion(version: number): [Network, HdKeyType, boolean] { for (const network of Network.all) { if (version === network.xpubVersion) { return [network, HdKeyType.x, false]; } else if (version === network.xprvVersion) { return [network, HdKeyType.x, true]; } else if (version === network.ypubVersion) { return [network, HdKeyType.y, false]; } else if (version === network.yprvVersion) { return [network, HdKeyType.y, true]; } else if (version === network.zpubVersion) { return [network, HdKeyType.z, false]; } else if (version === network.zprvVersion) { return [network, HdKeyType.z, true]; } } throw new BitcoinError(BitcoinErrorCode.UnkownHdKeyVersion, version.toString()); } /** * Decodes an extended private key or public key from the * serialization format defined in BIP32. * * For example: * xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi * xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8 * * @remarks * * The value uses a prefix of xprv, yprv, or zprv and is Base58Check. * * ``` * The format includes: * [4 byte]: version * [1 byte]: depth * [4 byte]: parent fingerprint * [4 byte]: number * [32 byte]: chaincode * [33 byte]: key * ``` * * The 33-byte key values uses a 0x00 prefix plus the 32-byte private * key. * * @param input encoded input * * @throws {@link BitcoinError} throws when there is an invalid * encoding, bad checksum, or if you attempt to decode a public key. * * @returns an instance of the extended private key or public key */ public static decode(input: string): HdPrivateKey | HdPublicKey { const buf = Base58Check.decode(input); Iif (buf.length !== 78) { throw new BitcoinError(BitcoinErrorCode.InvalidHdEncoding, input); } const r = new BufferReader(buf); const version: number = r.readUInt32BE(); const depth = r.readUInt8(); const parentFingerprint = r.readBytes(4); const childNum = r.readUInt32BE(); const chaincode = r.readBytes(32); const rawkey = r.readBytes(33); const [network, type, isPrivate] = HdKeyCodec.decodeVersion(version); if (depth === 0 && !parentFingerprint.equals(Buffer.alloc(4))) { throw new BitcoinError(BitcoinErrorCode.InvalidHdEncoding, input); } if (depth === 0 && childNum !== 0) { throw new BitcoinError(BitcoinErrorCode.InvalidHdEncoding, input); } let key: HdPrivateKey | HdPublicKey; // private key if (isPrivate) { key = new HdPrivateKey(); // validate correct prefix if (rawkey[0] !== 0x00) { throw new BitcoinError(BitcoinErrorCode.InvalidHdEncoding, input); } // construct and validate private key Eif (key instanceof HdPrivateKey) { key.privateKey = new PrivateKey(rawkey.slice(1), network); } } // public key else Eif (!isPrivate) { key = new HdPublicKey(); // construct and validate public key Eif (key instanceof HdPublicKey) { key.publicKey = new PublicKey(rawkey, network); } } // unknown key type else { throw new BitcoinError(BitcoinErrorCode.UnkownHdKeyVersion, input); } // apply the rest of the values key.type = type; key.depth = depth; key.parentFingerprint = parentFingerprint; key.number = childNum; key.chainCode = chaincode; return key; } /** * Encodes either a {@link HdPrivateKey} or {@link HdPublicKey} * according to BIP32. * * For example: * xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi * xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8 * * @remarks * The value uses a prefix of xprv, yprv, or zprv and is Base58Check * encoded. * * The format includes: * ``` * [4 byte]: version * [1 byte]: depth * [4 byte]: parent fingerprint * [4 byte]: number * [32 byte]: chaincode * [33 byte]: key * ``` * * For private keys, the 33-byte key value is prefixed with 0x00. * * @returns Base58Check encoded extended key */ public static encode(key: HdPrivateKey | HdPublicKey) { const w = new BufferWriter(Buffer.alloc(78)); w.writeUInt32BE(key.version); w.writeUInt8(key.depth); w.writeBytes(key.parentFingerprint); w.writeUInt32BE(key.number); w.writeBytes(key.chainCode); if (key instanceof HdPrivateKey) { w.writeUInt8(0); w.writeBytes(key.privateKey.toBuffer()); } else { w.writeBytes(key.publicKey.toBuffer()); } const buf = w.toBuffer(); return Base58Check.encode(buf); } } |