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); } } }
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"); }
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 void UpdateContract(byte[] address, ContractCapsule contract) { this.contract_cache.Put(new Key(address), Value.Create(contract.Data, ValueType.VALUE_TYPE_DIRTY)); }
public void CreateContract(byte[] address, ContractCapsule contract) { this.contract_cache.Add(new Key(address), Value.Create(contract.Data, ValueType.VALUE_TYPE_CREATE)); }
public void CreateContract(byte[] address, ContractCapsule contract) { this.deposit.CreateContract(address, contract); }
public override bool Validate() { if (this.contract == null) { throw new ContractValidateException("No contract!"); } if (this.db_manager == null) { throw new ContractValidateException("No db_manager!"); } if (this.contract.Is(UpdateSettingContract.Descriptor)) { UpdateSettingContract contract = null; try { contract = this.contract.Unpack <UpdateSettingContract>(); } catch (InvalidProtocolBufferException e) { Logger.Debug(e.Message); throw new ContractValidateException(e.Message); } if (!Wallet.IsValidAddress(contract.OwnerAddress.ToByteArray())) { throw new ContractValidateException("Invalid address"); } byte[] owner_address = contract.OwnerAddress.ToByteArray(); AccountCapsule account = this.db_manager.Account.Get(owner_address); if (account == null) { throw new ContractValidateException( "Account[" + owner_address.ToHexString() + "] not exists"); } long new_percent = contract.ConsumeUserResourcePercent; if (new_percent > 100 || new_percent < 0) { throw new ContractValidateException("percent not in [0, 100]"); } byte[] contractAddress = contract.ContractAddress.ToByteArray(); ContractCapsule deployed_contract = this.db_manager.Contract.Get(contractAddress); if (deployed_contract == null) { throw new ContractValidateException("Contract not exists"); } byte[] contract_owner_address = deployed_contract.Instance.OriginAddress.ToByteArray(); if (owner_address.SequenceEqual(contract_owner_address)) { throw new ContractValidateException( "Account[" + owner_address.ToHexString() + "] is not the owner of the contract"); } } else { throw new ContractValidateException( "contract type error,expected type [UpdateSettingContract],real type[" + contract.GetType().Name + "]"); } return(true); }
public List <ContractTrigger> ParseLogInfos(List <LogInfo> log_infos, IDeposit deposit) { List <ContractTrigger> triggers = new List <ContractTrigger>(); if (log_infos == null || log_infos.Count <= 0) { return(triggers); } Dictionary <string, string> signs = new Dictionary <string, string>(); Dictionary <string, string> abis = new Dictionary <string, string>(); foreach (LogInfo info in log_infos) { byte[] contract_address = Wallet.ToAddAddressPrefix(info.Address); string contract_address_str = contract_address.IsNotNullOrEmpty() ? Wallet.AddressToBase58(contract_address) : ""; if (signs.TryGetValue(contract_address_str, out _) == false) { continue; } ContractCapsule contract = deposit.GetContract(contract_address); if (contract == null) { signs.Add(contract_address_str, origin_address); abis.Add(contract_address_str, ""); continue; } ABI abi = contract.Instance.Abi; string creator_address = Wallet.AddressToBase58(Wallet.ToAddAddressPrefix(contract.Instance.OriginAddress.ToByteArray())); signs.Add(contract_address_str, creator_address); if (abi != null && abi.Entrys.Count > 0) { abis.Add(contract_address_str, JsonFormat.PrintToString(abi, false)); } else { abis.Add(contract_address_str, ""); } } int index = 1; foreach (LogInfo info in log_infos) { byte[] contract_address = Wallet.ToAddAddressPrefix(info.Address); string contract_address_str = contract_address.IsNotNullOrEmpty() ? Wallet.AddressToBase58(contract_address) : ""; string abi_value = abis[contract_address_str]; ContractTrigger trigger = new ContractTrigger(); string creator_address = signs[contract_address_str]; trigger.UniqueId = this.transaction_id + "_" + index; trigger.TransactionId = this.transaction_id; trigger.ContractAddress = contract_address_str; trigger.OriginAddress = this.origin_address; trigger.CallerAddress = ""; trigger.CreatorAddress = creator_address.IsNotNullOrEmpty() ? creator_address : ""; trigger.BlockNumber = this.block_num; trigger.Timestamp = this.block_timestamp; trigger.LogInfo = info; trigger.AbiString = abi_value; triggers.Add(trigger); index++; } return(triggers); }