Hello World! Revisiting the Ethereum Greeter tutorial for the summer of '17 by decentralised

View this thread on steempeak.com
· @decentralised · (edited)
Hello World! Revisiting the Ethereum Greeter tutorial for the summer of '17
<html>
<p>Hello World.</p>
<p>Such was the amazement with which I first saw an HTML page render in Internet Explorer, that I couldn't resist typing these exact same words on the first "web page" I built. Ethereum is what the Internet was back then because in both cases the possibilities are endless while, at the same time, even the smallest of challenges you overcome feels like a personal triumph of sorts.&nbsp;</p>
<p>The Greeter example is a good place to start if you are looking to get acquainted with Ethereum's cli tools and the engineering side of ÐApp development, but unfortunately no documentation can withstand the pace of development the Ethereum community offers so the tutorial in <a href="https://ethereum.org/greeter">ethereum.org</a> is in need of an update.</p>
<p>Getting down to business, this tutorial will assume that you are comfortable using the command line in both Linux and Geth or you can get up to speed quickly and, importantly, you have some Ether in your account. For clarity purposes, my development environment has the following setup:</p>
<p><code>solc Version: 0.4.11+commit.68ef5810.Linux.g++&nbsp;</code></p>
<p><code>geth Version: 1.6.7-stable-ab5646c5</code></p>
<p><code>evm Version: 1.6.7-stable-ab5646c5</code></p>
<p><code>Chain Version: Homestead&nbsp;</code></p>
<p><br></p>
<p>In your favourite text editor, create the file greeter.sol as such:</p>
<p><code>pragma solidity ^0.4.11;</code></p>
<p><code>contract Greeter {</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;/* Define variable owner of the type address */</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;address owner;</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;/* Define variable greeting of the type string */</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;string greeting;</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;/* A modifier acts as a filter on other functions */</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;modifier onlyOwner() {&nbsp;</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;require (owner == msg.sender);&nbsp;</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_;&nbsp;</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;}</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;/* Constructor sets the owner of the contract and stores a greeting string given on deployment*/</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;function Greeter(string _greeting) {&nbsp;</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;owner = msg.sender;&nbsp;</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;greeting = _greeting;</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;}</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;/* Main function */</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;function greet() constant returns (string) {&nbsp;</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return greeting;&nbsp;</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;}</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;/* This function allows the owner to set a new greeting string */</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;function setGreeting(string _greeting) {&nbsp;</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;greeting = _greeting;&nbsp;</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;}</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;/* This function destroys the contract instance and returns its funds to the owner. Notice how the modifier acts a sort of access control on this function */</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;function kill() onlyOwner {&nbsp;</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;selfdestruct(owner);&nbsp;</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;}</code></p>
<p><code>}</code></p>
<p>In this version of the greeter tutorial, we will be able to set a new greeting string after deployment and retain the ownership and mortality properties of the original tutorial. I trust the inline comments are helpful but comments and questions are welcomed!</p>
<p>Now we will need to compile the code and since Geth no longer supports compilation function we will use the solc &nbsp;compiler itself. In your favourite shell:</p>
<p><code>$ solc --bin --abi greeter.sol -o build</code></p>
<p><br></p>
<p>If successful, this command will create both the binary and the &nbsp;application binary interface (ABI) for the greeter contract and output it to a `build` directory.&nbsp;</p>
<p>Confirm you have both ./build/greeter.abi and ./build/greeter.bin files.&nbsp;</p>
<p><code>cat ./build/greeter.abi&nbsp;</code></p>
<p><code>[{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_greeting","type":"string"}],"name":"setGreeting","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"greet","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"inputs":[{"name":"_greeting","type":"string"}],"payable":false,"type":"constructor"}]</code></p>
<p>And...</p>
<p><code>$ cat ./build/creeter.bin&nbsp;</code></p>
<p><code>0x6060604052341561000c57fe5b6040516104d63803806104d6833981016040528080518201919050505b33600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060019080519060200190610080929190610088565b505b5061012d565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100c957805160ff19168380011785556100f7565b828001600101855582156100f7579182015b828111156100f65782518255916020019190600101906100db565b5b5090506101049190610108565b5090565b61012a91905b8082111561012657600081600090555060010161010e565b5090565b90565b61039a8061013c6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806341c0e1b514610051578063a413686214610063578063cfae3217146100bd575bfe5b341561005957fe5b610061610156565b005b341561006b57fe5b6100bb600480803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919050506101f1565b005b34156100c557fe5b6100cd61020c565b604051808060200182810382528381815181526020019150805190602001908083836000831461011c575b80518252602083111561011c576020820191506020810190506020830392506100f8565b505050905090810190601f1680156101485780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3373ffffffffffffffffffffffffffffffffffffffff16600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415156101b35760006000fd5b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b5b565b80600190805190602001906102079291906102b5565b505b50565b610214610335565b60018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102aa5780601f1061027f576101008083540402835291602001916102aa565b820191906000526020600020905b81548152906001019060200180831161028d57829003601f168201915b505050505090505b90565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106102f657805160ff1916838001178555610324565b82800160010185558215610324579182015b82811115610323578251825591602001919060010190610308565b5b5090506103319190610349565b5090565b602060405190810160405280600081525090565b61036b91905b8082111561036757600081600090555060010161034f565b5090565b905600a165627a7a7230582058af898b41d2be593e37def436ccefea8f348476d6f32c1afc1c0d3a3aa1beb50029</code></p>
<p><br></p>
<p>Now, we'll create a deployment script. Using your editor, create a file deployGreeter.js as such:</p>
<p><code>var _greeting = "Hello World";</code></p>
<p><code>var greeterContract = web3.eth.contract(...contents of your Greeter.abi as a single line of text... use mine above if needed...);</code></p>
<p><code>var greeter = greeterContract.new(</code></p>
<p><code>&nbsp;&nbsp;&nbsp;_greeting,</code></p>
<p><code>&nbsp;&nbsp;&nbsp;{</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from: web3.eth.accounts[0],&nbsp;</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data: '...contents of your Greeter.bin as a single line of text... use mine above if needed...',&nbsp;</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gas: '4700000'</code></p>
<p><code>&nbsp;&nbsp;&nbsp;}, function (e, contract){</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;console.log(e, contract);</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;if (typeof contract.address !== 'undefined') {</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);</code></p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;}</code></p>
<p><code>&nbsp;})</code></p>
<p><br></p>
<p>Now attach a geth console to your favourite TESTNET and type the following:</p>
<p><code>&gt; personal.unlockAccount(eth.accounts[0])</code></p>
<p><code>&gt; loadScript("deployGreeter.js")</code></p>
<p><br></p>
<p>Once the contract has been mined, you will receive a message in your Geth console <em>similar</em> to:</p>
<p><code>Contract mined! address: 0x5e0271f2e17730b7719fa570dc5fc13bfa3a6183 transactionHash: 0x249fac28de5d0a2f155f6f4f76c2fd835d599b9261fd3dfb44648853b6e8cb38</code></p>
<p><br></p>
<p>Now we can interact with our Greeter bot. The greet() function is a "read only" command since we've specified it as <code>constant</code> in our greeter.sol, so it should return "Hello World" pretty quickly as it doesn't require code to propagate through the network channel at all.</p>
<p><code>&gt; greeter.greet()</code></p>
<p><br></p>
<p>We can also change the greeting message at will. Actually anyone can, as long as they know your contract address and have the respective ABI. In your geth type:</p>
<p><code>&gt; greeter.setGreeting("Hello Steemit!", {from:eth.accounts[0]})</code></p>
<p><br></p>
<p>This last function effectively changes the state of your contract and as such it will be propagated through all of the network.</p>
<p>&nbsp;If you are on a TESTNET with multiple nodes it may take a few seconds to execute but you will receive a transaction hash like <code>"0x4171738b04b4eb25ad08b22fba46d728d6ec09669ddc823bd8be48e63a303ee2"</code> that you can use to look at the transaction itself while you wait. In geth:</p>
<p><code>&gt;eth.getTransaction("...your own transaction hash...")</code></p>
<p><code>{</code></p>
<p><code>&nbsp;&nbsp;blockHash: "0x0a9a2a0371bd28de1537f9b61de18605291602d43c48bd78dd9a78a9bedae2cb",</code></p>
<p><code>&nbsp;&nbsp;blockNumber: 352,</code></p>
<p><code>&nbsp;&nbsp;from: "...your eth.accounts[0]...",</code></p>
<p><code>&nbsp;&nbsp;gas: 90000,</code></p>
<p><code>&nbsp;&nbsp;gasPrice: 100000000000,</code></p>
<p><code>&nbsp;&nbsp;hash: "0x4171738b04b4eb25ad08b22fba46d728d6ec09669ddc823bd8be48e63a303ee2",</code></p>
<p><code>&nbsp;&nbsp;input: "0xa41368620000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000e48656c6c6f20537465656d697421000000000000000000000000000000000000",</code></p>
<p><code>&nbsp;&nbsp;nonce: 267,</code></p>
<p><code>&nbsp;&nbsp;r: "0x85f767dbc2fa6e4dbc3f956787165005d7fb520c2ac0bc18da4a6c562e7408be",</code></p>
<p><code>&nbsp;&nbsp;s: "0x4216604b5772f7193d10bf4c24878563eca34179fcaefa25ce07ed662c7860ac",</code></p>
<p><code>&nbsp;&nbsp;to: "...your Greeter contract address...",</code></p>
<p><code>&nbsp;&nbsp;transactionIndex: 0,</code></p>
<p><code>&nbsp;&nbsp;v: "0x78",</code></p>
<p><code>&nbsp;&nbsp;value: 0</code></p>
<p><code>}</code></p>
<p><br></p>
<p>Notice the input value for now: <code>0xa41368620....0e48656c6c6f20537465656d6974210</code>. I'll cover the function signature in another tutorial, but for the fun of it, type in geth:&nbsp;</p>
<p><code>&gt; web3.toAscii("0e48656c6c6f20537465656d697421")</code></p>
<p><code>"\x0eHello Steemit!"</code></p>
<p><br></p>
<p>Finally, our <code>setGreeting</code> transaction must be finished by now, let's check if that is the case by looking for the transaction receipt. In geth:</p>
<p><code>&gt; eth.getTransactionReceipt("...your own transaction hash...")</code></p>
<p><code>{</code></p>
<p><code>&nbsp;&nbsp;blockHash: "0x0a9a2a0371bd28de1537f9b61de18605291602d43c48bd78dd9a78a9bedae2cb",</code></p>
<p><code>&nbsp;&nbsp;blockNumber: 352,</code></p>
<p><code>&nbsp;&nbsp;contractAddress: null,</code></p>
<p><code>&nbsp;&nbsp;cumulativeGasUsed: 33610,</code></p>
<p><code>&nbsp;&nbsp;from: "...your eth.accounts[0]...",</code></p>
<p><code>&nbsp;&nbsp;gasUsed: 33610,</code></p>
<p><code>&nbsp;&nbsp;logs: [],</code></p>
<p><code>&nbsp;&nbsp;logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",</code></p>
<p><code>&nbsp;&nbsp;root: "0xfdce1da8e1f91e24b2b4d3ac7479817ebf9e3f6b11279c21043347d780477247",</code></p>
<p><code>&nbsp;&nbsp;to: "...your Greeter contract address...",</code></p>
<p><code>&nbsp;&nbsp;transactionHash: "...your own transaction hash...",</code></p>
<p><code>&nbsp;&nbsp;transactionIndex: 0</code></p>
<p><code>}</code></p>
<p><br></p>
<p>Repeatedly calling <code>greeter.greet()</code> until the new greeting string is returned also works... of course.&nbsp;</p>
<p>Now let's have a look at the Greeter contract storage to make sure our greeting has been etched in <del>stone</del> &nbsp;<del>blockchain </del>ethereum storage. In geth:</p>
<p><code>&gt; var Address = greeter.address</code></p>
<p><code>&gt; eth.getStorageAt(Address, 0)</code></p>
<p><code>&nbsp;"0x000000000000000000000000...your eth.accounts[0]..."</code></p>
<p><code>&gt; eth.getStorageAt(Address, 1)</code></p>
<p><code>"0x48656c6c6f20537465656d69742100000000000000000000000000000000001c"</code></p>
<p><code>&gt; web3.toAscii("0x48656c6c6f20537465656d69742100000000000000000000000000000000001c")</code></p>
<p><code>"Hello Steemit!\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c"</code></p>
<p><br></p>
<p>How about that? Your own personal Greeter bot is now unstoppable!</p>
</html>
👍  
properties (23)
post_id7,463,107
authordecentralised
permlinkhello-world-revisiting-the-ethereum-greeter-tutorial-for-the-summer-of-17
categoryethereum
json_metadata"{"app": "steemit/0.1", "format": "html", "links": ["https://ethereum.org/greeter"], "tags": ["ethereum", "solidity", "cli", "greeter", "tutorial"]}"
created2017-07-17 17:30:33
last_update2017-07-17 18:34:24
depth0
children2
net_rshares943,729,241
last_payout2017-07-24 17:30:33
cashout_time1969-12-31 23:59:59
total_payout_value0.000 SBD
curator_payout_value0.000 SBD
pending_payout_value0.000 SBD
promoted0.000 SBD
body_length14,560
author_reputation0
root_title"Hello World! Revisiting the Ethereum Greeter tutorial for the summer of '17"
beneficiaries[]
max_accepted_payout1,000,000.000 SBD
percent_steem_dollars10,000
author_curate_reward""
vote details (1)
@nocabuchsga ·
properties (23)
post_id9,606,079
authornocabuchsga
permlinkre-decentralised-hello-world-revisiting-the-ethereum-greeter-tutorial-for-the-summer-of-17-20170808t204759130z
categoryethereum
json_metadata"{"app": "steemit/0.1", "tags": ["ethereum"]}"
created2017-08-08 20:47:30
last_update2017-08-08 20:47:30
depth1
children0
net_rshares-16,120,093,399
last_payout2017-08-15 20:47:30
cashout_time1969-12-31 23:59:59
total_payout_value0.000 SBD
curator_payout_value0.000 SBD
pending_payout_value0.000 SBD
promoted0.000 SBD
body_length12
author_reputation1,036,467,182
root_title"Hello World! Revisiting the Ethereum Greeter tutorial for the summer of '17"
beneficiaries[]
max_accepted_payout1,000,000.000 SBD
percent_steem_dollars10,000
author_curate_reward""
vote details (25)
@steemitboard ·
Congratulations @decentralised! You received a personal award!

<table><tr><td>https://steemitimages.com/70x70/http://steemitboard.com/@decentralised/birthday2.png</td><td>Happy Birthday! - You are on the Steem blockchain for 2 years!</td></tr></table>

<sub>_You can view [your badges on your Steem Board](https://steemitboard.com/@decentralised) and compare to others on the [Steem Ranking](https://steemitboard.com/ranking/index.php?name=decentralised)_</sub>


###### [Vote for @Steemitboard as a witness](https://v2.steemconnect.com/sign/account-witness-vote?witness=steemitboard&approve=1) to get one more award and increased upvotes!
properties (22)
post_id78,033,885
authorsteemitboard
permlinksteemitboard-notify-decentralised-20190717t093045000z
categoryethereum
json_metadata{"image":["https:\/\/steemitboard.com\/img\/notify.png"]}
created2019-07-17 09:30:45
last_update2019-07-17 09:30:45
depth1
children0
net_rshares0
last_payout2019-07-24 09:30:45
cashout_time1969-12-31 23:59:59
total_payout_value0.000 SBD
curator_payout_value0.000 SBD
pending_payout_value0.000 SBD
promoted0.000 SBD
body_length640
author_reputation38,705,954,145,809
root_title"Hello World! Revisiting the Ethereum Greeter tutorial for the summer of '17"
beneficiaries[]
max_accepted_payout1,000,000.000 SBD
percent_steem_dollars10,000