Blockchain has the potential to change the way that the world approaches data. Develop Blockchain skills by understanding the data model behind Blockchain by developing your own simplified private blockchain. This projects provides a easy way to communicate with the private NodeJS blockchain, allowing clients to request block data for a given height and to create new blocks.
- Method 1: request a validation
- Method 2: validate the request with a signature
- Method 3: add a block with star data
- Method 4: get block by hash
- Method 5: get blocks create by address
- Method 6: get block by height
This project depends on NodeJS to work, you can download it and install it for your platform from here
npm install
All the necessary packages are automatically installed by npm based on the package.json file
- bitcoinjs-message v2.0.0 to sign and verify bitcoin signatures
- boom v7.3.0 for easy hapi.js exception handling
- crypto-js v3.1.9-1 to generate SHA256 hashes and crypto related functionality
- hapi v18.1.0 NodeJS framework to create REST API
- hex2ascii v0.0.3 Convert hex to ascii in JavaScript.
- level v4.0.0 Fast & simple storage. A Node.js-style LevelDB wrapper.
The server runs on localhost, port 8000. To execute the NodeJS app run the following
node BlockAPI.js
The server and port are showed in the console, as well as the current Blockheight
Server running at: http://localhost:8000
Current Blockchain Height 0
This API allows to claim ownership of a star by proving the signature of a message using a bitcoin wallet.
This works as follows:
- User starts the process by sending a request to the
/requestValidation
API Endpoint sending a JSON object with the bitcoin address that is going to be used for start ownership claiming, the method returns a JSON object with the message to be signed and the request is registered with a time out of 5 minutes - User sends a request to
/message-signature/validate
API Endpoint with the address and signature generated by her/his wallet for validation, if the signature is valid tha request is processed and gives user 5 minutes to send star data - User sends star data to
/block
API Endpoint to add it to the blockchain, the star object and previuous requests are validated before the process - User can retreive star data by hash (
/stars/hash:{hash}
), by address (/stars/address:{address}
) or height (/block/{height}
)
Adds a request to the mempool with the address sent as parameter, each call to this method will update the time left for signature validation (validationWindow)
- Method:
POST
- URL:
/requestValidation
- Required parameters:
{ "address":"19xaiMqayaNrn3x7AjV5cU4Mk5f5prRVpL" }
{
"walletAddress": "19xaiMqayaNrn3x7AjV5cU4Mk5f5prRVpL",
"requestTimeStamp": "1544451269",
"message": "19xaiMqayaNrn3x7AjV5cU4Mk5f5prRVpL:1544451269:starRegistry",
"validationWindow": 300
}
- 200 - Success: the request was added to the mempool and a valid JSON response was returned
- 400 - An invalid JSON object was sent, like an empty or malformed JSON or missing address property
- 500 - An error ocurred when processing the request
Validates the request checking that the signature sent as parameter is valid and signed with the address of the initial request, then it returns the validated request object with time validationWindow updated
- Method:
POST
- URL:
/message-signature/validate
- Required parameters:
{
"address":"19xaiMqayaNrn3x7AjV5cU4Mk5f5prRVpL",
"signature":"H8K4+1MvyJo9tcr2YN2KejwvX1oqneyCH+fsUL1z1WBdWmswB9bijeFfOfMqK68kQ5RO6ZxhomoXQG3fkLaBl+Q="
}
{
"registerStar": true,
"status": {
"address": "19xaiMqayaNrn3x7AjV5cU4Mk5f5prRVpL",
"requestTimeStamp": "1544454641",
"message": "19xaiMqayaNrn3x7AjV5cU4Mk5f5prRVpL:1544454641:starRegistry",
"validationWindow": 193,
"messageSignature": true
}
}
- 200 - Success: the request and signature was correctly validated and verified, so it's added to the valid mempool, a JSON response was returned
- 400 - An invalid JSON object was sent, like an empty or malformed JSON or missing address or signature property
- 403 - The signature couldn't be verified so a validated request won't be saved in the valid mempool
- 500 - An error ocurred when processing the request
After right previous request validations adds a new block to the levelDB BlockChain saving in the block's body the star data object
- Method:
POST
- URL:
/block
- Required parameters:
{
"address": "19xaiMqayaNrn3x7AjV5cU4Mk5f5prRVpL",
"star": {
"dec": "68° 52' 56.9",
"ra": "16h 29m 1.0s",
"story": "Found star using https://www.google.com/sky/"
}
}
{
"hash": "8098c1d7f44f4513ba1e7e8ba9965e013520e3652e2db5a7d88e51d7b99c3cc8",
"height": 1,
"body": {
"address": "19xaiMqayaNrn3x7AjV5cU4Mk5f5prRVpL",
"star": {
"ra": "16h 29m 1.0s",
"dec": "68° 52' 56.9",
"story": "466f756e642073746172207573696e672068747470733a2f2f7777772e676f6f676c652e636f6d2f736b792f"
}
},
"time": "1544455399",
"previousBlockHash": "639f8e4c4519759f489fc7da607054f50b212b7d8171e7717df244da2f7f2394"
}
- 201 - Returns 201 Created HTTP code idicating that the block was correclty added and also returns the JSON object with the added block data
- 400 - An invalid JSON object was sent, like an empty or malformed JSON or missing address or star property
- 403 - The signature couldn't be verified so there's no validated object in the valid mempool, the block won't be added and this error is returned
- 500 - An error ocurred when processing the request
Returns block data for a block with the specified hash
- Method:
GET
- URL:
/stars/hash:{hash}
- Required parameters: string -
{hash}
{
"hash": "a59e9e399bc17c2db32a7a87379a8012f2c8e08dd661d7c0a6a4845d4f3ffb9f",
"height": 1,
"body": {
"address": "142BDCeSGbXjWKaAnYXbMpZ6sbrSAo3DpZ",
"star": {
"ra": "16h 29m 1.0s",
"dec": "-26° 29' 24.9",
"story": "466f756e642073746172207573696e672068747470733a2f2f7777772e676f6f676c652e636f6d2f736b792f",
"storyDecoded": "Found star using https://www.google.com/sky/"
}
},
"time": "1532296234",
"previousBlockHash": "49cce61ec3e6ae664514d5fa5722d86069cf981318fc303750ce66032d0acff3"
}
- 200 - Block data in JSON format
- 404 - A block with specified hash wasn't found
- 500 - An error ocurred when processing the request
Returns an array of blocks created by the specified address
- Method:
GET
- URL:
/stars/address:{address}
- Required parameters: string -
{address}
[
{
"hash": "a59e9e399bc17c2db32a7a87379a8012f2c8e08dd661d7c0a6a4845d4f3ffb9f",
"height": 1,
"body": {
"address": "142BDCeSGbXjWKaAnYXbMpZ6sbrSAo3DpZ",
"star": {
"ra": "16h 29m 1.0s",
"dec": "-26° 29' 24.9",
"story": "466f756e642073746172207573696e672068747470733a2f2f7777772e676f6f676c652e636f6d2f736b792f",
"storyDecoded": "Found star using https://www.google.com/sky/"
}
},
"time": "1532296234",
"previousBlockHash": "49cce61ec3e6ae664514d5fa5722d86069cf981318fc303750ce66032d0acff3"
},
{
"hash": "6ef99fc533b9725bf194c18bdf79065d64a971fa41b25f098ff4dff29ee531d0",
"height": 2,
"body": {
"address": "142BDCeSGbXjWKaAnYXbMpZ6sbrSAo3DpZ",
"star": {
"ra": "17h 22m 13.1s",
"dec": "-27° 14' 8.2",
"story": "466f756e642073746172207573696e672068747470733a2f2f7777772e676f6f676c652e636f6d2f736b792f",
"storyDecoded": "Found star using https://www.google.com/sky/"
}
},
"time": "1532330848",
"previousBlockHash": "a59e9e399bc17c2db32a7a87379a8012f2c8e08dd661d7c0a6a4845d4f3ffb9f"
}
]
- 200 - Array of blocks in JSON format
- 404 - No block with specified address was found
- 500 - An error ocurred when processing the request
Returns block data for a block with the specified hash
- Method:
GET
- URL:
/block/{height}
- Required parameters: string -
{height}
{
"hash": "a59e9e399bc17c2db32a7a87379a8012f2c8e08dd661d7c0a6a4845d4f3ffb9f",
"height": 1,
"body": {
"address": "142BDCeSGbXjWKaAnYXbMpZ6sbrSAo3DpZ",
"star": {
"ra": "16h 29m 1.0s",
"dec": "-26° 29' 24.9",
"story": "466f756e642073746172207573696e672068747470733a2f2f7777772e676f6f676c652e636f6d2f736b792f",
"storyDecoded": "Found star using https://www.google.com/sky/"
}
},
"time": "1532296234",
"previousBlockHash": "49cce61ec3e6ae664514d5fa5722d86069cf981318fc303750ce66032d0acff3"
}
- 200 - Block data in JSON format
- 404 - A block with specified height wasn't found
- 500 - An error ocurred when processing the request
Currently, the API supports two methods:
- http://localhost:8000/api/block/{index} Get block by height - GET - Return a JSON representation of the block with the height passed as parameter
{
"hash": "8b43a6453a8e26cd28bc186e7adf76221005f20e50d0ee9f741faf7bb088d54e",
"height": 2,
"body": "datos2",
"time": "1551744127",
"previousBlockHash": "9e626346fe4f6024e79bf859864837d62df6814e6b7c48249f1feef824a6811d"
}
If an out-of-bounds height is passed, server responds with a 404 HTTP code
{
"statusCode": 404,
"error": "Not Found",
"message": "Block not found."
}
- http://localhost:8000/api/block/ Creates a new block in the chain - POST - Creates a new block with the data passed in the body property of JSON Object sent in the request and returns the new block as response with 201 Create HTTP Code
{"body":"data for the block"}
It is important to indicate the content-type header as application/json
{
"hash":"e32c7fdf49cdf878e690bcfa9dc568f71795e56d55aece0945067e8ba7496bd6",
"height":7,
"body":"data for the block",
"time":"1551829104",
"previousBlockHash":"cdbe67d80e9f865875eecf58cd5960d2967473bd8665a817d741c35e3a86964d"
}
If there's no a valid JSON object sent in the request, the server responds with a 400 HTTP code
{
"statusCode": 400,
"error": "Bad Request",
"message": "You have to specify a valid json object with a body property."
}
│ BlockAPI.js
│ LICENSE.md
│ package-lock.json
│ package.json
│ README.html
│ README.md
│ readmeold.md
│
├───controllers
│ BlockController.js
│ MempoolController.js
│ StarController.js
│
├───model
│ Block.js
│ requestObject.js
│ star.js
│ validRequestObject.js
│
├───services
│ Blockchain.js
│ levelSandbox.js
│ mempool.js
│ simpleChain.js
│
└───util
util.js
This project is licensed under the MIT License, for more information refer to the LICENSE.md file
I would like to thank to all of the Udacity team
Specially to the instructors in the following courses that helped me to make this project possible
- Udacity Blockchain Developer Nanodegree Program (https://www.udacity.com/course/blockchain-developer-nanodegree--nd1309)
- Designing RESTful APIs (https://www.udacity.com/course/designing-restful-apis--ud388)
- Writing READMEs (https://www.udacity.com/course/writing-readmes--ud777)