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);
        }
예제 #3
0
파일: Wallet.cs 프로젝트: lovecpus/mineral
        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));
        }
예제 #4
0
        public static CreateSmartContract GetSmartContractFromTransaction(Transaction tx)
        {
            CreateSmartContract contract = null;

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

            return(contract);
        }
예제 #5
0
        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);
        }
예제 #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;
        }
예제 #7
0
        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);
                }
            }
        }
예제 #8
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");
        }
        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);
        }