@alexbosworth/blockchain 3.0.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +132 -0
  3. package/addresses/bech32_type.js +52 -0
  4. package/addresses/decode_bech32.js +79 -0
  5. package/addresses/decode_bech32_address.js +86 -0
  6. package/addresses/index.js +2 -1
  7. package/addresses/modify_bech32_accumulator.js +24 -0
  8. package/hashes/id_for_transaction_components.js +2 -0
  9. package/index.js +16 -0
  10. package/package.json +1 -1
  11. package/script/index.js +14 -1
  12. package/script/p2pkh_output_script.js +37 -0
  13. package/script/p2sh_output_script.js +35 -0
  14. package/script/p2tr_output_script.js +32 -0
  15. package/script/p2wpkh_output_script.js +32 -0
  16. package/script/p2wsh_output_script.js +32 -0
  17. package/script/script_elements_as_output.js +41 -0
  18. package/script/script_elements_as_script.js +3 -22
  19. package/test/addresses/test_bech32_type.js +29 -0
  20. package/test/addresses/test_decode_bech32.js +49 -0
  21. package/test/addresses/test_decode_bech32_address.js +188 -0
  22. package/test/script/test_p2pkh_output_script.js +41 -0
  23. package/test/script/test_p2sh_output_script.js +41 -0
  24. package/test/script/test_p2tr_output_script.js +43 -0
  25. package/test/script/test_p2wpkh_output_script.js +41 -0
  26. package/test/script/test_p2wsh_output_script.js +43 -0
  27. package/test/transactions/test_id_for_transaction.js +72 -0
  28. package/test/transactions/test_unsigned_tx_from_psbt.js +72 -0
  29. package/transactions/id_for_transaction.js +39 -0
  30. package/transactions/index.js +4 -0
  31. package/transactions/parse_transaction.js +9 -11
  32. package/transactions/unsigned_tx_from_psbt.js +47 -0
  33. /package/test/addresses/{decode_base58_address.js → test_decode_base58_address.js} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Versions
2
2
 
3
+ ## 3.2.0
4
+
5
+ - `decode_bech32_address.js`: Add method to decode a bech32/bech32m address
6
+ - `id_for_transaction.js`: Add method to derive the standard tx id for a raw tx
7
+
8
+ ## 3.1.0
9
+
10
+ - `p2pkhOutputScript`: Add method to get an output script for a p2wpkh hash
11
+ - `p2shOutputScript`: Add method to get an output script for a p2sh hash
12
+ - `p2trOutputScript`: Add method to get an output script for a p2tr hash
13
+ - `p2wpkhOutputScript`: Add method to get an output script for a p2wpkh hash
14
+ - `p2wshOutputScript`: Add method to get an output script for a p2wsh hash
15
+ - `unsignedTxFromPsbt`: Add method to get the unsigned tx out of a PSBT
16
+
3
17
  ## 3.0.0
4
18
 
5
19
  - `decodeBase58Address`: Add method to convert b58 address to hash and version
package/README.md CHANGED
@@ -73,6 +73,24 @@ Derive output hash and version data from a base58 address string
73
73
  version: <Script Version Byte Number>
74
74
  }
75
75
 
76
+ ### decodeBech32Address
77
+
78
+ Decode a bech32 address string to derive the address details
79
+
80
+ {
81
+ address: <Bech32 Encoded Address String>
82
+ }
83
+
84
+ @throws
85
+ <Error>
86
+
87
+ @returns
88
+ {
89
+ data: <Output Data Buffer Object>
90
+ prefix: <Human Readable Prefix String>
91
+ version: <Witness Version Number>
92
+ }
93
+
76
94
  ### idForBlock
77
95
 
78
96
  Get an id for a block: the double sha256 hash of the block header
@@ -89,10 +107,28 @@ Get an id for a block: the double sha256 hash of the block header
89
107
  id: <Block Id Hex Encoded String>
90
108
  }
91
109
 
110
+ ### idForTransaction
111
+
112
+ Derive the standard transaction id for a raw serialized tx
113
+
114
+ {
115
+ transaction: <Hex Encoded Transaction String>
116
+ }
117
+
118
+ @throws
119
+ <Error>
120
+
121
+ @returns
122
+ {
123
+ id: <Transaction Id Hex Encoded String>
124
+ }
125
+
92
126
  ### idForTransactionComponents
93
127
 
94
128
  Determine a transaction id from transaction components
95
129
 
