Programming - Implementing a Blockchain using Python and Flask [Dev Blog 3]

[Image 1]


Hey it's a me again drifter1!

And with this post, we reach the third dev blog for the Blockchain implementation. I was quite busy during these days, and so there are some very important additions to cover!

First off, transactions can now be retrieved, posted or cancelled, through specialized endpoints that access the local to-each-client file. As such, the transactions.json file now acts as a "database" of unconfirmed transactions. Of course, a draft class and JSON format have also been defined, with all needed helper functions. For now, only the correct JSON format is being checked and not if the transaction can truly be allowed etc. All the important checks are, for the time, being skipped.

Next up, is the addition of block-specific endpoints. A draft class and JSON format have been defined for the block structure, and a total of four (for now) endpoints. Using these endpoints its possible to access the blocks directory of the corresponding client. As such, its possible to either create a new block (with no checks for now), or retrieve a block. For each specific block its also possible to request only the transactions, or even a specific transaction.

So, without further ado, let's get straight into it!

GitHub Repository

Transaction Structure

In actual blockchain implementations, transactions usually consist of various inputs and outputs. Each such input, be it an address or block reward, is validated by a signature that proves that the input is accessed by the corresponding owner. And during the transaction, each output receives the corresponding value, which is sent. That way, during a follow-up transaction, an output can become an input.

Of course, having multiple inputs and outputs can become quite tedious, and in order to avoid complications, I chose to start with one input and output, or sender and receiver as I call them in my implementation. A transaction is posted at a specific date and time, which is stored as a timestamp, and also contains the value being sent, as well as a fee (reward for the miner/validator). Lastly, a hash is calculated for all of the above data, and the sender hashes that hash again using the private key in order to generate a signature. This is an oversimplification of events, but I think that it's OK for now!

In JSON format, the current transaction structure is as follows:

    "timestamp": timestamp,
    "sender": sender,
    "receiver": receiver,
    "value": value,
    "fee": fee,
    "hash": hash,
    "signature": signature
and together with the class and helper defined in the file.

Transaction Endpoints

Now, for the endpoints that are needed for such unconfirmed transactions. Of course, the miner/validator needs to be able to retrieve such transactions, and so the first endpoint is:

  • GET ip_address:port/transactions/
This request returns the array of transactions, as it's stored in the local to-that-client transactions.json file.

In order to post a new transaction, I specified:

  • POST ip_address:port/transactions/
which needs to contain the correct JSON format transaction in the request body, and returns it back, if successful (for now).

Lastly, its also possible to cancel a posted transaction using:

  • DELETE ip_address:port/transactions/
This request is again combined with a JSON transaction in the request body, and is returned if successful!

All these endpoints are defined in the file, and included in the client using:

from common.transaction_endpoints import transaction_endpoints
transaction_endpoints(app, settings)

Of course some more endpoints need to be specified, in order to combine the unconfirmed transactions functionality with the block creation and validation. But, it's too soon for that!

Block Structure

Next up, is the block structure. A block is created in order for the unconfirmed transactions to be processed, and as such, contains an array of transactions. In addition to that, a block contains a timestamp, the block height, block reward, reward address, nonce, block hash and previous block hash. Most are self-explainatory. The previous hash is included in order to achieve the required security, and a block reward and address are included for the sake of "pushing" people into mining/validating.

In JSON format the block looks like this:

    "timestamp": timestamp,
    "height": height,
    "reward": reward,
    "reward_address": reward_address,
    "nonce": nonce,
    "transactions": transactions,
    "hash": hash,
    "prev_hash": prev_hash
and together with the corresponding class, and helper function, it's defined in the file.

Block-specific Endpoints

For blocks the following endpoints have been defined:

As such, after posting a test block using the POST endpoint:

it's possible to retrieve that block as a whole:

or the transactions only:

or even a specific transaction:

Retrieval, is basically done at that point, and so only the actual confirmation and validation of the block and its transactions needs to be implemented!

The endpoints are specified in the file, and included in the client as follows:

from common.block_endpoints import block_endpoints
block_endpoints(app, settings)

Of course there is a lot of Flask callback code, and local and general request helper functions have also been defined for the sake of readability!

I guess the hype has now increased by a significant margin! I'm also hyped, and can't wait to get more in-depth into the far more important and interesting topics!





The rest is screenshots or made using

Previous dev blogs of the series

Final words | Next up

And this is actually it for today's post!

I will keep you posted on my journey! Expect such articles to come out weekly, or even twice a week, until I'm finished!

Keep on drifting!

3 columns
2 columns
1 column