Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example fix #23

Merged
merged 4 commits into from
Dec 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 25 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,40 @@ Run

to pause or unpause the network respectively.

## Running the examples

In the `usr_scripts` directory, run `python3 <filename>.py`.

The logging will describe what steps are being taken, and will require you to hit "enter" to proceed at some points so you can inspect the outputs.


## Example explanation

### NonupdatingFileHashing
In this (admittedly barren) example, we will see two users (User A and User B) exchange messages (the exchange itself is outside of this example, you can imagine email, telegram, carrier pigeon...). Both users hash these messages and store this hash on the blockchain, as proof that they have sent the message at a specific time. Importantly, the message content is *not* on the blockchain and hence is *not* public.
### UnsentMessageExample.py
In this example, we will see two users (Jack and Jill) exchange messages (the exchange itself is outside of this example, you can imagine email, telegram, carrier pigeon...). Both users hash these messages and store the hashes on the blockchain, as proof that they have sent the message at a specific time. Importantly, the message content is *not* on the blockchain and hence is *not* public.

At some later time, User C is asked to verify that the messages were sent. User C, gathering those messages, can recalculate the hashes and search for them on the blockchain. By checking if those hashes are present in a block, User C can verify if a message was sent or not (more accurately, User C can verify if the message was *logged* as sent by this method)
At some later time, Victoria is asked to verify that the messages were sent. Victoria, gathering those messages, can recalculate the hashes and search for them on the blockchain. By checking if those hashes are present in a block, Victoria can verify if a message was sent or not (more accurately, Victoria can verify if the message was *logged* as sent by this method)

Over time the events are:
- User A sends message1.secret to User B. logging the hash
- User B replies to User A with message2.secret, logging the hash
- User A composes but does not send message3.secret
- User C gets message1.secret, computes the hash, and determines the hash *is* on chain
- Jack sends message1.secret to Jill. logging the hash
- Jill replies to Jack with message2.secret, logging the hash
- Jack composes but does not send message3.secret
- Victoria gets message1.secret, computes the hash, and determines the hash *is* on chain
- Verifies that message1.secret was sent
- User C gets message3.secret, computes the hash, and determines the hash is *not* on chain
- Verifies that message3.secret was not sent

### UpdatingFileHashing
In this example, one user (User A) creates a message and stores the hash in a new domain. All updates to this message can be stored in this domain and we can track updates to this file over time this way.

Some time later, User A updates the message, and again logs the hash
- Victoria gets message2.secret, computes the hash, and determines the hash *is* on chain
- Verifies that message2.secret was sent
- Victoria gets message3.secret, computes the hash, and determines the hash is *not* on chain
- Verifies that message3.secret was *not* sent

User B receives the message and checks the blockchain to see if this message is the most up to date. (It is)
### DifferingMessageExample.py
In this example, Alice sends a message to Bob and logs the hash on chain. Bob can verify that the message he receives has the same hash as he sees on chain, verifying the message. Alice can update the message, send it to Bob, and log the hash again. Bob can once again check the message and see it has updated.

## Running this example
Ensure the Iroha network is up by running `./manage-network up` from the root directory
A new user, Mallory, enters the picture and wants to trick Alice and Bob. Mallory creates a new message claiming Bob owes Mallory some money. Mallory logs this hash and sends it to Alice *only* (Bob does not see this message). Alice can see this hash and verify it, so she believes Bob owes Mallory. Mallory updates the message and sends the now non-dubious message to Bob.

In the `usr_scripts` directory, run `python3 <filename>.py`. The logging will describe what steps are being taken. When convinced that this program runs without error, checkout the source code to see how the above example is implemented.
Mallory now has two choices:
1. Do not log the new message hash on chain. Bob can check the chain and see his message hash is not the same as the one on chain, and knows he is being tricked
2. Log the new message hash on chain. Bob can check the chain and verify the hash (although the previous hash from Alice should raise suspicion).
Alice and Bob meet and Alice states Bob owes Mallory, citing her message hash. Bob disputes this and provides his message hash. Alice and Bob can now check the chain again, and Alice can see her message is outdated, so she will stop believing Bob owes Mallory.

## Some thoughts
- This example, as with much of blockchain and cryptography, relies on there being absolutely no hash collisions. If a hash collision occurs, it would be possible to trick the auditor User C.
Expand Down
140 changes: 140 additions & 0 deletions usr_scripts/DifferingMessageExample.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#! /bin/python

import grpc
from IrohaUtils import *
from IrohaHashCustodian import Custodian
import logging
import json
from time import sleep


def wait_point(msg):
input(f"{bcolors.OKGREEN}===> {msg}{bcolors.ENDC}")


