Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Diving into Merkle Trees

Diving into Merkle Trees

Introduced by Ralph C. Merkle, the Merkle Tree is a data structure used for efficiently summarizing and verifying the integrity of large sets of data. Due to its unique content validating and performance qualities, they are especially useful in distributed, peer-to-peer systems where the same data should exist in multiple places. Let's learn how to detect inconsistencies between trees and reduce the amount of transferred data enabling peer-to-peer file sharing by building our own tree with Elixir.

Pedro Tavares

February 21, 2019
Tweet

More Decks by Pedro Tavares

Other Decks in Programming

Transcript

  1. “[…] can sign an unlimited number of messages, and the

    signature size increases logarithmically.”
  2. “The general idea in this new system is to use

    an infinite tree of one-time signatures.”
  3. “[…] is a data structure used for efficiently summarizing and

    verifying the integrity of large sets of data.”
  4. “[…] it was used for the purpose of one-time signatures

    and authenticated public key distribution.”
  5. “A one-way function f is a function that is easy

    to compute but difficult to invert.”
  6. “[…] being able to store and identify data with a

    fixed length output can create vast storage savings.”
  7. “One time signatures are practical between a single pair of

    users who are willing to exchange the large amount of data necessary […]”
  8. “If 1000 messages are to be signed before new public

    authentication data is needed, over 20,000,000 bits or 2.5 megabytes must be stored as public information.”
  9. defmodule MerkleTree.Leaf do defstruct [:hash, :value] @type hash :: String.t

    @type value :: String.t @type t :: %MerkleTree.Leaf{ hash: hash, value: value } end
  10. defmodule MerkleTree.Leaf do defstruct [:hash, :value] @type hash :: String.t

    @type value :: String.t @type t :: %MerkleTree.Leaf{ hash: hash, value: value } end
  11. defmodule MerkleTree.Node do defstruct [:hash, :left, :right] @type hash ::

    String.t @type left :: MerkleTree.Node.t | MerkleTree.Leaf.t @type right :: MerkleTree.Node.t | MerkleTree.Leaf.t @type t :: %MerkleTree.Node{ hash: hash, left: left, right: right } end
  12. defmodule MerkleTree.Node do defstruct [:hash, :left, :right] @type hash ::

    String.t @type left :: MerkleTree.Node.t | MerkleTree.Leaf.t @type right :: MerkleTree.Node.t | MerkleTree.Leaf.t @type t :: %MerkleTree.Node{ hash: hash, left: left, right: right } end
  13. defmodule MerkleTree.Crypto do def hash(input, type \\ :sha256) do type

    |> :crypto.hash("#{input}") |> Base.encode16 end end
  14. defmodule MerkleTree do alias MerkleTree.Leaf alias MerkleTree.Crypto def new(blocks) do

    blocks |> Enum.map(&%Leaf.build(&1, Crypto.hash(&1))) end end
  15. defmodule MerkleTree do alias MerkleTree.Leaf alias MerkleTree.Crypto def new(blocks) do

    blocks |> Enum.map(&%Leaf.build(&1, Crypto.hash(&1))) end end
  16. defmodule MerkleTree do alias MerkleTree.Leaf alias MerkleTree.Crypto def new(blocks) do

    blocks |> Enum.map(&%Leaf.build(&1, Crypto.hash(&1))) end end
  17. defmodule MerkleTree.Node do alias MerkleTree.Crypto def new(nodes) do nodes |>

    Enum.map_join(&(&1.hash)) |> Crypto.hash |> build(nodes) end end
  18. defmodule MerkleTree.Node do alias MerkleTree.Crypto def new(nodes) do nodes |>

    Enum.map_join(&(&1.hash)) |> Crypto.hash |> build(nodes) end end
  19. defmodule MerkleTree.Node do alias MerkleTree.Crypto def new(nodes) do nodes |>

    Enum.map_join(&(&1.hash)) |> Crypto.hash |> build(nodes) end end
  20. defmodule MerkleTree.Node do alias MerkleTree.Crypto def new(nodes) do nodes |>

    Enum.map_join(&(&1.hash)) |> Crypto.hash |> build(nodes) end end
  21. defmodule MerkleTree.Node do alias MerkleTree.Crypto def new(nodes) do nodes |>

    Enum.map_join(&(&1.hash)) |> Crypto.hash |> build(nodes) end end
  22. defmodule MerkleTree do alias MerkleTree.Leaf alias MerkleTree.Crypto def new(blocks) do

    blocks |> Enum.map(&%Leaf.build(&1, Crypto.hash(&1))) end end
  23. defmodule MerkleTree do defp build([root]) do %MerkleTree{root: root} end defp

    build(nodes) do nodes |> Enum.chunk_every(2) |> Enum.map(&Node.new(&1)) |> build end end
  24. defmodule MerkleTree do defp build([root]) do %MerkleTree{root: root} end defp

    build(nodes) do nodes |> Enum.chunk_every(2) |> Enum.map(&Node.new(&1)) |> build end end
  25. defmodule MerkleTree do defp build([root]) do %MerkleTree{root: root} end defp

    build(nodes) do nodes |> Enum.chunk_every(2) |> Enum.map(&Node.new(&1)) |> build end end
  26. defmodule MerkleTree do defp build([root]) do %MerkleTree{root: root} end defp

    build(nodes) do nodes |> Enum.chunk_every(2) |> Enum.map(&Node.new(&1)) |> build end end
  27. defmodule MerkleTree do defp build([root]) do %MerkleTree{root: root} end defp

    build(nodes) do nodes |> Enum.chunk_every(2) |> Enum.map(&Node.new(&1)) |> build end end
  28. defmodule MerkleTree do defp build([root]) do %MerkleTree{root: root} end defp

    build(nodes) do nodes |> Enum.chunk_every(2) |> Enum.map(&Node.new(&1)) |> build end end
  29. defmodule MerkleTree do defp build([root]) do %MerkleTree{root: root} end defp

    build(nodes) do nodes |> Enum.chunk_every(2) |> Enum.map(&Node.new(&1)) |> build end end
  30. defmodule MerkleTree do defp build([root]) do %MerkleTree{root: root} end defp

    build(nodes) do nodes |> Enum.chunk_every(2) |> Enum.map(&Node.new(&1)) |> build end end
  31. defmodule MerkleTree do alias MerkleTree.Leaf alias MerkleTree.Crypto def new(blocks) do

    blocks |> Enum.map(&%Leaf.build(&1, Crypto.hash(&1))) |> build end end
  32. defmodule MerkleTree do alias MerkleTree.Leaf alias MerkleTree.Crypto def new(blocks) do

    blocks |> Enum.map(&%Leaf.build(&1, Crypto.hash(&1))) |> build end end
  33. defmodule MerkleTree do alias MerkleTree.Leaf alias MerkleTree.Crypto def new(blocks) do

    blocks |> Enum.map(&%Leaf.build(&1, Crypto.hash(&1))) |> build end end
  34. defmodule MerkleTree do alias MerkleTree.Leaf alias MerkleTree.Crypto def new(blocks) do

    blocks |> Enum.map(&%Leaf.build(&1, Crypto.hash(&1))) |> build end end
  35. %MerkleTree{ root: %MerkleTree.Node{ hash: “8C569660D98A20D59DE10E134D81A8CE55...”, left: %MerkleTree.Leaf{ value: “L1”, hash:

    “DFFE8596427FC50E8F64654A609AF135...” }, right: %MerkleTree.Leaf{ value: “L2”, hash: “D76354D8457898445BB69E0DC0DC95FB...” } } }
  36. %MerkleTree{ root: %MerkleTree.Node{ hash: “8C569660D98A20D59DE10E134D81A8CE55...”, left: %MerkleTree.Leaf{ value: “L1”, hash:

    “DFFE8596427FC50E8F64654A609AF135...” }, right: %MerkleTree.Leaf{ value: “L2”, hash: “D76354D8457898445BB69E0DC0DC95FB...” } } }
  37. %MerkleTree{ root: %MerkleTree.Node{ hash: “8C569660D98A20D59DE10E134D81A8CE55...”, left: %MerkleTree.Leaf{ value: “L1”, hash:

    “DFFE8596427FC50E8F64654A609AF135...” }, right: %MerkleTree.Leaf{ value: “L2”, hash: “D76354D8457898445BB69E0DC0DC95FB...” } } }
  38. %MerkleTree{ root: %MerkleTree.Node{ hash: “8C569660D98A20D59DE10E134D81A8CE55...”, left: %MerkleTree.Leaf{ value: “L1”, hash:

    “DFFE8596427FC50E8F64654A609AF135...” }, right: %MerkleTree.Leaf{ value: “L2”, hash: “D76354D8457898445BB69E0DC0DC95FB...” } } }
  39. %MerkleTree{ root: %MerkleTree.Node{ hash: “8C569660D98A20D59DE10E134D81A8CE55...”, left: %MerkleTree.Leaf{ value: “L1”, hash:

    “DFFE8596427FC50E8F64654A609AF135...” }, right: %MerkleTree.Leaf{ value: “L2”, hash: “D76354D8457898445BB69E0DC0DC95FB...” } } }
  40. L1 L4 Replica 1 L1 L3 L1 L4 L1 L2

    L1 L4 L1 L2 Replica 2 Replica 3 Repair Coordinator
  41. L1 L4 Replica 1 H1 H3 L1 L3 L1 L4

    H1 H2 L1 L2 L1 L4 H1 H2 L1 L2 Replica 2 Replica 3 Repair Coordinator
  42. L1 L4 Replica 1 B H1 H3 L1 L3 L1

    L4 A H1 H2 L1 L2 L1 L4 A H1 H2 L1 L2 Replica 2 Replica 3 Repair Coordinator
  43. L1 L4 Replica 1 B H1 H3 L1 L3 L1

    L4 A H1 H2 L1 L2 L1 L4 A H1 H2 L1 L2 Replica 2 Replica 3 Repair Coordinator
  44. B H1 H2 H1 H3 L1 L2 L1 L3 A

    Replica 2 Replica 3
  45. B H1 H2 H1 H3 L1 L2 L1 L3 A

    Replica 2 Replica 3
  46. B H1 H2 H1 H3 L1 L2 L1 L3 A

    Replica 2 Replica 3
  47. B H1 H2 H1 H3 L1 L2 L1 L2 A

    Replica 2 Replica 3
  48. B H1 H2 H1 H2 L1 L2 L1 L2 A

    Replica 2 Replica 3
  49. A H1 H2 H1 H2 L1 L2 L1 L2 A

    Replica 2 Replica 3
  50. Instead of taking a full copy, we can share the

    same tree between both the copy and the original tree.