Skip to content

Commit c3339ce

Browse files
committed
Add input index to console.log statements
1 parent cee4e3f commit c3339ce

File tree

3 files changed

+40
-29
lines changed

3 files changed

+40
-29
lines changed

packages/cashscript/src/debugging.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ const debugSingleScenario = (
6464
.filter((log) => executedDebugSteps.some((debugStep) => log.ip === debugStep.ip));
6565

6666
for (const log of executedLogs) {
67-
logConsoleLogStatement(log, executedDebugSteps, artifact);
67+
const inputIndex = extractInputIndexFromScenario(scenarioId);
68+
logConsoleLogStatement(log, executedDebugSteps, artifact, inputIndex);
6869
}
6970

7071
const lastExecutedDebugStep = executedDebugSteps[executedDebugSteps.length - 1];
@@ -139,6 +140,13 @@ const debugSingleScenario = (
139140
return fullDebugSteps;
140141
};
141142

143+
// Note: this relies on the naming convention that the scenario ID is of the form <name>_input<index>_evaluate
144+
const extractInputIndexFromScenario = (scenarioId: string): number => {
145+
const match = scenarioId.match(/_input(\d+)_/);
146+
if (!match) throw new Error(`Invalid scenario ID: ${scenarioId}`);
147+
return parseInt(match[1]);
148+
};
149+
142150
/* eslint-disable @typescript-eslint/indent */
143151
type VM = AuthenticationVirtualMachine<
144152
ResolvedTransactionCommon,
@@ -185,6 +193,7 @@ const logConsoleLogStatement = (
185193
log: LogEntry,
186194
debugSteps: AuthenticationProgramStateCommon[],
187195
artifact: Artifact,
196+
inputIndex: number,
188197
): void => {
189198
let line = `${artifact.contractName}.cash:${log.line}`;
190199
const decodedData = log.data.map((element) => {
@@ -194,7 +203,7 @@ const logConsoleLogStatement = (
194203
const transformedDebugStep = applyStackItemTransformations(element, debugStep);
195204
return decodeStackItem(element, transformedDebugStep.stack);
196205
});
197-
console.log(`${line} ${decodedData.join(' ')}`);
206+
console.log(`[Input #${inputIndex}] ${line} ${decodedData.join(' ')}`);
198207
};
199208

200209
const applyStackItemTransformations = (

packages/cashscript/test/debugging.test.ts

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ describe('Debugging tests', () => {
2828
.addOutput({ to: contractTestLogs.address, amount: 10000n });
2929

3030
// console.log(ownerSig, owner, num, beef, 1, "test", true);
31-
const expectedLog = new RegExp(`^Test.cash:10 0x[0-9a-f]{130} 0x${binToHex(alicePub)} 1000 0xbeef 1 test true$`);
31+
const expectedLog = new RegExp(`^\\[Input #0] Test.cash:10 0x[0-9a-f]{130} 0x${binToHex(alicePub)} 1000 0xbeef 1 test true$`);
3232
expect(transaction).toLog(expectedLog);
3333
});
3434

@@ -39,7 +39,7 @@ describe('Debugging tests', () => {
3939
.addOutput({ to: contractTestLogs.address, amount: 10000n });
4040

4141
// console.log(ownerSig, owner, num, beef, 1, "test", true);
42-
const expectedLog = new RegExp(`^Test.cash:10 0x[0-9a-f]{130} 0x${binToHex(alicePub)} 100 0xbeef 1 test true$`);
42+
const expectedLog = new RegExp(`^\\[Input #0] Test.cash:10 0x[0-9a-f]{130} 0x${binToHex(alicePub)} 100 0xbeef 1 test true$`);
4343
expect(transaction).toLog(expectedLog);
4444
});
4545

@@ -49,7 +49,7 @@ describe('Debugging tests', () => {
4949
.addInput(contractUtxo, contractTestLogs.unlock.transfer(new SignatureTemplate(incorrectPriv), 1000n))
5050
.addOutput({ to: contractTestLogs.address, amount: 10000n });
5151

52-
const expectedLog = new RegExp(`^Test.cash:10 0x[0-9a-f]{130} 0x${binToHex(alicePub)} 1000 0xbeef 1 test true$`);
52+
const expectedLog = new RegExp(`^\\[Input #0] Test.cash:10 0x[0-9a-f]{130} 0x${binToHex(alicePub)} 1000 0xbeef 1 test true$`);
5353
expect(transaction).not.toLog(expectedLog);
5454
});
5555

@@ -58,7 +58,7 @@ describe('Debugging tests', () => {
5858
.addInput(contractUtxo, contractTestLogs.unlock.secondFunction())
5959
.addOutput({ to: contractTestLogs.address, amount: 10000n });
6060

61-
expect(transaction).toLog(new RegExp('^Test.cash:16 Hello Second Function$'));
61+
expect(transaction).toLog(new RegExp('^\\[Input #0] Test.cash:16 Hello Second Function$'));
6262
expect(transaction).not.toLog(/Hello First Function/);
6363
});
6464

@@ -76,7 +76,7 @@ describe('Debugging tests', () => {
7676
.addInput(utxo, contractTestMultipleConstructorParameters.unlock.secondFunction())
7777
.addOutput({ to: contractTestMultipleConstructorParameters.address, amount: 10000n });
7878

79-
expect(transaction).toLog(new RegExp('^Test.cash:20 Hello Second Function$'));
79+
expect(transaction).toLog(new RegExp('^\\[Input #0] Test.cash:20 Hello Second Function$'));
8080
expect(transaction).not.toLog(/Hello First Function/);
8181
});
8282

@@ -85,18 +85,18 @@ describe('Debugging tests', () => {
8585
.addInput(contractUtxo, contractTestLogs.unlock.functionWithIfStatement(1n))
8686
.addOutput({ to: contractTestLogs.address, amount: 10000n });
8787

88-
expect(transaction1).toLog(new RegExp('^Test.cash:24 a is 1$'));
89-
expect(transaction1).toLog(new RegExp('^Test.cash:31 a equals 1$'));
90-
expect(transaction1).toLog(new RegExp('^Test.cash:32 b equals 1$'));
88+
expect(transaction1).toLog(new RegExp('^\\[Input #0] Test.cash:24 a is 1$'));
89+
expect(transaction1).toLog(new RegExp('^\\[Input #0] Test.cash:31 a equals 1$'));
90+
expect(transaction1).toLog(new RegExp('^\\[Input #0] Test.cash:32 b equals 1$'));
9191
expect(transaction1).not.toLog(/a is not 1/);
9292

9393
const transaction2 = new TransactionBuilder({ provider })
9494
.addInput(contractUtxo, contractTestLogs.unlock.functionWithIfStatement(2n))
9595
.addOutput({ to: contractTestLogs.address, amount: 10000n });
9696

97-
expect(transaction2).toLog(new RegExp('^Test.cash:27 a is not 1$'));
98-
expect(transaction2).toLog(new RegExp('^Test.cash:31 a equals 2$'));
99-
expect(transaction2).toLog(new RegExp('^Test.cash:32 b equals 2$'));
97+
expect(transaction2).toLog(new RegExp('^\\[Input #0] Test.cash:27 a is not 1$'));
98+
expect(transaction2).toLog(new RegExp('^\\[Input #0] Test.cash:31 a equals 2$'));
99+
expect(transaction2).toLog(new RegExp('^\\[Input #0] Test.cash:32 b equals 2$'));
100100
expect(transaction2).not.toLog(/a is 1/);
101101
});
102102

@@ -111,9 +111,9 @@ describe('Debugging tests', () => {
111111
.addOutput({ to: contractTestConsecutiveLogs.address, amount: 10000n });
112112

113113
// console.log(ownerSig, owner, num, beef);
114-
expect(transaction).toLog(new RegExp(`^Test.cash:9 0x[0-9a-f]{130} 0x${binToHex(alicePub)} 100$`));
114+
expect(transaction).toLog(new RegExp(`^\\[Input #0] Test.cash:9 0x[0-9a-f]{130} 0x${binToHex(alicePub)} 100$`));
115115
// console.log(1, "test", true)
116-
expect(transaction).toLog(new RegExp('^Test.cash:10 0xbeef 1 test true$'));
116+
expect(transaction).toLog(new RegExp('^\\[Input #0] Test.cash:10 0xbeef 1 test true$'));
117117
});
118118

119119
it('should log multiple console.log statements with other statements in between', async () => {
@@ -127,10 +127,10 @@ describe('Debugging tests', () => {
127127
.addOutput({ to: contractTestMultipleLogs.address, amount: 10000n });
128128

129129
// console.log(ownerSig, owner, num);
130-
const expectedFirstLog = new RegExp(`^Test.cash:6 0x[0-9a-f]{130} 0x${binToHex(alicePub)} 100$`);
130+
const expectedFirstLog = new RegExp(`^\\[Input #0] Test.cash:6 0x[0-9a-f]{130} 0x${binToHex(alicePub)} 100$`);
131131
expect(transaction).toLog(expectedFirstLog);
132132

133-
const expectedSecondLog = new RegExp('^Test.cash:11 0xbeef 1 test true$');
133+
const expectedSecondLog = new RegExp('^\\[Input #0] Test.cash:11 0xbeef 1 test true$');
134134
expect(transaction).toLog(expectedSecondLog);
135135
});
136136

@@ -140,8 +140,8 @@ describe('Debugging tests', () => {
140140
.addInput(contractUtxo, contractTestLogs.unlock.test_log_inside_notif_statement(false))
141141
.addOutput({ to: contractTestLogs.address, amount: contractUtxo.satoshis - 1000n });
142142

143-
expect(transaction).toLog(new RegExp(`^Test.cash:52 before: ${contractUtxo.satoshis}$`));
144-
expect(transaction).toLog(new RegExp(`^Test.cash:54 after: ${contractUtxo.satoshis}$`));
143+
expect(transaction).toLog(new RegExp(`^\\[Input #0] Test.cash:52 before: ${contractUtxo.satoshis}$`));
144+
expect(transaction).toLog(new RegExp(`^\\[Input #0] Test.cash:54 after: ${contractUtxo.satoshis}$`));
145145
});
146146

147147
it('should log intermediate results that get optimised out', async () => {
@@ -150,7 +150,7 @@ describe('Debugging tests', () => {
150150
.addOutput({ to: contractTestLogs.address, amount: 10000n });
151151

152152
const expectedHash = binToHex(sha256(alicePub));
153-
expect(transaction).toLog(new RegExp(`^Test.cash:43 0x${expectedHash}$`));
153+
expect(transaction).toLog(new RegExp(`^\\[Input #0] Test.cash:43 0x${expectedHash}$`));
154154
});
155155

156156
it.todo('intermediate results that is more complex than the test above');
@@ -542,7 +542,7 @@ describe('Debugging tests', () => {
542542

543543
expect(
544544
() => expect(transaction).toLog('^This is definitely not the log$'),
545-
).toThrow(/Expected: .*This is definitely not the log.*\nReceived: (.|\n)*?Test.cash:4 Hello World/);
545+
).toThrow(/Expected: .*This is definitely not the log.*\nReceived: (.|\n)*?\[Input #0] Test.cash:4 Hello World/);
546546
});
547547

548548
it('should fail the JestExtensions test if a log is logged that is NOT expected', async () => {
@@ -554,12 +554,14 @@ describe('Debugging tests', () => {
554554
.addOutput({ to: contractTestRequires.address, amount: 10000n });
555555

556556
expect(
557-
() => expect(transaction).not.toLog('^Test.cash:4 Hello World$'),
558-
).toThrow(/Expected: not .*Test.cash:4 Hello World.*\nReceived: (.|\n)*?Test.cash:4 Hello World/);
557+
() => expect(transaction).not.toLog('^\\[Input #0] Test.cash:4 Hello World$'),
558+
).toThrow(
559+
/Expected: not .*\\\\\[Input #0] Test.cash:4 Hello World.*\nReceived: (.|\n)*?\[Input #0] Test.cash:4 Hello World/,
560+
);
559561

560562
expect(
561563
() => expect(transaction).not.toLog(),
562-
).toThrow(/Expected: not .*undefined.*\nReceived: (.|\n)*?Test.cash:4 Hello World/);
564+
).toThrow(/Expected: not .*undefined.*\nReceived: (.|\n)*?\[Input #0] Test.cash:4 Hello World/);
563565
});
564566

565567
it('should fail the JestExtensions test if a log is expected where no log is logged', async () => {

packages/cashscript/test/multi-contract-debugging.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ describe('Multi-Contract-Debugging tests', () => {
5353
amount: sameNameDifferentPathContractUtxo.satoshis - 2000n,
5454
});
5555

56-
expect(tx).toLog('SiblingIntrospection.cash:6 outputBytecode: 0xaa2092e16594dd458916b3aa6cae4bf41352d1b3b39658698e8cddbeedd687efec7587\nSiblingIntrospection.cash:10 inputBytecode: 0xaa2092e16594dd458916b3aa6cae4bf41352d1b3b39658698e8cddbeedd687efec7587\nSameNameDifferentPath.cash:5 a is 0');
56+
expect(tx).toLog('[Input #0] SiblingIntrospection.cash:6 outputBytecode: 0xaa2092e16594dd458916b3aa6cae4bf41352d1b3b39658698e8cddbeedd687efec7587\n[Input #0] SiblingIntrospection.cash:10 inputBytecode: 0xaa2092e16594dd458916b3aa6cae4bf41352d1b3b39658698e8cddbeedd687efec7587\n[Input #1] SameNameDifferentPath.cash:5 a is 0');
5757
});
5858

5959
it('should log correct data for the reached console.log statements if a require statement fails, and not log unreached console.log statements', () => {
@@ -66,9 +66,9 @@ describe('Multi-Contract-Debugging tests', () => {
6666
amount: sameNameDifferentPathContractUtxo.satoshis - 2000n,
6767
});
6868

69-
expect(tx).toLog('SiblingIntrospection.cash:6 outputBytecode: 0xaa20d510df1721debb0d678d8e424b5f64f04f820005f017cb4731f7be94cd63755787');
70-
expect(tx).not.toLog('SiblingIntrospection.cash:10 inputBytecode: 0xaa2092e16594dd458916b3aa6cae4bf41352d1b3b39658698e8cddbeedd687efec7587');
71-
expect(tx).not.toLog('SameNameDifferentPath.cash:5 a is 0');
69+
expect(tx).toLog('[Input #0] SiblingIntrospection.cash:6 outputBytecode: 0xaa20d510df1721debb0d678d8e424b5f64f04f820005f017cb4731f7be94cd63755787');
70+
expect(tx).not.toLog('[Input #0] SiblingIntrospection.cash:10 inputBytecode: 0xaa2092e16594dd458916b3aa6cae4bf41352d1b3b39658698e8cddbeedd687efec7587');
71+
expect(tx).not.toLog('[Input #1] SameNameDifferentPath.cash:5 a is 0');
7272
});
7373
});
7474

@@ -88,7 +88,7 @@ describe('Multi-Contract-Debugging tests', () => {
8888
.addOutput({ to: sameNameDifferentPathContract1.address, amount: sameNameDifferentPathContract1Utxo.satoshis })
8989
.addOutput({ to: sameNameDifferentPathContract2.address, amount: sameNameDifferentPathContract2Utxo.satoshis });
9090

91-
expect(tx).toLog('SameNameDifferentPath.cash:5 a is 0\nSameNameDifferentPath.cash:8 a is not 0');
91+
expect(tx).toLog('[Input #0] SameNameDifferentPath.cash:5 a is 0\n[Input #1] SameNameDifferentPath.cash:8 a is not 0');
9292
});
9393
});
9494

0 commit comments

Comments
 (0)