Example #1
0
        public async Task <IActionResult> CallMethod([FromRoute] string address, [FromRoute] string method, [FromBody] JObject requestData)
        {
            var contractCode = this.stateRoot.GetCode(address.ToUint160(this.network));

            Result <IContractAssembly> loadResult = this.loader.Load((ContractByteCode)contractCode);

            IContractAssembly assembly = loadResult.Value;

            Type type = assembly.DeployedType;

            MethodInfo methodInfo = type.GetMethod(method);

            if (methodInfo == null)
            {
                throw new Exception("Method does not exist on contract.");
            }

            ParameterInfo[] parameters = methodInfo.GetParameters();

            if (!this.ValidateParams(requestData, parameters))
            {
                throw new Exception("Parameters don't match method signature.");
            }

            // Map the JObject to the parameter + types expected by the call.
            string[] methodParams = parameters.Map(requestData);

            BuildCallContractTransactionRequest request = this.MapCallRequest(address, method, methodParams, this.Request.Headers);

            // Proxy to the actual SC controller.
            return(this.smartContractWalletController.Call(request));
        }
Example #2
0
        /// <summary>
        /// Loads the contract bytecode and returns an <see cref="IContract"/> representing an uninitialized contract instance.
        /// </summary>
        private Result <IContract> Load(
            ContractByteCode byteCode,
            string typeName,
            uint160 address,
            ISmartContractState contractState)
        {
            Result <IContractAssembly> assemblyLoadResult = this.assemblyLoader.Load(byteCode);

            if (!assemblyLoadResult.IsSuccess)
            {
                return(Result.Fail <IContract>(assemblyLoadResult.Error));
            }

            IContractAssembly contractAssembly = assemblyLoadResult.Value;

            Type type = contractAssembly.GetType(typeName);

            if (type == null)
            {
                return(Result.Fail <IContract>("Type not found!"));
            }

            IContract contract = Contract.CreateUninitialized(type, contractState, address);

            return(Result.Ok(contract));
        }
        public Task <IActionResult> ContractSwaggerDoc(string address)
        {
            var code = this.stateRepository.GetCode(address.ToUint160(this.network));

            if (code == null)
            {
                throw new Exception("Contract does not exist");
            }

            Result <IContractAssembly> assemblyLoadResult = this.loader.Load((ContractByteCode)code);

            if (assemblyLoadResult.IsFailure)
            {
                throw new Exception("Error loading assembly");
            }

            IContractAssembly assembly = assemblyLoadResult.Value;

            // Default wallet is the first wallet as ordered by name.
            string defaultWalletName = this.walletmanager.GetWalletsNames().OrderBy(n => n).First();

            // Default address is the first address with a balance, or string.Empty if no addresses have been created.
            // Ordering this way is consistent with the wallet UI, ie. whatever appears first in the wallet will appear first here.
            string defaultAddress = this.walletmanager.GetAccountAddressesWithBalance(defaultWalletName).FirstOrDefault()?.Address ?? string.Empty;

            var swaggerGen = new ContractSwaggerDocGenerator(this.options, address, assembly, defaultWalletName, defaultAddress);

            OpenApiDocument doc = swaggerGen.GetSwagger("contracts");

            // TODO confirm v2/v3
            var outputString = doc.Serialize(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Json);

            return(Task.FromResult <IActionResult>(Ok(outputString)));
        }
Example #4
0
 public ContractSwaggerDocGenerator(SwaggerGeneratorOptions options, string address, IContractAssembly assembly, string defaultWalletName = "", string defaultSenderAddress = "")
 {
     this.options              = options;
     this.address              = address;
     this.assembly             = assembly;
     this.defaultWalletName    = defaultWalletName;
     this.defaultSenderAddress = defaultSenderAddress;
 }
Example #5
0
        public static IEnumerable <PropertyInfo> GetPublicGetterProperties(this IContractAssembly contractAssembly)
        {
            Type deployedType = contractAssembly.DeployedType;

            if (deployedType == null)
            {
                return(new List <PropertyInfo>());
            }

            return(deployedType
                   .GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)
                   .Where(p => p.GetGetMethod() != null));
        }
Example #6
0
        /// <summary>
        /// Gets the public methods defined by the contract, ignoring property getters/setters.
        /// </summary>
        /// <returns></returns>
        public static IEnumerable <MethodInfo> GetPublicMethods(this IContractAssembly contractAssembly)
        {
            Type deployedType = contractAssembly.DeployedType;

            if (deployedType == null)
            {
                return(new List <MethodInfo>());
            }

            return(deployedType
                   .GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance) // Get only the methods declared on the contract type
                   .Where(m => !m.IsSpecialName));                                                      // Ignore property setters/getters
        }
