- Published on
Run a Node, API and CLI
- Authors
- Name
- 이민기
- Github
- @mingi3442
Intro
오늘은 Run a Node, API and CLI파트에 대해서 정리해 왔습니다.
해당 게시글은 CLI를 이용한 API Routing을 제외한 Node에 대해 작성했습니다.
바로 시작하겠습니다~
Compile Simapp
Cosmos SDK 리포지토리에는 simapp
이라는 폴더가 있습니다.
이 폴더에서 Cosmos SDK의 시뮬레이션 버전을 실행하는 코드를 찾을 수 있으며 체인과 실제로 상호 작용하지 않고도 명령을 테스트할 수 있습니다.
바이너리는 simd라고 하며 이를 사용하여 노드와 상호 작용합니다.
먼저 폴더를 만들고 코스모스 폴더로 변경한 다음 해당 폴더에 cosmos-sdk 리포지토리를 클론합니다.
mkdir cosmos
cd cosmos
git clone https://github.com/cosmos/cosmos-sdk
cd cosmos-sdk
git checkout v0.45.4
🚨 해당 게시글은 v0.45.4버젼을 기준으로 진행되고 있습니다. 버젼을 확인 후 코스모스 SDK를 빌드합니다.
# local
make build
# docker
docker build . -t simd:v0.45.4
💡 Docker를 사용하는 경우 simd를 포함하는 새 Docker 이미지를 생성해야합니다.
성공적으로 컴파일 되었는지 확인
# local
./build/simd version
# dokcer
docker run --rm -it simd:v0.45.4 simd version
# 입력 후 "0.45.4"가 출력되어야 함.
Initialize Simapp
simapp을 실행 시키기 전, 다음과 같은 명령어로 초기화를 진행합니다.
rm -rf ./private/.simapp
제네시스 블록과 초기 체인 상태를 생성합니다.
# local
$ ./build/simd init demo \
--home ./private/.simapp \
--chain-id learning-chain-1
# docker
$ docker run --rm -it \
-v $(pwd)/private:/root \
simd:v0.45.4 \
simd init demo \
--chain-id learning-chain-1
# 해당 명령어 입력 후
# {"app_message":{"auth":{"accounts":[],"params":{"max_memo_characters":"256","sig_verify_cost_ed25519":"590","sig_verify_cost_secp256k1":"1000","tx_sig_limit":"7","tx_size_cost_per_byte":"10"}},"authz":{"authorization":[]},"bank":{"balances":[],"denom_metadata":[],"params":{"default_send_enabled":true,"send_enabled":[]},"supply":[]},"capability":{"index":"1","owners":[]},"crisis":{"constant_fee":{"amount":"1000","denom":"stake"}},"distribution":{"delegator_starting_infos":[],"delegator_withdraw_infos":[],"fee_pool":{"community_pool":[]},"outstanding_rewards":[],"params":{"base_proposer_reward":"0.010000000000000000","bonus_proposer_reward":"0.040000000000000000","community_tax":"0.020000000000000000","withdraw_addr_enabled":true},"previous_proposer":"","validator_accumulated_commissions":[],"validator_current_rewards":[],"validator_historical_rewards":[],"validator_slash_events":[]},"evidence":{"evidence":[]},"feegrant":{"allowances":[]},"genutil":{"gen_txs":[]},"gov":{"deposit_params":{"max_deposit_period":"172800s","min_deposit":[{"amount":"10000000","denom":"stake"}]},"deposits":[],"proposals":[],"starting_proposal_id":"1","tally_params":{"quorum":"0.334000000000000000","threshold":"0.500000000000000000","veto_threshold":"0.334000000000000000"},"votes":[],"voting_params":{"voting_period":"172800s"}},"mint":{"minter":{"annual_provisions":"0.000000000000000000","inflation":"0.130000000000000000"},"params":{"blocks_per_year":"6311520","goal_bonded":"0.670000000000000000","inflation_max":"0.200000000000000000","inflation_min":"0.070000000000000000","inflation_rate_change":"0.130000000000000000","mint_denom":"stake"}},"params":null,"slashing":{"missed_blocks":[],"params":{"downtime_jail_duration":"600s","min_signed_per_window":"0.500000000000000000","signed_blocks_window":"100","slash_fraction_double_sign":"0.050000000000000000","slash_fraction_downtime":"0.010000000000000000"},"signing_infos":[]},"staking":{"delegations":[],"exported":false,"last_total_power":"0","last_validator_powers":[],"params":{"bond_denom":"stake","historical_entries":10000,"max_entries":7,"max_validators":100,"unbonding_time":"1814400s"},"redelegations":[],"unbonding_delegations":[],"validators":[]},"upgrade":{},"vesting":{}},"chain_id":"learning-chain-1","gentxs_dir":"","moniker":"demo","node_id":"4f9021a015e696912f452532d53ac849d71cb750"}
# 출력이 되면 완료된 것 입니다.
✅ 해당 게시글은 튜토리얼 내용대로 learning-chain-1이라는 ID를 설정합니다.
// 💡 초기화 된 Simapp의 JSON 형식
{
"app_message": {
"auth": {
"accounts": [],
"params": {
"max_memo_characters": "256",
"sig_verify_cost_ed25519": "590",
"sig_verify_cost_secp256k1": "1000",
"tx_sig_limit": "7",
"tx_size_cost_per_byte": "10"
}
},
"authz": {
"authorization": []
},
"bank": {
"balances": [],
"denom_metadata": [],
"params": {
"default_send_enabled": true,
"send_enabled": []
},
"supply": []
},
"capability": {
"index": "1",
"owners": []
},
"crisis": {
"constant_fee": {
"amount": "1000",
"denom": "stake"
}
},
"distribution": {
"delegator_starting_infos": [],
"delegator_withdraw_infos": [],
"fee_pool": {
"community_pool": []
},
"outstanding_rewards": [],
"params": {
"base_proposer_reward": "0.010000000000000000",
"bonus_proposer_reward": "0.040000000000000000",
"community_tax": "0.020000000000000000",
"withdraw_addr_enabled": true
},
"previous_proposer": "",
"validator_accumulated_commissions": [],
"validator_current_rewards": [],
"validator_historical_rewards": [],
"validator_slash_events": []
},
"evidence": {
"evidence": []
},
"feegrant": {
"allowances": []
},
"genutil": {
"gen_txs": []
},
"gov": {
"deposit_params": {
"max_deposit_period": "172800s",
"min_deposit": [
{
"amount": "10000000",
"denom": "stake"
}
]
},
"deposits": [],
"proposals": [],
"starting_proposal_id": "1",
"tally_params": {
"quorum": "0.334000000000000000",
"threshold": "0.500000000000000000",
"veto_threshold": "0.334000000000000000"
},
"votes": [],
"voting_params": {
"voting_period": "172800s"
}
},
"mint": {
"minter": {
"annual_provisions": "0.000000000000000000",
"inflation": "0.130000000000000000"
},
"params": {
"blocks_per_year": "6311520",
"goal_bonded": "0.670000000000000000",
"inflation_max": "0.200000000000000000",
"inflation_min": "0.070000000000000000",
"inflation_rate_change": "0.130000000000000000",
"mint_denom": "stake"
}
},
"params": null,
"slashing": {
"missed_blocks": [],
"params": {
"downtime_jail_duration": "600s",
"min_signed_per_window": "0.500000000000000000",
"signed_blocks_window": "100",
"slash_fraction_double_sign": "0.050000000000000000",
"slash_fraction_downtime": "0.010000000000000000"
},
"signing_infos": []
},
"staking": {
"delegations": [],
"exported": false,
"last_total_power": "0",
"last_validator_powers": [],
"params": {
"bond_denom": "stake",
"historical_entries": 10000,
"max_entries": 7,
"max_validators": 100,
"unbonding_time": "1814400s"
},
"redelegations": [],
"unbonding_delegations": [],
"validators": []
},
"upgrade": {},
"vesting": {}
},
"chain_id": "learning-chain-1",
"gentxs_dir": "",
"moniker": "demo",
"node_id": "4f9021a015e696912f452532d53ac849d71cb750"
}
✅ 체인에 하드포크를 도입할 때를 고려하여 Chain ID 마지막에 -1 과 같은 숫자를 추가하는게 좋다고 합니다.
다음 명령어를 사용하여 초기 구성을 검사할 수 있습니다.
cat ./private/.simapp/config/genesis.json
Prepare Account
키를 검사할 수도 있으며, 이들은 기본적으로 운영 체제 또는 테스트의 백엔드 키링 중 하나에 보관됩니다.
# local
./build/simd keys list \
--home ./private/.simapp \
--keyring-backend test
# docker
docker run --rm -it \
-v $(pwd)/private:/root \
simd:v0.45.4 \
simd keys list \
--keyring-backend test
# 현재는 키를 생성하지 않았으므로, 빈 배열[]이 출력되는게 정상입니다.
✅ 해당 게시글은 튜토리얼 내용대로 일관성을 보장하기 위해 테스트 백엔드를 사용하고 ./private/.simapp
에 저장합니다.
다음은 키를 생성하는 작업입니다.
# local
$ ./build/simd keys add alice \
--home ./private/.simapp \
--keyring-backend test
# docker
$ docker run --rm -it \
-v $(pwd)/private:/root \
simd:v0.45.4 \
simd keys add alice \
--keyring-backend test
💡 헤당 키는 테스트용이므로 암호를 묻지 않고 ./private/.simapp/keyring-test
에 그대로 저장합니다.
# 출력 예시
- name: alice
type: local
address: cosmos1c6z8yjtfeuz2ehuva864nc2c67df2mmfw5v63r
pubkey: '{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AsCNcoWDXlTfDejDQo8az1NRUEPhDtgYz90H71976eNW"}'
mnemonic: ""
**Important:** write this mnemonic phrase in a safe place. It is the only way to recover your account if you ever forget your password.
ivory uniform actual spot floor vessel monster rose yellow noise smile odor veteran human reason miss stadium phrase assault puzzle sentence approve coral apology
💡 출력에 하단에 나오는 니모닉은 공개 및 개인 키를 복구하는데 사용할 수 있습니다.
다음 명령어로 키가 추가되었는지 확인합니다.
# local
./build/simd keys list \
--home ./private/.simapp \
--keyring-backend test
# local - alice
./build/simd keys show alice \
--home ./private/.simapp \
--keyring-backend test
# ---------------------------------
# docker
docker run --rm -it \
-v $(pwd)/private:/root \
simd:v0.45.4 \
simd keys list \
--keyring-backend test
# dcoker - alice
./build/simd keys show alice \
--home ./private/.simapp \
--keyring-backend test
# 출력예시
- name: alice
type: local
address: cosmos1c6z8yjtfeuz2ehuva864nc2c67df2mmfw5v63r
pubkey: '{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AsCNcoWDXlTfDejDQo8az1NRUEPhDtgYz90H71976eNW"}'
mnemonic: ""
✅ 최초 생성 이후에 확인할 때는 니모닉이 안나오는게 정상입니다..!
Make yourself a proper validator
Cosmos SDK 블록체인은 식별된 검증자(validator)들이 블록을 생성하는 데 의존합니다. 그러나, 초기에는 블록을 생성할 수 있는 검증자가 없습니다.
그러므로 초기화되고 시작되지 않은 체인에는 시작하기 위한 제네시스 계정과 검증자가 필요합니다.
이를 해결하기 위해서는 계정을 만들어 제네시스 파일에서 초기 잔액을 가지도록 해야 합니다.
이를 위해서는 Staking Denomination(스테이킹 단위)를 알아야 합니다.
grep bond_denom ./private/.simapp/config/genesis.json
# 출력
# "bond_denom": "stake"
다음 명령어를 이용하여 이전에 생성한 alice에게 지분을 줄 수 있습니다.
# local
./build/simd add-genesis-account alice 100000000stake \
--home ./private/.simapp \
--keyring-backend test
# docker
docker run --rm -it \
-v $(pwd)/private:/root \
simd:v0.45.4 \
simd add-genesis-account alice 100000000stake \
--keyring-backend test
이후 다음과 같은 명령어를 이용해서 제네시스 파일 자체에서 초기 잔액이 있는지 확인합니다.
grep -A 10 balances ./private/.simapp/config/genesis.json
# 출력
"balances": [
{
"address": "cosmos1c6z8yjtfeuz2ehuva864nc2c67df2mmfw5v63r",
"coins": [
{
"denom": "stake",
"amount": "100000000"
}
]
}
],
다음과 같은 초기 잔액이 있더라도, 블록체인을 실행하기 전에 BootStrap Transaction을 포함해야합니다.
💡 해당 시나리오에서는 네트워크가 실행되기 위해 validator의 2/3 비율을 충족해야하지만, 네트워크 상에서 혼자 일것이므로 최소 강제 지불 금액 이상인 어떤 수량이라도 staking할 수 있습니다.
예를 들어 100000000stake 이상을 스테이킹 할 수도 있습니다. 그러나 정직한 노드들이 큰 양의 staking을 해야 한다는 것을 상기하기 위해 방금 생성한 “alice”계정에서 100000000stake 중 70000000stake를 staking해야합니다.
이후에, 가스 비용을 지불하거나 토큰을 사용하기 위해 모든 토큰을 사용하지 않도록 주의해야합니다.
𖤐 또한 반드시 자신만의 --chain-id를 사용해야 합니다.
다음 명령어를 이용하여 제네시스 파일에 포함시킵니다.
# local
./build/simd gentx alice 70000000stake \
--home ./private/.simapp \
--keyring-backend test \
--chain-id learning-chain-1
# docker
docker run --rm -it \
-v $(pwd)/private:/root \
simd:v0.45.4 \
simd gentx alice 70000000stake \
--keyring-backend test \
--chain-id learning-chain-1
# 완료되면 다음과 같이 출력됩니다.
# Genesis transaction written to "/Users/alice/cosmos/cosmos-sdk/private/.simapp/config/gentx/gentx-cf6bff39bb84da39d214138ebba8bcba4ccb848d.json"
이후 collect-gentx 명령어를 이용하여 제네시스 트랜잭션을 수집 후 제네시스 파일에 포함시킵니다.
# local
./build/simd collect-gentxs \
--home ./private/.simapp
# docker
docker run --rm -it \
-v $(pwd)/private:/root \
simd:v0.45.4 \
simd collect-gentxs
# 완료되면 다음과 같이 출력됩니다.
# {"app_message":{"auth":{"accounts":[{"@type":"/cosmos.auth.v1beta1.BaseAccount","account_number":"0","address":"cosmos1nw793j9xvdzl2uc9ly8fas5tcfwfetercpdfqq","pub_key":null,"sequence":"0"}],"params":{"max_memo_characters":"256","sig_verify_cost_ed25519":"590","sig_verify_cost_secp256k1":"1000","tx_sig_limit":"7","tx_size_cost_per_byte":"10"}},"authz":{"authorization":[]},"bank":{"balances":[{"address":"cosmos1nw793j9xvdzl2uc9ly8fas5tcfwfetercpdfqq","coins":[{"amount":"100000000","denom":"stake"}]}],"denom_metadata":[],"params":{"default_send_enabled":true,"send_enabled":[]},"supply":[{"amount":"100000000","denom":"stake"}]},"capability":{"index":"1","owners":[]},"crisis":{"constant_fee":{"amount":"1000","denom":"stake"}},"distribution":{"delegator_starting_infos":[],"delegator_withdraw_infos":[],"fee_pool":{"community_pool":[]},"outstanding_rewards":[],"params":{"base_proposer_reward":"0.010000000000000000","bonus_proposer_reward":"0.040000000000000000","community_tax":"0.020000000000000000","withdraw_addr_enabled":true},"previous_proposer":"","validator_accumulated_commissions":[],"validator_current_rewards":[],"validator_historical_rewards":[],"validator_slash_events":[]},"evidence":{"evidence":[]},"feegrant":{"allowances":[]},"genutil":{"gen_txs":[{"auth_info":{"fee":{"amount":[],"gas_limit":"200000","granter":"","payer":""},"signer_infos":[{"mode_info":{"single":{"mode":"SIGN_MODE_DIRECT"}},"public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A6TrsRO/OH91fAEFLohw7RwFB832NRsRWhQvE2t8cfLK"},"sequence":"0"}],"tip":null},"body":{"extension_options":[],"memo":"cf6bff39bb84da39d214138ebba8bcba4ccb848d@192.168.1.7:26656","messages":[{"@type":"/cosmos.staking.v1beta1.MsgCreateValidator","commission":{"max_change_rate":"0.010000000000000000","max_rate":"0.200000000000000000","rate":"0.100000000000000000"},"delegator_address":"cosmos1nw793j9xvdzl2uc9ly8fas5tcfwfetercpdfqq","description":{"details":"","identity":"","moniker":"demo","security_contact":"","website":""},"min_self_delegation":"1","pubkey":{"@type":"/cosmos.crypto.ed25519.PubKey","key":"0wnjKoRtWjv9NOLEPS6UrlwFurQAmsJIXFsmhtbigF8="},"validator_address":"cosmosvaloper1nw793j9xvdzl2uc9ly8fas5tcfwfetera4euvn","value":{"amount":"70000000","denom":"stake"}}],"non_critical_extension_options":[],"timeout_height":"0"},"signatures":["NA23q62Vhfm1z3E1XafPeSDEVDkcPuTWXZmQr9QAZuN5wY2V6UFSRBO0w8Z255OxxZV4j47SJo1HOYWvcH4qvw=="]}]},"gov":{"deposit_params":{"max_deposit_period":"172800s","min_deposit":[{"amount":"10000000","denom":"stake"}]},"deposits":[],"proposals":[],"starting_proposal_id":"1","tally_params":{"quorum":"0.334000000000000000","threshold":"0.500000000000000000","veto_threshold":"0.334000000000000000"},"votes":[],"voting_params":{"voting_period":"172800s"}},"mint":{"minter":{"annual_provisions":"0.000000000000000000","inflation":"0.130000000000000000"},"params":{"blocks_per_year":"6311520","goal_bonded":"0.670000000000000000","inflation_max":"0.200000000000000000","inflation_min":"0.070000000000000000","inflation_rate_change":"0.130000000000000000","mint_denom":"stake"}},"params":null,"slashing":{"missed_blocks":[],"params":{"downtime_jail_duration":"600s","min_signed_per_window":"0.500000000000000000","signed_blocks_window":"100","slash_fraction_double_sign":"0.050000000000000000","slash_fraction_downtime":"0.010000000000000000"},"signing_infos":[]},"staking":{"delegations":[],"exported":false,"last_total_power":"0","last_validator_powers":[],"params":{"bond_denom":"stake","historical_entries":10000,"max_entries":7,"max_validators":100,"unbonding_time":"1814400s"},"redelegations":[],"unbonding_delegations":[],"validators":[]},"upgrade":{},"vesting":{}},"chain_id":"learning-chain-1","gentxs_dir":"/Users/muratoener/.simapp/config/gentx","moniker":"demo","node_id":"cf6bff39bb84da39d214138ebba8bcba4ccb848d"}
Create Blocks
이제 다음 명령어를 이용하여 단일 노드 블록체인을 시작할 수 있습니다.
# local
./build/simd start \
--home ./private/.simapp
# docker
docker run --rm -it \
--name simd \
-v $(pwd)/private:/root \
simd:v0.45.4 \
simd start
명령을 실행한 터미널 창에서 블록이 생성되고 검증되는 것을 볼 수 있습니다.
잔액을 확인하기 위해, 동일한 폴더에서 새 터미널을 연 후 alice의 주소 값을 받아옵니다.
# local
export alice=$(./build/simd keys show alice --address \
--home ./private/.simapp \
--keyring-backend test)
# docker
export alice=$(docker run --rm \
-v $(pwd)/private:/root \
simd:v0.45.4 simd keys show alice --address \
--keyring-backend test)
그 후 alice의 잔액을 확인합니다.
# local
./build/simd query bank balances $alice
# docker
docker exec simd simd query bank balances $alice
# 정상적으로 실행되면 다음과 같은 출력값이 나옵니다.
balances:
- amount: "30000000"
denom: stake
pagination:
next_key: null
total: "0"
Send Transaction
이제는 유효한 계정으로 토큰을 보낼 수 있습니다.
export bob=cosmos1ytt4z085fwxwnj0xdckk43ek4c9znuy00cghtq
✅ 튜토리얼에서는 Mintscan에서 계정을 가져오라고 했으나, 로컬에서 실행할 네트워크에는 해당 계정이 없으니 그대로 사용해도 무방합니다. 😀
토큰을 보내기 전에 새 계정의 잔액이 없는지 확인해야합니다.
# local
./build/simd query bank balances $bob
# docker
docker exec simd simd query bank balances $bob
# 정상적으로 실행되면 다음과 같은 출력값이 나옵니다.
balances: []
pagination:
next_key: null
total: "0"
계정에 잔액이 없다는 것을 확인한 후 거래를 위한 트랜잭션을 생성합니다.
# local
./build/simd tx bank send $alice $bob 10stake \
--home ./private/.simapp \
--keyring-backend test \
--chain-id learning-chain-1
# docker
docker exec -it simd simd tx bank send $alice $bob 10stake \
--keyring-backend test \
--chain-id learning-chain-1
서명하고 브로드캐스팅하기 전에 트랜잭션을 확인하라는 메시지가 표시됩니다.
{"body":{"messages":[{"@type":"/cosmos.bank.v1beta1.MsgSend","from_address":"cosmos1c6z8yjtfeuz2ehuva864nc2c67df2mmfw5v63r","to_address":"cosmos1ytt4z085fwxwnj0xdckk43ek4c9znuy00cghtq","amount":[{"denom":"stake","amount":"10"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}
confirm transaction before signing and broadcasting [y/N]: y
code: 0
codespace: ""
data: ""
events: []
gas_used: "0"
gas_wanted: "0"
height: "0"
info: ""
logs: []
raw_log: '[]'
timestamp: ""
tx: null
txhash: E432698B3C093FD4BD6CBBD0E9AA78E7A8ACA13BB2CFDFFD3E45058301D29F3C
여러 유용한 정보가 있으나, 트랜잭션이 블록에 포함되기 전에 출력된 값이기 때문에 txhash를 따로 저장합니다.
export txhash=E432698B3C093FD4BD6CBBD0E9AA78E7A8ACA13BB2CFDFFD3E45058301D29F3C
✅ 이전에 명령어들은 그대로 사용해도 무관하지만, 해당 txhash는 출력된 txhash를 사용해야합니다!
필요할 때마다 이 트랜잭션 해시를 사용하여 트랜잭션 정보를 콜백할 수 있습니다.
# local
./build/simd query tx $txhash
# docker
docker exec simd simd query bank balances $bob
# 정상적으로 실행되면 다음과 같이 출력됩니다.
balances:
- amount: "10"
denom: stake
pagination:
next_key: null
total: "0"
Outro
Run a Node, API and CLI파트에 있는 간단한 튜토리얼을 진행했습니다.
제네시스 파일, 트랜잭션과 블록 생성, 계정 생성, 토큰 전송 등의 기본적인 기능을 체험하기에는 적절한 튜토리얼이라고 생각됩니다!
혹시라도 CLI Routing
에도 관심이 있다면 확인해보시고 진행하시면 좋을 것 같습니다!