Packages
💰Customisable Bitcoin-Blockchain ecosystem in Elixir. Includes blockchain, crypto wallets, miners and simulation of transactions.
Current section
Files
Jump to
Current section
Files
lib/walletGenServer.ex
defmodule WalletGenServer do
use GenServer
def start_link(holderIndex, privateKey, publicKey, btc, minersList, transactionAutomatorPID) do
GenServer.start_link(__MODULE__, [holderIndex, privateKey, publicKey, btc, minersList, transactionAutomatorPID], name: {:via, Registry, {:node_store, holderIndex}})
end
# Retrieves pid from the register containing wallet pids
def pidRetriever(holderIndex) do
case Registry.lookup(:node_store, holderIndex) do
[{pid, _}] -> pid
[] -> nil
end
end
# State of the wallet is initialized here
def init([holderIndex, privateKey, publicKey, btc, minersList, transactionAutomatorPID]) do
state = %{"holderIndex" => holderIndex, "privateKey" => privateKey, "publicKey" => publicKey, "btc" => btc, "minersList" => minersList, "transactionAutomatorPID" => transactionAutomatorPID}
{:ok, state}
end
# New transaction is initiated, a signed message and transaction data are broadcasted for all miners to pick up and start mining
def handle_call({:initiateTransaction, [selfPID, sendToPK]}, _from, state) do
transactionData = %{
"btc" => Map.get(state, "btc")/2,
"receiversPK" => sendToPK,
"sendersPublicKey" => Map.get(state,"publicKey")
}
{:ok, signature} = RsaEx.sign("message", Map.get(state,"privateKey"), :sha256)
minersList = Map.get(state,"minersList")
IO.puts("Mining.. 🛠")
for i <- 0..(length(minersList) - 1) do
send Enum.at(minersList, i), {:ok, [transactionData, signature, selfPID, minersList]}
end
{:reply, state, state}
end
# Returns state of the wallet GenServer
def handle_call({:getWallet}, _from, appState) do
{:reply, appState, appState}
end
# Verification of the latest block in the blockchain is done.
def handle_call({:verifyBlockChain, [verificationAccumulatorPID, blockChainPID]}, _from, appState) do
blockChain = GenServer.call(blockChainPID, {:getBlockChain})
addedBlock = Enum.at(blockChain, length(blockChain) - 1)
signedMessage = Map.get(addedBlock, :signedMessage)
sendersPublicKey = Map.get(addedBlock, :sendersPublicKey)
{:ok, valid} = RsaEx.verify("message", signedMessage, sendersPublicKey)
send verificationAccumulatorPID, {:ok, valid}
{:reply, appState, appState}
end
def handle_cast({:decrementBTC, spentBTC}, state) do
currentBTC = Map.get(state, "btc")
newBTC = currentBTC - spentBTC
state = Map.replace!(state, "btc", newBTC)
IO.puts("sender's wallet 💰: #{inspect(newBTC)} btc")
{:noreply, state}
end
def handle_cast({:checkTransactionReceiver, receivedBTC, receiversPK}, state) do
cond do
Map.get(state, "publicKey") == receiversPK ->
currentBTC = Map.get(state, "btc")
newBTC = currentBTC + receivedBTC
state = Map.replace!(state, "btc", newBTC)
IO.puts("receiver's wallet 💰: #{inspect(newBTC)} btc")
send Map.get(state, "transactionAutomatorPID"), {:transactionEnded}
{:noreply, state}
true -> {:noreply, state}
end
end
def handle_info(_msg, state) do
# IO.puts "unknown message"
{:noreply, state}
end
end