NAV
shell python

Introduction to BITQAP

Welcome to the BITQAP project! This is blockchain based software. Currently this project under development.

Core block calculation app developed by BASH language, and network interface developed on python3. BITQAP network uses Peer to Peer concept using WebSocket protocol.

We have language bindings in Shell, Python. You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right.

Topology

# download git project
git clone https://github.com/bitqap/bitqap.git

# start server
cd bitqap/bin
python3 socketGateway3.py


# start local miner app (socket) TEST MODE.
./startLocalApp.sh

# another session
./startExternalApp.sh

Alt text

BITQAP uses BITQAP protocol suite on top of the WebSocket and Linux Namad Pipe technology. bashCoin.sh is core script which is manages application (mine, validation, coin send, etc.) bashCoin.sh binded to NAMED_PIPE_BSH (variable) pipe file over ./startLocalApp.sh script. Copy of ./startLocalApp.sh script output writing to NAMED_PIPE_EXT (variable) pipe file also to broadcast external servers and ./startExternalApp.sh script reads this message. NAMED_PIPE_BSH and NAMED_PIPE_EXT file descriptor is 3

Mining steps

Alt text

Steps:

Authentication

To generate Private/Public Key pair use this shell code:

# csr creted for mining node to accept encrypyed connections only over HTTPS
openssl genrsa -aes128 -out username_private.pem 1024
openssl genrsa  -out user.key 2048
openssl req -key user.key -new -out user.csr
openssl rsa -in user.key  -pubout > user.pub

Private/Public key required to do any action.

The BITQAP blockchain does not store any user information. Your private key is your everything. Third-party wallets can bind your email to your private key. However, in theory, the public and private keys are generated and stored on the end device (wallet). Wallet can share the public key with third parties in sha256sum format or QR code format. Wallet signs the transaction message with the private key stored on the end device. Only the Linux shell command for creating the public/private key is available in this documentation.

BITQAP messages

Network check (ping)

# no shell code for this.
python wsdump.py ws://127.0.0.1:8001
> {"command":"ping","messageType":"direct","status":0}

The above command returns JSON structured like this:

    {
        "command": "ping", 
        "messageType": "direct", 
        "destinationSocket": 2, 
        "from": "istehkam.com", 
        "status": 0, 
        "socketID": 1
    }

End point can send ping message periodically. If status:0 then ws ping request is successfull to node.

WS Request

webSocket.send(<JSON>);

message parameters

key value Description
command ping mandatory
messageType direct/broadcast mandatory

Account information

# this is your userid. You can share by text or QR code.
cat cert/example.com.pub| sha256sum  | awk '{print $1}'

The above command returns TXT structured like this:

497cea9f5af23c76922d7bfc6237d8e225248887defcc333f36ba853a1266848

Your account is sha256sum of Public key. In future other accounts will use this info to coins. You can provide this account as URL or QR code

no WS Request

message parameters.

key value Description
N/A N/A N/A

start mining

> cd bin
> ./bashCoin.sh '{"command":"mine","appType":"miner","messageType":"direct"}'
python wsdump.py ws://127.0.0.1:8001
> {"command":"mine","appType":"miner","messageType":"direct"}

The above command returns JSON structured like this:

{
  "command":"notification",
  "commandCode":"100",
  "appType":"miner",
  "messageType":"broadcast",
  "status":"0", 
  "timeUTC":"20211128102607",
  "difficulty":"1",
  "MINEDBLOCK":"163.blk.solved",
  "NEXTBLOCK":"164.blk"
}

Mine will insert the top transactions from the queue with the 100 highest into the next block and start calculating.

Steps:

WS Request

