remix-project mirror
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
remix-project/docs/tutorial_mist.rst

287 lines
10 KiB

8 years ago
Debugging a Dapp using Remix - Mist - Geth
===================================================
.. _tutorial-mist-geth:
8 years ago
The ultimate goal of this tutorial is to debug transactions that have been created by a dapp front end.
8 years ago
8 years ago
It is easy in Remix to debug a transaction created from its own GUI. Setting up an environment that allows to
8 years ago
debug transactions created outside of Remix require a bit more of complexity.
We will need four tools for that :
8 years ago
- Geth - this is the center piece and provides the blockchain environment. We will basically run geth in a `dev` mode.
8 years ago
- Mist - this is the Ethereum dapp browser. We will use it to browse our front end.
8 years ago
- Remix - this is the Ethereum IDE. We will use it to develop our Solidity contract.
8 years ago
- Any code editor you want - in order to write your front end :)
Install the environment
-----------------------
Install Mist
~~~~~~~~~~~~
Mist is the Ethereum browser and the entry point of a Dapp.
8 years ago
Please download `the latest version <http://github.com/ethereum/mist/releases>`_ (at least 0.8.9).
8 years ago
Basically we will always run our front end in Mist (note that it is also possible to use `Metamask <http://metamask.io>`_).
Install Geth
~~~~~~~~~~~~
`Geth <http://github.com/ethereum/go-ethereum/releases>`_ is the official Ethereum client.
Running the environment
-----------------------
Run Geth
~~~~~~~~
We will run a test node. This node will have a new empty state and will not be synced to the main or ropsten network.
::
geth --ipcpath <test-chain-directory>/geth.ipc --datadir <test-chain-directory> --dev console
``<test-chain-directory>`` is the folder where keys and chain data will be stored.
8 years ago
``--ipcpath`` defines the end point that other apps (like Mist) use to talk to geth.
8 years ago
8 years ago
``--datadir`` specifies the data directory.
8 years ago
8 years ago
``--dev`` sets the node into private chain mode and adds some debugging flags.
8 years ago
Then we need to create accounts and mine a bit to generate some Ether:
::
// from the geth console :
personal.newAccount() // You can execute this command several time if you need more than one account.
miner.start() // generate some Ether.
miner.stop() // stop mining after 30s-60s - we could also keep mining.
Next time we run Geth, we will only need to mine transactions (no need to recreate account).
Run Mist
~~~~~~~~
8 years ago
If we run Mist without any argument, its internal Geth node will run. As we have our own we need to specify the ipc path of the node installed above.
8 years ago
::
mist --rpc <test-chain-directory>/geth.ipc
(yes the option is --rpc)
Once Mist is started, Verify that it is connected to the test node (that's important !!).
On the bottom left check that the network is ``Private-net`` and that the block number is the same as reported by the test node we are currently running. Run the following command in the Geth Console to check: `web3.eth.blockNumber`.
8 years ago
8 years ago
.. image:: mist1.png
8 years ago
Clicking on `Wallet` will allow you to send transactions and check account balances (if you are currently mining you should see the balance increasing).
8 years ago
Starting Remix
~~~~~~~~~~~~~~
In Mist click on ``Develop`` / ``Open Remix IDE``
8 years ago
Remix will open in a new window. If this is the first time it is run, the ``Ballot`` contract is loaded.
8 years ago
8 years ago
Now, we need to check if Remix is connected to Mist:
8 years ago
Right panel / third tab from the left, ``Injected Provider`` should be checked.
8 years ago
.. image:: remix4.png
8 years ago
Right panel / second tab from the left, ``Transaction Origin`` should contain accounts we have previously created in Geth.
8 years ago
.. image:: remix5.png
Developing contract / front end
--------------------------------
8 years ago
Donation contract - Dapp Back end
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 years ago
Here is a sample solidity contract.
Copy and paste the following inside remix:
.. code-block:: none
8 years ago
contract Donation {
8 years ago
address owner;
event fundMoved(address _to, uint _amount);
modifier onlyowner { if (msg.sender == owner) _; }
address[] _giver;
uint[] _values;
8 years ago
function Donation() {
8 years ago
owner = msg.sender;
}
8 years ago
function donate() payable {
8 years ago
addGiver(msg.value);
}
function moveFund(address _to, uint _amount) onlyowner {
uint balance = this.balance;
uint amount = _amount;
if (_amount <= this.balance) {
if (_to.send(this.balance)) {
fundMoved(_to, _amount);
} else {
throw;
}
} else {
throw;
}
}
function addGiver(uint _amount) internal {
8 years ago
_giver.push(msg.sender);
_values.push(_amount);
8 years ago
}
}
Dapp Front end
~~~~~~~~~~~~~~
8 years ago
and here is the front end:
.. code-block:: none
<div>
<div>Donation Contract</div>
<br/>
<input id='contractaddress' placeholder='contract address'></intput>
<br/>
<div>
<br/>
8 years ago
<input id='fromGive' placeholder='from' ></intput><input placeholder='amount' id='valueGive'></intput><button id="fallbackbtn" onclick="donate()">give</button>
8 years ago
<br/>
<br/>
<input id='fromMoveFund' placeholder='from' ></intput><input id='moveFundTo' placeholder='move to' ></intput><input id='amountToMove' placeholder='amount' ></intput><button id="movefundbtn" onclick="movefund()">moveFund</button>
<br/>
<br/>
<div id='wait' ></div>
</div>
<br/>
<br/>
<div id='log'>
</div>
</div>
<script type="text/javascript">
8 years ago
function donate () {
var donation = contractspec.at(document.getElementById('contractaddress').value)
donation.donate({
8 years ago
from: document.getElementById('fromGive').value,
value: document.getElementById('valueGive').value
}, function (error, txHash) {
tryTillResponse(txHash, function (error, receipt) {
alert('done ' + txHash)
})
})
}
function movefund () {
var donation = contractspec.at(document.getElementById('contractaddress').value)
donation.moveFund(
document.getElementById('moveFundTo').value,
document.getElementById('amountToMove').value,
function (error, txHash) {
tryTillResponse(txHash, function (error, receipt) {
alert('done ' + txHash)
})
})
}
8 years ago
var contractspec = web3.eth.contract([{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"moveFund","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"donate","outputs":[],"payable":true,"type":"function"},{"inputs":[],"payable":false,"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_to","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"}],"name":"fundMoved","type":"event"}]);
8 years ago
function tryTillResponse (txhash, done) {
8 years ago
document.getElementById('wait').innerHTML = 'waiting for the transaction to be mined ...'
web3.eth.getTransactionReceipt(txhash, function (err, result) {
if (!err && !result) {
// Try again with a bit of delay
setTimeout(function () { tryTillResponse(txhash, done) }, 500)
} else {
document.getElementById('wait').innerHTML = ''
var log = document.createElement("div")
log.innerHTML = JSON.stringify(result)
document.getElementById('log').appendChild(log)
done(err,result)
}
})
8 years ago
}
</script>
I would suggest to serve this file using ``http-serve``, but you can use any web server you like.
Important notice !
The variable ``contractspec`` contains the abi of the ``donation`` contract. it means that if you change something in the contract interface (function names, parameters, ...)
you need to copy the new abi from remix to the front end.
Deploying
---------
Right panel / Red button ``Create``
8 years ago
8 years ago
.. image:: remix1.png
8 years ago
This create a new transaction that deploy the ``Donation`` contract (Mist will ask for the usual pasphrase check).
Wait for the transaction to be mined (don't forget to activate mining ``miner.start()``).
8 years ago
Once this is done, you can use it by executing the ``moveFund`` and ``donate`` function. But this is not what we
8 years ago
want to achieve. We want to run and debug those functions from the front end.
Remix also display the address of the contract. Save it, we'll need this address later.
8 years ago
.. image:: remix2.png
8 years ago
Debugging
---------
From Mist, browse the above front end.
In the first field, paste the address of the newly created contract, and let's call the first function (label ``give``).
You will need an account and a value.
The account could be any account that are declared in the Wallet section of Mist. This is the sender of the transaction we are going to create.
The value should be no more than the actual balance of the account - the unit is in `wei`, so just put ``100`` (100 wei), that should be fine.
Click on ``Give`` and wait for the transaction to be mined.
The HTML block with id ``log`` is filled by all the transactions created from the front end.
8 years ago
It was easier for the purpose of this tutorial to just log transactions in a div but you can have your own logging mechanism.
There is only one field that we need, this is the ``transactionHash``.
8 years ago
8 years ago
Copy it and switch to Remix. On the right half, the fifth panel shows a small "bug" icon, that is the debugger.
8 years ago
8 years ago
Paste the hash into the transaction field and click on the ``play`` button.
8 years ago
8 years ago
.. image:: remix3.png
8 years ago
You are now entering a debug session for the call to ``donate``.
8 years ago
8 years ago
Debugging in Remix is not much easier than with common tools like gdb because you can freely move in time.
Use the slider to change the current step and click on the panels below to expand them and explore the curret state, local variables, etc.
There are also breakpoints to move between sections of the code quickly, but more on all that later.
8 years ago
8 years ago
8 years ago
At the time of writing there is an issue that could break the contract creation.
There is a workaround for that at https://github.com/ethereum/go-ethereum/issues/3653 .
Please follow the workaround or wait for this issue to be closed.
8 years ago
8 years ago
Also, though retrieving a contract's storage when Remix is using the JavaScript VM is working well,
there is still work to be done when Remix is using eth or geth as backend.