EOS常见命令及样例演示

EOS常见命令及样例演示

1,摘要

【本文目标】 本文列出经常EOS环境经常会使用的命令格式以及样例,作为EOS命令的快速查找手册。 不管是EOS的命令行帮助说明还是命令行参考文档,对参数的引用描述都比较乱,辉哥重新整理后规定,用[表示参数可选],用<>表示执行命令时其里面的内容需要根据实际情况进行修改。

【技术收获】 1) EOS各种常见命令格式及样例演示;

2,具体命令及演示

2.1 环境相关

2.1.1 启动钱包环境

keosd --http-server-address=127.0.0.1:8900

参数说明: 1) --http-server-address=127.0.0.1:8900 表示用于监听http链接的本地IP和端口;

作为启动本地环境的第一步,需要启动钱包。成功输出结果如下:

duncanwang@duncanwang:~$ keosd --http-server-address=127.0.0.1:8900
3861ms thread-0   wallet_plugin.cpp:39          plugin_initialize    ] initializing wallet plugin
3862ms thread-0   http_plugin.cpp:290           plugin_initialize    ] configured http to listen on 127.0.0.1:8900
3863ms thread-0   http_plugin.cpp:377           add_handler          ] add api url: /v1/keosd/stop
3863ms thread-0   http_plugin.cpp:331           plugin_startup       ] start listening for http requests
3865ms thread-0   wallet_api_plugin.cpp:73      plugin_startup       ] starting wallet_api_plugin
3865ms thread-0   http_plugin.cpp:377           add_handler          ] add api url: /v1/wallet/create
3865ms thread-0   http_plugin.cpp:377           add_handler          ] add api url: /v1/wallet/create_key
3865ms thread-0   http_plugin.cpp:377           add_handler          ] add api url: /v1/wallet/get_public_keys
3865ms thread-0   http_plugin.cpp:377           add_handler          ] add api url: /v1/wallet/import_key
3865ms thread-0   http_plugin.cpp:377           add_handler          ] add api url: /v1/wallet/list_keys
3865ms thread-0   http_plugin.cpp:377           add_handler          ] add api url: /v1/wallet/list_wallets
3865ms thread-0   http_plugin.cpp:377           add_handler          ] add api url: /v1/wallet/lock
3865ms thread-0   http_plugin.cpp:377           add_handler          ] add api url: /v1/wallet/lock_all
3865ms thread-0   http_plugin.cpp:377           add_handler          ] add api url: /v1/wallet/open
3865ms thread-0   http_plugin.cpp:377           add_handler          ] add api url: /v1/wallet/remove_key
3865ms thread-0   http_plugin.cpp:377           add_handler          ] add api url: /v1/wallet/set_timeout
3865ms thread-0   http_plugin.cpp:377           add_handler          ] add api url: /v1/wallet/sign_digest
3866ms thread-0   http_plugin.cpp:377           add_handler          ] add api url: /v1/wallet/sign_transaction
3866ms thread-0   http_plugin.cpp:377           add_handler          ] add api url: /v1/wallet/unlock
75115ms thread-0   wallet.cpp:223                save_wallet_file     ] saving wallet to file /home/duncanwang/eosio-wallet/./duncanwang.wallet

2.1.2 启动本地节点

cd ~/eos/build/programs/nodeos ./nodeos -e -p eosio --plugin eosio::wallet_plugin --plugin eosio::chain_api_plugin --plugin eosio::history_api_plugin --replay-blockchain

参数说明: 1) -e enable-stale-production,开启后,即使链过时了,也能产生区块 2) -p eosio producer-name,生产者的名字,这里指定为eosio 3) --plugin eosio::wallet_plugin 在启动nodeos时,需要添加参数eosio::wallet_plugin,否则的话,每次节点重启,之前创建的钱包,账号都不会加载进来。 4)--plugin eosio::chain_api_plugin

5) --plugin eosio::history_api_plugin 记录执行过程。 7) --replay-blockchain --replay-blockchain表示清除数据库内链的状态,重新运行,它会导致重新启动时先读取之前的区块进行加载。

2.2 钱包,密钥对相关命令

2.2.1 创建钱包

cleos wallet create [-n ]

参数说明:

  1. -n :表示钱包名称为"wallet_name",不带该参数表示创建名称为'default'的钱包。

