cashscript 0.13.0-next.0 → 0.13.0-next.1

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 (2) hide show
  1. package/dist/debugging.js +33 -15
  2. package/package.json +3 -3
package/dist/debugging.js CHANGED
@@ -45,16 +45,32 @@ const debugSingleScenario = (template, artifact, unlockingScriptId, scenarioId)
45
45
  // https://libauth.org/types/AuthenticationVirtualMachine.html#__type.debug
46
46
  const lockingScriptDebugResult = fullDebugSteps.slice(findLastIndex(fullDebugSteps, (state) => state.ip === 0));
47
47
  // The controlStack determines whether the current debug step is in the executed branch
48
+ // It also tracks loop / function usage, but for the purpose of determining whether a step was executed,
49
+ // we only need to check that there are no 'false' items in the control stack.
48
50
  // https://libauth.org/types/AuthenticationProgramStateControlStack.html
51
+ // https://github.com/bitjson/bch-loops#control-stack
49
52
  const executedDebugSteps = lockingScriptDebugResult
50
- .filter((debugStep) => debugStep.controlStack.every(item => item === true));
53
+ .filter((debugStep) => debugStep.controlStack.every(item => item !== false));
51
54
  // P2PKH inputs do not have an artifact, so we skip the console.log handling
52
55
  if (artifact) {
53
- const executedLogs = (artifact.debug?.logs ?? [])
54
- .filter((log) => executedDebugSteps.some((debugStep) => log.ip === debugStep.ip));
55
- for (const log of executedLogs) {
56
+ // Try to match each executed debug step to a log entry if it exists. Note that inside loops,
57
+ // the same log statement may be executed multiple times in different debug steps
58
+ // Also note that multiple log statements may exist for the same ip, so we need to handle all of them
59
+ const executedLogs = executedDebugSteps
60
+ .flatMap((debugStep, index) => {
61
+ const logEntries = artifact.debug?.logs?.filter((log) => log.ip === debugStep.ip);
62
+ if (!logEntries || logEntries.length === 0)
63
+ return [];
64
+ const reversedPriorDebugSteps = executedDebugSteps.slice(0, index + 1).reverse();
65
+ return logEntries.map((logEntry) => {
66
+ const decodedLogData = logEntry.data
67
+ .map((dataEntry) => decodeLogDataEntry(dataEntry, reversedPriorDebugSteps, vm));
68
+ return { logEntry, decodedLogData };
69
+ });
70
+ });
71
+ for (const { logEntry, decodedLogData } of executedLogs) {
56
72
  const inputIndex = extractInputIndexFromScenario(scenarioId);
57
- logConsoleLogStatement(log, executedDebugSteps, artifact, inputIndex, vm);
73
+ logConsoleLogStatement(logEntry, decodedLogData, artifact.contractName, inputIndex);
58
74
  }
59
75
  }
60
76
  const lastExecutedDebugStep = executedDebugSteps[executedDebugSteps.length - 1];
@@ -147,16 +163,18 @@ const createProgram = (template, unlockingScriptId, scenarioId) => {
147
163
  }
148
164
  return { vm, program: scenarioGeneration.scenario.program };
149
165
  };
150
- const logConsoleLogStatement = (log, debugSteps, artifact, inputIndex, vm) => {
151
- let line = `${artifact.contractName}.cash:${log.line}`;
152
- const decodedData = log.data.map((element) => {
153
- if (typeof element === 'string')
154
- return element;
155
- const debugStep = debugSteps.find((step) => step.ip === element.ip);
156
- const transformedDebugStep = applyStackItemTransformations(element, debugStep, vm);
157
- return decodeStackItem(element, transformedDebugStep.stack);
158
- });
159
- console.log(`[Input #${inputIndex}] ${line} ${decodedData.join(' ')}`);
166
+ const logConsoleLogStatement = (log, decodedLogData, contractName, inputIndex) => {
167
+ console.log(`[Input #${inputIndex}] ${contractName}.cash:${log.line} ${decodedLogData.join(' ')}`);
168
+ };
169
+ const decodeLogDataEntry = (dataEntry, reversedPriorDebugSteps, vm) => {
170
+ if (typeof dataEntry === 'string')
171
+ return dataEntry;
172
+ const dataEntryDebugStep = reversedPriorDebugSteps.find((step) => step.ip === dataEntry.ip);
173
+ if (!dataEntryDebugStep) {
174
+ throw new Error(`Should not happen: corresponding data entry debug step not found for entry at ip ${dataEntry.ip}`);
175
+ }
176
+ const transformedDebugStep = applyStackItemTransformations(dataEntry, dataEntryDebugStep, vm);
177
+ return decodeStackItem(dataEntry, transformedDebugStep.stack);
160
178
  };
161
179
  const applyStackItemTransformations = (element, debugStep, vm) => {
162
180
  if (!element.transformations)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cashscript",
3
- "version": "0.13.0-next.0",
3
+ "version": "0.13.0-next.1",
4
4
  "description": "Easily write and interact with Bitcoin Cash contracts",
5
5
  "keywords": [
6
6
  "bitcoin cash",
@@ -46,7 +46,7 @@
46
46
  },
47
47
  "dependencies": {
48
48
  "@bitauth/libauth": "^3.1.0-next.8",
49
- "@cashscript/utils": "^0.13.0-next.0",
49
+ "@cashscript/utils": "^0.13.0-next.1",
50
50
  "@electrum-cash/network": "^4.1.3",
51
51
  "@mr-zwets/bchn-api-wrapper": "^1.0.1",
52
52
  "pako": "^2.1.0",
@@ -61,5 +61,5 @@
61
61
  "jest": "^29.7.0",
62
62
  "typescript": "^5.9.2"
63
63
  },
64
- "gitHead": "1514d30e3d5de5bb2024d6198ed93a7ae8ae4e30"
64
+ "gitHead": "f3d3fd75400c93f4457276b56ce094b11c0986d7"
65
65
  }