From 529ec0a47c377d7d35407394eced82edb712cec3 Mon Sep 17 00:00:00 2001 From: mainnet-pat Date: Mon, 8 Sep 2025 10:29:13 +0000 Subject: [PATCH 1/4] Update libauth to 3.1.0-next.8 --- packages/cashc/package.json | 2 +- packages/cashscript/package.json | 2 +- packages/cashscript/src/debugging.ts | 2 ++ packages/utils/package.json | 2 +- yarn.lock | 5 +++++ 5 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/cashc/package.json b/packages/cashc/package.json index 0c592984..0e90a460 100644 --- a/packages/cashc/package.json +++ b/packages/cashc/package.json @@ -51,7 +51,7 @@ "test": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' jest" }, "dependencies": { - "@bitauth/libauth": "^3.1.0-next.2", + "@bitauth/libauth": "^3.1.0-next.8", "@cashscript/utils": "^0.11.5", "antlr4": "^4.13.2", "commander": "^14.0.0", diff --git a/packages/cashscript/package.json b/packages/cashscript/package.json index d200fc41..c8722e06 100644 --- a/packages/cashscript/package.json +++ b/packages/cashscript/package.json @@ -45,7 +45,7 @@ "test": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' jest" }, "dependencies": { - "@bitauth/libauth": "^3.1.0-next.2", + "@bitauth/libauth": "^3.1.0-next.8", "@cashscript/utils": "^0.11.5", "@electrum-cash/network": "^4.1.3", "@mr-zwets/bchn-api-wrapper": "^1.0.1", diff --git a/packages/cashscript/src/debugging.ts b/packages/cashscript/src/debugging.ts index 82023d5d..128adcdf 100644 --- a/packages/cashscript/src/debugging.ts +++ b/packages/cashscript/src/debugging.ts @@ -236,6 +236,8 @@ const applyStackItemTransformations = ( instructions: transformationsAuthenticationInstructions, signedMessages: [], program: { ...debugStep.program }, + functionTable: debugStep.functionTable ?? {}, + functionCount: debugStep.functionCount ?? 0, }; const vm = createVirtualMachineBch2025(); diff --git a/packages/utils/package.json b/packages/utils/package.json index 76a99341..c29a3171 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -44,7 +44,7 @@ "test": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' jest" }, "dependencies": { - "@bitauth/libauth": "^3.1.0-next.2" + "@bitauth/libauth": "^3.1.0-next.8" }, "devDependencies": { "@jest/globals": "^29.7.0", diff --git a/yarn.lock b/yarn.lock index 0daa8efd..ad42ae0b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -630,6 +630,11 @@ resolved "https://registry.yarnpkg.com/@bitauth/libauth/-/libauth-3.1.0-next.2.tgz#121782b38774d9fba8226406db9b9af0c8d8e464" integrity sha512-XRtk9p8UHvtjSPS38rsfHXzaPHG5j9FpN4qHqqGLoAuZYy675PBiOy9zP6ah8lTnnIVaCFl2ekct8w0Hy1oefw== +"@bitauth/libauth@^3.1.0-next.8": + version "3.1.0-next.8" + resolved "https://registry.yarnpkg.com/@bitauth/libauth/-/libauth-3.1.0-next.8.tgz#d130e5db6c3c8b24731c8d04c4091be07f48b0ee" + integrity sha512-Pm+Ju+YP3JeBLLTiVrBnia2wwE4G17r4XqpvPRMcklElJTe8J6x3JgKRg1by0Xm3ZY6UFxACkEAoSA+x419/zA== + "@chris.troutner/bip32-utils@1.0.5": version "1.0.5" resolved "https://registry.yarnpkg.com/@chris.troutner/bip32-utils/-/bip32-utils-1.0.5.tgz#b6722aeaad5fcda6fba69cbeda7e2a5e8afbd692" From 9bf5c3c4aea9d2b0ad0466d4b551b81109d06c6d Mon Sep 17 00:00:00 2001 From: mainnet-pat Date: Mon, 8 Sep 2025 11:28:10 +0000 Subject: [PATCH 2/4] Add support to set debugger's target VM version --- packages/cashscript/src/LibauthTemplate.ts | 8 +++++- packages/cashscript/src/debugging.ts | 28 +++++++++++++++---- packages/cashscript/src/index.ts | 1 + .../src/network/MockNetworkProvider.ts | 9 ++++-- packages/cashscript/src/network/index.ts | 2 +- packages/cashscript/test/debugging.test.ts | 27 +++++++++++++++++- 6 files changed, 64 insertions(+), 11 deletions(-) diff --git a/packages/cashscript/src/LibauthTemplate.ts b/packages/cashscript/src/LibauthTemplate.ts index e09652eb..0ec3085e 100644 --- a/packages/cashscript/src/LibauthTemplate.ts +++ b/packages/cashscript/src/LibauthTemplate.ts @@ -1,4 +1,5 @@ import { + AuthenticationVirtualMachineIdentifier, binToBase64, binToHex, decodeCashAddress, @@ -60,11 +61,16 @@ export const getLibauthTemplates = ( const libauthTransaction = txn.buildLibauthTransaction(); const csTransaction = createTransactionTypeFromTransactionBuilder(txn); + let vmTarget: AuthenticationVirtualMachineIdentifier = 'BCH_2025_05'; + if ('vmTarget' in txn.provider) { + vmTarget = txn.provider.vmTarget as AuthenticationVirtualMachineIdentifier; + } + const baseTemplate: WalletTemplate = { $schema: 'https://ide.bitauth.com/authentication-template-v0.schema.json', description: 'Imported from cashscript', name: 'CashScript Generated Debugging Template', - supported: ['BCH_2025_05'], + supported: [vmTarget], version: 0, entities: {}, scripts: {}, diff --git a/packages/cashscript/src/debugging.ts b/packages/cashscript/src/debugging.ts index 128adcdf..2ca62fad 100644 --- a/packages/cashscript/src/debugging.ts +++ b/packages/cashscript/src/debugging.ts @@ -1,4 +1,4 @@ -import { AuthenticationErrorCommon, AuthenticationInstruction, AuthenticationProgramCommon, AuthenticationProgramStateCommon, AuthenticationVirtualMachine, ResolvedTransactionCommon, WalletTemplate, WalletTemplateScriptUnlocking, binToHex, createCompiler, createVirtualMachineBch2025, decodeAuthenticationInstructions, encodeAuthenticationInstruction, walletTemplateToCompilerConfiguration } from '@bitauth/libauth'; +import { AuthenticationErrorCommon, AuthenticationInstruction, AuthenticationProgramCommon, AuthenticationProgramStateCommon, AuthenticationVirtualMachine, AuthenticationVirtualMachineIdentifier, ResolvedTransactionCommon, WalletTemplate, WalletTemplateScriptUnlocking, binToHex, createCompiler, createVirtualMachineBch2023, createVirtualMachineBch2025, createVirtualMachineBch2026, createVirtualMachineBchSpec, decodeAuthenticationInstructions, encodeAuthenticationInstruction, walletTemplateToCompilerConfiguration } from '@bitauth/libauth'; import { Artifact, LogEntry, Op, PrimitiveType, StackItem, asmToBytecode, bytecodeToAsm, decodeBool, decodeInt, decodeString } from '@cashscript/utils'; import { findLastIndex, toRegExp } from './utils.js'; import { FailedRequireError, FailedTransactionError, FailedTransactionEvaluationError } from './Errors.js'; @@ -7,6 +7,21 @@ import { getBitauthUri } from './LibauthTemplate.js'; export type DebugResult = AuthenticationProgramStateCommon[]; export type DebugResults = Record; +const createVirualMachine = (vmTarget: AuthenticationVirtualMachineIdentifier) => { + switch (vmTarget) { + case 'BCH_2023_05': + return createVirtualMachineBch2023(); + case 'BCH_2025_05': + return createVirtualMachineBch2025(); + case 'BCH_2026_05': + return createVirtualMachineBch2026(); + case 'BCH_SPEC': + return createVirtualMachineBchSpec(); + default: + throw new Error(`Debugging is not supported for the ${vmTarget} virtual machine.`); + } +}; + // debugs the template, optionally logging the execution data export const debugTemplate = (template: WalletTemplate, artifacts: Artifact[]): DebugResults => { // If a contract has the same name, but a different bytecode, then it is considered a name collision @@ -61,7 +76,7 @@ const debugSingleScenario = ( for (const log of executedLogs) { const inputIndex = extractInputIndexFromScenario(scenarioId); - logConsoleLogStatement(log, executedDebugSteps, artifact, inputIndex); + logConsoleLogStatement(log, executedDebugSteps, artifact, inputIndex, vm); } } @@ -171,7 +186,7 @@ type CreateProgramResult = { vm: VM, program: Program }; // internal util. instantiates the virtual machine and compiles the template into a program const createProgram = (template: WalletTemplate, unlockingScriptId: string, scenarioId: string): CreateProgramResult => { const configuration = walletTemplateToCompilerConfiguration(template); - const vm = createVirtualMachineBch2025(); + const vm = createVirualMachine(template.supported[0]); const compiler = createCompiler(configuration); if (!template.scripts[unlockingScriptId]) { @@ -196,7 +211,7 @@ const createProgram = (template: WalletTemplate, unlockingScriptId: string, scen throw new FailedTransactionError(scenarioGeneration.scenario, getBitauthUri(template)); } - return { vm, program: scenarioGeneration.scenario.program }; + return { vm: vm as VM, program: scenarioGeneration.scenario.program }; }; const logConsoleLogStatement = ( @@ -204,13 +219,14 @@ const logConsoleLogStatement = ( debugSteps: AuthenticationProgramStateCommon[], artifact: Artifact, inputIndex: number, + vm: VM, ): void => { let line = `${artifact.contractName}.cash:${log.line}`; const decodedData = log.data.map((element) => { if (typeof element === 'string') return element; const debugStep = debugSteps.find((step) => step.ip === element.ip)!; - const transformedDebugStep = applyStackItemTransformations(element, debugStep); + const transformedDebugStep = applyStackItemTransformations(element, debugStep, vm); return decodeStackItem(element, transformedDebugStep.stack); }); console.log(`[Input #${inputIndex}] ${line} ${decodedData.join(' ')}`); @@ -219,6 +235,7 @@ const logConsoleLogStatement = ( const applyStackItemTransformations = ( element: StackItem, debugStep: AuthenticationProgramStateCommon, + vm: VM, ): AuthenticationProgramStateCommon => { if (!element.transformations) return debugStep; @@ -240,7 +257,6 @@ const applyStackItemTransformations = ( functionCount: debugStep.functionCount ?? 0, }; - const vm = createVirtualMachineBch2025(); const transformationsEndState = vm.stateEvaluate(transformationsStartState); return transformationsEndState; diff --git a/packages/cashscript/src/index.ts b/packages/cashscript/src/index.ts index 4a5633f2..0736ada0 100644 --- a/packages/cashscript/src/index.ts +++ b/packages/cashscript/src/index.ts @@ -18,6 +18,7 @@ export { ElectrumNetworkProvider, FullStackNetworkProvider, MockNetworkProvider, + VmTarget, } from './network/index.js'; export { randomUtxo, randomToken, randomNFT } from './utils.js'; export * from './walletconnect-utils.js'; diff --git a/packages/cashscript/src/network/MockNetworkProvider.ts b/packages/cashscript/src/network/MockNetworkProvider.ts index 52e9d02b..438fad24 100644 --- a/packages/cashscript/src/network/MockNetworkProvider.ts +++ b/packages/cashscript/src/network/MockNetworkProvider.ts @@ -1,13 +1,16 @@ -import { binToHex, decodeTransactionUnsafe, hexToBin, isHex } from '@bitauth/libauth'; +import { AuthenticationVirtualMachineIdentifier, binToHex, decodeTransactionUnsafe, hexToBin, isHex } from '@bitauth/libauth'; import { sha256 } from '@cashscript/utils'; import { Utxo, Network } from '../interfaces.js'; import NetworkProvider from './NetworkProvider.js'; import { addressToLockScript, libauthTokenDetailsToCashScriptTokenDetails } from '../utils.js'; -interface MockNetworkProviderOptions { +export interface MockNetworkProviderOptions { updateUtxoSet: boolean; + vmTarget?: VmTarget; } +export type VmTarget = AuthenticationVirtualMachineIdentifier; + export default class MockNetworkProvider implements NetworkProvider { // we use lockingBytecode hex as the key for utxoMap to make cash addresses and token addresses interchangeable private utxoSet: Array<[string, Utxo]> = []; @@ -15,9 +18,11 @@ export default class MockNetworkProvider implements NetworkProvider { public network: Network = Network.MOCKNET; public blockHeight: number = 133700; public options: MockNetworkProviderOptions; + public vmTarget: VmTarget; constructor(options?: Partial) { this.options = { updateUtxoSet: true, ...options }; + this.vmTarget = this.options.vmTarget ?? "BCH_2025_05"; } async getUtxos(address: string): Promise { diff --git a/packages/cashscript/src/network/index.ts b/packages/cashscript/src/network/index.ts index 8d31ddde..97ac4284 100644 --- a/packages/cashscript/src/network/index.ts +++ b/packages/cashscript/src/network/index.ts @@ -2,4 +2,4 @@ export type { default as NetworkProvider } from './NetworkProvider.js'; export { default as BitcoinRpcNetworkProvider } from './BitcoinRpcNetworkProvider.js'; export { default as ElectrumNetworkProvider } from './ElectrumNetworkProvider.js'; export { default as FullStackNetworkProvider } from './FullStackNetworkProvider.js'; -export { default as MockNetworkProvider } from './MockNetworkProvider.js'; +export { default as MockNetworkProvider, VmTarget } from './MockNetworkProvider.js'; diff --git a/packages/cashscript/test/debugging.test.ts b/packages/cashscript/test/debugging.test.ts index c174f473..4615e06b 100644 --- a/packages/cashscript/test/debugging.test.ts +++ b/packages/cashscript/test/debugging.test.ts @@ -1,4 +1,4 @@ -import { Contract, FailedTransactionError, MockNetworkProvider, SignatureAlgorithm, SignatureTemplate, TransactionBuilder } from '../src/index.js'; +import { Contract, FailedTransactionError, MockNetworkProvider, SignatureAlgorithm, SignatureTemplate, TransactionBuilder, VmTarget } from '../src/index.js'; import { aliceAddress, alicePriv, alicePub, bobPriv, bobPub } from './fixture/vars.js'; import '../src/test/JestExtensions.js'; import { randomUtxo } from '../src/utils.js'; @@ -649,4 +649,29 @@ describe('Debugging tests', () => { expect(() => transactionBuilder.debug()).toThrow(FailedTransactionError); }); }); + + describe('VmTargets', () => { + for (const vmTarget of ['BCH_2020_05', undefined, 'BCH_2023_05', 'BCH_2025_05', 'BCH_2026_05', 'BCH_SPEC'] as VmTarget[]) { + it(`should execute and log correctly with vmTarget ${vmTarget}`, async () => { + const provider = new MockNetworkProvider({ vmTarget }); + const contractTestLogs = new Contract(artifactTestLogs, [alicePub], { provider }); + const contractUtxo = randomUtxo(); + provider.addUtxo(contractTestLogs.address, contractUtxo); + + const transaction = new TransactionBuilder({ provider }) + .addInput(contractUtxo, contractTestLogs.unlock.transfer(new SignatureTemplate(alicePriv), 1000n)) + .addOutput({ to: contractTestLogs.address, amount: 10000n }); + + if (vmTarget === 'BCH_2020_05') { + expect(() => transaction.debug()).toThrow('Debugging is not supported for the BCH_2020_05 virtual machine.'); + return; + } + + expect(transaction.getLibauthTemplate().supported[0]).toBe(vmTarget ?? 'BCH_2025_05'); + + const expectedLog = new RegExp(`^\\[Input #0] Test.cash:10 0x[0-9a-f]{130} 0x${binToHex(alicePub)} 1000 0xbeef 1 test true$`); + expect(transaction).toLog(expectedLog); + }); + } + }); }); From 5c617ffe557b7a44adb857cb3e1600aca1ada2de Mon Sep 17 00:00:00 2001 From: mainnet-pat Date: Mon, 8 Sep 2025 11:46:35 +0000 Subject: [PATCH 3/4] Lint --- packages/cashscript/src/debugging.ts | 6 +++--- packages/cashscript/src/network/MockNetworkProvider.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cashscript/src/debugging.ts b/packages/cashscript/src/debugging.ts index 2ca62fad..ad6336b0 100644 --- a/packages/cashscript/src/debugging.ts +++ b/packages/cashscript/src/debugging.ts @@ -7,7 +7,7 @@ import { getBitauthUri } from './LibauthTemplate.js'; export type DebugResult = AuthenticationProgramStateCommon[]; export type DebugResults = Record; -const createVirualMachine = (vmTarget: AuthenticationVirtualMachineIdentifier) => { +const createVirtualMachine = (vmTarget: AuthenticationVirtualMachineIdentifier): VM => { switch (vmTarget) { case 'BCH_2023_05': return createVirtualMachineBch2023(); @@ -16,7 +16,7 @@ const createVirualMachine = (vmTarget: AuthenticationVirtualMachineIdentifier) = case 'BCH_2026_05': return createVirtualMachineBch2026(); case 'BCH_SPEC': - return createVirtualMachineBchSpec(); + return createVirtualMachineBchSpec() as unknown as VM; default: throw new Error(`Debugging is not supported for the ${vmTarget} virtual machine.`); } @@ -186,7 +186,7 @@ type CreateProgramResult = { vm: VM, program: Program }; // internal util. instantiates the virtual machine and compiles the template into a program const createProgram = (template: WalletTemplate, unlockingScriptId: string, scenarioId: string): CreateProgramResult => { const configuration = walletTemplateToCompilerConfiguration(template); - const vm = createVirualMachine(template.supported[0]); + const vm = createVirtualMachine(template.supported[0]); const compiler = createCompiler(configuration); if (!template.scripts[unlockingScriptId]) { diff --git a/packages/cashscript/src/network/MockNetworkProvider.ts b/packages/cashscript/src/network/MockNetworkProvider.ts index 438fad24..af242ac9 100644 --- a/packages/cashscript/src/network/MockNetworkProvider.ts +++ b/packages/cashscript/src/network/MockNetworkProvider.ts @@ -22,7 +22,7 @@ export default class MockNetworkProvider implements NetworkProvider { constructor(options?: Partial) { this.options = { updateUtxoSet: true, ...options }; - this.vmTarget = this.options.vmTarget ?? "BCH_2025_05"; + this.vmTarget = this.options.vmTarget ?? 'BCH_2025_05'; } async getUtxos(address: string): Promise { From d15d7b5f3c2a9dfcaeb437f5dd01d0d5625407b1 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Thu, 18 Sep 2025 12:14:54 +0200 Subject: [PATCH 4/4] Small changes to MockNetworkProvider vmTarget option --- packages/cashscript/src/LibauthTemplate.ts | 8 +++--- packages/cashscript/src/debugging.ts | 26 ++++++++++--------- packages/cashscript/src/index.ts | 1 - packages/cashscript/src/interfaces.ts | 9 +++++++ .../src/network/MockNetworkProvider.ts | 8 +++--- packages/cashscript/src/network/index.ts | 2 +- packages/cashscript/test/debugging.test.ts | 15 ++++++----- website/docs/releases/release-notes.md | 1 + 8 files changed, 40 insertions(+), 30 deletions(-) diff --git a/packages/cashscript/src/LibauthTemplate.ts b/packages/cashscript/src/LibauthTemplate.ts index 0ec3085e..979e7357 100644 --- a/packages/cashscript/src/LibauthTemplate.ts +++ b/packages/cashscript/src/LibauthTemplate.ts @@ -1,5 +1,4 @@ import { - AuthenticationVirtualMachineIdentifier, binToBase64, binToHex, decodeCashAddress, @@ -43,11 +42,13 @@ import { TokenDetails, UnlockableUtxo, Utxo, + VmTarget, } from './interfaces.js'; import SignatureTemplate from './SignatureTemplate.js'; import { addressToLockScript, extendedStringify, getSignatureAndPubkeyFromP2PKHInput, zip } from './utils.js'; import { TransactionBuilder } from './TransactionBuilder.js'; import { deflate } from 'pako'; +import MockNetworkProvider from './network/MockNetworkProvider.js'; // TODO: Add / improve descriptions throughout the template generation @@ -61,10 +62,7 @@ export const getLibauthTemplates = ( const libauthTransaction = txn.buildLibauthTransaction(); const csTransaction = createTransactionTypeFromTransactionBuilder(txn); - let vmTarget: AuthenticationVirtualMachineIdentifier = 'BCH_2025_05'; - if ('vmTarget' in txn.provider) { - vmTarget = txn.provider.vmTarget as AuthenticationVirtualMachineIdentifier; - } + const vmTarget = txn.provider instanceof MockNetworkProvider ? txn.provider.vmTarget : VmTarget.BCH_2025_05; const baseTemplate: WalletTemplate = { $schema: 'https://ide.bitauth.com/authentication-template-v0.schema.json', diff --git a/packages/cashscript/src/debugging.ts b/packages/cashscript/src/debugging.ts index ad6336b0..c138e819 100644 --- a/packages/cashscript/src/debugging.ts +++ b/packages/cashscript/src/debugging.ts @@ -1,13 +1,22 @@ -import { AuthenticationErrorCommon, AuthenticationInstruction, AuthenticationProgramCommon, AuthenticationProgramStateCommon, AuthenticationVirtualMachine, AuthenticationVirtualMachineIdentifier, ResolvedTransactionCommon, WalletTemplate, WalletTemplateScriptUnlocking, binToHex, createCompiler, createVirtualMachineBch2023, createVirtualMachineBch2025, createVirtualMachineBch2026, createVirtualMachineBchSpec, decodeAuthenticationInstructions, encodeAuthenticationInstruction, walletTemplateToCompilerConfiguration } from '@bitauth/libauth'; +import { AuthenticationErrorCommon, AuthenticationInstruction, AuthenticationProgramCommon, AuthenticationProgramStateCommon, AuthenticationVirtualMachine, ResolvedTransactionCommon, WalletTemplate, WalletTemplateScriptUnlocking, binToHex, createCompiler, createVirtualMachineBch2023, createVirtualMachineBch2025, createVirtualMachineBch2026, createVirtualMachineBchSpec, decodeAuthenticationInstructions, encodeAuthenticationInstruction, walletTemplateToCompilerConfiguration } from '@bitauth/libauth'; import { Artifact, LogEntry, Op, PrimitiveType, StackItem, asmToBytecode, bytecodeToAsm, decodeBool, decodeInt, decodeString } from '@cashscript/utils'; import { findLastIndex, toRegExp } from './utils.js'; import { FailedRequireError, FailedTransactionError, FailedTransactionEvaluationError } from './Errors.js'; import { getBitauthUri } from './LibauthTemplate.js'; +import { VmTarget } from './interfaces.js'; export type DebugResult = AuthenticationProgramStateCommon[]; export type DebugResults = Record; -const createVirtualMachine = (vmTarget: AuthenticationVirtualMachineIdentifier): VM => { +/* eslint-disable @typescript-eslint/indent */ +type VM = AuthenticationVirtualMachine< + ResolvedTransactionCommon, + AuthenticationProgramCommon, + AuthenticationProgramStateCommon +>; +/* eslint-enable @typescript-eslint/indent */ + +const createVirtualMachine = (vmTarget: VmTarget): VM => { switch (vmTarget) { case 'BCH_2023_05': return createVirtualMachineBch2023(); @@ -16,6 +25,7 @@ const createVirtualMachine = (vmTarget: AuthenticationVirtualMachineIdentifier): case 'BCH_2026_05': return createVirtualMachineBch2026(); case 'BCH_SPEC': + // TODO: This typecast is shitty, but it's hard to fix return createVirtualMachineBchSpec() as unknown as VM; default: throw new Error(`Debugging is not supported for the ${vmTarget} virtual machine.`); @@ -172,21 +182,13 @@ const extractInputIndexFromScenario = (scenarioId: string): number => { return parseInt(match[1]); }; -/* eslint-disable @typescript-eslint/indent */ -type VM = AuthenticationVirtualMachine< - ResolvedTransactionCommon, - AuthenticationProgramCommon, - AuthenticationProgramStateCommon ->; -/* eslint-enable @typescript-eslint/indent */ - type Program = AuthenticationProgramCommon; type CreateProgramResult = { vm: VM, program: Program }; // internal util. instantiates the virtual machine and compiles the template into a program const createProgram = (template: WalletTemplate, unlockingScriptId: string, scenarioId: string): CreateProgramResult => { const configuration = walletTemplateToCompilerConfiguration(template); - const vm = createVirtualMachine(template.supported[0]); + const vm = createVirtualMachine(template.supported[0] as VmTarget); const compiler = createCompiler(configuration); if (!template.scripts[unlockingScriptId]) { @@ -211,7 +213,7 @@ const createProgram = (template: WalletTemplate, unlockingScriptId: string, scen throw new FailedTransactionError(scenarioGeneration.scenario, getBitauthUri(template)); } - return { vm: vm as VM, program: scenarioGeneration.scenario.program }; + return { vm, program: scenarioGeneration.scenario.program }; }; const logConsoleLogStatement = ( diff --git a/packages/cashscript/src/index.ts b/packages/cashscript/src/index.ts index 0736ada0..4a5633f2 100644 --- a/packages/cashscript/src/index.ts +++ b/packages/cashscript/src/index.ts @@ -18,7 +18,6 @@ export { ElectrumNetworkProvider, FullStackNetworkProvider, MockNetworkProvider, - VmTarget, } from './network/index.js'; export { randomUtxo, randomToken, randomNFT } from './utils.js'; export * from './walletconnect-utils.js'; diff --git a/packages/cashscript/src/interfaces.ts b/packages/cashscript/src/interfaces.ts index d5a88c48..8e89e39e 100644 --- a/packages/cashscript/src/interfaces.ts +++ b/packages/cashscript/src/interfaces.ts @@ -144,6 +144,15 @@ export const Network = { export type Network = (typeof Network)[keyof typeof Network]; +export const VmTarget = { + BCH_2023_05: literal('BCH_2023_05'), + BCH_2025_05: literal('BCH_2025_05'), + BCH_2026_05: literal('BCH_2026_05'), + BCH_SPEC: literal('BCH_SPEC'), +}; + +export type VmTarget = (typeof VmTarget)[keyof typeof VmTarget]; + export interface TransactionDetails extends Transaction { txid: string; hex: string; diff --git a/packages/cashscript/src/network/MockNetworkProvider.ts b/packages/cashscript/src/network/MockNetworkProvider.ts index af242ac9..2af9b763 100644 --- a/packages/cashscript/src/network/MockNetworkProvider.ts +++ b/packages/cashscript/src/network/MockNetworkProvider.ts @@ -1,6 +1,6 @@ -import { AuthenticationVirtualMachineIdentifier, binToHex, decodeTransactionUnsafe, hexToBin, isHex } from '@bitauth/libauth'; +import { binToHex, decodeTransactionUnsafe, hexToBin, isHex } from '@bitauth/libauth'; import { sha256 } from '@cashscript/utils'; -import { Utxo, Network } from '../interfaces.js'; +import { Utxo, Network, VmTarget } from '../interfaces.js'; import NetworkProvider from './NetworkProvider.js'; import { addressToLockScript, libauthTokenDetailsToCashScriptTokenDetails } from '../utils.js'; @@ -9,8 +9,6 @@ export interface MockNetworkProviderOptions { vmTarget?: VmTarget; } -export type VmTarget = AuthenticationVirtualMachineIdentifier; - export default class MockNetworkProvider implements NetworkProvider { // we use lockingBytecode hex as the key for utxoMap to make cash addresses and token addresses interchangeable private utxoSet: Array<[string, Utxo]> = []; @@ -22,7 +20,7 @@ export default class MockNetworkProvider implements NetworkProvider { constructor(options?: Partial) { this.options = { updateUtxoSet: true, ...options }; - this.vmTarget = this.options.vmTarget ?? 'BCH_2025_05'; + this.vmTarget = this.options.vmTarget ?? VmTarget.BCH_2025_05; } async getUtxos(address: string): Promise { diff --git a/packages/cashscript/src/network/index.ts b/packages/cashscript/src/network/index.ts index 97ac4284..8d31ddde 100644 --- a/packages/cashscript/src/network/index.ts +++ b/packages/cashscript/src/network/index.ts @@ -2,4 +2,4 @@ export type { default as NetworkProvider } from './NetworkProvider.js'; export { default as BitcoinRpcNetworkProvider } from './BitcoinRpcNetworkProvider.js'; export { default as ElectrumNetworkProvider } from './ElectrumNetworkProvider.js'; export { default as FullStackNetworkProvider } from './FullStackNetworkProvider.js'; -export { default as MockNetworkProvider, VmTarget } from './MockNetworkProvider.js'; +export { default as MockNetworkProvider } from './MockNetworkProvider.js'; diff --git a/packages/cashscript/test/debugging.test.ts b/packages/cashscript/test/debugging.test.ts index 4615e06b..3183bb64 100644 --- a/packages/cashscript/test/debugging.test.ts +++ b/packages/cashscript/test/debugging.test.ts @@ -651,7 +651,15 @@ describe('Debugging tests', () => { }); describe('VmTargets', () => { - for (const vmTarget of ['BCH_2020_05', undefined, 'BCH_2023_05', 'BCH_2025_05', 'BCH_2026_05', 'BCH_SPEC'] as VmTarget[]) { + const vmTargets = [ + undefined, + VmTarget.BCH_2023_05, + VmTarget.BCH_2025_05, + VmTarget.BCH_2026_05, + VmTarget.BCH_SPEC, + ] as const; + + for (const vmTarget of vmTargets) { it(`should execute and log correctly with vmTarget ${vmTarget}`, async () => { const provider = new MockNetworkProvider({ vmTarget }); const contractTestLogs = new Contract(artifactTestLogs, [alicePub], { provider }); @@ -662,11 +670,6 @@ describe('Debugging tests', () => { .addInput(contractUtxo, contractTestLogs.unlock.transfer(new SignatureTemplate(alicePriv), 1000n)) .addOutput({ to: contractTestLogs.address, amount: 10000n }); - if (vmTarget === 'BCH_2020_05') { - expect(() => transaction.debug()).toThrow('Debugging is not supported for the BCH_2020_05 virtual machine.'); - return; - } - expect(transaction.getLibauthTemplate().supported[0]).toBe(vmTarget ?? 'BCH_2025_05'); const expectedLog = new RegExp(`^\\[Input #0] Test.cash:10 0x[0-9a-f]{130} 0x${binToHex(alicePub)} 1000 0xbeef 1 test true$`); diff --git a/website/docs/releases/release-notes.md b/website/docs/releases/release-notes.md index 703479ab..9576a66d 100644 --- a/website/docs/releases/release-notes.md +++ b/website/docs/releases/release-notes.md @@ -9,6 +9,7 @@ title: Release Notes - :boom: **BREAKING**: Make `provider` a required option in `Contract` constructor. - :boom: **BREAKING**: Remove deprecated "old" transaction builder (`contract.functions`). - :boom: **BREAKING**: No longer seed the MockNetworkProvider with any test UTXOs. +- :sparkles: Add a configurable `vmTarget` option to `MockNetworkProvider`. - :hammer_and_wrench: Improve libauth template generation. ## v0.11.5