@theqrl/hypc 0.0.2 → 0.3.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/README.md +62 -15
- package/abi.js +17 -7
- package/bindings/compile.js +158 -31
- package/bindings/core.js +22 -6
- package/bindings/helpers.js +3 -4
- package/bindings/index.js +13 -6
- package/common/helpers.js +17 -3
- package/downloadCurrentVersion.js +20 -14
- package/formatters.js +2 -3
- package/hypc.js +91 -35
- package/hypjson.js +110 -1732
- package/linker.js +63 -32
- package/package.json +28 -28
- package/smtchecker.js +3 -1
- package/smtsolver.js +44 -17
- package/translate.js +4 -4
- package/verifyVersion.js +17 -7
- package/wrapper.js +305 -30
- package/build/clean.js +0 -6
- package/build/pack-publish-block.js +0 -10
- package/build/postbuild.js +0 -3
- package/contractA_hyp_A.bin +0 -1
- package/contractB_hyp_B.bin +0 -1
- package/importA_hyp_C.bin +0 -1
- package/importB_hyp_D.bin +0 -1
- package/libX_hyp_X.bin +0 -1
- package/libY_hyp_Y.bin +0 -1
- package/libZ_hyp_Z.bin +0 -1
- package/test/abi.js +0 -77
- package/test/cli.js +0 -245
- package/test/compiler.js +0 -791
- package/test/index.js +0 -36
- package/test/linker.js +0 -132
- package/test/resources/fixtureAsmJson.hyp +0 -8
- package/test/resources/fixtureAsmJson.json +0 -528
- package/test/resources/fixtureAsmJson.output +0 -101
- package/test/resources/fixtureIncorrectSource.hyp +0 -1
- package/test/resources/fixtureSmoke.hyp +0 -5
- package/test/resources/importA.hyp +0 -7
- package/test/resources/importB.hyp +0 -5
- package/test/resources/importCallback/base/contractA.hyp +0 -8
- package/test/resources/importCallback/base/contractB.hyp +0 -6
- package/test/resources/importCallback/contractC.hyp +0 -4
- package/test/resources/importCallback/includeA/libX.hyp +0 -4
- package/test/resources/importCallback/includeA/libY.hyp +0 -6
- package/test/resources/importCallback/includeA/utils.hyp +0 -4
- package/test/resources/importCallback/includeB/libZ.hyp +0 -4
- package/test/resources/smtChecker/loop.hyp +0 -8
- package/test/resources/smtChecker/smoke.hyp +0 -5
- package/test/resources/smtChecker/smoke_with_engine.hyp +0 -6
- package/test/resources/smtChecker/smoke_with_multi_engine.hyp +0 -8
- package/test/smtcallback.js +0 -221
- package/test/smtchecker.js +0 -83
- package/test/translate.js +0 -83
- package/test_resources_fixtureSmoke_hyp_C.abi +0 -1
- package/test_resources_fixtureSmoke_hyp_C.bin +0 -1
- package/test_resources_importA_hyp_C.bin +0 -1
- package/test_resources_importB_hyp_D.bin +0 -1
- package/tsconfig.json +0 -25
- package/utils_hyp_Utils.bin +0 -1
|
@@ -18,33 +18,39 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
18
18
|
}) : function(o, v) {
|
|
19
19
|
o["default"] = v;
|
|
20
20
|
});
|
|
21
|
-
var __importStar = (this && this.__importStar) || function (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
31
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
39
|
const fs = __importStar(require("fs"));
|
|
33
40
|
const follow_redirects_1 = require("follow-redirects");
|
|
34
|
-
const memorystream_1 = __importDefault(require("memorystream"));
|
|
35
41
|
const js_sha3_1 = require("js-sha3");
|
|
36
42
|
const pkg = require('./package.json');
|
|
37
43
|
function getVersionList(cb) {
|
|
38
44
|
console.log('Retrieving available version list...');
|
|
39
|
-
const mem = new memorystream_1.default(null, { readable: false });
|
|
40
45
|
follow_redirects_1.https.get('https://binaries.theqrl.org/bin/list.json', function (response) {
|
|
41
46
|
if (response.statusCode !== 200) {
|
|
42
47
|
console.log('Error downloading file: ' + response.statusCode);
|
|
43
48
|
process.exit(1);
|
|
44
49
|
}
|
|
45
|
-
|
|
50
|
+
const chunks = [];
|
|
51
|
+
response.on('data', chunk => chunks.push(chunk));
|
|
46
52
|
response.on('end', function () {
|
|
47
|
-
cb(
|
|
53
|
+
cb(Buffer.concat(chunks).toString());
|
|
48
54
|
});
|
|
49
55
|
});
|
|
50
56
|
}
|
package/formatters.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.formatFatalError =
|
|
3
|
+
exports.formatFatalError = formatFatalError;
|
|
4
4
|
function formatFatalError(message) {
|
|
5
5
|
return JSON.stringify({
|
|
6
6
|
errors: [
|
|
@@ -8,10 +8,9 @@ function formatFatalError(message) {
|
|
|
8
8
|
type: 'JSONError',
|
|
9
9
|
component: 'hypcjs',
|
|
10
10
|
severity: 'error',
|
|
11
|
-
message
|
|
11
|
+
message,
|
|
12
12
|
formattedMessage: 'Error: ' + message
|
|
13
13
|
}
|
|
14
14
|
]
|
|
15
15
|
});
|
|
16
16
|
}
|
|
17
|
-
exports.formatFatalError = formatFatalError;
|
package/hypc.js
CHANGED
|
@@ -16,13 +16,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
16
16
|
}) : function(o, v) {
|
|
17
17
|
o["default"] = v;
|
|
18
18
|
});
|
|
19
|
-
var __importStar = (this && this.__importStar) || function (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
};
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
26
36
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
27
37
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
28
38
|
};
|
|
@@ -41,16 +51,15 @@ const originalUncaughtExceptionListeners = process.listeners('uncaughtException'
|
|
|
41
51
|
process.removeAllListeners('uncaughtException');
|
|
42
52
|
const program = new commander.Command();
|
|
43
53
|
const commanderParseInt = function (value) {
|
|
44
|
-
|
|
45
|
-
if (isNaN(parsedValue)) {
|
|
54
|
+
if (!/^\d+$/.test(value)) {
|
|
46
55
|
throw new commander.InvalidArgumentError('Not a valid integer.');
|
|
47
56
|
}
|
|
48
|
-
return
|
|
57
|
+
return parseInt(value, 10);
|
|
49
58
|
};
|
|
50
59
|
program.name('hypcjs');
|
|
51
|
-
program.version(index_1.default.version());
|
|
60
|
+
program.version(index_1.default.version(), '-V, --version', 'Show version and exit.');
|
|
52
61
|
program
|
|
53
|
-
.
|
|
62
|
+
.argument('[files...]', 'Source files to compile.')
|
|
54
63
|
.option('--optimize', 'Enable bytecode optimizer.', false)
|
|
55
64
|
.option('--optimize-runs <optimize-runs>', 'The number of runs specifies roughly how often each opcode of the deployed code will be executed across the lifetime of the contract. ' +
|
|
56
65
|
'Lower values will optimize more for initial deployment cost, higher values will optimize more for high-frequency usage.', commanderParseInt)
|
|
@@ -73,11 +82,43 @@ function abort(msg) {
|
|
|
73
82
|
console.error(msg || 'Error occurred');
|
|
74
83
|
process.exit(1);
|
|
75
84
|
}
|
|
85
|
+
function realPathIfExists(filePath) {
|
|
86
|
+
try {
|
|
87
|
+
return fs.realpathSync(filePath);
|
|
88
|
+
}
|
|
89
|
+
catch (e) {
|
|
90
|
+
return path.resolve(filePath);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// As in hypc, imports may only be read from the base path (the working directory by default),
|
|
94
|
+
// the include paths and the directories of the files given on the command line. Symlinks are
|
|
95
|
+
// resolved before the check, so a link cannot point outside these directories.
|
|
96
|
+
// Without a base path the working directory is not allowed when it is the root of the filesystem
|
|
97
|
+
// (or of a drive on Windows), since that would make every readable file importable.
|
|
98
|
+
function defaultAllowedDirectories() {
|
|
99
|
+
if (options.basePath) {
|
|
100
|
+
return [options.basePath];
|
|
101
|
+
}
|
|
102
|
+
const workingDirectory = realPathIfExists('.');
|
|
103
|
+
return path.parse(workingDirectory).root === workingDirectory ? [] : [workingDirectory];
|
|
104
|
+
}
|
|
105
|
+
const allowedDirectories = defaultAllowedDirectories()
|
|
106
|
+
.concat(options.includePath || [], files.map((file) => path.dirname(file)))
|
|
107
|
+
.map(realPathIfExists);
|
|
108
|
+
function isInsideAllowedDirectory(filePath) {
|
|
109
|
+
return allowedDirectories.some((directory) => {
|
|
110
|
+
const relativePath = path.relative(directory, filePath);
|
|
111
|
+
return relativePath === '' || (relativePath.split(path.sep)[0] !== '..' && !path.isAbsolute(relativePath));
|
|
112
|
+
});
|
|
113
|
+
}
|
|
76
114
|
function readFileCallback(sourcePath) {
|
|
77
115
|
const prefixes = [options.basePath ? options.basePath : ''].concat(options.includePath ? options.includePath : []);
|
|
78
116
|
for (const prefix of prefixes) {
|
|
79
117
|
const prefixedSourcePath = (prefix ? prefix + '/' : '') + sourcePath;
|
|
80
118
|
if (fs.existsSync(prefixedSourcePath)) {
|
|
119
|
+
if (!isInsideAllowedDirectory(fs.realpathSync(prefixedSourcePath))) {
|
|
120
|
+
return { error: 'File outside of allowed directories.' };
|
|
121
|
+
}
|
|
81
122
|
try {
|
|
82
123
|
return { contents: fs.readFileSync(prefixedSourcePath).toString('utf8') };
|
|
83
124
|
}
|
|
@@ -117,10 +158,25 @@ function makeSourcePathRelativeIfPossible(sourcePath) {
|
|
|
117
158
|
return withUnixPathSeparators(absoluteSourcePath);
|
|
118
159
|
}
|
|
119
160
|
function toFormattedJson(input) {
|
|
120
|
-
return JSON.stringify(input, null,
|
|
161
|
+
return JSON.stringify(input, null, options.prettyJson ? 4 : 0);
|
|
121
162
|
}
|
|
163
|
+
// Input that is not valid JSON is returned as it is, so that the compiler reports it.
|
|
122
164
|
function reformatJsonIfRequested(inputJson) {
|
|
123
|
-
|
|
165
|
+
if (!options.prettyJson) {
|
|
166
|
+
return inputJson;
|
|
167
|
+
}
|
|
168
|
+
try {
|
|
169
|
+
return toFormattedJson(JSON.parse(inputJson));
|
|
170
|
+
}
|
|
171
|
+
catch (e) {
|
|
172
|
+
return inputJson;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// Diagnostics go to stderr, so that stdout carries only the compiler output.
|
|
176
|
+
function verbose(message) {
|
|
177
|
+
if (options.verbose) {
|
|
178
|
+
console.error(message);
|
|
179
|
+
}
|
|
124
180
|
}
|
|
125
181
|
let callbacks;
|
|
126
182
|
if (options.basePath || !options.standardJson) {
|
|
@@ -128,20 +184,16 @@ if (options.basePath || !options.standardJson) {
|
|
|
128
184
|
}
|
|
129
185
|
if (options.standardJson) {
|
|
130
186
|
const input = fs.readFileSync(process.stdin.fd).toString('utf8');
|
|
131
|
-
|
|
132
|
-
console.log('>>> Compiling:\n' + reformatJsonIfRequested(input) + '\n');
|
|
133
|
-
}
|
|
187
|
+
verbose('>>> Compiling:\n' + reformatJsonIfRequested(input) + '\n');
|
|
134
188
|
let output = reformatJsonIfRequested(index_1.default.compile(input, callbacks));
|
|
135
189
|
try {
|
|
136
190
|
if (smtsolver_1.default.availableSolvers.length === 0) {
|
|
137
|
-
|
|
191
|
+
verbose('>>> Cannot retry compilation with SMT because there are no SMT solvers available.');
|
|
138
192
|
}
|
|
139
193
|
else {
|
|
140
194
|
const inputJSON = smtchecker_1.default.handleSMTQueries(JSON.parse(input), JSON.parse(output), smtsolver_1.default.smtSolver, smtsolver_1.default.availableSolvers[0]);
|
|
141
195
|
if (inputJSON) {
|
|
142
|
-
|
|
143
|
-
console.log('>>> Retrying compilation with SMT:\n' + toFormattedJson(inputJSON) + '\n');
|
|
144
|
-
}
|
|
196
|
+
verbose('>>> Retrying compilation with SMT:\n' + toFormattedJson(inputJSON) + '\n');
|
|
145
197
|
output = reformatJsonIfRequested(index_1.default.compile(JSON.stringify(inputJSON), callbacks));
|
|
146
198
|
}
|
|
147
199
|
}
|
|
@@ -160,9 +212,7 @@ if (options.standardJson) {
|
|
|
160
212
|
outputJSON.errors.push(addError);
|
|
161
213
|
output = toFormattedJson(outputJSON);
|
|
162
214
|
}
|
|
163
|
-
|
|
164
|
-
console.log('>>> Compilation result:');
|
|
165
|
-
}
|
|
215
|
+
verbose('>>> Compilation result:');
|
|
166
216
|
console.log(output);
|
|
167
217
|
process.exit(0);
|
|
168
218
|
}
|
|
@@ -203,15 +253,13 @@ const cliInput = {
|
|
|
203
253
|
},
|
|
204
254
|
outputSelection: {
|
|
205
255
|
'*': {
|
|
206
|
-
'*': ['abi', '
|
|
256
|
+
'*': ['abi', 'qrvm.bytecode']
|
|
207
257
|
}
|
|
208
258
|
}
|
|
209
259
|
},
|
|
210
|
-
sources
|
|
260
|
+
sources
|
|
211
261
|
};
|
|
212
|
-
|
|
213
|
-
console.log('>>> Compiling:\n' + toFormattedJson(cliInput) + '\n');
|
|
214
|
-
}
|
|
262
|
+
verbose('>>> Compiling:\n' + toFormattedJson(cliInput) + '\n');
|
|
215
263
|
const output = JSON.parse(index_1.default.compile(JSON.stringify(cliInput), callbacks));
|
|
216
264
|
let hasError = false;
|
|
217
265
|
if (!output) {
|
|
@@ -232,18 +280,26 @@ else if (output.errors) {
|
|
|
232
280
|
fs.mkdirSync(destination, { recursive: true });
|
|
233
281
|
function writeFile(file, content) {
|
|
234
282
|
file = path.join(destination, file);
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
283
|
+
try {
|
|
284
|
+
fs.writeFileSync(file, content);
|
|
285
|
+
}
|
|
286
|
+
catch (err) {
|
|
287
|
+
console.error('Failed to write ' + file + ': ' + err);
|
|
288
|
+
}
|
|
240
289
|
}
|
|
290
|
+
// Output names replace ':', '.', '/' and '\' with '_', so different contracts can map to one name.
|
|
291
|
+
const outputNames = new Map();
|
|
241
292
|
for (const fileName in output.contracts) {
|
|
242
293
|
for (const contractName in output.contracts[fileName]) {
|
|
243
294
|
let contractFileName = fileName + ':' + contractName;
|
|
244
295
|
contractFileName = contractFileName.replace(/[:./\\]/g, '_');
|
|
296
|
+
const previous = outputNames.get(contractFileName);
|
|
297
|
+
if (previous) {
|
|
298
|
+
console.error(`Warning: ${previous} and ${fileName}:${contractName} both write ${contractFileName}; the output of ${fileName}:${contractName} replaces the other.`);
|
|
299
|
+
}
|
|
300
|
+
outputNames.set(contractFileName, `${fileName}:${contractName}`);
|
|
245
301
|
if (options.bin) {
|
|
246
|
-
writeFile(contractFileName + '.bin', output.contracts[fileName][contractName].
|
|
302
|
+
writeFile(contractFileName + '.bin', output.contracts[fileName][contractName].qrvm.bytecode.object);
|
|
247
303
|
}
|
|
248
304
|
if (options.abi) {
|
|
249
305
|
writeFile(contractFileName + '.abi', toFormattedJson(output.contracts[fileName][contractName].abi));
|