C代写:COMP30023 Hashcash Mining

实现Bitcoin中的Hashcash Mining算法。

Overview

The aim of this project is to provide you with experience in writing (a) a program that interacts with other programs over a network (socket programming), and (b) multi-threaded applications. Specifically, you will write a server-based proof-of-work solver for the Hashcash mining algorithm used in Bitcoin.

This requires you to implement the functions in the Simple Stratum Text Protocol (SSTP), which is used to format messages between clients and your server program. The SSTP is described in Section 3. Background information related to the the Bitcoin mining process is described in Section 2. Detailed requirements and implementation guidelines are listed in Section 4.

Your program must be written in standard C. Use the POSIX pthread library for multi-threaded tasks. Other dynamic and static libraries are prohibited.

Your program must run on the School of Engineering Linux server digitalis or digitalis2.

Background

Introduction to Bitcoin

Bitcoin is the world’s first successful cryptocurrency and a payment network that is currently valued at more than 20 billion dollars. The system follows a fully decentralised peer-to-peer network topology and transactions take place between users directly without an intermediary. Transactions are verified by network nodes and recorded in a distributed ledger, commonly known as the blockchain.

Bitcoins are created as a reward in a competition where miners offer their computing power to record bitcoin transactions into the blockchain. This activity is called mining and successful miners are rewarded with transaction fees and the ability to create Bitcoins to pay to themselves1 .

In this project, we will not explore the purpose of mining in detail. However, we will focus on the steps necessary for you implement a server program that can execute the mining process using the SHA-256 algorithm. To get you started, please read the document https://en.bitcoin.it/wiki/Proof_of_work

It is important to note, that in general, it is very difficult to produce a valid proof-of-work solution of the mining process as there are 2256 possible outputs for some random input. Therefore, this is a problem that should be solved with some means of multi-threading, which enables you to distribute the workload.

Hashcash Algorithm

The Hashcash algorithm used in the Bitcoin mining process is described below:

Find x such that H(H(x)) = y and y < target
  • H is the SHA-256 hash function (see subsection 2.3)
  • target is a 256-bit unsigned integer, which represents the largest acceptable hash value of some input.
    See Section 4-Stage B for details on how to calculate the target value from an appropriately formatted input protocol message (as described in Sections 3)
  • x is defined as a seed value concatenated with nonce i.e., seed | nonce where:
    • seed is a 64 byte array, which is provided by a client through a protocol message (see Section 3 for details)
    • nonce is a 64 bit unsigned integer (nonce basically means “number once” ie., an arbitrary number that may only be used once.)

Hence, the goal is to find a nonce value, which when concatenated with seed creating x, yields a hash that is less than target. To do this, the search starts from some initial nonce value and checks whether the conditions listed above hold. If they do, great, you have a solution. If not, increment the nonce value and try again (and again and again … until a solution is found).

Cryptographic Hash Function SHA-256

Bitcoin’s mining algorithm, Hashcash, utilises a cryptography hash function known as the Secure Hash Algorithm (SHA-2). SHA-2 is a collection of six hash functions with digests (hash-values) that are 224, 256, 384 or 512 bits. For the purposes of our task, we will only be using the SHA-256 to produce a proof-of-work.

Knowing the specifics of how SHA-256 works is not necessary for the purposes of this project. A reference implementation of SHA-256 has been provided for you. The source code can be downloaded from the LMS.

Simple Stratum Text Protocol (SSTP)

Before working through the SSTP messages listed below, you should familiarise yourself with the primitive types provided by the standard C library. In this project, you will also make use of:

  • BYTE : unsigned char
  • uint256 : BYTE[32] You can download source code for uint256 from the LMS

Your server-based proof-of-work solver will use the Simple Stratum Text Protocol (SSTP).

Every protocol message should be delimited with the carriage return, followed by a line feed (i.e., \r\n). You may assume that every protocol message has a pre-defined length. Any message exceeding this pre-defined length will be considered an invalid message and you must handle this correctly with an ERRO message. Every message is comprised of a message header (4-bytes in length) followed by its payload (the length of which depends on the actual message). All network messages must be encoded and parsed in network byte order (i.e., big endian order).

There are seven messages in the protocol - your task in this project is to implement all of them

Ping Message PING

PING

On receive, the server replies with a PONG message.

Pong Message PONG

PONG

Your server should reply with an error message ERRO informing the client that PONG messages are strictly reserved for server responses.

Okay Message OKAY

OKAY

Your server should reply with an error message ERRO explaining that is not “okay” to send OKAY messages to the server.

Error Message ERRO

ERRO reason:  BYTE[40]

Example:

ERRO with an appropriate explanation

On receive, your server should reply with an error message ERRO indicating that this message should not be sent to the server.

Solution Message SOLN

SOLN difficulty:uint32 seed:BYTE[64] solution:uint64
Example:
SOLN 1fffffff 0000000019d6689c085ae165831e934ff763ae46a218a6c
172b3f1b60a8ce26f 10000000232123a2