# INFO gives descriptions of steps
# DEBUG gives information on transactions and queries too
logging.basicConfig(level=logging.INFO)

logging.info("Create hash custodian")
while True:
try:
custodian = Custodian(blockstore_threading=True)
break
except grpc._channel._InactiveRpcError:
logging.info("Network unreachable, retrying")
sleep(2)

logging.info("Create user Alice")
user_a = custodian.new_hashing_user("alice")
logging.info("Create user Bob")
user_b = custodian.new_hashing_user("bob")

domain_name = custodian._parse_domain_name("message")

wait_point("Alice creates a message, and sends this to Bob")
message = "Hello, World!"
logging.info(f"Message:\n{message}")
wait_point("Alice also hashes the message and stores the hash on chain")
message_hash = custodian.get_hash(message)
logging.info(f"{message_hash=}")
logging.info("Storing hash...")
status = custodian.store_hash_on_chain(user_a, message_hash, domain_name=domain_name)
assert status[0] == "COMMITTED"
logging.info(f"Message hash successfully logged in new domain {domain_name}")

wait_point("Bob, having received the message from Alice, wants to verify it")
received_hash = custodian.get_hash(message)
chain_asset = custodian.get_domain_hashes(domain_name=domain_name)[-1]
logging.info(f"Received Hash {received_hash}")
logging.info(f"Blockchain Info:\n{json.dumps(chain_asset, indent=2)}")
wait_point("Bob can see the two hashes are the same, and trusts the message")

print("\n\n")

wait_point("Alice changes the message slightly, sending Bob the new message")
message+="\n---Foobar---"
logging.info(f"Message: \n{message}")
wait_point("Alice again hashes and stores the hash in the same domain")
new_message_hash = custodian.get_hash(message)
logging.info(f"{new_message_hash=}")
logging.info("Storing hash...")
status = custodian.store_hash_on_chain(user_a, new_message_hash, domain_name=domain_name)
assert status[0] == "COMMITTED"
logging.info(f"Message hash successfully updated in {domain_name}")

wait_point("Bob, with a new message from Alice, wants to verify it")
received_hash = custodian.get_hash(message)
chain_asset = custodian.get_domain_hashes(domain_name=domain_name)[-1]
logging.info(f"Received Hash {received_hash}")
logging.info(f"Blockchain Info:\n{json.dumps(chain_asset, indent=2)}")
wait_point("Bob can see the two hashes are the same, and again trusts the message")

print("\n\n")

wait_point("A new user Mallory joins")
logging.info("Create user Mallory")
user_m = custodian.new_hashing_user("mal")

domain_name = custodian._parse_domain_name("mal-message")

wait_point("Mallory claims Bob owes her a small sum of money")
mal_message = "Bob owes Mallory $1,000,000"
logging.info(f"{mal_message=}")
wait_point("Mallory sends this message only to Alice, leaving Bob out")
mal_message_hash = custodian.get_hash(mal_message)
logging.info(f"{mal_message_hash=}")
logging.info("Storing hash...")
status = custodian.store_hash_on_chain(user_m, mal_message_hash, domain_name=domain_name)
assert status[0] == "COMMITTED"
logging.info(f"Message hash successfully stored in {domain_name}")

wait_point("Alice checks the received hash against the blockchain")
alice_received_hash = custodian.get_hash(mal_message)
logging.info(f"Received hash {alice_received_hash}")
chain_asset = custodian.get_domain_hashes(domain_name=domain_name)
logging.info(f"Blockchain info:\n{json.dumps(chain_asset, indent=2)}")
wait_point("Alice sees the hashes are the same, and believes Bob owes Mallory")

wait_point("Mallory changes the message and sends this to Bob instead")
mal_message = "Hello, Bob!"
logging.info(f"{mal_message=}")
wait_point("Mallory has two options:\n\t1) Do not store the new hash on chain")
logging.info("Bob checks received message against chain information")
bob_received_hash = custodian.get_hash(mal_message)
chain_asset = custodian.get_domain_hashes(domain_name=domain_name)
logging.info(f"Received hash {bob_received_hash}")
logging.info(f"Blockchain info:\n{json.dumps(chain_asset, indent=2)}")
logging.info("The hashes are different, so Bob knows he is being tricked")

