Beispiel #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);
        }
Beispiel #2
0
        /// <summary>
        /// calling graph is prepared for update contract code (check for DAG at that time)
        /// </summary>
        /// <param name="edges"></param>
        /// <returns></returns>
        /// <exception cref="FunctionMetadataException"></exception>
        private CallGraph BuildCallingGraph(SerializedCallGraph callGraph)
        {
            CallGraph graph = new CallGraph();

            graph.AddVertexRange(callGraph.Vertices);
            graph.AddEdgeRange(callGraph.Edges.Select(serializedEdge =>
                                                      new Edge <string>(serializedEdge.Source, serializedEdge.Target)));
            try
            {
                graph.TopologicalSort();
            }
            catch (NonAcyclicGraphException)
            {
                throw new FunctionMetadataException("The calling graph ISNOT DAG when restoring the calling graph according to the ContractMetadataTemplateMap from the database");
            }
            return(graph);
        }