public void Validate_Determinism_AnonymousClassFloats() { string adjustedSource = TestString.Replace(ReplaceCodeString, @"var test = new { Prop1 = 6.8 };").Replace(ReplaceReferencesString, ""); byte[] assemblyBytes = ContractCompiler.Compile(adjustedSource).Compilation; IContractModuleDefinition moduleDefinition = ContractDecompiler.GetModuleDefinition(assemblyBytes).Value; SmartContractValidationResult result = this.validator.Validate(moduleDefinition.ModuleDefinition); Assert.False(result.IsValid); }
public void Validate_Determinism_DynamicTypeAllowed() { string adjustedSource = TestString.Replace(ReplaceCodeString, "dynamic test = 56; test = \"aString\"; ").Replace(ReplaceReferencesString, ""); ContractCompilationResult compilationResult = ContractCompiler.Compile(adjustedSource); Assert.True(compilationResult.Success); byte[] assemblyBytes = compilationResult.Compilation; IContractModuleDefinition moduleDefinition = ContractDecompiler.GetModuleDefinition(assemblyBytes).Value; SmartContractValidationResult result = this.validator.Validate(moduleDefinition.ModuleDefinition); Assert.True(result.IsValid); }
public void ValidateAnonymousClassesDisallowed() { string adjustedSource = TestString.Replace(ReplaceCodeString, @"var test = new { Test = ""Stratis"" };").Replace(ReplaceReferencesString, ""); byte[] assemblyBytes = SmartContractCompiler.Compile(adjustedSource).Compilation; IContractModuleDefinition moduleDefinition = SmartContractDecompiler.GetModuleDefinition(assemblyBytes); SmartContractValidationResult result = this.validator.Validate(moduleDefinition.ModuleDefinition); Assert.False(result.IsValid); }
public void Validate_Determinism_GetHashCode() { string adjustedSource = TestString.Replace(ReplaceCodeString, "int hashCode = GetHashCode();").Replace(ReplaceReferencesString, ""); ContractCompilationResult compilationResult = ContractCompiler.Compile(adjustedSource); Assert.True(compilationResult.Success); byte[] assemblyBytes = compilationResult.Compilation; IContractModuleDefinition moduleDefinition = ContractDecompiler.GetModuleDefinition(assemblyBytes).Value; SmartContractValidationResult result = this.validator.Validate(moduleDefinition.ModuleDefinition); Assert.False(result.IsValid); }
public void Validate_Determinism_KnownBadMethodCall() { string adjustedSource = TestString.Replace(ReplaceCodeString, @"var floor = System.Math.Floor(12D);").Replace(ReplaceReferencesString, ""); ContractCompilationResult compilationResult = ContractCompiler.Compile(adjustedSource); Assert.True(compilationResult.Success); byte[] assemblyBytes = compilationResult.Compilation; IContractModuleDefinition moduleDefinition = ContractDecompiler.GetModuleDefinition(assemblyBytes).Value; SmartContractValidationResult result = this.validator.Validate(moduleDefinition.ModuleDefinition); Assert.False(result.IsValid); }
public void Validate_Determinism_Nullable_Fails() { string adjustedSource = TestString.Replace(ReplaceCodeString, "int? test = null;").Replace(ReplaceReferencesString, ""); ContractCompilationResult compilationResult = ContractCompiler.Compile(adjustedSource, OptimizationLevel.Debug); Assert.True(compilationResult.Success); byte[] assemblyBytes = compilationResult.Compilation; IContractModuleDefinition moduleDefinition = ContractDecompiler.GetModuleDefinition(assemblyBytes).Value; SmartContractValidationResult result = this.validator.Validate(moduleDefinition.ModuleDefinition); Assert.False(result.IsValid); }
public void Validate_Determinism_Fails_Array_Clone() { string code = @" var test = new int[25]; var ret = test.Clone();"; string adjustedSource = TestString.Replace(ReplaceCodeString, code).Replace(ReplaceReferencesString, ""); byte[] assemblyBytes = ContractCompiler.Compile(adjustedSource).Compilation; IContractModuleDefinition moduleDefinition = ContractDecompiler.GetModuleDefinition(assemblyBytes).Value; SmartContractValidationResult result = this.validator.Validate(moduleDefinition.ModuleDefinition); Assert.False(result.IsValid); }
/// <summary> /// Invokes a method on an existing smart contract /// </summary> public VmExecutionResult ExecuteMethod(ISmartContractState contractState, MethodCall methodCall, byte[] contractCode, string typeName) { this.logger.LogTrace("(){0}:{1}", nameof(methodCall.Name), methodCall.Name); ContractByteCode code; using (IContractModuleDefinition moduleDefinition = this.moduleDefinitionReader.Read(contractCode)) { moduleDefinition.InjectMethodGas(typeName, methodCall); code = moduleDefinition.ToByteCode(); } Result <IContract> contractLoadResult = this.Load( code, typeName, contractState.Message.ContractAddress.ToUint160(this.network), contractState); if (!contractLoadResult.IsSuccess) { // TODO this is temporary until we improve error handling overloads var exception = new Exception(contractLoadResult.Error); LogException(exception); this.logger.LogTrace("(-)[LOAD_CONTRACT_FAILED]"); return(VmExecutionResult.Error(exception)); } IContract contract = contractLoadResult.Value; LogExecutionContext(this.logger, contract.State.Block, contract.State.Message, contract.Address); IContractInvocationResult invocationResult = contract.Invoke(methodCall); if (!invocationResult.IsSuccess) { this.logger.LogTrace("(-)[CALLCONTRACT_INSTANTIATION_FAILED]"); return(VmExecutionResult.Error(new Exception("Method invocation failed!"))); } this.logger.LogTrace("[CALL_CONTRACT_INSTANTIATION_SUCCEEDED]"); this.logger.LogTrace("(-)"); return(VmExecutionResult.Success(invocationResult.Return, typeName)); }
/// <summary> /// Invokes a method on an existing smart contract /// </summary> public VmExecutionResult ExecuteMethod(ISmartContractState contractState, MethodCall methodCall, byte[] contractCode, string typeName) { this.logger.LogTrace("(){0}:{1}", nameof(methodCall.Name), methodCall.Name); ContractByteCode code; // Code we're loading from database - can assume it's valid. using (IContractModuleDefinition moduleDefinition = this.moduleDefinitionReader.Read(contractCode).Value) { var observer = new Observer(contractState.GasMeter, MemoryUnitLimit); var rewriter = new ObserverRewriter(observer); moduleDefinition.Rewrite(rewriter); code = moduleDefinition.ToByteCode(); } Result <IContract> contractLoadResult = this.Load( code, typeName, contractState.Message.ContractAddress.ToUint160(this.network), contractState); if (!contractLoadResult.IsSuccess) { LogErrorMessage(contractLoadResult.Error); this.logger.LogTrace("(-)[LOAD_CONTRACT_FAILED]"); return(VmExecutionResult.Fail(VmExecutionErrorKind.LoadFailed, contractLoadResult.Error)); } IContract contract = contractLoadResult.Value; LogExecutionContext(this.logger, contract.State.Block, contract.State.Message, contract.Address); IContractInvocationResult invocationResult = contract.Invoke(methodCall); if (!invocationResult.IsSuccess) { this.logger.LogTrace("(-)[CALLCONTRACT_INSTANTIATION_FAILED]"); return(GetInvocationVmErrorResult(invocationResult)); } this.logger.LogTrace("[CALL_CONTRACT_INSTANTIATION_SUCCEEDED]"); this.logger.LogTrace("(-)"); return(VmExecutionResult.Ok(invocationResult.Return, typeName)); }
public void Validate_Determinism_MethodParams_Private() { string adjustedSource = @"using System; using Stratis.SmartContracts; public class Test : SmartContract { public Test(ISmartContractState state) : base(state) {} private void PrivateStruct(TestStruct test) { } private void PrivateIntArray(int[] test) { } public void PublicIntArray(int[] test) { } public void PublicStruct(TestStruct test) { } internal void InternalStruct(TestStruct test) { } public struct TestStruct { public int TestInt; } }"; ContractCompilationResult compilationResult = ContractCompiler.Compile(adjustedSource, OptimizationLevel.Debug); Assert.True(compilationResult.Success); byte[] assemblyBytes = compilationResult.Compilation; IContractModuleDefinition moduleDefinition = ContractDecompiler.GetModuleDefinition(assemblyBytes).Value; SmartContractValidationResult result = this.validator.Validate(moduleDefinition.ModuleDefinition); Assert.False(result.IsValid); Assert.Equal(2, result.Errors.Count()); Assert.Contains("PublicIntArray", result.Errors.ElementAt(0).Message); Assert.Contains("PublicStruct", result.Errors.ElementAt(1).Message); }
public void Validate_Determinism_Floats() { string adjustedSource = TestString.Replace(ReplaceCodeString, "float test = (float) 3.5; test = test + 1;").Replace(ReplaceReferencesString, ""); ContractCompilationResult compilationResult = ContractCompiler.Compile(adjustedSource); Assert.True(compilationResult.Success); byte[] assemblyBytes = compilationResult.Compilation; IContractModuleDefinition moduleDefinition = ContractDecompiler.GetModuleDefinition(assemblyBytes).Value; SmartContractValidationResult result = this.validator.Validate(moduleDefinition.ModuleDefinition); Assert.False(result.IsValid); Assert.Contains(result.Errors, e => e is FloatValidator.FloatValidationResult); }
private bool Rewrite(IContractModuleDefinition moduleDefinition, IILRewriter rewriter) { try { moduleDefinition.Rewrite(rewriter); return(true); } catch (Exception e) { this.logger.LogError("Exception occurred: {0}", e.ToString()); this.logger.LogTrace("(-)[CONTRACT_REWRITE_FAILED]"); } return(false); }
public void Validate_Determinism_Globalisation() { string adjustedSource = TestString.Replace(ReplaceCodeString, "var r = System.Globalization.CultureInfo.CurrentCulture;") .Replace(ReplaceReferencesString, ""); SmartContractCompilationResult compilationResult = SmartContractCompiler.Compile(adjustedSource); Assert.True(compilationResult.Success); byte[] assemblyBytes = compilationResult.Compilation; IContractModuleDefinition moduleDefinition = SmartContractDecompiler.GetModuleDefinition(assemblyBytes); SmartContractValidationResult result = this.validator.Validate(moduleDefinition.ModuleDefinition); Assert.False(result.IsValid); }
public void Validate_Determinism_Decimal() { string adjustedSource = TestString.Replace(ReplaceCodeString, "decimal test = (decimal) 3.5; test = test / 2;").Replace(ReplaceReferencesString, ""); ContractCompilationResult compilationResult = ContractCompiler.Compile(adjustedSource); Assert.True(compilationResult.Success); byte[] assemblyBytes = compilationResult.Compilation; IContractModuleDefinition moduleDefinition = ContractDecompiler.GetModuleDefinition(assemblyBytes).Value; SmartContractValidationResult result = this.validator.Validate(moduleDefinition.ModuleDefinition); Assert.False(result.IsValid); Assert.True(result.Errors.All(e => e is WhitelistValidator.WhitelistValidationResult)); Assert.True(result.Errors.All(e => e.Message.Contains("Decimal"))); }
private Result <ContractByteCode> GetByteCode(IContractModuleDefinition moduleDefinition) { try { ContractByteCode code = moduleDefinition.ToByteCode(); return(Result.Ok(code)); } catch (Exception e) { this.logger.LogError("Exception occurred: {0}", e.ToString()); this.logger.LogTrace("(-)[CONTRACT_TOBYTECODE_FAILED]"); return(Result.Fail <ContractByteCode>("Exception occurred while serializing module")); } }
public void Validate_Determinism_TaskAwaiter() { string adjustedSource = TestString.Replace(ReplaceCodeString, "var r = new System.Runtime.CompilerServices.TaskAwaiter();") .Replace(ReplaceReferencesString, ""); ContractCompilationResult compilationResult = ContractCompiler.Compile(adjustedSource, OptimizationLevel.Debug); Assert.True(compilationResult.Success); byte[] assemblyBytes = compilationResult.Compilation; IContractModuleDefinition moduleDefinition = ContractDecompiler.GetModuleDefinition(assemblyBytes).Value; SmartContractValidationResult result = this.validator.Validate(moduleDefinition.ModuleDefinition); Assert.False(result.IsValid); }
public void Validate_Determinism_BitConverter() { string adjustedSource = TestString.Replace(ReplaceCodeString, @"var test = BitConverter.IsLittleEndian;").Replace(ReplaceReferencesString, ""); ContractCompilationResult compilationResult = ContractCompiler.Compile(adjustedSource); Assert.True(compilationResult.Success); byte[] assemblyBytes = compilationResult.Compilation; IContractModuleDefinition moduleDefinition = ContractDecompiler.GetModuleDefinition(assemblyBytes).Value; SmartContractValidationResult result = this.validator.Validate(moduleDefinition.ModuleDefinition); Assert.False(result.IsValid); Assert.Single(result.Errors); Assert.IsAssignableFrom <WhitelistValidator.WhitelistValidationResult>(result.Errors.Single()); }
public void Validate_Determinism_ActivatorNotAllowed() { string adjustedSource = TestString.Replace(ReplaceCodeString, @"Address ts = System.Activator.CreateInstance<Address>();").Replace(ReplaceReferencesString, ""); ContractCompilationResult compilationResult = ContractCompiler.Compile(adjustedSource); Assert.True(compilationResult.Success); byte[] assemblyBytes = compilationResult.Compilation; IContractModuleDefinition moduleDefinition = ContractDecompiler.GetModuleDefinition(assemblyBytes).Value; SmartContractValidationResult result = this.validator.Validate(moduleDefinition.ModuleDefinition); Assert.False(result.IsValid); Assert.Single(result.Errors); Assert.IsAssignableFrom <WhitelistValidator.WhitelistValidationResult>(result.Errors.Single()); }
private IContract GetContractAfterRewrite(string filename) { ContractCompilationResult compilationResult = ContractCompiler.CompileFile(filename); Assert.True(compilationResult.Success); byte[] originalAssemblyBytes = compilationResult.Compilation; IContractModuleDefinition module = this.moduleReader.Read(originalAssemblyBytes).Value; module.Rewrite(this.rewriter); CSharpFunctionalExtensions.Result <IContractAssembly> assembly = this.assemblyLoader.Load(module.ToByteCode()); return(Contract.CreateUninitialized(assembly.Value.GetType(module.ContractType.Name), this.state, null)); }
public void Validate_Determinism_ValidateActionDisallowed() { string adjustedSource = TestString.Replace(ReplaceCodeString, @"var test = new Action(() => { var insideAction = DateTime.Now; }); test();").Replace(ReplaceReferencesString, ""); ContractCompilationResult compilationResult = ContractCompiler.Compile(adjustedSource); Assert.True(compilationResult.Success); byte[] assemblyBytes = compilationResult.Compilation; IContractModuleDefinition moduleDefinition = ContractDecompiler.GetModuleDefinition(assemblyBytes).Value; SmartContractValidationResult result = this.validator.Validate(moduleDefinition.ModuleDefinition); Assert.False(result.IsValid); }
public void SmartContractValidator_Allow_SingleContract() { const string source = @"using System; using Stratis.SmartContracts; public class Test : SmartContract { public Test(ISmartContractState state) : base(state) { } }"; IContractModuleDefinition decompilation = CompileToModuleDef(source); SmartContractValidationResult result = new SmartContractValidator().Validate(decompilation.ModuleDefinition); Assert.True(result.IsValid); Assert.Empty(result.Errors); }
public void SmartContractValidator_Should_Allow_Consts() { const string source = @"using System; using Stratis.SmartContracts; public class Test : SmartContract { public const string Item = ""Test""; public Test(ISmartContractState state) : base(state) { var abc = Item.Length; } }"; IContractModuleDefinition decompilation = CompileToModuleDef(source); SmartContractValidationResult result = new SmartContractValidator().Validate(decompilation.ModuleDefinition); Assert.True(result.IsValid); }
public void SmartContractValidator_Should_Validate_Internal_Types() { var adjustedSource = @" using System; using Stratis.SmartContracts; [Deploy] public class Test : SmartContract { public Test(ISmartContractState state): base(state) { Create<Test2>(); } } public class Test2 : SmartContract { public Test2(ISmartContractState state): base(state) { PersistentState.SetString(""dt"", DateTime.Now.ToString()); } } "; ContractCompilationResult compilationResult = ContractCompiler.Compile(adjustedSource); Assert.True(compilationResult.Success); byte[] assemblyBytes = compilationResult.Compilation; IContractModuleDefinition decompilation = ContractDecompiler.GetModuleDefinition(assemblyBytes).Value; var moduleDefinition = decompilation.ModuleDefinition; var moduleType = moduleDefinition.GetType("<Module>"); moduleDefinition.Types.Remove(moduleType); var internalType = moduleDefinition.GetType("Test2"); internalType.Name = "<Module>"; SmartContractValidationResult result = new SmartContractValidator().Validate(moduleDefinition); Assert.False(result.IsValid); Assert.NotEmpty(result.Errors); Assert.True(result.Errors.All(e => e is WhitelistValidator.WhitelistValidationResult)); }
public void Validate_Determinism_ErrorMessages_Referenced_ThreeLevels() { string source = @" using Stratis.SmartContracts; public class MessageTest : SmartContract { public MessageTest(ISmartContractState smartContractState) : base(smartContractState) { } public void MessageTestValid() { MessageTestValid1(); } public void MessageTestValid1() { MessageTestValid2(); } public void MessageTestValid2() { MessageTestFloat1(); } public void MessageTestFloat1() { float test = (float) 3.5; } }"; SmartContractCompilationResult compilationResult = SmartContractCompiler.Compile(source); Assert.True(compilationResult.Success); IContractModuleDefinition moduleDefinition = SmartContractDecompiler.GetModuleDefinition(compilationResult.Compilation); SmartContractValidationResult result = this.validator.Validate(moduleDefinition.ModuleDefinition); Assert.False(result.IsValid); Assert.Single(result.Errors); Assert.Equal("Float usage", result.Errors.First().ValidationType); }
public void Validate_Determinism_StringIteration() { string adjustedSource = TestString.Replace(ReplaceCodeString, @"int randomNumber = 0; foreach (byte c in ""Abcdefgh"") { randomNumber += c; }").Replace(ReplaceReferencesString, ""); ContractCompilationResult compilationResult = ContractCompiler.Compile(adjustedSource); Assert.True(compilationResult.Success); byte[] assemblyBytes = compilationResult.Compilation; IContractModuleDefinition moduleDefinition = ContractDecompiler.GetModuleDefinition(assemblyBytes).Value; SmartContractValidationResult result = this.validator.Validate(moduleDefinition.ModuleDefinition); Assert.True(result.IsValid); }
public void SmartContractValidator_Should_Not_Allow_New_NestedReferenceType() { const string source = @"using System; using Stratis.SmartContracts; public class Test : SmartContract { public class A {} public Test(ISmartContractState state) : base(state) { } }"; IContractModuleDefinition decompilation = CompileToModuleDef(source); SmartContractValidationResult result = new SmartContractValidator().Validate(decompilation.ModuleDefinition); Assert.Contains(result.Errors, e => e is NestedTypeIsValueTypeValidator.NestedTypeIsValueTypeValidationResult); }
public void Validate_Determinism_Passes_Array_AllowedMembers() { string code = @" var test = new int[25]; var test2 = new int[25]; test[0] = 123; int ret = test[0]; int len = test.Length; Array.Resize(ref test, 50); Array.Copy(test, test2, len);"; string adjustedSource = TestString.Replace(ReplaceCodeString, code).Replace(ReplaceReferencesString, ""); byte[] assemblyBytes = ContractCompiler.Compile(adjustedSource).Compilation; IContractModuleDefinition moduleDefinition = ContractDecompiler.GetModuleDefinition(assemblyBytes).Value; SmartContractValidationResult result = this.validator.Validate(moduleDefinition.ModuleDefinition); Assert.True(result.IsValid); }
public void SmartContractValidator_Should_Not_Allow_Static_Constructors() { const string source = @"using System; using Stratis.SmartContracts; public class Test : SmartContract { static Test() {} public Test(ISmartContractState state) : base(state) { } }"; IContractModuleDefinition decompilation = CompileToModuleDef(source); SmartContractValidationResult result = new SmartContractValidator().Validate(decompilation.ModuleDefinition); Assert.False(result.IsValid); Assert.Contains(result.Errors, e => e is StaticConstructorValidator.StaticConstructorValidationResult); }
public void TestGasInjector_NestedType_GasInjectionSucceeds() { ContractCompilationResult compilationResult = ContractCompiler.Compile(@" using System; using Stratis.SmartContracts; public class Test : SmartContract { public Test(ISmartContractState state): base(state) { var other = new Other.NestedOther(); other.Loop(); } } public static class Other { public struct NestedOther { public void Loop() { while(true) {}} } } "); Assert.True(compilationResult.Success); byte[] originalAssemblyBytes = compilationResult.Compilation; IContractModuleDefinition module = this.moduleReader.Read(originalAssemblyBytes).Value; module.Rewrite(this.rewriter); CSharpFunctionalExtensions.Result <IContractAssembly> assembly = this.assemblyLoader.Load(module.ToByteCode()); assembly.Value.SetObserver(new Observer(this.gasMeter, new MemoryMeter(ReflectionVirtualMachine.MemoryUnitLimit))); IContract contract = Contract.CreateUninitialized(assembly.Value.GetType(module.ContractType.Name), this.state, null); IContractInvocationResult result = contract.InvokeConstructor(null); Assert.False(result.IsSuccess); Assert.Equal(this.gasMeter.GasLimit, this.gasMeter.GasConsumed); }
public void SmartContractValidator_Should_Allow_New_NestedType() { const string source = @"using System; using Stratis.SmartContracts; public class Test : SmartContract { public struct A {} public Test(ISmartContractState state) : base(state) { } public void B() { var test = new A(); } }"; IContractModuleDefinition decompilation = CompileToModuleDef(source); SmartContractValidationResult result = new SmartContractValidator().Validate(decompilation.ModuleDefinition); Assert.Empty(result.Errors); }