wait_point("\t2) Do store the new hash on chain")
mal_message_hash = custodian.get_hash(mal_message)
logging.info(f"{mal_message_hash=}")
logging.info("Storing hash...")
status = custodian.store_hash_on_chain(user_m, mal_message_hash, domain_name=domain_name)
assert status[0] == "COMMITTED"
logging.info(f"Message hash successfully stored in {domain_name}")
logging.info("Bob checks received message against chain information")
bob_received_hash = custodian.get_hash(mal_message)
chain_asset = custodian.get_domain_hashes(domain_name=domain_name)
logging.info(f"Bob received hash {bob_received_hash}")
logging.info(f"Blockchain info:\n{json.dumps(chain_asset, indent=2)}")
wait_point("Bob sees the most recent hash matches, so trusts the message\n(But may be suspicious because of the earlier hash he did not receive)")

wait_point("Alice and Bob now convene, and Alice states Bob owes Mallory, which Bob disputes")
logging.info("Alice and Bob exchange their received hashes")
logging.info(f"Alice received hash {alice_received_hash}")
logging.info(f"Bob received hash {bob_received_hash}")
logging.info("Alice and Bob see their hashes (and hence messages) are not the same")
wait_point("Because Alice and Bob both verified their received messages, they check the chain again")
logging.info(f"Alice received hash {alice_received_hash}")
logging.info(f"Bob received hash {bob_received_hash}")
logging.info(f"Blockchain info:\n{json.dumps(chain_asset, indent=2)}")
wait_point("Alice can see she now has an outdated message, so she stops believing the debt\n(or at least would require further proof since Bob denies it)")

wait_point("Mallory cannot trick Alice or Bob!")




log_all_blocks("node1.log")
46 changes: 0 additions & 46 deletions usr_scripts/NonupdatingFileHash.py

This file was deleted.

78 changes: 78 additions & 0 deletions usr_scripts/UnsentMessageExample.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#! /bin/python

from IrohaUtils import *
from IrohaHashCustodian import Custodian
import logging
import grpc
import json
from time import sleep


def wait_point(msg):
input(f"{bcolors.OKGREEN}===> {msg}{bcolors.ENDC}")

# INFO gives descriptions of steps
# DEBUG gives information on transactions and queries too
logging.basicConfig(level=logging.INFO)
logging.info("Create hash custodian")
while True:
try:
custodian = Custodian()
break
except grpc._channel._InactiveRpcError:
logging.info("Network unreachable, retrying")
sleep(2)
logging.info("Create user Jack")
user_a = custodian.new_hashing_user("jack")
logging.info("Create user Jill")
user_b = custodian.new_hashing_user("jill")
logging.info("Create user Victoria")
user_c = custodian.new_hashing_user("victoria")


wait_point("Jack sends message1 to Jill, logging the hash")
message1_hash = custodian.get_file_hash("messages/message1.secret")
logging.info(f"{message1_hash=}")
logging.info("Storing on chain...")
status = custodian.store_hash_on_chain(user_a, message1_hash)
assert status[0] == "COMMITTED"
logging.info("Jack successfully stored message1 hash")

wait_point("Jill replies to Jack and also logs the hash")
message2_hash = custodian.get_file_hash("messages/message2.secret")
logging.info(f"{message2_hash=}")
logging.info("Storing on chain...")
status = custodian.store_hash_on_chain(user_b, message2_hash)
assert status[0] == "COMMITTED"
logging.info("Jill successfully stored message2 hash")

wait_point("Jack, receiving Jill's reply, creates reply message3 but does not send it")

print("\n\n")

wait_point("Some time later, Victoria is called in to verify the communications have occurred")
logging.info("Victoria gets the chain hashes")
domain_hashes = custodian.get_domain_hashes()
logging.info(json.dumps(domain_hashes, indent=2))

wait_point("Victoria gets message1 and checks if the hash exists on the chain")
file_hash = custodian.get_file_hash("messages/message1.secret")
logging.info(f"Searching for hash {file_hash}...")
assert custodian.find_hash_on_chain(user_c, file_hash)
logging.info("Victoria found message1 hash on chain")

wait_point("Victoria gets message2 and checks if the hash exists on the chain")
file_hash = custodian.get_file_hash("messages/message2.secret")
logging.info(f"Searching for hash {file_hash}...")
assert custodian.find_hash_on_chain(user_c, file_hash)
logging.info("Victoria found message2 hash on chain")

wait_point("Victoria is asked to verify if message3 is on chain\nJack claims he sent message3 but actually did not")
file_hash = custodian.get_file_hash("messages/message3.secret")
logging.info(f"Searching for hash {file_hash}...")
assert not custodian.find_hash_on_chain(user_c, file_hash)
logging.info("Victoria did not find message3 hash on chain, verifies that message3 was not sent")

wait_point("Valid communications are verified, unsent messages are identified!")

log_all_blocks("node1.log")
41 changes: 0 additions & 41 deletions usr_scripts/UpdatingFileHash.py

This file was deleted.

Loading