Ejemplo n.º 1
0
        public void CheckIsConstant()
        {
            if (VMConfig.AllowTvmConstantinople)
            {
                return;
            }

            TriggerSmartContract trigger_contract = ContractCapsule.GetTriggerContractFromTransaction(this.Transaction.Instance);

            if (this.transaction_type == TransactionType.TX_CONTRACT_CALL_TYPE)
            {
                Deposit         deposit  = Deposit.CreateRoot(this.db_manager);
                ContractCapsule contract = deposit.GetContract(trigger_contract.ContractAddress.ToByteArray());
                if (contract == null)
                {
                    Logger.Info(string.Format("contract: {0} is not in contract store",
                                              Wallet.AddressToBase58(trigger_contract.ContractAddress.ToByteArray())));

                    throw new ContractValidateException("contract: "
                                                        + Wallet.AddressToBase58(trigger_contract.ContractAddress.ToByteArray())
                                                        + " is not in contract store");
                }
                ABI abi = contract.Instance.Abi;
                if (Wallet.IsConstant(abi, trigger_contract))
                {
                    throw new VMIllegalException("cannot call constant method");
                }
            }
        }
Ejemplo n.º 2
0
        private long GetTotalEnergyLimitWithFloatRatio(AccountCapsule creator,
                                                       AccountCapsule caller,
                                                       TriggerSmartContract trigger_contract,
                                                       long fee_limit,
                                                       long call_value)
        {
            long caller_energy_limit = GetAccountEnergyLimitWithFloatRatio(caller, fee_limit, call_value);

            if (creator.Address.ToByteArray().SequenceEqual(caller.Address.ToByteArray()))
            {
                return(caller_energy_limit);
            }

            long            creator_energy_limit     = this.energy_processor.GetAccountLeftEnergyFromFreeze(creator);
            ContractCapsule contractCapsule          = this.deposit.GetContract(trigger_contract.ContractAddress.ToByteArray());
            long            consume_resource_percent = contractCapsule.GetConsumeUserResourcePercent();

            if (creator_energy_limit * consume_resource_percent
                > (DefineParameter.ONE_HUNDRED - consume_resource_percent) * caller_energy_limit)
            {
                return((long)Math.Floor(((double)caller_energy_limit * DefineParameter.ONE_HUNDRED) / consume_resource_percent));
            }
            else
            {
                return(caller_energy_limit + creator_energy_limit);
            }
        }
Ejemplo n.º 3
0
        public async Task <decimal> BalanceOfAsync(string contractAddress, ITronAccount ownerAccount)
        {
            var contractAddressBytes = Base58Encoder.DecodeFromBase58Check(contractAddress);
            var ownerAddressBytes    = Base58Encoder.DecodeFromBase58Check(ownerAccount.Address);
            var wallet      = _walletClient.GetProtocol();
            var functionABI = ABITypedRegistry.GetFunctionABI <BalanceOfFunction>();

            try
            {
                var addressBytes = new byte[20];
                Array.Copy(ownerAddressBytes, 1, addressBytes, 0, addressBytes.Length);

                var addressBytesHex = "0x" + addressBytes.ToHex();

                var balanceOf = new BalanceOfFunction {
                    Owner = addressBytesHex
                };
                var decimals = GetDecimals(wallet, contractAddressBytes);

                var encodedHex = new FunctionCallEncoder().EncodeRequest(balanceOf, functionABI.Sha3Signature);

                var trigger = new TriggerSmartContract
                {
                    ContractAddress = ByteString.CopyFrom(contractAddressBytes),
                    OwnerAddress    = ByteString.CopyFrom(ownerAddressBytes),
                    Data            = ByteString.CopyFrom(encodedHex.HexToByteArray()),
                };

                var transactionExtention = await wallet.TriggerConstantContractAsync(trigger, headers : _walletClient.GetHeaders());

                if (!transactionExtention.Result.Result)
                {
                    throw new Exception(transactionExtention.Result.Message.ToStringUtf8());
                }
                if (transactionExtention.ConstantResult.Count == 0)
                {
                    throw new Exception($"result error, ConstantResult length=0.");
                }

                var result = new FunctionCallDecoder().DecodeFunctionOutput <BalanceOfFunctionOutput>(transactionExtention.ConstantResult[0].ToByteArray().ToHex());

                var balance = Convert.ToDecimal(result.Balance);
                if (decimals > 0)
                {
                    balance /= Convert.ToDecimal(Math.Pow(10, decimals));
                }

                return(balance);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
                throw;
            }
        }