创建duncanwang钱包成功,输出结果如下:

duncanwang@duncanwang:~/eos$ cleos wallet create -n duncanwang
Creating wallet: duncanwang
Save password to use in the future to unlock this wallet.
Without password imported keys will not be retrievable.
"PW5JMZdES2Cds5LsPRUBRo2THEXpbFSM17Xmcd2XWG7XBd49wveTo"

2.2.2 显示钱包列表

cleos wallet list [-n ]

显示该节点环境存在的钱包名称列表。 下面结果中,"duncanwang"表示钱包名称,"*"表示该钱包已解锁。

duncanwang@duncanwang:~$ cleos wallet list
Wallets:
[
  "duncanwang *"
]

2.2.3 创建密钥

cleos create key

创建密钥对的输出结果:

duncanwang@duncanwang:~/eos$ cleos create key
Private key: 5JZQmnt6ZtEzUADswgKgBwMp9qAwTSNM9JFHPRFu1FjrLjj49g7
Public key: EOS6EHAzvrpQ4wo1BPcAk86X6aGDARZgqTcAq1mJRF1SxEYgNGWN1

2.2.4 钱包导入密钥

cleos wallet import [-n ]

导入密钥对的私钥,可以用于操作该钱包内的账号account。命令结果会提示导入私钥对应的公钥。

duncanwang@duncanwang:~/eos$ cleos wallet import 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3 -n duncanwang
imported private key for: EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV

2.2.5 列出钱包密钥

cleos wallet keys [-n ]

显示钱包中所有的公钥列表。

duncanwang@duncanwang:~/eos$ cleos wallet keys
[
  "EOS6EHAzvrpQ4wo1BPcAk86X6aGDARZgqTcAq1mJRF1SxEYgNGWN1",
  "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
]

2.2.6 锁定钱包

cleos wallet lock [-n ]

节点退出或者默认时间到达时,钱包会自动锁定。显示钱包列表中,锁定的钱包在列表中没有 符号,解锁的钱包会有" "符号显示。

$ cleos wallet lock -n duncanwang
Locked: 'duncanwang'

2.2.7 解锁钱包

$ cleos wallet unlock [-n ] [--password ]

参数说明 --password : 表示打开钱包的密码,创建钱包时给出的。命令输入时不带该参数,会在命令回车后提示输入。 -n : 钱包名称,不存在的话表示解锁"default"钱包。

duncanwang@duncanwang:~/eos$ cleos wallet unlock -n duncanwang
password: Unlocked: duncanwang

2.2.8 打开钱包

cleos wallet open [-n ]

当EOS节点重启时,钱包列表并不能看到钱包列表时,需要重新打开钱包来加载。

$ cleos wallet open
Wallets: [
  "default"
]
$ cleos wallet open -n duncanwang
Wallets: [
  "default",
  "duncanwang"
]

2.3 账号相关

2.3.1 创建账号

cleos create account []

参数说明

  • control_account : 控制账号,eosio是超级用户,需要靠超级用户来创建其它的新用户。
  • new_account :账号名称,本地环境创建账号的命名规则遵守下边两个规则:小于13个字符;仅包含这些字符:.12345abcdefghijklmnopqrstuvwxyz
  • owner_public_key:表示分配给新账号的一个Owner认证的公钥;
  • active_public_key:表示分配给新账号一个Active认证的一个公钥; 成功输出结果:
duncanwang@duncanwang:~/eos$ cleos create account eosio boss EOS6EHAzvrpQ4wo1BPcAk86X6aGDARZgqTcAq1mJRF1SxEYgNGWN1 EOS6EHAzvrpQ4wo1BPcAk86X6aGDARZgqTcAq1mJRF1SxEYgNGWN1
executed transaction: cb6801fe82816f94b447cbfb903ae8e9477f5c99920322d679a9c8c04347e536  200 bytes  367 us
##         eosio &lt;= eosio::newaccount            {"creator":"eosio","name":"boss","owner":{"threshold":1,"keys":[{"key":"EOS6EHAzvrpQ4wo1BPcAk86X6aGD...
warning: transaction executed locally, but may not be confirmed by the network yet

2.3.3 获取帐户信息

$ cleos [-u ] get account

