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
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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(
|
|
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,
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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,
|
|
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
|
-
:
|
|
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
|
|
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 ??
|
|
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.
|
|
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.
|
|
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": "
|
|
64
|
+
"gitHead": "f3d3fd75400c93f4457276b56ce094b11c0986d7"
|
|
65
65
|
}
|