Example #7
0
        public void ContractAssemblyLoaderIsForwardCompatibleWithSmartContractAndStandardsUpdates()
        {
            // Create the byte code of a contract that contains new data types that are not (normally) supported by the current node.
            ContractCompilationResult result = ContractCompiler.Compile(this.testContract);

            byte[] bytes = result.Compilation;

            // Test that the node is able to load the futuristic contract.
            ContractAssemblyLoader loader = new ContractAssemblyLoader();

            CSharpFunctionalExtensions.Result <IContractAssembly> result2 = loader.Load(new ContractByteCode(bytes));
            IContractAssembly assembly = result2.Value;

            Assert.Equal("FruitVendor", assembly.Assembly.GetTypes().First().Name);
        }
        /// <summary>
        /// Loads the contract bytecode and returns an <see cref="IContract"/> representing an uninitialized contract instance.
        /// </summary>
        private Result <IContract> Load(
            ContractByteCode byteCode,
            string typeName,
            uint160 address,
            ISmartContractState contractState)
        {
            Result <IContractAssembly> assemblyLoadResult = this.assemblyLoader.Load(byteCode);

            if (!assemblyLoadResult.IsSuccess)
            {
                this.logger.LogTrace(assemblyLoadResult.Error);

                return(Result.Fail <IContract>(assemblyLoadResult.Error));
            }

            IContractAssembly contractAssembly = assemblyLoadResult.Value;

            Type type = contractAssembly.GetType(typeName);

            if (type == null)
            {
                const string typeNotFoundError = "Type not found!";

                this.logger.LogTrace(typeNotFoundError);

                return(Result.Fail <IContract>(typeNotFoundError));
            }

            IContract contract;

            try
            {
                contract = Contract.CreateUninitialized(type, contractState, address);
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());

                return(Result.Fail <IContract>("Exception occurred while instantiating contract instance"));
            }

            return(Result.Ok(contract));
        }
 /// <summary>
 /// Maps a contract assembly to its schemas.
 /// </summary>
 /// <param name="assembly"></param>
 /// <returns></returns>
 public IDictionary <string, OpenApiSchema> Map(IContractAssembly assembly)
 {
     return(this.Map(assembly.GetPublicMethods()));
 }
        public void Separate_Threads_Have_Different_Observer_Instances()
        {
            // Create a contract assembly.
            ContractCompilationResult compilationResult = ContractCompiler.Compile(TestSource);

            Assert.True(compilationResult.Success);

            byte[] originalAssemblyBytes = compilationResult.Compilation;

            IContractModuleDefinition module = this.moduleReader.Read(originalAssemblyBytes).Value;

            module.Rewrite(this.rewriter);

            CSharpFunctionalExtensions.Result <IContractAssembly> assemblyLoadResult = this.assemblyLoader.Load(module.ToByteCode());

            IContractAssembly assembly = assemblyLoadResult.Value;

            var threadCount = 10;

            var observers = new Observer[threadCount];

            var countdown = new CountdownEvent(threadCount);

            var threads = new Thread[threadCount];

            for (var i = 0; i < threadCount; i++)
            {
                // Create a fake observer with a counter.
                var observer = new Observer(new GasMeter((Gas)1000000), new MemoryMeter(1000000));

                observers[i] = observer;

                // Set a different observer on each thread.
                // Invoke the same method on each thread.
                Thread newThread = new Thread(() =>
                {
                    assembly.SetObserver(observer);

                    Assert.Same(observer, assembly.GetObserver());
                    var callData       = new MethodCall("TestMethod", new object[] { 1 });
                    IContract contract = Contract.CreateUninitialized(assembly.GetType(module.ContractType.Name), this.state, null);

                    IContractInvocationResult result = contract.Invoke(callData);

                    countdown.Signal();
                });

                newThread.Name = i.ToString();
                threads[i]     = newThread;
            }

            // Start the threads on a separate loop to ensure all time is spent on processing.
            foreach (Thread thread in threads)
            {
                thread.Start();
            }

            countdown.Wait();

            foreach (Observer observer in observers)
            {
                Assert.Equal(observers[0].GasMeter.GasConsumed, observer.GasMeter.GasConsumed);
                Assert.Equal(observers[0].MemoryMeter.MemoryConsumed, observer.MemoryMeter.MemoryConsumed);
            }
        }
Example #11
0
 public CachedAssemblyPackage(IContractAssembly assembly)
 {
     this.Assembly = assembly;
 }