Ejemplo n.º 4
0
 public long GetTotalEnergyLimit(AccountCapsule creator,
                                 AccountCapsule caller,
                                 TriggerSmartContract trigger_contract,
                                 long fee_limit,
                                 long call_value)
 {
     if (VMConfig.EnergyLimitHardFork)
     {
         return(GetTotalEnergyLimitWithFixRatio(creator, caller, trigger_contract, fee_limit, call_value));
     }
     else
     {
         return(GetTotalEnergyLimitWithFloatRatio(creator, caller, trigger_contract, fee_limit, call_value));
     }
 }
Ejemplo n.º 5
0
        public static TriggerSmartContract GetTriggerContractFromTransaction(Transaction tx)
        {
            TriggerSmartContract contract = null;

            try
            {
                contract = tx.RawData.Contract[0].Parameter.Unpack <TriggerSmartContract>();
            }
            catch
            {
                contract = null;
            }

            return(contract);
        }
Ejemplo n.º 6
0
        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;
        }
Ejemplo n.º 7
0
        public long GetTotalEnergyLimitWithFixRatio(AccountCapsule creator,
                                                    AccountCapsule caller,
                                                    TriggerSmartContract trigger_contract,
                                                    long fee_limit,
                                                    long call_value)
        {
            long caller_energy_limit = GetAccountEnergyLimitWithFixRatio(caller, fee_limit, call_value);

            if (creator.Address.ToByteArray().SequenceEqual(caller.Address.ToByteArray()))
            {
                return(caller_energy_limit);
            }

            long            creator_energy_limit     = 0;
            ContractCapsule contract                 = this.deposit.GetContract(trigger_contract.ContractAddress.ToByteArray());
            long            consume_resource_percent = contract.GetConsumeUserResourcePercent();
            long            origin_energy_limit      = contract.GetOriginEnergyLimit();

            if (origin_energy_limit < 0)
            {
                throw new ContractValidateException("origin_energy_limit can't be < 0");
            }

            if (consume_resource_percent <= 0)
            {
                creator_energy_limit = Math.Min(this.energy_processor.GetAccountLeftEnergyFromFreeze(creator), origin_energy_limit);
            }
            else
            {
                if (consume_resource_percent < DefineParameter.ONE_HUNDRED)
                {
                    BigInteger left = new BigInteger(caller_energy_limit);
                    left = BigInteger.Multiply(left, new BigInteger(DefineParameter.ONE_HUNDRED - consume_resource_percent));
                    left = BigInteger.Divide(left, new BigInteger(consume_resource_percent));

                    long right = Math.Min(this.energy_processor.GetAccountLeftEnergyFromFreeze(creator), origin_energy_limit);

                    creator_energy_limit = Math.Min((long)left, right);
                }
            }

            return(caller_energy_limit + creator_energy_limit);
        }
Ejemplo n.º 8
0
        public void Pay()
        {
            byte[] origin_account      = null;
            byte[] caller_account      = null;
            long   percent             = 0;
            long   origin_energy_limit = 0;

            switch (this.transaction_type)
            {
            case TransactionType.TX_CONTRACT_CREATION_TYPE:
            {
                caller_account = TransactionCapsule.GetOwner(this.transaction.Instance.RawData.Contract[0]);
                origin_account = caller_account;
            }
            break;

            case TransactionType.TX_CONTRACT_CALL_TYPE:
            {
                TriggerSmartContract trigger_contract = ContractCapsule.GetTriggerContractFromTransaction(this.transaction.Instance);
                ContractCapsule      contract         = this.db_manager.Contract.Get(trigger_contract.ContractAddress.ToByteArray());

                caller_account      = trigger_contract.OwnerAddress.ToByteArray();
                origin_account      = contract.OriginAddress;
                percent             = Math.Max(DefineParameter.ONE_HUNDRED - contract.GetConsumeUserResourcePercent(), 0);
                percent             = Math.Min(percent, DefineParameter.ONE_HUNDRED);
                origin_energy_limit = contract.GetOriginEnergyLimit();
            }
            break;

            default:
                return;
            }

            this.receipt.PayEnergyBill(this.db_manager,
                                       this.db_manager.Account.Get(origin_account),
                                       this.db_manager.Account.Get(caller_account),
                                       percent,
                                       origin_energy_limit,
                                       energy_processor,
                                       this.db_manager.WitnessController.GetHeadSlot());
        }