参数说明: -u : 连接的EOS节点; -:账号名称

输出结果样例:

duncanwang@duncanwang:~$ cleos -u https://node1.eoscannon.io get  account gobipartners
permissions: 
     owner     1:    1 EOS8gaYL4uHyAiZjviwNJ8CdY31xikYtQfexyUfkNUnDqhNpnYXQR
        active     1:    1 EOS8gaYL4uHyAiZjviwNJ8CdY31xikYtQfexyUfkNUnDqhNpnYXQR
memory: 
     quota:     7.959 KiB    used:     2.926 KiB  

net bandwidth: 
     delegated:       0.1000 EOS           (total staked delegated to account from others)
     used:                 0 bytes
     available:        55.92 KiB  
     limit:            55.92 KiB  

cpu bandwidth:
     delegated:       0.1000 EOS           (total staked delegated to account from others)
     used:                 0 us   
     available:         10.9 ms   
     limit:             10.9 ms

2.3.4 获取帐户余额

cleos [-u ] get currency balance eosio.token

参数说明: -u : 连接的EOS节点; -:账号名称

输出结果样例: 表明wangdenghui1账户中有16.2010个EOS。

duncanwang@duncanwang:~$ cleos -u https://node1.eoscannon.io get currency balance eosio.token wangdenghui1
16.2010 EOS

2.3.5 EOS转账

cleos [ -u ] transfer []

参数说明: -u : 连接的EOS节点; -:发送账号的名称; -:接收账号的名称; -quantity: EOS的数量,'0.1 EOS'可以表示到小数; -:'转给辉哥'形式,表示本笔交易的记录备注;

输出案例:

duncanwang@duncanwang:~$ cleos -u https://node1.eoscannon.io transfer wangdenghui1 gobipartners '0.1 EOS' 'test'
executed transaction: fb512f699b61209707a64f188ac9740d39d5747af82a51eebe8b765165f85ea5  136 bytes  879 us
##   eosio.token &lt;= eosio.token::transfer        {"from":"wangdenghui1","to":"gobipartners","quantity":"0.1000 EOS","memo":"test"}
##  wangdenghui1 &lt;= eosio.token::transfer        {"from":"wangdenghui1","to":"gobipartners","quantity":"0.1000 EOS","memo":"test"}
##  gobipartners &lt;= eosio.token::transfer        {"from":"wangdenghui1","to":"gobipartners","quantity":"0.1000 EOS","memo":"test"}
warning: transaction executed locally, but may not be confirmed by the network yet

2.3.6 变更账户的active_key

cleos set account permission active '{"threshold":1,"keys":[{"key":"","weight":1}]}' owner

输出结果案例: 变更结果成功,具体操作可参考 《第9课 如何变更EOS账号的active key和owner key?》 文章描述。

duncanwang@duncanwang:~$ cleos -u https://node1.eoscannon.io set account permission gobipartners active '{"threshold":1,"keys":[{"key":"EOS7Rq86JcZLgPXwZKRGPYUnLayBy7NcBV7FBE7gSNCW3HmGApK9V","weight":1}]}' owner
executed transaction: 0b7ab9fe92413e6b4b5d25578afdef81438c73adac015972ce56f59c570034e9  160 bytes  1317 us
##         eosio &lt;= eosio::updateauth            {"account":"gobipartners","permission":"active","parent":"owner","auth":{"threshold":1,"keys":[{"key...
warning: transaction executed locally, but may not be confirmed by the network yet

2.3.7 变更账户的owner_key

cleos set account permission [-x ] owner '{"threshold":1,"keys":[{"key":"","weight":1}]}' -p @owner

参数说明: -x :交易超时的时间。不输入的话默认为30秒。

输出结果案例:

duncanwang@duncanwang:~$ cleos -u https://node1.eoscannon.io set account permission -x 120 gobipartners owner '{"threshold":1,"keys":[{"key":"EOS7Rq86JcZLgPXwZKRGPYUnLayBy7NcBV7FBE7gSNCW3HmGApK9V","weight":1}]}' -p gobipartners@owner
executed transaction: ed1593fee153baa7b02e1e3e1155e732c3e7db4fbb3fd50ff73b0de1a04d5831  160 bytes  1186 us
##         eosio &lt;= eosio::updateauth            {"account":"gobipartners","permission":"owner","parent":"","auth":{"threshold":1,"keys":[{"key":"EOS...
warning: transaction executed locally, but may not be confirmed by the network yet

