public void SME_CreateContract_MethodParameters_ParameterTypeMismatch() { SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/ContractMethodParameterTypeMismatch.cs"); Assert.True(compilationResult.Success); byte[] contractCode = compilationResult.Compilation; string[] methodParameters = new string[] { string.Format("{0}#{1}", (int)SmartContractCarrierDataType.Bool, true), }; var carrier = SmartContractCarrier.CreateContract(0, contractCode, 1, (Gas)10000, methodParameters); var tx = new Transaction(); tx.AddOutput(0, new Script(carrier.Serialize())); ISmartContractTransactionContext transactionContext = new SmartContractTransactionContext(BlockHeight, CoinbaseAddress, MempoolFee, new uint160(2), tx); var executor = new CreateSmartContract( this.keyEncodingStrategy, this.loggerFactory, this.network, this.state, this.validator, this.refundProcessor, this.transferProcessor, this.vm); ISmartContractExecutionResult result = executor.Execute(transactionContext); Assert.NotNull(result.Exception); Assert.Equal(GasPriceList.BaseCost, result.GasConsumed); }
public void SME_CreateContract_ConstructorFails_Refund() { SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/ContractConstructorInvalid.cs"); Assert.True(compilationResult.Success); byte[] contractCode = compilationResult.Compilation; SmartContractCarrier carrier = SmartContractCarrier.CreateContract(0, contractCode, 1, (Gas)10000); var tx = new Transaction(); tx.AddOutput(0, new Script(carrier.Serialize())); ISmartContractTransactionContext transactionContext = new SmartContractTransactionContext(BlockHeight, CoinbaseAddress, MempoolFee, new uint160(2), tx); var executor = new CreateSmartContract( this.keyEncodingStrategy, this.loggerFactory, this.network, this.state, this.validator, this.refundProcessor, this.transferProcessor, this.vm); ISmartContractExecutionResult result = executor.Execute(transactionContext); Assert.NotNull(result.Exception); // Base cost + constructor cost Assert.Equal(GasPriceList.BaseCost + 13, result.GasConsumed); }
public static byte[] GenerateContractAddress(Transaction tx) { CreateSmartContract contract = ContractCapsule.GetSmartContractFromTransaction(tx); byte[] owner_address = contract.OwnerAddress.ToByteArray(); TransactionCapsule transaction = new TransactionCapsule(tx); byte[] tx_hash = transaction.Id.Hash; byte[] combined = new byte[tx_hash.Length + owner_address.Length]; Array.Copy(tx_hash, 0, combined, 0, tx_hash.Length); Array.Copy(owner_address, 0, combined, tx_hash.Length, owner_address.Length); return(Hash.ToAddress(combined)); }
public static CreateSmartContract GetSmartContractFromTransaction(Transaction tx) { CreateSmartContract contract = null; try { contract = tx.RawData.Contract[0].Parameter.Unpack <CreateSmartContract>(); } catch { contract = null; } return(contract); }
public static TransactionCapsule CreateTransactionCapsule(IMessage message, ContractType type) { DatabaseManager db_manager = Manager.Instance.DBManager; TransactionCapsule transaction = new TransactionCapsule(message, type); if (type != ContractType.CreateSmartContract && type != ContractType.TriggerSmartContract) { List <IActuator> actuators = ActuatorFactory.CreateActuator(transaction, db_manager); foreach (IActuator actuator in actuators) { actuator.Validate(); } } if (type == ContractType.CreateSmartContract) { CreateSmartContract contract = ContractCapsule.GetSmartContractFromTransaction(transaction.Instance); long percent = contract.NewContract.ConsumeUserResourcePercent; if (percent < 0 || percent > 100) { throw new ContractValidateException("percent must be >= 0 and <= 100"); } } try { BlockId id = db_manager.HeadBlockId; if (Args.Instance.Transaction.ReferenceBlock.Equals("solid")) { id = db_manager.SolidBlockId; } transaction.SetReference(id.Num, id.Hash); transaction.Expiration = db_manager.GetHeadBlockTimestamp() + (long)Args.Instance.Transaction.ExpireTimeInMillis; transaction.Timestamp = Helper.CurrentTimeMillis(); } catch (System.Exception e) { Logger.Error("Create transaction capsule failed.", e); } return(transaction); }
public InternalTransaction(Transaction tx, InternalTransaction.TransactionType tx_type) { this.transaction = tx; TransactionCapsule transaction = new TransactionCapsule(tx); this.proto_encoded = transaction.Data; this.nonce = 0; this.deep = -1; if (tx_type == TransactionType.TX_CONTRACT_CREATION_TYPE) { CreateSmartContract contract = ContractCapsule.GetSmartContractFromTransaction(tx); if (contract == null) { throw new ContractValidateException("Invalid CreateSmartContract protocol"); } this.send_address = contract.OwnerAddress.ToByteArray(); this.receive_address = new byte[0]; this.transfer_to_address = Wallet.GenerateContractAddress(tx); this.note = "create"; this.value = contract.NewContract.CallValue; this.data = contract.NewContract.Bytecode.ToByteArray(); this.token_info.Add(contract.TokenId.ToString(), contract.CallTokenValue); } else if (tx_type == TransactionType.TX_CONTRACT_CALL_TYPE) { TriggerSmartContract contract = ContractCapsule.GetTriggerContractFromTransaction(tx); if (contract == null) { throw new ContractValidateException("Invalid TriggerSmartContract protocol"); } this.send_address = contract.OwnerAddress.ToByteArray(); this.receive_address = contract.ContractAddress.ToByteArray(); this.transfer_to_address = (byte[])this.receive_address.Clone(); this.note = "call"; this.value = contract.CallValue; this.data = contract.Data.ToByteArray(); this.token_info.Add(contract.TokenId.ToString(), contract.CallTokenValue); } this.hash = transaction.Id.Hash; }
private void Create() { if (!this.deposit.DBManager.DynamicProperties.SupportVM()) { throw new ContractValidateException("vm work is off, need to be opened by the committee"); } CreateSmartContract contract = ContractCapsule.GetSmartContractFromTransaction(this.transaction); if (contract == null) { throw new ContractValidateException("Cannot get CreateSmartContract from transaction"); } SmartContract new_contract = contract.NewContract; if (!contract.OwnerAddress.Equals(new_contract.OriginAddress)) { Logger.Info("OwnerAddress not equals OriginAddress"); throw new VMIllegalException("OwnerAddress is not equals OriginAddress"); } byte[] contract_name = Encoding.UTF8.GetBytes(new_contract.Name); if (contract_name.Length > VMParameter.CONTRACT_NAME_LENGTH) { throw new ContractValidateException("contractName's length cannot be greater than 32"); } long percent = contract.NewContract.ConsumeUserResourcePercent; if (percent < 0 || percent > DefineParameter.ONE_HUNDRED) { throw new ContractValidateException("percent must be >= 0 and <= 100"); } byte[] contract_address = Wallet.GenerateContractAddress(this.transaction); if (this.deposit.GetAccount(contract_address) != null) { throw new ContractValidateException( "Trying to create a contract with existing contract address: " + Wallet.AddressToBase58(contract_address)); } new_contract.ContractAddress = ByteString.CopyFrom(contract_address); long call_value = new_contract.CallValue; long token_value = 0; long token_id = 0; if (VMConfig.AllowTvmTransferTrc10) { token_value = contract.CallTokenValue; token_id = contract.TokenId; } byte[] caller_address = contract.OwnerAddress.ToByteArray(); try { long fee_limit = this.transaction.RawData.FeeLimit; if (fee_limit < 0 || fee_limit > VMConfig.MAX_FEE_LIMIT) { Logger.Info(string.Format("invalid feeLimit {0}", fee_limit)); throw new ContractValidateException( "feeLimit must be >= 0 and <= " + VMConfig.MAX_FEE_LIMIT); } AccountCapsule creator = this.deposit.GetAccount(new_contract.OriginAddress.ToByteArray()); long energy_limit = 0; if (VMConfig.EnergyLimitHardFork) { if (call_value < 0) { throw new ContractValidateException("callValue must >= 0"); } if (token_value < 0) { throw new ContractValidateException("tokenValue must >= 0"); } if (new_contract.OriginEnergyLimit <= 0) { throw new ContractValidateException("The originEnergyLimit must be > 0"); } energy_limit = GetAccountEnergyLimitWithFixRatio(creator, fee_limit, call_value); } else { energy_limit = GetAccountEnergyLimitWithFloatRatio(creator, fee_limit, call_value); } CheckTokenValueAndId(token_value, token_id); byte[] ops = new_contract.Bytecode.ToByteArray(); this.root_internal_transaction = new InternalTransaction(this.transaction, this.transaction_type); long max_cpu_time_tx = this.deposit.DBManager.DynamicProperties.GetMaxCpuTimeOfOneTx() * DefineParameter.ONE_THOUSAND; long tx_cpu_limit = (long)(max_cpu_time_tx * GetCpuLimitInUsRatio()); long vm_start = Helper.NanoTime() / DefineParameter.ONE_THOUSAND; long vm_should_end = vm_start + tx_cpu_limit; IProgramInvoke invoke = this.invoke_factory.CreateProgramInvoke(TransactionType.TX_CONTRACT_CREATION_TYPE, this.executor_type, this.transaction, token_value, token_id, this.block.Instance, this.deposit, vm_start, vm_should_end, energy_limit); this.vm = new Vm(); this.program = new Program(ops, invoke, this.root_internal_transaction, this.block); byte[] tx_id = new TransactionCapsule(this.transaction).Id.Hash; this.program.RootTransactionId = tx_id; // TODO: EventPluginLoader is not Implementation //if (this.enable_listener // && (EventPluginLoader.getInstance().isContractEventTriggerEnable() // || EventPluginLoader.getInstance().isContractLogTriggerEnable()) // && IsCheckTransaction) //{ // logInfoTriggerParser = new LogInfoTriggerParser(this.block.getNum(), this.block.getTimeStamp(), txId, callerAddress); //} } catch (Exception e) { Logger.Info(e.Message); throw new ContractValidateException(e.Message); } this.program.Result.ContractAddress = contract_address; this.deposit.CreateAccount(contract_address, new_contract.Name, AccountType.Contract); this.deposit.CreateContract(contract_address, new ContractCapsule(new_contract)); byte[] code = new_contract.Bytecode.ToByteArray(); if (!VMConfig.AllowTvmConstantinople) { deposit.SaveCode(contract_address, ProgramPrecompile.GetCode(code)); } if (call_value > 0) { MUtil.Transfer(this.deposit, caller_address, contract_address, call_value); } if (VMConfig.AllowTvmTransferTrc10) { if (token_value > 0) { MUtil.TransferToken(this.deposit, caller_address, contract_address, token_id.ToString(), token_value); } } }
public IProgramInvoke CreateProgramInvoke(TransactionType tx_type, ExecutorType executor_type, Transaction tx, long token_value, long token_id, Block block, IDeposit deposit, long vm_start, long vm_should_end, long energy_limit) { byte[] data = null; byte[] last_hash = null; byte[] coinbase = null; byte[] contract_address = null; byte[] owner_address = null; long balance = 0; long number = -1; long timestamp = 0; if (tx_type == TransactionType.TX_CONTRACT_CREATION_TYPE) { CreateSmartContract contract = ContractCapsule.GetSmartContractFromTransaction(tx); contract_address = Wallet.GenerateContractAddress(tx); owner_address = contract.OwnerAddress.ToByteArray(); balance = deposit.GetBalance(owner_address); data = new byte[0]; long call_value = contract.NewContract.CallValue; switch (executor_type) { case ExecutorType.ET_NORMAL_TYPE: case ExecutorType.ET_PRE_TYPE: { if (null != block) { last_hash = block.BlockHeader.RawData.ParentHash.ToByteArray(); coinbase = block.BlockHeader.RawData.WitnessAddress.ToByteArray(); timestamp = block.BlockHeader.RawData.Timestamp / 1000; number = block.BlockHeader.RawData.Number; } } break; default: break; } return(new ProgramInvoke(contract_address, owner_address, owner_address, balance, call_value, token_value, token_id, data, last_hash, coinbase, timestamp, number, deposit, vm_start, vm_should_end, energy_limit)); } else if (tx_type == TransactionType.TX_CONTRACT_CALL_TYPE) { TriggerSmartContract contract = ContractCapsule.GetTriggerContractFromTransaction(tx); byte[] address = contract.ContractAddress.ToByteArray(); byte[] origin = contract.OwnerAddress.ToByteArray(); byte[] caller = contract.OwnerAddress.ToByteArray(); balance = deposit.GetBalance(caller); long call_value = contract.CallValue; data = contract.Data.ToByteArray(); switch (executor_type) { case ExecutorType.ET_CONSTANT_TYPE: break; case ExecutorType.ET_PRE_TYPE: case ExecutorType.ET_NORMAL_TYPE: if (null != block) { last_hash = block.BlockHeader.RawData.ParentHash.ToByteArray(); coinbase = block.BlockHeader.RawData.WitnessAddress.ToByteArray(); timestamp = block.BlockHeader.RawData.Timestamp / 1000; number = block.BlockHeader.RawData.Number; } break; default: break; } return(new ProgramInvoke(address, origin, caller, balance, call_value, token_value, token_id, data, last_hash, coinbase, timestamp, number, deposit, vm_start, vm_should_end, energy_limit)); } throw new ContractValidateException("Unknown contract type"); }
public void Execute_InterContractCall_InfiniteLoop_AllGasConsumed() { // Create contract 1 //Get the contract execution code------------------------ SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/InfiniteLoop.cs"); Assert.True(compilationResult.Success); byte[] contractExecutionCode = compilationResult.Compilation; //------------------------------------------------------- // Add contract creation code to transaction------------- var carrier = SmartContractCarrier.CreateContract(1, contractExecutionCode, 1, (Gas)3500); var transaction = new Transaction(); TxOut txOut = transaction.AddOutput(0, new Script(carrier.Serialize())); txOut.Value = 100; //------------------------------------------------------- //Deserialize the contract from the transaction---------- //and get the module definition ISmartContractTransactionContext transactionContext = new SmartContractTransactionContext(BlockHeight, CoinbaseAddress, MempoolFee, SenderAddress, transaction); var executor = new CreateSmartContract( this.keyEncodingStrategy, this.loggerFactory, this.network, this.state, this.validator, this.refundProcessor, this.transferProcessor, this.vm); ISmartContractExecutionResult result = executor.Execute(transactionContext); uint160 address1 = result.NewContractAddress; //------------------------------------------------------- // Create contract 2 //Get the contract execution code------------------------ compilationResult = SmartContractCompiler.CompileFile("SmartContracts/CallInfiniteLoopContract.cs"); Assert.True(compilationResult.Success); contractExecutionCode = compilationResult.Compilation; //------------------------------------------------------- //Call smart contract and add to transaction------------- carrier = SmartContractCarrier.CreateContract(1, contractExecutionCode, 1, (Gas)3500); transaction = new Transaction(); txOut = transaction.AddOutput(0, new Script(carrier.Serialize())); txOut.Value = 100; //------------------------------------------------------- //Deserialize the contract from the transaction---------- //and get the module definition //------------------------------------------------------- transactionContext = new SmartContractTransactionContext(BlockHeight, CoinbaseAddress, MempoolFee, SenderAddress, transaction); result = executor.Execute(transactionContext); uint160 address2 = result.NewContractAddress; // Invoke infinite loop var gasLimit = (Gas)1000000; string[] parameters = { string.Format("{0}#{1}", (int)SmartContractCarrierDataType.String, address1.ToAddress(this.network).Value), }; carrier = SmartContractCarrier.CallContract(1, address2, "CallInfiniteLoop", 1, gasLimit, parameters); transaction = new Transaction(); txOut = transaction.AddOutput(0, new Script(carrier.Serialize())); txOut.Value = 100; transactionContext = new SmartContractTransactionContext(BlockHeight, CoinbaseAddress, MempoolFee, SenderAddress, transaction); var callExecutor = new CallSmartContract( this.keyEncodingStrategy, this.loggerFactory, this.network, this.state, this.refundProcessor, this.transferProcessor, this.vm); // Because our contract contains an infinite loop, we want to kill our test after // some amount of time without achieving a result. 3 seconds is an arbitrarily high enough timeout // for the method body to have finished execution while minimising the amount of time we spend // running tests // If you're running with the debugger on this will obviously be a source of failures result = RunWithTimeout(3, () => callExecutor.Execute(transactionContext)); Assert.IsType <OutOfGasException>(result.Exception); Assert.Equal(gasLimit, result.GasConsumed); }