Section 3.6 Integrating Components
Dependencies and helper module
alias Blockchain.{
Block,
Extensions.SmartContracts,
Hash,
Main,
Transaction,
TransactionIO,
Utilities,
Wallet
}
[Blockchain.Block, Blockchain.Extensions.SmartContracts, Blockchain.Hash, Blockchain.Main,
Blockchain.Transaction, Blockchain.TransactionIO, Blockchain.Utilities, Blockchain.Wallet]
defmodule Blockchain.Main do
@doc """
Helper module that provides various printing functionality
"""
alias Blockchain
alias Blockchain.Block
alias Blockchain.Wallet
@spec print_blockchain(Blockchain.t()) :: Blockchain.t()
def print_blockchain(%Blockchain{blocks: blocks} = blockchain) do
for block <- blocks do
block
|> Block.format()
|> IO.puts()
end
blockchain
end
@spec print_wallets(Blockchain.t(), Wallet.t(), Wallet.t()) :: Blockchain.t()
def print_wallets(%Blockchain{} = blockchain, %Wallet{} = wallet_a, %Wallet{} = wallet_b) do
"""
Wallet A balance: #{Blockchain.balance_wallet_blockchain(blockchain, wallet_a)}
Wallet B balance: #{Blockchain.balance_wallet_blockchain(blockchain, wallet_b)}
"""
|> IO.puts()
blockchain
end
end
{:module, Blockchain.Main, <<70, 79, 82, 49, 0, 0, 11, ...>>, {:print_wallets, 3}}
Main
file_path = Path.join(__DIR__, "blockchain")
if File.exists?(file_path) do
IO.puts("Found 'blockchain.data', reading ...\n")
file_path
|> Utilities.file_to_data()
|> Main.print_blockchain()
end
nil
Initialize wallets …
coin_base = Wallet.new()
wallet_a = Wallet.new()
wallet_b = Wallet.new()
:ok
:ok
Make genesis transaction …
genesis_transaction = Transaction.new(coin_base, wallet_a, 100, [])
:ok
:ok
Initialize blockchain and print wallet balances …
blockchain = Blockchain.initialize(genesis_transaction, Hash.new("1337cafe"))
Main.print_wallets(blockchain, wallet_a, wallet_b)
:ok
Wallet A balance: 100
Wallet B balance: 0
:ok
Make second and third transactions …
blockchain =
blockchain
|> Blockchain.send_money(wallet_a, wallet_b, 20)
|> Main.print_wallets(wallet_a, wallet_b)
|> Blockchain.send_money(wallet_b, wallet_a, 10)
|> Main.print_wallets(wallet_a, wallet_b)
# Send invalid transaction
|> Blockchain.send_money(wallet_b, wallet_a, 100)
|> Main.print_wallets(wallet_a, wallet_b)
:ok
Wallet A balance: 130.0
Wallet B balance: 20
Wallet A balance: 140.0
Wallet B balance: 60.0
Wallet A balance: 140.0
Wallet B balance: 60.0
:ok
Check blockchain validity …
IO.puts("Blockchain is valid?: #{Blockchain.valid?(blockchain)}")
Blockchain is valid?: true
:ok
Print all blocks in blockchain …
Main.print_blockchain(blockchain)
:ok
Block information
=================
Hash: 20204dc074625780dfaed919a70c0f4d82e3e37a6edd6e41386551e69f72daab
Previous Hash: 202071c16890af8ceef2286ae1dbc7a39c58b4671db0dc5f333d94725768a612
Timestamp: 2022-02-25 05:04:50.172000Z
Nonce: 40221
Data: ... 913a ... sends ... 3d50 ... an amount of 10.
Block information
=================
Hash: 202071c16890af8ceef2286ae1dbc7a39c58b4671db0dc5f333d94725768a612
Previous Hash: 202020bdc6975a8943c71c7b7cea632c9fc93846c8f8c7acd0b66d7475124439
Timestamp: 2022-02-25 05:04:49.328000Z
Nonce: 45103
Data: ... 3d50 ... sends ... 913a ... an amount of 20.
Block information
=================
Hash: 202020bdc6975a8943c71c7b7cea632c9fc93846c8f8c7acd0b66d7475124439
Previous Hash: 3133333763616665
Timestamp: 2022-02-25 05:04:49.260000Z
Nonce: 3598
Data: ... 0740 ... sends ... 3d50 ... an amount of 100.
:ok
Smart Contracts
contract = {:if, {:=, {:+, 1, 2}, 3}, wallet_a, wallet_b}
blockchain
|> Blockchain.send_money(wallet_b, wallet_a, 10, contract)
|> Main.print_wallets(wallet_a, wallet_b)
:ok
Wallet A balance: 150.0
Wallet B balance: 100.0
:ok