public TranslatorContext(AST solidityAST, HashSet <Tuple <string, string> > ignoreMethods, bool _genInlineAttrInBpl, TranslatorFlags _translateFlags = null, String entryPointContract = "") { Program = new BoogieProgram(); ContractDefinitions = new HashSet <ContractDefinition>(); ASTNodeToSourcePathMap = new Dictionary <ASTNode, string>(); ASTNodeToSourceLineNumberMap = new Dictionary <ASTNode, int>(); ContractToSubTypesMap = new Dictionary <ContractDefinition, HashSet <ContractDefinition> >(); ContractToStateVarsMap = new Dictionary <ContractDefinition, HashSet <VariableDeclaration> >(); ContractToMappingsMap = new Dictionary <ContractDefinition, HashSet <VariableDeclaration> >(); ContractToArraysMap = new Dictionary <ContractDefinition, HashSet <VariableDeclaration> >(); StateVarToContractMap = new Dictionary <VariableDeclaration, ContractDefinition>(); ContractToConstructorMap = new Dictionary <ContractDefinition, FunctionDefinition>(); ContractToFallbackMap = new Dictionary <ContractDefinition, FunctionDefinition>(); ContractToEventsMap = new Dictionary <ContractDefinition, HashSet <EventDefinition> >(); EventToContractMap = new Dictionary <EventDefinition, ContractDefinition>(); ContractToFunctionsMap = new Dictionary <ContractDefinition, HashSet <FunctionDefinition> >(); ContractToFuncSigsMap = new Dictionary <ContractDefinition, HashSet <string> >(); FunctionToContractMap = new Dictionary <FunctionDefinition, ContractDefinition>(); FuncSigResolutionMap = new Dictionary <string, Dictionary <ContractDefinition, FunctionDefinition> >(); ContractToVisibleFunctionsMap = new Dictionary <ContractDefinition, HashSet <FunctionDefinition> >(); StateVarNameResolutionMap = new Dictionary <string, Dictionary <ContractDefinition, VariableDeclaration> >(); ContractToVisibleStateVarsMap = new Dictionary <ContractDefinition, HashSet <VariableDeclaration> >(); ModifierToBoogiePreProc = new Dictionary <string, BoogieProcedure>(); ModifierToBoogiePostProc = new Dictionary <string, BoogieProcedure>(); ModifierToBoogiePreImpl = new Dictionary <string, BoogieImplementation>(); ModifierToBoogiePostImpl = new Dictionary <string, BoogieImplementation>(); ModifierToPreludeLocalVars = new Dictionary <string, List <BoogieLocalVariable> >(); usingMap = new Dictionary <ContractDefinition, Dictionary <UserDefinedTypeName, List <TypeName> > >(); IgnoreMethods = ignoreMethods; genInlineAttrInBpl = _genInlineAttrInBpl; TranslateFlags = _translateFlags; EntryPointContract = entryPointContract; Analysis = new SolidityAnalyzer(solidityAST, ignoreMethods, entryPointContract); initFns = new HashSet <String>(); }
public TranslatorContext(HashSet <Tuple <string, string> > ignoreMethods, bool _genInlineAttrInBpl, TranslatorFlags _translateFlags = null) { Program = new BoogieProgram(); ContractDefinitions = new HashSet <ContractDefinition>(); ASTNodeToSourcePathMap = new Dictionary <ASTNode, string>(); ASTNodeToSourceLineNumberMap = new Dictionary <ASTNode, int>(); ContractToSubTypesMap = new Dictionary <ContractDefinition, HashSet <ContractDefinition> >(); ContractToStateVarsMap = new Dictionary <ContractDefinition, HashSet <VariableDeclaration> >(); ContractToMappingsMap = new Dictionary <ContractDefinition, HashSet <VariableDeclaration> >(); ContractToArraysMap = new Dictionary <ContractDefinition, HashSet <VariableDeclaration> >(); StateVarToContractMap = new Dictionary <VariableDeclaration, ContractDefinition>(); ContractToConstructorMap = new Dictionary <ContractDefinition, FunctionDefinition>(); ContractToFallbackMap = new Dictionary <ContractDefinition, FunctionDefinition>(); ContractToEventsMap = new Dictionary <ContractDefinition, HashSet <EventDefinition> >(); EventToContractMap = new Dictionary <EventDefinition, ContractDefinition>(); ContractToFunctionsMap = new Dictionary <ContractDefinition, HashSet <FunctionDefinition> >(); ContractToFuncSigsMap = new Dictionary <ContractDefinition, HashSet <string> >(); FunctionToContractMap = new Dictionary <FunctionDefinition, ContractDefinition>(); FuncSigResolutionMap = new Dictionary <string, Dictionary <ContractDefinition, FunctionDefinition> >(); ContractToVisibleFunctionsMap = new Dictionary <ContractDefinition, HashSet <FunctionDefinition> >(); StateVarNameResolutionMap = new Dictionary <string, Dictionary <ContractDefinition, VariableDeclaration> >(); ContractToVisibleStateVarsMap = new Dictionary <ContractDefinition, HashSet <VariableDeclaration> >(); ModifierToBoogiePreProc = new Dictionary <string, BoogieProcedure>(); ModifierToBoogiePostProc = new Dictionary <string, BoogieProcedure>(); ModifierToBoogiePreImpl = new Dictionary <string, BoogieImplementation>(); ModifierToBoogiePostImpl = new Dictionary <string, BoogieImplementation>(); IgnoreMethods = ignoreMethods; genInlineAttrInBpl = _genInlineAttrInBpl; TranslateFlags = _translateFlags; }
// set of method@contract pairs whose translatin is skipped public BoogieAST Translate(AST solidityAST, HashSet <Tuple <string, string> > ignoredMethods, TranslatorFlags _translatorFlags = null) { bool generateInlineAttributesInBpl = _translatorFlags.GenerateInlineAttributes; SourceUnitList sourceUnits = solidityAST.GetSourceUnits(); TranslatorContext context = new TranslatorContext(ignoredMethods, generateInlineAttributesInBpl, _translatorFlags); context.IdToNodeMap = solidityAST.GetIdToNodeMap(); context.SourceDirectory = solidityAST.SourceDirectory; // collect the absolute source path and line number for each AST node SourceInfoCollector sourceInfoCollector = new SourceInfoCollector(context); sourceUnits.Accept(sourceInfoCollector); // de-sugar the solidity AST // will modify the AST SolidityDesugaring desugaring = new SolidityDesugaring(context); sourceUnits.Accept(desugaring); // collect all contract definitions ContractCollector contractCollector = new ContractCollector(context); sourceUnits.Accept(contractCollector); // collect all sub types for each contract InheritanceCollector inheritanceCollector = new InheritanceCollector(context); inheritanceCollector.Collect(); // collect explicit state variables StateVariableCollector stateVariableCollector = new StateVariableCollector(context); sourceUnits.Accept(stateVariableCollector); // resolve state variable declarations and determine the visible ones for each contract StateVariableResolver stateVariableResolver = new StateVariableResolver(context); stateVariableResolver.Resolve(); // collect mappings and arrays MapArrayCollector mapArrayCollector = new MapArrayCollector(context); sourceUnits.Accept(mapArrayCollector); // collect constructor definitions ConstructorCollector constructorCollector = new ConstructorCollector(context); sourceUnits.Accept(constructorCollector); // collect explicit function and event definitions FunctionEventCollector functionEventCollector = new FunctionEventCollector(context); sourceUnits.Accept(functionEventCollector); // resolve function and event definitions and determine the actual definition for a dynamic type FunctionEventResolver functionEventResolver = new FunctionEventResolver(context); functionEventResolver.Resolve(); // add types, gobal ghost variables, and axioms GhostVarAndAxiomGenerator generator = new GhostVarAndAxiomGenerator(context); generator.Generate(); // collect modifiers information ModifierCollector modifierCollector = new ModifierCollector(context); sourceUnits.Accept(modifierCollector); // translate procedures ProcedureTranslator procTranslator = new ProcedureTranslator(context, generateInlineAttributesInBpl); sourceUnits.Accept(procTranslator); // generate fallbacks FallbackGenerator fallbackGenerator = new FallbackGenerator(context); fallbackGenerator.Generate(); // generate harness for each contract if (!context.TranslateFlags.NoHarness) { HarnessGenerator harnessGenerator = new HarnessGenerator(context, procTranslator.ContractInvariants); harnessGenerator.Generate(); } if (context.TranslateFlags.ModelReverts) { RevertLogicGenerator reverGenerator = new RevertLogicGenerator(context); reverGenerator.Generate(); } return(new BoogieAST(context.Program)); }
// TODO: extract into a VerificationFlags structure public static void ParseCommandLineArgs(string[] args, out string solidityFile, out string entryPointContractName, out bool tryProofFlag, out bool tryRefutation, out int recursionBound, out ILogger logger, out HashSet <Tuple <string, string> > ignoredMethods, out bool printTransactionSeq, ref TranslatorFlags translatorFlags) { //Console.WriteLine($"Command line args = {{{string.Join(", ", args.ToList())}}}"); solidityFile = args[0]; // Debug.Assert(!solidityFile.Contains("/"), $"Illegal solidity file name {solidityFile}"); //the file name can be foo/bar/baz.sol entryPointContractName = args[1]; Debug.Assert(!entryPointContractName.Contains("/"), $"Illegal contract name {entryPointContractName}"); tryProofFlag = !(args.Any(x => x.Equals("/noPrf")) || args.Any(x => x.Equals("/noChk"))); //args.Any(x => x.Equals("/tryProof")); tryRefutation = !args.Any(x => x.Equals("/noChk")); recursionBound = 4; var txBounds = args.Where(x => x.StartsWith("/txBound:")); if (txBounds.Count() > 0) { Debug.Assert(txBounds.Count() == 1, $"At most 1 /txBound:k expected, found {txBounds.Count()}"); recursionBound = int.Parse(txBounds.First().Substring("/txBound:".Length)); Debug.Assert(recursionBound > 0, $"Argument of /txBound:k should be positive, found {recursionBound}"); } ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); // new LoggerFactory().AddConsole(LogLevel.Information); logger = loggerFactory.CreateLogger("VeriSol"); ignoredMethods = new HashSet <Tuple <string, string> >(); foreach (var arg in args.Where(x => x.StartsWith("/ignoreMethod:"))) { Debug.Assert(arg.Contains("@"), $"Error: incorrect use of /ignoreMethod in {arg}"); Debug.Assert(arg.LastIndexOf("@") == arg.IndexOf("@"), $"Error: incorrect use of /ignoreMethod in {arg}"); var str = arg.Substring("/ignoreMethod:".Length); var method = str.Substring(0, str.IndexOf("@")); var contract = str.Substring(str.IndexOf("@") + 1); ignoredMethods.Add(Tuple.Create(method, contract)); } if (args.Any(x => x.StartsWith("/ignoreMethod:"))) { Console.WriteLine($"Ignored method/contract pairs ==> \n\t {string.Join(",", ignoredMethods.Select(x => x.Item1 + "@" + x.Item2))}"); } translatorFlags.GenerateInlineAttributes = true; if (args.Any(x => x.Equals("/noInlineAttrs"))) { translatorFlags.GenerateInlineAttributes = false; if (tryProofFlag) { throw new Exception("/noInlineAttrs cannot be used when /tryProof is used"); } } if (args.Any(x => x.Equals("/break"))) { Debugger.Launch(); } if (args.Any(x => x.Equals("/omitSourceLineInfo"))) { translatorFlags.NoSourceLineInfoFlag = true; } if (args.Any(x => x.Equals("/omitDataValuesInTrace"))) { translatorFlags.NoDataValuesInfoFlag = true; } if (args.Any(x => x.Equals("/useModularArithmetic"))) { translatorFlags.UseModularArithmetic = true; } if (args.Any(x => x.Equals("/omitUnsignedSemantics"))) { translatorFlags.NoUnsignedAssumesFlag = true; } if (args.Any(x => x.Equals("/omitAxioms"))) { translatorFlags.NoAxiomsFlag = true; } if (args.Any(x => x.Equals("/omitHarness"))) { translatorFlags.NoHarness = true; } if (args.Any(x => x.Equals("/omitBoogieHarness"))) { translatorFlags.NoBoogieHarness = true; } if (args.Any(x => x.Equals("/createMainHarness"))) { translatorFlags.CreateMainHarness = true; } if (args.Any(x => x.Equals("/noCustomTypes"))) { translatorFlags.NoCustomTypes = true; } if (args.Any(x => x.Equals("/modelReverts"))) { translatorFlags.ModelReverts = true; } if (args.Any(x => x.Equals("/instrumentGas"))) { translatorFlags.InstrumentGas = true; } var stubModels = args.Where(x => x.StartsWith("/stubModel:")); if (stubModels.Count() > 0) { Debug.Assert(stubModels.Count() == 1, "Multiple instances of /stubModel:"); var model = stubModels.First().Substring("/stubModel:".Length); Debug.Assert(model.Equals("skip") || model.Equals("havoc") || model.Equals("callback"), $"The argument to /stubModel: can be either {{skip, havoc, callback}}, found {model}"); translatorFlags.ModelOfStubs = model; } if (args.Any(x => x.StartsWith("/inlineDepth:"))) { var depth = args.Where(x => x.StartsWith("/inlineDepth:")).First(); translatorFlags.InlineDepthForBoogie = int.Parse(depth.Substring("/inlineDepth:".Length)); } if (args.Any(x => x.Equals("/doModSet"))) { translatorFlags.DoModSetAnalysis = true; } if (args.Any(x => x.Equals("/removeScopeInVarName"))) { // do not document this option, only needed for equivalence checking in Symdiff translatorFlags.RemoveScopeInVarName = true; } if (args.Any(x => x.Equals("/LazyNestedAlloc"))) { translatorFlags.LazyNestedAlloc = true; } if (args.Any(x => x.Equals("/OmitAssumeFalseForDynDispatch"))) { translatorFlags.OmitAssumeFalseForDynDispatch = true; } if (args.Any(x => x.Equals("/QuantFreeAllocs"))) { translatorFlags.QuantFreeAllocs = true; // Turn LazyNestedAlloc on by default if QuantFreeAllocs is provided. if (!translatorFlags.LazyNestedAlloc) { translatorFlags.LazyNestedAlloc = true; } } if (args.Any(x => x.Equals("/instrumentSums"))) { translatorFlags.InstrumentSums = true; } translatorFlags.PerformContractInferce = args.Any(x => x.StartsWith("/contractInfer")); // don't perform verification for some of these omitFlags if (tryProofFlag || tryRefutation) { Debug.Assert(!translatorFlags.NoHarness && !translatorFlags.NoAxiomsFlag && !translatorFlags.NoUnsignedAssumesFlag && !translatorFlags.NoDataValuesInfoFlag && !translatorFlags.NoSourceLineInfoFlag && !translatorFlags.RemoveScopeInVarName, "Cannot perform verification when any of " + "/omitSourceLineInfo, " + "/omitDataValuesInTrace, " + "/omitAxioms, " + "/omitHarness, " + "/omitUnsignedSemantics, " + "/removeScopeInVarName are specified"); } printTransactionSeq = !args.Any(x => x.Equals("/noTxSeq")); }
public static void Main(string[] args) { if (args.Length < 3) { Console.WriteLine("Usage: SolToBoogie <relative path to filename.sol> <workingdir> <relative path to outfile.bpl> [options]"); Console.WriteLine("\t Options:"); Console.WriteLine("\t\t /break: Opens the debugger"); Console.WriteLine("\t\t /ignoreMethod:<method>@<contract>: Ignores translation of the method within contract, and only generates a declaration"); Console.WriteLine("\t\t\t\t multiple such pairs can be specified, ignored set is the union"); Console.WriteLine("\t\t\t\t a wild card '*' can be used for method, would mean all the methods of the contract"); Console.WriteLine("\t\t /noInlineAttrs: do not generate any {:inline x} attributes, to speed Corral"); return; } string filePath = Path.Combine(Directory.GetCurrentDirectory(), args[0]); string workingDirectory = args[1]; string outFile = Path.Combine(Directory.GetCurrentDirectory(), args[2]); string solcName = GetSolcNameByOSPlatform(); string solcPath = Path.Combine(workingDirectory, "Binaries", solcName); SolidityCompiler compiler = new SolidityCompiler(); CompilerOutput compilerOutput = compiler.Compile(solcPath, filePath); HashSet <Tuple <string, string> > ignoredMethods = new HashSet <Tuple <string, string> >(); // Issue with run_verisol_win.cmd it passes "/ignoreMethod:a@b /ignoreMethod:c@d .." as a single string var splitArgs = new List <string>(); args.Select(arg => arg.Split(" ")) .ToList() .ForEach(a => a.ToList().ForEach(b => splitArgs.Add(b))); if (splitArgs.Any(x => x.Equals("/break"))) { Debugger.Launch(); } foreach (var arg in splitArgs.Where(x => x.StartsWith("/ignoreMethod:"))) { Debug.Assert(arg.Contains("@"), $"Error: incorrect use of /ignoreMethod in {arg}"); Debug.Assert(arg.LastIndexOf("@") == arg.IndexOf("@"), $"Error: incorrect use of /ignoreMethod in {arg}"); var str = arg.Substring("/ignoreMethod:".Length); var method = str.Substring(0, str.IndexOf("@")); var contract = str.Substring(str.IndexOf("@") + 1); ignoredMethods.Add(Tuple.Create(method, contract)); } Console.WriteLine($"Ignored method/contract pairs ==> \n\t {string.Join(",", ignoredMethods.Select(x => x.Item1 + "@" + x.Item2))}"); bool genInlineAttributesInBpl = true; if (splitArgs.Any(x => x.Equals("/noInlineAttrs"))) { genInlineAttributesInBpl = false; } if (compilerOutput.ContainsError()) { PrintErrors(compilerOutput.Errors); throw new SystemException("Compilation Error"); } else { AST solidityAST = new AST(compilerOutput, Path.GetDirectoryName(filePath)); try { BoogieTranslator translator = new BoogieTranslator(); var translatorFlags = new TranslatorFlags(); translatorFlags.GenerateInlineAttributes = genInlineAttributesInBpl; BoogieAST boogieAST = translator.Translate(solidityAST, ignoredMethods, translatorFlags); using (var outWriter = new StreamWriter(outFile)) { outWriter.WriteLine(boogieAST.GetRoot()); } } catch (Exception e) { Console.WriteLine($"Verisol translation exception: {e.Message}"); } } }