2.4 合约相关

2.4.1 部署合约

cleos set contract ../ [ -p ]

or

cleos set contract ../.wast ../.abi

参数说明: : 账号名称; ../: 合约类的名称; -p : 表示用account_name例如wangdenghui账户的active权限签署此操作;

输出结果样例

duncanwang@duncanwang:~/eos/build/contracts/hello$ cleos set contract wangdenghui ../hello -p wangdenghui
Reading WAST/WASM from ../hello/hello.wasm...
Using already assembled WASM...
Publishing contract...
executed transaction: 79830b81c90a22ab42b427ac70ff0c764441d92ea128999712e3376ae6b2460d  4168 bytes  741 us
##         eosio &lt;= eosio::setcode               {"account":"wangdenghui","vmtype":0,"vmversion":0,"code":"0061736d01000000013b0c60027f7e006000017e60...
##         eosio &lt;= eosio::setabi                {"account":"wangdenghui","abi":"0e656f73696f3a3a6162692f312e30000102686900010475736572046e616d650100...
warning: transaction executed locally, but may not be confirmed by the network yet

2.4.2 执行合约

cleos push action [] -p

参数说明: :执行合约的账号,例如wangdenghui; : 动作函数,例如hi; :输入参数,例如"World!"; -p :由哪个账号来执行;

输出结果样例: 输出结果有>> "Hello World!"

duncanwang@duncanwang:~/eos/build/contracts/hello$ cleos push action wangdenghui hi '["World!"]' -p wangdenghui
executed transaction: d10de21ee792c4997ae697e5db00ad571cfd67c374e9e9fcb741a2a7046c9e49  104 bytes  830 us
##   wangdenghui &lt;= wangdenghui::hi              {"strContent":"World!"}
>> Hello World!
warning: transaction executed locally, but may not be confirmed by the network yet

2.4.3 查询合约表信息

cleos [-u ]get table

参数说明: -u : 连接的EOS节点,不填写表示本地节点; -:合约名称,eosio表示拥有这个表的超级用户; -:查询范围,"gobipartners"表示查询该账号的相关信息; -:合同ABI信息约定的表名,例如"userres"表示用户资源;

输出案例:

duncanwang@duncanwang:~$ cleos -u https://node1.eoscannon.io get table eosio gobipartners userres
{
  "rows": [{
      "owner": "gobipartners",
      "net_weight": "0.1000 EOS",
      "cpu_weight": "0.1000 EOS",
      "ram_bytes": 8150
    }
  ],
  "more": false
}

2.4 系统相关

2.4.1 创建系统账号

cleos -u system newaccount -x 1000 --stake-net '0.0010 EOS' --stake-cpu '0.0010 EOS' --buy-ram-kbytes 8

参数说明: -u : 连接的EOS节点; -x 1000: 1000s内最长反馈时间; --stake-net:使用带宽抵押的EOS; --stake-cpu:使用CPU抵押的EOS; --buy-ram-kbytes:购买的内存(最低8KB); :即第3步记下来的12个字符的账户名; :同样是12个字符,只能使用小写字母a-z,和数字1-5;

【经验】 NET Stake (in EOS): 0.05 CPU Stake (in EOS): 0.1 RAM (in kbytes):8

输出结果(创建成功):

