예제 #1
0
        /// <summary>
        /// Try to update the calling graph when updating the function.
        /// If some functions have unknow reference of foreign edge(call other contract's function), the update will not be approved and nothing will take effect
        /// </summary>
        /// <param name=""></param>
        /// <param name="contractAddress"></param>
        /// <param name="callingGraph"></param>
        /// <param name="contractMetadataTemplate"></param>
        /// <returns>The new calling graph</returns>
        /// <exception cref="FunctionMetadataException"></exception>
        public CallGraph TryUpdateAndGetCallingGraph(Address contractAddress, CallGraph callingGraph,
                                                     ContractMetadataTemplate contractMetadataTemplate)
        {
            List <Edge <string> > outEdgesToAdd = new List <Edge <string> >();

            //check for unknown reference
            foreach (var kvPair in contractMetadataTemplate.MethodMetadataTemplates)
            {
                var sourceFunc =
                    Replacement.ReplaceValueIntoReplacement(kvPair.Key, Replacement.This,
                                                            contractAddress.GetFormatted());

                foreach (var calledFunc in kvPair.Value.CallingSet)
                {
                    if (!calledFunc.Contains(Replacement.This))
                    {
                        Replacement.TryGetReplacementWithIndex(calledFunc, 0, out var memberReplacement);
                        var referenceAddress =
                            contractMetadataTemplate.ContractReferences[
                                Replacement.Value(
                                    memberReplacement)]; //FunctionMetadataTemplate itself ensure this value exist
                        var globalCalledFunc = Replacement.ReplaceValueIntoReplacement(calledFunc, memberReplacement,
                                                                                       referenceAddress.GetFormatted());
                        if (!callingGraph.ContainsVertex(globalCalledFunc))
                        {
                            throw new FunctionMetadataException(
                                      "Unknow reference of the foreign target in edge <" + sourceFunc + "," + calledFunc +
                                      "> when trying to add contract " + contractMetadataTemplate.FullName +
                                      " into calling graph, consider the target function does not exist in the metadata");
                        }

                        outEdgesToAdd.Add(new Edge <string>(sourceFunc, globalCalledFunc));
                    }
                }
            }

            //Merge local calling graph, mind that there are functions that call nothing, they also need to appear in the call graph (to be called in future)
            foreach (var localVertex in contractMetadataTemplate.LocalCallingGraph.Vertices)
            {
                var globalVertex =
                    Replacement.ReplaceValueIntoReplacement(localVertex, Replacement.This,
                                                            contractAddress.GetFormatted());
                callingGraph.AddVertex(globalVertex);
                foreach (var outEdge in contractMetadataTemplate.LocalCallingGraph.OutEdges(localVertex))
                {
                    var toVertex = Replacement.ReplaceValueIntoReplacement(outEdge.Target, Replacement.This,
                                                                           contractAddress.GetFormatted());
                    callingGraph.AddVerticesAndEdge(new Edge <string>(globalVertex, toVertex));
                }
            }

            //add foreign edges
            callingGraph.AddEdgeRange(outEdgesToAdd);

            return(callingGraph);
        }
예제 #2
0
        /// <summary>
        /// try to get
        /// (1) local calling graph, where only local function calls are considered
        /// (2) process function order ( reverse order of topological order of the calling graph)
        /// (3) external function call list for every function
        /// </summary>
        /// <param name="callGraph"></param>
        /// <param name="topologicRes"></param>
        private void TrySetLocalCallingGraph(out CallGraph callGraph, out IEnumerable <string> topologicRes)
        {
            callGraph = new CallGraph();
            foreach (var kvPair in MethodMetadataTemplates)
            {
                callGraph.AddVertex(kvPair.Key);
                foreach (var calledFunc in kvPair.Value.CallingSet)
                {
                    if (calledFunc.StartsWith(Replacement.This))
                    {
                        callGraph.AddVerticesAndEdge(new Edge <string>(kvPair.Key, calledFunc));
                    }
                    else
                    {
                        if (!ExternalFuncCall.TryGetValue(kvPair.Key, out var callingList))
                        {
                            callingList = new List <string>();
                            ExternalFuncCall.Add(kvPair.Key, callingList);
                        }
                        callingList.Add(calledFunc);
                    }
                }
            }

            try
            {
                topologicRes = callGraph.TopologicalSort();
            }
            catch (NonAcyclicGraphException)
            {
                callGraph.Clear();
                callGraph    = null;
                topologicRes = null;
                throw new FunctionMetadataException($"Calling graph of contract {FullName} is Non-DAG thus nothing take effect");
            }
        }