Ecoer Logo
VOTING POWER100.00%
DOWNVOTE POWER100.00%
RESOURCE CREDITS100.00%
REPUTATION PROGRESS85.94%
Net Worth
0.976USD
STEEM
0.032STEEM
SBD
0.062SBD
Own SP
17.469SP

Detailed Balance

STEEM
balance
0.032STEEM
market_balance
0.000STEEM
savings_balance
0.000STEEM
reward_steem_balance
0.000STEEM
STEEM POWER
Own SP
17.469SP
Delegated Out
0.000SP
Delegation In
0.000SP
Effective Power
17.469SP
Reward SP (pending)
0.000SP
SBD
sbd_balance
0.062SBD
sbd_conversions
0.000SBD
sbd_market_balance
0.000SBD
savings_sbd_balance
0.000SBD
reward_sbd_balance
0.000SBD
{
  "balance": "0.032 STEEM",
  "savings_balance": "0.000 STEEM",
  "reward_steem_balance": "0.000 STEEM",
  "vesting_shares": "28446.038766 VESTS",
  "delegated_vesting_shares": "0.000000 VESTS",
  "received_vesting_shares": "0.000000 VESTS",
  "sbd_balance": "0.062 SBD",
  "savings_sbd_balance": "0.000 SBD",
  "reward_sbd_balance": "0.000 SBD",
  "conversions": []
}

Account Info

namechrisdotn
id99004
rank86,010
reputation16091528483
created2016-09-29T12:03:03
recovery_accountanonsteem
proxyNone
post_count4
comment_count0
lifetime_vote_count0
witnesses_voted_for0
last_post2017-10-31T15:09:36
last_root_post2017-10-31T15:09:36
last_vote_time2016-09-29T12:14:21
proxied_vsf_votes0, 0, 0, 0
can_vote1
voting_power9,950
delayed_votes0
balance0.032 STEEM
savings_balance0.000 STEEM
sbd_balance0.062 SBD
savings_sbd_balance0.000 SBD
vesting_shares28446.038766 VESTS
delegated_vesting_shares0.000000 VESTS
received_vesting_shares0.000000 VESTS
reward_vesting_balance0.000000 VESTS
vesting_balance0.000 STEEM
vesting_withdraw_rate0.000000 VESTS
next_vesting_withdrawal1969-12-31T23:59:59
withdrawn0
to_withdraw0
withdraw_routes0
savings_withdraw_requests0
last_account_recovery1970-01-01T00:00:00
reset_accountnull
last_owner_update2016-09-29T12:10:27
last_account_update2017-10-31T15:15:00
minedNo
sbd_seconds0
sbd_last_interest_payment1970-01-01T00:00:00
savings_sbd_last_interest_payment1970-01-01T00:00:00
{
  "active": {
    "account_auths": [],
    "key_auths": [
      [
        "STM5wrUbfcisGneZWNFjcHtF5pZup1GQ33yFhQdS9D8RMJ5yxEjMr",
        1
      ]
    ],
    "weight_threshold": 1
  },
  "balance": "0.032 STEEM",
  "can_vote": true,
  "comment_count": 0,
  "created": "2016-09-29T12:03:03",
  "curation_rewards": 0,
  "delegated_vesting_shares": "0.000000 VESTS",
  "downvote_manabar": {
    "current_mana": 0,
    "last_update_time": 1475150583
  },
  "guest_bloggers": [],
  "id": 99004,
  "json_metadata": "{\"profile\":{\"profile_image\":\"https://www.maibornwolff.de/sites/default/files/styles/team_grid/public/images/team/christophnk.jpg\"}}",
  "last_account_recovery": "1970-01-01T00:00:00",
  "last_account_update": "2017-10-31T15:15:00",
  "last_owner_update": "2016-09-29T12:10:27",
  "last_post": "2017-10-31T15:09:36",
  "last_root_post": "2017-10-31T15:09:36",
  "last_vote_time": "2016-09-29T12:14:21",
  "lifetime_vote_count": 0,
  "market_history": [],
  "memo_key": "STM71cR3DpoopFQLnQJGvHZviZbDSWL5oTXLzFFxXqeJG8ykyU5fY",
  "mined": false,
  "name": "chrisdotn",
  "next_vesting_withdrawal": "1969-12-31T23:59:59",
  "other_history": [],
  "owner": {
    "account_auths": [],
    "key_auths": [
      [
        "STM5FoVHxANi1mGRYPPB9QQUgQxKntRJHSVhc4pGkmrKMW4iY2Kzv",
        1
      ]
    ],
    "weight_threshold": 1
  },
  "pending_claimed_accounts": 0,
  "post_bandwidth": 10000,
  "post_count": 4,
  "post_history": [],
  "posting": {
    "account_auths": [],
    "key_auths": [
      [
        "STM7bDiV6Gc735HVppr3JasRX7mKxfqi9YCFdq5zMZySTtQyEVero",
        1
      ]
    ],
    "weight_threshold": 1
  },
  "posting_json_metadata": "{\"profile\":{\"profile_image\":\"https://www.maibornwolff.de/sites/default/files/styles/team_grid/public/images/team/christophnk.jpg\"}}",
  "posting_rewards": 317,
  "proxied_vsf_votes": [
    0,
    0,
    0,
    0
  ],
  "proxy": "",
  "received_vesting_shares": "0.000000 VESTS",
  "recovery_account": "anonsteem",
  "reputation": "16091528483",
  "reset_account": "null",
  "reward_sbd_balance": "0.000 SBD",
  "reward_steem_balance": "0.000 STEEM",
  "reward_vesting_balance": "0.000000 VESTS",
  "reward_vesting_steem": "0.000 STEEM",
  "savings_balance": "0.000 STEEM",
  "savings_sbd_balance": "0.000 SBD",
  "savings_sbd_last_interest_payment": "1970-01-01T00:00:00",
  "savings_sbd_seconds": "0",
  "savings_sbd_seconds_last_update": "1970-01-01T00:00:00",
  "savings_withdraw_requests": 0,
  "sbd_balance": "0.062 SBD",
  "sbd_last_interest_payment": "1970-01-01T00:00:00",
  "sbd_seconds": "0",
  "sbd_seconds_last_update": "2016-09-30T12:46:30",
  "tags_usage": [],
  "to_withdraw": 0,
  "transfer_history": [],
  "vesting_balance": "0.000 STEEM",
  "vesting_shares": "28446.038766 VESTS",
  "vesting_withdraw_rate": "0.000000 VESTS",
  "vote_history": [],
  "voting_manabar": {
    "current_mana": 9950,
    "last_update_time": 1475151261
  },
  "voting_power": 9950,
  "withdraw_routes": 0,
  "withdrawn": 0,
  "witness_votes": [],
  "witnesses_voted_for": 0,
  "rank": 86010
}

Withdraw Routes