duncanwang@duncanwang:~$ cleos -u https://node1.eoscannon.io system newaccount -x 1000 --stake-net "0.1 EOS" --stake-cpu "0.1 EOS" --buy-ram-kbytes 8 wangdenghui1 gobipartners EOS8gaYL4uHyAiZjviwNJ8CdY31xikYtQfexyUfkNUnDqhNpnYXQR EOS8gaYL4uHyAiZjviwNJ8CdY31xikYtQfexyUfkNUnDqhNpnYXQR
1229333ms thread-0   main.cpp:429                  create_action        ] result: {"binargs":"109c6e6caac4a6e180af9af99aea0e6500200000"} arg: {"code":"eosio","action":"buyrambytes","args":{"payer":"wangdenghui1","receiver":"gobipartners","bytes":8192}} 
1229958ms thread-0   main.cpp:429                  create_action        ] result: {"binargs":"109c6e6caac4a6e180af9af99aea0e65e80300000000000004454f5300000000e80300000000000004454f530000000000"} arg: {"code":"eosio","action":"delegatebw","args":{"from":"wangdenghui1","receiver":"gobipartners","stake_net_quantity":"0.1000 EOS","stake_cpu_quantity":"0.1000 EOS","transfer":false}} 
executed transaction: d0c3543b6db8787a151a748ab73d0dec9210442cf7022a442c42fa9fe2a27f3c  336 bytes  5477 us
##         eosio &lt;= eosio::newaccount            {"creator":"wangdenghui1","name":"gobipartners","owner":{"threshold":1,"keys":[{"key":"EOS8gaYL4uHyA...
##         eosio &lt;= eosio::buyrambytes           {"payer":"wangdenghui1","receiver":"gobipartners","bytes":8192}
##   eosio.token &lt;= eosio.token::transfer        {"from":"wangdenghui1","to":"eosio.ram","quantity":"2.9714 EOS","memo":"buy ram"}
##  wangdenghui1 &lt;= eosio.token::transfer        {"from":"wangdenghui1","to":"eosio.ram","quantity":"2.9714 EOS","memo":"buy ram"}
##     eosio.ram &lt;= eosio.token::transfer        {"from":"wangdenghui1","to":"eosio.ram","quantity":"2.9714 EOS","memo":"buy ram"}
##   eosio.token &lt;= eosio.token::transfer        {"from":"wangdenghui1","to":"eosio.ramfee","quantity":"0.0150 EOS","memo":"ram fee"}
##  wangdenghui1 &lt;= eosio.token::transfer        {"from":"wangdenghui1","to":"eosio.ramfee","quantity":"0.0150 EOS","memo":"ram fee"}
##  eosio.ramfee &lt;= eosio.token::transfer        {"from":"wangdenghui1","to":"eosio.ramfee","quantity":"0.0150 EOS","memo":"ram fee"}
##         eosio &lt;= eosio::delegatebw            {"from":"wangdenghui1","receiver":"gobipartners","stake_net_quantity":"0.1000 EOS","stake_cpu_quanti...
##   eosio.token &lt;= eosio.token::transfer        {"from":"wangdenghui1","to":"eosio.stake","quantity":"0.2000 EOS","memo":"stake bandwidth"}
##  wangdenghui1 &lt;= eosio.token::transfer        {"from":"wangdenghui1","to":"eosio.stake","quantity":"0.2000 EOS","memo":"stake bandwidth"}
##   eosio.stake &lt;= eosio.token::transfer        {"from":"wangdenghui1","to":"eosio.stake","quantity":"0.2000 EOS","memo":"stake bandwidth"}
warning: transaction executed locally, but may not be confirmed by the network yet

2.4.2 显示账号抵押的带宽

cleos [-u ] system listbw

参数说明: -u :节点名称; : 账号名称;

输出结果样例(待补充有效的):

cleos -u https://node1.eoscannon.io system listbw gobipartners

2.4.3 查询短名出价情况

cleos system bidnameinfo

参数说明: : 参与竞拍的小于12位的账号名称; 输出结果案例,表明fenbushi的域名的当前竞标价格为0.0221 EOS。:

duncanwang@duncanwang:~$ cleos -u https://node1.eoscannon.io system bidnameinfo fenbushi
bidname:                          fenbushi
highest bidder:               eosallblue4u
highest bid:                           221
last bid time:     2018-07-07T17:05:01.500

2.4.4 参与竞拍

cleos system bidname

参数说明: :竞拍用的账号名称; :竞拍的短账号名称; :给出的竞拍价;

输出结果案例: 每次竞拍要有10%以上的涨幅,辉哥本次竞拍的标价为0.0444个EOS,竞拍给价成功。

