Skip to content

Commit ac6b50f

Browse files
committed
feat: working parser (at least for tx requests)
1 parent 2694323 commit ac6b50f

File tree

3 files changed

+78
-21
lines changed

3 files changed

+78
-21
lines changed

bin/inspect2.js

+12-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,18 @@ async function main() {
1313
let hex = Fs.readFileSync(filepath, "utf8");
1414
hex = hex.trim();
1515

16-
let txInfo = Tx.parseUnknown(hex);
17-
Tx._debugPrint(txInfo);
16+
let txInfo;
17+
try {
18+
txInfo = Tx.parseUnknown(hex);
19+
} catch (e) {
20+
//@ts-ignore
21+
console.log(e.transaction);
22+
throw e;
23+
}
24+
25+
console.info(txInfo);
26+
let out = Tx._debugPrint(txInfo);
27+
console.info(out);
1828
}
1929

2030
main()

dashtx.js

+38-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
* @prop {Uint32} MAX_INPUT_PAD - 2 (possible ASN.1 BigInt padding)
99
* @prop {Uint32} MAX_INPUT_SIZE - 149 each (with padding)
1010
* @prop {Uint32} OUTPUT_SIZE - 34 each
11-
* @prop {Uint32} SIGHASH_ALL - 0x01
11+
* @prop {Uint32|0x00000001} SIGHASH_ALL - 0x01
12+
* @prop {Uint32|0x00000080} SIGHASH_ANYONECANPAY - 0x80
1213
* @prop {TxAppraise} appraise
1314
* @prop {TxAppraiseCounts} _appraiseCounts
1415
* @prop {TxAppraiseMemos} _appraiseMemos
@@ -22,6 +23,10 @@
2223
* @prop {TxGetId} getId - only useful for fully signed tx
2324
* @prop {TxHashPartial} hashPartial - useful for computing sigs
2425
* @prop {TxCreateLegacyTx} createLegacyTx
26+
* @prop {TxParseUnknown} parseUnknown
27+
* @prop {TxParseRequest} parseRequest
28+
* @prop {TxParseHashable} parseHashable
29+
* @prop {TxParseSigned} parseSigned
2530
* @prop {TxSortBySats} sortBySatsAsc
2631
* @prop {TxSortBySats} sortBySatsDsc
2732
* @prop {TxSortInputs} sortInputs
@@ -32,12 +37,14 @@
3237
* @prop {Function} _create
3338
* @prop {Function} _createInsufficientFundsError
3439
* @prop {Function} _createMemoScript
40+
* @prop {Function} _debugPrint
3541
* @prop {Function} _hash
3642
* @prop {Function} _hashAndSignAll
3743
* @prop {Function} _legacyMustSelectInputs
3844
* @prop {Function} _legacySelectOptimalUtxos
3945
* @prop {Function} _packInputs
4046
* @prop {Function} _packOutputs
47+
* @prop {Function} _parse
4148
*/
4249