Ejemplo n.º 9
0
        private long GetDecimals(Wallet.WalletClient wallet, byte[] contractAddressBytes)
        {
            var trc20Decimals = new DecimalsFunction();

            var callEncoder = new FunctionCallEncoder();
            var functionABI = ABITypedRegistry.GetFunctionABI <DecimalsFunction>();

            var encodedHex = callEncoder.EncodeRequest(trc20Decimals, functionABI.Sha3Signature);

            var trigger = new TriggerSmartContract
            {
                ContractAddress = ByteString.CopyFrom(contractAddressBytes),
                Data            = ByteString.CopyFrom(encodedHex.HexToByteArray()),
            };

            var txnExt = wallet.TriggerConstantContract(trigger, headers: _walletClient.GetHeaders());

            var result = txnExt.ConstantResult[0].ToByteArray().ToHex();

            return(new FunctionCallDecoder().DecodeOutput <long>(result, new Parameter("uint8", "d")));
        }
Ejemplo n.º 10
0
 public static bool IsConstant(ABI abi, TriggerSmartContract trigger_contract)
 {
     try
     {
         bool constant = IsConstant(abi, GetSelector(trigger_contract.Data.ToByteArray()));
         if (constant)
         {
             if (Args.Instance.VM.SupportConstant == false)
             {
                 throw new ContractValidateException("this node don't support constant");
             }
         }
         return(constant);
     }
     catch (ContractValidateException e)
     {
         throw e;
     }
     catch
     {
         return(false);
     }
 }
Ejemplo n.º 11
0
        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);
                }
            }
        }
Ejemplo n.º 12
0
        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");
        }
Ejemplo n.º 13
0
        public async Task <string> TransferAsync(string contractAddress, ITronAccount ownerAccount, string toAddress, decimal amount, string memo, long feeLimit)
        {
            var contractAddressBytes = Base58Encoder.DecodeFromBase58Check(contractAddress);
            var callerAddressBytes   = Base58Encoder.DecodeFromBase58Check(toAddress);
            var ownerAddressBytes    = Base58Encoder.DecodeFromBase58Check(ownerAccount.Address);
            var wallet      = _walletClient.GetProtocol();
            var functionABI = ABITypedRegistry.GetFunctionABI <TransferFunction>();

            try
            {
                var contract = await wallet.GetContractAsync(new BytesMessage
                {
                    Value = ByteString.CopyFrom(contractAddressBytes),
                }, headers : _walletClient.GetHeaders());

                var toAddressBytes = new byte[20];
                Array.Copy(callerAddressBytes, 1, toAddressBytes, 0, toAddressBytes.Length);

                var toAddressHex = "0x" + toAddressBytes.ToHex();

                var decimals = GetDecimals(wallet, contractAddressBytes);

                var tokenAmount = amount;
                if (decimals > 0)
                {
                    tokenAmount = amount * Convert.ToDecimal(Math.Pow(10, decimals));
                }

                var trc20Transfer = new TransferFunction
                {
                    To          = toAddressHex,
                    TokenAmount = Convert.ToInt64(tokenAmount),
                };

                var encodedHex = new FunctionCallEncoder().EncodeRequest(trc20Transfer, functionABI.Sha3Signature);


                var trigger = new TriggerSmartContract
                {
                    ContractAddress = ByteString.CopyFrom(contractAddressBytes),
                    OwnerAddress    = ByteString.CopyFrom(ownerAddressBytes),
                    Data            = ByteString.CopyFrom(encodedHex.HexToByteArray()),
                };

                var transactionExtention = await wallet.TriggerConstantContractAsync(trigger, headers : _walletClient.GetHeaders());

                if (!transactionExtention.Result.Result)
                {
                    _logger.LogWarning($"[transfer]transfer failed, message={transactionExtention.Result.Message.ToStringUtf8()}.");
                    return(null);
                }

                var transaction = transactionExtention.Transaction;

                if (transaction.Ret.Count > 0 && transaction.Ret[0].Ret == Transaction.Types.Result.Types.code.Failed)
                {
                    return(null);
                }

                transaction.RawData.Data     = ByteString.CopyFromUtf8(memo);
                transaction.RawData.FeeLimit = feeLimit;

                var transSign = _transactionClient.GetTransactionSign(transaction, ownerAccount.PrivateKey);

                var result = await _transactionClient.BroadcastTransactionAsync(transSign);

                return(transSign.GetTxid());
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
                return(null);
            }
        }