130
+ Note: remember the input hash is the reversed byte order of a normal tx id
131
+
96
132
  {
97
133
  inputs: [{
98
134
  hash: <Spending Internal Byte Order Transaction Id Buffer Object>
@@ -149,6 +185,86 @@ Convert a number to compact size integer serialization
149
185
  encoded: <Serialized Compact Integer Buffer Object>
150
186
  }
151
187
 
188
+ ### p2pkhOutputScript
189
+
190
+ Get a Pay To Witness Public Key Hash Output Script
191
+
192
+ {
193
+ hash: <Public Key Hash Buffer Object>
194
+ }
195
+
196
+ @throws
197
+ <Error>
198
+
199
+ @returns
200
+ {
201
+ script: <Output Script Buffer Object>
202
+ }
203
+
204
+ ### p2shOutputScript
205
+
206
+ Get a Pay To Script Hash Output Script
207
+
208
+ {
209
+ hash: <Script Hash Buffer Object>
210
+ }
211
+
212
+ @throws
213
+ <Error>
214
+
215
+ @returns
216
+ {
217
+ script: <Output Script Buffer Object>
218
+ }
219
+
220
+ ### p2trOutputScript
221
+
222
+ Get a Pay To Taproot Output Script
223
+
224
+ {
225
+ hash: <Taproot Hash Buffer Object>
226
+ }
227
+
228
+ @throws
229
+ <Error>
230
+
231
+ @returns
232
+ {
233
+ script: <Output Script Buffer Object>
234
+ }
235
+
236
+ ### p2wpkhOutputScript
237
+
238
+ Get a Pay To Witness Public Key Hash Output Script
239
+
240
+ {
241
+ hash: <Witness Public Key Hash Buffer Object>
242
+ }
243
+
244
+ @throws
245
+ <Error>
246
+
247
+ @returns
248
+ {
249
+ script: <Output Script Buffer Object>
250
+ }
251
+
252
+ ### p2wshOutputScript
253
+
254
+ Get a Pay To Witness Script Hash Output Script
255
+
256
+ {
257
+ hash: <Witness Script Hash Buffer Object>
258
+ }
259
+
260
+ @throws
261
+ <Error>
262
+
263
+ @returns
264
+ {
265
+ script: <Output Script Buffer Object>
266
+ }
267
+
152
268
  ### previousBlockId
153
269
 
154
270
  Given a raw block, return the previous block id
@@ -218,3 +334,19 @@ Map array of script buffer elements to a fully formed script
218
334
  {
219
335
  script: <Script Hex String>
220
336
  }
337
+
338
+ ### unsignedTxFromPsbt
339
+
340
+ Get the unsigned transaction out of a PSBT
341
+
342
+ {
343
+ psbt: <PSBT Hex String>
344
+ }
345
+
346
+ @throws
347
+ <Error>
348
+
349
+ @returns
350
+ {
351
+ transaction: <Unsigned Transaction Buffer Object>
352
+ }
@@ -0,0 +1,52 @@
1
+ const modifyBech32Accumulator = require('./modify_bech32_accumulator');
2
+
3
+ const codeForBech32 = 1;
4
+ const codeForBech32m = 0x2bc830a3;
5
+ const {from} = Array;
6
+ const separator = 0;
7
+
8
+ /** Determine the type of bech32 data being represented and verify checksum
9
+
10
+ {
11
+ prefix: <Lowercase Human Readable Prefix String>
12
+ words: [<Bech32 5-Bit Data Number>]
13
+ }
14
+
15
+ @throws
16
+ <Error>
17
+
18
+ @returns
19
+ {
20
+ type: <Bech32 Type String>
21
+ }
22
+ */
23
+ module.exports = ({prefix, words}) => {
24
+ let accumulator = 1;
25
+
26
+ // Collect the high bits
27
+ const highBits = from(
28
+ {length: prefix.length},
29
+ (_, i) => prefix.charCodeAt(i) >> 5
30
+ );
31
+
32
+ // Collect the low bits
33
+ const lowBits = from(
34
+ {length: prefix.length},
35
+ (_, i) => prefix.charCodeAt(i) & 31
36
+ );
37
+
38
+ [...highBits, separator, ...lowBits, ...words].forEach(v => {
39
+ return accumulator = modifyBech32Accumulator(accumulator) ^ (v & 31);
40
+ });
41
+
42
+ switch (accumulator) {
43
+ case codeForBech32:
44
+ return {type: 'bech32'};
45
+
46
+ case codeForBech32m:
47
+ return {type: 'bech32m'};
48
+
49
+ default:
50
+ throw new Error('UnexpectedChecksumValueForBech32DataAndPrefix');
51
+ }
52
+ };
@@ -0,0 +1,79 @@
1
+ const bech32Type = require('./bech32_type');
2
+
3
+ const alphabet = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';
4
+ const knownPrefixes = ['bc', 'tb', 'bcrt'];
5
+ const lengthSeparator = 1;
6
+ const lengthChecksum = 6;
7
+ const prefixDividerCharacter = '1';
8
+ const maximumCharactersLength = 90;
9
+ const minimumCharactersLength = 8;
10
+ const minimumDividerPosition = 1;
11
+ const notFoundIndex = -1;
12
+ const removeChecksum = words => words.slice(0, -6);
13
+ const split = (str, index) => [str.slice(0, index), str.slice(index + 1)];
14
+
15
+ /** Decode a Bech32/Bech32m encoded string and validate/remove checksum
16
+
17
+ {
18
+ encoded: <Bech32/Bech32m Encoded String
19
+ }
20
+
21
+ @throws
22
+ <Error>
23
+
24
+ @returns
25
+ {
26
+ prefix: <Human Readable Part String>
27
+ type: <Bech32 Type String>
28
+ words: [<Data Words Number>]
29
+ }
30
+ */
31
+ module.exports = ({encoded}) => {
32
+ if (typeof encoded !== 'string') {
33
+ throw new Error('ExpectedEncodedStringToDecodeBech32String');
34
+ }
35
+
36
+ if (encoded.length > maximumCharactersLength) {
37
+ throw new Error('ExpectedShorterBech32EncodedStringToDecode');
38
+ }
39
+
40
+ if (encoded.length < minimumCharactersLength) {
41
+ throw new Error('ExpectedLongerBech32EncodedStringToDecode');
42
+ }
43
+
44
+ const converted = encoded.toLowerCase();
45
+
46
+ if (encoded !== converted && encoded !== encoded.toUpperCase()) {
47
+ throw new Error('ExpectedSingleCasingStyleForBech32EncodedString');
48
+ }
49
+
50
+ // Find the last index of the prefix divider character
51
+ const dividerPosition = converted.lastIndexOf(prefixDividerCharacter);
52
+
53
+ if (dividerPosition < minimumDividerPosition) {
54
+ throw new Error('ExpectedLaterDividerPositionForBech32String');
55
+ }
56
+
57
+ if (converted.length - dividerPosition < lengthSeparator + lengthChecksum) {
58
+ throw new Error('ExpectedChecksumDataForBech32String');
59
+ }
60
+
61
+ // Divide the data from the human readable prefix
62
+ const [prefix, data] = split(converted, dividerPosition);
63
+
64
+ // Make sure the prefix is a known one
65
+ if (!knownPrefixes.includes(prefix)) {
66
+ throw new Error('ExpectedKnownBech32AddressPrefixToDecodeBech32');
67
+ }
68
+
69
+ // Convert data part into bech32 words
70
+ const words = [...data].map(char => alphabet.indexOf(char));
71
+
72
+ if (words.includes(notFoundIndex)) {
73
+ throw new Error('ExpectedAllKnownCharactersForBech32EncodedString');
74
+ }
75
+
76
+ const {type} = bech32Type({prefix, words});
77
+
78
+ return {prefix, type, words: removeChecksum(words)};
79
+ };
@@ -0,0 +1,86 @@
1
+ const decodeBech32 = require('./decode_bech32');
2
+
3
+ const bitsPerBech32Word = 5;
4
+ const bitsPerByte = 8;
5
+ const byteMask = 0xff;
6
+ const bytesArrayAsBuffer = arr => Buffer.from(arr);
7
+ const knownV0ProgramLengths = [20, 32];
8
+ const maxProgLength = 40;
9
+ const maximumSegwitVersion = 16;
10
+ const minimumProgLength = 2;
11
+ const typeBech32V1 = 'bech32m';
12
+ const typeInitialSegwit = 'bech32';
13
+ const versionInitialSegwit = 0;
14
+
15
+ /** Decode a bech32 address string to derive the address details
16
+
17
+ {
18
+ address: <Bech32 Encoded Address String>
19
+ }
20
+
21
+ @throws
22
+ <Error>
23
+
24
+ @returns
25
+ {
26
+ prefix: <Human Readable Prefix String>
27
+ program: <Output Data Buffer Object>
28
+ version: <Witness Version Number>
29
+ }
30
+ */
31
+ module.exports = ({address}) => {
32
+ const {prefix, type, words} = decodeBech32({encoded: address});
33
+
34
+ if (!words.length) {
35
+ throw new Error('ExpectedNonEmptyWitnessCommitmentDataInBech32Address');
36
+ }
37
+
38
+ const [version, ...data] = words;
39
+
40
+ if (version > maximumSegwitVersion) {
41
+ throw new Error('UnexpectedHighSegwitWitnessVersion');
42
+ }
43
+
44
+ if (version === versionInitialSegwit && type !== typeInitialSegwit) {
45
+ throw new Error('ExpectedInitialSegwitTypeForInitialSegwitVersion');
46
+ }
47
+
48
+ if (version !== versionInitialSegwit && type !== typeBech32V1) {
49
+ throw new Error('ExpectedUseOfLaterVersionBech32PostInitialSegwit');
50
+ }
51
+
52
+ let bits = 0;
53
+ let carry = 0;
54
+ const program = [];
55
+
56
+ // Convert the 5 bit bech32 words into 8 bit (ie bytes) data
57
+ data.forEach(value => {
58
+ carry = (carry << bitsPerBech32Word) | value;
59
+
60
+ bits += bitsPerBech32Word;
61
+
62
+ while (bits >= bitsPerByte) {
63
+ bits -= bitsPerByte;
64
+
65
+ program.push((carry >> bits) & byteMask);
66
+ }
67
+ });
68
+
69
+ if (bits >= bitsPerBech32Word) {
70
+ throw new Error('ExpectedNoPaddingOnBech32Address');
71
+ };
72
+
73
+ if (((carry << (bitsPerByte - bits)) & byteMask) !== 0) {
74
+ throw new Error('UnexpectedNonZeroPadding');
75
+ }
76
+
77
+ if (program.length < minimumProgLength || program.length > maxProgLength) {
78
+ throw new Error('UnexpectedSizeOfBech32AddressProgram');
79
+ }
80
+
81
+ if (version === 0 && !knownV0ProgramLengths.includes(program.length)) {
82
+ throw new Error('UnexpectedBech32AddressProgramSizeForV0Address')
83
+ }
84
+
85
+ return {version, prefix, program: bytesArrayAsBuffer(program)};
86
+ };
@@ -1,3 +1,4 @@
1
1
  const decodeBase58Address = require('./decode_base58_address');
2
+ const decodeBech32Address = require('./decode_bech32_address');
2
3
 
3
- module.exports = {decodeBase58Address};
4
+ module.exports = {decodeBase58Address, decodeBech32Address};
@@ -0,0 +1,24 @@
1
+ const generatedModifierValues = [[0x01, 0x3b6a57b2], [0x02, 0x26508e6d], [0x04, 0x1ea119fa], [0x08, 0x3d4233dd], [0x10, 0x2a1462b3]];
2
+ const lowerBitsBitMask = 0x1ffffff;
3
+
4
+ /** Update the 30 bit accumulator with Bech32 precomputed values
5
+
6
+ accumulator: <Current Accumulator 32-Bit Range Integer Number>
7
+
8
+ @returns
9
+ <Bech32 Generator Constants Modified Number>
10
+ */
11
+ module.exports = accumulator => {
12
+ // Take the top 5 bits of the accumulator value (30 - 5 = 25)
13
+ const topBits = accumulator >> 25;
14
+
15
+ // Shift the lower 25 bits up by 5
16
+ let modified = ((accumulator & lowerBitsBitMask) << 5) >>> 0;
17
+
18
+ // Based on bit masks, apply the appropriate precomputed Bech32 values
19
+ generatedModifierValues
20
+ .filter(([mask]) => topBits & mask)
21
+ .forEach(([, modifier]) => modified ^= modifier);
22
+
23
+ return modified;
24
+ };
@@ -12,6 +12,8 @@ const sha256 = preimage => createHash('sha256').update(preimage).digest();
12
12
 
13
13
  /** Determine a transaction id from transaction components
14
14
 
15
+ Note: remember the input hash is the reversed byte order of a normal tx id
16
+
15
17
  {
16
18
  inputs: [{
17
19
  hash: <Spending Internal Byte Order Transaction Id Buffer Object>
package/index.js CHANGED
@@ -1,25 +1,41 @@
1
1
  const {compactIntAsNumber} = require('./numbers');
2
2
  const {componentsOfTransaction} = require('./transactions');
3
3
  const {decodeBase58Address} = require('./addresses');
4
+ const {decodeBech32Address} = require('./addresses');
4
5
  const {idForBlock} = require('./hashes');
6
+ const {idForTransaction} = require('./transactions');
5
7
  const {idForTransactionComponents} = require('./hashes');
6
8
  const {noLocktimeIdForTransaction} = require('./transactions');
7
9
  const {numberAsCompactInt} = require('./numbers');
10
+ const {p2pkhOutputScript} = require('./script');
11
+ const {p2shOutputScript} = require('./script');
12
+ const {p2trOutputScript} = require('./script');
13
+ const {p2wpkhOutputScript} = require('./script');
14
+ const {p2wshOutputScript} = require('./script');
8
15
  const {previousBlockId} = require('./hashes');
9
16
  const {queryTransactions} = require('./transactions');
10
17
  const {scriptAsScriptElements} = require('./script');
11
18
  const {scriptElementsAsScript} = require('./script');
19
+ const {unsignedTxFromPsbt} = require('./transactions');
12
20
 
13
21
  module.exports = {
14
22
  compactIntAsNumber,
15
23
  componentsOfTransaction,
16
24
  decodeBase58Address,
25
+ decodeBech32Address,
17
26
  idForBlock,
27
+ idForTransaction,
18
28
  idForTransactionComponents,
19
29
  noLocktimeIdForTransaction,
20
30
  numberAsCompactInt,
31
+ p2pkhOutputScript,
32
+ p2shOutputScript,
33
+ p2trOutputScript,
34
+ p2wpkhOutputScript,
35
+ p2wshOutputScript,
21
36
  previousBlockId,
22
37
  queryTransactions,
23
38
  scriptAsScriptElements,
24
39
  scriptElementsAsScript,
40
+ unsignedTxFromPsbt,
25
41
  };
package/package.json CHANGED
@@ -19,5 +19,5 @@
19
19
  "scripts": {
20
20
  "test": "npx nyc@17.1.0 node --experimental-test-coverage --test test/addresses/*.js test/hashes/*.js test/numbers/*.js test/script/*.js test/transactions/*.js"
21
21
  },
22
- "version": "3.0.0"
22
+ "version": "3.2.0"
23
23
  }
package/script/index.js CHANGED
@@ -1,4 +1,17 @@
1
+ const p2pkhOutputScript = require('./p2pkh_output_script');
2
+ const p2shOutputScript = require('./p2sh_output_script');
3
+ const p2trOutputScript = require('./p2tr_output_script');
4
+ const p2wpkhOutputScript = require('./p2wpkh_output_script');
5
+ const p2wshOutputScript = require('./p2wsh_output_script');
1
6
  const scriptAsScriptElements = require('./script_as_script_elements');
2
7
  const scriptElementsAsScript = require('./script_elements_as_script');
3
8
 
4
- module.exports = {scriptAsScriptElements, scriptElementsAsScript};
9
+ module.exports = {
10
+ p2pkhOutputScript,
11
+ p2shOutputScript,
12
+ p2trOutputScript,
13
+ p2wpkhOutputScript,
14
+ p2wshOutputScript,
15
+ scriptAsScriptElements,
16
+ scriptElementsAsScript,
17
+ };
@@ -0,0 +1,37 @@
1
+ const scriptElementsAsOutput = require('./script_elements_as_output');
2
+
3
+ const expectedHashLength = 20;
4
+ const OP_CHECKSIG = 0xac;
5
+ const OP_DUP = 0x76;
6
+ const OP_EQUALVERIFY = 0x88;
7
+ const OP_HASH160 = 0xa9;
8
+
9
+ /** Get a Pay To Public Key Hash Output Script
10
+
11
+ {
12
+ hash: <Public Key Hash Buffer Object>
13
+ }
14
+
15
+ @throws
16
+ <Error>
17
+
18
+ @returns
19
+ {
20
+ script: <Output Script Buffer Object>
21
+ }
22
+ */
23
+ module.exports = ({hash}) => {
24
+ if (!hash) {
25
+ throw new Error('ExpectedPublicKeyHashToDeriveOutputScript');
26
+ }
27
+
28
+ if (hash.length !== expectedHashLength) {
29
+ throw new Error('UnexpectedHashLengthForPublicKeyHashOutputScript');
30
+ }
31
+
32
+ const {output} = scriptElementsAsOutput({
33
+ elements: [OP_DUP, OP_HASH160, hash, OP_EQUALVERIFY, OP_CHECKSIG],
34
+ });
35
+
36
+ return {script: output};
37
+ };
@@ -0,0 +1,35 @@
1
+ const scriptElementsAsOutput = require('./script_elements_as_output');
2
+
3
+ const expectedHashLength = 20;
4
+ const OP_EQUAL = 0x87;
5
+ const OP_HASH160 = 0xa9;
6
+
7
+ /** Get a Pay To Script Hash Output Script
8
+
9
+ {
10
+ hash: <Script Hash Buffer Object>
11
+ }
12
+
13
+ @throws
14
+ <Error>
15
+
16
+ @returns
17
+ {
18
+ script: <Output Script Buffer Object>
19
+ }
20
+ */
21
+ module.exports = ({hash}) => {
22
+ if (!hash) {
23
+ throw new Error('ExpectedScriptHashToDerivePayToScriptOutputScript');
24
+ }
25
+
26
+ if (hash.length !== expectedHashLength) {
27
+ throw new Error('UnexpectedHashLengthForPayToScriptHashOutputScript');
28
+ }
29
+
30
+ const {output} = scriptElementsAsOutput({
31
+ elements: [OP_HASH160, hash, OP_EQUAL],
32
+ });
33
+
34
+ return {script: output};
35
+ };
@@ -0,0 +1,32 @@
1
+ const scriptElementsAsOutput = require('./script_elements_as_output');
2
+
3
+ const expectedHashLength = 32;
4
+ const OP_1 = 0x51;
5
+
6
+ /** Get a Pay To Taproot Output Script
7
+
8
+ {
9
+ hash: <Taproot Hash Buffer Object>
10
+ }
11
+
12
+ @throws
13
+ <Error>
14
+
15
+ @returns
16
+ {
17
+ script: <Output Script Buffer Object>
18
+ }
19
+ */
20
+ module.exports = ({hash}) => {
21
+ if (!hash) {
22
+ throw new Error('ExpectedTaprootHashToDeriveOutputScript');
23
+ }
24
+
25
+ if (hash.length !== expectedHashLength) {
26
+ throw new Error('ExpectedKnownLengthTaprootHashForOutputScript');
27
+ }
28
+
29
+ const {output} = scriptElementsAsOutput({elements: [OP_1, hash]});
30
+
31
+ return {script: output};
32
+ };
@@ -0,0 +1,32 @@
1
+ const scriptElementsAsOutput = require('./script_elements_as_output');
2
+
3
+ const expectedHashLength = 20;
4
+ const OP_0 = 0x00;
5
+
6
+ /** Get a Pay To Witness Public Key Hash Output Script
7
+
8
+ {
9
+ hash: <Witness Public Key Hash Buffer Object>
10
+ }
11
+
12
+ @throws
13
+ <Error>
14
+
15
+ @returns
16
+ {
17
+ script: <Output Script Buffer Object>
18
+ }
19
+ */
20
+ module.exports = ({hash}) => {
21
+ if (!hash) {
22
+ throw new Error('ExpectedWitnessPublicKeyHashToDeriveOutputScript');
23
+ }
24
+
25
+ if (hash.length !== expectedHashLength) {
26
+ throw new Error('ExpectedKnownLengthWitnessPublicKeyHashForOutputScript');
27
+ }
28
+
29
+ const {output} = scriptElementsAsOutput({elements: [OP_0, hash]});
30
+
31
+ return {script: output};
32
+ };
@@ -0,0 +1,32 @@
1
+ const scriptElementsAsOutput = require('./script_elements_as_output');
2
+
3
+ const expectedHashLength = 32;
4
+ const OP_0 = 0x00;
5
+
6
+ /** Get a Pay To Witness Script Hash Output Script
7
+
8
+ {
9
+ hash: <Witness Script Hash Buffer Object>
10
+ }
11
+
12
+ @throws
13
+ <Error>
14
+
15
+ @returns
16
+ {
17
+ script: <Output Script Buffer Object>
18
+ }
19
+ */
20
+ module.exports = ({hash}) => {
21
+ if (!hash) {
22
+ throw new Error('ExpectedWitnessScriptHashToDeriveOutputScript');
23
+ }
24
+
25
+ if (hash.length !== expectedHashLength) {
26
+ throw new Error('ExpectedKnownLengthWitnessScriptHashForOutputScript');
27
+ }
28
+
29
+ const {output} = scriptElementsAsOutput({elements: [OP_0, hash]});
30
+
31
+ return {script: output};
32
+ };