To create an iterable blockchain, which could work with an extendable transaction class. Here the link GitHub repo!
base_transaction
class.block
class with Transaction
and HashFunction
templates.blockchain
class with the same templates and custom iterators to make it iterable.Lets Setup the extra files!
Create a includes
folder and add files from Github
not_implemented_exception
: The exception that is thrown when a requested method or operation is not implemented.class not_implemented_exception : public logic_error
{
public:
not_implemented_exception(
string function = __builtin_FUNCTION()
) : logic_error("`" + function + "` not implemented!"){};
};
base_transaction<EncryptionAlgo>
Here are the required things:
from_addr
, to_addr
, transfer_amount
generate_hash_input
)string
Operator (for string type casting)<<
Operator (for cout
)<
Operator (for comparison)get_balance(addr)
)sign_transaction(key_pair)
)is_transaction_valid(verifying_func)
)Every Function logic will be same, which is to throw not_implemented_exception
, for example:
operator string() const {throw not_implemented_exception();}
custom_transaction : public base_transaction<EncryptionAlgo>
Private Members:
from_address
(Yours public_key
)to_address
(Others public_key
)transfer_amount
timestamp
signature
(Initially 0
, will be updated in sign_transaction
)Public Members:
from_addr
, to_addr
, transfer_amount
custom_transaction(from_adrr, to_addr, amount){
from_address = from_addr;
to_address = to_addr;
transfer_amount = amount;
timestamp = chrono::steady_clock::now();
signature = 0;
}
generate_hash_input
)# Concatenation of all stringified private variables (except Signature)
# to_string(...) in C++
return (str(from_addr) + str(to_addr) + str(amount) + str(timestamp))
string
Operator (for string typecasting)operator string() const
{
string from_address_str = "\nfrom_address: " + to_string(from_address);
string to_address_str = "\nto_address: " + to_string(to_address);
string transfer_amount_str = "\ntransfer_amount: " + to_string(transfer_amount);
string signature_str = "\nsignature: " + to_string(signature);
return from_address_str + to_address_str + transfer_amount_str + signature_str;
}
<<
Operator (for cout
)friend ostream &operator<<(ostream &out, custom_transaction const &temp)
{
// Using above string operator
return out << string(temp);
}
<
Operator (for comparison)bool operator<(const custom_transaction &other) const
{
return generate_hash_input() < other.generate_hash_input();
}
get_balance(addr)
)float get_balance(addr) const
{
if (addr == to_address)
return transfer_amount;
if (addr == from_address)
return -transfer_amount;
return 0;
}
sign_transaction(key_pair)
)Here are some Pointers regarding signing
from_address
should match public_key
in key_pair
. Let us create an Error Regarding that:
class public_key_mismatch : public invalid_argument
{
public:
public_key_mismatch(
string addr, std::string pk) : invalid_argument("from_addr: '" + addr + "' do not match public_key: '" + pk + "'"){};
};
class resign_transaction_exception : public logic_error
{
public:
resign_transaction_exception(string transaction) : logic_error("Resigning Transaction!" + transaction){};
};
generate_hash_input()
template <typename EncryptionAlgo>
bool sign_transaction(EncryptionAlgo key_pair)
{
if (from_address != key_pair.get_public_key())
throw public_key_mismatch(to_string(from_address), to_string(key_pair.get_public_key()));
if (signature != 0) // already signed
throw resign_transaction_exception(*this);
signature = key_pair.sign(generate_hash_input());
return true;
}
is_transaction_valid(verifying_func)
)bool is_transaction_valid(bool (*verfication_function)(string, size_t, address)) const
{
// reward, since reward is given by admin, there is no key pair
if (from_address == 0)
return true;
return verfication_function(generate_hash_input(), signature, from_address);
}
block <Transaction, HashFunctionClass>
NOTES:
nonce
(“number used once”) a 32-bit, data computed in proof-of-workhash_function
is an instance of template class used for all hashing related needs (std::hash
used in main.cpp
)
# Here `nonce` is found via brute force
# until HASH_PATTERNis matched.
while(1):
hash_input = str(...) + str(nonce)
if re.match(hash_function(hash_input), HASH_PATTERN):
return nonce
nonce += 1
sha256
n
zeros, higher the n
, harder to compute.namespace::ra
:
std::hash<string>
for reference)15/n
, lesser the n, harder to compute.block_chain <Transaction, HashFunctionClass>
Well as the name states it is a chain of blocks, So Naturally, It will contain the same Template Arguments as Block
Private Members:
list<BlockType> chain
(A list of blocks)list<Trasaction> pending_transaction
(Temperaroy Buffer before mining (create a block and adding it to list))difficulty
(to be passed in block
class)minning_reward
(If exists, will add a new transaction from admin before mining block)verfication_function
(to verify block or transaction itself)Public Members:
Iterator Class (To make iteration easy)
std::_List_iterator<block_type>
block_ptr,==
, !=
, ++
, &++
, --
, &--
, for example:iterator operator--(int)
{
iterator _temp = *this;
m_block_ptr--;
return _temp;
}
const iterator begin() { return chain.begin(); }
const iterator end() { return chain.end(); }
block_type &back() { return chain.back(); }
block_type &front() { return chain.front(); }
int size() { return chain.size(); }
block_chain(diffuculty, verfication_function, minning_reward)
Constructor:
float balance = 0
block_chai
n from begin()
to end()
using iterator class and add it to balance
balance
add_transaction(temp)
temp
using is_transaction_valid
by passing in verfication_function
pending_transaction
else Throw Errormine_pending_transactions(minning_reward_address)
minning_reward
exsits, add a reward transaction
to minning_reward_address
, else continuepending_transaction
, and push it to chain.pending_transaction
.is_chain_valid()
chain
, check the validity of current block using is_block_valid
by passing in verfication_function
previous_hash
of current block matches hash
of the previous block