4350
/**
@@ -153,6 +160,7 @@ var DashTx = ("object" === typeof module && exports) || {};
153160
25; // lockscript
154161

155162
Tx.SIGHASH_ALL = 0x01;
163+
Tx.SIGHASH_ANYONECANPAY = 0x80;
156164

157165
Tx.appraise = function (txInfo) {
158166
let extraSize = Tx._appraiseMemos(txInfo.outputs);
@@ -1368,8 +1376,8 @@ var DashTx = ("object" === typeof module && exports) || {};
13681376
let sigHashTypeHex = TxUtils._toUint32LE(sigHashType);
13691377
txSignable = `${txSignable}${sigHashTypeHex}`;
13701378
}
1371-
//console.log("Signable Tx Hex");
1372-
//console.log(txSignable);
1379+
console.log("Signable Tx Hex");
1380+
console.log(txSignable);
13731381

13741382
let u8 = Tx.utils.hexToBytes(txSignable);
13751383
//console.log("Signable Tx Buffer");
@@ -1609,9 +1617,10 @@ if ("object" === typeof module) {
16091617
// Type Aliases
16101618

16111619
/** @typedef {Number} Float64 */
1612-
/** @typedef {Number} Uint53 */
1613-
/** @typedef {Number} Uint32 */
16141620
/** @typedef {Number} Uint8 */
1621+
/** @typedef {Number} Uint32 */
1622+
/** @typedef {Number} Uint53 */
1623+
/** @typedef {String} Hex */
16151624
/** @typedef {Uint8Array} TxPrivateKey */
16161625
/** @typedef {Uint8Array} TxPublicKey */
16171626
/** @typedef {Uint8Array} TxSignature */
@@ -1878,6 +1887,30 @@ if ("object" === typeof module) {
18781887
* @returns {Promise<TxInfo>}
18791888
*/
18801889

1890+
/**
1891+
* @callback TxParseRequest
1892+
* @param {Hex} hex - a tx request with unsigned or partially signed inputs
1893+
* @returns {TxInfo}
1894+
*/
1895+
1896+
/**
1897+
* @callback TxParseHashable
1898+
* @param {Hex} hex - a ready-to-sign tx with input script and trailing sighash byte
1899+
* @returns {TxInfo}
1900+
*/
1901+
1902+
/**
1903+
* @callback TxParseSigned
1904+
* @param {Hex} hex - a fully signed, ready-to-broadcast transaction
1905+
* @returns {TxInfo}
1906+
*/
1907+
1908+
/**
1909+
* @callback TxParseUnknown
1910+
* @param {Hex} hex - a tx request, hashable tx, or signed tx
1911+
* @returns {TxInfo}
1912+
*/
1913+
18811914
/**
18821915
* @callback TxReverseHex
18831916
* @param {String} hex

txparser.js

+28-14
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,15 @@ Tx.parseUnknown = function (txHex) {
1818
//@ts-ignore - trust me bro, it's an error
1919
let err = e;
2020
let msg = err.message;
21+
let out = "";
22+
try {
23+
out = Tx._debugPrint(txInfo);
24+
} catch (e) {
25+
//@ts-ignore
26+
out = e.message;
27+
}
2128
Object.assign(err, {
22-
message: Tx._debugPrint(txInfo),
29+
message: out,
2330
code: "E_TX_PARSE",
2431
transaction: txInfo,
2532
});
@@ -47,37 +54,31 @@ Tx._parse = function (tx, hex) {
4754
tx.offset += 8;
4855
tx.version = version;
4956
tx.versionHex = versionHex;
50-
tx.inputs = [];
51-
tx.outputs = [];
5257

5358
let [numInputs, numInputsSize] = parseVarIntHex(hex, tx.offset);
5459
tx.offset += numInputsSize;
5560
tx.numInputsHex = numInputs.toString(16);
5661
tx.numInputsHex = tx.numInputsHex.padStart(2, "0");
5762
tx.numInputs = numInputs;
5863

64+
tx.inputs = [];
5965
for (let i = 0; i < numInputs; i += 1) {
6066
let input = {};
6167
tx.inputs.push(input);
6268

6369
input.txidHex = hex.substr(tx.offset, 64);
64-
input.txid = Tx.utils.reverseHex(tx.txidHex);
70+
input.txid = Tx.utils.reverseHex(input.txidHex);
71+
input.txId = input.txid; // TODO
6572
tx.offset += 64;
6673

6774
input.outputIndexHex = hex.substr(tx.offset, 8);
6875
let outputIndexHexLe = Tx.utils.reverseHex(input.outputIndexHex);
6976
input.outputIndex = parseInt(outputIndexHexLe, 16);
70-
// console.info(
71-
// ` ${outputIndexHex} # Previous Output index (${outputIndex})`,
72-
// );
7377
tx.offset += 8;
7478

7579
// TODO VarInt
7680
input.scriptSizeHex = hex.substr(tx.offset, 2);
7781
input.scriptSize = parseInt(input.scriptSizeHex, 16);
78-
// console.info(
79-
// ` ${input.scriptSizeHex} # Script Size (${input.scriptSize} bytes)`,
80-
// );
8182
tx.offset += 2;
8283

8384
input.script = "";
@@ -204,13 +205,14 @@ Tx._parse = function (tx, hex) {
204205
tx.numOutputsHex = tx.numOutputsHex.padStart(2, "0");
205206
tx.numOutputs = numOutputs;
206207

208+
tx.outputs = [];
207209
for (let i = 0; i < tx.numOutputs; i += 1) {
208210
let output = {};
209211
tx.outputs.push(output);
210212

211213
output.satoshisHex = hex.substr(tx.offset, 16);
212214
tx.offset += 16;
213-
let satsHex = Tx.utils.reverseHex(tx.satoshisHex);
215+
let satsHex = Tx.utils.reverseHex(output.satoshisHex);
214216
output.satoshis = parseInt(satsHex, 16);
215217
tx.totalSatoshis += output.satoshis;
216218
// console.info(
@@ -230,6 +232,7 @@ Tx._parse = function (tx, hex) {
230232

231233
output.scriptTypeHex = output.script.slice(0, 2);
232234
output.scriptType = parseInt(output.scriptTypeHex, 16);
235+
output.pubKeyHash = "";
233236
output.memo = "";
234237
output.message = "";
235238
if (output.scriptType === OP_RETURN) {
@@ -242,6 +245,9 @@ Tx._parse = function (tx, hex) {
242245
} catch (e) {
243246
output.message = "<non-UTF-8 bytes>";
244247
}
248+
} else {
249+
// TODO check the script type
250+
output.pubKeyHash = output.script.slice(6, -4);
245251
}
246252
}
247253

@@ -328,7 +334,7 @@ Tx._debugPrint = function (tx) {
328334
lines.push(
329335
`${tx.numInputsHex} # Inputs (${tx.numInputs})`,
330336
);
331-
for (let i = 0; i < tx.inputs.length; i += 1) {
337+
for (let i = 0; i < tx.inputs?.length; i += 1) {
332338
let count = i + 1;
333339
let input = tx.inputs[i];
334340
lines.push("");
@@ -338,18 +344,26 @@ Tx._debugPrint = function (tx) {
338344
let txid2 = input.txidHex.slice(16, 32);
339345
let txid3 = input.txidHex.slice(32, 48);
340346
let txid4 = input.txidHex.slice(48, 64);
341-
lines.push(` ${txid1} # Previous Output TX ID"`);
347+
lines.push(` ${txid1} # Previous Output TX ID`);
342348
lines.push(` ${txid2}`);
343349
lines.push(` ${txid3}`);
344350
lines.push(` ${txid4}`);
351+
352+
lines.push(
353+
` ${input.outputIndexHex} # Previous Output index (${input.outputIndex})`,
354+
);
355+
356+
lines.push(
357+
` ${input.scriptSizeHex} # Script Size (${input.scriptSize} bytes)`,
358+
);
345359
}
346360

347361
// outputs
348362
lines.push("");
349363
lines.push(
350364
`${tx.numOutputsHex} # Outputs (${tx.numOutputs})`,
351365
);
352-
for (let i = 0; i < tx.outputs.length; i += 1) {
366+
for (let i = 0; i < tx.outputs?.length; i += 1) {
353367
let count = i + 1;
354368
let output = tx.outputs[i];
355369

0 commit comments

Comments
 (0)