private void Call() { if (!this.deposit.DBManager.DynamicProperties.SupportVM()) { Logger.Info("vm work is off, need to be opened by the committee"); throw new ContractValidateException("VM work is off, need to be opened by the committee"); } TriggerSmartContract contract = ContractCapsule.GetTriggerContractFromTransaction(this.transaction); if (contract == null) { return; } if (contract.ContractAddress == null) { throw new ContractValidateException("Cannot get contract address from TriggerContract"); } byte[] contract_address = contract.ContractAddress.ToByteArray(); ContractCapsule deployed_contract = this.deposit.GetContract(contract_address); if (null == deployed_contract) { Logger.Info("No contract or not a smart contract"); throw new ContractValidateException("No contract or not a smart contract"); } long call_value = contract.CallValue; long token_value = 0; long token_id = 0; if (VMConfig.AllowTvmTransferTrc10) { token_value = contract.CallTokenValue; token_id = contract.TokenId; } if (VMConfig.EnergyLimitHardFork) { if (call_value < 0) { throw new ContractValidateException("callValue must >= 0"); } if (token_value < 0) { throw new ContractValidateException("tokenValue must >= 0"); } } byte[] caller_address = contract.OwnerAddress.ToByteArray(); CheckTokenValueAndId(token_value, token_id); byte[] code = this.deposit.GetCode(contract_address); if (code != null && code.Length > 0) { 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 caller = this.deposit.GetAccount(caller_address); long energy_limit = 0; if (this.is_static_call) { energy_limit = DefineParameter.ENERGY_LIMIT_IN_CONSTANT_TX; } else { AccountCapsule creator = this.deposit.GetAccount(deployed_contract.Instance.OriginAddress.ToByteArray()); energy_limit = GetTotalEnergyLimit(creator, caller, contract, fee_limit, call_value); } 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_CALL_TYPE, this.executor_type, this.transaction, token_value, token_id, this.block.Instance, this.deposit, vm_start, vm_should_end, energy_limit); if (this.is_static_call) { invoke.IsStaticCall = true; } this.vm = new Vm(); this.root_internal_transaction = new InternalTransaction(this.transaction, this.transaction_type); this.program = new Program(code, 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 (enableEventLinstener && // (EventPluginLoader.getInstance().isContractEventTriggerEnable() // || EventPluginLoader.getInstance().isContractLogTriggerEnable()) // && isCheckTransaction()) //{ // logInfoTriggerParser = new LogInfoTriggerParser(this.block.getNum(), this.block.getTimeStamp(), txId, callerAddress); //} } this.program.Result.ContractAddress = contract_address; 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); } } }
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); } } }