cashscript 0.12.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.
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)
@@ -1,12 +1,12 @@
1
1
  import { binToBase64, binToHex, utf8ToBin, } from '@bitauth/libauth';
2
2
  import { encodeFunctionArguments } from '../Argument.js';
3
3
  import { debugTemplate } from '../debugging.js';
4
- import { isContractUnlocker, isP2PKHUnlocker, isStandardUnlockableUtxo, isUnlockableUtxo, VmTarget, } from '../interfaces.js';
4
+ import { isContractUnlocker, isP2PKHUnlocker, isStandardUnlockableUtxo, isUnlockableUtxo, } from '../interfaces.js';
5
5
  import SignatureTemplate from '../SignatureTemplate.js';
6
6
  import { addressToLockScript, extendedStringify, zip } from '../utils.js';
7
7
  import { deflate } from 'pako';
8
8
  import MockNetworkProvider from '../network/MockNetworkProvider.js';
9
- import { addHexPrefixExceptEmpty, formatBytecodeForDebugging, formatParametersForDebugging, getLockScriptName, getSignatureAndPubkeyFromP2PKHInput, getUnlockScriptName, lockingBytecodeIsSetToSlot, serialiseTokenDetails } from './utils.js';
9
+ import { addHexPrefixExceptEmpty, DEFAULT_VM_TARGET, formatBytecodeForDebugging, formatParametersForDebugging, getLockScriptName, getSignatureAndPubkeyFromP2PKHInput, getUnlockScriptName, lockingBytecodeIsSetToSlot, serialiseTokenDetails } from './utils.js';
10
10
  // TODO: Add / improve descriptions throughout the template generation
11
11
  export const getLibauthTemplate = (transactionBuilder) => {
12
12
  if (transactionBuilder.inputs.some((input) => !isStandardUnlockableUtxo(input))) {
@@ -15,7 +15,7 @@ export const getLibauthTemplate = (transactionBuilder) => {
15
15
  const libauthTransaction = transactionBuilder.buildLibauthTransaction();
16
16
  const vmTarget = transactionBuilder.provider instanceof MockNetworkProvider
17
17
  ? transactionBuilder.provider.vmTarget
18
- : VmTarget.BCH_2025_05;
18
+ : DEFAULT_VM_TARGET;
19
19
  const template = {
20
20
  $schema: 'https://ide.bitauth.com/authentication-template-v0.schema.json',
21
21
  description: 'Imported from cashscript',
@@ -3,6 +3,7 @@ import { HashType, LibauthTokenDetails, SignatureAlgorithm, TokenDetails } from
3
3
  import { type WalletTemplateScenarioBytecode, Input } from '@bitauth/libauth';
4
4
  import { EncodedFunctionArgument } from '../Argument.js';
5
5
  import { Contract } from '../Contract.js';
6
+ export declare const DEFAULT_VM_TARGET: "BCH_2026_05";
6
7
  export declare const getLockScriptName: (contract: Contract) => string;
7
8
  export declare const getUnlockScriptName: (contract: Contract, abiFunction: AbiFunction, inputIndex: number) => string;
8
9
  export declare const getSignatureAlgorithmName: (signatureAlgorithm: SignatureAlgorithm) => string;
@@ -1,8 +1,9 @@
1
1
  import { bytecodeToScript, formatBitAuthScript } from '@cashscript/utils';
2
- import { HashType, SignatureAlgorithm } from '../interfaces.js';
2
+ import { HashType, SignatureAlgorithm, VmTarget } from '../interfaces.js';
3
3
  import { hexToBin, binToHex, isHex, decodeCashAddress, assertSuccess, decodeAuthenticationInstructions } from '@bitauth/libauth';
4
4
  import { zip } from '../utils.js';
5
5
  import SignatureTemplate from '../SignatureTemplate.js';
6
+ export const DEFAULT_VM_TARGET = VmTarget.BCH_2026_05;
6
7
  export const getLockScriptName = (contract) => {
7
8
  const result = decodeCashAddress(contract.address);
8
9
  if (typeof result === 'string')
@@ -1,7 +1,8 @@
1
1
  import { binToHex, decodeTransactionUnsafe, hexToBin, isHex } from '@bitauth/libauth';
2
2
  import { sha256 } from '@cashscript/utils';
3
- import { Network, VmTarget } from '../interfaces.js';
3
+ import { Network } from '../interfaces.js';
4
4
  import { addressToLockScript, libauthTokenDetailsToCashScriptTokenDetails } from '../utils.js';
5
+ import { DEFAULT_VM_TARGET } from '../libauth-template/utils.js';
5
6
  export default class MockNetworkProvider {
6
7
  constructor(options) {
7
8
  // we use lockingBytecode hex as the key for utxoMap to make cash addresses and token addresses interchangeable
@@ -10,7 +11,7 @@ export default class MockNetworkProvider {
10
11
  this.network = Network.MOCKNET;
11
12
  this.blockHeight = 133700;
12
13
  this.options = { updateUtxoSet: true, ...options };
13
- this.vmTarget = this.options.vmTarget ?? VmTarget.BCH_2025_05;
14
+ this.vmTarget = this.options.vmTarget ?? DEFAULT_VM_TARGET;
14
15
  }
15
16
  async getUtxos(address) {
16
17
  const addressLockingBytecode = binToHex(addressToLockScript(address));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cashscript",
3
- "version": "0.12.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.12.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": "dfa7ea1cfe1c369ab1dd9a919ab89b9a98331872"
64
+ "gitHead": "f3d3fd75400c93f4457276b56ce094b11c0986d7"
65
65
  }