Ejemplo n.º 1
0
        /// <summary>
        /// //TODO: in fact, only public interface of contact need to be added into FunctionMetadataMap
        /// </summary>
        /// <param name="chainId"></param>
        /// <param name="contractAddr"></param>
        /// <param name="contractMetadataTemplate"></param>
        /// <exception cref="FunctionMetadataException"></exception>
        public async Task DeployNewContract(Hash chainId, Address contractAddr, ContractMetadataTemplate contractMetadataTemplate)
        {
            Dictionary <string, FunctionMetadata> tempMap = new Dictionary <string, FunctionMetadata>();

            try
            {
                var globalCallGraph = await GetCallingGraphForChain(chainId);

                var newCallGraph = TryUpdateAndGetCallingGraph(chainId, contractAddr, globalCallGraph, contractMetadataTemplate);

                foreach (var localFuncName in contractMetadataTemplate.ProcessFunctionOrder)
                {
                    var funcNameWithAddr =
                        Replacement.ReplaceValueIntoReplacement(localFuncName, Replacement.This,
                                                                contractAddr.DumpHex());
                    var funcMetadata = await GetMetadataForNewFunction(chainId, funcNameWithAddr,
                                                                       contractMetadataTemplate.MethodMetadataTemplates[localFuncName],
                                                                       contractAddr, contractMetadataTemplate.ContractReferences, tempMap);

                    tempMap.Add(funcNameWithAddr, funcMetadata);
                }

                //if no exception is thrown, merge the tempMap into FunctionMetadataMap and update call graph in database
                await _dataStore.InsertAsync(chainId.OfType(HashType.CallingGraph),
                                             SerializeCallingGraph(newCallGraph));

                foreach (var functionMetadata in tempMap)
                {
                    FunctionMetadataMap.Add(functionMetadata.Key, functionMetadata.Value);

                    await _dataStore.InsertAsync(
                        DataPath.CalculatePointerForMetadata(chainId, functionMetadata.Key),
                        functionMetadata.Value);
                }
            }
            catch (FunctionMetadataException e)
            {
                _logger?.Error(e, "Exception while deploy new contract.");
                throw;
            }
        }
Ejemplo n.º 2
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="chainId"></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(Hash chainId, 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.DumpHex());

                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.DumpHex());
                        if (!callingGraph.ContainsVertex(globalCalledFunc))
                        {
                            throw new FunctionMetadataException("ChainId [" + chainId.DumpHex() + "] 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.DumpHex());
                callingGraph.AddVertex(globalVertex);
                foreach (var outEdge in contractMetadataTemplate.LocalCallingGraph.OutEdges(localVertex))
                {
                    var toVertex = Replacement.ReplaceValueIntoReplacement(outEdge.Target, Replacement.This, contractAddress.DumpHex());
                    callingGraph.AddVerticesAndEdge(new Edge <string>(globalVertex, toVertex));
                }
            }
            //add foreign edges
            callingGraph.AddEdgeRange(outEdgesToAdd);

            return(callingGraph);
        }