{"id":19329969,"url":"https://github.com/lichuan/askcoin","last_synced_at":"2025-07-16T22:35:32.456Z","repository":{"id":50799092,"uuid":"93148492","full_name":"lichuan/askcoin","owner":"lichuan","description":"Askcoin (ASIC-resistant) is a decentralized Q\u0026A and prediction platform","archived":false,"fork":false,"pushed_at":"2021-05-29T01:57:23.000Z","size":27075,"stargazers_count":8,"open_issues_count":2,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2023-05-04T23:51:20.320Z","etag":null,"topics":["askcoin","bitcoin","block","blockchain","consensus","consensus-algorithm","cplusplus-11","cpp","cpp11","cryptocurrency","pow"],"latest_commit_sha":null,"homepage":"https://www.askcoin.me","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lichuan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-06-02T09:10:03.000Z","updated_at":"2022-08-16T07:49:33.000Z","dependencies_parsed_at":"2022-09-06T00:20:45.602Z","dependency_job_id":null,"html_url":"https://github.com/lichuan/askcoin","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lichuan%2Faskcoin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lichuan%2Faskcoin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lichuan%2Faskcoin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lichuan%2Faskcoin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lichuan","download_url":"https://codeload.github.com/lichuan/askcoin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223906425,"owners_count":17223046,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["askcoin","bitcoin","block","blockchain","consensus","consensus-algorithm","cplusplus-11","cpp","cpp11","cryptocurrency","pow"],"created_at":"2024-11-10T02:32:55.026Z","updated_at":"2024-11-10T02:32:55.546Z","avatar_url":"https://github.com/lichuan.png","language":"C++","readme":"## Askcoin\n\nAskcoin is a cryptocurrency for real-time Q\u0026A and event prediction. It has a built-in decentralized exchange, It was created for people to ask questions freely, to talk freely, to trade freely and to predict events freely. It's decentralized and ASIC-resistant, this is achieved by a new POW consensus algorithm.\n\nAs we all know, bitcoin is mined by calculating sha256, so whoever calculates sha256 fast will be able to produce new blocks before anyone else, this is exactly what ASIC mining machines on the market are good at.\n\nIn order to weaken the advantages of ASIC mining machine, the mining algorithm of askcoin uses sha256 combined with memory loading to resist ASIC machine. In askcoin, the speed of mining depends mainly on the speed of memory load, not the speed of sha256 calculation.\n\n\n\n\n\n## System requirement (recommend)\n\n### *Hardware requirements:*\n\n| Resource |     Require      |\n| :------: | :--------------: |\n|   CPU    | 16 cores or more |\n|  Memory  |   16G or more    |\n|   Disk   |   100G or more   |\n| Network  |   100Mb / sec    |\n\n\n\n### *Operating system:*\n\nAskcoin can run on any Linux distribution *(64bit and support c++11)* such as Centos, Ubuntu, Debian, etc.\n\nThe binary release archive on GitHub is currently built on CentOS 7.4\n\n\n\n\n\n## Configuration\n\nThe configuration file (***config.json***) for askcoin is as follows:\n\n```json\n{\n    \"log_level\": \"info\",\n    \"log_path\": \"./log\",\n    \"db_path\": \"./db\",\n    \"network\": {\n        \"p2p\": {\n            \"host\": \"here should be your host (domain or ip address)\",\n            \"port\": 18050,\n            \"max_conn\": 1000,\n            \"init_peer\": [\n                {\n                    \"host\": \"node1.askcoin.me\",\n                    \"port\": 18050\n                },\n                {\n                    \"host\": \"node2.askcoin.me\",\n                    \"port\": 18050\n                }\n            ]\n        },\n        \"websocket\": {\n            \"enable\": true,\n            \"host\": \"0.0.0.0\",\n            \"port\": 19050,\n            \"max_conn\": 5000\n        }\n    }\n}\n```\n\n- ***log_level***:  control the level of the log and the corresponding output content, its value can be \"fatal\", \"error\", \"warn\", \"info\", \"debug\".\n- ***log_path***:  the directory in which the log files are stored.\n- ***db_path***:  directory for storing leveldb database files.\n- ***network.p2p.host***:  host address for P2P network communication (IP or domain name).\n- ***network.p2p.port***:  port number for P2P network communication.\n- ***network.p2p.max_conn***:  maximum number of P2P network connections allowed.\n- ***network.p2p.init_peer***:  initial peer nodes in P2P networks.\n- ***network.websocket.enable***:  whether to open websocket service.\n- ***network.websocket.host***:  websocket address that mobile app or explorer can connect to. If you only want to provide internal network access, you can set this as a private address (such as 192.168.1.234).\n- ***network.websocket.port***:  websocket port that mobile app or explorer can connect to.\n- ***network.websocket.max_conn***:  maximum number of websocket connections allowed.\n\n\n\n\n\n## Max open files\n\nOn the Linux system, you can get the limit of the number of open files on the current system by typing the following command:\n\n```bash\nulimit -a\n```\n\n![max open files](res/files_limit.jpg)\n\nIf you want to provide websocket service on the full node to a large number of mobile app users, you need to increase the maximum number of open files allowed by the system. Here are two ways to do this:\n\n- modify the ***/etc/security/limits.conf*** file (you can get how to do it by google)\n- start askcoin by running the ***start.sh*** script in the release package\n\nThe following is the content of the ***start.sh*** script file:\n\n```bash\n#!/bin/bash\nulimit -HSn 50000\n./askcoin\n```\n\n\n\n\n\n## Firewall ports\n\nAs described in the ***configuration*** section above, askcoin needs to open two ports in the firewall:\n\n- P2P communication port (default 18050)\n- Websocket service port (default 19050)\n\n\n\n\n\n## Account model\n\nUnlike Bitcoin, askcoin uses an account model, so before using askcoin, you have to register an account in the block chain. In askcoin, there are five types of transactions:\n\n1. Register an account\n2. Transfer\n3. Ask a question (or topic)\n4. Reply to a question\n5. Reward a reply\n\nIn order to prevent DDoS attacks, 2 ASK fees will be deducted from the initiator of each transaction. But if you are registering an account, who will pay for it? That's what your referrer should do.\n\nIn askcoin, if you want to register an account, you need to enter your username, avatar, and the string signed by your referrer. When the full node receives your registration request, it will deduct 2 ASK from your referrer's account.\n\nOf the 2 ASK fees paid for each transaction you initiate since then, 1 ASK will be paid to the miner's account that put the transaction in the block, and another 1 ASK will be paid to your referrer's account.\n\n\n\n\n\n## Miner\n\nIf you want to be a miner, you need to do the following steps:\n\n1. Synchronize your system time with global UTC time (using **crontab** and **ntpdate**)\n\n2. Run the askcoin full node by executing the ***start.sh*** script\n\n3. When your full node is successfully started, you will see the following output on the shell terminal:\n\n   ![start](res/start.jpg)\n\n   you can open another shell terminal and run this command: ***tail -f log/askcoin.log*** to check the output log generated, waiting for your full node to synchronize to the latest block (new miners can use the \"merge point\" to dramatically reduce synchronization time, you can refer to [***askcoin-merge-point***](https://github.com/lichuan/askcoin-merge-point) for more information)\n\n4. If you haven't registered an account before, you need to execute ***gen_privkey*** to generate a new private key:\n\n   ![gen_privkey](res/gen_privkey.jpg)\n\n5. Import your private key by executing ***import_privkey***:\n\n   ![import_privkey](res/import_privkey.jpg)\n\n6. Let a user who has registered an account in askcoin execute ***gen_reg_sign*** command to help you generate a signature string for your registration. When you register successfully, he or she will automatically become your referrer: (to make it easier for new users to register, we have released a web tool to generate signature strings for users to register: [***askcoin-gen-reg-sign***](https://github.com/lichuan/askcoin-gen-reg-sign) If you are a new user and need to register, you can generate the signature string through the following address:\n   [http://generate.askcoin.me](http://generate.askcoin.me/) )\n\n   ![gen_reg_sign](res/gen_reg_sign.jpg)\n\n7. Now you can register a new account by executing the ***reg_account*** command, which requires entering your account name, your avatar ID (ranging from 1 to 100), and the signature string generated by your referrer:\n\n   ![reg_account](res/reg_account.jpg)\n\n   You need to wait patiently for the miner to put your registration request into the block. Usually it only takes about 20 seconds to get the miner's confirmation. You can confirm whether the registration is successful by executing ***get_balance***. If the output of this command shows that your balance is 0, it means that you have successfully registered. Otherwise, it means that you still need to wait for confirmation from the miner:\n\n   ![get_balance](res/get_balance.jpg)\n\n   When you register successfully, your account will automatically start mining, you can stop mining by executing the ***enable_mine*** command:\n\n   ![enable_mine](res/enable_mine.jpg)\n\n\n\n\n\n## Build\n\nAskcoin is built through scons (2.5.1 compatible version). On CentOS 7.4, you can install it and some other dependency packages by running the following command:\n\n```shell\nyum install -y scons cmake3 gcc-c++ autoconf automake libtool\n```\n\nAskcoin is open-source now, so you can clone it and its submodules by executing the following command:\n\n```shell\ngit clone https://github.com/lichuan/askcoin.git --recursive\n```\n\nYou can then go to askcoin directory and compile askcoin's source code using ***scons*** command:\n\n```shell\ncd askcoin\nscons\n```\n\n\n\n\n\n## Exchange API\n\nIf some centralized exchanges wish to list ASK coin, they can follow the steps described in this section.\n\n1. Add an `exchange` field under the `websocket` field of the ***config.json*** file in the **full node** you run, then fill in the ID and name (base64) of the account representing the exchange wallet , and set a password to add a layer of security check:\n\n   ```json\n   {\n       \"log_level\": \"info\",\n       \"log_path\": \"./log\",\n       \"db_path\": \"./db\",\n       \"network\": {\n           \"p2p\": {\n               \"host\": \"here should be your host (domain or ip address)\",\n               \"port\": 18050,\n               \"max_conn\": 1000,\n               \"init_peer\": [\n                   {\n                       \"host\": \"node1.askcoin.me\",\n                       \"port\": 18050\n                   },\n                   {\n                       \"host\": \"node2.askcoin.me\",\n                       \"port\": 18050\n                   }\n               ]\n           },\n           \"websocket\": {\n               \"enable\": true,\n               \"host\": \"0.0.0.0\",\n               \"port\": 19050,\n               \"max_conn\": 5000,\n               \"exchange\": {\n                   \"account_id\": 123,\n                   \"account_b64\": \"ZXhjaGFuZ2VfdXNlcg==\",\n                   \"password\": \"exchange_api_password\"\n               }\n           }\n       }\n   }\n   ```\n\n2. Establish a websocket connection to your **full node** and send **EXCHANGE_LOGIN** message:\n\n   ```javascript\n   var WebSocket = require('ws');\n   // change the following to your own account\n   var exchange_account_id = 123;\n   var exchange_account_b64 = \"ZXhjaGFuZ2VfdXNlcg==\"; // base64 of account name\n   var exchange_password = \"exchange_api_password\";\n   var exchange_account_privkey_str = \"Vm1wSmQwMVhSWGxUYTJScVUwWktXRmxzVWtKaVJUQjN=\";\n   var privkey_buf = Buffer.from(exchange_account_privkey_str, 'base64');\n   var exchange_account_privkey = ec.keyFromPrivate(privkey_buf);\n   var pubkey_hex = exchange_account_privkey.getPublic('hex');\n   var exchange_account_pubkey_b64 = Buffer.from(pubkey_hex, 'hex').toString('base64');\n   var ws = new WebSocket('ws://your-full-node.com:19050');\n   ws.on('open', function() {\n       // send EXCHANGE_LOGIN message\n       ws.send(JSON.stringify({\n           msg_type: 6,\n           msg_cmd: 0,\n           msg_id: 0,\n           account_id: exchange_account_id,\n           account_b64: exchange_account_b64,\n           password: exchange_password\n           \n           // If you miss some blocks due to network interruption or downtime,\n           // you can add the following two fields to the next EXCHANGE_LOGIN message\n           // to query the withdrawal and deposit records within the blocks.\n           // block_id_from: 1000,\n           // block_id_to: 2000\n       }));\n   });\n   ```\n\n   From now on, if someone transfers ASK coin to your exchange account, you will receive a real-time notification message (**EXCHANGE_NOTIFY_DEPOSIT**) containing the sender's account information, the amount of transfer and **memo**. You can identify the depositor's account according to the **memo**.\n\n   Since **consensus algorithm** judges which chain is the **main chain** based on **cumulative difficulty**, it may abandon the current branch chain and switch to the new main chain many times in the process of consensus, it is these characteristics that you need to constantly send **EXCHANGE_DEPOSIT_TX_PROBE** messages to check whether the transaction receives enough confirmations from miners.\n\n3. If someone initiates withdrawal of ASK coin, the first thing to do is to construct an **ACCOUNT_QUERY** message, fill in the ID of the account, and then send it to your **full node** to query the public key string of the account ID.\n\n   ```javascript\n   function request_for_withdrawal(user_name, receiver_id, receiver_name, amount,memo)\n   {\n       if(balance_of_each_user[user_name] \u003c amount) {\n           console.log(\"Your account balance is insufficient\");\n           return;\n       }\n   \n       withdraw_unique_id += 1;\n       \n       // Query the corresponding account public key\n       // from the Full-node according to the account ID\n       ws.send(JSON.stringify({ // send ACCOUNT_QUERY message\n           msg_type: 1,\n           msg_cmd: 3,\n           msg_id: withdraw_unique_id,\n           id: receiver_id\n       }));\n       \n       var pre_withdraw = {};\n       pre_withdraw.sender_name = user_name;\n       pre_withdraw.receiver_id = receiver_id;\n       pre_withdraw.receiver_name = receiver_name;\n       pre_withdraw.amount = amount;\n       pre_withdraw.memo = memo\n       pre_pending_withdraw_txs[withdraw_unique_id] = pre_withdraw;\n       console.log(\"withdraw_unique_id:\", withdraw_unique_id);\n   }\n   ```\n\n   When you query the public key corresponding to the account id, you need to construct a transfer transaction, fill in the recipient's public key, transfer amount and other information, and calculate the transaction ID of the transaction, and use your private key to sign the transaction, and finally send the transaction to your **full node** again.\n\n   ```js\n   if(msg_obj.msg_type == 1 \u0026\u0026 msg_obj.msg_cmd == 3) // ACCOUNT_QUERY\n   {\n       var pre_withdraw = pre_pending_withdraw_txs[msg_obj.msg_id];\n   \n       if(msg_obj.err_code == 12) // ERR_RECEIVER_NOT_EXIST\n       {\n           console.log(\"receiver not exist\");\n           pre_pending_withdraw_txs[msg_obj.msg_id] = null;\n           return;\n       }\n   \n       var buf = Buffer.from(pre_withdraw.receiver_name);\n       var receiver_b64 = buf.toString('base64');\n   \n       if(receiver_b64 != msg_obj.name) {\n           console.log(\"your receiver_name does not match the one from full-node\");\n           pre_pending_withdraw_txs[msg_obj.msg_id] = null;\n           return;\n       }\n   \n       // sendcoin\n       var data_obj = {};\n       data_obj.type = 2;\n       data_obj.pubkey = exchange_account_pubkey_b64;\n       var utc = (Date.now() / 1000);\n       data_obj.utc = parseInt(utc);\n       data_obj.block_id = latest_block_id;\n       data_obj.fee = 2;\n       data_obj.amount = pre_withdraw.amount;\n   \n       if(pre_withdraw.memo \u0026\u0026 pre_withdraw.memo.length \u003e 0) {\n           data_obj.memo = Buffer.from(pre_withdraw.memo).toString('base64');\n       }\n   \n       data_obj.receiver = msg_obj.pubkey;\n       var tx_hash_raw = hash.sha256().update(hash.sha256().update(JSON.stringify(data_obj)).digest()).digest();\n       var tx_id = Buffer.from(tx_hash_raw).toString('base64');\n       var sign = exchange_account_privkey.sign(tx_hash_raw).toDER();\n       var sign_b64 = Buffer.from(sign).toString('base64');\n       ws.send(JSON.stringify({\n           msg_type: 2,\n           msg_cmd: 0,\n           msg_id: 0,\n           sign: sign_b64,\n           data: data_obj\n       }));\n   \n       var withdraw_info = {};\n       withdraw_info.sender_name = pre_withdraw.sender_name;\n       withdraw_info.tx_id = tx_id;\n       withdraw_info.block_id = data_obj.block_id;\n       withdraw_info.utc = data_obj.utc;\n       withdraw_info.receiver_name = pre_withdraw.receiver_name;\n       withdraw_info.receiver_id = pre_withdraw.receiver_id;\n       withdraw_info.amount = pre_withdraw.amount;\n       withdraw_info.memo = data_obj.memo;\n       pending_withdraw_txs[tx_id] = withdraw_info;\n       pre_pending_withdraw_txs[withdraw_unique_id] = null;\n   }\n   ```\n\n4. Similar to the **EXCHANGE_DEPOSIT_TX_PROBE** message, the withdrawal process also needs to send **EXCHANGE_WITHDRAW_TX_PROBE** message periodically to confirm whether enough confirmations have been received from miners.\n\n   ```javascript\n   setTimeout(function() {\n       // send EXCHANGE_WITHDRAW_TX_PROBE message\n       ws.send(JSON.stringify({\n           msg_type: 6,\n           msg_cmd: 3,\n           msg_id: 0,\n           block_id: withdraw_info.block_id,\n           tx_id: tx_id\n       }));\n   }, 10000);\n   ```\n\nYou can refer to the [***exchange_api.js***](api_usage/exchange_api.js) file in the **api_usage** directory for a complete usage of the exchange api, which contains all the examples needed for deposit and withdrawal.\n\n\n\n\n\n## Generate registration string programmatically\n\nIf you want to generate registration string for new users programmatically, you can do like this:\n\n```javascript\n// how to generate registration sign string\nvar data_obj = {};\ndata_obj.block_id = latest_block_id;\ndata_obj.fee = 2;\ndata_obj.name = Buffer.from(\"username\").toString('base64');\n\n// change the public key in the following line to your own\ndata_obj.referrer = 'BC9YHbvohhgCxA+8FbHbcJozcVKl0W9ltw3veDxzO066ulbmu19Hb4kY2OS3NnNmIDFNKSzh8fjl7u6KqcUoWQA=';\nvar data_obj_hash_raw = hash.sha256().update(hash.sha256().update(JSON.stringify(data_obj)).digest()).digest();\nvar sign = your_privkey.sign(data_obj_hash_raw).toDER();\nvar sign_b64 = Buffer.from(sign).toString('base64');\nvar sign_string = '{\"sign\":\"' + sign_b64 + '\",\"sign_data\":' + JSON.stringify(data_obj) + '}';\nconsole.log(\"sign_string is:\", sign_string);\n```\n\nYou can refer to the [***askcoin-gen-reg-sign***](https://github.com/lichuan/askcoin-gen-reg-sign) for a complete usage of the process of generating registration string.\n\n\n\n\n\n## Explorer \u0026 Mobile app\n\n- Block explorer: https://github.com/lichuan/askcoin-explorer\n- Mobile app: https://github.com/lichuan/askcoin-client\n\n\n\n\n\n## Big data on the chain\n\nWith more and more users and transactions, the data on the block chain will become larger and larger. This will bring higher and higher costs to the people who run the full node. In fact, since the beginning of askcoin's design, the problem of data expansion on the chain has been considered. Askcoin is designed to focus on decentralization and real-time Q\u0026A, the lifetime of each topic (or question) is about one day (equivalent to 4320 block intervals). When you run askcoin for several years, the amount of data on the chain may exceed what you can accept, you can freely cut out the expired topics from the chain and choose a widely accepted block as the merging point. You can safely delete all previous blocks, just keep all account information generated until the merge point. This process is also called pruning and merging. As long as the protocol of communication between all nodes remains unchanged or compatible, there will be no adverse impact, you can refer to [***askcoin-merge-point***](https://github.com/lichuan/askcoin-merge-point) for more information.\n\n![merge](res/merge.jpg)\n\n\n\n\n\n## Donation\n\nAt present, the development of askcoin is funded by ourselves. If you want to provide some financial assistance for this project, you can transfer some BTC to the address below:\n\n**1HiAvroczUyjBWQTCfZJigAB5QoUeP1U7S**\n\nThank you for your support !\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flichuan%2Faskcoin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flichuan%2Faskcoin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flichuan%2Faskcoin/lists"}