@ -22,6 +22,8 @@
# include <libsolidity/Token.h>
# include <libsolidity/Types.h>
# include <utility>
# include <stdexcept>
# include <boost/exception/diagnostic_information.hpp>
# include <QtConcurrent/QtConcurrent>
# include <QDebug>
# include <QQmlContext>
@ -55,7 +57,8 @@ QString toQString(dev::u256 _value)
return QString : : fromStdString ( s . str ( ) ) ;
}
AssemblyDebuggerControl : : AssemblyDebuggerControl ( AppContext * _context ) : Extension ( _context , ExtensionDisplayBehavior : : ModalDialog )
AssemblyDebuggerControl : : AssemblyDebuggerControl ( AppContext * _context ) :
Extension ( _context , ExtensionDisplayBehavior : : ModalDialog ) , m_running ( false )
{
qRegisterMetaType < QVariableDefinition * > ( " QVariableDefinition* " ) ;
qRegisterMetaType < QVariableDefinitionList * > ( " QVariableDefinitionList* " ) ;
@ -63,14 +66,11 @@ AssemblyDebuggerControl::AssemblyDebuggerControl(AppContext* _context): Extensio
qRegisterMetaType < QList < QVariableDeclaration * > > ( " QList<QVariableDeclaration*> " ) ;
qRegisterMetaType < QVariableDeclaration * > ( " QVariableDeclaration* " ) ;
qRegisterMetaType < AssemblyDebuggerData > ( " AssemblyDebuggerData " ) ;
qRegisterMetaType < DebuggingStatusResult > ( " DebuggingStatusResult " ) ;
connect ( this , SIGNAL ( dataAvailable ( bool , DebuggingStatusResult , QList < QVariableDefinition * > , QList < QObject * > , AssemblyDebuggerData ) ) ,
this , SLOT ( updateGUI ( bool , DebuggingStatusResult , QList < QVariableDefinition * > , QList < QObject * > , AssemblyDebuggerData ) ) , Qt : : QueuedConnection ) ;
connect ( this , & AssemblyDebuggerControl : : dataAvailable , this , & AssemblyDebuggerControl : : showDebugger , Qt : : QueuedConnection ) ;
m_modelDebugger = std : : unique_ptr < AssemblyDebuggerModel > ( new AssemblyDebuggerModel ) ;
_context - > appEngine ( ) - > rootContext ( ) - > setContextProperty ( " debugModel " , this ) ;
m_modelDebugger = std : : unique_ptr < AssemblyDebuggerModel > ( new AssemblyDebuggerModel ) ;
}
QString AssemblyDebuggerControl : : contentUrl ( ) const
@ -80,7 +80,7 @@ QString AssemblyDebuggerControl::contentUrl() const
QString AssemblyDebuggerControl : : title ( ) const
{
return QApplication : : tr ( " d ebugger" ) ;
return QApplication : : tr ( " D ebugger" ) ;
}
void AssemblyDebuggerControl : : start ( ) const
@ -89,7 +89,7 @@ void AssemblyDebuggerControl::start() const
void AssemblyDebuggerControl : : debugDeployment ( )
{
deployContract ( ) ;
executeSequence ( std : : vector < TransactionSettings > ( ) , 0 ) ;
}
void AssemblyDebuggerControl : : debugState ( QVariantMap _state )
@ -97,8 +97,7 @@ void AssemblyDebuggerControl::debugState(QVariantMap _state)
u256 balance = fromQString ( _state . value ( " balance " ) . toString ( ) ) ;
QVariantList transactions = _state . value ( " transactions " ) . toList ( ) ;
resetState ( ) ;
deployContract ( ) ;
std : : vector < TransactionSettings > transactionSequence ;
for ( auto const & t : transactions )
{
@ -114,93 +113,106 @@ void AssemblyDebuggerControl::debugState(QVariantMap _state)
for ( auto p = params . cbegin ( ) ; p ! = params . cend ( ) ; + + p )
transactionSettings . parameterValues . insert ( std : : make_pair ( p . key ( ) , fromQString ( p . value ( ) . toString ( ) ) ) ) ;
runTransaction ( transactionSettings ) ;
transactionSequence . push_back ( transactionSettings ) ;
}
executeSequence ( transactionSequence , balance ) ;
}
void AssemblyDebuggerControl : : resetState ( )
{
m_modelDebugger - > resetState ( ) ;
m_ctx - > displayMessageDialog ( QApplication : : tr ( " State status " ) , QApplication : : tr ( " State reseted ... need to redeploy contract " ) ) ;
}
void AssemblyDebuggerControl : : callContract ( TransactionSettings _tr , dev : : Address _contract )
void AssemblyDebuggerControl : : executeSequence ( std : : vector < TransactionSettings > const & _sequence , u256 _balance )
{
if ( m_running )
throw ( std : : logic_error ( " debugging already running " ) ) ;
auto compilerRes = m_ctx - > codeModel ( ) - > code ( ) ;
if ( ! compilerRes - > successfull ( ) )
m_ctx - > displayMessageDialog ( " debugger " , " compilation failed " ) ;
else
std : : shared_ptr < QContractDefinition > contractDef = compilerRes - > sharedContract ( ) ;
m_running = true ;
emit runStarted ( ) ;
emit stateChanged ( ) ;
//run sequence
QtConcurrent : : run ( [ = ] ( )
{
try
{
bytes contractCode = compilerRes - > bytes ( ) ;
std : : vector < dev : : bytes > transactonData ;
QFunctionDefinition * f ;
ContractCallDataEncoder c ;
QContractDefinition const * contractDef = compilerRes - > contract ( ) ;
QFunctionDefinition * f = nullptr ;
//encode data for all transactions
for ( auto const & t : _sequence )
{
f = nullptr ;
for ( int k = 0 ; k < contractDef - > functionsList ( ) . size ( ) ; k + + )
{
if ( contractDef - > functionsList ( ) . at ( k ) - > name ( ) = = _ tr . functionId )
if ( contractDef - > functionsList ( ) . at ( k ) - > name ( ) = = t . functionId )
{
f = contractDef - > functionsList ( ) . at ( k ) ;
break ;
}
}
if ( ! f )
m_ctx - > displayMessageDialog ( QApplication : : tr ( " debugger " ) , QApplication : : tr ( " function not found. Please redeploy this contract. " ) ) ;
else
{
throw std : : runtime_error ( " function " + t . functionId . toStdString ( ) + " not found " ) ;
c . encode ( f - > index ( ) ) ;
for ( int k = 0 ; k < f - > parametersList ( ) . size ( ) ; k + + )
{
QVariableDeclaration * var = ( QVariableDeclaration * ) f - > parametersList ( ) . at ( k ) ;
c . encode ( var , _tr . parameterValues [ var - > name ( ) ] ) ;
}
DebuggingContent debuggingContent = m_modelDebugger - > callContract ( _contract , c . encodedData ( ) , _tr ) ;
debuggingContent . returnParameters = c . decode ( f - > returnParameters ( ) , debuggingContent . returnValue ) ;
finalizeExecution ( debuggingContent ) ;
u256 value = 0 ;
auto v = t . parameterValues . find ( var - > name ( ) ) ;
if ( v ! = t . parameterValues . cend ( ) )
value = v - > second ;
c . encode ( var , value ) ;
}
transactonData . emplace_back ( c . encodedData ( ) ) ;
}
}
void AssemblyDebuggerControl : : deployContract ( )
{
auto compilerRes = m_ctx - > codeModel ( ) - > code ( ) ;
if ( ! compilerRes - > successfull ( ) )
emit dataAvailable ( false , DebuggingStatusResult : : Compilationfailed ) ;
else
{
m_previousDebugResult = m_modelDebugger - > deployContract ( compilerRes - > bytes ( ) ) ;
finalizeExecution ( m_previousDebugResult ) ;
}
}
//run contract creation first
m_modelDebugger - > resetState ( _balance ) ;
DebuggingContent debuggingContent = m_modelDebugger - > deployContract ( contractCode ) ;
Address address = debuggingContent . contractAddress ;
for ( unsigned i = 0 ; i < _sequence . size ( ) ; + + i )
debuggingContent = m_modelDebugger - > callContract ( address , transactonData . at ( i ) , _sequence . at ( i ) ) ;
if ( f )
debuggingContent . returnParameters = c . decode ( f - > returnParameters ( ) , debuggingContent . returnValue ) ;
void AssemblyDebuggerControl : : finalizeExecution ( DebuggingContent _debuggingContent )
{
//we need to wrap states in a QObject before sending to QML.
QList < QObject * > wStates ;
for ( int i = 0 ; i < _ debuggingContent. machineStates . size ( ) ; i + + )
for ( int i = 0 ; i < debuggingContent . machineStates . size ( ) ; i + + )
{
QPointer < DebuggingStateWrapper > s ( new DebuggingStateWrapper ( _ debuggingContent. executionCode , _ debuggingContent. executionData . toBytes ( ) ) ) ;
s - > setState ( _ debuggingContent. machineStates . at ( i ) ) ;
QPointer < DebuggingStateWrapper > s ( new DebuggingStateWrapper ( debuggingContent . executionCode , debuggingContent . executionData . toBytes ( ) ) ) ;
s - > setState ( debuggingContent . machineStates . at ( i ) ) ;
wStates . append ( s ) ;
}
AssemblyDebuggerData code = DebuggingStateWrapper : : getHumanReadableCode ( _debuggingContent . executionCode ) ;
emit dataAvailable ( true , DebuggingStatusResult : : Ok , _debuggingContent . returnParameters , wStates , code ) ;
//collect states for last transaction
AssemblyDebuggerData code = DebuggingStateWrapper : : getHumanReadableCode ( debuggingContent . executionCode ) ;
emit dataAvailable ( debuggingContent . returnParameters , wStates , code ) ;
emit runComplete ( ) ;
}
catch ( boost : : exception const & e )
{
emit runFailed ( QString : : fromStdString ( boost : : current_exception_diagnostic_information ( ) ) ) ;
}
catch ( std : : exception const & e )
{
emit runFailed ( e . what ( ) ) ;
}
m_running = false ;
emit stateChanged ( ) ;
} ) ;
}
void AssemblyDebuggerControl : : updateGUI ( bool _success , DebuggingStatusResult const & _reason , QList < QVariableDefinition * > const & _returnParam , QList < QObject * > const & _wStates , AssemblyDebuggerData const & _code )
void AssemblyDebuggerControl : : showDebugger ( QList < QVariableDefinition * > const & _returnParam , QList < QObject * > const & _wStates , AssemblyDebuggerData const & _code )
{
Q_UNUSED ( _reason ) ;
if ( _success )
{
m_appEngine - > rootContext ( ) - > setContextProperty ( " debugStates " , QVariant : : fromValue ( _wStates ) ) ;
m_appEngine - > rootContext ( ) - > setContextProperty ( " humanReadableExecutionCode " , QVariant : : fromValue ( std : : get < 0 > ( _code ) ) ) ;
m_appEngine - > rootContext ( ) - > setContextProperty ( " bytesCodeMapping " , QVariant : : fromValue ( std : : get < 1 > ( _code ) ) ) ;
m_appEngine - > rootContext ( ) - > setContextProperty ( " contractCallReturnParameters " , QVariant : : fromValue ( new QVariableDefinitionList ( _returnParam ) ) ) ;
this - > addContentOn ( this ) ;
}
else
m_ctx - > displayMessageDialog ( QApplication : : tr ( " debugger " ) , QApplication : : tr ( " compilation failed " ) ) ;
}
void AssemblyDebuggerControl : : runTransaction ( TransactionSettings const & _t r)
void AssemblyDebuggerControl : : showDebugError ( QString const & _error )
{
callContract ( _tr , m_previousDebugResult . contractAddress ) ;
m_ctx - > displayMessageDialog ( QApplication : : tr ( " Debugger " ) , _error ) ;
}