tx mempool start, hello packet
This commit is contained in:
@@ -12,29 +12,12 @@
|
||||
#include <utils.h>
|
||||
#include <uint256.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t bytes[32];
|
||||
} key32_t;
|
||||
|
||||
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
|
||||
uint256_t balance;
|
||||
// TODO: Additional things
|
||||
} balance_sheet_entry_t;
|
||||
|
||||
static inline uint32_t hash_key32(key32_t k) {
|
||||
uint32_t hash = 2166136261u;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
hash ^= k.bytes[i];
|
||||
hash *= 16777619;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
static inline int eq_key32(key32_t a, key32_t b) {
|
||||
return memcmp(a.bytes, b.bytes, 32) == 0;
|
||||
}
|
||||
|
||||
KHASH_INIT(balance_sheet_map_m, key32_t, balance_sheet_entry_t, 1, hash_key32, eq_key32)
|
||||
extern khash_t(balance_sheet_map_m)* sheetMap;
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <block/chain.h>
|
||||
#include <block/block.h>
|
||||
|
||||
extern uint64_t currentBlockHeight;
|
||||
|
||||
// Nets
|
||||
#define MAX_CONS 32 // Some baseline for now
|
||||
#define LISTEN_PORT 9393
|
||||
|
||||
@@ -55,6 +55,9 @@ size_t DynArr_capacity(DynArr* p);
|
||||
|
||||
void DynArr_destroy(DynArr* p);
|
||||
|
||||
// Note: Make sure to not overread or overwrite
|
||||
void* DynArr_c_arr(DynArr* p);
|
||||
|
||||
#define DYNARR_CREATE(T, initialCapacity) DynArr_create(sizeof(T), initialCapacity)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <dynarr.h>
|
||||
|
||||
typedef struct {
|
||||
tcp_server_t* server;
|
||||
tcp_client_t outboundClients[MAX_CONS];
|
||||
|
||||
@@ -5,9 +5,14 @@
|
||||
|
||||
typedef enum {
|
||||
PACKET_TYPE_NONE = 0,
|
||||
PACKET_TYPE_REQUEST = 1,
|
||||
PACKET_TYPE_RESPONSE = 2,
|
||||
PACKET_TYPE_MAX = 3
|
||||
PACKET_TYPE_HELLO = 1, // Hello, let's connect! Here's who I am, and what I have!
|
||||
PACKET_TYPE_FETCH_BLOCK = 2, // I want a Block
|
||||
PACKET_TYPE_BLOCK_DATA = 3, // Here's a Block (response to fetch) - I don't care what you do with it, but you wanted it, so here it is!
|
||||
PACKET_TYPE_BROADCAST_BLOCK = 4, // Here's a new Block I want to share with the network (unsolicited - e.g. just mined it)
|
||||
PACKET_TYPE_ACK_BLOCK = 5, // I have received your block, here's what I did with it (response to broadcast)
|
||||
PACKET_TYPE_BROADCAST_TX = 6, // Here's a new transaction I want to share with the network
|
||||
PACKET_TYPE_ACK_TX = 7, // I have received your transaction, here's what I did with it (response to broadcast)
|
||||
PACKET_TYPE_MAX = 9
|
||||
} packet_type_t;
|
||||
|
||||
static inline int PacketType_IsValid(uint8_t packetType) {
|
||||
|
||||
18
include/txmempool.h
Normal file
18
include/txmempool.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef TXMEMPOOL_H
|
||||
#define TXMEMPOOL_H
|
||||
|
||||
#include <block/transaction.h>
|
||||
#include <khash/khash.h>
|
||||
#include <utils.h>
|
||||
#include <uint256.h>
|
||||
|
||||
KHASH_INIT(tx_mempool_map_m, key32_t, signed_transaction_t, 1, hash_key32, eq_key32)
|
||||
extern khash_t(tx_mempool_map_m)* txMempool;
|
||||
|
||||
void TxMempool_Init();
|
||||
int TxMempool_Insert(signed_transaction_t tx);
|
||||
bool TxMempool_Lookup(uint8_t* txHash, signed_transaction_t* out);
|
||||
void TxMempool_Print();
|
||||
void TxMempool_Destroy();
|
||||
|
||||
#endif
|
||||
@@ -6,6 +6,23 @@
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t bytes[32];
|
||||
} key32_t;
|
||||
|
||||
static inline uint32_t hash_key32(key32_t k) {
|
||||
uint32_t hash = 2166136261u;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
hash ^= k.bytes[i];
|
||||
hash *= 16777619;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
static inline int eq_key32(key32_t a, key32_t b) {
|
||||
return memcmp(a.bytes, b.bytes, 32) == 0;
|
||||
}
|
||||
|
||||
static inline void AddressToHexString(const uint8_t address[32], char out[65]) {
|
||||
if (!address || !out) {
|
||||
return;
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
uint64_t currentBlockHeight = 0;
|
||||
|
||||
static bool EnsureDirectoryExists(const char* dirpath) {
|
||||
if (!dirpath || dirpath[0] == '\0') {
|
||||
return false;
|
||||
@@ -176,6 +178,7 @@ bool Chain_AddBlock(blockchain_t* chain, block_t* block) {
|
||||
return false;
|
||||
}
|
||||
chain->size++;
|
||||
currentBlockHeight = (uint64_t)(chain->size - 1);
|
||||
|
||||
// Second pass: apply the ledger changes.
|
||||
if (blk->transactions) {
|
||||
@@ -269,6 +272,7 @@ bool Chain_IsValid(blockchain_t* chain) {
|
||||
|
||||
void Chain_Wipe(blockchain_t* chain) {
|
||||
Chain_ClearBlocks(chain);
|
||||
currentBlockHeight = 0;
|
||||
}
|
||||
|
||||
bool Chain_SaveToFile(blockchain_t* chain, const char* dirpath, uint256_t currentSupply, uint64_t currentReward) {
|
||||
|
||||
@@ -173,3 +173,7 @@ void DynArr_destroy(DynArr* p) {
|
||||
free(p->data);
|
||||
free(p);
|
||||
}
|
||||
|
||||
void* DynArr_c_arr(DynArr* p) {
|
||||
return p->data;
|
||||
}
|
||||
|
||||
@@ -561,8 +561,15 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
free(block); // Chain stores block by value and owns copied transaction array.
|
||||
|
||||
if (i % 1000 == 0) {
|
||||
// Mid-mine flush
|
||||
(void)FlushChainAndSheet(chain, chainDataDir, currentSupply, currentReward);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (minedAll) {
|
||||
(void)FlushChainAndSheet(chain, chainDataDir, currentSupply, currentReward);
|
||||
printf("mine finished and chain flushed\n");
|
||||
|
||||
@@ -160,6 +160,7 @@ int Node_SendPacket(net_node_t* node, tcp_connection_t* conn, packet_type_t pack
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
if (conn->role == TCP_CONNECTION_ROLE_INBOUND && packetType != PACKET_TYPE_RESPONSE) {
|
||||
return -1;
|
||||
}
|
||||
@@ -167,6 +168,7 @@ int Node_SendPacket(net_node_t* node, tcp_connection_t* conn, packet_type_t pack
|
||||
if (conn->role == TCP_CONNECTION_ROLE_OUTBOUND && packetType != PACKET_TYPE_REQUEST) {
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
|
||||
size_t framePayloadLen = payloadLen + 1;
|
||||
unsigned char* framed = (unsigned char*)malloc(framePayloadLen);
|
||||
@@ -200,9 +202,34 @@ void Node_Server_OnData(tcp_connection_t* client) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (packetType != PACKET_TYPE_REQUEST) {
|
||||
return;
|
||||
}
|
||||
switch (packetType) {
|
||||
case PACKET_TYPE_HELLO: {
|
||||
// Decode HELLO
|
||||
if (payloadLen < sizeof(uint32_t) + sizeof(uint64_t)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t protoVersion;
|
||||
uint64_t blockHeight;
|
||||
memcpy(&protoVersion, payload, sizeof(protoVersion));
|
||||
memcpy(&blockHeight, payload + sizeof(protoVersion), sizeof(blockHeight));
|
||||
|
||||
// TODO: Save these somewhere and maybe respond
|
||||
printf("Received HELLO from node %u: protoVersion=%u, blockHeight=%" PRIu64 "\n",
|
||||
client ? client->connectionId : 0U, protoVersion, blockHeight);
|
||||
|
||||
break;
|
||||
}
|
||||
case PACKET_TYPE_FETCH_BLOCK:
|
||||
case PACKET_TYPE_BLOCK_DATA:
|
||||
case PACKET_TYPE_BROADCAST_BLOCK:
|
||||
case PACKET_TYPE_ACK_BLOCK:
|
||||
case PACKET_TYPE_BROADCAST_TX:
|
||||
case PACKET_TYPE_ACK_TX:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
net_node_t* node = Node_FromConnection(client);
|
||||
Node_ForwardData(node, client, payload, payloadLen);
|
||||
@@ -218,6 +245,22 @@ void Node_Client_OnConnect(tcp_connection_t* client) {
|
||||
net_node_t* node = Node_FromConnection(client);
|
||||
Node_ForwardConnect(node, client);
|
||||
printf("Outbound node connected: %u\n", client ? client->connectionId : 0U);
|
||||
|
||||
// Construct and send HELLO
|
||||
if (node) {
|
||||
uint8_t buf[100];
|
||||
uint8_t* data = buf;
|
||||
|
||||
size_t offset = 0;
|
||||
uint32_t protoVersion = 1; // little-endian
|
||||
uint64_t blockHeight = currentBlockHeight;
|
||||
memcpy((unsigned char*)data + offset, &protoVersion, sizeof(protoVersion)); // This is technically "unsafe", but I honestly just don't give a shit at this point
|
||||
offset += sizeof(protoVersion);
|
||||
memcpy((unsigned char*)data + offset, &blockHeight, sizeof(blockHeight));
|
||||
offset += sizeof(blockHeight);
|
||||
|
||||
Node_SendPacket(node, client, PACKET_TYPE_HELLO, data, offset);
|
||||
}
|
||||
}
|
||||
|
||||
void Node_Client_OnData(tcp_connection_t* client) {
|
||||
@@ -229,8 +272,17 @@ void Node_Client_OnData(tcp_connection_t* client) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (packetType != PACKET_TYPE_RESPONSE) {
|
||||
return;
|
||||
switch (packetType) {
|
||||
case PACKET_TYPE_HELLO:
|
||||
case PACKET_TYPE_FETCH_BLOCK:
|
||||
case PACKET_TYPE_BLOCK_DATA:
|
||||
case PACKET_TYPE_BROADCAST_BLOCK:
|
||||
case PACKET_TYPE_ACK_BLOCK:
|
||||
case PACKET_TYPE_BROADCAST_TX:
|
||||
case PACKET_TYPE_ACK_TX:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
net_node_t* node = Node_FromConnection(client);
|
||||
|
||||
71
src/txmempool.c
Normal file
71
src/txmempool.c
Normal file
@@ -0,0 +1,71 @@
|
||||
#include <txmempool.h>
|
||||
|
||||
khash_t(tx_mempool_map_m)* txMempool = NULL;
|
||||
|
||||
void TxMempool_Init() {
|
||||
txMempool = kh_init(tx_mempool_map_m);
|
||||
}
|
||||
|
||||
int TxMempool_Insert(signed_transaction_t tx) {
|
||||
if (!txMempool) { return -1; }
|
||||
|
||||
uint8_t txHash[32];
|
||||
Transaction_CalculateHash(&tx.transaction, txHash);
|
||||
|
||||
key32_t key;
|
||||
memcpy(key.bytes, txHash, 32);
|
||||
|
||||
int ret;
|
||||
khiter_t k = kh_put(tx_mempool_map_m, txMempool, key, &ret);
|
||||
if (k == kh_end(txMempool)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
kh_value(txMempool, k) = tx;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool TxMempool_Lookup(uint8_t* txHash, signed_transaction_t* out) {
|
||||
if (!txMempool || !txHash || !out) { return false; }
|
||||
|
||||
key32_t key;
|
||||
memcpy(key.bytes, txHash, 32);
|
||||
|
||||
khiter_t k = kh_get(tx_mempool_map_m, txMempool, key);
|
||||
if (k != kh_end(txMempool)) {
|
||||
signed_transaction_t tx = kh_value(txMempool, k);
|
||||
memcpy(out, &tx, sizeof(signed_transaction_t));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void TxMempool_Print() {
|
||||
if (!txMempool) { return; }
|
||||
|
||||
khiter_t k;
|
||||
for (k = kh_begin(txMempool); k != kh_end(txMempool); ++k) {
|
||||
if (kh_exist(txMempool, k)) {
|
||||
signed_transaction_t tx = kh_val(txMempool, k);
|
||||
char senderHex[65];
|
||||
char recipient1Hex[65];
|
||||
char recipient2Hex[65];
|
||||
AddressToHexString(tx.transaction.senderAddress, senderHex);
|
||||
AddressToHexString(tx.transaction.recipientAddress1, recipient1Hex);
|
||||
AddressToHexString(tx.transaction.recipientAddress2, recipient2Hex);
|
||||
printf("TX in mempool: sender=%s recipient1=%s recipient2=%s amount1=%llu amount2=%llu fee=%llu\n",
|
||||
senderHex, recipient1Hex, recipient2Hex,
|
||||
(unsigned long long)tx.transaction.amount1,
|
||||
(unsigned long long)tx.transaction.amount2,
|
||||
(unsigned long long)tx.transaction.fee);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TxMempool_Destroy() {
|
||||
if (txMempool) {
|
||||
kh_destroy(tx_mempool_map_m, txMempool);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user