Copied TCP impl from other project, basic Block implementation, randomx pow, signing via secp256k1
This commit is contained in:
11
include/balance_sheet.h
Normal file
11
include/balance_sheet.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef BALANCE_SHEET_H
|
||||
#define BALANCE_SHEET_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t address[32]; // For now just the SHA-256 of the public key; allows representation in different encodings (base58, bech32, etc) without changing the underlying data structure
|
||||
uint64_t balance;
|
||||
} balance_sheet_entry_t;
|
||||
|
||||
#endif
|
||||
36
include/block/block.h
Normal file
36
include/block/block.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef BLOCK_H
|
||||
#define BLOCK_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <dynarr.h>
|
||||
#include <block/transaction.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <randomx/librx_wrapper.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t version;
|
||||
uint32_t blockNumber;
|
||||
uint8_t prevHash[32];
|
||||
uint8_t merkleRoot[32];
|
||||
uint64_t timestamp;
|
||||
uint32_t difficultyTarget; // Encoding: [1 byte exponent][3 byte coefficient]; Target = coefficient * 256^(exponent-3)
|
||||
uint64_t nonce; // Higher nonce for RandomX
|
||||
} block_header_t;
|
||||
|
||||
typedef struct {
|
||||
block_header_t header;
|
||||
DynArr* transactions; // Array of signed_transaction_t
|
||||
} block_t;
|
||||
|
||||
block_t* Block_Create();
|
||||
void Block_CalculateHash(const block_t* block, uint8_t* outHash);
|
||||
void Block_CalculateRandomXHash(const block_t* block, uint8_t* outHash);
|
||||
void Block_AddTransaction(block_t* block, signed_transaction_t* tx);
|
||||
void Block_RemoveTransaction(block_t* block, uint8_t* txHash);
|
||||
bool Block_HasValidProofOfWork(const block_t* block);
|
||||
bool Block_AllTransactionsValid(const block_t* block);
|
||||
void Block_Destroy(block_t* block);
|
||||
|
||||
#endif
|
||||
20
include/block/chain.h
Normal file
20
include/block/chain.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef CHAIN_H
|
||||
#define CHAIN_H
|
||||
|
||||
#include <block/block.h>
|
||||
#include <dynarr.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct {
|
||||
DynArr* blocks;
|
||||
size_t size;
|
||||
} blockchain_t;
|
||||
|
||||
blockchain_t* Chain_Create();
|
||||
void Chain_Destroy(blockchain_t* chain);
|
||||
bool Chain_AddBlock(blockchain_t* chain, block_t* block);
|
||||
block_t* Chain_GetBlock(blockchain_t* chain, size_t index);
|
||||
size_t Chain_Size(blockchain_t* chain);
|
||||
bool Chain_IsValid(blockchain_t* chain);
|
||||
|
||||
#endif
|
||||
48
include/block/transaction.h
Normal file
48
include/block/transaction.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef TRANSACTION_H
|
||||
#define TRANSACTION_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <crypto/crypto.h>
|
||||
|
||||
// Special sender/recipient address marker for coinbase logic: 32 bytes of 0xFF.
|
||||
static inline bool Address_IsCoinbase(const uint8_t address[32]) {
|
||||
if (!address) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 32; ++i) {
|
||||
if (address[i] != 0xFF) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 178 bytes total for v1
|
||||
typedef struct {
|
||||
uint8_t version;
|
||||
uint8_t senderAddress[32];
|
||||
uint8_t recipientAddress[32];
|
||||
uint64_t amount;
|
||||
uint64_t fee; // Rewarded to the miner; can be zero, but the miner may choose to ignore transactions with very low fees
|
||||
uint8_t compressedPublicKey[33];
|
||||
// Timestamp is dictated by the block
|
||||
} transaction_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t txHash[32];
|
||||
uint8_t signature[64]; // Signature of the hash
|
||||
} transaction_sig_t;
|
||||
|
||||
typedef struct {
|
||||
transaction_t transaction;
|
||||
transaction_sig_t signature;
|
||||
} signed_transaction_t;
|
||||
|
||||
void Transaction_CalculateHash(const signed_transaction_t* tx, uint8_t* outHash);
|
||||
void Transaction_Sign(signed_transaction_t* tx, const uint8_t* privateKey);
|
||||
bool Transaction_Verify(const signed_transaction_t* tx);
|
||||
|
||||
#endif
|
||||
13
include/crypto/crypto.h
Normal file
13
include/crypto/crypto.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef CRYPTO_H
|
||||
#define CRYPTO_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <secp256k1.h>
|
||||
|
||||
bool Crypto_VerifySignature(const uint8_t* data, size_t len, const uint8_t* signature, const uint8_t* publicKey);
|
||||
void Crypto_SignData(const uint8_t* data, size_t len, const uint8_t* privateKey, uint8_t* outSignature);
|
||||
|
||||
#endif
|
||||
60
include/dynarr.h
Normal file
60
include/dynarr.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#ifndef DYNARR_H
|
||||
#define DYNARR_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DYNARR_MAX_CAPACITY ((size_t)0x7FFFFFFF)
|
||||
|
||||
typedef struct {
|
||||
size_t size;
|
||||
size_t elemSize;
|
||||
size_t capacity;
|
||||
void* data;
|
||||
} DynArr;
|
||||
|
||||
// Do not use; Use DYNARR_CREATE macro instead.
|
||||
DynArr* DynArr_create(size_t elemSize, size_t capacity);
|
||||
|
||||
// Reserve n blocks in arary; New size will be n, NOT size + n; Reserving less memory that current will fail, use prune instead.
|
||||
void DynArr_reserve(DynArr* p, size_t n);
|
||||
|
||||
// Push data into a new block at the end of the array
|
||||
void* DynArr_push_back(DynArr* p, void* value);
|
||||
|
||||
// Remove the last block in the array.
|
||||
void DynArr_pop_back(DynArr* p);
|
||||
|
||||
// Remove first block from array.
|
||||
void DynArr_pop_front(DynArr* p);
|
||||
|
||||
// Remove index from array. This moves all blocks after the index block.
|
||||
void DynArr_remove(DynArr* p, size_t index);
|
||||
|
||||
// Erase the array. This will not free unused blocks.
|
||||
void DynArr_erase(DynArr* p);
|
||||
|
||||
// Prune and free unused blocks. If pruning to zero, ensure to reserve after.
|
||||
void DynArr_prune(DynArr* p);
|
||||
|
||||
// Get a pointer to a block by index
|
||||
void* DynArr_at(DynArr* p, size_t index);
|
||||
|
||||
// Get the index by block pointer
|
||||
size_t DynArr_at_ptr(DynArr* p, void* ptr);
|
||||
|
||||
// Get size
|
||||
size_t DynArr_size(DynArr* p);
|
||||
|
||||
// Get element size
|
||||
size_t DynArr_elemSize(DynArr* p);
|
||||
|
||||
// Get capacity
|
||||
size_t DynArr_capacity(DynArr* p);
|
||||
|
||||
void DynArr_destroy(DynArr* p);
|
||||
|
||||
#define DYNARR_CREATE(T, initialCapacity) DynArr_create(sizeof(T), initialCapacity)
|
||||
|
||||
#endif
|
||||
20
include/dynset.h
Normal file
20
include/dynset.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef DYNSET_H
|
||||
#define DYNSET_H
|
||||
|
||||
#include <dynarr.h>
|
||||
|
||||
// Dynamic Set structure - basically DynArr with uniqueness enforced
|
||||
typedef struct {
|
||||
DynArr* arr;
|
||||
} DynSet;
|
||||
|
||||
// Function prototypes
|
||||
DynSet* DynSet_Create(size_t elemSize);
|
||||
void DynSet_Destroy(DynSet* set);
|
||||
int DynSet_Insert(DynSet* set, const void* element);
|
||||
int DynSet_Contains(DynSet* set, const void* element);
|
||||
size_t DynSet_Size(DynSet* set);
|
||||
void* DynSet_Get(DynSet* set, size_t index);
|
||||
void DynSet_Remove(DynSet* set, const void* element);
|
||||
|
||||
#endif
|
||||
14
include/numgen.h
Normal file
14
include/numgen.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef NUMGEN_H
|
||||
#define NUMGEN_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
unsigned char random_byte(void);
|
||||
uint16_t random_two_byte(void);
|
||||
uint32_t random_four_byte(void);
|
||||
uint64_t random_eight_byte(void);
|
||||
|
||||
#endif
|
||||
18
include/packettype.h
Normal file
18
include/packettype.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef PACKETTYPE_H
|
||||
#define PACKETTYPE_H
|
||||
|
||||
typedef enum {
|
||||
PACKET_TYPE_NONE = 0,
|
||||
PACKET_TYPE_HELLO = 1,
|
||||
PACKET_TYPE_TASK_ASSIGN = 2,
|
||||
PACKET_TYPE_TASK_RESULT = 3,
|
||||
PACKET_TYPE_STATUS_UPDATE = 4,
|
||||
PACKET_TYPE_CLIENT_CAPABILITIES = 5,
|
||||
PACKET_TYPE_TASK_REQUEST = 6,
|
||||
PACKET_TYPE_MISSING_INFO = 7,
|
||||
PACKET_TYPE_ACKNOWLEDGE = 8,
|
||||
PACKET_TYPE_TASK_REJECT = 9,
|
||||
PACKET_TYPE_TASK_NONE_AVAILABLE = 10
|
||||
} PacketType;
|
||||
|
||||
#endif
|
||||
21
include/randomx/librx_wrapper.h
Normal file
21
include/randomx/librx_wrapper.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef LIBRX_WRAPPER_H
|
||||
#define LIBRX_WRAPPER_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <randomx.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool RandomX_Init(const char* key);
|
||||
void RandomX_Destroy();
|
||||
void RandomX_CalculateHash(const uint8_t* input, size_t inputLen, uint8_t* output);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
29
include/tcpd/tcpclient.h
Normal file
29
include/tcpd/tcpclient.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef TCPCLIENT_H
|
||||
#define TCPCLIENT_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <dynarr.h>
|
||||
|
||||
#define MTU 1500
|
||||
|
||||
struct TcpClient {
|
||||
int clientFd;
|
||||
struct sockaddr_in clientAddr;
|
||||
uint32_t clientId;
|
||||
|
||||
unsigned char dataBuf[MTU];
|
||||
ssize_t dataBufLen;
|
||||
void (*on_data)(struct TcpClient* client);
|
||||
void (*on_disconnect)(struct TcpClient* client);
|
||||
|
||||
pthread_t clientThread;
|
||||
};
|
||||
|
||||
typedef struct TcpClient TcpClient;
|
||||
|
||||
#endif
|
||||
56
include/tcpd/tcpserver.h
Normal file
56
include/tcpd/tcpserver.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#ifndef TCPSERVER_H
|
||||
#define TCPSERVER_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <tcpd/tcpclient.h>
|
||||
#include <numgen.h>
|
||||
#include <dynarr.h>
|
||||
|
||||
typedef struct {
|
||||
int sockFd;
|
||||
struct sockaddr_in addr;
|
||||
int opt;
|
||||
|
||||
// Called before the client thread runs
|
||||
void (*on_connect)(TcpClient* client);
|
||||
// Called when data is received
|
||||
void (*on_data)(TcpClient* client);
|
||||
// Called before the socket and client thread are killed; Do NOT free client manually
|
||||
void (*on_disconnect)(TcpClient* client);
|
||||
|
||||
// max clients
|
||||
size_t clients;
|
||||
TcpClient** clientsArrPtr;
|
||||
|
||||
pthread_t svrThread;
|
||||
} TcpServer;
|
||||
|
||||
struct tcpclient_thread_args {
|
||||
TcpClient* clientPtr;
|
||||
TcpServer* serverPtr;
|
||||
};
|
||||
|
||||
typedef struct tcpclient_thread_args tcpclient_thread_args;
|
||||
|
||||
TcpServer* TcpServer_Create();
|
||||
void TcpServer_Destroy(TcpServer* ptr);
|
||||
|
||||
void TcpServer_Init(TcpServer* ptr, unsigned short port, const char* addr);
|
||||
void TcpServer_Start(TcpServer* ptr, int maxcons);
|
||||
void TcpServer_Stop(TcpServer* ptr);
|
||||
void TcpServer_Send(TcpServer* ptr, TcpClient* cli, void* data, size_t len);
|
||||
void Generic_SendSocket(int sock, void* data, size_t len);
|
||||
void TcpServer_Disconnect(TcpServer* ptr, TcpClient* cli);
|
||||
void TcpServer_KillClient(TcpServer* ptr, TcpClient* cli);
|
||||
|
||||
size_t Generic_FindClientInArrayByPtr(TcpClient** arr, TcpClient* ptr, size_t len);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user