Example #1
0
 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>();
 }
Example #2
0
 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;
 }
Example #3
0
        // 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));
        }
Example #4
0
        // 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"));
        }
Example #5
0
        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}");
                }
            }
        }