webSocket.send(<JSON>");

message parameters

key value Description
command mine mandatory
appType miner/wallet optional
messageType direct/broadcast mandatory

check balance

cd bin
./bashCoin.sh '{"command":"checkbalance","ACCTNUM":"50416596951b715b7e8e658de7d9f751fb8b97ce4edf0891f269f64c8fa8e034","messageType":"direct"}'
python wsdump.py ws://127.0.0.1:8001
> {"command":"checkbalance","ACCTNUM":"50416596951b715b7e8e658de7d9f751fb8b97ce4edf0891f269f64c8fa8e034","messageType":"direct"}

The above command returns JSON structured like this:

  {
    "command": "checkbalance", 
    "commandCode": "200", 
    "messageType": "direct", 
    "status": "0", 
    "destinationSocket": "4", 
    "result": 
      {
        "publicKeyHASH256": "50416596951b715b7e8e658de7d9f751fb8b97ce4edf0891f269f64c8fa8e034", 
        "balance": "46"
      }
    }

This function will use UTXO method to calculate balance. Once balance calculate it wil add to block as latest information and signature will included. If TX found <pubkey1>:<pubkey1>:<AMOUNT>:...<PUBKEY>:<SIGNATURE> then will return balance.

WS Request

webSocket.send(<JSON>");

message parameters

key value Description
command checkbalance mandatory
messageType direct/broadcast mandatory
ACCTNUM sha256 hash of Pub key mandatory

send coin

#full message

fullMessage='{"command": "getTransactionMessageForSign", "status": 0, "destinationSocket": "2", "result": {"forReciverData": "50416596951b715b7e8e658de7d9f751fb8b97ce4edf0891f269f64c8fa8e034:b1bd54c941aef5e0096c46fd21d971b3a3cf5325226afb89c0a9d6845a491af6:5:3:202111121313", "forSenderData": "50416596951b715b7e8e658de7d9f751fb8b97ce4edf0891f269f64c8fa8e034:50416596951b715b7e8e658de7d9f751fb8b97ce4edf0891f269f64c8fa8e034:38:0:202111121313"}}'

# key pair
privKey="/root/bashCo1/cert/example.com.key"
publKey="/root/bashCo1/cert/example.com.pub"

# orignal raw message need to be hashed for TxID
rawMsgRecv=$(echo $fullMessage | jq -r '.result' | jq -r '.forReciverData')
rawMsgSend=$(echo $fullMessage | jq -r '.result' | jq -r '.forSenderData')

# hash sha256
txIDRecv=$(echo ${rawMsgRecv}| sha256sum | awk '{print $1}')
txIDSend=$(echo ${rawMsgSend}| sha256sum | awk '{print $1}')

# raw message need to be signed (txID included)
OrigMSG_Recv=$(echo "TX$txIDRecv:$rawMsgRecv")
OrigMSG_Send=$(echo "TX$txIDSend:$rawMsgRecv")

# encoded Public key as base64 
pubKeyBase64=$(cat ${publKey}| base64 | tr '\n' ' ' | sed 's/ //g')

# signatures of both messages
signedMsgRecv=$(echo ${OrigMSG_Recv}| openssl dgst -sign ${privKey} -keyform PEM -sha256 | base64 | tr '\n' ' ' | sed 's/ //g')
signedMsgSend=$(echo ${OrigMSG_Send}| openssl dgst -sign ${privKey} -keyform PEM -sha256 | base64 | tr '\n' ' ' | sed 's/ //g')

# construct of messages
recv="$OrigMSG_Recv:$pubKeyBase64:$signedMsgRecv"
send="$OrigMSG_Send:$pubKeyBase64:$signedMsgSend"

# build JSON
result=[]
# add reciever msg
result=$(echo ${result}| jq --arg dt $recv '. + [ $dt ]')
# add sender msg
result=$(echo ${result}| jq --arg dt $send '. + [ $dt ]')

# Full messages
returnMesssage="{\"command\":\"pushSignedMessageToPending\", \"messageType\": \"direct\", \"result\":$result}"

echo $returnMesssage

python wsdump.py ws://127.0.0.1:8001
>  { "command":"getTransactionMessageForSign","messageType":"direct","result":{"forReciverData":"50416596951b715b7e8e658de7d9f751fb8b97ce4edf0891f269f64c8fa8e034:b1bd54c941aef5e0096c46fd21d971b3a3cf5325226afb89c0a9d6845a491af6:5:3:202111121313","forSenderData":"50416596951b715b7e8e658de7d9f751fb8b97ce4edf0891f269f64c8fa8e034:50416596951b715b7e8e658de7d9f751fb8b97ce4edf0891f269f64c8fa8e034:38:0:202111121313"}}

# used shell section to build message. Unfortunatelly pytyon code is not ready to build signed message
> {"command":"pushSignedMessageToPending", "messageType": "direct", "result":["message1...","message2..."]}

The above command returns JSON structured like this for getTransactionMessageForSign command. result message will be signed by Wallet and send back by pushSignedMessageToPending command. :

{
  "command": "getTransactionMessageForSign", 
  "messageType": "direct", 
  "status": 0, 
  "destinationSocket": 2, 
  "result": 
    {
      "forReciverData": "50416596951b715b7e8e658de7d9f751fb8b97ce4edf0891f269f64c8fa8e034:b1bd54c941aef5e0096c46fd21d971b3a3cf5325226afb89c0a9d6845a491af6:5:3:202111121313", 
      "forSenderData": "50416596951b715b7e8e658de7d9f751fb8b97ce4edf0891f269f64c8fa8e034:50416596951b715b7e8e658de7d9f751fb8b97ce4edf0891f269f64c8fa8e034:38:0:202111121313"
    }, 
    "socketID": 1}

The above command returns JSON structured like this for pushSignedMessageToPending command:

{
  "command": "notification", 
  "tag": "FFFFx0", 
  "status": 0, 
  "commandCode": "402", 
  "exceptSocket": [3], 
  "messageType": "broadcast", 
  "result": 
    ["TX0aea1917ee5c4e1090f264ebb3d00269775b6c0a853f64c30abcae47b4edfd16","TXe6d2642c00c9a782b58a0d5b7f0f537282f9257b736cc97648d8589701a02a85"], 
  "socketID": 1
}

Send coint consist of 2 steps. getTransactionMessageForSign and pushSignedMessageToPending commands.

getTransactionMessageForSign is used for get message from Node (with balance info). pushSignedMessageToPending is used for to sign message with Wallet privsate key and push to Node (pending transactions).

  1. When you send coin to someone you need to use getTransactionMessageForSign command.
  2. Response for getTransactionMessageForSign command will get 2 message (for reciever and for sender).
  3. Each message need to reconstruct separately and push to pending transaction by pushSignedMessageToPending command.

Message reconstruction steps

Step1. Parse forReciverData and forSenderData
Step2. Calculate sha256 hash sum of message and make TX ID ( txID=TX$hash256(message) )
Step3. Construct message by adding TX info. (message=$txID:$message)
Step4. Encode public key by base64. (pubKeyBASE64=base64(key.pub))
Step5. Sign message with private key (signature=dgstSign(message))
Step6. Encode signature by base64. (sign=base64(signature))
Step7. Reconstruct message again. message=$message:$pubKeyBASE64:$signature

Follow same steps for forReciverData and forSenderData message and push to block in result list object by pushSignedMessageToPending command

WS Request

webSocket.send(<JSON>");

getTransactionMessageForSign message parameters

key value Description
command getTransactionMessageForSign mandatory
messageType direct mandatory
result list mandatory
forReciverData text mandatory
forSenderData text mandatory

pushSignedMessageToPending message parameters

key value Description
command pushSignedMessageToPending mandatory
messageType direct mandatory
result list mandatory

get history

cd bin
./bashCoin.sh '{"command":"getHistory","messageType":"direct","account":"50416596951b715b7e8e658de7d9f751fb8b97ce4edf0891f269f64c8fa8e034","messageType":"direct"}'
python wsdump.py ws://127.0.0.1:8001
> {"command":"getHistory","messageType":"direct","account":"50416596951b715b7e8e658de7d9f751fb8b97ce4edf0891f269f64c8fa8e034","messageType":"direct"}

The above command returns JSON structured like this:

  {
    "command": "getHistory", 
    "commandCode": "403", 
    "messageType": "direct", 
    "status": "0", 
    "destinationSocket": "4",
    "responseID":"a121dfrwesff33"
    "txHistory": 
      [
        "TX808a7828b2f0c27d3fa01ce4f4...:REWARD:504165969...:2:0:20211029225028:in", 
        "TXda48dd60ae50ca61c9828743b8...:REWARD:504165969...:2:0:20211029225055:in",
        "TXd4fsdf60ae50ca61c9828743b8...:bca2504165969df...:504165969...:2:0:20211029225055:in"
      ]
    }

This method to get historical transactions for requested account Message will return transactions in list with ":" seprated

transaction fields

column value Description
:1 txID transaction ID in HASH
:2 Sender hashSHA256(pubKey)
:3 Reciever hashSHA256(pubKey)
:4 Amount amount of transfered coin
:5 Fee fee for transaction (commision)
:6 Tranaction time Tranaction time in UTC
:7 Direction incoming or outgoing

WS Request

webSocket.send(<JSON>");

message parameters

key value Description
command getHistory mandatory
messageType direct/broadcast mandatory
account sha256 hash of Pub key mandatory

Errors


> cat bin/functMapFunc2Code.sh

mapERRORFunction2Code () {
        funcName=$1
        case "$funcName" in 
                mine)
                                code=500
                                ;;
                mineGenesis)
                                code=501
                                ;;
                checkAccountBal)
                                code=510
                                ;;
                getTransactionMessageForSign)
                                code=511
                                ;;
                pushSignedMessageToPending)
                                code=512
                                ;;
                AddBlockFromNetwork)
                                code=520
                                ;;
                listNewBlock)
                                code=521
                                ;;
                provideBlocks)
                                code=522
                                ;;
                validateNetworkBlockHash)
                                code=523
                                ;;
                updateNetworkInfo)
                                code=401
                                ;;
                *)
                                code=000
                                ;;
        esac
        echo $code
}

Function Error Code
mine 1500
mineGenesis 1501
checkAccountBal 1510
getTransactionMessageForSign 1511
AddTransactionFromNetwork 1512
pushSignedMessageToPending 1513
askBlockContent 1514
provideTXMessage 1515
AddNewBlockFromNode 1520
listNewBlock 1521
provideBlockContent 1522
validateNetworkBlockHash 1523
askBlockContent 1514
updateNetworkInfo 1401fo

You can add your own ERROR code to bin/functMapFunc2Code.sh file and call from functions.