@cashscript/utils 0.13.1 → 0.14.0-next.0
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/bitauth-script.js +17 -0
- package/dist/script.js +20 -2
- package/dist/types.d.ts +5 -2
- package/dist/types.js +10 -0
- package/package.json +2 -2
package/dist/bitauth-script.js
CHANGED
|
@@ -48,6 +48,11 @@ const PROLOGUE_KINDS = [
|
|
|
48
48
|
SourceTagKind.LOCKTIME_GUARD,
|
|
49
49
|
SourceTagKind.PARAMETER_VALIDATION,
|
|
50
50
|
];
|
|
51
|
+
// Compiler-injected epilogue checks: emitted after the function/loop body
|
|
52
|
+
const EPILOGUE_KINDS = [
|
|
53
|
+
SourceTagKind.SCOPE_CLEANUP,
|
|
54
|
+
SourceTagKind.LOOP_CONDITION,
|
|
55
|
+
];
|
|
51
56
|
function buildInsertions(locationData, sourceLines, sourceTags) {
|
|
52
57
|
const tags = (sourceTags ? parseSourceTags(sourceTags) : []);
|
|
53
58
|
return tags.map((tag) => {
|
|
@@ -70,6 +75,14 @@ function deriveAnchor(tag, tags, locationData, sourceLines) {
|
|
|
70
75
|
indent: lineIndent(sourceLines, firstBodyLine),
|
|
71
76
|
};
|
|
72
77
|
}
|
|
78
|
+
// Scope cleanup and loop-back condition tags always get inserted right before the scope's closing brace.
|
|
79
|
+
if (EPILOGUE_KINDS.includes(tag.kind)) {
|
|
80
|
+
const braceLine = getDisplayLine(locationData[tag.startIndex]);
|
|
81
|
+
return {
|
|
82
|
+
insertAfterLine: braceLine - 1,
|
|
83
|
+
indent: deriveIndent(locationData[tag.startIndex].location.start.line, sourceLines),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
73
86
|
return {
|
|
74
87
|
insertAfterLine: getDisplayLine(locationData[Math.max(tag.startIndex - 1, 0)]),
|
|
75
88
|
indent: deriveIndent(getDisplayLine(locationData[tag.startIndex]), sourceLines),
|
|
@@ -113,6 +126,10 @@ function tagDescription(tag, locationData, sourceLines) {
|
|
|
113
126
|
const parameter = deriveSourceText(tag, locationData, sourceLines);
|
|
114
127
|
return `>>> parameter type check${parameter ? ` (${parameter})` : ''}`;
|
|
115
128
|
}
|
|
129
|
+
case SourceTagKind.SCOPE_CLEANUP:
|
|
130
|
+
return '>>> scope cleanup';
|
|
131
|
+
case SourceTagKind.LOOP_CONDITION:
|
|
132
|
+
return '>>> loop condition check';
|
|
116
133
|
case SourceTagKind.FOR_UPDATE:
|
|
117
134
|
default:
|
|
118
135
|
return `>>> for-loop update (${deriveSourceText(tag, locationData, sourceLines)})`;
|
package/dist/script.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { encodeDataPush, hexToBin, disassembleBytecodeBch, flattenBinArray, encodeAuthenticationInstructions, decodeAuthenticationInstructions, OpcodesBch, } from '@bitauth/libauth';
|
|
2
2
|
import OptimisationsEquivFile from './cashproof-optimisations.js';
|
|
3
3
|
import { optimisationReplacements } from './optimisations.js';
|
|
4
|
-
import {
|
|
4
|
+
import { range } from './data.js';
|
|
5
|
+
import { PositionHint, SourceTagKind } from './types.js';
|
|
5
6
|
export const Op = OpcodesBch;
|
|
6
7
|
export function scriptToAsm(script) {
|
|
7
8
|
return bytecodeToAsm(scriptToBytecode(script));
|
|
@@ -120,7 +121,24 @@ export function optimiseBytecode(script, locationData, logs, requires, sourceTag
|
|
|
120
121
|
requires = newRequires;
|
|
121
122
|
sourceTags = newSourceTags;
|
|
122
123
|
}
|
|
123
|
-
return { script, locationData, logs, requires, sourceTags };
|
|
124
|
+
return { script, locationData, logs, requires, sourceTags: reconcileScopeCleanupTags(script, sourceTags) };
|
|
125
|
+
}
|
|
126
|
+
const SCOPE_CLEANUP_OPCODES = [Op.OP_DROP, Op.OP_NIP, Op.OP_2DROP];
|
|
127
|
+
// Make sure that scope cleanup tags are only displayed if they did not merge with other tags or drift
|
|
128
|
+
// due to compiler optimisations.
|
|
129
|
+
function reconcileScopeCleanupTags(script, sourceTags) {
|
|
130
|
+
const otherTags = sourceTags.filter((tag) => tag.kind !== SourceTagKind.SCOPE_CLEANUP);
|
|
131
|
+
return sourceTags.filter((tag) => {
|
|
132
|
+
if (tag.kind !== SourceTagKind.SCOPE_CLEANUP)
|
|
133
|
+
return true;
|
|
134
|
+
const isOnlyCleanupOpcodes = range(tag.startIndex, tag.endIndex)
|
|
135
|
+
.every((index) => SCOPE_CLEANUP_OPCODES.includes(script[index]));
|
|
136
|
+
if (!isOnlyCleanupOpcodes)
|
|
137
|
+
return false;
|
|
138
|
+
const overlapsOtherTag = otherTags
|
|
139
|
+
.some((other) => tag.startIndex <= other.endIndex && other.startIndex <= tag.endIndex);
|
|
140
|
+
return !overlapsOtherTag;
|
|
141
|
+
});
|
|
124
142
|
}
|
|
125
143
|
export function optimiseBytecodeOld(script, runs = 1000) {
|
|
126
144
|
const optimisations = OptimisationsEquivFile
|
package/dist/types.d.ts
CHANGED
|
@@ -24,7 +24,8 @@ export declare enum PrimitiveType {
|
|
|
24
24
|
PUBKEY = "pubkey",
|
|
25
25
|
SIG = "sig",
|
|
26
26
|
DATASIG = "datasig",
|
|
27
|
-
ANY = "any"
|
|
27
|
+
ANY = "any",
|
|
28
|
+
VOID = "void"
|
|
28
29
|
}
|
|
29
30
|
export declare function explicitlyCastable(from?: Type, to?: Type): boolean;
|
|
30
31
|
export declare function implicitlyCastable(actual?: Type, expected?: Type): boolean;
|
|
@@ -54,7 +55,9 @@ export declare enum PositionHint {
|
|
|
54
55
|
export declare enum SourceTagKind {
|
|
55
56
|
FOR_UPDATE = "fu",
|
|
56
57
|
LOCKTIME_GUARD = "lg",
|
|
57
|
-
PARAMETER_VALIDATION = "pv"
|
|
58
|
+
PARAMETER_VALIDATION = "pv",
|
|
59
|
+
SCOPE_CLEANUP = "sc",
|
|
60
|
+
LOOP_CONDITION = "lc"
|
|
58
61
|
}
|
|
59
62
|
export interface SourceTagEntry {
|
|
60
63
|
startIndex: number;
|
package/dist/types.js
CHANGED
|
@@ -38,6 +38,7 @@ export var PrimitiveType;
|
|
|
38
38
|
PrimitiveType["SIG"] = "sig";
|
|
39
39
|
PrimitiveType["DATASIG"] = "datasig";
|
|
40
40
|
PrimitiveType["ANY"] = "any";
|
|
41
|
+
PrimitiveType["VOID"] = "void";
|
|
41
42
|
})(PrimitiveType || (PrimitiveType = {}));
|
|
42
43
|
const ExplicitlyCastableTo = {
|
|
43
44
|
[PrimitiveType.INT]: [PrimitiveType.INT, PrimitiveType.BOOL],
|
|
@@ -47,10 +48,14 @@ const ExplicitlyCastableTo = {
|
|
|
47
48
|
[PrimitiveType.SIG]: [PrimitiveType.SIG],
|
|
48
49
|
[PrimitiveType.DATASIG]: [PrimitiveType.DATASIG],
|
|
49
50
|
[PrimitiveType.ANY]: [],
|
|
51
|
+
[PrimitiveType.VOID]: [],
|
|
50
52
|
};
|
|
51
53
|
export function explicitlyCastable(from, to) {
|
|
52
54
|
if (!from || !to)
|
|
53
55
|
return false;
|
|
56
|
+
// `void` is not a real value type, so it can never participate in a cast
|
|
57
|
+
if (from === PrimitiveType.VOID || to === PrimitiveType.VOID)
|
|
58
|
+
return false;
|
|
54
59
|
// Tuples can't be cast
|
|
55
60
|
if (from instanceof TupleType || to instanceof TupleType)
|
|
56
61
|
return false;
|
|
@@ -104,6 +109,9 @@ export function explicitlyCastable(from, to) {
|
|
|
104
109
|
export function implicitlyCastable(actual, expected) {
|
|
105
110
|
if (!actual || !expected)
|
|
106
111
|
return false;
|
|
112
|
+
// `void` is not a real value type, so it can never be assigned to or from (not even to `any`)
|
|
113
|
+
if (actual === PrimitiveType.VOID || expected === PrimitiveType.VOID)
|
|
114
|
+
return false;
|
|
107
115
|
if (actual instanceof TupleType && expected instanceof TupleType) {
|
|
108
116
|
const leftIsCompatible = implicitlyCastable(actual.leftType, expected.leftType);
|
|
109
117
|
const rightIsCompatible = implicitlyCastable(actual.rightType, expected.rightType);
|
|
@@ -197,5 +205,7 @@ export var SourceTagKind;
|
|
|
197
205
|
SourceTagKind["FOR_UPDATE"] = "fu";
|
|
198
206
|
SourceTagKind["LOCKTIME_GUARD"] = "lg";
|
|
199
207
|
SourceTagKind["PARAMETER_VALIDATION"] = "pv";
|
|
208
|
+
SourceTagKind["SCOPE_CLEANUP"] = "sc";
|
|
209
|
+
SourceTagKind["LOOP_CONDITION"] = "lc";
|
|
200
210
|
})(SourceTagKind || (SourceTagKind = {}));
|
|
201
211
|
//# sourceMappingURL=types.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cashscript/utils",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0-next.0",
|
|
4
4
|
"description": "CashScript utilities and types",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bitcoin cash",
|
|
@@ -48,5 +48,5 @@
|
|
|
48
48
|
"typescript": "^5.9.2",
|
|
49
49
|
"vitest": "^4.0.15"
|
|
50
50
|
},
|
|
51
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "790d4a2c608ef492a9a1f886b1489d2e4ffe95e2"
|
|
52
52
|
}
|