I'm writing a project to simulate (an oversimplified version) of a blockchain. I've written a class called Block to manage blocks in the blockchain:
(You may notice that I am referencing some additional classes/headers which are not listed in an #include statement at the top. To my knowledge, all the dependencies are adequately taken care of by the makefile.)
#include "Block.h"
/**** constructors ****/
Block::Block()
{
prevHash = "";
merkleRoot = "";
nonce = "";
}
Block::Block(std::string str)
{
std::vector<std::string> strings;
std::string word;
int pos = str.find(" ");
while(pos != std::string::npos)
{
word = str.substr(0, pos);
strings.push_back(word);
pos = str.find(" ");
str = str.substr(pos+1);
}
if(strings.size() != 3)
{
prevHash = "";
merkleRoot = "";
nonce = "";
}
else
{
prevHash = strings.at(0);
merkleRoot = strings.at(1);
nonce = strings.at(2);
}
}
Block::Block(std::vector<Block> &blocks, std::string merkle)
{
// use prev block from Block vector to get hash of prev block
Block prevBlock = blocks.at(0);
prevHash = picosha2::hash256_hex_string(utils::hexToString(prevBlock.toString()));
merkleRoot = merkle;
nonce = mine();
}
Block::Block(std::string hash, std::string merkle, std::string n)
{
prevHash = hash;
merkleRoot = merkle;
nonce = n;
}
Block::Block(const Block &b) //copy constructor
{
prevHash = b.getPrevHash();
merkleRoot = b.getMerkleRoot();
nonce = b.mine();
}
Block::~Block() //destructor
{
}
/**** public methods ****/
bool Block::isValid()
{
std::string hash = picosha2::hash256_hex_string(utils::hexToString(this->toString()));
if(hash[0] == '0')
return true;
return false;
}
std::string Block::toString()
{
return prevHash + merkleRoot + nonce;
}
std::string Block::mine() const
{
// brute force nonces so hash begins with zero/block is valid
for(int i = 0; i < pow(2, 8); i++)
{
Block temp(this->getPrevHash(), this->getMerkleRoot(), std::to_string(i));
if(temp.isValid())
{
// convert i to hex string and return
std::stringstream stream;
stream << std::hex << std::to_string(i);
return stream.str();
}
}
std::cout << "No nonce found." << std::endl;
return "";
}
// calculate this block's hash
std::string Block::calcHash()
{
std::string hash = picosha2::hash256_hex_string(utils::hexToString(this->toString()));
return hash;
}
std::string Block::getPrevHash() const
{
return prevHash;
}
std::string Block::getMerkleRoot() const
{
return merkleRoot;
}
std::string Block::getNonce() const
{
return nonce;
}
So, the actual problem: I can't add instances of the Block class to my vector of Blocks (or an array of Blocks, for that matter; I tried that too). I can create a Block, print it out, basically anything I want. But if I add it to a vector, my computer throws a runtime error. Below is my main file and the output of a run:
#include "main.h"
// function prototype
std::string merkleRoot(std::vector<Transaction> &);
int main(int argc, char ** argv)
{
int numblocks = 0;
int numtransactions = 0;
std::vector<Block> blocks;
std::vector<Transaction> transactions;
if(argc != 3)
{
std::cout << "Usage: main [blockchain.txt] [transaction.txt]" << std::endl;
exit(1);
}
std::string blockchainFileName = argv[1];
std::string transactionFileName = argv[2];
std::cout << "blockchainFileName: " << blockchainFileName << std::endl;
std::cout << "transactionFileName: " << transactionFileName << std::endl;
std::ifstream blockchainFile(blockchainFileName);
std::ifstream transactionFile(transactionFileName);
if(!blockchainFile)
{
std::cout << "Cannot open " << blockchainFileName << std::endl;
exit(1);
}
if(!transactionFile)
{
std::cout << "Cannot open " << transactionFileName << std::endl;
exit(1);
}
/*** Read in blockchain ***/
std::string line;
int count = 0;
while(std::getline(blockchainFile, line))
{
std::vector<Block> temp;
std::cout << "line number " << ++count << std::endl;
Block newBlock(line);
std::cout << newBlock.toString() << std::endl;
blocks.push_back(newBlock);
}
}
Output:
$ ./main textfiles/blockchain_1.txt textfiles/transactions_1.txt
blockchainFileName: textfiles/blockchain_1.txt
transactionFileName: textfiles/transactions_1.txt
line number 1
026765a1c8235d4ac23d2582cda3b9f5c062f805540320173eb9e9148c0dc518704b42e4b11ca131b443c2b02a07ec0b45407f1b125027e3e68b86ace692445800000001
libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: basic_string
Abort trap: 6
blockchain_1.txt file:
026765a1c8235d4ac23d2582cda3b9f5c062f805540320173eb9e9148c0dc518 704b42e4b11ca131b443c2b02a07ec0b45407f1b125027e3e68b86ace6924458 00000001
0b53181ae351f4508363cdc3e8fb3e819fb706c4ba98a3005a980a837561074a 06aa7a8cbda7ac4351c0cae116c589c2eb0ca96cb4c90844812945cb4ffe27c5 00000019
000000000000000000ad6e90c0790e83760a9d13728c23474352a2c8c7a6e0eb 2b12fcf1b09288fcaff797d71e950e71ae42b91e8bdb2304758dfcffc2b620e3 0000000f
transactions_1.txt file:
Bob Alice 5.0
Alice Bob 1.0
John Bill 2.4
Bill Alice 1.3
John Bill 2.7
Bob John 7.9
Tom Todd 4.5
Todd Bob 12.0
I've dug around for several hours now and I'm kind of out of leads. I will say that I am a little rusty with C++, particularly constructing and using my own classes. If anyone has any ideas, I'd really appreciate it! Let me know if you need any additional parts of my code.
Aucun commentaire:
Enregistrer un commentaire