Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Section 3.6 Integrating Components

notebooks/main.livemd

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