(Note: line wrap used in seed simply for formatting on the project spec)

On receive, your server should check if the concatenation of the seed and the solution (which is actually a particular nonce value) does in fact produce a hash which satisfies the target requirement derived from the difficulty value (see Section 4-Stage B below for details). Here, an 8 byte hexadecimal representation has been used for the difficulty.

If it is a valid proof-of-work, then you should reply with OKAY. Otherwise, reply with ERRO with a 40-byte string describing what the error is.

Work Message WORK

WORK difficulty:uint32 seed:BYTE[64] start:uint64 worker count:uint8
Example: WORK 1fffffff 0000000019d6689c085ae165831e934ff763ae
46a218a6c172b3f1b60a8ce26f 1000000023212399 02

(Note: line wrap used in seed simply for formatting on the project spec)
Once again, an 8 byte hexadecimal representation has been used for the difficulty. start is the initial nonce value4 and worker count is the number of threads to use in the computation task. See section 2.3 for an explanation of the computation steps.

On receive, your server should queue this work in a work queue. Once a proof-of-work solution is found, reply with the SOLN message with the correct nonce (i.e., the solution field in the SOLN message) which produces the proof-of-work solution.

Abort Message ABRT

ABRT

On receive, your server should traverse the work queue and remove all pending work for the client that sent this message. It should also pre-maturely terminate all active proof of work worker threads. Once this is completed, an OKAY response should be sent.

Requirements

We strongly recommend that you complete the project in four clearly defined stages listed below.

Stage A

Create a simple text-based server capable of handling multiple concurrent requests. This basically means extending the TCP server program introduced in the labs so that it can correctly reply to simple messages received from client programs concurrently.

You will have to make a decision as to the best way to deal with concurrent requests from clients. Begin by implementing a simple plain-text server that is capable of receiving and sending PING/PONG messages. Then add the OKAY and ERRO messages.

Your server should also be able to receive requests (messages) from more than one client at any given time and still be able to manage the processing of protocol messages between all connected clients.

Stage B

Extend your server program from Stage A so that when an appropriately formatted message is received from a client, your server program will parse the message and perform appropriate computations on the parsed message to verify whether the message is a valid solution for the proof-of-work. That is, your server must be capable of validating whether a properly formatted SOLN message contains a valid proof-of-work.

To make things easier for you in Stages B (and Stages C and D) helper functions (i.e., uint256 functions and functions to execute SHA-256) have been provided for you. You can download the source code from the LMS.

Given the fact that the target requires 64 bytes of text space within a block protocol message, a mapping between the target and difficulty in the SOLN message is used. Here, difficulty is represented using a 32 bit unsigned integer and the corresponding mathematical formula to compute the target.

When your server is processing a SOLN message, it still should be able to receive requests from multiple clients and manage the processing of protocol messages between all connected clients. For example, your server must be capable of immediately responding to PING messages with a PONG for a separate client.

Stage C

Your server program will be extended again such that it can compute a proof-of-work for a given WORK message by parsing the input received from the client and creating a specific number of threads to do the actual computations. The solution verification tasks completed in the previous Stage will also be used here.

To complete this task, you will have to maintain a work queue based on the current submitted client WORK messages. You will need to implement a server function that finds a valid proof-of-work for each job in the queue (in turn) by iteratively incrementing the nonce based on a properly formatted WORK message. When you find a solution, the server replies with the SOLN message. To keep things simple, in this Stage you should just use one thread to do the computation.

While searching for the proof-of-work, your server implementation must still be able to respond to all requests from clients. For example, while the search for a proof-of-work solution is carried out, your server must be capable of immediately responding to PING messages with a PONG etc.

Stage D: Bonus marks

In this final bonus mark Stage, you will further extend your server program so that multiple threads (workers) can be used to do the computation (or searching for a proof-of-work ). The actual number of threads to be used will be given in the WORK message.

Your server will need to handle incomplete messages (i.e., messages that have not ended with a delimiter). Your server must store incomplete messages in a buffer and continue to receive the subsequent segments of incomplete messages until the message is delimited or exceeds the maximum message length.

On client disconnection, all queued work from the client should be removed from the work queue. Active worker threads working on searching for proof-of-work solutions should also stop working immediately and should start working on the next work item in the work queue.

Server Log File

You must continually write to a log file (./log.txt)5 detailing each (and every) interaction between the server and individual clients. Each log file entry will include:

  • a time-stamp (system date/time)
  • IP address of the client or 0.0.0.0 for the server
  • a socket id (or file descriptor) for the client connection
  • SSTP message for the exchange between server and client

Note: Your log file should reflect the Stages of the project task that you have completed. If your server crashes you may not have any entries in your log file - so take care.

Limits

The following limits will be used:

  • maximum number of clients: 100
  • maximum number of pending jobs: 10
  • maximum number of processors: unbounded
  • maximum number of threads: unbounded

One final comment: there is no need to handle unsolvable WORK messages. We will not be giving you any unsolvable work.