/* This file is part of cpp-ethereum. cpp-ethereum is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. cpp-ethereum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ /** @file ClientModel.h * @author Yann yann@ethdev.com * @author Arkadiy Paronyan arkadiy@ethdev.com * @date 2015 * Ethereum IDE client. */ #pragma once #include #include #include #include #include "MachineStates.h" namespace dev { namespace mix { class AppContext; class Web3Server; class RpcConnector; class QEther; class QDebugData; class MixClient; class QVariableDefinition; /// Backend transaction config class struct TransactionSettings { TransactionSettings() {} TransactionSettings(QString const& _contractId, QString const& _functionId, u256 _value, u256 _gas, u256 _gasPrice, Secret _sender): contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasPrice(_gasPrice), sender(_sender) {} TransactionSettings(QString const& _stdContractName, QString const& _stdContractUrl): contractId(_stdContractName), stdContractUrl(_stdContractUrl) {} /// Contract name QString contractId; /// Contract function name QString functionId; /// Transaction value u256 value; /// Gas u256 gas; /// Gas price u256 gasPrice; /// Mapping from contract function parameter name to value QList parameterValues; /// Standard contract url QString stdContractUrl; /// Sender Secret sender; }; /// UI Transaction log record class RecordLogEntry: public QObject { Q_OBJECT Q_ENUMS(RecordType) /// Recording index Q_PROPERTY(unsigned recordIndex MEMBER m_recordIndex CONSTANT) /// Human readable transaction bloack and transaction index Q_PROPERTY(QString transactionIndex MEMBER m_transactionIndex CONSTANT) /// Contract name if any Q_PROPERTY(QString contract MEMBER m_contract CONSTANT) /// Function name if any Q_PROPERTY(QString function MEMBER m_function CONSTANT) /// Transaction value Q_PROPERTY(QString value MEMBER m_value CONSTANT) /// Receiving address Q_PROPERTY(QString address MEMBER m_address CONSTANT) /// Returned value or transaction address in case of creation Q_PROPERTY(QString returned MEMBER m_returned CONSTANT) /// true if call, false if transaction Q_PROPERTY(bool call MEMBER m_call CONSTANT) /// @returns record type Q_PROPERTY(RecordType type MEMBER m_type CONSTANT) public: enum RecordType { Transaction, Block }; RecordLogEntry(): m_recordIndex(0), m_call(false), m_type(RecordType::Transaction) {} RecordLogEntry(unsigned _recordIndex, QString _transactionIndex, QString _contract, QString _function, QString _value, QString _address, QString _returned, bool _call, RecordType _type): m_recordIndex(_recordIndex), m_transactionIndex(_transactionIndex), m_contract(_contract), m_function(_function), m_value(_value), m_address(_address), m_returned(_returned), m_call(_call), m_type(_type) {} private: unsigned m_recordIndex; QString m_transactionIndex; QString m_contract; QString m_function; QString m_value; QString m_address; QString m_returned; bool m_call; RecordType m_type; }; /** * @brief Ethereum state control */ class ClientModel: public QObject { Q_OBJECT public: ClientModel(AppContext* _context); ~ClientModel(); /// @returns true if currently executing contract code Q_PROPERTY(bool running MEMBER m_running NOTIFY runStateChanged) /// @returns true if currently mining Q_PROPERTY(bool mining MEMBER m_mining NOTIFY miningStateChanged) /// @returns deployed contracts addresses Q_PROPERTY(QVariantMap contractAddresses READ contractAddresses NOTIFY contractAddressesChanged) // @returns the last block Q_PROPERTY(RecordLogEntry* lastBlock READ lastBlock CONSTANT) /// ethereum.js RPC request entry point /// @param _message RPC request in Json format /// @returns RPC response in Json format Q_INVOKABLE QString apiCall(QString const& _message); /// Simulate mining. Creates a new block Q_INVOKABLE void mine(); public slots: /// Setup state, run transaction sequence, show debugger for the last transaction /// @param _state JS object with state configuration void setupState(QVariantMap _state); /// Show the debugger for a specified record Q_INVOKABLE void debugRecord(unsigned _index); /// Show the debugger for an empty record Q_INVOKABLE void emptyRecord(); Q_INVOKABLE QString newAddress(); private slots: /// Update UI with machine states result. Display a modal dialog. void showDebugger(); /// Update UI with transaction run error. void showDebugError(QString const& _error); signals: /// Transaction execution started void runStarted(); /// Transaction execution completed successfully void runComplete(); /// Mining has started void miningStarted(); /// Mined a new block void miningComplete(); /// Mining stopped or started void miningStateChanged(); /// Transaction execution completed with error /// @param _message Error message void runFailed(QString const& _message); /// Contract address changed void contractAddressesChanged(); /// Execution state changed void newBlock(); /// Execution state changed void runStateChanged(); /// Show debugger window request void debugDataReady(QObject* _debugData); /// ethereum.js RPC response ready /// @param _message RPC response in Json format void apiResponse(QString const& _message); /// New transaction log entry void newRecord(RecordLogEntry* _r); /// State (transaction log) cleared void stateCleared(); private: RecordLogEntry* lastBlock() const; QVariantMap contractAddresses() const; void executeSequence(std::vector const& _sequence, std::map const& _balances); dev::Address deployContract(bytes const& _code, TransactionSettings const& _tr = TransactionSettings()); void callContract(Address const& _contract, bytes const& _data, TransactionSettings const& _tr); void onNewTransaction(); void onStateReset(); void showDebuggerForTransaction(ExecutionResult const& _t); AppContext* m_context; std::atomic m_running; std::atomic m_mining; std::unique_ptr m_client; std::unique_ptr m_rpcConnector; std::unique_ptr m_web3Server; std::map m_contractAddresses; std::map m_contractNames; std::map m_stdContractAddresses; std::map m_stdContractNames; }; } } Q_DECLARE_METATYPE(dev::mix::RecordLogEntry*)