-
Notifications
You must be signed in to change notification settings - Fork 0
/
Miner.cpp
127 lines (116 loc) · 3.99 KB
/
Miner.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include "Miner.h"
Miner::Miner() {
this->highestTransactionFees = new Transaction[MAX_TRANSACTIONS_PER_BLOCK];
this->verified = false;
}
//trying to make bread $$$$$ find highest txn fees
bool Miner::setHighestTransactionsFees(TransactionPool* transactionPool) {
if (transactionPool->getTransactionsPending().size() == 0) {
delete[] this->highestTransactionFees;
this->highestTransactionFees = nullptr;
return true;
}
unsigned int maxFeeOne = 0;
unsigned int maxFeeTwo = 0;
for (auto pendingTransaction : transactionPool->getTransactionsPending()) {
auto gasFee = pendingTransaction.getGasFee();
if (maxFeeOne < gasFee) {
if (maxFeeTwo < maxFeeOne && maxFeeOne > 0) {
maxFeeTwo = maxFeeOne;
this->highestTransactionFees[1] = this->highestTransactionFees[0];
}
maxFeeOne = gasFee;
this->highestTransactionFees[0] = pendingTransaction;
}
else if (maxFeeTwo < gasFee) {
maxFeeTwo = gasFee;
this->highestTransactionFees[1] = pendingTransaction;
}
}
return false;
}
Transaction* Miner::getHighestTransactionFees() {
return this->highestTransactionFees;
}
void Miner::mine(Puzzle* puzzle, TransactionPool* transactionPool, mutex * mtx, Blockchain * blockChain, atomic_int * confirmations) {
if (setHighestTransactionsFees(transactionPool)) {
return;
}
auto block = new Block();
do {
string input = this->getTransactionInput(this->highestTransactionFees);
string randomString = this->generateRandomString(10);
string hash = this->createHash(input + randomString);
bool wonChallenge = this->verifyHash(hash, puzzle);
//reward first miner only by locking critical section
(*mtx).lock();
if (wonChallenge && blockChain->getProposedBlock() == nullptr) {
this->verified = true;
block->setCurrentHash(hash);
block->setInput(randomString);
block->setProposedTransactions(this->highestTransactionFees);
blockChain->proposeBlock(block);
++(*confirmations);
} else if (confirmations->load() > (MINERS_TO_SPAWN / 2) && !blockChain->getBlockAccepted()) {
transactionPool->remove(this->highestTransactionFees[0]);
transactionPool->remove(this->highestTransactionFees[1]);
blockChain->addBlock();
blockChain->displayBlockchain();
}
(*mtx).unlock();
if (blockChain->getProposedBlock() != nullptr && !this->verified) {
//it will run a verification whether hash is good or bad
this->verified = true;
string transactionsString = this->getTransactionInput(blockChain->getProposedBlock()->getProposedTransactions());
string verifiedHash = this->createHash(transactionsString + blockChain->getProposedBlock()->getInput());
bool confirmed = this->verifyHash(verifiedHash, puzzle);
if (confirmed) {
++(*confirmations);
}
}
if (blockChain->getBlockAccepted()) {
break;
}
} while (true);
delete[] this->highestTransactionFees;
this->highestTransactionFees = new Transaction[MAX_TRANSACTIONS_PER_BLOCK];
this->verified = false;
//wait for other miners
std::this_thread::sleep_for(milliseconds(1000));
confirmations->store(0);
blockChain->setBlockAccepted(false);
blockChain->proposeBlock(nullptr);
delete block;
block = nullptr;
//mine until no more transactions in pool
mine(puzzle, transactionPool, mtx, blockChain, confirmations);
int i = 0;
}
string Miner::createHash(string input) {
return sha256(input);
}
string Miner::getTransactionInput(Transaction* transactions) {
string transactionString;
for (int i = 0; i < MAX_TRANSACTIONS_PER_BLOCK; i++) {
transactionString += transactions[i].toString() + "|";
}
return transactionString;
}
bool Miner::verifyHash(string hash, Puzzle* puzzle) {
return puzzle->getPuzzle() == hash.substr(0, PUZZLE_DIFFICULTY);
}
string Miner::generateRandomString(size_t length)
{
auto randchar = []() -> char
{
const char charset[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
const size_t max_index = (sizeof(charset) - 1);
return charset[rand() % max_index];
};
std::string str(length, 0);
std::generate_n(str.begin(), length, randchar);
return str;
}