@theqrl/hypc 0.0.2
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/LICENSE +0 -0
- package/README.md +361 -0
- package/abi.js +80 -0
- package/bindings/compile.js +157 -0
- package/bindings/core.js +116 -0
- package/bindings/helpers.js +35 -0
- package/bindings/index.js +16 -0
- package/build/clean.js +6 -0
- package/build/pack-publish-block.js +10 -0
- package/build/postbuild.js +3 -0
- package/common/helpers.js +24 -0
- package/common/types.js +2 -0
- package/contractA_hyp_A.bin +1 -0
- package/contractB_hyp_B.bin +1 -0
- package/downloadCurrentVersion.js +93 -0
- package/formatters.js +17 -0
- package/hypc.js +259 -0
- package/hypjson.js +1733 -0
- package/importA_hyp_C.bin +1 -0
- package/importB_hyp_D.bin +1 -0
- package/index.js +7 -0
- package/libX_hyp_X.bin +1 -0
- package/libY_hyp_Y.bin +1 -0
- package/libZ_hyp_Z.bin +1 -0
- package/linker.js +156 -0
- package/package.json +74 -0
- package/smtchecker.js +39 -0
- package/smtsolver.js +89 -0
- package/test/abi.js +77 -0
- package/test/cli.js +245 -0
- package/test/compiler.js +791 -0
- package/test/index.js +36 -0
- package/test/linker.js +132 -0
- package/test/resources/fixtureAsmJson.hyp +8 -0
- package/test/resources/fixtureAsmJson.json +528 -0
- package/test/resources/fixtureAsmJson.output +101 -0
- package/test/resources/fixtureIncorrectSource.hyp +1 -0
- package/test/resources/fixtureSmoke.hyp +5 -0
- package/test/resources/importA.hyp +7 -0
- package/test/resources/importB.hyp +5 -0
- package/test/resources/importCallback/base/contractA.hyp +8 -0
- package/test/resources/importCallback/base/contractB.hyp +6 -0
- package/test/resources/importCallback/contractC.hyp +4 -0
- package/test/resources/importCallback/includeA/libX.hyp +4 -0
- package/test/resources/importCallback/includeA/libY.hyp +6 -0
- package/test/resources/importCallback/includeA/utils.hyp +4 -0
- package/test/resources/importCallback/includeB/libZ.hyp +4 -0
- package/test/resources/smtChecker/loop.hyp +8 -0
- package/test/resources/smtChecker/smoke.hyp +5 -0
- package/test/resources/smtChecker/smoke_with_engine.hyp +6 -0
- package/test/resources/smtChecker/smoke_with_multi_engine.hyp +8 -0
- package/test/smtcallback.js +221 -0
- package/test/smtchecker.js +83 -0
- package/test/translate.js +83 -0
- package/test_resources_fixtureSmoke_hyp_C.abi +1 -0
- package/test_resources_fixtureSmoke_hyp_C.bin +1 -0
- package/test_resources_importA_hyp_C.bin +1 -0
- package/test_resources_importB_hyp_D.bin +1 -0
- package/translate.js +186 -0
- package/tsconfig.json +25 -0
- package/utils_hyp_Utils.bin +1 -0
- package/verifyVersion.js +43 -0
- package/wrapper.js +143 -0
package/bindings/core.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.setupCore = void 0;
|
|
7
|
+
const helpers_1 = require("./helpers");
|
|
8
|
+
const translate_1 = __importDefault(require("../translate"));
|
|
9
|
+
const helpers_2 = require("../common/helpers");
|
|
10
|
+
function setupCore(hypJson) {
|
|
11
|
+
const core = {
|
|
12
|
+
alloc: bindAlloc(hypJson),
|
|
13
|
+
license: bindLicense(hypJson),
|
|
14
|
+
version: bindVersion(hypJson),
|
|
15
|
+
reset: bindReset(hypJson)
|
|
16
|
+
};
|
|
17
|
+
const helpers = {
|
|
18
|
+
addFunction: unboundAddFunction.bind(this, hypJson),
|
|
19
|
+
removeFunction: unboundRemoveFunction.bind(this, hypJson),
|
|
20
|
+
copyFromCString: unboundCopyFromCString.bind(this, hypJson),
|
|
21
|
+
copyToCString: unboundCopyToCString.bind(this, hypJson, core.alloc),
|
|
22
|
+
// @ts-ignore
|
|
23
|
+
versionToSemver: versionToSemver(core.version())
|
|
24
|
+
};
|
|
25
|
+
return {
|
|
26
|
+
...core,
|
|
27
|
+
...helpers
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
exports.setupCore = setupCore;
|
|
31
|
+
/**********************
|
|
32
|
+
* Core Functions
|
|
33
|
+
**********************/
|
|
34
|
+
/**
|
|
35
|
+
* Returns a binding to the hyperion_alloc function.
|
|
36
|
+
*
|
|
37
|
+
* @param hypJson The Emscripten compiled Hyperion object.
|
|
38
|
+
*/
|
|
39
|
+
function bindAlloc(hypJson) {
|
|
40
|
+
const allocBinding = (0, helpers_1.bindHypcMethod)(hypJson, 'hyperion_alloc', 'number', ['number'], null);
|
|
41
|
+
// the fallback malloc is not a cwrap function and should just be returned
|
|
42
|
+
// directly in-case the alloc binding could not happen.
|
|
43
|
+
if ((0, helpers_2.isNil)(allocBinding)) {
|
|
44
|
+
return hypJson._malloc;
|
|
45
|
+
}
|
|
46
|
+
return allocBinding;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Returns a binding to the hyperion_version method.
|
|
50
|
+
*
|
|
51
|
+
* @param hypJson The Emscripten compiled Hyperion object.
|
|
52
|
+
*/
|
|
53
|
+
function bindVersion(hypJson) {
|
|
54
|
+
return (0, helpers_1.bindHypcMethodWithFallbackFunc)(hypJson, 'hyperion_version', 'string', [], 'version');
|
|
55
|
+
}
|
|
56
|
+
function versionToSemver(version) {
|
|
57
|
+
return translate_1.default.versionToSemver.bind(this, version);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Returns a binding to the hyperion_license method.
|
|
61
|
+
*
|
|
62
|
+
* If the current hypJson version < 0.4.14 then this will bind an empty function.
|
|
63
|
+
*
|
|
64
|
+
* @param hypJson The Emscripten compiled Hyperion object.
|
|
65
|
+
*/
|
|
66
|
+
function bindLicense(hypJson) {
|
|
67
|
+
return (0, helpers_1.bindHypcMethodWithFallbackFunc)(hypJson, 'hyperion_license', 'string', [], 'license', () => {
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Returns a binding to the hyperion_reset method.
|
|
72
|
+
*
|
|
73
|
+
* @param hypJson The Emscripten compiled Hyperion object.
|
|
74
|
+
*/
|
|
75
|
+
function bindReset(hypJson) {
|
|
76
|
+
return (0, helpers_1.bindHypcMethod)(hypJson, 'hyperion_reset', null, [], null);
|
|
77
|
+
}
|
|
78
|
+
/**********************
|
|
79
|
+
* Helpers Functions
|
|
80
|
+
**********************/
|
|
81
|
+
/**
|
|
82
|
+
* Copy to a C string.
|
|
83
|
+
*
|
|
84
|
+
* Allocates memory using hypc's allocator.
|
|
85
|
+
*
|
|
86
|
+
* After 0.6.0:
|
|
87
|
+
* The duty is on hypc-js to free these pointers. We accomplish that by calling `reset` at the end.
|
|
88
|
+
*
|
|
89
|
+
* @param hypJson The Emscripten compiled Hyperion object.
|
|
90
|
+
* @param alloc The memory allocation function.
|
|
91
|
+
* @param str The source string being copied to a C string.
|
|
92
|
+
* @param ptr The pointer location where the C string will be set.
|
|
93
|
+
*/
|
|
94
|
+
function unboundCopyToCString(hypJson, alloc, str, ptr) {
|
|
95
|
+
const length = hypJson.lengthBytesUTF8(str);
|
|
96
|
+
const buffer = alloc(length + 1);
|
|
97
|
+
hypJson.stringToUTF8(str, buffer, length + 1);
|
|
98
|
+
hypJson.setValue(ptr, buffer, '*');
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Wrapper over Emscripten's C String copying function (which can be different
|
|
102
|
+
* on different versions).
|
|
103
|
+
*
|
|
104
|
+
* @param hypJson The Emscripten compiled Hyperion object.
|
|
105
|
+
* @param ptr The pointer location where the C string will be referenced.
|
|
106
|
+
*/
|
|
107
|
+
function unboundCopyFromCString(hypJson, ptr) {
|
|
108
|
+
const copyFromCString = hypJson.UTF8ToString || hypJson.Pointer_stringify;
|
|
109
|
+
return copyFromCString(ptr);
|
|
110
|
+
}
|
|
111
|
+
function unboundAddFunction(hypJson, func, signature) {
|
|
112
|
+
return (hypJson.addFunction || hypJson.Runtime.addFunction)(func, signature);
|
|
113
|
+
}
|
|
114
|
+
function unboundRemoveFunction(hypJson, ptr) {
|
|
115
|
+
return (hypJson.removeFunction || hypJson.Runtime.removeFunction)(ptr);
|
|
116
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSupportedMethods = exports.bindHypcMethodWithFallbackFunc = exports.bindHypcMethod = void 0;
|
|
4
|
+
const helpers_1 = require("../common/helpers");
|
|
5
|
+
function bindHypcMethod(hypJson, method, returnType, args, defaultValue) {
|
|
6
|
+
if ((0, helpers_1.isNil)(hypJson[`_${method}`]) && defaultValue !== undefined) {
|
|
7
|
+
return defaultValue;
|
|
8
|
+
}
|
|
9
|
+
return hypJson.cwrap(method, returnType, args);
|
|
10
|
+
}
|
|
11
|
+
exports.bindHypcMethod = bindHypcMethod;
|
|
12
|
+
function bindHypcMethodWithFallbackFunc(hypJson, method, returnType, args, fallbackMethod, finalFallback = undefined) {
|
|
13
|
+
const methodFunc = bindHypcMethod(hypJson, method, returnType, args, null);
|
|
14
|
+
if (!(0, helpers_1.isNil)(methodFunc)) {
|
|
15
|
+
return methodFunc;
|
|
16
|
+
}
|
|
17
|
+
return bindHypcMethod(hypJson, fallbackMethod, returnType, args, finalFallback);
|
|
18
|
+
}
|
|
19
|
+
exports.bindHypcMethodWithFallbackFunc = bindHypcMethodWithFallbackFunc;
|
|
20
|
+
function getSupportedMethods(hypJson) {
|
|
21
|
+
return {
|
|
22
|
+
licenseSupported: anyMethodExists(hypJson, 'hyperion_license'),
|
|
23
|
+
versionSupported: anyMethodExists(hypJson, 'hyperion_version'),
|
|
24
|
+
allocSupported: anyMethodExists(hypJson, 'hyperion_alloc'),
|
|
25
|
+
resetSupported: anyMethodExists(hypJson, 'hyperion_reset'),
|
|
26
|
+
compileJsonSupported: anyMethodExists(hypJson, 'compileJSON'),
|
|
27
|
+
compileJsonMultiSupported: anyMethodExists(hypJson, 'compileJSONMulti'),
|
|
28
|
+
compileJsonCallbackSuppported: anyMethodExists(hypJson, 'compileJSONCallback'),
|
|
29
|
+
compileJsonStandardSupported: anyMethodExists(hypJson, 'compileStandard', 'hyperion_compile')
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
exports.getSupportedMethods = getSupportedMethods;
|
|
33
|
+
function anyMethodExists(hypJson, ...names) {
|
|
34
|
+
return names.some(name => !(0, helpers_1.isNil)(hypJson[`_${name}`]));
|
|
35
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("./core");
|
|
4
|
+
const helpers_1 = require("./helpers");
|
|
5
|
+
const compile_1 = require("./compile");
|
|
6
|
+
function setupBindings(hypJson) {
|
|
7
|
+
const coreBindings = (0, core_1.setupCore)(hypJson);
|
|
8
|
+
const compileBindings = (0, compile_1.setupCompile)(hypJson, coreBindings);
|
|
9
|
+
const methodFlags = (0, helpers_1.getSupportedMethods)(hypJson);
|
|
10
|
+
return {
|
|
11
|
+
methodFlags,
|
|
12
|
+
coreBindings,
|
|
13
|
+
compileBindings
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
exports.default = setupBindings;
|
package/build/clean.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// This is meant to run in a hook before npm pack.
|
|
2
|
+
// Reporting an error from the hook interrupts the command.
|
|
3
|
+
if (process.env.BYPASS_SAFETY_CHECK === 'false' || process.env.BYPASS_SAFETY_CHECK === undefined) {
|
|
4
|
+
console.error('Run `npm run build:tarball` or `npm run publish:tarball` to pack or publish the package');
|
|
5
|
+
process.exit(1);
|
|
6
|
+
}
|
|
7
|
+
else if (process.env.BYPASS_SAFETY_CHECK !== 'true') {
|
|
8
|
+
console.error('Invalid value of the BYPASS_SAFETY_CHECK variable. Must be "true", "false" or unset.');
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isObject = exports.isNil = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Returns true if and only if the value is null or undefined.
|
|
6
|
+
*
|
|
7
|
+
* @param value
|
|
8
|
+
*/
|
|
9
|
+
function isNil(value) {
|
|
10
|
+
// Uses == over === which compares both null and undefined.
|
|
11
|
+
return value == null;
|
|
12
|
+
}
|
|
13
|
+
exports.isNil = isNil;
|
|
14
|
+
/**
|
|
15
|
+
* Returns true if and only if the value is an object and not an array.
|
|
16
|
+
*
|
|
17
|
+
* @param value
|
|
18
|
+
*/
|
|
19
|
+
function isObject(value) {
|
|
20
|
+
// typeof [] will result in an 'object' so this additionally uses Array.isArray
|
|
21
|
+
// to confirm it's just an object.
|
|
22
|
+
return typeof value === 'object' && !Array.isArray(value);
|
|
23
|
+
}
|
|
24
|
+
exports.isObject = isObject;
|
package/common/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
6080604052348015600e575f80fd5b50603e80601a5f395ff3fe60806040525f80fdfea26469706673582212207da9777c17d9abc5309ba89332ae703efba54bf7fb9c290d475d6c0f7cb7a6c86468797063430000020033
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
6080604052348015600e575f80fd5b50603e80601a5f395ff3fe60806040525f80fdfea264697066735822122019ceaad2fc0893d39b61042424757a67bf6723d77172da4c38279007c2723bbf6468797063430000020033
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
// This is used to download the correct binary version
|
|
4
|
+
// as part of the prepublish step.
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
22
|
+
if (mod && mod.__esModule) return mod;
|
|
23
|
+
var result = {};
|
|
24
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
25
|
+
__setModuleDefault(result, mod);
|
|
26
|
+
return result;
|
|
27
|
+
};
|
|
28
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
29
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
30
|
+
};
|
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
+
const fs = __importStar(require("fs"));
|
|
33
|
+
const follow_redirects_1 = require("follow-redirects");
|
|
34
|
+
const memorystream_1 = __importDefault(require("memorystream"));
|
|
35
|
+
const js_sha3_1 = require("js-sha3");
|
|
36
|
+
const pkg = require('./package.json');
|
|
37
|
+
function getVersionList(cb) {
|
|
38
|
+
console.log('Retrieving available version list...');
|
|
39
|
+
const mem = new memorystream_1.default(null, { readable: false });
|
|
40
|
+
follow_redirects_1.https.get('https://binaries.theqrl.org/bin/list.json', function (response) {
|
|
41
|
+
if (response.statusCode !== 200) {
|
|
42
|
+
console.log('Error downloading file: ' + response.statusCode);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
response.pipe(mem);
|
|
46
|
+
response.on('end', function () {
|
|
47
|
+
cb(mem.toString());
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function downloadBinary(outputName, version, expectedHash) {
|
|
52
|
+
console.log('Downloading version', version);
|
|
53
|
+
// Remove if existing
|
|
54
|
+
if (fs.existsSync(outputName)) {
|
|
55
|
+
fs.unlinkSync(outputName);
|
|
56
|
+
}
|
|
57
|
+
process.on('SIGINT', function () {
|
|
58
|
+
console.log('Interrupted, removing file.');
|
|
59
|
+
fs.unlinkSync(outputName);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
});
|
|
62
|
+
const file = fs.createWriteStream(outputName, { encoding: 'binary' });
|
|
63
|
+
follow_redirects_1.https.get('https://binaries.theqrl.org/bin/' + version, function (response) {
|
|
64
|
+
if (response.statusCode !== 200) {
|
|
65
|
+
console.log('Error downloading file: ' + response.statusCode);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
response.pipe(file);
|
|
69
|
+
file.on('finish', function () {
|
|
70
|
+
file.close(function () {
|
|
71
|
+
const hash = '0x' + (0, js_sha3_1.keccak256)(fs.readFileSync(outputName, { encoding: 'binary' }));
|
|
72
|
+
if (expectedHash !== hash) {
|
|
73
|
+
console.log('Hash mismatch: ' + expectedHash + ' vs ' + hash);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
console.log('Done.');
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
console.log('Downloading correct hyperion binary...');
|
|
82
|
+
getVersionList(function (list) {
|
|
83
|
+
list = JSON.parse(list);
|
|
84
|
+
const wanted = pkg.version.match(/^(\d+\.\d+\.\d+)$/)[1];
|
|
85
|
+
const releaseFileName = list.releases[wanted];
|
|
86
|
+
const expectedFile = list.builds.filter(function (entry) { return entry.path === releaseFileName; })[0];
|
|
87
|
+
if (!expectedFile) {
|
|
88
|
+
console.log('Version list is invalid or corrupted?');
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
const expectedHash = expectedFile.keccak256;
|
|
92
|
+
downloadBinary('hypjson.js', releaseFileName, expectedHash);
|
|
93
|
+
});
|
package/formatters.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatFatalError = void 0;
|
|
4
|
+
function formatFatalError(message) {
|
|
5
|
+
return JSON.stringify({
|
|
6
|
+
errors: [
|
|
7
|
+
{
|
|
8
|
+
type: 'JSONError',
|
|
9
|
+
component: 'hypcjs',
|
|
10
|
+
severity: 'error',
|
|
11
|
+
message: message,
|
|
12
|
+
formattedMessage: 'Error: ' + message
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
exports.formatFatalError = formatFatalError;
|
package/hypc.js
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
20
|
+
if (mod && mod.__esModule) return mod;
|
|
21
|
+
var result = {};
|
|
22
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
23
|
+
__setModuleDefault(result, mod);
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
26
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
27
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
28
|
+
};
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
const commander = __importStar(require("commander"));
|
|
31
|
+
const fs = __importStar(require("fs"));
|
|
32
|
+
const os = __importStar(require("os"));
|
|
33
|
+
const path = __importStar(require("path"));
|
|
34
|
+
const index_1 = __importDefault(require("./index"));
|
|
35
|
+
const smtchecker_1 = __importDefault(require("./smtchecker"));
|
|
36
|
+
const smtsolver_1 = __importDefault(require("./smtsolver"));
|
|
37
|
+
// hold on to any exception handlers that existed prior to this script running, we'll be adding them back at the end
|
|
38
|
+
const originalUncaughtExceptionListeners = process.listeners('uncaughtException');
|
|
39
|
+
// FIXME: remove annoying exception catcher of Emscripten
|
|
40
|
+
// see https://github.com/chriseth/browser-solidity/issues/167
|
|
41
|
+
process.removeAllListeners('uncaughtException');
|
|
42
|
+
const program = new commander.Command();
|
|
43
|
+
const commanderParseInt = function (value) {
|
|
44
|
+
const parsedValue = parseInt(value, 10);
|
|
45
|
+
if (isNaN(parsedValue)) {
|
|
46
|
+
throw new commander.InvalidArgumentError('Not a valid integer.');
|
|
47
|
+
}
|
|
48
|
+
return parsedValue;
|
|
49
|
+
};
|
|
50
|
+
program.name('hypcjs');
|
|
51
|
+
program.version(index_1.default.version());
|
|
52
|
+
program
|
|
53
|
+
.option('--version', 'Show version and exit.')
|
|
54
|
+
.option('--optimize', 'Enable bytecode optimizer.', false)
|
|
55
|
+
.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
|
+
'Lower values will optimize more for initial deployment cost, higher values will optimize more for high-frequency usage.', commanderParseInt)
|
|
57
|
+
.option('--bin', 'Binary of the contracts in hex.')
|
|
58
|
+
.option('--abi', 'ABI of the contracts.')
|
|
59
|
+
.option('--standard-json', 'Turn on Standard JSON Input / Output mode.')
|
|
60
|
+
.option('--base-path <path>', 'Root of the project source tree. ' +
|
|
61
|
+
'The import callback will attempt to interpret all import paths as relative to this directory.')
|
|
62
|
+
.option('--include-path <path...>', 'Extra source directories available to the import callback. ' +
|
|
63
|
+
'When using a package manager to install libraries, use this option to specify directories where packages are installed. ' +
|
|
64
|
+
'Can be used multiple times to provide multiple locations.')
|
|
65
|
+
.option('-o, --output-dir <output-directory>', 'Output directory for the contracts.')
|
|
66
|
+
.option('-p, --pretty-json', 'Pretty-print all JSON output.', false)
|
|
67
|
+
.option('-v, --verbose', 'More detailed console output.', false);
|
|
68
|
+
program.parse(process.argv);
|
|
69
|
+
const options = program.opts();
|
|
70
|
+
const files = program.args;
|
|
71
|
+
const destination = options.outputDir || '.';
|
|
72
|
+
function abort(msg) {
|
|
73
|
+
console.error(msg || 'Error occurred');
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
function readFileCallback(sourcePath) {
|
|
77
|
+
const prefixes = [options.basePath ? options.basePath : ''].concat(options.includePath ? options.includePath : []);
|
|
78
|
+
for (const prefix of prefixes) {
|
|
79
|
+
const prefixedSourcePath = (prefix ? prefix + '/' : '') + sourcePath;
|
|
80
|
+
if (fs.existsSync(prefixedSourcePath)) {
|
|
81
|
+
try {
|
|
82
|
+
return { contents: fs.readFileSync(prefixedSourcePath).toString('utf8') };
|
|
83
|
+
}
|
|
84
|
+
catch (e) {
|
|
85
|
+
return { error: 'Error reading ' + prefixedSourcePath + ': ' + e };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return { error: 'File not found inside the base path or any of the include paths.' };
|
|
90
|
+
}
|
|
91
|
+
function withUnixPathSeparators(filePath) {
|
|
92
|
+
// On UNIX-like systems forward slashes in paths are just a part of the file name.
|
|
93
|
+
if (os.platform() !== 'win32') {
|
|
94
|
+
return filePath;
|
|
95
|
+
}
|
|
96
|
+
return filePath.replace(/\\/g, '/');
|
|
97
|
+
}
|
|
98
|
+
function makeSourcePathRelativeIfPossible(sourcePath) {
|
|
99
|
+
const absoluteBasePath = (options.basePath ? path.resolve(options.basePath) : path.resolve('.'));
|
|
100
|
+
const absoluteIncludePaths = (options.includePath
|
|
101
|
+
? options.includePath.map((prefix) => { return path.resolve(prefix); })
|
|
102
|
+
: []);
|
|
103
|
+
// Compared to base path stripping logic in hypc this is much simpler because path.resolve()
|
|
104
|
+
// handles symlinks correctly (does not resolve them except in work dir) and strips .. segments
|
|
105
|
+
// from paths going beyond root (e.g. `/../../a/b/c` -> `/a/b/c/`). It's simpler also because it
|
|
106
|
+
// ignores less important corner cases: drive letters are not stripped from absolute paths on
|
|
107
|
+
// Windows and UNC paths are not handled in a special way (at least on Linux). Finally, it has
|
|
108
|
+
// very little test coverage so there might be more differences that we are just not aware of.
|
|
109
|
+
const absoluteSourcePath = path.resolve(sourcePath);
|
|
110
|
+
for (const absolutePrefix of [absoluteBasePath].concat(absoluteIncludePaths)) {
|
|
111
|
+
const relativeSourcePath = path.relative(absolutePrefix, absoluteSourcePath);
|
|
112
|
+
if (!relativeSourcePath.startsWith('../')) {
|
|
113
|
+
return withUnixPathSeparators(relativeSourcePath);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// File is not located inside base path or include paths so use its absolute path.
|
|
117
|
+
return withUnixPathSeparators(absoluteSourcePath);
|
|
118
|
+
}
|
|
119
|
+
function toFormattedJson(input) {
|
|
120
|
+
return JSON.stringify(input, null, program.prettyJson ? 4 : 0);
|
|
121
|
+
}
|
|
122
|
+
function reformatJsonIfRequested(inputJson) {
|
|
123
|
+
return (program.prettyJson ? toFormattedJson(JSON.parse(inputJson)) : inputJson);
|
|
124
|
+
}
|
|
125
|
+
let callbacks;
|
|
126
|
+
if (options.basePath || !options.standardJson) {
|
|
127
|
+
callbacks = { import: readFileCallback };
|
|
128
|
+
}
|
|
129
|
+
if (options.standardJson) {
|
|
130
|
+
const input = fs.readFileSync(process.stdin.fd).toString('utf8');
|
|
131
|
+
if (program.verbose) {
|
|
132
|
+
console.log('>>> Compiling:\n' + reformatJsonIfRequested(input) + '\n');
|
|
133
|
+
}
|
|
134
|
+
let output = reformatJsonIfRequested(index_1.default.compile(input, callbacks));
|
|
135
|
+
try {
|
|
136
|
+
if (smtsolver_1.default.availableSolvers.length === 0) {
|
|
137
|
+
console.log('>>> Cannot retry compilation with SMT because there are no SMT solvers available.');
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
const inputJSON = smtchecker_1.default.handleSMTQueries(JSON.parse(input), JSON.parse(output), smtsolver_1.default.smtSolver, smtsolver_1.default.availableSolvers[0]);
|
|
141
|
+
if (inputJSON) {
|
|
142
|
+
if (program.verbose) {
|
|
143
|
+
console.log('>>> Retrying compilation with SMT:\n' + toFormattedJson(inputJSON) + '\n');
|
|
144
|
+
}
|
|
145
|
+
output = reformatJsonIfRequested(index_1.default.compile(JSON.stringify(inputJSON), callbacks));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
catch (e) {
|
|
150
|
+
const addError = {
|
|
151
|
+
component: 'general',
|
|
152
|
+
formattedMessage: e.toString(),
|
|
153
|
+
message: e.toString(),
|
|
154
|
+
type: 'Warning'
|
|
155
|
+
};
|
|
156
|
+
const outputJSON = JSON.parse(output);
|
|
157
|
+
if (!outputJSON.errors) {
|
|
158
|
+
outputJSON.errors = [];
|
|
159
|
+
}
|
|
160
|
+
outputJSON.errors.push(addError);
|
|
161
|
+
output = toFormattedJson(outputJSON);
|
|
162
|
+
}
|
|
163
|
+
if (program.verbose) {
|
|
164
|
+
console.log('>>> Compilation result:');
|
|
165
|
+
}
|
|
166
|
+
console.log(output);
|
|
167
|
+
process.exit(0);
|
|
168
|
+
}
|
|
169
|
+
else if (files.length === 0) {
|
|
170
|
+
console.error('Must provide a file');
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
if (!(options.bin || options.abi)) {
|
|
174
|
+
abort('Invalid option selected, must specify either --bin or --abi');
|
|
175
|
+
}
|
|
176
|
+
if (!options.basePath && options.includePath && options.includePath.length > 0) {
|
|
177
|
+
abort('--include-path option requires a non-empty base path.');
|
|
178
|
+
}
|
|
179
|
+
if (options.includePath) {
|
|
180
|
+
for (const includePath of options.includePath) {
|
|
181
|
+
if (!includePath) {
|
|
182
|
+
abort('Empty values are not allowed in --include-path.');
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const sources = {};
|
|
187
|
+
for (let i = 0; i < files.length; i++) {
|
|
188
|
+
try {
|
|
189
|
+
sources[makeSourcePathRelativeIfPossible(files[i])] = {
|
|
190
|
+
content: fs.readFileSync(files[i]).toString()
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
catch (e) {
|
|
194
|
+
abort('Error reading ' + files[i] + ': ' + e);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
const cliInput = {
|
|
198
|
+
language: 'Hyperion',
|
|
199
|
+
settings: {
|
|
200
|
+
optimizer: {
|
|
201
|
+
enabled: options.optimize,
|
|
202
|
+
runs: options.optimizeRuns
|
|
203
|
+
},
|
|
204
|
+
outputSelection: {
|
|
205
|
+
'*': {
|
|
206
|
+
'*': ['abi', 'zvm.bytecode']
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
sources: sources
|
|
211
|
+
};
|
|
212
|
+
if (program.verbose) {
|
|
213
|
+
console.log('>>> Compiling:\n' + toFormattedJson(cliInput) + '\n');
|
|
214
|
+
}
|
|
215
|
+
const output = JSON.parse(index_1.default.compile(JSON.stringify(cliInput), callbacks));
|
|
216
|
+
let hasError = false;
|
|
217
|
+
if (!output) {
|
|
218
|
+
abort('No output from compiler');
|
|
219
|
+
}
|
|
220
|
+
else if (output.errors) {
|
|
221
|
+
for (const error in output.errors) {
|
|
222
|
+
const message = output.errors[error];
|
|
223
|
+
if (message.severity === 'warning') {
|
|
224
|
+
console.log(message.formattedMessage);
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
console.error(message.formattedMessage);
|
|
228
|
+
hasError = true;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
fs.mkdirSync(destination, { recursive: true });
|
|
233
|
+
function writeFile(file, content) {
|
|
234
|
+
file = path.join(destination, file);
|
|
235
|
+
fs.writeFile(file, content, function (err) {
|
|
236
|
+
if (err) {
|
|
237
|
+
console.error('Failed to write ' + file + ': ' + err);
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
for (const fileName in output.contracts) {
|
|
242
|
+
for (const contractName in output.contracts[fileName]) {
|
|
243
|
+
let contractFileName = fileName + ':' + contractName;
|
|
244
|
+
contractFileName = contractFileName.replace(/[:./\\]/g, '_');
|
|
245
|
+
if (options.bin) {
|
|
246
|
+
writeFile(contractFileName + '.bin', output.contracts[fileName][contractName].zvm.bytecode.object);
|
|
247
|
+
}
|
|
248
|
+
if (options.abi) {
|
|
249
|
+
writeFile(contractFileName + '.abi', toFormattedJson(output.contracts[fileName][contractName].abi));
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// Put back original exception handlers.
|
|
254
|
+
originalUncaughtExceptionListeners.forEach(function (listener) {
|
|
255
|
+
process.addListener('uncaughtException', listener);
|
|
256
|
+
});
|
|
257
|
+
if (hasError) {
|
|
258
|
+
process.exit(1);
|
|
259
|
+
}
|