IncomingOutgoing
Empty
Empty
{
  "incoming": [],
  "outgoing": []
}
From Date
To Date
2019/09/29 13:48:54
authorsteemitboard
bodyCongratulations @chrisdotn! You received a personal award! <table><tr><td>https://steemitimages.com/70x70/http://steemitboard.com/@chrisdotn/birthday3.png</td><td>Happy Birthday! - You are on the Steem blockchain for 3 years!</td></tr></table> <sub>_You can view [your badges on your Steem Board](https://steemitboard.com/@chrisdotn) and compare to others on the [Steem Ranking](https://steemitboard.com/ranking/index.php?name=chrisdotn)_</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!
json metadata{"image":["https://steemitboard.com/img/notify.png"]}
parent authorchrisdotn
parent permlinkhow-does-the-blockchain-know-a-football-match-s-result
permlinksteemitboard-notify-chrisdotn-20190929t134853000z
title
Transaction InfoBlock #36846870/Trx 5f7e58b4bf0d13681d56c7032d3e7cebefe2f1d7
View Raw JSON Data
{
  "block": 36846870,
  "op": [
    "comment",
    {
      "author": "steemitboard",
      "body": "Congratulations @chrisdotn! You received a personal award!\n\n<table><tr><td>https://steemitimages.com/70x70/http://steemitboard.com/@chrisdotn/birthday3.png</td><td>Happy Birthday! - You are on the Steem blockchain for 3 years!</td></tr></table>\n\n<sub>_You can view [your badges on your Steem Board](https://steemitboard.com/@chrisdotn) and compare to others on the [Steem Ranking](https://steemitboard.com/ranking/index.php?name=chrisdotn)_</sub>\n\n\n###### [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!",
      "json_metadata": "{\"image\":[\"https://steemitboard.com/img/notify.png\"]}",
      "parent_author": "chrisdotn",
      "parent_permlink": "how-does-the-blockchain-know-a-football-match-s-result",
      "permlink": "steemitboard-notify-chrisdotn-20190929t134853000z",
      "title": ""
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2019-09-29T13:48:54",
  "trx_id": "5f7e58b4bf0d13681d56c7032d3e7cebefe2f1d7",
  "trx_in_block": 6,
  "virtual_op": 0
}
2018/10/05 00:30:09
authorchrisdotn
permlinka-json-parser-for-solidity
voterjza
weight10000 (100.00%)
Transaction InfoBlock #26527005/Trx 425f494a78ce73bcaa43daeb69f4cec8db4a3ec5
View Raw JSON Data
{
  "block": 26527005,
  "op": [
    "vote",
    {
      "author": "chrisdotn",
      "permlink": "a-json-parser-for-solidity",
      "voter": "jza",
      "weight": 10000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-10-05T00:30:09",
  "trx_id": "425f494a78ce73bcaa43daeb69f4cec8db4a3ec5",
  "trx_in_block": 17,
  "virtual_op": 0
}
2018/09/29 13:12:18
authorsteemitboard
bodyCongratulations @chrisdotn! You have received a personal award! [![](https://steemitimages.com/70x70/http://steemitboard.com/@chrisdotn/birthday2.png)](http://steemitboard.com/@chrisdotn) 2 Years on Steemit <sub>_Click on the badge to view your Board of Honor._</sub> **Do not miss the last post from @steemitboard:** <table><tr><td><a href="https://steemit.com/steemitboard/@steemitboard/steemitboard-knock-out-by-hardfork"><img src="https://steemitimages.com/64x128/https://cdn.steemitimages.com/DQmSPagmBYytsJBn8FwewvqDFRphP6swbbndADgYEsaLNkZ/image.png"></a></td><td><a href="https://steemit.com/steemitboard/@steemitboard/steemitboard-knock-out-by-hardfork">SteemitBoard knock out by hardfork</a></td></tr></table> > Support [SteemitBoard's project](https://steemit.com/@steemitboard)! **[Vote for its witness](https://v2.steemconnect.com/sign/account-witness-vote?witness=steemitboard&approve=1)** and **get one more award**!
json metadata{"image":["https://steemitboard.com/img/notify.png"]}
parent authorchrisdotn
parent permlinkhow-does-the-blockchain-know-a-football-match-s-result
permlinksteemitboard-notify-chrisdotn-20180929t131217000z
title
Transaction InfoBlock #26369543/Trx 9a2dd3b9cc63ed265c76aaff52a73c2f850716c5
View Raw JSON Data
{
  "block": 26369543,
  "op": [
    "comment",
    {
      "author": "steemitboard",
      "body": "Congratulations @chrisdotn! You have received a personal award!\n\n[![](https://steemitimages.com/70x70/http://steemitboard.com/@chrisdotn/birthday2.png)](http://steemitboard.com/@chrisdotn)  2 Years on Steemit\n<sub>_Click on the badge to view your Board of Honor._</sub>\n\n\n**Do not miss the last post from @steemitboard:**\n<table><tr><td><a href=\"https://steemit.com/steemitboard/@steemitboard/steemitboard-knock-out-by-hardfork\"><img src=\"https://steemitimages.com/64x128/https://cdn.steemitimages.com/DQmSPagmBYytsJBn8FwewvqDFRphP6swbbndADgYEsaLNkZ/image.png\"></a></td><td><a href=\"https://steemit.com/steemitboard/@steemitboard/steemitboard-knock-out-by-hardfork\">SteemitBoard knock out by hardfork</a></td></tr></table>\n\n> Support [SteemitBoard's project](https://steemit.com/@steemitboard)! **[Vote for its witness](https://v2.steemconnect.com/sign/account-witness-vote?witness=steemitboard&approve=1)** and **get one more award**!",
      "json_metadata": "{\"image\":[\"https://steemitboard.com/img/notify.png\"]}",
      "parent_author": "chrisdotn",
      "parent_permlink": "how-does-the-blockchain-know-a-football-match-s-result",
      "permlink": "steemitboard-notify-chrisdotn-20180929t131217000z",
      "title": ""
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-09-29T13:12:18",
  "trx_id": "9a2dd3b9cc63ed265c76aaff52a73c2f850716c5",
  "trx_in_block": 0,
  "virtual_op": 0
}
2018/05/26 17:54:48
authorchrisdotn
permlinka-json-parser-for-solidity
voterpynchon
weight10000 (100.00%)
Transaction InfoBlock #22774575/Trx 9d4ae6847b2ae1845924f8371ad60a5852ac12a0
View Raw JSON Data
{
  "block": 22774575,
  "op": [
    "vote",
    {
      "author": "chrisdotn",
      "permlink": "a-json-parser-for-solidity",
      "voter": "pynchon",
      "weight": 10000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-05-26T17:54:48",
  "trx_id": "9d4ae6847b2ae1845924f8371ad60a5852ac12a0",
  "trx_in_block": 33,
  "virtual_op": 0
}
2018/03/29 11:36:27
authorchrisdotn
permlinka-json-parser-for-solidity
voterberkes
weight10000 (100.00%)
Transaction InfoBlock #21097926/Trx 6f2fd1e1816624c2673e8aecb259522dccc6b13d
View Raw JSON Data
{
  "block": 21097926,
  "op": [
    "vote",
    {
      "author": "chrisdotn",
      "permlink": "a-json-parser-for-solidity",
      "voter": "berkes",
      "weight": 10000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-03-29T11:36:27",
  "trx_id": "6f2fd1e1816624c2673e8aecb259522dccc6b13d",
  "trx_in_block": 35,
  "virtual_op": 0
}
2018/03/11 14:00:18
authorchrisdotn
permlinka-json-parser-for-solidity
voterkav
weight10000 (100.00%)
Transaction InfoBlock #20583493/Trx 5f25fceeafcf43b6caf1f1dc3b0d6ee43459b590
View Raw JSON Data
{
  "block": 20583493,
  "op": [
    "vote",
    {
      "author": "chrisdotn",
      "permlink": "a-json-parser-for-solidity",
      "voter": "kav",
      "weight": 10000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-03-11T14:00:18",
  "trx_id": "5f25fceeafcf43b6caf1f1dc3b0d6ee43459b590",
  "trx_in_block": 16,
  "virtual_op": 0
}
2018/03/11 14:00:12
authorchrisdotn
permlinka-json-parser-for-solidity
voterkav
weight10000 (100.00%)
Transaction InfoBlock #20583491/Trx 3a23b730ed55cbcb9ae6d4f458e34fd5b144d797
View Raw JSON Data
{
  "block": 20583491,
  "op": [
    "vote",
    {
      "author": "chrisdotn",
      "permlink": "a-json-parser-for-solidity",
      "voter": "kav",
      "weight": 10000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-03-11T14:00:12",
  "trx_id": "3a23b730ed55cbcb9ae6d4f458e34fd5b144d797",
  "trx_in_block": 24,
  "virtual_op": 0
}
2017/10/31 15:40:00
authorchrisdotn
permlinkhow-does-the-blockchain-know-a-football-match-s-result
voterokae
weight700 (7.00%)
Transaction InfoBlock #16815554/Trx 8f0068f3520812fa51cc045e69a292c9e10ef664
View Raw JSON Data
{
  "block": 16815554,
  "op": [
    "vote",
    {
      "author": "chrisdotn",
      "permlink": "how-does-the-blockchain-know-a-football-match-s-result",
      "voter": "okae",
      "weight": 700
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2017-10-31T15:40:00",
  "trx_id": "8f0068f3520812fa51cc045e69a292c9e10ef664",
  "trx_in_block": 49,
  "virtual_op": 0
}
2017/10/31 15:30:30
authorchrisdotn
body@@ -1,8 +1,177 @@ +!%5BCiro Immobile by Dirk Vorderstra%C3%9Fe CC BY 3.0%5D(https://upload.wikimedia.org/wikipedia/commons/thumb/9/90/Ciro-immobile-bvb-2014.jpg/1200px-Ciro-immobile-bvb-2014.jpg)%0A%0A **The Et
json metadata{"tags":["ethereum","cryptocurrency","oracle","development","blockchain"],"links":["http://solidity.readthedocs.io/en/develop/","http://www.oraclize.it/","http://api.football-data.org/index","https://github.com/chrisdotn/footballBet","http://jsonpath.com/","https://medium.com/@chrisdotn/a-json-parser-for-solidity-9cc73b4b42","https://tlsnotary.org","https://bitcointalk.org/index.php?topic=301538.0","https://www.realitykeys.com"],"app":"steemit/0.1","format":"markdown","image":["https://upload.wikimedia.org/wikipedia/commons/thumb/9/90/Ciro-immobile-bvb-2014.jpg/1200px-Ciro-immobile-bvb-2014.jpg"]}
parent author
parent permlinkethereum
permlinkhow-does-the-blockchain-know-a-football-match-s-result
titleHow Does The Blockchain Know A Football Match's Result?
Transaction InfoBlock #16815364/Trx 92492b161a052bda83dfb877a96418fb63d4dd8d
View Raw JSON Data
{
  "block": 16815364,
  "op": [
    "comment",
    {
      "author": "chrisdotn",
      "body": "@@ -1,8 +1,177 @@\n+!%5BCiro Immobile by Dirk Vorderstra%C3%9Fe CC BY 3.0%5D(https://upload.wikimedia.org/wikipedia/commons/thumb/9/90/Ciro-immobile-bvb-2014.jpg/1200px-Ciro-immobile-bvb-2014.jpg)%0A%0A\n **The Et\n",
      "json_metadata": "{\"tags\":[\"ethereum\",\"cryptocurrency\",\"oracle\",\"development\",\"blockchain\"],\"links\":[\"http://solidity.readthedocs.io/en/develop/\",\"http://www.oraclize.it/\",\"http://api.football-data.org/index\",\"https://github.com/chrisdotn/footballBet\",\"http://jsonpath.com/\",\"https://medium.com/@chrisdotn/a-json-parser-for-solidity-9cc73b4b42\",\"https://tlsnotary.org\",\"https://bitcointalk.org/index.php?topic=301538.0\",\"https://www.realitykeys.com\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\",\"image\":[\"https://upload.wikimedia.org/wikipedia/commons/thumb/9/90/Ciro-immobile-bvb-2014.jpg/1200px-Ciro-immobile-bvb-2014.jpg\"]}",
      "parent_author": "",
      "parent_permlink": "ethereum",
      "permlink": "how-does-the-blockchain-know-a-football-match-s-result",
      "title": "How Does The Blockchain Know A Football Match's Result?"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2017-10-31T15:30:30",
  "trx_id": "92492b161a052bda83dfb877a96418fb63d4dd8d",
  "trx_in_block": 24,
  "virtual_op": 0
}
chrisdotnupdated their account properties
2017/10/31 15:15:00
accountchrisdotn
json metadata{"profile":{"profile_image":"https://www.maibornwolff.de/sites/default/files/styles/team_grid/public/images/team/christophnk.jpg"}}
memo keySTM71cR3DpoopFQLnQJGvHZviZbDSWL5oTXLzFFxXqeJG8ykyU5fY
Transaction InfoBlock #16815054/Trx 653ffa477276f1b645a0edac77385c63ebec44dc
View Raw JSON Data
{
  "block": 16815054,
  "op": [
    "account_update",
    {
      "account": "chrisdotn",
      "json_metadata": "{\"profile\":{\"profile_image\":\"https://www.maibornwolff.de/sites/default/files/styles/team_grid/public/images/team/christophnk.jpg\"}}",
      "memo_key": "STM71cR3DpoopFQLnQJGvHZviZbDSWL5oTXLzFFxXqeJG8ykyU5fY"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2017-10-31T15:15:00",
  "trx_id": "653ffa477276f1b645a0edac77385c63ebec44dc",
  "trx_in_block": 29,
  "virtual_op": 0
}
chrisdotnupdated their account properties
2017/10/31 15:10:54
accountchrisdotn
json metadata{"profile":{"name":"chrisdotn","about":"Blockchain enthusiast and ethereum developer","location":"Munich"}}
memo keySTM71cR3DpoopFQLnQJGvHZviZbDSWL5oTXLzFFxXqeJG8ykyU5fY
Transaction InfoBlock #16814972/Trx 7f9358ff9353df1d34e19c8e06bdc933118bea80
View Raw JSON Data
{
  "block": 16814972,
  "op": [
    "account_update",
    {
      "account": "chrisdotn",
      "json_metadata": "{\"profile\":{\"name\":\"chrisdotn\",\"about\":\"Blockchain enthusiast and ethereum developer\",\"location\":\"Munich\"}}",
      "memo_key": "STM71cR3DpoopFQLnQJGvHZviZbDSWL5oTXLzFFxXqeJG8ykyU5fY"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2017-10-31T15:10:54",
  "trx_id": "7f9358ff9353df1d34e19c8e06bdc933118bea80",
  "trx_in_block": 17,
  "virtual_op": 0
}
2017/10/31 15:09:36
authorchrisdotn
body**The Ethereum Blockchain allows to use so called "smart contracts" to be executed on the Blockchain itself. Besides Bitcoin as the first and biggest crypto currency, Ethereum has taken the second spot with its focus on smart contracts. But there is an obstacle: Smart contracts on the blockchain cannot access data from outside of the blockchain. However, real world data is most often the basis for processes in a smart contract. How does a smart contract access information from the real world without pulling it into the blockchain all by itself?** Smart contracts on Ethereum are small programs written in [Solidity](http://solidity.readthedocs.io/en/develop/). These programs execute on the blockchain itself and can act upon data that is available on the blockchain. The Ethereum blockchain has its focus on these smart contracts and does not solely focus on the payment functions. Smart contract mimic "normal", paper based contracts in that they encode various clauses and conditions that have been agreed on between two or more parties. In addition to just _storing_ these conditions, a smart contract also _executes_ these conditions just like a "normal" computer program would do. A smart contract is thus an entity that combines functions of a paper based, traditional contract and a computer program. Because the blockchain is an "append-only" system a contract on the blockchain cannot be changed under normal circumstances (this rule has had known deviations). For "normal" operations the blockchain can be considered immutable. A smart contract will execute the encoded clauses automatically. Because the blockchain is an open system, everyone can look at a smart contract and verify that the contract acts as advertised. ## A Bet As a Smart Contract A (simple) example for a smart contract is a bet: The smart contract acts as a platform for betting, users can place bets by paying some money to the contract (ie. sending some money to the contract via transaction). As soon as the event that has been bet on has been resolved, the smart contract will determine winners and losers of the bet and pay the wins to the the winners automatically. Because of the transparent nature of the contract a user does not need to _trust_ that the contract behaves as expected, but he can _prove_ that the contract does indeed pay out the wins instead of running away with them by studying the sources of the contract. Such a proof works charmingly well if all data that is needed to determine the outcome of a bet is available on chain: The smart contract can access such data and process it. Difficulty arises if the contract relies on data that is _external_ to the blockchain for winner determination. Such a real world event does not have any connection to the blockchain by itself and cannot be used within the contract. Even though all conditions and clauses are part of the contract and can be used, the actual data that determines the result of the bet is not. An example is a bet on a football match: The result of the match cannot be read on chain and thus, the contract cannot determine a winner. To allow for smart contracts that make use of real world data, the data has to be fed into the blockchain via transaction. After that it is stored on the chain and can be used by smart contracts. In the most simple case smart contracts would rely on services to be _blockchain aware_. Such services would fed data into the blockchain and make it available for processing. However, external services aren't usually set up to interact with a blockchain. Mostly they provide data via API in JSON format that is useful for automatic processing. Therefore, we need an intermediary that will call a service via REST API and feed the data into the blockchain for the smart contract at a specific point in time. ### Oracles To The Rescue The function of an intermediary is adopted by so called oracles. They provide a smart contract on the blockchain that can be called by other smart contracts. An external service, run by the owners of the oracle contract, will monitor the oracle contract and feed data into the blockchain as needed. The oracle contract will then call the contract that ordered the external data. It is the calling contracts responsibility to interpret the response. In that way oracles act just the the ancient oracle of Delphi: A caller can ask a question and will received an answer. The interpretation of the answer lies with the caller. In particular, a caller does not know (and cannot see) how the answer came to be. It must trust the oracle to provide correct data and act truthfully. Currently, one of the most used oracle services on the Ethereum blockchain is [oraclize.it](http://www.oraclize.it/). The service provides an oracle on Ethereum and (with limits) on other blockchains such as Bitcoin. To use it a smart contract calls the oracle contract with the REST call that it wants the answer to. The oracle will get the answer via its external service and the call the original caller with a callback function. The callback receives the response to the REST call. For our football bet, we rely on the data from [http://api.football-data.org/index]. It provides the results of various football leagues in a machine readable format. The full code for the example contract is available on [Github](https://github.com/chrisdotn/footballBet). The actual code (slightly shortened here for readability) is pretty straight forward: ``` contract FootballBet is usingOraclize { struct Game { string gameId; string date; string status; string homeTeam; string awayTeam; uint homeTeamGoals; uint awayTeamGoals; Result result; uint receivedGoalMsgs; } struct Request { bool initialized; bool processed; string key; } Game game; mapping (bytes32 => Request) requests; function queryFootballData(string gameId, string key, uint gas) public { if (oraclize_getPrice('URL') > this.balance) { Info('Oraclize query was NOT sent, please add some ETH to cover for the query fee'); } else { string memory url = generateUrl('https://api.football-data.org/v1/fixtures/', gameId, '?head2head=0', key); bytes32 requestId = oraclize_query('URL', url, gas); requests[requestId] = Request(true, false, key); Info('Oraclize query was sent, standing by for the answer..'); } } function __callback(bytes32 myid, string result) public { Request memory r = requests[myid]; if (r.initialized && !r.processed) { // new response if (r.key.toSlice().equals(JSON_FIXTURE.toSlice())) { var (success, tokens, numberTokens) = JsmnSol.parse(result, 45); if (success) { for (uint k=0; k<=numberTokens; k++) { // get Token contents if (tokens[k].jsmnType == JsmnSol.JsmnType.STRING) { string memory key = JsmnSol.getBytes(result, tokens[k]); if (key.toSlice().equals(JSON_STATUS.toSlice())) { game.status = JsmnSol.getBytes(result, tokens[++k]); } else if (key.toSlice().equals(JSON_HOME_TEAM.toSlice())) { game.homeTeam = JsmnSol.getBytes(result, tokens[++k]); } else if (key.toSlice().equals(JSON_AWAY_TEAM.toSlice())) { game.awayTeam = JsmnSol.getBytes(result, tokens[++k]); } } } } } Info(gameToString()); requests[myid].processed = true; } } } ``` The contract inherits `usingOraclize` as its parent contract. It provides the functions to interact with the oracle contract. In particular the two functions `oraclize_query(string data_source, string url, uint gas)` and `__callback(bytes32 myid, string result)` are interesting as they are the two main interactions with the oracle. The betting contract can ask for external data by calling the `oraclize_query`. Its three parameters define the request to an external service: - The data source should be the constant `'URL'` for calls to REST APIs. - `url` is the actual URL that should be called on the REST API. - `gas` is the maximum amount of gas that the _callback function_ (see below) is allowed to use. In our example the `url` is `json(https://api.football-data.org/v1/fixtures/{gameId}?head2head=0){jsonPath}`. It specifies the actual URL with a variable `gameId` and a variable `jsonPath`. The [JSONPath](http://jsonpath.com/) can be used to filter the JSON response. Normally not the entire JSON response is needed for the smart contract, but only parts of it. String processing is relatively expensive in Solidity. Thus, it is useful to provide the minimally useful JSON to the contract and process only that bit. The response of the call football-data.org is this (slightly shortened) JSON: ``` { "fixture": { "date": "2016-08-27T13:30:00Z", "status": "FINISHED", "matchday": 1, "homeTeamName": "FC Augsburg", "awayTeamName": "VfL Wolfsburg", "result": { "goalsHomeTeam": 0, "goalsAwayTeam": 2 } } ``` The JSONPath `$.fixture.result` will further filter the JSON to `{ "goalsHomeTeam": 0, "goalsAwayTeam": 2 }`. This part is small enough to be [parsed on chain](https://medium.com/@chrisdotn/a-json-parser-for-solidity-9cc73b4b42). `oraclize_query` returns a unique ID for the call to the oracle. This ID can be used in the callback to identify the original request to the API. For matching a callback to a specific query call each query is saved as a `Request` object. The requests are stored in a mapping so that the callback can retrieve the `Request` with its ID. The attribute `Request.processed` is a boolean value that identifies whether the request has been processed in a callback already. This mechanism shields the contract against replay attacks. Furthermore, the contract will only process responses that have originally been requested by the contract itself: Only responses for requests with `Request.initialized == true` are processed by the callback. This step is needed because Solidity has the (slightly odd) behavior of initializing anything with its default value (`0` for `uint`, `false` for `bool` etc.). Together with the (again slightly odd) fact that mappings are initialized for any conceivable key, a smart contract has to guard against callbacks that have not been requested by the contract itself. ### There Is No Free Lunch In addition to the actual oracle contract on-chain oracle services have to provide external servers, which will trigger the actual transactions to store data on the blockchain. Therefore, they are charging a fee for every call. The fee is charged to the contract that is calling `oraclize_query`. The contract must have enough ether in its balance to pay the fees to the oracle. `queryFootballData` ensures that the contract has indeed enough money to pay the oracle before calling the oracle. Furthermore, the calling contract has to supply the transactions fees that the oracle has to pay to call the callback function. Depending on the callback's complexity they default 200,000 gas may not be enough to pay for the callback. In our example the callback parses the response JSON. String processing is rather expensive in Ethereum. The callback is, thus, one of the more costly functions in the contract and will not execute on 200,000 gas. The third parameter, `gas` can be used to provide a custom amount of gas to the oracle to cover the callback's fees. The contract has to cover two kinds of fees: The first one is the call to the oracle itself, the second one is the fee for the callback transaction. Both are deducted from the contract's balance. ### Truthful Behavior Can Be Verified Trust in the blockchain is based on the possibility to verify any transaction that has happened on chain. Oracles provide a means to push external, "real world" data onto the blockchain. Any transaction that relies on such data is, as per definition, as trustworthy as the original data source. A contract for bets on football matches will only find users if the match result show up truthfully and unmodified on the blockchain. A first trust anchor is the data source that provides the match's results. In our example this is football-data.org. For this blog post's purpose, we assume the data source to be trustworthy and reliable. If responses from the data source end up unmodified on the blockchain, a user can trust the smart contract as much as he would trust the data source. However, using an oracle a third party comes into the transaction that needs to be included in the trust chain. For our contract that is undesirable, because a user has to trust an additional party. A smart contract should only use such a service if and only if the service can somehow show that it does not alter the data in transit. It should somehow show that the data provided to the blockchain are the same data that it received from the original data source. Orclize.it supports notarization of the oracle's response with [TLSNotary](https://tlsnotary.org). If a user requests a TLSNotary proof, oraclize will provide a proof that the response that is sent to the callback is actually the same, unaltered response that the oracle has received from the external service. Thus, the trust chain is extended: A user still has to trust the original service, however, by means of the TLSNotary proof the user neither needs to trust the oracle, nor does he need to trust the actual smart contract. In our smart contract we need to set the "Proof-Type" before querying the oracle: ``` function queryFootballData(string gameId, string key, uint gas) public { if (oraclize_getPrice('URL') > this.balance) { Info('Oraclize query was NOT sent, please add some ETH to cover for the query fee'); } else { string memory url = generateUrl('https://api.football-data.org/v1/fixtures/', gameId, '?head2head=0', key); oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS); bytes32 requestId = oraclize_query('URL', url, gas); requests[requestId] = Request(true, false, key); Info('Oraclize query was sent, standing by for the answer..'); } } ``` The call to `oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS)` asks the oracle to notarize the external server call and store the proof on the _Interplanetary Filesystem_ (IPFS). TLSNotary allows for notarization of connections that are secured by TLS 1.0 or TLS 1.1. For the notarization case we want the connection to be secured _and_ verifiable for a (named) third party. This is an extension of the TLS protocol as TLS itself allows to secure a connection without the ability to audit the connection later on. If a user ask for a proof the oracle will call a callback with the signature `function __callback(bytes32 myid, string result, bytes proof)`. This callback has a third additional parameter, the `proof`. The parameter holds the IPFS multihash that can be used to retrieve the actual proof from IPFS. Since the proof itself is too large to be stored on the blockchain, the oracle will store it on IPFS and only put its multihash on the chain. For our oracle use case, oraclize.it acts as "Auditee", i.e. as the party that wants to prove that it has received the server's response "as is" and has not modified it in transit. The counterpart, the "Auditor" is the party that wants to know that the response has been received by the auditee and – in the case of the oracle – that it has been relayed to the smart contract unmodified. The TLSNotary mechanism relies on parts of the communication during the TLS handshake being withheld until a further time in the connection. Because a smart contract cannot hold secrets by definition, it cannot act as auditor for the TLSNotary proof. Since TLSNotary seems to be a intricately clever mechanism this result is unfortunate: We cannot use the mechanism directly to let the oracle prove that it acts truthfully. To work around this limitation, oraclize.it chose to modify the whole process a bit: Instead of the smart contract acting as a auditor, another (fourth) party is involved in the process. Instead of the smart contract auditing the communication between oraclize and the server this task is delegated to a [specially secured VM instance hosted at Amazon](https://bitcointalk.org/index.php?topic=301538.0). For proof verification, a user can prove that the communication has been audited by this AWS VM. If someone managed to hack this VM, the hacker would gain access to the secret. If he would manage to hack oraclize's servers too, he would be able to fake proofs. The TLSNotary proof can, thus, be faked in theory, but the need to access to different servers (AWS VM _and_ oraclize servers) makes it improbable in practice. ## Different Keys To Truth Oraclize.it is not the only oracle service for Ethereum. [_Reality Keys_](https://www.realitykeys.com) uses a conceptually different approach. It works using these steps: 1. A user registers an event with Reality Key's API. In our case the event is a football match at a certain time and place. 2. Reality Key's service creates two so called «reality keys» (RK) – one for a positive outcome of the event (ie. BVB wins) and another for the negative outcome (ie. team 2 wins or the match ends in a draw). 3. The service publishes both _public_ keys for the RKs. Additionally it publishes a so called fact containing the result after it will have been determined on the Ethereum blockchain. 4. After the event has resolved (ie. the match has ended and the result has been determined conclusively) the service will publish the _private_ key to the winning RK. The private key for the loosing RK will be destroyed. Furthermore the fact on the Ethereum blockchain will be amended with the final result. 5. A user can rely on the fact and the published result on the Ethereum blockchain by verifying that the fact has been signed by Reality Key's with their private key. 6. The result determination by the service is subject to a defined appellation period: If a user (contract or human) disagrees with the result, he can appeal to Reality Keys and request a manual, human result determination. This request has a fee, that has to be paid by the user. A result determined by human resolution is binding in the context of the service. The trust chain when using Reality Keys as oracle is similar to the the one with oraclize.it: The user has to trust the server to create a truthful response and he has to trust Reality Keys to publish the correct result on chain. To allow for appellation a user can request an event resolutioon to be verified by a human. However, there is not built-in mechanism with Reality Keys to verify that a response from a server has been correctly relayed to the blockchain by the service. Thus, the service builds on reputation. ## Conclusion Smart contracts allow for complex computation to happen on the blockchain. Often they rely on data that originates in the real world, i.e. outside of the blockchain. Oracle services have shown up that push data from real world via transaction into the blockchain. Oraclize.is is the most commonly used service; smart contracts can integrate its services relatively easily. Using an oracle breaks the original trust chain: Data in the blockchain are transparent and verifiable, external data is not. Thus, a user has to trust the original server that provides the data. Oraclize.it provides a means to proof that the service relays the data as is and does not tamper with them. This TLSNotary proof is done with a specially secured AWS VM for technical reasons. As long as the AWS instance can be trusted, the service cannot fake proofs. Other oracles use a different concept. Reality Keys doesn't integrate as smoothly and does not provide proofs for their server communications. However, in particular for simple binary decisions it might be a better choice as much of the logic to determine the positive or negative outcome can be delayed to the oracle. Thus, a smart contract does not have to compute the outcome based on the data directly but can take the outcome directly from the oracle. The contract could be cheaper to use. Oracles provide a means to process external events on the blockchain as long as real world services are not _blockchain aware_ by themselves. If they were, trust would have to be placed in the services only. The need for rather complex proofs (such as TLSNotary) would not arise. Until then – probably for quite some time – oracles bridge the gap between real world and blockchain.
json metadata{"tags":["ethereum","cryptocurrency","oracle","development","blockchain"],"links":["http://solidity.readthedocs.io/en/develop/","http://www.oraclize.it/","http://api.football-data.org/index","https://github.com/chrisdotn/footballBet","http://jsonpath.com/","https://medium.com/@chrisdotn/a-json-parser-for-solidity-9cc73b4b42","https://tlsnotary.org","https://bitcointalk.org/index.php?topic=301538.0","https://www.realitykeys.com"],"app":"steemit/0.1","format":"markdown"}
parent author
parent permlinkethereum
permlinkhow-does-the-blockchain-know-a-football-match-s-result
titleHow Does The Blockchain Know A Football Match's Result?
Transaction InfoBlock #16814946/Trx 195b65b834c23c87c6f1375b29ecf1e127d8f06c
View Raw JSON Data
{
  "block": 16814946,
  "op": [
    "comment",
    {
      "author": "chrisdotn",
      "body": "**The Ethereum Blockchain allows to use so called \"smart contracts\" to be executed on the Blockchain itself. Besides Bitcoin as the first and biggest crypto currency, Ethereum has taken the second spot with its focus on smart contracts. But there is an obstacle: Smart contracts on the blockchain cannot access data from outside of the blockchain. However, real world data is most often the basis for processes in a smart contract. How does a smart contract access information from the real world without pulling it into the blockchain all by itself?**\n\nSmart contracts on Ethereum are small programs written in [Solidity](http://solidity.readthedocs.io/en/develop/). These programs execute on the blockchain itself and can act upon data that is available on the blockchain. The Ethereum blockchain has its focus on these smart contracts and does not solely focus on the payment functions. Smart contract mimic \"normal\", paper based contracts in that they encode various clauses and conditions that have been agreed on between two or more parties. In addition to just _storing_ these conditions, a smart contract also _executes_ these conditions just like a \"normal\" computer program would do. A smart contract is thus an entity that combines functions of a paper based, traditional contract and a computer program.\n\nBecause the blockchain is an \"append-only\" system a contract on the blockchain cannot be changed under normal circumstances (this rule has had known deviations). For \"normal\" operations the blockchain can be considered immutable. A smart contract will execute the encoded clauses automatically. Because the blockchain is an open system, everyone can look at a smart contract and verify that the contract acts as advertised.\n\n## A Bet As a Smart Contract\nA (simple) example for a smart contract is a bet: The smart contract acts as a platform for betting, users can place bets by paying some money to the contract (ie. sending some money to the contract via transaction). As soon as the event that has been bet on has been resolved, the smart contract will determine winners and losers of the bet and pay the wins to the the winners automatically.\n\nBecause of the transparent nature of the contract a user does not need to _trust_ that the contract behaves as expected, but he can _prove_ that the contract does indeed pay out the wins instead of running away with them by studying the sources of the contract.\n\nSuch a proof works charmingly well if all data that is needed to determine the outcome of a bet is available on chain: The smart contract can access such data and process it. Difficulty arises if the contract relies on data  that is _external_ to the blockchain for winner determination. Such a real world event does not have any connection to the blockchain by itself and cannot be used within the contract. Even though all conditions and clauses are part of the contract and can be used, the actual data that determines the result of the bet is not. An example is a bet on a football match: The result of the match cannot be read on chain and thus, the contract cannot determine a winner.\n\nTo allow for smart contracts that make use of real world data, the data has to be fed into the blockchain via transaction. After that it is stored on the chain and can be used by smart contracts.\n\nIn the most simple case smart contracts would rely on services to be _blockchain aware_. Such services would fed data into the blockchain and make it available for processing. However, external services aren't usually set up to interact with a blockchain. Mostly they provide data via API in JSON format that is useful for automatic processing. Therefore, we need an intermediary that will call a service via REST API and feed the data into the blockchain for the smart contract at a specific point in time.\n\n### Oracles To The Rescue\nThe function of an intermediary is adopted by so called oracles. They provide a smart contract on the blockchain that can be called by other smart contracts. An external service, run by the owners of the oracle contract, will monitor the oracle contract and feed data into the blockchain as needed. The oracle contract will then call the contract that ordered the external data. It is the calling contracts responsibility to interpret the response. In that way oracles act just the the ancient oracle of Delphi: A caller can ask a question and will received an answer. The interpretation of the answer lies with the caller. In particular, a caller does not know (and cannot see) how the answer came to be. It must trust the oracle to provide correct data and act truthfully.\n\nCurrently, one of the most used oracle services on the Ethereum blockchain is [oraclize.it](http://www.oraclize.it/). The service provides an oracle on Ethereum and (with limits) on other blockchains such as Bitcoin. To use it a smart contract calls the oracle contract with the REST call that it wants the answer to. The oracle will get the answer via its external service and the call the original caller with a callback function. The callback receives the response to the REST call.\n\nFor our football bet, we rely on the data from [http://api.football-data.org/index]. It provides the results of various football leagues in a machine readable format. The full code for the example contract is available on [Github](https://github.com/chrisdotn/footballBet). The actual code (slightly shortened here for readability) is pretty straight forward:\n```\ncontract FootballBet is usingOraclize {\n\n    struct Game {\n        string gameId;\n        string date;\n        string status;\n        string homeTeam;\n        string awayTeam;\n        uint homeTeamGoals;\n        uint awayTeamGoals;\n        Result result;\n        uint receivedGoalMsgs;\n    }\n\n    struct Request {\n        bool initialized;\n        bool processed;\n        string key;\n    }\n\n    Game game;\n    mapping (bytes32 => Request) requests;\n\n    function queryFootballData(string gameId, string key, uint gas) public {\n        if (oraclize_getPrice('URL') > this.balance) {\n            Info('Oraclize query was NOT sent, please add some ETH to cover for the query fee');\n        } else {\n            string memory url = generateUrl('https://api.football-data.org/v1/fixtures/', gameId, '?head2head=0', key);\n            bytes32 requestId = oraclize_query('URL', url, gas);\n            requests[requestId] = Request(true, false, key);\n            Info('Oraclize query was sent, standing by for the answer..');\n        }\n    }\n\n    function __callback(bytes32 myid, string result) public {\n        Request memory r = requests[myid];\n\n        if (r.initialized && !r.processed) {\n            // new response\n            if (r.key.toSlice().equals(JSON_FIXTURE.toSlice())) {\n                var (success, tokens, numberTokens) = JsmnSol.parse(result, 45);\n                if (success) {\n                    for (uint k=0; k<=numberTokens; k++) {\n                        // get Token contents\n                        if (tokens[k].jsmnType == JsmnSol.JsmnType.STRING) {\n                            string memory key = JsmnSol.getBytes(result, tokens[k]);\n                            if (key.toSlice().equals(JSON_STATUS.toSlice())) {\n                                game.status = JsmnSol.getBytes(result, tokens[++k]);\n                            } else if (key.toSlice().equals(JSON_HOME_TEAM.toSlice())) {\n                                game.homeTeam = JsmnSol.getBytes(result, tokens[++k]);\n                            } else if (key.toSlice().equals(JSON_AWAY_TEAM.toSlice())) {\n                                game.awayTeam = JsmnSol.getBytes(result, tokens[++k]);\n                            }\n                        }\n                    }\n                }\n            }\n            Info(gameToString());\n            requests[myid].processed = true;\n        }\n    }    \n}\n```\n\nThe contract inherits `usingOraclize` as its parent contract. It provides the functions to interact with the oracle contract. In particular the two functions `oraclize_query(string data_source, string url, uint gas)` and `__callback(bytes32 myid, string result)` are interesting as they are the two main interactions with the oracle.\n\nThe betting contract can ask for external data by calling the `oraclize_query`. Its three parameters define the request to an external service:\n- The data source should be the constant `'URL'` for calls to REST APIs.\n- `url` is the actual URL that should be called on the REST API.\n- `gas` is the maximum amount of gas that the _callback function_ (see below) is allowed to use.\n\nIn our example the `url` is `json(https://api.football-data.org/v1/fixtures/{gameId}?head2head=0){jsonPath}`. It specifies the actual URL with a variable `gameId` and a variable `jsonPath`. The [JSONPath](http://jsonpath.com/) can be used to filter the JSON response. Normally not the entire JSON response is needed for the smart contract, but only parts of it. String processing is relatively expensive in Solidity. Thus, it is useful to provide the minimally useful JSON to the contract and process only that bit. The response of the call football-data.org is this (slightly shortened) JSON:\n```\n{\n  \"fixture\": {\n    \"date\": \"2016-08-27T13:30:00Z\",\n    \"status\": \"FINISHED\",\n    \"matchday\": 1,\n    \"homeTeamName\": \"FC Augsburg\",\n    \"awayTeamName\": \"VfL Wolfsburg\",\n    \"result\": {\n      \"goalsHomeTeam\": 0,\n      \"goalsAwayTeam\": 2\n    }\n  }\n```\n\nThe JSONPath `$.fixture.result` will further filter the JSON to `{ \"goalsHomeTeam\": 0, \"goalsAwayTeam\": 2 }`. This part is small enough to be [parsed on chain](https://medium.com/@chrisdotn/a-json-parser-for-solidity-9cc73b4b42).\n\n`oraclize_query` returns a unique ID for the call to the oracle. This ID can be used in the callback to identify the original request to the API. For matching a callback to a specific query call each query is saved as a `Request` object. The requests are stored in a mapping so that the callback can retrieve the `Request` with its ID. The attribute `Request.processed` is a boolean value that identifies whether the request has been processed in a callback already. This mechanism shields the contract against replay attacks.\n\nFurthermore, the contract will only process responses that have originally been requested by the contract itself: Only responses for requests with  `Request.initialized == true` are processed by the callback. This step is needed because Solidity has the (slightly odd) behavior of initializing anything with its default value (`0` for `uint`, `false` for `bool` etc.). Together with the (again slightly odd) fact that mappings are initialized for any conceivable key, a smart contract has to guard against callbacks that have not been requested by the contract itself.\n\n### There Is No Free Lunch\nIn addition to the actual oracle contract on-chain oracle services have to provide external servers, which will trigger the actual transactions to store data on the blockchain. Therefore, they are charging a fee for every call. The fee is charged to the contract that is calling `oraclize_query`. The contract must have enough ether in its balance to pay the fees to the oracle. `queryFootballData` ensures that the contract has indeed enough money to pay the oracle before calling the oracle.\n\nFurthermore, the calling contract has to supply the transactions fees that the oracle has to pay to call the callback function. Depending on the callback's complexity they default 200,000 gas may not be enough to pay for the callback. In our example the callback parses the response JSON. String processing is rather expensive in Ethereum. The callback is, thus, one of the more costly functions in the contract and will not execute on  200,000 gas. The third parameter, `gas` can be used to provide a custom amount of gas to the oracle to cover the callback's fees.\n\nThe contract has to cover two kinds of fees: The first one is the call to the oracle itself, the second one is the fee for the callback transaction. Both are deducted from the contract's balance.\n\n### Truthful Behavior Can Be Verified\nTrust in the blockchain is based on the possibility to verify any transaction that has happened on chain. Oracles provide a means to push external, \"real world\" data onto the blockchain. Any transaction that relies on such data is, as per definition, as trustworthy as the original data source. A contract for bets on football matches will only find users if the match result show up truthfully and unmodified on the blockchain.\n\nA first trust anchor is the data source that provides the match's results. In our example this is football-data.org. For this blog post's purpose, we assume the data source to be trustworthy and reliable. If responses from the data source end up unmodified on the blockchain, a user can trust the smart contract as much as he would trust the data source.\n\nHowever, using an oracle a third party comes into the transaction that needs to be included in the trust chain. For our contract that is undesirable, because a user has to trust an additional party. A smart contract should only use such a service if and only if the service can somehow show that it does not alter the data in transit. It should somehow show that the data provided to the blockchain are the same data that it received from the original data source.\n\nOrclize.it supports notarization of the oracle's response with [TLSNotary](https://tlsnotary.org). If a user requests a TLSNotary proof, oraclize will provide a proof that the response that is sent to the callback is actually the same, unaltered response that the oracle has received from the external service. Thus, the trust chain is extended: A user still has to trust the original service, however, by means of the TLSNotary proof the user neither needs to trust the oracle, nor does he need to trust the actual smart contract.\n\nIn our smart contract we need to set the \"Proof-Type\" before querying the oracle:\n```\nfunction queryFootballData(string gameId, string key, uint gas) public {\n    if (oraclize_getPrice('URL') > this.balance) {\n        Info('Oraclize query was NOT sent, please add some ETH to cover for the query fee');\n    } else {\n        string memory url = generateUrl('https://api.football-data.org/v1/fixtures/', gameId, '?head2head=0', key);\n        oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS);\n        bytes32 requestId = oraclize_query('URL', url, gas);\n        requests[requestId] = Request(true, false, key);\n        Info('Oraclize query was sent, standing by for the answer..');\n    }\n}\n```\n\nThe call to `oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS)` asks the oracle to notarize the external server call and store the proof on the _Interplanetary Filesystem_ (IPFS). TLSNotary allows for notarization of connections that are secured by TLS 1.0 or TLS 1.1. For the notarization case we want the connection to be secured _and_ verifiable for a (named) third party. This is an extension of the TLS protocol as TLS itself allows to secure a connection without the ability to audit the connection later on.\n\nIf a user ask for a proof the oracle will call a callback with the signature `function __callback(bytes32 myid, string result, bytes proof)`. This callback has a third additional parameter, the `proof`. The parameter holds the IPFS multihash that can be used to retrieve the actual proof from IPFS. Since the proof itself is too large to be stored on the blockchain, the oracle will store it on IPFS and only put its multihash on the chain.\n\nFor our oracle use case, oraclize.it acts as \"Auditee\", i.e. as the party that wants to prove that it has received the server's response \"as is\" and has not modified it in transit. The counterpart, the \"Auditor\" is the party that wants to know that the response has been received by the auditee and – in the case of the oracle – that it has been relayed to the smart contract unmodified.\n\nThe TLSNotary mechanism relies on parts of the communication during the TLS handshake being withheld until a further time in the connection. Because a smart contract cannot hold secrets by definition, it cannot act as auditor for the TLSNotary proof. Since TLSNotary seems to be a intricately clever mechanism this result is unfortunate: We cannot use the mechanism directly to let the oracle prove that it acts truthfully.\n\nTo work around this limitation, oraclize.it chose to modify the whole process a bit: Instead of the smart contract acting as a auditor, another (fourth) party is involved in the process. Instead of the smart contract auditing the communication between oraclize and the server this task is delegated to a [specially secured VM instance hosted at Amazon](https://bitcointalk.org/index.php?topic=301538.0). For proof verification, a user can prove that the communication has been audited by this AWS VM. If someone managed to hack this VM, the hacker would gain access to the secret. If he would manage to hack oraclize's servers too, he would be able to fake proofs. The TLSNotary proof can, thus, be faked in theory, but the need to access to different servers (AWS VM _and_ oraclize servers) makes it improbable in practice.\n\n## Different Keys To Truth\nOraclize.it is not the only oracle service for Ethereum. [_Reality Keys_](https://www.realitykeys.com) uses a conceptually different approach. It works using these steps:\n1. A user registers an event with Reality Key's API. In our case the event is a football match at a certain time and place.\n2. Reality Key's service creates two so called «reality keys» (RK) – one for a positive outcome of the event (ie. BVB wins) and another for the negative outcome (ie. team 2 wins or the match ends in a draw).\n3. The service publishes both _public_ keys for the RKs. Additionally it publishes a so called fact containing the result after it will have been determined on the Ethereum blockchain.\n4. After the event has resolved (ie. the match has ended and the result has been determined conclusively) the service will publish the _private_ key to the winning RK. The private key for the loosing RK will be destroyed. Furthermore the fact on the Ethereum blockchain will be amended with the final result.\n5. A user can rely on the fact and the published result on the Ethereum blockchain by verifying that the fact has been signed by Reality Key's with their private key.\n6. The result determination by the service is subject to a defined appellation period: If a user (contract or human) disagrees with the result, he can appeal to Reality Keys and request a manual, human result determination. This request has a fee, that has to be paid by the user. A result determined by human resolution is binding in the context of the service.\n\nThe trust chain when using Reality Keys as oracle is similar to the the one with oraclize.it: The user has to trust the server to create a truthful response and he has to trust Reality Keys to publish the correct result on chain. To allow for appellation a user can request an event resolutioon to be verified by a human. However, there is not built-in mechanism with Reality Keys to verify that a response from a server has been correctly relayed to the blockchain by the service. Thus, the service builds on reputation.\n\n## Conclusion\nSmart contracts allow for complex computation to happen on the blockchain. Often they rely on data that originates in the real world, i.e. outside of the blockchain. Oracle services have shown up that push data from real world via transaction into the blockchain. Oraclize.is is the most commonly used service; smart contracts can integrate its services relatively easily.\n\nUsing an oracle breaks the original trust chain: Data in the blockchain are transparent and verifiable, external data is not. Thus, a user has to trust the original server that provides the data. Oraclize.it provides a means to proof that the service relays the data as is and does not tamper with them. This TLSNotary proof is done with a specially secured AWS VM for technical reasons. As long as the AWS instance can be trusted, the service cannot fake proofs.\n\nOther oracles use a different concept. Reality Keys doesn't integrate as smoothly and does not provide proofs for their server communications. However, in particular for simple binary decisions it might be a better choice as much of the logic to determine the positive or negative outcome can be delayed to the oracle. Thus, a smart contract does not have to compute the outcome based on the data directly but can take the outcome directly from the oracle. The contract could be cheaper to use.\n\nOracles provide a means to process external events on the blockchain as long as real world services are not _blockchain aware_ by themselves. If they were, trust would have to be placed in the services only. The need for rather complex proofs (such as TLSNotary) would not arise. Until then – probably for quite some time – oracles bridge the gap between real world and blockchain.",
      "json_metadata": "{\"tags\":[\"ethereum\",\"cryptocurrency\",\"oracle\",\"development\",\"blockchain\"],\"links\":[\"http://solidity.readthedocs.io/en/develop/\",\"http://www.oraclize.it/\",\"http://api.football-data.org/index\",\"https://github.com/chrisdotn/footballBet\",\"http://jsonpath.com/\",\"https://medium.com/@chrisdotn/a-json-parser-for-solidity-9cc73b4b42\",\"https://tlsnotary.org\",\"https://bitcointalk.org/index.php?topic=301538.0\",\"https://www.realitykeys.com\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
      "parent_author": "",
      "parent_permlink": "ethereum",
      "permlink": "how-does-the-blockchain-know-a-football-match-s-result",
      "title": "How Does The Blockchain Know A Football Match's Result?"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2017-10-31T15:09:36",
  "trx_id": "195b65b834c23c87c6f1375b29ecf1e127d8f06c",
  "trx_in_block": 15,
  "virtual_op": 0
}
2017/10/31 15:06:09
authorchrisdotn
body# A JSON Parser For Solidity **Because smart contract development is still in its infant stages, there aren't many libraries around. In particular – when dealing with oracle responses – the lack of a proper JSON parser is painful. Thus, I created one that is hopefully useful and makes dealing with JSON in Solidity a bit easier.** Developing smart contracts in Ethereum has become easier with the advent of frameworks such as [Truffle](https://www.truffleframework.com) and services such as [oraclize.it](https://oraclize.it). In particular, using oracles to access information that is external to the blockchain has become simple enough for contract development. However, most of the data that is fed into the blockchain via transactions from oracles comes in as JSON formatted data. This requires a smart contract to parse a JSON object to process the data supplied by an oracle. String processing is particularly expensive on the Ethereum blockchain. Thus, the JSON parser should be ‟lightweight” and not use much computation for parsing and processing a JSON string. As there was not JSON parser for Solidity that I'm aware of, I set out to create my own. As a basis I ported the code from [jsmn](https://github.com/zserge/jsmn) to Solidity. The main design consideration of jsmn is parsing a JSON string in a single pass and avoid copying substrings along the way. Thus, the parser only generates _meta data_ on the provided string that can be used for locating and accessing objects later on. ## Single Pass, Fixed Memory, No Copying The parser works by parsing the supplied string character by character once. Along the way it creates tokens, which each identify an object in the string and indicate its starting and ending position in the string. A `token` has this structure: ``` struct Token { JsmnType jsmnType; uint start; bool startSet; uint end; bool endSet; uint8 size; } ``` The `JsmnType` encodes the type of the token. Valid values are: ``` enum JsmnType { UNDEFINED, OBJECT, ARRAY, STRING, PRIMITIVE } ``` Note that `number`, `boolean` and `null` are all treated as `JsmnType.PRIMITIVE`. They can be distinguished by evaluating the first character of the token. Next are the two values `start` and `end`. They encode the starting and the ending position of the substring identifying the object. The `size` indicates the number of sub-objects for that object (that is the number of children in the JSON hierarchy). For technical reasons there are two more variables (`startSet` and `endSet`) that are `false` on initialization and flip to `true` once the values for `start` or `end` have been set by the parse. They are needed because Solidity has the habit of initializing every variable to its default value. A newly created `Token` would return 0 for both `token.start` and `token.end`. The parser uses `startSet` to distinguish a newly initialized token from a token whose object actually starts at position 0 in the string. ## Installation The library is available on [Github](https://github.com/chrisdotn/jsmnSol) or on the [Ethereum Package Manager](https://www.ethpm.com/) `ethpm` as package `jsmnsol-lib`. If you are using truffle you can easily include the library by running `truffle install jsmnsol-lib`. ## Usage **Note:** _The following description is valid for version 0.1.x of the parser, which is the beta release. If the version is >0.1.x at the time of reading, please refer to the Github repo for a more recent documentation._ The library basically requires only one call: `function parse(string json, uint numberElements) internal returns (uint, Token[], uint)`. This call takes two input parameters: - `string json`: The string containing the JSON - `uint numberOfT3okens`: The maximum number of tokens to allocate for parsing. This parameter ensures reasonable gas consumption. Whenever the string has more objects than `numberOfTokens` allows, the parser returns with an error. After parsing, it returns the three values `(uint returnCode, Token[] tokens, uint actualNumber)`. These are: - `uint returnCode`: The `returnCode` indicates whether or not the call was successful. A value of `0` shows a successful parsing, any non-zero value marks an error. The valid values are: ``` uint constant RETURN_SUCCESS = 0; uint constant RETURN_ERROR_INVALID_JSON = 1; uint constant RETURN_ERROR_PART = 2; uint constant RETURN_ERROR_NO_MEM = 3; ``` - `Token[] tokens`: The array with the actual result of the parsing, the tokens. It has `tokens.length == numberElements` (i.e. the value of the input parameter), but not all tokens have useful values. - `uint actualNumber`: The number of parsed tokens in `tokens`. Only tokens from `0`–`(actualNumber-1)` contain useful tokens. The remaining values in the array (`actualNumber`–`tokens.length`) only contain the default values and can be disregarded for further processing. ### A Simple Example The JSON that we want to parse is this: ``` { "key1": { "key1.1": "value", "key1.2": 3, "key1.3": true } } ``` The actual JSON that we pass to the parser is a minified version of the JSON above so that we have the following string: `{ "key1": { "key1.1": "value", "key1.2": 3, "key1.3": true } }`. After a call to `parse(json, 10)`, the parser would return three values: - `uint`: The return value. It is zero for _success_ and non-zero for _errors_ - `Token[]`: An array of tokens. The array has 10 elements. - `uint`: The number of tokens returned. This number is generally less than the length of the token array. It should be used to access the tokens. Indices greater than the number of elements return a default token. The token array would look like this: | # | JsmnType | start | end | startSet | endSet | size | |---|-----------|-------|-----|----------|--------|------| | 0 | OBJECT | 0 | 62 | true | true | 1 | | 1 | STRING | 3 | 7 | true | true | 1 | | 2 | OBJECT | 10 | 60 | true | true | 3 | | 3 | STRING | 13 | 19 | true | true | 1 | | 4 | STRING | 23 | 28 | true | true | 0 | | 5 | STRING | 32 | 38 | true | true | 1 | | 6 | PRIMITIVE | 41 | 42 | true | true | 0 | | 7 | STRING | 45 | 51 | true | true | 1 | | 8 | PRIMITIVE | 54 | 58 | true | true | 0 | | 9 | UNDEFINED | 0 | 0 | false | false | 0 | ## Use Case: Response Data From an Oracle One of the possible use cases for the parser is processing an oracle response. For instance, if you are using oraclize.it as oracle, the data that is returned in the callback is most likely a JSON string that is the result of a call to a REST API. Usually these responses include all kinds of data that is probably not relevant for the smart contract. It might, however, be the case that the contract is not only interested in one specific datum from the JSON, but more than one. An example would be a bet for a football match: A call to an API (this one specifically is the response of `GET https://api.football-data.org/v1/fixtures/152250?head2head=0`) returns the result of the match as JSON: ``` { "fixture": { "_links": { "self": { "href": "http://api.football-data.org/v1/fixtures/152250" }, "competition": { "href": "http://api.football-data.org/v1/competitions/430" }, "homeTeam": { "href": "http://api.football-data.org/v1/teams/16" }, "awayTeam": { "href": "http://api.football-data.org/v1/teams/11" } }, "date": "2016-08-27T13:30:00Z", "status": "FINISHED", "matchday": 1, "homeTeamName": "FC Augsburg", "awayTeamName": "VfL Wolfsburg", "result": { "goalsHomeTeam": 0, "goalsAwayTeam": 2 }, "odds": { "homeWin": 3.0, "draw": 3.3, "awayWin": 2.37 } } } ``` For winner determination the only interesting part of that response is the `result` part of the response. From that result part, we need two elements, namely the number for `goalsHomeTeam` and the number of `goalsAwayTeam`. We need to compare the numbers to decide on the winner of the match. There are two steps to facilitate processing of the response: ### Reduce The Result to Fewer Elements... The first step to make that reponse useful is to reduce it to the actually needed parts. oraclize.it provides a means to filter a response from a server with [JSONPath](http://goessner.net/articles/JsonPath/)). By filtering the response with `$.fixture.result` oraclize would only return the following part of the JSON to our smart contract (again as a minified string actually): ``` { "goalsHomeTeam": 0, "goalsAwayTeam": 2 } ``` ### ...And Parse Them This bit is much less expensive to process on-chain. We can use the parser to parse this string. It would return the following tokens: | # | JsmnType | start | end | startSet | endSet | size | |---|-----------|-------|-----|----------|--------|------| | 0 | OBJECT | 0 | 42 | true | true | 2 | | 1 | STRING | 3 | 16 | true | true | 1 | | 2 | PRIMITIVE | 19 | 20 | true | true | 0 | | 3 | STRING | 23 | 36 | true | true | 1 | | 4 | PRIMITIVE | 39 | 40 | true | true | 0 | Now we can use the two tokens `token[2]` and `token[4]` to access the two interesting numbers. To extract the substring for `token[2]` we would call: `string goalsHT_string = getBytes(json, token[2].start, token[2].end)`. This call returns a string. To do useful comparisons on the actual numbers, we still need to convert that string to a `uint`. A call to `uint goalsHT = parseInt(goalsHT_string)` accomplishes that. This procedure of combining a filter on the result via JSONPath and then parsing the result with the parser allows processing of oracle responses with a smart contract. # Final Words This parser is still in _beta_; this is its first release. Because of the gas cost it should not be used to parse large JSON files as that will most likely fail. String processing is computation intensive and thus expensive. However, for small JSONs (possibly already reduced by a suitable JSONPath) it can be economical to parse them on-chain and save another call to an oracle to get another part of the JSON. If you find the library useful, I would appreciate a comment or a donation. Issues and or feature request can be filed on [Github](https://github.com/chrisdotn/jsmnSol).
json metadata{"tags":["json","ethereum","cryptocurrency","development"],"links":["https://www.truffleframework.com","https://oraclize.it","https://github.com/zserge/jsmn","https://github.com/chrisdotn/jsmnSol","https://www.ethpm.com/","http://goessner.net/articles/JsonPath/"],"app":"steemit/0.1","format":"markdown"}
parent author
parent permlinkjson
permlinka-json-parser-for-solidity
titleA JSON Parser For Solidity
Transaction InfoBlock #16814877/Trx fdf2acd07d2ee4e61c1f596e7d30b92c04b46f3c
View Raw JSON Data
{
  "block": 16814877,
  "op": [
    "comment",
    {
      "author": "chrisdotn",
      "body": "# A JSON Parser For Solidity\n**Because smart contract development is still in its infant stages, there aren't many libraries around. In particular – when dealing with oracle responses – the lack of a proper JSON parser is painful. Thus, I created one that is hopefully useful and makes dealing with JSON in Solidity a bit easier.**\n\nDeveloping smart contracts in Ethereum has become easier with the advent of frameworks such as [Truffle](https://www.truffleframework.com) and services such as [oraclize.it](https://oraclize.it). In particular, using oracles to access information that is external to the blockchain has become simple enough for contract development. However, most of the data that is fed into the blockchain via transactions from oracles comes in as JSON formatted data. This requires a smart contract to parse a JSON object to process the data supplied by an oracle.\n\nString processing is particularly expensive on the Ethereum blockchain. Thus, the JSON parser should be ‟lightweight” and not use much computation for parsing and processing a JSON string.\n\nAs there was not JSON parser for Solidity that I'm aware of, I set out to create my own. As a basis I ported the code from [jsmn](https://github.com/zserge/jsmn) to Solidity. The main design consideration of jsmn is parsing a JSON string in a single pass and avoid copying substrings along the way. Thus, the parser only generates _meta data_ on the provided string that can be used for locating and accessing objects later on.\n\n## Single Pass, Fixed Memory, No Copying\nThe parser works by parsing the supplied string character by character once. Along the way it creates tokens, which each identify an object in the string and indicate its starting and ending position in the string. A `token` has this structure:\n```\nstruct Token {\n    JsmnType jsmnType;\n    uint start;\n    bool startSet;\n    uint end;\n    bool endSet;\n    uint8 size;\n}\n```\n\nThe `JsmnType` encodes the type of the token. Valid values are:\n```\nenum JsmnType { UNDEFINED, OBJECT, ARRAY, STRING, PRIMITIVE }\n```\n\nNote that `number`, `boolean` and `null` are all treated as `JsmnType.PRIMITIVE`. They can be distinguished by evaluating the first character of the token.\n\nNext are the two values `start` and `end`. They encode the starting and the ending position of the substring identifying the object. The `size` indicates the number of sub-objects for that object (that is the number of children in the JSON hierarchy). For technical reasons there are two more variables (`startSet` and `endSet`) that are `false` on initialization and flip to `true` once the values for `start` or `end` have been set by the parse. They are needed because Solidity has the habit of initializing every variable to its default value. A newly created `Token` would return 0 for both `token.start` and `token.end`. The parser uses `startSet` to distinguish a newly initialized token from a token whose object actually starts at position 0 in the string.\n\n## Installation\nThe library is available on [Github](https://github.com/chrisdotn/jsmnSol) or on the [Ethereum Package Manager](https://www.ethpm.com/) `ethpm` as package `jsmnsol-lib`. If you are using truffle you can easily include the library by running `truffle install jsmnsol-lib`.\n\n## Usage\n**Note:** _The following description is valid for version 0.1.x of the parser, which is the beta release. If the version is >0.1.x at the time of reading, please refer to the Github repo for a more recent documentation._\n\nThe library basically requires only one call: `function parse(string json, uint numberElements) internal returns (uint, Token[], uint)`. This call takes two input parameters:\n- `string json`: The string containing the JSON\n- `uint numberOfT3okens`: The maximum number of tokens to allocate for parsing. This parameter ensures reasonable gas consumption. Whenever the string has more objects than `numberOfTokens` allows, the parser returns with an error.\n\nAfter parsing, it returns the three values `(uint returnCode, Token[] tokens, uint actualNumber)`. These are:\n- `uint returnCode`: The `returnCode` indicates whether or not the call was successful. A value of `0` shows a successful parsing, any non-zero value marks an error. The valid values are:\n```\nuint constant RETURN_SUCCESS = 0;\nuint constant RETURN_ERROR_INVALID_JSON = 1;\nuint constant RETURN_ERROR_PART = 2;\nuint constant RETURN_ERROR_NO_MEM = 3;\n```\n\n- `Token[] tokens`: The array with the actual result of the parsing, the tokens. It has `tokens.length == numberElements` (i.e. the value of the input parameter), but not all tokens have useful values.\n- `uint actualNumber`: The number of parsed tokens in `tokens`. Only tokens from `0`–`(actualNumber-1)` contain useful tokens. The remaining values in the array (`actualNumber`–`tokens.length`) only contain the default values and can be disregarded for further processing.\n\n### A Simple Example\nThe JSON that we want to parse is this:\n```\n{\n    \"key1\": {\n        \"key1.1\": \"value\",\n        \"key1.2\": 3,\n        \"key1.3\": true\n    }\n}\n```\n\nThe actual JSON that we pass to the parser is a minified version of the JSON above so that we have the following string: `{ \"key1\": { \"key1.1\": \"value\", \"key1.2\": 3, \"key1.3\": true } }`.\n\nAfter a call to `parse(json, 10)`, the parser would return three values:\n - `uint`: The return value. It is zero for _success_ and non-zero for _errors_\n - `Token[]`: An array of tokens. The array has 10 elements.\n - `uint`: The number of tokens returned. This number is generally less than the length of the token array. It should be used to access the tokens. Indices greater than the number of elements return a default token.\n\n The token array would look like this:\n\n| # | JsmnType  | start | end | startSet | endSet | size |\n|---|-----------|-------|-----|----------|--------|------|\n| 0 | OBJECT    |     0 |  62 | true     | true   |    1 |\n| 1 | STRING    |     3 |   7 | true     | true   |    1 |\n| 2 | OBJECT    |    10 |  60 | true     | true   |    3 |\n| 3 | STRING    |    13 |  19 | true     | true   |    1 |\n| 4 | STRING    |    23 |  28 | true     | true   |    0 |\n| 5 | STRING    |    32 |  38 | true     | true   |    1 |\n| 6 | PRIMITIVE |    41 |  42 | true     | true   |    0 |\n| 7 | STRING    |    45 |  51 | true     | true   |    1 |\n| 8 | PRIMITIVE |    54 |  58 | true     | true   |    0 |\n| 9 | UNDEFINED |     0 |   0 | false    | false  |    0 |\n\n## Use Case: Response Data From an Oracle\nOne of the possible use cases for the parser is processing an oracle response. For instance, if you are using oraclize.it as oracle, the data that is returned in the callback is most likely a JSON string that is the result of a call to a REST API. Usually these responses include all kinds of data that is probably not relevant for the smart contract. It might, however, be the case that the contract is not only interested in one specific datum from the JSON, but more than one. An example would be a bet for a football match: A call to an API (this one specifically is the response of `GET https://api.football-data.org/v1/fixtures/152250?head2head=0`) returns the result of the match as JSON:\n```\n{\n    \"fixture\": {\n        \"_links\": {\n            \"self\": {\n                \"href\": \"http://api.football-data.org/v1/fixtures/152250\"\n            },\n            \"competition\": {\n                \"href\": \"http://api.football-data.org/v1/competitions/430\"\n            },\n            \"homeTeam\": {\n                \"href\": \"http://api.football-data.org/v1/teams/16\"\n            },\n            \"awayTeam\": {\n                \"href\": \"http://api.football-data.org/v1/teams/11\"\n            }\n        },\n        \"date\": \"2016-08-27T13:30:00Z\",\n        \"status\": \"FINISHED\",\n        \"matchday\": 1,\n        \"homeTeamName\": \"FC Augsburg\",\n        \"awayTeamName\": \"VfL Wolfsburg\",\n        \"result\": {\n            \"goalsHomeTeam\": 0,\n            \"goalsAwayTeam\": 2\n        },\n        \"odds\": {\n            \"homeWin\": 3.0,\n            \"draw\": 3.3,\n            \"awayWin\": 2.37\n        }\n    }\n}\n```\n\nFor winner determination the only interesting part of that response is the `result` part of the response. From that result part, we need two elements, namely the number for `goalsHomeTeam` and the number of `goalsAwayTeam`. We need to compare the numbers to decide on the winner of the match. There are two steps to facilitate processing of the response:\n\n### Reduce The Result to Fewer Elements...\nThe first step to make that reponse useful is to reduce it to the actually needed parts. oraclize.it provides a means to filter a response from a server with [JSONPath](http://goessner.net/articles/JsonPath/)). By filtering the response with `$.fixture.result` oraclize would only return the following part of the JSON to our smart contract (again as a minified string actually):\n```\n{\n    \"goalsHomeTeam\": 0,\n    \"goalsAwayTeam\": 2\n}\n```\n\n### ...And Parse Them\nThis bit is much less expensive to process on-chain. We can use the parser to parse this string. It would return the following tokens:\n\n| # | JsmnType  | start | end | startSet | endSet | size |\n|---|-----------|-------|-----|----------|--------|------|\n| 0 | OBJECT    |     0 |  42 | true     | true   |    2 |\n| 1 | STRING    |     3 |  16 | true     | true   |    1 |\n| 2 | PRIMITIVE |    19 |  20 | true     | true   |    0 |\n| 3 | STRING    |    23 |  36 | true     | true   |    1 |\n| 4 | PRIMITIVE |    39 |  40 | true     | true   |    0 |\n\nNow we can use the two tokens `token[2]` and `token[4]` to access the two interesting numbers. To extract the substring for `token[2]` we would call: `string goalsHT_string = getBytes(json, token[2].start, token[2].end)`. This call returns a string. To do useful comparisons on the actual numbers, we still need to convert that string to a `uint`. A call to `uint goalsHT = parseInt(goalsHT_string)` accomplishes that.\n\nThis procedure of combining a filter on the result via JSONPath and then parsing the result with the parser allows processing of oracle responses with a smart contract.\n\n# Final Words\nThis parser is still in _beta_; this is its first release. Because of the gas cost it should not be used to parse large JSON files as that will most likely fail. String processing is computation intensive and thus expensive. However, for small JSONs (possibly already reduced by a suitable JSONPath) it can be economical to parse them on-chain and save another call to an oracle to get another part of the JSON.\n\nIf you find the library useful, I would appreciate a comment or a donation. Issues and or feature request can be filed on [Github](https://github.com/chrisdotn/jsmnSol).",
      "json_metadata": "{\"tags\":[\"json\",\"ethereum\",\"cryptocurrency\",\"development\"],\"links\":[\"https://www.truffleframework.com\",\"https://oraclize.it\",\"https://github.com/zserge/jsmn\",\"https://github.com/chrisdotn/jsmnSol\",\"https://www.ethpm.com/\",\"http://goessner.net/articles/JsonPath/\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
      "parent_author": "",
      "parent_permlink": "json",
      "permlink": "a-json-parser-for-solidity",
      "title": "A JSON Parser For Solidity"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2017-10-31T15:06:09",
  "trx_id": "fdf2acd07d2ee4e61c1f596e7d30b92c04b46f3c",
  "trx_in_block": 33,
  "virtual_op": 0
}
2017/10/31 15:05:57
authorchrisdotn
body# A JSON Parser For Solidity **Because smart contract development is still in its infant stages, there aren't many libraries around. In particular – when dealing with oracle responses – the lack of a proper JSON parser is painful. Thus, I created one that is hopefully useful and makes dealing with JSON in Solidity a bit easier.** Developing smart contracts in Ethereum has become easier with the advent of frameworks such as [Truffle](https://www.truffleframework.com) and services such as [oraclize.it](https://oraclize.it). In particular, using oracles to access information that is external to the blockchain has become simple enough for contract development. However, most of the data that is fed into the blockchain via transactions from oracles comes in as JSON formatted data. This requires a smart contract to parse a JSON object to process the data supplied by an oracle. String processing is particularly expensive on the Ethereum blockchain. Thus, the JSON parser should be ‟lightweight” and not use much computation for parsing and processing a JSON string. As there was not JSON parser for Solidity that I'm aware of, I set out to create my own. As a basis I ported the code from [jsmn](https://github.com/zserge/jsmn) to Solidity. The main design consideration of jsmn is parsing a JSON string in a single pass and avoid copying substrings along the way. Thus, the parser only generates _meta data_ on the provided string that can be used for locating and accessing objects later on. ## Single Pass, Fixed Memory, No Copying The parser works by parsing the supplied string character by character once. Along the way it creates tokens, which each identify an object in the string and indicate its starting and ending position in the string. A `token` has this structure: ``` struct Token { JsmnType jsmnType; uint start; bool startSet; uint end; bool endSet; uint8 size; } ``` The `JsmnType` encodes the type of the token. Valid values are: ``` enum JsmnType { UNDEFINED, OBJECT, ARRAY, STRING, PRIMITIVE } ``` Note that `number`, `boolean` and `null` are all treated as `JsmnType.PRIMITIVE`. They can be distinguished by evaluating the first character of the token. Next are the two values `start` and `end`. They encode the starting and the ending position of the substring identifying the object. The `size` indicates the number of sub-objects for that object (that is the number of children in the JSON hierarchy). For technical reasons there are two more variables (`startSet` and `endSet`) that are `false` on initialization and flip to `true` once the values for `start` or `end` have been set by the parse. They are needed because Solidity has the habit of initializing every variable to its default value. A newly created `Token` would return 0 for both `token.start` and `token.end`. The parser uses `startSet` to distinguish a newly initialized token from a token whose object actually starts at position 0 in the string. ## Installation The library is available on [Github](https://github.com/chrisdotn/jsmnSol) or on the [Ethereum Package Manager](https://www.ethpm.com/) `ethpm` as package `jsmnsol-lib`. If you are using truffle you can easily include the library by running `truffle install jsmnsol-lib`. ## Usage **Note:** _The following description is valid for version 0.1.x of the parser, which is the beta release. If the version is >0.1.x at the time of reading, please refer to the Github repo for a more recent documentation._ The library basically requires only one call: `function parse(string json, uint numberElements) internal returns (uint, Token[], uint)`. This call takes two input parameters: - `string json`: The string containing the JSON - `uint numberOfT3okens`: The maximum number of tokens to allocate for parsing. This parameter ensures reasonable gas consumption. Whenever the string has more objects than `numberOfTokens` allows, the parser returns with an error. After parsing, it returns the three values `(uint returnCode, Token[] tokens, uint actualNumber)`. These are: - `uint returnCode`: The `returnCode` indicates whether or not the call was successful. A value of `0` shows a successful parsing, any non-zero value marks an error. The valid values are: ``` uint constant RETURN_SUCCESS = 0; uint constant RETURN_ERROR_INVALID_JSON = 1; uint constant RETURN_ERROR_PART = 2; uint constant RETURN_ERROR_NO_MEM = 3; ``` - `Token[] tokens`: The array with the actual result of the parsing, the tokens. It has `tokens.length == numberElements` (i.e. the value of the input parameter), but not all tokens have useful values. - `uint actualNumber`: The number of parsed tokens in `tokens`. Only tokens from `0`–`(actualNumber-1)` contain useful tokens. The remaining values in the array (`actualNumber`–`tokens.length`) only contain the default values and can be disregarded for further processing. ### A Simple Example The JSON that we want to parse is this: ``` { "key1": { "key1.1": "value", "key1.2": 3, "key1.3": true } } ``` The actual JSON that we pass to the parser is a minified version of the JSON above so that we have the following string: `{ "key1": { "key1.1": "value", "key1.2": 3, "key1.3": true } }`. After a call to `parse(json, 10)`, the parser would return three values: - `uint`: The return value. It is zero for _success_ and non-zero for _errors_ - `Token[]`: An array of tokens. The array has 10 elements. - `uint`: The number of tokens returned. This number is generally less than the length of the token array. It should be used to access the tokens. Indices greater than the number of elements return a default token. The token array would look like this: | # | JsmnType | start | end | startSet | endSet | size | |---|-----------|-------|-----|----------|--------|------| | 0 | OBJECT | 0 | 62 | true | true | 1 | | 1 | STRING | 3 | 7 | true | true | 1 | | 2 | OBJECT | 10 | 60 | true | true | 3 | | 3 | STRING | 13 | 19 | true | true | 1 | | 4 | STRING | 23 | 28 | true | true | 0 | | 5 | STRING | 32 | 38 | true | true | 1 | | 6 | PRIMITIVE | 41 | 42 | true | true | 0 | | 7 | STRING | 45 | 51 | true | true | 1 | | 8 | PRIMITIVE | 54 | 58 | true | true | 0 | | 9 | UNDEFINED | 0 | 0 | false | false | 0 | ## Use Case: Response Data From an Oracle One of the possible use cases for the parser is processing an oracle response. For instance, if you are using oraclize.it as oracle, the data that is returned in the callback is most likely a JSON string that is the result of a call to a REST API. Usually these responses include all kinds of data that is probably not relevant for the smart contract. It might, however, be the case that the contract is not only interested in one specific datum from the JSON, but more than one. An example would be a bet for a football match: A call to an API (this one specifically is the response of `GET https://api.football-data.org/v1/fixtures/152250?head2head=0`) returns the result of the match as JSON: ``` { "fixture": { "_links": { "self": { "href": "http://api.football-data.org/v1/fixtures/152250" }, "competition": { "href": "http://api.football-data.org/v1/competitions/430" }, "homeTeam": { "href": "http://api.football-data.org/v1/teams/16" }, "awayTeam": { "href": "http://api.football-data.org/v1/teams/11" } }, "date": "2016-08-27T13:30:00Z", "status": "FINISHED", "matchday": 1, "homeTeamName": "FC Augsburg", "awayTeamName": "VfL Wolfsburg", "result": { "goalsHomeTeam": 0, "goalsAwayTeam": 2 }, "odds": { "homeWin": 3.0, "draw": 3.3, "awayWin": 2.37 } } } ``` For winner determination the only interesting part of that response is the `result` part of the response. From that result part, we need two elements, namely the number for `goalsHomeTeam` and the number of `goalsAwayTeam`. We need to compare the numbers to decide on the winner of the match. There are two steps to facilitate processing of the response: ### Reduce The Result to Fewer Elements... The first step to make that reponse useful is to reduce it to the actually needed parts. oraclize.it provides a means to filter a response from a server with [JSONPath](http://goessner.net/articles/JsonPath/)). By filtering the response with `$.fixture.result` oraclize would only return the following part of the JSON to our smart contract (again as a minified string actually): ``` { "goalsHomeTeam": 0, "goalsAwayTeam": 2 } ``` ### ...And Parse Them This bit is much less expensive to process on-chain. We can use the parser to parse this string. It would return the following tokens: | # | JsmnType | start | end | startSet | endSet | size | |---|-----------|-------|-----|----------|--------|------| | 0 | OBJECT | 0 | 42 | true | true | 2 | | 1 | STRING | 3 | 16 | true | true | 1 | | 2 | PRIMITIVE | 19 | 20 | true | true | 0 | | 3 | STRING | 23 | 36 | true | true | 1 | | 4 | PRIMITIVE | 39 | 40 | true | true | 0 | Now we can use the two tokens `token[2]` and `token[4]` to access the two interesting numbers. To extract the substring for `token[2]` we would call: `string goalsHT_string = getBytes(json, token[2].start, token[2].end)`. This call returns a string. To do useful comparisons on the actual numbers, we still need to convert that string to a `uint`. A call to `uint goalsHT = parseInt(goalsHT_string)` accomplishes that. This procedure of combining a filter on the result via JSONPath and then parsing the result with the parser allows processing of oracle responses with a smart contract. # Final Words This parser is still in _beta_; this is its first release. Because of the gas cost it should not be used to parse large JSON files as that will most likely fail. String processing is computation intensive and thus expensive. However, for small JSONs (possibly already reduced by a suitable JSONPath) it can be economical to parse them on-chain and save another call to an oracle to get another part of the JSON. If you find the library useful, I would appreciate a comment or a donation. Issues and or feature request can be filed on [Github](https://github.com/chrisdotn/jsmnSol).
json metadata{"tags":["json","ethereum","cryptocurrency","development"],"links":["https://www.truffleframework.com","https://oraclize.it","https://github.com/zserge/jsmn","https://github.com/chrisdotn/jsmnSol","https://www.ethpm.com/","http://goessner.net/articles/JsonPath/"],"app":"steemit/0.1","format":"markdown"}
parent author
parent permlinkjson
permlinka-json-parser-for-solidity
titleA JSON Parser For Solidity
Transaction InfoBlock #16814873/Trx 2f6cb432ffe2f9505ad74b3929f0b9df0d9b462c
View Raw JSON Data
{
  "block": 16814873,
  "op": [
    "comment",
    {
      "author": "chrisdotn",
      "body": "# A JSON Parser For Solidity\n**Because smart contract development is still in its infant stages, there aren't many libraries around. In particular – when dealing with oracle responses – the lack of a proper JSON parser is painful. Thus, I created one that is hopefully useful and makes dealing with JSON in Solidity a bit easier.**\n\nDeveloping smart contracts in Ethereum has become easier with the advent of frameworks such as [Truffle](https://www.truffleframework.com) and services such as [oraclize.it](https://oraclize.it). In particular, using oracles to access information that is external to the blockchain has become simple enough for contract development. However, most of the data that is fed into the blockchain via transactions from oracles comes in as JSON formatted data. This requires a smart contract to parse a JSON object to process the data supplied by an oracle.\n\nString processing is particularly expensive on the Ethereum blockchain. Thus, the JSON parser should be ‟lightweight” and not use much computation for parsing and processing a JSON string.\n\nAs there was not JSON parser for Solidity that I'm aware of, I set out to create my own. As a basis I ported the code from [jsmn](https://github.com/zserge/jsmn) to Solidity. The main design consideration of jsmn is parsing a JSON string in a single pass and avoid copying substrings along the way. Thus, the parser only generates _meta data_ on the provided string that can be used for locating and accessing objects later on.\n\n## Single Pass, Fixed Memory, No Copying\nThe parser works by parsing the supplied string character by character once. Along the way it creates tokens, which each identify an object in the string and indicate its starting and ending position in the string. A `token` has this structure:\n```\nstruct Token {\n    JsmnType jsmnType;\n    uint start;\n    bool startSet;\n    uint end;\n    bool endSet;\n    uint8 size;\n}\n```\n\nThe `JsmnType` encodes the type of the token. Valid values are:\n```\nenum JsmnType { UNDEFINED, OBJECT, ARRAY, STRING, PRIMITIVE }\n```\n\nNote that `number`, `boolean` and `null` are all treated as `JsmnType.PRIMITIVE`. They can be distinguished by evaluating the first character of the token.\n\nNext are the two values `start` and `end`. They encode the starting and the ending position of the substring identifying the object. The `size` indicates the number of sub-objects for that object (that is the number of children in the JSON hierarchy). For technical reasons there are two more variables (`startSet` and `endSet`) that are `false` on initialization and flip to `true` once the values for `start` or `end` have been set by the parse. They are needed because Solidity has the habit of initializing every variable to its default value. A newly created `Token` would return 0 for both `token.start` and `token.end`. The parser uses `startSet` to distinguish a newly initialized token from a token whose object actually starts at position 0 in the string.\n\n## Installation\nThe library is available on [Github](https://github.com/chrisdotn/jsmnSol) or on the [Ethereum Package Manager](https://www.ethpm.com/) `ethpm` as package `jsmnsol-lib`. If you are using truffle you can easily include the library by running `truffle install jsmnsol-lib`.\n\n## Usage\n**Note:** _The following description is valid for version 0.1.x of the parser, which is the beta release. If the version is >0.1.x at the time of reading, please refer to the Github repo for a more recent documentation._\n\nThe library basically requires only one call: `function parse(string json, uint numberElements) internal returns (uint, Token[], uint)`. This call takes two input parameters:\n- `string json`: The string containing the JSON\n- `uint numberOfT3okens`: The maximum number of tokens to allocate for parsing. This parameter ensures reasonable gas consumption. Whenever the string has more objects than `numberOfTokens` allows, the parser returns with an error.\n\nAfter parsing, it returns the three values `(uint returnCode, Token[] tokens, uint actualNumber)`. These are:\n- `uint returnCode`: The `returnCode` indicates whether or not the call was successful. A value of `0` shows a successful parsing, any non-zero value marks an error. The valid values are:\n```\nuint constant RETURN_SUCCESS = 0;\nuint constant RETURN_ERROR_INVALID_JSON = 1;\nuint constant RETURN_ERROR_PART = 2;\nuint constant RETURN_ERROR_NO_MEM = 3;\n```\n\n- `Token[] tokens`: The array with the actual result of the parsing, the tokens. It has `tokens.length == numberElements` (i.e. the value of the input parameter), but not all tokens have useful values.\n- `uint actualNumber`: The number of parsed tokens in `tokens`. Only tokens from `0`–`(actualNumber-1)` contain useful tokens. The remaining values in the array (`actualNumber`–`tokens.length`) only contain the default values and can be disregarded for further processing.\n\n### A Simple Example\nThe JSON that we want to parse is this:\n```\n{\n    \"key1\": {\n        \"key1.1\": \"value\",\n        \"key1.2\": 3,\n        \"key1.3\": true\n    }\n}\n```\n\nThe actual JSON that we pass to the parser is a minified version of the JSON above so that we have the following string: `{ \"key1\": { \"key1.1\": \"value\", \"key1.2\": 3, \"key1.3\": true } }`.\n\nAfter a call to `parse(json, 10)`, the parser would return three values:\n - `uint`: The return value. It is zero for _success_ and non-zero for _errors_\n - `Token[]`: An array of tokens. The array has 10 elements.\n - `uint`: The number of tokens returned. This number is generally less than the length of the token array. It should be used to access the tokens. Indices greater than the number of elements return a default token.\n\n The token array would look like this:\n\n| # | JsmnType  | start | end | startSet | endSet | size |\n|---|-----------|-------|-----|----------|--------|------|\n| 0 | OBJECT    |     0 |  62 | true     | true   |    1 |\n| 1 | STRING    |     3 |   7 | true     | true   |    1 |\n| 2 | OBJECT    |    10 |  60 | true     | true   |    3 |\n| 3 | STRING    |    13 |  19 | true     | true   |    1 |\n| 4 | STRING    |    23 |  28 | true     | true   |    0 |\n| 5 | STRING    |    32 |  38 | true     | true   |    1 |\n| 6 | PRIMITIVE |    41 |  42 | true     | true   |    0 |\n| 7 | STRING    |    45 |  51 | true     | true   |    1 |\n| 8 | PRIMITIVE |    54 |  58 | true     | true   |    0 |\n| 9 | UNDEFINED |     0 |   0 | false    | false  |    0 |\n\n## Use Case: Response Data From an Oracle\nOne of the possible use cases for the parser is processing an oracle response. For instance, if you are using oraclize.it as oracle, the data that is returned in the callback is most likely a JSON string that is the result of a call to a REST API. Usually these responses include all kinds of data that is probably not relevant for the smart contract. It might, however, be the case that the contract is not only interested in one specific datum from the JSON, but more than one. An example would be a bet for a football match: A call to an API (this one specifically is the response of `GET https://api.football-data.org/v1/fixtures/152250?head2head=0`) returns the result of the match as JSON:\n```\n{\n    \"fixture\": {\n        \"_links\": {\n            \"self\": {\n                \"href\": \"http://api.football-data.org/v1/fixtures/152250\"\n            },\n            \"competition\": {\n                \"href\": \"http://api.football-data.org/v1/competitions/430\"\n            },\n            \"homeTeam\": {\n                \"href\": \"http://api.football-data.org/v1/teams/16\"\n            },\n            \"awayTeam\": {\n                \"href\": \"http://api.football-data.org/v1/teams/11\"\n            }\n        },\n        \"date\": \"2016-08-27T13:30:00Z\",\n        \"status\": \"FINISHED\",\n        \"matchday\": 1,\n        \"homeTeamName\": \"FC Augsburg\",\n        \"awayTeamName\": \"VfL Wolfsburg\",\n        \"result\": {\n            \"goalsHomeTeam\": 0,\n            \"goalsAwayTeam\": 2\n        },\n        \"odds\": {\n            \"homeWin\": 3.0,\n            \"draw\": 3.3,\n            \"awayWin\": 2.37\n        }\n    }\n}\n```\n\nFor winner determination the only interesting part of that response is the `result` part of the response. From that result part, we need two elements, namely the number for `goalsHomeTeam` and the number of `goalsAwayTeam`. We need to compare the numbers to decide on the winner of the match. There are two steps to facilitate processing of the response:\n\n### Reduce The Result to Fewer Elements...\nThe first step to make that reponse useful is to reduce it to the actually needed parts. oraclize.it provides a means to filter a response from a server with [JSONPath](http://goessner.net/articles/JsonPath/)). By filtering the response with `$.fixture.result` oraclize would only return the following part of the JSON to our smart contract (again as a minified string actually):\n```\n{\n    \"goalsHomeTeam\": 0,\n    \"goalsAwayTeam\": 2\n}\n```\n\n### ...And Parse Them\nThis bit is much less expensive to process on-chain. We can use the parser to parse this string. It would return the following tokens:\n\n| # | JsmnType  | start | end | startSet | endSet | size |\n|---|-----------|-------|-----|----------|--------|------|\n| 0 | OBJECT    |     0 |  42 | true     | true   |    2 |\n| 1 | STRING    |     3 |  16 | true     | true   |    1 |\n| 2 | PRIMITIVE |    19 |  20 | true     | true   |    0 |\n| 3 | STRING    |    23 |  36 | true     | true   |    1 |\n| 4 | PRIMITIVE |    39 |  40 | true     | true   |    0 |\n\nNow we can use the two tokens `token[2]` and `token[4]` to access the two interesting numbers. To extract the substring for `token[2]` we would call: `string goalsHT_string = getBytes(json, token[2].start, token[2].end)`. This call returns a string. To do useful comparisons on the actual numbers, we still need to convert that string to a `uint`. A call to `uint goalsHT = parseInt(goalsHT_string)` accomplishes that.\n\nThis procedure of combining a filter on the result via JSONPath and then parsing the result with the parser allows processing of oracle responses with a smart contract.\n\n# Final Words\nThis parser is still in _beta_; this is its first release. Because of the gas cost it should not be used to parse large JSON files as that will most likely fail. String processing is computation intensive and thus expensive. However, for small JSONs (possibly already reduced by a suitable JSONPath) it can be economical to parse them on-chain and save another call to an oracle to get another part of the JSON.\n\nIf you find the library useful, I would appreciate a comment or a donation. Issues and or feature request can be filed on [Github](https://github.com/chrisdotn/jsmnSol).",
      "json_metadata": "{\"tags\":[\"json\",\"ethereum\",\"cryptocurrency\",\"development\"],\"links\":[\"https://www.truffleframework.com\",\"https://oraclize.it\",\"https://github.com/zserge/jsmn\",\"https://github.com/chrisdotn/jsmnSol\",\"https://www.ethpm.com/\",\"http://goessner.net/articles/JsonPath/\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
      "parent_author": "",
      "parent_permlink": "json",
      "permlink": "a-json-parser-for-solidity",
      "title": "A JSON Parser For Solidity"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2017-10-31T15:05:57",
  "trx_id": "2f6cb432ffe2f9505ad74b3929f0b9df0d9b462c",
  "trx_in_block": 0,
  "virtual_op": 0
}
2017/10/31 15:05:48
authorchrisdotn
body# A JSON Parser For Solidity **Because smart contract development is still in its infant stages, there aren't many libraries around. In particular – when dealing with oracle responses – the lack of a proper JSON parser is painful. Thus, I created one that is hopefully useful and makes dealing with JSON in Solidity a bit easier.** Developing smart contracts in Ethereum has become easier with the advent of frameworks such as [Truffle](https://www.truffleframework.com) and services such as [oraclize.it](https://oraclize.it). In particular, using oracles to access information that is external to the blockchain has become simple enough for contract development. However, most of the data that is fed into the blockchain via transactions from oracles comes in as JSON formatted data. This requires a smart contract to parse a JSON object to process the data supplied by an oracle. String processing is particularly expensive on the Ethereum blockchain. Thus, the JSON parser should be ‟lightweight” and not use much computation for parsing and processing a JSON string. As there was not JSON parser for Solidity that I'm aware of, I set out to create my own. As a basis I ported the code from [jsmn](https://github.com/zserge/jsmn) to Solidity. The main design consideration of jsmn is parsing a JSON string in a single pass and avoid copying substrings along the way. Thus, the parser only generates _meta data_ on the provided string that can be used for locating and accessing objects later on. ## Single Pass, Fixed Memory, No Copying The parser works by parsing the supplied string character by character once. Along the way it creates tokens, which each identify an object in the string and indicate its starting and ending position in the string. A `token` has this structure: ``` struct Token { JsmnType jsmnType; uint start; bool startSet; uint end; bool endSet; uint8 size; } ``` The `JsmnType` encodes the type of the token. Valid values are: ``` enum JsmnType { UNDEFINED, OBJECT, ARRAY, STRING, PRIMITIVE } ``` Note that `number`, `boolean` and `null` are all treated as `JsmnType.PRIMITIVE`. They can be distinguished by evaluating the first character of the token. Next are the two values `start` and `end`. They encode the starting and the ending position of the substring identifying the object. The `size` indicates the number of sub-objects for that object (that is the number of children in the JSON hierarchy). For technical reasons there are two more variables (`startSet` and `endSet`) that are `false` on initialization and flip to `true` once the values for `start` or `end` have been set by the parse. They are needed because Solidity has the habit of initializing every variable to its default value. A newly created `Token` would return 0 for both `token.start` and `token.end`. The parser uses `startSet` to distinguish a newly initialized token from a token whose object actually starts at position 0 in the string. ## Installation The library is available on [Github](https://github.com/chrisdotn/jsmnSol) or on the [Ethereum Package Manager](https://www.ethpm.com/) `ethpm` as package `jsmnsol-lib`. If you are using truffle you can easily include the library by running `truffle install jsmnsol-lib`. ## Usage **Note:** _The following description is valid for version 0.1.x of the parser, which is the beta release. If the version is >0.1.x at the time of reading, please refer to the Github repo for a more recent documentation._ The library basically requires only one call: `function parse(string json, uint numberElements) internal returns (uint, Token[], uint)`. This call takes two input parameters: - `string json`: The string containing the JSON - `uint numberOfT3okens`: The maximum number of tokens to allocate for parsing. This parameter ensures reasonable gas consumption. Whenever the string has more objects than `numberOfTokens` allows, the parser returns with an error. After parsing, it returns the three values `(uint returnCode, Token[] tokens, uint actualNumber)`. These are: - `uint returnCode`: The `returnCode` indicates whether or not the call was successful. A value of `0` shows a successful parsing, any non-zero value marks an error. The valid values are: ``` uint constant RETURN_SUCCESS = 0; uint constant RETURN_ERROR_INVALID_JSON = 1; uint constant RETURN_ERROR_PART = 2; uint constant RETURN_ERROR_NO_MEM = 3; ``` - `Token[] tokens`: The array with the actual result of the parsing, the tokens. It has `tokens.length == numberElements` (i.e. the value of the input parameter), but not all tokens have useful values. - `uint actualNumber`: The number of parsed tokens in `tokens`. Only tokens from `0`–`(actualNumber-1)` contain useful tokens. The remaining values in the array (`actualNumber`–`tokens.length`) only contain the default values and can be disregarded for further processing. ### A Simple Example The JSON that we want to parse is this: ``` { "key1": { "key1.1": "value", "key1.2": 3, "key1.3": true } } ``` The actual JSON that we pass to the parser is a minified version of the JSON above so that we have the following string: `{ "key1": { "key1.1": "value", "key1.2": 3, "key1.3": true } }`. After a call to `parse(json, 10)`, the parser would return three values: - `uint`: The return value. It is zero for _success_ and non-zero for _errors_ - `Token[]`: An array of tokens. The array has 10 elements. - `uint`: The number of tokens returned. This number is generally less than the length of the token array. It should be used to access the tokens. Indices greater than the number of elements return a default token. The token array would look like this: | # | JsmnType | start | end | startSet | endSet | size | |---|-----------|-------|-----|----------|--------|------| | 0 | OBJECT | 0 | 62 | true | true | 1 | | 1 | STRING | 3 | 7 | true | true | 1 | | 2 | OBJECT | 10 | 60 | true | true | 3 | | 3 | STRING | 13 | 19 | true | true | 1 | | 4 | STRING | 23 | 28 | true | true | 0 | | 5 | STRING | 32 | 38 | true | true | 1 | | 6 | PRIMITIVE | 41 | 42 | true | true | 0 | | 7 | STRING | 45 | 51 | true | true | 1 | | 8 | PRIMITIVE | 54 | 58 | true | true | 0 | | 9 | UNDEFINED | 0 | 0 | false | false | 0 | ## Use Case: Response Data From an Oracle One of the possible use cases for the parser is processing an oracle response. For instance, if you are using oraclize.it as oracle, the data that is returned in the callback is most likely a JSON string that is the result of a call to a REST API. Usually these responses include all kinds of data that is probably not relevant for the smart contract. It might, however, be the case that the contract is not only interested in one specific datum from the JSON, but more than one. An example would be a bet for a football match: A call to an API (this one specifically is the response of `GET https://api.football-data.org/v1/fixtures/152250?head2head=0`) returns the result of the match as JSON: ``` { "fixture": { "_links": { "self": { "href": "http://api.football-data.org/v1/fixtures/152250" }, "competition": { "href": "http://api.football-data.org/v1/competitions/430" }, "homeTeam": { "href": "http://api.football-data.org/v1/teams/16" }, "awayTeam": { "href": "http://api.football-data.org/v1/teams/11" } }, "date": "2016-08-27T13:30:00Z", "status": "FINISHED", "matchday": 1, "homeTeamName": "FC Augsburg", "awayTeamName": "VfL Wolfsburg", "result": { "goalsHomeTeam": 0, "goalsAwayTeam": 2 }, "odds": { "homeWin": 3.0, "draw": 3.3, "awayWin": 2.37 } } } ``` For winner determination the only interesting part of that response is the `result` part of the response. From that result part, we need two elements, namely the number for `goalsHomeTeam` and the number of `goalsAwayTeam`. We need to compare the numbers to decide on the winner of the match. There are two steps to facilitate processing of the response: ### Reduce The Result to Fewer Elements... The first step to make that reponse useful is to reduce it to the actually needed parts. oraclize.it provides a means to filter a response from a server with [JSONPath](http://goessner.net/articles/JsonPath/)). By filtering the response with `$.fixture.result` oraclize would only return the following part of the JSON to our smart contract (again as a minified string actually): ``` { "goalsHomeTeam": 0, "goalsAwayTeam": 2 } ``` ### ...And Parse Them This bit is much less expensive to process on-chain. We can use the parser to parse this string. It would return the following tokens: | # | JsmnType | start | end | startSet | endSet | size | |---|-----------|-------|-----|----------|--------|------| | 0 | OBJECT | 0 | 42 | true | true | 2 | | 1 | STRING | 3 | 16 | true | true | 1 | | 2 | PRIMITIVE | 19 | 20 | true | true | 0 | | 3 | STRING | 23 | 36 | true | true | 1 | | 4 | PRIMITIVE | 39 | 40 | true | true | 0 | Now we can use the two tokens `token[2]` and `token[4]` to access the two interesting numbers. To extract the substring for `token[2]` we would call: `string goalsHT_string = getBytes(json, token[2].start, token[2].end)`. This call returns a string. To do useful comparisons on the actual numbers, we still need to convert that string to a `uint`. A call to `uint goalsHT = parseInt(goalsHT_string)` accomplishes that. This procedure of combining a filter on the result via JSONPath and then parsing the result with the parser allows processing of oracle responses with a smart contract. # Final Words This parser is still in _beta_; this is its first release. Because of the gas cost it should not be used to parse large JSON files as that will most likely fail. String processing is computation intensive and thus expensive. However, for small JSONs (possibly already reduced by a suitable JSONPath) it can be economical to parse them on-chain and save another call to an oracle to get another part of the JSON. If you find the library useful, I would appreciate a comment or a donation. Issues and or feature request can be filed on [Github](https://github.com/chrisdotn/jsmnSol).
json metadata{"tags":["json","ethereum","cryptocurrency","development"],"links":["https://www.truffleframework.com","https://oraclize.it","https://github.com/zserge/jsmn","https://github.com/chrisdotn/jsmnSol","https://www.ethpm.com/","http://goessner.net/articles/JsonPath/"],"app":"steemit/0.1","format":"markdown"}
parent author
parent permlinkjson
permlinka-json-parser-for-solidity
titleA JSON Parser For Solidity
Transaction InfoBlock #16814870/Trx 62f0bba359065eea254bc6c5cc87cb7971f108b8
View Raw JSON Data
{
  "block": 16814870,
  "op": [
    "comment",
    {
      "author": "chrisdotn",
      "body": "# A JSON Parser For Solidity\n**Because smart contract development is still in its infant stages, there aren't many libraries around. In particular – when dealing with oracle responses – the lack of a proper JSON parser is painful. Thus, I created one that is hopefully useful and makes dealing with JSON in Solidity a bit easier.**\n\nDeveloping smart contracts in Ethereum has become easier with the advent of frameworks such as [Truffle](https://www.truffleframework.com) and services such as [oraclize.it](https://oraclize.it). In particular, using oracles to access information that is external to the blockchain has become simple enough for contract development. However, most of the data that is fed into the blockchain via transactions from oracles comes in as JSON formatted data. This requires a smart contract to parse a JSON object to process the data supplied by an oracle.\n\nString processing is particularly expensive on the Ethereum blockchain. Thus, the JSON parser should be ‟lightweight” and not use much computation for parsing and processing a JSON string.\n\nAs there was not JSON parser for Solidity that I'm aware of, I set out to create my own. As a basis I ported the code from [jsmn](https://github.com/zserge/jsmn) to Solidity. The main design consideration of jsmn is parsing a JSON string in a single pass and avoid copying substrings along the way. Thus, the parser only generates _meta data_ on the provided string that can be used for locating and accessing objects later on.\n\n## Single Pass, Fixed Memory, No Copying\nThe parser works by parsing the supplied string character by character once. Along the way it creates tokens, which each identify an object in the string and indicate its starting and ending position in the string. A `token` has this structure:\n```\nstruct Token {\n    JsmnType jsmnType;\n    uint start;\n    bool startSet;\n    uint end;\n    bool endSet;\n    uint8 size;\n}\n```\n\nThe `JsmnType` encodes the type of the token. Valid values are:\n```\nenum JsmnType { UNDEFINED, OBJECT, ARRAY, STRING, PRIMITIVE }\n```\n\nNote that `number`, `boolean` and `null` are all treated as `JsmnType.PRIMITIVE`. They can be distinguished by evaluating the first character of the token.\n\nNext are the two values `start` and `end`. They encode the starting and the ending position of the substring identifying the object. The `size` indicates the number of sub-objects for that object (that is the number of children in the JSON hierarchy). For technical reasons there are two more variables (`startSet` and `endSet`) that are `false` on initialization and flip to `true` once the values for `start` or `end` have been set by the parse. They are needed because Solidity has the habit of initializing every variable to its default value. A newly created `Token` would return 0 for both `token.start` and `token.end`. The parser uses `startSet` to distinguish a newly initialized token from a token whose object actually starts at position 0 in the string.\n\n## Installation\nThe library is available on [Github](https://github.com/chrisdotn/jsmnSol) or on the [Ethereum Package Manager](https://www.ethpm.com/) `ethpm` as package `jsmnsol-lib`. If you are using truffle you can easily include the library by running `truffle install jsmnsol-lib`.\n\n## Usage\n**Note:** _The following description is valid for version 0.1.x of the parser, which is the beta release. If the version is >0.1.x at the time of reading, please refer to the Github repo for a more recent documentation._\n\nThe library basically requires only one call: `function parse(string json, uint numberElements) internal returns (uint, Token[], uint)`. This call takes two input parameters:\n- `string json`: The string containing the JSON\n- `uint numberOfT3okens`: The maximum number of tokens to allocate for parsing. This parameter ensures reasonable gas consumption. Whenever the string has more objects than `numberOfTokens` allows, the parser returns with an error.\n\nAfter parsing, it returns the three values `(uint returnCode, Token[] tokens, uint actualNumber)`. These are:\n- `uint returnCode`: The `returnCode` indicates whether or not the call was successful. A value of `0` shows a successful parsing, any non-zero value marks an error. The valid values are:\n```\nuint constant RETURN_SUCCESS = 0;\nuint constant RETURN_ERROR_INVALID_JSON = 1;\nuint constant RETURN_ERROR_PART = 2;\nuint constant RETURN_ERROR_NO_MEM = 3;\n```\n\n- `Token[] tokens`: The array with the actual result of the parsing, the tokens. It has `tokens.length == numberElements` (i.e. the value of the input parameter), but not all tokens have useful values.\n- `uint actualNumber`: The number of parsed tokens in `tokens`. Only tokens from `0`–`(actualNumber-1)` contain useful tokens. The remaining values in the array (`actualNumber`–`tokens.length`) only contain the default values and can be disregarded for further processing.\n\n### A Simple Example\nThe JSON that we want to parse is this:\n```\n{\n    \"key1\": {\n        \"key1.1\": \"value\",\n        \"key1.2\": 3,\n        \"key1.3\": true\n    }\n}\n```\n\nThe actual JSON that we pass to the parser is a minified version of the JSON above so that we have the following string: `{ \"key1\": { \"key1.1\": \"value\", \"key1.2\": 3, \"key1.3\": true } }`.\n\nAfter a call to `parse(json, 10)`, the parser would return three values:\n - `uint`: The return value. It is zero for _success_ and non-zero for _errors_\n - `Token[]`: An array of tokens. The array has 10 elements.\n - `uint`: The number of tokens returned. This number is generally less than the length of the token array. It should be used to access the tokens. Indices greater than the number of elements return a default token.\n\n The token array would look like this:\n\n| # | JsmnType  | start | end | startSet | endSet | size |\n|---|-----------|-------|-----|----------|--------|------|\n| 0 | OBJECT    |     0 |  62 | true     | true   |    1 |\n| 1 | STRING    |     3 |   7 | true     | true   |    1 |\n| 2 | OBJECT    |    10 |  60 | true     | true   |    3 |\n| 3 | STRING    |    13 |  19 | true     | true   |    1 |\n| 4 | STRING    |    23 |  28 | true     | true   |    0 |\n| 5 | STRING    |    32 |  38 | true     | true   |    1 |\n| 6 | PRIMITIVE |    41 |  42 | true     | true   |    0 |\n| 7 | STRING    |    45 |  51 | true     | true   |    1 |\n| 8 | PRIMITIVE |    54 |  58 | true     | true   |    0 |\n| 9 | UNDEFINED |     0 |   0 | false    | false  |    0 |\n\n## Use Case: Response Data From an Oracle\nOne of the possible use cases for the parser is processing an oracle response. For instance, if you are using oraclize.it as oracle, the data that is returned in the callback is most likely a JSON string that is the result of a call to a REST API. Usually these responses include all kinds of data that is probably not relevant for the smart contract. It might, however, be the case that the contract is not only interested in one specific datum from the JSON, but more than one. An example would be a bet for a football match: A call to an API (this one specifically is the response of `GET https://api.football-data.org/v1/fixtures/152250?head2head=0`) returns the result of the match as JSON:\n```\n{\n    \"fixture\": {\n        \"_links\": {\n            \"self\": {\n                \"href\": \"http://api.football-data.org/v1/fixtures/152250\"\n            },\n            \"competition\": {\n                \"href\": \"http://api.football-data.org/v1/competitions/430\"\n            },\n            \"homeTeam\": {\n                \"href\": \"http://api.football-data.org/v1/teams/16\"\n            },\n            \"awayTeam\": {\n                \"href\": \"http://api.football-data.org/v1/teams/11\"\n            }\n        },\n        \"date\": \"2016-08-27T13:30:00Z\",\n        \"status\": \"FINISHED\",\n        \"matchday\": 1,\n        \"homeTeamName\": \"FC Augsburg\",\n        \"awayTeamName\": \"VfL Wolfsburg\",\n        \"result\": {\n            \"goalsHomeTeam\": 0,\n            \"goalsAwayTeam\": 2\n        },\n        \"odds\": {\n            \"homeWin\": 3.0,\n            \"draw\": 3.3,\n            \"awayWin\": 2.37\n        }\n    }\n}\n```\n\nFor winner determination the only interesting part of that response is the `result` part of the response. From that result part, we need two elements, namely the number for `goalsHomeTeam` and the number of `goalsAwayTeam`. We need to compare the numbers to decide on the winner of the match. There are two steps to facilitate processing of the response:\n\n### Reduce The Result to Fewer Elements...\nThe first step to make that reponse useful is to reduce it to the actually needed parts. oraclize.it provides a means to filter a response from a server with [JSONPath](http://goessner.net/articles/JsonPath/)). By filtering the response with `$.fixture.result` oraclize would only return the following part of the JSON to our smart contract (again as a minified string actually):\n```\n{\n    \"goalsHomeTeam\": 0,\n    \"goalsAwayTeam\": 2\n}\n```\n\n### ...And Parse Them\nThis bit is much less expensive to process on-chain. We can use the parser to parse this string. It would return the following tokens:\n\n| # | JsmnType  | start | end | startSet | endSet | size |\n|---|-----------|-------|-----|----------|--------|------|\n| 0 | OBJECT    |     0 |  42 | true     | true   |    2 |\n| 1 | STRING    |     3 |  16 | true     | true   |    1 |\n| 2 | PRIMITIVE |    19 |  20 | true     | true   |    0 |\n| 3 | STRING    |    23 |  36 | true     | true   |    1 |\n| 4 | PRIMITIVE |    39 |  40 | true     | true   |    0 |\n\nNow we can use the two tokens `token[2]` and `token[4]` to access the two interesting numbers. To extract the substring for `token[2]` we would call: `string goalsHT_string = getBytes(json, token[2].start, token[2].end)`. This call returns a string. To do useful comparisons on the actual numbers, we still need to convert that string to a `uint`. A call to `uint goalsHT = parseInt(goalsHT_string)` accomplishes that.\n\nThis procedure of combining a filter on the result via JSONPath and then parsing the result with the parser allows processing of oracle responses with a smart contract.\n\n# Final Words\nThis parser is still in _beta_; this is its first release. Because of the gas cost it should not be used to parse large JSON files as that will most likely fail. String processing is computation intensive and thus expensive. However, for small JSONs (possibly already reduced by a suitable JSONPath) it can be economical to parse them on-chain and save another call to an oracle to get another part of the JSON.\n\nIf you find the library useful, I would appreciate a comment or a donation. Issues and or feature request can be filed on [Github](https://github.com/chrisdotn/jsmnSol).",
      "json_metadata": "{\"tags\":[\"json\",\"ethereum\",\"cryptocurrency\",\"development\"],\"links\":[\"https://www.truffleframework.com\",\"https://oraclize.it\",\"https://github.com/zserge/jsmn\",\"https://github.com/chrisdotn/jsmnSol\",\"https://www.ethpm.com/\",\"http://goessner.net/articles/JsonPath/\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
      "parent_author": "",
      "parent_permlink": "json",
      "permlink": "a-json-parser-for-solidity",
      "title": "A JSON Parser For Solidity"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2017-10-31T15:05:48",
  "trx_id": "62f0bba359065eea254bc6c5cc87cb7971f108b8",
  "trx_in_block": 9,
  "virtual_op": 0
}
2017/10/31 15:05:39
authorchrisdotn
body# A JSON Parser For Solidity **Because smart contract development is still in its infant stages, there aren't many libraries around. In particular – when dealing with oracle responses – the lack of a proper JSON parser is painful. Thus, I created one that is hopefully useful and makes dealing with JSON in Solidity a bit easier.** Developing smart contracts in Ethereum has become easier with the advent of frameworks such as [Truffle](https://www.truffleframework.com) and services such as [oraclize.it](https://oraclize.it). In particular, using oracles to access information that is external to the blockchain has become simple enough for contract development. However, most of the data that is fed into the blockchain via transactions from oracles comes in as JSON formatted data. This requires a smart contract to parse a JSON object to process the data supplied by an oracle. String processing is particularly expensive on the Ethereum blockchain. Thus, the JSON parser should be ‟lightweight” and not use much computation for parsing and processing a JSON string. As there was not JSON parser for Solidity that I'm aware of, I set out to create my own. As a basis I ported the code from [jsmn](https://github.com/zserge/jsmn) to Solidity. The main design consideration of jsmn is parsing a JSON string in a single pass and avoid copying substrings along the way. Thus, the parser only generates _meta data_ on the provided string that can be used for locating and accessing objects later on. ## Single Pass, Fixed Memory, No Copying The parser works by parsing the supplied string character by character once. Along the way it creates tokens, which each identify an object in the string and indicate its starting and ending position in the string. A `token` has this structure: ``` struct Token { JsmnType jsmnType; uint start; bool startSet; uint end; bool endSet; uint8 size; } ``` The `JsmnType` encodes the type of the token. Valid values are: ``` enum JsmnType { UNDEFINED, OBJECT, ARRAY, STRING, PRIMITIVE } ``` Note that `number`, `boolean` and `null` are all treated as `JsmnType.PRIMITIVE`. They can be distinguished by evaluating the first character of the token. Next are the two values `start` and `end`. They encode the starting and the ending position of the substring identifying the object. The `size` indicates the number of sub-objects for that object (that is the number of children in the JSON hierarchy). For technical reasons there are two more variables (`startSet` and `endSet`) that are `false` on initialization and flip to `true` once the values for `start` or `end` have been set by the parse. They are needed because Solidity has the habit of initializing every variable to its default value. A newly created `Token` would return 0 for both `token.start` and `token.end`. The parser uses `startSet` to distinguish a newly initialized token from a token whose object actually starts at position 0 in the string. ## Installation The library is available on [Github](https://github.com/chrisdotn/jsmnSol) or on the [Ethereum Package Manager](https://www.ethpm.com/) `ethpm` as package `jsmnsol-lib`. If you are using truffle you can easily include the library by running `truffle install jsmnsol-lib`. ## Usage **Note:** _The following description is valid for version 0.1.x of the parser, which is the beta release. If the version is >0.1.x at the time of reading, please refer to the Github repo for a more recent documentation._ The library basically requires only one call: `function parse(string json, uint numberElements) internal returns (uint, Token[], uint)`. This call takes two input parameters: - `string json`: The string containing the JSON - `uint numberOfT3okens`: The maximum number of tokens to allocate for parsing. This parameter ensures reasonable gas consumption. Whenever the string has more objects than `numberOfTokens` allows, the parser returns with an error. After parsing, it returns the three values `(uint returnCode, Token[] tokens, uint actualNumber)`. These are: - `uint returnCode`: The `returnCode` indicates whether or not the call was successful. A value of `0` shows a successful parsing, any non-zero value marks an error. The valid values are: ``` uint constant RETURN_SUCCESS = 0; uint constant RETURN_ERROR_INVALID_JSON = 1; uint constant RETURN_ERROR_PART = 2; uint constant RETURN_ERROR_NO_MEM = 3; ``` - `Token[] tokens`: The array with the actual result of the parsing, the tokens. It has `tokens.length == numberElements` (i.e. the value of the input parameter), but not all tokens have useful values. - `uint actualNumber`: The number of parsed tokens in `tokens`. Only tokens from `0`–`(actualNumber-1)` contain useful tokens. The remaining values in the array (`actualNumber`–`tokens.length`) only contain the default values and can be disregarded for further processing. ### A Simple Example The JSON that we want to parse is this: ``` { "key1": { "key1.1": "value", "key1.2": 3, "key1.3": true } } ``` The actual JSON that we pass to the parser is a minified version of the JSON above so that we have the following string: `{ "key1": { "key1.1": "value", "key1.2": 3, "key1.3": true } }`. After a call to `parse(json, 10)`, the parser would return three values: - `uint`: The return value. It is zero for _success_ and non-zero for _errors_ - `Token[]`: An array of tokens. The array has 10 elements. - `uint`: The number of tokens returned. This number is generally less than the length of the token array. It should be used to access the tokens. Indices greater than the number of elements return a default token. The token array would look like this: | # | JsmnType | start | end | startSet | endSet | size | |---|-----------|-------|-----|----------|--------|------| | 0 | OBJECT | 0 | 62 | true | true | 1 | | 1 | STRING | 3 | 7 | true | true | 1 | | 2 | OBJECT | 10 | 60 | true | true | 3 | | 3 | STRING | 13 | 19 | true | true | 1 | | 4 | STRING | 23 | 28 | true | true | 0 | | 5 | STRING | 32 | 38 | true | true | 1 | | 6 | PRIMITIVE | 41 | 42 | true | true | 0 | | 7 | STRING | 45 | 51 | true | true | 1 | | 8 | PRIMITIVE | 54 | 58 | true | true | 0 | | 9 | UNDEFINED | 0 | 0 | false | false | 0 | ## Use Case: Response Data From an Oracle One of the possible use cases for the parser is processing an oracle response. For instance, if you are using oraclize.it as oracle, the data that is returned in the callback is most likely a JSON string that is the result of a call to a REST API. Usually these responses include all kinds of data that is probably not relevant for the smart contract. It might, however, be the case that the contract is not only interested in one specific datum from the JSON, but more than one. An example would be a bet for a football match: A call to an API (this one specifically is the response of `GET https://api.football-data.org/v1/fixtures/152250?head2head=0`) returns the result of the match as JSON: ``` { "fixture": { "_links": { "self": { "href": "http://api.football-data.org/v1/fixtures/152250" }, "competition": { "href": "http://api.football-data.org/v1/competitions/430" }, "homeTeam": { "href": "http://api.football-data.org/v1/teams/16" }, "awayTeam": { "href": "http://api.football-data.org/v1/teams/11" } }, "date": "2016-08-27T13:30:00Z", "status": "FINISHED", "matchday": 1, "homeTeamName": "FC Augsburg", "awayTeamName": "VfL Wolfsburg", "result": { "goalsHomeTeam": 0, "goalsAwayTeam": 2 }, "odds": { "homeWin": 3.0, "draw": 3.3, "awayWin": 2.37 } } } ``` For winner determination the only interesting part of that response is the `result` part of the response. From that result part, we need two elements, namely the number for `goalsHomeTeam` and the number of `goalsAwayTeam`. We need to compare the numbers to decide on the winner of the match. There are two steps to facilitate processing of the response: ### Reduce The Result to Fewer Elements... The first step to make that reponse useful is to reduce it to the actually needed parts. oraclize.it provides a means to filter a response from a server with [JSONPath](http://goessner.net/articles/JsonPath/)). By filtering the response with `$.fixture.result` oraclize would only return the following part of the JSON to our smart contract (again as a minified string actually): ``` { "goalsHomeTeam": 0, "goalsAwayTeam": 2 } ``` ### ...And Parse Them This bit is much less expensive to process on-chain. We can use the parser to parse this string. It would return the following tokens: | # | JsmnType | start | end | startSet | endSet | size | |---|-----------|-------|-----|----------|--------|------| | 0 | OBJECT | 0 | 42 | true | true | 2 | | 1 | STRING | 3 | 16 | true | true | 1 | | 2 | PRIMITIVE | 19 | 20 | true | true | 0 | | 3 | STRING | 23 | 36 | true | true | 1 | | 4 | PRIMITIVE | 39 | 40 | true | true | 0 | Now we can use the two tokens `token[2]` and `token[4]` to access the two interesting numbers. To extract the substring for `token[2]` we would call: `string goalsHT_string = getBytes(json, token[2].start, token[2].end)`. This call returns a string. To do useful comparisons on the actual numbers, we still need to convert that string to a `uint`. A call to `uint goalsHT = parseInt(goalsHT_string)` accomplishes that. This procedure of combining a filter on the result via JSONPath and then parsing the result with the parser allows processing of oracle responses with a smart contract. # Final Words This parser is still in _beta_; this is its first release. Because of the gas cost it should not be used to parse large JSON files as that will most likely fail. String processing is computation intensive and thus expensive. However, for small JSONs (possibly already reduced by a suitable JSONPath) it can be economical to parse them on-chain and save another call to an oracle to get another part of the JSON. If you find the library useful, I would appreciate a comment or a donation. Issues and or feature request can be filed on [Github](https://github.com/chrisdotn/jsmnSol).
json metadata{"tags":["json","ethereum","cryptocurreny","development"],"links":["https://www.truffleframework.com","https://oraclize.it","https://github.com/zserge/jsmn","https://github.com/chrisdotn/jsmnSol","https://www.ethpm.com/","http://goessner.net/articles/JsonPath/"],"app":"steemit/0.1","format":"markdown"}
parent author
parent permlinkjson
permlinka-json-parser-for-solidity
titleA JSON Parser For Solidity
Transaction InfoBlock #16814867/Trx 5924d2dda3f2008e70daf6112f28f98621774665
View Raw JSON Data
{
  "block": 16814867,
  "op": [
    "comment",
    {
      "author": "chrisdotn",
      "body": "# A JSON Parser For Solidity\n**Because smart contract development is still in its infant stages, there aren't many libraries around. In particular – when dealing with oracle responses – the lack of a proper JSON parser is painful. Thus, I created one that is hopefully useful and makes dealing with JSON in Solidity a bit easier.**\n\nDeveloping smart contracts in Ethereum has become easier with the advent of frameworks such as [Truffle](https://www.truffleframework.com) and services such as [oraclize.it](https://oraclize.it). In particular, using oracles to access information that is external to the blockchain has become simple enough for contract development. However, most of the data that is fed into the blockchain via transactions from oracles comes in as JSON formatted data. This requires a smart contract to parse a JSON object to process the data supplied by an oracle.\n\nString processing is particularly expensive on the Ethereum blockchain. Thus, the JSON parser should be ‟lightweight” and not use much computation for parsing and processing a JSON string.\n\nAs there was not JSON parser for Solidity that I'm aware of, I set out to create my own. As a basis I ported the code from [jsmn](https://github.com/zserge/jsmn) to Solidity. The main design consideration of jsmn is parsing a JSON string in a single pass and avoid copying substrings along the way. Thus, the parser only generates _meta data_ on the provided string that can be used for locating and accessing objects later on.\n\n## Single Pass, Fixed Memory, No Copying\nThe parser works by parsing the supplied string character by character once. Along the way it creates tokens, which each identify an object in the string and indicate its starting and ending position in the string. A `token` has this structure:\n```\nstruct Token {\n    JsmnType jsmnType;\n    uint start;\n    bool startSet;\n    uint end;\n    bool endSet;\n    uint8 size;\n}\n```\n\nThe `JsmnType` encodes the type of the token. Valid values are:\n```\nenum JsmnType { UNDEFINED, OBJECT, ARRAY, STRING, PRIMITIVE }\n```\n\nNote that `number`, `boolean` and `null` are all treated as `JsmnType.PRIMITIVE`. They can be distinguished by evaluating the first character of the token.\n\nNext are the two values `start` and `end`. They encode the starting and the ending position of the substring identifying the object. The `size` indicates the number of sub-objects for that object (that is the number of children in the JSON hierarchy). For technical reasons there are two more variables (`startSet` and `endSet`) that are `false` on initialization and flip to `true` once the values for `start` or `end` have been set by the parse. They are needed because Solidity has the habit of initializing every variable to its default value. A newly created `Token` would return 0 for both `token.start` and `token.end`. The parser uses `startSet` to distinguish a newly initialized token from a token whose object actually starts at position 0 in the string.\n\n## Installation\nThe library is available on [Github](https://github.com/chrisdotn/jsmnSol) or on the [Ethereum Package Manager](https://www.ethpm.com/) `ethpm` as package `jsmnsol-lib`. If you are using truffle you can easily include the library by running `truffle install jsmnsol-lib`.\n\n## Usage\n**Note:** _The following description is valid for version 0.1.x of the parser, which is the beta release. If the version is >0.1.x at the time of reading, please refer to the Github repo for a more recent documentation._\n\nThe library basically requires only one call: `function parse(string json, uint numberElements) internal returns (uint, Token[], uint)`. This call takes two input parameters:\n- `string json`: The string containing the JSON\n- `uint numberOfT3okens`: The maximum number of tokens to allocate for parsing. This parameter ensures reasonable gas consumption. Whenever the string has more objects than `numberOfTokens` allows, the parser returns with an error.\n\nAfter parsing, it returns the three values `(uint returnCode, Token[] tokens, uint actualNumber)`. These are:\n- `uint returnCode`: The `returnCode` indicates whether or not the call was successful. A value of `0` shows a successful parsing, any non-zero value marks an error. The valid values are:\n```\nuint constant RETURN_SUCCESS = 0;\nuint constant RETURN_ERROR_INVALID_JSON = 1;\nuint constant RETURN_ERROR_PART = 2;\nuint constant RETURN_ERROR_NO_MEM = 3;\n```\n\n- `Token[] tokens`: The array with the actual result of the parsing, the tokens. It has `tokens.length == numberElements` (i.e. the value of the input parameter), but not all tokens have useful values.\n- `uint actualNumber`: The number of parsed tokens in `tokens`. Only tokens from `0`–`(actualNumber-1)` contain useful tokens. The remaining values in the array (`actualNumber`–`tokens.length`) only contain the default values and can be disregarded for further processing.\n\n### A Simple Example\nThe JSON that we want to parse is this:\n```\n{\n    \"key1\": {\n        \"key1.1\": \"value\",\n        \"key1.2\": 3,\n        \"key1.3\": true\n    }\n}\n```\n\nThe actual JSON that we pass to the parser is a minified version of the JSON above so that we have the following string: `{ \"key1\": { \"key1.1\": \"value\", \"key1.2\": 3, \"key1.3\": true } }`.\n\nAfter a call to `parse(json, 10)`, the parser would return three values:\n - `uint`: The return value. It is zero for _success_ and non-zero for _errors_\n - `Token[]`: An array of tokens. The array has 10 elements.\n - `uint`: The number of tokens returned. This number is generally less than the length of the token array. It should be used to access the tokens. Indices greater than the number of elements return a default token.\n\n The token array would look like this:\n\n| # | JsmnType  | start | end | startSet | endSet | size |\n|---|-----------|-------|-----|----------|--------|------|\n| 0 | OBJECT    |     0 |  62 | true     | true   |    1 |\n| 1 | STRING    |     3 |   7 | true     | true   |    1 |\n| 2 | OBJECT    |    10 |  60 | true     | true   |    3 |\n| 3 | STRING    |    13 |  19 | true     | true   |    1 |\n| 4 | STRING    |    23 |  28 | true     | true   |    0 |\n| 5 | STRING    |    32 |  38 | true     | true   |    1 |\n| 6 | PRIMITIVE |    41 |  42 | true     | true   |    0 |\n| 7 | STRING    |    45 |  51 | true     | true   |    1 |\n| 8 | PRIMITIVE |    54 |  58 | true     | true   |    0 |\n| 9 | UNDEFINED |     0 |   0 | false    | false  |    0 |\n\n## Use Case: Response Data From an Oracle\nOne of the possible use cases for the parser is processing an oracle response. For instance, if you are using oraclize.it as oracle, the data that is returned in the callback is most likely a JSON string that is the result of a call to a REST API. Usually these responses include all kinds of data that is probably not relevant for the smart contract. It might, however, be the case that the contract is not only interested in one specific datum from the JSON, but more than one. An example would be a bet for a football match: A call to an API (this one specifically is the response of `GET https://api.football-data.org/v1/fixtures/152250?head2head=0`) returns the result of the match as JSON:\n```\n{\n    \"fixture\": {\n        \"_links\": {\n            \"self\": {\n                \"href\": \"http://api.football-data.org/v1/fixtures/152250\"\n            },\n            \"competition\": {\n                \"href\": \"http://api.football-data.org/v1/competitions/430\"\n            },\n            \"homeTeam\": {\n                \"href\": \"http://api.football-data.org/v1/teams/16\"\n            },\n            \"awayTeam\": {\n                \"href\": \"http://api.football-data.org/v1/teams/11\"\n            }\n        },\n        \"date\": \"2016-08-27T13:30:00Z\",\n        \"status\": \"FINISHED\",\n        \"matchday\": 1,\n        \"homeTeamName\": \"FC Augsburg\",\n        \"awayTeamName\": \"VfL Wolfsburg\",\n        \"result\": {\n            \"goalsHomeTeam\": 0,\n            \"goalsAwayTeam\": 2\n        },\n        \"odds\": {\n            \"homeWin\": 3.0,\n            \"draw\": 3.3,\n            \"awayWin\": 2.37\n        }\n    }\n}\n```\n\nFor winner determination the only interesting part of that response is the `result` part of the response. From that result part, we need two elements, namely the number for `goalsHomeTeam` and the number of `goalsAwayTeam`. We need to compare the numbers to decide on the winner of the match. There are two steps to facilitate processing of the response:\n\n### Reduce The Result to Fewer Elements...\nThe first step to make that reponse useful is to reduce it to the actually needed parts. oraclize.it provides a means to filter a response from a server with [JSONPath](http://goessner.net/articles/JsonPath/)). By filtering the response with `$.fixture.result` oraclize would only return the following part of the JSON to our smart contract (again as a minified string actually):\n```\n{\n    \"goalsHomeTeam\": 0,\n    \"goalsAwayTeam\": 2\n}\n```\n\n### ...And Parse Them\nThis bit is much less expensive to process on-chain. We can use the parser to parse this string. It would return the following tokens:\n\n| # | JsmnType  | start | end | startSet | endSet | size |\n|---|-----------|-------|-----|----------|--------|------|\n| 0 | OBJECT    |     0 |  42 | true     | true   |    2 |\n| 1 | STRING    |     3 |  16 | true     | true   |    1 |\n| 2 | PRIMITIVE |    19 |  20 | true     | true   |    0 |\n| 3 | STRING    |    23 |  36 | true     | true   |    1 |\n| 4 | PRIMITIVE |    39 |  40 | true     | true   |    0 |\n\nNow we can use the two tokens `token[2]` and `token[4]` to access the two interesting numbers. To extract the substring for `token[2]` we would call: `string goalsHT_string = getBytes(json, token[2].start, token[2].end)`. This call returns a string. To do useful comparisons on the actual numbers, we still need to convert that string to a `uint`. A call to `uint goalsHT = parseInt(goalsHT_string)` accomplishes that.\n\nThis procedure of combining a filter on the result via JSONPath and then parsing the result with the parser allows processing of oracle responses with a smart contract.\n\n# Final Words\nThis parser is still in _beta_; this is its first release. Because of the gas cost it should not be used to parse large JSON files as that will most likely fail. String processing is computation intensive and thus expensive. However, for small JSONs (possibly already reduced by a suitable JSONPath) it can be economical to parse them on-chain and save another call to an oracle to get another part of the JSON.\n\nIf you find the library useful, I would appreciate a comment or a donation. Issues and or feature request can be filed on [Github](https://github.com/chrisdotn/jsmnSol).",
      "json_metadata": "{\"tags\":[\"json\",\"ethereum\",\"cryptocurreny\",\"development\"],\"links\":[\"https://www.truffleframework.com\",\"https://oraclize.it\",\"https://github.com/zserge/jsmn\",\"https://github.com/chrisdotn/jsmnSol\",\"https://www.ethpm.com/\",\"http://goessner.net/articles/JsonPath/\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
      "parent_author": "",
      "parent_permlink": "json",
      "permlink": "a-json-parser-for-solidity",
      "title": "A JSON Parser For Solidity"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2017-10-31T15:05:39",
  "trx_id": "5924d2dda3f2008e70daf6112f28f98621774665",
  "trx_in_block": 18,
  "virtual_op": 0
}
2017/10/31 15:05:24
authorchrisdotn
body# A JSON Parser For Solidity **Because smart contract development is still in its infant stages, there aren't many libraries around. In particular – when dealing with oracle responses – the lack of a proper JSON parser is painful. Thus, I created one that is hopefully useful and makes dealing with JSON in Solidity a bit easier.** Developing smart contracts in Ethereum has become easier with the advent of frameworks such as [Truffle](https://www.truffleframework.com) and services such as [oraclize.it](https://oraclize.it). In particular, using oracles to access information that is external to the blockchain has become simple enough for contract development. However, most of the data that is fed into the blockchain via transactions from oracles comes in as JSON formatted data. This requires a smart contract to parse a JSON object to process the data supplied by an oracle. String processing is particularly expensive on the Ethereum blockchain. Thus, the JSON parser should be ‟lightweight” and not use much computation for parsing and processing a JSON string. As there was not JSON parser for Solidity that I'm aware of, I set out to create my own. As a basis I ported the code from [jsmn](https://github.com/zserge/jsmn) to Solidity. The main design consideration of jsmn is parsing a JSON string in a single pass and avoid copying substrings along the way. Thus, the parser only generates _meta data_ on the provided string that can be used for locating and accessing objects later on. ## Single Pass, Fixed Memory, No Copying The parser works by parsing the supplied string character by character once. Along the way it creates tokens, which each identify an object in the string and indicate its starting and ending position in the string. A `token` has this structure: ``` struct Token { JsmnType jsmnType; uint start; bool startSet; uint end; bool endSet; uint8 size; } ``` The `JsmnType` encodes the type of the token. Valid values are: ``` enum JsmnType { UNDEFINED, OBJECT, ARRAY, STRING, PRIMITIVE } ``` Note that `number`, `boolean` and `null` are all treated as `JsmnType.PRIMITIVE`. They can be distinguished by evaluating the first character of the token. Next are the two values `start` and `end`. They encode the starting and the ending position of the substring identifying the object. The `size` indicates the number of sub-objects for that object (that is the number of children in the JSON hierarchy). For technical reasons there are two more variables (`startSet` and `endSet`) that are `false` on initialization and flip to `true` once the values for `start` or `end` have been set by the parse. They are needed because Solidity has the habit of initializing every variable to its default value. A newly created `Token` would return 0 for both `token.start` and `token.end`. The parser uses `startSet` to distinguish a newly initialized token from a token whose object actually starts at position 0 in the string. ## Installation The library is available on [Github](https://github.com/chrisdotn/jsmnSol) or on the [Ethereum Package Manager](https://www.ethpm.com/) `ethpm` as package `jsmnsol-lib`. If you are using truffle you can easily include the library by running `truffle install jsmnsol-lib`. ## Usage **Note:** _The following description is valid for version 0.1.x of the parser, which is the beta release. If the version is >0.1.x at the time of reading, please refer to the Github repo for a more recent documentation._ The library basically requires only one call: `function parse(string json, uint numberElements) internal returns (uint, Token[], uint)`. This call takes two input parameters: - `string json`: The string containing the JSON - `uint numberOfT3okens`: The maximum number of tokens to allocate for parsing. This parameter ensures reasonable gas consumption. Whenever the string has more objects than `numberOfTokens` allows, the parser returns with an error. After parsing, it returns the three values `(uint returnCode, Token[] tokens, uint actualNumber)`. These are: - `uint returnCode`: The `returnCode` indicates whether or not the call was successful. A value of `0` shows a successful parsing, any non-zero value marks an error. The valid values are: ``` uint constant RETURN_SUCCESS = 0; uint constant RETURN_ERROR_INVALID_JSON = 1; uint constant RETURN_ERROR_PART = 2; uint constant RETURN_ERROR_NO_MEM = 3; ``` - `Token[] tokens`: The array with the actual result of the parsing, the tokens. It has `tokens.length == numberElements` (i.e. the value of the input parameter), but not all tokens have useful values. - `uint actualNumber`: The number of parsed tokens in `tokens`. Only tokens from `0`–`(actualNumber-1)` contain useful tokens. The remaining values in the array (`actualNumber`–`tokens.length`) only contain the default values and can be disregarded for further processing. ### A Simple Example The JSON that we want to parse is this: ``` { "key1": { "key1.1": "value", "key1.2": 3, "key1.3": true } } ``` The actual JSON that we pass to the parser is a minified version of the JSON above so that we have the following string: `{ "key1": { "key1.1": "value", "key1.2": 3, "key1.3": true } }`. After a call to `parse(json, 10)`, the parser would return three values: - `uint`: The return value. It is zero for _success_ and non-zero for _errors_ - `Token[]`: An array of tokens. The array has 10 elements. - `uint`: The number of tokens returned. This number is generally less than the length of the token array. It should be used to access the tokens. Indices greater than the number of elements return a default token. The token array would look like this: | # | JsmnType | start | end | startSet | endSet | size | |---|-----------|-------|-----|----------|--------|------| | 0 | OBJECT | 0 | 62 | true | true | 1 | | 1 | STRING | 3 | 7 | true | true | 1 | | 2 | OBJECT | 10 | 60 | true | true | 3 | | 3 | STRING | 13 | 19 | true | true | 1 | | 4 | STRING | 23 | 28 | true | true | 0 | | 5 | STRING | 32 | 38 | true | true | 1 | | 6 | PRIMITIVE | 41 | 42 | true | true | 0 | | 7 | STRING | 45 | 51 | true | true | 1 | | 8 | PRIMITIVE | 54 | 58 | true | true | 0 | | 9 | UNDEFINED | 0 | 0 | false | false | 0 | ## Use Case: Response Data From an Oracle One of the possible use cases for the parser is processing an oracle response. For instance, if you are using oraclize.it as oracle, the data that is returned in the callback is most likely a JSON string that is the result of a call to a REST API. Usually these responses include all kinds of data that is probably not relevant for the smart contract. It might, however, be the case that the contract is not only interested in one specific datum from the JSON, but more than one. An example would be a bet for a football match: A call to an API (this one specifically is the response of `GET https://api.football-data.org/v1/fixtures/152250?head2head=0`) returns the result of the match as JSON: ``` { "fixture": { "_links": { "self": { "href": "http://api.football-data.org/v1/fixtures/152250" }, "competition": { "href": "http://api.football-data.org/v1/competitions/430" }, "homeTeam": { "href": "http://api.football-data.org/v1/teams/16" }, "awayTeam": { "href": "http://api.football-data.org/v1/teams/11" } }, "date": "2016-08-27T13:30:00Z", "status": "FINISHED", "matchday": 1, "homeTeamName": "FC Augsburg", "awayTeamName": "VfL Wolfsburg", "result": { "goalsHomeTeam": 0, "goalsAwayTeam": 2 }, "odds": { "homeWin": 3.0, "draw": 3.3, "awayWin": 2.37 } } } ``` For winner determination the only interesting part of that response is the `result` part of the response. From that result part, we need two elements, namely the number for `goalsHomeTeam` and the number of `goalsAwayTeam`. We need to compare the numbers to decide on the winner of the match. There are two steps to facilitate processing of the response: ### Reduce The Result to Fewer Elements... The first step to make that reponse useful is to reduce it to the actually needed parts. oraclize.it provides a means to filter a response from a server with [JSONPath](http://goessner.net/articles/JsonPath/)). By filtering the response with `$.fixture.result` oraclize would only return the following part of the JSON to our smart contract (again as a minified string actually): ``` { "goalsHomeTeam": 0, "goalsAwayTeam": 2 } ``` ### ...And Parse Them This bit is much less expensive to process on-chain. We can use the parser to parse this string. It would return the following tokens: | # | JsmnType | start | end | startSet | endSet | size | |---|-----------|-------|-----|----------|--------|------| | 0 | OBJECT | 0 | 42 | true | true | 2 | | 1 | STRING | 3 | 16 | true | true | 1 | | 2 | PRIMITIVE | 19 | 20 | true | true | 0 | | 3 | STRING | 23 | 36 | true | true | 1 | | 4 | PRIMITIVE | 39 | 40 | true | true | 0 | Now we can use the two tokens `token[2]` and `token[4]` to access the two interesting numbers. To extract the substring for `token[2]` we would call: `string goalsHT_string = getBytes(json, token[2].start, token[2].end)`. This call returns a string. To do useful comparisons on the actual numbers, we still need to convert that string to a `uint`. A call to `uint goalsHT = parseInt(goalsHT_string)` accomplishes that. This procedure of combining a filter on the result via JSONPath and then parsing the result with the parser allows processing of oracle responses with a smart contract. # Final Words This parser is still in _beta_; this is its first release. Because of the gas cost it should not be used to parse large JSON files as that will most likely fail. String processing is computation intensive and thus expensive. However, for small JSONs (possibly already reduced by a suitable JSONPath) it can be economical to parse them on-chain and save another call to an oracle to get another part of the JSON. If you find the library useful, I would appreciate a comment or a donation. Issues and or feature request can be filed on [Github](https://github.com/chrisdotn/jsmnSol).
json metadata{"tags":["json","ethereum","cryptocurreny","development"],"links":["https://www.truffleframework.com","https://oraclize.it","https://github.com/zserge/jsmn","https://github.com/chrisdotn/jsmnSol","https://www.ethpm.com/","http://goessner.net/articles/JsonPath/"],"app":"steemit/0.1","format":"markdown"}
parent author
parent permlinkjson
permlinka-json-parser-for-solidity
titleA JSON Parser For Solidity
Transaction InfoBlock #16814862/Trx 733cd1848ef7ae5e5eb6f50b462292065c261ec3
View Raw JSON Data
{
  "block": 16814862,
  "op": [
    "comment",
    {
      "author": "chrisdotn",
      "body": "# A JSON Parser For Solidity\n**Because smart contract development is still in its infant stages, there aren't many libraries around. In particular – when dealing with oracle responses – the lack of a proper JSON parser is painful. Thus, I created one that is hopefully useful and makes dealing with JSON in Solidity a bit easier.**\n\nDeveloping smart contracts in Ethereum has become easier with the advent of frameworks such as [Truffle](https://www.truffleframework.com) and services such as [oraclize.it](https://oraclize.it). In particular, using oracles to access information that is external to the blockchain has become simple enough for contract development. However, most of the data that is fed into the blockchain via transactions from oracles comes in as JSON formatted data. This requires a smart contract to parse a JSON object to process the data supplied by an oracle.\n\nString processing is particularly expensive on the Ethereum blockchain. Thus, the JSON parser should be ‟lightweight” and not use much computation for parsing and processing a JSON string.\n\nAs there was not JSON parser for Solidity that I'm aware of, I set out to create my own. As a basis I ported the code from [jsmn](https://github.com/zserge/jsmn) to Solidity. The main design consideration of jsmn is parsing a JSON string in a single pass and avoid copying substrings along the way. Thus, the parser only generates _meta data_ on the provided string that can be used for locating and accessing objects later on.\n\n## Single Pass, Fixed Memory, No Copying\nThe parser works by parsing the supplied string character by character once. Along the way it creates tokens, which each identify an object in the string and indicate its starting and ending position in the string. A `token` has this structure:\n```\nstruct Token {\n    JsmnType jsmnType;\n    uint start;\n    bool startSet;\n    uint end;\n    bool endSet;\n    uint8 size;\n}\n```\n\nThe `JsmnType` encodes the type of the token. Valid values are:\n```\nenum JsmnType { UNDEFINED, OBJECT, ARRAY, STRING, PRIMITIVE }\n```\n\nNote that `number`, `boolean` and `null` are all treated as `JsmnType.PRIMITIVE`. They can be distinguished by evaluating the first character of the token.\n\nNext are the two values `start` and `end`. They encode the starting and the ending position of the substring identifying the object. The `size` indicates the number of sub-objects for that object (that is the number of children in the JSON hierarchy). For technical reasons there are two more variables (`startSet` and `endSet`) that are `false` on initialization and flip to `true` once the values for `start` or `end` have been set by the parse. They are needed because Solidity has the habit of initializing every variable to its default value. A newly created `Token` would return 0 for both `token.start` and `token.end`. The parser uses `startSet` to distinguish a newly initialized token from a token whose object actually starts at position 0 in the string.\n\n## Installation\nThe library is available on [Github](https://github.com/chrisdotn/jsmnSol) or on the [Ethereum Package Manager](https://www.ethpm.com/) `ethpm` as package `jsmnsol-lib`. If you are using truffle you can easily include the library by running `truffle install jsmnsol-lib`.\n\n## Usage\n**Note:** _The following description is valid for version 0.1.x of the parser, which is the beta release. If the version is >0.1.x at the time of reading, please refer to the Github repo for a more recent documentation._\n\nThe library basically requires only one call: `function parse(string json, uint numberElements) internal returns (uint, Token[], uint)`. This call takes two input parameters:\n- `string json`: The string containing the JSON\n- `uint numberOfT3okens`: The maximum number of tokens to allocate for parsing. This parameter ensures reasonable gas consumption. Whenever the string has more objects than `numberOfTokens` allows, the parser returns with an error.\n\nAfter parsing, it returns the three values `(uint returnCode, Token[] tokens, uint actualNumber)`. These are:\n- `uint returnCode`: The `returnCode` indicates whether or not the call was successful. A value of `0` shows a successful parsing, any non-zero value marks an error. The valid values are:\n```\nuint constant RETURN_SUCCESS = 0;\nuint constant RETURN_ERROR_INVALID_JSON = 1;\nuint constant RETURN_ERROR_PART = 2;\nuint constant RETURN_ERROR_NO_MEM = 3;\n```\n\n- `Token[] tokens`: The array with the actual result of the parsing, the tokens. It has `tokens.length == numberElements` (i.e. the value of the input parameter), but not all tokens have useful values.\n- `uint actualNumber`: The number of parsed tokens in `tokens`. Only tokens from `0`–`(actualNumber-1)` contain useful tokens. The remaining values in the array (`actualNumber`–`tokens.length`) only contain the default values and can be disregarded for further processing.\n\n### A Simple Example\nThe JSON that we want to parse is this:\n```\n{\n    \"key1\": {\n        \"key1.1\": \"value\",\n        \"key1.2\": 3,\n        \"key1.3\": true\n    }\n}\n```\n\nThe actual JSON that we pass to the parser is a minified version of the JSON above so that we have the following string: `{ \"key1\": { \"key1.1\": \"value\", \"key1.2\": 3, \"key1.3\": true } }`.\n\nAfter a call to `parse(json, 10)`, the parser would return three values:\n - `uint`: The return value. It is zero for _success_ and non-zero for _errors_\n - `Token[]`: An array of tokens. The array has 10 elements.\n - `uint`: The number of tokens returned. This number is generally less than the length of the token array. It should be used to access the tokens. Indices greater than the number of elements return a default token.\n\n The token array would look like this:\n\n| # | JsmnType  | start | end | startSet | endSet | size |\n|---|-----------|-------|-----|----------|--------|------|\n| 0 | OBJECT    |     0 |  62 | true     | true   |    1 |\n| 1 | STRING    |     3 |   7 | true     | true   |    1 |\n| 2 | OBJECT    |    10 |  60 | true     | true   |    3 |\n| 3 | STRING    |    13 |  19 | true     | true   |    1 |\n| 4 | STRING    |    23 |  28 | true     | true   |    0 |\n| 5 | STRING    |    32 |  38 | true     | true   |    1 |\n| 6 | PRIMITIVE |    41 |  42 | true     | true   |    0 |\n| 7 | STRING    |    45 |  51 | true     | true   |    1 |\n| 8 | PRIMITIVE |    54 |  58 | true     | true   |    0 |\n| 9 | UNDEFINED |     0 |   0 | false    | false  |    0 |\n\n## Use Case: Response Data From an Oracle\nOne of the possible use cases for the parser is processing an oracle response. For instance, if you are using oraclize.it as oracle, the data that is returned in the callback is most likely a JSON string that is the result of a call to a REST API. Usually these responses include all kinds of data that is probably not relevant for the smart contract. It might, however, be the case that the contract is not only interested in one specific datum from the JSON, but more than one. An example would be a bet for a football match: A call to an API (this one specifically is the response of `GET https://api.football-data.org/v1/fixtures/152250?head2head=0`) returns the result of the match as JSON:\n```\n{\n    \"fixture\": {\n        \"_links\": {\n            \"self\": {\n                \"href\": \"http://api.football-data.org/v1/fixtures/152250\"\n            },\n            \"competition\": {\n                \"href\": \"http://api.football-data.org/v1/competitions/430\"\n            },\n            \"homeTeam\": {\n                \"href\": \"http://api.football-data.org/v1/teams/16\"\n            },\n            \"awayTeam\": {\n                \"href\": \"http://api.football-data.org/v1/teams/11\"\n            }\n        },\n        \"date\": \"2016-08-27T13:30:00Z\",\n        \"status\": \"FINISHED\",\n        \"matchday\": 1,\n        \"homeTeamName\": \"FC Augsburg\",\n        \"awayTeamName\": \"VfL Wolfsburg\",\n        \"result\": {\n            \"goalsHomeTeam\": 0,\n            \"goalsAwayTeam\": 2\n        },\n        \"odds\": {\n            \"homeWin\": 3.0,\n            \"draw\": 3.3,\n            \"awayWin\": 2.37\n        }\n    }\n}\n```\n\nFor winner determination the only interesting part of that response is the `result` part of the response. From that result part, we need two elements, namely the number for `goalsHomeTeam` and the number of `goalsAwayTeam`. We need to compare the numbers to decide on the winner of the match. There are two steps to facilitate processing of the response:\n\n### Reduce The Result to Fewer Elements...\nThe first step to make that reponse useful is to reduce it to the actually needed parts. oraclize.it provides a means to filter a response from a server with [JSONPath](http://goessner.net/articles/JsonPath/)). By filtering the response with `$.fixture.result` oraclize would only return the following part of the JSON to our smart contract (again as a minified string actually):\n```\n{\n    \"goalsHomeTeam\": 0,\n    \"goalsAwayTeam\": 2\n}\n```\n\n### ...And Parse Them\nThis bit is much less expensive to process on-chain. We can use the parser to parse this string. It would return the following tokens:\n\n| # | JsmnType  | start | end | startSet | endSet | size |\n|---|-----------|-------|-----|----------|--------|------|\n| 0 | OBJECT    |     0 |  42 | true     | true   |    2 |\n| 1 | STRING    |     3 |  16 | true     | true   |    1 |\n| 2 | PRIMITIVE |    19 |  20 | true     | true   |    0 |\n| 3 | STRING    |    23 |  36 | true     | true   |    1 |\n| 4 | PRIMITIVE |    39 |  40 | true     | true   |    0 |\n\nNow we can use the two tokens `token[2]` and `token[4]` to access the two interesting numbers. To extract the substring for `token[2]` we would call: `string goalsHT_string = getBytes(json, token[2].start, token[2].end)`. This call returns a string. To do useful comparisons on the actual numbers, we still need to convert that string to a `uint`. A call to `uint goalsHT = parseInt(goalsHT_string)` accomplishes that.\n\nThis procedure of combining a filter on the result via JSONPath and then parsing the result with the parser allows processing of oracle responses with a smart contract.\n\n# Final Words\nThis parser is still in _beta_; this is its first release. Because of the gas cost it should not be used to parse large JSON files as that will most likely fail. String processing is computation intensive and thus expensive. However, for small JSONs (possibly already reduced by a suitable JSONPath) it can be economical to parse them on-chain and save another call to an oracle to get another part of the JSON.\n\nIf you find the library useful, I would appreciate a comment or a donation. Issues and or feature request can be filed on [Github](https://github.com/chrisdotn/jsmnSol).",
      "json_metadata": "{\"tags\":[\"json\",\"ethereum\",\"cryptocurreny\",\"development\"],\"links\":[\"https://www.truffleframework.com\",\"https://oraclize.it\",\"https://github.com/zserge/jsmn\",\"https://github.com/chrisdotn/jsmnSol\",\"https://www.ethpm.com/\",\"http://goessner.net/articles/JsonPath/\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
      "parent_author": "",
      "parent_permlink": "json",
      "permlink": "a-json-parser-for-solidity",
      "title": "A JSON Parser For Solidity"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2017-10-31T15:05:24",
  "trx_id": "733cd1848ef7ae5e5eb6f50b462292065c261ec3",
  "trx_in_block": 4,
  "virtual_op": 0
}
2017/10/31 15:00:51
authorchrisdotn
body# A JSON Parser For Solidity **Because smart contract development is still in its infant stages, there aren't many libraries around. In particular – when dealing with oracle responses – the lack of a proper JSON parser is painful. Thus, I created one that is hopefully useful and makes dealing with JSON in Solidity a bit easier.** Developing smart contracts in Ethereum has become easier with the advent of frameworks such as [Truffle](https://www.truffleframework.com) and services such as [oraclize.it](https://oraclize.it). In particular, using oracles to access information that is external to the blockchain has become simple enough for contract development. However, most of the data that is fed into the blockchain via transactions from oracles comes in as JSON formatted data. This requires a smart contract to parse a JSON object to process the data supplied by an oracle. String processing is particularly expensive on the Ethereum blockchain. Thus, the JSON parser should be ‟lightweight” and not use much computation for parsing and processing a JSON string. As there was not JSON parser for Solidity that I'm aware of, I set out to create my own. As a basis I ported the code from [jsmn](https://github.com/zserge/jsmn) to Solidity. The main design consideration of jsmn is parsing a JSON string in a single pass and avoid copying substrings along the way. Thus, the parser only generates _meta data_ on the provided string that can be used for locating and accessing objects later on. ## Single Pass, Fixed Memory, No Copying The parser works by parsing the supplied string character by character once. Along the way it creates tokens, which each identify an object in the string and indicate its starting and ending position in the string. A `token` has this structure: ``` struct Token { JsmnType jsmnType; uint start; bool startSet; uint end; bool endSet; uint8 size; } ``` The `JsmnType` encodes the type of the token. Valid values are: ``` enum JsmnType { UNDEFINED, OBJECT, ARRAY, STRING, PRIMITIVE } ``` Note that `number`, `boolean` and `null` are all treated as `JsmnType.PRIMITIVE`. They can be distinguished by evaluating the first character of the token. Next are the two values `start` and `end`. They encode the starting and the ending position of the substring identifying the object. The `size` indicates the number of sub-objects for that object (that is the number of children in the JSON hierarchy). For technical reasons there are two more variables (`startSet` and `endSet`) that are `false` on initialization and flip to `true` once the values for `start` or `end` have been set by the parse. They are needed because Solidity has the habit of initializing every variable to its default value. A newly created `Token` would return 0 for both `token.start` and `token.end`. The parser uses `startSet` to distinguish a newly initialized token from a token whose object actually starts at position 0 in the string. ## Installation The library is available on [Github](https://github.com/chrisdotn/jsmnSol) or on the [Ethereum Package Manager](https://www.ethpm.com/) `ethpm` as package `jsmnsol-lib`. If you are using truffle you can easily include the library by running `truffle install jsmnsol-lib`. ## Usage **Note:** _The following description is valid for version 0.1.x of the parser, which is the beta release. If the version is >0.1.x at the time of reading, please refer to the Github repo for a more recent documentation._ The library basically requires only one call: `function parse(string json, uint numberElements) internal returns (uint, Token[], uint)`. This call takes two input parameters: - `string json`: The string containing the JSON - `uint numberOfT3okens`: The maximum number of tokens to allocate for parsing. This parameter ensures reasonable gas consumption. Whenever the string has more objects than `numberOfTokens` allows, the parser returns with an error. After parsing, it returns the three values `(uint returnCode, Token[] tokens, uint actualNumber)`. These are: - `uint returnCode`: The `returnCode` indicates whether or not the call was successful. A value of `0` shows a successful parsing, any non-zero value marks an error. The valid values are: ``` uint constant RETURN_SUCCESS = 0; uint constant RETURN_ERROR_INVALID_JSON = 1; uint constant RETURN_ERROR_PART = 2; uint constant RETURN_ERROR_NO_MEM = 3; ``` - `Token[] tokens`: The array with the actual result of the parsing, the tokens. It has `tokens.length == numberElements` (i.e. the value of the input parameter), but not all tokens have useful values. - `uint actualNumber`: The number of parsed tokens in `tokens`. Only tokens from `0`–`(actualNumber-1)` contain useful tokens. The remaining values in the array (`actualNumber`–`tokens.length`) only contain the default values and can be disregarded for further processing. ### A Simple Example The JSON that we want to parse is this: ``` { "key1": { "key1.1": "value", "key1.2": 3, "key1.3": true } } ``` The actual JSON that we pass to the parser is a minified version of the JSON above so that we have the following string: `{ "key1": { "key1.1": "value", "key1.2": 3, "key1.3": true } }`. After a call to `parse(json, 10)`, the parser would return three values: - `uint`: The return value. It is zero for _success_ and non-zero for _errors_ - `Token[]`: An array of tokens. The array has 10 elements. - `uint`: The number of tokens returned. This number is generally less than the length of the token array. It should be used to access the tokens. Indices greater than the number of elements return a default token. The token array would look like this: | # | JsmnType | start | end | startSet | endSet | size | |---|-----------|-------|-----|----------|--------|------| | 0 | OBJECT | 0 | 62 | true | true | 1 | | 1 | STRING | 3 | 7 | true | true | 1 | | 2 | OBJECT | 10 | 60 | true | true | 3 | | 3 | STRING | 13 | 19 | true | true | 1 | | 4 | STRING | 23 | 28 | true | true | 0 | | 5 | STRING | 32 | 38 | true | true | 1 | | 6 | PRIMITIVE | 41 | 42 | true | true | 0 | | 7 | STRING | 45 | 51 | true | true | 1 | | 8 | PRIMITIVE | 54 | 58 | true | true | 0 | | 9 | UNDEFINED | 0 | 0 | false | false | 0 | ## Use Case: Response Data From an Oracle One of the possible use cases for the parser is processing an oracle response. For instance, if you are using oraclize.it as oracle, the data that is returned in the callback is most likely a JSON string that is the result of a call to a REST API. Usually these responses include all kinds of data that is probably not relevant for the smart contract. It might, however, be the case that the contract is not only interested in one specific datum from the JSON, but more than one. An example would be a bet for a football match: A call to an API (this one specifically is the response of `GET https://api.football-data.org/v1/fixtures/152250?head2head=0`) returns the result of the match as JSON: ``` { "fixture": { "_links": { "self": { "href": "http://api.football-data.org/v1/fixtures/152250" }, "competition": { "href": "http://api.football-data.org/v1/competitions/430" }, "homeTeam": { "href": "http://api.football-data.org/v1/teams/16" }, "awayTeam": { "href": "http://api.football-data.org/v1/teams/11" } }, "date": "2016-08-27T13:30:00Z", "status": "FINISHED", "matchday": 1, "homeTeamName": "FC Augsburg", "awayTeamName": "VfL Wolfsburg", "result": { "goalsHomeTeam": 0, "goalsAwayTeam": 2 }, "odds": { "homeWin": 3.0, "draw": 3.3, "awayWin": 2.37 } } } ``` For winner determination the only interesting part of that response is the `result` part of the response. From that result part, we need two elements, namely the number for `goalsHomeTeam` and the number of `goalsAwayTeam`. We need to compare the numbers to decide on the winner of the match. There are two steps to facilitate processing of the response: ### Reduce The Result to Fewer Elements... The first step to make that reponse useful is to reduce it to the actually needed parts. oraclize.it provides a means to filter a response from a server with [JSONPath](http://goessner.net/articles/JsonPath/)). By filtering the response with `$.fixture.result` oraclize would only return the following part of the JSON to our smart contract (again as a minified string actually): ``` { "goalsHomeTeam": 0, "goalsAwayTeam": 2 } ``` ### ...And Parse Them This bit is much less expensive to process on-chain. We can use the parser to parse this string. It would return the following tokens: | # | JsmnType | start | end | startSet | endSet | size | |---|-----------|-------|-----|----------|--------|------| | 0 | OBJECT | 0 | 42 | true | true | 2 | | 1 | STRING | 3 | 16 | true | true | 1 | | 2 | PRIMITIVE | 19 | 20 | true | true | 0 | | 3 | STRING | 23 | 36 | true | true | 1 | | 4 | PRIMITIVE | 39 | 40 | true | true | 0 | Now we can use the two tokens `token[2]` and `token[4]` to access the two interesting numbers. To extract the substring for `token[2]` we would call: `string goalsHT_string = getBytes(json, token[2].start, token[2].end)`. This call returns a string. To do useful comparisons on the actual numbers, we still need to convert that string to a `uint`. A call to `uint goalsHT = parseInt(goalsHT_string)` accomplishes that. This procedure of combining a filter on the result via JSONPath and then parsing the result with the parser allows processing of oracle responses with a smart contract. # Final Words This parser is still in _beta_; this is its first release. Because of the gas cost it should not be used to parse large JSON files as that will most likely fail. String processing is computation intensive and thus expensive. However, for small JSONs (possibly already reduced by a suitable JSONPath) it can be economical to parse them on-chain and save another call to an oracle to get another part of the JSON. If you find the library useful, I would appreciate a comment or a donation. Issues and or feature request can be filed on [Github](https://github.com/chrisdotn/jsmnSol).
json metadata{"tags":["json","ethereum","smart","contract","development"],"links":["https://www.truffleframework.com","https://oraclize.it","https://github.com/zserge/jsmn","https://github.com/chrisdotn/jsmnSol","https://www.ethpm.com/","http://goessner.net/articles/JsonPath/"],"app":"steemit/0.1","format":"markdown"}
parent author
parent permlinkjson
permlinka-json-parser-for-solidity
titleA JSON Parser For Solidity
Transaction InfoBlock #16814771/Trx 42569c0b6387da057f6b8e6106130c5a55211e18
View Raw JSON Data
{
  "block": 16814771,
  "op": [
    "comment",
    {
      "author": "chrisdotn",
      "body": "# A JSON Parser For Solidity\n**Because smart contract development is still in its infant stages, there aren't many libraries around. In particular – when dealing with oracle responses – the lack of a proper JSON parser is painful. Thus, I created one that is hopefully useful and makes dealing with JSON in Solidity a bit easier.**\n\nDeveloping smart contracts in Ethereum has become easier with the advent of frameworks such as [Truffle](https://www.truffleframework.com) and services such as [oraclize.it](https://oraclize.it). In particular, using oracles to access information that is external to the blockchain has become simple enough for contract development. However, most of the data that is fed into the blockchain via transactions from oracles comes in as JSON formatted data. This requires a smart contract to parse a JSON object to process the data supplied by an oracle.\n\nString processing is particularly expensive on the Ethereum blockchain. Thus, the JSON parser should be ‟lightweight” and not use much computation for parsing and processing a JSON string.\n\nAs there was not JSON parser for Solidity that I'm aware of, I set out to create my own. As a basis I ported the code from [jsmn](https://github.com/zserge/jsmn) to Solidity. The main design consideration of jsmn is parsing a JSON string in a single pass and avoid copying substrings along the way. Thus, the parser only generates _meta data_ on the provided string that can be used for locating and accessing objects later on.\n\n## Single Pass, Fixed Memory, No Copying\nThe parser works by parsing the supplied string character by character once. Along the way it creates tokens, which each identify an object in the string and indicate its starting and ending position in the string. A `token` has this structure:\n```\nstruct Token {\n    JsmnType jsmnType;\n    uint start;\n    bool startSet;\n    uint end;\n    bool endSet;\n    uint8 size;\n}\n```\n\nThe `JsmnType` encodes the type of the token. Valid values are:\n```\nenum JsmnType { UNDEFINED, OBJECT, ARRAY, STRING, PRIMITIVE }\n```\n\nNote that `number`, `boolean` and `null` are all treated as `JsmnType.PRIMITIVE`. They can be distinguished by evaluating the first character of the token.\n\nNext are the two values `start` and `end`. They encode the starting and the ending position of the substring identifying the object. The `size` indicates the number of sub-objects for that object (that is the number of children in the JSON hierarchy). For technical reasons there are two more variables (`startSet` and `endSet`) that are `false` on initialization and flip to `true` once the values for `start` or `end` have been set by the parse. They are needed because Solidity has the habit of initializing every variable to its default value. A newly created `Token` would return 0 for both `token.start` and `token.end`. The parser uses `startSet` to distinguish a newly initialized token from a token whose object actually starts at position 0 in the string.\n\n## Installation\nThe library is available on [Github](https://github.com/chrisdotn/jsmnSol) or on the [Ethereum Package Manager](https://www.ethpm.com/) `ethpm` as package `jsmnsol-lib`. If you are using truffle you can easily include the library by running `truffle install jsmnsol-lib`.\n\n## Usage\n**Note:** _The following description is valid for version 0.1.x of the parser, which is the beta release. If the version is >0.1.x at the time of reading, please refer to the Github repo for a more recent documentation._\n\nThe library basically requires only one call: `function parse(string json, uint numberElements) internal returns (uint, Token[], uint)`. This call takes two input parameters:\n- `string json`: The string containing the JSON\n- `uint numberOfT3okens`: The maximum number of tokens to allocate for parsing. This parameter ensures reasonable gas consumption. Whenever the string has more objects than `numberOfTokens` allows, the parser returns with an error.\n\nAfter parsing, it returns the three values `(uint returnCode, Token[] tokens, uint actualNumber)`. These are:\n- `uint returnCode`: The `returnCode` indicates whether or not the call was successful. A value of `0` shows a successful parsing, any non-zero value marks an error. The valid values are:\n```\nuint constant RETURN_SUCCESS = 0;\nuint constant RETURN_ERROR_INVALID_JSON = 1;\nuint constant RETURN_ERROR_PART = 2;\nuint constant RETURN_ERROR_NO_MEM = 3;\n```\n\n- `Token[] tokens`: The array with the actual result of the parsing, the tokens. It has `tokens.length == numberElements` (i.e. the value of the input parameter), but not all tokens have useful values.\n- `uint actualNumber`: The number of parsed tokens in `tokens`. Only tokens from `0`–`(actualNumber-1)` contain useful tokens. The remaining values in the array (`actualNumber`–`tokens.length`) only contain the default values and can be disregarded for further processing.\n\n### A Simple Example\nThe JSON that we want to parse is this:\n```\n{\n    \"key1\": {\n        \"key1.1\": \"value\",\n        \"key1.2\": 3,\n        \"key1.3\": true\n    }\n}\n```\n\nThe actual JSON that we pass to the parser is a minified version of the JSON above so that we have the following string: `{ \"key1\": { \"key1.1\": \"value\", \"key1.2\": 3, \"key1.3\": true } }`.\n\nAfter a call to `parse(json, 10)`, the parser would return three values:\n - `uint`: The return value. It is zero for _success_ and non-zero for _errors_\n - `Token[]`: An array of tokens. The array has 10 elements.\n - `uint`: The number of tokens returned. This number is generally less than the length of the token array. It should be used to access the tokens. Indices greater than the number of elements return a default token.\n\n The token array would look like this:\n\n| # | JsmnType  | start | end | startSet | endSet | size |\n|---|-----------|-------|-----|----------|--------|------|\n| 0 | OBJECT    |     0 |  62 | true     | true   |    1 |\n| 1 | STRING    |     3 |   7 | true     | true   |    1 |\n| 2 | OBJECT    |    10 |  60 | true     | true   |    3 |\n| 3 | STRING    |    13 |  19 | true     | true   |    1 |\n| 4 | STRING    |    23 |  28 | true     | true   |    0 |\n| 5 | STRING    |    32 |  38 | true     | true   |    1 |\n| 6 | PRIMITIVE |    41 |  42 | true     | true   |    0 |\n| 7 | STRING    |    45 |  51 | true     | true   |    1 |\n| 8 | PRIMITIVE |    54 |  58 | true     | true   |    0 |\n| 9 | UNDEFINED |     0 |   0 | false    | false  |    0 |\n\n## Use Case: Response Data From an Oracle\nOne of the possible use cases for the parser is processing an oracle response. For instance, if you are using oraclize.it as oracle, the data that is returned in the callback is most likely a JSON string that is the result of a call to a REST API. Usually these responses include all kinds of data that is probably not relevant for the smart contract. It might, however, be the case that the contract is not only interested in one specific datum from the JSON, but more than one. An example would be a bet for a football match: A call to an API (this one specifically is the response of `GET https://api.football-data.org/v1/fixtures/152250?head2head=0`) returns the result of the match as JSON:\n```\n{\n    \"fixture\": {\n        \"_links\": {\n            \"self\": {\n                \"href\": \"http://api.football-data.org/v1/fixtures/152250\"\n            },\n            \"competition\": {\n                \"href\": \"http://api.football-data.org/v1/competitions/430\"\n            },\n            \"homeTeam\": {\n                \"href\": \"http://api.football-data.org/v1/teams/16\"\n            },\n            \"awayTeam\": {\n                \"href\": \"http://api.football-data.org/v1/teams/11\"\n            }\n        },\n        \"date\": \"2016-08-27T13:30:00Z\",\n        \"status\": \"FINISHED\",\n        \"matchday\": 1,\n        \"homeTeamName\": \"FC Augsburg\",\n        \"awayTeamName\": \"VfL Wolfsburg\",\n        \"result\": {\n            \"goalsHomeTeam\": 0,\n            \"goalsAwayTeam\": 2\n        },\n        \"odds\": {\n            \"homeWin\": 3.0,\n            \"draw\": 3.3,\n            \"awayWin\": 2.37\n        }\n    }\n}\n```\n\nFor winner determination the only interesting part of that response is the `result` part of the response. From that result part, we need two elements, namely the number for `goalsHomeTeam` and the number of `goalsAwayTeam`. We need to compare the numbers to decide on the winner of the match. There are two steps to facilitate processing of the response:\n\n### Reduce The Result to Fewer Elements...\nThe first step to make that reponse useful is to reduce it to the actually needed parts. oraclize.it provides a means to filter a response from a server with [JSONPath](http://goessner.net/articles/JsonPath/)). By filtering the response with `$.fixture.result` oraclize would only return the following part of the JSON to our smart contract (again as a minified string actually):\n```\n{\n    \"goalsHomeTeam\": 0,\n    \"goalsAwayTeam\": 2\n}\n```\n\n### ...And Parse Them\nThis bit is much less expensive to process on-chain. We can use the parser to parse this string. It would return the following tokens:\n\n| # | JsmnType  | start | end | startSet | endSet | size |\n|---|-----------|-------|-----|----------|--------|------|\n| 0 | OBJECT    |     0 |  42 | true     | true   |    2 |\n| 1 | STRING    |     3 |  16 | true     | true   |    1 |\n| 2 | PRIMITIVE |    19 |  20 | true     | true   |    0 |\n| 3 | STRING    |    23 |  36 | true     | true   |    1 |\n| 4 | PRIMITIVE |    39 |  40 | true     | true   |    0 |\n\nNow we can use the two tokens `token[2]` and `token[4]` to access the two interesting numbers. To extract the substring for `token[2]` we would call: `string goalsHT_string = getBytes(json, token[2].start, token[2].end)`. This call returns a string. To do useful comparisons on the actual numbers, we still need to convert that string to a `uint`. A call to `uint goalsHT = parseInt(goalsHT_string)` accomplishes that.\n\nThis procedure of combining a filter on the result via JSONPath and then parsing the result with the parser allows processing of oracle responses with a smart contract.\n\n# Final Words\nThis parser is still in _beta_; this is its first release. Because of the gas cost it should not be used to parse large JSON files as that will most likely fail. String processing is computation intensive and thus expensive. However, for small JSONs (possibly already reduced by a suitable JSONPath) it can be economical to parse them on-chain and save another call to an oracle to get another part of the JSON.\n\nIf you find the library useful, I would appreciate a comment or a donation. Issues and or feature request can be filed on [Github](https://github.com/chrisdotn/jsmnSol).",
      "json_metadata": "{\"tags\":[\"json\",\"ethereum\",\"smart\",\"contract\",\"development\"],\"links\":[\"https://www.truffleframework.com\",\"https://oraclize.it\",\"https://github.com/zserge/jsmn\",\"https://github.com/chrisdotn/jsmnSol\",\"https://www.ethpm.com/\",\"http://goessner.net/articles/JsonPath/\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
      "parent_author": "",
      "parent_permlink": "json",
      "permlink": "a-json-parser-for-solidity",
      "title": "A JSON Parser For Solidity"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2017-10-31T15:00:51",
  "trx_id": "42569c0b6387da057f6b8e6106130c5a55211e18",
  "trx_in_block": 2,
  "virtual_op": 0
}
2017/09/29 13:50:09
authorsteemitboard
bodyCongratulations @chrisdotn! You have received a personal award! [![](https://steemitimages.com/70x70/http://steemitboard.com/@chrisdotn/birthday1.png)](http://steemitboard.com/@chrisdotn) Happy Birthday - 1 Year on Steemit Happy Birthday - 1 Year on Steemit Click on the badge to view your own Board of Honor on SteemitBoard. For more information about this award, click [here](https://steemit.com/steemitboard/@steemitboard/steemitboard-update-8-happy-birthday) > By upvoting this notification, you can help all Steemit users. Learn how [here](https://steemit.com/steemitboard/@steemitboard/http-i-cubeupload-com-7ciqeo-png)!
json metadata{"image":["https://steemitboard.com/img/notifications.png"]}
parent authorchrisdotn
parent permlinkdeveloping-smart-contracts-for-ethereum-part-1
permlinksteemitboard-notify-chrisdotn-20170929t135011000z
title
Transaction InfoBlock #15892682/Trx 6dbad3cf9a2e302102a7166c3e351af78ed9445e
View Raw JSON Data
{
  "block": 15892682,
  "op": [
    "comment",
    {
      "author": "steemitboard",
      "body": "Congratulations @chrisdotn! You have received a personal award!\n\n[![](https://steemitimages.com/70x70/http://steemitboard.com/@chrisdotn/birthday1.png)](http://steemitboard.com/@chrisdotn)  Happy Birthday - 1 Year on Steemit Happy Birthday - 1 Year on Steemit\nClick on the badge to view your own Board of Honor on SteemitBoard.\n\nFor more information about this award, click [here](https://steemit.com/steemitboard/@steemitboard/steemitboard-update-8-happy-birthday)\n> By upvoting this notification, you can help all Steemit users. Learn how [here](https://steemit.com/steemitboard/@steemitboard/http-i-cubeupload-com-7ciqeo-png)!",
      "json_metadata": "{\"image\":[\"https://steemitboard.com/img/notifications.png\"]}",
      "parent_author": "chrisdotn",
      "parent_permlink": "developing-smart-contracts-for-ethereum-part-1",
      "permlink": "steemitboard-notify-chrisdotn-20170929t135011000z",
      "title": ""
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2017-09-29T13:50:09",
  "trx_id": "6dbad3cf9a2e302102a7166c3e351af78ed9445e",
  "trx_in_block": 20,
  "virtual_op": 0
}
2017/04/09 19:21:24
authorchrisdotn
permlinkdeveloping-smart-contracts-for-ethereum-part-1
votermacrobug
weight10000 (100.00%)
Transaction InfoBlock #10922302/Trx 1b0a1374afb02d9251dea7ea06cef9c9af32291a
View Raw JSON Data
{
  "block": 10922302,
  "op": [
    "vote",
    {
      "author": "chrisdotn",
      "permlink": "developing-smart-contracts-for-ethereum-part-1",
      "voter": "macrobug",
      "weight": 10000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2017-04-09T19:21:24",
  "trx_id": "1b0a1374afb02d9251dea7ea06cef9c9af32291a",
  "trx_in_block": 4,
  "virtual_op": 0
}
2016/11/29 14:04:27
authorchrisdotn
permlinkdeveloping-smart-contracts-for-ethereum-part-1
votergellej
weight10000 (100.00%)
Transaction InfoBlock #7149836/Trx 97cc4be9b44d1bba152be8efdf521e34b23b97ef
View Raw JSON Data
{
  "block": 7149836,
  "op": [
    "vote",
    {
      "author": "chrisdotn",
      "permlink": "developing-smart-contracts-for-ethereum-part-1",
      "voter": "gellej",
      "weight": 10000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2016-11-29T14:04:27",
  "trx_id": "97cc4be9b44d1bba152be8efdf521e34b23b97ef",
  "trx_in_block": 1,
  "virtual_op": 0
}
2016/10/09 08:11:09
authorchrisdotn
bodyAs an exercise I started to look into Ethereum Smart Contracts a couple of months ago. This journey has been quite interesting and I did learn a lot in that time. I took me a while to find the right tools and setup my environment before I could actually focus on developing smart contracts. This tutorial will point towards the tools I'm currently using and help set them up. Hopefully this will save some time for interested people so that they can focus on the actual development sooner. ## Why Ethereum? After Bitcoin [Ethereum](http://ethereum.org "Ethereum.org") is currently the crypto-currency with the second largest [market cap](http://coinmarketcap.com/ "CoinMarketCap for various cryptocurrencies"). In contrast to Bitcoin its blockchain is focused on smart contracts. Ethereum tries to make the smart contracts really powerful entities on the blockchain. For that purpose it provides a turing-complete development language call Solidity. It syntax is loosely based on Javascript and thus easier to learn than the Bitcoin Script. The high level Solidity programs (called "contracts" in the ethereum space) compile down into the actual code that is stored on the blockchain. Apart from the lower entry barriers to contract development, Ethereum has a large developer community that works on various pieces for Ethereum. There are different, independent clients (eg. [Geth](https://github.com/ethereum/go-ethereum/wiki/geth) or [Parity](https://ethcore.io/parity.html), to name just the two largest ones) for the blockchain, development frameworks ([Truffle](http://truffleframework.com/) or [Embark](https://iurimatias.github.io/embark-framework/)), different development languages ([Solidity](http://solidity.readthedocs.io/en/develop/) or [Serpent](https://github.com/ethereum/wiki/wiki/Serpent)) and nice and useful development/enduser tools ([Testrpc](https://github.com/ethereumjs/testrpc), [Mist](https://github.com/ethereum/mist) or the [Solditiy Realtime Compiler](https://ethereum.github.io/browser-solidity)). All of these tools are actively being developed. As such the environment is a friendly one. # Which Chain is Right For Me? There are a couple of steps to start developing properly. A smart contract is a program that is stored on the blockchain and it is run by the nodes running the blockchain. There are currently two public blockchains: 1. **Mainnet**: The mainnet is the public blockchain that is used for production. Ether on this blockchain have real value and are actively traded. All the clients connect to this chain by default (ie. without providing any other parameters). For development purposes this chain is of course fairly useless. 2. **Morden/Testnet**: The morden blockchain is used for development. Ether on this chain are more or less easy to come by and do not have real value. This chain should be used for final testing/integration before releasing a contract on to the Mainnet. Both public blockchains are useful in the later stages of development. To start it is better to setup a private blockchain that makes it really easy to mine new blocks or to use a "blockchain simulator" locally. At each start it provides a new in memory blockchain. It provides most operations that are permitted on the real blockchain, but is significantly faster as there is no delay as blocks are mined on demand locally. ## Using Testrpc as In-Memory Blockchain [Testrpc](https://github.com/ethereumjs/testrpc) is a blockchain simulator. It is easy to install via: npm install -g ethereumjs-testrpc For windows users there are installation instructions on the webpage. Just running `testrpc` will start the simulator. It creates a new blockchain with ten accounts by default. Those accounts are equipped with 100 ether by default. Testrpc print the addresses and private keys for the accounts to the console (I left out account 1-8 here): Available Accounts ================== (0) 0x6958d360f3752c2820bd4e3dbca6e240597f3ee5 ... (9) 0xeec30f0ad8d6d32707f843673ffe4f116d330f4a Private Keys ================== (0) 8677a4fc469a8a9b3799efa85df75fcd2ce10a8e4eb3b0f00183910126ef167e ... (9) dd803ca83548de759cbd7a59e3db7cc0dcb2574fea53daeb2aee153dbba02f38 HD Wallet ================== Mnemonic: oyster sight emerge prize umbrella focus laptop truth online shove direct employ Base HD Path: m/44'/60'/0'/0/{account_index} These accounts will be generated randomly at each start. # How Do I Program a Contract? Contracts are written in Solidity and then compiled into a script for the blockchain. After compiling they need to be deployed on the blockchain. A user can use a contract if he knows the contract's address on the blockchain as well as the ABI as a JSON file. A deployed contract can be used either directly with the right RPC calls or via a wallet like [Mist](https://github.com/ethereum/mist). It does not have a useful GUI on its own. To make it user-friendly, we need to provide a frontend to enable users to interact with it in a non-developer way. Such a frontend can be written in Html/Javascript. The [Web3 Javascript Ðapp API](https://github.com/ethereum/wiki/wiki/JavaScript-API) library provides access to the blockchain from Javascript. # Using Truffle as Framework Frameworks like [Truffle](http://truffleframework.com/) automate the deployment tasks and allow to focus on the actual contract and frontend development. So far I've always used Truffle; thus I focus on truffle for now. Truffle needs to be installed. If using npm, the installation is a simple npm install -g truffle To start a new project, create a folder for the project and `cd` into it. Running `truffle init` will scaffold a project structure in the directory. Furthermore it will create an example contract called "Metacoin" This contract is useful for education purposes. It gets referred to in various tutorial by the Truffle team. Truffle creates quite some files. For starters the most important ones are: * `$(PROJECT)/contracts/`: The contracts folder has the contract(s) as solidity files in it. Solidity files use the suffix `.sol`. * `$(PROJECT)/app/javascripts/`: This folder contains a file `app.js`, which provides the code for the frontend website. * `$(PROJECT)/truffle.js`: This file configures truffle. It has various sections that define how the code gets deployed. As a first step the truffle config needs to be customized to the local environment. ## Configuring Truffle The `truffle.js` consists of various sections. Each of them is explained in detail in the [official documentation](http://truffle.readthedocs.io/en/latest). For now, only a few parts need modifications. `truffle init` provides a config with the sections _build_ and _rpc_. _Build_ defines how the frontend codes ends up being deployed and does not need to be changed. _Rpc_ defines the host and port for rpc calls. Truffle expects a client to a blockchain running on this host and listening at the specified port. `Localhost` on port 8545 is the default setting that most clients use. Therefore, the default values do not need to be changed either. It is, however, useful to add a _networks_ section to the config file. _Networks_ define the chains that the contract can be deployed to. When they are configured, one can use a parameter when calling truffle to choose the correct chain. A useful setting for networks is: networks: { "live": { network_id: 1, // Ethereum public network }, "morden": { network_id: 2, // Official Ethereum test network }, "development": { network_id: "default" } This configures three networks for truffle: * **live**: The main network for production purposes. * **morden**: The public testnet for integration tests. * **development**: The *local* chain for development. This is the blockchain that is provided by Testrpc. The configuration defines a `network_id` for each of the networks. While the ids are defined for the live (`1`) and the test chain (`2`), they can be set to an arbitrary value for local or private chains. By setting the network_id of the development chain to `default`. This value matches for any network id that _does not_ match any other id in the list. This is useful for development with Testrpc as we want to start with a fresh network each time we start Testrpc and do not care for long-term storage of deployed contracts. ## Deploying a Contract To deploy a contract to a blockchain, the blockchain must be accessible for truffle. As per the configuration, truffle expects the node to listen on `localhost:8545`. Thus, before we can deploy a contract with truffle we must start the node. By running `testrpc` on the console, the node will simulate the in-memory blockchain. By default it listens on `localhost:8545`, just as truffle expects. Once the node has started, we can deploy a contract. `truffle init` has provided us with the Metacoin contract. As a first contract we will deploy this contract to our development blockchain: truffle migrate deploys the contracts to the blockchain. Without any parameters, it uses the development network from our configuration. The actual deployment is a rather long sequence of rpc calls to the node. To see, which calls truffle makes and what responses it receives, the command would be truffle migrate --verbose-rpc Truffle saves the latest migrations in a separate contract on the blockchain. Another useful parameter for the migration command is `--reset`, which will start the migration from scratch as if there had not been any prior migrations for the contract. ## Interacting With the frontend Truffle already provides us with a web frontend for the Metacoin contract. This frontend can be used to interact with the contract. This is more user-friendly than to expect a user to do the rpc call manually. Truffle can serve the web frontend. The command is truffle serve It will serve the website and watch for changes in the Html/JS files. If they are changed, it will redeploy the frontend on the fly. Pointing your browser to [http://localhost:8080](http://localhost:8080) will show you the frontend. The `app.js` file automatically uses the Web3 JS library to interact with the blockchain. In the metacoin example, the frontend uses the first available contract on the blockchain to deploy and interact with the contract. # Summary And Next Steps To start smart contract development, I have found the combination of Truffle and Testrpc quite useful. So far, we have installed both tools, started a local in-memory blockchain and deployed a first contract. The contract already has a user-friendly interface that can be accessed in a browser. The next part of the tutorial will introduce another tool to the mix that simplifies the account handling considerably. After that, we are ready to move on to the public testnet and see if our contract works on _morden_ too.
json metadata{"tags":["ethereum","smart-contract","truffle","testrpc","development"],"links":["http://ethereum.org","http://coinmarketcap.com/","https://github.com/ethereum/go-ethereum/wiki/geth","https://ethcore.io/parity.html","http://truffleframework.com/","https://iurimatias.github.io/embark-framework/","http://solidity.readthedocs.io/en/develop/","https://github.com/ethereum/wiki/wiki/Serpent","https://github.com/ethereumjs/testrpc","https://github.com/ethereum/mist","https://ethereum.github.io/browser-solidity","https://github.com/ethereum/wiki/wiki/JavaScript-API","http://truffle.readthedocs.io/en/latest","http://localhost:8080"]}
parent author
parent permlinkethereum
permlinkdeveloping-smart-contracts-for-ethereum-part-1
titleDeveloping Smart Contracts for Ethereum -- Part 1
Transaction InfoBlock #5675571/Trx cda79c11ad63cf449aa9bd16a7cd7f56a7f56fcc
View Raw JSON Data
{
  "block": 5675571,
  "op": [
    "comment",
    {
      "author": "chrisdotn",
      "body": "As an exercise I started to look into Ethereum Smart Contracts a couple of months ago. This journey has been quite interesting and I did learn a lot in that time. I took me a while to find the right tools and setup my environment before I could actually focus on developing smart contracts. This tutorial will point towards the tools I'm currently using and help set them up. Hopefully this will save some time for interested people so that they can focus on the actual development sooner.\n\n## Why Ethereum?\nAfter Bitcoin [Ethereum](http://ethereum.org \"Ethereum.org\") is currently the crypto-currency with the second largest [market cap](http://coinmarketcap.com/ \"CoinMarketCap for various cryptocurrencies\"). In contrast to Bitcoin its blockchain is focused on smart contracts. Ethereum tries to make the smart contracts really powerful entities on the blockchain. For that purpose it provides a turing-complete development language call Solidity. It syntax is loosely based on Javascript and thus easier to learn than the Bitcoin Script. The high level Solidity programs (called \"contracts\" in the ethereum space) compile down into the actual code that is stored on the blockchain.\n\nApart from the lower entry barriers to contract development, Ethereum has a large developer community that works on various pieces for Ethereum. There are different, independent clients (eg. [Geth](https://github.com/ethereum/go-ethereum/wiki/geth) or [Parity](https://ethcore.io/parity.html), to name just the two largest ones) for the blockchain, development frameworks ([Truffle](http://truffleframework.com/) or [Embark](https://iurimatias.github.io/embark-framework/)), different development languages ([Solidity](http://solidity.readthedocs.io/en/develop/) or [Serpent](https://github.com/ethereum/wiki/wiki/Serpent)) and nice and useful development/enduser tools ([Testrpc](https://github.com/ethereumjs/testrpc), [Mist](https://github.com/ethereum/mist) or the [Solditiy Realtime Compiler](https://ethereum.github.io/browser-solidity)). All of these tools are actively being developed. As such the environment is a friendly one.\n\n# Which Chain is Right For Me?\nThere are a couple of steps to start developing properly. A smart contract is a program that is stored on the blockchain and it is run by the nodes running the blockchain. There are currently two public blockchains:\n\n1. **Mainnet**: The mainnet is the public blockchain that is used for production. Ether on this blockchain have real value and are actively traded. All the clients connect to this chain by default (ie. without providing any other parameters). For development purposes this chain is of course fairly useless.\n\n2. **Morden/Testnet**: The morden blockchain is used for development. Ether on this chain are more or less easy to come by and do not have real value. This chain should be used for final testing/integration before releasing a contract on to the Mainnet.\n\nBoth public blockchains are useful in the later stages of development. To start it is better to setup a private blockchain that makes it really easy to mine new blocks or to use a \"blockchain simulator\" locally. At each start it provides a new in memory blockchain. It provides most operations that are permitted on the real blockchain, but is significantly faster as there is no delay as blocks are mined on demand locally.\n\n## Using Testrpc as In-Memory Blockchain\n[Testrpc](https://github.com/ethereumjs/testrpc) is a blockchain simulator. It is easy to install via:\n\n    npm install -g ethereumjs-testrpc\n\nFor windows users there are installation instructions on the webpage. Just running `testrpc` will start the simulator. It creates a new blockchain with ten accounts by default. Those accounts are equipped with 100 ether by default. Testrpc print the addresses and private keys for the accounts to the console (I left out account 1-8 here):\n\n    Available Accounts\n    ==================\n    (0) 0x6958d360f3752c2820bd4e3dbca6e240597f3ee5\n    ...\n    (9) 0xeec30f0ad8d6d32707f843673ffe4f116d330f4a\n\n    Private Keys\n    ==================\n    (0) 8677a4fc469a8a9b3799efa85df75fcd2ce10a8e4eb3b0f00183910126ef167e\n    ...\n    (9) dd803ca83548de759cbd7a59e3db7cc0dcb2574fea53daeb2aee153dbba02f38\n\n    HD Wallet\n    ==================\n    Mnemonic:      oyster sight emerge prize umbrella focus laptop truth online shove direct employ\n    Base HD Path:  m/44'/60'/0'/0/{account_index}\n\nThese accounts will be generated randomly at each start.\n\n# How Do I Program a Contract?\nContracts are written in Solidity and then compiled into a script for the blockchain. After compiling they need to be deployed on the blockchain. A user can use a contract if he knows the contract's address on the blockchain as well as the ABI as a JSON file.\n\nA deployed contract can be used either directly with the right RPC calls or via a wallet like [Mist](https://github.com/ethereum/mist). It does not have a useful GUI on its own. To make it user-friendly, we need to provide a frontend to enable users to interact with it in a non-developer way. Such a frontend can be written in Html/Javascript. The [Web3 Javascript Ðapp API](https://github.com/ethereum/wiki/wiki/JavaScript-API) library provides access to the blockchain from Javascript.\n\n# Using Truffle as Framework\nFrameworks like [Truffle](http://truffleframework.com/) automate the deployment tasks and allow to focus on the actual contract and frontend development. So far I've always used Truffle; thus I focus on truffle for now.\n\nTruffle needs to be installed. If using npm, the installation is a simple\n\n    npm install -g truffle\n\nTo start a new project, create a folder for the project and `cd` into it. Running `truffle init` will scaffold a project structure in the directory. Furthermore it will create an example contract called \"Metacoin\" This contract is useful for education purposes. It gets referred to in various tutorial by the Truffle team.\n\nTruffle creates quite some files. For starters the most important ones are:\n\n* `$(PROJECT)/contracts/`: The contracts folder has the contract(s) as solidity files in it. Solidity files use the suffix `.sol`.\n* `$(PROJECT)/app/javascripts/`: This folder contains a file `app.js`, which provides the code for the frontend website.\n* `$(PROJECT)/truffle.js`: This file configures truffle. It has various sections that define how the code gets deployed.\n\nAs a first step the truffle config needs to be customized to the local environment.\n\n## Configuring Truffle\nThe `truffle.js` consists of various sections. Each of them is explained in detail in the [official documentation](http://truffle.readthedocs.io/en/latest). For now, only a few parts need modifications.\n\n`truffle init` provides a config with the sections _build_ and _rpc_. _Build_ defines how the frontend codes ends up being deployed and does not need to be changed. _Rpc_ defines the host and port for rpc calls. Truffle expects a client to a blockchain running on this host and listening at the specified port. `Localhost` on port 8545 is the default setting that most clients use. Therefore, the  default values do not need to be changed either.\n\nIt is, however, useful to add a _networks_ section to the config file. _Networks_ define the chains that the contract can be deployed to. When they are configured, one can use a parameter when calling truffle to choose the correct chain. A useful setting for networks is:\n\n    networks: {\n        \"live\": {\n            network_id: 1, // Ethereum public network\n        },\n        \"morden\": {\n            network_id: 2, // Official Ethereum test network\n        },\n        \"development\": {\n            network_id: \"default\"\n        }\n\nThis configures three networks for truffle:\n\n* **live**: The main network for production purposes.\n* **morden**: The public testnet for integration tests.\n* **development**: The *local* chain for development. This is the blockchain that is provided by Testrpc.\n\nThe configuration defines a `network_id` for each of the networks. While the ids are defined for the live (`1`) and the test chain (`2`), they can be set to an arbitrary value for local or private chains. By setting the network_id of the development chain to `default`. This value matches for any network id that _does not_ match any other id in the list. This is useful for development with Testrpc as we want to start with a fresh network each time we start Testrpc and do not care for long-term storage of deployed contracts.\n\n## Deploying a Contract\nTo deploy a contract to a blockchain, the blockchain must be accessible for truffle. As per the configuration, truffle expects the node to listen on `localhost:8545`. Thus, before we can deploy a contract with truffle we must start the node. By running `testrpc` on the console, the node will simulate the in-memory blockchain. By default it listens on `localhost:8545`, just as truffle expects.\n\nOnce the node has started, we can deploy a contract. `truffle init` has provided us with the Metacoin contract. As a first contract we will deploy this contract to our development blockchain:\n\n    truffle migrate\n\ndeploys the contracts to the blockchain. Without any parameters, it uses the development network from our configuration.\n\nThe actual deployment is a rather long sequence of rpc calls to the node. To see, which calls truffle makes and what responses it receives, the command would be\n\n    truffle migrate --verbose-rpc\n\nTruffle saves the latest migrations in a separate contract on the blockchain. Another useful parameter for the migration command is `--reset`, which will start the migration from scratch as if there had not been any prior migrations for the contract.\n\n## Interacting With the frontend\nTruffle already provides us with a web frontend for the Metacoin contract. This frontend can be used to interact with the contract. This is more user-friendly than to expect a user to do the rpc call manually. Truffle can serve the web frontend. The command is\n\n    truffle serve\n\nIt will serve the website and watch for changes in the Html/JS files. If they are changed, it will redeploy the frontend on the fly.  Pointing your browser to [http://localhost:8080](http://localhost:8080) will show you the frontend.\n\nThe `app.js` file automatically uses the Web3 JS library to interact with the blockchain. In the metacoin example, the frontend uses the first available contract on the blockchain to deploy and interact with the contract.\n\n# Summary And Next Steps\nTo start smart contract development, I have found the combination of Truffle and Testrpc quite useful. So far, we have installed both tools, started a local in-memory blockchain and deployed a first contract. The contract already has a user-friendly interface that can be accessed in a browser.\n\nThe next part of the tutorial will introduce another tool to the mix that simplifies the account handling considerably. After that, we are ready to move on to the public testnet and see if our contract works on _morden_ too.",
      "json_metadata": "{\"tags\":[\"ethereum\",\"smart-contract\",\"truffle\",\"testrpc\",\"development\"],\"links\":[\"http://ethereum.org\",\"http://coinmarketcap.com/\",\"https://github.com/ethereum/go-ethereum/wiki/geth\",\"https://ethcore.io/parity.html\",\"http://truffleframework.com/\",\"https://iurimatias.github.io/embark-framework/\",\"http://solidity.readthedocs.io/en/develop/\",\"https://github.com/ethereum/wiki/wiki/Serpent\",\"https://github.com/ethereumjs/testrpc\",\"https://github.com/ethereum/mist\",\"https://ethereum.github.io/browser-solidity\",\"https://github.com/ethereum/wiki/wiki/JavaScript-API\",\"http://truffle.readthedocs.io/en/latest\",\"http://localhost:8080\"]}",
      "parent_author": "",
      "parent_permlink": "ethereum",
      "permlink": "developing-smart-contracts-for-ethereum-part-1",
      "title": "Developing Smart Contracts for Ethereum -- Part 1"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2016-10-09T08:11:09",
  "trx_id": "cda79c11ad63cf449aa9bd16a7cd7f56a7f56fcc",
  "trx_in_block": 1,
  "virtual_op": 0
}
2016/10/08 12:57:45
authorchrisdotn
bodyHappy to hear that!
json metadata{"tags":["ethereum"]}
parent authordavidburela
parent permlinkre-chrisdotn-developing-smart-contracts-for-ethereum-part-1-20161005t083300664z
permlinkre-davidburela-re-chrisdotn-developing-smart-contracts-for-ethereum-part-1-20161008t125742362z
title
Transaction InfoBlock #5652504/Trx 53bd2b3fd2f7f701a5653ec1b226de4481f48554
View Raw JSON Data
{
  "block": 5652504,
  "op": [
    "comment",
    {
      "author": "chrisdotn",
      "body": "Happy to hear that!",
      "json_metadata": "{\"tags\":[\"ethereum\"]}",
      "parent_author": "davidburela",
      "parent_permlink": "re-chrisdotn-developing-smart-contracts-for-ethereum-part-1-20161005t083300664z",
      "permlink": "re-davidburela-re-chrisdotn-developing-smart-contracts-for-ethereum-part-1-20161008t125742362z",
      "title": ""
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2016-10-08T12:57:45",
  "trx_id": "53bd2b3fd2f7f701a5653ec1b226de4481f48554",
  "trx_in_block": 1,
  "virtual_op": 0
}
2016/10/05 08:33:00
authordavidburela
bodyThanks, this helped get myself bootstrapped
json metadata{"tags":["ethereum"]}
parent authorchrisdotn
parent permlinkdeveloping-smart-contracts-for-ethereum-part-1
permlinkre-chrisdotn-developing-smart-contracts-for-ethereum-part-1-20161005t083300664z
title
Transaction InfoBlock #5560832/Trx 0b75f39952e2a44b657be260e4fc91ad0daaa1ca
View Raw JSON Data
{
  "block": 5560832,
  "op": [
    "comment",
    {
      "author": "davidburela",
      "body": "Thanks, this helped get myself bootstrapped",
      "json_metadata": "{\"tags\":[\"ethereum\"]}",
      "parent_author": "chrisdotn",
      "parent_permlink": "developing-smart-contracts-for-ethereum-part-1",
      "permlink": "re-chrisdotn-developing-smart-contracts-for-ethereum-part-1-20161005t083300664z",
      "title": ""
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2016-10-05T08:33:00",
  "trx_id": "0b75f39952e2a44b657be260e4fc91ad0daaa1ca",
  "trx_in_block": 5,
  "virtual_op": 0
}
2016/10/05 08:32:12
authorchrisdotn
permlinkdeveloping-smart-contracts-for-ethereum-part-1
voterdavidburela
weight10000 (100.00%)
Transaction InfoBlock #5560816/Trx 85174815c0e8a221558d127497ce86c6e36e585f
View Raw JSON Data
{
  "block": 5560816,
  "op": [
    "vote",
    {
      "author": "chrisdotn",
      "permlink": "developing-smart-contracts-for-ethereum-part-1",
      "voter": "davidburela",
      "weight": 10000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2016-10-05T08:32:12",
  "trx_id": "85174815c0e8a221558d127497ce86c6e36e585f",
  "trx_in_block": 4,
  "virtual_op": 0
}
2016/09/30 20:13:09
authorchrisdotn
permlinkdeveloping-smart-contracts-for-ethereum-part-1
voterz3r0d4yz
weight10000 (100.00%)
Transaction InfoBlock #5430974/Trx 088df2e36aa02579d8edd98b7bfa25df30a43896
View Raw JSON Data
{
  "block": 5430974,
  "op": [
    "vote",
    {
      "author": "chrisdotn",
      "permlink": "developing-smart-contracts-for-ethereum-part-1",
      "voter": "z3r0d4yz",
      "weight": 10000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2016-09-30T20:13:09",
  "trx_id": "088df2e36aa02579d8edd98b7bfa25df30a43896",
  "trx_in_block": 3,
  "virtual_op": 0
}
chrisdotnreceived 0.032 STEEM, 0.062 SBD, 0.272 SP author reward for @chrisdotn / developing-smart-contracts-for-ethereum-part-1
2016/09/30 12:46:30
authorchrisdotn
permlinkdeveloping-smart-contracts-for-ethereum-part-1
sbd payout0.062 SBD
steem payout0.032 STEEM
vesting payout442.994273 VESTS
Transaction InfoBlock #5422042/Virtual Operation #3
View Raw JSON Data
{
  "block": 5422042,
  "op": [
    "author_reward",
    {
      "author": "chrisdotn",
      "permlink": "developing-smart-contracts-for-ethereum-part-1",
      "sbd_payout": "0.062 SBD",
      "steem_payout": "0.032 STEEM",
      "vesting_payout": "442.994273 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2016-09-30T12:46:30",
  "trx_id": "0000000000000000000000000000000000000000",
  "trx_in_block": 4294967295,
  "virtual_op": 3
}
2016/09/29 12:54:18
authorchrisdotn
permlinkdeveloping-smart-contracts-for-ethereum-part-1
votergramion
weight10000 (100.00%)
Transaction InfoBlock #5393409/Trx 6df4a12c26e4f52caf086a142c98b92dd8e7f598
View Raw JSON Data
{
  "block": 5393409,
  "op": [
    "vote",
    {
      "author": "chrisdotn",
      "permlink": "developing-smart-contracts-for-ethereum-part-1",
      "voter": "gramion",
      "weight": 10000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2016-09-29T12:54:18",
  "trx_id": "6df4a12c26e4f52caf086a142c98b92dd8e7f598",
  "trx_in_block": 1,
  "virtual_op": 0
}
2016/09/29 12:47:45
authorchrisdotn
permlinkdeveloping-smart-contracts-for-ethereum-part-1
voteranomaly
weight100 (1.00%)
Transaction InfoBlock #5393279/Trx fa906b16b6c0ab933bb97b12baa7f6f9678a12eb
View Raw JSON Data
{
  "block": 5393279,
  "op": [
    "vote",
    {
      "author": "chrisdotn",
      "permlink": "developing-smart-contracts-for-ethereum-part-1",
      "voter": "anomaly",
      "weight": 100
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2016-09-29T12:47:45",
  "trx_id": "fa906b16b6c0ab933bb97b12baa7f6f9678a12eb",
  "trx_in_block": 1,
  "virtual_op": 0
}
2016/09/29 12:46:48
authorchrisdotn
permlinkdeveloping-smart-contracts-for-ethereum-part-1
voterjames212
weight10000 (100.00%)
Transaction InfoBlock #5393260/Trx dcd2e6c5ebd8c9d5dc492ab19b55993c3750b295
View Raw JSON Data
{
  "block": 5393260,
  "op": [
    "vote",
    {
      "author": "chrisdotn",
      "permlink": "developing-smart-contracts-for-ethereum-part-1",
      "voter": "james212",
      "weight": 10000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2016-09-29T12:46:48",
  "trx_id": "dcd2e6c5ebd8c9d5dc492ab19b55993c3750b295",
  "trx_in_block": 0,
  "virtual_op": 0
}
2016/09/29 12:20:54
authorchrisdotn
permlinkdeveloping-smart-contracts-for-ethereum-part-1
votermichiel
weight10000 (100.00%)
Transaction InfoBlock #5392742/Trx 5bfdbe3bf41c5c908b18abafe9348f9671593f55
View Raw JSON Data
{
  "block": 5392742,
  "op": [
    "vote",
    {
      "author": "chrisdotn",
      "permlink": "developing-smart-contracts-for-ethereum-part-1",
      "voter": "michiel",
      "weight": 10000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2016-09-29T12:20:54",
  "trx_id": "5bfdbe3bf41c5c908b18abafe9348f9671593f55",
  "trx_in_block": 2,
  "virtual_op": 0
}
2016/09/29 12:20:45
authorchrisdotn
permlinkdeveloping-smart-contracts-for-ethereum-part-1
voternataleeoliver
weight10000 (100.00%)
Transaction InfoBlock #5392739/Trx d57f56dd66ebc80ce7a6118539b87e2c8f0cfcdf
View Raw JSON Data
{
  "block": 5392739,
  "op": [
    "vote",
    {
      "author": "chrisdotn",
      "permlink": "developing-smart-contracts-for-ethereum-part-1",
      "voter": "nataleeoliver",
      "weight": 10000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2016-09-29T12:20:45",
  "trx_id": "d57f56dd66ebc80ce7a6118539b87e2c8f0cfcdf",
  "trx_in_block": 3,
  "virtual_op": 0
}
2016/09/29 12:16:33
authorchrisdotn
body@@ -240,18 +240,18 @@ could ac -u t +u ally foc @@ -8112,16 +8112,17 @@ arbitra +r y value @@ -10379,17 +10379,16 @@ t availa -l ble cont
json metadata{"tags":["ethereum","smart-contract","truffle","testrpc","development"],"links":["http://ethereum.org","http://coinmarketcap.com/","https://github.com/ethereum/go-ethereum/wiki/geth","https://ethcore.io/parity.html","http://truffleframework.com/","https://iurimatias.github.io/embark-framework/","http://solidity.readthedocs.io/en/develop/","https://github.com/ethereum/wiki/wiki/Serpent","https://github.com/ethereumjs/testrpc","https://github.com/ethereum/mist","https://ethereum.github.io/browser-solidity","https://github.com/ethereum/wiki/wiki/JavaScript-API","http://truffle.readthedocs.io/en/latest","http://localhost:8080"]}
parent author
parent permlinkethereum
permlinkdeveloping-smart-contracts-for-ethereum-part-1
titleDeveloping Smart Contracts for Ethereum -- Part 1
Transaction InfoBlock #5392656/Trx f63cb8e371aadf915eb1225966bff7e9e486747c
View Raw JSON Data
{
  "block": 5392656,
  "op": [
    "comment",
    {
      "author": "chrisdotn",
      "body": "@@ -240,18 +240,18 @@\n could ac\n-u\n t\n+u\n ally foc\n@@ -8112,16 +8112,17 @@\n  arbitra\n+r\n y value \n@@ -10379,17 +10379,16 @@\n t availa\n-l\n ble cont\n",
      "json_metadata": "{\"tags\":[\"ethereum\",\"smart-contract\",\"truffle\",\"testrpc\",\"development\"],\"links\":[\"http://ethereum.org\",\"http://coinmarketcap.com/\",\"https://github.com/ethereum/go-ethereum/wiki/geth\",\"https://ethcore.io/parity.html\",\"http://truffleframework.com/\",\"https://iurimatias.github.io/embark-framework/\",\"http://solidity.readthedocs.io/en/develop/\",\"https://github.com/ethereum/wiki/wiki/Serpent\",\"https://github.com/ethereumjs/testrpc\",\"https://github.com/ethereum/mist\",\"https://ethereum.github.io/browser-solidity\",\"https://github.com/ethereum/wiki/wiki/JavaScript-API\",\"http://truffle.readthedocs.io/en/latest\",\"http://localhost:8080\"]}",
      "parent_author": "",
      "parent_permlink": "ethereum",
      "permlink": "developing-smart-contracts-for-ethereum-part-1",
      "title": "Developing Smart Contracts for Ethereum -- Part 1"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2016-09-29T12:16:33",
  "trx_id": "f63cb8e371aadf915eb1225966bff7e9e486747c",
  "trx_in_block": 2,
  "virtual_op": 0
}
2016/09/29 12:16:09
authorchrisdotn
permlinkdeveloping-smart-contracts-for-ethereum-part-1
votersunshine
weight300 (3.00%)
Transaction InfoBlock #5392648/Trx 79d5f10b2294239970872f3ef7599496ea2287ac
View Raw JSON Data
{
  "block": 5392648,
  "op": [
    "vote",
    {
      "author": "chrisdotn",
      "permlink": "developing-smart-contracts-for-ethereum-part-1",
      "voter": "sunshine",
      "weight": 300
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2016-09-29T12:16:09",
  "trx_id": "79d5f10b2294239970872f3ef7599496ea2287ac",
  "trx_in_block": 1,
  "virtual_op": 0
}
2016/09/29 12:14:21
authorchrisdotn
permlinkdeveloping-smart-contracts-for-ethereum-part-1
voterchrisdotn
weight10000 (100.00%)
Transaction InfoBlock #5392612/Trx 2f11a7a76cc7346580a63166f73928f578d78bc4
View Raw JSON Data
{
  "block": 5392612,
  "op": [
    "vote",
    {
      "author": "chrisdotn",
      "permlink": "developing-smart-contracts-for-ethereum-part-1",
      "voter": "chrisdotn",
      "weight": 10000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2016-09-29T12:14:21",
  "trx_id": "2f11a7a76cc7346580a63166f73928f578d78bc4",
  "trx_in_block": 1,
  "virtual_op": 0
}
2016/09/29 12:14:21
authorchrisdotn
bodyAs an exercise I started to look into Ethereum Smart Contracts a couple of months ago. This journey has been quite interesting and I did learn a lot in that time. I took me a while to find the right tools and setup my environment before I could acutally focus on developing smart contracts. This tutorial will point towards the tools I'm currently using and help set them up. Hopefully this will save some time for interested people so that they can focus on the actual development sooner. ## Why Ethereum? After Bitcoin [Ethereum](http://ethereum.org "Ethereum.org") is currently the crypto-currency with the second largest [market cap](http://coinmarketcap.com/ "CoinMarketCap for various cryptocurrencies"). In contrast to Bitcoin its blockchain is focused on smart contracts. Ethereum tries to make the smart contracts really powerful entities on the blockchain. For that purpose it provides a turing-complete development language call Solidity. It syntax is loosely based on Javascript and thus easier to learn than the Bitcoin Script. The high level Solidity programs (called "contracts" in the ethereum space) compile down into the actual code that is stored on the blockchain. Apart from the lower entry barriers to contract development, Ethereum has a large developer community that works on various pieces for Ethereum. There are different, independent clients (eg. [Geth](https://github.com/ethereum/go-ethereum/wiki/geth) or [Parity](https://ethcore.io/parity.html), to name just the two largest ones) for the blockchain, development frameworks ([Truffle](http://truffleframework.com/) or [Embark](https://iurimatias.github.io/embark-framework/)), different development languages ([Solidity](http://solidity.readthedocs.io/en/develop/) or [Serpent](https://github.com/ethereum/wiki/wiki/Serpent)) and nice and useful development/enduser tools ([Testrpc](https://github.com/ethereumjs/testrpc), [Mist](https://github.com/ethereum/mist) or the [Solditiy Realtime Compiler](https://ethereum.github.io/browser-solidity)). All of these tools are actively being developed. As such the environment is a friendly one. # Which Chain is Right For Me? There are a couple of steps to start developing properly. A smart contract is a program that is stored on the blockchain and it is run by the nodes running the blockchain. There are currently two public blockchains: 1. **Mainnet**: The mainnet is the public blockchain that is used for production. Ether on this blockchain have real value and are actively traded. All the clients connect to this chain by default (ie. without providing any other parameters). For development purposes this chain is of course fairly useless. 2. **Morden/Testnet**: The morden blockchain is used for development. Ether on this chain are more or less easy to come by and do not have real value. This chain should be used for final testing/integration before releasing a contract on to the Mainnet. Both public blockchains are useful in the later stages of development. To start it is better to setup a private blockchain that makes it really easy to mine new blocks or to use a "blockchain simulator" locally. At each start it provides a new in memory blockchain. It provides most operations that are permitted on the real blockchain, but is significantly faster as there is no delay as blocks are mined on demand locally. ## Using Testrpc as In-Memory Blockchain [Testrpc](https://github.com/ethereumjs/testrpc) is a blockchain simulator. It is easy to install via: npm install -g ethereumjs-testrpc For windows users there are installation instructions on the webpage. Just running `testrpc` will start the simulator. It creates a new blockchain with ten accounts by default. Those accounts are equipped with 100 ether by default. Testrpc print the addresses and private keys for the accounts to the console (I left out account 1-8 here): Available Accounts ================== (0) 0x6958d360f3752c2820bd4e3dbca6e240597f3ee5 ... (9) 0xeec30f0ad8d6d32707f843673ffe4f116d330f4a Private Keys ================== (0) 8677a4fc469a8a9b3799efa85df75fcd2ce10a8e4eb3b0f00183910126ef167e ... (9) dd803ca83548de759cbd7a59e3db7cc0dcb2574fea53daeb2aee153dbba02f38 HD Wallet ================== Mnemonic: oyster sight emerge prize umbrella focus laptop truth online shove direct employ Base HD Path: m/44'/60'/0'/0/{account_index} These accounts will be generated randomly at each start. # How Do I Program a Contract? Contracts are written in Solidity and then compiled into a script for the blockchain. After compiling they need to be deployed on the blockchain. A user can use a contract if he knows the contract's address on the blockchain as well as the ABI as a JSON file. A deployed contract can be used either directly with the right RPC calls or via a wallet like [Mist](https://github.com/ethereum/mist). It does not have a useful GUI on its own. To make it user-friendly, we need to provide a frontend to enable users to interact with it in a non-developer way. Such a frontend can be written in Html/Javascript. The [Web3 Javascript Ðapp API](https://github.com/ethereum/wiki/wiki/JavaScript-API) library provides access to the blockchain from Javascript. # Using Truffle as Framework Frameworks like [Truffle](http://truffleframework.com/) automate the deployment tasks and allow to focus on the actual contract and frontend development. So far I've always used Truffle; thus I focus on truffle for now. Truffle needs to be installed. If using npm, the installation is a simple npm install -g truffle To start a new project, create a folder for the project and `cd` into it. Running `truffle init` will scaffold a project structure in the directory. Furthermore it will create an example contract called "Metacoin" This contract is useful for education purposes. It gets referred to in various tutorial by the Truffle team. Truffle creates quite some files. For starters the most important ones are: * `$(PROJECT)/contracts/`: The contracts folder has the contract(s) as solidity files in it. Solidity files use the suffix `.sol`. * `$(PROJECT)/app/javascripts/`: This folder contains a file `app.js`, which provides the code for the frontend website. * `$(PROJECT)/truffle.js`: This file configures truffle. It has various sections that define how the code gets deployed. As a first step the truffle config needs to be customized to the local environment. ## Configuring Truffle The `truffle.js` consists of various sections. Each of them is explained in detail in the [official documentation](http://truffle.readthedocs.io/en/latest). For now, only a few parts need modifications. `truffle init` provides a config with the sections _build_ and _rpc_. _Build_ defines how the frontend codes ends up being deployed and does not need to be changed. _Rpc_ defines the host and port for rpc calls. Truffle expects a client to a blockchain running on this host and listening at the specified port. `Localhost` on port 8545 is the default setting that most clients use. Therefore, the default values do not need to be changed either. It is, however, useful to add a _networks_ section to the config file. _Networks_ define the chains that the contract can be deployed to. When they are configured, one can use a parameter when calling truffle to choose the correct chain. A useful setting for networks is: networks: { "live": { network_id: 1, // Ethereum public network }, "morden": { network_id: 2, // Official Ethereum test network }, "development": { network_id: "default" } This configures three networks for truffle: * **live**: The main network for production purposes. * **morden**: The public testnet for integration tests. * **development**: The *local* chain for development. This is the blockchain that is provided by Testrpc. The configuration defines a `network_id` for each of the networks. While the ids are defined for the live (`1`) and the test chain (`2`), they can be set to an arbitray value for local or private chains. By setting the network_id of the development chain to `default`. This value matches for any network id that _does not_ match any other id in the list. This is useful for development with Testrpc as we want to start with a fresh network each time we start Testrpc and do not care for long-term storage of deployed contracts. ## Deploying a Contract To deploy a contract to a blockchain, the blockchain must be accessible for truffle. As per the configuration, truffle expects the node to listen on `localhost:8545`. Thus, before we can deploy a contract with truffle we must start the node. By running `testrpc` on the console, the node will simulate the in-memory blockchain. By default it listens on `localhost:8545`, just as truffle expects. Once the node has started, we can deploy a contract. `truffle init` has provided us with the Metacoin contract. As a first contract we will deploy this contract to our development blockchain: truffle migrate deploys the contracts to the blockchain. Without any parameters, it uses the development network from our configuration. The actual deployment is a rather long sequence of rpc calls to the node. To see, which calls truffle makes and what responses it receives, the command would be truffle migrate --verbose-rpc Truffle saves the latest migrations in a separate contract on the blockchain. Another useful parameter for the migration command is `--reset`, which will start the migration from scratch as if there had not been any prior migrations for the contract. ## Interacting With the frontend Truffle already provides us with a web frontend for the Metacoin contract. This frontend can be used to interact with the contract. This is more user-friendly than to expect a user to do the rpc call manually. Truffle can serve the web frontend. The command is truffle serve It will serve the website and watch for changes in the Html/JS files. If they are changed, it will redeploy the frontend on the fly. Pointing your browser to [http://localhost:8080](http://localhost:8080) will show you the frontend. The `app.js` file automatically uses the Web3 JS library to interact with the blockchain. In the metacoin example, the frontend uses the first availalble contract on the blockchain to deploy and interact with the contract. # Summary And Next Steps To start smart contract development, I have found the combination of Truffle and Testrpc quite useful. So far, we have installed both tools, started a local in-memory blockchain and deployed a first contract. The contract already has a user-friendly interface that can be accessed in a browser. The next part of the tutorial will introduce another tool to the mix that simplifies the account handling considerably. After that, we are ready to move on to the public testnet and see if our contract works on _morden_ too.
json metadata{"tags":["ethereum","smart-contract","truffle","testrpc","development"],"links":["http://ethereum.org","http://coinmarketcap.com/","https://github.com/ethereum/go-ethereum/wiki/geth","https://ethcore.io/parity.html","http://truffleframework.com/","https://iurimatias.github.io/embark-framework/","http://solidity.readthedocs.io/en/develop/","https://github.com/ethereum/wiki/wiki/Serpent","https://github.com/ethereumjs/testrpc","https://github.com/ethereum/mist","https://ethereum.github.io/browser-solidity","https://github.com/ethereum/wiki/wiki/JavaScript-API","http://truffle.readthedocs.io/en/latest","http://localhost:8080"]}
parent author
parent permlinkethereum
permlinkdeveloping-smart-contracts-for-ethereum-part-1
titleDeveloping Smart Contracts for Ethereum -- Part 1
Transaction InfoBlock #5392612/Trx 2f11a7a76cc7346580a63166f73928f578d78bc4
View Raw JSON Data
{
  "block": 5392612,
  "op": [
    "comment",
    {
      "author": "chrisdotn",
      "body": "As an exercise I started to look into Ethereum Smart Contracts a couple of months ago. This journey has been quite interesting and I did learn a lot in that time. I took me a while to find the right tools and setup my environment before I could acutally focus on developing smart contracts. This tutorial will point towards the tools I'm currently using and help set them up. Hopefully this will save some time for interested people so that they can focus on the actual development sooner.\n\n## Why Ethereum?\nAfter Bitcoin [Ethereum](http://ethereum.org \"Ethereum.org\") is currently the crypto-currency with the second largest [market cap](http://coinmarketcap.com/ \"CoinMarketCap for various cryptocurrencies\"). In contrast to Bitcoin its blockchain is focused on smart contracts. Ethereum tries to make the smart contracts really powerful entities on the blockchain. For that purpose it provides a turing-complete development language call Solidity. It syntax is loosely based on Javascript and thus easier to learn than the Bitcoin Script. The high level Solidity programs (called \"contracts\" in the ethereum space) compile down into the actual code that is stored on the blockchain.\n\nApart from the lower entry barriers to contract development, Ethereum has a large developer community that works on various pieces for Ethereum. There are different, independent clients (eg. [Geth](https://github.com/ethereum/go-ethereum/wiki/geth) or [Parity](https://ethcore.io/parity.html), to name just the two largest ones) for the blockchain, development frameworks ([Truffle](http://truffleframework.com/) or [Embark](https://iurimatias.github.io/embark-framework/)), different development languages ([Solidity](http://solidity.readthedocs.io/en/develop/) or [Serpent](https://github.com/ethereum/wiki/wiki/Serpent)) and nice and useful development/enduser tools ([Testrpc](https://github.com/ethereumjs/testrpc), [Mist](https://github.com/ethereum/mist) or the [Solditiy Realtime Compiler](https://ethereum.github.io/browser-solidity)). All of these tools are actively being developed. As such the environment is a friendly one.\n\n# Which Chain is Right For Me?\nThere are a couple of steps to start developing properly. A smart contract is a program that is stored on the blockchain and it is run by the nodes running the blockchain. There are currently two public blockchains:\n\n1. **Mainnet**: The mainnet is the public blockchain that is used for production. Ether on this blockchain have real value and are actively traded. All the clients connect to this chain by default (ie. without providing any other parameters). For development purposes this chain is of course fairly useless.\n\n2. **Morden/Testnet**: The morden blockchain is used for development. Ether on this chain are more or less easy to come by and do not have real value. This chain should be used for final testing/integration before releasing a contract on to the Mainnet.\n\nBoth public blockchains are useful in the later stages of development. To start it is better to setup a private blockchain that makes it really easy to mine new blocks or to use a \"blockchain simulator\" locally. At each start it provides a new in memory blockchain. It provides most operations that are permitted on the real blockchain, but is significantly faster as there is no delay as blocks are mined on demand locally.\n\n## Using Testrpc as In-Memory Blockchain\n[Testrpc](https://github.com/ethereumjs/testrpc) is a blockchain simulator. It is easy to install via:\n\n    npm install -g ethereumjs-testrpc\n\nFor windows users there are installation instructions on the webpage. Just running `testrpc` will start the simulator. It creates a new blockchain with ten accounts by default. Those accounts are equipped with 100 ether by default. Testrpc print the addresses and private keys for the accounts to the console (I left out account 1-8 here):\n\n    Available Accounts\n    ==================\n    (0) 0x6958d360f3752c2820bd4e3dbca6e240597f3ee5\n    ...\n    (9) 0xeec30f0ad8d6d32707f843673ffe4f116d330f4a\n\n    Private Keys\n    ==================\n    (0) 8677a4fc469a8a9b3799efa85df75fcd2ce10a8e4eb3b0f00183910126ef167e\n    ...\n    (9) dd803ca83548de759cbd7a59e3db7cc0dcb2574fea53daeb2aee153dbba02f38\n\n    HD Wallet\n    ==================\n    Mnemonic:      oyster sight emerge prize umbrella focus laptop truth online shove direct employ\n    Base HD Path:  m/44'/60'/0'/0/{account_index}\n\nThese accounts will be generated randomly at each start.\n\n# How Do I Program a Contract?\nContracts are written in Solidity and then compiled into a script for the blockchain. After compiling they need to be deployed on the blockchain. A user can use a contract if he knows the contract's address on the blockchain as well as the ABI as a JSON file.\n\nA deployed contract can be used either directly with the right RPC calls or via a wallet like [Mist](https://github.com/ethereum/mist). It does not have a useful GUI on its own. To make it user-friendly, we need to provide a frontend to enable users to interact with it in a non-developer way. Such a frontend can be written in Html/Javascript. The [Web3 Javascript Ðapp API](https://github.com/ethereum/wiki/wiki/JavaScript-API) library provides access to the blockchain from Javascript.\n\n# Using Truffle as Framework\nFrameworks like [Truffle](http://truffleframework.com/) automate the deployment tasks and allow to focus on the actual contract and frontend development. So far I've always used Truffle; thus I focus on truffle for now.\n\nTruffle needs to be installed. If using npm, the installation is a simple\n\n    npm install -g truffle\n\nTo start a new project, create a folder for the project and `cd` into it. Running `truffle init` will scaffold a project structure in the directory. Furthermore it will create an example contract called \"Metacoin\" This contract is useful for education purposes. It gets referred to in various tutorial by the Truffle team.\n\nTruffle creates quite some files. For starters the most important ones are:\n\n* `$(PROJECT)/contracts/`: The contracts folder has the contract(s) as solidity files in it. Solidity files use the suffix `.sol`.\n* `$(PROJECT)/app/javascripts/`: This folder contains a file `app.js`, which provides the code for the frontend website.\n* `$(PROJECT)/truffle.js`: This file configures truffle. It has various sections that define how the code gets deployed.\n\nAs a first step the truffle config needs to be customized to the local environment.\n\n## Configuring Truffle\nThe `truffle.js` consists of various sections. Each of them is explained in detail in the [official documentation](http://truffle.readthedocs.io/en/latest). For now, only a few parts need modifications.\n\n`truffle init` provides a config with the sections _build_ and _rpc_. _Build_ defines how the frontend codes ends up being deployed and does not need to be changed. _Rpc_ defines the host and port for rpc calls. Truffle expects a client to a blockchain running on this host and listening at the specified port. `Localhost` on port 8545 is the default setting that most clients use. Therefore, the  default values do not need to be changed either.\n\nIt is, however, useful to add a _networks_ section to the config file. _Networks_ define the chains that the contract can be deployed to. When they are configured, one can use a parameter when calling truffle to choose the correct chain. A useful setting for networks is:\n\n    networks: {\n        \"live\": {\n            network_id: 1, // Ethereum public network\n        },\n        \"morden\": {\n            network_id: 2, // Official Ethereum test network\n        },\n        \"development\": {\n            network_id: \"default\"\n        }\n\nThis configures three networks for truffle:\n\n* **live**: The main network for production purposes.\n* **morden**: The public testnet for integration tests.\n* **development**: The *local* chain for development. This is the blockchain that is provided by Testrpc.\n\nThe configuration defines a `network_id` for each of the networks. While the ids are defined for the live (`1`) and the test chain (`2`), they can be set to an arbitray value for local or private chains. By setting the network_id of the development chain to `default`. This value matches for any network id that _does not_ match any other id in the list. This is useful for development with Testrpc as we want to start with a fresh network each time we start Testrpc and do not care for long-term storage of deployed contracts.\n\n## Deploying a Contract\nTo deploy a contract to a blockchain, the blockchain must be accessible for truffle. As per the configuration, truffle expects the node to listen on `localhost:8545`. Thus, before we can deploy a contract with truffle we must start the node. By running `testrpc` on the console, the node will simulate the in-memory blockchain. By default it listens on `localhost:8545`, just as truffle expects.\n\nOnce the node has started, we can deploy a contract. `truffle init` has provided us with the Metacoin contract. As a first contract we will deploy this contract to our development blockchain:\n\n    truffle migrate\n\ndeploys the contracts to the blockchain. Without any parameters, it uses the development network from our configuration.\n\nThe actual deployment is a rather long sequence of rpc calls to the node. To see, which calls truffle makes and what responses it receives, the command would be\n\n    truffle migrate --verbose-rpc\n\nTruffle saves the latest migrations in a separate contract on the blockchain. Another useful parameter for the migration command is `--reset`, which will start the migration from scratch as if there had not been any prior migrations for the contract.\n\n## Interacting With the frontend\nTruffle already provides us with a web frontend for the Metacoin contract. This frontend can be used to interact with the contract. This is more user-friendly than to expect a user to do the rpc call manually. Truffle can serve the web frontend. The command is\n\n    truffle serve\n\nIt will serve the website and watch for changes in the Html/JS files. If they are changed, it will redeploy the frontend on the fly.  Pointing your browser to [http://localhost:8080](http://localhost:8080) will show you the frontend.\n\nThe `app.js` file automatically uses the Web3 JS library to interact with the blockchain. In the metacoin example, the frontend uses the first availalble contract on the blockchain to deploy and interact with the contract.\n\n# Summary And Next Steps\nTo start smart contract development, I have found the combination of Truffle and Testrpc quite useful. So far, we have installed both tools, started a local in-memory blockchain and deployed a first contract. The contract already has a user-friendly interface that can be accessed in a browser.\n\nThe next part of the tutorial will introduce another tool to the mix that simplifies the account handling considerably. After that, we are ready to move on to the public testnet and see if our contract works on _morden_ too.",
      "json_metadata": "{\"tags\":[\"ethereum\",\"smart-contract\",\"truffle\",\"testrpc\",\"development\"],\"links\":[\"http://ethereum.org\",\"http://coinmarketcap.com/\",\"https://github.com/ethereum/go-ethereum/wiki/geth\",\"https://ethcore.io/parity.html\",\"http://truffleframework.com/\",\"https://iurimatias.github.io/embark-framework/\",\"http://solidity.readthedocs.io/en/develop/\",\"https://github.com/ethereum/wiki/wiki/Serpent\",\"https://github.com/ethereumjs/testrpc\",\"https://github.com/ethereum/mist\",\"https://ethereum.github.io/browser-solidity\",\"https://github.com/ethereum/wiki/wiki/JavaScript-API\",\"http://truffle.readthedocs.io/en/latest\",\"http://localhost:8080\"]}",
      "parent_author": "",
      "parent_permlink": "ethereum",
      "permlink": "developing-smart-contracts-for-ethereum-part-1",
      "title": "Developing Smart Contracts for Ethereum -- Part 1"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2016-09-29T12:14:21",
  "trx_id": "2f11a7a76cc7346580a63166f73928f578d78bc4",
  "trx_in_block": 1,
  "virtual_op": 0
}
chrisdotnupdated their account properties
2016/09/29 12:10:27
accountchrisdotn
active{"account_auths":[],"key_auths":[["STM5wrUbfcisGneZWNFjcHtF5pZup1GQ33yFhQdS9D8RMJ5yxEjMr",1]],"weight_threshold":1}
json metadata
memo keySTM71cR3DpoopFQLnQJGvHZviZbDSWL5oTXLzFFxXqeJG8ykyU5fY
owner{"account_auths":[],"key_auths":[["STM5FoVHxANi1mGRYPPB9QQUgQxKntRJHSVhc4pGkmrKMW4iY2Kzv",1]],"weight_threshold":1}
posting{"account_auths":[],"key_auths":[["STM7bDiV6Gc735HVppr3JasRX7mKxfqi9YCFdq5zMZySTtQyEVero",1]],"weight_threshold":1}
Transaction InfoBlock #5392534/Trx 83195f3382ea95924abd541539b38342bf27857d
View Raw JSON Data
{
  "block": 5392534,
  "op": [
    "account_update",
    {
      "account": "chrisdotn",
      "active": {
        "account_auths": [],
        "key_auths": [
          [
            "STM5wrUbfcisGneZWNFjcHtF5pZup1GQ33yFhQdS9D8RMJ5yxEjMr",
            1
          ]
        ],
        "weight_threshold": 1
      },
      "json_metadata": "",
      "memo_key": "STM71cR3DpoopFQLnQJGvHZviZbDSWL5oTXLzFFxXqeJG8ykyU5fY",
      "owner": {
        "account_auths": [],
        "key_auths": [
          [
            "STM5FoVHxANi1mGRYPPB9QQUgQxKntRJHSVhc4pGkmrKMW4iY2Kzv",
            1
          ]
        ],
        "weight_threshold": 1
      },
      "posting": {
        "account_auths": [],
        "key_auths": [
          [
            "STM7bDiV6Gc735HVppr3JasRX7mKxfqi9YCFdq5zMZySTtQyEVero",
            1
          ]
        ],
        "weight_threshold": 1
      }
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2016-09-29T12:10:27",
  "trx_id": "83195f3382ea95924abd541539b38342bf27857d",
  "trx_in_block": 0,
  "virtual_op": 0
}
anonsteemcreated a new account: @chrisdotn
2016/09/29 12:03:03
active{"account_auths":[],"key_auths":[["STM5WJvSg6Z1dX5cieeStWNKjjd7dPNEQAQVVbwiqDQqBNp7Aug4u",1]],"weight_threshold":1}
creatoranonsteem
fee10.000 STEEM
json metadata
memo keySTM75zguPV1xdpVot12c2dsonMbfsor8rq35LyWLABfJ8Na2NG3s8
new account namechrisdotn
owner{"account_auths":[],"key_auths":[["STM7Pzrq7ahuhByNZdhjnuwec3PmEBjs6wgqE7E3RJBn4Gt9Z8zms",1]],"weight_threshold":1}
posting{"account_auths":[],"key_auths":[["STM8Q6uVxr2q1DtQd71enMpso53sxwzhuJ8DuLhrmgNQyDvkqJoXH",1]],"weight_threshold":1}
Transaction InfoBlock #5392386/Trx a156d999d1be1000dd079619c9f58ae2556e3f64
View Raw JSON Data
{
  "block": 5392386,
  "op": [
    "account_create",
    {
      "active": {
        "account_auths": [],
        "key_auths": [
          [
            "STM5WJvSg6Z1dX5cieeStWNKjjd7dPNEQAQVVbwiqDQqBNp7Aug4u",
            1
          ]
        ],
        "weight_threshold": 1
      },
      "creator": "anonsteem",
      "fee": "10.000 STEEM",
      "json_metadata": "",
      "memo_key": "STM75zguPV1xdpVot12c2dsonMbfsor8rq35LyWLABfJ8Na2NG3s8",
      "new_account_name": "chrisdotn",
      "owner": {
        "account_auths": [],
        "key_auths": [
          [
            "STM7Pzrq7ahuhByNZdhjnuwec3PmEBjs6wgqE7E3RJBn4Gt9Z8zms",
            1
          ]
        ],
        "weight_threshold": 1
      },
      "posting": {
        "account_auths": [],
        "key_auths": [
          [
            "STM8Q6uVxr2q1DtQd71enMpso53sxwzhuJ8DuLhrmgNQyDvkqJoXH",
            1
          ]
        ],
        "weight_threshold": 1
      }
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2016-09-29T12:03:03",
  "trx_id": "a156d999d1be1000dd079619c9f58ae2556e3f64",
  "trx_in_block": 2,
  "virtual_op": 0
}

Account Metadata

POSTING JSON METADATA
profile{"profile_image":"https://www.maibornwolff.de/sites/default/files/styles/team_grid/public/images/team/christophnk.jpg"}
JSON METADATA
profile{"profile_image":"https://www.maibornwolff.de/sites/default/files/styles/team_grid/public/images/team/christophnk.jpg"}
{
  "posting_json_metadata": {
    "profile": {
      "profile_image": "https://www.maibornwolff.de/sites/default/files/styles/team_grid/public/images/team/christophnk.jpg"
    }
  },
  "json_metadata": {
    "profile": {
      "profile_image": "https://www.maibornwolff.de/sites/default/files/styles/team_grid/public/images/team/christophnk.jpg"
    }
  }
}

Auth Keys

Owner
Single Signature
Public Keys
STM5FoVHxANi1mGRYPPB9QQUgQxKntRJHSVhc4pGkmrKMW4iY2Kzv1/1
Active
Single Signature
Public Keys
STM5wrUbfcisGneZWNFjcHtF5pZup1GQ33yFhQdS9D8RMJ5yxEjMr1/1
Posting
Single Signature
Public Keys
STM7bDiV6Gc735HVppr3JasRX7mKxfqi9YCFdq5zMZySTtQyEVero1/1
Memo
STM71cR3DpoopFQLnQJGvHZviZbDSWL5oTXLzFFxXqeJG8ykyU5fY
{
  "owner": {
    "account_auths": [],
    "key_auths": [
      [
        "STM5FoVHxANi1mGRYPPB9QQUgQxKntRJHSVhc4pGkmrKMW4iY2Kzv",
        1
      ]
    ],
    "weight_threshold": 1
  },
  "active": {
    "account_auths": [],
    "key_auths": [
      [
        "STM5wrUbfcisGneZWNFjcHtF5pZup1GQ33yFhQdS9D8RMJ5yxEjMr",
        1
      ]
    ],
    "weight_threshold": 1
  },
  "posting": {
    "account_auths": [],
    "key_auths": [
      [
        "STM7bDiV6Gc735HVppr3JasRX7mKxfqi9YCFdq5zMZySTtQyEVero",
        1
      ]
    ],
    "weight_threshold": 1
  },
  "memo": "STM71cR3DpoopFQLnQJGvHZviZbDSWL5oTXLzFFxXqeJG8ykyU5fY"
}

Witness Votes

0 / 30
No active witness votes.
[]