|
|
|
/*
|
|
|
|
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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
/** @file ClientModel.h
|
|
|
|
* @author Yann yann@ethdev.com
|
|
|
|
* @author Arkadiy Paronyan arkadiy@ethdev.com
|
|
|
|
* @date 2015
|
|
|
|
* Ethereum IDE client.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <atomic>
|
|
|
|
#include <map>
|
|
|
|
#include <QString>
|
|
|
|
#include <QQmlListProperty>
|
|
|
|
#include <QVariantMap>
|
|
|
|
#include <QFuture>
|
|
|
|
#include <QVariableDeclaration.h>
|
|
|
|
#include "MachineStates.h"
|
|
|
|
|
|
|
|
namespace dev
|
|
|
|
{
|
|
|
|
|
|
|
|
namespace eth { class Account; }
|
|
|
|
|
|
|
|
namespace mix
|
|
|
|
{
|
|
|
|
|
|
|
|
class Web3Server;
|
|
|
|
class RpcConnector;
|
|
|
|
class QEther;
|
|
|
|
class QDebugData;
|
|
|
|
class MixClient;
|
|
|
|
class QVariableDefinition;
|
|
|
|
class CodeModel;
|
|
|
|
struct SolidityType;
|
|
|
|
|
|
|
|
/// Backend transaction config class
|
|
|
|
struct TransactionSettings
|
|
|
|
{
|
|
|
|
TransactionSettings() {}
|
|
|
|
TransactionSettings(QString const& _contractId, QString const& _functionId, u256 _value, u256 _gas, bool _gasAuto, u256 _gasPrice, Secret _sender):
|
|
|
|
contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasAuto(_gasAuto), gasPrice(_gasPrice), sender(_sender) {}
|
|
|
|
TransactionSettings(QString const& _stdContractName, QString const& _stdContractUrl):
|
|
|
|
contractId(_stdContractName), gasAuto(true), stdContractUrl(_stdContractUrl) {}
|
|
|
|
|
|
|
|
/// Contract name
|
|
|
|
QString contractId;
|
|
|
|
/// Contract function name
|
|
|
|
QString functionId;
|
|
|
|
/// Transaction value
|
|
|
|
u256 value;
|
|
|
|
/// Gas
|
|
|
|
u256 gas;
|
|
|
|
/// Calculate gas automatically
|
|
|
|
bool gasAuto = true;
|
|
|
|
/// Gas price
|
|
|
|
u256 gasPrice;
|
|
|
|
/// Mapping from contract function parameter name to value
|
|
|
|
QVariantMap 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)
|
|
|
|
/// Gas used
|
|
|
|
Q_PROPERTY(QString gasUsed MEMBER m_gasUsed 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, QString _gasUsed):
|
|
|
|
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), m_gasUsed(_gasUsed) {}
|
|
|
|
|
|
|
|
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;
|
|
|
|
QString m_gasUsed;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Ethereum state control
|
|
|
|
*/
|
|
|
|
class ClientModel: public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
public:
|
|
|
|
ClientModel();
|
|
|
|
~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 deployed contracts gas costs
|
|
|
|
Q_PROPERTY(QVariantList gasCosts READ gasCosts NOTIFY gasCostsChanged)
|
|
|
|
// @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();
|
|
|
|
/// Get/set code model. Should be set from qml
|
|
|
|
Q_PROPERTY(CodeModel* codeModel MEMBER m_codeModel)
|
|
|
|
/// Encode parameters
|
|
|
|
Q_INVOKABLE QStringList encodeParams(QVariant const& _param, QString const& _contract, QString const& _function);
|
|
|
|
/// Encode parameter
|
|
|
|
Q_INVOKABLE QString encodeStringParam(QString const& _param);
|
|
|
|
/// To Hex number
|
|
|
|
Q_INVOKABLE QString toHex(QString const& _int);
|
|
|
|
|
|
|
|
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();
|
|
|
|
/// Generate new secret
|
|
|
|
Q_INVOKABLE QString newSecret();
|
|
|
|
/// retrieve the address of @arg _secret
|
|
|
|
Q_INVOKABLE QString address(QString const& _secret);
|
|
|
|
/// Encode a string to ABI parameter. Returns a hex string
|
|
|
|
Q_INVOKABLE QString encodeAbiString(QString _string);
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
/// Update UI with machine states result. Display a modal dialog.
|
|
|
|
void showDebugger();
|
|
|
|
|
|
|
|
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();
|
|
|
|
/// Gas costs updated
|
|
|
|
void gasCostsChanged();
|
|
|
|
/// 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;
|
|
|
|
QVariantList gasCosts() const;
|
|
|
|
void executeSequence(std::vector<TransactionSettings> const& _sequence, std::map<Address, dev::eth::Account> const& _accounts, Secret const& _miner);
|
|
|
|
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);
|
|
|
|
QVariant formatValue(SolidityType const& _type, dev::u256 const& _value);
|
|
|
|
QVariant formatStorageValue(SolidityType const& _type, std::map<dev::u256, dev::u256> const& _storage, unsigned _offset, dev::u256 const& _slot);
|
|
|
|
|
|
|
|
std::atomic<bool> m_running;
|
|
|
|
std::atomic<bool> m_mining;
|
|
|
|
QFuture<void> m_runFuture;
|
|
|
|
std::unique_ptr<MixClient> m_client;
|
|
|
|
std::unique_ptr<RpcConnector> m_rpcConnector;
|
|
|
|
std::unique_ptr<Web3Server> m_web3Server;
|
|
|
|
QList<u256> m_gasCosts;
|
|
|
|
std::map<QString, Address> m_contractAddresses;
|
|
|
|
std::map<Address, QString> m_contractNames;
|
|
|
|
std::map<QString, Address> m_stdContractAddresses;
|
|
|
|
std::map<Address, QString> m_stdContractNames;
|
|
|
|
CodeModel* m_codeModel = nullptr;
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Q_DECLARE_METATYPE(dev::mix::RecordLogEntry*)
|