public void SmartContract_Constructor_NoParamSuccess() { LifecycleResult constructionResult = SmartContractConstructor .Construct(typeof(NoParamContract), this.state); Assert.True(constructionResult.Success); Assert.NotNull(constructionResult.Object); }
public void SmartContract_Constructor_ConstructorInvokedSuccess() { LifecycleResult constructionResult = SmartContractConstructor .Construct(typeof(ConstructorInvokedContract), this.state); Assert.True(constructionResult.Success); Assert.NotNull(constructionResult.Object); Assert.True(((ConstructorInvokedContract)constructionResult.Object).ConstructorInvoked); }
public void SmartContract_Constructor_OneParamSuccess() { ulong startBlock = 12345; LifecycleResult constructionResult = SmartContractConstructor .Construct(typeof(OneParamContract), this.state, startBlock); Assert.True(constructionResult.Success); Assert.NotNull(constructionResult.Object); }
public void SmartContract_Constructor_NonpublicStateFieldsSetSuccess() { LifecycleResult constructionResult = SmartContractConstructor .Construct(typeof(NoParamContract), this.state); Assert.True(constructionResult.Success); SmartContract contract = constructionResult.Object; FieldInfo[] fields = typeof(SmartContract).GetFields( BindingFlags.Instance | BindingFlags.NonPublic ); foreach (FieldInfo field in fields) { object value = field.GetValue(contract); switch (field.Name) { case "Block": Assert.Equal(this.state.Block, value); break; case "Message": Assert.Equal(this.state.Message, value); break; case "PersistentState": Assert.Equal(this.state.PersistentState, value); break; case "gasMeter": Assert.Equal(this.state.GasMeter, value); break; case "getBalance": Assert.Equal(this.state.GetBalance, value); break; case "internalTransactionExecutor": Assert.Equal(this.state.InternalTransactionExecutor, value); break; case "internalHashHelper": Assert.Equal(this.state.InternalHashHelper, value); break; case "smartContractState": Assert.Equal(this.state, value); break; } } }
public void SmartContract_Constructor_InvalidParamSuccess() { ulong startBlock = 12345; LifecycleResult constructionResult = SmartContractConstructor .Construct(typeof(NoParamContract), this.state, startBlock); Assert.False(constructionResult.Success); Assert.Null(constructionResult.Object); Assert.NotNull(constructionResult.Exception); }
/// <summary> /// Creates a new instance of a smart contract by invoking the contract's constructor /// </summary> public VmExecutionResult Create(byte[] contractCode, ISmartContractExecutionContext context, IGasMeter gasMeter, IPersistentState persistentState, IContractStateRepository repository) { this.logger.LogTrace("()"); byte[] gasInjectedCode = SmartContractGasInjector.AddGasCalculationToConstructor(contractCode); Type contractType = Load(gasInjectedCode); var internalTransferList = new List <TransferInfo>(); IInternalTransactionExecutor internalTransactionExecutor = this.internalTransactionExecutorFactory.Create(repository, internalTransferList); var balanceState = new BalanceState(repository, context.Message.Value, internalTransferList); var contractState = new SmartContractState( context.Block, context.Message, persistentState, gasMeter, internalTransactionExecutor, new InternalHashHelper(), () => balanceState.GetBalance(context.ContractAddress)); // Invoke the constructor of the provided contract code LifecycleResult result = SmartContractConstructor.Construct(contractType, contractState, context.Parameters); if (!result.Success) { LogException(result.Exception); this.logger.LogTrace("(-)[CREATE_CONTRACT_INSTANTIATION_FAILED]:{0}={1}", nameof(gasMeter.GasConsumed), gasMeter.GasConsumed); return(VmExecutionResult.Error(gasMeter.GasConsumed, result.Exception.InnerException ?? result.Exception)); } else { this.logger.LogTrace("[CREATE_CONTRACT_INSTANTIATION_SUCCEEDED]"); } this.logger.LogTrace("(-):{0}={1}", nameof(gasMeter.GasConsumed), gasMeter.GasConsumed); return(VmExecutionResult.Success(internalTransferList, gasMeter.GasConsumed, result.Object)); }
private static void ValidateContract(string fileName, IConsole console, string[] parameters, ValidationServiceResult validationServiceResult) { byte[] compilation; SmartContractDecompilation decompilation; BuildModuleDefinition(console, validationServiceResult, out compilation, out decompilation); console.WriteLine($"Validating file {fileName}..."); Assembly smartContract = Assembly.Load(compilation); var serializer = new MethodParameterSerializer(); object[] methodParameters = null; if (parameters.Length != 0) { var methodParametersRaw = new MethodParameterSerializer().ToRaw(parameters); methodParameters = serializer.ToObjects(methodParametersRaw); } validationServiceResult.LifeCycleResult = SmartContractConstructor.Construct(smartContract.ExportedTypes.FirstOrDefault(), new ValidatorSmartContractState(), methodParameters); if (!validationServiceResult.LifeCycleResult.Success) { console.WriteLine("Smart contract construction failed."); console.WriteLine("If the smart contract is constructed with parameters, please ensure they are provided."); } validationServiceResult.DeterminismValidationResult = new SmartContractDeterminismValidator().Validate(decompilation); validationServiceResult.FormatValidationResult = new SmartContractFormatValidator(ReferencedAssemblyResolver.AllowedAssemblies).Validate(decompilation); if (!validationServiceResult.DeterminismValidationResult.IsValid || !validationServiceResult.FormatValidationResult.IsValid) { console.WriteLine("Smart Contract failed validation. Run validate [FILE] for more info."); } console.WriteLine(); }
/// <summary> /// Creates a new instance of a smart contract by invoking the contract's constructor /// </summary> public VmExecutionResult Create(IGasMeter gasMeter, IContractStateRepository repository, ICreateData createData, ITransactionContext transactionContext) { this.logger.LogTrace("()"); // TODO: Spend Validation + Creation Fee here. // Decompile the contract execution code and validate it. SmartContractDecompilation decompilation = SmartContractDecompiler.GetModuleDefinition(createData.ContractExecutionCode); SmartContractValidationResult validation = this.validator.Validate(decompilation); // If validation failed, refund the sender any remaining gas. if (!validation.IsValid) { this.logger.LogTrace("(-)[CONTRACT_VALIDATION_FAILED]"); return(VmExecutionResult.Error(gasMeter.GasConsumed, new SmartContractValidationException(validation.Errors))); } byte[] gasInjectedCode = SmartContractGasInjector.AddGasCalculationToConstructor(createData.ContractExecutionCode, decompilation.ContractType.Name); Type contractType = Load(gasInjectedCode, decompilation.ContractType.Name); uint160 contractAddress = this.addressGenerator.GenerateAddress(transactionContext.TransactionHash, transactionContext.GetNonceAndIncrement()); // Create an account for the contract in the state repository. repository.CreateAccount(contractAddress); IPersistenceStrategy persistenceStrategy = new MeteredPersistenceStrategy(repository, gasMeter, new BasicKeyEncodingStrategy()); var persistentState = new PersistentState(persistenceStrategy, contractAddress, this.network); var internalTransferList = new List <TransferInfo>(); IInternalTransactionExecutor internalTransactionExecutor = this.internalTransactionExecutorFactory.Create(this, repository, internalTransferList, transactionContext); var balanceState = new BalanceState(repository, transactionContext.Amount, internalTransferList); var contractState = new SmartContractState( new Block( transactionContext.BlockHeight, transactionContext.Coinbase.ToAddress(this.network) ), new Message( contractAddress.ToAddress(this.network), transactionContext.From.ToAddress(this.network), transactionContext.Amount ), persistentState, gasMeter, internalTransactionExecutor, new InternalHashHelper(), () => balanceState.GetBalance(contractAddress)); LogExecutionContext(this.logger, contractState.Block, contractState.Message, contractAddress, createData); // Invoke the constructor of the provided contract code LifecycleResult result = SmartContractConstructor.Construct(contractType, contractState, createData.MethodParameters); if (!result.Success) { LogException(result.Exception); this.logger.LogTrace("(-)[CREATE_CONTRACT_INSTANTIATION_FAILED]:{0}={1}", nameof(gasMeter.GasConsumed), gasMeter.GasConsumed); return(VmExecutionResult.Error(gasMeter.GasConsumed, result.Exception.InnerException ?? result.Exception)); } this.logger.LogTrace("[CREATE_CONTRACT_INSTANTIATION_SUCCEEDED]"); this.logger.LogTrace("(-):{0}={1}, {2}={3}", nameof(contractAddress), contractAddress, nameof(gasMeter.GasConsumed), gasMeter.GasConsumed); repository.SetCode(contractAddress, createData.ContractExecutionCode); repository.SetContractType(contractAddress, contractType.Name); return(VmExecutionResult.CreationSuccess(contractAddress, internalTransferList, gasMeter.GasConsumed, result.Object)); }