duncanwang@duncanwang:~$ cleos -u https://node1.eoscannon.io system bidname wangdenghui1 fenbushi '0.0444 EOS'
2574251ms thread-0   main.cpp:429                  create_action        ] result: {"binargs":"109c6e6caac4a6e1000000ae617da65abc0100000000000004454f5300000000"} arg: {"code":"eosio","action":"bidname","args":{"bidder":"wangdenghui1","newname":"fenbushi","bid":"0.0444 EOS"}} 
executed transaction: fbcd8cbea0e7f655ce608f10a615d4a8f04acecb647e9a692b8aac78613a56ef  128 bytes  3587 us
##         eosio &lt;= eosio::bidname               {"bidder":"wangdenghui1","newname":"fenbushi","bid":"0.0444 EOS"}
##   eosio.token &lt;= eosio.token::transfer        {"from":"wangdenghui1","to":"eosio.names","quantity":"0.0444 EOS","memo":"bid name fenbushi"}
##  wangdenghui1 &lt;= eosio.token::transfer        {"from":"wangdenghui1","to":"eosio.names","quantity":"0.0444 EOS","memo":"bid name fenbushi"}
##   eosio.names &lt;= eosio.token::transfer        {"from":"wangdenghui1","to":"eosio.names","quantity":"0.0444 EOS","memo":"bid name fenbushi"}
##   eosio.token &lt;= eosio.token::transfer        {"from":"eosio.names","to":"eosallblue4u","quantity":"0.0221 EOS","memo":"refund bid on name fenbush...
##   eosio.names &lt;= eosio.token::transfer        {"from":"eosio.names","to":"eosallblue4u","quantity":"0.0221 EOS","memo":"refund bid on name fenbush...
##  eosallblue4u &lt;= eosio.token::transfer        {"from":"eosio.names","to":"eosallblue4u","quantity":"0.0221 EOS","memo":"refund bid on name fenbush...
warning: transaction executed locally, but may not be confirmed by the network yet

2.4.5 列出所有BP

cleos [-u ] system listproducers 输出结果案例(待补充)

2.4.5 购买RAM

cleos [-u ] system buyram

参数说明: :支付RAM的账号 : 收益的账号; :购买数量,"1 EOS"表示1个EOS。

输出结果案例(待补充)

cleos -u https://eos.greymass.com system buyram 主账号 子帐号 "1 EOS"

2.4.6 卖出RAM

cleos [-u ] system sellram

参数说明: :支付RAM的账号 :RAM字节数

输出结果案例(待补充)

cleos -u https://eos.greymass.com system sellram 卖出帐号 RAM字节数

2.4.7 抵押net和cpu资源

cleos [-u ] system delegatebw

参数说明: :抵押扣除EOS的账号; :抵押收益的账号,就是获得带宽和CPU资源的账号; stake_net_quantity:获取带宽的EOS抵押数量,例如"1 EOS" stake_cpu_quantity:获取CPU的EOS抵押数量,例如"1 EOS"

输出结果案例(待补充)

cleos -u https://eos.greymass.com system delegatebw 主账号 子帐号 "1 EOS" "1 EOS"

2.4.8 取消抵押net和cpu资源

cleos [-u ] system undelegatebw

参数说明: :取消抵押的账号; :取消抵押收益的账号,就是获得EOS的账号; unstake_net_quantity:取消抵押带宽获取的EOS的数量; unstake_cpu_quantity: 取消抵押CPU获取的EOS的数量;

输出结果案例(待补充)

cleos -u https://eos.greymass.com system undelegatebw 主账号 子帐号 "1 EOS" "1 EOS"

3. Cleos命令框架

更多的命令和说明请参考官网帮助文档。

大的功能模块说明: 1、version:获取版本信息 2、create:在EOS区块链上或链下本地创建一些东西 3、get:从EOS区块链上获取各种数据和信息 4、set:设置或者更新区块链状态 5、transfer:在EOS账户之间进行转账 6、net:管理或查询本地p2p网络连接状态 7、wallet:管理本地钱包 8、sign:对交易进行签名 9、push:把任意交易发送至区块链 10、multisig:多重签名功能 11、sudo:通过超级账户eosio.sudo执行命令,可越过权限验证,目前该超级账户还未创建 12、system:向区块链发送系统合约内置的相关动作

4,参考

1) cleos快速命令查询 2) 官网命令参考

  • 发表于 2018-07-17 21:03
  • 阅读 ( 1321 )
  • 学分 ( 10 )
  • 分类:EOS

1 条评论

请先 登录 后评论
辉哥
辉哥

CTO

107 篇文章, 924 学分