forked from carver/mix
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ClientModel.h
282 lines (257 loc) · 9.58 KB
/
ClientModel.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
/*
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 [email protected]
* @author Arkadiy Paronyan [email protected]
* @date 2015
* Ethereum IDE client.
*/
#pragma once
#include <atomic>
#include <map>
#include <QString>
#include <QQmlListProperty>
#include <QVariantMap>
#include <QFuture>
#include <QVariableDeclaration.h>
#include <libethereum/Account.h>
#include "MachineStates.h"
namespace dev
{
namespace eth { class FixedAccountHolder; }
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, bool _isContractCreation, bool _isFunctionCall):
contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasAuto(_gasAuto), gasPrice(_gasPrice), sender(_sender), isContractCreation(_isContractCreation), isFunctionCall(_isFunctionCall) {}
TransactionSettings(QString const& _stdContractName, QString const& _stdContractUrl):
contractId(_stdContractName), gasAuto(true), stdContractUrl(_stdContractUrl), isContractCreation(true), isFunctionCall(true) {}
/// 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;
/// Tr deploys a contract
bool isContractCreation;
/// Tr call a ctr function
bool isFunctionCall;
};
/// 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)
/// Sender
Q_PROPERTY(QString sender MEMBER m_sender CONSTANT)
/// label
Q_PROPERTY(QString label MEMBER m_label CONSTANT)
/// input parameters
Q_PROPERTY(QVariantMap parameters MEMBER m_inputParameters CONSTANT)
/// logs
Q_PROPERTY(QVariantList logs MEMBER m_logs 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,
QString _sender, QString _label, QVariantMap _inputParameters, QVariantList _logs):
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),
m_sender(_sender), m_label(_label), m_inputParameters(_inputParameters), m_logs(_logs) {}
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;
QString m_sender;
QString m_label;
QVariantMap m_inputParameters;
QVariantList m_logs;
};
/**
* @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 scenario, run transaction sequence, show debugger for the last transaction
/// @param _state JS object with state configuration
void setupScenario(QVariantMap _scenario);
/// Execute the given @param _tr on the current state
void executeTr(QVariantMap _tr);
/// 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);
dev::Address deployContract(bytes const& _code, TransactionSettings const& _tr = TransactionSettings());
void callAddress(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);
QString resolveToken(std::pair<QString, int> const& _value);
std::pair<QString, int> retrieveToken(QString const& _value);
std::pair<QString, int> resolvePair(QString const& _contractId);
QVariant formatStorageValue(SolidityType const& _type, std::unordered_map<dev::u256, dev::u256> const& _storage, unsigned _offset, dev::u256 const& _slot);
void processNextTransactions();
void finalizeBlock();
void stopExecution();
void setupExecutionChain();
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;
std::shared_ptr<eth::FixedAccountHolder> m_ethAccounts;
std::unordered_map<Address, eth::Account> m_accounts;
std::vector<KeyPair> m_accountsSecret;
QList<u256> m_gasCosts;
std::map<std::pair<QString, int>, 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;
QList<QVariantList> m_queueTransactions;
mutable boost::shared_mutex x_queueTransactions;
};
}
}
Q_DECLARE_METATYPE(dev::mix::RecordLogEntry*)