VOTING POWER100.00%
DOWNVOTE POWER100.00%
RESOURCE CREDITS100.00%
REPUTATION PROGRESS15.94%
Net Worth
6.291USD
STEEM
0.234STEEM
SBD
0.002SBD
Own SP
108.222SP
Detailed Balance
| STEEM | ||
| balance | 0.234STEEM | STEEM |
| market_balance | 0.000STEEM | STEEM |
| savings_balance | 0.000STEEM | STEEM |
| reward_steem_balance | 0.000STEEM | STEEM |
| STEEM POWER | ||
| Own SP | 108.222SP | SP |
| Delegated Out | 0.000SP | SP |
| Delegation In | 0.000SP | SP |
| Effective Power | 108.222SP | SP |
| Reward SP (pending) | 0.181SP | SP |
| SBD | ||
| sbd_balance | 0.002SBD | SBD |
| sbd_conversions | 0.000SBD | SBD |
| sbd_market_balance | 0.000SBD | SBD |
| savings_sbd_balance | 0.000SBD | SBD |
| reward_sbd_balance | 0.000SBD | SBD |
{
"balance": "0.234 STEEM",
"savings_balance": "0.000 STEEM",
"reward_steem_balance": "0.000 STEEM",
"vesting_shares": "175995.433057 VESTS",
"delegated_vesting_shares": "0.000000 VESTS",
"received_vesting_shares": "0.000000 VESTS",
"sbd_balance": "0.002 SBD",
"savings_sbd_balance": "0.000 SBD",
"reward_sbd_balance": "0.000 SBD",
"conversions": []
}Account Info
| name | fuzz-ai |
| id | 1181985 |
| rank | 16,858 |
| reputation | 1041620891642 |
| created | 2018-12-02T23:54:18 |
| recovery_account | anonsteem |
| proxy | None |
| post_count | 16 |
| comment_count | 0 |
| lifetime_vote_count | 0 |
| witnesses_voted_for | 0 |
| last_post | 2019-02-18T22:22:48 |
| last_root_post | 2019-02-18T22:22:48 |
| last_vote_time | 2019-02-18T22:35:39 |
| proxied_vsf_votes | 0, 0, 0, 0 |
| can_vote | 1 |
| voting_power | 9,664 |
| delayed_votes | 0 |
| balance | 0.234 STEEM |
| savings_balance | 0.000 STEEM |
| sbd_balance | 0.002 SBD |
| savings_sbd_balance | 0.000 SBD |
| vesting_shares | 175995.433057 VESTS |
| delegated_vesting_shares | 0.000000 VESTS |
| received_vesting_shares | 0.000000 VESTS |
| reward_vesting_balance | 362.665457 VESTS |
| vesting_balance | 0.000 STEEM |
| vesting_withdraw_rate | 0.000000 VESTS |
| next_vesting_withdrawal | 1969-12-31T23:59:59 |
| withdrawn | 0 |
| to_withdraw | 0 |
| withdraw_routes | 0 |
| savings_withdraw_requests | 0 |
| last_account_recovery | 1970-01-01T00:00:00 |
| reset_account | null |
| last_owner_update | 2018-12-03T00:05:54 |
| last_account_update | 2018-12-17T05:36:42 |
| mined | No |
| sbd_seconds | 0 |
| sbd_last_interest_payment | 2019-02-18T22:35:45 |
| savings_sbd_last_interest_payment | 1970-01-01T00:00:00 |
{
"id": 1181985,
"name": "fuzz-ai",
"owner": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [
[
"STM7JgPxo2canzkidXS7zAoSqqqAJNzPF4SAx8ELsKA1L2nea9ALr",
1
]
]
},
"active": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [
[
"STM8SBFrSjJrVx7kXUPDUHAiEhczqgbEDkqiHRGyb8kjw6vjmFsWF",
1
]
]
},
"posting": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [
[
"STM7bqBr4whvNjfrQ1GpoPsJBwfqxBmr5W149osTq9EApmMtntg75",
1
]
]
},
"memo_key": "STM8Ae4PwgFhBEQ2CDWD38g4oghFY4ZvfGfyrJTZATYJJXH3SpirV",
"json_metadata": "{\"profile\":{\"profile_image\":\"https://cdn.steemitimages.com/DQmaFMMXPaiBTdBSLYtRs4dQLVWZEKdC57yFZqY6hj5ztvJ/logo-v1-notext.png\",\"cover_image\":\"https://cdn.steemitimages.com/DQmXzPM8p2iFa4rHpbxgYNXfjqCQrRE1biEQ5nGwGqP1w3J/giraffe-banner-3.jpg\",\"website\":\"http://www.fuzz.ai/\",\"about\":\"An early-stage startup building software correctness tools.\"}}",
"posting_json_metadata": "{\"profile\":{\"profile_image\":\"https://cdn.steemitimages.com/DQmaFMMXPaiBTdBSLYtRs4dQLVWZEKdC57yFZqY6hj5ztvJ/logo-v1-notext.png\",\"cover_image\":\"https://cdn.steemitimages.com/DQmXzPM8p2iFa4rHpbxgYNXfjqCQrRE1biEQ5nGwGqP1w3J/giraffe-banner-3.jpg\",\"website\":\"http://www.fuzz.ai/\",\"about\":\"An early-stage startup building software correctness tools.\"}}",
"proxy": "",
"last_owner_update": "2018-12-03T00:05:54",
"last_account_update": "2018-12-17T05:36:42",
"created": "2018-12-02T23:54:18",
"mined": false,
"recovery_account": "anonsteem",
"last_account_recovery": "1970-01-01T00:00:00",
"reset_account": "null",
"comment_count": 0,
"lifetime_vote_count": 0,
"post_count": 16,
"can_vote": true,
"voting_manabar": {
"current_mana": "170090243459",
"last_update_time": 1550529345
},
"downvote_manabar": {
"current_mana": 0,
"last_update_time": 1543794858
},
"voting_power": 9664,
"balance": "0.234 STEEM",
"savings_balance": "0.000 STEEM",
"sbd_balance": "0.002 SBD",
"sbd_seconds": "0",
"sbd_seconds_last_update": "2019-02-18T22:35:45",
"sbd_last_interest_payment": "2019-02-18T22:35:45",
"savings_sbd_balance": "0.000 SBD",
"savings_sbd_seconds": "0",
"savings_sbd_seconds_last_update": "1970-01-01T00:00:00",
"savings_sbd_last_interest_payment": "1970-01-01T00:00:00",
"savings_withdraw_requests": 0,
"reward_sbd_balance": "0.000 SBD",
"reward_steem_balance": "0.000 STEEM",
"reward_vesting_balance": "362.665457 VESTS",
"reward_vesting_steem": "0.181 STEEM",
"vesting_shares": "175995.433057 VESTS",
"delegated_vesting_shares": "0.000000 VESTS",
"received_vesting_shares": "0.000000 VESTS",
"vesting_withdraw_rate": "0.000000 VESTS",
"next_vesting_withdrawal": "1969-12-31T23:59:59",
"withdrawn": 0,
"to_withdraw": 0,
"withdraw_routes": 0,
"curation_rewards": 26,
"posting_rewards": 75915,
"proxied_vsf_votes": [
0,
0,
0,
0
],
"witnesses_voted_for": 0,
"last_post": "2019-02-18T22:22:48",
"last_root_post": "2019-02-18T22:22:48",
"last_vote_time": "2019-02-18T22:35:39",
"post_bandwidth": 0,
"pending_claimed_accounts": 0,
"vesting_balance": "0.000 STEEM",
"reputation": "1041620891642",
"transfer_history": [],
"market_history": [],
"post_history": [],
"vote_history": [],
"other_history": [],
"witness_votes": [],
"tags_usage": [],
"guest_bloggers": [],
"rank": 16858
}Withdraw Routes
| Incoming | Outgoing |
|---|---|
Empty | Empty |
{
"incoming": [],
"outgoing": []
}From Date
To Date
urduhaqaiqflagged (-100.00%) @fuzz-ai / a-memory-exhaustion-attack-against-the-steem-blockchain2020/01/09 07:55:00
urduhaqaiqflagged (-100.00%) @fuzz-ai / a-memory-exhaustion-attack-against-the-steem-blockchain
2020/01/09 07:55:00
| voter | urduhaqaiq |
| author | fuzz-ai |
| permlink | a-memory-exhaustion-attack-against-the-steem-blockchain |
| weight | -10000 (-100.00%) |
| Transaction Info | Block #39771779/Trx 7794fda1a52ff87d21eb40a7fcb876d7e5caea3e |
View Raw JSON Data
{
"trx_id": "7794fda1a52ff87d21eb40a7fcb876d7e5caea3e",
"block": 39771779,
"trx_in_block": 19,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2020-01-09T07:55:00",
"op": [
"vote",
{
"voter": "urduhaqaiq",
"author": "fuzz-ai",
"permlink": "a-memory-exhaustion-attack-against-the-steem-blockchain",
"weight": -10000
}
]
}2019/12/03 01:19:33
2019/12/03 01:19:33
| parent author | fuzz-ai |
| parent permlink | the-json-parsing-vulnerability-fixed-by-steemd-0-20-9 |
| author | steemitboard |
| permlink | steemitboard-notify-fuzz-ai-20191203t011935000z |
| title | |
| body | Congratulations @fuzz-ai! You received a personal award! <table><tr><td>https://steemitimages.com/70x70/http://steemitboard.com/@fuzz-ai/birthday1.png</td><td>Happy Birthday! - You are on the Steem blockchain for 1 year!</td></tr></table> <sub>_You can view [your badges on your Steem Board](https://steemitboard.com/@fuzz-ai) and compare to others on the [Steem Ranking](https://steemitboard.com/ranking/index.php?name=fuzz-ai)_</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"]} |
| Transaction Info | Block #38700237/Trx 7c1f419fc2c48fd62f19252c866b40beeeb9397b |
View Raw JSON Data
{
"trx_id": "7c1f419fc2c48fd62f19252c866b40beeeb9397b",
"block": 38700237,
"trx_in_block": 24,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-12-03T01:19:33",
"op": [
"comment",
{
"parent_author": "fuzz-ai",
"parent_permlink": "the-json-parsing-vulnerability-fixed-by-steemd-0-20-9",
"author": "steemitboard",
"permlink": "steemitboard-notify-fuzz-ai-20191203t011935000z",
"title": "",
"body": "Congratulations @fuzz-ai! You received a personal award!\n\n<table><tr><td>https://steemitimages.com/70x70/http://steemitboard.com/@fuzz-ai/birthday1.png</td><td>Happy Birthday! - You are on the Steem blockchain for 1 year!</td></tr></table>\n\n<sub>_You can view [your badges on your Steem Board](https://steemitboard.com/@fuzz-ai) and compare to others on the [Steem Ranking](https://steemitboard.com/ranking/index.php?name=fuzz-ai)_</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\"]}"
}
]
}2019/03/12 15:23:30
2019/03/12 15:23:30
| from | dlease |
| to | fuzz-ai |
| amount | 0.001 STEEM |
| memo | BuildTeam is proud to announce the release of DLease.io - our flagship P2P leasing marketplace app, aimed at assisting Steemians in leasing and delegating STEEM POWER for daily passive returns, with recent yields as high as 20% APR. DLease.io is a professional grade app , designed to replace the current MinnowBooster.net leasing market which has to date facilitated nearly 20 Million STEEM POWER in lease value to happy BuildTeam customers. View the new app at https://dlease.io/ or read the announcement post on https://steemit.com/@dlease. |
| Transaction Info | Block #31091908/Trx eb1a11ef250be6004427387b2cfcc4ea0350e0f8 |
View Raw JSON Data
{
"trx_id": "eb1a11ef250be6004427387b2cfcc4ea0350e0f8",
"block": 31091908,
"trx_in_block": 29,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-03-12T15:23:30",
"op": [
"transfer",
{
"from": "dlease",
"to": "fuzz-ai",
"amount": "0.001 STEEM",
"memo": "BuildTeam is proud to announce the release of DLease.io - our flagship P2P leasing marketplace app, aimed at assisting Steemians in leasing and delegating STEEM POWER for daily passive returns, with recent yields as high as 20% APR. DLease.io is a professional grade app , designed to replace the current MinnowBooster.net leasing market which has to date facilitated nearly 20 Million STEEM POWER in lease value to happy BuildTeam customers. View the new app at https://dlease.io/ or read the announcement post on https://steemit.com/@dlease."
}
]
}fuzz-aireceived 0.218 SP author reward for @fuzz-ai / the-json-parsing-vulnerability-fixed-by-steemd-0-20-92019/02/25 22:22:48
fuzz-aireceived 0.218 SP author reward for @fuzz-ai / the-json-parsing-vulnerability-fixed-by-steemd-0-20-9
2019/02/25 22:22:48
| author | fuzz-ai |
| permlink | the-json-parsing-vulnerability-fixed-by-steemd-0-20-9 |
| sbd payout | 0.000 SBD |
| steem payout | 0.000 STEEM |
| vesting payout | 354.650751 VESTS |
| Transaction Info | Block #30668578/Virtual Operation #9 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 30668578,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 9,
"timestamp": "2019-02-25T22:22:48",
"op": [
"author_reward",
{
"author": "fuzz-ai",
"permlink": "the-json-parsing-vulnerability-fixed-by-steemd-0-20-9",
"sbd_payout": "0.000 SBD",
"steem_payout": "0.000 STEEM",
"vesting_payout": "354.650751 VESTS"
}
]
}fuzz-aireceived 0.005 SP curation reward for @fuzz-ai / the-json-parsing-vulnerability-fixed-by-steemd-0-20-92019/02/25 22:22:48
fuzz-aireceived 0.005 SP curation reward for @fuzz-ai / the-json-parsing-vulnerability-fixed-by-steemd-0-20-9
2019/02/25 22:22:48
| curator | fuzz-ai |
| reward | 8.014706 VESTS |
| comment author | fuzz-ai |
| comment permlink | the-json-parsing-vulnerability-fixed-by-steemd-0-20-9 |
| Transaction Info | Block #30668578/Virtual Operation #7 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 30668578,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 7,
"timestamp": "2019-02-25T22:22:48",
"op": [
"curation_reward",
{
"curator": "fuzz-ai",
"reward": "8.014706 VESTS",
"comment_author": "fuzz-ai",
"comment_permlink": "the-json-parsing-vulnerability-fixed-by-steemd-0-20-9"
}
]
}crokkonupvoted (100.00%) @fuzz-ai / the-json-parsing-vulnerability-fixed-by-steemd-0-20-92019/02/19 05:36:42
crokkonupvoted (100.00%) @fuzz-ai / the-json-parsing-vulnerability-fixed-by-steemd-0-20-9
2019/02/19 05:36:42
| voter | crokkon |
| author | fuzz-ai |
| permlink | the-json-parsing-vulnerability-fixed-by-steemd-0-20-9 |
| weight | 10000 (100.00%) |
| Transaction Info | Block #30475797/Trx 1f8c18e312337ea79cf74ef541d6b611b20106cc |
View Raw JSON Data
{
"trx_id": "1f8c18e312337ea79cf74ef541d6b611b20106cc",
"block": 30475797,
"trx_in_block": 35,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-02-19T05:36:42",
"op": [
"vote",
{
"voter": "crokkon",
"author": "fuzz-ai",
"permlink": "the-json-parsing-vulnerability-fixed-by-steemd-0-20-9",
"weight": 10000
}
]
}hozn4ukhlytriwcupvoted (15.00%) @fuzz-ai / the-json-parsing-vulnerability-fixed-by-steemd-0-20-92019/02/18 23:06:33
hozn4ukhlytriwcupvoted (15.00%) @fuzz-ai / the-json-parsing-vulnerability-fixed-by-steemd-0-20-9
2019/02/18 23:06:33
| voter | hozn4ukhlytriwc |
| author | fuzz-ai |
| permlink | the-json-parsing-vulnerability-fixed-by-steemd-0-20-9 |
| weight | 1500 (15.00%) |
| Transaction Info | Block #30468000/Trx e08531f18330df4f04a7143bf582777dbd7d4a49 |
View Raw JSON Data
{
"trx_id": "e08531f18330df4f04a7143bf582777dbd7d4a49",
"block": 30468000,
"trx_in_block": 19,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-02-18T23:06:33",
"op": [
"vote",
{
"voter": "hozn4ukhlytriwc",
"author": "fuzz-ai",
"permlink": "the-json-parsing-vulnerability-fixed-by-steemd-0-20-9",
"weight": 1500
}
]
}warofcraftupvoted (20.00%) @fuzz-ai / the-json-parsing-vulnerability-fixed-by-steemd-0-20-92019/02/18 22:43:36
warofcraftupvoted (20.00%) @fuzz-ai / the-json-parsing-vulnerability-fixed-by-steemd-0-20-9
2019/02/18 22:43:36
| voter | warofcraft |
| author | fuzz-ai |
| permlink | the-json-parsing-vulnerability-fixed-by-steemd-0-20-9 |
| weight | 2000 (20.00%) |
| Transaction Info | Block #30467541/Trx eac5e3b7236f9c6673c008e405495909b7438f5e |
View Raw JSON Data
{
"trx_id": "eac5e3b7236f9c6673c008e405495909b7438f5e",
"block": 30467541,
"trx_in_block": 0,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-02-18T22:43:36",
"op": [
"vote",
{
"voter": "warofcraft",
"author": "fuzz-ai",
"permlink": "the-json-parsing-vulnerability-fixed-by-steemd-0-20-9",
"weight": 2000
}
]
}portugalcoinupvoted (15.00%) @fuzz-ai / the-json-parsing-vulnerability-fixed-by-steemd-0-20-92019/02/18 22:38:06
portugalcoinupvoted (15.00%) @fuzz-ai / the-json-parsing-vulnerability-fixed-by-steemd-0-20-9
2019/02/18 22:38:06
| voter | portugalcoin |
| author | fuzz-ai |
| permlink | the-json-parsing-vulnerability-fixed-by-steemd-0-20-9 |
| weight | 1500 (15.00%) |
| Transaction Info | Block #30467431/Trx 567491bd8c6caeb3c3c8b16cb02dc27caa955e4b |
View Raw JSON Data
{
"trx_id": "567491bd8c6caeb3c3c8b16cb02dc27caa955e4b",
"block": 30467431,
"trx_in_block": 18,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-02-18T22:38:06",
"op": [
"vote",
{
"voter": "portugalcoin",
"author": "fuzz-ai",
"permlink": "the-json-parsing-vulnerability-fixed-by-steemd-0-20-9",
"weight": 1500
}
]
}fuzz-aiclaimed reward balance: 0.231 STEEM, 0.295 SP2019/02/18 22:35:45
fuzz-aiclaimed reward balance: 0.231 STEEM, 0.295 SP
2019/02/18 22:35:45
| account | fuzz-ai |
| reward steem | 0.231 STEEM |
| reward sbd | 0.000 SBD |
| reward vests | 480.082369 VESTS |
| Transaction Info | Block #30467384/Trx 11e301c203731171c40ee7cb7ab83bcde0909719 |
View Raw JSON Data
{
"trx_id": "11e301c203731171c40ee7cb7ab83bcde0909719",
"block": 30467384,
"trx_in_block": 36,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-02-18T22:35:45",
"op": [
"claim_reward_balance",
{
"account": "fuzz-ai",
"reward_steem": "0.231 STEEM",
"reward_sbd": "0.000 SBD",
"reward_vests": "480.082369 VESTS"
}
]
}fuzz-aiupvoted (100.00%) @fuzz-ai / the-json-parsing-vulnerability-fixed-by-steemd-0-20-92019/02/18 22:35:39
fuzz-aiupvoted (100.00%) @fuzz-ai / the-json-parsing-vulnerability-fixed-by-steemd-0-20-9
2019/02/18 22:35:39
| voter | fuzz-ai |
| author | fuzz-ai |
| permlink | the-json-parsing-vulnerability-fixed-by-steemd-0-20-9 |
| weight | 10000 (100.00%) |
| Transaction Info | Block #30467382/Trx 4a11bac36917aeff6b032bf758f8e664a07624f1 |
View Raw JSON Data
{
"trx_id": "4a11bac36917aeff6b032bf758f8e664a07624f1",
"block": 30467382,
"trx_in_block": 11,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-02-18T22:35:39",
"op": [
"vote",
{
"voter": "fuzz-ai",
"author": "fuzz-ai",
"permlink": "the-json-parsing-vulnerability-fixed-by-steemd-0-20-9",
"weight": 10000
}
]
}bluesniperupvoted (0.08%) @fuzz-ai / the-json-parsing-vulnerability-fixed-by-steemd-0-20-92019/02/18 22:34:39
bluesniperupvoted (0.08%) @fuzz-ai / the-json-parsing-vulnerability-fixed-by-steemd-0-20-9
2019/02/18 22:34:39
| voter | bluesniper |
| author | fuzz-ai |
| permlink | the-json-parsing-vulnerability-fixed-by-steemd-0-20-9 |
| weight | 8 (0.08%) |
| Transaction Info | Block #30467362/Trx e34b277915a7e7c16a628408799114d3f02f7d9f |
View Raw JSON Data
{
"trx_id": "e34b277915a7e7c16a628408799114d3f02f7d9f",
"block": 30467362,
"trx_in_block": 4,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-02-18T22:34:39",
"op": [
"vote",
{
"voter": "bluesniper",
"author": "fuzz-ai",
"permlink": "the-json-parsing-vulnerability-fixed-by-steemd-0-20-9",
"weight": 8
}
]
}jurikupvoted (50.00%) @fuzz-ai / the-json-parsing-vulnerability-fixed-by-steemd-0-20-92019/02/18 22:33:45
jurikupvoted (50.00%) @fuzz-ai / the-json-parsing-vulnerability-fixed-by-steemd-0-20-9
2019/02/18 22:33:45
| voter | jurik |
| author | fuzz-ai |
| permlink | the-json-parsing-vulnerability-fixed-by-steemd-0-20-9 |
| weight | 5000 (50.00%) |
| Transaction Info | Block #30467344/Trx 0b673bead13e1094353bc11817961e6835e28b9f |
View Raw JSON Data
{
"trx_id": "0b673bead13e1094353bc11817961e6835e28b9f",
"block": 30467344,
"trx_in_block": 20,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-02-18T22:33:45",
"op": [
"vote",
{
"voter": "jurik",
"author": "fuzz-ai",
"permlink": "the-json-parsing-vulnerability-fixed-by-steemd-0-20-9",
"weight": 5000
}
]
}serginoupvoted (2.00%) @fuzz-ai / the-json-parsing-vulnerability-fixed-by-steemd-0-20-92019/02/18 22:33:39
serginoupvoted (2.00%) @fuzz-ai / the-json-parsing-vulnerability-fixed-by-steemd-0-20-9
2019/02/18 22:33:39
| voter | sergino |
| author | fuzz-ai |
| permlink | the-json-parsing-vulnerability-fixed-by-steemd-0-20-9 |
| weight | 200 (2.00%) |
| Transaction Info | Block #30467342/Trx d6ef20da872f02794acca3635d19d9ce2fdc9256 |
View Raw JSON Data
{
"trx_id": "d6ef20da872f02794acca3635d19d9ce2fdc9256",
"block": 30467342,
"trx_in_block": 13,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-02-18T22:33:39",
"op": [
"vote",
{
"voter": "sergino",
"author": "fuzz-ai",
"permlink": "the-json-parsing-vulnerability-fixed-by-steemd-0-20-9",
"weight": 200
}
]
}fuzz-aipublished a new post: the-json-parsing-vulnerability-fixed-by-steemd-0-20-92019/02/18 22:32:36
fuzz-aipublished a new post: the-json-parsing-vulnerability-fixed-by-steemd-0-20-9
2019/02/18 22:32:36
| parent author | |
| parent permlink | steem |
| author | fuzz-ai |
| permlink | the-json-parsing-vulnerability-fixed-by-steemd-0-20-9 |
| title | The JSON-parsing vulnerability fixed by Steemd 0.20.9 |
| body | @@ -2954,20 +2954,21 @@ ed! So -also +while the fal |
| json metadata | {"tags":["steem","programming","security","software","json"],"users":["crokkon"],"image":["https://cdn.steemitimages.com/DQmP8hhtEA1jciL8BW5RGNYPSpwYKtDyYxZdk2cEahTJGPS/etienne-steenkamp-1166506-unsplash.jpg"],"links":["https://steemit.com/utopian-io/@fuzz-ai/steemd-0-20-6-bug-memory-exhaustion-when-parsing-malicious-hellomessage#@crokkon/re-fuzz-ai-steemd-0-20-6-bug-memory-exhaustion-when-parsing-malicious-hellomessage-20181220t130349251z","https://github.com/bitshares/bitshares-fc/commit/f9802f686007e7efeaa88cba31f647ca96f1ee0c"],"app":"steemit/0.1","format":"markdown"} |
| Transaction Info | Block #30467321/Trx b177e5b27c0d6db786d6197666699f04a35db51f |
View Raw JSON Data
{
"trx_id": "b177e5b27c0d6db786d6197666699f04a35db51f",
"block": 30467321,
"trx_in_block": 46,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-02-18T22:32:36",
"op": [
"comment",
{
"parent_author": "",
"parent_permlink": "steem",
"author": "fuzz-ai",
"permlink": "the-json-parsing-vulnerability-fixed-by-steemd-0-20-9",
"title": "The JSON-parsing vulnerability fixed by Steemd 0.20.9",
"body": "@@ -2954,20 +2954,21 @@\n ed! So \n-also\n+while\n the fal\n",
"json_metadata": "{\"tags\":[\"steem\",\"programming\",\"security\",\"software\",\"json\"],\"users\":[\"crokkon\"],\"image\":[\"https://cdn.steemitimages.com/DQmP8hhtEA1jciL8BW5RGNYPSpwYKtDyYxZdk2cEahTJGPS/etienne-steenkamp-1166506-unsplash.jpg\"],\"links\":[\"https://steemit.com/utopian-io/@fuzz-ai/steemd-0-20-6-bug-memory-exhaustion-when-parsing-malicious-hellomessage#@crokkon/re-fuzz-ai-steemd-0-20-6-bug-memory-exhaustion-when-parsing-malicious-hellomessage-20181220t130349251z\",\"https://github.com/bitshares/bitshares-fc/commit/f9802f686007e7efeaa88cba31f647ca96f1ee0c\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
}
]
}fuzz-aipublished a new post: the-json-parsing-vulnerability-fixed-by-steemd-0-20-92019/02/18 22:24:12
fuzz-aipublished a new post: the-json-parsing-vulnerability-fixed-by-steemd-0-20-9
2019/02/18 22:24:12
| parent author | |
| parent permlink | steem |
| author | fuzz-ai |
| permlink | the-json-parsing-vulnerability-fixed-by-steemd-0-20-9 |
| title | The JSON-parsing vulnerability fixed by Steemd 0.20.9 |
| body | @@ -2154,17 +2154,16 @@ ow recur -i sion dep @@ -2178,14 +2178,12 @@ ack -height +size mig |
| json metadata | {"tags":["steem","programming","security","software","json"],"users":["crokkon"],"image":["https://cdn.steemitimages.com/DQmP8hhtEA1jciL8BW5RGNYPSpwYKtDyYxZdk2cEahTJGPS/etienne-steenkamp-1166506-unsplash.jpg"],"links":["https://steemit.com/utopian-io/@fuzz-ai/steemd-0-20-6-bug-memory-exhaustion-when-parsing-malicious-hellomessage#@crokkon/re-fuzz-ai-steemd-0-20-6-bug-memory-exhaustion-when-parsing-malicious-hellomessage-20181220t130349251z","https://github.com/bitshares/bitshares-fc/commit/f9802f686007e7efeaa88cba31f647ca96f1ee0c"],"app":"steemit/0.1","format":"markdown"} |
| Transaction Info | Block #30467153/Trx 2583420c8ce5e1d9bd12ac13b92aa391d9e3a6b5 |
View Raw JSON Data
{
"trx_id": "2583420c8ce5e1d9bd12ac13b92aa391d9e3a6b5",
"block": 30467153,
"trx_in_block": 5,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-02-18T22:24:12",
"op": [
"comment",
{
"parent_author": "",
"parent_permlink": "steem",
"author": "fuzz-ai",
"permlink": "the-json-parsing-vulnerability-fixed-by-steemd-0-20-9",
"title": "The JSON-parsing vulnerability fixed by Steemd 0.20.9",
"body": "@@ -2154,17 +2154,16 @@\n ow recur\n-i\n sion dep\n@@ -2178,14 +2178,12 @@\n ack \n-height\n+size\n mig\n",
"json_metadata": "{\"tags\":[\"steem\",\"programming\",\"security\",\"software\",\"json\"],\"users\":[\"crokkon\"],\"image\":[\"https://cdn.steemitimages.com/DQmP8hhtEA1jciL8BW5RGNYPSpwYKtDyYxZdk2cEahTJGPS/etienne-steenkamp-1166506-unsplash.jpg\"],\"links\":[\"https://steemit.com/utopian-io/@fuzz-ai/steemd-0-20-6-bug-memory-exhaustion-when-parsing-malicious-hellomessage#@crokkon/re-fuzz-ai-steemd-0-20-6-bug-memory-exhaustion-when-parsing-malicious-hellomessage-20181220t130349251z\",\"https://github.com/bitshares/bitshares-fc/commit/f9802f686007e7efeaa88cba31f647ca96f1ee0c\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
}
]
}fuzz-aiupdated options for the-json-parsing-vulnerability-fixed-by-steemd-0-20-92019/02/18 22:22:48
fuzz-aiupdated options for the-json-parsing-vulnerability-fixed-by-steemd-0-20-9
2019/02/18 22:22:48
| author | fuzz-ai |
| permlink | the-json-parsing-vulnerability-fixed-by-steemd-0-20-9 |
| max accepted payout | 1000000.000 SBD |
| percent steem dollars | 0 |
| allow votes | true |
| allow curation rewards | true |
| extensions | [] |
| Transaction Info | Block #30467125/Trx ad50d5d863104e2f5981d8704fd512387e0c75c7 |
View Raw JSON Data
{
"trx_id": "ad50d5d863104e2f5981d8704fd512387e0c75c7",
"block": 30467125,
"trx_in_block": 9,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-02-18T22:22:48",
"op": [
"comment_options",
{
"author": "fuzz-ai",
"permlink": "the-json-parsing-vulnerability-fixed-by-steemd-0-20-9",
"max_accepted_payout": "1000000.000 SBD",
"percent_steem_dollars": 0,
"allow_votes": true,
"allow_curation_rewards": true,
"extensions": []
}
]
}fuzz-aipublished a new post: the-json-parsing-vulnerability-fixed-by-steemd-0-20-92019/02/18 22:22:48
fuzz-aipublished a new post: the-json-parsing-vulnerability-fixed-by-steemd-0-20-9
2019/02/18 22:22:48
| parent author | |
| parent permlink | steem |
| author | fuzz-ai |
| permlink | the-json-parsing-vulnerability-fixed-by-steemd-0-20-9 |
| title | The JSON-parsing vulnerability fixed by Steemd 0.20.9 |
| body | In my previous bug report on steemd, @crokkon asked [if custom JSON was also vulnerable](https://steemit.com/utopian-io/@fuzz-ai/steemd-0-20-6-bug-memory-exhaustion-when-parsing-malicious-hellomessage#@crokkon/re-fuzz-ai-steemd-0-20-6-bug-memory-exhaustion-when-parsing-malicious-hellomessage-20181220t130349251z) which inspired me to take a closer look. The JSON parsing code in the FC library used by Steem did have a check for nesting, but it was not adequate: ``` /** the purpose of this check is to verify that we will not get a stack overflow in the recursive descent parser */ void check_string_depth( const string& utf8_str ) { int32_t open_object = 0; int32_t open_array = 0; for( auto c : utf8_str ) { switch( c ) { case '{': open_object++; break; case '}': open_object--; break; case '[': open_array++; break; case ']': open_array--; break; default: break; } FC_ASSERT( open_object < 100 && open_array < 100, "object graph too deep", ("object depth",open_object)("array depth", open_array) ); } } ``` This count checks the depth of opening braces, but it has both false positives and false negatives, because it neglects to check whether the brace appears within a string. For example, the following JSON string would be viewed as having a large array depth, even though it does not have any arrays at all: ``` { "foo" : "[[[[[[...[[[" } ``` (Example had to be truncated, see addendum below.) The other direction is more concerning; we can construct a malfomed JSON-RPC call which exhausts the stack of the caller, causing the process to crash. The following pattern can be repeated up the maximum size of an accepted message (2MB). ``` {"jsonrpc":"2.0","method": ["]",["]",["]",["]",["]",["]",["]",["]",... ``` This bug was reported to [email protected] on January 2nd and fixed in Steemd version 0.20.9 on January 22nd. ## Analysis Stack-exhaustion attacks are not as easy to find with a coverage-based tool like AFL, as memory-exhaustion attacks are. It might be that setting a very low recurision depth or stack height might have allowed AFL to find this problem, but it seems likely that the necessary path through the code is one that's not easy for a purely coverage-based tool to find. I'd be interested in learning what other sort of tools would be better at identifying this sort of weakness. Bitshares fixed this vulnerability far earlier, in March 2018: https://github.com/bitshares/bitshares-fc/commit/f9802f686007e7efeaa88cba31f647ca96f1ee0c But, the fractured nature of the FC and Graphene ecosystem means that the vulnerability was not communicated to other implementations (or ignored if it was.) ## Addendum An earlier version of this article was rejected with the "object too deep" error, because the example above of a false positive triggered the code check I quoted! So also the false negative had been fixed, the false positive bug remains.  Photo by Etienne Steenkamp on Unsplash |
| json metadata | {"tags":["steem","programming","security","software","json"],"users":["crokkon"],"image":["https://cdn.steemitimages.com/DQmP8hhtEA1jciL8BW5RGNYPSpwYKtDyYxZdk2cEahTJGPS/etienne-steenkamp-1166506-unsplash.jpg"],"links":["https://steemit.com/utopian-io/@fuzz-ai/steemd-0-20-6-bug-memory-exhaustion-when-parsing-malicious-hellomessage#@crokkon/re-fuzz-ai-steemd-0-20-6-bug-memory-exhaustion-when-parsing-malicious-hellomessage-20181220t130349251z","https://github.com/bitshares/bitshares-fc/commit/f9802f686007e7efeaa88cba31f647ca96f1ee0c"],"app":"steemit/0.1","format":"markdown"} |
| Transaction Info | Block #30467125/Trx ad50d5d863104e2f5981d8704fd512387e0c75c7 |
View Raw JSON Data
{
"trx_id": "ad50d5d863104e2f5981d8704fd512387e0c75c7",
"block": 30467125,
"trx_in_block": 9,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-02-18T22:22:48",
"op": [
"comment",
{
"parent_author": "",
"parent_permlink": "steem",
"author": "fuzz-ai",
"permlink": "the-json-parsing-vulnerability-fixed-by-steemd-0-20-9",
"title": "The JSON-parsing vulnerability fixed by Steemd 0.20.9",
"body": "In my previous bug report on steemd, @crokkon asked [if custom JSON was also vulnerable](https://steemit.com/utopian-io/@fuzz-ai/steemd-0-20-6-bug-memory-exhaustion-when-parsing-malicious-hellomessage#@crokkon/re-fuzz-ai-steemd-0-20-6-bug-memory-exhaustion-when-parsing-malicious-hellomessage-20181220t130349251z) which inspired me to take a closer look.\n\nThe JSON parsing code in the FC library used by Steem did have a check for nesting, but it was not adequate:\n\n```\n /** the purpose of this check is to verify that we will not get a stack overflow in the recursive descent parser */\n void check_string_depth( const string& utf8_str )\n {\n int32_t open_object = 0;\n int32_t open_array = 0;\n for( auto c : utf8_str )\n {\n switch( c )\n {\n case '{': open_object++; break;\n case '}': open_object--; break;\n case '[': open_array++; break;\n case ']': open_array--; break;\n default: break;\n }\n FC_ASSERT( open_object < 100 && open_array < 100, \"object graph too deep\", (\"object depth\",open_object)(\"array depth\", open_array) );\n }\n }\n ```\n\nThis count checks the depth of opening braces, but it has both false positives and false negatives, because it neglects to check whether the brace appears within a string.\n\nFor example, the following JSON string would be viewed as having a large array depth, even though it does not have any arrays at all:\n\n```\n{ \"foo\" : \"[[[[[[...[[[\" }\n```\n\n(Example had to be truncated, see addendum below.)\n\nThe other direction is more concerning; we can construct a malfomed JSON-RPC call which exhausts the stack of the caller, causing the process to crash. The following pattern can be repeated up the maximum size of an accepted message (2MB).\n\n```\n{\"jsonrpc\":\"2.0\",\"method\": [\"]\",[\"]\",[\"]\",[\"]\",[\"]\",[\"]\",[\"]\",[\"]\",...\n```\n\nThis bug was reported to [email protected] on January 2nd and fixed in Steemd version 0.20.9 on January 22nd.\n\n## Analysis\n\nStack-exhaustion attacks are not as easy to find with a coverage-based tool like AFL, as memory-exhaustion attacks are. It might be that setting a very low recurision depth or stack height might have allowed AFL to find this problem, but it seems likely that the necessary path through the code is one that's not easy for a purely coverage-based tool to find. I'd be interested in learning what other sort of tools would be better at identifying this sort of weakness.\n\nBitshares fixed this vulnerability far earlier, in March 2018: https://github.com/bitshares/bitshares-fc/commit/f9802f686007e7efeaa88cba31f647ca96f1ee0c But, the fractured nature of the FC and Graphene ecosystem means that the vulnerability was not communicated to other implementations (or ignored if it was.)\n\n## Addendum\n\nAn earlier version of this article was rejected with the \"object too deep\" error, because the example above of a false positive triggered the code check I quoted! So also the false negative had been fixed, the false positive bug remains.\n\n\nPhoto by Etienne Steenkamp on Unsplash",
"json_metadata": "{\"tags\":[\"steem\",\"programming\",\"security\",\"software\",\"json\"],\"users\":[\"crokkon\"],\"image\":[\"https://cdn.steemitimages.com/DQmP8hhtEA1jciL8BW5RGNYPSpwYKtDyYxZdk2cEahTJGPS/etienne-steenkamp-1166506-unsplash.jpg\"],\"links\":[\"https://steemit.com/utopian-io/@fuzz-ai/steemd-0-20-6-bug-memory-exhaustion-when-parsing-malicious-hellomessage#@crokkon/re-fuzz-ai-steemd-0-20-6-bug-memory-exhaustion-when-parsing-malicious-hellomessage-20181220t130349251z\",\"https://github.com/bitshares/bitshares-fc/commit/f9802f686007e7efeaa88cba31f647ca96f1ee0c\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
}
]
}fuzz-aiupvoted (100.00%) @fuzz-ai / reproducing-a-memory-tracking-bug-with-tla2019/02/18 21:52:00
fuzz-aiupvoted (100.00%) @fuzz-ai / reproducing-a-memory-tracking-bug-with-tla
2019/02/18 21:52:00
| voter | fuzz-ai |
| author | fuzz-ai |
| permlink | reproducing-a-memory-tracking-bug-with-tla |
| weight | 10000 (100.00%) |
| Transaction Info | Block #30466509/Trx b99394847ceacae59cdf4c3dd4cf90022ab15e6e |
View Raw JSON Data
{
"trx_id": "b99394847ceacae59cdf4c3dd4cf90022ab15e6e",
"block": 30466509,
"trx_in_block": 7,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-02-18T21:52:00",
"op": [
"vote",
{
"voter": "fuzz-ai",
"author": "fuzz-ai",
"permlink": "reproducing-a-memory-tracking-bug-with-tla",
"weight": 10000
}
]
}portugalcoinupvoted (15.00%) @fuzz-ai / reproducing-a-memory-tracking-bug-with-tla2019/02/18 02:52:48
portugalcoinupvoted (15.00%) @fuzz-ai / reproducing-a-memory-tracking-bug-with-tla
2019/02/18 02:52:48
| voter | portugalcoin |
| author | fuzz-ai |
| permlink | reproducing-a-memory-tracking-bug-with-tla |
| weight | 1500 (15.00%) |
| Transaction Info | Block #30443739/Trx d891e02cd44248f5925686b850570406240f2c54 |
View Raw JSON Data
{
"trx_id": "d891e02cd44248f5925686b850570406240f2c54",
"block": 30443739,
"trx_in_block": 14,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-02-18T02:52:48",
"op": [
"vote",
{
"voter": "portugalcoin",
"author": "fuzz-ai",
"permlink": "reproducing-a-memory-tracking-bug-with-tla",
"weight": 1500
}
]
}yofanupvoted (100.00%) @fuzz-ai / reproducing-a-memory-tracking-bug-with-tla2019/02/18 02:37:54
yofanupvoted (100.00%) @fuzz-ai / reproducing-a-memory-tracking-bug-with-tla
2019/02/18 02:37:54
| voter | yofan |
| author | fuzz-ai |
| permlink | reproducing-a-memory-tracking-bug-with-tla |
| weight | 10000 (100.00%) |
| Transaction Info | Block #30443441/Trx de4455b529a50f2f4de06f0fe1cbef09affb8273 |
View Raw JSON Data
{
"trx_id": "de4455b529a50f2f4de06f0fe1cbef09affb8273",
"block": 30443441,
"trx_in_block": 22,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-02-18T02:37:54",
"op": [
"vote",
{
"voter": "yofan",
"author": "fuzz-ai",
"permlink": "reproducing-a-memory-tracking-bug-with-tla",
"weight": 10000
}
]
}fuzz-aipublished a new post: reproducing-a-memory-tracking-bug-with-tla2019/02/18 02:37:30
fuzz-aipublished a new post: reproducing-a-memory-tracking-bug-with-tla
2019/02/18 02:37:30
| parent author | |
| parent permlink | programming |
| author | fuzz-ai |
| permlink | reproducing-a-memory-tracking-bug-with-tla |
| title | Reproducing a Memory-Tracking Bug with TLA+ |
| body | <div class="pull-right">  </div> I was interested in a first project for getting familiar with [TLA+](https://lamport.azurewebsites.net/tla/tla.html), “a high-level language for modelling programs and systems.” TLA+ has been used to find errors in the design of real-world distributed systems, so I was curious how it compared to model checkers I have previously used such as [Alloy](http://alloytools.org/). A co-worker recently tracked down a concurrency bug that was causing some test failures. I was interested in seeing if I could model the system with TLA+, and reproduce the failure using its consistency checker, TLC. The system where the failure occurs is a wrapper around memory allocation. It tracks, per allocation, which “phase” performed the allocation. A phase is just a lightweight replacement for a full backtrace; it’s an identifier representing a particular section of code, maintained in a per-thread stack. In the failing tests, memory usage was reported per-phase by walking a list of allocated memory items and summing their sizes. This process asserted because it found an allocation marked free within the list. The bug was a simple ordering problem. While the deallocation code should have removed the memory from a per-phase list first, then marked it free, it did the reverse: ``` wrap_free( void *m ) { Wrapper *p = convert_to_wrapper( m ); p->state = FREE; PhaseList *l = get_list( p->phase ); lock( l->mutex ); remove_from_list( l, p ); unlock( l->mutex ); } ``` The complete model I wrote can be found here: https://gist.github.com/fuzz-ai/5013d8fca33bd924c1ffd35584bf66fb ## Modelling allocation and deallocation In order to demonstrate the concurrency problem, the allocate and deallocate operations have to be split into multiple actions. Otherwise, the model will act as if the entire sequence of events was an atomic operation. But, we don’t need to explicitly represent the memory allocator itself, or the operation of the mutex. Instead, i chose to represent each operation as the portion outside the mutex, and the critical section inside the mutex. In the model these are the actions `AllocNoncritical`, `AllocCritical`, `FreeNonCritical`, and `FreeCritical`. I also had to decide what portion of the state is worth including. I chose to represent a memory allocation as a record with three elements: a memory address (to ensure uniqueness), a phase, and a state (free, allocated, or none.) ``` States == { "alloc", "free", "none" } MemoryAllocation == [ addr : Address, phase: Phase, state : States ] ``` `Address` and `Phase` are “constants” of the model, which in TLA+ terms means they could be any object at all. When it comes time to check the model with TLC, a specific set of “model objects” are plugged in to make the model finite. The third constant in the model is a set of threads: ``` CONSTANTS Phase, (* A set of phases *) Thread, (* A set of threads *) Address (* A set of addresses *) ``` A point in time of a TLA+ model corresponds to an assignment of values to variables. The variables may (or may not!) change at each step in the evolution of the model. I used one variable to represent a set of allocations “in use”, a second variable to track the per-phase lists, and the third variable to track the local variable inside a particular thread. ``` VARIABLES memory, (* All in-use allocations *) memoryByPhase, (* A mapping from phases to sets of allocated items *) memoryByThread (* A mapping from threads to an allocated record *) ``` I chose to have the thread state be represented by a `MemoryAllocation` as well, which may have been a questionable choice. That is why a memory allocation may have a “none” state to represent a thread not currently engaged in an allocation or deallocation. I represented that as a special `MemoryAllocation`, one which all threads start with. But because the record needs an address and phase, I asked TLA to pick one arbitrarily: ``` DontCareAddress == CHOOSE a \in Address : TRUE DontCarePhase == CHOOSE p \in Phase: TRUE NoAllocation == [ addr |-> DontCareAddress, phase |-> DontCarePhase, state |-> "none" ] Init == /\ memory = {} /\ memoryByPhase = [ p \in Phase |-> {} ] /\ memoryByThread = [ t \in Thread |-> NoAllocation ] ``` We can also write a predicate that checks whether the variables have the correct type: ``` TypeInvariant == /\ memory \in SUBSET MemoryAllocation /\ memoryByPhase \in [Phase -> SUBSET MemoryAllocation] (* Each phase has a list, but order not important *) /\ memoryByThread \in [Thread -> MemoryAllocation] (* Each thread can only be doing one allocation or deallocation at a time *) ``` Now we can write the actions in terms of the current state (unprimed variables) and the next state (primed variables). The action of a particular thread `t` allocating memory in phase `p` is represented by the following action: ``` (* Non-critical section: allocate some memory from the heap *) AllocNoncritical(t,p) == /\ memoryByThread[t].state = "none" /\ \E m \in MemoryAllocation : /\ m.state = "alloc" /\ m.phase = p /\ AddressNotInUse(m) /\ memoryByThread' = [ memoryByThread EXCEPT ![t] = m ] /\ UNCHANGED <<memoryByPhase, memory>> (* Critical section; add it to the list for the phase it was allocated (and return it for use.) *) AllocCritical(t) == LET m == memoryByThread[t] IN /\ m.state = "alloc" /\ memoryByPhase' = [ memoryByPhase EXCEPT ![m.phase] = memoryByPhase[m.phase] \union { m } ] /\ memoryByThread' = [ memoryByThread EXCEPT ![t] = NoAllocation ] /\ memory' = memory \union { m } ``` In TLA+ you can’t “modify” a set or mapping. You instead have to provide a replacement set or mapping for the new time step. The `EXCEPT` syntax is a way to take a function and provide a new one that’s the same everywhere but one value. The use of `memoryByThread` ensures that a particular thread must “execute” `AllocNoncritical` first (so that the memory it points to is no longer a “none”), and cannot execute `AllocNoncritical` a second time without going through `AllocCritical`. This is one way to represent the flow of execution. In practice, it’s probably easier to write the model in PlusCal instead which provides a more natural way of representing a sequence of operations. Writing the `FreeCritical` action is so painful that it screams there is a problem here, even before running the model checker. Again, there’s no sense in TLA+ of “changing the MemoryAllocation object”. The record isn’t a variable; it’s not mutable. We have to replace the `MemoryAllocation`, wherever it occurs, with a replacement record: ``` FreeNoncritical(t,m) == LET m2 == [ addr |-> m.addr, state |-> "free", phase |-> m.phase ] IN /\ m \in memory /\ memoryByThread[t].state = "none" /\ memoryByThread' = [memoryByThread EXCEPT ![t] = m2] /\ memoryByPhase' = [memoryByPhase EXCEPT ![m.phase] = (memoryByPhase[m.phase] \ {m}) \union {m2} ] /\ memory' = (memory \ { m }) \union { m2 } ``` We finish the specification by combining all the actions and the initial state, along with the temporal operator `[]` which means “always”, into the top-level specification: ``` Next == \/ \E t \in Thread, p \in Phase : AllocNoncritical(t, p) \/ \E t \in Thread : AllocCritical(t) \/ \E t \in Thread, m \in MemoryAllocation : FreeNoncritical(t, m) \/ \E t \in Thread : FreeCritical( t ) vars == <<memory,memoryByPhase,memoryByThread>> Spec == Init /\ [][Next]_vars ``` ## Checking the model In the original code, the assertion fired when an element in the per-phase list was not listed as allocated. So, our assertion about the behavior of the model will required that every memory allocation, on every per-phase list, is in the allocated state: ``` AllAlloced == \A p \in Phase : \A m \in MemoryAllocation : m \in memoryByPhase[p] => m.state = "alloc" ``` Or, in TLA+’s neatly typeset form:  To perform an exhaustive search for violations of this invariant, we need to fill in the model’s constants with finite sets. I arbitrarily picked five different addresses, three phases, and two threads. Each of the sets is treated as “symmetrical” which means that the checker can test just one permutation of the elements.  TLC quickly finds and flags the error: ``` Invariant AllAlloced is violated ``` and provides an explorable time sequence that lead to the state where the invariant is false:  ## Pitfalls The first version of the invariant, I wrote like this: ``` AllAlloced == \A p \in Phase : \A m \in memoryByPhase[p] : m.state = "alloc" ``` and this is valid TLA+. However, due to other errors in the specification, TLC complained that it couldn’t enumerate all the values of m; it believed that was an infinite set. Unfortunately, “unable to enumerate” is a frequent outcome from errors in the specification. For example, I got the syntax wrong for records; instead of ``` NoAllocation == [ addr |-> DontCareAddress, phase |-> DontCarePhase, state |-> "none" ] ``` I used ``` NoAllocation == [ addr : DontCareAddress, phase : DontCarePhase, state : "none" ] ``` which produces the following error: ``` Attempted to enumerate a set of the form [l1 : v1, ..., ln : vn], but can't enumerate the value of the `addr' field: a1 While working on the initial state: /\ memoryByThread = (t1 :> [addr: a1, phase: p1, state: "none"] @@ t2 :> [addr: a1, phase: p1, state: "none"]) /\ memoryByPhase = (p1 :> {} @@ p2 :> {} @@ p3 :> {}) /\ memory = {} ``` This led me to make a lot of changes to try to work around the problem: was I setting up model variables incorrectly? Was my weirdo use of `CHOOSE` the problem? Should my strings be constants as well? Part of the problem is that the initial state *looks* OK, to a novice. It’s got the structures I expected to see, but those aren’t structures, they are sets. The real initial state looks like this: ``` /\ memory = {} /\ memoryByPhase = (p1 :> {} @@ p2 :> {} @@ p3 :> {}) /\ memoryByThread = ( t1 :> [addr |-> a1, phase |-> p1, state |-> "none"] @@ t2 :> [addr |-> a1, phase |-> p1, state |-> "none"] ) ``` A further pitfall was that “Specifying Systems”, the authoritative book on TLA+, quickly abandons using the input format in favor of nicely-typeset specifications. This made it hard to reproduce a construct introduced in the text, without referring elsewhere to an example specification. For example, tuples are enclosed in `<< >>` but are typeset with a single angle bracket. Perhaps a [Detexifier](http://detexify.kirelabs.org/classify.html) for TLA+ would help. ## Conclusions My experience getting a toy specification written in TLA+ was much more difficult than other model-checking systems I have previously used, such as Alloy or SPIN. Probably if I had gotten Hillel Wayne’s Practical TLA+ first instead of Specifying Systems, I would have done this exercise is PlusCal instead which may have been an easier path. The model checker did, as expected, find the bug my co-worked discovered. However, the exercise of writing the specification would probably have been, by itself, sufficient warning that the order of operations was incorrect--- assuming that the model clearly separated out the mutex-protected and non-mutex-protected sections as I did here. I think there is a lot of opportunity to improve on the TLA+ and TLC experience. Better error messages would help (see https://groups.google.com/d/msg/tlaplus/w3OCMI-5Dz4/sUV9M7_njykJ for an even worse experience than mine, but from 2013.) The TLA toolbox does a good job of packaging everything up so that it works out of the box, but from a usability perspective the maze of tabs and sub-windows doesn’t feel very modern, and sometimes errors were hidden as pop-ups behind tiny icons. Model-checking also felt like a very manual process rather than one where there were sensible defaults. For example, in Alloy you can specify the maximum size of the model in terms of number of objects. You can also ask Alloy “show me an example of X” and get a nice graphical representation, which I found lacking when trying to understand an issue where memory wasn’t being successfully allocated. TLC can function as a “calculator” for TLA+, which is useful, but it’s far from a smooth, interactive experience, at least through Toolbox. Further reading; * https://www.learntla.com and ["Practical TLA+"](https://www.amazon.com/Practical-TLA-Planning-Driven-Development/dp/1484238281) by Hillel Wayne * https://lamport.azurewebsites.net/tla/tla.html and ["Specifying Systems”](https://www.amazon.com/Specifying-Systems-Language-Hardware-Engineers/dp/032114306X) by Leslie Lamport ## Fuzz.ai [Fuzz.ai](http://www.fuzz.ai/) is an early-stage startup dedicated to making software correctness tools easier to use. Fuzzers, model checkers, and property-based testing can make software more robust, expose security vulnerabilities, and speed development. |
| json metadata | {"tags":["programming","software","tlaplus","steemstem","concurrency"],"image":["https://cdn.steemitimages.com/DQmYRX4ZdoPukkiEdmLSMm3Er73NCaKex1eRn2gENTF1uqt/image.png","https://cdn.steemitimages.com/DQmajnnUwyYn953ryfBLEspL14qw6vRnQFhtbu8udNfth6P/tla-memory-3.png","https://cdn.steemitimages.com/DQmPjhwTwekFbhp3ZqVJ1nCGMeXzGtUZZLmghtB1M7aqDX2/tla-memory-1.png","https://cdn.steemitimages.com/DQmREFE6y6QWp3fdWg8ZLTMwrCFCqEHASLnFUsJEWr1XBZZ/tla-memory--2.png"],"links":["https://lamport.azurewebsites.net/tla/tla.html","http://alloytools.org/","https://gist.github.com/fuzz-ai/5013d8fca33bd924c1ffd35584bf66fb","http://detexify.kirelabs.org/classify.html","https://groups.google.com/d/msg/tlaplus/w3OCMI-5Dz4/sUV9M7_njykJ","https://www.learntla.com","https://www.amazon.com/Practical-TLA-Planning-Driven-Development/dp/1484238281","https://www.amazon.com/Specifying-Systems-Language-Hardware-Engineers/dp/032114306X","http://www.fuzz.ai/"],"app":"steemit/0.1","format":"markdown"} |
| Transaction Info | Block #30443433/Trx 9d93a232b433eb4bb72ba638dd384104041d66e1 |
View Raw JSON Data
{
"trx_id": "9d93a232b433eb4bb72ba638dd384104041d66e1",
"block": 30443433,
"trx_in_block": 26,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-02-18T02:37:30",
"op": [
"comment",
{
"parent_author": "",
"parent_permlink": "programming",
"author": "fuzz-ai",
"permlink": "reproducing-a-memory-tracking-bug-with-tla",
"title": "Reproducing a Memory-Tracking Bug with TLA+",
"body": "<div class=\"pull-right\">\n\n\n</div>\n\nI was interested in a first project for getting familiar with [TLA+](https://lamport.azurewebsites.net/tla/tla.html), “a high-level language for modelling programs and systems.” TLA+ has been used to find errors in the design of real-world distributed systems, so I was curious how it compared to model checkers I have previously used such as [Alloy](http://alloytools.org/). A co-worker recently tracked down a concurrency bug that was causing some test failures. I was interested in seeing if I could model the system with TLA+, and reproduce the failure using its consistency checker, TLC.\n\n\nThe system where the failure occurs is a wrapper around memory allocation. It tracks, per allocation, which “phase” performed the allocation. A phase is just a lightweight replacement for a full backtrace; it’s an identifier representing a particular section of code, maintained in a per-thread stack. In the failing tests, memory usage was reported per-phase by walking a list of allocated memory items and summing their sizes. This process asserted because it found an allocation marked free within the list.\n\nThe bug was a simple ordering problem. While the deallocation code should have removed the memory from a per-phase list first, then marked it free, it did the reverse:\n\n```\nwrap_free( void *m ) {\n Wrapper *p = convert_to_wrapper( m );\n p->state = FREE;\n PhaseList *l = get_list( p->phase );\n\n lock( l->mutex );\n remove_from_list( l, p );\n unlock( l->mutex );\n}\n```\n\nThe complete model I wrote can be found here: https://gist.github.com/fuzz-ai/5013d8fca33bd924c1ffd35584bf66fb\n\n## Modelling allocation and deallocation\n\nIn order to demonstrate the concurrency problem, the allocate and deallocate operations have to be split into multiple actions. Otherwise, the model will act as if the entire sequence of events was an atomic operation. But, we don’t need to explicitly represent the memory allocator itself, or the operation of the mutex. Instead, i chose to represent each operation as the portion outside the mutex, and the critical section inside the mutex. In the model these are the actions `AllocNoncritical`, `AllocCritical`, `FreeNonCritical`, and `FreeCritical`.\n\nI also had to decide what portion of the state is worth including. I chose to represent a memory allocation as a record with three elements: a memory address (to ensure uniqueness), a phase, and a state (free, allocated, or none.)\n\n```\nStates == { \"alloc\", \"free\", \"none\" }\nMemoryAllocation == [ addr : Address, phase: Phase, state : States ]\n```\n\n`Address` and `Phase` are “constants” of the model, which in TLA+ terms means they could be any object at all. When it comes time to check the model with TLC, a specific set of “model objects” are plugged in to make the model finite. The third constant in the model is a set of threads:\n\n```\nCONSTANTS Phase, (* A set of phases *)\n Thread, (* A set of threads *)\n Address (* A set of addresses *)\n```\n\nA point in time of a TLA+ model corresponds to an assignment of values to variables. The variables may (or may not!) change at each step in the evolution of the model. I used one variable to represent a set of allocations “in use”, a second variable to track the per-phase lists, and the third variable to track the local variable inside a particular thread.\n\n```\nVARIABLES memory, (* All in-use allocations *)\n memoryByPhase, (* A mapping from phases to sets of allocated items *)\n memoryByThread (* A mapping from threads to an allocated record *) \n```\n\nI chose to have the thread state be represented by a `MemoryAllocation` as well, which may have been a questionable choice. That is why a memory allocation may have a “none” state to represent a thread not currently engaged in an allocation or deallocation. I represented that as a special `MemoryAllocation`, one which all threads start with. But because the record needs an address and phase, I asked TLA to pick one arbitrarily:\n\n```\nDontCareAddress == CHOOSE a \\in Address : TRUE\nDontCarePhase == CHOOSE p \\in Phase: TRUE\nNoAllocation == [ addr |-> DontCareAddress, phase |-> DontCarePhase, state |-> \"none\" ]\n \nInit ==\n /\\ memory = {}\n /\\ memoryByPhase = [ p \\in Phase |-> {} ]\n /\\ memoryByThread = [ t \\in Thread |-> NoAllocation ]\n```\n\nWe can also write a predicate that checks whether the variables have the correct type:\n\n```\nTypeInvariant == \n /\\ memory \\in SUBSET MemoryAllocation\n /\\ memoryByPhase \\in [Phase -> SUBSET MemoryAllocation] (* Each phase has a list, but order not important *) \n /\\ memoryByThread \\in [Thread -> MemoryAllocation] (* Each thread can only be doing one allocation or deallocation at a time *)\n```\n\nNow we can write the actions in terms of the current state (unprimed variables) and the next state (primed variables). The action of a particular thread `t` allocating memory in phase `p` is represented by the following action:\n\n```\n (* Non-critical section: allocate some memory from the heap *) \nAllocNoncritical(t,p) == \n /\\ memoryByThread[t].state = \"none\"\n /\\ \\E m \\in MemoryAllocation :\n /\\ m.state = \"alloc\"\n /\\ m.phase = p\n /\\ AddressNotInUse(m) \n /\\ memoryByThread' = [ memoryByThread EXCEPT ![t] = m ]\n /\\ UNCHANGED <<memoryByPhase, memory>>\n \n(* Critical section; add it to the list for the phase it was allocated (and return it for use.) *) \nAllocCritical(t) == \n LET m == memoryByThread[t] IN\n /\\ m.state = \"alloc\"\n /\\ memoryByPhase' = [ memoryByPhase EXCEPT ![m.phase] = memoryByPhase[m.phase] \\union { m } ]\n /\\ memoryByThread' = [ memoryByThread EXCEPT ![t] = NoAllocation ]\n /\\ memory' = memory \\union { m }\n```\n\nIn TLA+ you can’t “modify” a set or mapping. You instead have to provide a replacement set or mapping for the new time step. The `EXCEPT` syntax is a way to take a function and provide a new one that’s the same everywhere but one value.\n\nThe use of `memoryByThread` ensures that a particular thread must “execute” `AllocNoncritical` first (so that the memory it points to is no longer a “none”), and cannot execute `AllocNoncritical` a second time without going through `AllocCritical`. This is one way to represent the flow of execution. In practice, it’s probably easier to write the model in PlusCal instead which provides a more natural way of representing a sequence of operations.\n\nWriting the `FreeCritical` action is so painful that it screams there is a problem here, even before running the model checker. Again, there’s no sense in TLA+ of “changing the MemoryAllocation object”. The record isn’t a variable; it’s not mutable. We have to replace the `MemoryAllocation`, wherever it occurs, with a replacement record:\n\n```\nFreeNoncritical(t,m) ==\n LET m2 == [ addr |-> m.addr, state |-> \"free\", phase |-> m.phase ] IN\n /\\ m \\in memory\n /\\ memoryByThread[t].state = \"none\"\n /\\ memoryByThread' = [memoryByThread EXCEPT ![t] = m2]\n /\\ memoryByPhase' = [memoryByPhase EXCEPT ![m.phase] = (memoryByPhase[m.phase] \\ {m}) \\union {m2} ]\n /\\ memory' = (memory \\ { m }) \\union { m2 } \n```\n\nWe finish the specification by combining all the actions and the initial state, along with the temporal operator `[]` which means “always”, into the top-level specification:\n\n```\nNext == \n \\/ \\E t \\in Thread, p \\in Phase : AllocNoncritical(t, p)\n \\/ \\E t \\in Thread : AllocCritical(t)\n \\/ \\E t \\in Thread, m \\in MemoryAllocation : FreeNoncritical(t, m)\n \\/ \\E t \\in Thread : FreeCritical( t )\n\nvars == <<memory,memoryByPhase,memoryByThread>>\n \nSpec == Init /\\ [][Next]_vars\n```\n\n## Checking the model\n\nIn the original code, the assertion fired when an element in the per-phase list was not listed as allocated. So, our assertion about the behavior of the model will required that every memory allocation, on every per-phase list, is in the allocated state:\n\n```\nAllAlloced == \\A p \\in Phase : \\A m \\in MemoryAllocation : m \\in memoryByPhase[p] => m.state = \"alloc\"\n```\n\nOr, in TLA+’s neatly typeset form:\n\n\n\nTo perform an exhaustive search for violations of this invariant, we need to fill in the model’s constants with finite sets. I arbitrarily picked five different addresses, three phases, and two threads. Each of the sets is treated as “symmetrical” which means that the checker can test just one permutation of the elements.\n\n\n\nTLC quickly finds and flags the error:\n```\nInvariant AllAlloced is violated\n```\nand provides an explorable time sequence that lead to the state where the invariant is false:\n\n\n## Pitfalls\n\nThe first version of the invariant, I wrote like this:\n\n```\nAllAlloced == \\A p \\in Phase : \\A m \\in memoryByPhase[p] : m.state = \"alloc\"\n```\n\nand this is valid TLA+. However, due to other errors in the specification, TLC complained that it couldn’t enumerate all the values of m; it believed that was an infinite set. Unfortunately, “unable to enumerate” is a frequent outcome from errors in the specification.\n\nFor example, I got the syntax wrong for records; instead of\n\n```\nNoAllocation == [ addr |-> DontCareAddress, phase |-> DontCarePhase, state |-> \"none\" ]\n```\n\nI used\n\n```\nNoAllocation == [ addr : DontCareAddress, phase : DontCarePhase, state : \"none\" ]\n```\n\nwhich produces the following error:\n\n```\nAttempted to enumerate a set of the form [l1 : v1, ..., ln : vn],\nbut can't enumerate the value of the `addr' field:\na1\nWhile working on the initial state:\n/\\ memoryByThread = (t1 :> [addr: a1, phase: p1, state: \"none\"] @@ t2 :> [addr: a1, phase: p1, state: \"none\"])\n/\\ memoryByPhase = (p1 :> {} @@ p2 :> {} @@ p3 :> {})\n/\\ memory = {}\n```\n\nThis led me to make a lot of changes to try to work around the problem: was I setting up model variables incorrectly? Was my weirdo use of `CHOOSE` the problem? Should my strings be constants as well?\n\nPart of the problem is that the initial state *looks* OK, to a novice. It’s got the structures I expected to see, but those aren’t structures, they are sets. The real initial state looks like this:\n\n```\n/\\ memory = {}\n/\\ memoryByPhase = (p1 :> {} @@ p2 :> {} @@ p3 :> {})\n/\\ memoryByThread = ( t1 :> [addr |-> a1, phase |-> p1, state |-> \"none\"] @@\n t2 :> [addr |-> a1, phase |-> p1, state |-> \"none\"] )\n```\n\nA further pitfall was that “Specifying Systems”, the authoritative book on TLA+, quickly abandons using the input format in favor of nicely-typeset specifications. This made it hard to reproduce a construct introduced in the text, without referring elsewhere to an example specification. For example, tuples are enclosed in `<< >>` but are typeset with a single angle bracket. Perhaps a [Detexifier](http://detexify.kirelabs.org/classify.html) for TLA+ would help.\n\n## Conclusions\n\nMy experience getting a toy specification written in TLA+ was much more difficult than other model-checking systems I have previously used, such as Alloy or SPIN. Probably if I had gotten Hillel Wayne’s Practical TLA+ first instead of Specifying Systems, I would have done this exercise is PlusCal instead which may have been an easier path.\n\nThe model checker did, as expected, find the bug my co-worked discovered. However, the exercise of writing the specification would probably have been, by itself, sufficient warning that the order of operations was incorrect--- assuming that the model clearly separated out the mutex-protected and non-mutex-protected sections as I did here.\n\nI think there is a lot of opportunity to improve on the TLA+ and TLC experience. Better error messages would help (see https://groups.google.com/d/msg/tlaplus/w3OCMI-5Dz4/sUV9M7_njykJ for an even worse experience than mine, but from 2013.) The TLA toolbox does a good job of packaging everything up so that it works out of the box, but from a usability perspective the maze of tabs and sub-windows doesn’t feel very modern, and sometimes errors were hidden as pop-ups behind tiny icons.\n\nModel-checking also felt like a very manual process rather than one where there were sensible defaults. For example, in Alloy you can specify the maximum size of the model in terms of number of objects. You can also ask Alloy “show me an example of X” and get a nice graphical representation, which I found lacking when trying to understand an issue where memory wasn’t being successfully allocated. TLC can function as a “calculator” for TLA+, which is useful, but it’s far from a smooth, interactive experience, at least through Toolbox.\n\nFurther reading;\n * https://www.learntla.com and [\"Practical TLA+\"](https://www.amazon.com/Practical-TLA-Planning-Driven-Development/dp/1484238281) by Hillel Wayne\n * https://lamport.azurewebsites.net/tla/tla.html and [\"Specifying Systems”](https://www.amazon.com/Specifying-Systems-Language-Hardware-Engineers/dp/032114306X) by Leslie Lamport\n\n## Fuzz.ai\n\n[Fuzz.ai](http://www.fuzz.ai/) is an early-stage startup dedicated to making software correctness tools easier to use. Fuzzers, model checkers, and property-based testing can make software more robust, expose security vulnerabilities, and speed development.",
"json_metadata": "{\"tags\":[\"programming\",\"software\",\"tlaplus\",\"steemstem\",\"concurrency\"],\"image\":[\"https://cdn.steemitimages.com/DQmYRX4ZdoPukkiEdmLSMm3Er73NCaKex1eRn2gENTF1uqt/image.png\",\"https://cdn.steemitimages.com/DQmajnnUwyYn953ryfBLEspL14qw6vRnQFhtbu8udNfth6P/tla-memory-3.png\",\"https://cdn.steemitimages.com/DQmPjhwTwekFbhp3ZqVJ1nCGMeXzGtUZZLmghtB1M7aqDX2/tla-memory-1.png\",\"https://cdn.steemitimages.com/DQmREFE6y6QWp3fdWg8ZLTMwrCFCqEHASLnFUsJEWr1XBZZ/tla-memory--2.png\"],\"links\":[\"https://lamport.azurewebsites.net/tla/tla.html\",\"http://alloytools.org/\",\"https://gist.github.com/fuzz-ai/5013d8fca33bd924c1ffd35584bf66fb\",\"http://detexify.kirelabs.org/classify.html\",\"https://groups.google.com/d/msg/tlaplus/w3OCMI-5Dz4/sUV9M7_njykJ\",\"https://www.learntla.com\",\"https://www.amazon.com/Practical-TLA-Planning-Driven-Development/dp/1484238281\",\"https://www.amazon.com/Specifying-Systems-Language-Hardware-Engineers/dp/032114306X\",\"http://www.fuzz.ai/\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
}
]
}2019/02/08 06:03:12
2019/02/08 06:03:12
| parent author | fuzz-ai |
| parent permlink | fuzz-testing-the-snappy-compression-algorithm |
| author | bobinson |
| permlink | re-fuzz-ai-fuzz-testing-the-snappy-compression-algorithm-20190208t060310426z |
| title | |
| body | Thats impressive snappy ;-) |
| json metadata | {"tags":["software"],"app":"steemit/0.1"} |
| Transaction Info | Block #30159760/Trx bf6e6b66540b91dbc08a27c6592e6338bb6803dc |
View Raw JSON Data
{
"trx_id": "bf6e6b66540b91dbc08a27c6592e6338bb6803dc",
"block": 30159760,
"trx_in_block": 11,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-02-08T06:03:12",
"op": [
"comment",
{
"parent_author": "fuzz-ai",
"parent_permlink": "fuzz-testing-the-snappy-compression-algorithm",
"author": "bobinson",
"permlink": "re-fuzz-ai-fuzz-testing-the-snappy-compression-algorithm-20190208t060310426z",
"title": "",
"body": "Thats impressive snappy ;-)",
"json_metadata": "{\"tags\":[\"software\"],\"app\":\"steemit/0.1\"}"
}
]
}2019/02/03 15:09:45
2019/02/03 15:09:45
| from | aro.steem |
| to | fuzz-ai |
| amount | 0.001 STEEM |
| memo | Yo Steemian, 💧 1 ETH award Ethereum Smart Contract Lottery, Hurry Up and Join! https://www.etherdrop.app |
| Transaction Info | Block #30026831/Trx 3d3360f4b1120f50212bfd19e601898b07550164 |
View Raw JSON Data
{
"trx_id": "3d3360f4b1120f50212bfd19e601898b07550164",
"block": 30026831,
"trx_in_block": 12,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-02-03T15:09:45",
"op": [
"transfer",
{
"from": "aro.steem",
"to": "fuzz-ai",
"amount": "0.001 STEEM",
"memo": "Yo Steemian, 💧 1 ETH award Ethereum Smart Contract Lottery, Hurry Up and Join! https://www.etherdrop.app"
}
]
}2019/01/18 08:19:48
2019/01/18 08:19:48
| parent author | fuzz-ai |
| parent permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| author | partiko |
| permlink | partiko-re-fuzz-ai-fuzz-testing-ontology-s-neovm-execution-engine-20190118t081948398z |
| title | |
| body | Thank you so much for sharing this amazing post with us! Have you heard about Partiko? It’s a really convenient mobile app for Steem! With Partiko, you can easily see what’s going on in the Steem community, make posts and comments (no beneficiary cut forever!), and always stayed connected with your followers via push notification! Partiko also rewards you with Partiko Points (3000 Partiko Point bonus when you first use it!), and Partiko Points can be converted into Steem tokens. You can earn Partiko Points easily by making posts and comments using Partiko. We also noticed that your Steem Power is low. We will be very happy to delegate 15 Steem Power to you once you have made a post using Partiko! With more Steem Power, you can make more posts and comments, and earn more rewards! If that all sounds interesting, you can: - Download Partiko Android at [Google Play](http://bit.ly/2SRFIta) - Or Download Partiko iOS on the [App Store](https://apple.co/2PcXkSd) Thank you so much for reading this message! |
| json metadata | {"app":"partiko"} |
| Transaction Info | Block #29558301/Trx f92507e5eb200d468afafeb14325e90693ebfcc0 |
View Raw JSON Data
{
"trx_id": "f92507e5eb200d468afafeb14325e90693ebfcc0",
"block": 29558301,
"trx_in_block": 16,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-18T08:19:48",
"op": [
"comment",
{
"parent_author": "fuzz-ai",
"parent_permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"author": "partiko",
"permlink": "partiko-re-fuzz-ai-fuzz-testing-ontology-s-neovm-execution-engine-20190118t081948398z",
"title": "",
"body": "Thank you so much for sharing this amazing post with us!\n\nHave you heard about Partiko? It’s a really convenient mobile app for Steem! With Partiko, you can easily see what’s going on in the Steem community, make posts and comments (no beneficiary cut forever!), and always stayed connected with your followers via push notification!\n\nPartiko also rewards you with Partiko Points (3000 Partiko Point bonus when you first use it!), and Partiko Points can be converted into Steem tokens. You can earn Partiko Points easily by making posts and comments using Partiko.\n\nWe also noticed that your Steem Power is low. We will be very happy to delegate 15 Steem Power to you once you have made a post using Partiko! With more Steem Power, you can make more posts and comments, and earn more rewards!\n\nIf that all sounds interesting, you can: \n\n- Download Partiko Android at [Google Play](http://bit.ly/2SRFIta)\n- Or Download Partiko iOS on the [App Store](https://apple.co/2PcXkSd)\n\nThank you so much for reading this message!",
"json_metadata": "{\"app\":\"partiko\"}"
}
]
}fuzz-aireceived 0.134 STEEM, 0.167 SP author reward for @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/15 05:59:36
fuzz-aireceived 0.134 STEEM, 0.167 SP author reward for @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/15 05:59:36
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| sbd payout | 0.000 SBD |
| steem payout | 0.134 STEEM |
| vesting payout | 271.143235 VESTS |
| Transaction Info | Block #29469200/Virtual Operation #25 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 29469200,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 25,
"timestamp": "2019-01-15T05:59:36",
"op": [
"author_reward",
{
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"sbd_payout": "0.000 SBD",
"steem_payout": "0.134 STEEM",
"vesting_payout": "271.143235 VESTS"
}
]
}fuzz-aireceived 0.001 SP curation reward for @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/15 05:59:36
fuzz-aireceived 0.001 SP curation reward for @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/15 05:59:36
| curator | fuzz-ai |
| reward | 2.008468 VESTS |
| comment author | fuzz-ai |
| comment permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| Transaction Info | Block #29469200/Virtual Operation #23 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 29469200,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 23,
"timestamp": "2019-01-15T05:59:36",
"op": [
"curation_reward",
{
"curator": "fuzz-ai",
"reward": "2.008468 VESTS",
"comment_author": "fuzz-ai",
"comment_permlink": "fuzz-testing-ontology-s-neovm-execution-engine"
}
]
}fuzz-aireceived 0.006 SP curation reward for @mattockfs / tutorial-asynchonous-python-with-twisted-part-three2019/01/14 21:44:15
fuzz-aireceived 0.006 SP curation reward for @mattockfs / tutorial-asynchonous-python-with-twisted-part-three
2019/01/14 21:44:15
| curator | fuzz-ai |
| reward | 10.042533 VESTS |
| comment author | mattockfs |
| comment permlink | tutorial-asynchonous-python-with-twisted-part-three |
| Transaction Info | Block #29459305/Virtual Operation #35 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 29459305,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 35,
"timestamp": "2019-01-14T21:44:15",
"op": [
"curation_reward",
{
"curator": "fuzz-ai",
"reward": "10.042533 VESTS",
"comment_author": "mattockfs",
"comment_permlink": "tutorial-asynchonous-python-with-twisted-part-three"
}
]
}fuzz-aiupvoted (100.00%) @timcliff / bounty-mission-success-multisignature-transaction-guide-complete2019/01/10 06:00:36
fuzz-aiupvoted (100.00%) @timcliff / bounty-mission-success-multisignature-transaction-guide-complete
2019/01/10 06:00:36
| voter | fuzz-ai |
| author | timcliff |
| permlink | bounty-mission-success-multisignature-transaction-guide-complete |
| weight | 10000 (100.00%) |
| Transaction Info | Block #29325321/Trx a6baeeb32dd0780b9547dc9f04fb62ae681b253d |
View Raw JSON Data
{
"trx_id": "a6baeeb32dd0780b9547dc9f04fb62ae681b253d",
"block": 29325321,
"trx_in_block": 18,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-10T06:00:36",
"op": [
"vote",
{
"voter": "fuzz-ai",
"author": "timcliff",
"permlink": "bounty-mission-success-multisignature-transaction-guide-complete",
"weight": 10000
}
]
}fuzz-aiupvoted (100.00%) @whatsup / censorship-resistance-is-at-the-blockchain-level2019/01/10 05:59:27
fuzz-aiupvoted (100.00%) @whatsup / censorship-resistance-is-at-the-blockchain-level
2019/01/10 05:59:27
| voter | fuzz-ai |
| author | whatsup |
| permlink | censorship-resistance-is-at-the-blockchain-level |
| weight | 10000 (100.00%) |
| Transaction Info | Block #29325298/Trx eced425605c4f50d428d45e7fdaf6a092aea95a0 |
View Raw JSON Data
{
"trx_id": "eced425605c4f50d428d45e7fdaf6a092aea95a0",
"block": 29325298,
"trx_in_block": 15,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-10T05:59:27",
"op": [
"vote",
{
"voter": "fuzz-ai",
"author": "whatsup",
"permlink": "censorship-resistance-is-at-the-blockchain-level",
"weight": 10000
}
]
}fuzz-aireceived 0.001 SP curation reward for @codingdefined / 2018-year-in-review-as-an-open-source-developer2019/01/10 05:20:57
fuzz-aireceived 0.001 SP curation reward for @codingdefined / 2018-year-in-review-as-an-open-source-developer
2019/01/10 05:20:57
| curator | fuzz-ai |
| reward | 2.009029 VESTS |
| comment author | codingdefined |
| comment permlink | 2018-year-in-review-as-an-open-source-developer |
| Transaction Info | Block #29324527/Virtual Operation #97 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 29324527,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 97,
"timestamp": "2019-01-10T05:20:57",
"op": [
"curation_reward",
{
"curator": "fuzz-ai",
"reward": "2.009029 VESTS",
"comment_author": "codingdefined",
"comment_permlink": "2018-year-in-review-as-an-open-source-developer"
}
]
}markgritterupvoted (100.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/10 05:18:06
markgritterupvoted (100.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/10 05:18:06
| voter | markgritter |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 10000 (100.00%) |
| Transaction Info | Block #29324471/Trx 651ec4d43d04c12655b094e1d0019bdc13222933 |
View Raw JSON Data
{
"trx_id": "651ec4d43d04c12655b094e1d0019bdc13222933",
"block": 29324471,
"trx_in_block": 32,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-10T05:18:06",
"op": [
"vote",
{
"voter": "markgritter",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 10000
}
]
}minnowboostersent 0.001 SBD to @fuzz-ai- "Congrats! You have been accepted to the @minnowbooster Community driven Whitelist. You now have access to some nice perks, such as bigger upvote limits and the potential to earn bonus payments! Want t..."2019/01/10 01:56:39
minnowboostersent 0.001 SBD to @fuzz-ai- "Congrats! You have been accepted to the @minnowbooster Community driven Whitelist. You now have access to some nice perks, such as bigger upvote limits and the potential to earn bonus payments! Want t..."
2019/01/10 01:56:39
| from | minnowbooster |
| to | fuzz-ai |
| amount | 0.001 SBD |
| memo | Congrats! You have been accepted to the @minnowbooster Community driven Whitelist. You now have access to some nice perks, such as bigger upvote limits and the potential to earn bonus payments! Want to contribute? Click here: https://www.minnowbooster.net/whitelist |
| Transaction Info | Block #29320445/Trx c7438a50974b489c1ed44cbe33a728a1dbf458bb |
View Raw JSON Data
{
"trx_id": "c7438a50974b489c1ed44cbe33a728a1dbf458bb",
"block": 29320445,
"trx_in_block": 14,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-10T01:56:39",
"op": [
"transfer",
{
"from": "minnowbooster",
"to": "fuzz-ai",
"amount": "0.001 SBD",
"memo": "Congrats! You have been accepted to the @minnowbooster Community driven Whitelist. You now have access to some nice perks, such as bigger upvote limits and the potential to earn bonus payments! Want to contribute? Click here: https://www.minnowbooster.net/whitelist"
}
]
}fuzz-aireceived 0.097 STEEM, 0.120 SP author reward for @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing2019/01/09 22:09:21
fuzz-aireceived 0.097 STEEM, 0.120 SP author reward for @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing
2019/01/09 22:09:21
| author | fuzz-ai |
| permlink | improving-ripple-unit-test-coverage-with-fuzzing |
| sbd payout | 0.000 SBD |
| steem payout | 0.097 STEEM |
| vesting payout | 194.879104 VESTS |
| Transaction Info | Block #29315900/Virtual Operation #5 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 29315900,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 5,
"timestamp": "2019-01-09T22:09:21",
"op": [
"author_reward",
{
"author": "fuzz-ai",
"permlink": "improving-ripple-unit-test-coverage-with-fuzzing",
"sbd_payout": "0.000 SBD",
"steem_payout": "0.097 STEEM",
"vesting_payout": "194.879104 VESTS"
}
]
}crokkonupvoted (100.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 07:24:09
crokkonupvoted (100.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 07:24:09
| voter | crokkon |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 10000 (100.00%) |
| Transaction Info | Block #29269421/Trx c0fb526cb2b71657029716947aae68dcc27a5ee6 |
View Raw JSON Data
{
"trx_id": "c0fb526cb2b71657029716947aae68dcc27a5ee6",
"block": 29269421,
"trx_in_block": 18,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T07:24:09",
"op": [
"vote",
{
"voter": "crokkon",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 10000
}
]
}councilupvoted (10.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 07:11:21
councilupvoted (10.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 07:11:21
| voter | council |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 1000 (10.00%) |
| Transaction Info | Block #29269165/Trx 440f6859198d2dd9b17f85cd5903d35da186b7b4 |
View Raw JSON Data
{
"trx_id": "440f6859198d2dd9b17f85cd5903d35da186b7b4",
"block": 29269165,
"trx_in_block": 1,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T07:11:21",
"op": [
"vote",
{
"voter": "council",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 1000
}
]
}sensationupvoted (100.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 06:53:36
sensationupvoted (100.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 06:53:36
| voter | sensation |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 10000 (100.00%) |
| Transaction Info | Block #29268810/Trx 17140443373d6af1ce33e7b2e9b199b8c5d76121 |
View Raw JSON Data
{
"trx_id": "17140443373d6af1ce33e7b2e9b199b8c5d76121",
"block": 29268810,
"trx_in_block": 26,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T06:53:36",
"op": [
"vote",
{
"voter": "sensation",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 10000
}
]
}fuzz-aiupvoted (100.00%) @greer184 / steem-history-march-23-20162019/01/08 06:42:18
fuzz-aiupvoted (100.00%) @greer184 / steem-history-march-23-2016
2019/01/08 06:42:18
| voter | fuzz-ai |
| author | greer184 |
| permlink | steem-history-march-23-2016 |
| weight | 10000 (100.00%) |
| Transaction Info | Block #29268584/Trx db2eb0efe14f97377b69e8c4bf157d085cf7f1d7 |
View Raw JSON Data
{
"trx_id": "db2eb0efe14f97377b69e8c4bf157d085cf7f1d7",
"block": 29268584,
"trx_in_block": 7,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T06:42:18",
"op": [
"vote",
{
"voter": "fuzz-ai",
"author": "greer184",
"permlink": "steem-history-march-23-2016",
"weight": 10000
}
]
}magpieloverupvoted (100.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 06:31:03
magpieloverupvoted (100.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 06:31:03
| voter | magpielover |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 10000 (100.00%) |
| Transaction Info | Block #29268359/Trx 881874aa10b51dd4b6e803a04f18321de7242f02 |
View Raw JSON Data
{
"trx_id": "881874aa10b51dd4b6e803a04f18321de7242f02",
"block": 29268359,
"trx_in_block": 24,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T06:31:03",
"op": [
"vote",
{
"voter": "magpielover",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 10000
}
]
}matildapurseupvoted (25.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 06:26:39
matildapurseupvoted (25.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 06:26:39
| voter | matildapurse |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 2500 (25.00%) |
| Transaction Info | Block #29268271/Trx 0f4e32994366ad5052355f8ace9ac2e9214e679e |
View Raw JSON Data
{
"trx_id": "0f4e32994366ad5052355f8ace9ac2e9214e679e",
"block": 29268271,
"trx_in_block": 8,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T06:26:39",
"op": [
"vote",
{
"voter": "matildapurse",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 2500
}
]
}fuzz-aiupvoted (100.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 06:19:09
fuzz-aiupvoted (100.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 06:19:09
| voter | fuzz-ai |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 10000 (100.00%) |
| Transaction Info | Block #29268121/Trx da328d86be2d202f5228d0a5d2489e263e81b27c |
View Raw JSON Data
{
"trx_id": "da328d86be2d202f5228d0a5d2489e263e81b27c",
"block": 29268121,
"trx_in_block": 12,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T06:19:09",
"op": [
"vote",
{
"voter": "fuzz-ai",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 10000
}
]
}portugalcoinupvoted (15.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 06:14:48
portugalcoinupvoted (15.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 06:14:48
| voter | portugalcoin |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 1500 (15.00%) |
| Transaction Info | Block #29268034/Trx 93b77c58a7c5e34a9b85ba05fce4cd06d7d7cda2 |
View Raw JSON Data
{
"trx_id": "93b77c58a7c5e34a9b85ba05fce4cd06d7d7cda2",
"block": 29268034,
"trx_in_block": 34,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T06:14:48",
"op": [
"vote",
{
"voter": "portugalcoin",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 1500
}
]
}effofexupvoted (0.64%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 06:14:06
effofexupvoted (0.64%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 06:14:06
| voter | effofex |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 64 (0.64%) |
| Transaction Info | Block #29268020/Trx 845acce5eb10c80d814361e2196aab838531d8ed |
View Raw JSON Data
{
"trx_id": "845acce5eb10c80d814361e2196aab838531d8ed",
"block": 29268020,
"trx_in_block": 28,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T06:14:06",
"op": [
"vote",
{
"voter": "effofex",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 64
}
]
}merlin7upvoted (0.12%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 06:14:06
merlin7upvoted (0.12%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 06:14:06
| voter | merlin7 |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 12 (0.12%) |
| Transaction Info | Block #29268020/Trx 33474d49d6d1f693dc5279a4a681d7db21bd89d0 |
View Raw JSON Data
{
"trx_id": "33474d49d6d1f693dc5279a4a681d7db21bd89d0",
"block": 29268020,
"trx_in_block": 23,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T06:14:06",
"op": [
"vote",
{
"voter": "merlin7",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 12
}
]
}mbappeupvoted (10.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 06:13:24
mbappeupvoted (10.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 06:13:24
| voter | mbappe |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 1000 (10.00%) |
| Transaction Info | Block #29268006/Trx 6bbcd5dbb610ce93bab80303fb7aac8502aa00ed |
View Raw JSON Data
{
"trx_id": "6bbcd5dbb610ce93bab80303fb7aac8502aa00ed",
"block": 29268006,
"trx_in_block": 31,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T06:13:24",
"op": [
"vote",
{
"voter": "mbappe",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 1000
}
]
}birddroppingsupvoted (10.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 06:13:24
birddroppingsupvoted (10.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 06:13:24
| voter | birddroppings |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 1000 (10.00%) |
| Transaction Info | Block #29268006/Trx 79a67e96ac79e195e2383aad0cda79a4f8a2eabd |
View Raw JSON Data
{
"trx_id": "79a67e96ac79e195e2383aad0cda79a4f8a2eabd",
"block": 29268006,
"trx_in_block": 21,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T06:13:24",
"op": [
"vote",
{
"voter": "birddroppings",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 1000
}
]
}acceleratorupvoted (1.29%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 06:13:24
acceleratorupvoted (1.29%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 06:13:24
| voter | accelerator |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 129 (1.29%) |
| Transaction Info | Block #29268006/Trx 127023d3b2b4d74c484bb5c768f785e989c6db1b |
View Raw JSON Data
{
"trx_id": "127023d3b2b4d74c484bb5c768f785e989c6db1b",
"block": 29268006,
"trx_in_block": 13,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T06:13:24",
"op": [
"vote",
{
"voter": "accelerator",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 129
}
]
}steemtakerupvoted (2.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 06:13:24
steemtakerupvoted (2.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 06:13:24
| voter | steemtaker |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 200 (2.00%) |
| Transaction Info | Block #29268006/Trx 2c5204bbe8afff4ecf8e7242f90fe7b8189b5b8c |
View Raw JSON Data
{
"trx_id": "2c5204bbe8afff4ecf8e7242f90fe7b8189b5b8c",
"block": 29268006,
"trx_in_block": 11,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T06:13:24",
"op": [
"vote",
{
"voter": "steemtaker",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 200
}
]
}nfcupvoted (9.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 06:12:42
nfcupvoted (9.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 06:12:42
| voter | nfc |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 900 (9.00%) |
| Transaction Info | Block #29267992/Trx d95d140c828fa09472cad3af236a6afa7ea4de96 |
View Raw JSON Data
{
"trx_id": "d95d140c828fa09472cad3af236a6afa7ea4de96",
"block": 29267992,
"trx_in_block": 17,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T06:12:42",
"op": [
"vote",
{
"voter": "nfc",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 900
}
]
}whitebotupvoted (1.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 06:07:42
whitebotupvoted (1.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 06:07:42
| voter | whitebot |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 100 (1.00%) |
| Transaction Info | Block #29267892/Trx 50c5f754dd6f844b84a2b19aa58dc024a3d4e9c2 |
View Raw JSON Data
{
"trx_id": "50c5f754dd6f844b84a2b19aa58dc024a3d4e9c2",
"block": 29267892,
"trx_in_block": 13,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T06:07:42",
"op": [
"vote",
{
"voter": "whitebot",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 100
}
]
}raise-me-upupvoted (0.01%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 06:04:24
raise-me-upupvoted (0.01%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 06:04:24
| voter | raise-me-up |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 1 (0.01%) |
| Transaction Info | Block #29267826/Trx 7cd140174037db228c590439c83526adaff4ddb5 |
View Raw JSON Data
{
"trx_id": "7cd140174037db228c590439c83526adaff4ddb5",
"block": 29267826,
"trx_in_block": 13,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T06:04:24",
"op": [
"vote",
{
"voter": "raise-me-up",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 1
}
]
}bluesniperupvoted (0.50%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 06:03:54
bluesniperupvoted (0.50%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 06:03:54
| voter | bluesniper |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 50 (0.50%) |
| Transaction Info | Block #29267816/Trx 1a32eca58bf3939f9b3f15a3ede5cb0bc9c061b2 |
View Raw JSON Data
{
"trx_id": "1a32eca58bf3939f9b3f15a3ede5cb0bc9c061b2",
"block": 29267816,
"trx_in_block": 22,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T06:03:54",
"op": [
"vote",
{
"voter": "bluesniper",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 50
}
]
}hnubupvoted (50.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 06:03:54
hnubupvoted (50.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 06:03:54
| voter | hnub |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 5000 (50.00%) |
| Transaction Info | Block #29267816/Trx 31b2cd20d376e6d16d31eb818f7fdddff4f6f590 |
View Raw JSON Data
{
"trx_id": "31b2cd20d376e6d16d31eb818f7fdddff4f6f590",
"block": 29267816,
"trx_in_block": 20,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T06:03:54",
"op": [
"vote",
{
"voter": "hnub",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 5000
}
]
}ralph-rennoldsonupvoted (0.25%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 06:03:30
ralph-rennoldsonupvoted (0.25%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 06:03:30
| voter | ralph-rennoldson |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 25 (0.25%) |
| Transaction Info | Block #29267808/Trx ec8d93543b5c87cce8ee9fa54e469f5994500727 |
View Raw JSON Data
{
"trx_id": "ec8d93543b5c87cce8ee9fa54e469f5994500727",
"block": 29267808,
"trx_in_block": 9,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T06:03:30",
"op": [
"vote",
{
"voter": "ralph-rennoldson",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 25
}
]
}bitok.xyzupvoted (1.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 06:03:12
bitok.xyzupvoted (1.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 06:03:12
| voter | bitok.xyz |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 100 (1.00%) |
| Transaction Info | Block #29267802/Trx edec1847c2b9ac637b7c9d88b230301082a89ea9 |
View Raw JSON Data
{
"trx_id": "edec1847c2b9ac637b7c9d88b230301082a89ea9",
"block": 29267802,
"trx_in_block": 17,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T06:03:12",
"op": [
"vote",
{
"voter": "bitok.xyz",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 100
}
]
}ezravandiupvoted (1.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 06:02:51
ezravandiupvoted (1.00%) @fuzz-ai / fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 06:02:51
| voter | ezravandi |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| weight | 100 (1.00%) |
| Transaction Info | Block #29267795/Trx 3f9c1258d47568c37f8e42676dae1176bc30bdc6 |
View Raw JSON Data
{
"trx_id": "3f9c1258d47568c37f8e42676dae1176bc30bdc6",
"block": 29267795,
"trx_in_block": 22,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T06:02:51",
"op": [
"vote",
{
"voter": "ezravandi",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"weight": 100
}
]
}fuzz-aipublished a new post: fuzz-testing-ontology-s-neovm-execution-engine2019/01/08 05:59:36
fuzz-aipublished a new post: fuzz-testing-ontology-s-neovm-execution-engine
2019/01/08 05:59:36
| parent author | |
| parent permlink | ontology |
| author | fuzz-ai |
| permlink | fuzz-testing-ontology-s-neovm-execution-engine |
| title | Fuzz-testing Ontology's NeoVM Execution Engine |
| body | * Two smart contract fragments were identified that cause panics in the NeoVM implementation in the Ontology blockchain code. # Introduction <div class="pull-left">  </div> [Ontology](https://ont.io) is a “distributed trust collaboration platform”, a blockchain that supports identity management and smart contracts. Ontology smart contracts can be written in a variety of languages using an online IDE. It currently supports two different virtual machine implementations--- WASM (Web Assembly) and NeoVM, a virtual machine created for the NEO blockchain. NeoVM is a stack-oriented virtual machine with single-byte opcodes. Unfortunately we could locate few details of its design, other than the opcode listing included in the source. The implementation in NEO is in C#; the version included in Ontology is a reimplementation. In the future we might use fuzzing to compare the behavior of the two implementations, but for this article we looked just at the implementation’s robustness. Ontology’s implementation is written in Go, so we can demonstrate a fuzzing tool for Go, `go-fuzz`. (https://github.com/dvyukov/go-fuzz). `go-fuzz` has a long list of bugs in its “trophy case”, and credits American Fuzzy Lop for the design of its fuzzing logic. # Building a test harness for fuzzing Fortunately, Ontology already contains a unit test which does fuzzing. It generates random opcodes and attempts to execute them. See https://github.com/ontio/ontology/blob/1e5cdc4ca0d099444eb7ea68b89534f1f353bfc4/smartcontract/test/panic_test.go#L37 Each unit test run does 90 tests, 10 random strings of 1 to 9 bytes each. It is easy to adapt that to `go-fuzz`’s requirements. Go’s dependency management, and `go-fuzz`’s compiler, makes it much easier to write a test harness even when there are complicated dependencies to get a particular piece of code to compile. ``` // +build gofuzz package test import ( "github.com/ontio/ontology/smartcontract" "github.com/ontio/ontology/core/types" ) func Fuzz( data []byte ) int { config := &smartcontract.Config{ Time: 10, Height: 10, Tx: &types.Transaction{}, } sc := smartcontract.SmartContract{ Config: config, Gas: 100000, CacheDB: nil, } engine, err := sc.NewExecuteEngine( data ); _, err = engine.Invoke() if err != nil { return 1 } else { return 0 } } ``` `go-fuzz` requests that the fuzzing function return 1 for “interesting” test cases, such as examples that parse correctly, and 0 for “uninteresting” cases. If the file above is placed in the “test” subdirectory, then `go-fuzz-build github.com/ontio/ontology/smartcontract/test` builds a binary for fuzzing. # Fuzzing the virtual machine Like AFL, `go-fuzz` needs a corpus of example to bootstrap its search, and other unit tests provided suitable example strings of valid code. However, it does not accept a dictionary so I could not give it hints about the valid tokens and interesting strings such as function names. `go-fuzz` also launches multiple execution threads by default (which is a somewhat more cumbersome process with AFL.) Its output looks like this: ``` 2018/12/14 20:07:10 workers: 2, corpus: 1077 (17m29s ago), crashers: 5, restarts: 1/139, execs: 57731757 (836/sec), cover: 3168, uptime: 19h10m 2018/12/14 20:07:13 workers: 2, corpus: 1077 (17m32s ago), crashers: 5, restarts: 1/139, execs: 57731777 (836/sec), cover: 3168, uptime: 19h11m 2018/12/14 20:07:16 workers: 2, corpus: 1077 (17m35s ago), crashers: 5, restarts: 1/139, execs: 57731778 (836/sec), cover: 3168, uptime: 19h11m ``` The fuzzer found 1077 test cases, which cover about 3168 transitions between basic blocks in the code. Five of its test cases crash. One of these accesses the `CacheDB`, which is `nil`. Earlier versions of the original unit test used a real backing store, but there have been interface changes made recently in this area, so it proved difficult to add a `CacheDB` instance. Using the real backing store was extremely heavyweight and reduced the execution speed to well below 100/second. `go-fuzz` reported this failure only once, but the high restart rate suggests we could have been more efficient by avoiding this code path. Two of the others seem like legitimate failures, and are reproducible in a unit test ## Underflow bug ``` code = []byte( "\x00\x00|v\x83\x83d\xfb\xff" ) 0x00 0x00 0x7c 0x76 0x83 0x83 0x64 0xfb 0xff PUSH0, PUSH0, SWAP, DUP, INVERT, INVERT, JMPIFNOT, invalid?, invalid? ``` This “contract” causes an underflow in the math library: ``` panic: underflow [recovered] panic: underflow goroutine 5 [running]: testing.tRunner.func1(0xc0000aa400) /usr/local/go/src/testing/testing.go:792 +0x387 panic(0x8086c0, 0x90e340) /usr/local/go/src/runtime/panic.go:513 +0x1b9 math/big.nat.sub(0xc000026450, 0x1, 0x5, 0xc000026450, 0x1, 0x5, 0xbd7500, 0x1, 0x1, 0xc00000cde0, ...) /usr/local/go/src/math/big/nat.go:142 +0x334 math/big.(*Int).Not(0xc00000cde0, 0xc00000cde0, 0x0) /usr/local/go/src/math/big/int.go:1120 +0x92 github.com/ontio/ontology/vm/neovm.opInvert(0xc0000c0b60, 0x0, 0x0, 0x851380) .../ontology/vm/neovm/func_bitwise.go:26 +0x65 github.com/ontio/ontology/vm/neovm.(*ExecutionEngine).ExecuteOp(0xc0000c0b60, 0x859500, 0x89ef11, 0x6) .../ontology/vm/neovm/execution_engine.go:119 +0x52 github.com/ontio/ontology/vm/neovm.(*ExecutionEngine).StepInto(0xc0000c0b60, 0x1, 0x1) .../ontology/vm/neovm/execution_engine.go:96 +0x2b github.com/ontio/ontology/smartcontract/service/neovm.(*NeoVmService).Invoke(0xc0000aec80, 0xc000022770, 0x9, 0x10, 0x9103c0) .../ontology/smartcontract/service/neovm/neovm_service.go:243 +0x798 command-line-arguments.TestCrashes(0xc0000aa400) .../ontology/smartcontract/test/panic_test.go:85 +0x184 testing.tRunner(0xc0000aa400, 0x8bb558) /usr/local/go/src/testing/testing.go:827 +0xbf created by testing.(*T).Run /usr/local/go/src/testing/testing.go:878 +0x353 FAIL command-line-arguments 0.008s ``` We must admit that we don’t fully understand the behavior here. `INVERT` of 0 results in a large negative number, and attending to apply `Not` to that again results in underflow. But the three remaining bytes in the contract are necessary to exhibit the bug; the unit test does not panic without them. ## Slice Bound violation ``` code = []byte( "_\x00s" ) 0x5f 0x0 0x73 PUSH15, PUSH0, XTUCK ``` This contract causes an error accessing the VM’s stack: ``` panic: runtime error: slice bounds out of range [recovered] panic: runtime error: slice bounds out of range goroutine 5 [running]: testing.tRunner.func1(0xc0000aa400) /usr/local/go/src/testing/testing.go:792 +0x387 panic(0x8302e0, 0xc06cf0) /usr/local/go/src/runtime/panic.go:513 +0x1b9 github.com/ontio/ontology/vm/neovm.(*RandomAccessStack).Insert(...) .../ontology/vm/neovm/stack.go:51 github.com/ontio/ontology/vm/neovm.opXTuck(0xc0000c0b60, 0x0, 0x0, 0x851380) .../ontology/vm/neovm/func_stack.go:62 +0x2d8 github.com/ontio/ontology/vm/neovm.(*ExecutionEngine).ExecuteOp(0xc0000c0b60, 0x859500, 0x89ec5a, 0x5) .../ontology/vm/neovm/execution_engine.go:119 +0x52 github.com/ontio/ontology/vm/neovm.(*ExecutionEngine).StepInto(0xc0000c0b60, 0x1, 0x1) .../ontology/vm/neovm/execution_engine.go:96 +0x2b github.com/ontio/ontology/smartcontract/service/neovm.(*NeoVmService).Invoke(0xc0000aebe0, 0xc000022748, 0x3, 0x8, 0x9103a0) .../ontology/smartcontract/service/neovm/neovm_service.go:243 +0x798 command-line-arguments.TestCrashes(0xc0000aa400) .../ontology/smartcontract/test/panic_test.go:85 +0x184 testing.tRunner(0xc0000aa400, 0x8bb550) /usr/local/go/src/testing/testing.go:827 +0xbf created by testing.(*T).Run /usr/local/go/src/testing/testing.go:878 +0x353 FAIL command-line-arguments 0.007s ``` This failure seems like a more straightforward lack of bounds-checking. The `XTUCK` opcode calls insert on a 1-element stack (stored in `r.e`), with argument index 1: ``` 45: l := len(r.e) 46: if index > l { 47: return 48: } 49: index = l - index 50: r.e = append(r.e, r.e[l-1]) 51: copy(r.e[index+1:l], r.e[index:]) 52: r.e[index] = t ``` (Original code: https://github.com/ontio/ontology/blob/8f56616ab7c5cdd2b43701835448aaedb8557366/vm/neovm/stack.go#L41) After line 50, the stack is of size two; however, the first access in line 51 is to `r.e[2:1]`, which provokes an out-of-bound error because the start index is larger than the end index. It may be that the bounds check on line 46 should be `>=`. # Analysis These bugs have the potential to be serious, if the panic condition is not caught by the code that calls `Invoke()`. Spot-checking of several locations in the Ontology implementation where this occurs suggested it was not done consistently, but I am unfamiliar with the overall structure of the code. Both may well be harmless. We were not able to understand the intended use of the `XTUCK` operation, or the reason why the double-`INVERT` caused a problem in some cases but not others. Fortunately our limited understanding does not stand in the way of finding crashes, when using an automated testing tool. An individual run of the randomized unit test explores about 90 cases. Finding these two bugs took over 50,000,000 executions, though one was identified practically right away. Worse, the unit test exercises 1-token strings quite aggressively, but there are only 256 of them and none of them generate a failure by themselves. On the other hand, exhaustive search of the space of 9-byte programs would require 256^9 executions, an unimaginably large number. The fuzzer is able to focus its search on regions of this space which look promising. Unit test code which performs random testing can, and should be, converted to use fuzzing instead to efficiently get greater coverage and ensure that the cost of writing the test is not wasted through ineffective use.  (Photo by [Paweł Czerwiński](https://unsplash.com/photos/mlOJWyNsYyA?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on Unsplash) Ontology does not provide a security contact email, but it does participate in a bounty program run by Slowmist. (Unfortunately, their submission form will not accept submissions without an ETH address for awards.) We submitted a bug bounty claim on December 15th but received no update after the promised 10 working days. A followup email to [email protected] on January 1st went unanswered as of January 7th. # Fuzz.ai [Fuzz.ai](http://www.fuzz.ai/) is an early-stage startup dedicated to making software correctness tools easier to use. Fuzzers, model checkers, and property-based testing can make software more robust, expose security vulnerabilities, and speed development. |
| json metadata | {"tags":["ontology","blockchain","software","programming","fuzzing"],"image":["https://cdn.steemitimages.com/DQmWxqxZjvaTCJC9tqzCqyxCFfHqVneEQJBifKkQ1sbMQmY/image.png","https://cdn.steemitimages.com/DQmbdRb2xMpEDzNJJioTZ9kD5Pp8x8aVifQgqW29yNfBFpW/pawel-czerwinski-758007-unsplash.jpg"],"links":["https://ont.io","https://github.com/dvyukov/go-fuzz","https://github.com/ontio/ontology/blob/1e5cdc4ca0d099444eb7ea68b89534f1f353bfc4/smartcontract/test/panic_test.go#L37","https://github.com/ontio/ontology/blob/8f56616ab7c5cdd2b43701835448aaedb8557366/vm/neovm/stack.go#L41","https://unsplash.com/photos/mlOJWyNsYyA?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText","http://www.fuzz.ai/"],"app":"steemit/0.1","format":"markdown"} |
| Transaction Info | Block #29267730/Trx dd79392f0c10d59695a023ac680a57d2f0f8925b |
View Raw JSON Data
{
"trx_id": "dd79392f0c10d59695a023ac680a57d2f0f8925b",
"block": 29267730,
"trx_in_block": 26,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T05:59:36",
"op": [
"comment",
{
"parent_author": "",
"parent_permlink": "ontology",
"author": "fuzz-ai",
"permlink": "fuzz-testing-ontology-s-neovm-execution-engine",
"title": "Fuzz-testing Ontology's NeoVM Execution Engine",
"body": "* Two smart contract fragments were identified that cause panics in the NeoVM implementation in the Ontology blockchain code.\n\n# Introduction\n\n<div class=\"pull-left\">\n\n\n</div>\n\n[Ontology](https://ont.io) is a “distributed trust collaboration platform”, a blockchain that supports identity management and smart contracts. Ontology smart contracts can be written in a variety of languages using an online IDE. It currently supports two different virtual machine implementations--- WASM (Web Assembly) and NeoVM, a virtual machine created for the NEO blockchain.\n\nNeoVM is a stack-oriented virtual machine with single-byte opcodes. Unfortunately we could locate few details of its design, other than the opcode listing included in the source. The implementation in NEO is in C#; the version included in Ontology is a reimplementation. In the future we might use fuzzing to compare the behavior of the two implementations, but for this article we looked just at the implementation’s robustness.\n\nOntology’s implementation is written in Go, so we can demonstrate a fuzzing tool for Go, `go-fuzz`. (https://github.com/dvyukov/go-fuzz). `go-fuzz` has a long list of bugs in its “trophy case”, and credits American Fuzzy Lop for the design of its fuzzing logic.\n\n# Building a test harness for fuzzing\n\nFortunately, Ontology already contains a unit test which does fuzzing. It generates random opcodes and attempts to execute them. \n See https://github.com/ontio/ontology/blob/1e5cdc4ca0d099444eb7ea68b89534f1f353bfc4/smartcontract/test/panic_test.go#L37\n\nEach unit test run does 90 tests, 10 random strings of 1 to 9 bytes each. It is easy to adapt that to `go-fuzz`’s requirements.\n\nGo’s dependency management, and `go-fuzz`’s compiler, makes it much easier to write a test harness even when there are complicated dependencies to get a particular piece of code to compile. \n\n```\n// +build gofuzz\n\npackage test\n\nimport (\n\t\"github.com/ontio/ontology/smartcontract\"\n\t\"github.com/ontio/ontology/core/types\"\n)\n\nfunc Fuzz( data []byte ) int {\n\tconfig := &smartcontract.Config{\n\t\tTime: 10,\n\t\tHeight: 10,\n\t\tTx: &types.Transaction{},\n\n\t}\n\t\n\tsc := smartcontract.SmartContract{\n\t\tConfig: config,\n\t\tGas: 100000,\n\t\tCacheDB: nil,\n\t}\n\tengine, err := sc.NewExecuteEngine( data );\n\t_, err = engine.Invoke()\n\n\tif err != nil {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\t\n}\n```\n\n`go-fuzz` requests that the fuzzing function return 1 for “interesting” test cases, such as examples that parse correctly, and 0 for “uninteresting” cases. If the file above is placed in the “test” subdirectory, then\n\n`go-fuzz-build github.com/ontio/ontology/smartcontract/test`\n\nbuilds a binary for fuzzing.\n\n# Fuzzing the virtual machine\n\nLike AFL, `go-fuzz` needs a corpus of example to bootstrap its search, and other unit tests provided suitable example strings of valid code. However, it does not accept a dictionary so I could not give it hints about the valid tokens and interesting strings such as function names.\n\n`go-fuzz` also launches multiple execution threads by default (which is a somewhat more cumbersome process with AFL.) Its output looks like this:\n\n```\n2018/12/14 20:07:10 workers: 2, corpus: 1077 (17m29s ago), crashers: 5, restarts: 1/139, execs: 57731757 (836/sec), cover: 3168, uptime: 19h10m\n2018/12/14 20:07:13 workers: 2, corpus: 1077 (17m32s ago), crashers: 5, restarts: 1/139, execs: 57731777 (836/sec), cover: 3168, uptime: 19h11m\n2018/12/14 20:07:16 workers: 2, corpus: 1077 (17m35s ago), crashers: 5, restarts: 1/139, execs: 57731778 (836/sec), cover: 3168, uptime: 19h11m\n```\n\nThe fuzzer found 1077 test cases, which cover about 3168 transitions between basic blocks in the code. Five of its test cases crash.\n\nOne of these accesses the `CacheDB`, which is `nil`. Earlier versions of the original unit test used a real backing store, but there have been interface changes made recently in this area, so it proved difficult to add a `CacheDB` instance. Using the real backing store was extremely heavyweight and reduced the execution speed to well below 100/second. `go-fuzz` reported this failure only once, but the high restart rate suggests we could have been more efficient by avoiding this code path.\n\nTwo of the others seem like legitimate failures, and are reproducible in a unit test\n\n## Underflow bug \n\n```\n\tcode = []byte( \"\\x00\\x00|v\\x83\\x83d\\xfb\\xff\" )\n 0x00 0x00 0x7c 0x76 0x83 0x83 0x64 0xfb 0xff\n PUSH0, PUSH0, SWAP, DUP, INVERT, INVERT, JMPIFNOT, invalid?, invalid?\n```\n\nThis “contract” causes an underflow in the math library:\n\n```\npanic: underflow [recovered]\n\tpanic: underflow\n\ngoroutine 5 [running]:\ntesting.tRunner.func1(0xc0000aa400)\n\t/usr/local/go/src/testing/testing.go:792 +0x387\npanic(0x8086c0, 0x90e340)\n\t/usr/local/go/src/runtime/panic.go:513 +0x1b9\nmath/big.nat.sub(0xc000026450, 0x1, 0x5, 0xc000026450, 0x1, 0x5, 0xbd7500, 0x1, 0x1, 0xc00000cde0, ...)\n\t/usr/local/go/src/math/big/nat.go:142 +0x334\nmath/big.(*Int).Not(0xc00000cde0, 0xc00000cde0, 0x0)\n\t/usr/local/go/src/math/big/int.go:1120 +0x92\ngithub.com/ontio/ontology/vm/neovm.opInvert(0xc0000c0b60, 0x0, 0x0, 0x851380)\n\t.../ontology/vm/neovm/func_bitwise.go:26 +0x65\ngithub.com/ontio/ontology/vm/neovm.(*ExecutionEngine).ExecuteOp(0xc0000c0b60, 0x859500, 0x89ef11, 0x6)\n\t.../ontology/vm/neovm/execution_engine.go:119 +0x52\ngithub.com/ontio/ontology/vm/neovm.(*ExecutionEngine).StepInto(0xc0000c0b60, 0x1, 0x1)\n\t.../ontology/vm/neovm/execution_engine.go:96 +0x2b\ngithub.com/ontio/ontology/smartcontract/service/neovm.(*NeoVmService).Invoke(0xc0000aec80, 0xc000022770, 0x9, 0x10, 0x9103c0)\n\t.../ontology/smartcontract/service/neovm/neovm_service.go:243 +0x798\ncommand-line-arguments.TestCrashes(0xc0000aa400)\n\t.../ontology/smartcontract/test/panic_test.go:85 +0x184\ntesting.tRunner(0xc0000aa400, 0x8bb558)\n\t/usr/local/go/src/testing/testing.go:827 +0xbf\ncreated by testing.(*T).Run\n\t/usr/local/go/src/testing/testing.go:878 +0x353\nFAIL\tcommand-line-arguments\t0.008s\n```\n\nWe must admit that we don’t fully understand the behavior here. `INVERT` of 0 results in a large negative number, and attending to apply `Not` to that again results in underflow. But the three remaining bytes in the contract are necessary to exhibit the bug; the unit test does not panic without them.\n\n## Slice Bound violation\n\n```\n\tcode = []byte( \"_\\x00s\" )\n 0x5f 0x0 0x73\n\tPUSH15, PUSH0, XTUCK\n```\n\nThis contract causes an error accessing the VM’s stack: \n\n```\npanic: runtime error: slice bounds out of range [recovered]\n\tpanic: runtime error: slice bounds out of range\n\ngoroutine 5 [running]:\ntesting.tRunner.func1(0xc0000aa400)\n\t/usr/local/go/src/testing/testing.go:792 +0x387\npanic(0x8302e0, 0xc06cf0)\n\t/usr/local/go/src/runtime/panic.go:513 +0x1b9\ngithub.com/ontio/ontology/vm/neovm.(*RandomAccessStack).Insert(...)\n\t.../ontology/vm/neovm/stack.go:51\ngithub.com/ontio/ontology/vm/neovm.opXTuck(0xc0000c0b60, 0x0, 0x0, 0x851380)\n\t.../ontology/vm/neovm/func_stack.go:62 +0x2d8\ngithub.com/ontio/ontology/vm/neovm.(*ExecutionEngine).ExecuteOp(0xc0000c0b60, 0x859500, 0x89ec5a, 0x5)\n\t.../ontology/vm/neovm/execution_engine.go:119 +0x52\ngithub.com/ontio/ontology/vm/neovm.(*ExecutionEngine).StepInto(0xc0000c0b60, 0x1, 0x1)\n\t.../ontology/vm/neovm/execution_engine.go:96 +0x2b\ngithub.com/ontio/ontology/smartcontract/service/neovm.(*NeoVmService).Invoke(0xc0000aebe0, 0xc000022748, 0x3, 0x8, 0x9103a0)\n\t.../ontology/smartcontract/service/neovm/neovm_service.go:243 +0x798\ncommand-line-arguments.TestCrashes(0xc0000aa400)\n\t.../ontology/smartcontract/test/panic_test.go:85 +0x184\ntesting.tRunner(0xc0000aa400, 0x8bb550)\n\t/usr/local/go/src/testing/testing.go:827 +0xbf\ncreated by testing.(*T).Run\n\t/usr/local/go/src/testing/testing.go:878 +0x353\nFAIL\tcommand-line-arguments\t0.007s\n```\n\nThis failure seems like a more straightforward lack of bounds-checking. The `XTUCK` opcode calls insert on a 1-element stack (stored in `r.e`), with argument index 1:\n\n```\n 45:\t\tl := len(r.e)\n 46:\t\tif index > l {\n 47:\t\t\treturn\n 48:\t\t}\n 49:\t\tindex = l - index\n 50:\t\tr.e = append(r.e, r.e[l-1])\n 51:\t\tcopy(r.e[index+1:l], r.e[index:])\n 52:\t\tr.e[index] = t\n```\n(Original code: https://github.com/ontio/ontology/blob/8f56616ab7c5cdd2b43701835448aaedb8557366/vm/neovm/stack.go#L41)\n\nAfter line 50, the stack is of size two; however, the first access in line 51 is to `r.e[2:1]`, which provokes an out-of-bound error because the start index is larger than the end index.\n\nIt may be that the bounds check on line 46 should be `>=`.\n\n# Analysis\n\nThese bugs have the potential to be serious, if the panic condition is not caught by the code that calls `Invoke()`. Spot-checking of several locations in the Ontology implementation where this occurs suggested it was not done consistently, but I am unfamiliar with the overall structure of the code. Both may well be harmless.\n\nWe were not able to understand the intended use of the `XTUCK` operation, or the reason why the double-`INVERT` caused a problem in some cases but not others. Fortunately our limited understanding does not stand in the way of finding crashes, when using an automated testing tool.\n\nAn individual run of the randomized unit test explores about 90 cases. Finding these two bugs took over 50,000,000 executions, though one was identified practically right away. Worse, the unit test exercises 1-token strings quite aggressively, but there are only 256 of them and none of them generate a failure by themselves.\n\nOn the other hand, exhaustive search of the space of 9-byte programs would require 256^9 executions, an unimaginably large number. The fuzzer is able to focus its search on regions of this space which look promising. Unit test code which performs random testing can, and should be, converted to use fuzzing instead to efficiently get greater coverage and ensure that the cost of writing the test is not wasted through ineffective use.\n\n\n\n(Photo by [Paweł Czerwiński](https://unsplash.com/photos/mlOJWyNsYyA?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on Unsplash)\n\nOntology does not provide a security contact email, but it does participate in a bounty program run by Slowmist. (Unfortunately, their submission form will not accept submissions without an ETH address for awards.) We submitted a bug bounty claim on December 15th but received no update after the promised 10 working days. A followup email to [email protected] on January 1st went unanswered as of January 7th.\n\n# Fuzz.ai\n\n[Fuzz.ai](http://www.fuzz.ai/) is an early-stage startup dedicated to making software correctness tools easier to use. Fuzzers, model checkers, and property-based testing can make software more robust, expose security vulnerabilities, and speed development.",
"json_metadata": "{\"tags\":[\"ontology\",\"blockchain\",\"software\",\"programming\",\"fuzzing\"],\"image\":[\"https://cdn.steemitimages.com/DQmWxqxZjvaTCJC9tqzCqyxCFfHqVneEQJBifKkQ1sbMQmY/image.png\",\"https://cdn.steemitimages.com/DQmbdRb2xMpEDzNJJioTZ9kD5Pp8x8aVifQgqW29yNfBFpW/pawel-czerwinski-758007-unsplash.jpg\"],\"links\":[\"https://ont.io\",\"https://github.com/dvyukov/go-fuzz\",\"https://github.com/ontio/ontology/blob/1e5cdc4ca0d099444eb7ea68b89534f1f353bfc4/smartcontract/test/panic_test.go#L37\",\"https://github.com/ontio/ontology/blob/8f56616ab7c5cdd2b43701835448aaedb8557366/vm/neovm/stack.go#L41\",\"https://unsplash.com/photos/mlOJWyNsYyA?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\",\"http://www.fuzz.ai/\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
}
]
}fuzz-aiupvoted (100.00%) @therealwolf / 100-beneficiary-community-project-experiment2019/01/08 05:46:24
fuzz-aiupvoted (100.00%) @therealwolf / 100-beneficiary-community-project-experiment
2019/01/08 05:46:24
| voter | fuzz-ai |
| author | therealwolf |
| permlink | 100-beneficiary-community-project-experiment |
| weight | 10000 (100.00%) |
| Transaction Info | Block #29267467/Trx 823612a25dc7ad524e3082a1778b136c1bc599b1 |
View Raw JSON Data
{
"trx_id": "823612a25dc7ad524e3082a1778b136c1bc599b1",
"block": 29267467,
"trx_in_block": 5,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T05:46:24",
"op": [
"vote",
{
"voter": "fuzz-ai",
"author": "therealwolf",
"permlink": "100-beneficiary-community-project-experiment",
"weight": 10000
}
]
}fuzz-aiupvoted (100.00%) @mattockfs / tutorial-asynchonous-python-with-twisted-part-three2019/01/08 05:46:15
fuzz-aiupvoted (100.00%) @mattockfs / tutorial-asynchonous-python-with-twisted-part-three
2019/01/08 05:46:15
| voter | fuzz-ai |
| author | mattockfs |
| permlink | tutorial-asynchonous-python-with-twisted-part-three |
| weight | 10000 (100.00%) |
| Transaction Info | Block #29267464/Trx a9496576d8a09f5acb64a557d0c14a702c3af118 |
View Raw JSON Data
{
"trx_id": "a9496576d8a09f5acb64a557d0c14a702c3af118",
"block": 29267464,
"trx_in_block": 14,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-08T05:46:15",
"op": [
"vote",
{
"voter": "fuzz-ai",
"author": "mattockfs",
"permlink": "tutorial-asynchonous-python-with-twisted-part-three",
"weight": 10000
}
]
}fuzz-aiupvoted (100.00%) @holger80 / beempy-com-shows-results-of-all-played-steemmonster-challenges2019/01/03 06:39:33
fuzz-aiupvoted (100.00%) @holger80 / beempy-com-shows-results-of-all-played-steemmonster-challenges
2019/01/03 06:39:33
| voter | fuzz-ai |
| author | holger80 |
| permlink | beempy-com-shows-results-of-all-played-steemmonster-challenges |
| weight | 10000 (100.00%) |
| Transaction Info | Block #29124700/Trx e3807dd4e889adfb97f750014d5a83b0b724a7a9 |
View Raw JSON Data
{
"trx_id": "e3807dd4e889adfb97f750014d5a83b0b724a7a9",
"block": 29124700,
"trx_in_block": 15,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-03T06:39:33",
"op": [
"vote",
{
"voter": "fuzz-ai",
"author": "holger80",
"permlink": "beempy-com-shows-results-of-all-played-steemmonster-challenges",
"weight": 10000
}
]
}fuzz-aiupvoted (100.00%) @codingdefined / 2018-year-in-review-as-an-open-source-developer2019/01/03 06:39:24
fuzz-aiupvoted (100.00%) @codingdefined / 2018-year-in-review-as-an-open-source-developer
2019/01/03 06:39:24
| voter | fuzz-ai |
| author | codingdefined |
| permlink | 2018-year-in-review-as-an-open-source-developer |
| weight | 10000 (100.00%) |
| Transaction Info | Block #29124697/Trx 1ab69d232eb674f4f68cb77d9c5ee669cad1b558 |
View Raw JSON Data
{
"trx_id": "1ab69d232eb674f4f68cb77d9c5ee669cad1b558",
"block": 29124697,
"trx_in_block": 27,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-03T06:39:24",
"op": [
"vote",
{
"voter": "fuzz-ai",
"author": "codingdefined",
"permlink": "2018-year-in-review-as-an-open-source-developer",
"weight": 10000
}
]
}fuzz-aiupvoted (100.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing2019/01/02 22:50:15
fuzz-aiupvoted (100.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing
2019/01/02 22:50:15
| voter | fuzz-ai |
| author | fuzz-ai |
| permlink | improving-ripple-unit-test-coverage-with-fuzzing |
| weight | 10000 (100.00%) |
| Transaction Info | Block #29115326/Trx 3fcac1645ba02f33be8fb47e71c96e6b8f779673 |
View Raw JSON Data
{
"trx_id": "3fcac1645ba02f33be8fb47e71c96e6b8f779673",
"block": 29115326,
"trx_in_block": 26,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-02T22:50:15",
"op": [
"vote",
{
"voter": "fuzz-ai",
"author": "fuzz-ai",
"permlink": "improving-ripple-unit-test-coverage-with-fuzzing",
"weight": 10000
}
]
}mikitsupvoted (100.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing2019/01/02 22:40:39
mikitsupvoted (100.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing
2019/01/02 22:40:39
| voter | mikits |
| author | fuzz-ai |
| permlink | improving-ripple-unit-test-coverage-with-fuzzing |
| weight | 10000 (100.00%) |
| Transaction Info | Block #29115134/Trx 9af6b29ea31e3c6a55146c8058117699df9148e9 |
View Raw JSON Data
{
"trx_id": "9af6b29ea31e3c6a55146c8058117699df9148e9",
"block": 29115134,
"trx_in_block": 38,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-02T22:40:39",
"op": [
"vote",
{
"voter": "mikits",
"author": "fuzz-ai",
"permlink": "improving-ripple-unit-test-coverage-with-fuzzing",
"weight": 10000
}
]
}matildapurseupvoted (25.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing2019/01/02 22:36:24
matildapurseupvoted (25.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing
2019/01/02 22:36:24
| voter | matildapurse |
| author | fuzz-ai |
| permlink | improving-ripple-unit-test-coverage-with-fuzzing |
| weight | 2500 (25.00%) |
| Transaction Info | Block #29115049/Trx e100044d75e04afc68f86879ec0bd57c506541f3 |
View Raw JSON Data
{
"trx_id": "e100044d75e04afc68f86879ec0bd57c506541f3",
"block": 29115049,
"trx_in_block": 14,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-02T22:36:24",
"op": [
"vote",
{
"voter": "matildapurse",
"author": "fuzz-ai",
"permlink": "improving-ripple-unit-test-coverage-with-fuzzing",
"weight": 2500
}
]
}portugalcoinupvoted (15.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing2019/01/02 22:24:39
portugalcoinupvoted (15.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing
2019/01/02 22:24:39
| voter | portugalcoin |
| author | fuzz-ai |
| permlink | improving-ripple-unit-test-coverage-with-fuzzing |
| weight | 1500 (15.00%) |
| Transaction Info | Block #29114814/Trx 7c01dead3aadffc68ce21141832e4ca00047ee49 |
View Raw JSON Data
{
"trx_id": "7c01dead3aadffc68ce21141832e4ca00047ee49",
"block": 29114814,
"trx_in_block": 4,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-02T22:24:39",
"op": [
"vote",
{
"voter": "portugalcoin",
"author": "fuzz-ai",
"permlink": "improving-ripple-unit-test-coverage-with-fuzzing",
"weight": 1500
}
]
}merlin7upvoted (0.30%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing2019/01/02 22:22:48
merlin7upvoted (0.30%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing
2019/01/02 22:22:48
| voter | merlin7 |
| author | fuzz-ai |
| permlink | improving-ripple-unit-test-coverage-with-fuzzing |
| weight | 30 (0.30%) |
| Transaction Info | Block #29114777/Trx 08f3761c0bd99838858168f40a7361d434273c32 |
View Raw JSON Data
{
"trx_id": "08f3761c0bd99838858168f40a7361d434273c32",
"block": 29114777,
"trx_in_block": 35,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-02T22:22:48",
"op": [
"vote",
{
"voter": "merlin7",
"author": "fuzz-ai",
"permlink": "improving-ripple-unit-test-coverage-with-fuzzing",
"weight": 30
}
]
}dreamarifupvoted (6.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing2019/01/02 22:22:48
dreamarifupvoted (6.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing
2019/01/02 22:22:48
| voter | dreamarif |
| author | fuzz-ai |
| permlink | improving-ripple-unit-test-coverage-with-fuzzing |
| weight | 600 (6.00%) |
| Transaction Info | Block #29114777/Trx 5691143d6c5893720bb1330b5f83821cb8672da8 |
View Raw JSON Data
{
"trx_id": "5691143d6c5893720bb1330b5f83821cb8672da8",
"block": 29114777,
"trx_in_block": 30,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-02T22:22:48",
"op": [
"vote",
{
"voter": "dreamarif",
"author": "fuzz-ai",
"permlink": "improving-ripple-unit-test-coverage-with-fuzzing",
"weight": 600
}
]
}ascorphatupvoted (2.50%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing2019/01/02 22:21:48
ascorphatupvoted (2.50%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing
2019/01/02 22:21:48
| voter | ascorphat |
| author | fuzz-ai |
| permlink | improving-ripple-unit-test-coverage-with-fuzzing |
| weight | 250 (2.50%) |
| Transaction Info | Block #29114757/Trx e632085a808eb1e9c3cb2a1c93dbf039cdc70f84 |
View Raw JSON Data
{
"trx_id": "e632085a808eb1e9c3cb2a1c93dbf039cdc70f84",
"block": 29114757,
"trx_in_block": 43,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-02T22:21:48",
"op": [
"vote",
{
"voter": "ascorphat",
"author": "fuzz-ai",
"permlink": "improving-ripple-unit-test-coverage-with-fuzzing",
"weight": 250
}
]
}photocirclebotupvoted (6.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing2019/01/02 22:21:42
photocirclebotupvoted (6.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing
2019/01/02 22:21:42
| voter | photocirclebot |
| author | fuzz-ai |
| permlink | improving-ripple-unit-test-coverage-with-fuzzing |
| weight | 600 (6.00%) |
| Transaction Info | Block #29114755/Trx 6e356d93de18253a93e80eb1e1707e4a901292e5 |
View Raw JSON Data
{
"trx_id": "6e356d93de18253a93e80eb1e1707e4a901292e5",
"block": 29114755,
"trx_in_block": 23,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-02T22:21:42",
"op": [
"vote",
{
"voter": "photocirclebot",
"author": "fuzz-ai",
"permlink": "improving-ripple-unit-test-coverage-with-fuzzing",
"weight": 600
}
]
}steemtakerupvoted (6.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing2019/01/02 22:21:42
steemtakerupvoted (6.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing
2019/01/02 22:21:42
| voter | steemtaker |
| author | fuzz-ai |
| permlink | improving-ripple-unit-test-coverage-with-fuzzing |
| weight | 600 (6.00%) |
| Transaction Info | Block #29114755/Trx 078c2a2b9c7f6075fbb2bb132c3ffaf0785f9ccc |
View Raw JSON Data
{
"trx_id": "078c2a2b9c7f6075fbb2bb132c3ffaf0785f9ccc",
"block": 29114755,
"trx_in_block": 10,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-02T22:21:42",
"op": [
"vote",
{
"voter": "steemtaker",
"author": "fuzz-ai",
"permlink": "improving-ripple-unit-test-coverage-with-fuzzing",
"weight": 600
}
]
}espoemupvoted (1.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing2019/01/02 22:21:42
espoemupvoted (1.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing
2019/01/02 22:21:42
| voter | espoem |
| author | fuzz-ai |
| permlink | improving-ripple-unit-test-coverage-with-fuzzing |
| weight | 100 (1.00%) |
| Transaction Info | Block #29114755/Trx da4c4a81a46728251169005e67c955bbc2f79a9d |
View Raw JSON Data
{
"trx_id": "da4c4a81a46728251169005e67c955bbc2f79a9d",
"block": 29114755,
"trx_in_block": 3,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-02T22:21:42",
"op": [
"vote",
{
"voter": "espoem",
"author": "fuzz-ai",
"permlink": "improving-ripple-unit-test-coverage-with-fuzzing",
"weight": 100
}
]
}whitebotupvoted (6.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing2019/01/02 22:20:57
whitebotupvoted (6.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing
2019/01/02 22:20:57
| voter | whitebot |
| author | fuzz-ai |
| permlink | improving-ripple-unit-test-coverage-with-fuzzing |
| weight | 600 (6.00%) |
| Transaction Info | Block #29114740/Trx 5f59ba6f5e38e2c0714d3b791a91c4cd9b0e6e89 |
View Raw JSON Data
{
"trx_id": "5f59ba6f5e38e2c0714d3b791a91c4cd9b0e6e89",
"block": 29114740,
"trx_in_block": 18,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-02T22:20:57",
"op": [
"vote",
{
"voter": "whitebot",
"author": "fuzz-ai",
"permlink": "improving-ripple-unit-test-coverage-with-fuzzing",
"weight": 600
}
]
}2019/01/02 22:15:21
2019/01/02 22:15:21
| from | allaz |
| to | fuzz-ai |
| amount | 0.001 STEEM |
| memo | Promote your post. Your post will be min. 10 resteemed with over 13000 followers and min. 25 Upvote Different account (5000 STEEM POWER). Your post will be more popular and you will find new friends. Send 0.5 SBD or STEEM to @allaz (post URL as memo ) Service Active. |
| Transaction Info | Block #29114628/Trx 3ac75c6387d00b497522f9601369ffc43af4e00e |
View Raw JSON Data
{
"trx_id": "3ac75c6387d00b497522f9601369ffc43af4e00e",
"block": 29114628,
"trx_in_block": 20,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-02T22:15:21",
"op": [
"transfer",
{
"from": "allaz",
"to": "fuzz-ai",
"amount": "0.001 STEEM",
"memo": "Promote your post. Your post will be min. 10 resteemed with over 13000 followers and min. 25 Upvote Different account (5000 STEEM POWER). Your post will be more popular and you will find new friends. Send 0.5 SBD or STEEM to @allaz (post URL as memo ) Service Active."
}
]
}supuupvoted (2.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing2019/01/02 22:11:30
supuupvoted (2.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing
2019/01/02 22:11:30
| voter | supu |
| author | fuzz-ai |
| permlink | improving-ripple-unit-test-coverage-with-fuzzing |
| weight | 200 (2.00%) |
| Transaction Info | Block #29114552/Trx 0aeb14ddde9fc0722f910d356e7dd1d827fe9efb |
View Raw JSON Data
{
"trx_id": "0aeb14ddde9fc0722f910d356e7dd1d827fe9efb",
"block": 29114552,
"trx_in_block": 13,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-02T22:11:30",
"op": [
"vote",
{
"voter": "supu",
"author": "fuzz-ai",
"permlink": "improving-ripple-unit-test-coverage-with-fuzzing",
"weight": 200
}
]
}eforucomupvoted (1.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing2019/01/02 22:11:30
eforucomupvoted (1.00%) @fuzz-ai / improving-ripple-unit-test-coverage-with-fuzzing
2019/01/02 22:11:30
| voter | eforucom |
| author | fuzz-ai |
| permlink | improving-ripple-unit-test-coverage-with-fuzzing |
| weight | 100 (1.00%) |
| Transaction Info | Block #29114552/Trx 5496ade396deceedb063513ae5eddb21db8b1b5f |
View Raw JSON Data
{
"trx_id": "5496ade396deceedb063513ae5eddb21db8b1b5f",
"block": 29114552,
"trx_in_block": 2,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2019-01-02T22:11:30",
"op": [
"vote",
{
"voter": "eforucom",
"author": "fuzz-ai",
"permlink": "improving-ripple-unit-test-coverage-with-fuzzing",
"weight": 100
}
]
}Manabar
Voting Power100.00%
Downvote Power100.00%
Resource Credits100.00%
Reputation Progress15.94%
{
"voting_manabar": {
"current_mana": "170090243459",
"last_update_time": 1550529345
},
"downvote_manabar": {
"current_mana": 0,
"last_update_time": 1543794858
},
"rc_account": {
"account": "fuzz-ai",
"rc_manabar": {
"current_mana": "182035256823",
"last_update_time": 1551133368
},
"max_rc_creation_adjustment": {
"amount": "6039823766",
"precision": 6,
"nai": "@@000000037"
},
"max_rc": "182035256823"
}
}Account Metadata
| POSTING JSON METADATA | |
| profile | {"profile_image":"https://cdn.steemitimages.com/DQmaFMMXPaiBTdBSLYtRs4dQLVWZEKdC57yFZqY6hj5ztvJ/logo-v1-notext.png","cover_image":"https://cdn.steemitimages.com/DQmXzPM8p2iFa4rHpbxgYNXfjqCQrRE1biEQ5nGwGqP1w3J/giraffe-banner-3.jpg","website":"http://www.fuzz.ai/","about":"An early-stage startup building software correctness tools."} |
| JSON METADATA | |
| profile | {"profile_image":"https://cdn.steemitimages.com/DQmaFMMXPaiBTdBSLYtRs4dQLVWZEKdC57yFZqY6hj5ztvJ/logo-v1-notext.png","cover_image":"https://cdn.steemitimages.com/DQmXzPM8p2iFa4rHpbxgYNXfjqCQrRE1biEQ5nGwGqP1w3J/giraffe-banner-3.jpg","website":"http://www.fuzz.ai/","about":"An early-stage startup building software correctness tools."} |
{
"posting_json_metadata": {
"profile": {
"profile_image": "https://cdn.steemitimages.com/DQmaFMMXPaiBTdBSLYtRs4dQLVWZEKdC57yFZqY6hj5ztvJ/logo-v1-notext.png",
"cover_image": "https://cdn.steemitimages.com/DQmXzPM8p2iFa4rHpbxgYNXfjqCQrRE1biEQ5nGwGqP1w3J/giraffe-banner-3.jpg",
"website": "http://www.fuzz.ai/",
"about": "An early-stage startup building software correctness tools."
}
},
"json_metadata": {
"profile": {
"profile_image": "https://cdn.steemitimages.com/DQmaFMMXPaiBTdBSLYtRs4dQLVWZEKdC57yFZqY6hj5ztvJ/logo-v1-notext.png",
"cover_image": "https://cdn.steemitimages.com/DQmXzPM8p2iFa4rHpbxgYNXfjqCQrRE1biEQ5nGwGqP1w3J/giraffe-banner-3.jpg",
"website": "http://www.fuzz.ai/",
"about": "An early-stage startup building software correctness tools."
}
}
}Auth Keys
Owner
Single Signature
Public Keys
STM7JgPxo2canzkidXS7zAoSqqqAJNzPF4SAx8ELsKA1L2nea9ALr1/1
Active
Single Signature
Public Keys
STM8SBFrSjJrVx7kXUPDUHAiEhczqgbEDkqiHRGyb8kjw6vjmFsWF1/1
Posting
Single Signature
Public Keys
STM7bqBr4whvNjfrQ1GpoPsJBwfqxBmr5W149osTq9EApmMtntg751/1
Memo
STM8Ae4PwgFhBEQ2CDWD38g4oghFY4ZvfGfyrJTZATYJJXH3SpirV
{
"owner": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [
[
"STM7JgPxo2canzkidXS7zAoSqqqAJNzPF4SAx8ELsKA1L2nea9ALr",
1
]
]
},
"active": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [
[
"STM8SBFrSjJrVx7kXUPDUHAiEhczqgbEDkqiHRGyb8kjw6vjmFsWF",
1
]
]
},
"posting": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [
[
"STM7bqBr4whvNjfrQ1GpoPsJBwfqxBmr5W149osTq9EApmMtntg75",
1
]
]
},
"memo": "STM8Ae4PwgFhBEQ2CDWD38g4oghFY4ZvfGfyrJTZATYJJXH3SpirV"
}Witness Votes
0 / 30
No active witness votes.
[]