Ecoer Logo
VOTING POWER100.00%
DOWNVOTE POWER100.00%
RESOURCE CREDITS100.00%
REPUTATION PROGRESS24.88%
Net Worth
0.374USD
STEEM
0.291STEEM
SBD
0.668SBD
Effective Power
5.008SP
├── Own SP
0.630SP
└── Incoming Deleg
+4.378SP

Detailed Balance

STEEM
balance
0.000STEEM
market_balance
0.000STEEM
savings_balance
0.000STEEM
reward_steem_balance
0.291STEEM
STEEM POWER
Own SP
0.630SP
Delegated Out
0.000SP
Delegation In
4.378SP
Effective Power
5.008SP
Reward SP (pending)
0.663SP
SBD
sbd_balance
0.000SBD
sbd_conversions
0.000SBD
sbd_market_balance
0.000SBD
savings_sbd_balance
0.000SBD
reward_sbd_balance
0.668SBD
{
  "balance": "0.000 STEEM",
  "savings_balance": "0.000 STEEM",
  "reward_steem_balance": "0.291 STEEM",
  "vesting_shares": "1024.637169 VESTS",
  "delegated_vesting_shares": "0.000000 VESTS",
  "received_vesting_shares": "7119.022637 VESTS",
  "sbd_balance": "0.000 SBD",
  "savings_sbd_balance": "0.000 SBD",
  "reward_sbd_balance": "0.668 SBD",
  "conversions": []
}

Account Info

namedlgusdn616
id542391
rank220,812
reputation17777213574
created2017-12-31T02:03:42
recovery_accountsteem
proxyNone
post_count10
comment_count0
lifetime_vote_count0
witnesses_voted_for0
last_post2018-09-30T09:20:54
last_root_post2018-09-30T09:20:54
last_vote_time2018-06-10T10:19:18
proxied_vsf_votes0, 0, 0, 0
can_vote1
voting_power0
delayed_votes0
balance0.000 STEEM
savings_balance0.000 STEEM
sbd_balance0.000 SBD
savings_sbd_balance0.000 SBD
vesting_shares1024.637169 VESTS
delegated_vesting_shares0.000000 VESTS
received_vesting_shares7119.022637 VESTS
reward_vesting_balance1346.278634 VESTS
vesting_balance0.000 STEEM
vesting_withdraw_rate0.000000 VESTS
next_vesting_withdrawal1969-12-31T23:59:59
withdrawn0
to_withdraw0
withdraw_routes0
savings_withdraw_requests0
last_account_recovery1970-01-01T00:00:00
reset_accountnull
last_owner_update1970-01-01T00:00:00
last_account_update2018-11-03T14:14:36
minedNo
sbd_seconds0
sbd_last_interest_payment1970-01-01T00:00:00
savings_sbd_last_interest_payment1970-01-01T00:00:00
{
  "id": 542391,
  "name": "dlgusdn616",
  "owner": {
    "weight_threshold": 1,
    "account_auths": [],
    "key_auths": [
      [
        "STM6jHpFiRziMjRgADbN7cGv8So31uHzPG1BsqRmUpnRP27BWBYWD",
        1
      ]
    ]
  },
  "active": {
    "weight_threshold": 1,
    "account_auths": [],
    "key_auths": [
      [
        "STM742zB8LV8i4gL2LW13R1sfWB1Zhee6qqrLBQPthPuUoNyxWRUx",
        1
      ]
    ]
  },
  "posting": {
    "weight_threshold": 1,
    "account_auths": [],
    "key_auths": [
      [
        "STM7y1D1gJ3xyn4hrUA6mP16yqCKSuWzAZsvM3xgYg1YnBM2VYzHA",
        1
      ]
    ]
  },
  "memo_key": "STM5XSA9F2q9wZMSAEV8mJpS5Le74o8WzE4ozhDYCcy7D7MVyLQtS",
  "json_metadata": "{\"profile\":{\"name\":\"waca\",\"profile_image\":\"https://cdn.steemitimages.com/DQmZvgrAx9hpBLnDPayrgV3692nSzwVgStwxWjoGp5btDva/%E1%84%8B%E1%85%B5%E1%84%92%E1%85%A7%E1%86%AB%E1%84%8B%E1%85%AE%E1%84%82%E1%85%B5%E1%86%B7.jpg\",\"location\":\"한국\"}}",
  "posting_json_metadata": "{\"profile\":{\"name\":\"waca\",\"profile_image\":\"https://cdn.steemitimages.com/DQmZvgrAx9hpBLnDPayrgV3692nSzwVgStwxWjoGp5btDva/%E1%84%8B%E1%85%B5%E1%84%92%E1%85%A7%E1%86%AB%E1%84%8B%E1%85%AE%E1%84%82%E1%85%B5%E1%86%B7.jpg\",\"location\":\"한국\"}}",
  "proxy": "",
  "last_owner_update": "1970-01-01T00:00:00",
  "last_account_update": "2018-11-03T14:14:36",
  "created": "2017-12-31T02:03:42",
  "mined": false,
  "recovery_account": "steem",
  "last_account_recovery": "1970-01-01T00:00:00",
  "reset_account": "null",
  "comment_count": 0,
  "lifetime_vote_count": 0,
  "post_count": 10,
  "can_vote": true,
  "voting_manabar": {
    "current_mana": "8143659806",
    "last_update_time": 1779060867
  },
  "downvote_manabar": {
    "current_mana": 2035914951,
    "last_update_time": 1779060867
  },
  "voting_power": 0,
  "balance": "0.000 STEEM",
  "savings_balance": "0.000 STEEM",
  "sbd_balance": "0.000 SBD",
  "sbd_seconds": "0",
  "sbd_seconds_last_update": "1970-01-01T00:00:00",
  "sbd_last_interest_payment": "1970-01-01T00:00:00",
  "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.668 SBD",
  "reward_steem_balance": "0.291 STEEM",
  "reward_vesting_balance": "1346.278634 VESTS",
  "reward_vesting_steem": "0.663 STEEM",
  "vesting_shares": "1024.637169 VESTS",
  "delegated_vesting_shares": "0.000000 VESTS",
  "received_vesting_shares": "7119.022637 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": 0,
  "posting_rewards": 1325,
  "proxied_vsf_votes": [
    0,
    0,
    0,
    0
  ],
  "witnesses_voted_for": 0,
  "last_post": "2018-09-30T09:20:54",
  "last_root_post": "2018-09-30T09:20:54",
  "last_vote_time": "2018-06-10T10:19:18",
  "post_bandwidth": 0,
  "pending_claimed_accounts": 0,
  "vesting_balance": "0.000 STEEM",
  "reputation": "17777213574",
  "transfer_history": [],
  "market_history": [],
  "post_history": [],
  "vote_history": [],
  "other_history": [],
  "witness_votes": [],
  "tags_usage": [],
  "guest_bloggers": [],
  "rank": 220812
}

Withdraw Routes

IncomingOutgoing
Empty
Empty
{
  "incoming": [],
  "outgoing": []
}
From Date
To Date
steemdelegated 4.378 SP to @dlgusdn616
2026/05/17 23:34:27
delegatorsteem
delegateedlgusdn616
vesting shares7119.022637 VESTS
Transaction InfoBlock #106142637/Trx df5e75098f91705a6c498adf6a54c7ab001faa31
View Raw JSON Data
{
  "trx_id": "df5e75098f91705a6c498adf6a54c7ab001faa31",
  "block": 106142637,
  "trx_in_block": 0,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2026-05-17T23:34:27",
  "op": [
    "delegate_vesting_shares",
    {
      "delegator": "steem",
      "delegatee": "dlgusdn616",
      "vesting_shares": "7119.022637 VESTS"
    }
  ]
}
steemdelegated 2.710 SP to @dlgusdn616
2026/05/12 01:06:21
delegatorsteem
delegateedlgusdn616
vesting shares4406.812232 VESTS
Transaction InfoBlock #105972436/Trx 8e1ff9f1ba98db1468a324ac183f21be71faf64c
View Raw JSON Data
{
  "trx_id": "8e1ff9f1ba98db1468a324ac183f21be71faf64c",
  "block": 105972436,
  "trx_in_block": 0,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2026-05-12T01:06:21",
  "op": [
    "delegate_vesting_shares",
    {
      "delegator": "steem",
      "delegatee": "dlgusdn616",
      "vesting_shares": "4406.812232 VESTS"
    }
  ]
}
steemdelegated 4.385 SP to @dlgusdn616
2026/04/25 22:56:30
delegatorsteem
delegateedlgusdn616
vesting shares7131.538393 VESTS
Transaction InfoBlock #105510309/Trx e72f2519764aa117bcc795923f255e2f3b789e3b
View Raw JSON Data
{
  "trx_id": "e72f2519764aa117bcc795923f255e2f3b789e3b",
  "block": 105510309,
  "trx_in_block": 1,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2026-04-25T22:56:30",
  "op": [
    "delegate_vesting_shares",
    {
      "delegator": "steem",
      "delegatee": "dlgusdn616",
      "vesting_shares": "7131.538393 VESTS"
    }
  ]
}
steemdelegated 2.735 SP to @dlgusdn616
2026/01/23 05:59:06
delegatorsteem
delegateedlgusdn616
vesting shares4448.359051 VESTS
Transaction InfoBlock #102849632/Trx a4c2bd554d977831d584c878e10dfbc29f42c931
View Raw JSON Data
{
  "trx_id": "a4c2bd554d977831d584c878e10dfbc29f42c931",
  "block": 102849632,
  "trx_in_block": 4,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2026-01-23T05:59:06",
  "op": [
    "delegate_vesting_shares",
    {
      "delegator": "steem",
      "delegatee": "dlgusdn616",
      "vesting_shares": "4448.359051 VESTS"
    }
  ]
}
steemdelegated 2.836 SP to @dlgusdn616
2024/12/17 01:19:03
delegatorsteem
delegateedlgusdn616
vesting shares4612.578248 VESTS
Transaction InfoBlock #91296059/Trx 8a28d548b35a58e73a3580ccea763fac4c2cd707
View Raw JSON Data
{
  "trx_id": "8a28d548b35a58e73a3580ccea763fac4c2cd707",
  "block": 91296059,
  "trx_in_block": 3,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2024-12-17T01:19:03",
  "op": [
    "delegate_vesting_shares",
    {
      "delegator": "steem",
      "delegatee": "dlgusdn616",
      "vesting_shares": "4612.578248 VESTS"
    }
  ]
}
steemdelegated 2.940 SP to @dlgusdn616
2023/11/13 17:02:03
delegatorsteem
delegateedlgusdn616
vesting shares4781.711780 VESTS
Transaction InfoBlock #79850274/Trx 4d3dec196494b3c5ca49ffc135947644707084e1
View Raw JSON Data
{
  "trx_id": "4d3dec196494b3c5ca49ffc135947644707084e1",
  "block": 79850274,
  "trx_in_block": 0,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2023-11-13T17:02:03",
  "op": [
    "delegate_vesting_shares",
    {
      "delegator": "steem",
      "delegatee": "dlgusdn616",
      "vesting_shares": "4781.711780 VESTS"
    }
  ]
}
steemdelegated 4.747 SP to @dlgusdn616
2023/09/21 21:01:57
delegatorsteem
delegateedlgusdn616
vesting shares7718.990566 VESTS
Transaction InfoBlock #78346873/Trx 16f34f7fd3f70bef1a10a1e5c8792d681d513a73
View Raw JSON Data
{
  "trx_id": "16f34f7fd3f70bef1a10a1e5c8792d681d513a73",
  "block": 78346873,
  "trx_in_block": 0,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2023-09-21T21:01:57",
  "op": [
    "delegate_vesting_shares",
    {
      "delegator": "steem",
      "delegatee": "dlgusdn616",
      "vesting_shares": "7718.990566 VESTS"
    }
  ]
}
steemdelegated 4.883 SP to @dlgusdn616
2022/11/03 10:55:48
delegatorsteem
delegateedlgusdn616
vesting shares7940.672004 VESTS
Transaction InfoBlock #69112339/Trx 8c07cbe28db5d8f97213e2911b35e6ae22b04517
View Raw JSON Data
{
  "trx_id": "8c07cbe28db5d8f97213e2911b35e6ae22b04517",
  "block": 69112339,
  "trx_in_block": 2,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2022-11-03T10:55:48",
  "op": [
    "delegate_vesting_shares",
    {
      "delegator": "steem",
      "delegatee": "dlgusdn616",
      "vesting_shares": "7940.672004 VESTS"
    }
  ]
}
steemdelegated 5.019 SP to @dlgusdn616
2022/01/17 10:15:24
delegatorsteem
delegateedlgusdn616
vesting shares8161.205235 VESTS
Transaction InfoBlock #60808578/Trx 7dbde078b89128c7caae70a61dff6a38eaa58977
View Raw JSON Data
{
  "trx_id": "7dbde078b89128c7caae70a61dff6a38eaa58977",
  "block": 60808578,
  "trx_in_block": 6,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2022-01-17T10:15:24",
  "op": [
    "delegate_vesting_shares",
    {
      "delegator": "steem",
      "delegatee": "dlgusdn616",
      "vesting_shares": "8161.205235 VESTS"
    }
  ]
}
steemdelegated 5.132 SP to @dlgusdn616
2021/06/14 00:12:09
delegatorsteem
delegateedlgusdn616
vesting shares8344.973893 VESTS
Transaction InfoBlock #54606995/Trx 9d122c8cc2a445505a6fbb85e09cbe00e434ebf7
View Raw JSON Data
{
  "trx_id": "9d122c8cc2a445505a6fbb85e09cbe00e434ebf7",
  "block": 54606995,
  "trx_in_block": 9,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2021-06-14T00:12:09",
  "op": [
    "delegate_vesting_shares",
    {
      "delegator": "steem",
      "delegatee": "dlgusdn616",
      "vesting_shares": "8344.973893 VESTS"
    }
  ]
}
steemdelegated 5.247 SP to @dlgusdn616
2020/12/11 10:32:18
delegatorsteem
delegateedlgusdn616
vesting shares8532.395867 VESTS
Transaction InfoBlock #49354489/Trx 39df8d3a7f69aa9eb4fdbbf751dccfc057a7457a
View Raw JSON Data
{
  "trx_id": "39df8d3a7f69aa9eb4fdbbf751dccfc057a7457a",
  "block": 49354489,
  "trx_in_block": 4,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2020-12-11T10:32:18",
  "op": [
    "delegate_vesting_shares",
    {
      "delegator": "steem",
      "delegatee": "dlgusdn616",
      "vesting_shares": "8532.395867 VESTS"
    }
  ]
}
steemdelegated 1.176 SP to @dlgusdn616
2020/12/06 04:09:33
delegatorsteem
delegateedlgusdn616
vesting shares1912.543513 VESTS
Transaction InfoBlock #49206052/Trx afa7f51ab18806bb93065ff5a3f17e4c08df2865
View Raw JSON Data
{
  "trx_id": "afa7f51ab18806bb93065ff5a3f17e4c08df2865",
  "block": 49206052,
  "trx_in_block": 1,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2020-12-06T04:09:33",
  "op": [
    "delegate_vesting_shares",
    {
      "delegator": "steem",
      "delegatee": "dlgusdn616",
      "vesting_shares": "1912.543513 VESTS"
    }
  ]
}
steemdelegated 5.251 SP to @dlgusdn616
2020/12/05 14:10:27
delegatorsteem
delegateedlgusdn616
vesting shares8538.603721 VESTS
Transaction InfoBlock #49189584/Trx 08fde3941373e510178d59b897d7a74ec0413e44
View Raw JSON Data
{
  "trx_id": "08fde3941373e510178d59b897d7a74ec0413e44",
  "block": 49189584,
  "trx_in_block": 11,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2020-12-05T14:10:27",
  "op": [
    "delegate_vesting_shares",
    {
      "delegator": "steem",
      "delegatee": "dlgusdn616",
      "vesting_shares": "8538.603721 VESTS"
    }
  ]
}
steemdelegated 1.181 SP to @dlgusdn616
2020/11/02 14:20:54
delegatorsteem
delegateedlgusdn616
vesting shares1920.017158 VESTS
Transaction InfoBlock #48256278/Trx ae9bd19033f6dfcead13527e6a922cd3132d7658
View Raw JSON Data
{
  "trx_id": "ae9bd19033f6dfcead13527e6a922cd3132d7658",
  "block": 48256278,
  "trx_in_block": 4,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2020-11-02T14:20:54",
  "op": [
    "delegate_vesting_shares",
    {
      "delegator": "steem",
      "delegatee": "dlgusdn616",
      "vesting_shares": "1920.017158 VESTS"
    }
  ]
}
steemdelegated 5.375 SP to @dlgusdn616
2020/05/09 05:05:57
delegatorsteem
delegateedlgusdn616
vesting shares8741.409080 VESTS
Transaction InfoBlock #43216287/Trx 6ece0d8429ffcdab2df3e2186e6d702cdeac55da
View Raw JSON Data
{
  "trx_id": "6ece0d8429ffcdab2df3e2186e6d702cdeac55da",
  "block": 43216287,
  "trx_in_block": 12,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2020-05-09T05:05:57",
  "op": [
    "delegate_vesting_shares",
    {
      "delegator": "steem",
      "delegatee": "dlgusdn616",
      "vesting_shares": "8741.409080 VESTS"
    }
  ]
}
steemdelegated 1.201 SP to @dlgusdn616
2020/05/08 08:36:30
delegatorsteem
delegateedlgusdn616
vesting shares1953.311140 VESTS
Transaction InfoBlock #43192274/Trx 5855222bf77b6740d6d886f0ac29062012179fdc
View Raw JSON Data
{
  "trx_id": "5855222bf77b6740d6d886f0ac29062012179fdc",
  "block": 43192274,
  "trx_in_block": 9,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2020-05-08T08:36:30",
  "op": [
    "delegate_vesting_shares",
    {
      "delegator": "steem",
      "delegatee": "dlgusdn616",
      "vesting_shares": "1953.311140 VESTS"
    }
  ]
}
2019/12/31 02:32:39
parent authordlgusdn616
parent permlinkiot
authorsteemitboard
permlinksteemitboard-notify-dlgusdn616-20191231t023239000z
title
bodyCongratulations @dlgusdn616! You received a personal award! <table><tr><td>https://steemitimages.com/70x70/http://steemitboard.com/@dlgusdn616/birthday2.png</td><td>Happy Birthday! - You are on the Steem blockchain for 2 years!</td></tr></table> <sub>_You can view [your badges on your Steem Board](https://steemitboard.com/@dlgusdn616) and compare to others on the [Steem Ranking](https://steemitboard.com/ranking/index.php?name=dlgusdn616)_</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 InfoBlock #39506616/Trx 731769a2076562024bf7df3cdb61552f95ab3f6d
View Raw JSON Data
{
  "trx_id": "731769a2076562024bf7df3cdb61552f95ab3f6d",
  "block": 39506616,
  "trx_in_block": 9,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2019-12-31T02:32:39",
  "op": [
    "comment",
    {
      "parent_author": "dlgusdn616",
      "parent_permlink": "iot",
      "author": "steemitboard",
      "permlink": "steemitboard-notify-dlgusdn616-20191231t023239000z",
      "title": "",
      "body": "Congratulations @dlgusdn616! You received a personal award!\n\n<table><tr><td>https://steemitimages.com/70x70/http://steemitboard.com/@dlgusdn616/birthday2.png</td><td>Happy Birthday! - You are on the Steem blockchain for 2 years!</td></tr></table>\n\n<sub>_You can view [your badges on your Steem Board](https://steemitboard.com/@dlgusdn616) and compare to others on the [Steem Ranking](https://steemitboard.com/ranking/index.php?name=dlgusdn616)_</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\"]}"
    }
  ]
}
steemdelegated 5.429 SP to @dlgusdn616
2019/12/02 17:32:06
delegatorsteem
delegateedlgusdn616
vesting shares8829.255214 VESTS
Transaction InfoBlock #38690907/Trx dc301a00b2c929acebb02001799cf9d3bcf7cc36
View Raw JSON Data
{
  "trx_id": "dc301a00b2c929acebb02001799cf9d3bcf7cc36",
  "block": 38690907,
  "trx_in_block": 4,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2019-12-02T17:32:06",
  "op": [
    "delegate_vesting_shares",
    {
      "delegator": "steem",
      "delegatee": "dlgusdn616",
      "vesting_shares": "8829.255214 VESTS"
    }
  ]
}
2018/12/31 03:05:42
parent authordlgusdn616
parent permlinkiot
authorsteemitboard
permlinksteemitboard-notify-dlgusdn616-20181231t030542000z
title
bodyCongratulations @dlgusdn616! You received a personal award! <table><tr><td>https://steemitimages.com/70x70/http://steemitboard.com/@dlgusdn616/birthday1.png</td><td>1 Year on Steemit</td></tr></table> <sub>_[Click here to view your Board](https://steemitboard.com/@dlgusdn616)_</sub> **Do not miss the last post from @steemitboard:** <table><tr><td><a href="https://steemit.com/christmas/@steemitboard/christmas-challenge-send-a-gift-to-to-your-friends-the-party-continues"><img src="https://steemitimages.com/64x128/http://i.cubeupload.com/kf4SJb.png"></a></td><td><a href="https://steemit.com/christmas/@steemitboard/christmas-challenge-send-a-gift-to-to-your-friends-the-party-continues">Christmas Challenge - The party continues</a></td></tr></table> > Support [SteemitBoard's project](https://steemit.com/@steemitboard)! **[Vote for its witness](https://v2.steemconnect.com/sign/account-witness-vote?witness=steemitboard&approve=1)** and **get one more award**!
json metadata{"image":["https://steemitboard.com/img/notify.png"]}
Transaction InfoBlock #29034127/Trx ee63c406e1d380cbda0bf61c5bc47ab7f98b5fdb
View Raw JSON Data
{
  "trx_id": "ee63c406e1d380cbda0bf61c5bc47ab7f98b5fdb",
  "block": 29034127,
  "trx_in_block": 2,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-12-31T03:05:42",
  "op": [
    "comment",
    {
      "parent_author": "dlgusdn616",
      "parent_permlink": "iot",
      "author": "steemitboard",
      "permlink": "steemitboard-notify-dlgusdn616-20181231t030542000z",
      "title": "",
      "body": "Congratulations @dlgusdn616! You received a personal award!\n\n<table><tr><td>https://steemitimages.com/70x70/http://steemitboard.com/@dlgusdn616/birthday1.png</td><td>1 Year on Steemit</td></tr></table>\n\n<sub>_[Click here to view your Board](https://steemitboard.com/@dlgusdn616)_</sub>\n\n\n**Do not miss the last post from @steemitboard:**\n<table><tr><td><a href=\"https://steemit.com/christmas/@steemitboard/christmas-challenge-send-a-gift-to-to-your-friends-the-party-continues\"><img src=\"https://steemitimages.com/64x128/http://i.cubeupload.com/kf4SJb.png\"></a></td><td><a href=\"https://steemit.com/christmas/@steemitboard/christmas-challenge-send-a-gift-to-to-your-friends-the-party-continues\">Christmas Challenge - The party continues</a></td></tr></table>\n\n> Support [SteemitBoard's project](https://steemit.com/@steemitboard)! **[Vote for its witness](https://v2.steemconnect.com/sign/account-witness-vote?witness=steemitboard&approve=1)** and **get one more award**!",
      "json_metadata": "{\"image\":[\"https://steemitboard.com/img/notify.png\"]}"
    }
  ]
}
steemdelegated 5.551 SP to @dlgusdn616
2018/12/30 10:39:15
delegatorsteem
delegateedlgusdn616
vesting shares9026.382088 VESTS
Transaction InfoBlock #29014411/Trx 2eec7f757ff86278e7d301c0b9a30089345ec999
View Raw JSON Data
{
  "trx_id": "2eec7f757ff86278e7d301c0b9a30089345ec999",
  "block": 29014411,
  "trx_in_block": 20,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-12-30T10:39:15",
  "op": [
    "delegate_vesting_shares",
    {
      "delegator": "steem",
      "delegatee": "dlgusdn616",
      "vesting_shares": "9026.382088 VESTS"
    }
  ]
}
dlgusdn616updated their account properties
2018/11/03 14:14:36
accountdlgusdn616
memo keySTM5XSA9F2q9wZMSAEV8mJpS5Le74o8WzE4ozhDYCcy7D7MVyLQtS
json metadata{"profile":{"name":"waca","profile_image":"https://cdn.steemitimages.com/DQmZvgrAx9hpBLnDPayrgV3692nSzwVgStwxWjoGp5btDva/%E1%84%8B%E1%85%B5%E1%84%92%E1%85%A7%E1%86%AB%E1%84%8B%E1%85%AE%E1%84%82%E1%85%B5%E1%86%B7.jpg","location":"한국"}}
Transaction InfoBlock #27378075/Trx 83f6e8c94e1076b323b4b2b6004deace94d74f45
View Raw JSON Data
{
  "trx_id": "83f6e8c94e1076b323b4b2b6004deace94d74f45",
  "block": 27378075,
  "trx_in_block": 20,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-11-03T14:14:36",
  "op": [
    "account_update",
    {
      "account": "dlgusdn616",
      "memo_key": "STM5XSA9F2q9wZMSAEV8mJpS5Le74o8WzE4ozhDYCcy7D7MVyLQtS",
      "json_metadata": "{\"profile\":{\"name\":\"waca\",\"profile_image\":\"https://cdn.steemitimages.com/DQmZvgrAx9hpBLnDPayrgV3692nSzwVgStwxWjoGp5btDva/%E1%84%8B%E1%85%B5%E1%84%92%E1%85%A7%E1%86%AB%E1%84%8B%E1%85%AE%E1%84%82%E1%85%B5%E1%86%B7.jpg\",\"location\":\"한국\"}}"
    }
  ]
}
sensationupvoted (100.00%) @dlgusdn616 / iot
2018/09/30 10:55:33
votersensation
authordlgusdn616
permlinkiot
weight10000 (100.00%)
Transaction InfoBlock #26395579/Trx 8861c3be6ee52351593b0f084390a8e47a1ce8ba
View Raw JSON Data
{
  "trx_id": "8861c3be6ee52351593b0f084390a8e47a1ce8ba",
  "block": 26395579,
  "trx_in_block": 2,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-09-30T10:55:33",
  "op": [
    "vote",
    {
      "voter": "sensation",
      "author": "dlgusdn616",
      "permlink": "iot",
      "weight": 10000
    }
  ]
}
hackerzizonupvoted (1.00%) @dlgusdn616 / iot
2018/09/30 10:07:45
voterhackerzizon
authordlgusdn616
permlinkiot
weight100 (1.00%)
Transaction InfoBlock #26394625/Trx c3748c4ca7e22867329bd92a71593c7adbe34307
View Raw JSON Data
{
  "trx_id": "c3748c4ca7e22867329bd92a71593c7adbe34307",
  "block": 26394625,
  "trx_in_block": 21,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-09-30T10:07:45",
  "op": [
    "vote",
    {
      "voter": "hackerzizon",
      "author": "dlgusdn616",
      "permlink": "iot",
      "weight": 100
    }
  ]
}
dlgusdn616published a new post: iot
2018/09/30 10:07:30
parent author
parent permlinkethereum
authordlgusdn616
permlinkiot
title이더리움을 활용한 IoT 프로젝트 제안 및 프로토타입 구현
body@@ -24640,12 +24640,108 @@ %EC%A0%84%EB%9E%B5%EC%9D%B4%EB%9D%BC %ED%95%A0 %EC%88%98 %EC%9E%88%EB%8B%A4. +%0A%0A## 7. %EC%82%AC%EC%9A%A9%ED%95%9C %EC%86%8C%EC%8A%A4%EC%BD%94%EB%93%9C%0A%EA%B4%80%EB%A0%A8%EB%90%9C %EC%86%8C%EC%8A%A4%EC%BD%94%EB%93%9C %EB%A7%81%ED%81%AC%EB%8A%94 %EC%95%84%EB%9E%98%EC%99%80 %EA%B0%99%EB%8B%A4.%0Ahttps://github.com/dlgusdn616/ethereum-gas-station-project
json metadata{"tags":["ethereum","smartcontract","blockchain","iot"],"image":["https://cdn.steemitimages.com/DQme6C24nVuyR4exGQFAF9wRPczm8ubickiuZCxxP7Yy9wb/image.png","https://cdn.steemitimages.com/DQmU8EqqG81CC6JnL9KDJ94o6THSLMGQqwMTZpJxxqyXHH6/image.png","https://cdn.steemitimages.com/DQmSKMC8qPzZgd1oJZaAsgS3VugzrqgpUwuoBLFjPDuen6P/image.png","https://cdn.steemitimages.com/DQmP1qkZ1zbgxQrBmgrARN7VsZtskVwjRo8RaKY6K2PGAnp/image.png","https://cdn.steemitimages.com/DQmQfWXkXLnrPhYQB24qnyTGWcE4BzoqmbBVCJoLNaN1Ewa/image.png","https://cdn.steemitimages.com/DQmNUcea65SPfjdah4ca7fofiA1BiRfEN6FfEpZTeQ621Lk/image.png","https://cdn.steemitimages.com/DQmSuRNMq5yxLgyeNSn9nJ4DHEMx5nX4WuRaJP2JznTkRjq/image.png","https://cdn.steemitimages.com/DQmSWA7aT7Qrm55yeHEL1tmeWT4JEuEDDfLz9zspLV6DR8G/image.png","https://cdn.steemitimages.com/DQmSm41avcPcGgFC8nYyKUjmR9QMUaxZBgdUyQdEUHvEmfm/image.png","https://cdn.steemitimages.com/DQmZhYtBBLmDWzQmY4Y5Mcxd91z8hzLYQAjsubvPTujyuXE/image.png","https://cdn.steemitimages.com/DQmVsDSF4rUAMNDxf24gpjsX8AeYQgmP59wUYEPhDt9uouJ/image.png","https://cdn.steemitimages.com/DQmeCZnMKKGK4oH8YsNn5jipC9qEuXYNvwam1nXuU2g6xjb/image.png","https://cdn.steemitimages.com/DQmdSBHqafsD6WNSPb1P7KQREjRKk78Kvf8QaPJCkYYHK43/image.png","https://cdn.steemitimages.com/DQmYbupHfiVkBLvX2DfjZHYaNoAiPifPfdDkFozoBsKWDAh/image.png","https://cdn.steemitimages.com/DQmPVC28GfjpSFwksaQNRVGpFcBqvnhynjpcfN2wRiQwpFC/image.png","https://cdn.steemitimages.com/DQmeHs9dWaPGumnXf8rHEAeE1D4Ki1yhv6vRy81LuFgdPE2/image.png"],"links":["https://github.com/dlgusdn616","https://medium.com/@dlgusdn616","https://github.com/heuristicwave","https://medium.com/@heuristicwave","https://github.com/Bookstore3","http://www.ndsl.kr/ndsl/search/detail/report/reportSearchResultDetail.do?cn=TRKO201600002359","https://github.com/dlgusdn616/ethereum-gas-station-project"],"app":"steemit/0.1","format":"markdown"}
Transaction InfoBlock #26394620/Trx 3d8334bf7e8c0ac52f9455201bef8f82740f789c
View Raw JSON Data
{
  "trx_id": "3d8334bf7e8c0ac52f9455201bef8f82740f789c",
  "block": 26394620,
  "trx_in_block": 17,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-09-30T10:07:30",
  "op": [
    "comment",
    {
      "parent_author": "",
      "parent_permlink": "ethereum",
      "author": "dlgusdn616",
      "permlink": "iot",
      "title": "이더리움을 활용한 IoT 프로젝트 제안 및 프로토타입 구현",
      "body": "@@ -24640,12 +24640,108 @@\n %EC%A0%84%EB%9E%B5%EC%9D%B4%EB%9D%BC %ED%95%A0 %EC%88%98 %EC%9E%88%EB%8B%A4.\n+%0A%0A## 7. %EC%82%AC%EC%9A%A9%ED%95%9C %EC%86%8C%EC%8A%A4%EC%BD%94%EB%93%9C%0A%EA%B4%80%EB%A0%A8%EB%90%9C %EC%86%8C%EC%8A%A4%EC%BD%94%EB%93%9C %EB%A7%81%ED%81%AC%EB%8A%94 %EC%95%84%EB%9E%98%EC%99%80 %EA%B0%99%EB%8B%A4.%0Ahttps://github.com/dlgusdn616/ethereum-gas-station-project\n",
      "json_metadata": "{\"tags\":[\"ethereum\",\"smartcontract\",\"blockchain\",\"iot\"],\"image\":[\"https://cdn.steemitimages.com/DQme6C24nVuyR4exGQFAF9wRPczm8ubickiuZCxxP7Yy9wb/image.png\",\"https://cdn.steemitimages.com/DQmU8EqqG81CC6JnL9KDJ94o6THSLMGQqwMTZpJxxqyXHH6/image.png\",\"https://cdn.steemitimages.com/DQmSKMC8qPzZgd1oJZaAsgS3VugzrqgpUwuoBLFjPDuen6P/image.png\",\"https://cdn.steemitimages.com/DQmP1qkZ1zbgxQrBmgrARN7VsZtskVwjRo8RaKY6K2PGAnp/image.png\",\"https://cdn.steemitimages.com/DQmQfWXkXLnrPhYQB24qnyTGWcE4BzoqmbBVCJoLNaN1Ewa/image.png\",\"https://cdn.steemitimages.com/DQmNUcea65SPfjdah4ca7fofiA1BiRfEN6FfEpZTeQ621Lk/image.png\",\"https://cdn.steemitimages.com/DQmSuRNMq5yxLgyeNSn9nJ4DHEMx5nX4WuRaJP2JznTkRjq/image.png\",\"https://cdn.steemitimages.com/DQmSWA7aT7Qrm55yeHEL1tmeWT4JEuEDDfLz9zspLV6DR8G/image.png\",\"https://cdn.steemitimages.com/DQmSm41avcPcGgFC8nYyKUjmR9QMUaxZBgdUyQdEUHvEmfm/image.png\",\"https://cdn.steemitimages.com/DQmZhYtBBLmDWzQmY4Y5Mcxd91z8hzLYQAjsubvPTujyuXE/image.png\",\"https://cdn.steemitimages.com/DQmVsDSF4rUAMNDxf24gpjsX8AeYQgmP59wUYEPhDt9uouJ/image.png\",\"https://cdn.steemitimages.com/DQmeCZnMKKGK4oH8YsNn5jipC9qEuXYNvwam1nXuU2g6xjb/image.png\",\"https://cdn.steemitimages.com/DQmdSBHqafsD6WNSPb1P7KQREjRKk78Kvf8QaPJCkYYHK43/image.png\",\"https://cdn.steemitimages.com/DQmYbupHfiVkBLvX2DfjZHYaNoAiPifPfdDkFozoBsKWDAh/image.png\",\"https://cdn.steemitimages.com/DQmPVC28GfjpSFwksaQNRVGpFcBqvnhynjpcfN2wRiQwpFC/image.png\",\"https://cdn.steemitimages.com/DQmeHs9dWaPGumnXf8rHEAeE1D4Ki1yhv6vRy81LuFgdPE2/image.png\"],\"links\":[\"https://github.com/dlgusdn616\",\"https://medium.com/@dlgusdn616\",\"https://github.com/heuristicwave\",\"https://medium.com/@heuristicwave\",\"https://github.com/Bookstore3\",\"http://www.ndsl.kr/ndsl/search/detail/report/reportSearchResultDetail.do?cn=TRKO201600002359\",\"https://github.com/dlgusdn616/ethereum-gas-station-project\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
    }
  ]
}
dlgusdn616published a new post: iot
2018/09/30 09:28:00
parent author
parent permlinkethereum
authordlgusdn616
permlinkiot
title이더리움을 활용한 IoT 프로젝트 제안 및 프로토타입 구현
body@@ -24131,16 +24131,121 @@ %EB%B3%BC %EC%88%98 %EC%9E%88%EB%8B%A4.%0A +!%5Btoken-economy%5D(https://cdn.steemitimages.com/DQmeHs9dWaPGumnXf8rHEAeE1D4Ki1yhv6vRy81LuFgdPE2/image.png) %0A1. %EC%82%AC%EC%9A%A9%EC%9E%90%EB%93%A4
json metadata{"tags":["ethereum","smartcontract","blockchain","iot"],"image":["https://cdn.steemitimages.com/DQme6C24nVuyR4exGQFAF9wRPczm8ubickiuZCxxP7Yy9wb/image.png","https://cdn.steemitimages.com/DQmU8EqqG81CC6JnL9KDJ94o6THSLMGQqwMTZpJxxqyXHH6/image.png","https://cdn.steemitimages.com/DQmSKMC8qPzZgd1oJZaAsgS3VugzrqgpUwuoBLFjPDuen6P/image.png","https://cdn.steemitimages.com/DQmP1qkZ1zbgxQrBmgrARN7VsZtskVwjRo8RaKY6K2PGAnp/image.png","https://cdn.steemitimages.com/DQmQfWXkXLnrPhYQB24qnyTGWcE4BzoqmbBVCJoLNaN1Ewa/image.png","https://cdn.steemitimages.com/DQmNUcea65SPfjdah4ca7fofiA1BiRfEN6FfEpZTeQ621Lk/image.png","https://cdn.steemitimages.com/DQmSuRNMq5yxLgyeNSn9nJ4DHEMx5nX4WuRaJP2JznTkRjq/image.png","https://cdn.steemitimages.com/DQmSWA7aT7Qrm55yeHEL1tmeWT4JEuEDDfLz9zspLV6DR8G/image.png","https://cdn.steemitimages.com/DQmSm41avcPcGgFC8nYyKUjmR9QMUaxZBgdUyQdEUHvEmfm/image.png","https://cdn.steemitimages.com/DQmZhYtBBLmDWzQmY4Y5Mcxd91z8hzLYQAjsubvPTujyuXE/image.png","https://cdn.steemitimages.com/DQmVsDSF4rUAMNDxf24gpjsX8AeYQgmP59wUYEPhDt9uouJ/image.png","https://cdn.steemitimages.com/DQmeCZnMKKGK4oH8YsNn5jipC9qEuXYNvwam1nXuU2g6xjb/image.png","https://cdn.steemitimages.com/DQmdSBHqafsD6WNSPb1P7KQREjRKk78Kvf8QaPJCkYYHK43/image.png","https://cdn.steemitimages.com/DQmYbupHfiVkBLvX2DfjZHYaNoAiPifPfdDkFozoBsKWDAh/image.png","https://cdn.steemitimages.com/DQmPVC28GfjpSFwksaQNRVGpFcBqvnhynjpcfN2wRiQwpFC/image.png","https://cdn.steemitimages.com/DQmeHs9dWaPGumnXf8rHEAeE1D4Ki1yhv6vRy81LuFgdPE2/image.png"],"links":["https://github.com/dlgusdn616","https://medium.com/@dlgusdn616","https://github.com/heuristicwave","https://medium.com/@heuristicwave","https://github.com/Bookstore3","http://www.ndsl.kr/ndsl/search/detail/report/reportSearchResultDetail.do?cn=TRKO201600002359"],"app":"steemit/0.1","format":"markdown"}
Transaction InfoBlock #26393830/Trx a5f99c9bca690ed02d787e1a9501eaaa4e7eeb4e
View Raw JSON Data
{
  "trx_id": "a5f99c9bca690ed02d787e1a9501eaaa4e7eeb4e",
  "block": 26393830,
  "trx_in_block": 24,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-09-30T09:28:00",
  "op": [
    "comment",
    {
      "parent_author": "",
      "parent_permlink": "ethereum",
      "author": "dlgusdn616",
      "permlink": "iot",
      "title": "이더리움을 활용한 IoT 프로젝트 제안 및 프로토타입 구현",
      "body": "@@ -24131,16 +24131,121 @@\n %EB%B3%BC %EC%88%98 %EC%9E%88%EB%8B%A4.%0A\n+!%5Btoken-economy%5D(https://cdn.steemitimages.com/DQmeHs9dWaPGumnXf8rHEAeE1D4Ki1yhv6vRy81LuFgdPE2/image.png)\n %0A1. %EC%82%AC%EC%9A%A9%EC%9E%90%EB%93%A4\n",
      "json_metadata": "{\"tags\":[\"ethereum\",\"smartcontract\",\"blockchain\",\"iot\"],\"image\":[\"https://cdn.steemitimages.com/DQme6C24nVuyR4exGQFAF9wRPczm8ubickiuZCxxP7Yy9wb/image.png\",\"https://cdn.steemitimages.com/DQmU8EqqG81CC6JnL9KDJ94o6THSLMGQqwMTZpJxxqyXHH6/image.png\",\"https://cdn.steemitimages.com/DQmSKMC8qPzZgd1oJZaAsgS3VugzrqgpUwuoBLFjPDuen6P/image.png\",\"https://cdn.steemitimages.com/DQmP1qkZ1zbgxQrBmgrARN7VsZtskVwjRo8RaKY6K2PGAnp/image.png\",\"https://cdn.steemitimages.com/DQmQfWXkXLnrPhYQB24qnyTGWcE4BzoqmbBVCJoLNaN1Ewa/image.png\",\"https://cdn.steemitimages.com/DQmNUcea65SPfjdah4ca7fofiA1BiRfEN6FfEpZTeQ621Lk/image.png\",\"https://cdn.steemitimages.com/DQmSuRNMq5yxLgyeNSn9nJ4DHEMx5nX4WuRaJP2JznTkRjq/image.png\",\"https://cdn.steemitimages.com/DQmSWA7aT7Qrm55yeHEL1tmeWT4JEuEDDfLz9zspLV6DR8G/image.png\",\"https://cdn.steemitimages.com/DQmSm41avcPcGgFC8nYyKUjmR9QMUaxZBgdUyQdEUHvEmfm/image.png\",\"https://cdn.steemitimages.com/DQmZhYtBBLmDWzQmY4Y5Mcxd91z8hzLYQAjsubvPTujyuXE/image.png\",\"https://cdn.steemitimages.com/DQmVsDSF4rUAMNDxf24gpjsX8AeYQgmP59wUYEPhDt9uouJ/image.png\",\"https://cdn.steemitimages.com/DQmeCZnMKKGK4oH8YsNn5jipC9qEuXYNvwam1nXuU2g6xjb/image.png\",\"https://cdn.steemitimages.com/DQmdSBHqafsD6WNSPb1P7KQREjRKk78Kvf8QaPJCkYYHK43/image.png\",\"https://cdn.steemitimages.com/DQmYbupHfiVkBLvX2DfjZHYaNoAiPifPfdDkFozoBsKWDAh/image.png\",\"https://cdn.steemitimages.com/DQmPVC28GfjpSFwksaQNRVGpFcBqvnhynjpcfN2wRiQwpFC/image.png\",\"https://cdn.steemitimages.com/DQmeHs9dWaPGumnXf8rHEAeE1D4Ki1yhv6vRy81LuFgdPE2/image.png\"],\"links\":[\"https://github.com/dlgusdn616\",\"https://medium.com/@dlgusdn616\",\"https://github.com/heuristicwave\",\"https://medium.com/@heuristicwave\",\"https://github.com/Bookstore3\",\"http://www.ndsl.kr/ndsl/search/detail/report/reportSearchResultDetail.do?cn=TRKO201600002359\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
    }
  ]
}
dlgusdn616published a new post: iot
2018/09/30 09:20:54
parent author
parent permlinkethereum
authordlgusdn616
permlinkiot
title이더리움을 활용한 IoT 프로젝트 제안 및 프로토타입 구현
body# 이더리움 스마트컨트랙트를 활용한 신뢰받는 주유소 시스템 구축 ## 1. 이 글을 읽기 전에 본 포스팅은 국가암호공모전 및 SK블록체인 해커톤, 한성대학교 공학경진대회에 출품하였던 `이더리움 스마트 컨트랙트를 활용한 신뢰받는 주유소 시스템` 에 대해 다룹니다. 포스팅의 타겟은 이미 블록체인과 이더리움에 대해 지식이 있고 직접 활용해본 혹은 활용할 예정인 분들입니다. "블록체인을 활용하면 현실 세계의 어떤 문제들을 해결할 수 있을까?"를 고민하는 분들께 도움이 되었으면 합니다. 본 포스팅은 먼저 *이상적인 시스템의 구성에 대해 설명하는 파트* 그리고 그 중 일부를 구현한 *프로토타입에 대해 설명하는 파트* 이렇게 2개의 대분류로 이루어져 있습니다. 본 포스팅에서 예시로 드는 정유사는 `SK에너지`로 설정하였습니다. (`SK에너지`로 설정한 건 단순히 해커톤을 주최한 그룹이라는 점 때문입니다...) 본 작품의 저자는 이현우, 임지훈, 최승주이며 각 저자의 블로그 및 깃허브 링크는 아래와 같습니다. 혹시 연락을 주실 일이 있다면 아래의 경로를 통해 주시면 감사하겠습니다. * 이현우 Github: https://github.com/dlgusdn616 Medium: https://medium.com/@dlgusdn616 Email: [email protected] Role: Geth(go-ethereum) 노드 구성 및 운영, 네트워크 및 환경 구축 * 임지훈 Github: https://github.com/heuristicwave Medium: https://medium.com/@heuristicwave Email: [email protected] Role: Node js 백엔드 및 프론트엔드 설계 * 최승주 Github: https://github.com/Bookstore3 ## 2. 개요 오늘날 주유소를 이용하는 소비자들이 가짜 석유 및 조작된 주유량으로 금전적 피해를 보는 사례가 다수 발생하고 있다. 가짜 석유 문제는 석유의 유통 과정에서 각 주유소 지점에 기름이 공급될 때부터 조작이 되어 있는 경우와 주유소 지점에서 자체적으로 시행하는 조작으로 이루어진다. 전자는 주유소 지점의 책임이 아닌 중간 공급업자에 책임이며 후자는 주유소 지점에 책임이 있다. 본 포스팅에서 제시한 프로토타입은 후자의 경우만 예방하고 감독할 수 있다. 전자의 경우를 예방하는 방법은 글의 마지막 부분에서 다루도록 한다. 주유량 조작 문제는 명백하게 주유소 지점에 책임이 있다. 이러한 행위는 보통 계기판에 기름량을 산정하는 프로그램을 조작함으로써 이루어진다. 예를 들어, 어떤 소비자가 경유를 100L 가량 주유받는다고 할 때 소비자는 그에 상응하는 돈을 지불할 것인데 이때 참고할 수 있는 객관적 기준은 주유기에 표시되는 계기판 밖에는 없다. 100L라고 표시는 되지만 사실은 95L가 주유된 것은 아닌지 확인할 수 있는 방법이 현재로서는 존재하지 않는다. 따라서 본 제안에서는 이더리움 블록체인을 활용하여 주유소 지점내에서 이루어지는 불법적인 행위를 감독하고 예방할 수 있는 시스템을 제시한다. 본 시스템이 실제로 상용화된다면, 매년 발생하는 주유소 지점내의 불법적인 행위가 현저히 감소할 것으로 기대가 된다. 시스템의 요지는 주유소 내의 특정 데이터를 스마트 컨트랙트에 지속적으로 반영하여 불법적인 행위가 발생했을 때 바로 확인할 수 있으며 해당 행위가 영구적으로 블록체인에 기록되기 때문에 2차 피해를 예방하고 적절한 조치를 취할 수 있는 것이다. ## 3. 시스템 제안 ![system-overview](https://cdn.steemitimages.com/DQme6C24nVuyR4exGQFAF9wRPczm8ubickiuZCxxP7Yy9wb/image.png) ### 3.1 시스템 설계 시스템은 이더리움 합의엔진 중 Clique PoA(Proof of Authority)를 활용하며 다음과 같이 크게 두 가지 요소로 구성이 되어 있다. 정유사(SK 에너지 등) 노드와 가맹 주유소 노드로 구성되어 있으며, 아래 그림은 시스템의 개략적인 구성도이다. ![system-architecture](https://cdn.steemitimages.com/DQmU8EqqG81CC6JnL9KDJ94o6THSLMGQqwMTZpJxxqyXHH6/image.png) 정유사 노드에서는 가맹 주유소 노드들이 전송하는 트랜잭션들을 검증 후 데이터베이스 갱신하는 역할을 담당하고, 가맹 주유소 노드들은 보유하고 있는 탱크의 기름 변동량을 센서로 체크하여 읽어 온 값을 담은 트랜잭션을 발생시키는 역할을 담당한다. ### 3.1 주유소 노드 주유소 노드의 동작 프로세스를 설명하기 전, 먼저 몇 가지 전제조건을 제시한다. 이는 전국의 모든 주유소가 전부 동일한 형태로 존재하지 않기 때문이다. 시스템의 원활한 설계를 위해 주유소 노드를 다음과 같이 상정하였다. 제안에 예시로 사용되는 기름의 종류는 경유이다. ![fuel-station-node](https://cdn.steemitimages.com/DQmSKMC8qPzZgd1oJZaAsgS3VugzrqgpUwuoBLFjPDuen6P/image.png) #### 3.1.1 Tank(경유 탱크) * 주유소에는 하나의 경유 탱크가 존재한다. * 하나의 경유 탱크에 연결된 주유기는 3대로, 동 시간대에 총 3대의 차량에 주유가 가능하다. * 경유 탱크에는 기름의 변동량을 수시로 체크해주는 수위 센서, 가짜 경유인지 진짜 경유인지를 구별해주는 초음파 센서가 설치되어 있다. * 측정된 센서 값을 이더리움 네트워크로 전송 해주는 역할은 라즈베리파이(Rpi)가 수행하며 라즈베리 파이는 중간에 연결되어 있는 아두이노를 통해 센서값을 읽어온다. 중간에 아두이노를 둔 이유는, 향후 탱크의 개수가 많아질 때 라즈베리 파이를 늘리는 것이 아니라 아두이노만 늘리는 방식으로 설계할 수 있기 때문이다. 즉, 모든 탱크에서 측정되는 데이터는 라즈베리 파이 한 대가 이더리움 네트워크로 전송하게끔 되어 있다. * 탱크 내의 센서는 하나의 모듈로 구성되어 있다. 한 번 탱크 내에 들어가면 탈부착이 어렵게끔 되어 있으며 이는 센서의 물리적인 조작을 방지하기 위함이다. * 주유소의 데이터를 반영할 스마트 컨트랙트는 주유소 내 탱크별로 존재한다. 본 제안에서 상정한 모델에 따르면 하나의 주유소에는 하나의 경유 탱크가 존재하므로 주유소 지점당 컨트랙트가 존재한다. 아래의 코드는 실제 적용될 스마트컨트랙트의 생성자 함수이다. ``` // 생성자가 2개의 매개변수로 주유소 이름(gasStationName)과 탱크가 담고 있는 기름의 종류(gasTankType)을 취하고 있음을 확인할 수 있다. // 본 제안에서 기름의 종류는 경유(DIESEL)로 통일시킨다. constructor(string _gasStationName, string _gasTankType) public { bytes memory isSationNameEmpty = bytes(_gasStationName); bytes memory isGasTypeEmpty = bytes(_gasTankType); if (isSationNameEmpty.length == 0 || isGasTypeEmpty.length == 0) { revert(); } else { owner = msg.sender; gasStation = _gasStationName; gasTankType = _gasTankType; errorRange = 5; } } ``` #### 3.1.2 라즈베리파이3(Rpi3) * 라즈베리파이를 사용한 이유는 이더리움 네트워크에 단순히 트랜잭션만 전송 가능할 정도의 사양을 취하기 위함이다. 굳이 더 좋은 하드웨어를 사용할 필요가 없다. * 아두이노로부터 시리얼 통신으로 센서 값을 읽어들인다. * 읽어 들인 센서값을 이더리움 스마트컨트랙트에 기록하는 트랜잭션을 발생시킨다. #### 3.1.3 주유기(Fuel) * 탱크에는 3개의 연결된 주유기가 존재한다. 하나의 탱크에서 각 주유기를 통해 경유가 빠져나간다. * 경유가 빠져나가는 루트는 주유기가 유일하다. 특별한 상황(탱크를 청소해야 하거나, 영업을 위해 부족한 기름을 정유사로부터 공급받는 행위)을 제외하고는 오로지 주유기를 통해서만 경유가 빠져나가야 한다. 그 이외의 경우는 전부 비정상적인 상황이며 곧바로 적절한 조취를 취할 수 있어야 한다. * 주유기에는 기름이 빠져나간 양을 측정할 수 있는 모듈이 존재한다. 주유가 끝났을 때, 하나의 탱크에 연결된 3대의 주유기로부터 데이터를 받을 수 있다. 라즈베리파이는 탱크 뿐만 아니라 주유기와도 연결되어 있으므로 3대의 주유기로부터 데이터를 각각 가져와 총합한다. #### 이더리움 스마트 컨트랙트에 기록될 데이터의 종류 * 수위 센서로 측정한 탱크 내 경유의 잔여량 (높이 및 무게로 측정) * 초음파 센서로 측정한 순수 경유 식별값 * 3대의 측정한 주유량 (라즈베리파이가 합산하여 스마트 컨트랙트에 반영) * 위 데이터는 트랜잭션이 발생할 때마다 스마트 컨트랙트에 전송되고 모든 값을 다 가지고 있는 것이 아니라 같은 변수에 덮어씌어지는 방식으로 동작한다. ### 3.2 검증자 노드 (정유사 노드) #### 3.2.1 노드의 구성 본 제안에서 제시하는 권한 증명 기반 이더리움 프라이빗 네트워크는 2개의 부트 노드와 4개의 검증자 노드로 구성한다. 서버 권역(Availability Zone)은 2개로 구성하였고 각 서버 권역에는 2개의 검증자 노드가 존재한다. 부트 노드는 네트워크 내의 노드들이 서로 인식할 수 있게 해주는 역할을 하고, 검증자 노드들은 주유소 노드에서 발생한 트랜잭션을 블록체인에 반영해주는 역할을 한다. 만약 주유소 노드에서 보낸 트랜잭션에 이상이 감지되면 이벤트 로그가 위조 및 변조 불가능한 기록으로 남게 되고 그 내용을 쉽게 확인할 수 있다. 네트워크를 2개의 권역으로 구성한 것은 하나의 권역이 물리적으로 손상되어도 네트워크 유지에는 이상이 없게 하려는 의도이고 4개의 검증자 노드는 제안의 편의를 위해 설정한 것이다. 설계적인 관점에서 올바른 노드 구성에 대해 설명하기 위해 먼저 잘못된 예시를 제시한 후에 올바른 예시를 제시하려 한다. 2개의 권역 중 하나의 권역이 다운되었을 때도 네트워크가 유지되는 설계가 좋은 설계이고, 하나의 권역이 다운되었을 때 네트워크가 멈추는 건 잘못된 설계다. *잘못된 설계* ![wrong-architecture](https://cdn.steemitimages.com/DQmP1qkZ1zbgxQrBmgrARN7VsZtskVwjRo8RaKY6K2PGAnp/image.png) 위의 그림을 보면 4개의 검증자 노드가 모두 다 다르다는 것을 알 수 있다. 다름의 기준은 해당 노드의 계정 주소(EOA, Externally Owned Account)이다. 즉 모두 다른 주소를 가지고 있는 노드로 구성된 것이다. 이렇게 제각기 다른 노드들로 구성을 하면 Clique엔진의 검증자 노드 공식(`int(4 / 2) + 1`)에 따라 최소 3개의 노드가 작동 중일 때만 네트워크가 유지된다. 만약 3개 미만의 노드가 동작중이라면, 프라이빗 네트워크에는 더이상 블록이 생성되지 않고 주유소 노드들이 보내는 트랜잭션들이 기록되지 않는다. 즉, 4개의 노드가 모두 다른 계정으로 구성되어 있다면 이는 안전하지 않은 설계일 뿐더러, 권역을 2개로 나눈 의미 역시 무색해진다. *올바른 설계* ![right-architecture](https://cdn.steemitimages.com/DQmQfWXkXLnrPhYQB24qnyTGWcE4BzoqmbBVCJoLNaN1Ewa/image.png) 위의 그림을 보면 4개의 검증자 노드가 존재하는데, 색깔이 2개씩 동일하다는 점을 확인할 수 있을 것이다. 노드가 4개인 것은 맞지만 이 중 2개씩은 같은 EOA(Externally Owned Account)로 구성되어 있다. 이더리움 합의 엔진인 Clique의 검증자 노드 공식(`int(2 / N) + 1`)에서 N의 기준은 EOA이기 때문에 아래의 그림에서 물리적인 노드의 수는 4개지만 실제 검증자로 구분되는 노드는 2개이다. 따라서 최소 검증 노드 수는 2개가 되고 둘 중 하나의 권역이 다운되더라도 네트워크는 이상없이 동작할 수 있다.   ### 3.3 작동 매커니즘 실제 블록체인이 주유소에 접목되었을 때의 유즈케이스(Usecase)를 기술한다. 언제 트랜잭션이 발생하여 블록체인에 데이터가 기록되는지가 핵심이고 그 부분은 빨간색으로 기술되어 있다. 이해를 돕기 위해 관련 소스코드 또한 일부를 첨부했다. 먼저 정상적인 루틴에서의 동작을 설명하고 예외가 발생할 수 있는 상황과 그에 따른 대처를 다루었다. 정상적인 루틴 보다는 예외 상황을 어떻게 처리하는지가 신뢰 있는 주유소를 만드는데 있어 더 중요하기 때문에 예외처리 루틴은 매우 중요하고 또 정교하게 설계되어야 한다. #### 3.3.1 정상적인 루틴 1. 빈 탱크에 정유사로부터 경유를 공급받아 탱크의 내용물을 채운다. 2. 탱크에 경유 공급이 완료되었다면 이제 정상영업이 시작된다. 3. 주유가 필요한 차량이 주유소로 들어온다. 4. 주유기에서 주유가 시작된다. 3개가 동시에 주유될 수도 있고 1개의 주유기에서만 주유될 수도 있다. 5. 주유기 모듈(Fuel)은 3개의 주유기 모두 주유가 종료될 때까지 대기한다. 6. 3개의 주유기에서 모두 주유가 끝났을 때 다음 기술된 세가지 데이터가 연결된 라즈베리파이로 전송된다. 탱크의 수위와 탱크 내 경유의 식별 값을 아두이노가 시리얼 통신을 통해 라즈베리파이로 전송, 주유기 모듈이 탱크와 연결된 3개의 주유기에서 발생한 주유량을 총합하여 그 값을 라즈베리파이로 전송 7. 라즈베리파이는 주유기 모듈로부터 받은 총 주유량, 아두이노에서 전송 받은 탱크 내 경유 수위, 경우의 식별 값을 담은 트랜잭션을 발생시킨다. 8. 검증자 노드에서는 주유소 노드에서 발생된 트랜잭션들을 모아 블록을 생성하고 반영한다. *요약* 3개의 주유기 중 하나라도 주유를 시작할 때 루틴이 시작되며 3대의 주유기가 모두 주유 종료 상태가 되면 라즈베리파이는 블록체인에 관련 데이터를 전송한다. > 영업을 하지 않을 때는 약 5분마다 트랜잭션을 생성한다. #### 3.3.2 예외처리 루틴 예외가 발생하는 경우를 감지할 때는 주유기에서 발생한 주유량 값과 탱크 내 수위 센서로 경유의 양을 측정한 값으로 비교를 한다. 해당 값들만으로 예외 처리가 되지 않는 경우(3.2.3) 에는 경유 식별 값을 추가로 사용하여 경유의 위조 및 변조 여부를 확인한다. ##### 3.3.2.1 주유 전 측정한 탱크 내 경유 잔여량 != 주유량 + 주유 후 탱크 내 경유 잔여량 만약 주유가 끝난 후에 센서로 측정된 경유 탱크의 잔여 경유량 + 주유기에서 빠져나간 경유의 총량이 이전에 측정했던 탱크의 경유량과 다르다면 이는 탱크에 어떤 조작이 가해졌다는 것을 뜻한다. 예를 들어, 원래 100L의 경유가 존재했고 20L를 주유했다면, 남아 있는 경유는 80L가 될 것 이다. 그러나, 예상한 값이 아니라면 탱크에 이상이 발생한것이다. 수위를 측정하는 센서가 언제나 정확한 값을 산출하는 것은 아니기 때문에 오차범위가 존재하고 예외 상황이란 건 허용할 수 있는 오차범위를 넘어설 때를 의미한다. 위와 같은 경우 아래의 두 가지 구체적인 상항을 생각해볼 수 있다. ##### 3.3.2.2 주유 전 측정한 탱크 내 경유 잔여량 > 주유량 + 주유 후 탱크 내 경유 잔여량 주유 전 측정한 탱크 내 경유 잔여량이 100L였고, 주유기에서 빠져나간 주유량이 20L인 상황에서 주유 후 탱크 내 경유 잔여량이 70L인 상황을 생각해보자. 원래라면 80L가 있어야했지만 10L가 부족한 상황이다. 정상적으로 기름이 빠져나가는 건 주유기를 통해서만 가능하므로 이와 같은 상황은 주유기 이외의 다른 방법으로 경유가 탱크에서 빠져나간 것으로 합리적 추론이 가능하다. 따라서 이를 블록체인 네트워크에 기록할 필요가 있다. 관련 스마트 컨트랙트에서 이벤트 로그 기능을 통해 "Tank has lower amount of gas. Possible abnormal gas extraction occurred” 메시지를 블록체인에 기록하여 예외 상황을 기록해 놓는다. ##### 3.3.2.3 주유 전 측정한 탱크 내 경유 잔여량 < 주유량 + 주유 후 탱크 내 경유 잔여량 주유 전 측정한 탱크 내 경유 잔여량이 100L였고, 주유기에서 빠져나간 주유량이 20L인 상황에서 주유 후 탱크 내 경유 잔여량이 90L인 상황을 생각해보자. 원래라면 80L가 있어야했지만 10L가 초과된 상황이다. 있어야할 경유의 양보다 더 많아진 경우이므로 외부에서 경유가 유입되었다는 것으로 판단할 수 있다. 순수하게 경유를 유입한 것인지 아니면 다른 불순물을 섞었는지 판단하기 위하여 이러한 경우 경유 식별 값을 추가로 포함시켜서 트랜잭션을 발생시킨다. 정상적인 상황에 대한 로직 그리고 예외적인 상황인3.3.2.2와 3.3.2.3에 대한 예외처리 로직을 구현한 스마트 컨트랙트(솔리디티) 소스코드는 아래의 코드와 같다. ``` // beforeFuelAmount: 주유 전 측정한 탱크 내 경유 잔여량 // _filledOutAmount: 주유량 // _sensoredTankAmount: 주유 후 탱크 내 경유 잔여량 // _sensoredGasDensity: 주유 후 경유 식별값 function checkGasTankAmount(uint256 _filledOutAmount, uint256 _sensoredTankAmount, uint256 _sensoredGasDensity) public notFueling notCleaning { uint256 inputFuelAmount = _sensoredTankAmount.add(_filledOutAmount); // 오차범위를 반영한 최대 허용치 uint256 maxErrorAmount = beforeFuelAmount.add(errorRange); // 오차범위를 반영한 최소 허용치 uint256 minErrorAmount = beforeFuelAmount.sub(errorRange); // 정상적인 루틴: 오차범위 내에서 경유 변동량에 이상이 없는 경우 if(minErrorAmount<= inputFuelAmount && inputFuelAmount <= maxErrorAmount){ //Allows the error range amount. beforeFuelAmount = _sensoredTankAmount; emit gasTankCheckedEvent(gasStation, gasTankType, "Tank has correct amount of gas"); } // 예외 상황 3.3.2.2: 주유 전 측정한 탱크 내 경유 잔여량 > 주유량 + 주유 후 탱크 내 경유 잔여량 // 경유가 정상적인 방법 이외에 유출된 경우가 발생한 상황이다. else if(inputFuelAmount < minErrorAmount){ //The tank has less fuel than it should uint256 minAbnormalAmount = beforeFuelAmount.sub( _sensoredTankAmount); beforeFuelAmount = _sensoredTankAmount; // 이벤트 로그를 블록체인에 기록 emit abnormalTankCheckedEvent(gasStation, gasTankType, "Tank has lower amount of gas. Possible abnormal gas extraction occured", minAbnormalAmount ); } // 예외 상황 3.3.2.3: 주유 전 측정한 탱크 내 경유 잔여량 < 주유량 + 주유 후 탱크 내 경유 잔여량 // 경유가 원래 있어야 할 정량보다 많은 경우가 발생한 상황이다. else { //The tank has more fuel than it should. uint256 maxAbnormalAmount = _sensoredTankAmount.sub(beforeFuelAmount); beforeFuelAmount = _sensoredTankAmount; // 이벤트 로그를 블록체인에 기록 // 불순물이 섞였을 가능성을 생각하여 주유 후 경유 식별값인 _sensoredGasDensity 또한 이벤트 로그에 반영해줘야 한다. emit abnormalTankCheckedEvent(gasStation, gasTankType, "Tank has higher amount of gas. Possible abnormal liquid mixing occured", maxAbnormalAmount, _sensoredGasDensity ); } } ``` 예외 처리가 발생했을 때는 이더리움 블록체인에 이벤트 로그가 기록된다. 이로써 각 주유소 지점들을 관리하는 정유사는 어떤 주유소에서 어떤 문제가 발생했는지 파악하고 조치를 취할 수 있다. ##### 3.3.2.4 주유를 하지 않을 때 5분 전 경유 잔여량 != 5분 뒤 경유 잔여량 (오차범위를 감안했을 때) 주유기를 통해 기름이 빠져나가지 안핬는데, 5분 전 경유 잔여량과 5분 뒤 경유 잔여량이 다른 것은 말이 안된다. 주유소 지점 탱크에 어떤 조작이 가해졌음을 확인할 수 있다. 아래의 코드에서 보는 것과 같이 라즈베리파이에서 5분 간격으로 측정을 진행한다. 측정한 값은 곧바로 스마트 컨트랙트로 전송된다. ``` function refueling(m){ _timerCount[m.machine] = 0; _timer[m.machine] = setInterval(function(){ let thisMachine = _gasMachine["machine" + m.machine]; _timerCount[m.machine]++; thisMachine.useLiter = thisMachine.useLiter + 1; let percent = _timerCount[m.machine]/thisMachine.nowRefuelingAmout; ... if(_timerCount[m.machine]===thisMachine.nowRefuelingAmout){ clearInterval(_timer[m.machine]); ... //node send const url = "http://127.0.0.1:3000/usedgasamount/"+sum; fetch(url, { mode: 'no-cors', method: 'get' }) .then(function(response) { response.text().then(function(text) { return 0; }); }) .catch(function(error) { console.log(error); }); } } }, 300000); ``` #### 3.3.3 허용되는 예외 기름의 변동측정량이 비정상적이지만 이 중에는 분명 허용되는 예외상황도 존재한다. 허용되는 예외상황들은 다음과 같다. ##### 3.3.3.1 빈 탱크에 정유사로부터 경유를 공급 받을 때 탱크 내 경유 총량이 갑작스레 증가하는 상황이지만, 정유사로부터 경유를 공급받는 것이니 문제가 발생하는 상황은 아니다. 경유 공급의 시작과 종료 시점만 정확하게 기록되면 되는 것이다. 구현한 스마트 컨트랙트 소스 코드는 아래와 같다. ``` function startFueling(uint256 _fillingFuelAmount) external onlyOwner { Fueling = true; newFuelAmount = _fillingFuelAmount; emit FuelingEvent(gasStation, gasTankType, _fillingFuelAmount, "Filling the gas tank"); } function stopFueling(uint256 _sensoredGasDensity) external onlyOwner { Fueling = false; beforeFuelAmount = beforeFuelAmount.add(newFuelAmount); newFuelAmount = 0; emit FuelingEvent(gasStation, gasTankType, beforeFuelAmount, _sensoredGasDensity, "Finished filling the gas tank"); } ``` 정유사로부터 경유 공급이 시작될 때는 `startFueling` 함수가 호출되고 주유소 지점(`gasStation`), 탱크 정보(`gasTankType`), 공급량(`_fillingFuelAmount`)에 대한 정보가 이벤트 로그로 블록체인에 기록된다. 주유 공급이 끝나면 탱크 내 경유의 식별 값을 매개변수로 취하는 `stopFueling` 함수가 호출된다. 이로써 공급이 완료된 후에 위조 및 변조 되지 않은 경유가 들어왔는지 여부를 확인할 수 있다. ##### 3.3.3.2 탱크를 청소하기 위해 경유를 모두 추출하거나 청소 후 다시 채워 넣을 때 탱크 내 경유 총량이 갑작스레 감소하는 상황이지만, 청소를 위해 경유를 빼는 것이니 문제가 발생하는 상황은 아니다. 관련된 스마트 컨트랙트 코드는 아래와 같다. ``` function startCleaning(uint256 _sensoredGasDensity) external onlyOwner { Emptying = true; EmptyingAmount = beforeFuelAmount; beforeFuelAmount = 0; emit CleaningEvent(gasStation, gasTankType, EmptyingAmount, _sensoredGasDensity, "Started cleaning the tank"); } // 청소 다하고 기름 채워넣었을 때 function stopCleaning(uint256 _sensoredTankAmount, uint256 _sensoredGasDensity) external onlyOwner { //When cleaning is over and the fuel has been recharged. Emptying = false; uint256 maxErrorAmount = EmptyingAmount.add(errorRange); uint256 minErrorAmount = EmptyingAmount.sub(errorRange); if(minErrorAmount<= _sensoredTankAmount && _sensoredTankAmount <= maxErrorAmount){ beforeFuelAmount = EmptyingAmount; } emit CleaningEvent(gasStation, gasTankType, EmptyingAmount, _sensoredGasDensity, "Finished cleaning the tank"); } ``` 허용되는 예외 상황들이 발생했을 때는 이벤트 로그가 블록체인에 기록된다. 허용되는 예외 상황은 계약을 배포한 정유사 본사(SK에너지)에서 이루어지는데 이때 무분별한 사용과 소비자를 기만할 목적으로 사용될 수 없도록 전에 있던 데이터 양을 고스란히 기록하여 이벤트 로그를 발생시킨다. 이로써 해당 메서드를 호출할 때 정유사로서는 신중을 기할 수밖에 없으며 혹여나 남발했을 경우 이더리움 블록체인에 영구적으로 남기 때문에 소비자들이 직접 확인할 수 있을 것이다. ## 4. 프로토타입 본 제안을 구체화해보고자 탱크 내의 센서의 값을 스마트 컨트랙트에 반영하는 프로토타입을 제작하였다. 시스템의 전반적인 스펙은 다음과 같다. ![prototype-overview](https://cdn.steemitimages.com/DQmNUcea65SPfjdah4ca7fofiA1BiRfEN6FfEpZTeQ621Lk/image.png) 다만, 프로토타입에서 사용되는 센서는 수위센서뿐이다. 초음파로 경유를 식별하는 센서의 경우 아직 연구중이며 프로토타입에 적합한 유량 식별 센서를 찾기 어려웠기 때문이다. 본 프로토타입의 한계는 경유 탱크의 변동량만 이더리움 블록체인에 기록되게끔 구현되어 있다는 점이다. 또한 구현의 편의성을 위해 Clique PoA(권한 증명) 엔진이 아닌 Ethash PoW(작업 증명) 엔진을 채택했다. ### 4.1 프로토타입 설계 전체 설계도를 미리 살펴보면 아래의 그림과 같다. 빠른 구현을 위해 하나의 랩톱에서 작업 증명 방식의 프라이빗 블록 체인을 구축했다. ![prototype-architecture](https://cdn.steemitimages.com/DQmSuRNMq5yxLgyeNSn9nJ4DHEMx5nX4WuRaJP2JznTkRjq/image.png) #### 4.2 주유소 노드 프로토타입의 주유소 노드에 사용된 구성은 아래의 그림과 같다. 본 시스템 제안에서 제시했던 구성과의 차이점은 빨간 글씨로 표시되어 있다. ![gas-station-node](https://cdn.steemitimages.com/DQmSWA7aT7Qrm55yeHEL1tmeWT4JEuEDDfLz9zspLV6DR8G/image.png) ##### 4.2.1 물통(Bottle) * 주유소에 존재하는 탱크의 역할을 담당하는 물통이다. * 물통에는 물의 높이를 측정해주는 수위 센서가 존재한다. * 수위 센서는 아두이노로 측정한 값을 보내고 아두이노는 시리얼 통신으로 라즈베리파이에 값을 전송한다. > 실제 탱크 대신 물통을 사용하였으며 센서는 수위 센서 하나만 사용하였다. 아두이노의 회로 구성과 코드는 다음과 같다. ![arduino](https://cdn.steemitimages.com/DQmSm41avcPcGgFC8nYyKUjmR9QMUaxZBgdUyQdEUHvEmfm/image.png) 1. 수위 센서로 읽어온 값은 A0핀 (노란색 선)을 통해 받아온다. 2. 시리얼 통신을 사용하여 읽어온 센서 값을 3초 간격으로 라즈베리파이에 전송한다. ``` const int WATER_SENSOR_PIN0 = A0; void setup() { Serial.begin(9600); } void loop() { int sensorVal0 = analogRead(WATER_SOURCE_PIN0); Serial.print("0 sensor value = "); serial.println(sensorval0); delay(3000); } ``` #### 4.2.2 주유기(Web) * 실제 주유소 노드의 탱크에 연결된 3대의 주유기를 웹으로 구현하였다. * 아래의 그림과 같이 3대의 주유기가 존재하고 각각 `START`, END` 버튼이 존재한다. `START` 버튼을 클릭함으로써 주유가 시작되고 시간이 지나서 종료가 되거나 직접 `END` 버튼을 눌러 종료할 수 있다. ![fuel-machines](https://cdn.steemitimages.com/DQmZhYtBBLmDWzQmY4Y5Mcxd91z8hzLYQAjsubvPTujyuXE/image.png) * 금액 혹은 리터를 입력한 뒤 `START` 버튼을 누르면 주유가 시작되고 파란색 진행 막대가 채워지기 시작한다. * 금액을 입력했을 때는 좌측 상단의 금액 환산표에 따라 리터가 결정된다. 1리터당 1초로 환산하여 주유 시간도 정해진다. * 막대가 다 채워지면 (정해진 시간이 지나면) 주유가 종료된다. 주유 중에 END 버튼을 눌러도 주유가 종료된다. * 웹 페이지의 자바스크립트 소스코드에는 `Web3` 라이브러리를 활용하여 이더리움 네트워크에 트랜잭션을 발생시킬 수 있게끔 되어 있다. #### 4.2.3 노드(Node) * 아두이노로부터 전송 받은 센서 값을 스마트컨트랙트에 반영하는 트랜잭션을 발생시킨다. * 라즈베리파이에서 `Web3` 모듈을 사용한 `NodeJs` 코드를 동작시킴으로써 작동한다. * 주유기가 구현되어 있는 웹 페이지를 호스팅한다. ### 4.3 검증자 노드 ![validator](https://cdn.steemitimages.com/DQmVsDSF4rUAMNDxf24gpjsX8AeYQgmP59wUYEPhDt9uouJ/image.png) 프로토타입에서의 검증자 노드 구성은 모두 하나의 컴퓨터에서 이루어진다. 위 그림에 표현된 노드들은 각각 하나의 geth 프로세스를 의미한다. #### 4.3.1 채굴 노드 * 채굴(Mining)을 담당하는 geth 프로세스다. * 로컬환경에서 발생하는 트랜잭션들을 모아 블록을 생성하고 이더리움 블록체인에 반영한다. #### 4.3.2 배포 노드 * 탱크(프로토타입에서는 물통)와 관련된 스마트 컨트랙트를 배포하고 관리하는 geth 프로세스다. * 탱크에서 발생하는 센서 값들을 사용하여 트랜잭션을 발생시킨다. #### 4.3.3 예비 노드 * 채굴 노드와 배포 노드 둘 중 하나의 노드가 제 기능을 못하게 되었을 때 언제든지 대체할 수 있는 노드를 의미한다. * 프로토타입에서의 합의 알고리즘은 작업 증명이기 때문에 하나의 네트워크에 속해 있기만 하다면 언제든지 채굴 노드 혹은 배포 노드를 대체할 수 있다. ### 4.3 프로토타입 동작 설명 #### 4.3.1 주유 시작 ![process](https://cdn.steemitimages.com/DQmeCZnMKKGK4oH8YsNn5jipC9qEuXYNvwam1nXuU2g6xjb/image.png) 1. 위 그림의 각 주유기에 원하는 주유량을 입력한 뒤 `START`버튼을 눌러 주유를 시작한다. 2. 진행 막대가 다 채워지거나 3대의 주유기에 `END` 버튼이 눌렸을 때 주유가 종료된다. #### 4.3.2 주유 종료 1. `NodeJs`로 작성한 서버 코드에서는 세 대의 주유기에서 모두 주유가 끝났는지 확인하고 3대의 양을 총합한다. 2. 모두 끝나고 합산이 완료되었다면 이더리움 네트워크에 반영하는 모듈로 합산량을 전송한다. 구현된 코드는 아래와 같다. ``` let sum = 0, state = 0; for( var key in _gasMachine ) { sum = sum +_gasMachine[key].useLiter; state = state+_gasMachine[key].state; } if(state){ console.log('progress'); }else{ for( var key in _gasMachine ) { _gasMachine[key].useLiter = 0; } console.log('total refueling : '+sum); //node send const url = "http://127.0.0.1:3000/usedgasamount/"+sum; fetch(url, { mode: 'no-cors', method: 'get' }) .then(function(response) { response.text().then(function(text) { return 0; }); }) ``` #### 4.3.3 전송된 주유량과 센서 데이터 값을 스마트 컨트랙트에 반영 1. 배포되어 있는 스마트 컨트랙트의 함수를 호출한다. 주유량과 센서 데이터 값을 매개변수로 전달한다. 2. 함수를 호추함과 동시에 트랜잭션이 발생한다. 3. 발생된 트랜잭션은 채굴 노드에서 블록체인에 반영한다. 코드는 아래와 같다. `NodeJs` 와 `Web3` 라이브러리를 사용한 코드다. ``` server.route({ method:'GET', path:'/usedgasamount/{value}', handler:function(request,h) { console.log("Is in the server.route"); var cntSerial = 0; var extractedGasAmount = request.params.value; console.log(extractedGasAmount); parser.on('data', function(data) { var length = data.length; var sensor_value = data.slice(8, length); var waterHeight = parseInt(sensor_value); var t0 = "0"; if (cntSerial++ === 0) { if(data[0] === t0) { myContract.methods.checkGasTankAmount(extractedGasAmount,waterHeight).send({from: rpiEoa0}) else { console.log('error'); console.log('data: ' + data); console.log('data[0] ' + data[0]); } } }); return 0; } }); ``` 호출한 스마트 컨트랙트의 함수 코드는 아래와 같다. *3.3.2 예외처리 루틴*에서 설명된 예외 상황 중 일부가 구현되어 있다. 초음파로 경유를 식별하는 식별 값이 없다는 점 외에는 *3.3.2 예외처리 루틴*에서 제시 되었던 로직과 동일하다. ``` // beforeFuelAmount: 주유 전 측정한 탱크 내 경유 잔여량 // _filledOutAmount: 주유량 // _sensoredTankAmount: 주유 후 탱크 내 경유 잔여량 function checkGasTankAmount(uint256 _filledOutAmount, uint256 _sensoredTankAmount) public notFueling notCleaning { uint256 inputFuelAmount = _sensoredTankAmount.add(_filledOutAmount); // 오차범위를 반영한 최대 허용치 uint256 maxErrorAmount = beforeFuelAmount.add(errorRange); // 오차범위를 반영한 최소 허용치 uint256 minErrorAmount = beforeFuelAmount.sub(errorRange); // 정상적인 루틴: 오차범위 내에서 경유 변동량에 이상이 없는 경우 if(minErrorAmount<= inputFuelAmount && inputFuelAmount <= maxErrorAmount){ //Allows the error range amount. beforeFuelAmount = _sensoredTankAmount; emit gasTankCheckedEvent(gasStation, gasTankType, "Tank has correct amount of gas"); } // 예외 상황 3.2.2: 주유 전 측정한 탱크 내 경유 잔여량 > 주유량 + 주유 후 탱크 내 경유 잔여량 // 경유가 정상적인 방법 이외에 유출된 경우가 발생한 상황이다. else if(inputFuelAmount < minErrorAmount){ //The tank has less fuel than it should uint256 minAbnormalAmount = beforeFuelAmount.sub( _sensoredTankAmount); beforeFuelAmount = _sensoredTankAmount; // 이벤트 로그를 블록체인에 기록 emit abnormalTankCheckedEvent(gasStation, gasTankType, "Tank has lower amount of gas. Possible abnormal gas extraction occured", minAbnormalAmount ); } // 예외 상황 3.2.3: 주유 전 측정한 탱크 내 경유 잔여량 < 주유량 + 주유 후 탱크 내 경유 잔여량 // 경유가 원래 있어야 할 정량보다 많은 경우가 발생한 상황이다. else { //The tank has more fuel than it should. uint256 maxAbnormalAmount = _sensoredTankAmount.sub(beforeFuelAmount); beforeFuelAmount = _sensoredTankAmount; // 이벤트 로그를 블록체인에 기록 emit abnormalTankCheckedEvent(gasStation, gasTankType, "Tank has higher amount of gas. Possible abnormal liquid mixing occured", maxAbnormalAmount ); } } ``` 비정상적인 상황이 인지되면 이더리움 블록체인에 Event 로그를 기록한다. 이벤트는 아래의 코드에 나와 있는 양식으로 블록체인에 기록된다. ``` {address: "0xe5006916ad70ca9c440ee74860c3853674bf0e88", blockNumber: 625, transactionHash: "0xf3f25b509a9fbb6b8d2dbc7a37ccdb7960890c952d99d031742d46c65dee6eb7", transactionIndex: 0, blockHash: "0x1fd9b564e1ad9373bc711f5304dbd272e6a366a85c7904285ef863ec2407a089", …} 1. address:"0xe5006916ad70ca9c440ee74860c3853674bf0e88" 2. args:{_gasStationName: "SK_ENERGY", _gasTankType: "DIESEL", _fillingFuelAmount: BigNumber, _statusMessage: "Filling the gas tank"} 3. blockHash:"0x1fd9b564e1ad9373bc711f5304dbd272e6a366a85c7904285ef863ec2407a089" 4. blockNumber:625 5. event:"FuelingEvent" 6. logIndex:0 7. removed:false 8. transactionHash:"0xf3f25b509a9fbb6b8d2dbc7a37ccdb7960890c952d99d031742d46c65dee6eb7" 9. transactionIndex:0 10. __proto__:Object ``` 2번 필드를 살펴보면, “SK_ENERGY” 주유소의 “DIESEL”(경유) 탱크에 “Filling the gas tank” 이벤트가 발생하였음을 확인할 수 있다. 그 아래 필드는 기록되어 있는 블록 번호, 블록 해시, 트랜잭션 해시 등의 정보가 기입되어 있고 결과값으로 나온 정보 중 필요한 내용을 파싱하여 출력해보면 아래와 같다. * 허용되는 예외 상황(*정유사로부터 기름을 공급받을 때*)에 대한 이벤트 로그 ![exception-log-1](https://cdn.steemitimages.com/DQmdSBHqafsD6WNSPb1P7KQREjRKk78Kvf8QaPJCkYYHK43/image.png) * *예외 상황 3.3.2.2*에 해당하는 이벤트 로그 ![exception-log-2](https://cdn.steemitimages.com/DQmYbupHfiVkBLvX2DfjZHYaNoAiPifPfdDkFozoBsKWDAh/image.png) * *예외 상황 3.3.2.3*에 해당하는 이벤트 로그 ![exception-log-3](https://cdn.steemitimages.com/DQmPVC28GfjpSFwksaQNRVGpFcBqvnhynjpcfN2wRiQwpFC/image.png) ### 4.4 프로토타입의 한계 및 개선 방안 1. 경유의 성분 분석을 할 수 있는 초음파 식별 센서를 적용하지 못했다. 식별 센서를 적용하지 못할 경우 다음과 같은 불상사가 발생할 수 있다. 기름 탱크를 청소하기 위해 경유를 전부 뺐다가 청소 후 다시 경유를 채울 때 불순물을 섞어서 채우는 것이 가능하다. 즉, 경유 식별 센서가 없다면 *탱크를 완전히 비우고 채울 때 조작이 가능*하다. 2. 부실한 외부 접근 제한 운영자 geth 노드의 정보 (포트 번호, eNode 정보 등)가 외부로 유출 되었을 시 데이터 조작이 가능하다. PoW 체인이기 때문에 더 많은 블록을 빠른 시간 안에 전파하면 데이터가 갈아 엎어진다. 3. 센서에서 측정된 데이터 값을 토대로 판단하는 시스템이기 대문에 센서 자체가 조작되는 것에 대한 보안은 되어 있지 않다. 4. 측정에 사용되는 방법은 단순히 높이를 측정하는 것이므로 경유가 출렁이거나 탱크 자체가 움직이는 상황 등이 발생하면 정확한 측정이 어렵다. 또한 기름의 특성상 온도에 따라 부피가 약간씩 달라지기 때문에 높이만으로 측정하는 방법에는 한계가 있다. *위의 한계점들에 대한 개선 방안은 아래와 같다.* 1. 모듈화가 가능한 경유 식별 센서에 대한 연구는 게속 진행중이다. 초음파 뿐만 아니라 [나노기술기반 가짜 석유 식별센서 개발 및 상용화](http://www.ndsl.kr/ndsl/search/detail/report/reportSearchResultDetail.do?cn=TRKO201600002359)를 주제로 한 연구 또한 진행중이다. 직접 개발하거나 연구되고 있는 기술들을 종합하여 센서를 개발하고 향후 탱크에 적용하는 방향으로 문제를 개선할 수 있다. 2. 외부로부터의 허가되지 않은 접근을 제한하기 위해 정유사만의 VPC망 안에 프라이빗 네트워크를 구축함으로써 허가 받지 않은 접근을 방지할 수 있다. (사실 이미 SK에서 자체적으로 운영하고 있는 네트워크가 있다고 하니 이 부분은 크게 걱정하지 않아도 될 것 같다.) 3. 한 번 탱크에 부착된 센서 및 관련 모듈들에 외부 조작을 가할 수 없게끔 결합도가 강하게 설계하는 방법이 있다. 그렇게 하면 센서 자체를 조작해서 탈부착하거나 센서를 무력화시키는 행위 등에 대한 예방이 가능하다. 만약 조작을 하더라도 조작한 기록까지 블록체인에 기록이 되므로 정유사 본사에서 적절한 조치를 취할 수 있다. 즉 감시 및 모니터링은 충분히 이루어질 수 있다. 4. 높이 센서 뿐만 아니라 무게 센서를 함께 차용하는 방안이 있다. 경유가 출렁거려 높이가 달라지더라도 무게는 같기 때문에 더 정확한 측정이 가능하다. ## 5. 결론 구상한 서비스를 현실에 적용하기에는 아직까지 개선점이 많이 필요한 아이디어지만, 지속적인 연구를 통해 서비스를 개선해간다면 분명 깨끗한 유류 관리 시스템을 만들어낼 수 있을 것이다. 소비자들이 피해받지 않고 믿고 쓸 수 있는 주유소 유통 공급망 시스템이 구축되었으면 하는 바람이다. ## 6. 보너스: 토큰 이코노미 현재 주유를 하면 자동으로 적립이 되는 시스템이 운영되고 있다. 그러나 블록체인 시스템이 도입되면 다음과 같은 매커니즘도 생각해볼 수 있다. 1. 사용자들이 주유를 받으면 영수증에 사용자가 주유한 내용이 반영되어 있는 트랜잭션의 해시가 QR코드가 적혀있다. 2. 사용자는 해당 QR코드를 인식하면 사용자가 주유한 건에 대한 트랜잭션이 정상적으로 처리가 되었는지 확인할 수 있다. 3. 이상현상이 발생하지 않았음을 확인한 사용자는 안심할 수 있으며 현재 이 블록체인 시스템이 정상운영 되는지를 직접 확인한 검증자가 된다. 4. 검증을 직접한 대가로 정유사에서는 포인트를 제공해준다. 정유사는 위와 같은 서비스를 제공했을 때, 소비자로부터 신뢰를 받을 수 있으며 광고 및 입소문 효과까지 누릴 수 있다. 소비자는 주유가 제대로 되었는지 확인하고 안심할 수 있으며 포인트까지 적립받으니 이는 소비자 및 정유사 모두에게 이득이 되는 WIN-WIN 전략이라 할 수 있다.
json metadata{"tags":["ethereum","smartcontract","blockchain","iot"],"image":["https://cdn.steemitimages.com/DQme6C24nVuyR4exGQFAF9wRPczm8ubickiuZCxxP7Yy9wb/image.png","https://cdn.steemitimages.com/DQmU8EqqG81CC6JnL9KDJ94o6THSLMGQqwMTZpJxxqyXHH6/image.png","https://cdn.steemitimages.com/DQmSKMC8qPzZgd1oJZaAsgS3VugzrqgpUwuoBLFjPDuen6P/image.png","https://cdn.steemitimages.com/DQmP1qkZ1zbgxQrBmgrARN7VsZtskVwjRo8RaKY6K2PGAnp/image.png","https://cdn.steemitimages.com/DQmQfWXkXLnrPhYQB24qnyTGWcE4BzoqmbBVCJoLNaN1Ewa/image.png","https://cdn.steemitimages.com/DQmNUcea65SPfjdah4ca7fofiA1BiRfEN6FfEpZTeQ621Lk/image.png","https://cdn.steemitimages.com/DQmSuRNMq5yxLgyeNSn9nJ4DHEMx5nX4WuRaJP2JznTkRjq/image.png","https://cdn.steemitimages.com/DQmSWA7aT7Qrm55yeHEL1tmeWT4JEuEDDfLz9zspLV6DR8G/image.png","https://cdn.steemitimages.com/DQmSm41avcPcGgFC8nYyKUjmR9QMUaxZBgdUyQdEUHvEmfm/image.png","https://cdn.steemitimages.com/DQmZhYtBBLmDWzQmY4Y5Mcxd91z8hzLYQAjsubvPTujyuXE/image.png","https://cdn.steemitimages.com/DQmVsDSF4rUAMNDxf24gpjsX8AeYQgmP59wUYEPhDt9uouJ/image.png","https://cdn.steemitimages.com/DQmeCZnMKKGK4oH8YsNn5jipC9qEuXYNvwam1nXuU2g6xjb/image.png","https://cdn.steemitimages.com/DQmdSBHqafsD6WNSPb1P7KQREjRKk78Kvf8QaPJCkYYHK43/image.png","https://cdn.steemitimages.com/DQmYbupHfiVkBLvX2DfjZHYaNoAiPifPfdDkFozoBsKWDAh/image.png","https://cdn.steemitimages.com/DQmPVC28GfjpSFwksaQNRVGpFcBqvnhynjpcfN2wRiQwpFC/image.png"],"links":["https://github.com/dlgusdn616","https://medium.com/@dlgusdn616","https://github.com/heuristicwave","https://medium.com/@heuristicwave","https://github.com/Bookstore3","http://www.ndsl.kr/ndsl/search/detail/report/reportSearchResultDetail.do?cn=TRKO201600002359"],"app":"steemit/0.1","format":"markdown"}
Transaction InfoBlock #26393688/Trx 81b11ee6440297a1a44b402d888db4d8d9be3a12
View Raw JSON Data
{
  "trx_id": "81b11ee6440297a1a44b402d888db4d8d9be3a12",
  "block": 26393688,
  "trx_in_block": 21,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-09-30T09:20:54",
  "op": [
    "comment",
    {
      "parent_author": "",
      "parent_permlink": "ethereum",
      "author": "dlgusdn616",
      "permlink": "iot",
      "title": "이더리움을 활용한 IoT 프로젝트 제안 및 프로토타입 구현",
      "body": "# 이더리움 스마트컨트랙트를 활용한 신뢰받는 주유소 시스템 구축\n## 1. 이 글을 읽기 전에\n본 포스팅은 국가암호공모전 및 SK블록체인 해커톤, 한성대학교 공학경진대회에 출품하였던 `이더리움 스마트 컨트랙트를 활용한  신뢰받는 주유소 시스템` 에 대해 다룹니다. 포스팅의 타겟은 이미 블록체인과 이더리움에 대해 지식이 있고 직접 활용해본 혹은 활용할 예정인 분들입니다. \"블록체인을 활용하면 현실 세계의 어떤 문제들을 해결할 수 있을까?\"를 고민하는 분들께 도움이 되었으면 합니다.\n\n본 포스팅은 먼저 *이상적인 시스템의 구성에 대해 설명하는 파트* 그리고 그 중 일부를 구현한 *프로토타입에 대해 설명하는 파트* 이렇게 2개의 대분류로 이루어져 있습니다. 본 포스팅에서 예시로 드는 정유사는 `SK에너지`로 설정하였습니다. (`SK에너지`로 설정한 건 단순히 해커톤을 주최한 그룹이라는 점 때문입니다...)\n\n본 작품의 저자는 이현우, 임지훈, 최승주이며 각 저자의 블로그 및 깃허브 링크는 아래와 같습니다. 혹시 연락을 주실 일이 있다면 아래의 경로를 통해 주시면 감사하겠습니다.\n* 이현우\nGithub: https://github.com/dlgusdn616\nMedium: https://medium.com/@dlgusdn616\nEmail: [email protected]\nRole: Geth(go-ethereum) 노드 구성 및 운영, 네트워크 및 환경 구축\n* 임지훈\nGithub: https://github.com/heuristicwave\nMedium: https://medium.com/@heuristicwave\nEmail: [email protected]\nRole: Node js 백엔드 및 프론트엔드 설계\n* 최승주\nGithub: https://github.com/Bookstore3\n\n## 2. 개요\n오늘날 주유소를 이용하는 소비자들이 가짜 석유 및 조작된 주유량으로 금전적 피해를 보는 사례가 다수 발생하고 있다. 가짜 석유 문제는 석유의 유통 과정에서 각 주유소 지점에 기름이 공급될 때부터 조작이 되어 있는 경우와 주유소 지점에서 자체적으로 시행하는 조작으로 이루어진다.\n\n전자는 주유소 지점의 책임이 아닌 중간 공급업자에 책임이며 후자는 주유소 지점에 책임이 있다. 본 포스팅에서 제시한 프로토타입은 후자의 경우만 예방하고 감독할 수 있다. 전자의 경우를 예방하는 방법은 글의 마지막 부분에서 다루도록 한다.\n\n주유량 조작 문제는 명백하게 주유소 지점에 책임이 있다. 이러한 행위는 보통 계기판에 기름량을 산정하는 프로그램을 조작함으로써 이루어진다. 예를 들어, 어떤 소비자가 경유를 100L 가량 주유받는다고 할 때 소비자는 그에 상응하는 돈을 지불할 것인데 이때 참고할 수 있는 객관적 기준은 주유기에 표시되는 계기판 밖에는 없다. 100L라고 표시는 되지만 사실은 95L가 주유된 것은 아닌지 확인할 수 있는 방법이 현재로서는 존재하지 않는다.\n\n따라서 본 제안에서는 이더리움 블록체인을 활용하여 주유소 지점내에서 이루어지는 불법적인 행위를 감독하고 예방할 수 있는 시스템을 제시한다. 본 시스템이 실제로 상용화된다면, 매년 발생하는 주유소 지점내의 불법적인 행위가 현저히 감소할 것으로 기대가 된다.\n\n시스템의 요지는 주유소 내의 특정 데이터를 스마트 컨트랙트에 지속적으로 반영하여 불법적인 행위가 발생했을 때 바로 확인할 수 있으며 해당 행위가 영구적으로 블록체인에 기록되기 때문에 2차 피해를 예방하고 적절한 조치를 취할 수 있는 것이다.\n\n## 3. 시스템 제안\n![system-overview](https://cdn.steemitimages.com/DQme6C24nVuyR4exGQFAF9wRPczm8ubickiuZCxxP7Yy9wb/image.png)\n### 3.1 시스템 설계\n시스템은 이더리움 합의엔진 중 Clique PoA(Proof of Authority)를 활용하며 다음과 같이 크게 두 가지 요소로 구성이 되어 있다. 정유사(SK 에너지 등) 노드와 가맹 주유소 노드로 구성되어 있으며, 아래 그림은 시스템의 개략적인 구성도이다.\n\n![system-architecture](https://cdn.steemitimages.com/DQmU8EqqG81CC6JnL9KDJ94o6THSLMGQqwMTZpJxxqyXHH6/image.png)\n\n정유사 노드에서는 가맹 주유소 노드들이 전송하는 트랜잭션들을 검증 후 데이터베이스 갱신하는 역할을 담당하고, 가맹 주유소 노드들은 보유하고 있는 탱크의 기름 변동량을 센서로 체크하여 읽어 온 값을 담은 트랜잭션을 발생시키는 역할을 담당한다.\n\n### 3.1 주유소 노드\n주유소 노드의 동작 프로세스를 설명하기 전, 먼저 몇 가지 전제조건을 제시한다. 이는 전국의 모든 주유소가 전부 동일한 형태로 존재하지 않기 때문이다. 시스템의 원활한 설계를 위해 주유소 노드를 다음과 같이 상정하였다. 제안에 예시로 사용되는 기름의 종류는 경유이다.\n\n![fuel-station-node](https://cdn.steemitimages.com/DQmSKMC8qPzZgd1oJZaAsgS3VugzrqgpUwuoBLFjPDuen6P/image.png)\n\n#### 3.1.1 Tank(경유 탱크)\n* 주유소에는 하나의 경유 탱크가 존재한다.\n* 하나의 경유 탱크에 연결된 주유기는 3대로, 동 시간대에 총 3대의 차량에 주유가 가능하다.\n* 경유 탱크에는 기름의 변동량을 수시로 체크해주는 수위 센서, 가짜 경유인지 진짜 경유인지를 구별해주는 초음파 센서가 설치되어 있다. \n* 측정된 센서 값을 이더리움 네트워크로 전송 해주는 역할은 라즈베리파이(Rpi)가 수행하며 라즈베리 파이는 중간에 연결되어 있는 아두이노를 통해 센서값을 읽어온다. 중간에 아두이노를 둔 이유는, 향후 탱크의 개수가 많아질 때 라즈베리 파이를 늘리는 것이 아니라 아두이노만 늘리는 방식으로 설계할 수 있기 때문이다. 즉, 모든 탱크에서 측정되는 데이터는 라즈베리 파이 한 대가 이더리움 네트워크로 전송하게끔 되어 있다.\n* 탱크 내의 센서는 하나의 모듈로 구성되어 있다. 한 번 탱크 내에 들어가면 탈부착이 어렵게끔 되어 있으며 이는 센서의 물리적인 조작을 방지하기 위함이다.\n* 주유소의 데이터를 반영할 스마트 컨트랙트는 주유소 내 탱크별로 존재한다. 본 제안에서 상정한 모델에 따르면 하나의 주유소에는 하나의 경유 탱크가 존재하므로 주유소 지점당 컨트랙트가 존재한다. 아래의 코드는 실제 적용될 스마트컨트랙트의 생성자 함수이다. \n```\n    // 생성자가 2개의 매개변수로 주유소 이름(gasStationName)과 탱크가 담고 있는 기름의 종류(gasTankType)을 취하고 있음을 확인할 수 있다.\n    // 본 제안에서 기름의 종류는 경유(DIESEL)로 통일시킨다.\n    constructor(string _gasStationName, string _gasTankType) public {\n        bytes memory isSationNameEmpty = bytes(_gasStationName);\n        bytes memory isGasTypeEmpty = bytes(_gasTankType);\n        if (isSationNameEmpty.length == 0 || isGasTypeEmpty.length == 0) {\n            revert();\n        }\n        else {\n            owner = msg.sender;\n            gasStation = _gasStationName;\n            gasTankType = _gasTankType;\n            errorRange = 5;\n        }\n    }\n```\n#### 3.1.2 라즈베리파이3(Rpi3)\n* 라즈베리파이를 사용한 이유는 이더리움 네트워크에 단순히 트랜잭션만 전송 가능할 정도의 사양을 취하기 위함이다. 굳이 더 좋은 하드웨어를 사용할 필요가 없다.\n* 아두이노로부터 시리얼 통신으로 센서 값을 읽어들인다.\n* 읽어 들인 센서값을 이더리움 스마트컨트랙트에 기록하는 트랜잭션을 발생시킨다. \n#### 3.1.3 주유기(Fuel)\n* 탱크에는 3개의 연결된 주유기가 존재한다. 하나의 탱크에서 각 주유기를 통해 경유가 빠져나간다.\n* 경유가 빠져나가는 루트는 주유기가 유일하다. 특별한 상황(탱크를 청소해야 하거나, 영업을 위해 부족한 기름을 정유사로부터 공급받는 행위)을 제외하고는 오로지 주유기를 통해서만 경유가 빠져나가야 한다. 그 이외의 경우는 전부 비정상적인 상황이며 곧바로 적절한 조취를 취할 수 있어야 한다.\n* 주유기에는 기름이 빠져나간 양을 측정할 수 있는 모듈이 존재한다. 주유가 끝났을 때, 하나의 탱크에 연결된 3대의 주유기로부터 데이터를 받을 수 있다. 라즈베리파이는 탱크 뿐만 아니라 주유기와도 연결되어 있으므로 3대의 주유기로부터 데이터를 각각 가져와 총합한다.\n#### 이더리움 스마트 컨트랙트에 기록될 데이터의 종류\n* 수위 센서로 측정한 탱크 내 경유의 잔여량 (높이 및 무게로 측정)\n* 초음파 센서로 측정한 순수 경유 식별값\n* 3대의 측정한 주유량 (라즈베리파이가 합산하여 스마트 컨트랙트에 반영)\n* 위 데이터는 트랜잭션이 발생할 때마다 스마트 컨트랙트에 전송되고 모든 값을 다 가지고 있는 것이 아니라 같은 변수에 덮어씌어지는 방식으로 동작한다.\n### 3.2 검증자 노드 (정유사 노드)\n#### 3.2.1 노드의 구성\n본 제안에서 제시하는 권한 증명 기반 이더리움 프라이빗 네트워크는 2개의 부트 노드와 4개의 검증자 노드로 구성한다. 서버 권역(Availability Zone)은 2개로 구성하였고 각 서버 권역에는 2개의 검증자 노드가 존재한다.\n부트 노드는 네트워크 내의 노드들이 서로 인식할 수 있게 해주는 역할을 하고, 검증자 노드들은 주유소 노드에서 발생한 트랜잭션을 블록체인에 반영해주는 역할을 한다. 만약 주유소 노드에서 보낸 트랜잭션에 이상이 감지되면 이벤트 로그가 위조 및 변조 불가능한 기록으로 남게 되고 그 내용을 쉽게 확인할 수 있다.\n네트워크를 2개의 권역으로 구성한 것은 하나의 권역이 물리적으로 손상되어도 네트워크 유지에는 이상이 없게 하려는 의도이고 4개의 검증자 노드는 제안의 편의를 위해 설정한 것이다.\n설계적인 관점에서 올바른 노드 구성에 대해 설명하기 위해 먼저 잘못된 예시를 제시한 후에 올바른 예시를 제시하려 한다.\n2개의 권역 중 하나의 권역이 다운되었을 때도 네트워크가 유지되는 설계가 좋은 설계이고, 하나의 권역이 다운되었을 때 네트워크가 멈추는 건 잘못된 설계다.\n\n*잘못된 설계*\n\n![wrong-architecture](https://cdn.steemitimages.com/DQmP1qkZ1zbgxQrBmgrARN7VsZtskVwjRo8RaKY6K2PGAnp/image.png)\n\n위의 그림을 보면 4개의 검증자 노드가 모두 다 다르다는 것을 알 수 있다. 다름의 기준은 해당 노드의 계정 주소(EOA, Externally Owned Account)이다. 즉 모두 다른 주소를 가지고 있는 노드로 구성된 것이다.\n\n이렇게 제각기 다른 노드들로 구성을 하면 Clique엔진의 검증자 노드 공식(`int(4 / 2) + 1`)에 따라 최소 3개의 노드가 작동 중일 때만 네트워크가 유지된다. 만약 3개 미만의 노드가 동작중이라면, 프라이빗 네트워크에는 더이상 블록이 생성되지 않고 주유소 노드들이 보내는 트랜잭션들이 기록되지 않는다.\n\n즉, 4개의 노드가 모두 다른 계정으로 구성되어 있다면 이는 안전하지 않은 설계일 뿐더러, 권역을 2개로 나눈 의미 역시 무색해진다.\n\n*올바른 설계*\n\n![right-architecture](https://cdn.steemitimages.com/DQmQfWXkXLnrPhYQB24qnyTGWcE4BzoqmbBVCJoLNaN1Ewa/image.png)\n\n위의 그림을 보면 4개의 검증자 노드가 존재하는데, 색깔이 2개씩 동일하다는 점을 확인할 수 있을 것이다. 노드가 4개인 것은 맞지만 이 중 2개씩은 같은 EOA(Externally Owned Account)로 구성되어 있다. \n\n이더리움 합의 엔진인 Clique의 검증자 노드 공식(`int(2 / N) + 1`)에서 N의 기준은 EOA이기 때문에 아래의 그림에서 물리적인 노드의 수는 4개지만 실제 검증자로 구분되는 노드는 2개이다.\n\n따라서 최소 검증 노드 수는 2개가 되고 둘 중 하나의 권역이 다운되더라도 네트워크는 이상없이 동작할 수 있다. \n \n### 3.3 작동 매커니즘\n\n실제 블록체인이 주유소에 접목되었을 때의 유즈케이스(Usecase)를 기술한다. 언제 트랜잭션이 발생하여 블록체인에 데이터가 기록되는지가 핵심이고 그 부분은 빨간색으로 기술되어 있다. 이해를 돕기 위해 관련 소스코드 또한 일부를 첨부했다.\n\n먼저 정상적인 루틴에서의 동작을 설명하고 예외가 발생할 수 있는 상황과 그에 따른 대처를 다루었다. 정상적인 루틴 보다는 예외 상황을 어떻게 처리하는지가 신뢰 있는 주유소를 만드는데 있어 더 중요하기 때문에 예외처리 루틴은 매우 중요하고 또 정교하게 설계되어야 한다.\n\n#### 3.3.1 정상적인 루틴\n1. 빈 탱크에 정유사로부터 경유를 공급받아 탱크의 내용물을 채운다.\n2. 탱크에 경유 공급이 완료되었다면 이제 정상영업이 시작된다.\n3. 주유가 필요한 차량이 주유소로 들어온다.\n4. 주유기에서 주유가 시작된다. 3개가 동시에 주유될 수도 있고 1개의 주유기에서만 주유될 수도 있다.\n5. 주유기 모듈(Fuel)은 3개의 주유기 모두 주유가 종료될 때까지 대기한다.\n6. 3개의 주유기에서 모두 주유가 끝났을 때 다음 기술된 세가지 데이터가 연결된 라즈베리파이로 전송된다. 탱크의 수위와 탱크 내 경유의 식별 값을 아두이노가 시리얼 통신을 통해 라즈베리파이로 전송, 주유기 모듈이 탱크와 연결된 3개의 주유기에서 발생한 주유량을 총합하여 그 값을 라즈베리파이로 전송\n7. 라즈베리파이는 주유기 모듈로부터 받은 총 주유량, 아두이노에서 전송 받은 탱크 내 경유 수위, 경우의 식별 값을 담은 트랜잭션을 발생시킨다.\n8. 검증자 노드에서는 주유소 노드에서 발생된 트랜잭션들을 모아 블록을 생성하고 반영한다. \n\n*요약* 3개의 주유기 중 하나라도 주유를 시작할 때 루틴이 시작되며 3대의 주유기가 모두 주유 종료 상태가 되면 라즈베리파이는 블록체인에 관련 데이터를 전송한다. \n> 영업을 하지 않을 때는 약 5분마다 트랜잭션을 생성한다. \n\n#### 3.3.2 예외처리 루틴\n예외가 발생하는 경우를 감지할 때는 주유기에서 발생한 주유량 값과 탱크 내 수위 센서로 경유의 양을 측정한 값으로 비교를 한다. 해당 값들만으로 예외 처리가 되지 않는 경우(3.2.3) 에는 경유 식별 값을 추가로 사용하여 경유의 위조 및 변조 여부를 확인한다.\n\n##### 3.3.2.1 주유 전 측정한 탱크 내 경유 잔여량 != 주유량 + 주유 후 탱크 내 경유 잔여량\n만약 주유가 끝난 후에 센서로 측정된 경유 탱크의 잔여 경유량 + 주유기에서 빠져나간 경유의 총량이 이전에 측정했던 탱크의 경유량과 다르다면 이는 탱크에 어떤 조작이 가해졌다는 것을 뜻한다.\n\n예를 들어, 원래 100L의 경유가 존재했고 20L를 주유했다면, 남아 있는 경유는 80L가 될 것 이다. 그러나, 예상한 값이 아니라면 탱크에 이상이 발생한것이다. \n\n수위를 측정하는 센서가 언제나 정확한 값을 산출하는 것은 아니기 때문에 오차범위가 존재하고 예외 상황이란 건 허용할 수 있는 오차범위를 넘어설 때를 의미한다.\n\n위와 같은 경우 아래의 두 가지 구체적인 상항을 생각해볼 수 있다.\n\n##### 3.3.2.2 주유 전 측정한 탱크 내 경유 잔여량 > 주유량 + 주유 후 탱크 내 경유 잔여량\n주유 전 측정한 탱크 내 경유 잔여량이 100L였고, 주유기에서 빠져나간 주유량이 20L인 상황에서 주유 후 탱크 내 경유 잔여량이 70L인 상황을 생각해보자. 원래라면 80L가 있어야했지만 10L가 부족한 상황이다. \n\n정상적으로 기름이 빠져나가는 건 주유기를 통해서만 가능하므로 이와 같은 상황은 주유기 이외의 다른 방법으로 경유가 탱크에서 빠져나간 것으로 합리적 추론이 가능하다. 따라서 이를 블록체인 네트워크에 기록할 필요가 있다. \n\n관련 스마트 컨트랙트에서 이벤트 로그 기능을 통해 \"Tank has lower amount of gas. Possible abnormal gas extraction occurred” 메시지를 블록체인에 기록하여 예외 상황을 기록해 놓는다.\n\n##### 3.3.2.3 주유 전 측정한 탱크 내 경유 잔여량 < 주유량 + 주유 후 탱크 내 경유 잔여량\n주유 전 측정한 탱크 내 경유 잔여량이 100L였고, 주유기에서 빠져나간 주유량이 20L인 상황에서 주유 후 탱크 내 경유 잔여량이 90L인 상황을 생각해보자. 원래라면 80L가 있어야했지만 10L가 초과된 상황이다.\n\n있어야할 경유의 양보다 더 많아진 경우이므로 외부에서 경유가 유입되었다는 것으로 판단할 수 있다. 순수하게 경유를 유입한 것인지 아니면 다른 불순물을 섞었는지 판단하기 위하여 이러한 경우 경유 식별 값을 추가로 포함시켜서 트랜잭션을 발생시킨다.\n\n정상적인 상황에 대한 로직 그리고 예외적인 상황인3.3.2.2와 3.3.2.3에 대한 예외처리 로직을 구현한 스마트 컨트랙트(솔리디티) 소스코드는 아래의 코드와 같다. \n\n```\n// beforeFuelAmount: 주유 전 측정한 탱크 내 경유 잔여량\n// _filledOutAmount: 주유량\n// _sensoredTankAmount: 주유 후 탱크 내 경유 잔여량\n// _sensoredGasDensity: 주유 후 경유 식별값\nfunction checkGasTankAmount(uint256 _filledOutAmount, uint256 _sensoredTankAmount, uint256 _sensoredGasDensity) public notFueling notCleaning {\n    uint256 inputFuelAmount = _sensoredTankAmount.add(_filledOutAmount);\n    // 오차범위를 반영한 최대 허용치\n    uint256 maxErrorAmount = beforeFuelAmount.add(errorRange);\n    // 오차범위를 반영한 최소 허용치\n    uint256 minErrorAmount = beforeFuelAmount.sub(errorRange);\n    // 정상적인 루틴: 오차범위 내에서 경유 변동량에 이상이 없는 경우\n    if(minErrorAmount<= inputFuelAmount && inputFuelAmount <= maxErrorAmount){ \n//Allows the error range amount.\n        beforeFuelAmount = _sensoredTankAmount;\n        emit gasTankCheckedEvent(gasStation, gasTankType, \"Tank has correct amount of gas\");\n    }\n    // 예외 상황 3.3.2.2: 주유 전 측정한 탱크 내 경유 잔여량 > 주유량 + 주유 후 탱크 내 경유 잔여량\n    // 경유가 정상적인 방법 이외에 유출된 경우가 발생한 상황이다.\n    else if(inputFuelAmount < minErrorAmount){ //The tank has less fuel than it should\n        uint256 minAbnormalAmount = beforeFuelAmount.sub( _sensoredTankAmount);\n        beforeFuelAmount = _sensoredTankAmount;\n        // 이벤트 로그를 블록체인에 기록\n        emit abnormalTankCheckedEvent(gasStation, gasTankType, \"Tank has lower amount of gas. Possible abnormal gas extraction occured\", minAbnormalAmount );\n    }\n    // 예외 상황 3.3.2.3: 주유 전 측정한 탱크 내 경유 잔여량 < 주유량 + 주유 후 탱크 내 경유 잔여량\n    // 경유가 원래 있어야 할 정량보다 많은 경우가 발생한 상황이다.\n    else { //The tank has more fuel than it should.\n        uint256 maxAbnormalAmount = _sensoredTankAmount.sub(beforeFuelAmount);\n        beforeFuelAmount = _sensoredTankAmount;\n        // 이벤트 로그를 블록체인에 기록\n        // 불순물이 섞였을 가능성을 생각하여 주유 후 경유 식별값인 _sensoredGasDensity 또한 이벤트 로그에 반영해줘야 한다. \n        emit abnormalTankCheckedEvent(gasStation, gasTankType, \"Tank has higher amount of gas. Possible abnormal liquid mixing occured\", maxAbnormalAmount, _sensoredGasDensity );\n    }\n}\n```\n예외 처리가 발생했을 때는 이더리움 블록체인에 이벤트 로그가 기록된다. 이로써 각 주유소 지점들을 관리하는 정유사는 어떤 주유소에서 어떤 문제가 발생했는지 파악하고 조치를 취할 수 있다. \n\n##### 3.3.2.4 주유를 하지 않을 때 5분 전 경유 잔여량 != 5분 뒤 경유 잔여량 (오차범위를 감안했을 때)\n주유기를 통해 기름이 빠져나가지 안핬는데, 5분 전 경유 잔여량과 5분 뒤 경유 잔여량이 다른 것은 말이 안된다. 주유소 지점 탱크에 어떤 조작이 가해졌음을 확인할 수 있다. 아래의 코드에서 보는 것과 같이 라즈베리파이에서 5분 간격으로 측정을 진행한다. 측정한 값은 곧바로 스마트 컨트랙트로 전송된다.\n```\n        function refueling(m){\n      _timerCount[m.machine] = 0;\n      _timer[m.machine] = setInterval(function(){\n\n        let thisMachine = _gasMachine[\"machine\" + m.machine];\n        _timerCount[m.machine]++;\n        thisMachine.useLiter = thisMachine.useLiter + 1;\n\n        let percent = _timerCount[m.machine]/thisMachine.nowRefuelingAmout;\n        ...\n\n        if(_timerCount[m.machine]===thisMachine.nowRefuelingAmout){\n          clearInterval(_timer[m.machine]);\n        ...\n             //node send\n              const url = \"http://127.0.0.1:3000/usedgasamount/\"+sum;\n\n        \t\tfetch(url, {\n        \t\t\tmode: 'no-cors',\n        \t\t\tmethod: 'get'\n        \t\t})\n        \t\t.then(function(response) {\n        \t\t\tresponse.text().then(function(text) {\n        \t\t\t\treturn 0;\n        \t\t\t});\n        \t\t})\n        \t\t.catch(function(error) {\n        \t\t\tconsole.log(error);\n        \t\t});\n          }\n        }\n      }, 300000);\n```\n#### 3.3.3 허용되는 예외\n기름의 변동측정량이 비정상적이지만 이 중에는 분명 허용되는 예외상황도 존재한다. 허용되는 예외상황들은 다음과 같다. \n##### 3.3.3.1 빈 탱크에 정유사로부터 경유를 공급 받을 때\n탱크 내 경유 총량이 갑작스레 증가하는 상황이지만, 정유사로부터 경유를 공급받는 것이니 문제가 발생하는 상황은 아니다. 경유 공급의 시작과 종료 시점만 정확하게 기록되면 되는 것이다. 구현한 스마트 컨트랙트 소스 코드는 아래와 같다.\n\n```\nfunction startFueling(uint256 _fillingFuelAmount) external onlyOwner {\n    Fueling = true;\n    newFuelAmount = _fillingFuelAmount;\n    emit FuelingEvent(gasStation, gasTankType, _fillingFuelAmount, \"Filling the gas tank\");\n}\nfunction stopFueling(uint256 _sensoredGasDensity) external onlyOwner {\n    Fueling = false;\n    beforeFuelAmount = beforeFuelAmount.add(newFuelAmount);\n    newFuelAmount = 0;\n    emit FuelingEvent(gasStation, gasTankType, beforeFuelAmount, _sensoredGasDensity, \"Finished filling the gas tank\");\n}\n```\n정유사로부터 경유 공급이 시작될 때는 `startFueling` 함수가 호출되고 주유소 지점(`gasStation`), 탱크 정보(`gasTankType`), 공급량(`_fillingFuelAmount`)에 대한 정보가 이벤트 로그로 블록체인에 기록된다.\n\n주유 공급이 끝나면 탱크 내 경유의 식별 값을 매개변수로 취하는 `stopFueling` 함수가 호출된다. 이로써 공급이 완료된 후에 위조 및 변조 되지 않은 경유가 들어왔는지 여부를 확인할 수 있다.\n\n##### 3.3.3.2 탱크를 청소하기 위해 경유를 모두 추출하거나 청소 후 다시 채워 넣을 때\n탱크 내 경유 총량이 갑작스레 감소하는 상황이지만, 청소를 위해 경유를 빼는 것이니 문제가 발생하는 상황은 아니다. 관련된 스마트 컨트랙트 코드는 아래와 같다.\n\n```\nfunction startCleaning(uint256 _sensoredGasDensity) external onlyOwner {\n    Emptying = true;\n    EmptyingAmount = beforeFuelAmount;\n    beforeFuelAmount = 0;\n    emit CleaningEvent(gasStation, gasTankType, EmptyingAmount, _sensoredGasDensity, \"Started cleaning the tank\");\n}\n// 청소 다하고 기름 채워넣었을 때\nfunction stopCleaning(uint256 _sensoredTankAmount, uint256 _sensoredGasDensity) external onlyOwner { //When cleaning is over and the fuel has been recharged.\n    Emptying = false;\n    uint256 maxErrorAmount = EmptyingAmount.add(errorRange);\n    uint256 minErrorAmount = EmptyingAmount.sub(errorRange);\n    if(minErrorAmount<= _sensoredTankAmount && _sensoredTankAmount <= maxErrorAmount){\n        beforeFuelAmount = EmptyingAmount;\n    }\n    emit CleaningEvent(gasStation, gasTankType, EmptyingAmount, _sensoredGasDensity, \"Finished cleaning the tank\");\n}\n```\n\n허용되는 예외 상황들이 발생했을 때는 이벤트 로그가 블록체인에 기록된다. 허용되는 예외 상황은 계약을 배포한 정유사 본사(SK에너지)에서 이루어지는데 이때 무분별한 사용과 소비자를 기만할 목적으로 사용될 수 없도록 전에 있던 데이터 양을 고스란히 기록하여 이벤트 로그를 발생시킨다. \n\n이로써 해당 메서드를 호출할 때 정유사로서는 신중을 기할 수밖에 없으며 혹여나 남발했을 경우 이더리움 블록체인에 영구적으로 남기 때문에 소비자들이 직접 확인할 수 있을 것이다.\n\n## 4. 프로토타입\n본 제안을 구체화해보고자 탱크 내의 센서의 값을 스마트 컨트랙트에 반영하는 프로토타입을 제작하였다. 시스템의 전반적인 스펙은 다음과 같다.\n![prototype-overview](https://cdn.steemitimages.com/DQmNUcea65SPfjdah4ca7fofiA1BiRfEN6FfEpZTeQ621Lk/image.png)\n\n다만, 프로토타입에서 사용되는 센서는 수위센서뿐이다. 초음파로 경유를 식별하는 센서의 경우 아직 연구중이며 프로토타입에 적합한 유량 식별 센서를 찾기 어려웠기 때문이다. 본 프로토타입의 한계는 경유 탱크의 변동량만 이더리움 블록체인에 기록되게끔 구현되어 있다는 점이다.\n\n또한 구현의 편의성을 위해 Clique PoA(권한 증명) 엔진이 아닌 Ethash PoW(작업 증명) 엔진을 채택했다.\n\n### 4.1 프로토타입 설계\n전체 설계도를 미리 살펴보면 아래의 그림과 같다. 빠른 구현을 위해 하나의 랩톱에서 작업 증명 방식의 프라이빗 블록 체인을 구축했다.\n\n![prototype-architecture](https://cdn.steemitimages.com/DQmSuRNMq5yxLgyeNSn9nJ4DHEMx5nX4WuRaJP2JznTkRjq/image.png)\n\n#### 4.2 주유소 노드\n프로토타입의 주유소 노드에 사용된 구성은 아래의 그림과 같다. 본 시스템 제안에서 제시했던 구성과의 차이점은 빨간 글씨로 표시되어 있다.\n\n![gas-station-node](https://cdn.steemitimages.com/DQmSWA7aT7Qrm55yeHEL1tmeWT4JEuEDDfLz9zspLV6DR8G/image.png)\n\n##### 4.2.1 물통(Bottle)\n* 주유소에 존재하는 탱크의 역할을 담당하는 물통이다.\n* 물통에는 물의 높이를 측정해주는 수위 센서가 존재한다.\n* 수위 센서는 아두이노로 측정한 값을 보내고 아두이노는 시리얼 통신으로 라즈베리파이에 값을 전송한다.\n>  실제 탱크 대신 물통을 사용하였으며 센서는 수위 센서 하나만 사용하였다.\n\n아두이노의 회로 구성과 코드는 다음과 같다.\n![arduino](https://cdn.steemitimages.com/DQmSm41avcPcGgFC8nYyKUjmR9QMUaxZBgdUyQdEUHvEmfm/image.png)\n\n1. 수위 센서로 읽어온 값은 A0핀 (노란색 선)을 통해 받아온다.\n2. 시리얼 통신을 사용하여 읽어온 센서 값을 3초 간격으로 라즈베리파이에 전송한다.\n\n```\nconst int WATER_SENSOR_PIN0 = A0;\nvoid setup() {\n    Serial.begin(9600);\n}\nvoid loop() {\n    int sensorVal0 = analogRead(WATER_SOURCE_PIN0);\n    Serial.print(\"0 sensor value = \");\n    serial.println(sensorval0);\n    delay(3000);\n}\n```\n\n#### 4.2.2 주유기(Web)\n* 실제 주유소 노드의 탱크에 연결된 3대의 주유기를 웹으로 구현하였다.\n* 아래의 그림과 같이 3대의 주유기가 존재하고 각각 `START`, END` 버튼이 존재한다. `START` 버튼을 클릭함으로써 주유가 시작되고 시간이 지나서 종료가 되거나 직접 `END` 버튼을 눌러 종료할 수 있다.\n\n![fuel-machines](https://cdn.steemitimages.com/DQmZhYtBBLmDWzQmY4Y5Mcxd91z8hzLYQAjsubvPTujyuXE/image.png)\n\n* 금액 혹은 리터를 입력한 뒤 `START` 버튼을 누르면 주유가 시작되고 파란색 진행 막대가 채워지기 시작한다.\n* 금액을 입력했을 때는 좌측 상단의 금액 환산표에 따라 리터가 결정된다. 1리터당 1초로 환산하여 주유 시간도 정해진다.\n* 막대가 다 채워지면 (정해진 시간이 지나면) 주유가 종료된다. 주유 중에 END 버튼을 눌러도 주유가 종료된다.\n* 웹 페이지의 자바스크립트 소스코드에는 `Web3` 라이브러리를 활용하여 이더리움 네트워크에 트랜잭션을 발생시킬 수 있게끔 되어 있다.\n\n#### 4.2.3 노드(Node)\n* 아두이노로부터 전송 받은 센서 값을 스마트컨트랙트에 반영하는 트랜잭션을 발생시킨다. \n* 라즈베리파이에서 `Web3` 모듈을 사용한 `NodeJs` 코드를 동작시킴으로써 작동한다.\n* 주유기가 구현되어 있는 웹 페이지를 호스팅한다.\n\n### 4.3 검증자 노드\n![validator](https://cdn.steemitimages.com/DQmVsDSF4rUAMNDxf24gpjsX8AeYQgmP59wUYEPhDt9uouJ/image.png)\n \n프로토타입에서의 검증자 노드 구성은 모두 하나의 컴퓨터에서 이루어진다. 위 그림에 표현된 노드들은 각각 하나의 geth 프로세스를 의미한다.\n\n#### 4.3.1 채굴 노드\n* 채굴(Mining)을 담당하는 geth 프로세스다.\n* 로컬환경에서 발생하는 트랜잭션들을 모아 블록을 생성하고 이더리움 블록체인에 반영한다.\n\n#### 4.3.2 배포 노드\n* 탱크(프로토타입에서는 물통)와 관련된 스마트 컨트랙트를 배포하고 관리하는 geth 프로세스다.\n* 탱크에서 발생하는 센서 값들을 사용하여 트랜잭션을 발생시킨다.\n\n#### 4.3.3 예비 노드\n* 채굴 노드와 배포 노드 둘 중 하나의 노드가 제 기능을 못하게 되었을 때 언제든지 대체할 수 있는 노드를 의미한다.\n* 프로토타입에서의 합의 알고리즘은 작업 증명이기 때문에 하나의 네트워크에 속해 있기만 하다면 언제든지 채굴 노드 혹은 배포 노드를 대체할 수 있다.\n\n### 4.3 프로토타입 동작 설명\n#### 4.3.1 주유 시작\n![process](https://cdn.steemitimages.com/DQmeCZnMKKGK4oH8YsNn5jipC9qEuXYNvwam1nXuU2g6xjb/image.png)\n\n1. 위 그림의 각 주유기에 원하는 주유량을 입력한 뒤 `START`버튼을 눌러 주유를 시작한다.\n2. 진행 막대가 다 채워지거나 3대의 주유기에 `END` 버튼이 눌렸을 때 주유가 종료된다.\n\n#### 4.3.2 주유 종료\n1. `NodeJs`로 작성한 서버 코드에서는 세 대의 주유기에서 모두 주유가 끝났는지 확인하고 3대의 양을 총합한다.\n2. 모두 끝나고 합산이 완료되었다면 이더리움 네트워크에 반영하는 모듈로 합산량을 전송한다.\n\n구현된 코드는 아래와 같다.\n```\nlet sum = 0,\nstate = 0;\n          for( var key in _gasMachine ) {\n            sum = sum +_gasMachine[key].useLiter;\n            state = state+_gasMachine[key].state;\n          }\n          if(state){\n            console.log('progress');\n          }else{\n            for( var key in _gasMachine ) {\n              _gasMachine[key].useLiter = 0;\n            }\n            console.log('total refueling : '+sum);\n              //node send\n              const url = \"http://127.0.0.1:3000/usedgasamount/\"+sum;\n        \t\tfetch(url, {\n        \t\t\tmode: 'no-cors',\n        \t\t\tmethod: 'get'\n        \t\t})\n        \t\t.then(function(response) {\n        \t\t\tresponse.text().then(function(text) {\n        \t\t\t\treturn 0;\n        \t\t\t});\n        \t\t})\n```\n\n#### 4.3.3 전송된 주유량과 센서 데이터 값을 스마트 컨트랙트에 반영\n1. 배포되어 있는 스마트 컨트랙트의 함수를 호출한다. 주유량과 센서 데이터 값을 매개변수로 전달한다.\n2. 함수를 호추함과 동시에 트랜잭션이 발생한다.\n3. 발생된 트랜잭션은 채굴 노드에서 블록체인에 반영한다.\n\n코드는 아래와 같다. `NodeJs` 와 `Web3` 라이브러리를 사용한 코드다.\n```\nserver.route({\n        method:'GET',\n        path:'/usedgasamount/{value}',\n        handler:function(request,h) {\n            console.log(\"Is in the server.route\");\n            var cntSerial = 0;\n            var extractedGasAmount = request.params.value;\n            console.log(extractedGasAmount);\n\n            parser.on('data', function(data) {\n                var length = data.length;\n                \n                var sensor_value = data.slice(8, length);\nvar waterHeight = parseInt(sensor_value);\n                var t0 = \"0\";\n                if (cntSerial++ === 0) {\n\n                    if(data[0] === t0) {\n        myContract.methods.checkGasTankAmount(extractedGasAmount,waterHeight).send({from: rpiEoa0})\n\nelse {\n                        console.log('error');\n                        console.log('data: ' + data);\n                        console.log('data[0] ' + data[0]);\n                    }\n                }\n            });\n            \n            return 0;\n        }\n     });\n```\n\n호출한 스마트 컨트랙트의 함수 코드는 아래와 같다. *3.3.2 예외처리 루틴*에서 설명된 예외 상황 중 일부가 구현되어 있다. 초음파로 경유를 식별하는 식별 값이 없다는 점 외에는 *3.3.2 예외처리 루틴*에서 제시 되었던 로직과 동일하다.\n\n```\n// beforeFuelAmount: 주유 전 측정한 탱크 내 경유 잔여량\n// _filledOutAmount: 주유량\n// _sensoredTankAmount: 주유 후 탱크 내 경유 잔여량\nfunction checkGasTankAmount(uint256 _filledOutAmount, uint256 _sensoredTankAmount) public notFueling notCleaning {\n    uint256 inputFuelAmount = _sensoredTankAmount.add(_filledOutAmount);\n    // 오차범위를 반영한 최대 허용치\n    uint256 maxErrorAmount = beforeFuelAmount.add(errorRange);\n    // 오차범위를 반영한 최소 허용치\n    uint256 minErrorAmount = beforeFuelAmount.sub(errorRange);\n    // 정상적인 루틴: 오차범위 내에서 경유 변동량에 이상이 없는 경우\n    if(minErrorAmount<= inputFuelAmount && inputFuelAmount <= maxErrorAmount){ //Allows the error range amount.\n        beforeFuelAmount = _sensoredTankAmount;\n        emit gasTankCheckedEvent(gasStation, gasTankType, \"Tank has correct amount of gas\");\n    }\n    // 예외 상황 3.2.2: 주유 전 측정한 탱크 내 경유 잔여량 > 주유량 + 주유 후 탱크 내 경유 잔여량\n    // 경유가 정상적인 방법 이외에 유출된 경우가 발생한 상황이다.\n    else if(inputFuelAmount < minErrorAmount){ //The tank has less fuel than it should\n        uint256 minAbnormalAmount = beforeFuelAmount.sub( _sensoredTankAmount);\n        beforeFuelAmount = _sensoredTankAmount;\n        // 이벤트 로그를 블록체인에 기록\n        emit abnormalTankCheckedEvent(gasStation, gasTankType, \"Tank has lower amount of gas. Possible abnormal gas extraction occured\", minAbnormalAmount );\n    }\n    // 예외 상황 3.2.3: 주유 전 측정한 탱크 내 경유 잔여량 < 주유량 + 주유 후 탱크 내 경유 잔여량\n    // 경유가 원래 있어야 할 정량보다 많은 경우가 발생한 상황이다.\n    else { //The tank has more fuel than it should.\n        uint256 maxAbnormalAmount = _sensoredTankAmount.sub(beforeFuelAmount);\n        beforeFuelAmount = _sensoredTankAmount;\n        // 이벤트 로그를 블록체인에 기록\n        emit abnormalTankCheckedEvent(gasStation, gasTankType, \"Tank has higher amount of gas. Possible abnormal liquid mixing occured\", maxAbnormalAmount );\n    }\n}\n```\n\n비정상적인 상황이 인지되면 이더리움 블록체인에 Event 로그를 기록한다. 이벤트는 아래의 코드에 나와 있는 양식으로 블록체인에 기록된다.\n```\n{address: \"0xe5006916ad70ca9c440ee74860c3853674bf0e88\", blockNumber: 625, transactionHash: \"0xf3f25b509a9fbb6b8d2dbc7a37ccdb7960890c952d99d031742d46c65dee6eb7\", transactionIndex: 0, blockHash: \"0x1fd9b564e1ad9373bc711f5304dbd272e6a366a85c7904285ef863ec2407a089\", …}\n1.\taddress:\"0xe5006916ad70ca9c440ee74860c3853674bf0e88\"\n2.\targs:{_gasStationName: \"SK_ENERGY\", _gasTankType: \"DIESEL\", _fillingFuelAmount: BigNumber, _statusMessage: \"Filling the gas tank\"}\n3.\tblockHash:\"0x1fd9b564e1ad9373bc711f5304dbd272e6a366a85c7904285ef863ec2407a089\"\n4.\tblockNumber:625\n5.\tevent:\"FuelingEvent\"\n6.\tlogIndex:0\n7.\tremoved:false\n8.\ttransactionHash:\"0xf3f25b509a9fbb6b8d2dbc7a37ccdb7960890c952d99d031742d46c65dee6eb7\"\n9.\ttransactionIndex:0\n10.\t__proto__:Object\n```\n\n2번 필드를 살펴보면, “SK_ENERGY” 주유소의 “DIESEL”(경유) 탱크에 “Filling the gas tank” 이벤트가 발생하였음을 확인할 수 있다. 그 아래 필드는 기록되어 있는 블록 번호, 블록 해시, 트랜잭션 해시 등의 정보가 기입되어 있고 결과값으로 나온 정보 중 필요한 내용을 파싱하여 출력해보면 아래와 같다.\n\n* 허용되는 예외 상황(*정유사로부터 기름을 공급받을 때*)에 대한 이벤트 로그\n\n![exception-log-1](https://cdn.steemitimages.com/DQmdSBHqafsD6WNSPb1P7KQREjRKk78Kvf8QaPJCkYYHK43/image.png)\n\n* *예외 상황 3.3.2.2*에 해당하는 이벤트 로그\n\n![exception-log-2](https://cdn.steemitimages.com/DQmYbupHfiVkBLvX2DfjZHYaNoAiPifPfdDkFozoBsKWDAh/image.png)\n\n* *예외 상황 3.3.2.3*에 해당하는 이벤트 로그\n\n![exception-log-3](https://cdn.steemitimages.com/DQmPVC28GfjpSFwksaQNRVGpFcBqvnhynjpcfN2wRiQwpFC/image.png)\n\n### 4.4 프로토타입의 한계 및 개선 방안\n1. 경유의 성분 분석을 할 수 있는 초음파 식별 센서를 적용하지 못했다.\n식별 센서를 적용하지 못할 경우 다음과 같은 불상사가 발생할 수 있다. 기름 탱크를 청소하기 위해 경유를 전부 뺐다가 청소 후 다시 경유를 채울 때 불순물을 섞어서 채우는 것이 가능하다. 즉, 경유 식별 센서가 없다면 *탱크를 완전히 비우고 채울 때 조작이 가능*하다.\n\n2. 부실한 외부 접근 제한\n운영자 geth 노드의 정보 (포트 번호, eNode 정보 등)가 외부로 유출 되었을 시 데이터 조작이 가능하다. PoW 체인이기 때문에 더 많은 블록을 빠른 시간 안에 전파하면 데이터가 갈아 엎어진다.\n\n3. 센서에서 측정된 데이터 값을 토대로 판단하는 시스템이기 대문에 센서 자체가 조작되는 것에 대한 보안은 되어 있지 않다.\n\n4. 측정에 사용되는 방법은 단순히 높이를 측정하는 것이므로 경유가 출렁이거나 탱크 자체가 움직이는 상황 등이 발생하면 정확한 측정이 어렵다. 또한 기름의 특성상 온도에 따라 부피가 약간씩 달라지기 때문에 높이만으로 측정하는 방법에는 한계가 있다.\n\n*위의 한계점들에 대한 개선 방안은 아래와 같다.*\n\n1. 모듈화가 가능한 경유 식별 센서에 대한 연구는 게속 진행중이다. 초음파 뿐만 아니라 [나노기술기반 가짜 석유 식별센서 개발 및 상용화](http://www.ndsl.kr/ndsl/search/detail/report/reportSearchResultDetail.do?cn=TRKO201600002359)를 주제로 한 연구 또한 진행중이다. 직접 개발하거나 연구되고 있는 기술들을 종합하여 센서를 개발하고 향후 탱크에 적용하는 방향으로 문제를 개선할 수 있다.\n\n2. 외부로부터의 허가되지 않은 접근을 제한하기 위해 정유사만의 VPC망 안에 프라이빗 네트워크를 구축함으로써 허가 받지 않은 접근을 방지할 수 있다. (사실 이미 SK에서 자체적으로 운영하고 있는 네트워크가 있다고 하니 이 부분은 크게 걱정하지 않아도 될 것 같다.)\n\n3. 한 번 탱크에 부착된 센서 및 관련 모듈들에 외부 조작을 가할 수 없게끔 결합도가 강하게 설계하는 방법이 있다. 그렇게 하면 센서 자체를 조작해서 탈부착하거나 센서를 무력화시키는 행위 등에 대한 예방이 가능하다. 만약 조작을 하더라도 조작한 기록까지 블록체인에 기록이 되므로 정유사 본사에서 적절한 조치를 취할 수 있다. 즉 감시 및 모니터링은 충분히 이루어질 수 있다.\n\n4. 높이 센서 뿐만 아니라 무게 센서를 함께 차용하는 방안이 있다. 경유가 출렁거려 높이가 달라지더라도 무게는 같기 때문에 더 정확한 측정이 가능하다.\n\n## 5. 결론\n구상한 서비스를 현실에 적용하기에는 아직까지 개선점이 많이 필요한 아이디어지만, 지속적인 연구를 통해 서비스를 개선해간다면 분명 깨끗한 유류 관리 시스템을 만들어낼 수 있을 것이다. 소비자들이 피해받지 않고 믿고 쓸 수 있는 주유소 유통 공급망 시스템이 구축되었으면 하는 바람이다.\n\n## 6. 보너스: 토큰 이코노미\n현재 주유를 하면 자동으로 적립이 되는 시스템이 운영되고 있다. 그러나 블록체인 시스템이 도입되면 다음과 같은 매커니즘도 생각해볼 수 있다.\n\n1. 사용자들이 주유를 받으면 영수증에 사용자가 주유한 내용이 반영되어 있는 트랜잭션의 해시가 QR코드가 적혀있다.\n\n2. 사용자는 해당 QR코드를 인식하면 사용자가 주유한 건에 대한 트랜잭션이 정상적으로 처리가 되었는지 확인할 수 있다.\n\n3. 이상현상이 발생하지 않았음을 확인한 사용자는 안심할 수 있으며 현재 이 블록체인 시스템이 정상운영 되는지를 직접 확인한 검증자가 된다.\n\n4. 검증을 직접한 대가로 정유사에서는 포인트를 제공해준다.\n\n정유사는 위와 같은 서비스를 제공했을 때, 소비자로부터 신뢰를 받을 수 있으며 광고 및 입소문 효과까지 누릴 수 있다. 소비자는 주유가 제대로 되었는지 확인하고 안심할 수 있으며 포인트까지 적립받으니 이는 소비자 및 정유사 모두에게 이득이 되는 WIN-WIN 전략이라 할 수 있다.",
      "json_metadata": "{\"tags\":[\"ethereum\",\"smartcontract\",\"blockchain\",\"iot\"],\"image\":[\"https://cdn.steemitimages.com/DQme6C24nVuyR4exGQFAF9wRPczm8ubickiuZCxxP7Yy9wb/image.png\",\"https://cdn.steemitimages.com/DQmU8EqqG81CC6JnL9KDJ94o6THSLMGQqwMTZpJxxqyXHH6/image.png\",\"https://cdn.steemitimages.com/DQmSKMC8qPzZgd1oJZaAsgS3VugzrqgpUwuoBLFjPDuen6P/image.png\",\"https://cdn.steemitimages.com/DQmP1qkZ1zbgxQrBmgrARN7VsZtskVwjRo8RaKY6K2PGAnp/image.png\",\"https://cdn.steemitimages.com/DQmQfWXkXLnrPhYQB24qnyTGWcE4BzoqmbBVCJoLNaN1Ewa/image.png\",\"https://cdn.steemitimages.com/DQmNUcea65SPfjdah4ca7fofiA1BiRfEN6FfEpZTeQ621Lk/image.png\",\"https://cdn.steemitimages.com/DQmSuRNMq5yxLgyeNSn9nJ4DHEMx5nX4WuRaJP2JznTkRjq/image.png\",\"https://cdn.steemitimages.com/DQmSWA7aT7Qrm55yeHEL1tmeWT4JEuEDDfLz9zspLV6DR8G/image.png\",\"https://cdn.steemitimages.com/DQmSm41avcPcGgFC8nYyKUjmR9QMUaxZBgdUyQdEUHvEmfm/image.png\",\"https://cdn.steemitimages.com/DQmZhYtBBLmDWzQmY4Y5Mcxd91z8hzLYQAjsubvPTujyuXE/image.png\",\"https://cdn.steemitimages.com/DQmVsDSF4rUAMNDxf24gpjsX8AeYQgmP59wUYEPhDt9uouJ/image.png\",\"https://cdn.steemitimages.com/DQmeCZnMKKGK4oH8YsNn5jipC9qEuXYNvwam1nXuU2g6xjb/image.png\",\"https://cdn.steemitimages.com/DQmdSBHqafsD6WNSPb1P7KQREjRKk78Kvf8QaPJCkYYHK43/image.png\",\"https://cdn.steemitimages.com/DQmYbupHfiVkBLvX2DfjZHYaNoAiPifPfdDkFozoBsKWDAh/image.png\",\"https://cdn.steemitimages.com/DQmPVC28GfjpSFwksaQNRVGpFcBqvnhynjpcfN2wRiQwpFC/image.png\"],\"links\":[\"https://github.com/dlgusdn616\",\"https://medium.com/@dlgusdn616\",\"https://github.com/heuristicwave\",\"https://medium.com/@heuristicwave\",\"https://github.com/Bookstore3\",\"http://www.ndsl.kr/ndsl/search/detail/report/reportSearchResultDetail.do?cn=TRKO201600002359\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
    }
  ]
}
steemdelegated 18.013 SP to @dlgusdn616
2018/09/22 00:04:45
delegatorsteem
delegateedlgusdn616
vesting shares29292.535515 VESTS
Transaction InfoBlock #26152538/Trx 7cf6f21407ed14f33a45a392d71c7c70278f1b59
View Raw JSON Data
{
  "trx_id": "7cf6f21407ed14f33a45a392d71c7c70278f1b59",
  "block": 26152538,
  "trx_in_block": 46,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-09-22T00:04:45",
  "op": [
    "delegate_vesting_shares",
    {
      "delegator": "steem",
      "delegatee": "dlgusdn616",
      "vesting_shares": "29292.535515 VESTS"
    }
  ]
}
dlgusdn616received 0.105 STEEM, 0.131 SP author reward for @dlgusdn616 / aws-puppeth-ethereum-private-blockchain-poa
2018/08/27 16:30:30
authordlgusdn616
permlinkaws-puppeth-ethereum-private-blockchain-poa
sbd payout0.000 SBD
steem payout0.105 STEEM
vesting payout212.504886 VESTS
Transaction InfoBlock #25439382/Virtual Operation #10
View Raw JSON Data
{
  "trx_id": "0000000000000000000000000000000000000000",
  "block": 25439382,
  "trx_in_block": 4294967295,
  "op_in_trx": 0,
  "virtual_op": 10,
  "timestamp": "2018-08-27T16:30:30",
  "op": [
    "author_reward",
    {
      "author": "dlgusdn616",
      "permlink": "aws-puppeth-ethereum-private-blockchain-poa",
      "sbd_payout": "0.000 SBD",
      "steem_payout": "0.105 STEEM",
      "vesting_payout": "212.504886 VESTS"
    }
  ]
}
2018/08/27 10:45:15
parent author
parent permlinkethereum
authordlgusdn616
permlinkaws-puppeth-ethereum-private-blockchain-poa
titleAWS와 Puppeth를 활용한 Ethereum Private Blockchain (POA) 구축하기
body@@ -20452,18 +20452,16 @@ iner_id%3E - %60 geth at
json metadata{"tags":["ethereum","poa","blockchain","privateblockchain","puppeth"],"image":["https://cdn.steemitimages.com/DQmNae973aXjn5G5YG98h91bBTQsq4TCKnGy5EcbagEdXxU/image.png","https://cdn.steemitimages.com/DQmbtRNUZqUYSkWsDRMKMujpjdx1br9RGouZouXt5eRJMhD/image.png"],"links":["https://medium.com/@collin.cusce/using-puppeth-to-manually-create-an-ethereum-proof-of-authority-clique-network-on-aws-ae0d7c906cce"],"app":"steemit/0.1","format":"markdown"}
Transaction InfoBlock #25432478/Trx 7ac8090ca8b58da43ae00932b6f6c50757d74575
View Raw JSON Data
{
  "trx_id": "7ac8090ca8b58da43ae00932b6f6c50757d74575",
  "block": 25432478,
  "trx_in_block": 32,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-08-27T10:45:15",
  "op": [
    "comment",
    {
      "parent_author": "",
      "parent_permlink": "ethereum",
      "author": "dlgusdn616",
      "permlink": "aws-puppeth-ethereum-private-blockchain-poa",
      "title": "AWS와 Puppeth를 활용한 Ethereum Private Blockchain (POA) 구축하기",
      "body": "@@ -20452,18 +20452,16 @@\n iner_id%3E\n- %60\n  geth at\n",
      "json_metadata": "{\"tags\":[\"ethereum\",\"poa\",\"blockchain\",\"privateblockchain\",\"puppeth\"],\"image\":[\"https://cdn.steemitimages.com/DQmNae973aXjn5G5YG98h91bBTQsq4TCKnGy5EcbagEdXxU/image.png\",\"https://cdn.steemitimages.com/DQmbtRNUZqUYSkWsDRMKMujpjdx1br9RGouZouXt5eRJMhD/image.png\"],\"links\":[\"https://medium.com/@collin.cusce/using-puppeth-to-manually-create-an-ethereum-proof-of-authority-clique-network-on-aws-ae0d7c906cce\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
    }
  ]
}
2018/08/21 12:32:51
votercard1001
authordlgusdn616
permlinkaws-puppeth-ethereum-private-blockchain-poa
weight10000 (100.00%)
Transaction InfoBlock #25261911/Trx eae8a661ec43e01be9b018c9e7fbb36087fe99f8
View Raw JSON Data
{
  "trx_id": "eae8a661ec43e01be9b018c9e7fbb36087fe99f8",
  "block": 25261911,
  "trx_in_block": 8,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-08-21T12:32:51",
  "op": [
    "vote",
    {
      "voter": "card1001",
      "author": "dlgusdn616",
      "permlink": "aws-puppeth-ethereum-private-blockchain-poa",
      "weight": 10000
    }
  ]
}
2018/08/21 06:00:45
votermodolee
authordlgusdn616
permlinkaws-puppeth-ethereum-private-blockchain-poa
weight10000 (100.00%)
Transaction InfoBlock #25254069/Trx 83e351ef83f02feefccd6daaaa8ba520b4cb8f29
View Raw JSON Data
{
  "trx_id": "83e351ef83f02feefccd6daaaa8ba520b4cb8f29",
  "block": 25254069,
  "trx_in_block": 2,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-08-21T06:00:45",
  "op": [
    "vote",
    {
      "voter": "modolee",
      "author": "dlgusdn616",
      "permlink": "aws-puppeth-ethereum-private-blockchain-poa",
      "weight": 10000
    }
  ]
}
2018/08/21 05:07:00
parent author
parent permlinkethereum
authordlgusdn616
permlinkaws-puppeth-ethereum-private-blockchain-poa
titleAWS와 Puppeth를 활용한 Ethereum Private Blockchain (POA) 구축하기
body@@ -427,17 +427,17 @@ %ED%95%98%EC%97%AC %ED%95%84%EC%88%98%EC%9A%94%EC%86%8C%EB%93%A4 -%EC%9C%BC +%EC%9D%84 %EA%B0%96%EC%B6%98 %ED%94%84%EB%9D%BC%EC%9D%B4%EB%B9%97
json metadata{"tags":["ethereum","poa","blockchain","privateblockchain","puppeth"],"image":["https://cdn.steemitimages.com/DQmNae973aXjn5G5YG98h91bBTQsq4TCKnGy5EcbagEdXxU/image.png","https://cdn.steemitimages.com/DQmbtRNUZqUYSkWsDRMKMujpjdx1br9RGouZouXt5eRJMhD/image.png"],"links":["https://medium.com/@collin.cusce/using-puppeth-to-manually-create-an-ethereum-proof-of-authority-clique-network-on-aws-ae0d7c906cce"],"app":"steemit/0.1","format":"markdown"}
Transaction InfoBlock #25252994/Trx 52e78146ff614a3cc4a88ab51536a4609725779b
View Raw JSON Data
{
  "trx_id": "52e78146ff614a3cc4a88ab51536a4609725779b",
  "block": 25252994,
  "trx_in_block": 9,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-08-21T05:07:00",
  "op": [
    "comment",
    {
      "parent_author": "",
      "parent_permlink": "ethereum",
      "author": "dlgusdn616",
      "permlink": "aws-puppeth-ethereum-private-blockchain-poa",
      "title": "AWS와 Puppeth를 활용한 Ethereum Private Blockchain (POA) 구축하기",
      "body": "@@ -427,17 +427,17 @@\n %ED%95%98%EC%97%AC %ED%95%84%EC%88%98%EC%9A%94%EC%86%8C%EB%93%A4\n-%EC%9C%BC\n+%EC%9D%84\n  %EA%B0%96%EC%B6%98 %ED%94%84%EB%9D%BC%EC%9D%B4%EB%B9%97\n",
      "json_metadata": "{\"tags\":[\"ethereum\",\"poa\",\"blockchain\",\"privateblockchain\",\"puppeth\"],\"image\":[\"https://cdn.steemitimages.com/DQmNae973aXjn5G5YG98h91bBTQsq4TCKnGy5EcbagEdXxU/image.png\",\"https://cdn.steemitimages.com/DQmbtRNUZqUYSkWsDRMKMujpjdx1br9RGouZouXt5eRJMhD/image.png\"],\"links\":[\"https://medium.com/@collin.cusce/using-puppeth-to-manually-create-an-ethereum-proof-of-authority-clique-network-on-aws-ae0d7c906cce\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
    }
  ]
}
2018/08/20 17:55:57
votersensation
authordlgusdn616
permlinkaws-puppeth-ethereum-private-blockchain-poa
weight10000 (100.00%)
Transaction InfoBlock #25239575/Trx a6a3b0f38f2d80efe2263b743f2a74dd6a6c07cc
View Raw JSON Data
{
  "trx_id": "a6a3b0f38f2d80efe2263b743f2a74dd6a6c07cc",
  "block": 25239575,
  "trx_in_block": 20,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-08-20T17:55:57",
  "op": [
    "vote",
    {
      "voter": "sensation",
      "author": "dlgusdn616",
      "permlink": "aws-puppeth-ethereum-private-blockchain-poa",
      "weight": 10000
    }
  ]
}
2018/08/20 16:36:36
parent author
parent permlinkethereum
authordlgusdn616
permlinkaws-puppeth-ethereum-private-blockchain-poa
titleAWS와 Puppeth를 활용한 Ethereum Private Blockchain (POA) 구축하기
body* 해당 포스팅은 [Using puppeth To Manually Create An Ethereum Proof Of Authority (Clique) Network On AWS](https://medium.com/@collin.cusce/using-puppeth-to-manually-create-an-ethereum-proof-of-authority-clique-network-on-aws-ae0d7c906cce) 포스팅을 참조하여 작성되었습니다. * 필자가 사용한 운영체제는 MacOS 입니다. > 포스팅 목적: 일반적으로 Private Network를 구축할 때 필요한 까다롭고 다소 번거로운 작업들을 빠르고 효율적으로 할 수 있는 Puppeth의 사용법과 AWS EC2에게 각 역할(faucet, wallet, dashboard etc...)을 부여하여 필수요소들으 갖춘 프라이빗 네트워크를 구축하는 방법을 알아본다. ## 1. 들어가기 전에 ### Proof Of Authority 먼저, Proof Of Authority(POA)에 대해 알아볼 필요가 있다. Proof Of Work와는 다르게 POA는 일반적인 노드들이 Miner로 참여할 수 없다. 그 말인 즉슨, 네트워크에 기여할 수 있는 혹은 네트워크를 운영하는 주체는 아무나 될 수 없다는 말이다. 네트워크를 운영할 수 있는 건 해당 네트워크를 제작한 설계자가 초기에 결정하게 되어 있다. > 여기서 네트워크를 운영한다는 말은 거래기록들을 담는 블록을 생성하는 컴퓨팅 작업을 의미한다. POW에서는 이 작업을 mining 이라 표현하고 작업을 진행하고 있는 노드를 miner라 칭한다. 그러나 POA에서는 이 작업을 signing이라 표현하고 작업을 진행하는 노드를 signer라고 표현한다. 처음 네트워크를 생성할 때 3개의 Sealer 노드를 지정했다면, 그 3개의 노드가 블록을 생성하는 역할을 담당하게 된다. 만약 특정 노드가 새로운 Sealer로 네트워크에 참여하고 싶다면, 기존의 Sealer들이 투표 매커니즘을 진행해서 참여여부를 결정해야 한다. 일반적으로 POW에서는 특정 이더리움 노드의 `genesis file` 그리고 `enode 정보`를 알고 있으면 네트워크에 접속해서 miner로 활동할 수 있었지만, POA에서는 그러한 작업이 기본적으로 차단되어 있다. 즉, 네트워크의 내용은 볼 수 있지만 블록을 생성하거나 거래를 검증하는 작업 등은 할 수 없다. 필자가 준비하고 있는 서비스에는 POA 환경이 좀 더 적합하기에 이더리움의 POA 합의 알고리즘 엔진(Clique)을 이용하여 환경구성을 진행해보려 한다. ## 2. AWS EC2 환경 구축 진행 ### 2.1 AWS EC2 포스팅에서 사용되는 EC2인스턴스들의 정보는 아래와 같다. * 컨트롤러 역할(다른 geth 노드들을 제어)을 하는 t2.micro Ubuntu 16.04 인스턴스 1개 * 노드 역할을 하는 t2.medium (10 gb) Ubuntu 16.04 인스턴스 3개 각 인스턴스를 생성할 때 주의할 점은 보안 그룹과 Keypair를 모두 동일한 세팅으로 맞춰줘야 한다는 점이다. 또한 puppeth 프로그램 소스코드 내에서 취급되는 키의 이름은 `id_rsa`이므로 동일한 이름으로 keypair를 생성해주는 게 좋다. keypair를 생성해주면 `id_rsa.pem` 파일을 다운로드 받을 수 있을 것이다. 각 인스턴스에 접근할 때 사용되므로 잘 보관해두도록 한다. 맥이나 리눅스의 경우 `~/.ssh` 디렉토리 내에 위치시켜두는 것이 좋다. 해당 디렉토리 내에서도 용도에 따라 구분할 수 있게 디렉토리를 생성하여 체계적으로 관리할 수 있도록 한다. 필자의 경우 `~/.ssh/AWS` 디렉토리 내에 모든 키를 보관한다. 이로써 `id_rsa.pem` 파일만 있으면 `ssh -i "id_rsa.pem" ubuntu@<ip of EC2 instance` 명령어 포맷으로 원격접속을 할 수 있게 된다. 다운로드 받은 키는 미리 실행권한을 400으로 바꿔주도록 한다. `chmod 400 id_rsa.pem` 명령으로 오직 관리자만이 write 권한을 가지게끔 변경해준다. AWS 인스턴스에 원격접속을 할 때는 실행권한이 400이 아니면 원격접속이 되지 않는다. ### 2.2 EC2 Security Setting 각 인스턴스는 아래의 보안 규칙을 따른다. 새로 생성하여 적용하도록 한다. 실제 서비스를 제작하여 운용할 방침이라면, 좀 더 깐깐하게 설정해주는 게 맞지만 테스트용이기 때문에 약간 더 넓게 설정해두었다. ![](https://cdn.steemitimages.com/DQmNae973aXjn5G5YG98h91bBTQsq4TCKnGy5EcbagEdXxU/image.png) 필자가 생성한 인스턴스 정보는 아래와 같다. 각 인스턴스의 이름도 신경써서 제작해주도록 하자. 필자의 인스턴스는 하나의 컨트롤러와 3개의 노드(0, 1, 2번)로 구성되어 있다. ``` // name, ip, vpc 순으로 기재했다. duel.poa.controller:52.79.234.126 vpc:172-31-31-148 t2.micro duel.poa.node0: 13.124.241.99 vpc: 172-31-30-127 t2.medium duel.poa.node1: 52.78.17.178 vpc: 172-31-17-195 t2.medium duel.poa.node2: 13.209.73.50 vpc: 172-31-22-46 t2.medium ``` `id_rsa.pem` 파일만 있으면 위 4개의 인스턴스에 얼마든지 접근할 수 있다. ### 2.3 Install Geth 각 인스턴스에 geth를 설치하는 작업을 진행한다. 이 포스티에서는 4개의 terminal를 띄워 명령어를 복사하여 실행하는 방법으로 진행한다. 하나의 인스턴스를 만들어 놓은 뒤 이미지로 따로 추출하여 해당 이미지로 인스턴스를 생성하는 방법이 존재하기 때문에, 이 방법을 이용해도 된다. 먼저 4개의 터미널에서 인스턴스에 접속한다. `id_rsa.pem`파일이 있는 폴더 내에서 아래의 명령을 실행하면 된다. ``` ssh -i "id_rsa.pem" [email protected] ssh -i "id_rsa.pem" [email protected] ssh -i "id_rsa.pem" [email protected] ssh -i "id_rsa.pem" [email protected] ``` 각 인스턴스에 원격접속을 했다면, 아래의 커맨드로 4개의 instance에 각각 적용해준다. ``` sudo apt-get install software-properties-common sudo add-apt-repository -y ppa:ethereum/ethereum sudo apt-get update sudo apt-get install ethereum ``` ## 3. 각 Node의 역할에 맞게 환경 구성 ### 3.1 Controller `t2.micro` 인스턴스 1개가 컨트롤러 역할을 진행한다. 나머지 3개의 `t2.medium` 인스턴스에 접근하고 제어하는 역할을 할 것이다. 위에서 EC2 인스턴스들을 생성하고 접근할 때 사용한 `id_rsa.pem` 파일의 내용을 복사해두도록 한다. 복사를 했으면 다음의 작업을 진행한다. > 복사를 진행한 이유: .pem 파일은 프라이빗 키로 사용된다. 퍼블릭 프라이빗 키 개념을 간단하게 설명하자면, 각 EC2 인스턴스에는 퍼블릭 키가 존재하고 해당 퍼블릭키와 매칭되는 프라이빗키가 존재할 때 프라이빗 키로 해당 인스턴스에 원격으로 접속할 수가 있다. * `cd ~/.ssh` 디렉토리에 접근하여 아래의 작업들을 진행한다. * `vim id_rsa.pem` 명령으로 파일을 생성한 후 복사한 내용(우리 컴퓨터에 존재하는 `id_rsa.pem` 파일의 내용)을 붙여넣는다. > 우리가 현재 사용하고 있는 컴퓨터에서 제어할 수 있지만 이렇게 했을 경우, 컴퓨터가 망가지거나 가지고 나오지 않았을 시 접근할 수 있는 방법이 존재하지 않는다. 따라서 별도의 컨트롤러 노드를 구성한 것이고 이 노드에서 각 인스턴스 노드에 접근하는 역할을 할 것이므로, 우리 컴퓨터에 있던 `id_rsa.pem` 파일을 그대로 Controller 노드에도 넣어주는 것이다. * `sudo perl -pi -e 'chomp if elf' id_rsa.pem` 명령을 실행하여 불필요한 라인들을 제거해준다. (있을 경우 제대로 키의 역할을 할 수 없게된다.) * 다른 노드를 컨트롤 할 때 사용할 자신만의 키를 생성해준다. 이미 `id_rsa.pem` 파일이 있는데 굳이 별도의 작업을 진행하는 이유는 `ssh ubuntu@<ip of node>` 명령어 만으로 각 노드에 접근하기 위해서다. 또한 `puppeth`를 실행할 때도 `puppeth`가 찾는 것은 `id_rsa.pub` 파일이고 파일을 별도로 지정하는 기능은 현재 `puppeth`에 구현되어 있지 않으므로 별도로 생성해주고 설정하는 작업이 필요한 것이다. * `ssh-keygen` 명령어로 키를 생성하며 passphrase를 묻는 입력란들이 나오면 전부 Enter를 치고 넘어간다. (원할 경우 따로 지정해줘도 상관은 없다. 실제로 서비스를 상용화할 때는 하는 것이 더 좋겠다.) * 명령어를 실행하면 `id_rsa, id_rsa.pub` 이라는 두 개의 파일이 생성된 것을 확인할 수 있다. 각각 개인키, 공개키를 의미한다. * 이제 각 t2.medium 노드들에 접근하기 위해 `~/.ssh/authorized_keys` 파일의 내용을 편집해줄 차례다. 다음 명령어를 실행해주도록 한다. `ssh -i id_rsa.pem ubuntu@<ip of node> 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub` 필자의 경우 아래와 같은 3개의 명령어를 Controller node에서 실행해주었다. ``` ssh -i id_rsa.pem [email protected] 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub ssh -i id_rsa.pem [email protected] 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub ssh -i id_rsa.pem [email protected] 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub ``` 명령어를 실행해준 이후에 Controller node(t2.micro)에서 `ssh ubuntu@<ip of node>`로 3개의 t2.medium 노드들에 접근이 되는지 확인해보고 접속이 되었다면 작업이 잘 마무리 된 것이다. ### 3.2 3개의 인스턴스(t2.medium)들을 설정 각 인스턴스의 의존성 문제를 해결, 그리고 도커를 사용하기 위해 아래의 모든 명령어를 각 인스턴스에서 실행하도록 한다. ``` sudo apt-get update sudo apt-get upgrade sudo apt-get install linux-image-extra-4.4.0–59-generic linux-image-extra-virtual sudo apt-get install \ apt-transport-https \ ca-certificates \ curl \ software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo apt-key fingerprint 0EBFCD88 sudo add-apt-repository \ “deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable” sudo apt-get update sudo apt-get install docker-ce sudo apt-get install docker-compose ``` 각 인스턴스를 재부팅하여 `docker ps` 명령으로 도커가 잘 실행되는지 확인해주도록 한다. ### 3.3 Controller 노드에서 Wallet 생성하기 `puppeth`를 이용하여 네트워크를 생성하기 전에 해줘야 할 작업들이 있는데, Ethereum Wallet을 생성하는 것과 pre-funded accounts를 미리 만들어두는 것이다. Controller(t2.micro)에서 해당 작업을 진행한다. #### 3.3.1 비밀번호 생성하기 각 계정을 사용할 때 필요한 비밀번호를 파일로 만들어 놓도록 한다. 필자의 경우 1234라는 비밀번호로 `passfile`에 내용을 기록했다. 파일을 생성한 후에 관리자에게 read, write, execute 권한을 부여한다. ``` cd ~/ethereum/duelnet vim passfile sudo perl -pi -e 'chomp if eof' passfile chmod 700 passfile ``` #### 3.3.2 이더리움 계정 10개 생성하기 계정을 미리 생성해둬야 `puppeth`를 이용해서 네트워크를 설정할 때 Signer의 역할을 특정 계정에 부여하고 미리 이더를 지급받을 수 있다. 따라서 간단한 쉘 스크립트를 제작하여 이더리움 계정을 생성해주도록 한다. 실습을 진행하기 전에 먼저 디렉토리 구조를 신경쓸 필요가 있다. 필자의 경우 먼저 `~/ethereum/duelnet/node`와 같은 구조로 디렉토리를 구성했고 향후 추가된 네트워크 설정이나 별도의 네트워크 설정을 구축하고 싶다면 `~/ethereum/<other network setup>`와 같이 디렉토리를 구성할 계획이다. 먼저, 하나의 계정을 생성하려면 다음의 명령을 터미널에서 입력한다. `geth --datadir ~/ethereum/duelnet/node` account new --password ~/passfile` 이 명령을 실행하면 `~/ethereum/duelnet/node` 디렉토리를 기준으로 geth의 설정이 적용된다. 방금 생성된 계정을 Sealer0라고 칭하도록 한다. Signer라는 명칭도 있지만, Sealer라는 명칭도 있다고 이해하면 된다. 스크립트 파일을 하나 생성(`vim ~/ethereum/duelnet/create_accounts.sh`)해주고 아래의 내용을 써주도록 한다. ``` for ((n=0; n<10; n++)); do geth --datadir ~/ethereum/duelnet/node account new --password ~/ethereum/duelnet/passfile; done ``` 그 후 `duelnet$ chmod +x create_accounts.sh` 명령어로 실해우건한을 추가시켜주고 `duelnet$ ./create_accounts.sh` 명령으로 스크립트를 실행하도록 한다. 10개의 계정이 추가로 생성되는 것을 확인할 수 있고 생성된 계정들을 따로 텍스트 편집기를 열어 기록을 해둔다. 필자의 경우 아래의 10개 계정들에 차례로 Sealer, Faucet과 같은 역할을 부여했다. ``` sealer0: 81bb2bfb72fc0ab991f79a58e9568d7cae57ccaa sealer1: 4a4961cd93da26276a22d5145a296c3a5a1b83fb sealer2: 78ddd4d1fa2036547687655fcac914852e558740 faucet: 3417cf2e1dea066db77239ad99f7e07f1e14cf0a accounts: d723a1aa820a5c5aa9ed1999e860f045038b2b05 5e5e07c810948e7e837679db1b51e02cc936afc2 096156b2c9a8043b6b288d0d40903f1dbe74b432 a0cff2ac0a0ca43fa0dcdb2b77b02bf6c3c2a86d 16966aebf2532170a04efe2eb05b4a1d1acc9b62 273dae58a042de73b4831cc7381020abe4921768 c730380e33404f2b90be965fc04e1050cac0555a ``` 검증을 하는 노드가 3개 있고, 네트워크 참가자들이 이더를 요청해서 받을 때 각 계정에게 전송시켜주는 faucet 노드가 1개 있다. 나머지 7개 노드들은 네트워크 내에 존재하는 일반 계정들로 의미를 부여했다. 이제 본격적으로 `puppeth`를 실행하도록 한다. ### 3.4 Puppeth를 사용하여 이더리움 네트워크 정의 및 생성 `~/ethereum/duelnet$ puppeth`로 명령을 실행한다. 각자의 디렉토리에서 `puppeth`를 입력하여 실행하면 된다. 실행한 뒤에 쭈욱 과정을 진행하면 되는데, 아래를 참조하도록 한다. ``` +-----------------------------------------------------------+ | Welcome to puppeth, your Ethereum private network manager | | | | This tool lets you create a new Ethereum network down to | | the genesis block, bootnodes, miners and ethstats servers | | without the hassle that it would normally entail. | | | | Puppeth uses SSH to dial in to remote servers, and builds | | its network components out of Docker containers using the | | docker-compose toolset. | +-----------------------------------------------------------+ // 자신이 생성할 네트워크 설정의 이름을 정한다. Please specify a network name to administer (no spaces or hyphens, please) > duelnet Sweet, you can set this via --network=duelnet_demo next time! INFO [08-08|09:39:10.290] Administering Ethereum network name=duelnet_demo WARN [08-08|09:39:10.291] No previous configurations found path=/home/ubuntu/.puppeth/duelnet_demo // 제네시스 파일을 새로 구성할 수 있는 2번을 선택한다. What would you like to do? (default = stats) 1. Show network stats 2. Configure new genesis 3. Track new remote server 4. Deploy network components > 2 // PoA 엔진인 Clique를 선택한다. Which consensus engine to use? (default = clique) 1. Ethash - proof-of-work 2. Clique - proof-of-authority > 2 // 블록의 생성시간을 기술해준다. How many seconds should blocks take? (default = 15) > 1 // 위에서 의미룰 부여해주었던 계정들을 쭈욱 적어준다. Which accounts are allowed to seal? (mandatory at least one) > 0x81bb2bfb72fc0ab991f79a58e9568d7cae57ccaa > 0x4a4961cd93da26276a22d5145a296c3a5a1b83fb > 0x78ddd4d1fa2036547687655fcac914852e558740 > 0x // sealer 노드들과 faucet, accounts 0~2까지 이더를 지급한다. // PoA에서는 채굴 과정이 따로 없기 때문에 sealer 노드를 제외한 다른 노드들이 faucet 말고는 이더를 지급받을 방법이 존재하지 않는다. Which accounts should be pre-funded? (advisable at least one) > 0x81bb2bfb72fc0ab991f79a58e9568d7cae57ccaa > 0x4a4961cd93da26276a22d5145a296c3a5a1b83fb > 0x78ddd4d1fa2036547687655fcac914852e558740 > 0x3417cf2e1dea066db77239ad99f7e07f1e14cf0a > 0xd723a1aa820a5c5aa9ed1999e860f045038b2b05 > 0x5e5e07c810948e7e837679db1b51e02cc936afc2 > 0x096156b2c9a8043b6b288d0d40903f1dbe74b432 > 0x // 디폴트로 랜덤한 네트워크 아이디를 생성해준다. Enter만 입력하고 넘어가자. Specify your chain/network ID if you want an explicit one (default = random) > INFO [08-08|09:40:54.552] Configured new genesis block // 위에서 생성한 제네시스 파일을 추출하기 위해 2번을 선택한다. What would you like to do? (default = stats) 1. Show network stats 2. Manage existing genesis 3. Track new remote server 4. Deploy network components > 2 1. Modify existing fork rules 2. Export genesis configuration 3. Remove genesis configuration > 2 // 디폴트로 설정하기 위해 Enter만 입력하여 진행 Which file to save the genesis into? (default = duelnet_demo.json) > INFO [08-08|09:40:58.932] Exported existing genesis block What would you like to do? (default = stats) 1. Show network stats 2. Manage existing genesis 3. Track new remote server 4. Deploy network components > Ctrl + c // 원하는 작업을 실행했으니 종료한다. ``` 생성된 제네시스 파일을 편집기로 열어보면 내용이 꽤 길다는 것을 확인할 수 있다. 이는 `puppeth`가 중간 중간 dummy accounts를 미리 생성해두었기 때문이다. 자신이 설정한 계정들을 제외하고는 전부 지워주어 파일을 보기 편리하게 만들어두는 것을 추천한다. 따로 조작하지 않아도 상관은 없다. #### 3.5 Get Wallet Keyfiles Sealer 노드들의 개인키를 복사하여 puppeth 내에서 사용가능하도록 환경을 구성할 것이다. 따라서 Sealer 노드들과 Faucet 노드의 개인키 파일의 내용을 따로 복사해두어 기록해두도록 한다. 아래와 같이 실행하여 나온 결과들을 따로 기록해두자. ``` Sealer 0: cat UTC--2018-08-08T09-27-37.241084125Z--81bb2bfb72fc0ab991f79a58e9568d7cae57ccaa Sealer 1: cat UTC--2018-08-08T09-33-06.102438431Z--4a4961cd93da26276a22d5145a296c3a5a1b83fb Sealer 2: cat UTC--2018-08-08T09-33-07.073882847Z--78ddd4d1fa2036547687655fcac914852e558740 Faucet: cat UTC--2018-08-08T09-33-08.031975188Z--3417cf2e1dea066db77239ad99f7e07f1e14cf0a ``` 각 명령어들에 대한 결과는 아래와 같고 아래의 내용들을 따로 기록해두면 된다. ``` Sealer 0: {"address":"81bb2bfb72fc0ab991f79a58e9568d7cae57ccaa","crypto":{"cipher":"aes-128-ctr","ciphertext":"a30dc751a3ec33bb36b8ce5ca78abe7dbdf8ca68892bc2c9f8509cfc49077ee1","cipherparams":{"iv":"2263fd6f213c7030abdc12b56acf3ce8"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"4c84fd7a79af24a7be3c5314b37aa08998ec69188c324181e19357ddc51497ce"},"mac":"eae031ffa5e046a8dd17d07d7b7f7c235cc0ea8c726f4eac32b0a302e7107754"},"id":"befc4d2e-9244-46d9-8227-cd37da8efd6f","version":3} Sealer 1: {"address":"4a4961cd93da26276a22d5145a296c3a5a1b83fb","crypto":{"cipher":"aes-128-ctr","ciphertext":"e176164bfd9fc6653e0ea3e418084af1de528a2dd10ffe29b9b35ea733f3ca9b","cipherparams":{"iv":"cd7ea7ae9426d56138d62cbb3e9b14dd"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"e82093953f5892b60c84749e98fb575e2acd1a43d4477f6ea6f682974a806d13"},"mac":"e6c56be76c1009fafc2c921ab1b331f7c3874590f9e5e6a8b36dc98169abfa28"},"id":"528c9ce2-b4fe-4403-be02-898c0a0b096b","version":3} Sealer 2: {"address":"78ddd4d1fa2036547687655fcac914852e558740","crypto":{"cipher":"aes-128-ctr","ciphertext":"1730c3d659528dafab59f854cccef85714cfab2f7e3c573058aa0e7c6bdc282a","cipherparams":{"iv":"f56a23b8b4d4377510655a775e90df2f"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"2373352ac9a663385100c45d93287263153e1dc020cbc884294370d261033450"},"mac":"7a745f562fd47a1cdf9e65597e76ceb4f7d27f4d469469ccea41f54ad733ea3d"},"id":"42356c9d-e3fd-4790-8c7f-9ca629d2f3f5","version":3} Faucet: {"address":"3417cf2e1dea066db77239ad99f7e07f1e14cf0a","crypto":{"cipher":"aes-128-ctr","ciphertext":"e9be248ab81f9a6b9536827fb53160a5567825628ec952d8599837e78e024cb5","cipherparams":{"iv":"48ec9dbf1ea1a555f5f8860f70f6d183"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"180ab095a7f3de3427a0b67028b5e5e74afa43cfc42310f9bb422268aa8a41b9"},"mac":"19e401009907e226b2c73bc7c06d33fb6bbc0fb90e378cd2afd33f0ad19f3019"},"id":"661b0dd8-0176-4beb-9fa7-bd81dcd2d533","version":3} ``` ## 4. Puppeth를 이용한 네트워크 배포 `puppeth --network duelnet` 와 같은 포맷으로 네트워크 옵션을 주어 자신이 기존에 생성해두었던 네트워크 세팅을 불러온다. 진행해야 할 작업들은 아래와 같다. ### 4.1 node0에게 Ethstat 역할을 부여한다. 1. 4. Deploy network components를 선택한다. `puppeth`에서 미리 제작해둔 편리한 기능들을 이용하여 각 노드들에 알맞은 역할을 부여하는 작업을 진행할 것이다. 2. 1. Connect another server를 선택한다. 3. 13.124.241.99 // 자신의 인스턴스 중 node0의 아이피 주소를 입력해준다. 4. 8080 // 다른 포트로 진행해도 상관은 없지만, 필자는 8080으로 설정했다. 5. n // 포트 공유를 하지 못하게 설정해놓는다. 온전한 서비스를 위해서. 6. secret password는 설정해도 되고 설정하지 않아도 된다. 위의 과정을 진행하면 아래와 같은 결과물을 확인할 수 있다. ``` Creating network "duelnet_default" with the default driver Building ethstats Step 1/2 : FROM puppeth/ethstats:latest latest: Pulling from puppeth/ethstats Digest: sha256:1728c03555d3327f68be924116eed9f9de56671949c21505f4b78518f06e687e Status: Downloaded newer image for puppeth/ethstats:latest ---> fb62abe59cb2 Step 2/2 : RUN echo 'module.exports = {trusted: ["13.124.241.99"], banned: [], reserved: ["yournode"]};' > lib/utils/config.js ---> Running in 08f875b59b9b ---> 2b43e5422c5d Removing intermediate container 08f875b59b9b Successfully built 2b43e5422c5d Creating duelnetdemo_ethstats_1 INFO [08-08|09:54:02.907] Starting remote server health-check server=13.124.241.99 +---------------+---------------+---------+--------+-------+ | SERVER | ADDRESS | SERVICE | CONFIG | VALUE | +---------------+---------------+---------+--------+-------+ | 13.124.241.99 | 13.124.241.99 | | | | +---------------+---------------+---------+--------+-------+ ``` 이로써 Ethstat이 동작함을 확인할 수 있다. `http://<ip of node0>:8080` 포맷으로 웹 브라우저 주소창에 검색해서 들어가면 Ethstat 페이지를 만나볼 수 있다. 우리가 한 작업을 요약하자면, Controller 노드에서 `puppeth`를 사용하여 `node0`(t2.medium)이 `Docker`를 활용하여 `Ethstat` 서비스를 실행하게끔 구성한 것이다. `puppeth`가 `node0`을 제어할 수 있었던 이유는 사전에 우리가 `public key, private key` 작업을 미리 해줬기 때문이다. ### 4.2 node0에게 Bootnode의 역할을 추가로 부여한다. 역할을 추가로 부여한다는 건 결국 해당 노드의 도커 컨테이너를 하나 더 생성해서 실행시켜준다는 의미다. `puppeth`를 실행하여 아래의 과정을 진행하여 부트노드를 동작 시켜보자. 1. 4. Manage network components 메뉴를 선택한다. 2. 2. Deploy new network component 항목을 선택한다. 3. 2. Bootnode 항목을 선택한다. 4. 1. 13.124.241.99를 선택한다. // 현재 Ethstat의 역할을 담당하고 있는 node0에게 추가로 권한을 부여하는 것이므로 node0의 ip주소를 그대로 사용하는 것이 맞다. 5. `/home/ubuntu/ethereum/duelnet/bootnode` // 이 포맷으로 Bootnode관련 데이터를 어디 저장시킬 것인지를 기술한다. 6. 나머지 옵션들(connecting peer number, light peers number)은 생략한다. 7. `duelnet_bootnode`으로 이름을 작성한다. // 해당 노드의 역할에 이름을 붙이는 것이라고 생각하면 된다. 실행하면 아래와 같은 결과를 만나볼 수 있다. ``` +---------------+---------------+----------+--------------------------+----------------------------------------+ | SERVER | ADDRESS | SERVICE | CONFIG | VALUE | +---------------+---------------+----------+--------------------------+----------------------------------------+ | 13.124.241.99 | 13.124.241.99 | bootnode | Data directory | /home/ubuntu/ethereum/duelnet/bootnode | | | | | Ethstats username | duelnet_bootnode | | | | | Listener port | 30305 | | | | | Peer count (all total) | 512 | | | | | Peer count (light nodes) | 256 | | | | | ------------------------ | -------------------------------------- | | | | ethstats | Banned addresses | | | | | | Login secret | 2326 | | | | | Website address | 13.124.241.99 | | | | | Website listener port | 8080 | +---------------+---------------+----------+--------------------------+----------------------------------------+ ``` ### 4.3 노드0, 노드1, 노드2에게 각각 Sealer 역할 부여 현재까지 노드0에서는 Ethstats 및 Bootnode 역할을 담당하고 있다. 이제는 블록 검증을 위한 Sealer 노드들을 설정하고 이용할 차례다. 아래의 과정을 각 노드(노드0 ~ 노드2)에게 진행하면 된다. 즉 Controller 노드에서 `puppeth`를 실행시키고 노드0~노드2의 ip주소를 각각 입력하여 Sealer 역할을 부여하면 된다. 1. 4. Deploy network components 메뉴를 선택한다. 2. 3. Deploy new network component 메뉴를 선택한다. // 참여하는 노드가 점점 많아질 수록 이 수치는 점점 높아진다. 3. 3. Sealer // 새로운 블록을 생성하는 Full node 역할을 담당하게 된다. 4. 2. Connect another server 메뉴를 선택해서 각 노드의 ip를 적용시켜주면 된다. 5. `/home/ubuntu/ethereum/duelnet/sealernode` 디렉토리를 데이터 디렉토리로 설정한다. 6. 나머지 옵션들(TCP/IP port, number of peer connections, light peers)은 default로 둬도 상관 없으므로 Enter로 넘어가도록 한다. 7. 이름을 지정해줘야 하므로 `duelnet_sealer_0, duelnet_sealer_1, duelnet_sealer2` 와 같이 체계적인 이름으로 각 노드의 역할에 이름을 부여한다. 위의 과정을 진행하여 3개의 노드가 Sealer 노드로 모두 참여시켜 네트워크를 구성한 후 다시한 번 웹 브라우저에서 Ethstats 방문한다면 아래와 같은 화면을 만나볼 수 있을 것이다. https://cdn.steemitimages.com/DQmbtRNUZqUYSkWsDRMKMujpjdx1br9RGouZouXt5eRJMhD/image.png Sealer 노드가 3개 존재하고 Bootnode가 존재하고 있다. 모든 노드들이 정상적으로 등록되고 인식되고 있다는 것을 확인할 수 있다. ### 4.4 채굴 진행해보기 (채굴이라 칭하기도 하고, Sealing | Validating로 불리기도 한다.) 지금까지 구성한 환경만으로는 아직 블록이 하나도 생성되지 않고 있다. `Ethstats` 에 웹브라우저로 접근하면 알 수 있다. 네트워크가 현재 멈춰 있으므로 채굴 과정을 진행시켜보겠다. 먼저 Controller node에서 `ssh ubuntu@<ip of boonode>` 를 입력하여 `Bootnode` 역할을 담당하고 있는 `node0`에게 접속한다. 그리고 `docker ps` 명령어로 현재 실행중인 컨테이너를 확인한다. 명령의 결과는 아래와 같다. ``` CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c1efa7cbe17f duelnet/sealnode "/bin/sh geth.sh" 11 minutes ago Up 11 minutes 8545-8546/tcp, 0.0.0.0:30303->30303/tcp, 0.0.0.0:30303->30303/udp duelnet_sealnode_1 8266f6a9d2d2 duelnet/bootnode "/bin/sh geth.sh" 22 minutes ago Up 22 minutes 8545-8546/tcp, 30303/tcp, 30303/udp, 0.0.0.0:30305->30305/tcp, 0.0.0.0:30305->30305/udp duelnet_bootnode_1 0a1265c25972 duelnet/ethstats "npm start" 33 minutes ago Up 33 minutes 0.0.0.0:8080->3000/tcp duelnet_ethstats_1 ``` 가장 첫번째로 출력되는 `duelnet/sealnode`의 `CONTAINER ID` 를 확인하여 다음의 명령어 포맷으로 `geth` 콘솔을 실행하도록 하자. `docker exec -it <container_id> ` geth attach ipc:/root/.ethereum/geth.ipc` 필자의 경우는 `docker exec -it c1e geth attach` 명령으로 `geth console`을 실행할 수 있었다. 콘솔에 접근한 이유는 해당 노드의 `enode` 정보를 알아내기 위한 것이다. 콘솔 내에서 `admin.nodeInfo.enode` 명령으로 해당 노드의 `enode`정보를 추출하고 위 작업을 node1, node2에게도 동일하게 진행한다. 각 과정을 진행하면서 `enode` 정보를 기록하고, 그렇게 하면 아래와 같은 정보를 얻어낼 수 있을 것이다. ``` Sealer 0: "enode://ec9046bc66b3c5f940bcb8023f127aa721da61c02ae4906e8e2c738295aa17bf18acbcb5f27f21f026f4b37eb44fe24e0b674ac69a01e4db0b4a4007a5e5e6b2@13.124.241.98:30303" Sealer 1: "enode://cf47010e6b3a855511eb719cfd29c6b80e74e7e5a023878eaf393fc157b9f9a7704f6650f7719a247c64cf68903738233483f83a7081e12a4f641c11564e7431@52.78.17.178:30303" Sealer 2: "enode://87789df6d972fc357384606cd833dc8529a178cfde411d81125ba229c8be1e1425483ca97da055a2a5bc8419d38c859181ff152678e7f7bc6c5339090e4122db@13.209.73.50:30303" ``` 기억한 `enode` 정보를 가지고 `Bootnode` 역할을 맡고 있는 node0의 `geth console`을 실행시켜 다음의 명령어 포맷으로 각 노드를 연결시켜주도록 한다. `admin.addPeer("<enode from other nodes>")` 현재 노드0에서 실행하고 있으므로 노드1과 노드2의 `enode` 정보를 확인한 후에 적용시켜주면 된다. ## 5. 나머지 서비스 구현 > 나머지 서비스들은 모두 Ethstats 서비스를 제공하고 있는 노드0에서 이루어져야 한다. 구축해야 할 서비스들은 아래와 같다. 1. The MyCrypto wallet app 2. A faucet 3. A block explorer (PoA 네트워크에서는 아직 지원되지 않는다.) 4. A dashboard to tie it all together `puppeth` 를 사용하여 배포할 때 헷갈리는 점이 있는 건 `faucet app` 뿐이므로 해당 절차만 기술하도록 하겠다. 나머지는 필요에 따라 본인이 직접 조작해보는 걸 추천한다. ### 5.1 Wallet App ### 5.2 Faucet App 특이하게도 `reCAPCHA v2` 서비스의 `Site key` `Secret key`를 요구한다. 이 경우 `reCAPCHA` 사이트에 접속하여 생성할 수 있고 생성하여 얻은 각 키 정보를 입력해주면 된다. ### 5.3 Dashboard ## 6. 마치며 개발자가 해야할 일을 대폭 줄여주는 `puppeth`는 확실히 효자 프로그램이라 할 수 있다. 그러나 여전히 근본적인 구조에 대한 이해는 필요하다고 생각한다. 각 앱을 구현하는데 있어서 필요한 정보가 어떤 것이 있을지 생각해보고 `puppeth` 를 이용하는 것이 개발 실력 뿐만 아니라 통찰에도 많은 도움을 줄 거라 생각한다. 마침 아직 PoA에 관한 `Block Explorer` 는`puppeth` 에서 제공하지 않으니 직접 구현해보는 건 어떨까? 이번 포스팅은 여기서 마치도록 한다.
json metadata{"tags":["ethereum","poa","blockchain","privateblockchain","puppeth"],"image":["https://cdn.steemitimages.com/DQmNae973aXjn5G5YG98h91bBTQsq4TCKnGy5EcbagEdXxU/image.png","https://cdn.steemitimages.com/DQmbtRNUZqUYSkWsDRMKMujpjdx1br9RGouZouXt5eRJMhD/image.png"],"links":["https://medium.com/@collin.cusce/using-puppeth-to-manually-create-an-ethereum-proof-of-authority-clique-network-on-aws-ae0d7c906cce"],"app":"steemit/0.1","format":"markdown"}
Transaction InfoBlock #25237988/Trx e88b304c14e995025d36f9f64279ab0853078046
View Raw JSON Data
{
  "trx_id": "e88b304c14e995025d36f9f64279ab0853078046",
  "block": 25237988,
  "trx_in_block": 14,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-08-20T16:36:36",
  "op": [
    "comment",
    {
      "parent_author": "",
      "parent_permlink": "ethereum",
      "author": "dlgusdn616",
      "permlink": "aws-puppeth-ethereum-private-blockchain-poa",
      "title": "AWS와 Puppeth를 활용한 Ethereum Private Blockchain (POA) 구축하기",
      "body": "* 해당 포스팅은 [Using puppeth To Manually Create An Ethereum Proof Of Authority (Clique) Network On AWS](https://medium.com/@collin.cusce/using-puppeth-to-manually-create-an-ethereum-proof-of-authority-clique-network-on-aws-ae0d7c906cce)  포스팅을 참조하여 작성되었습니다.\n\n* 필자가 사용한 운영체제는 MacOS 입니다.\n\n> 포스팅 목적: 일반적으로 Private Network를 구축할 때 필요한 까다롭고 다소 번거로운 작업들을 빠르고 효율적으로 할 수 있는 Puppeth의 사용법과 AWS EC2에게 각 역할(faucet, wallet, dashboard etc...)을 부여하여 필수요소들으 갖춘 프라이빗 네트워크를 구축하는 방법을 알아본다.\n\n## 1. 들어가기 전에\n###  Proof Of Authority\n먼저, Proof Of Authority(POA)에 대해 알아볼 필요가 있다. Proof Of Work와는 다르게 POA는 일반적인 노드들이 Miner로 참여할 수 없다. 그 말인 즉슨, 네트워크에 기여할 수 있는 혹은 네트워크를 운영하는 주체는 아무나 될 수 없다는 말이다. 네트워크를 운영할 수 있는 건 해당 네트워크를 제작한 설계자가 초기에 결정하게 되어 있다. \n> 여기서 네트워크를 운영한다는 말은 거래기록들을 담는 블록을 생성하는 컴퓨팅 작업을 의미한다. POW에서는 이 작업을 mining 이라 표현하고 작업을 진행하고 있는 노드를 miner라 칭한다. 그러나 POA에서는 이 작업을 signing이라 표현하고 작업을 진행하는 노드를  signer라고 표현한다.\n\n처음 네트워크를 생성할 때 3개의 Sealer 노드를 지정했다면, 그 3개의 노드가 블록을 생성하는 역할을 담당하게 된다. 만약 특정 노드가 새로운 Sealer로 네트워크에 참여하고 싶다면, 기존의 Sealer들이 투표 매커니즘을 진행해서 참여여부를 결정해야 한다.\n\n일반적으로 POW에서는 특정 이더리움 노드의 `genesis file` 그리고  `enode 정보`를 알고 있으면 네트워크에 접속해서 miner로 활동할 수 있었지만, POA에서는 그러한 작업이 기본적으로 차단되어 있다. 즉, 네트워크의 내용은 볼 수 있지만 블록을 생성하거나 거래를 검증하는 작업 등은 할 수 없다.\n\n필자가 준비하고 있는 서비스에는 POA 환경이 좀 더 적합하기에 이더리움의 POA 합의 알고리즘 엔진(Clique)을 이용하여 환경구성을 진행해보려 한다.\n\n## 2. AWS EC2 환경 구축 진행\n### 2.1 AWS EC2\n포스팅에서 사용되는 EC2인스턴스들의 정보는 아래와 같다. \n* 컨트롤러 역할(다른 geth 노드들을 제어)을 하는 t2.micro Ubuntu 16.04 인스턴스 1개\n* 노드 역할을 하는 t2.medium (10 gb) Ubuntu 16.04 인스턴스 3개\n\n각 인스턴스를 생성할 때 주의할 점은 보안 그룹과 Keypair를 모두 동일한 세팅으로 맞춰줘야 한다는 점이다. 또한 puppeth 프로그램 소스코드 내에서 취급되는 키의 이름은 `id_rsa`이므로 동일한 이름으로 keypair를 생성해주는 게 좋다.\n\nkeypair를 생성해주면 `id_rsa.pem` 파일을 다운로드 받을 수 있을 것이다. 각 인스턴스에 접근할 때 사용되므로 잘 보관해두도록 한다. 맥이나 리눅스의 경우  `~/.ssh` 디렉토리 내에 위치시켜두는 것이 좋다. 해당 디렉토리 내에서도 용도에 따라 구분할 수 있게 디렉토리를 생성하여 체계적으로 관리할 수 있도록 한다. 필자의 경우 `~/.ssh/AWS` 디렉토리 내에 모든 키를 보관한다.\n\n이로써 `id_rsa.pem` 파일만 있으면 `ssh -i \"id_rsa.pem\" ubuntu@<ip of EC2 instance` 명령어 포맷으로 원격접속을 할 수 있게 된다.\n\n다운로드 받은 키는 미리 실행권한을 400으로 바꿔주도록 한다. `chmod 400 id_rsa.pem` 명령으로 오직 관리자만이 write 권한을 가지게끔 변경해준다. AWS 인스턴스에 원격접속을 할 때는 실행권한이 400이 아니면 원격접속이 되지 않는다. \n\n### 2.2 EC2 Security Setting\n각 인스턴스는 아래의 보안 규칙을 따른다. 새로 생성하여 적용하도록 한다. 실제 서비스를 제작하여 운용할 방침이라면, 좀 더 깐깐하게 설정해주는 게 맞지만 테스트용이기 때문에 약간 더 넓게 설정해두었다.\n![](https://cdn.steemitimages.com/DQmNae973aXjn5G5YG98h91bBTQsq4TCKnGy5EcbagEdXxU/image.png)\n\n필자가 생성한 인스턴스 정보는 아래와 같다. 각 인스턴스의 이름도 신경써서 제작해주도록 하자. 필자의 인스턴스는 하나의 컨트롤러와 3개의 노드(0, 1, 2번)로 구성되어 있다.\n```\n// name, ip, vpc 순으로 기재했다.\nduel.poa.controller:52.79.234.126\tvpc:172-31-31-148\tt2.micro\nduel.poa.node0:\t\t13.124.241.99\tvpc: 172-31-30-127\tt2.medium\nduel.poa.node1:\t\t52.78.17.178\tvpc: 172-31-17-195\tt2.medium\nduel.poa.node2:\t\t13.209.73.50\tvpc: 172-31-22-46\tt2.medium\n```\n\n`id_rsa.pem` 파일만 있으면 위 4개의 인스턴스에 얼마든지 접근할 수 있다.\n\n### 2.3 Install Geth\n각 인스턴스에 geth를 설치하는 작업을 진행한다. 이 포스티에서는 4개의 terminal를 띄워 명령어를 복사하여 실행하는 방법으로 진행한다.\n하나의 인스턴스를 만들어 놓은 뒤 이미지로 따로 추출하여 해당 이미지로 인스턴스를 생성하는 방법이 존재하기 때문에, 이 방법을 이용해도 된다.\n\n먼저 4개의 터미널에서 인스턴스에 접속한다. `id_rsa.pem`파일이 있는 폴더 내에서 아래의 명령을 실행하면 된다.\n```\nssh -i \"id_rsa.pem\" [email protected]\nssh -i \"id_rsa.pem\" [email protected]\nssh -i \"id_rsa.pem\" [email protected]\nssh -i \"id_rsa.pem\" [email protected]\n```\n각 인스턴스에 원격접속을 했다면, 아래의 커맨드로 4개의 instance에 각각 적용해준다.\n```\nsudo apt-get install software-properties-common\nsudo add-apt-repository -y ppa:ethereum/ethereum\nsudo apt-get update\nsudo apt-get install ethereum\n```\n\n## 3. 각 Node의 역할에 맞게 환경 구성\n### 3.1 Controller\n`t2.micro` 인스턴스 1개가 컨트롤러 역할을 진행한다. 나머지 3개의 `t2.medium` 인스턴스에 접근하고 제어하는 역할을 할 것이다. 위에서 EC2 인스턴스들을 생성하고 접근할 때 사용한 `id_rsa.pem` 파일의 내용을 복사해두도록 한다. 복사를 했으면 다음의 작업을 진행한다.\n> 복사를 진행한 이유: .pem 파일은 프라이빗 키로 사용된다. 퍼블릭 프라이빗 키 개념을 간단하게 설명하자면, 각 EC2 인스턴스에는 퍼블릭 키가 존재하고 해당 퍼블릭키와 매칭되는 프라이빗키가 존재할 때 프라이빗 키로 해당 인스턴스에 원격으로 접속할 수가 있다.\n\n* `cd ~/.ssh` 디렉토리에 접근하여 아래의 작업들을 진행한다.\n* `vim id_rsa.pem` 명령으로 파일을 생성한 후 복사한 내용(우리 컴퓨터에 존재하는 `id_rsa.pem` 파일의 내용)을 붙여넣는다.\n\n> 우리가 현재 사용하고 있는 컴퓨터에서 제어할 수 있지만 이렇게 했을 경우, 컴퓨터가 망가지거나 가지고 나오지 않았을 시 접근할 수 있는 방법이 존재하지 않는다. 따라서 별도의 컨트롤러 노드를 구성한 것이고 이 노드에서 각 인스턴스 노드에 접근하는 역할을 할 것이므로, 우리 컴퓨터에 있던 `id_rsa.pem` 파일을 그대로 Controller 노드에도 넣어주는 것이다.\n\n\n* `sudo perl -pi -e 'chomp if elf' id_rsa.pem` 명령을 실행하여 불필요한 라인들을 제거해준다. (있을 경우 제대로 키의 역할을 할 수 없게된다.)\n* 다른 노드를 컨트롤 할 때 사용할 자신만의 키를 생성해준다. 이미 `id_rsa.pem` 파일이 있는데 굳이 별도의 작업을 진행하는 이유는 `ssh ubuntu@<ip of node>` 명령어 만으로 각 노드에 접근하기 위해서다. 또한 `puppeth`를 실행할 때도 `puppeth`가 찾는 것은 `id_rsa.pub` 파일이고 파일을 별도로 지정하는 기능은 현재 `puppeth`에 구현되어 있지 않으므로 별도로 생성해주고 설정하는 작업이 필요한 것이다.\n*  `ssh-keygen` 명령어로 키를 생성하며 passphrase를 묻는 입력란들이 나오면 전부 Enter를 치고 넘어간다. (원할 경우 따로 지정해줘도 상관은 없다. 실제로 서비스를 상용화할 때는 하는 것이 더 좋겠다.)\n* 명령어를 실행하면 `id_rsa, id_rsa.pub` 이라는 두 개의 파일이 생성된 것을 확인할 수 있다. 각각 개인키, 공개키를 의미한다.\n* 이제 각 t2.medium 노드들에 접근하기 위해 `~/.ssh/authorized_keys` 파일의 내용을 편집해줄 차례다. 다음 명령어를 실행해주도록 한다. `ssh -i id_rsa.pem ubuntu@<ip of node> 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub`\n필자의 경우 아래와 같은 3개의 명령어를 Controller node에서 실행해주었다.\n```\nssh -i id_rsa.pem [email protected] 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub\nssh -i id_rsa.pem [email protected] 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub\nssh -i id_rsa.pem [email protected] 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub\n```\n\n명령어를 실행해준 이후에 Controller node(t2.micro)에서 `ssh ubuntu@<ip of node>`로 3개의 t2.medium 노드들에 접근이 되는지 확인해보고 접속이 되었다면 작업이 잘 마무리 된 것이다.\n\n### 3.2 3개의 인스턴스(t2.medium)들을 설정\n각 인스턴스의 의존성 문제를 해결, 그리고 도커를 사용하기 위해 아래의 모든 명령어를 각 인스턴스에서 실행하도록 한다. \n```\nsudo apt-get update\nsudo apt-get upgrade\nsudo apt-get install linux-image-extra-4.4.0–59-generic linux-image-extra-virtual\nsudo apt-get install \\\n apt-transport-https \\\n ca-certificates \\\n curl \\\n software-properties-common\ncurl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -\nsudo apt-key fingerprint 0EBFCD88\nsudo add-apt-repository \\\n “deb [arch=amd64] https://download.docker.com/linux/ubuntu \\\n $(lsb_release -cs) \\\n stable”\nsudo apt-get update\nsudo apt-get install docker-ce\nsudo apt-get install docker-compose\n```\n각 인스턴스를 재부팅하여 `docker ps` 명령으로 도커가 잘 실행되는지 확인해주도록 한다.\n\n### 3.3 Controller 노드에서 Wallet 생성하기\n`puppeth`를 이용하여 네트워크를 생성하기 전에 해줘야 할 작업들이 있는데, Ethereum Wallet을 생성하는 것과 pre-funded accounts를 미리 만들어두는 것이다. Controller(t2.micro)에서 해당 작업을 진행한다.\n\n#### 3.3.1 비밀번호 생성하기\n각 계정을 사용할 때 필요한 비밀번호를 파일로 만들어 놓도록 한다. 필자의 경우 1234라는 비밀번호로 `passfile`에 내용을 기록했다. 파일을 생성한 후에 관리자에게 read, write, execute 권한을 부여한다.\n```\ncd ~/ethereum/duelnet\nvim passfile\nsudo perl -pi -e 'chomp if eof' passfile\nchmod 700 passfile\n```\n\n#### 3.3.2 이더리움 계정 10개 생성하기\n계정을 미리 생성해둬야 `puppeth`를 이용해서 네트워크를 설정할 때 Signer의 역할을 특정 계정에 부여하고 미리 이더를 지급받을 수 있다. 따라서 간단한 쉘 스크립트를 제작하여 이더리움 계정을 생성해주도록 한다.\n\n실습을 진행하기 전에 먼저 디렉토리 구조를 신경쓸 필요가 있다. 필자의 경우 먼저 `~/ethereum/duelnet/node`와 같은 구조로 디렉토리를 구성했고 향후 추가된 네트워크 설정이나 별도의 네트워크 설정을 구축하고 싶다면 `~/ethereum/<other network setup>`와 같이 디렉토리를 구성할 계획이다.\n\n먼저, 하나의 계정을 생성하려면 다음의 명령을 터미널에서 입력한다. `geth --datadir ~/ethereum/duelnet/node` account new --password ~/passfile` 이 명령을 실행하면 `~/ethereum/duelnet/node` 디렉토리를 기준으로 geth의 설정이 적용된다.\n\n방금 생성된 계정을 Sealer0라고 칭하도록 한다. Signer라는 명칭도 있지만, Sealer라는 명칭도 있다고 이해하면 된다. 스크립트 파일을 하나 생성(`vim ~/ethereum/duelnet/create_accounts.sh`)해주고 아래의 내용을 써주도록 한다.\n```\nfor ((n=0; n<10; n++)); do geth --datadir ~/ethereum/duelnet/node account new --password ~/ethereum/duelnet/passfile; done\n```\n그 후 `duelnet$ chmod +x create_accounts.sh` 명령어로 실해우건한을 추가시켜주고 `duelnet$ ./create_accounts.sh` 명령으로 스크립트를 실행하도록 한다. \n\n10개의 계정이 추가로 생성되는 것을 확인할 수 있고 생성된 계정들을 따로 텍스트 편집기를 열어 기록을 해둔다. 필자의 경우 아래의 10개 계정들에 차례로 Sealer, Faucet과 같은 역할을 부여했다.\n```\nsealer0: 81bb2bfb72fc0ab991f79a58e9568d7cae57ccaa\nsealer1: 4a4961cd93da26276a22d5145a296c3a5a1b83fb\nsealer2: 78ddd4d1fa2036547687655fcac914852e558740\nfaucet: 3417cf2e1dea066db77239ad99f7e07f1e14cf0a\n\naccounts:\nd723a1aa820a5c5aa9ed1999e860f045038b2b05\n5e5e07c810948e7e837679db1b51e02cc936afc2\n096156b2c9a8043b6b288d0d40903f1dbe74b432\na0cff2ac0a0ca43fa0dcdb2b77b02bf6c3c2a86d\n16966aebf2532170a04efe2eb05b4a1d1acc9b62\n273dae58a042de73b4831cc7381020abe4921768\nc730380e33404f2b90be965fc04e1050cac0555a\n```\n검증을 하는 노드가 3개 있고,  네트워크 참가자들이 이더를 요청해서 받을 때 각 계정에게 전송시켜주는 faucet 노드가 1개 있다. 나머지 7개 노드들은 네트워크 내에 존재하는 일반 계정들로 의미를 부여했다.\n\n이제 본격적으로 `puppeth`를 실행하도록 한다.\n\n### 3.4 Puppeth를 사용하여 이더리움 네트워크 정의 및 생성\n`~/ethereum/duelnet$ puppeth`로 명령을 실행한다. 각자의 디렉토리에서 `puppeth`를 입력하여 실행하면 된다. 실행한 뒤에 쭈욱 과정을 진행하면 되는데, 아래를 참조하도록 한다.\n```\n+-----------------------------------------------------------+\n| Welcome to puppeth, your Ethereum private network manager |\n|                                                           |\n| This tool lets you create a new Ethereum network down to  |\n| the genesis block, bootnodes, miners and ethstats servers |\n| without the hassle that it would normally entail.         |\n|                                                           |\n| Puppeth uses SSH to dial in to remote servers, and builds |\n| its network components out of Docker containers using the |\n| docker-compose toolset.                                   |\n+-----------------------------------------------------------+\n\n// 자신이 생성할 네트워크 설정의 이름을 정한다.\nPlease specify a network name to administer (no spaces or hyphens, please)\n> duelnet\n\nSweet, you can set this via --network=duelnet_demo next time!\n\nINFO [08-08|09:39:10.290] Administering Ethereum network           name=duelnet_demo\nWARN [08-08|09:39:10.291] No previous configurations found         path=/home/ubuntu/.puppeth/duelnet_demo\n\n// 제네시스 파일을 새로 구성할 수 있는 2번을 선택한다.\nWhat would you like to do? (default = stats)\n 1. Show network stats\n 2. Configure new genesis\n 3. Track new remote server\n 4. Deploy network components\n> 2\n\n// PoA 엔진인 Clique를 선택한다.\nWhich consensus engine to use? (default = clique)\n 1. Ethash - proof-of-work\n 2. Clique - proof-of-authority\n> 2\n\n// 블록의 생성시간을 기술해준다.\nHow many seconds should blocks take? (default = 15)\n> 1\n\n// 위에서 의미룰 부여해주었던 계정들을 쭈욱 적어준다.\nWhich accounts are allowed to seal? (mandatory at least one)\n> 0x81bb2bfb72fc0ab991f79a58e9568d7cae57ccaa\n> 0x4a4961cd93da26276a22d5145a296c3a5a1b83fb\n> 0x78ddd4d1fa2036547687655fcac914852e558740\n> 0x\n\n// sealer 노드들과 faucet, accounts 0~2까지 이더를 지급한다.\n// PoA에서는 채굴 과정이 따로 없기 때문에 sealer 노드를 제외한 다른 노드들이 faucet 말고는 이더를 지급받을 방법이 존재하지 않는다.\nWhich accounts should be pre-funded? (advisable at least one)\n> 0x81bb2bfb72fc0ab991f79a58e9568d7cae57ccaa\n> 0x4a4961cd93da26276a22d5145a296c3a5a1b83fb\n> 0x78ddd4d1fa2036547687655fcac914852e558740\n> 0x3417cf2e1dea066db77239ad99f7e07f1e14cf0a\n> 0xd723a1aa820a5c5aa9ed1999e860f045038b2b05\n> 0x5e5e07c810948e7e837679db1b51e02cc936afc2\n> 0x096156b2c9a8043b6b288d0d40903f1dbe74b432\n> 0x\n\n// 디폴트로 랜덤한 네트워크 아이디를 생성해준다. Enter만 입력하고 넘어가자.\nSpecify your chain/network ID if you want an explicit one (default = random)\n>\nINFO [08-08|09:40:54.552] Configured new genesis block\n\n// 위에서 생성한 제네시스 파일을 추출하기 위해 2번을 선택한다.\nWhat would you like to do? (default = stats)\n 1. Show network stats\n 2. Manage existing genesis\n 3. Track new remote server\n 4. Deploy network components\n> 2\n\n 1. Modify existing fork rules\n 2. Export genesis configuration\n 3. Remove genesis configuration\n> 2\n\n// 디폴트로 설정하기 위해 Enter만 입력하여 진행\nWhich file to save the genesis into? (default = duelnet_demo.json)\n>\nINFO [08-08|09:40:58.932] Exported existing genesis block\n\nWhat would you like to do? (default = stats)\n 1. Show network stats\n 2. Manage existing genesis\n 3. Track new remote server\n 4. Deploy network components\n> Ctrl + c // 원하는 작업을 실행했으니 종료한다.\n```\n\n생성된 제네시스 파일을 편집기로 열어보면 내용이 꽤 길다는 것을 확인할 수 있다. 이는 `puppeth`가 중간 중간 dummy accounts를 미리 생성해두었기 때문이다. 자신이 설정한 계정들을 제외하고는 전부 지워주어 파일을 보기 편리하게 만들어두는 것을 추천한다. 따로 조작하지 않아도 상관은 없다.\n\n#### 3.5 Get Wallet Keyfiles\nSealer 노드들의 개인키를 복사하여 puppeth 내에서 사용가능하도록 환경을 구성할 것이다. 따라서 Sealer 노드들과 Faucet 노드의 개인키 파일의 내용을 따로 복사해두어 기록해두도록 한다. 아래와 같이 실행하여 나온 결과들을 따로 기록해두자.\n```\nSealer 0:\ncat UTC--2018-08-08T09-27-37.241084125Z--81bb2bfb72fc0ab991f79a58e9568d7cae57ccaa\nSealer 1:\ncat UTC--2018-08-08T09-33-06.102438431Z--4a4961cd93da26276a22d5145a296c3a5a1b83fb\nSealer 2:\ncat UTC--2018-08-08T09-33-07.073882847Z--78ddd4d1fa2036547687655fcac914852e558740\nFaucet:\ncat UTC--2018-08-08T09-33-08.031975188Z--3417cf2e1dea066db77239ad99f7e07f1e14cf0a\n```\n각 명령어들에 대한 결과는 아래와 같고 아래의 내용들을 따로 기록해두면 된다.\n```\nSealer 0:\n{\"address\":\"81bb2bfb72fc0ab991f79a58e9568d7cae57ccaa\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"ciphertext\":\"a30dc751a3ec33bb36b8ce5ca78abe7dbdf8ca68892bc2c9f8509cfc49077ee1\",\"cipherparams\":{\"iv\":\"2263fd6f213c7030abdc12b56acf3ce8\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"4c84fd7a79af24a7be3c5314b37aa08998ec69188c324181e19357ddc51497ce\"},\"mac\":\"eae031ffa5e046a8dd17d07d7b7f7c235cc0ea8c726f4eac32b0a302e7107754\"},\"id\":\"befc4d2e-9244-46d9-8227-cd37da8efd6f\",\"version\":3}\n\nSealer 1:\n{\"address\":\"4a4961cd93da26276a22d5145a296c3a5a1b83fb\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"ciphertext\":\"e176164bfd9fc6653e0ea3e418084af1de528a2dd10ffe29b9b35ea733f3ca9b\",\"cipherparams\":{\"iv\":\"cd7ea7ae9426d56138d62cbb3e9b14dd\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"e82093953f5892b60c84749e98fb575e2acd1a43d4477f6ea6f682974a806d13\"},\"mac\":\"e6c56be76c1009fafc2c921ab1b331f7c3874590f9e5e6a8b36dc98169abfa28\"},\"id\":\"528c9ce2-b4fe-4403-be02-898c0a0b096b\",\"version\":3}\n\nSealer 2:\n{\"address\":\"78ddd4d1fa2036547687655fcac914852e558740\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"ciphertext\":\"1730c3d659528dafab59f854cccef85714cfab2f7e3c573058aa0e7c6bdc282a\",\"cipherparams\":{\"iv\":\"f56a23b8b4d4377510655a775e90df2f\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"2373352ac9a663385100c45d93287263153e1dc020cbc884294370d261033450\"},\"mac\":\"7a745f562fd47a1cdf9e65597e76ceb4f7d27f4d469469ccea41f54ad733ea3d\"},\"id\":\"42356c9d-e3fd-4790-8c7f-9ca629d2f3f5\",\"version\":3}\n\nFaucet:\n{\"address\":\"3417cf2e1dea066db77239ad99f7e07f1e14cf0a\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"ciphertext\":\"e9be248ab81f9a6b9536827fb53160a5567825628ec952d8599837e78e024cb5\",\"cipherparams\":{\"iv\":\"48ec9dbf1ea1a555f5f8860f70f6d183\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"180ab095a7f3de3427a0b67028b5e5e74afa43cfc42310f9bb422268aa8a41b9\"},\"mac\":\"19e401009907e226b2c73bc7c06d33fb6bbc0fb90e378cd2afd33f0ad19f3019\"},\"id\":\"661b0dd8-0176-4beb-9fa7-bd81dcd2d533\",\"version\":3}\n```\n\n## 4. Puppeth를 이용한 네트워크 배포\n`puppeth --network duelnet` 와 같은 포맷으로 네트워크 옵션을 주어 자신이 기존에 생성해두었던 네트워크 세팅을 불러온다. 진행해야 할 작업들은 아래와 같다.\n\n### 4.1 node0에게 Ethstat 역할을 부여한다.\n\n1. 4. Deploy network components를 선택한다. `puppeth`에서 미리 제작해둔 편리한 기능들을 이용하여 각 노드들에 알맞은 역할을 부여하는 작업을 진행할 것이다.\n2. 1. Connect another server를 선택한다.\n3. 13.124.241.99 // 자신의 인스턴스 중 node0의 아이피 주소를 입력해준다.\n4. 8080 // 다른 포트로 진행해도 상관은 없지만, 필자는 8080으로 설정했다.\n5. n // 포트 공유를 하지 못하게 설정해놓는다. 온전한 서비스를 위해서.\n6. secret password는 설정해도 되고 설정하지 않아도 된다.\n\n위의 과정을 진행하면 아래와 같은 결과물을 확인할 수 있다.\n```\nCreating network \"duelnet_default\" with the default driver\nBuilding ethstats\nStep 1/2 : FROM puppeth/ethstats:latest\nlatest: Pulling from puppeth/ethstats\nDigest: sha256:1728c03555d3327f68be924116eed9f9de56671949c21505f4b78518f06e687e\nStatus: Downloaded newer image for puppeth/ethstats:latest\n ---> fb62abe59cb2\nStep 2/2 : RUN echo 'module.exports = {trusted: [\"13.124.241.99\"], banned: [], reserved: [\"yournode\"]};' > lib/utils/config.js\n ---> Running in 08f875b59b9b\n ---> 2b43e5422c5d\nRemoving intermediate container 08f875b59b9b\nSuccessfully built 2b43e5422c5d\nCreating duelnetdemo_ethstats_1\nINFO [08-08|09:54:02.907] Starting remote server health-check      server=13.124.241.99\n+---------------+---------------+---------+--------+-------+\n|    SERVER     |    ADDRESS    | SERVICE | CONFIG | VALUE |\n+---------------+---------------+---------+--------+-------+\n| 13.124.241.99 | 13.124.241.99 |         |        |       |\n+---------------+---------------+---------+--------+-------+\n```\n\n이로써 Ethstat이 동작함을 확인할 수 있다. `http://<ip of node0>:8080` 포맷으로 웹 브라우저 주소창에 검색해서 들어가면 Ethstat 페이지를 만나볼 수 있다.\n\n우리가 한 작업을 요약하자면, Controller 노드에서 `puppeth`를 사용하여 `node0`(t2.medium)이 `Docker`를 활용하여 `Ethstat` 서비스를 실행하게끔 구성한 것이다. `puppeth`가 `node0`을 제어할 수 있었던 이유는 사전에 우리가 `public key, private key` 작업을 미리 해줬기 때문이다.\n\n### 4.2 node0에게 Bootnode의 역할을 추가로 부여한다.\n역할을 추가로 부여한다는 건 결국 해당 노드의 도커 컨테이너를 하나 더 생성해서 실행시켜준다는 의미다. `puppeth`를 실행하여 아래의 과정을 진행하여 부트노드를 동작 시켜보자.\n\n1. 4. Manage network components 메뉴를 선택한다.\n2. 2. Deploy new network component 항목을 선택한다.\n3. 2. Bootnode 항목을 선택한다.\n4. 1. 13.124.241.99를 선택한다. // 현재 Ethstat의 역할을 담당하고 있는 node0에게 추가로 권한을 부여하는 것이므로 node0의 ip주소를 그대로 사용하는 것이 맞다.\n5. `/home/ubuntu/ethereum/duelnet/bootnode` // 이 포맷으로 Bootnode관련 데이터를 어디 저장시킬 것인지를 기술한다.\n6. 나머지 옵션들(connecting peer number, light peers number)은 생략한다.\n7. `duelnet_bootnode`으로 이름을 작성한다. // 해당 노드의 역할에 이름을 붙이는 것이라고 생각하면 된다.\n\n실행하면 아래와 같은 결과를 만나볼 수 있다.\n```\n+---------------+---------------+----------+--------------------------+----------------------------------------+\n|    SERVER     |    ADDRESS    | SERVICE  |          CONFIG          |                 VALUE                  |\n+---------------+---------------+----------+--------------------------+----------------------------------------+\n| 13.124.241.99 | 13.124.241.99 | bootnode | Data directory           | /home/ubuntu/ethereum/duelnet/bootnode |\n|               |               |          | Ethstats username        | duelnet_bootnode                       |\n|               |               |          | Listener port            | 30305                                  |\n|               |               |          | Peer count (all total)   | 512                                    |\n|               |               |          | Peer count (light nodes) | 256                                    |\n|               |               |          | ------------------------ | -------------------------------------- |\n|               |               | ethstats | Banned addresses         |                                        |\n|               |               |          | Login secret             | 2326                                   |\n|               |               |          | Website address          | 13.124.241.99                          |\n|               |               |          | Website listener port    | 8080                                   |\n+---------------+---------------+----------+--------------------------+----------------------------------------+\n```\n\n### 4.3 노드0, 노드1, 노드2에게 각각 Sealer 역할 부여\n현재까지 노드0에서는 Ethstats 및 Bootnode 역할을 담당하고 있다. 이제는 블록 검증을 위한 Sealer 노드들을 설정하고 이용할 차례다. 아래의 과정을 각 노드(노드0 ~ 노드2)에게 진행하면 된다. 즉 Controller 노드에서 `puppeth`를 실행시키고 노드0~노드2의 ip주소를 각각 입력하여 Sealer 역할을 부여하면 된다.\n\n1. 4. Deploy network components 메뉴를 선택한다.\n2. 3. Deploy new network component 메뉴를 선택한다. // 참여하는 노드가 점점 많아질 수록 이 수치는 점점 높아진다.\n3. 3. Sealer // 새로운 블록을 생성하는 Full node 역할을 담당하게 된다.\n4. 2. Connect another server 메뉴를 선택해서 각 노드의 ip를 적용시켜주면 된다.\n5. `/home/ubuntu/ethereum/duelnet/sealernode` 디렉토리를 데이터 디렉토리로 설정한다.\n6. 나머지 옵션들(TCP/IP port, number of peer connections, light peers)은 default로 둬도 상관 없으므로 Enter로 넘어가도록 한다.\n7. 이름을 지정해줘야 하므로 `duelnet_sealer_0, duelnet_sealer_1, duelnet_sealer2` 와 같이 체계적인 이름으로 각 노드의 역할에 이름을 부여한다.\n\n위의 과정을 진행하여 3개의 노드가 Sealer 노드로 모두 참여시켜 네트워크를 구성한 후 다시한 번 웹 브라우저에서 Ethstats 방문한다면 아래와 같은 화면을 만나볼 수 있을 것이다.\n\nhttps://cdn.steemitimages.com/DQmbtRNUZqUYSkWsDRMKMujpjdx1br9RGouZouXt5eRJMhD/image.png\n\nSealer 노드가 3개 존재하고 Bootnode가 존재하고 있다. 모든 노드들이 정상적으로 등록되고 인식되고 있다는 것을 확인할 수 있다.\n\n### 4.4 채굴 진행해보기 (채굴이라 칭하기도 하고, Sealing | Validating로 불리기도 한다.)\n지금까지 구성한 환경만으로는 아직 블록이 하나도 생성되지 않고 있다. `Ethstats` 에 웹브라우저로 접근하면 알 수 있다. 네트워크가 현재 멈춰 있으므로 채굴 과정을 진행시켜보겠다.\n\n먼저 Controller node에서 `ssh ubuntu@<ip of boonode>` 를 입력하여 `Bootnode` 역할을 담당하고 있는 `node0`에게 접속한다. 그리고 `docker ps` 명령어로 현재 실행중인 컨테이너를 확인한다. 명령의 결과는 아래와 같다.\n\n```\nCONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                                                                                     NAMES\nc1efa7cbe17f        duelnet/sealnode    \"/bin/sh geth.sh\"   11 minutes ago      Up 11 minutes       8545-8546/tcp, 0.0.0.0:30303->30303/tcp, 0.0.0.0:30303->30303/udp                         duelnet_sealnode_1\n8266f6a9d2d2        duelnet/bootnode    \"/bin/sh geth.sh\"   22 minutes ago      Up 22 minutes       8545-8546/tcp, 30303/tcp, 30303/udp, 0.0.0.0:30305->30305/tcp, 0.0.0.0:30305->30305/udp   duelnet_bootnode_1\n0a1265c25972        duelnet/ethstats    \"npm start\"         33 minutes ago      Up 33 minutes       0.0.0.0:8080->3000/tcp                                                                    duelnet_ethstats_1\n```\n\n가장 첫번째로 출력되는 `duelnet/sealnode`의 `CONTAINER ID` 를 확인하여 다음의 명령어 포맷으로 `geth` 콘솔을 실행하도록 하자. `docker exec -it <container_id> ` geth attach ipc:/root/.ethereum/geth.ipc`\n\n필자의 경우는 `docker exec -it c1e geth attach` 명령으로 `geth console`을 실행할 수 있었다. 콘솔에 접근한 이유는 해당 노드의 `enode` 정보를 알아내기 위한 것이다. 콘솔 내에서 `admin.nodeInfo.enode` 명령으로 해당 노드의 `enode`정보를 추출하고 위 작업을 node1, node2에게도 동일하게 진행한다.\n\n각 과정을 진행하면서 `enode` 정보를 기록하고, 그렇게 하면 아래와 같은 정보를 얻어낼 수 있을 것이다.\n```\nSealer 0:\n\"enode://ec9046bc66b3c5f940bcb8023f127aa721da61c02ae4906e8e2c738295aa17bf18acbcb5f27f21f026f4b37eb44fe24e0b674ac69a01e4db0b4a4007a5e5e6b2@13.124.241.98:30303\"\n\nSealer 1:\n\"enode://cf47010e6b3a855511eb719cfd29c6b80e74e7e5a023878eaf393fc157b9f9a7704f6650f7719a247c64cf68903738233483f83a7081e12a4f641c11564e7431@52.78.17.178:30303\"\n\nSealer 2:\n\"enode://87789df6d972fc357384606cd833dc8529a178cfde411d81125ba229c8be1e1425483ca97da055a2a5bc8419d38c859181ff152678e7f7bc6c5339090e4122db@13.209.73.50:30303\"\n```\n\n기억한 `enode` 정보를 가지고 `Bootnode` 역할을 맡고 있는 node0의 `geth console`을 실행시켜 다음의 명령어 포맷으로 각 노드를 연결시켜주도록 한다. `admin.addPeer(\"<enode from other nodes>\")` 현재 노드0에서 실행하고 있으므로 노드1과 노드2의 `enode` 정보를 확인한 후에 적용시켜주면 된다.\n\n## 5. 나머지 서비스 구현\n> 나머지 서비스들은 모두 Ethstats 서비스를 제공하고 있는 노드0에서 이루어져야 한다. 구축해야 할 서비스들은 아래와 같다.\n1. The MyCrypto wallet app\n2. A faucet\n3. A block explorer (PoA 네트워크에서는 아직 지원되지 않는다.)\n4. A dashboard to tie it all together\n\n`puppeth` 를 사용하여 배포할 때 헷갈리는 점이 있는 건 `faucet app` 뿐이므로 해당 절차만 기술하도록 하겠다. 나머지는 필요에 따라 본인이 직접 조작해보는 걸 추천한다.\n\n### 5.1 Wallet App\n### 5.2 Faucet App\n특이하게도 `reCAPCHA v2` 서비스의 `Site key` `Secret key`를 요구한다. 이 경우 `reCAPCHA` 사이트에 접속하여 생성할 수 있고 생성하여 얻은 각 키 정보를 입력해주면 된다.\n### 5.3 Dashboard\n\n## 6. 마치며\n개발자가 해야할 일을 대폭 줄여주는 `puppeth`는 확실히 효자 프로그램이라 할 수 있다. 그러나 여전히 근본적인 구조에 대한 이해는 필요하다고 생각한다. 각 앱을 구현하는데 있어서 필요한 정보가 어떤 것이 있을지 생각해보고 `puppeth` 를 이용하는 것이 개발 실력 뿐만 아니라 통찰에도 많은 도움을 줄 거라 생각한다.\n\n마침 아직 PoA에 관한 `Block Explorer` 는`puppeth` 에서 제공하지 않으니 직접 구현해보는 건 어떨까? 이번 포스팅은 여기서 마치도록 한다.",
      "json_metadata": "{\"tags\":[\"ethereum\",\"poa\",\"blockchain\",\"privateblockchain\",\"puppeth\"],\"image\":[\"https://cdn.steemitimages.com/DQmNae973aXjn5G5YG98h91bBTQsq4TCKnGy5EcbagEdXxU/image.png\",\"https://cdn.steemitimages.com/DQmbtRNUZqUYSkWsDRMKMujpjdx1br9RGouZouXt5eRJMhD/image.png\"],\"links\":[\"https://medium.com/@collin.cusce/using-puppeth-to-manually-create-an-ethereum-proof-of-authority-clique-network-on-aws-ae0d7c906cce\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
    }
  ]
}
2018/08/20 16:30:30
parent author
parent permlinkethereum
authordlgusdn616
permlinkaws-puppeth-ethereum-private-blockchain-poa
titleAWS와 Puppeth를 활용한 Ethereum Private Blockchain (POA) 구축하기
body* 해당 포스팅은 [Using puppeth To Manually Create An Ethereum Proof Of Authority (Clique) Network On AWS](https://medium.com/@collin.cusce/using-puppeth-to-manually-create-an-ethereum-proof-of-authority-clique-network-on-aws-ae0d7c906cce) 포스팅을 참조하여 작성되었습니다. * 필자가 사용한 운영체제는 MacOS 입니다. > 포스팅 목적: 일반적으로 Private Network를 구축할 때 필요한 까다롭고 다소 번거로운 작업들을 빠르고 효율적으로 할 수 있는 Puppeth의 사용법과 AWS EC2에게 각 역할(faucet, wallet, dashboard etc...)을 부여하여 필수요소들으 갖춘 프라이빗 네트워크를 구축하는 방법을 알아본다. ## 1. 들어가기 전에 ### Proof Of Authority 먼저, Proof Of Authority(POA)에 대해 알아볼 필요가 있다. Proof Of Work와는 다르게 POA는 일반적인 노드들이 Miner로 참여할 수 없다. 그 말인 즉슨, 네트워크에 기여할 수 있는 혹은 네트워크를 운영하는 주체는 아무나 될 수 없다는 말이다. 네트워크를 운영할 수 있는 건 해당 네트워크를 제작한 설계자가 초기에 결정하게 되어 있다. > 여기서 네트워크를 운영한다는 말은 거래기록들을 담는 블록을 생성하는 컴퓨팅 작업을 의미한다. POW에서는 이 작업을 mining 이라 표현하고 작업을 진행하고 있는 노드를 miner라 칭한다. 그러나 POA에서는 이 작업을 signing이라 표현하고 작업을 진행하는 노드를 signer라고 표현한다. 처음 네트워크를 생성할 때 3개의 Sealer 노드를 지정했다면, 그 3개의 노드가 블록을 생성하는 역할을 담당하게 된다. 만약 특정 노드가 새로운 Sealer로 네트워크에 참여하고 싶다면, 기존의 Sealer들이 투표 매커니즘을 진행해서 참여여부를 결정해야 한다. 일반적으로 POW에서는 특정 이더리움 노드의 `genesis file` 그리고 `enode 정보`를 알고 있으면 네트워크에 접속해서 miner로 활동할 수 있었지만, POA에서는 그러한 작업이 기본적으로 차단되어 있다. 즉, 네트워크의 내용은 볼 수 있지만 블록을 생성하거나 거래를 검증하는 작업 등은 할 수 없다. 필자가 준비하고 있는 서비스에는 POA 환경이 좀 더 적합하기에 이더리움의 POA 합의 알고리즘 엔진(Clique)을 이용하여 환경구성을 진행해보려 한다. ## 2. AWS EC2 환경 구축 진행 ### 2.1 AWS EC2 포스팅에서 사용되는 EC2인스턴스들의 정보는 아래와 같다. * 컨트롤러 역할(다른 geth 노드들을 제어)을 하는 t2.micro Ubuntu 16.04 인스턴스 1개 * 노드 역할을 하는 t2.medium (10 gb) Ubuntu 16.04 인스턴스 3개 각 인스턴스를 생성할 때 주의할 점은 보안 그룹과 Keypair를 모두 동일한 세팅으로 맞춰줘야 한다는 점이다. 또한 puppeth 프로그램 소스코드 내에서 취급되는 키의 이름은 `id_rsa`이므로 동일한 이름으로 keypair를 생성해주는 게 좋다. keypair를 생성해주면 `id_rsa.pem` 파일을 다운로드 받을 수 있을 것이다. 각 인스턴스에 접근할 때 사용되므로 잘 보관해두도록 한다. 맥이나 리눅스의 경우 `~/.ssh` 디렉토리 내에 위치시켜두는 것이 좋다. 해당 디렉토리 내에서도 용도에 따라 구분할 수 있게 디렉토리를 생성하여 체계적으로 관리할 수 있도록 한다. 필자의 경우 `~/.ssh/AWS` 디렉토리 내에 모든 키를 보관한다. 이로써 `id_rsa.pem` 파일만 있으면 `ssh -i "id_rsa.pem" ubuntu@<ip of EC2 instance` 명령어 포맷으로 원격접속을 할 수 있게 된다. 다운로드 받은 키는 미리 실행권한을 400으로 바꿔주도록 한다. `chmod 400 id_rsa.pem` 명령으로 오직 관리자만이 write 권한을 가지게끔 변경해준다. AWS 인스턴스에 원격접속을 할 때는 실행권한이 400이 아니면 원격접속이 되지 않는다. ### 2.2 EC2 Security Setting 각 인스턴스는 아래의 보안 규칙을 따른다. 새로 생성하여 적용하도록 한다. 실제 서비스를 제작하여 운용할 방침이라면, 좀 더 깐깐하게 설정해주는 게 맞지만 테스트용이기 때문에 약간 더 넓게 설정해두었다. ![](https://cdn.steemitimages.com/DQmNae973aXjn5G5YG98h91bBTQsq4TCKnGy5EcbagEdXxU/image.png) 필자가 생성한 인스턴스 정보는 아래와 같다. 각 인스턴스의 이름도 신경써서 제작해주도록 하자. 필자의 인스턴스는 하나의 컨트롤러와 3개의 노드(0, 1, 2번)로 구성되어 있다. ``` // name, ip, vpc 순으로 기재했다. duel.poa.controller:52.79.234.126 vpc:172-31-31-148 t2.micro duel.poa.node0: 13.124.241.99 vpc: 172-31-30-127 t2.medium duel.poa.node1: 52.78.17.178 vpc: 172-31-17-195 t2.medium duel.poa.node2: 13.209.73.50 vpc: 172-31-22-46 t2.medium ``` `id_rsa.pem` 파일만 있으면 위 4개의 인스턴스에 얼마든지 접근할 수 있다. ### 2.3 Install Geth 각 인스턴스에 geth를 설치하는 작업을 진행한다. 이 포스티에서는 4개의 terminal를 띄워 명령어를 복사하여 실행하는 방법으로 진행한다. 하나의 인스턴스를 만들어 놓은 뒤 이미지로 따로 추출하여 해당 이미지로 인스턴스를 생성하는 방법이 존재하기 때문에, 이 방법을 이용해도 된다. 먼저 4개의 터미널에서 인스턴스에 접속한다. `id_rsa.pem`파일이 있는 폴더 내에서 아래의 명령을 실행하면 된다. ``` ssh -i "id_rsa.pem" [email protected] ssh -i "id_rsa.pem" [email protected] ssh -i "id_rsa.pem" [email protected] ssh -i "id_rsa.pem" [email protected] ``` 각 인스턴스에 원격접속을 했다면, 아래의 커맨드로 4개의 instance에 각각 적용해준다. ``` sudo apt-get install software-properties-common sudo add-apt-repository -y ppa:ethereum/ethereum sudo apt-get update sudo apt-get install ethereum ``` ## 3. 각 Node의 역할에 맞게 환경 구성 ### 3.1 Controller `t2.micro` 인스턴스 1개가 컨트롤러 역할을 진행한다. 나머지 3개의 `t2.medium` 인스턴스에 접근하고 제어하는 역할을 할 것이다. 위에서 EC2 인스턴스들을 생성하고 접근할 때 사용한 `id_rsa.pem` 파일의 내용을 복사해두도록 한다. 복사를 했으면 다음의 작업을 진행한다. > 복사를 진행한 이유: .pem 파일은 프라이빗 키로 사용된다. 퍼블릭 프라이빗 키 개념을 간단하게 설명하자면, 각 EC2 인스턴스에는 퍼블릭 키가 존재하고 해당 퍼블릭키와 매칭되는 프라이빗키가 존재할 때 프라이빗 키로 해당 인스턴스에 원격으로 접속할 수가 있다. * `cd ~/.ssh` 디렉토리에 접근하여 아래의 작업들을 진행한다. * `vim id_rsa.pem` 명령으로 파일을 생성한 후 복사한 내용(우리 컴퓨터에 존재하는 `id_rsa.pem` 파일의 내용)을 붙여넣는다. > 우리가 현재 사용하고 있는 컴퓨터에서 제어할 수 있지만 이렇게 했을 경우, 컴퓨터가 망가지거나 가지고 나오지 않았을 시 접근할 수 있는 방법이 존재하지 않는다. 따라서 별도의 컨트롤러 노드를 구성한 것이고 이 노드에서 각 인스턴스 노드에 접근하는 역할을 할 것이므로, 우리 컴퓨터에 있던 `id_rsa.pem` 파일을 그대로 Controller 노드에도 넣어주는 것이다. * `sudo perl -pi -e 'chomp if elf' id_rsa.pem` 명령을 실행하여 불필요한 라인들을 제거해준다. (있을 경우 제대로 키의 역할을 할 수 없게된다.) * 다른 노드를 컨트롤 할 때 사용할 자신만의 키를 생성해준다. 이미 `id_rsa.pem` 파일이 있는데 굳이 별도의 작업을 진행하는 이유는 `ssh ubuntu@<ip of node>` 명령어 만으로 각 노드에 접근하기 위해서다. 또한 `puppeth`를 실행할 때도 `puppeth`가 찾는 것은 `id_rsa.pub` 파일이고 파일을 별도로 지정하는 기능은 현재 `puppeth`에 구현되어 있지 않으므로 별도로 생성해주고 설정하는 작업이 필요한 것이다. * `ssh-keygen` 명령어로 키를 생성하며 passphrase를 묻는 입력란들이 나오면 전부 Enter를 치고 넘어간다. (원할 경우 따로 지정해줘도 상관은 없다. 실제로 서비스를 상용화할 때는 하는 것이 더 좋겠다.) * 명령어를 실행하면 `id_rsa, id_rsa.pub` 이라는 두 개의 파일이 생성된 것을 확인할 수 있다. 각각 개인키, 공개키를 의미한다. * 이제 각 t2.medium 노드들에 접근하기 위해 `~/.ssh/authorized_keys` 파일의 내용을 편집해줄 차례다. 다음 명령어를 실행해주도록 한다. `ssh -i id_rsa.pem ubuntu@<ip of node> 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub` 필자의 경우 아래와 같은 3개의 명령어를 Controller node에서 실행해주었다. ``` ssh -i id_rsa.pem [email protected] 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub ssh -i id_rsa.pem [email protected] 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub ssh -i id_rsa.pem [email protected] 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub ``` 명령어를 실행해준 이후에 Controller node(t2.micro)에서 `ssh ubuntu@<ip of node>`로 3개의 t2.medium 노드들에 접근이 되는지 확인해보고 접속이 되었다면 작업이 잘 마무리 된 것이다. ### 3.2 3개의 인스턴스(t2.medium)들을 설정 각 인스턴스의 의존성 문제를 해결, 그리고 도커를 사용하기 위해 아래의 모든 명령어를 각 인스턴스에서 실행하도록 한다. ``` sudo apt-get update sudo apt-get upgrade sudo apt-get install linux-image-extra-4.4.0–59-generic linux-image-extra-virtual sudo apt-get install \ apt-transport-https \ ca-certificates \ curl \ software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo apt-key fingerprint 0EBFCD88 sudo add-apt-repository \ “deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable” sudo apt-get update sudo apt-get install docker-ce sudo apt-get install docker-compose ``` 각 인스턴스를 재부팅하여 `docker ps` 명령으로 도커가 잘 실행되는지 확인해주도록 한다. ### 3.3 Controller 노드에서 Wallet 생성하기 `puppeth`를 이용하여 네트워크를 생성하기 전에 해줘야 할 작업들이 있는데, Ethereum Wallet을 생성하는 것과 pre-funded accounts를 미리 만들어두는 것이다. Controller(t2.micro)에서 해당 작업을 진행한다. #### 3.3.1 비밀번호 생성하기 각 계정을 사용할 때 필요한 비밀번호를 파일로 만들어 놓도록 한다. 필자의 경우 1234라는 비밀번호로 `passfile`에 내용을 기록했다. 파일을 생성한 후에 관리자에게 read, write, execute 권한을 부여한다. ``` cd ~/ethereum/duelnet vim passfile sudo perl -pi -e 'chomp if eof' passfile chmod 700 passfile ``` #### 3.3.2 이더리움 계정 10개 생성하기 계정을 미리 생성해둬야 `puppeth`를 이용해서 네트워크를 설정할 때 Signer의 역할을 특정 계정에 부여하고 미리 이더를 지급받을 수 있다. 따라서 간단한 쉘 스크립트를 제작하여 이더리움 계정을 생성해주도록 한다. 실습을 진행하기 전에 먼저 디렉토리 구조를 신경쓸 필요가 있다. 필자의 경우 먼저 `~/ethereum/duelnet/node`와 같은 구조로 디렉토리를 구성했고 향후 추가된 네트워크 설정이나 별도의 네트워크 설정을 구축하고 싶다면 `~/ethereum/<other network setup>`와 같이 디렉토리를 구성할 계획이다. 먼저, 하나의 계정을 생성하려면 다음의 명령을 터미널에서 입력한다. `geth --datadir ~/ethereum/duelnet/node` account new --password ~/passfile` 이 명령을 실행하면 `~/ethereum/duelnet/node` 디렉토리를 기준으로 geth의 설정이 적용된다. 방금 생성된 계정을 Sealer0라고 칭하도록 한다. Signer라는 명칭도 있지만, Sealer라는 명칭도 있다고 이해하면 된다. 스크립트 파일을 하나 생성(`vim ~/ethereum/duelnet/create_accounts.sh`)해주고 아래의 내용을 써주도록 한다. ``` for ((n=0; n<10; n++)); do geth --datadir ~/ethereum/duelnet/node account new --password ~/ethereum/duelnet/passfile; done ``` 그 후 `duelnet$ chmod +x create_accounts.sh` 명령어로 실해우건한을 추가시켜주고 `duelnet$ ./create_accounts.sh` 명령으로 스크립트를 실행하도록 한다. 10개의 계정이 추가로 생성되는 것을 확인할 수 있고 생성된 계정들을 따로 텍스트 편집기를 열어 기록을 해둔다. 필자의 경우 아래의 10개 계정들에 차례로 Sealer, Faucet과 같은 역할을 부여했다. ``` sealer0: 81bb2bfb72fc0ab991f79a58e9568d7cae57ccaa sealer1: 4a4961cd93da26276a22d5145a296c3a5a1b83fb sealer2: 78ddd4d1fa2036547687655fcac914852e558740 faucet: 3417cf2e1dea066db77239ad99f7e07f1e14cf0a accounts: d723a1aa820a5c5aa9ed1999e860f045038b2b05 5e5e07c810948e7e837679db1b51e02cc936afc2 096156b2c9a8043b6b288d0d40903f1dbe74b432 a0cff2ac0a0ca43fa0dcdb2b77b02bf6c3c2a86d 16966aebf2532170a04efe2eb05b4a1d1acc9b62 273dae58a042de73b4831cc7381020abe4921768 c730380e33404f2b90be965fc04e1050cac0555a ``` 검증을 하는 노드가 3개 있고, 네트워크 참가자들이 이더를 요청해서 받을 때 각 계정에게 전송시켜주는 faucet 노드가 1개 있다. 나머지 7개 노드들은 네트워크 내에 존재하는 일반 계정들로 의미를 부여했다. 이제 본격적으로 `puppeth`를 실행하도록 한다. ### 3.4 Puppeth를 사용하여 이더리움 네트워크 정의 및 생성 `~/ethereum/duelnet$ puppeth`로 명령을 실행한다. 각자의 디렉토리에서 `puppeth`를 입력하여 실행하면 된다. 실행한 뒤에 쭈욱 과정을 진행하면 되는데, 아래를 참조하도록 한다. ``` +-----------------------------------------------------------+ | Welcome to puppeth, your Ethereum private network manager | | | | This tool lets you create a new Ethereum network down to | | the genesis block, bootnodes, miners and ethstats servers | | without the hassle that it would normally entail. | | | | Puppeth uses SSH to dial in to remote servers, and builds | | its network components out of Docker containers using the | | docker-compose toolset. | +-----------------------------------------------------------+ // 자신이 생성할 네트워크 설정의 이름을 정한다. Please specify a network name to administer (no spaces or hyphens, please) > duelnet Sweet, you can set this via --network=duelnet_demo next time! INFO [08-08|09:39:10.290] Administering Ethereum network name=duelnet_demo WARN [08-08|09:39:10.291] No previous configurations found path=/home/ubuntu/.puppeth/duelnet_demo // 제네시스 파일을 새로 구성할 수 있는 2번을 선택한다. What would you like to do? (default = stats) 1. Show network stats 2. Configure new genesis 3. Track new remote server 4. Deploy network components > 2 // PoA 엔진인 Clique를 선택한다. Which consensus engine to use? (default = clique) 1. Ethash - proof-of-work 2. Clique - proof-of-authority > 2 // 블록의 생성시간을 기술해준다. How many seconds should blocks take? (default = 15) > 1 // 위에서 의미룰 부여해주었던 계정들을 쭈욱 적어준다. Which accounts are allowed to seal? (mandatory at least one) > 0x81bb2bfb72fc0ab991f79a58e9568d7cae57ccaa > 0x4a4961cd93da26276a22d5145a296c3a5a1b83fb > 0x78ddd4d1fa2036547687655fcac914852e558740 > 0x // sealer 노드들과 faucet, accounts 0~2까지 이더를 지급한다. // PoA에서는 채굴 과정이 따로 없기 때문에 sealer 노드를 제외한 다른 노드들이 faucet 말고는 이더를 지급받을 방법이 존재하지 않는다. Which accounts should be pre-funded? (advisable at least one) > 0x81bb2bfb72fc0ab991f79a58e9568d7cae57ccaa > 0x4a4961cd93da26276a22d5145a296c3a5a1b83fb > 0x78ddd4d1fa2036547687655fcac914852e558740 > 0x3417cf2e1dea066db77239ad99f7e07f1e14cf0a > 0xd723a1aa820a5c5aa9ed1999e860f045038b2b05 > 0x5e5e07c810948e7e837679db1b51e02cc936afc2 > 0x096156b2c9a8043b6b288d0d40903f1dbe74b432 > 0x // 디폴트로 랜덤한 네트워크 아이디를 생성해준다. Enter만 입력하고 넘어가자. Specify your chain/network ID if you want an explicit one (default = random) > INFO [08-08|09:40:54.552] Configured new genesis block // 위에서 생성한 제네시스 파일을 추출하기 위해 2번을 선택한다. What would you like to do? (default = stats) 1. Show network stats 2. Manage existing genesis 3. Track new remote server 4. Deploy network components > 2 1. Modify existing fork rules 2. Export genesis configuration 3. Remove genesis configuration > 2 // 디폴트로 설정하기 위해 Enter만 입력하여 진행 Which file to save the genesis into? (default = duelnet_demo.json) > INFO [08-08|09:40:58.932] Exported existing genesis block What would you like to do? (default = stats) 1. Show network stats 2. Manage existing genesis 3. Track new remote server 4. Deploy network components > Ctrl + c // 원하는 작업을 실행했으니 종료한다. ``` 생성된 제네시스 파일을 편집기로 열어보면 내용이 꽤 길다는 것을 확인할 수 있다. 이는 `puppeth`가 중간 중간 dummy accounts를 미리 생성해두었기 때문이다. 자신이 설정한 계정들을 제외하고는 전부 지워주어 파일을 보기 편리하게 만들어두는 것을 추천한다. 따로 조작하지 않아도 상관은 없다. #### 3.5 Get Wallet Keyfiles Sealer 노드들의 개인키를 복사하여 puppeth 내에서 사용가능하도록 환경을 구성할 것이다. 따라서 Sealer 노드들과 Faucet 노드의 개인키 파일의 내용을 따로 복사해두어 기록해두도록 한다. 아래와 같이 실행하여 나온 결과들을 따로 기록해두자. ``` Sealer 0: cat UTC--2018-08-08T09-27-37.241084125Z--81bb2bfb72fc0ab991f79a58e9568d7cae57ccaa Sealer 1: cat UTC--2018-08-08T09-33-06.102438431Z--4a4961cd93da26276a22d5145a296c3a5a1b83fb Sealer 2: cat UTC--2018-08-08T09-33-07.073882847Z--78ddd4d1fa2036547687655fcac914852e558740 Faucet: cat UTC--2018-08-08T09-33-08.031975188Z--3417cf2e1dea066db77239ad99f7e07f1e14cf0a ``` 각 명령어들에 대한 결과는 아래와 같고 아래의 내용들을 따로 기록해두면 된다. ``` Sealer 0: {"address":"81bb2bfb72fc0ab991f79a58e9568d7cae57ccaa","crypto":{"cipher":"aes-128-ctr","ciphertext":"a30dc751a3ec33bb36b8ce5ca78abe7dbdf8ca68892bc2c9f8509cfc49077ee1","cipherparams":{"iv":"2263fd6f213c7030abdc12b56acf3ce8"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"4c84fd7a79af24a7be3c5314b37aa08998ec69188c324181e19357ddc51497ce"},"mac":"eae031ffa5e046a8dd17d07d7b7f7c235cc0ea8c726f4eac32b0a302e7107754"},"id":"befc4d2e-9244-46d9-8227-cd37da8efd6f","version":3} Sealer 1: {"address":"4a4961cd93da26276a22d5145a296c3a5a1b83fb","crypto":{"cipher":"aes-128-ctr","ciphertext":"e176164bfd9fc6653e0ea3e418084af1de528a2dd10ffe29b9b35ea733f3ca9b","cipherparams":{"iv":"cd7ea7ae9426d56138d62cbb3e9b14dd"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"e82093953f5892b60c84749e98fb575e2acd1a43d4477f6ea6f682974a806d13"},"mac":"e6c56be76c1009fafc2c921ab1b331f7c3874590f9e5e6a8b36dc98169abfa28"},"id":"528c9ce2-b4fe-4403-be02-898c0a0b096b","version":3} Sealer 2: {"address":"78ddd4d1fa2036547687655fcac914852e558740","crypto":{"cipher":"aes-128-ctr","ciphertext":"1730c3d659528dafab59f854cccef85714cfab2f7e3c573058aa0e7c6bdc282a","cipherparams":{"iv":"f56a23b8b4d4377510655a775e90df2f"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"2373352ac9a663385100c45d93287263153e1dc020cbc884294370d261033450"},"mac":"7a745f562fd47a1cdf9e65597e76ceb4f7d27f4d469469ccea41f54ad733ea3d"},"id":"42356c9d-e3fd-4790-8c7f-9ca629d2f3f5","version":3} Faucet: {"address":"3417cf2e1dea066db77239ad99f7e07f1e14cf0a","crypto":{"cipher":"aes-128-ctr","ciphertext":"e9be248ab81f9a6b9536827fb53160a5567825628ec952d8599837e78e024cb5","cipherparams":{"iv":"48ec9dbf1ea1a555f5f8860f70f6d183"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"180ab095a7f3de3427a0b67028b5e5e74afa43cfc42310f9bb422268aa8a41b9"},"mac":"19e401009907e226b2c73bc7c06d33fb6bbc0fb90e378cd2afd33f0ad19f3019"},"id":"661b0dd8-0176-4beb-9fa7-bd81dcd2d533","version":3} ``` ## 4. Puppeth를 이용한 네트워크 배포 `puppeth --network duelnet` 와 같은 포맷으로 네트워크 옵션을 주어 자신이 기존에 생성해두었던 네트워크 세팅을 불러온다. 진행해야 할 작업들은 아래와 같다. ### 4.1 node0에게 Ethstat 역할을 부여한다. 1. 4. Deploy network components를 선택한다. `puppeth`에서 미리 제작해둔 편리한 기능들을 이용하여 각 노드들에 알맞은 역할을 부여하는 작업을 진행할 것이다. 2. 1. Connect another server를 선택한다. 3. 13.124.241.99 // 자신의 인스턴스 중 node0의 아이피 주소를 입력해준다. 4. 8080 // 다른 포트로 진행해도 상관은 없지만, 필자는 8080으로 설정했다. 5. n // 포트 공유를 하지 못하게 설정해놓는다. 온전한 서비스를 위해서. 6. secret password는 설정해도 되고 설정하지 않아도 된다. 위의 과정을 진행하면 아래와 같은 결과물을 확인할 수 있다. ``` Creating network "duelnet_default" with the default driver Building ethstats Step 1/2 : FROM puppeth/ethstats:latest latest: Pulling from puppeth/ethstats Digest: sha256:1728c03555d3327f68be924116eed9f9de56671949c21505f4b78518f06e687e Status: Downloaded newer image for puppeth/ethstats:latest ---> fb62abe59cb2 Step 2/2 : RUN echo 'module.exports = {trusted: ["13.124.241.99"], banned: [], reserved: ["yournode"]};' > lib/utils/config.js ---> Running in 08f875b59b9b ---> 2b43e5422c5d Removing intermediate container 08f875b59b9b Successfully built 2b43e5422c5d Creating duelnetdemo_ethstats_1 INFO [08-08|09:54:02.907] Starting remote server health-check server=13.124.241.99 +---------------+---------------+---------+--------+-------+ | SERVER | ADDRESS | SERVICE | CONFIG | VALUE | +---------------+---------------+---------+--------+-------+ | 13.124.241.99 | 13.124.241.99 | | | | +---------------+---------------+---------+--------+-------+ ``` 이로써 Ethstat이 동작함을 확인할 수 있다. `http://<ip of node0>:8080` 포맷으로 웹 브라우저 주소창에 검색해서 들어가면 Ethstat 페이지를 만나볼 수 있다. 우리가 한 작업을 요약하자면, Controller 노드에서 `puppeth`를 사용하여 `node0`(t2.medium)이 `Docker`를 활용하여 `Ethstat` 서비스를 실행하게끔 구성한 것이다. `puppeth`가 `node0`을 제어할 수 있었던 이유는 사전에 우리가 `public key, private key` 작업을 미리 해줬기 때문이다. ### 4.2 node0에게 Bootnode의 역할을 추가로 부여한다. 역할을 추가로 부여한다는 건 결국 해당 노드의 도커 컨테이너를 하나 더 생성해서 실행시켜준다는 의미다. `puppeth`를 실행하여 아래의 과정을 진행하여 부트노드를 동작 시켜보자. 1. 4. Manage network components 메뉴를 선택한다. 2. 2. Deploy new network component 항목을 선택한다. 3. 2. Bootnode 항목을 선택한다. 4. 1. 13.124.241.99를 선택한다. // 현재 Ethstat의 역할을 담당하고 있는 node0에게 추가로 권한을 부여하는 것이므로 node0의 ip주소를 그대로 사용하는 것이 맞다. 5. `/home/ubuntu/ethereum/duelnet/bootnode` // 이 포맷으로 Bootnode관련 데이터를 어디 저장시킬 것인지를 기술한다. 6. 나머지 옵션들(connecting peer number, light peers number)은 생략한다. 7. `duelnet_bootnode`으로 이름을 작성한다. // 해당 노드의 역할에 이름을 붙이는 것이라고 생각하면 된다. 실행하면 아래와 같은 결과를 만나볼 수 있다. ``` +---------------+---------------+----------+--------------------------+----------------------------------------+ | SERVER | ADDRESS | SERVICE | CONFIG | VALUE | +---------------+---------------+----------+--------------------------+----------------------------------------+ | 13.124.241.99 | 13.124.241.99 | bootnode | Data directory | /home/ubuntu/ethereum/duelnet/bootnode | | | | | Ethstats username | duelnet_bootnode | | | | | Listener port | 30305 | | | | | Peer count (all total) | 512 | | | | | Peer count (light nodes) | 256 | | | | | ------------------------ | -------------------------------------- | | | | ethstats | Banned addresses | | | | | | Login secret | 2326 | | | | | Website address | 13.124.241.99 | | | | | Website listener port | 8080 | +---------------+---------------+----------+--------------------------+----------------------------------------+ ``` ### 4.3 노드0, 노드1, 노드2에게 각각 Sealer 역할 부여 현재까지 노드0에서는 Ethstats 및 Bootnode 역할을 담당하고 있다. 이제는 블록 검증을 위한 Sealer 노드들을 설정하고 이용할 차례다. 아래의 과정을 각 노드(노드0 ~ 노드2)에게 진행하면 된다. 즉 Controller 노드에서 `puppeth`를 실행시키고 노드0~노드2의 ip주소를 각각 입력하여 Sealer 역할을 부여하면 된다. 1. 4. Deploy network components 메뉴를 선택한다. 2. 3. Deploy new network component 메뉴를 선택한다. // 참여하는 노드가 점점 많아질 수록 이 수치는 점점 높아진다. 3. 3. Sealer // 새로운 블록을 생성하는 Full node 역할을 담당하게 된다. 4. 2. Connect another server 메뉴를 선택해서 각 노드의 ip를 적용시켜주면 된다. 5. `/home/ubuntu/ethereum/duelnet/sealernode` 디렉토리를 데이터 디렉토리로 설정한다. 6. 나머지 옵션들(TCP/IP port, number of peer connections, light peers)은 default로 둬도 상관 없으므로 Enter로 넘어가도록 한다. 7. 이름을 지정해줘야 하므로 `duelnet_sealer_0, duelnet_sealer_1, duelnet_sealer2` 와 같이 체계적인 이름으로 각 노드의 역할에 이름을 부여한다. 위의 과정을 진행하여 3개의 노드가 Sealer 노드로 모두 참여시켜 네트워크를 구성한 후 다시한 번 웹 브라우저에서 Ethstats 방문한다면 아래와 같은 화면을 만나볼 수 있을 것이다. https://cdn.steemitimages.com/DQmbtRNUZqUYSkWsDRMKMujpjdx1br9RGouZouXt5eRJMhD/image.png Sealer 노드가 3개 존재하고 Bootnode가 존재하고 있다. 모든 노드들이 정상적으로 등록되고 인식되고 있다는 것을 확인할 수 있다. ### 4.4 채굴 진행해보기 (채굴이라 칭하기도 하고, Sealing | Validating로 불리기도 한다.) 지금까지 구성한 환경만으로는 아직 블록이 하나도 생성되지 않고 있다. `Ethstats` 에 웹브라우저로 접근하면 알 수 있다. 네트워크가 현재 멈춰 있으므로 채굴 과정을 진행시켜보겠다. 먼저 Controller node에서 `ssh ubuntu@<ip of boonode>` 를 입력하여 `Bootnode` 역할을 담당하고 있는 `node0`에게 접속한다. 그리고 `docker ps` 명령어로 현재 실행중인 컨테이너를 확인한다. 명령의 결과는 아래와 같다. ``` CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c1efa7cbe17f duelnet/sealnode "/bin/sh geth.sh" 11 minutes ago Up 11 minutes 8545-8546/tcp, 0.0.0.0:30303->30303/tcp, 0.0.0.0:30303->30303/udp duelnet_sealnode_1 8266f6a9d2d2 duelnet/bootnode "/bin/sh geth.sh" 22 minutes ago Up 22 minutes 8545-8546/tcp, 30303/tcp, 30303/udp, 0.0.0.0:30305->30305/tcp, 0.0.0.0:30305->30305/udp duelnet_bootnode_1 0a1265c25972 duelnet/ethstats "npm start" 33 minutes ago Up 33 minutes 0.0.0.0:8080->3000/tcp duelnet_ethstats_1 ``` 가장 첫번째로 출력되는 `duelnet/sealnode`의 `CONTAINER ID` 를 확인하여 다음의 명령어 포맷으로 `geth` 콘솔을 실행하도록 하자. `docker exec -it <container_id> ` geth attach ipc:/root/.ethereum/geth.ipc` 필자의 경우는 `docker exec -it c1e geth attach` 명령으로 `geth console`을 실행할 수 있었다. 콘솔에 접근한 이유는 해당 노드의 `enode` 정보를 알아내기 위한 것이다. 콘솔 내에서 `admin.nodeInfo.enode` 명령으로 해당 노드의 `enode`정보를 추출하고 위 작업을 node1, node2에게도 동일하게 진행한다. 각 과정을 진행하면서 `enode` 정보를 기록하고, 그렇게 하면 아래와 같은 정보를 얻어낼 수 있을 것이다. ``` Sealer 0: "enode://ec9046bc66b3c5f940bcb8023f127aa721da61c02ae4906e8e2c738295aa17bf18acbcb5f27f21f026f4b37eb44fe24e0b674ac69a01e4db0b4a4007a5e5e6b2@13.124.241.98:30303" Sealer 1: "enode://cf47010e6b3a855511eb719cfd29c6b80e74e7e5a023878eaf393fc157b9f9a7704f6650f7719a247c64cf68903738233483f83a7081e12a4f641c11564e7431@52.78.17.178:30303" Sealer 2: "enode://87789df6d972fc357384606cd833dc8529a178cfde411d81125ba229c8be1e1425483ca97da055a2a5bc8419d38c859181ff152678e7f7bc6c5339090e4122db@13.209.73.50:30303" ``` 기억한 `enode` 정보를 가지고 `Bootnode` 역할을 맡고 있는 node0의 `geth console`을 실행시켜 다음의 명령어 포맷으로 각 노드를 연결시켜주도록 한다. `admin.addPeer("<enode from other nodes>")` 현재 노드0에서 실행하고 있으므로 노드1과 노드2의 `enode` 정보를 확인한 후에 적용시켜주면 된다. ## 5. 나머지 서비스 구현 > 나머지 서비스들은 모두 Ethstats 서비스를 제공하고 있는 노드0에서 이루어져야 한다. 구축해야 할 서비스들은 아래와 같다. 1. The MyCrypto wallet app 2. A faucet 3. A block explorer (PoA 네트워크에서는 아직 지원되지 않는다.) 4. A dashboard to tie it all together `puppeth` 를 사용하여 배포할 때 헷갈리는 점이 있는 건 `faucet app` 뿐이므로 해당 절차만 기술하도록 하겠다. 나머지는 필요에 따라 본인이 직접 조작해보는 걸 추천한다. ### 5.1 Wallet App ### 5.2 Faucet App 특이하게도 `reCAPCHA v2` 서비스의 `Site key` `Secret key`를 요구한다. 이 경우 `reCAPCHA` 사이트에 접속하여 생성할 수 있고 생성하여 얻은 각 키 정보를 입력해주면 된다. ### 5.3 Dashboard ## 6. 마치며 개발자가 해야할 일을 대폭 줄여주는 `puppeth`는 확실히 효자 프로그램이라 할 수 있다. 그러나 여전히 근본적인 구조에 대한 이해는 필요하다고 생각한다. 각 앱을 구현하는데 있어서 필요한 정보가 어떤 것이 있을지 생각해보고 `puppeth` 를 이용하는 것이 개발 실력 뿐만 아니라 통찰에도 많은 도움을 줄 거라 생각한다. 마침 아직 PoA에 관한 `Block Explorer` 는`puppeth` 에서 제공하지 않으니 직접 구현해보는 건 어떨까? 이번 포스팅은 여기서 마치도록 한다.
json metadata{"tags":["ethereum","poa","blockchain","privateblockchain"],"image":["https://cdn.steemitimages.com/DQmNae973aXjn5G5YG98h91bBTQsq4TCKnGy5EcbagEdXxU/image.png","https://cdn.steemitimages.com/DQmbtRNUZqUYSkWsDRMKMujpjdx1br9RGouZouXt5eRJMhD/image.png"],"links":["https://medium.com/@collin.cusce/using-puppeth-to-manually-create-an-ethereum-proof-of-authority-clique-network-on-aws-ae0d7c906cce"],"app":"steemit/0.1","format":"markdown"}
Transaction InfoBlock #25237866/Trx 20d25757aefa973466f7344dfc3e20a62231cb43
View Raw JSON Data
{
  "trx_id": "20d25757aefa973466f7344dfc3e20a62231cb43",
  "block": 25237866,
  "trx_in_block": 6,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-08-20T16:30:30",
  "op": [
    "comment",
    {
      "parent_author": "",
      "parent_permlink": "ethereum",
      "author": "dlgusdn616",
      "permlink": "aws-puppeth-ethereum-private-blockchain-poa",
      "title": "AWS와 Puppeth를 활용한 Ethereum Private Blockchain (POA) 구축하기",
      "body": "* 해당 포스팅은 [Using puppeth To Manually Create An Ethereum Proof Of Authority (Clique) Network On AWS](https://medium.com/@collin.cusce/using-puppeth-to-manually-create-an-ethereum-proof-of-authority-clique-network-on-aws-ae0d7c906cce)  포스팅을 참조하여 작성되었습니다.\n\n* 필자가 사용한 운영체제는 MacOS 입니다.\n\n> 포스팅 목적: 일반적으로 Private Network를 구축할 때 필요한 까다롭고 다소 번거로운 작업들을 빠르고 효율적으로 할 수 있는 Puppeth의 사용법과 AWS EC2에게 각 역할(faucet, wallet, dashboard etc...)을 부여하여 필수요소들으 갖춘 프라이빗 네트워크를 구축하는 방법을 알아본다.\n\n## 1. 들어가기 전에\n###  Proof Of Authority\n먼저, Proof Of Authority(POA)에 대해 알아볼 필요가 있다. Proof Of Work와는 다르게 POA는 일반적인 노드들이 Miner로 참여할 수 없다. 그 말인 즉슨, 네트워크에 기여할 수 있는 혹은 네트워크를 운영하는 주체는 아무나 될 수 없다는 말이다. 네트워크를 운영할 수 있는 건 해당 네트워크를 제작한 설계자가 초기에 결정하게 되어 있다. \n> 여기서 네트워크를 운영한다는 말은 거래기록들을 담는 블록을 생성하는 컴퓨팅 작업을 의미한다. POW에서는 이 작업을 mining 이라 표현하고 작업을 진행하고 있는 노드를 miner라 칭한다. 그러나 POA에서는 이 작업을 signing이라 표현하고 작업을 진행하는 노드를  signer라고 표현한다.\n\n처음 네트워크를 생성할 때 3개의 Sealer 노드를 지정했다면, 그 3개의 노드가 블록을 생성하는 역할을 담당하게 된다. 만약 특정 노드가 새로운 Sealer로 네트워크에 참여하고 싶다면, 기존의 Sealer들이 투표 매커니즘을 진행해서 참여여부를 결정해야 한다.\n\n일반적으로 POW에서는 특정 이더리움 노드의 `genesis file` 그리고  `enode 정보`를 알고 있으면 네트워크에 접속해서 miner로 활동할 수 있었지만, POA에서는 그러한 작업이 기본적으로 차단되어 있다. 즉, 네트워크의 내용은 볼 수 있지만 블록을 생성하거나 거래를 검증하는 작업 등은 할 수 없다.\n\n필자가 준비하고 있는 서비스에는 POA 환경이 좀 더 적합하기에 이더리움의 POA 합의 알고리즘 엔진(Clique)을 이용하여 환경구성을 진행해보려 한다.\n\n## 2. AWS EC2 환경 구축 진행\n### 2.1 AWS EC2\n포스팅에서 사용되는 EC2인스턴스들의 정보는 아래와 같다. \n* 컨트롤러 역할(다른 geth 노드들을 제어)을 하는 t2.micro Ubuntu 16.04 인스턴스 1개\n* 노드 역할을 하는 t2.medium (10 gb) Ubuntu 16.04 인스턴스 3개\n\n각 인스턴스를 생성할 때 주의할 점은 보안 그룹과 Keypair를 모두 동일한 세팅으로 맞춰줘야 한다는 점이다. 또한 puppeth 프로그램 소스코드 내에서 취급되는 키의 이름은 `id_rsa`이므로 동일한 이름으로 keypair를 생성해주는 게 좋다.\n\nkeypair를 생성해주면 `id_rsa.pem` 파일을 다운로드 받을 수 있을 것이다. 각 인스턴스에 접근할 때 사용되므로 잘 보관해두도록 한다. 맥이나 리눅스의 경우  `~/.ssh` 디렉토리 내에 위치시켜두는 것이 좋다. 해당 디렉토리 내에서도 용도에 따라 구분할 수 있게 디렉토리를 생성하여 체계적으로 관리할 수 있도록 한다. 필자의 경우 `~/.ssh/AWS` 디렉토리 내에 모든 키를 보관한다.\n\n이로써 `id_rsa.pem` 파일만 있으면 `ssh -i \"id_rsa.pem\" ubuntu@<ip of EC2 instance` 명령어 포맷으로 원격접속을 할 수 있게 된다.\n\n다운로드 받은 키는 미리 실행권한을 400으로 바꿔주도록 한다. `chmod 400 id_rsa.pem` 명령으로 오직 관리자만이 write 권한을 가지게끔 변경해준다. AWS 인스턴스에 원격접속을 할 때는 실행권한이 400이 아니면 원격접속이 되지 않는다. \n\n### 2.2 EC2 Security Setting\n각 인스턴스는 아래의 보안 규칙을 따른다. 새로 생성하여 적용하도록 한다. 실제 서비스를 제작하여 운용할 방침이라면, 좀 더 깐깐하게 설정해주는 게 맞지만 테스트용이기 때문에 약간 더 넓게 설정해두었다.\n![](https://cdn.steemitimages.com/DQmNae973aXjn5G5YG98h91bBTQsq4TCKnGy5EcbagEdXxU/image.png)\n\n필자가 생성한 인스턴스 정보는 아래와 같다. 각 인스턴스의 이름도 신경써서 제작해주도록 하자. 필자의 인스턴스는 하나의 컨트롤러와 3개의 노드(0, 1, 2번)로 구성되어 있다.\n```\n// name, ip, vpc 순으로 기재했다.\nduel.poa.controller:52.79.234.126\tvpc:172-31-31-148\tt2.micro\nduel.poa.node0:\t\t13.124.241.99\tvpc: 172-31-30-127\tt2.medium\nduel.poa.node1:\t\t52.78.17.178\tvpc: 172-31-17-195\tt2.medium\nduel.poa.node2:\t\t13.209.73.50\tvpc: 172-31-22-46\tt2.medium\n```\n\n`id_rsa.pem` 파일만 있으면 위 4개의 인스턴스에 얼마든지 접근할 수 있다.\n\n### 2.3 Install Geth\n각 인스턴스에 geth를 설치하는 작업을 진행한다. 이 포스티에서는 4개의 terminal를 띄워 명령어를 복사하여 실행하는 방법으로 진행한다.\n하나의 인스턴스를 만들어 놓은 뒤 이미지로 따로 추출하여 해당 이미지로 인스턴스를 생성하는 방법이 존재하기 때문에, 이 방법을 이용해도 된다.\n\n먼저 4개의 터미널에서 인스턴스에 접속한다. `id_rsa.pem`파일이 있는 폴더 내에서 아래의 명령을 실행하면 된다.\n```\nssh -i \"id_rsa.pem\" [email protected]\nssh -i \"id_rsa.pem\" [email protected]\nssh -i \"id_rsa.pem\" [email protected]\nssh -i \"id_rsa.pem\" [email protected]\n```\n각 인스턴스에 원격접속을 했다면, 아래의 커맨드로 4개의 instance에 각각 적용해준다.\n```\nsudo apt-get install software-properties-common\nsudo add-apt-repository -y ppa:ethereum/ethereum\nsudo apt-get update\nsudo apt-get install ethereum\n```\n\n## 3. 각 Node의 역할에 맞게 환경 구성\n### 3.1 Controller\n`t2.micro` 인스턴스 1개가 컨트롤러 역할을 진행한다. 나머지 3개의 `t2.medium` 인스턴스에 접근하고 제어하는 역할을 할 것이다. 위에서 EC2 인스턴스들을 생성하고 접근할 때 사용한 `id_rsa.pem` 파일의 내용을 복사해두도록 한다. 복사를 했으면 다음의 작업을 진행한다.\n> 복사를 진행한 이유: .pem 파일은 프라이빗 키로 사용된다. 퍼블릭 프라이빗 키 개념을 간단하게 설명하자면, 각 EC2 인스턴스에는 퍼블릭 키가 존재하고 해당 퍼블릭키와 매칭되는 프라이빗키가 존재할 때 프라이빗 키로 해당 인스턴스에 원격으로 접속할 수가 있다.\n\n* `cd ~/.ssh` 디렉토리에 접근하여 아래의 작업들을 진행한다.\n* `vim id_rsa.pem` 명령으로 파일을 생성한 후 복사한 내용(우리 컴퓨터에 존재하는 `id_rsa.pem` 파일의 내용)을 붙여넣는다.\n\n> 우리가 현재 사용하고 있는 컴퓨터에서 제어할 수 있지만 이렇게 했을 경우, 컴퓨터가 망가지거나 가지고 나오지 않았을 시 접근할 수 있는 방법이 존재하지 않는다. 따라서 별도의 컨트롤러 노드를 구성한 것이고 이 노드에서 각 인스턴스 노드에 접근하는 역할을 할 것이므로, 우리 컴퓨터에 있던 `id_rsa.pem` 파일을 그대로 Controller 노드에도 넣어주는 것이다.\n\n\n* `sudo perl -pi -e 'chomp if elf' id_rsa.pem` 명령을 실행하여 불필요한 라인들을 제거해준다. (있을 경우 제대로 키의 역할을 할 수 없게된다.)\n* 다른 노드를 컨트롤 할 때 사용할 자신만의 키를 생성해준다. 이미 `id_rsa.pem` 파일이 있는데 굳이 별도의 작업을 진행하는 이유는 `ssh ubuntu@<ip of node>` 명령어 만으로 각 노드에 접근하기 위해서다. 또한 `puppeth`를 실행할 때도 `puppeth`가 찾는 것은 `id_rsa.pub` 파일이고 파일을 별도로 지정하는 기능은 현재 `puppeth`에 구현되어 있지 않으므로 별도로 생성해주고 설정하는 작업이 필요한 것이다.\n*  `ssh-keygen` 명령어로 키를 생성하며 passphrase를 묻는 입력란들이 나오면 전부 Enter를 치고 넘어간다. (원할 경우 따로 지정해줘도 상관은 없다. 실제로 서비스를 상용화할 때는 하는 것이 더 좋겠다.)\n* 명령어를 실행하면 `id_rsa, id_rsa.pub` 이라는 두 개의 파일이 생성된 것을 확인할 수 있다. 각각 개인키, 공개키를 의미한다.\n* 이제 각 t2.medium 노드들에 접근하기 위해 `~/.ssh/authorized_keys` 파일의 내용을 편집해줄 차례다. 다음 명령어를 실행해주도록 한다. `ssh -i id_rsa.pem ubuntu@<ip of node> 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub`\n필자의 경우 아래와 같은 3개의 명령어를 Controller node에서 실행해주었다.\n```\nssh -i id_rsa.pem [email protected] 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub\nssh -i id_rsa.pem [email protected] 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub\nssh -i id_rsa.pem [email protected] 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub\n```\n\n명령어를 실행해준 이후에 Controller node(t2.micro)에서 `ssh ubuntu@<ip of node>`로 3개의 t2.medium 노드들에 접근이 되는지 확인해보고 접속이 되었다면 작업이 잘 마무리 된 것이다.\n\n### 3.2 3개의 인스턴스(t2.medium)들을 설정\n각 인스턴스의 의존성 문제를 해결, 그리고 도커를 사용하기 위해 아래의 모든 명령어를 각 인스턴스에서 실행하도록 한다. \n```\nsudo apt-get update\nsudo apt-get upgrade\nsudo apt-get install linux-image-extra-4.4.0–59-generic linux-image-extra-virtual\nsudo apt-get install \\\n apt-transport-https \\\n ca-certificates \\\n curl \\\n software-properties-common\ncurl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -\nsudo apt-key fingerprint 0EBFCD88\nsudo add-apt-repository \\\n “deb [arch=amd64] https://download.docker.com/linux/ubuntu \\\n $(lsb_release -cs) \\\n stable”\nsudo apt-get update\nsudo apt-get install docker-ce\nsudo apt-get install docker-compose\n```\n각 인스턴스를 재부팅하여 `docker ps` 명령으로 도커가 잘 실행되는지 확인해주도록 한다.\n\n### 3.3 Controller 노드에서 Wallet 생성하기\n`puppeth`를 이용하여 네트워크를 생성하기 전에 해줘야 할 작업들이 있는데, Ethereum Wallet을 생성하는 것과 pre-funded accounts를 미리 만들어두는 것이다. Controller(t2.micro)에서 해당 작업을 진행한다.\n\n#### 3.3.1 비밀번호 생성하기\n각 계정을 사용할 때 필요한 비밀번호를 파일로 만들어 놓도록 한다. 필자의 경우 1234라는 비밀번호로 `passfile`에 내용을 기록했다. 파일을 생성한 후에 관리자에게 read, write, execute 권한을 부여한다.\n```\ncd ~/ethereum/duelnet\nvim passfile\nsudo perl -pi -e 'chomp if eof' passfile\nchmod 700 passfile\n```\n\n#### 3.3.2 이더리움 계정 10개 생성하기\n계정을 미리 생성해둬야 `puppeth`를 이용해서 네트워크를 설정할 때 Signer의 역할을 특정 계정에 부여하고 미리 이더를 지급받을 수 있다. 따라서 간단한 쉘 스크립트를 제작하여 이더리움 계정을 생성해주도록 한다.\n\n실습을 진행하기 전에 먼저 디렉토리 구조를 신경쓸 필요가 있다. 필자의 경우 먼저 `~/ethereum/duelnet/node`와 같은 구조로 디렉토리를 구성했고 향후 추가된 네트워크 설정이나 별도의 네트워크 설정을 구축하고 싶다면 `~/ethereum/<other network setup>`와 같이 디렉토리를 구성할 계획이다.\n\n먼저, 하나의 계정을 생성하려면 다음의 명령을 터미널에서 입력한다. `geth --datadir ~/ethereum/duelnet/node` account new --password ~/passfile` 이 명령을 실행하면 `~/ethereum/duelnet/node` 디렉토리를 기준으로 geth의 설정이 적용된다.\n\n방금 생성된 계정을 Sealer0라고 칭하도록 한다. Signer라는 명칭도 있지만, Sealer라는 명칭도 있다고 이해하면 된다. 스크립트 파일을 하나 생성(`vim ~/ethereum/duelnet/create_accounts.sh`)해주고 아래의 내용을 써주도록 한다.\n```\nfor ((n=0; n<10; n++)); do geth --datadir ~/ethereum/duelnet/node account new --password ~/ethereum/duelnet/passfile; done\n```\n그 후 `duelnet$ chmod +x create_accounts.sh` 명령어로 실해우건한을 추가시켜주고 `duelnet$ ./create_accounts.sh` 명령으로 스크립트를 실행하도록 한다. \n\n10개의 계정이 추가로 생성되는 것을 확인할 수 있고 생성된 계정들을 따로 텍스트 편집기를 열어 기록을 해둔다. 필자의 경우 아래의 10개 계정들에 차례로 Sealer, Faucet과 같은 역할을 부여했다.\n```\nsealer0: 81bb2bfb72fc0ab991f79a58e9568d7cae57ccaa\nsealer1: 4a4961cd93da26276a22d5145a296c3a5a1b83fb\nsealer2: 78ddd4d1fa2036547687655fcac914852e558740\nfaucet: 3417cf2e1dea066db77239ad99f7e07f1e14cf0a\n\naccounts:\nd723a1aa820a5c5aa9ed1999e860f045038b2b05\n5e5e07c810948e7e837679db1b51e02cc936afc2\n096156b2c9a8043b6b288d0d40903f1dbe74b432\na0cff2ac0a0ca43fa0dcdb2b77b02bf6c3c2a86d\n16966aebf2532170a04efe2eb05b4a1d1acc9b62\n273dae58a042de73b4831cc7381020abe4921768\nc730380e33404f2b90be965fc04e1050cac0555a\n```\n검증을 하는 노드가 3개 있고,  네트워크 참가자들이 이더를 요청해서 받을 때 각 계정에게 전송시켜주는 faucet 노드가 1개 있다. 나머지 7개 노드들은 네트워크 내에 존재하는 일반 계정들로 의미를 부여했다.\n\n이제 본격적으로 `puppeth`를 실행하도록 한다.\n\n### 3.4 Puppeth를 사용하여 이더리움 네트워크 정의 및 생성\n`~/ethereum/duelnet$ puppeth`로 명령을 실행한다. 각자의 디렉토리에서 `puppeth`를 입력하여 실행하면 된다. 실행한 뒤에 쭈욱 과정을 진행하면 되는데, 아래를 참조하도록 한다.\n```\n+-----------------------------------------------------------+\n| Welcome to puppeth, your Ethereum private network manager |\n|                                                           |\n| This tool lets you create a new Ethereum network down to  |\n| the genesis block, bootnodes, miners and ethstats servers |\n| without the hassle that it would normally entail.         |\n|                                                           |\n| Puppeth uses SSH to dial in to remote servers, and builds |\n| its network components out of Docker containers using the |\n| docker-compose toolset.                                   |\n+-----------------------------------------------------------+\n\n// 자신이 생성할 네트워크 설정의 이름을 정한다.\nPlease specify a network name to administer (no spaces or hyphens, please)\n> duelnet\n\nSweet, you can set this via --network=duelnet_demo next time!\n\nINFO [08-08|09:39:10.290] Administering Ethereum network           name=duelnet_demo\nWARN [08-08|09:39:10.291] No previous configurations found         path=/home/ubuntu/.puppeth/duelnet_demo\n\n// 제네시스 파일을 새로 구성할 수 있는 2번을 선택한다.\nWhat would you like to do? (default = stats)\n 1. Show network stats\n 2. Configure new genesis\n 3. Track new remote server\n 4. Deploy network components\n> 2\n\n// PoA 엔진인 Clique를 선택한다.\nWhich consensus engine to use? (default = clique)\n 1. Ethash - proof-of-work\n 2. Clique - proof-of-authority\n> 2\n\n// 블록의 생성시간을 기술해준다.\nHow many seconds should blocks take? (default = 15)\n> 1\n\n// 위에서 의미룰 부여해주었던 계정들을 쭈욱 적어준다.\nWhich accounts are allowed to seal? (mandatory at least one)\n> 0x81bb2bfb72fc0ab991f79a58e9568d7cae57ccaa\n> 0x4a4961cd93da26276a22d5145a296c3a5a1b83fb\n> 0x78ddd4d1fa2036547687655fcac914852e558740\n> 0x\n\n// sealer 노드들과 faucet, accounts 0~2까지 이더를 지급한다.\n// PoA에서는 채굴 과정이 따로 없기 때문에 sealer 노드를 제외한 다른 노드들이 faucet 말고는 이더를 지급받을 방법이 존재하지 않는다.\nWhich accounts should be pre-funded? (advisable at least one)\n> 0x81bb2bfb72fc0ab991f79a58e9568d7cae57ccaa\n> 0x4a4961cd93da26276a22d5145a296c3a5a1b83fb\n> 0x78ddd4d1fa2036547687655fcac914852e558740\n> 0x3417cf2e1dea066db77239ad99f7e07f1e14cf0a\n> 0xd723a1aa820a5c5aa9ed1999e860f045038b2b05\n> 0x5e5e07c810948e7e837679db1b51e02cc936afc2\n> 0x096156b2c9a8043b6b288d0d40903f1dbe74b432\n> 0x\n\n// 디폴트로 랜덤한 네트워크 아이디를 생성해준다. Enter만 입력하고 넘어가자.\nSpecify your chain/network ID if you want an explicit one (default = random)\n>\nINFO [08-08|09:40:54.552] Configured new genesis block\n\n// 위에서 생성한 제네시스 파일을 추출하기 위해 2번을 선택한다.\nWhat would you like to do? (default = stats)\n 1. Show network stats\n 2. Manage existing genesis\n 3. Track new remote server\n 4. Deploy network components\n> 2\n\n 1. Modify existing fork rules\n 2. Export genesis configuration\n 3. Remove genesis configuration\n> 2\n\n// 디폴트로 설정하기 위해 Enter만 입력하여 진행\nWhich file to save the genesis into? (default = duelnet_demo.json)\n>\nINFO [08-08|09:40:58.932] Exported existing genesis block\n\nWhat would you like to do? (default = stats)\n 1. Show network stats\n 2. Manage existing genesis\n 3. Track new remote server\n 4. Deploy network components\n> Ctrl + c // 원하는 작업을 실행했으니 종료한다.\n```\n\n생성된 제네시스 파일을 편집기로 열어보면 내용이 꽤 길다는 것을 확인할 수 있다. 이는 `puppeth`가 중간 중간 dummy accounts를 미리 생성해두었기 때문이다. 자신이 설정한 계정들을 제외하고는 전부 지워주어 파일을 보기 편리하게 만들어두는 것을 추천한다. 따로 조작하지 않아도 상관은 없다.\n\n#### 3.5 Get Wallet Keyfiles\nSealer 노드들의 개인키를 복사하여 puppeth 내에서 사용가능하도록 환경을 구성할 것이다. 따라서 Sealer 노드들과 Faucet 노드의 개인키 파일의 내용을 따로 복사해두어 기록해두도록 한다. 아래와 같이 실행하여 나온 결과들을 따로 기록해두자.\n```\nSealer 0:\ncat UTC--2018-08-08T09-27-37.241084125Z--81bb2bfb72fc0ab991f79a58e9568d7cae57ccaa\nSealer 1:\ncat UTC--2018-08-08T09-33-06.102438431Z--4a4961cd93da26276a22d5145a296c3a5a1b83fb\nSealer 2:\ncat UTC--2018-08-08T09-33-07.073882847Z--78ddd4d1fa2036547687655fcac914852e558740\nFaucet:\ncat UTC--2018-08-08T09-33-08.031975188Z--3417cf2e1dea066db77239ad99f7e07f1e14cf0a\n```\n각 명령어들에 대한 결과는 아래와 같고 아래의 내용들을 따로 기록해두면 된다.\n```\nSealer 0:\n{\"address\":\"81bb2bfb72fc0ab991f79a58e9568d7cae57ccaa\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"ciphertext\":\"a30dc751a3ec33bb36b8ce5ca78abe7dbdf8ca68892bc2c9f8509cfc49077ee1\",\"cipherparams\":{\"iv\":\"2263fd6f213c7030abdc12b56acf3ce8\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"4c84fd7a79af24a7be3c5314b37aa08998ec69188c324181e19357ddc51497ce\"},\"mac\":\"eae031ffa5e046a8dd17d07d7b7f7c235cc0ea8c726f4eac32b0a302e7107754\"},\"id\":\"befc4d2e-9244-46d9-8227-cd37da8efd6f\",\"version\":3}\n\nSealer 1:\n{\"address\":\"4a4961cd93da26276a22d5145a296c3a5a1b83fb\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"ciphertext\":\"e176164bfd9fc6653e0ea3e418084af1de528a2dd10ffe29b9b35ea733f3ca9b\",\"cipherparams\":{\"iv\":\"cd7ea7ae9426d56138d62cbb3e9b14dd\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"e82093953f5892b60c84749e98fb575e2acd1a43d4477f6ea6f682974a806d13\"},\"mac\":\"e6c56be76c1009fafc2c921ab1b331f7c3874590f9e5e6a8b36dc98169abfa28\"},\"id\":\"528c9ce2-b4fe-4403-be02-898c0a0b096b\",\"version\":3}\n\nSealer 2:\n{\"address\":\"78ddd4d1fa2036547687655fcac914852e558740\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"ciphertext\":\"1730c3d659528dafab59f854cccef85714cfab2f7e3c573058aa0e7c6bdc282a\",\"cipherparams\":{\"iv\":\"f56a23b8b4d4377510655a775e90df2f\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"2373352ac9a663385100c45d93287263153e1dc020cbc884294370d261033450\"},\"mac\":\"7a745f562fd47a1cdf9e65597e76ceb4f7d27f4d469469ccea41f54ad733ea3d\"},\"id\":\"42356c9d-e3fd-4790-8c7f-9ca629d2f3f5\",\"version\":3}\n\nFaucet:\n{\"address\":\"3417cf2e1dea066db77239ad99f7e07f1e14cf0a\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"ciphertext\":\"e9be248ab81f9a6b9536827fb53160a5567825628ec952d8599837e78e024cb5\",\"cipherparams\":{\"iv\":\"48ec9dbf1ea1a555f5f8860f70f6d183\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"180ab095a7f3de3427a0b67028b5e5e74afa43cfc42310f9bb422268aa8a41b9\"},\"mac\":\"19e401009907e226b2c73bc7c06d33fb6bbc0fb90e378cd2afd33f0ad19f3019\"},\"id\":\"661b0dd8-0176-4beb-9fa7-bd81dcd2d533\",\"version\":3}\n```\n\n## 4. Puppeth를 이용한 네트워크 배포\n`puppeth --network duelnet` 와 같은 포맷으로 네트워크 옵션을 주어 자신이 기존에 생성해두었던 네트워크 세팅을 불러온다. 진행해야 할 작업들은 아래와 같다.\n\n### 4.1 node0에게 Ethstat 역할을 부여한다.\n\n1. 4. Deploy network components를 선택한다. `puppeth`에서 미리 제작해둔 편리한 기능들을 이용하여 각 노드들에 알맞은 역할을 부여하는 작업을 진행할 것이다.\n2. 1. Connect another server를 선택한다.\n3. 13.124.241.99 // 자신의 인스턴스 중 node0의 아이피 주소를 입력해준다.\n4. 8080 // 다른 포트로 진행해도 상관은 없지만, 필자는 8080으로 설정했다.\n5. n // 포트 공유를 하지 못하게 설정해놓는다. 온전한 서비스를 위해서.\n6. secret password는 설정해도 되고 설정하지 않아도 된다.\n\n위의 과정을 진행하면 아래와 같은 결과물을 확인할 수 있다.\n```\nCreating network \"duelnet_default\" with the default driver\nBuilding ethstats\nStep 1/2 : FROM puppeth/ethstats:latest\nlatest: Pulling from puppeth/ethstats\nDigest: sha256:1728c03555d3327f68be924116eed9f9de56671949c21505f4b78518f06e687e\nStatus: Downloaded newer image for puppeth/ethstats:latest\n ---> fb62abe59cb2\nStep 2/2 : RUN echo 'module.exports = {trusted: [\"13.124.241.99\"], banned: [], reserved: [\"yournode\"]};' > lib/utils/config.js\n ---> Running in 08f875b59b9b\n ---> 2b43e5422c5d\nRemoving intermediate container 08f875b59b9b\nSuccessfully built 2b43e5422c5d\nCreating duelnetdemo_ethstats_1\nINFO [08-08|09:54:02.907] Starting remote server health-check      server=13.124.241.99\n+---------------+---------------+---------+--------+-------+\n|    SERVER     |    ADDRESS    | SERVICE | CONFIG | VALUE |\n+---------------+---------------+---------+--------+-------+\n| 13.124.241.99 | 13.124.241.99 |         |        |       |\n+---------------+---------------+---------+--------+-------+\n```\n\n이로써 Ethstat이 동작함을 확인할 수 있다. `http://<ip of node0>:8080` 포맷으로 웹 브라우저 주소창에 검색해서 들어가면 Ethstat 페이지를 만나볼 수 있다.\n\n우리가 한 작업을 요약하자면, Controller 노드에서 `puppeth`를 사용하여 `node0`(t2.medium)이 `Docker`를 활용하여 `Ethstat` 서비스를 실행하게끔 구성한 것이다. `puppeth`가 `node0`을 제어할 수 있었던 이유는 사전에 우리가 `public key, private key` 작업을 미리 해줬기 때문이다.\n\n### 4.2 node0에게 Bootnode의 역할을 추가로 부여한다.\n역할을 추가로 부여한다는 건 결국 해당 노드의 도커 컨테이너를 하나 더 생성해서 실행시켜준다는 의미다. `puppeth`를 실행하여 아래의 과정을 진행하여 부트노드를 동작 시켜보자.\n\n1. 4. Manage network components 메뉴를 선택한다.\n2. 2. Deploy new network component 항목을 선택한다.\n3. 2. Bootnode 항목을 선택한다.\n4. 1. 13.124.241.99를 선택한다. // 현재 Ethstat의 역할을 담당하고 있는 node0에게 추가로 권한을 부여하는 것이므로 node0의 ip주소를 그대로 사용하는 것이 맞다.\n5. `/home/ubuntu/ethereum/duelnet/bootnode` // 이 포맷으로 Bootnode관련 데이터를 어디 저장시킬 것인지를 기술한다.\n6. 나머지 옵션들(connecting peer number, light peers number)은 생략한다.\n7. `duelnet_bootnode`으로 이름을 작성한다. // 해당 노드의 역할에 이름을 붙이는 것이라고 생각하면 된다.\n\n실행하면 아래와 같은 결과를 만나볼 수 있다.\n```\n+---------------+---------------+----------+--------------------------+----------------------------------------+\n|    SERVER     |    ADDRESS    | SERVICE  |          CONFIG          |                 VALUE                  |\n+---------------+---------------+----------+--------------------------+----------------------------------------+\n| 13.124.241.99 | 13.124.241.99 | bootnode | Data directory           | /home/ubuntu/ethereum/duelnet/bootnode |\n|               |               |          | Ethstats username        | duelnet_bootnode                       |\n|               |               |          | Listener port            | 30305                                  |\n|               |               |          | Peer count (all total)   | 512                                    |\n|               |               |          | Peer count (light nodes) | 256                                    |\n|               |               |          | ------------------------ | -------------------------------------- |\n|               |               | ethstats | Banned addresses         |                                        |\n|               |               |          | Login secret             | 2326                                   |\n|               |               |          | Website address          | 13.124.241.99                          |\n|               |               |          | Website listener port    | 8080                                   |\n+---------------+---------------+----------+--------------------------+----------------------------------------+\n```\n\n### 4.3 노드0, 노드1, 노드2에게 각각 Sealer 역할 부여\n현재까지 노드0에서는 Ethstats 및 Bootnode 역할을 담당하고 있다. 이제는 블록 검증을 위한 Sealer 노드들을 설정하고 이용할 차례다. 아래의 과정을 각 노드(노드0 ~ 노드2)에게 진행하면 된다. 즉 Controller 노드에서 `puppeth`를 실행시키고 노드0~노드2의 ip주소를 각각 입력하여 Sealer 역할을 부여하면 된다.\n\n1. 4. Deploy network components 메뉴를 선택한다.\n2. 3. Deploy new network component 메뉴를 선택한다. // 참여하는 노드가 점점 많아질 수록 이 수치는 점점 높아진다.\n3. 3. Sealer // 새로운 블록을 생성하는 Full node 역할을 담당하게 된다.\n4. 2. Connect another server 메뉴를 선택해서 각 노드의 ip를 적용시켜주면 된다.\n5. `/home/ubuntu/ethereum/duelnet/sealernode` 디렉토리를 데이터 디렉토리로 설정한다.\n6. 나머지 옵션들(TCP/IP port, number of peer connections, light peers)은 default로 둬도 상관 없으므로 Enter로 넘어가도록 한다.\n7. 이름을 지정해줘야 하므로 `duelnet_sealer_0, duelnet_sealer_1, duelnet_sealer2` 와 같이 체계적인 이름으로 각 노드의 역할에 이름을 부여한다.\n\n위의 과정을 진행하여 3개의 노드가 Sealer 노드로 모두 참여시켜 네트워크를 구성한 후 다시한 번 웹 브라우저에서 Ethstats 방문한다면 아래와 같은 화면을 만나볼 수 있을 것이다.\n\nhttps://cdn.steemitimages.com/DQmbtRNUZqUYSkWsDRMKMujpjdx1br9RGouZouXt5eRJMhD/image.png\n\nSealer 노드가 3개 존재하고 Bootnode가 존재하고 있다. 모든 노드들이 정상적으로 등록되고 인식되고 있다는 것을 확인할 수 있다.\n\n### 4.4 채굴 진행해보기 (채굴이라 칭하기도 하고, Sealing | Validating로 불리기도 한다.)\n지금까지 구성한 환경만으로는 아직 블록이 하나도 생성되지 않고 있다. `Ethstats` 에 웹브라우저로 접근하면 알 수 있다. 네트워크가 현재 멈춰 있으므로 채굴 과정을 진행시켜보겠다.\n\n먼저 Controller node에서 `ssh ubuntu@<ip of boonode>` 를 입력하여 `Bootnode` 역할을 담당하고 있는 `node0`에게 접속한다. 그리고 `docker ps` 명령어로 현재 실행중인 컨테이너를 확인한다. 명령의 결과는 아래와 같다.\n\n```\nCONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                                                                                     NAMES\nc1efa7cbe17f        duelnet/sealnode    \"/bin/sh geth.sh\"   11 minutes ago      Up 11 minutes       8545-8546/tcp, 0.0.0.0:30303->30303/tcp, 0.0.0.0:30303->30303/udp                         duelnet_sealnode_1\n8266f6a9d2d2        duelnet/bootnode    \"/bin/sh geth.sh\"   22 minutes ago      Up 22 minutes       8545-8546/tcp, 30303/tcp, 30303/udp, 0.0.0.0:30305->30305/tcp, 0.0.0.0:30305->30305/udp   duelnet_bootnode_1\n0a1265c25972        duelnet/ethstats    \"npm start\"         33 minutes ago      Up 33 minutes       0.0.0.0:8080->3000/tcp                                                                    duelnet_ethstats_1\n```\n\n가장 첫번째로 출력되는 `duelnet/sealnode`의 `CONTAINER ID` 를 확인하여 다음의 명령어 포맷으로 `geth` 콘솔을 실행하도록 하자. `docker exec -it <container_id> ` geth attach ipc:/root/.ethereum/geth.ipc`\n\n필자의 경우는 `docker exec -it c1e geth attach` 명령으로 `geth console`을 실행할 수 있었다. 콘솔에 접근한 이유는 해당 노드의 `enode` 정보를 알아내기 위한 것이다. 콘솔 내에서 `admin.nodeInfo.enode` 명령으로 해당 노드의 `enode`정보를 추출하고 위 작업을 node1, node2에게도 동일하게 진행한다.\n\n각 과정을 진행하면서 `enode` 정보를 기록하고, 그렇게 하면 아래와 같은 정보를 얻어낼 수 있을 것이다.\n```\nSealer 0:\n\"enode://ec9046bc66b3c5f940bcb8023f127aa721da61c02ae4906e8e2c738295aa17bf18acbcb5f27f21f026f4b37eb44fe24e0b674ac69a01e4db0b4a4007a5e5e6b2@13.124.241.98:30303\"\n\nSealer 1:\n\"enode://cf47010e6b3a855511eb719cfd29c6b80e74e7e5a023878eaf393fc157b9f9a7704f6650f7719a247c64cf68903738233483f83a7081e12a4f641c11564e7431@52.78.17.178:30303\"\n\nSealer 2:\n\"enode://87789df6d972fc357384606cd833dc8529a178cfde411d81125ba229c8be1e1425483ca97da055a2a5bc8419d38c859181ff152678e7f7bc6c5339090e4122db@13.209.73.50:30303\"\n```\n\n기억한 `enode` 정보를 가지고 `Bootnode` 역할을 맡고 있는 node0의 `geth console`을 실행시켜 다음의 명령어 포맷으로 각 노드를 연결시켜주도록 한다. `admin.addPeer(\"<enode from other nodes>\")` 현재 노드0에서 실행하고 있으므로 노드1과 노드2의 `enode` 정보를 확인한 후에 적용시켜주면 된다.\n\n## 5. 나머지 서비스 구현\n> 나머지 서비스들은 모두 Ethstats 서비스를 제공하고 있는 노드0에서 이루어져야 한다. 구축해야 할 서비스들은 아래와 같다.\n1. The MyCrypto wallet app\n2. A faucet\n3. A block explorer (PoA 네트워크에서는 아직 지원되지 않는다.)\n4. A dashboard to tie it all together\n\n`puppeth` 를 사용하여 배포할 때 헷갈리는 점이 있는 건 `faucet app` 뿐이므로 해당 절차만 기술하도록 하겠다. 나머지는 필요에 따라 본인이 직접 조작해보는 걸 추천한다.\n\n### 5.1 Wallet App\n### 5.2 Faucet App\n특이하게도 `reCAPCHA v2` 서비스의 `Site key` `Secret key`를 요구한다. 이 경우 `reCAPCHA` 사이트에 접속하여 생성할 수 있고 생성하여 얻은 각 키 정보를 입력해주면 된다.\n### 5.3 Dashboard\n\n## 6. 마치며\n개발자가 해야할 일을 대폭 줄여주는 `puppeth`는 확실히 효자 프로그램이라 할 수 있다. 그러나 여전히 근본적인 구조에 대한 이해는 필요하다고 생각한다. 각 앱을 구현하는데 있어서 필요한 정보가 어떤 것이 있을지 생각해보고 `puppeth` 를 이용하는 것이 개발 실력 뿐만 아니라 통찰에도 많은 도움을 줄 거라 생각한다.\n\n마침 아직 PoA에 관한 `Block Explorer` 는`puppeth` 에서 제공하지 않으니 직접 구현해보는 건 어떨까? 이번 포스팅은 여기서 마치도록 한다.",
      "json_metadata": "{\"tags\":[\"ethereum\",\"poa\",\"blockchain\",\"privateblockchain\"],\"image\":[\"https://cdn.steemitimages.com/DQmNae973aXjn5G5YG98h91bBTQsq4TCKnGy5EcbagEdXxU/image.png\",\"https://cdn.steemitimages.com/DQmbtRNUZqUYSkWsDRMKMujpjdx1br9RGouZouXt5eRJMhD/image.png\"],\"links\":[\"https://medium.com/@collin.cusce/using-puppeth-to-manually-create-an-ethereum-proof-of-authority-clique-network-on-aws-ae0d7c906cce\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
    }
  ]
}
2018/07/10 11:02:42
voteryehey
authordlgusdn616
permlinkethereum-abi-q-and-a
weight1000 (10.00%)
Transaction InfoBlock #24051528/Trx 1671c7212e5b218193f3b8277321302c7b02cc4b
View Raw JSON Data
{
  "trx_id": "1671c7212e5b218193f3b8277321302c7b02cc4b",
  "block": 24051528,
  "trx_in_block": 21,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-07-10T11:02:42",
  "op": [
    "vote",
    {
      "voter": "yehey",
      "author": "dlgusdn616",
      "permlink": "ethereum-abi-q-and-a",
      "weight": 1000
    }
  ]
}
2018/07/10 10:23:24
voteralphabot
authordlgusdn616
permlinkethereum-abi-q-and-a
weight100 (1.00%)
Transaction InfoBlock #24050742/Trx 278b0b14e7451b32b040aafe9ac007220592b537
View Raw JSON Data
{
  "trx_id": "278b0b14e7451b32b040aafe9ac007220592b537",
  "block": 24050742,
  "trx_in_block": 39,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-07-10T10:23:24",
  "op": [
    "vote",
    {
      "voter": "alphabot",
      "author": "dlgusdn616",
      "permlink": "ethereum-abi-q-and-a",
      "weight": 100
    }
  ]
}
dlgusdn616published a new post: ethereum-abi-q-and-a
2018/07/10 10:23:15
parent author
parent permlinketheruem
authordlgusdn616
permlinkethereum-abi-q-and-a
titleEthereum:: ABI와 관련된 Q&A 정리
body@@ -4043,12 +4043,288 @@ lower level. +%0A%0A### %EB%B3%B4%EB%84%88%EC%8A%A4: Function Selector%EB%9E%80?%0A%0A%ED%95%A8%EC%88%98 %ED%98%B8%EC%B6%9C%EC%8B%9C %EB%B0%9C%EC%83%9D%ED%95%98%EB%8A%94 4%EB%B0%94%EC%9D%B4%ED%8A%B8%EC%9D%98 %EC%BD%9C %EB%8D%B0%EC%9D%B4%ED%84%B0%EB%8A%94 %ED%98%B8%EC%B6%9C%ED%95%A0 %ED%95%A8%EC%88%98%EB%A5%BC %EA%B2%B0%EC%A0%95%ED%95%9C%EB%8B%A4. 4%EB%B0%94%EC%9D%B4%ED%8A%B8%EC%9D%98 %EB%8D%B0%EC%9D%B4%ED%84%B0%EB%8A%94 Keccack256%EB%A1%9C %ED%95%A8%EC%88%98%EC%9D%98 %EC%84%9C%EB%AA%85%EC%A0%95%EB%B3%B4%EB%A5%BC %ED%95%B4%EC%8B%9C%ED%95%98%EC%97%AC %EB%B9%85 %EC%97%94%EB%94%94%EC%95%88 %EB%B0%A9%EC%8B%9D%EC%9C%BC%EB%A1%9C %EA%B8%B0%EC%88%A0%ED%96%88%EC%9D%84 %EC%8B%9C, %EC%B2%AB %EB%B2%88%EC%A7%B8 %EB%84%A4 %EB%B0%94%EC%9D%B4%ED%8A%B8%EB%A5%BC %EC%9D%BC%EC%BB%AB%EB%8A%94%EB%8B%A4. %0A%EC%84%9C%EB%AA%85 %EC%A0%95%EB%B3%B4%EB%8A%94 %EA%B8%B0%EB%B3%B8%EC%A0%81%EC%9D%B8 %ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85%EC%97%90 %EB%8C%80%ED%95%9C %ED%91%9C%ED%98%84%EB%B2%95%EC%9C%BC%EB%A1%9C %EC%A0%95%EC%9D%98%EB%90%9C%EB%8B%A4. %EC%98%88%EB%A1%9C, %ED%95%A8%EC%88%98 %EC%9D%B4%EB%A6%84%EA%B3%BC %EB%A7%A4%EA%B0%9C%EB%B3%80%EC%88%98%EB%93%A4%EC%9D%98 %EC%9E%90%EB%A3%8C%ED%98%95%EC%9D%B4 %EC%9E%88%EB%8B%A4. %EB%A7%A4%EA%B0%9C%EB%B3%80%EC%88%98%EC%9D%98 %EC%9E%90%EB%A3%8C%ED%98%95%EC%9D%80 %EC%BD%A4%EB%A7%88%EB%A1%9C %EA%B5%AC%EB%B6%84%EB%90%98%EB%A9%B0 %EA%B3%B5%EB%B0%B1%EA%B5%AC%EB%B6%84%EC%9E%90%EB%8A%94 %EC%9D%B8%EC%A0%95%EB%90%98%EC%A7%80 %EC%95%8A%EB%8A%94%EB%8B%A4.%0A%0A%3E %EB%A6%AC%ED%84%B4%ED%83%80%EC%9E%85%EC%9D%98 %EA%B2%BD%EC%9A%B0 %ED%95%A8%EC%88%98 %EC%84%9C%EB%AA%85%EC%A0%95%EB%B3%B4%EC%97%90 %ED%8F%AC%ED%95%A8%EB%90%98%EC%A7%80 %EC%95%8A%EB%8A%94%EB%8B%A4.
json metadata{"tags":["etheruem","abi","bytecode"],"links":["https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI","https://ethereum.stackexchange.com/questions/29717/is-sending-some-datas-in-the-data-field-safe","https://github.com/ethereum/yellowpaper"],"app":"steemit/0.1","format":"markdown"}
Transaction InfoBlock #24050739/Trx 0ef17244f764551bd386d8f29421edc99e965f85
View Raw JSON Data
{
  "trx_id": "0ef17244f764551bd386d8f29421edc99e965f85",
  "block": 24050739,
  "trx_in_block": 11,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-07-10T10:23:15",
  "op": [
    "comment",
    {
      "parent_author": "",
      "parent_permlink": "etheruem",
      "author": "dlgusdn616",
      "permlink": "ethereum-abi-q-and-a",
      "title": "Ethereum:: ABI와 관련된 Q&A 정리",
      "body": "@@ -4043,12 +4043,288 @@\n lower level.\n+%0A%0A### %EB%B3%B4%EB%84%88%EC%8A%A4: Function Selector%EB%9E%80?%0A%0A%ED%95%A8%EC%88%98 %ED%98%B8%EC%B6%9C%EC%8B%9C %EB%B0%9C%EC%83%9D%ED%95%98%EB%8A%94 4%EB%B0%94%EC%9D%B4%ED%8A%B8%EC%9D%98 %EC%BD%9C %EB%8D%B0%EC%9D%B4%ED%84%B0%EB%8A%94 %ED%98%B8%EC%B6%9C%ED%95%A0 %ED%95%A8%EC%88%98%EB%A5%BC %EA%B2%B0%EC%A0%95%ED%95%9C%EB%8B%A4. 4%EB%B0%94%EC%9D%B4%ED%8A%B8%EC%9D%98 %EB%8D%B0%EC%9D%B4%ED%84%B0%EB%8A%94 Keccack256%EB%A1%9C %ED%95%A8%EC%88%98%EC%9D%98 %EC%84%9C%EB%AA%85%EC%A0%95%EB%B3%B4%EB%A5%BC %ED%95%B4%EC%8B%9C%ED%95%98%EC%97%AC  %EB%B9%85 %EC%97%94%EB%94%94%EC%95%88 %EB%B0%A9%EC%8B%9D%EC%9C%BC%EB%A1%9C %EA%B8%B0%EC%88%A0%ED%96%88%EC%9D%84 %EC%8B%9C, %EC%B2%AB %EB%B2%88%EC%A7%B8 %EB%84%A4 %EB%B0%94%EC%9D%B4%ED%8A%B8%EB%A5%BC %EC%9D%BC%EC%BB%AB%EB%8A%94%EB%8B%A4. %0A%EC%84%9C%EB%AA%85 %EC%A0%95%EB%B3%B4%EB%8A%94 %EA%B8%B0%EB%B3%B8%EC%A0%81%EC%9D%B8 %ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85%EC%97%90 %EB%8C%80%ED%95%9C %ED%91%9C%ED%98%84%EB%B2%95%EC%9C%BC%EB%A1%9C %EC%A0%95%EC%9D%98%EB%90%9C%EB%8B%A4. %EC%98%88%EB%A1%9C, %ED%95%A8%EC%88%98 %EC%9D%B4%EB%A6%84%EA%B3%BC %EB%A7%A4%EA%B0%9C%EB%B3%80%EC%88%98%EB%93%A4%EC%9D%98 %EC%9E%90%EB%A3%8C%ED%98%95%EC%9D%B4 %EC%9E%88%EB%8B%A4. %EB%A7%A4%EA%B0%9C%EB%B3%80%EC%88%98%EC%9D%98 %EC%9E%90%EB%A3%8C%ED%98%95%EC%9D%80 %EC%BD%A4%EB%A7%88%EB%A1%9C %EA%B5%AC%EB%B6%84%EB%90%98%EB%A9%B0 %EA%B3%B5%EB%B0%B1%EA%B5%AC%EB%B6%84%EC%9E%90%EB%8A%94 %EC%9D%B8%EC%A0%95%EB%90%98%EC%A7%80 %EC%95%8A%EB%8A%94%EB%8B%A4.%0A%0A%3E %EB%A6%AC%ED%84%B4%ED%83%80%EC%9E%85%EC%9D%98 %EA%B2%BD%EC%9A%B0 %ED%95%A8%EC%88%98 %EC%84%9C%EB%AA%85%EC%A0%95%EB%B3%B4%EC%97%90 %ED%8F%AC%ED%95%A8%EB%90%98%EC%A7%80 %EC%95%8A%EB%8A%94%EB%8B%A4.\n",
      "json_metadata": "{\"tags\":[\"etheruem\",\"abi\",\"bytecode\"],\"links\":[\"https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI\",\"https://ethereum.stackexchange.com/questions/29717/is-sending-some-datas-in-the-data-field-safe\",\"https://github.com/ethereum/yellowpaper\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
    }
  ]
}
2018/07/10 10:16:42
voterfastresteem
authordlgusdn616
permlinkethereum-abi-q-and-a
weight100 (1.00%)
Transaction InfoBlock #24050608/Trx ac26b877fea3b992dddd0740e745674c7046a459
View Raw JSON Data
{
  "trx_id": "ac26b877fea3b992dddd0740e745674c7046a459",
  "block": 24050608,
  "trx_in_block": 3,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-07-10T10:16:42",
  "op": [
    "vote",
    {
      "voter": "fastresteem",
      "author": "dlgusdn616",
      "permlink": "ethereum-abi-q-and-a",
      "weight": 100
    }
  ]
}
dlgusdn616published a new post: ethereum-abi-q-and-a
2018/07/10 10:16:30
parent author
parent permlinketheruem
authordlgusdn616
permlinkethereum-abi-q-and-a
titleEthereum:: ABI와 관련된 Q&A 정리
body## ABI (Application Binary Interface) 이더리움의 ABI에 대해 공부하면서 EthereumStackExchange 사이트를 정말 많이 이용하였습니다. 사이트를 돌아다니면서 ABI를 이해하는데 있어서 저에게 많은 도움이 되었던 질문 및 답변을 정리한 포스팅입니다. ### Question: ABI는 어떻게 바이트 코드로 저장되는가? `0x25d8dcf2`와 같은 16진수 문자열의 정보만으로 컨트랙트 내의 함수를 어떻게 식별할 수 있을까? 함수 서명정보의 해시이다. * Answer1: 메서드 ID를 가지고 컨트랙트의 바이트코드 안에 주소와 정확하게 연결시켜주는 작업을 하는 것이 컴파일러고, 컴파일러는 정확하게 동작하는 EVM 바이트코드를 생성할 것이다. MethodID는 4바이트이기 때문에, 해시 충돌 (2개의 서로 다른 함수에서)이 가능하다. 솔리디티 컴파일러는 해시 충돌의 경우 에러를 반환하고 어떠한 바이트코드도 더이상 생산해내지 않는다. EVM 컴파일러가 생성하는 바이트코드의 예시는 아래와 같다. ``` method_id = first 4 bytes of msg.data if method_id == 0x25d8dcf2 jump to 0x11 if method_id == 0xaabbccdd jump to 0x22 if method_id == 0xffaaccee jump to 0x33 other code 0x11: code for function with method id 0x25d8dcf2 0x22: code for another function 0x33: code for another function ``` ### ABI는 무엇이고 컨트랙트에 왜 필요한가? * Answer1 ABI는 보통 두 프로그램 모듈의 인터페이스 역할을 하고 그 중 하나는 종종 기계어 레벨에 있다. 인터페이스는 데이터를 기계 코드로 인코딩/디코딩 하기 위한 방법이다. 이더리움에서는 기본적으로 EVM에 솔리디티 컨트랙트 호출을 할 때 인코딩을 하거나, 트랜잭션들로부터 데이터를 읽는 방법이다. * Answer2 ABI는 컨트랙트 내의 함수를 호출하거나 컨트랙트로부터 데이터를 얻는 방법이다. 이더리움 스마트 컨트랙트는 이더리움 블록체인에 배포된 바이트코드다. 컨트랙트 내에 여러 개의 함수가 있을 수 있을 것이다. ABI는 컨트랙트 내의 어떤 함수를 호출할지를 지정하는데 필요하며, 우리가 생각했던 대로 함수가 데이터를 리턴한다는 것을 보장하기 위해 반드시 필요하다. [Ethereum Contract ABI ](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI) 에 등장한 예시를 살펴보면: ``` contract Foo { function bar(real[2] xy) {} function baz(uint32 x, bool y) returns (bool r) { r = x > 32 || y; } function sam(bytes name, bool z, uint[] data) {} } ``` 만약 baz 함수를 69와 true를 매개변수로 호출했다고 가정해보자. 아래와 같이 총 68바이트의 데이터를 사용할 것이다. 메서드 식별자 4바이트, 32바이트로 감싸진 69라는 값, 32바이트로 감싸진 true값 이렇게 68바이트다. ``` 0xcdcd77c0: the Method ID. This is derived as the first 4 bytes of the Keccak-256 hash of the ASCII form of the signature baz(uint32,bool). 0x0000000000000000000000000000000000000000000000000000000000000045: the first parameter, a uint32 value 69 padded to 32 bytes 0x0000000000000000000000000000000000000000000000000000000000000001: the second parameter - boolean true, padded to 32 bytes ``` 위의 68바이트 데이터는 트랜잭션의 `data` 필드에 기술될 것이다: 관련 보안적인 이슈가 있으니 확인을 해보도록 하자. [보안 이슈](https://ethereum.stackexchange.com/questions/29717/is-sending-some-datas-in-the-data-field-safe). 해당 보안 이슈를 요약하자면 데이터 필드에 값을 넣을 때는 조심해야 한다는 것이다. 컨트랙트를 호출 시 데이터를 함께 보내는 과정에서 부작용이 발생할 수 있기 때문. 메서드 식별자를 추출할 때, 일반적으로 알려진 위험을 예방하려면 `canonical types`가 반드시 사용되어야 한다. 예를 들어, `uint`대신 `uint256`을 사용하도록 한다. 솔리디티가 메서드 식별자를 계산할 때의 과정을 위 코드의 `sam`메서드를 이용하여 예로 들어보면: `bytes4(sha3("sam(bytes, bool, uint256[])")` web3.js와 같은 고수준 라이브러리를 사용하다보면, 이런 디테일을 놓칠 수 있다. 여전히 이러한 고수준 라이브러리에서도 JSON형식의 ABI가 제공될 필요가 있다. > ABI는 [코어 이더리움 프로토콜](https://github.com/ethereum/yellowpaper)에 포함되지는 않는다. 누구나 자신의 컨트랙트에 대응되는 ABI를 만들어낼 수 있다. 물론 호출자는 해당 컨트랙트의 ABI를 알고 있어야 컨트랙트를 제대로 이용할 수 있다. * Answer3 **Contract Definition**: 전형적인 고수준 코드로 정의 **Compiled Contract**: 이더리움 가상 머신(EVM)에서 동작하기 위해 바이트 코드로 변환된 컨트랙트. 함수의 이름과 매개변수들이 컴파일 과정에서 해시된다. 그러므로 다른 계정이 함수를 호출하기 위해서는 함수 이름과 매개변수들을 알고 있어야 한다. ABI의 등장 이유 **Application Binary Interface**: 컨트랙트의 함수와 매개변수들을 JSON 형식으로 나타낸 리스트다. 스마트 컨트랙트의 함수를 이용하기 위해서는 ABI를 사용하여 함수의를 해시할 수 있어야 한다. 이렇게 하면 해당 함수를 호출하기 위해 필요한 EVM 바이트 코드를 생성할 수 있다. 그러고선 트랜잭션의 데이터 필드인 Td에 포함되고 EVM에 의해 해석(컨트랙트 주소에 맞춰 코드가 해석됨)된다. * Answer4 think of "ABI" as an "API" at a low level. > 따로 번역은 하지 않았지만.. 꼭 읽어보시는 걸 추천드립니다. The API consists of a set of routines, objects, etc. that you can use in your code to access the functionality of that external component. An ABI is very similar. Think of it as the compiled version of an API (or as an API on the low level). as you know The contract are stored as bytecode in a binary form into the blockchain under a specific address. so you can accesses the binary data in the contract through the ABI which indicates to the caller the needed information (functions signatures and variables declarations) to encode a meaningful(understood by the VM) call to the bytecode(contract). The ABI defines the structures and methods that you will use to interact with binary contract (just like the API did), only on a lower level.
json metadata{"tags":["etheruem","abi","bytecode"],"links":["https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI","https://ethereum.stackexchange.com/questions/29717/is-sending-some-datas-in-the-data-field-safe","https://github.com/ethereum/yellowpaper"],"app":"steemit/0.1","format":"markdown"}
Transaction InfoBlock #24050604/Trx baf429242883dc7abecba7c54db237ce1a52220a
View Raw JSON Data
{
  "trx_id": "baf429242883dc7abecba7c54db237ce1a52220a",
  "block": 24050604,
  "trx_in_block": 38,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-07-10T10:16:30",
  "op": [
    "comment",
    {
      "parent_author": "",
      "parent_permlink": "etheruem",
      "author": "dlgusdn616",
      "permlink": "ethereum-abi-q-and-a",
      "title": "Ethereum:: ABI와 관련된 Q&A 정리",
      "body": "## ABI (Application Binary Interface)\n이더리움의 ABI에 대해 공부하면서 EthereumStackExchange 사이트를 정말 많이 이용하였습니다. 사이트를 돌아다니면서 ABI를 이해하는데 있어서 저에게 많은 도움이 되었던 질문 및 답변을 정리한 포스팅입니다.\n### Question: ABI는 어떻게 바이트 코드로 저장되는가?\n`0x25d8dcf2`와 같은 16진수 문자열의 정보만으로 컨트랙트 내의 함수를 어떻게 식별할 수 있을까? 함수 서명정보의 해시이다. \n* Answer1:\n메서드 ID를 가지고 컨트랙트의 바이트코드 안에 주소와 정확하게 연결시켜주는 작업을 하는 것이 컴파일러고, 컴파일러는 정확하게 동작하는 EVM 바이트코드를 생성할 것이다.\nMethodID는 4바이트이기 때문에, 해시 충돌 (2개의 서로 다른 함수에서)이 가능하다. 솔리디티 컴파일러는 해시 충돌의 경우 에러를 반환하고 어떠한 바이트코드도 더이상 생산해내지 않는다.\nEVM 컴파일러가 생성하는 바이트코드의 예시는 아래와 같다.\n```\nmethod_id = first 4 bytes of msg.data\nif method_id == 0x25d8dcf2 jump to 0x11\nif method_id == 0xaabbccdd jump to 0x22\nif method_id == 0xffaaccee jump to 0x33\nother code\n0x11:\ncode for function with method id 0x25d8dcf2\n0x22:\ncode for another function\n0x33:\ncode for another function\n```\n\n\n### ABI는 무엇이고 컨트랙트에 왜 필요한가?\n* Answer1\nABI는 보통 두 프로그램 모듈의 인터페이스 역할을 하고 그 중 하나는 종종 기계어 레벨에 있다. 인터페이스는 데이터를 기계 코드로 인코딩/디코딩 하기 위한 방법이다. \n이더리움에서는 기본적으로 EVM에 솔리디티 컨트랙트 호출을 할 때 인코딩을 하거나, 트랜잭션들로부터 데이터를 읽는 방법이다. \n\n* Answer2\nABI는 컨트랙트 내의 함수를 호출하거나 컨트랙트로부터 데이터를 얻는 방법이다. 이더리움 스마트 컨트랙트는 이더리움 블록체인에 배포된 바이트코드다. 컨트랙트 내에 여러 개의 함수가 있을 수 있을 것이다. ABI는 컨트랙트 내의 어떤 함수를 호출할지를 지정하는데 필요하며, 우리가 생각했던 대로 함수가 데이터를 리턴한다는 것을 보장하기 위해 반드시 필요하다.\n\n[Ethereum Contract ABI ](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI) 에 등장한 예시를 살펴보면:\n```\ncontract Foo {\n  function bar(real[2] xy) {}\n  function baz(uint32 x, bool y) returns (bool r) { r = x > 32 || y; }\n  function sam(bytes name, bool z, uint[] data) {}\n}\n```\n만약 baz 함수를 69와 true를 매개변수로 호출했다고 가정해보자. 아래와 같이 총 68바이트의 데이터를 사용할 것이다. 메서드 식별자 4바이트, 32바이트로 감싸진 69라는 값, 32바이트로 감싸진 true값 이렇게 68바이트다.\n```\n0xcdcd77c0: the Method ID. This is derived as the first 4 bytes of the Keccak-256 hash of the ASCII form of the signature baz(uint32,bool). 0x0000000000000000000000000000000000000000000000000000000000000045: the first parameter, a uint32 value 69 padded to 32 bytes 0x0000000000000000000000000000000000000000000000000000000000000001: the second parameter - boolean true, padded to 32 bytes\n```\n위의 68바이트 데이터는 트랜잭션의 `data` 필드에 기술될 것이다: 관련 보안적인 이슈가 있으니 확인을 해보도록 하자. [보안 이슈](https://ethereum.stackexchange.com/questions/29717/is-sending-some-datas-in-the-data-field-safe). 해당 보안 이슈를 요약하자면 데이터 필드에 값을 넣을 때는 조심해야 한다는 것이다. 컨트랙트를 호출 시 데이터를 함께 보내는 과정에서 부작용이 발생할 수 있기 때문.\n메서드 식별자를 추출할 때, 일반적으로 알려진 위험을 예방하려면 `canonical types`가 반드시 사용되어야 한다. 예를 들어, `uint`대신 `uint256`을 사용하도록 한다.\n솔리디티가 메서드 식별자를 계산할 때의 과정을 위 코드의 `sam`메서드를 이용하여 예로 들어보면:\n`bytes4(sha3(\"sam(bytes, bool, uint256[])\")`\nweb3.js와 같은 고수준 라이브러리를 사용하다보면, 이런 디테일을 놓칠 수 있다. 여전히 이러한 고수준 라이브러리에서도 JSON형식의 ABI가 제공될 필요가 있다.\n> ABI는 [코어 이더리움 프로토콜](https://github.com/ethereum/yellowpaper)에 포함되지는 않는다. 누구나 자신의 컨트랙트에 대응되는 ABI를 만들어낼 수 있다. 물론 호출자는 해당 컨트랙트의 ABI를 알고 있어야 컨트랙트를 제대로 이용할 수 있다.\n\n* Answer3\n**Contract Definition**: 전형적인 고수준 코드로 정의 \n**Compiled Contract**:  이더리움 가상 머신(EVM)에서 동작하기 위해 바이트 코드로 변환된 컨트랙트. 함수의 이름과 매개변수들이 컴파일 과정에서 해시된다. 그러므로 다른 계정이 함수를 호출하기 위해서는 함수 이름과 매개변수들을 알고 있어야 한다. ABI의 등장 이유\n**Application Binary Interface**: 컨트랙트의 함수와 매개변수들을 JSON 형식으로 나타낸 리스트다. 스마트 컨트랙트의 함수를 이용하기 위해서는 ABI를 사용하여 함수의를 해시할 수 있어야 한다. 이렇게 하면 해당 함수를 호출하기 위해 필요한 EVM 바이트 코드를 생성할 수 있다. 그러고선 트랜잭션의 데이터 필드인 Td에 포함되고 EVM에 의해 해석(컨트랙트 주소에 맞춰 코드가 해석됨)된다.\n\n* Answer4\nthink of \"ABI\" as an \"API\" at a low level.\n> 따로 번역은 하지 않았지만.. 꼭 읽어보시는 걸 추천드립니다.\n\nThe API consists of a set of routines, objects, etc. that you can use in your code to access the functionality of that external component. An ABI is very similar. Think of it as the compiled version of an API (or as an API on the low level). as you know The contract are stored as bytecode in a binary form into the blockchain under a specific address. so you can accesses the binary data in the contract through the ABI which indicates to the caller the needed information (functions signatures and variables declarations) to encode a meaningful(understood by the VM) call to the bytecode(contract). The ABI defines the structures and methods that you will use to interact with binary contract (just like the API did), only on a lower level.",
      "json_metadata": "{\"tags\":[\"etheruem\",\"abi\",\"bytecode\"],\"links\":[\"https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI\",\"https://ethereum.stackexchange.com/questions/29717/is-sending-some-datas-in-the-data-field-safe\",\"https://github.com/ethereum/yellowpaper\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
    }
  ]
}
2018/07/02 19:32:42
votersteemitboard
authordlgusdn616
permlinkethereum01-02
weight100 (1.00%)
Transaction InfoBlock #23841264/Trx e6e995fb8085d057f08f69329b96cb9789a58993
View Raw JSON Data
{
  "trx_id": "e6e995fb8085d057f08f69329b96cb9789a58993",
  "block": 23841264,
  "trx_in_block": 7,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-07-02T19:32:42",
  "op": [
    "vote",
    {
      "voter": "steemitboard",
      "author": "dlgusdn616",
      "permlink": "ethereum01-02",
      "weight": 100
    }
  ]
}
2018/07/02 19:32:39
parent authordlgusdn616
parent permlinkethereum01-02
authorsteemitboard
permlinksteemitboard-notify-dlgusdn616-20180702t193238000z
title
bodyCongratulations @dlgusdn616! You have completed the following achievement on Steemit and have been rewarded with new badge(s) : [![](https://steemitimages.com/70x70/http://steemitboard.com/notifications/firstpayout.png)](http://steemitboard.com/@dlgusdn616) You got your First payout <sub>_Click on the badge to view your Board of Honor._</sub> <sub>_If you no longer want to receive notifications, reply to this comment with the word_ `STOP`</sub> To support your work, I also upvoted your post! **Do not miss the last post from @steemitboard:** [SteemitBoard World Cup Contest - Colombia vs England](https://steemit.com/steemitboard/@steemitboard/steemitboard-world-cup-contest-colombia-vs-england) --- **Participate in the [SteemitBoard World Cup Contest](https://steemit.com/steemitboard/@steemitboard/steemitboard-world-cup-contest-collect-badges-and-win-free-sbd)!** Collect World Cup badges and win free SBD Support the Gold Sponsors of the contest: [@good-karma](https://v2.steemconnect.com/sign/account-witness-vote?witness=good-karma&approve=1) and [@lukestokes](https://v2.steemconnect.com/sign/account-witness-vote?witness=lukestokes.mhth&approve=1) --- > Do you like [SteemitBoard's project](https://steemit.com/@steemitboard)? Then **[Vote for its witness](https://v2.steemconnect.com/sign/account-witness-vote?witness=steemitboard&approve=1)** and **get one more award**!
json metadata{"image":["https://steemitboard.com/img/notify.png"]}
Transaction InfoBlock #23841263/Trx a1e2cf6514fc7c346cb7ea41f4e2f7aa4fe002ba
View Raw JSON Data
{
  "trx_id": "a1e2cf6514fc7c346cb7ea41f4e2f7aa4fe002ba",
  "block": 23841263,
  "trx_in_block": 1,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-07-02T19:32:39",
  "op": [
    "comment",
    {
      "parent_author": "dlgusdn616",
      "parent_permlink": "ethereum01-02",
      "author": "steemitboard",
      "permlink": "steemitboard-notify-dlgusdn616-20180702t193238000z",
      "title": "",
      "body": "Congratulations @dlgusdn616! You have completed the following achievement on Steemit and have been rewarded with new badge(s) :\n\n[![](https://steemitimages.com/70x70/http://steemitboard.com/notifications/firstpayout.png)](http://steemitboard.com/@dlgusdn616) You got your First payout\n\n<sub>_Click on the badge to view your Board of Honor._</sub>\n<sub>_If you no longer want to receive notifications, reply to this comment with the word_ `STOP`</sub>\n\n\nTo support your work, I also upvoted your post!\n\n\n**Do not miss the last post from @steemitboard:**\n[SteemitBoard World Cup Contest - Colombia vs England](https://steemit.com/steemitboard/@steemitboard/steemitboard-world-cup-contest-colombia-vs-england)\n\n---\n**Participate in the [SteemitBoard World Cup Contest](https://steemit.com/steemitboard/@steemitboard/steemitboard-world-cup-contest-collect-badges-and-win-free-sbd)!**\nCollect World Cup badges and win free SBD\nSupport the Gold Sponsors of the contest: [@good-karma](https://v2.steemconnect.com/sign/account-witness-vote?witness=good-karma&approve=1) and [@lukestokes](https://v2.steemconnect.com/sign/account-witness-vote?witness=lukestokes.mhth&approve=1)\n\n---\n\n> Do you like [SteemitBoard's project](https://steemit.com/@steemitboard)? Then **[Vote for its witness](https://v2.steemconnect.com/sign/account-witness-vote?witness=steemitboard&approve=1)** and **get one more award**!",
      "json_metadata": "{\"image\":[\"https://steemitboard.com/img/notify.png\"]}"
    }
  ]
}
ubgupvoted (1.00%) @dlgusdn616 / ethereum01-02
2018/07/02 17:33:57
voterubg
authordlgusdn616
permlinkethereum01-02
weight100 (1.00%)
Transaction InfoBlock #23838890/Trx 07ee5459d795e2b182b2a480a70c214222707ae8
View Raw JSON Data
{
  "trx_id": "07ee5459d795e2b182b2a480a70c214222707ae8",
  "block": 23838890,
  "trx_in_block": 55,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-07-02T17:33:57",
  "op": [
    "vote",
    {
      "voter": "ubg",
      "author": "dlgusdn616",
      "permlink": "ethereum01-02",
      "weight": 100
    }
  ]
}
2018/07/02 17:02:42
voterhackerzizon
authordlgusdn616
permlinkethereum01-02
weight100 (1.00%)
Transaction InfoBlock #23838265/Trx 056b3079eeee284a175b51773ffded6dcc45984c
View Raw JSON Data
{
  "trx_id": "056b3079eeee284a175b51773ffded6dcc45984c",
  "block": 23838265,
  "trx_in_block": 5,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-07-02T17:02:42",
  "op": [
    "vote",
    {
      "voter": "hackerzizon",
      "author": "dlgusdn616",
      "permlink": "ethereum01-02",
      "weight": 100
    }
  ]
}
dlgusdn616published a new post: ethereum01-02
2018/07/02 17:01:36
parent author
parent permlinkethereum
authordlgusdn616
permlinkethereum01-02
titleEthereum01-02: 이더리움 프라이빗 블록체인 구축 (여러 노드들을 연결)
body@@ -216,10 +216,9 @@ %EB%B9%84%EB%AC%BC:%0A -1. +* %EC%9C%88%EB%8F%84%EC%9A%B0 @@ -259,15 +259,8 @@ ine%0A -2. Mist %0A%0A##
json metadata{"tags":["ethereum","private","blockchain","geth","enode"],"image":["https://cdn.steemitimages.com/DQmeXAynGoHShoWQMpMnY7X3EisibRaapP2HcfvKTrCqVne/image.png","https://cdn.steemitimages.com/DQmfFdejaQpqDobt1r9aJgmHJHt2yUwUwERYbnVy1YoK27f/image.png","https://cdn.steemitimages.com/DQmYXdBEd5zH1ztnzVeiaYYfAS54s3xquPCb6bYur1H7Znq/image.png","https://cdn.steemitimages.com/DQmZGmoCB8HW9qfjA3XwozBaEmXGzYJaBF4SZJAm9guL5Dd/image.png","https://cdn.steemitimages.com/DQmNwBCohwNs7uH9QRLAkxu8xiZtxoMDo16QXENkjnyNrFb/image.png","https://cdn.steemitimages.com/DQmf1EW4qZzFG6tgAFQFiDYwB3kHu9yfSg7YL2g67KGpeX6/image.png"],"links":["https://steemit.com/ethereum/@dlgusdn616/ethereum01-01"],"app":"steemit/0.1","format":"markdown"}
Transaction InfoBlock #23838243/Trx 0d2547e5a3050a3282f343dc28d49ece73f48750
View Raw JSON Data
{
  "trx_id": "0d2547e5a3050a3282f343dc28d49ece73f48750",
  "block": 23838243,
  "trx_in_block": 25,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-07-02T17:01:36",
  "op": [
    "comment",
    {
      "parent_author": "",
      "parent_permlink": "ethereum",
      "author": "dlgusdn616",
      "permlink": "ethereum01-02",
      "title": "Ethereum01-02: 이더리움 프라이빗 블록체인 구축 (여러 노드들을 연결)",
      "body": "@@ -216,10 +216,9 @@\n %EB%B9%84%EB%AC%BC:%0A\n-1.\n+*\n  %EC%9C%88%EB%8F%84%EC%9A%B0\n@@ -259,15 +259,8 @@\n ine%0A\n-2. Mist\n %0A%0A##\n",
      "json_metadata": "{\"tags\":[\"ethereum\",\"private\",\"blockchain\",\"geth\",\"enode\"],\"image\":[\"https://cdn.steemitimages.com/DQmeXAynGoHShoWQMpMnY7X3EisibRaapP2HcfvKTrCqVne/image.png\",\"https://cdn.steemitimages.com/DQmfFdejaQpqDobt1r9aJgmHJHt2yUwUwERYbnVy1YoK27f/image.png\",\"https://cdn.steemitimages.com/DQmYXdBEd5zH1ztnzVeiaYYfAS54s3xquPCb6bYur1H7Znq/image.png\",\"https://cdn.steemitimages.com/DQmZGmoCB8HW9qfjA3XwozBaEmXGzYJaBF4SZJAm9guL5Dd/image.png\",\"https://cdn.steemitimages.com/DQmNwBCohwNs7uH9QRLAkxu8xiZtxoMDo16QXENkjnyNrFb/image.png\",\"https://cdn.steemitimages.com/DQmf1EW4qZzFG6tgAFQFiDYwB3kHu9yfSg7YL2g67KGpeX6/image.png\"],\"links\":[\"https://steemit.com/ethereum/@dlgusdn616/ethereum01-01\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
    }
  ]
}
2018/07/02 16:58:36
parent authordlgusdn616
parent permlinkethereum01-02
authorjesusisking
permlinkre-dlgusdn616-ethereum01-02-20180702t165837005z
title
body# # upvote for me please? https://steemit.com/news/@bible.com/2sysip #
json metadata{"tags":["ethereum"],"links":["https://steemit.com/news/@bible.com/2sysip"],"app":"steemit/0.1"}
Transaction InfoBlock #23838183/Trx e29df4d06c3e38f9e08c4f2f84cfae1793e4819d
View Raw JSON Data
{
  "trx_id": "e29df4d06c3e38f9e08c4f2f84cfae1793e4819d",
  "block": 23838183,
  "trx_in_block": 1,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-07-02T16:58:36",
  "op": [
    "comment",
    {
      "parent_author": "dlgusdn616",
      "parent_permlink": "ethereum01-02",
      "author": "jesusisking",
      "permlink": "re-dlgusdn616-ethereum01-02-20180702t165837005z",
      "title": "",
      "body": "#\n# upvote for me please? https://steemit.com/news/@bible.com/2sysip\n#",
      "json_metadata": "{\"tags\":[\"ethereum\"],\"links\":[\"https://steemit.com/news/@bible.com/2sysip\"],\"app\":\"steemit/0.1\"}"
    }
  ]
}
dlgusdn616published a new post: ethereum01-02
2018/07/02 16:57:42
parent author
parent permlinkethereum
authordlgusdn616
permlinkethereum01-02
titleEthereum01-02: 이더리움 프라이빗 블록체인 구축 (여러 노드들을 연결)
body# 포스팅 주제 * 하나의 노드가 아닌 여러 개의 노드를 동작시켜 프라이빗 블록체인을 구성하는 방법을 설명한다. * 하나의 노드만으로 프라이빗 블록체인을 구성하고 싶다면 전에 있던 게시물을 참조하도록 한다. > 나만의 프라이빗 블록체인 구축하기: [Ethereum01-01](https://steemit.com/ethereum/@dlgusdn616/ethereum01-01) ## 준비물: 1. 윈도우 및 우분투가 설치되어 있는 컴퓨터 혹은 VirtualMachine 2. Mist ## 절차 설명: ### <1> 이전 게시물 [Ethereum01-01](https://steemit.com/ethereum/@dlgusdn616/ethereum01-01)을 참조하여 메인 노드역할을 하는 컴퓨터에 geth를 실행할 수 있는 환경을 조성한다. 필자의 경우 MAC 데스크톱에 실행환경을 조성했다. 단, 전 게시물을 참고할 때 댓글란을 꼭 보도록 하자. 잘못된 내용에 대해 수정한 사안이 있기 때문이다. 이때 중요한 건, **genesis.json** 파일이다. **genesis.json** 파일 안에 있는 정보 중, **"chainId": 52687550** 필드값이 가장 중요했다. **chainId** 로 분기되어 있는 이더리움의 수많은 체인 중 자신의 체인을 유일하게 식별할 수 있는 값이기 때문이다. > 만약 유일한 값을 할당하기 어렵다면, 기존에 존재하는 체인 아이디 (0, 1, 2, ...)를 할당하고 geth를 실행할 때 `--nodiscover`옵션을 주면 된다. 이 옵션을 할당하면, 기존에 존재했던 체인들과 체인 아이디가 같아도 별도의 체인으로 구축할 수 있다. 프라이빗일 경우에만 해당이 된다. 메인 노드의 geth를 실행시켰다면, console 명령으로 `admin.nodeInfo.enode` 명령어로 **enode** 값을 확인하도록 한다. > 참고로 명령어를 입력할 때, tab 기능을 활용한다면 일일이 타이핑을 하지 않아도 된다. ![](https://cdn.steemitimages.com/DQmeXAynGoHShoWQMpMnY7X3EisibRaapP2HcfvKTrCqVne/image.png) 결과로 출력되는 enode의 값을 따로 클립보드 혹은 메모장에 복사해둔 후에 다음 절차를 진행하도록 하자. ### <2> 이제는 메인 노드의 역할을 하는 컴퓨터와 동일한 환경으로 여러 대의 컴퓨터를 준비할 차례다. 본 포스팅에서는 편의상 Ubuntu 16.04 LTS 운영체제를 설치한 가상머신만을 이용해서 메인 노드와 연결 해보도록 하겠다. 아래 내용은 geth를 이미 설치했다는 가정 하에 진행된다. 먼저 홈 디렉토리에 **genesis.json** 파일을 위치시켜준다. 물론, **genesis.json** 파일은 메인 노드를 초기화할 때 사용했던 파일과 정확히 일치해야 한다. 홈 디렉토리에 임의의 폴더를 생성한다. 필자의 경우 **waca-private** 라는 폴더를 생성했다. 이 디렉토리에는 앞으로 실행할 블록체인에 대한 정보들이 기록이 될 것이다. geth를 실행하기 전 환경 구축을 먼저 하는 과정이라고 생각하면 된다. ![](https://cdn.steemitimages.com/DQmfFdejaQpqDobt1r9aJgmHJHt2yUwUwERYbnVy1YoK27f/image.png) 자, 이제 명령어를 입력하도록 하자. `geth --datadir waca-private init genesis.json` 명령으로 해당 디렉토리를 초기화 시켜준다. ![](https://cdn.steemitimages.com/DQmYXdBEd5zH1ztnzVeiaYYfAS54s3xquPCb6bYur1H7Znq/image.png) 이렇게 해당 디렉토리를 초기화 해준 후에, `geth --datadir waca-private --networkid 52687550 console` 명령어로 geth를 실행시켜 준다. **--networkid 52687550** 파트는 정확하게 **genesis.json** 파일 안의 **chainId: 52687550** 필드 값과 일치해야 한다. ![](https://cdn.steemitimages.com/DQmZGmoCB8HW9qfjA3XwozBaEmXGzYJaBF4SZJAm9guL5Dd/image.png) <1>번 과정에서 메인 노드의 geth console에서 우리는 메인 노드의 **enode** 값을 따로 저장해뒀다. 지금부터, 메인 노드와 연결을 시도해보도록 하자. `admin.addPeer("enode://d5d94092e79de457b540fcfd5f309ed877cdc6b9ee1e51c2ca32d0de684ecc29a35cc250a3be6db7e94bf238c9a35563013126db70b7a34494645e0ecbc97823@182.172.130.70:30303"` 과 같이 명령어를 입력하도록 하자. 여기서의 enode 값은 실습할 때마다 바뀔 것이다. 이렇게 연결을 시도하면, 두 대의 서로다른 머신이 동기화를 시도할 것이다. ![](https://cdn.steemitimages.com/DQmNwBCohwNs7uH9QRLAkxu8xiZtxoMDo16QXENkjnyNrFb/image.png) 만약 제대로 동기화가 이루어지지 않거나 아무 로그도 출력되지 않는다면 반대로 연결을 시도해본다. 즉, 메인 노드에서 다른 노드의 enode 정보를 알아낸 후 추가하는 방법을 사용하도록 해보자. 아래의 사진은, MAC에서 우분투 머신에서 동작 중인 enode 정보를 알아낸 후에 연결을 시도한 화면이다. ![](https://cdn.steemitimages.com/DQmf1EW4qZzFG6tgAFQFiDYwB3kHu9yfSg7YL2g67KGpeX6/image.png) 위와 같이 연결을 시도한 후에, `admin.peers` 명령어를 실행하면 위의 사진의 출력과 같이 연결된 머신에 대한 정보를 출력해줄 것이다. 성공적으로 연결이 된 것이다. 곧 있으면 체인 싱크가 일어날 것이다. ChainId가 겹치지 않는다면 싱크가 성공적으로 될 것이다. 만약 제대로 되지 않는다면, `--nodiscover` 옵션을 추가하여 geth를 실행하거나 더 유니크한 체인 아이디를 할당해준 후에 다시 실습해보도록 하자.
json metadata{"tags":["ethereum","private","blockchain","geth","enode"],"image":["https://cdn.steemitimages.com/DQmeXAynGoHShoWQMpMnY7X3EisibRaapP2HcfvKTrCqVne/image.png","https://cdn.steemitimages.com/DQmfFdejaQpqDobt1r9aJgmHJHt2yUwUwERYbnVy1YoK27f/image.png","https://cdn.steemitimages.com/DQmYXdBEd5zH1ztnzVeiaYYfAS54s3xquPCb6bYur1H7Znq/image.png","https://cdn.steemitimages.com/DQmZGmoCB8HW9qfjA3XwozBaEmXGzYJaBF4SZJAm9guL5Dd/image.png","https://cdn.steemitimages.com/DQmNwBCohwNs7uH9QRLAkxu8xiZtxoMDo16QXENkjnyNrFb/image.png","https://cdn.steemitimages.com/DQmf1EW4qZzFG6tgAFQFiDYwB3kHu9yfSg7YL2g67KGpeX6/image.png"],"links":["https://steemit.com/ethereum/@dlgusdn616/ethereum01-01"],"app":"steemit/0.1","format":"markdown"}
Transaction InfoBlock #23838165/Trx b4da319488aaec240748be80fc2494b5a7dfb6f4
View Raw JSON Data
{
  "trx_id": "b4da319488aaec240748be80fc2494b5a7dfb6f4",
  "block": 23838165,
  "trx_in_block": 8,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-07-02T16:57:42",
  "op": [
    "comment",
    {
      "parent_author": "",
      "parent_permlink": "ethereum",
      "author": "dlgusdn616",
      "permlink": "ethereum01-02",
      "title": "Ethereum01-02: 이더리움 프라이빗 블록체인 구축 (여러 노드들을 연결)",
      "body": "# 포스팅 주제\n* 하나의 노드가 아닌 여러 개의 노드를 동작시켜 프라이빗 블록체인을 구성하는 방법을 설명한다.\n* 하나의 노드만으로 프라이빗 블록체인을 구성하고 싶다면 전에 있던 게시물을 참조하도록 한다.\n> 나만의 프라이빗 블록체인 구축하기: [Ethereum01-01](https://steemit.com/ethereum/@dlgusdn616/ethereum01-01)\n\n## 준비물:\n1. 윈도우 및 우분투가 설치되어 있는 컴퓨터 혹은 VirtualMachine\n2. Mist\n\n## 절차 설명:\n### <1>\n이전 게시물 [Ethereum01-01](https://steemit.com/ethereum/@dlgusdn616/ethereum01-01)을 참조하여 메인 노드역할을 하는 컴퓨터에 geth를 실행할 수 있는 환경을 조성한다. 필자의 경우 MAC 데스크톱에 실행환경을 조성했다. 단, 전 게시물을 참고할 때 댓글란을 꼭 보도록 하자. 잘못된 내용에 대해 수정한 사안이 있기 때문이다.\n\n이때 중요한 건, **genesis.json** 파일이다. **genesis.json** 파일 안에 있는 정보 중, **\"chainId\": 52687550** 필드값이 가장 중요했다. **chainId** 로 분기되어 있는 이더리움의 수많은 체인 중 자신의 체인을 유일하게 식별할 수 있는 값이기 때문이다.\n> 만약 유일한 값을 할당하기 어렵다면, 기존에 존재하는 체인 아이디 (0, 1, 2, ...)를 할당하고 geth를 실행할 때 `--nodiscover`옵션을 주면 된다. 이 옵션을 할당하면, 기존에 존재했던 체인들과 체인 아이디가 같아도 별도의 체인으로 구축할 수 있다. 프라이빗일 경우에만 해당이 된다.\n\n메인 노드의 geth를 실행시켰다면, console 명령으로 `admin.nodeInfo.enode` 명령어로 **enode** 값을 확인하도록 한다.\n> 참고로 명령어를 입력할 때, tab 기능을 활용한다면 일일이 타이핑을 하지 않아도 된다.\n\n![](https://cdn.steemitimages.com/DQmeXAynGoHShoWQMpMnY7X3EisibRaapP2HcfvKTrCqVne/image.png)\n\n결과로 출력되는 enode의 값을 따로 클립보드 혹은 메모장에 복사해둔 후에 다음 절차를 진행하도록 하자.\n\n### <2> \n이제는 메인 노드의 역할을 하는 컴퓨터와 동일한 환경으로 여러 대의 컴퓨터를 준비할 차례다. 본 포스팅에서는 편의상 Ubuntu 16.04 LTS 운영체제를 설치한 가상머신만을 이용해서 메인 노드와 연결 해보도록 하겠다. 아래 내용은 geth를 이미 설치했다는 가정 하에 진행된다.\n\n먼저 홈 디렉토리에 **genesis.json** 파일을 위치시켜준다. 물론, **genesis.json** 파일은 메인 노드를 초기화할 때 사용했던 파일과 정확히 일치해야 한다. \n\n홈 디렉토리에 임의의 폴더를 생성한다. 필자의 경우 **waca-private** 라는 폴더를 생성했다. 이 디렉토리에는 앞으로 실행할 블록체인에 대한 정보들이 기록이 될 것이다. geth를 실행하기 전 환경 구축을 먼저 하는 과정이라고 생각하면 된다.\n\n![](https://cdn.steemitimages.com/DQmfFdejaQpqDobt1r9aJgmHJHt2yUwUwERYbnVy1YoK27f/image.png)\n\n자, 이제 명령어를 입력하도록 하자.\n`geth --datadir waca-private init genesis.json` 명령으로 해당 디렉토리를 초기화 시켜준다.\n\n![](https://cdn.steemitimages.com/DQmYXdBEd5zH1ztnzVeiaYYfAS54s3xquPCb6bYur1H7Znq/image.png)\n\n이렇게 해당 디렉토리를 초기화 해준 후에, `geth --datadir waca-private --networkid 52687550 console` 명령어로 geth를 실행시켜 준다. **--networkid 52687550** 파트는 정확하게 **genesis.json** 파일 안의 **chainId: 52687550** 필드 값과 일치해야 한다.\n\n![](https://cdn.steemitimages.com/DQmZGmoCB8HW9qfjA3XwozBaEmXGzYJaBF4SZJAm9guL5Dd/image.png)\n\n<1>번 과정에서 메인 노드의 geth console에서 우리는 메인 노드의 **enode** 값을 따로 저장해뒀다. 지금부터, 메인 노드와 연결을 시도해보도록 하자. \n\n`admin.addPeer(\"enode://d5d94092e79de457b540fcfd5f309ed877cdc6b9ee1e51c2ca32d0de684ecc29a35cc250a3be6db7e94bf238c9a35563013126db70b7a34494645e0ecbc97823@182.172.130.70:30303\"` 과 같이 명령어를 입력하도록 하자. 여기서의 enode 값은 실습할 때마다 바뀔 것이다. \n\n이렇게 연결을 시도하면, 두 대의 서로다른 머신이 동기화를 시도할 것이다. \n\n![](https://cdn.steemitimages.com/DQmNwBCohwNs7uH9QRLAkxu8xiZtxoMDo16QXENkjnyNrFb/image.png)\n\n만약 제대로 동기화가 이루어지지 않거나 아무 로그도 출력되지 않는다면 반대로 연결을 시도해본다. 즉, 메인 노드에서 다른 노드의 enode 정보를 알아낸 후 추가하는 방법을 사용하도록 해보자. 아래의 사진은, MAC에서 우분투 머신에서 동작 중인 enode 정보를 알아낸 후에 연결을 시도한 화면이다.\n\n![](https://cdn.steemitimages.com/DQmf1EW4qZzFG6tgAFQFiDYwB3kHu9yfSg7YL2g67KGpeX6/image.png)\n\n위와 같이 연결을 시도한 후에, `admin.peers` 명령어를 실행하면 위의 사진의 출력과 같이 연결된 머신에 대한 정보를 출력해줄 것이다. 성공적으로 연결이 된 것이다.\n\n곧 있으면 체인 싱크가 일어날 것이다. ChainId가 겹치지 않는다면 싱크가 성공적으로 될 것이다. 만약 제대로 되지 않는다면, `--nodiscover` 옵션을 추가하여 geth를 실행하거나 더 유니크한 체인 아이디를 할당해준 후에 다시 실습해보도록 하자.",
      "json_metadata": "{\"tags\":[\"ethereum\",\"private\",\"blockchain\",\"geth\",\"enode\"],\"image\":[\"https://cdn.steemitimages.com/DQmeXAynGoHShoWQMpMnY7X3EisibRaapP2HcfvKTrCqVne/image.png\",\"https://cdn.steemitimages.com/DQmfFdejaQpqDobt1r9aJgmHJHt2yUwUwERYbnVy1YoK27f/image.png\",\"https://cdn.steemitimages.com/DQmYXdBEd5zH1ztnzVeiaYYfAS54s3xquPCb6bYur1H7Znq/image.png\",\"https://cdn.steemitimages.com/DQmZGmoCB8HW9qfjA3XwozBaEmXGzYJaBF4SZJAm9guL5Dd/image.png\",\"https://cdn.steemitimages.com/DQmNwBCohwNs7uH9QRLAkxu8xiZtxoMDo16QXENkjnyNrFb/image.png\",\"https://cdn.steemitimages.com/DQmf1EW4qZzFG6tgAFQFiDYwB3kHu9yfSg7YL2g67KGpeX6/image.png\"],\"links\":[\"https://steemit.com/ethereum/@dlgusdn616/ethereum01-01\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
    }
  ]
}
2018/07/02 16:10:21
parent authordlgusdn616
parent permlinkethereum01-01
authordlgusdn616
permlinkre-dlgusdn616-ethereum01-01-20180702t161019330z
title
body<2>번 절차와 <3>번 절차 사이에 명령어 하나가 빠졌습니다. `geth --datadir waca-private init genesis.json` 명령어를 실행해야, 해당 디렉토리가 geth를 실행할 준비를 마칩니다. 중요한 내용을 빠뜨렸네요.
json metadata{"tags":["ethereum"],"app":"steemit/0.1"}
Transaction InfoBlock #23837219/Trx 029090da5c21e56380af1f8aa50b142815a09a00
View Raw JSON Data
{
  "trx_id": "029090da5c21e56380af1f8aa50b142815a09a00",
  "block": 23837219,
  "trx_in_block": 17,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-07-02T16:10:21",
  "op": [
    "comment",
    {
      "parent_author": "dlgusdn616",
      "parent_permlink": "ethereum01-01",
      "author": "dlgusdn616",
      "permlink": "re-dlgusdn616-ethereum01-01-20180702t161019330z",
      "title": "",
      "body": "<2>번 절차와 <3>번 절차 사이에 명령어 하나가 빠졌습니다.\n`geth --datadir waca-private init genesis.json` 명령어를 실행해야, 해당 디렉토리가 geth를 실행할 준비를 마칩니다. 중요한 내용을 빠뜨렸네요.",
      "json_metadata": "{\"tags\":[\"ethereum\"],\"app\":\"steemit/0.1\"}"
    }
  ]
}
dlgusdn616received 0.186 STEEM, 0.668 SBD, 0.697 SP author reward for @dlgusdn616 / bitcoin01-01
2018/06/14 03:45:27
authordlgusdn616
permlinkbitcoin01-01
sbd payout0.668 SBD
steem payout0.186 STEEM
vesting payout1133.773748 VESTS
Transaction InfoBlock #23304078/Virtual Operation #5
View Raw JSON Data
{
  "trx_id": "0000000000000000000000000000000000000000",
  "block": 23304078,
  "trx_in_block": 4294967295,
  "op_in_trx": 0,
  "virtual_op": 5,
  "timestamp": "2018-06-14T03:45:27",
  "op": [
    "author_reward",
    {
      "author": "dlgusdn616",
      "permlink": "bitcoin01-01",
      "sbd_payout": "0.668 SBD",
      "steem_payout": "0.186 STEEM",
      "vesting_payout": "1133.773748 VESTS"
    }
  ]
}
dlgusdn616published a new post: r-and-d-cheat-sheet
2018/06/12 09:24:30
parent author
parent permlinkonther
authordlgusdn616
permlinkr-and-d-cheat-sheet
title이더리움 블록체인 R&D스타트업 온더 채용 Cheat Sheet
body@@ -577,16 +577,17 @@ nswer:%0A%0A +%0A * 0x60 %EC%98%B5 @@ -864,16 +864,27 @@ %ED%95%B4%EC%84%9C %EA%B8%B0%EC%88%A0%ED%95%98%EB%9D%BC%0A +%3E Answer:%0A%0A %0A* %EB%AA%A8%EB%93%A0 %EA%B1%B0%EB%9E%98 @@ -1188,16 +1188,17 @@ %EB%B6%88%EA%B0%80%EB%8A%A5%ED%95%98%EB%8B%A4.%0A +%0A * %EB%A7%88%EC%9D%B4%EB%8B%9D %EB%85%B8 @@ -1276,16 +1276,27 @@ %EA%B7%B8 %EC%9D%B4%EC%9C%A0%EB%8A%94?%0A +%3E Answer:%0A%0A * payabl @@ -1372,16 +1372,27 @@ %EB%8A%94 %EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80?%0A +%3E Answer:%0A%0A * %EC%A0%84%EC%B2%B4 %ED%86%A0%ED%81%B0%EC%9D%98 @@ -1471,16 +1471,121 @@ %EA%B7%B8 %EC%9D%B4%EC%9C%A0%EB%8A%94?%0A +%3E Answer: %0A%ED%86%A0%ED%81%B0%EC%9D%98 %EC%A0%84%EC%86%A1%EC%9D%84 %EB%A9%88%EC%B6%98%EB%8B%A4%EA%B3%A0 %ED%95%B4%EC%84%9C %EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8%EC%97%90 %EC%A0%80%EC%9E%A5%EB%90%98%EC%96%B4 %EC%9E%88%EB%8A%94 %EA%B1%B0%EB%9E%98 %EB%82%B4%EC%97%AD%EC%9D%B4 %EC%9C%84%EB%B3%80%EC%A1%B0%EB%90%98%EB%8A%94 %EA%B1%B4 %EC%95%84%EB%8B%88%EB%8B%A4. %EB%A9%88%EC%B6%94%EA%B8%B0 %EC%9D%B4%EC%A0%84%EA%B9%8C%EC%A7%80%EC%9D%98 %EC%A0%95%EB%B3%B4%EB%8A%94 %EC%9D%B4%EB%AF%B8 %EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8%EC%83%81%EC%97%90 %EA%B8%B0%EB%A1%9D%EB%90%98%EC%96%B4 %EC%9E%88%EC%9D%84 %EA%B2%83%EC%9D%B4%EA%B8%B0 %EB%95%8C%EB%AC%B8%EC%9D%B4%EB%8B%A4. %0A%0A * %ED%94%8C%EB%9D%BC%EC%A6%88%EB%A7%88 %EC%B2%B4 @@ -1609,16 +1609,27 @@ %ED%95%B4%EC%84%9C %EC%84%9C%EC%88%A0%ED%95%98%EB%9D%BC%0A +%3E Answer:%0A%0A * %ED%94%8C%EB%9D%BC%EC%A6%88%EB%A7%88 %EC%B2%B4 @@ -1664,16 +1664,27 @@ %ED%95%B4%EC%84%9C %EC%84%9C%EC%88%A0%ED%95%98%EB%9D%BC%0A +%3E Answer:%0A%0A * truffl @@ -2091,16 +2091,17 @@ ry.com)%0A +%0A * github @@ -2157,24 +2157,25 @@ ?%0A%3E Answer:%0A +%0A * %EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80 %EA%B3%84%EC%A0%95 %EC%83%9D%EC%84%B1 @@ -2256,16 +2256,18 @@ Answer:%0A +%0A%0A * %ED%8C%A8%EB%9F%AC%ED%8B%B0 %EB%A9%80%ED%8B%B0 @@ -2342,16 +2342,17 @@ nswer: %0A +%0A * %EC%86%94%EB%A6%AC%EB%94%94%ED%8B%B0 P @@ -2385,16 +2385,17 @@ nswer: %0A +%0A * call, @@ -2446,16 +2446,17 @@ nswer: %0A +%0A * solidi @@ -2495,16 +2495,17 @@ Answer:%0A +%0A * O(n)%EC%9D%98 @@ -2924,16 +2924,135 @@ Answer:%0A +ICO%EB%A5%BC %EC%A7%84%ED%96%89%ED%95%A8%EC%97%90 %EC%9E%88%EC%96%B4 %ED%86%A0%ED%81%B0%EC%9D%98 %EC%B4%9D %EB%B0%9C%ED%96%89%EB%9F%89 %7C %ED%86%A0%ED%81%B0%EC%9D%98 %EA%B0%80%EA%B2%A9 %7C %ED%86%A0%ED%81%B0%EC%9D%98 %EC%82%AC%ED%9B%84%EC%A0%81 %EB%B6%84%EB%B0%B0%EC%9C%A8, %EC%9D%B4 3%EA%B0%80%EC%A7%80 %ED%95%AD%EB%AA%A9%EC%9D%B4 %EB%8F%99%EC%8B%9C%EC%97%90 %EA%B3%A0%EC%A0%95%EB%90%A0 %EC%88%98 %EC%97%86%EB%8A%94 %EA%B2%83%EC%9D%84 %EC%9D%98%EB%AF%B8%ED%95%9C%EB%8B%A4.%0AReference: https://medium.com/@kevin.j%0A%0A * PoA %ED%95%A9%EC%9D%98 @@ -3101,16 +3101,17 @@ Answer:%0A +%0A * %ED%86%A0%ED%81%B0%EC%9D%98 %EB%B6%84%EB%A5%98 @@ -3200,16 +3200,17 @@ Answer:%0A +%0A * puppet @@ -4680,16 +4680,17 @@ in01-01%0A +%0A * 2%EC%84%B8%EB%8C%80 %EB%B8%94%EB%A1%9D @@ -4968,16 +4968,27 @@ %EC%A7%80 %EC%84%A4%EB%AA%85%ED%95%98%EB%9D%BC.%0A +%3E Answer:%0A%0A * PoW %EC%97%90%EC%84%9C @@ -5426,24 +5426,26 @@ %EC%9D%84 %EC%84%A4%EB%AA%85%ED%95%98%EB%9D%BC.%0A +%3E Answer:%0A - %0A* Whisp @@ -5537,24 +5537,26 @@ %EB%A5%BC %EC%84%A4%EB%AA%85%ED%95%98%EB%9D%BC.%0A +%3E Answer:%0A - %0A* EA a @@ -5664,24 +5664,26 @@ %EB%95%8C %CE%B1 %EB%8A%94? %0A +%3E Answer:%0A - n_a - g_ @@ -5805,16 +5805,17 @@ %EC%86%A1%ED%95%98%EA%B2%8C %EB%90%9C%EB%8B%A4.%0A +%0A * swarm @@ -5852,16 +5852,27 @@ %EC%A7%80 %EC%84%A4%EB%AA%85%ED%95%98%EC%8B%9C%EC%98%A4%0A +%3E Answer:%0A%0A * %EC%83%81%ED%98%B8 %EB%8F%85%EB%A6%BD%EC%A0%81 @@ -5956,24 +5956,35 @@ p %EB%B0%A9%EC%8B%9D%EC%9D%84 %EC%84%A4%EB%AA%85%ED%95%98%EB%9D%BC.%0A +%3E Answer:%0A%0A * Casper FFG @@ -6036,16 +6036,17 @@ Answer:%0A +%0A * %EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80 %EB%B8%94 @@ -6099,16 +6099,27 @@ %ED%95%B4 %EC%84%A4%EB%AA%85%ED%95%98%EB%9D%BC.%0A +%3E Answer:%0A%0A * Ethash @@ -7262,16 +7262,27 @@ %EC%97%AC %EC%84%A4%EB%AA%85%ED%95%98%EB%9D%BC.%0A +%3E Answer:%0A%0A * Casper @@ -8281,16 +8281,17 @@ %EA%B0%84%EC%9D%B4 %EC%95%84%EB%8B%88%EB%8B%A4.%0A +%0A * Token @@ -8345,16 +8345,28 @@ %EC%84%9C%EC%88%A0%ED%95%98%EC%84%B8%EC%9A%94.%0A +%3E Answer: %0A%0A * PoW%EC%97%90%EC%84%9C @@ -8427,12 +8427,22 @@ %EA%B3%A0 %ED%95%98%EB%8A%94%EC%A7%80 %EC%84%9C%EC%88%A0%ED%95%98%EC%84%B8%EC%9A%94. +%0A%3E Answer:
json metadata{"tags":["onther","ethereum","blockchain"],"links":["https://medium.com/@kevin.j","http://javaexpert.tistory.com","https://paritytech.io/security-alert-2/","https://steemit.com/bitcoin/@dlgusdn616/bitcoin01-01"],"app":"steemit/0.1","format":"markdown"}
Transaction InfoBlock #23253269/Trx c41edef5df3d01490e506b2017c21064afe2a305
View Raw JSON Data
{
  "trx_id": "c41edef5df3d01490e506b2017c21064afe2a305",
  "block": 23253269,
  "trx_in_block": 7,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-12T09:24:30",
  "op": [
    "comment",
    {
      "parent_author": "",
      "parent_permlink": "onther",
      "author": "dlgusdn616",
      "permlink": "r-and-d-cheat-sheet",
      "title": "이더리움 블록체인 R&D스타트업 온더 채용 Cheat Sheet",
      "body": "@@ -577,16 +577,17 @@\n nswer:%0A%0A\n+%0A\n * 0x60 %EC%98%B5\n@@ -864,16 +864,27 @@\n %ED%95%B4%EC%84%9C %EA%B8%B0%EC%88%A0%ED%95%98%EB%9D%BC%0A\n+%3E Answer:%0A%0A\n %0A* %EB%AA%A8%EB%93%A0 %EA%B1%B0%EB%9E%98\n@@ -1188,16 +1188,17 @@\n  %EB%B6%88%EA%B0%80%EB%8A%A5%ED%95%98%EB%8B%A4.%0A\n+%0A\n *  %EB%A7%88%EC%9D%B4%EB%8B%9D %EB%85%B8\n@@ -1276,16 +1276,27 @@\n  %EA%B7%B8 %EC%9D%B4%EC%9C%A0%EB%8A%94?%0A\n+%3E Answer:%0A%0A\n * payabl\n@@ -1372,16 +1372,27 @@\n %EB%8A%94 %EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80?%0A\n+%3E Answer:%0A%0A\n * %EC%A0%84%EC%B2%B4 %ED%86%A0%ED%81%B0%EC%9D%98\n@@ -1471,16 +1471,121 @@\n  %EA%B7%B8 %EC%9D%B4%EC%9C%A0%EB%8A%94?%0A\n+%3E Answer: %0A%ED%86%A0%ED%81%B0%EC%9D%98 %EC%A0%84%EC%86%A1%EC%9D%84 %EB%A9%88%EC%B6%98%EB%8B%A4%EA%B3%A0 %ED%95%B4%EC%84%9C %EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8%EC%97%90 %EC%A0%80%EC%9E%A5%EB%90%98%EC%96%B4 %EC%9E%88%EB%8A%94 %EA%B1%B0%EB%9E%98 %EB%82%B4%EC%97%AD%EC%9D%B4 %EC%9C%84%EB%B3%80%EC%A1%B0%EB%90%98%EB%8A%94 %EA%B1%B4 %EC%95%84%EB%8B%88%EB%8B%A4. %EB%A9%88%EC%B6%94%EA%B8%B0 %EC%9D%B4%EC%A0%84%EA%B9%8C%EC%A7%80%EC%9D%98 %EC%A0%95%EB%B3%B4%EB%8A%94 %EC%9D%B4%EB%AF%B8 %EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8%EC%83%81%EC%97%90 %EA%B8%B0%EB%A1%9D%EB%90%98%EC%96%B4 %EC%9E%88%EC%9D%84 %EA%B2%83%EC%9D%B4%EA%B8%B0 %EB%95%8C%EB%AC%B8%EC%9D%B4%EB%8B%A4. %0A%0A\n * %ED%94%8C%EB%9D%BC%EC%A6%88%EB%A7%88 %EC%B2%B4\n@@ -1609,16 +1609,27 @@\n %ED%95%B4%EC%84%9C %EC%84%9C%EC%88%A0%ED%95%98%EB%9D%BC%0A\n+%3E Answer:%0A%0A\n * %ED%94%8C%EB%9D%BC%EC%A6%88%EB%A7%88 %EC%B2%B4\n@@ -1664,16 +1664,27 @@\n %ED%95%B4%EC%84%9C %EC%84%9C%EC%88%A0%ED%95%98%EB%9D%BC%0A\n+%3E Answer:%0A%0A\n * truffl\n@@ -2091,16 +2091,17 @@\n ry.com)%0A\n+%0A\n * github\n@@ -2157,24 +2157,25 @@\n ?%0A%3E Answer:%0A\n+%0A\n * %EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80 %EA%B3%84%EC%A0%95 %EC%83%9D%EC%84%B1\n@@ -2256,16 +2256,18 @@\n Answer:%0A\n+%0A%0A\n * %ED%8C%A8%EB%9F%AC%ED%8B%B0 %EB%A9%80%ED%8B%B0\n@@ -2342,16 +2342,17 @@\n nswer: %0A\n+%0A\n * %EC%86%94%EB%A6%AC%EB%94%94%ED%8B%B0 P\n@@ -2385,16 +2385,17 @@\n nswer: %0A\n+%0A\n * call, \n@@ -2446,16 +2446,17 @@\n nswer: %0A\n+%0A\n * solidi\n@@ -2495,16 +2495,17 @@\n Answer:%0A\n+%0A\n * O(n)%EC%9D%98 \n@@ -2924,16 +2924,135 @@\n Answer:%0A\n+ICO%EB%A5%BC %EC%A7%84%ED%96%89%ED%95%A8%EC%97%90 %EC%9E%88%EC%96%B4 %ED%86%A0%ED%81%B0%EC%9D%98 %EC%B4%9D %EB%B0%9C%ED%96%89%EB%9F%89 %7C %ED%86%A0%ED%81%B0%EC%9D%98 %EA%B0%80%EA%B2%A9 %7C %ED%86%A0%ED%81%B0%EC%9D%98 %EC%82%AC%ED%9B%84%EC%A0%81 %EB%B6%84%EB%B0%B0%EC%9C%A8, %EC%9D%B4 3%EA%B0%80%EC%A7%80 %ED%95%AD%EB%AA%A9%EC%9D%B4 %EB%8F%99%EC%8B%9C%EC%97%90 %EA%B3%A0%EC%A0%95%EB%90%A0 %EC%88%98 %EC%97%86%EB%8A%94 %EA%B2%83%EC%9D%84 %EC%9D%98%EB%AF%B8%ED%95%9C%EB%8B%A4.%0AReference: https://medium.com/@kevin.j%0A%0A\n * PoA %ED%95%A9%EC%9D%98\n@@ -3101,16 +3101,17 @@\n Answer:%0A\n+%0A\n * %ED%86%A0%ED%81%B0%EC%9D%98 %EB%B6%84%EB%A5%98\n@@ -3200,16 +3200,17 @@\n Answer:%0A\n+%0A\n * puppet\n@@ -4680,16 +4680,17 @@\n in01-01%0A\n+%0A\n * 2%EC%84%B8%EB%8C%80 %EB%B8%94%EB%A1%9D\n@@ -4968,16 +4968,27 @@\n %EC%A7%80 %EC%84%A4%EB%AA%85%ED%95%98%EB%9D%BC.%0A\n+%3E Answer:%0A%0A\n * PoW %EC%97%90%EC%84%9C\n@@ -5426,24 +5426,26 @@\n %EC%9D%84 %EC%84%A4%EB%AA%85%ED%95%98%EB%9D%BC.%0A\n+%3E \n Answer:%0A\n-\n %0A* Whisp\n@@ -5537,24 +5537,26 @@\n %EB%A5%BC %EC%84%A4%EB%AA%85%ED%95%98%EB%9D%BC.%0A\n+%3E \n Answer:%0A\n-\n %0A* EA a \n@@ -5664,24 +5664,26 @@\n %EB%95%8C %CE%B1 %EB%8A%94? %0A\n+%3E \n Answer:%0A\n-\n n_a - g_\n@@ -5805,16 +5805,17 @@\n %EC%86%A1%ED%95%98%EA%B2%8C %EB%90%9C%EB%8B%A4.%0A\n+%0A\n * swarm \n@@ -5852,16 +5852,27 @@\n %EC%A7%80 %EC%84%A4%EB%AA%85%ED%95%98%EC%8B%9C%EC%98%A4%0A\n+%3E Answer:%0A%0A\n * %EC%83%81%ED%98%B8 %EB%8F%85%EB%A6%BD%EC%A0%81\n@@ -5956,24 +5956,35 @@\n p %EB%B0%A9%EC%8B%9D%EC%9D%84 %EC%84%A4%EB%AA%85%ED%95%98%EB%9D%BC.%0A\n+%3E Answer:%0A%0A\n * Casper FFG\n@@ -6036,16 +6036,17 @@\n Answer:%0A\n+%0A\n * %EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80 %EB%B8%94\n@@ -6099,16 +6099,27 @@\n %ED%95%B4 %EC%84%A4%EB%AA%85%ED%95%98%EB%9D%BC.%0A\n+%3E Answer:%0A%0A\n * Ethash\n@@ -7262,16 +7262,27 @@\n %EC%97%AC %EC%84%A4%EB%AA%85%ED%95%98%EB%9D%BC.%0A\n+%3E Answer:%0A%0A\n * Casper\n@@ -8281,16 +8281,17 @@\n %EA%B0%84%EC%9D%B4 %EC%95%84%EB%8B%88%EB%8B%A4.%0A\n+%0A\n * Token \n@@ -8345,16 +8345,28 @@\n  %EC%84%9C%EC%88%A0%ED%95%98%EC%84%B8%EC%9A%94.%0A\n+%3E Answer: %0A%0A\n * PoW%EC%97%90%EC%84%9C \n@@ -8427,12 +8427,22 @@\n %EA%B3%A0 %ED%95%98%EB%8A%94%EC%A7%80 %EC%84%9C%EC%88%A0%ED%95%98%EC%84%B8%EC%9A%94.\n+%0A%3E Answer:\n",
      "json_metadata": "{\"tags\":[\"onther\",\"ethereum\",\"blockchain\"],\"links\":[\"https://medium.com/@kevin.j\",\"http://javaexpert.tistory.com\",\"https://paritytech.io/security-alert-2/\",\"https://steemit.com/bitcoin/@dlgusdn616/bitcoin01-01\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
    }
  ]
}
dlgusdn616published a new post: r-and-d-cheat-sheet
2018/06/12 07:17:21
parent author
parent permlinkonther
authordlgusdn616
permlinkr-and-d-cheat-sheet
title이더리움 블록체인 R&D스타트업 온더 채용 Cheat Sheet
body@@ -1042,16 +1042,19 @@ %EC%A0%95%EB%B3%B4%EB%8F%84 %EC%97%86%EB%8B%A4.%0A - +%0A%3E %ED%95%B4%EC%BB%A4%EA%B0%80 %ED%8A%B9%EC%A0%95 %ED%92%80 @@ -1718,16 +1718,18 @@ %EC%8B%9C%EC%9E%91%ED%95%9C%EB%8B%A4. %0A%0A +%3E compile: @@ -1828,16 +1828,18 @@ %EC%A7%84%ED%96%89%EB%90%9C%EB%8B%A4.%0A%0A +%3E test: te @@ -2497,16 +2497,19 @@ %EC%86%8C%EB%AA%A8%ED%95%9C%EB%8B%A4. %0A - +%0A%3E gaslimit @@ -3288,16 +3288,19 @@ %EA%B8%B0 %EC%9C%84%ED%95%B4%EC%84%9C%EB%8A%94 %0A +%0A%3E %EC%B2%AB%EC%A7%B8: %ED%95%B4%EB%8B%B9 U @@ -3415,16 +3415,19 @@ %EC%9E%88%EC%96%B4%EC%95%BC %ED%95%9C%EB%8B%A4.%0A +%0A%3E %EB%91%98%EC%A7%B8: scri @@ -3573,16 +3573,18 @@ %EB%AC%BC%EB%A1%A0%EC%9D%B4%EB%8B%A4. %0A%0A +%3E %EA%B2%B0%EA%B5%AD %EC%9E%90%EC%8B%A0%EC%9D%98 %EC%A3%BC @@ -3934,16 +3934,18 @@ %EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EB%8B%A4.%0A%0A +%3E Transcat @@ -4146,16 +4146,18 @@ %EB%95%8C%EB%AC%B8%EC%9D%B4%EB%8B%A4.%0A%0A +%3E %EB%A8%B8%ED%81%B4 path%EB%8A%94 @@ -4293,16 +4293,18 @@ %EC%88%98 %EC%9E%88%EB%8B%A4.%0A%0A +%3E %EC%BD%94%EB%93%9C %EC%88%98%EC%A4%80%EC%97%90%EC%84%9C%EC%9D%98 @@ -5828,32 +5828,34 @@ %EB%AA%85%ED%95%98%EA%B3%A0 %EA%B7%B8 %ED%95%9C%EA%B3%84%EB%A5%BC %EC%A0%9C%EC%8B%9C%ED%95%98%EB%9D%BC.%0A - +%3E Answer:%0A%EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80%EC%9D%98 Po @@ -6052,16 +6052,18 @@ %EC%B6%94%EA%B0%80%ED%96%88%EB%8B%A4.%0A%0A +%3E %EB%8B%A8%EC%88%9C%ED%9E%88 SHA2 @@ -6211,16 +6211,18 @@ %EA%B3%BC%EA%B0%80 %EC%9E%88%EB%8B%A4.%0A%0A +%3E %EA%B7%B8%EB%9F%AC%EB%82%98 %EB%A7%8C%EC%95%BD %EB%A9%94 @@ -6492,16 +6492,18 @@ %EC%9D%B4%EB%9D%BC %ED%95%9C%EB%8B%A4.%0A%0A +%3E uncleBlo @@ -6697,16 +6697,18 @@ %EA%B0%9C%EB%B0%9C%ED%96%88%EB%8B%A4.%0A%0A +%3E %EB%B9%84%ED%8A%B8%EC%BD%94%EC%9D%B8%EC%9D%98 %EA%B2%BD%EC%9A%B0 @@ -7209,16 +7209,18 @@ %EA%B5%AC%EC%A1%B0%EC%98%80%EB%8B%A4.%0A%0A +%3E %EC%9D%B4%EB%9F%B0 %EB%AC%B8%EC%A0%9C%EB%A5%BC %ED%95%B4 @@ -7422,16 +7422,18 @@ %EC%88%98 %EC%9E%88%EB%8B%A4.%0A%0A +%3E %EA%B7%B8%EB%A0%87%EB%8B%A4%EB%A9%B4 %EC%97%AC%EA%B8%B0%EC%84%9C @@ -7466,16 +7466,18 @@ %EC%88%98 %EC%9E%88%EC%9D%84%EA%B9%8C.%0A%0A +%3E Capser%EB%8A%94 @@ -7728,16 +7728,18 @@ %EC%9D%B8%EC%9D%B4 %EB%90%9C%EB%8B%A4.%0A%0A +%3E %EC%A6%89, %EC%9D%B4 Fin @@ -7814,16 +7814,18 @@ %EC%88%98 %EC%9E%88%EB%8B%A4.%0A%0A +%3E %EB%A7%88%EC%A7%80%EB%A7%89%EC%9C%BC%EB%A1%9C %EC%9D%B4
json metadata{"tags":["onther","ethereum","blockchain"],"links":["https://medium.com/@kevin.j","http://javaexpert.tistory.com","https://paritytech.io/security-alert-2/","https://steemit.com/bitcoin/@dlgusdn616/bitcoin01-01"],"app":"steemit/0.1","format":"markdown"}
Transaction InfoBlock #23250726/Trx 15ce74fe6f544145636c255c16088b11b51d38ac
View Raw JSON Data
{
  "trx_id": "15ce74fe6f544145636c255c16088b11b51d38ac",
  "block": 23250726,
  "trx_in_block": 73,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-12T07:17:21",
  "op": [
    "comment",
    {
      "parent_author": "",
      "parent_permlink": "onther",
      "author": "dlgusdn616",
      "permlink": "r-and-d-cheat-sheet",
      "title": "이더리움 블록체인 R&D스타트업 온더 채용 Cheat Sheet",
      "body": "@@ -1042,16 +1042,19 @@\n %EC%A0%95%EB%B3%B4%EB%8F%84 %EC%97%86%EB%8B%A4.%0A\n-\n \n+%0A%3E \n %ED%95%B4%EC%BB%A4%EA%B0%80 %ED%8A%B9%EC%A0%95 %ED%92%80\n@@ -1718,16 +1718,18 @@\n %EC%8B%9C%EC%9E%91%ED%95%9C%EB%8B%A4. %0A%0A\n+%3E \n compile:\n@@ -1828,16 +1828,18 @@\n  %EC%A7%84%ED%96%89%EB%90%9C%EB%8B%A4.%0A%0A\n+%3E \n test: te\n@@ -2497,16 +2497,19 @@\n  %EC%86%8C%EB%AA%A8%ED%95%9C%EB%8B%A4. %0A\n-\n \n+%0A%3E \n gaslimit\n@@ -3288,16 +3288,19 @@\n %EA%B8%B0 %EC%9C%84%ED%95%B4%EC%84%9C%EB%8A%94 %0A\n+%0A%3E \n %EC%B2%AB%EC%A7%B8: %ED%95%B4%EB%8B%B9 U\n@@ -3415,16 +3415,19 @@\n %EC%9E%88%EC%96%B4%EC%95%BC %ED%95%9C%EB%8B%A4.%0A\n+%0A%3E \n %EB%91%98%EC%A7%B8: scri\n@@ -3573,16 +3573,18 @@\n %EB%AC%BC%EB%A1%A0%EC%9D%B4%EB%8B%A4. %0A%0A\n+%3E \n %EA%B2%B0%EA%B5%AD %EC%9E%90%EC%8B%A0%EC%9D%98 %EC%A3%BC\n@@ -3934,16 +3934,18 @@\n %EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EB%8B%A4.%0A%0A\n+%3E \n Transcat\n@@ -4146,16 +4146,18 @@\n  %EB%95%8C%EB%AC%B8%EC%9D%B4%EB%8B%A4.%0A%0A\n+%3E \n %EB%A8%B8%ED%81%B4 path%EB%8A%94\n@@ -4293,16 +4293,18 @@\n  %EC%88%98 %EC%9E%88%EB%8B%A4.%0A%0A\n+%3E \n %EC%BD%94%EB%93%9C %EC%88%98%EC%A4%80%EC%97%90%EC%84%9C%EC%9D%98\n@@ -5828,32 +5828,34 @@\n %EB%AA%85%ED%95%98%EA%B3%A0 %EA%B7%B8 %ED%95%9C%EA%B3%84%EB%A5%BC %EC%A0%9C%EC%8B%9C%ED%95%98%EB%9D%BC.%0A\n-\n \n+%3E \n Answer:%0A%EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80%EC%9D%98 Po\n@@ -6052,16 +6052,18 @@\n  %EC%B6%94%EA%B0%80%ED%96%88%EB%8B%A4.%0A%0A\n+%3E \n %EB%8B%A8%EC%88%9C%ED%9E%88 SHA2\n@@ -6211,16 +6211,18 @@\n %EA%B3%BC%EA%B0%80 %EC%9E%88%EB%8B%A4.%0A%0A\n+%3E \n %EA%B7%B8%EB%9F%AC%EB%82%98 %EB%A7%8C%EC%95%BD %EB%A9%94\n@@ -6492,16 +6492,18 @@\n %EC%9D%B4%EB%9D%BC %ED%95%9C%EB%8B%A4.%0A%0A\n+%3E \n uncleBlo\n@@ -6697,16 +6697,18 @@\n  %EA%B0%9C%EB%B0%9C%ED%96%88%EB%8B%A4.%0A%0A\n+%3E \n %EB%B9%84%ED%8A%B8%EC%BD%94%EC%9D%B8%EC%9D%98 %EA%B2%BD%EC%9A%B0\n@@ -7209,16 +7209,18 @@\n  %EA%B5%AC%EC%A1%B0%EC%98%80%EB%8B%A4.%0A%0A\n+%3E \n %EC%9D%B4%EB%9F%B0 %EB%AC%B8%EC%A0%9C%EB%A5%BC %ED%95%B4\n@@ -7422,16 +7422,18 @@\n  %EC%88%98 %EC%9E%88%EB%8B%A4.%0A%0A\n+%3E \n %EA%B7%B8%EB%A0%87%EB%8B%A4%EB%A9%B4 %EC%97%AC%EA%B8%B0%EC%84%9C\n@@ -7466,16 +7466,18 @@\n %EC%88%98 %EC%9E%88%EC%9D%84%EA%B9%8C.%0A%0A\n+%3E \n Capser%EB%8A%94 \n@@ -7728,16 +7728,18 @@\n %EC%9D%B8%EC%9D%B4 %EB%90%9C%EB%8B%A4.%0A%0A\n+%3E \n %EC%A6%89, %EC%9D%B4 Fin\n@@ -7814,16 +7814,18 @@\n  %EC%88%98 %EC%9E%88%EB%8B%A4.%0A%0A\n+%3E \n %EB%A7%88%EC%A7%80%EB%A7%89%EC%9C%BC%EB%A1%9C %EC%9D%B4 \n",
      "json_metadata": "{\"tags\":[\"onther\",\"ethereum\",\"blockchain\"],\"links\":[\"https://medium.com/@kevin.j\",\"http://javaexpert.tistory.com\",\"https://paritytech.io/security-alert-2/\",\"https://steemit.com/bitcoin/@dlgusdn616/bitcoin01-01\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
    }
  ]
}
2018/06/12 07:15:15
voterubg
authordlgusdn616
permlinkr-and-d-cheat-sheet
weight100 (1.00%)
Transaction InfoBlock #23250684/Trx 81642e49f597ebff5d0f0b55fd72c5ece1987913
View Raw JSON Data
{
  "trx_id": "81642e49f597ebff5d0f0b55fd72c5ece1987913",
  "block": 23250684,
  "trx_in_block": 20,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-12T07:15:15",
  "op": [
    "vote",
    {
      "voter": "ubg",
      "author": "dlgusdn616",
      "permlink": "r-and-d-cheat-sheet",
      "weight": 100
    }
  ]
}
dlgusdn616published a new post: r-and-d-cheat-sheet
2018/06/12 07:14:15
parent author
parent permlinkonther
authordlgusdn616
permlinkr-and-d-cheat-sheet
title이더리움 블록체인 R&D스타트업 온더 채용 Cheat Sheet
body@@ -134,16 +134,20 @@ %EC%9E%91%EC%84%B1%ED%95%98%EA%B2%8C %EB%90%90%EB%8B%A4. +%0A## %0A%0A* ETC%EB%A5%BC @@ -1041,24 +1041,16 @@ %EC%A0%95%EB%B3%B4%EB%8F%84 %EC%97%86%EB%8B%A4. - address %0A%ED%95%B4%EC%BB%A4%EA%B0%80 %ED%8A%B9%EC%A0%95 @@ -1177,10 +1177,10 @@ %ED%95%98%EB%8B%A4.%0A -8. +* %EB%A7%88%EC%9D%B4%EB%8B%9D @@ -1714,16 +1714,17 @@ %EC%8B%9C%EC%9E%91%ED%95%9C%EB%8B%A4. %0A +%0A compile: @@ -1822,16 +1822,17 @@ %EC%9D%B4 %EC%A7%84%ED%96%89%EB%90%9C%EB%8B%A4.%0A +%0A test: te @@ -3556,16 +3556,17 @@ %EB%AC%BC%EB%A1%A0%EC%9D%B4%EB%8B%A4. %0A +%0A %EA%B2%B0%EA%B5%AD %EC%9E%90%EC%8B%A0%EC%9D%98 %EC%A3%BC @@ -3915,16 +3915,17 @@ %EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EB%8B%A4.%0A +%0A Transcat @@ -4125,16 +4125,17 @@ %EC%9D%B4 %EB%95%8C%EB%AC%B8%EC%9D%B4%EB%8B%A4.%0A +%0A %EB%A8%B8%ED%81%B4 path%EB%8A%94 @@ -4270,18 +4270,47 @@ %ED%95%A0 %EC%88%98 %EC%9E%88%EB%8B%A4.%0A -%3E +%0A%EC%BD%94%EB%93%9C %EC%88%98%EC%A4%80%EC%97%90%EC%84%9C%EC%9D%98 %EC%9E%90%EC%84%B8%ED%95%9C %EB%82%B4%EC%9A%A9%EC%9D%80 %EC%95%84%EB%9E%98%EC%9D%98 %EB%A0%88%ED%8D%BC%EB%9F%B0%EC%8A%A4%EB%A5%BC %EC%B0%B8%EC%A1%B0%0A Referenc @@ -4871,16 +4871,17 @@ %ED%95%A0 %EC%88%98 %EC%9E%88%EB%8B%A4.%0A +%0A %EC%95%95%EB%8F%84%EC%A0%81%EC%9D%B8 %ED%95%B4%EC%8B%9C%EB%9F%89 @@ -6025,16 +6025,17 @@ %EC%9D%84 %EC%B6%94%EA%B0%80%ED%96%88%EB%8B%A4.%0A +%0A %EB%8B%A8%EC%88%9C%ED%9E%88 SHA2 @@ -6182,16 +6182,17 @@ %ED%9A%A8%EA%B3%BC%EA%B0%80 %EC%9E%88%EB%8B%A4.%0A +%0A %EA%B7%B8%EB%9F%AC%EB%82%98 %EB%A7%8C%EC%95%BD %EB%A9%94 @@ -6461,16 +6461,17 @@ k%EC%9D%B4%EB%9D%BC %ED%95%9C%EB%8B%A4.%0A +%0A uncleBlo @@ -6664,16 +6664,17 @@ %EC%9D%84 %EA%B0%9C%EB%B0%9C%ED%96%88%EB%8B%A4.%0A +%0A %EB%B9%84%ED%8A%B8%EC%BD%94%EC%9D%B8%EC%9D%98 %EA%B2%BD%EC%9A%B0 @@ -6880,24 +6880,24 @@ %EB%B9%84%EA%B5%90%ED%95%98%EC%97%AC %EC%84%A4%EB%AA%85%ED%95%98%EB%9D%BC.%0A - * Casper%EB%8A%94 %EC%A0%84%ED%86%B5 @@ -6966,16 +6966,932 @@ %EB%AA%85%EC%8B%9C%ED%95%98%EC%8B%9C%EC%98%A4)%0A +%3E Answer: (by Bookstore3)%0ANothing at stake %EB%AC%B8%EC%A0%9C%EB%9E%80 %EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80%EC%97%90%EC%84%9C %EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8%EC%9D%B4 %ED%8F%AC%ED%81%AC%EA%B0%80 %EB%90%A0 %EB%95%8C %EB%B0%9C%EC%83%9D%ED%95%98%EB%8A%94 %EB%AC%B8%EC%A0%9C%EB%8B%A4. %EA%B8%B0%EC%A1%B4 PoS %EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98 %EC%83%81%EC%97%90%EC%84%9C%EB%8A%94 %ED%8F%AC%ED%81%AC%EA%B0%80 %EB%B0%9C%EC%83%9D%ED%95%98%EC%97%AC %EB%85%B8%EB%93%9C%EA%B0%80 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%95%A0 %EB%95%8C, %EB%82%98%EB%88%A0%EC%A7%84 %EB%91%90 %EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8%EC%97%90 %EB%AA%A8%EB%91%90 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%95%B4%EB%8F%84 %EC%86%90%ED%95%B4%EB%A5%BC %EB%B3%B4%EA%B2%8C %EB%90%98%EB%8A%94 %EA%B5%AC%EC%A1%B0%EA%B0%80 %EC%95%84%EB%8B%88%EC%98%80%EB%8B%A4. %EA%B2%B0%EA%B5%AD %EB%91%98 %EB%8B%A4 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%95%B4 %EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC%EA%B0%80 %EC%B1%84%ED%83%9D%ED%95%9C %EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8%EC%97%90 %EB%8C%80%ED%95%9C %EB%B3%B4%EC%83%81%EB%A7%8C %EC%B1%99%EA%B8%B0%EB%A9%B4 %EB%90%98%EB%8A%94 %EA%B5%AC%EC%A1%B0%EC%98%80%EB%8B%A4.%0A%0A%EC%9D%B4%EB%9F%B0 %EB%AC%B8%EC%A0%9C%EB%A5%BC %ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0 %EC%9C%84%ED%95%B4 Casper%EC%97%90%EC%84%9C%EB%8A%94 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%95%98%EB%8A%94 %EB%85%B8%EB%93%9C%EB%93%A4%EC%9D%B4 %EB%B3%B8%EC%9D%B8%EC%9D%98 %EC%A7%80%EB%B6%84, %EC%A6%89 %EB%8F%88%EC%9D%84 %EA%B1%B8%EA%B3%A0 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%95%98%EA%B2%8C %EB%A7%8C%EB%93%A4%EA%B3%A0, %EB%A7%8C%EC%95%BD %EB%B3%B8%EC%9D%B8%EC%9D%B4 %EC%95%85%EC%9D%98%EC%A0%81%EC%9C%BC%EB%A1%9C %ED%88%AC%ED%91%9C%EB%A5%BC %EB%91%90 %EC%B2%B4%EC%9D%B8%EC%97%90 %EB%AA%A8%EB%91%90 %ED%95%98%EA%B2%8C %EB%90%98%EB%A9%B4 %EB%8F%88%EC%9D%84 %EC%9E%83%EA%B2%8C %EB%90%98%EB%8A%94 %EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EC%9D%84 %EC%82%AC%EC%9A%A9%ED%95%9C%EB%8B%A4. %EC%A6%89, %ED%88%AC%ED%91%9C%EB%A5%BC %EC%9E%98 %EB%AA%BB %ED%95%B4%EB%8F%84 %EC%83%81%EA%B4%80%EC%9D%80 %EC%97%86%EC%A7%80%EB%A7%8C, %EC%9D%B4%EC%A4%91 %ED%88%AC%ED%91%9C%EB%8A%94 %EB%B0%A9%EC%A7%80%ED%95%98%EA%B2%A0%EB%8B%A4%EB%8A%94 %EA%B2%83%EC%9D%B4%EB%8B%A4. %EC%B0%B8%EA%B3%A0%EB%A1%9C %EC%9D%B4%EB%9F%B0 %ED%88%AC%ED%91%9C%ED%95%9C %EC%82%AC%EC%8B%A4%EC%9D%80 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%95%A0 %EB%95%8C %EB%B3%B8%EC%9D%B8 %ED%82%A4%EB%A1%9C %EC%84%9C%EB%AA%85%EC%9D%84 %ED%95%98%EB%AF%80%EB%A1%9C %EC%89%BD%EA%B2%8C %EC%95%8C%EC%95%84%EB%82%BC %EC%88%98 %EC%9E%88%EB%8B%A4.%0A%0A%EA%B7%B8%EB%A0%87%EB%8B%A4%EB%A9%B4 %EC%97%AC%EA%B8%B0%EC%84%9C %EC%96%B4%EB%96%BB%EA%B2%8C %EB%B3%B8%EC%9D%B8%EC%9D%B4 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%95%9C %EC%B2%B4%EC%9D%B8%EC%9D%B4 %EC%A0%95%EC%A7%81%ED%95%9C%EC%A7%80 %EC%95%8C %EC%88%98 %EC%9E%88%EC%9D%84%EA%B9%8C.%0A%0ACapser%EB%8A%94 %EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8%EC%97%90 Checkpoint%EB%9D%BC%EB%8A%94 %EC%A7%80%EC%A0%90%EC%9D%84 %EC%A0%95%ED%95%B4%EB%86%93%EB%8A%94%EB%8B%A4. %ED%95%B4%EC%84%9C %EA%B0%81 50%EB%B2%88%EC%A7%B8 %EB%B8%94%EB%A1%9D%EB%A7%88%EB%8B%A4 Checkpoint%EA%B0%80 %EC%9E%88%EB%8B%A4%EB%A9%B4 %EC%9D%B4%EB%9F%B0 Checkpoint%EA%B0%80 %EC%9C%A0%ED%9A%A8%ED%95%9C%EC%A7%80 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%95%9C%EB%8B%A4. %EA%B7%B8%EB%9F%BC %ED%88%AC%ED%91%9C %EB%85%B8%EB%93%9C%EC%9D%98 2/3%EC%9D%B4 %EC%9D%B8%EC%A0%95%EC%9D%84 %ED%95%98%EB%A9%B4 %EC%9C%A0%ED%9A%A8%ED%95%9C %ED%88%AC%ED%91%9C%EA%B0%80 %EB%90%98%EA%B3%A0 %EA%B7%B8 %EB%B8%94%EB%A1%9D%EC%9D%80 %EC%9D%BC%EB%8B%A8 Justified%EA%B0%80 %EB%90%9C%EB%8B%A4. %EA%B7%B8%EB%9F%B0 %EB%8B%A4%EC%9D%8C %EB%8B%A4%EC%9D%8C%EB%B2%88 Checkpoint %EB%B8%94%EB%A1%9D%EC%9D%B4 %EB%8B%A4%EC%9D%8C%EB%B2%88 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%86%B5%ED%95%B4 Justified%EA%B0%80 %EB%90%98%EB%A9%B4, %EC%B2%98%EC%9D%8C Justified%EA%B0%80 %EB%90%98%EC%97%88%EB%8D%98 %EB%B8%94%EB%A1%9D%EC%9D%80 Finalized%EA%B0%80 %EB%90%98%EC%96%B4 %EC%99%84%EC%A0%84%ED%9E%88 %EC%9C%A0%ED%9A%A8%ED%95%9C %EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8%EC%9D%B4 %EB%90%9C%EB%8B%A4.%0A%0A%EC%A6%89, %EC%9D%B4 Finalized%EC%99%80 Justified %EB%B8%94%EB%A1%9D%EB%93%A4%EC%9D%84 %EC%9E%98 %EB%94%B0%EB%9D%BC%EA%B0%80%EB%A9%B0 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%95%98%EB%A9%B4 %EC%9D%98%EB%8F%84%EC%B9%98 %EC%95%8A%EA%B2%8C %EC%95%85%EC%9D%98%EC%A0%81%EC%9D%B8 %EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8%EC%97%90 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%95%98%EB%8A%94 %EA%B2%83%EC%9D%84 %EB%B0%A9%EC%A7%80%ED%95%A0 %EC%88%98 %EC%9E%88%EB%8B%A4.%0A%0A%EB%A7%88%EC%A7%80%EB%A7%89%EC%9C%BC%EB%A1%9C %EC%9D%B4 Checkpoint%EA%B0%80 50%EB%B2%88%EC%A7%B8 %EB%B8%94%EB%A1%9D%EB%A7%88%EB%8B%A4 %EB%9D%BC%EA%B3%A0 %ED%95%B4%EC%84%9C %EB%A7%A4%EC%9A%B0 %EA%B8%B4 %EC%8B%9C%EA%B0%84%EC%9D%B4%EB%9D%BC %EC%83%9D%EA%B0%81%ED%95%A0 %EC%88%98 %EC%9E%88%EC%9D%84%EC%A7%80 %EB%AA%A8%EB%A5%B4%EC%A7%80%EB%A7%8C, %EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80%EC%9D%80 %ED%95%9C %EB%B8%94%EB%A1%9D%EC%9D%B4 %EC%95%BD 15%EC%B4%88%EC%97%90 %EC%83%9D%EC%84%B1%EB%90%9C%EB%8B%A4%EB%8A%94 %EA%B2%83%EC%9D%84 %EA%B3%A0%EB%A0%A4%ED%95%98%EB%A9%B4 %EA%B7%B8%EB%A0%87%EA%B2%8C %EA%B8%B4 %EC%8B%9C%EA%B0%84%EC%9D%B4 %EC%95%84%EB%8B%88%EB%8B%A4.%0A * Token
json metadata{"tags":["onther","ethereum","blockchain"],"links":["https://medium.com/@kevin.j","http://javaexpert.tistory.com","https://paritytech.io/security-alert-2/","https://steemit.com/bitcoin/@dlgusdn616/bitcoin01-01"],"app":"steemit/0.1","format":"markdown"}
Transaction InfoBlock #23250664/Trx 3004f31ca5e72a8a4a49308d2af7cacddc2b00a1
View Raw JSON Data
{
  "trx_id": "3004f31ca5e72a8a4a49308d2af7cacddc2b00a1",
  "block": 23250664,
  "trx_in_block": 36,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-12T07:14:15",
  "op": [
    "comment",
    {
      "parent_author": "",
      "parent_permlink": "onther",
      "author": "dlgusdn616",
      "permlink": "r-and-d-cheat-sheet",
      "title": "이더리움 블록체인 R&D스타트업 온더 채용 Cheat Sheet",
      "body": "@@ -134,16 +134,20 @@\n %EC%9E%91%EC%84%B1%ED%95%98%EA%B2%8C %EB%90%90%EB%8B%A4.\n+%0A## \n %0A%0A* ETC%EB%A5%BC\n@@ -1041,24 +1041,16 @@\n  %EC%A0%95%EB%B3%B4%EB%8F%84 %EC%97%86%EB%8B%A4.\n- address\n %0A%ED%95%B4%EC%BB%A4%EA%B0%80 %ED%8A%B9%EC%A0%95 \n@@ -1177,10 +1177,10 @@\n %ED%95%98%EB%8B%A4.%0A\n-8.\n+* \n  %EB%A7%88%EC%9D%B4%EB%8B%9D\n@@ -1714,16 +1714,17 @@\n  %EC%8B%9C%EC%9E%91%ED%95%9C%EB%8B%A4. %0A\n+%0A\n compile:\n@@ -1822,16 +1822,17 @@\n %EC%9D%B4 %EC%A7%84%ED%96%89%EB%90%9C%EB%8B%A4.%0A\n+%0A\n test: te\n@@ -3556,16 +3556,17 @@\n  %EB%AC%BC%EB%A1%A0%EC%9D%B4%EB%8B%A4. %0A\n+%0A\n %EA%B2%B0%EA%B5%AD %EC%9E%90%EC%8B%A0%EC%9D%98 %EC%A3%BC\n@@ -3915,16 +3915,17 @@\n  %EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EB%8B%A4.%0A\n+%0A\n Transcat\n@@ -4125,16 +4125,17 @@\n %EC%9D%B4 %EB%95%8C%EB%AC%B8%EC%9D%B4%EB%8B%A4.%0A\n+%0A\n %EB%A8%B8%ED%81%B4 path%EB%8A%94\n@@ -4270,18 +4270,47 @@\n %ED%95%A0 %EC%88%98 %EC%9E%88%EB%8B%A4.%0A\n-%3E \n+%0A%EC%BD%94%EB%93%9C %EC%88%98%EC%A4%80%EC%97%90%EC%84%9C%EC%9D%98 %EC%9E%90%EC%84%B8%ED%95%9C %EB%82%B4%EC%9A%A9%EC%9D%80 %EC%95%84%EB%9E%98%EC%9D%98 %EB%A0%88%ED%8D%BC%EB%9F%B0%EC%8A%A4%EB%A5%BC %EC%B0%B8%EC%A1%B0%0A\n Referenc\n@@ -4871,16 +4871,17 @@\n %ED%95%A0 %EC%88%98 %EC%9E%88%EB%8B%A4.%0A\n+%0A\n %EC%95%95%EB%8F%84%EC%A0%81%EC%9D%B8 %ED%95%B4%EC%8B%9C%EB%9F%89\n@@ -6025,16 +6025,17 @@\n %EC%9D%84 %EC%B6%94%EA%B0%80%ED%96%88%EB%8B%A4.%0A\n+%0A\n %EB%8B%A8%EC%88%9C%ED%9E%88 SHA2\n@@ -6182,16 +6182,17 @@\n %ED%9A%A8%EA%B3%BC%EA%B0%80 %EC%9E%88%EB%8B%A4.%0A\n+%0A\n %EA%B7%B8%EB%9F%AC%EB%82%98 %EB%A7%8C%EC%95%BD %EB%A9%94\n@@ -6461,16 +6461,17 @@\n k%EC%9D%B4%EB%9D%BC %ED%95%9C%EB%8B%A4.%0A\n+%0A\n uncleBlo\n@@ -6664,16 +6664,17 @@\n %EC%9D%84 %EA%B0%9C%EB%B0%9C%ED%96%88%EB%8B%A4.%0A\n+%0A\n %EB%B9%84%ED%8A%B8%EC%BD%94%EC%9D%B8%EC%9D%98 %EA%B2%BD%EC%9A%B0\n@@ -6880,24 +6880,24 @@\n  %EB%B9%84%EA%B5%90%ED%95%98%EC%97%AC %EC%84%A4%EB%AA%85%ED%95%98%EB%9D%BC.%0A\n-\n * Casper%EB%8A%94 %EC%A0%84%ED%86%B5\n@@ -6966,16 +6966,932 @@\n  %EB%AA%85%EC%8B%9C%ED%95%98%EC%8B%9C%EC%98%A4)%0A\n+%3E Answer: (by Bookstore3)%0ANothing at stake %EB%AC%B8%EC%A0%9C%EB%9E%80 %EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80%EC%97%90%EC%84%9C %EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8%EC%9D%B4 %ED%8F%AC%ED%81%AC%EA%B0%80 %EB%90%A0 %EB%95%8C %EB%B0%9C%EC%83%9D%ED%95%98%EB%8A%94 %EB%AC%B8%EC%A0%9C%EB%8B%A4. %EA%B8%B0%EC%A1%B4 PoS %EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98 %EC%83%81%EC%97%90%EC%84%9C%EB%8A%94 %ED%8F%AC%ED%81%AC%EA%B0%80 %EB%B0%9C%EC%83%9D%ED%95%98%EC%97%AC %EB%85%B8%EB%93%9C%EA%B0%80 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%95%A0 %EB%95%8C, %EB%82%98%EB%88%A0%EC%A7%84 %EB%91%90 %EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8%EC%97%90 %EB%AA%A8%EB%91%90 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%95%B4%EB%8F%84 %EC%86%90%ED%95%B4%EB%A5%BC %EB%B3%B4%EA%B2%8C %EB%90%98%EB%8A%94 %EA%B5%AC%EC%A1%B0%EA%B0%80 %EC%95%84%EB%8B%88%EC%98%80%EB%8B%A4. %EA%B2%B0%EA%B5%AD %EB%91%98 %EB%8B%A4 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%95%B4 %EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC%EA%B0%80 %EC%B1%84%ED%83%9D%ED%95%9C %EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8%EC%97%90 %EB%8C%80%ED%95%9C %EB%B3%B4%EC%83%81%EB%A7%8C %EC%B1%99%EA%B8%B0%EB%A9%B4 %EB%90%98%EB%8A%94 %EA%B5%AC%EC%A1%B0%EC%98%80%EB%8B%A4.%0A%0A%EC%9D%B4%EB%9F%B0 %EB%AC%B8%EC%A0%9C%EB%A5%BC %ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0 %EC%9C%84%ED%95%B4 Casper%EC%97%90%EC%84%9C%EB%8A%94 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%95%98%EB%8A%94 %EB%85%B8%EB%93%9C%EB%93%A4%EC%9D%B4 %EB%B3%B8%EC%9D%B8%EC%9D%98 %EC%A7%80%EB%B6%84, %EC%A6%89 %EB%8F%88%EC%9D%84 %EA%B1%B8%EA%B3%A0 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%95%98%EA%B2%8C %EB%A7%8C%EB%93%A4%EA%B3%A0, %EB%A7%8C%EC%95%BD %EB%B3%B8%EC%9D%B8%EC%9D%B4 %EC%95%85%EC%9D%98%EC%A0%81%EC%9C%BC%EB%A1%9C %ED%88%AC%ED%91%9C%EB%A5%BC %EB%91%90 %EC%B2%B4%EC%9D%B8%EC%97%90 %EB%AA%A8%EB%91%90 %ED%95%98%EA%B2%8C %EB%90%98%EB%A9%B4 %EB%8F%88%EC%9D%84 %EC%9E%83%EA%B2%8C %EB%90%98%EB%8A%94 %EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EC%9D%84 %EC%82%AC%EC%9A%A9%ED%95%9C%EB%8B%A4. %EC%A6%89, %ED%88%AC%ED%91%9C%EB%A5%BC %EC%9E%98 %EB%AA%BB %ED%95%B4%EB%8F%84 %EC%83%81%EA%B4%80%EC%9D%80 %EC%97%86%EC%A7%80%EB%A7%8C, %EC%9D%B4%EC%A4%91 %ED%88%AC%ED%91%9C%EB%8A%94 %EB%B0%A9%EC%A7%80%ED%95%98%EA%B2%A0%EB%8B%A4%EB%8A%94 %EA%B2%83%EC%9D%B4%EB%8B%A4. %EC%B0%B8%EA%B3%A0%EB%A1%9C %EC%9D%B4%EB%9F%B0 %ED%88%AC%ED%91%9C%ED%95%9C %EC%82%AC%EC%8B%A4%EC%9D%80 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%95%A0 %EB%95%8C %EB%B3%B8%EC%9D%B8 %ED%82%A4%EB%A1%9C %EC%84%9C%EB%AA%85%EC%9D%84 %ED%95%98%EB%AF%80%EB%A1%9C %EC%89%BD%EA%B2%8C %EC%95%8C%EC%95%84%EB%82%BC %EC%88%98 %EC%9E%88%EB%8B%A4.%0A%0A%EA%B7%B8%EB%A0%87%EB%8B%A4%EB%A9%B4 %EC%97%AC%EA%B8%B0%EC%84%9C %EC%96%B4%EB%96%BB%EA%B2%8C %EB%B3%B8%EC%9D%B8%EC%9D%B4 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%95%9C %EC%B2%B4%EC%9D%B8%EC%9D%B4 %EC%A0%95%EC%A7%81%ED%95%9C%EC%A7%80 %EC%95%8C %EC%88%98 %EC%9E%88%EC%9D%84%EA%B9%8C.%0A%0ACapser%EB%8A%94 %EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8%EC%97%90 Checkpoint%EB%9D%BC%EB%8A%94 %EC%A7%80%EC%A0%90%EC%9D%84 %EC%A0%95%ED%95%B4%EB%86%93%EB%8A%94%EB%8B%A4. %ED%95%B4%EC%84%9C %EA%B0%81 50%EB%B2%88%EC%A7%B8 %EB%B8%94%EB%A1%9D%EB%A7%88%EB%8B%A4 Checkpoint%EA%B0%80 %EC%9E%88%EB%8B%A4%EB%A9%B4 %EC%9D%B4%EB%9F%B0 Checkpoint%EA%B0%80 %EC%9C%A0%ED%9A%A8%ED%95%9C%EC%A7%80 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%95%9C%EB%8B%A4. %EA%B7%B8%EB%9F%BC %ED%88%AC%ED%91%9C %EB%85%B8%EB%93%9C%EC%9D%98 2/3%EC%9D%B4 %EC%9D%B8%EC%A0%95%EC%9D%84 %ED%95%98%EB%A9%B4 %EC%9C%A0%ED%9A%A8%ED%95%9C %ED%88%AC%ED%91%9C%EA%B0%80 %EB%90%98%EA%B3%A0 %EA%B7%B8 %EB%B8%94%EB%A1%9D%EC%9D%80 %EC%9D%BC%EB%8B%A8 Justified%EA%B0%80 %EB%90%9C%EB%8B%A4. %EA%B7%B8%EB%9F%B0 %EB%8B%A4%EC%9D%8C %EB%8B%A4%EC%9D%8C%EB%B2%88 Checkpoint %EB%B8%94%EB%A1%9D%EC%9D%B4 %EB%8B%A4%EC%9D%8C%EB%B2%88 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%86%B5%ED%95%B4 Justified%EA%B0%80 %EB%90%98%EB%A9%B4, %EC%B2%98%EC%9D%8C Justified%EA%B0%80 %EB%90%98%EC%97%88%EB%8D%98 %EB%B8%94%EB%A1%9D%EC%9D%80 Finalized%EA%B0%80 %EB%90%98%EC%96%B4 %EC%99%84%EC%A0%84%ED%9E%88 %EC%9C%A0%ED%9A%A8%ED%95%9C %EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8%EC%9D%B4 %EB%90%9C%EB%8B%A4.%0A%0A%EC%A6%89, %EC%9D%B4 Finalized%EC%99%80 Justified %EB%B8%94%EB%A1%9D%EB%93%A4%EC%9D%84 %EC%9E%98 %EB%94%B0%EB%9D%BC%EA%B0%80%EB%A9%B0 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%95%98%EB%A9%B4 %EC%9D%98%EB%8F%84%EC%B9%98 %EC%95%8A%EA%B2%8C %EC%95%85%EC%9D%98%EC%A0%81%EC%9D%B8 %EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8%EC%97%90 %ED%88%AC%ED%91%9C%EB%A5%BC %ED%95%98%EB%8A%94 %EA%B2%83%EC%9D%84 %EB%B0%A9%EC%A7%80%ED%95%A0 %EC%88%98 %EC%9E%88%EB%8B%A4.%0A%0A%EB%A7%88%EC%A7%80%EB%A7%89%EC%9C%BC%EB%A1%9C %EC%9D%B4 Checkpoint%EA%B0%80 50%EB%B2%88%EC%A7%B8 %EB%B8%94%EB%A1%9D%EB%A7%88%EB%8B%A4 %EB%9D%BC%EA%B3%A0 %ED%95%B4%EC%84%9C %EB%A7%A4%EC%9A%B0 %EA%B8%B4 %EC%8B%9C%EA%B0%84%EC%9D%B4%EB%9D%BC %EC%83%9D%EA%B0%81%ED%95%A0 %EC%88%98 %EC%9E%88%EC%9D%84%EC%A7%80 %EB%AA%A8%EB%A5%B4%EC%A7%80%EB%A7%8C, %EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80%EC%9D%80 %ED%95%9C %EB%B8%94%EB%A1%9D%EC%9D%B4 %EC%95%BD 15%EC%B4%88%EC%97%90 %EC%83%9D%EC%84%B1%EB%90%9C%EB%8B%A4%EB%8A%94 %EA%B2%83%EC%9D%84 %EA%B3%A0%EB%A0%A4%ED%95%98%EB%A9%B4 %EA%B7%B8%EB%A0%87%EA%B2%8C %EA%B8%B4 %EC%8B%9C%EA%B0%84%EC%9D%B4 %EC%95%84%EB%8B%88%EB%8B%A4.%0A\n * Token \n",
      "json_metadata": "{\"tags\":[\"onther\",\"ethereum\",\"blockchain\"],\"links\":[\"https://medium.com/@kevin.j\",\"http://javaexpert.tistory.com\",\"https://paritytech.io/security-alert-2/\",\"https://steemit.com/bitcoin/@dlgusdn616/bitcoin01-01\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
    }
  ]
}
dlgusdn616published a new post: r-and-d-cheat-sheet
2018/06/12 06:43:45
parent author
parent permlinkonther
authordlgusdn616
permlinkr-and-d-cheat-sheet
title이더리움 블록체인 R&D스타트업 온더 채용 Cheat Sheet
body@@ -136,18 +136,17 @@ %ED%95%98%EA%B2%8C %EB%90%90%EB%8B%A4.%0A%0A -1. +* ETC%EB%A5%BC ET @@ -492,18 +492,17 @@ kevin.j%0A -2. +* solidit @@ -562,18 +562,28 @@ %EB%8A%94 %EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80?%0A -3. +%3E Answer:%0A%0A* 0x60 %EC%98%B5%EC%BD%94 @@ -610,18 +610,17 @@ :%0APush1%0A -4. +* EA%EA%B0%80 CA%ED%95%9C @@ -714,18 +714,28 @@ %EB%B6%80%EB%B6%84%EC%9D%80 %EC%97%86%EB%8B%A4.%0A -5. +%3E Answer:%0A%0A* %EC%98%90%EB%A1%9C%EC%9A%B0%ED%8E%98%EC%9D%B4%ED%8D%BC%EC%97%90 @@ -807,11 +807,21 @@ %EC%96%B4%EB%9D%BC.%0A -%0A6. +%3E Answer:%0A%0A%0A* EVM @@ -860,18 +860,17 @@ %EC%84%9C %EA%B8%B0%EC%88%A0%ED%95%98%EB%9D%BC%0A%0A -7. +* %EB%AA%A8%EB%93%A0 %EA%B1%B0%EB%9E%98%EB%82%B4%EC%97%AD @@ -1264,18 +1264,17 @@ %EA%B7%B8 %EC%9D%B4%EC%9C%A0%EB%8A%94?%0A -9. +* payable @@ -1353,11 +1353,9 @@ %EC%9D%B8%EA%B0%80?%0A -10. +* %EC%A0%84%EC%B2%B4 @@ -1441,11 +1441,9 @@ %EC%9C%A0%EB%8A%94?%0A -11. +* %ED%94%8C%EB%9D%BC%EC%A6%88 @@ -1474,11 +1474,9 @@ %EC%88%A0%ED%95%98%EB%9D%BC%0A -12. +* %ED%94%8C%EB%9D%BC%EC%A6%88 @@ -1518,11 +1518,9 @@ %EC%88%A0%ED%95%98%EB%9D%BC%0A -13. +* tru @@ -1928,11 +1928,9 @@ om)%0A -14. +* git @@ -1997,11 +1997,9 @@ er:%0A -15. +* %EC%9D%B4%EB%8D%94%EB%A6%AC @@ -2091,11 +2091,9 @@ er:%0A -16. +* %ED%8C%A8%EB%9F%AC%ED%8B%B0 @@ -2175,11 +2175,9 @@ r: %0A -17. +* %EC%86%94%EB%A6%AC%EB%94%94 @@ -2217,11 +2217,9 @@ r: %0A -18. +* cal @@ -2277,11 +2277,9 @@ r: %0A -19. +* sol @@ -2325,11 +2325,9 @@ er:%0A -20. +* O(n @@ -2681,11 +2681,9 @@ %EC%9E%88%EB%8B%A4.%0A -21. +* sol @@ -2720,11 +2720,9 @@ r: %0A -22. +* ICO @@ -2750,11 +2750,9 @@ er:%0A -23. +* PoA @@ -2808,11 +2808,9 @@ er:%0A -24. +* %ED%86%A0%ED%81%B0%EC%9D%98 @@ -2906,11 +2906,9 @@ er:%0A -25. +* pup @@ -2986,11 +2986,9 @@ r:%0A%0A -26. +* pup @@ -3049,11 +3049,9 @@ r:%0A%0A -27. +* sol @@ -3126,11 +3126,9 @@ r:%0A%0A -28. +* %EB%B9%84%ED%8A%B8%EC%BD%94 @@ -3715,11 +3715,9 @@ %EB%90%9C%EB%8B%A4.%0A -29. +* %EB%B8%94%EB%A1%9D%EC%B2%B4 @@ -4339,11 +4339,9 @@ -01%0A -30. +* 2%EC%84%B8%EB%8C%80 @@ -4394,16 +4394,17 @@ r: (by H +e uristicW @@ -4556,11 +4556,9 @@ %EC%9E%88%EB%8B%A4.%0A -31. +* %EB%B9%84%ED%8A%B8%EC%BD%94 @@ -4626,11 +4626,9 @@ %ED%95%98%EB%9D%BC.%0A -32. +* PoW @@ -4990,11 +4990,9 @@ %EC%9D%B4%EB%8B%A4.%0A -33. +* PoW @@ -5081,11 +5081,9 @@ r:%0A%0A -34. +* Whi @@ -5190,11 +5190,9 @@ r:%0A%0A -35. +* EA @@ -5445,11 +5445,9 @@ %EB%90%9C%EB%8B%A4.%0A -36. +* swa @@ -5491,11 +5491,9 @@ %ED%95%98%EC%8B%9C%EC%98%A4%0A -37. +* %EC%83%81%ED%98%B8 @@ -5588,11 +5588,9 @@ %ED%95%98%EB%9D%BC.%0A -38. +* Cas @@ -5653,11 +5653,9 @@ er:%0A -39. +* %EC%9D%B4%EB%8D%94%EB%A6%AC @@ -5715,11 +5715,9 @@ %ED%95%98%EB%9D%BC.%0A -40. +* Eth @@ -6225,11 +6225,9 @@ %EC%9D%B4%EB%8B%A4.%0A -41. +* %EC%9D%B4%EB%8D%94%EB%A6%AC @@ -6792,11 +6792,9 @@ %EC%9D%B4%EB%8B%A4.%0A -42. +* Cas @@ -6853,11 +6853,9 @@ %ED%95%98%EB%9D%BC.%0A -43. +* Cas @@ -6935,11 +6935,9 @@ %EC%8B%9C%EC%98%A4)%0A -44. +* Tok @@ -6998,11 +6998,9 @@ %EC%84%B8%EC%9A%94.%0A -45. +* PoW
json metadata{"tags":["onther","ethereum","blockchain"],"links":["https://medium.com/@kevin.j","http://javaexpert.tistory.com","https://paritytech.io/security-alert-2/","https://steemit.com/bitcoin/@dlgusdn616/bitcoin01-01"],"app":"steemit/0.1","format":"markdown"}
Transaction InfoBlock #23250055/Trx 4718547ebd497aae3d2d43e8c23b2ac369e8d37f
View Raw JSON Data
{
  "trx_id": "4718547ebd497aae3d2d43e8c23b2ac369e8d37f",
  "block": 23250055,
  "trx_in_block": 29,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-12T06:43:45",
  "op": [
    "comment",
    {
      "parent_author": "",
      "parent_permlink": "onther",
      "author": "dlgusdn616",
      "permlink": "r-and-d-cheat-sheet",
      "title": "이더리움 블록체인 R&D스타트업 온더 채용 Cheat Sheet",
      "body": "@@ -136,18 +136,17 @@\n %ED%95%98%EA%B2%8C %EB%90%90%EB%8B%A4.%0A%0A\n-1.\n+*\n  ETC%EB%A5%BC ET\n@@ -492,18 +492,17 @@\n kevin.j%0A\n-2.\n+*\n  solidit\n@@ -562,18 +562,28 @@\n %EB%8A%94 %EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80?%0A\n-3.\n+%3E Answer:%0A%0A*\n  0x60 %EC%98%B5%EC%BD%94\n@@ -610,18 +610,17 @@\n :%0APush1%0A\n-4.\n+*\n  EA%EA%B0%80 CA%ED%95%9C\n@@ -714,18 +714,28 @@\n %EB%B6%80%EB%B6%84%EC%9D%80 %EC%97%86%EB%8B%A4.%0A\n-5.\n+%3E Answer:%0A%0A*\n  %EC%98%90%EB%A1%9C%EC%9A%B0%ED%8E%98%EC%9D%B4%ED%8D%BC%EC%97%90\n@@ -807,11 +807,21 @@\n %EC%96%B4%EB%9D%BC.%0A\n-%0A6.\n+%3E Answer:%0A%0A%0A*\n  EVM\n@@ -860,18 +860,17 @@\n %EC%84%9C %EA%B8%B0%EC%88%A0%ED%95%98%EB%9D%BC%0A%0A\n-7.\n+*\n  %EB%AA%A8%EB%93%A0 %EA%B1%B0%EB%9E%98%EB%82%B4%EC%97%AD\n@@ -1264,18 +1264,17 @@\n  %EA%B7%B8 %EC%9D%B4%EC%9C%A0%EB%8A%94?%0A\n-9.\n+*\n  payable\n@@ -1353,11 +1353,9 @@\n %EC%9D%B8%EA%B0%80?%0A\n-10.\n+*\n  %EC%A0%84%EC%B2%B4 \n@@ -1441,11 +1441,9 @@\n %EC%9C%A0%EB%8A%94?%0A\n-11.\n+*\n  %ED%94%8C%EB%9D%BC%EC%A6%88\n@@ -1474,11 +1474,9 @@\n %EC%88%A0%ED%95%98%EB%9D%BC%0A\n-12.\n+*\n  %ED%94%8C%EB%9D%BC%EC%A6%88\n@@ -1518,11 +1518,9 @@\n %EC%88%A0%ED%95%98%EB%9D%BC%0A\n-13.\n+*\n  tru\n@@ -1928,11 +1928,9 @@\n om)%0A\n-14.\n+*\n  git\n@@ -1997,11 +1997,9 @@\n er:%0A\n-15.\n+*\n  %EC%9D%B4%EB%8D%94%EB%A6%AC\n@@ -2091,11 +2091,9 @@\n er:%0A\n-16.\n+*\n  %ED%8C%A8%EB%9F%AC%ED%8B%B0\n@@ -2175,11 +2175,9 @@\n r: %0A\n-17.\n+*\n  %EC%86%94%EB%A6%AC%EB%94%94\n@@ -2217,11 +2217,9 @@\n r: %0A\n-18.\n+*\n  cal\n@@ -2277,11 +2277,9 @@\n r: %0A\n-19.\n+*\n  sol\n@@ -2325,11 +2325,9 @@\n er:%0A\n-20.\n+*\n  O(n\n@@ -2681,11 +2681,9 @@\n %EC%9E%88%EB%8B%A4.%0A\n-21.\n+*\n  sol\n@@ -2720,11 +2720,9 @@\n r: %0A\n-22.\n+*\n  ICO\n@@ -2750,11 +2750,9 @@\n er:%0A\n-23.\n+*\n  PoA\n@@ -2808,11 +2808,9 @@\n er:%0A\n-24.\n+*\n  %ED%86%A0%ED%81%B0%EC%9D%98\n@@ -2906,11 +2906,9 @@\n er:%0A\n-25.\n+*\n  pup\n@@ -2986,11 +2986,9 @@\n r:%0A%0A\n-26.\n+*\n  pup\n@@ -3049,11 +3049,9 @@\n r:%0A%0A\n-27.\n+*\n  sol\n@@ -3126,11 +3126,9 @@\n r:%0A%0A\n-28.\n+*\n  %EB%B9%84%ED%8A%B8%EC%BD%94\n@@ -3715,11 +3715,9 @@\n %EB%90%9C%EB%8B%A4.%0A\n-29.\n+*\n  %EB%B8%94%EB%A1%9D%EC%B2%B4\n@@ -4339,11 +4339,9 @@\n -01%0A\n-30.\n+*\n  2%EC%84%B8%EB%8C%80\n@@ -4394,16 +4394,17 @@\n r: (by H\n+e\n uristicW\n@@ -4556,11 +4556,9 @@\n %EC%9E%88%EB%8B%A4.%0A\n-31.\n+*\n  %EB%B9%84%ED%8A%B8%EC%BD%94\n@@ -4626,11 +4626,9 @@\n %ED%95%98%EB%9D%BC.%0A\n-32.\n+*\n  PoW\n@@ -4990,11 +4990,9 @@\n %EC%9D%B4%EB%8B%A4.%0A\n-33.\n+*\n  PoW\n@@ -5081,11 +5081,9 @@\n r:%0A%0A\n-34.\n+*\n  Whi\n@@ -5190,11 +5190,9 @@\n r:%0A%0A\n-35.\n+*\n  EA \n@@ -5445,11 +5445,9 @@\n %EB%90%9C%EB%8B%A4.%0A\n-36.\n+*\n  swa\n@@ -5491,11 +5491,9 @@\n %ED%95%98%EC%8B%9C%EC%98%A4%0A\n-37.\n+*\n  %EC%83%81%ED%98%B8 \n@@ -5588,11 +5588,9 @@\n %ED%95%98%EB%9D%BC.%0A\n-38.\n+*\n  Cas\n@@ -5653,11 +5653,9 @@\n er:%0A\n-39.\n+*\n  %EC%9D%B4%EB%8D%94%EB%A6%AC\n@@ -5715,11 +5715,9 @@\n %ED%95%98%EB%9D%BC.%0A\n-40.\n+*\n  Eth\n@@ -6225,11 +6225,9 @@\n %EC%9D%B4%EB%8B%A4.%0A\n-41.\n+*\n  %EC%9D%B4%EB%8D%94%EB%A6%AC\n@@ -6792,11 +6792,9 @@\n %EC%9D%B4%EB%8B%A4.%0A\n-42.\n+*\n  Cas\n@@ -6853,11 +6853,9 @@\n %ED%95%98%EB%9D%BC.%0A\n-43.\n+*\n  Cas\n@@ -6935,11 +6935,9 @@\n %EC%8B%9C%EC%98%A4)%0A\n-44.\n+*\n  Tok\n@@ -6998,11 +6998,9 @@\n %EC%84%B8%EC%9A%94.%0A\n-45.\n+*\n  PoW\n",
      "json_metadata": "{\"tags\":[\"onther\",\"ethereum\",\"blockchain\"],\"links\":[\"https://medium.com/@kevin.j\",\"http://javaexpert.tistory.com\",\"https://paritytech.io/security-alert-2/\",\"https://steemit.com/bitcoin/@dlgusdn616/bitcoin01-01\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
    }
  ]
}
dlgusdn616published a new post: r-and-d-cheat-sheet
2018/06/12 04:52:54
parent author
parent permlinkonther
authordlgusdn616
permlinkr-and-d-cheat-sheet
title이더리움 블록체인 R&D스타트업 온더 채용 Cheat Sheet
body@@ -221,16 +221,288 @@ nswer: %0A +%EA%B1%B0%EB%9E%98%EC%86%8C%EA%B0%80 %EC%82%AC%EC%9A%A9%EC%9E%90%EC%97%90%EA%B2%8C %EB%B6%80%EC%97%AC%ED%95%9C %EC%A7%80%EA%B0%91 %EC%A3%BC%EC%86%8C%EB%8A%94 EA%EC%A3%BC%EC%86%8C%EA%B0%80 %EC%95%84%EB%8B%8C %EC%BB%A8%ED%8A%B8%EB%9E%99%ED%8A%B8 %EC%A3%BC%EC%86%8C%EB%8B%A4. %EA%B7%B8%EB%A6%AC%EA%B3%A0 %EC%BB%A8%ED%8A%B8%EB%9E%99%ED%8A%B8 %EC%A3%BC%EC%86%8C%EB%8A%94 %EC%83%9D%EC%84%B1%EB%90%98%EB%8A%94 %EA%B7%9C%EC%B9%99%EA%B3%BC %EB%B0%A9%EC%8B%9D%EC%9D%B4 %EC%A0%95%ED%95%B4%EC%A0%B8 %EC%9E%88%EB%8B%A4. %EA%B7%B8%EB%A6%AC%EA%B3%A0 %EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80%EA%B3%BC %EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80 %ED%81%B4%EB%9E%98%EC%8B%9D%EC%9D%80 %EB%8F%99%EC%9D%BC%ED%95%9C %EC%A3%BC%EC%86%8C %EC%83%9D%EC%84%B1 %EA%B7%9C%EC%B9%99%EC%9D%84 %EA%B0%80%EC%A7%80%EA%B3%A0 %EC%9E%88%EA%B8%B0 %EB%95%8C%EB%AC%B8%EC%97%90, %EB%A7%8C%EC%95%BD %EC%9D%B4%EB%8D%94 %ED%81%B4%EB%9E%98%EC%8B%9D%EC%9D%84 %EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80 %EB%A9%94%EC%9D%B8%EB%84%B7%EC%9D%98 ERC20 %EC%BB%A8%ED%8A%B8%EB%9E%99%ED%8A%B8 %EC%A3%BC%EC%86%8C%EB%A1%9C %EC%9E%98%EB%AA%BB %EC%9E%85%EA%B8%88%ED%96%88%EB%8B%A4%EB%A9%B4, %EB%8F%99%EC%9D%BC%ED%95%9C %EB%B0%A9%EC%8B%9D%EC%9C%BC%EB%A1%9C %EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80 %ED%81%B4%EB%9E%98%EC%8B%9D %EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC%EC%97%90%EC%84%9C %EC%BB%A8%ED%8A%B8%EB%9E%99%ED%8A%B8 %EC%A3%BC%EC%86%8C%EB%A5%BC %EB%A7%8C%EB%93%A4%EC%96%B4 %EB%8F%8C%EB%A0%A4%EB%B0%9B%EC%9D%80 %EB%8B%A4%EC%9D%8C %EC%98%A4%EC%9E%85%EA%B8%88%ED%95%9C %EC%82%AC%EC%9A%A9%EC%9E%90%EC%97%90%EA%B2%8C %EB%8F%8C%EB%A0%A4%EC%A3%BC%EB%A9%B4 %EB%90%9C%EB%8B%A4.%0AReference: https://medium.com/@kevin.j%0A 2. solid @@ -586,24 +586,26 @@ %EB%96%A4 %EB%AA%85%EB%A0%B9%EC%9D%B8%EA%B0%80?%0A +%3E Answer:%0A - Push1%0A4. @@ -987,19 +987,16 @@ %ED%95%98%EB%8A%94 %EA%B1%B4 %ED%95%B4%EC%BB%A4%EC%9D%98 - %EA%B3%84%EC%A0%95 address @@ -1012,16 +1012,23 @@ %EC%A0%95%EB%B3%B4%EB%8F%84 %EC%97%86%EB%8B%A4. +address %0A%ED%95%B4%EC%BB%A4%EA%B0%80 %ED%8A%B9%EC%A0%95 @@ -1812,14 +1812,106 @@ %EB%90%9C%EB%8B%A4.%0A - test: +test %ED%8F%B4%EB%8D%94%EB%82%B4%EC%97%90 .sol, .js %ED%8C%8C%EC%9D%BC%EB%93%A4%EC%9D%84 %EC%BB%B4%ED%8C%8C%EC%9D%BC %ED%9B%84 %EC%9C%A0%EB%8B%9B%ED%85%8C%EC%8A%A4%ED%8C%85%EC%9D%84 %EC%A7%84%ED%96%89%ED%95%9C%EB%8B%A4. (Answerd by %EC%88%98%EC%A7%80%EC%95%84%EB%B9%A0: http://javaexpert.tistory.com) %0A14.
json metadata{"tags":["onther","ethereum","blockchain"],"links":["https://medium.com/@kevin.j","http://javaexpert.tistory.com","https://paritytech.io/security-alert-2/","https://steemit.com/bitcoin/@dlgusdn616/bitcoin01-01"],"app":"steemit/0.1","format":"markdown"}
Transaction InfoBlock #23247838/Trx 9a376ae4efb7c94f034de310dd502b1ccd6bf309
View Raw JSON Data
{
  "trx_id": "9a376ae4efb7c94f034de310dd502b1ccd6bf309",
  "block": 23247838,
  "trx_in_block": 31,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-12T04:52:54",
  "op": [
    "comment",
    {
      "parent_author": "",
      "parent_permlink": "onther",
      "author": "dlgusdn616",
      "permlink": "r-and-d-cheat-sheet",
      "title": "이더리움 블록체인 R&D스타트업 온더 채용 Cheat Sheet",
      "body": "@@ -221,16 +221,288 @@\n nswer: %0A\n+%EA%B1%B0%EB%9E%98%EC%86%8C%EA%B0%80 %EC%82%AC%EC%9A%A9%EC%9E%90%EC%97%90%EA%B2%8C %EB%B6%80%EC%97%AC%ED%95%9C %EC%A7%80%EA%B0%91 %EC%A3%BC%EC%86%8C%EB%8A%94 EA%EC%A3%BC%EC%86%8C%EA%B0%80 %EC%95%84%EB%8B%8C %EC%BB%A8%ED%8A%B8%EB%9E%99%ED%8A%B8 %EC%A3%BC%EC%86%8C%EB%8B%A4. %EA%B7%B8%EB%A6%AC%EA%B3%A0 %EC%BB%A8%ED%8A%B8%EB%9E%99%ED%8A%B8 %EC%A3%BC%EC%86%8C%EB%8A%94 %EC%83%9D%EC%84%B1%EB%90%98%EB%8A%94 %EA%B7%9C%EC%B9%99%EA%B3%BC %EB%B0%A9%EC%8B%9D%EC%9D%B4 %EC%A0%95%ED%95%B4%EC%A0%B8 %EC%9E%88%EB%8B%A4. %EA%B7%B8%EB%A6%AC%EA%B3%A0 %EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80%EA%B3%BC %EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80 %ED%81%B4%EB%9E%98%EC%8B%9D%EC%9D%80 %EB%8F%99%EC%9D%BC%ED%95%9C %EC%A3%BC%EC%86%8C %EC%83%9D%EC%84%B1 %EA%B7%9C%EC%B9%99%EC%9D%84 %EA%B0%80%EC%A7%80%EA%B3%A0 %EC%9E%88%EA%B8%B0 %EB%95%8C%EB%AC%B8%EC%97%90, %EB%A7%8C%EC%95%BD %EC%9D%B4%EB%8D%94 %ED%81%B4%EB%9E%98%EC%8B%9D%EC%9D%84 %EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80 %EB%A9%94%EC%9D%B8%EB%84%B7%EC%9D%98 ERC20 %EC%BB%A8%ED%8A%B8%EB%9E%99%ED%8A%B8 %EC%A3%BC%EC%86%8C%EB%A1%9C %EC%9E%98%EB%AA%BB %EC%9E%85%EA%B8%88%ED%96%88%EB%8B%A4%EB%A9%B4, %EB%8F%99%EC%9D%BC%ED%95%9C %EB%B0%A9%EC%8B%9D%EC%9C%BC%EB%A1%9C %EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80 %ED%81%B4%EB%9E%98%EC%8B%9D %EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC%EC%97%90%EC%84%9C %EC%BB%A8%ED%8A%B8%EB%9E%99%ED%8A%B8 %EC%A3%BC%EC%86%8C%EB%A5%BC %EB%A7%8C%EB%93%A4%EC%96%B4 %EB%8F%8C%EB%A0%A4%EB%B0%9B%EC%9D%80 %EB%8B%A4%EC%9D%8C %EC%98%A4%EC%9E%85%EA%B8%88%ED%95%9C %EC%82%AC%EC%9A%A9%EC%9E%90%EC%97%90%EA%B2%8C %EB%8F%8C%EB%A0%A4%EC%A3%BC%EB%A9%B4 %EB%90%9C%EB%8B%A4.%0AReference: https://medium.com/@kevin.j%0A\n 2. solid\n@@ -586,24 +586,26 @@\n %EB%96%A4 %EB%AA%85%EB%A0%B9%EC%9D%B8%EA%B0%80?%0A\n+%3E \n Answer:%0A\n-\n Push1%0A4.\n@@ -987,19 +987,16 @@\n %ED%95%98%EB%8A%94 %EA%B1%B4 %ED%95%B4%EC%BB%A4%EC%9D%98\n- %EA%B3%84%EC%A0%95\n  address\n@@ -1012,16 +1012,23 @@\n %EC%A0%95%EB%B3%B4%EB%8F%84 %EC%97%86%EB%8B%A4. \n+address\n %0A%ED%95%B4%EC%BB%A4%EA%B0%80 %ED%8A%B9%EC%A0%95 \n@@ -1812,14 +1812,106 @@\n %EB%90%9C%EB%8B%A4.%0A\n-\n test: \n+test %ED%8F%B4%EB%8D%94%EB%82%B4%EC%97%90 .sol, .js %ED%8C%8C%EC%9D%BC%EB%93%A4%EC%9D%84 %EC%BB%B4%ED%8C%8C%EC%9D%BC %ED%9B%84 %EC%9C%A0%EB%8B%9B%ED%85%8C%EC%8A%A4%ED%8C%85%EC%9D%84 %EC%A7%84%ED%96%89%ED%95%9C%EB%8B%A4. (Answerd by %EC%88%98%EC%A7%80%EC%95%84%EB%B9%A0: http://javaexpert.tistory.com)\n %0A14.\n",
      "json_metadata": "{\"tags\":[\"onther\",\"ethereum\",\"blockchain\"],\"links\":[\"https://medium.com/@kevin.j\",\"http://javaexpert.tistory.com\",\"https://paritytech.io/security-alert-2/\",\"https://steemit.com/bitcoin/@dlgusdn616/bitcoin01-01\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
    }
  ]
}
osyvvupvoted (100.00%) @dlgusdn616 / bitcoin01-01
2018/06/12 04:41:03
voterosyvv
authordlgusdn616
permlinkbitcoin01-01
weight10000 (100.00%)
Transaction InfoBlock #23247601/Trx ace6133c3d9bf97d1da12a639ecc5df75ae8075d
View Raw JSON Data
{
  "trx_id": "ace6133c3d9bf97d1da12a639ecc5df75ae8075d",
  "block": 23247601,
  "trx_in_block": 43,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-12T04:41:03",
  "op": [
    "vote",
    {
      "voter": "osyvv",
      "author": "dlgusdn616",
      "permlink": "bitcoin01-01",
      "weight": 10000
    }
  ]
}
2018/06/12 03:53:39
votersensation
authordlgusdn616
permlinkr-and-d-cheat-sheet
weight10000 (100.00%)
Transaction InfoBlock #23246654/Trx 7ab2389060cb55870a1239ada66149b8f4b9a2b1
View Raw JSON Data
{
  "trx_id": "7ab2389060cb55870a1239ada66149b8f4b9a2b1",
  "block": 23246654,
  "trx_in_block": 42,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-12T03:53:39",
  "op": [
    "vote",
    {
      "voter": "sensation",
      "author": "dlgusdn616",
      "permlink": "r-and-d-cheat-sheet",
      "weight": 10000
    }
  ]
}
dlgusdn616published a new post: r-and-d-cheat-sheet
2018/06/12 03:34:36
parent author
parent permlinkonther
authordlgusdn616
permlinkr-and-d-cheat-sheet
title이더리움 블록체인 R&D스타트업 온더 채용 Cheat Sheet
body@@ -314,16 +314,30 @@ %EB%96%A4 %EB%AA%85%EB%A0%B9%EC%9D%B8%EA%B0%80?%0A +Answer:%0APush1%0A 4. EA%EA%B0%80 C @@ -512,16 +512,17 @@ %EC%8B%9C%EB%A5%BC %EC%A0%81%EC%96%B4%EB%9D%BC.%0A +%0A 6. EVM%EC%98%B5%EC%BD%94 @@ -558,16 +558,17 @@ %ED%95%B4%EC%84%9C %EA%B8%B0%EC%88%A0%ED%95%98%EB%9D%BC%0A +%0A 7. %EB%AA%A8%EB%93%A0 %EA%B1%B0%EB%9E%98 @@ -2118,16 +2118,17 @@ %EB%A5%BC %EC%86%8C%EB%AA%A8%ED%95%9C%EB%8B%A4. +%0A gaslimit @@ -2881,16 +2881,15 @@ %EB%9E%9C%EC%9E%AD%EC%85%98%EB%93%A4 -%EC%9D%84 %EC%A0%80%EC%9E%A5%ED%95%A0 %EB%95%8C%EB%8A%94 +%EC%9D%80 %EB%B8%94%EB%A1%9D %EB%82%B4%EC%97%90 1%EC%B0%A8%EC%9B%90 @@ -2903,44 +2903,12 @@ %EB%A1%9C %EC%A0%80%EC%9E%A5 -%ED%95%98%EB%A9%B0 %EA%B0%81 %EB%B8%94%EB%A1%9D %EB%82%B4%EC%97%90 %ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98%EB%93%A4%EC%9D%98 vector%EA%B0%80 %EC%A0%80%EC%9E%A5%EB%90%98%EC%96%B4 %EC%9E%88%EB%8A%94 %EA%B5%AC%EC%A1%B0 +%EB%90%98%EC%96%B4 %EC%9E%88 %EB%8B%A4.%0AU @@ -2922,16 +2922,21 @@ %ED%95%98%EA%B8%B0 %EC%9C%84%ED%95%B4%EC%84%9C%EB%8A%94 +%0A%EC%B2%AB%EC%A7%B8: %ED%95%B4%EB%8B%B9 UTXO%EC%9D%98 @@ -3047,18 +3047,19 @@ %EC%9E%88%EC%96%B4%EC%95%BC %ED%95%9C%EB%8B%A4.%0A -%EB%98%90%ED%95%9C +%EB%91%98%EC%A7%B8: scriptP @@ -3109,16 +3109,25 @@ %EC%9D%B4 %EC%84%9C%EB%AA%85 %EC%A0%95%EB%B3%B4%EB%A5%BC + %ED%86%B5%ED%95%B4 %EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%A5%BC %EC%A6%9D%EB%AA%85%ED%95%A0 %EC%88%98 %EC%9E%88 @@ -3133,21 +3133,9 @@ %EC%9E%88%EC%96%B4%EC%95%BC -UTXO%EB%A5%BC %EC%82%AC%EC%9A%A9%ED%95%A0 %EC%88%98 %EC%9E%88 +%ED%95%9C %EB%8B%A4. %EB%AC%BC @@ -3148,16 +3148,8 @@ %EC%A0%84%EC%97%90, - %EC%9E%90%EC%8B%A0%EC%9D%98 %EC%A3%BC%EC%86%8C%EC%97%90 %EC%82%AC%EC%9A%A9%ED%95%98 @@ -3252,16 +3252,29 @@ %EB%A9%B0 %EC%82%AC%EC%9A%A9%ED%95%A0 %EB%95%8C%EB%8A%94 + input%EC%9C%BC%EB%A1%9C %EB%93%A4%EC%96%B4 %EC%98%A8 scriptP @@ -3287,17 +3287,28 @@ %EC%8B%A4%ED%96%89%ED%95%98 -%EA%B3%A0 %EB%B3%B4%EB%82%B4%EB%A0%A4%EB%8A%94 %EC%82%AC%EB%9E%8C +%EB%A9%B4 %EB%90%98%EB%8A%94 %EA%B2%83%EC%9D%B4%EA%B3%A0, %EC%A0%84%EC%86%A1%ED%95%A0 %EB%95%8C%EB%8A%94 %EC%88%98%EC%8B%A0%EC%9E%90 %EC%9D%98 %EC%A3%BC%EC%86%8C @@ -3914,16 +3914,82 @@ %ED%95%A0 %EC%88%98 %EC%9E%88%EB%8B%A4.%0A +%3E Reference: https://steemit.com/bitcoin/@dlgusdn616/bitcoin01-01%0A 30. 2%EC%84%B8%EB%8C%80 @@ -5936,32 +5936,34 @@ %EC%8B%9D %EA%B0%84%EC%9D%98 %EC%B0%A8%EC%9D%B4%EC%A0%90%EC%9D%84 %EC%84%A4%EB%AA%85%ED%95%98%EB%9D%BC.%0A +%3E Answer:%0A%EB%B9%84%ED%8A%B8%EC%BD%94%EC%9D%B8%EC%9D%98 %EA%B2%BD%EC%9A%B0 @@ -5994,14 +5994,17 @@ %EC%96%B4%EB%B2%84%EB%A6%B0 +%EC%8B%A4%ED%9A%A8( stale - +) %EB%B8%94%EB%A1%9D%EC%97%90 @@ -6067,26 +6067,30 @@ , %EC%9D%B4%EB%95%8C - %EB%B3%B4%EC%83%81 %EB%B0%9B%EB%8A%94 %EB%B8%94%EB%A1%9D%EC%9D%84 +%EC%9D%98 %EC%8B%A4%ED%9A%A8%EB%B8%94%EB%A1%9D%EC%9D%84 %EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80%EC%97%90%EC%84%9C%EB%8A%94 uncle - b +B lock @@ -6097,26 +6097,25 @@ %EC%9D%B4%EB%9D%BC %ED%95%9C%EB%8B%A4.%0Auncle - b +B lock%EC%9D%84 %EC%83%9D%EC%84%B1%ED%95%9C %EC%82%AC%EB%9E%8C @@ -6133,18 +6133,17 @@ %EA%B3%A0, uncle - b +B lock%EC%9D%84 %EC%A0%9C%EB%B3%B4 @@ -6262,26 +6262,44 @@ %EC%88%98 %EC%9E%88 -%EA%B8%B0 %EB%95%8C%EB%AC%B8%EC%97%90 %EC%9D%B4%EB%9F%AC%ED%95%9C +%EB%8B%A4. %EC%9D%B4%EB%9F%AC%ED%95%9C %EB%B0%B0%EA%B2%BD %EB%95%8C%EB%AC%B8%EC%97%90 %EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80%EC%97%90%EC%84%9C%EB%8A%94 GHOST %ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C%EC%9D%84 -%EC%B1%84%ED%83%9D +%EA%B0%9C%EB%B0%9C %ED%96%88%EB%8B%A4.%0A
json metadata{"tags":["onther","ethereum","blockchain"],"links":["https://paritytech.io/security-alert-2/","https://steemit.com/bitcoin/@dlgusdn616/bitcoin01-01"],"app":"steemit/0.1","format":"markdown"}
Transaction InfoBlock #23246273/Trx 9fb548aee4bc8cb177c3c65e20ca81922c09a238
View Raw JSON Data
{
  "trx_id": "9fb548aee4bc8cb177c3c65e20ca81922c09a238",
  "block": 23246273,
  "trx_in_block": 34,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-12T03:34:36",
  "op": [
    "comment",
    {
      "parent_author": "",
      "parent_permlink": "onther",
      "author": "dlgusdn616",
      "permlink": "r-and-d-cheat-sheet",
      "title": "이더리움 블록체인 R&D스타트업 온더 채용 Cheat Sheet",
      "body": "@@ -314,16 +314,30 @@\n %EB%96%A4 %EB%AA%85%EB%A0%B9%EC%9D%B8%EA%B0%80?%0A\n+Answer:%0APush1%0A\n 4. EA%EA%B0%80 C\n@@ -512,16 +512,17 @@\n %EC%8B%9C%EB%A5%BC %EC%A0%81%EC%96%B4%EB%9D%BC.%0A\n+%0A\n 6. EVM%EC%98%B5%EC%BD%94\n@@ -558,16 +558,17 @@\n %ED%95%B4%EC%84%9C %EA%B8%B0%EC%88%A0%ED%95%98%EB%9D%BC%0A\n+%0A\n 7. %EB%AA%A8%EB%93%A0 %EA%B1%B0%EB%9E%98\n@@ -2118,16 +2118,17 @@\n %EB%A5%BC %EC%86%8C%EB%AA%A8%ED%95%9C%EB%8B%A4. \n+%0A\n gaslimit\n@@ -2881,16 +2881,15 @@\n %EB%9E%9C%EC%9E%AD%EC%85%98%EB%93%A4\n-%EC%9D%84 %EC%A0%80%EC%9E%A5%ED%95%A0 %EB%95%8C%EB%8A%94\n+%EC%9D%80 %EB%B8%94%EB%A1%9D %EB%82%B4%EC%97%90\n  1%EC%B0%A8%EC%9B%90\n@@ -2903,44 +2903,12 @@\n %EB%A1%9C %EC%A0%80%EC%9E%A5\n-%ED%95%98%EB%A9%B0 %EA%B0%81 %EB%B8%94%EB%A1%9D %EB%82%B4%EC%97%90 %ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98%EB%93%A4%EC%9D%98 vector%EA%B0%80 %EC%A0%80%EC%9E%A5%EB%90%98%EC%96%B4 %EC%9E%88%EB%8A%94 %EA%B5%AC%EC%A1%B0\n+%EB%90%98%EC%96%B4 %EC%9E%88\n %EB%8B%A4.%0AU\n@@ -2922,16 +2922,21 @@\n %ED%95%98%EA%B8%B0 %EC%9C%84%ED%95%B4%EC%84%9C%EB%8A%94 \n+%0A%EC%B2%AB%EC%A7%B8: \n %ED%95%B4%EB%8B%B9 UTXO%EC%9D%98\n@@ -3047,18 +3047,19 @@\n %EC%9E%88%EC%96%B4%EC%95%BC %ED%95%9C%EB%8B%A4.%0A\n-%EB%98%90%ED%95%9C\n+%EB%91%98%EC%A7%B8:\n  scriptP\n@@ -3109,16 +3109,25 @@\n %EC%9D%B4 %EC%84%9C%EB%AA%85 %EC%A0%95%EB%B3%B4%EB%A5%BC\n+ %ED%86%B5%ED%95%B4 %EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%A5%BC\n  %EC%A6%9D%EB%AA%85%ED%95%A0 %EC%88%98 %EC%9E%88\n@@ -3133,21 +3133,9 @@\n %EC%9E%88%EC%96%B4%EC%95%BC \n-UTXO%EB%A5%BC %EC%82%AC%EC%9A%A9%ED%95%A0 %EC%88%98 %EC%9E%88\n+%ED%95%9C\n %EB%8B%A4. %EB%AC%BC\n@@ -3148,16 +3148,8 @@\n  %EC%A0%84%EC%97%90,\n- %EC%9E%90%EC%8B%A0%EC%9D%98 %EC%A3%BC%EC%86%8C%EC%97%90\n  %EC%82%AC%EC%9A%A9%ED%95%98\n@@ -3252,16 +3252,29 @@\n %EB%A9%B0 %EC%82%AC%EC%9A%A9%ED%95%A0 %EB%95%8C%EB%8A%94\n+ input%EC%9C%BC%EB%A1%9C %EB%93%A4%EC%96%B4 %EC%98%A8\n  scriptP\n@@ -3287,17 +3287,28 @@\n  %EC%8B%A4%ED%96%89%ED%95%98\n-%EA%B3%A0 %EB%B3%B4%EB%82%B4%EB%A0%A4%EB%8A%94 %EC%82%AC%EB%9E%8C\n+%EB%A9%B4 %EB%90%98%EB%8A%94 %EA%B2%83%EC%9D%B4%EA%B3%A0, %EC%A0%84%EC%86%A1%ED%95%A0 %EB%95%8C%EB%8A%94 %EC%88%98%EC%8B%A0%EC%9E%90\n %EC%9D%98 %EC%A3%BC%EC%86%8C\n@@ -3914,16 +3914,82 @@\n %ED%95%A0 %EC%88%98 %EC%9E%88%EB%8B%A4.%0A\n+%3E Reference: https://steemit.com/bitcoin/@dlgusdn616/bitcoin01-01%0A\n 30. 2%EC%84%B8%EB%8C%80 \n@@ -5936,32 +5936,34 @@\n %EC%8B%9D %EA%B0%84%EC%9D%98 %EC%B0%A8%EC%9D%B4%EC%A0%90%EC%9D%84 %EC%84%A4%EB%AA%85%ED%95%98%EB%9D%BC.%0A\n+%3E \n Answer:%0A%EB%B9%84%ED%8A%B8%EC%BD%94%EC%9D%B8%EC%9D%98 %EA%B2%BD%EC%9A%B0\n@@ -5994,14 +5994,17 @@\n %EC%96%B4%EB%B2%84%EB%A6%B0 \n+%EC%8B%A4%ED%9A%A8(\n stale\n- \n+)\n %EB%B8%94%EB%A1%9D%EC%97%90 \n@@ -6067,26 +6067,30 @@\n , %EC%9D%B4%EB%95%8C\n- %EB%B3%B4%EC%83%81 %EB%B0%9B%EB%8A%94 %EB%B8%94%EB%A1%9D%EC%9D%84\n+%EC%9D%98 %EC%8B%A4%ED%9A%A8%EB%B8%94%EB%A1%9D%EC%9D%84 %EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80%EC%97%90%EC%84%9C%EB%8A%94\n  uncle\n- b\n+B\n lock\n@@ -6097,26 +6097,25 @@\n %EC%9D%B4%EB%9D%BC %ED%95%9C%EB%8B%A4.%0Auncle\n- b\n+B\n lock%EC%9D%84 %EC%83%9D%EC%84%B1%ED%95%9C %EC%82%AC%EB%9E%8C\n@@ -6133,18 +6133,17 @@\n %EA%B3%A0, uncle\n- b\n+B\n lock%EC%9D%84 %EC%A0%9C%EB%B3%B4\n@@ -6262,26 +6262,44 @@\n  %EC%88%98 %EC%9E%88\n-%EA%B8%B0 %EB%95%8C%EB%AC%B8%EC%97%90 %EC%9D%B4%EB%9F%AC%ED%95%9C\n+%EB%8B%A4. %EC%9D%B4%EB%9F%AC%ED%95%9C %EB%B0%B0%EA%B2%BD %EB%95%8C%EB%AC%B8%EC%97%90 %EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80%EC%97%90%EC%84%9C%EB%8A%94 GHOST\n  %ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C%EC%9D%84 \n-%EC%B1%84%ED%83%9D\n+%EA%B0%9C%EB%B0%9C\n %ED%96%88%EB%8B%A4.%0A\n",
      "json_metadata": "{\"tags\":[\"onther\",\"ethereum\",\"blockchain\"],\"links\":[\"https://paritytech.io/security-alert-2/\",\"https://steemit.com/bitcoin/@dlgusdn616/bitcoin01-01\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
    }
  ]
}
dlgusdn616published a new post: r-and-d-cheat-sheet
2018/06/12 03:18:12
parent author
parent permlinkonther
authordlgusdn616
permlinkr-and-d-cheat-sheet
title이더리움 블록체인 R&D스타트업 온더 채용 Cheat Sheet
body## Onther 채용 시험지 Cheat Sheet (작성 중) ### 작성 계기: 이더리움을 공부하는 사람으로서 아래와 같은 질문들에 답을 하면서 그 동안 공부했던 내용을 정리하고, 몰랐던 내용이 있다면 연구해서 보충하고 싶다는 취지로 작성하게 됐다. 1. ETC를 ETH메인넷의 ERC20주소로 보내버렸다. 복구할 방법이 있는가? 단 ERC20주소를 만든 개인키는 잃어버리지 않았다. >Answer: 2. solidity의 keccak함수의 연산은 EVM의 스택머신에서 이뤄질까? 그렇다면 혹은 그렇지 않다면 이유는 무엇인가? 3. 0x60 옵코드는 어떤 명령인가? 4. EA가 CA한테 이더를 보냈다. CA의 balance와 storageRoot는 모두 바뀐다. 참일까 거짓일까? 그 이유는? 단 CA 코드에 msg.value를 사용하는 부분은 없다. 5. 옐로우페이퍼에 적힌 트랜잭션 value가 표현할 수 있는 값의 최대 범위는? 근거가 되는 수식 번호와 옐로우페이퍼 커밋 해시를 적어라. 6. EVM옵코드 중 JUMP와 JUMPDEST의 차이와 역할에 대해서 기술하라 7. 모든 거래내역이 공개되어 있음에도 불구하고, 해커가 비트코인을 훔쳐갔을 때 추적하기 어려운 이유는? > Answer: 비트코인 시스템에서 계정을 생성할 때는 실세계에 있는 어떠한 정보도 필요가 없다. 따라서 공개된 거래내역이 있어도, 결국 거래내역에 존재하는 건 해커의 계정 address 이외의 어떠한 정보도 없다. 해커가 특정 풀노드에 지속적으로 의존하는 등의 패턴을 보이지 않는 이상 IP추적 등의 방법 또한 어렵다. 그리고 만약 해커가 훔쳐간 비트코인을 모네로, 지캐시 등의 익명 코인으로 변환하여 과정을 꼬아버린다면 추적은 사실상 불가능하다. 8. 마이닝 노드가 20개, 풀노드가 10개인 프라이빗 네트워크가 있다. tx 2개가 생성되어 블록에 포함되었을 때, 생성되는 EVM의 갯수와 그 이유는? 9. payable모디파이어에 대해서 설명하라. 그리고 payable모디파이어가 없는 ICO컨트랙트는 만들어 질 수 있을까? 있다면 그 이유는 무엇인가? 10. 전체 토큰의 전송을 멈출 수 있는 transfer pause 기능은 블록체인의 위변조불가능한 특성을 위배하는가? 그렇다면 혹은 그렇지 않다면 그 이유는? 11. 플라즈마 체인의 challenge과정에 대해서 서술하라 12. 플라즈마 체인의 합의 알고리즘과 exit 프로세스의 관계에 대해서 서술하라 13. truffle migrate, truffle compile, truffle test 각각의 명령어는 어떤 일을 하는가? > Answer: migrate: 이 명령어를 통해 스마트 컨트랙트를 네트워크에 배포한다. 만약 complie과정을 진행하지 않았다면, contracts 폴더 내의 솔리디티로 작성되어 있는 컨트랙트 소스코드들을 컴파일하는 것부터 시작한다. compile: contracts 폴더 내의 솔리디티로 작성되어 있는 컨트랙트 소스코드들을 컴파일한다. 두번째 컴파일부터는 변경된 이력이 있는 컨트랙트 소스코드에 대해서만 컴파일이 진행된다. test: 14. github에 solidity코드가 알록달록하게 보이기 위해서는(linter) 어떤 조치를 해야할까? > Answer: 15. 이더리움 계정 생성간 뉴모닉 단어를 이용할 수 있다. 뉴모닉이 만들 수 있는 계정 갯수의 한도는 있는가? 그렇다면 혹은 그렇지 않다면 그 이유는? > Answer: 16. 패러티 멀티시그 해킹(해킹(https://paritytech.io/security-alert-2/)의 구조와 원리를 설명하라. > Answer: 17. 솔리디티 Proxy Pattern에 대해서 설명하라 > Answer: 18. call, delegate call, static call의 차이에 대해서 설명하라 > Answer: 19. solidity와 vyper의 차이점과 장단점에 대해서 설명하라 > Answer: 20. O(n)의 시간복잡도를 가진 알고리즘은 퍼블릭 이더리움에서 동작 가능할까? 가능하다면 혹은 가능하지 않다면 그 이유는? > Answer: 어떤 내용을 가지고 있느냐에 따라 실행가능 여부가 달라진다. 예를 들어, transfer를 생각해보자. 이 메서드는 한 번의 실행 당 21,000가스를 소모한다. gaslimit이 800만이라고 할 때, for (i = 0; i < 2000; i++) trasnfer를 실행하게 된다면? 퍼블릭 이더리움에서 해당 알고리즘의 실행은 실행 도중 비정상적으로 중단될 수밖에 없다. 따라서 얼마나 많은 gas를 소모하는지를 측정하는 가스복잡도의 관점에서 컨트랙트 코드를 분석하고 활용할 필요가 있다. 21. solidity optimizer란 무엇인가? > Answer: 22. ICO트릴레마에 대해서 설명하라 > Answer: 23. PoA 합의 알고리즘에서 validator를 변경할 수 있는가? 이유는 무엇인가? > Answer: 24. 토큰의 분류 중 Work Token의 개념을 설명하고 Work token의 경우 토큰의 이상적인 형태는 무엇인가? 그 예(2가지 이상)는 무엇이 있을까? > Answer: 25. puppeth를 이용해 여러개의 Bootnode를 갖고 있는 프라이빗 네트워크를 운영할 수 있는가? 이유는 무엇인가? > Answer: 26. puppeth를 이용해 프라이빗 네트워크를 구축하기 위해 필요한 준비사항을 모두 적으시오 > Answer: 27. solidity에서 함수 인자로 전달된 파라미터 a를 함수 내부에서 소괄호로 감쌌다. eq) (a) 무슨 의미인가? >Answer: 28. 비트코인의 블럭, TX 구조를 간략히 설명하고, UTXO 를 사용 / 검증하기 위한 과정을 설명하라 > Answer: 비트코인의 블록은 크게 블록헤더와 트랜잭션들로 구성되어 있다. 실제로 트랜잭션들을 저장할 때는 1차원 vector로 저장하며 각 블록 내에 트랜잭션들의 vector가 저장되어 있는 구조다. UTXO를 사용하기 위해서는 해당 UTXO의 scriptPubKey에 OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG 중 hash160에 자신의 주소가 포함되어 있어야 한다. 또한 scriptPubKey 스크립트를 실행하여 마지막에 true가 반환될 수 있다면, 즉 자신이 서명 정보를 증명할 수 있어야 UTXO를 사용할 수 있다. 물론 사용하기 전에, 자신의 주소에 사용하려는 output value보다 더 많은 input value가 있어야 되는 것은 물론이다. 결국 자신의 주소로 할당된 UTXO의 value가 사용할 value보다 커야하며 사용할 때는 scriptPubKey를 실행하고 보내려는 사람의 주소를 기반으로 scriptPubKey를 생성하고 거래를 네트워크 상에 배포하면 된다. 29. 블록체인의 중요 요소는 해쉬함수와 머클 트리이다. 해쉬 함수를 사용하는 것의 의미(해쉬 함수의 특성)을 설명하고, 머클 트리, 머클 path 를 설명하라. > Answer: 해시함수는 input에 매핑되는 고유한 output을 만들어내는 함수다. 머클 트리는 이 해시함수의 특성을 아주 잘 이용한 자료구조 중 하나로, 이진 트리에 해시 개념을 도입한 자료구조다. Transcation이 여러 개 있을 때, 이 트랜잭션들을 리프노드로 두고 두개씩 묶어서 해시하고 해시된 값들을 또 두개씩 묶어 해시하는 과정을 반복하면서 루트까지 거슬러 올라간다. 이렇게 해시의 해시들로 구성되어 결국 루트까지 갔을 때, 그 루트를 머클루트라 한다. 리프 노드에 해당하는 거래내역이 하나라도 변조된다면 머클 루트값이 변하게 되는 원리는 바로 이 때문이다. 머클 path는 머클 트리의 장점이다. 특정 트랜잭션의 위변조 여부를 알고 싶을 때, 머클 트리내에 해당 트랜잭션과 관련된 해시만 따로 추출하게 되는데 이 때의 관련 해시들을 Merkle Branch라고 하며 이 Branch가 곧 path라고 할 수 있다. 30. 2세대 블록체인이라 불리는 이더리움과 비트코인의 구조적인 차이를 설명하라. > Answer: (by HuristicWave) 비트코인의 블록헤더는 이전 블록 헤더의 해시, 타임스탬프, 난이도, 넌스, 머클트리의 루트해시를 가지고 있지만, 이더리움의 블록헤더는 이전블록 헤더의 해시, 타임스탬프, 넌스, 난이도, 가스의 사용량, 상태 루트, 트랜잭션 루트, 리시트루트를 가지고 있다. 31. 비트코인, 이더리움, 혹은 그 밖의 블록체인들의 현존하는 스케일링 솔루션을 제시하고 어떤 방식으로 구현하려는지 설명하라. 32. PoW 에서 일어날 수 있는 공격 방식을 제시하라. > Answer: 전체 Hash Power(연산량)의 51% 이상을 차지했을 때, 해당 해시파워를 가지고 있는 노드는 다음 블록을 생성할 수 있는 확률이 50%가 된다. 따라서 연산량을 압도적으로 높여서 독점하게 되면 사실상 블록을 검증하고 블록체인에 추가해나가는 작업을 임의의 노드가 통제할 수 있고, 여기서 공격이 발생할 수 있다. 압도적인 해시량을 바탕으로 특정 시점부터 체인을 분기시킬 수도 있고, 자기 입맛대로 거래내역을 추가하는 공격도 할 수 있다. 체인 분기 공격이 사실상 가장 피해가 큰 공격유형이며, 네트워크 가치를 하락시킴으로써 코인 생태계 자체를 무너뜨릴 수 있는 공격이다. 33. PoW 가 아닌 합의 알고리즘은 어떤 것들이 있는가? Casper FFG, DPoS, Tendermint, 혹은 그 밖의 알고리즘을 설명하라. Answer: 34. Whisper, Swarm, IPFS, Infura, Gnosis, Aragon, Metamask, Golem, 혹은 그 밖의 이더리움 생태계에 기여하는 프로젝트를 설명하라. Answer: 35. EA a 와 b 의 balance 가 각각 n_a, n_b 일 때, a 의 모든 잔액을 b 에게 보냈다. gas price 를 g_p 라고 한다면, b 의 밸런스는 n_b + α 이다. 이 때 α 는? Answer: n_a - g_p; EA a가 자신의 모든 잔액 n_a를 보낼 때는 트랜잭션 실행을 위한 gas price g_p가 필연적으로 동반된다. 따라서 온전히 n_a는 보낼 수 없으며 gas price g_p를 차감한 잔액을 전송하게 된다. 36. swarm ls 명령어를 실행하기 위해 필요한 값은 어떤것이 있는지 설명하시오 37. 상호 독립적인 토큰이 서로 교환되는 Atomic Swap 방식에 대해 설명하고, Plasma Fast Withdrawl 절차에서의 Atomic Swap 방식을 설명하라. 38. Casper FFG가 어떻게 이더리움 블록체인의 확장성 문제를 해결할 수 있는지 근거를 제시하라. Answer: 39. 이더리움 블록체인에 대해서 Oracle이 갖는 의미를 설명하고 Oracle Problem에 대해 설명하라. 40. Ethash 기반의 이더리움 PoW 체인은 비트코인 PoW 체인보다 어떤 비교우위가 있는지 설명하고 그 한계를 제시하라. Answer: 이더리움의 PoW체인은 합의 엔진인 이대시(Ethash)에 구현되어 있다. 이대시의 경우 비트코인에 비해 가지는 장점은 ASIC 채굴기가 큰 영향을 발휘하지 못한다는 것이다. 비트코인에서는 연산량만 고려하면 되기 때문에, ASIC을 대량으로 가지고 있는 노드가 네트워크 생태계 자체를 독점할 수 있지만 이더리움에서는 기존의 PoW연산에 메모리 관련 연산을 추가했다. 단순히 SHA256 연산만을 필요로했던 비트코인과는 달리 이더리움은 DAG를 통해 미리 알 수 없는, 할 수 없는 순차적 메모리 연산을 요구하여 ASIC제작을 어렵게 했다. 메모리를 읽고 쓰는 부분에서의 기술 발전은 아직까지 속도가 그리 빠르지 않기 때문에 충분히 효과가 있다. 그러나 만약 메모리 관련 연산이 급격히 빨라지는 기술 발전이 이루어진다면, 이더리움의 PoW 또한 효력을 상실하게 될 것이다. 41. 이더리움의 GHOST Protocol 방식과 비트코인의 블록 생성방식 간의 차이점을 설명하라. Answer: 비트코인의 경우 체인이 분기되면서 유효하지 않은 블록이 되어버린 stale 블록에 대해서 따로 보상을 해주지 않는다. 그러나 이더리움에서는 Stale블록이 된 경우에도 보상을 해주는데, 이때 보상 받는 블록을 uncle block이라 한다. uncle block을 생성한 사람에게도 보상이 주어지고, uncle block을 제보하는 행위에 대해서도 보상이 주어진다. 이러한 프로토콜을 GHOST Protocol이라 하며 이더리움의 경우 블록 생성시간이 비트코인에 비해 약 40배빠르기 때문에, 체인이 분기되는 상황이 자주 연출될 수 있기 때문에 이러한 프로토콜을 채택했다. 비트코인의 경우 애초에 분기되는 상황이 그리 자주 발생하지 않기 때문에 보상에 대한 매커니즘을 특별히 고려하지 않았던 것이고, 이더리움의 경우 블록 생성시간이 빠르기 때문에 분기가 자주 발생하고 그로 인해 손해를 보는 채굴자들이 네트워크를 떠나지 않게끔 보상정책이 필요했던 것이다. 42. Casepr는 51% 공격 문제를 어떻게 해결할 것인지에 대해서 PoW 체인의 경우와 비교하여 설명하라. 43. Casper는 전통적인 PoS 알고리즘의 Nothing at Stake 문제를 어떻게 해결하려고 하는지 설명하라. (최소삭감조건을 명시하시오) 44. Token Economy의 가치 확보 문제와 Token Velocity Problem을 연관지어 서술하세요. 45. PoW에서 확보되지 않았던 경제적 완결성 개념이 무엇인지 설명하고, Casper는 이 문제를 어떻게 해결하려고 하는지 서술하세요.
json metadata{"tags":["onther","ethereum","blockchain"],"links":["https://paritytech.io/security-alert-2/"],"app":"steemit/0.1","format":"markdown"}
Transaction InfoBlock #23245945/Trx 509bd9b493585aff19c3c536a5df34d6cb79d6ad
View Raw JSON Data
{
  "trx_id": "509bd9b493585aff19c3c536a5df34d6cb79d6ad",
  "block": 23245945,
  "trx_in_block": 12,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-12T03:18:12",
  "op": [
    "comment",
    {
      "parent_author": "",
      "parent_permlink": "onther",
      "author": "dlgusdn616",
      "permlink": "r-and-d-cheat-sheet",
      "title": "이더리움 블록체인 R&D스타트업 온더 채용 Cheat Sheet",
      "body": "## Onther 채용 시험지 Cheat Sheet (작성 중)\n### 작성 계기: 이더리움을 공부하는 사람으로서 아래와 같은 질문들에 답을 하면서 그 동안 공부했던 내용을 정리하고, 몰랐던 내용이 있다면 연구해서 보충하고 싶다는 취지로 작성하게 됐다.\n\n1. ETC를 ETH메인넷의 ERC20주소로 보내버렸다. 복구할 방법이 있는가? 단 ERC20주소를 만든 개인키는 잃어버리지 않았다.\n>Answer: \n2. solidity의 keccak함수의 연산은 EVM의 스택머신에서 이뤄질까? 그렇다면 혹은 그렇지 않다면 이유는 무엇인가?\n3. 0x60 옵코드는 어떤 명령인가?\n4. EA가 CA한테 이더를 보냈다. CA의 balance와 storageRoot는 모두 바뀐다. 참일까 거짓일까? 그 이유는? 단 CA 코드에 msg.value를 사용하는 부분은 없다.\n5. 옐로우페이퍼에 적힌 트랜잭션 value가 표현할 수 있는 값의 최대 범위는? 근거가 되는 수식 번호와 옐로우페이퍼 커밋 해시를 적어라.\n6. EVM옵코드 중 JUMP와 JUMPDEST의 차이와 역할에 대해서 기술하라\n7. 모든 거래내역이 공개되어 있음에도 불구하고, 해커가 비트코인을 훔쳐갔을 때 추적하기 어려운 이유는?\n> Answer: \n비트코인 시스템에서 계정을 생성할 때는 실세계에 있는 어떠한 정보도 필요가 없다. 따라서 공개된 거래내역이 있어도, 결국 거래내역에 존재하는 건 해커의 계정 address 이외의 어떠한 정보도 없다. \n해커가 특정 풀노드에 지속적으로 의존하는 등의 패턴을 보이지 않는 이상 IP추적 등의 방법 또한 어렵다. 그리고 만약 해커가 훔쳐간 비트코인을 모네로, 지캐시 등의 익명 코인으로 변환하여 과정을 꼬아버린다면 추적은 사실상 불가능하다.\n8. 마이닝 노드가 20개, 풀노드가 10개인 프라이빗 네트워크가 있다. tx 2개가 생성되어 블록에 포함되었을 때, 생성되는 EVM의 갯수와 그 이유는?\n9. payable모디파이어에 대해서 설명하라. 그리고 payable모디파이어가 없는 ICO컨트랙트는 만들어 질 수 있을까? 있다면 그 이유는 무엇인가?\n10. 전체 토큰의 전송을 멈출 수 있는 transfer pause 기능은 블록체인의 위변조불가능한 특성을 위배하는가? 그렇다면 혹은 그렇지 않다면 그 이유는?\n11. 플라즈마 체인의 challenge과정에 대해서 서술하라\n12. 플라즈마 체인의 합의 알고리즘과 exit 프로세스의 관계에 대해서 서술하라\n13. truffle migrate, truffle compile, truffle test 각각의 명령어는 어떤 일을 하는가?\n> Answer:\nmigrate: 이 명령어를 통해 스마트 컨트랙트를 네트워크에 배포한다. 만약 complie과정을 진행하지 않았다면, contracts 폴더 내의 솔리디티로 작성되어 있는 컨트랙트 소스코드들을 컴파일하는 것부터 시작한다. \ncompile: contracts 폴더 내의 솔리디티로 작성되어 있는 컨트랙트 소스코드들을 컴파일한다. 두번째 컴파일부터는 변경된 이력이 있는 컨트랙트 소스코드에 대해서만 컴파일이 진행된다.\ntest: \n14. github에 solidity코드가 알록달록하게 보이기 위해서는(linter) 어떤 조치를 해야할까?\n> Answer:\n15. 이더리움 계정 생성간 뉴모닉 단어를 이용할 수 있다. 뉴모닉이 만들 수 있는 계정 갯수의 한도는 있는가? 그렇다면 혹은 그렇지 않다면 그 이유는?\n> Answer:\n16. 패러티 멀티시그 해킹(해킹(https://paritytech.io/security-alert-2/)의 구조와 원리를 설명하라.\n> Answer: \n17. 솔리디티 Proxy Pattern에 대해서 설명하라\n> Answer: \n18. call, delegate call, static call의 차이에 대해서 설명하라\n> Answer: \n19. solidity와 vyper의 차이점과 장단점에 대해서 설명하라\n> Answer:\n20. O(n)의 시간복잡도를 가진 알고리즘은 퍼블릭 이더리움에서 동작 가능할까? 가능하다면 혹은 가능하지 않다면 그 이유는?\n> Answer:\n어떤 내용을 가지고 있느냐에 따라 실행가능 여부가 달라진다. 예를 들어, transfer를 생각해보자. 이 메서드는 한 번의 실행 당 21,000가스를 소모한다. gaslimit이 800만이라고 할 때, for (i = 0; i < 2000; i++) trasnfer를 실행하게 된다면? 퍼블릭 이더리움에서 해당 알고리즘의 실행은 실행 도중 비정상적으로 중단될 수밖에 없다.\n따라서 얼마나 많은 gas를 소모하는지를 측정하는 가스복잡도의 관점에서 컨트랙트 코드를 분석하고 활용할 필요가 있다.\n21. solidity optimizer란 무엇인가?\n> Answer: \n22. ICO트릴레마에 대해서 설명하라\n> Answer:\n23. PoA 합의 알고리즘에서 validator를 변경할 수 있는가? 이유는 무엇인가?\n> Answer:\n24. 토큰의 분류 중 Work Token의 개념을 설명하고 Work token의 경우 토큰의 이상적인 형태는 무엇인가? 그 예(2가지 이상)는 무엇이 있을까?\n> Answer:\n25. puppeth를 이용해 여러개의 Bootnode를 갖고 있는 프라이빗 네트워크를 운영할 수 있는가? 이유는 무엇인가? \n> Answer:\n\n26. puppeth를 이용해 프라이빗 네트워크를 구축하기 위해 필요한 준비사항을 모두 적으시오\n> Answer:\n\n27. solidity에서 함수 인자로 전달된 파라미터 a를 함수 내부에서 소괄호로 감쌌다. eq) (a) 무슨 의미인가?\n>Answer:\n\n28. 비트코인의 블럭, TX 구조를 간략히 설명하고, UTXO 를 사용 / 검증하기 위한 과정을 설명하라\n> Answer:\n비트코인의 블록은 크게 블록헤더와 트랜잭션들로 구성되어 있다. 실제로 트랜잭션들을 저장할 때는 1차원 vector로 저장하며 각 블록 내에 트랜잭션들의 vector가 저장되어 있는 구조다.\nUTXO를 사용하기 위해서는 해당 UTXO의 scriptPubKey에 OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG 중 hash160에 자신의 주소가 포함되어 있어야 한다.\n또한 scriptPubKey 스크립트를 실행하여 마지막에 true가 반환될 수 있다면, 즉 자신이 서명 정보를 증명할 수 있어야 UTXO를 사용할 수 있다. 물론 사용하기 전에, 자신의 주소에 사용하려는 output value보다 더 많은 input value가 있어야 되는 것은 물론이다. \n결국 자신의 주소로 할당된 UTXO의 value가 사용할 value보다 커야하며 사용할 때는 scriptPubKey를 실행하고 보내려는 사람의 주소를 기반으로 scriptPubKey를 생성하고 거래를 네트워크 상에 배포하면 된다.\n29. 블록체인의 중요 요소는 해쉬함수와 머클 트리이다. 해쉬 함수를 사용하는 것의 의미(해쉬 함수의 특성)을 설명하고, 머클 트리, 머클 path 를 설명하라.\n> Answer:\n해시함수는 input에 매핑되는 고유한 output을 만들어내는 함수다. 머클 트리는 이 해시함수의 특성을 아주 잘 이용한 자료구조 중 하나로, 이진 트리에 해시 개념을 도입한 자료구조다.\nTranscation이 여러 개 있을 때, 이 트랜잭션들을 리프노드로 두고 두개씩 묶어서 해시하고 해시된 값들을 또 두개씩 묶어 해시하는 과정을 반복하면서 루트까지 거슬러 올라간다. 이렇게 해시의 해시들로 구성되어 결국 루트까지 갔을 때, 그 루트를 머클루트라 한다. 리프 노드에 해당하는 거래내역이 하나라도 변조된다면 머클 루트값이 변하게 되는 원리는 바로 이 때문이다.\n머클 path는 머클 트리의 장점이다. 특정 트랜잭션의 위변조 여부를 알고 싶을 때, 머클 트리내에 해당 트랜잭션과 관련된 해시만 따로 추출하게 되는데 이 때의 관련 해시들을 Merkle Branch라고 하며 이 Branch가 곧 path라고 할 수 있다.\n30. 2세대 블록체인이라 불리는 이더리움과 비트코인의 구조적인 차이를 설명하라.\n> Answer: (by HuristicWave)\n비트코인의 블록헤더는 이전 블록 헤더의 해시, 타임스탬프, 난이도, 넌스, 머클트리의 루트해시를 가지고 있지만, 이더리움의 블록헤더는 이전블록 헤더의 해시, 타임스탬프, 넌스, 난이도, 가스의 사용량, 상태 루트, 트랜잭션 루트, 리시트루트를 가지고 있다.\n31. 비트코인, 이더리움, 혹은 그 밖의 블록체인들의 현존하는 스케일링 솔루션을 제시하고 어떤 방식으로 구현하려는지 설명하라.\n32. PoW 에서 일어날 수 있는 공격 방식을 제시하라.\n> Answer:\n전체 Hash Power(연산량)의 51% 이상을 차지했을 때, 해당 해시파워를 가지고 있는 노드는 다음 블록을 생성할 수 있는 확률이 50%가 된다. 따라서 연산량을 압도적으로 높여서 독점하게 되면 사실상 블록을 검증하고 블록체인에 추가해나가는 작업을 임의의 노드가 통제할 수 있고, 여기서 공격이 발생할 수 있다.\n압도적인 해시량을 바탕으로 특정 시점부터 체인을 분기시킬 수도 있고, 자기 입맛대로 거래내역을 추가하는 공격도 할 수 있다. 체인 분기 공격이 사실상 가장 피해가 큰 공격유형이며, 네트워크 가치를 하락시킴으로써 코인 생태계 자체를 무너뜨릴 수 있는 공격이다.\n33. PoW 가 아닌 합의 알고리즘은 어떤 것들이 있는가? Casper FFG, DPoS, Tendermint, 혹은 그 밖의 알고리즘을 설명하라.\nAnswer:\n\n34. Whisper, Swarm, IPFS, Infura, Gnosis, Aragon, Metamask, Golem, 혹은 그 밖의 이더리움 생태계에 기여하는 프로젝트를 설명하라.\nAnswer:\n\n35. EA a 와 b 의 balance 가 각각 n_a, n_b 일 때, a 의 모든 잔액을 b 에게 보냈다. gas price 를 g_p 라고 한다면, b 의 밸런스는 n_b + α 이다. 이 때 α 는? \nAnswer:\nn_a - g_p; EA a가 자신의 모든 잔액 n_a를 보낼 때는 트랜잭션 실행을 위한 gas price g_p가 필연적으로 동반된다. 따라서 온전히 n_a는 보낼 수 없으며 gas price g_p를 차감한 잔액을 전송하게 된다.\n36. swarm ls 명령어를 실행하기 위해 필요한 값은 어떤것이 있는지 설명하시오\n37. 상호 독립적인 토큰이 서로 교환되는 Atomic Swap 방식에 대해 설명하고, Plasma Fast Withdrawl 절차에서의 Atomic Swap 방식을 설명하라.\n38. Casper FFG가 어떻게 이더리움 블록체인의 확장성 문제를 해결할 수 있는지 근거를 제시하라.\nAnswer:\n39. 이더리움 블록체인에 대해서 Oracle이 갖는 의미를 설명하고 Oracle Problem에 대해 설명하라.\n40. Ethash 기반의 이더리움 PoW 체인은 비트코인 PoW 체인보다 어떤 비교우위가 있는지 설명하고 그 한계를 제시하라.\nAnswer:\n이더리움의 PoW체인은 합의 엔진인 이대시(Ethash)에 구현되어 있다. 이대시의 경우 비트코인에 비해 가지는 장점은 ASIC 채굴기가 큰 영향을 발휘하지 못한다는 것이다. 비트코인에서는 연산량만 고려하면 되기 때문에, ASIC을 대량으로 가지고 있는 노드가 네트워크 생태계 자체를 독점할 수 있지만 이더리움에서는 기존의 PoW연산에 메모리 관련 연산을 추가했다.\n단순히 SHA256 연산만을 필요로했던 비트코인과는 달리 이더리움은 DAG를 통해 미리 알 수 없는, 할 수 없는 순차적 메모리 연산을 요구하여 ASIC제작을 어렵게 했다. 메모리를 읽고 쓰는 부분에서의 기술 발전은 아직까지 속도가 그리 빠르지 않기 때문에 충분히 효과가 있다.\n그러나 만약 메모리 관련 연산이 급격히 빨라지는 기술 발전이 이루어진다면, 이더리움의 PoW 또한 효력을 상실하게 될 것이다.\n41. 이더리움의 GHOST Protocol 방식과 비트코인의 블록 생성방식 간의 차이점을 설명하라.\nAnswer:\n비트코인의 경우 체인이 분기되면서 유효하지 않은 블록이 되어버린 stale 블록에 대해서 따로 보상을 해주지 않는다. 그러나 이더리움에서는 Stale블록이 된 경우에도 보상을 해주는데, 이때 보상 받는 블록을 uncle block이라 한다.\nuncle block을 생성한 사람에게도 보상이 주어지고, uncle block을 제보하는 행위에 대해서도 보상이 주어진다. 이러한 프로토콜을 GHOST Protocol이라 하며 이더리움의 경우 블록 생성시간이 비트코인에 비해 약 40배빠르기 때문에, 체인이 분기되는 상황이 자주 연출될 수 있기 때문에 이러한 프로토콜을 채택했다.\n비트코인의 경우 애초에 분기되는 상황이 그리 자주 발생하지 않기 때문에 보상에 대한 매커니즘을 특별히 고려하지 않았던 것이고, 이더리움의 경우 블록 생성시간이 빠르기 때문에 분기가 자주 발생하고 그로 인해 손해를 보는 채굴자들이 네트워크를 떠나지 않게끔 보상정책이 필요했던 것이다.\n42. Casepr는 51% 공격 문제를 어떻게 해결할 것인지에 대해서 PoW 체인의 경우와 비교하여 설명하라.\n43. Casper는 전통적인 PoS 알고리즘의 Nothing at Stake 문제를 어떻게 해결하려고 하는지 설명하라. (최소삭감조건을 명시하시오)\n44. Token Economy의 가치 확보 문제와 Token Velocity Problem을 연관지어 서술하세요.\n45. PoW에서 확보되지 않았던 경제적 완결성 개념이 무엇인지 설명하고, Casper는 이 문제를 어떻게 해결하려고 하는지 서술하세요.",
      "json_metadata": "{\"tags\":[\"onther\",\"ethereum\",\"blockchain\"],\"links\":[\"https://paritytech.io/security-alert-2/\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
    }
  ]
}
2018/06/12 02:48:00
voterlionindayard
authordlgusdn616
permlinkr-and-d-cheat-sheet
weight49 (0.49%)
Transaction InfoBlock #23245341/Trx 079d0ef556e51f61ec343000536d27a68d3061f1
View Raw JSON Data
{
  "trx_id": "079d0ef556e51f61ec343000536d27a68d3061f1",
  "block": 23245341,
  "trx_in_block": 4,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-12T02:48:00",
  "op": [
    "vote",
    {
      "voter": "lionindayard",
      "author": "dlgusdn616",
      "permlink": "r-and-d-cheat-sheet",
      "weight": 49
    }
  ]
}
2018/06/12 02:47:57
votermarketstack
authordlgusdn616
permlinkr-and-d-cheat-sheet
weight49 (0.49%)
Transaction InfoBlock #23245340/Trx a817a78b92584c6aea615f1de22a0d443f06cd35
View Raw JSON Data
{
  "trx_id": "a817a78b92584c6aea615f1de22a0d443f06cd35",
  "block": 23245340,
  "trx_in_block": 31,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-12T02:47:57",
  "op": [
    "vote",
    {
      "voter": "marketstack",
      "author": "dlgusdn616",
      "permlink": "r-and-d-cheat-sheet",
      "weight": 49
    }
  ]
}
dlgusdn616published a new post: r-and-d-cheat-sheet
2018/06/12 02:18:51
parent author
parent permlinkonther
authordlgusdn616
permlinkr-and-d-cheat-sheet
title이더리움 블록체인 R&D스타트업 온더 채용 Cheat Sheet
body## Onther 채용 시험지 Cheat Sheet (작성 중) ### 작성 계기: 이더리움을 공부하는 사람으로서 아래와 같은 질문들에 답을 하면서 그 동안 공부했던 내용을 정리하고, 몰랐던 내용이 있다면 연구해서 보충하고 싶다는 취지로 작성하게 됐다. 1. ETC를 ETH메인넷의 ERC20주소로 보내버렸다. 복구할 방법이 있는가? 단 ERC20주소를 만든 개인키는 잃어버리지 않았다. >Answer: 2. solidity의 keccak함수의 연산은 EVM의 스택머신에서 이뤄질까? 그렇다면 혹은 그렇지 않다면 이유는 무엇인가? 3. 0x60 옵코드는 어떤 명령인가? 4. EA가 CA한테 이더를 보냈다. CA의 balance와 storageRoot는 모두 바뀐다. 참일까 거짓일까? 그 이유는? 단 CA 코드에 msg.value를 사용하는 부분은 없다. 5. 옐로우페이퍼에 적힌 트랜잭션 value가 표현할 수 있는 값의 최대 범위는? 근거가 되는 수식 번호와 옐로우페이퍼 커밋 해시를 적어라. 6. EVM옵코드 중 JUMP와 JUMPDEST의 차이와 역할에 대해서 기술하라 7. 모든 거래내역이 공개되어 있음에도 불구하고, 해커가 비트코인을 훔쳐갔을 때 추적하기 어려운 이유는? 8. 마이닝 노드가 20개, 풀노드가 10개인 프라이빗 네트워크가 있다. tx 2개가 생성되어 블록에 포함되었을 때, 생성되는 EVM의 갯수와 그 이유는? 9. payable모디파이어에 대해서 설명하라. 그리고 payable모디파이어가 없는 ICO컨트랙트는 만들어 질 수 있을까? 있다면 그 이유는 무엇인가? 10. 전체 토큰의 전송을 멈출 수 있는 transfer pause 기능은 블록체인의 위변조불가능한 특성을 위배하는가? 그렇다면 혹은 그렇지 않다면 그 이유는? 11. 플라즈마 체인의 challenge과정에 대해서 서술하라 12. 플라즈마 체인의 합의 알고리즘과 exit 프로세스의 관계에 대해서 서술하라 13. truffle migrate, truffle compile, truffle test 각각의 명령어는 어떤 일을 하는가? 14. github에 solidity코드가 알록달록하게 보이기 위해서는(linter) 어떤 조치를 해야할까? 15. 이더리움 계정 생성간 뉴모닉 단어를 이용할 수 있다. 뉴모닉이 만들 수 있는 계정 갯수의 한도는 있는가? 그렇다면 혹은 그렇지 않다면 그 이유는? 16. 패러티 멀티시그 해킹(해킹(https://paritytech.io/security-alert-2/)의 구조와 원리를 설명하라. 17. 솔리디티 Proxy Pattern에 대해서 설명하라 18. call, delegate call, static call의 차이에 대해서 설명하라 19. solidity와 vyper의 차이점과 장단점에 대해서 설명하라 20. O(n)의 시간복잡도를 가진 알고리즘은 퍼블릭 이더리움에서 동작 가능할까? 가능하다면 혹은 가능하지 않다면 그 이유는? 21. solidity optimizer란 무엇인가? 22. ICO트릴레마에 대해서 설명하라 23. PoA 합의 알고리즘에서 validator를 변경할 수 있는가? 이유는 무엇인가? 24. 토큰의 분류 중 Work Token의 개념을 설명하고 Work token의 경우 토큰의 이상적인 형태는 무엇인가? 그 예(2가지 이상)는 무엇이 있을까? 25. puppeth를 이용해 여러개의 Bootnode를 갖고 있는 프라이빗 네트워크를 운영할 수 있는가? 이유는 무엇인가? 26. puppeth를 이용해 프라이빗 네트워크를 구축하기 위해 필요한 준비사항을 모두 적으시오 27. solidity에서 함수 인자로 전달된 파라미터 a를 함수 내부에서 소괄호로 감쌌다. eq) (a) 무슨 의미인가? 28. 비트코인의 블럭, TX 구조를 간략히 설명하고, UTXO 를 사용 / 검증하기 위한 과정을 설명하라 29. 블록체인의 중요 요소는 해쉬함수와 머클 트리이다. 해쉬 함수를 사용하는 것의 의미(해쉬 함수의 특성)을 설명하고, 머클 트리, 머클 path 를 설명하라. 30. 2세대 블록체인이라 불리는 이더리움과 비트코인의 구조적인 차이를 설명하라. 31. 비트코인, 이더리움, 혹은 그 밖의 블록체인들의 현존하는 스케일링 솔루션을 제시하고 어떤 방식으로 구현하려는지 설명하라. 32. PoW 에서 일어날 수 있는 공격 방식을 제시하라. 33. PoW 가 아닌 합의 알고리즘은 어떤 것들이 있는가? Casper FFG, DPoS, Tendermint, 혹은 그 밖의 알고리즘을 설명하라. 34. Whisper, Swarm, IPFS, Infura, Gnosis, Aragon, Metamask, Golem, 혹은 그 밖의 이더리움 생태계에 기여하는 프로젝트를 설명하라. 35. EA a 와 b 의 balance 가 각각 n_a, n_b 일 때, a 의 모든 잔액을 b 에게 보냈다. gas price 를 g_p 라고 한다면, b 의 밸런스는 n_b + α 이다. 이 때 α 는? 36. swarm ls 명령어를 실행하기 위해 필요한 값은 어떤것이 있는지 설명하시오 37. 상호 독립적인 토큰이 서로 교환되는 Atomic Swap 방식에 대해 설명하고, Plasma Fast Withdrawl 절차에서의 Atomic Swap 방식을 설명하라. 38. Casper FFG가 어떻게 이더리움 블록체인의 확장성 문제를 해결할 수 있는지 근거를 제시하라. 39. 이더리움 블록체인에 대해서 Oracle이 갖는 의미를 설명하고 Oracle Problem에 대해 설명하라. 40. Ethash 기반의 이더리움 PoW 체인은 비트코인 PoW 체인보다 어떤 비교우위가 있는지 설명하고 그 한계를 제시하라. 41. 이더리움의 GHOST Protocol 방식과 비트코인의 블록 생성방식 간의 차이점을 설명하라. 42. Casepr는 51% 공격 문제를 어떻게 해결할 것인지에 대해서 PoW 체인의 경우와 비교하여 설명하라. 43. Casper는 전통적인 PoS 알고리즘의 Nothing at Stake 문제를 어떻게 해결하려고 하는지 설명하라. (최소삭감조건을 명시하시오) 44. Token Economy의 가치 확보 문제와 Token Velocity Problem을 연관지어 서술하세요. 45. PoW에서 확보되지 않았던 경제적 완결성 개념이 무엇인지 설명하고, Casper는 이 문제를 어떻게 해결하려고 하는지 서술하세요.
json metadata{"tags":["onther","ethereum","blockchain"],"links":["https://paritytech.io/security-alert-2/"],"app":"steemit/0.1","format":"markdown"}
Transaction InfoBlock #23244758/Trx 7ab26510aae7090656ea6b0498f92c4cb2c60637
View Raw JSON Data
{
  "trx_id": "7ab26510aae7090656ea6b0498f92c4cb2c60637",
  "block": 23244758,
  "trx_in_block": 10,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-12T02:18:51",
  "op": [
    "comment",
    {
      "parent_author": "",
      "parent_permlink": "onther",
      "author": "dlgusdn616",
      "permlink": "r-and-d-cheat-sheet",
      "title": "이더리움 블록체인 R&D스타트업 온더 채용 Cheat Sheet",
      "body": "## Onther 채용 시험지 Cheat Sheet (작성 중)\n### 작성 계기: 이더리움을 공부하는 사람으로서 아래와 같은 질문들에 답을 하면서 그 동안 공부했던 내용을 정리하고, 몰랐던 내용이 있다면 연구해서 보충하고 싶다는 취지로 작성하게 됐다.\n\n1. ETC를 ETH메인넷의 ERC20주소로 보내버렸다. 복구할 방법이 있는가? 단 ERC20주소를 만든 개인키는 잃어버리지 않았다.\n>Answer: \n2. solidity의 keccak함수의 연산은 EVM의 스택머신에서 이뤄질까? 그렇다면 혹은 그렇지 않다면 이유는 무엇인가?\n3. 0x60 옵코드는 어떤 명령인가?\n4. EA가 CA한테 이더를 보냈다. CA의 balance와 storageRoot는 모두 바뀐다. 참일까 거짓일까? 그 이유는? 단 CA 코드에 msg.value를 사용하는 부분은 없다.\n5. 옐로우페이퍼에 적힌 트랜잭션 value가 표현할 수 있는 값의 최대 범위는? 근거가 되는 수식 번호와 옐로우페이퍼 커밋 해시를 적어라.\n6. EVM옵코드 중 JUMP와 JUMPDEST의 차이와 역할에 대해서 기술하라\n7. 모든 거래내역이 공개되어 있음에도 불구하고, 해커가 비트코인을 훔쳐갔을 때 추적하기 어려운 이유는?\n8. 마이닝 노드가 20개, 풀노드가 10개인 프라이빗 네트워크가 있다. tx 2개가 생성되어 블록에 포함되었을 때, 생성되는 EVM의 갯수와 그 이유는?\n9. payable모디파이어에 대해서 설명하라. 그리고 payable모디파이어가 없는 ICO컨트랙트는 만들어 질 수 있을까? 있다면 그 이유는 무엇인가?\n10. 전체 토큰의 전송을 멈출 수 있는 transfer pause 기능은 블록체인의 위변조불가능한 특성을 위배하는가? 그렇다면 혹은 그렇지 않다면 그 이유는?\n11. 플라즈마 체인의 challenge과정에 대해서 서술하라\n12. 플라즈마 체인의 합의 알고리즘과 exit 프로세스의 관계에 대해서 서술하라\n13. truffle migrate, truffle compile, truffle test 각각의 명령어는 어떤 일을 하는가?\n14. github에 solidity코드가 알록달록하게 보이기 위해서는(linter) 어떤 조치를 해야할까?\n15. 이더리움 계정 생성간 뉴모닉 단어를 이용할 수 있다. 뉴모닉이 만들 수 있는 계정 갯수의 한도는 있는가? 그렇다면 혹은 그렇지 않다면 그 이유는?\n16. 패러티 멀티시그 해킹(해킹(https://paritytech.io/security-alert-2/)의 구조와 원리를 설명하라.\n17. 솔리디티 Proxy Pattern에 대해서 설명하라\n18. call, delegate call, static call의 차이에 대해서 설명하라\n19. solidity와 vyper의 차이점과 장단점에 대해서 설명하라\n20. O(n)의 시간복잡도를 가진 알고리즘은 퍼블릭 이더리움에서 동작 가능할까? 가능하다면 혹은 가능하지 않다면 그 이유는?\n21. solidity optimizer란 무엇인가?\n22. ICO트릴레마에 대해서 설명하라\n23. PoA 합의 알고리즘에서 validator를 변경할 수 있는가? 이유는 무엇인가?\n24. 토큰의 분류 중 Work Token의 개념을 설명하고 Work token의 경우 토큰의 이상적인 형태는 무엇인가? 그 예(2가지 이상)는 무엇이 있을까?\n25. puppeth를 이용해 여러개의 Bootnode를 갖고 있는 프라이빗 네트워크를 운영할 수 있는가? 이유는 무엇인가?\n26. puppeth를 이용해 프라이빗 네트워크를 구축하기 위해 필요한 준비사항을 모두 적으시오\n27. solidity에서 함수 인자로 전달된 파라미터 a를 함수 내부에서 소괄호로 감쌌다. eq) (a) 무슨 의미인가?\n28. 비트코인의 블럭, TX 구조를 간략히 설명하고, UTXO 를 사용 / 검증하기 위한 과정을 설명하라\n29. 블록체인의 중요 요소는 해쉬함수와 머클 트리이다. 해쉬 함수를 사용하는 것의 의미(해쉬 함수의 특성)을 설명하고, 머클 트리, 머클 path 를 설명하라.\n30. 2세대 블록체인이라 불리는 이더리움과 비트코인의 구조적인 차이를 설명하라.\n31. 비트코인, 이더리움, 혹은 그 밖의 블록체인들의 현존하는 스케일링 솔루션을 제시하고 어떤 방식으로 구현하려는지 설명하라.\n32. PoW 에서 일어날 수 있는 공격 방식을 제시하라.\n33. PoW 가 아닌 합의 알고리즘은 어떤 것들이 있는가? Casper FFG, DPoS, Tendermint, 혹은 그 밖의 알고리즘을 설명하라.\n34. Whisper, Swarm, IPFS, Infura, Gnosis, Aragon, Metamask, Golem, 혹은 그 밖의 이더리움 생태계에 기여하는 프로젝트를 설명하라.\n35. EA a 와 b 의 balance 가 각각 n_a, n_b 일 때, a 의 모든 잔액을 b 에게 보냈다. gas price 를 g_p 라고 한다면, b 의 밸런스는 n_b + α 이다. 이 때 α 는?\n36. swarm ls 명령어를 실행하기 위해 필요한 값은 어떤것이 있는지 설명하시오\n37. 상호 독립적인 토큰이 서로 교환되는 Atomic Swap 방식에 대해 설명하고, Plasma Fast Withdrawl 절차에서의 Atomic Swap 방식을 설명하라.\n38. Casper FFG가 어떻게 이더리움 블록체인의 확장성 문제를 해결할 수 있는지 근거를 제시하라.\n39. 이더리움 블록체인에 대해서 Oracle이 갖는 의미를 설명하고 Oracle Problem에 대해 설명하라.\n40. Ethash 기반의 이더리움 PoW 체인은 비트코인 PoW 체인보다 어떤 비교우위가 있는지 설명하고 그 한계를 제시하라.\n41. 이더리움의 GHOST Protocol 방식과 비트코인의 블록 생성방식 간의 차이점을 설명하라.\n42. Casepr는 51% 공격 문제를 어떻게 해결할 것인지에 대해서 PoW 체인의 경우와 비교하여 설명하라.\n43. Casper는 전통적인 PoS 알고리즘의 Nothing at Stake 문제를 어떻게 해결하려고 하는지 설명하라. (최소삭감조건을 명시하시오)\n44. Token Economy의 가치 확보 문제와 Token Velocity Problem을 연관지어 서술하세요.\n45. PoW에서 확보되지 않았던 경제적 완결성 개념이 무엇인지 설명하고, Casper는 이 문제를 어떻게 해결하려고 하는지 서술하세요.",
      "json_metadata": "{\"tags\":[\"onther\",\"ethereum\",\"blockchain\"],\"links\":[\"https://paritytech.io/security-alert-2/\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
    }
  ]
}
2018/06/10 14:33:42
parent authordlgusdn616
parent permlinkbitcoin01-01
authorsteemitboard
permlinksteemitboard-notify-dlgusdn616-20180610t143342000z
title
bodyCongratulations @dlgusdn616! You have completed some achievement on Steemit and have been rewarded with new badge(s) : [![](https://steemitimages.com/70x70/http://steemitboard.com/notifications/firstvote.png)](http://steemitboard.com/@dlgusdn616) You made your First Vote <sub>_Click on the badge to view your Board of Honor._</sub> <sub>_If you no longer want to receive notifications, reply to this comment with the word_ `STOP`</sub> > Do you like [SteemitBoard's project](https://steemit.com/@steemitboard)? Then **[Vote for its witness](https://v2.steemconnect.com/sign/account-witness-vote?witness=steemitboard&approve=1)** and **get one more award**!
json metadata{"image":["https://steemitboard.com/img/notify.png"]}
Transaction InfoBlock #23202411/Trx 95908f97537a8aff734fd36c56ab053335a745b5
View Raw JSON Data
{
  "trx_id": "95908f97537a8aff734fd36c56ab053335a745b5",
  "block": 23202411,
  "trx_in_block": 15,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-10T14:33:42",
  "op": [
    "comment",
    {
      "parent_author": "dlgusdn616",
      "parent_permlink": "bitcoin01-01",
      "author": "steemitboard",
      "permlink": "steemitboard-notify-dlgusdn616-20180610t143342000z",
      "title": "",
      "body": "Congratulations @dlgusdn616! You have completed some achievement on Steemit and have been rewarded with new badge(s) :\n\n[![](https://steemitimages.com/70x70/http://steemitboard.com/notifications/firstvote.png)](http://steemitboard.com/@dlgusdn616) You made your First Vote\n\n<sub>_Click on the badge to view your Board of Honor._</sub>\n<sub>_If you no longer want to receive notifications, reply to this comment with the word_ `STOP`</sub>\n\n\n\n> Do you like [SteemitBoard's project](https://steemit.com/@steemitboard)? Then **[Vote for its witness](https://v2.steemconnect.com/sign/account-witness-vote?witness=steemitboard&approve=1)** and **get one more award**!",
      "json_metadata": "{\"image\":[\"https://steemitboard.com/img/notify.png\"]}"
    }
  ]
}
2018/06/10 10:19:33
parent authorendiyou
parent permlinkre-dlgusdn616-bitcoin01-01-20180610t014638219z
authordlgusdn616
permlinkre-endiyou-re-dlgusdn616-bitcoin01-01-20180610t101933288z
title
body도움이 되었다니 다행입니다 :)
json metadata{"tags":["bitcoin"],"app":"steemit/0.1"}
Transaction InfoBlock #23197337/Trx 6cb91eb672e8378be5b8fd59c4695efa7342f24e
View Raw JSON Data
{
  "trx_id": "6cb91eb672e8378be5b8fd59c4695efa7342f24e",
  "block": 23197337,
  "trx_in_block": 24,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-10T10:19:33",
  "op": [
    "comment",
    {
      "parent_author": "endiyou",
      "parent_permlink": "re-dlgusdn616-bitcoin01-01-20180610t014638219z",
      "author": "dlgusdn616",
      "permlink": "re-endiyou-re-dlgusdn616-bitcoin01-01-20180610t101933288z",
      "title": "",
      "body": "도움이 되었다니 다행입니다 :)",
      "json_metadata": "{\"tags\":[\"bitcoin\"],\"app\":\"steemit/0.1\"}"
    }
  ]
}
2018/06/10 10:19:18
voterdlgusdn616
authorendiyou
permlinkre-dlgusdn616-bitcoin01-01-20180610t014638219z
weight10000 (100.00%)
Transaction InfoBlock #23197332/Trx 3b4ff86a227f92d4b9152cc50093c22a9c323574
View Raw JSON Data
{
  "trx_id": "3b4ff86a227f92d4b9152cc50093c22a9c323574",
  "block": 23197332,
  "trx_in_block": 23,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-10T10:19:18",
  "op": [
    "vote",
    {
      "voter": "dlgusdn616",
      "author": "endiyou",
      "permlink": "re-dlgusdn616-bitcoin01-01-20180610t014638219z",
      "weight": 10000
    }
  ]
}
2018/06/10 01:46:39
parent authordlgusdn616
parent permlinkbitcoin01-01
authorendiyou
permlinkre-dlgusdn616-bitcoin01-01-20180610t014638219z
title
body좋은 글 감사합니다.
json metadata{"tags":["bitcoin"],"app":"steemit/0.1"}
Transaction InfoBlock #23187095/Trx dd2213ffcdccbc2688b2953882b93a70910dedc2
View Raw JSON Data
{
  "trx_id": "dd2213ffcdccbc2688b2953882b93a70910dedc2",
  "block": 23187095,
  "trx_in_block": 12,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-10T01:46:39",
  "op": [
    "comment",
    {
      "parent_author": "dlgusdn616",
      "parent_permlink": "bitcoin01-01",
      "author": "endiyou",
      "permlink": "re-dlgusdn616-bitcoin01-01-20180610t014638219z",
      "title": "",
      "body": "좋은 글 감사합니다.",
      "json_metadata": "{\"tags\":[\"bitcoin\"],\"app\":\"steemit/0.1\"}"
    }
  ]
}
endiyouupvoted (100.00%) @dlgusdn616 / bitcoin01-01
2018/06/10 01:45:48
voterendiyou
authordlgusdn616
permlinkbitcoin01-01
weight10000 (100.00%)
Transaction InfoBlock #23187078/Trx 36d3a2eeaf519e44e11e439b10f646bc69d26e6d
View Raw JSON Data
{
  "trx_id": "36d3a2eeaf519e44e11e439b10f646bc69d26e6d",
  "block": 23187078,
  "trx_in_block": 29,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-10T01:45:48",
  "op": [
    "vote",
    {
      "voter": "endiyou",
      "author": "dlgusdn616",
      "permlink": "bitcoin01-01",
      "weight": 10000
    }
  ]
}
bonseungupvoted (100.00%) @dlgusdn616 / bitcoin01-01
2018/06/09 11:38:09
voterbonseung
authordlgusdn616
permlinkbitcoin01-01
weight10000 (100.00%)
Transaction InfoBlock #23170127/Trx e0dbe557e2907019373b401acc695c6c063c35a4
View Raw JSON Data
{
  "trx_id": "e0dbe557e2907019373b401acc695c6c063c35a4",
  "block": 23170127,
  "trx_in_block": 27,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-09T11:38:09",
  "op": [
    "vote",
    {
      "voter": "bonseung",
      "author": "dlgusdn616",
      "permlink": "bitcoin01-01",
      "weight": 10000
    }
  ]
}
2018/06/09 10:49:36
voterfoodmockgame
authordlgusdn616
permlinkethereum01-01
weight10000 (100.00%)
Transaction InfoBlock #23169156/Trx 8fc51fe095a5f19e81be7ec0e966795b6b90756b
View Raw JSON Data
{
  "trx_id": "8fc51fe095a5f19e81be7ec0e966795b6b90756b",
  "block": 23169156,
  "trx_in_block": 29,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-09T10:49:36",
  "op": [
    "vote",
    {
      "voter": "foodmockgame",
      "author": "dlgusdn616",
      "permlink": "ethereum01-01",
      "weight": 10000
    }
  ]
}
coalashupvoted (100.00%) @dlgusdn616 / bitcoin01-01
2018/06/09 07:13:03
votercoalash
authordlgusdn616
permlinkbitcoin01-01
weight10000 (100.00%)
Transaction InfoBlock #23164827/Trx d9ff377cf7afcd5a81a1bc60ffb221a11b204caf
View Raw JSON Data
{
  "trx_id": "d9ff377cf7afcd5a81a1bc60ffb221a11b204caf",
  "block": 23164827,
  "trx_in_block": 29,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-09T07:13:03",
  "op": [
    "vote",
    {
      "voter": "coalash",
      "author": "dlgusdn616",
      "permlink": "bitcoin01-01",
      "weight": 10000
    }
  ]
}
2018/06/09 06:39:06
votersignalandnoise
authordlgusdn616
permlinkbitcoin01-01
weight10000 (100.00%)
Transaction InfoBlock #23164148/Trx fb8d3c14e4f31682076767084052f08e4ca66a77
View Raw JSON Data
{
  "trx_id": "fb8d3c14e4f31682076767084052f08e4ca66a77",
  "block": 23164148,
  "trx_in_block": 2,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-09T06:39:06",
  "op": [
    "vote",
    {
      "voter": "signalandnoise",
      "author": "dlgusdn616",
      "permlink": "bitcoin01-01",
      "weight": 10000
    }
  ]
}
modoleeupvoted (100.00%) @dlgusdn616 / ethereum01-01
2018/06/09 04:15:48
votermodolee
authordlgusdn616
permlinkethereum01-01
weight10000 (100.00%)
Transaction InfoBlock #23161282/Trx e50ba609c49cda91b056246e4bf49fc29d5570d1
View Raw JSON Data
{
  "trx_id": "e50ba609c49cda91b056246e4bf49fc29d5570d1",
  "block": 23161282,
  "trx_in_block": 23,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-09T04:15:48",
  "op": [
    "vote",
    {
      "voter": "modolee",
      "author": "dlgusdn616",
      "permlink": "ethereum01-01",
      "weight": 10000
    }
  ]
}
modoleeupvoted (100.00%) @dlgusdn616 / bitcoin01-01
2018/06/09 04:14:33
votermodolee
authordlgusdn616
permlinkbitcoin01-01
weight10000 (100.00%)
Transaction InfoBlock #23161257/Trx 391db30c2d7cd3f4f556a09d19166c996102d048
View Raw JSON Data
{
  "trx_id": "391db30c2d7cd3f4f556a09d19166c996102d048",
  "block": 23161257,
  "trx_in_block": 15,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-09T04:14:33",
  "op": [
    "vote",
    {
      "voter": "modolee",
      "author": "dlgusdn616",
      "permlink": "bitcoin01-01",
      "weight": 10000
    }
  ]
}
2018/06/09 03:52:45
voterhanmomhanda
authordlgusdn616
permlinkbitcoin01-01
weight10000 (100.00%)
Transaction InfoBlock #23160822/Trx d7ef24ad548951f36435d155c85a780bc2bb9a89
View Raw JSON Data
{
  "trx_id": "d7ef24ad548951f36435d155c85a780bc2bb9a89",
  "block": 23160822,
  "trx_in_block": 40,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-09T03:52:45",
  "op": [
    "vote",
    {
      "voter": "hanmomhanda",
      "author": "dlgusdn616",
      "permlink": "bitcoin01-01",
      "weight": 10000
    }
  ]
}
dlgusdn616published a new post: bitcoin01-01
2018/06/07 08:29:27
parent author
parent permlinkbitcoin
authordlgusdn616
permlinkbitcoin01-01
titleBitcoin01-01: 비트코인 코어 소스코드로 살펴보는 머클 트리
body@@ -2355,45 +2355,8 @@ - foreach(const CTransaction& tx, vtx) // @@ -2392,16 +2392,61 @@ Tree %EC%83%9D%EC%84%B1%0A + foreach(const CTransaction& tx, vtx)%0A @@ -2668,36 +2668,8 @@ - int i2 = min(i+1, nSize-1); // @@ -2714,24 +2714,121 @@ %EC%8B%A0%EA%B3%BC %ED%95%B4%EC%8B%9C%ED%95%98%EA%B2%8C %EB%90%9C%EB%8B%A4.%0A + int i2 = min(i+1, nSize-1); %0A // %ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98%EC%9D%98 %ED%95%B4%EC%8B%9C%EB%A5%BC 2%EA%B0%9C%EC%94%A9 %EB%AC%B6%EC%96%B4%EC%84%9C %EB%8B%A4%EC%8B%9C %EB%A8%B8%ED%81%B4%ED%8A%B8%EB%A6%AC%EC%97%90 %EC%82%BD%EC%9E%85%ED%95%9C%EB%8B%A4.%0A @@ -3005,44 +3005,8 @@ ))); - // %ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98%EC%9D%98 %ED%95%B4%EC%8B%9C%EB%A5%BC 2%EA%B0%9C%EC%94%A9 %EB%AC%B6%EC%96%B4%EC%84%9C %EB%8B%A4%EC%8B%9C %EB%A8%B8%ED%81%B4%ED%8A%B8%EB%A6%AC%EC%97%90 %EC%82%BD%EC%9E%85%ED%95%9C%EB%8B%A4. %0A @@ -5652,12 +5652,194 @@ %EC%9E%88%EB%8A%94 %EA%B1%B8 %EC%95%8C %EC%88%98 %EC%9E%88%EB%8B%A4. +%0A- %EC%BD%94%EB%93%9C %EC%A4%91%EA%B0%84%EC%A4%91%EA%B0%84 %5C%EA%B0%80 %EB%B6%99%EC%9D%80 %ED%8C%8C%ED%8A%B8%EA%B0%80 %EC%9E%88%EC%9D%84 %EC%88%98 %EC%9E%88%EB%8A%94%EB%8D%B0, %EC%9D%B4%EB%8A%94 %EC%8A%A4%ED%8B%B0%EB%B0%8B %EB%B8%94%EB%A1%9C%EA%B7%B8%EC%97%90 %EC%BD%94%EB%93%9C%EB%A5%BC %EC%82%BD%EC%9E%85%ED%95%A0 %EB%95%8C %EA%BA%BD%EC%87%84 '%3C', '%3E'%EB%A5%BC %EC%82%AC%EC%9A%A9%ED%96%88%EC%9D%84 %EB%95%8C %EC%97%85%EB%A1%9C%EB%93%9C%EA%B0%80 %EB%90%98%EC%A7%80 %EC%95%8A%EB%8A%94 %EB%AC%B8%EC%A0%9C%EC%A0%90%EB%95%8C%EB%AC%B8%EC%97%90 %EC%B7%A8%ED%95%9C %EC%A1%B0%EC%B9%98%EC%9E%85%EB%8B%88%EB%8B%A4. %EA%B7%B8%EB%9F%AC%EB%8B%88 %EC%9D%BD%EC%9D%84 %EB%95%8C %ED%97%B7%EA%B0%88%EB%A0%A4%ED%95%98%EC%A7%80 %EC%95%8A%EA%B2%8C %EC%A3%BC%EC%9D%98 %EB%B0%94%EB%9E%8D%EB%8B%88%EB%8B%A4. %ED%98%B9%EC%8B%9C %EA%BA%BD%EC%87%84%EB%A5%BC %EA%B2%BD%EA%B3%A0 %EC%97%86%EC%9D%B4 %EC%82%AC%EC%9A%A9%ED%95%A0 %EC%88%98 %EC%9E%88%EB%8A%94 %EB%B0%A9%EB%B2%95%EC%9D%84 %EC%95%84%EC%8B%9C%EB%8A%94 %EB%B6%84%EA%BB%98%EC%84%9C%EB%8A%94 %EC%A7%80%EC%8B%9D %EB%82%98%EB%88%A0%EC%A3%BC%EC%8B%9C%EB%A9%B4 %EA%B0%90%EC%82%AC%ED%95%98%EA%B2%A0%EC%8A%B5%EB%8B%88%EB%8B%A4 :)
json metadata{"tags":["bitcoin","merkletree","merkleroot","bitcoincore"],"image":["https://cdn.steemitimages.com/DQmQrntFrZM7Kh6n2bN5kKxBt6ooRuJEQ8nevAAH7nSzwgw/image.png","https://cdn.steemitimages.com/DQmUegLWtij5qFeZLFwutnKgZZ4MHfBRzvAmNTV9xEFfq6V/image.png","https://cdn.steemitimages.com/DQmWwCKzgSEygPnpFr7G6daf3dMdDkKiZ36fboqEE4bbBfW/image.png"],"app":"steemit/0.1","format":"markdown"}
Transaction InfoBlock #23108778/Trx cba4a41bfd2ea18aa67823b5969e51421a4d1c0b
View Raw JSON Data
{
  "trx_id": "cba4a41bfd2ea18aa67823b5969e51421a4d1c0b",
  "block": 23108778,
  "trx_in_block": 12,
  "op_in_trx": 0,
  "virtual_op": 0,
  "timestamp": "2018-06-07T08:29:27",
  "op": [
    "comment",
    {
      "parent_author": "",
      "parent_permlink": "bitcoin",
      "author": "dlgusdn616",
      "permlink": "bitcoin01-01",
      "title": "Bitcoin01-01: 비트코인 코어 소스코드로 살펴보는 머클 트리",
      "body": "@@ -2355,45 +2355,8 @@\n     \n- foreach(const CTransaction& tx, vtx)\n  // \n@@ -2392,16 +2392,61 @@\n Tree %EC%83%9D%EC%84%B1%0A\n+        foreach(const CTransaction& tx, vtx)%0A\n         \n@@ -2668,36 +2668,8 @@\n     \n- int i2 = min(i+1, nSize-1);\n  // \n@@ -2714,24 +2714,121 @@\n %EC%8B%A0%EA%B3%BC %ED%95%B4%EC%8B%9C%ED%95%98%EA%B2%8C %EB%90%9C%EB%8B%A4.%0A\n+                int i2 = min(i+1, nSize-1); %0A                // %ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98%EC%9D%98 %ED%95%B4%EC%8B%9C%EB%A5%BC 2%EA%B0%9C%EC%94%A9 %EB%AC%B6%EC%96%B4%EC%84%9C %EB%8B%A4%EC%8B%9C %EB%A8%B8%ED%81%B4%ED%8A%B8%EB%A6%AC%EC%97%90 %EC%82%BD%EC%9E%85%ED%95%9C%EB%8B%A4.%0A\n             \n@@ -3005,44 +3005,8 @@\n )));\n- // %ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98%EC%9D%98 %ED%95%B4%EC%8B%9C%EB%A5%BC 2%EA%B0%9C%EC%94%A9 %EB%AC%B6%EC%96%B4%EC%84%9C %EB%8B%A4%EC%8B%9C %EB%A8%B8%ED%81%B4%ED%8A%B8%EB%A6%AC%EC%97%90 %EC%82%BD%EC%9E%85%ED%95%9C%EB%8B%A4.\n %0A   \n@@ -5652,12 +5652,194 @@\n %EC%9E%88%EB%8A%94 %EA%B1%B8 %EC%95%8C %EC%88%98 %EC%9E%88%EB%8B%A4.\n+%0A- %EC%BD%94%EB%93%9C %EC%A4%91%EA%B0%84%EC%A4%91%EA%B0%84 %5C%EA%B0%80 %EB%B6%99%EC%9D%80 %ED%8C%8C%ED%8A%B8%EA%B0%80 %EC%9E%88%EC%9D%84 %EC%88%98 %EC%9E%88%EB%8A%94%EB%8D%B0, %EC%9D%B4%EB%8A%94 %EC%8A%A4%ED%8B%B0%EB%B0%8B %EB%B8%94%EB%A1%9C%EA%B7%B8%EC%97%90 %EC%BD%94%EB%93%9C%EB%A5%BC %EC%82%BD%EC%9E%85%ED%95%A0 %EB%95%8C %EA%BA%BD%EC%87%84 '%3C', '%3E'%EB%A5%BC %EC%82%AC%EC%9A%A9%ED%96%88%EC%9D%84 %EB%95%8C %EC%97%85%EB%A1%9C%EB%93%9C%EA%B0%80 %EB%90%98%EC%A7%80 %EC%95%8A%EB%8A%94 %EB%AC%B8%EC%A0%9C%EC%A0%90%EB%95%8C%EB%AC%B8%EC%97%90 %EC%B7%A8%ED%95%9C %EC%A1%B0%EC%B9%98%EC%9E%85%EB%8B%88%EB%8B%A4. %EA%B7%B8%EB%9F%AC%EB%8B%88 %EC%9D%BD%EC%9D%84 %EB%95%8C %ED%97%B7%EA%B0%88%EB%A0%A4%ED%95%98%EC%A7%80 %EC%95%8A%EA%B2%8C %EC%A3%BC%EC%9D%98 %EB%B0%94%EB%9E%8D%EB%8B%88%EB%8B%A4. %ED%98%B9%EC%8B%9C %EA%BA%BD%EC%87%84%EB%A5%BC %EA%B2%BD%EA%B3%A0 %EC%97%86%EC%9D%B4 %EC%82%AC%EC%9A%A9%ED%95%A0 %EC%88%98 %EC%9E%88%EB%8A%94 %EB%B0%A9%EB%B2%95%EC%9D%84 %EC%95%84%EC%8B%9C%EB%8A%94 %EB%B6%84%EA%BB%98%EC%84%9C%EB%8A%94 %EC%A7%80%EC%8B%9D %EB%82%98%EB%88%A0%EC%A3%BC%EC%8B%9C%EB%A9%B4 %EA%B0%90%EC%82%AC%ED%95%98%EA%B2%A0%EC%8A%B5%EB%8B%88%EB%8B%A4 :)\n",
      "json_metadata": "{\"tags\":[\"bitcoin\",\"merkletree\",\"merkleroot\",\"bitcoincore\"],\"image\":[\"https://cdn.steemitimages.com/DQmQrntFrZM7Kh6n2bN5kKxBt6ooRuJEQ8nevAAH7nSzwgw/image.png\",\"https://cdn.steemitimages.com/DQmUegLWtij5qFeZLFwutnKgZZ4MHfBRzvAmNTV9xEFfq6V/image.png\",\"https://cdn.steemitimages.com/DQmWwCKzgSEygPnpFr7G6daf3dMdDkKiZ36fboqEE4bbBfW/image.png\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"
    }
  ]
}

Account Metadata

POSTING JSON METADATA
profile{"name":"waca","profile_image":"https://cdn.steemitimages.com/DQmZvgrAx9hpBLnDPayrgV3692nSzwVgStwxWjoGp5btDva/%E1%84%8B%E1%85%B5%E1%84%92%E1%85%A7%E1%86%AB%E1%84%8B%E1%85%AE%E1%84%82%E1%85%B5%E1%86%B7.jpg","location":"한국"}
JSON METADATA
profile{"name":"waca","profile_image":"https://cdn.steemitimages.com/DQmZvgrAx9hpBLnDPayrgV3692nSzwVgStwxWjoGp5btDva/%E1%84%8B%E1%85%B5%E1%84%92%E1%85%A7%E1%86%AB%E1%84%8B%E1%85%AE%E1%84%82%E1%85%B5%E1%86%B7.jpg","location":"한국"}
{
  "posting_json_metadata": {
    "profile": {
      "name": "waca",
      "profile_image": "https://cdn.steemitimages.com/DQmZvgrAx9hpBLnDPayrgV3692nSzwVgStwxWjoGp5btDva/%E1%84%8B%E1%85%B5%E1%84%92%E1%85%A7%E1%86%AB%E1%84%8B%E1%85%AE%E1%84%82%E1%85%B5%E1%86%B7.jpg",
      "location": "한국"
    }
  },
  "json_metadata": {
    "profile": {
      "name": "waca",
      "profile_image": "https://cdn.steemitimages.com/DQmZvgrAx9hpBLnDPayrgV3692nSzwVgStwxWjoGp5btDva/%E1%84%8B%E1%85%B5%E1%84%92%E1%85%A7%E1%86%AB%E1%84%8B%E1%85%AE%E1%84%82%E1%85%B5%E1%86%B7.jpg",
      "location": "한국"
    }
  }
}

Auth Keys

Owner
Single Signature
Public Keys
STM6jHpFiRziMjRgADbN7cGv8So31uHzPG1BsqRmUpnRP27BWBYWD1/1
Active
Single Signature
Public Keys
STM742zB8LV8i4gL2LW13R1sfWB1Zhee6qqrLBQPthPuUoNyxWRUx1/1
Posting
Single Signature
Public Keys
STM7y1D1gJ3xyn4hrUA6mP16yqCKSuWzAZsvM3xgYg1YnBM2VYzHA1/1
Memo
STM5XSA9F2q9wZMSAEV8mJpS5Le74o8WzE4ozhDYCcy7D7MVyLQtS
{
  "owner": {
    "weight_threshold": 1,
    "account_auths": [],
    "key_auths": [
      [
        "STM6jHpFiRziMjRgADbN7cGv8So31uHzPG1BsqRmUpnRP27BWBYWD",
        1
      ]
    ]
  },
  "active": {
    "weight_threshold": 1,
    "account_auths": [],
    "key_auths": [
      [
        "STM742zB8LV8i4gL2LW13R1sfWB1Zhee6qqrLBQPthPuUoNyxWRUx",
        1
      ]
    ]
  },
  "posting": {
    "weight_threshold": 1,
    "account_auths": [],
    "key_auths": [
      [
        "STM7y1D1gJ3xyn4hrUA6mP16yqCKSuWzAZsvM3xgYg1YnBM2VYzHA",
        1
      ]
    ]
  },
  "memo": "STM5XSA9F2q9wZMSAEV8mJpS5Le74o8WzE4ozhDYCcy7D7MVyLQtS"
}

Witness Votes

0 / 30
No active witness votes.
[]