forked from ethereum/solc-js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
smtsolver.js
59 lines (54 loc) · 1.69 KB
/
smtsolver.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
var commandExistsSync = require('command-exists').sync;
var execSync = require('child_process').execSync;
var fs = require('fs');
var tmp = require('tmp');
const timeout = 10000;
var potentialSolvers = [
{
name: 'z3',
params: '-smt2 -t:' + timeout
},
{
name: 'cvc4',
params: '--lang=smt2 --tlimit=' + timeout
}
];
var solvers = potentialSolvers.filter(solver => commandExistsSync(solver.name));
function solve (query) {
if (solvers.length === 0) {
throw new Error('No SMT solver available. Assertion checking will not be performed.');
}
var tmpFile = tmp.fileSync({ postfix: '.smt2' });
fs.writeFileSync(tmpFile.name, query);
// TODO For now only the first SMT solver found is used.
// At some point a computation similar to the one done in
// SMTPortfolio::check should be performed, where the results
// given by different solvers are compared and an error is
// reported if solvers disagree (i.e. SAT vs UNSAT).
var solverOutput;
try {
solverOutput = execSync(
solvers[0].name + ' ' + solvers[0].params + ' ' + tmpFile.name, {
timeout: 10000
}
).toString();
} catch (e) {
// execSync throws if the process times out or returns != 0.
// The latter might happen with z3 if the query asks for a model
// for an UNSAT formula. We can still use stdout.
solverOutput = e.stdout.toString();
if (
!solverOutput.startsWith('sat') &&
!solverOutput.startsWith('unsat') &&
!solverOutput.startsWith('unknown')
) {
throw new Error('Failed solve SMT query. ' + e.toString());
}
}
// Trigger early manual cleanup
tmpFile.removeCallback();
return solverOutput;
}
module.exports = {
smtSolver: solve
};