CSE 422: Assignment #9

Blockchains

Due: Wed, Mar 13, 11:59pm
Gradescope Link
Dropbox for code

Problem 1: Distributed consensus

(a) [4 points] A simple BB protocol

Consider the following protocol for the Byzantine Broadcast (BB) problem:

Does this protocol solve the BB problem? In order words, does it satisfy both the Consistency and Validity requirements? If so, argue that this is true. If not, give an attack that breaks one of the two properties (use as few corrupted nodes as possible).

(b) [4 points] Multi-bit consensus

Recall the Dolev-Strong protocol for distributed consensus:

Present a protocol in which the sender receives an \(\ell\)-bit message \(m \in \{0,1\}^{\ell}\) and wants to propagate it to all the nodes. Consistency and Validity are defined as before. As for Dolev-Strong, your protocol should be secure as long as the number of corrupted nodes is at most \(f \leq n\).

(c) [4 points] Flawed implementations of Dolev-Strong

Analyze each of these (flawed) implementations of the Dolev-Strong protocol and present an attack using as few corrupted nodes as possible. In each case, explain which of the two defining properties your attack violates.

Problem 2: Dynamic security parameters

Recall that a block in some blockchain is a \(4\)-tuple:

\[\left[h_{-1}, \eta, \mathsf{tx}, h\right],\]

where \(h_{-1}\) is the previous hash, \(\eta\) is the “puzzle solution”, \(\mathsf{tx}\) is the set of transactions to be recorded on the chain, and \(h = \mathsf{H}(h_{-1},\eta,\mathsf{tx})\).

Recall also that this block is valid if it holds that

\[h = \mathsf{H}(h_{-1}, \eta, \mathsf{tx}) < D,\]

where \(D\) is the hardness parameter (and we interpret the output of \(\mathsf{H}\) as an integer).

For this problem, you will use sha256 to implement $\mathsf{H}$. You can look up the documentation for hashlib in Python. To create a hash of a \(3\)-tuple, consider the example code:

   import hashlib

   h = hashlib.sha256()
   h.update(h_prev)
   h.update(eta)
   h.update(tx)

   hash = int.from_bytes(h.digest(), byteorder='little')
   

Note that h.update takes a bytestring as input. It doesn’t matter how you convert between ints, strings, and bytes as long as you are consistent (e.g., use a consistent byteorder).

(a) [4 points]

Suppose you have a target for the amount of time it should take to create a new block on the chain. For this problem, use TARGET_TIME = 10.0 (seconds).

Clearly the total computational power associated to mining can change throughout the life of the blockchain, and therefore it makes sense that the security parameter \(D\) is dynamic.

Implement code that repeatedly creates valid new blocks with \(\mathsf{tx}\) equal to the block index (\(\mathsf{tx}=0,1,2,\ldots\)), where the security parameter \(D_j\) is allowed to change. You can start with an arbitrary \(D_0\) (for instance, \(D_0 = 0.01 \cdot 2^{256}\) makes sense).

Write a loop that creates a blockchain of length \(100\) and records the elapsed time for the creation of each new block. If elapsed < TARGET_TIME, update the security parameter as \(D_{j+1} = D_j/2\), and otherwise \(D_{j+1} = 2 D_j\).

For this part, include your code, as well as a log of the \(100\) blocks, the time elapsed in creating the block, and the security parameter for each block.

(b) [6 points]

Plot a histogram of the elapsed block times and compute the mean and variance of the elapsed times.

(c) [4 points]

Since a transaction is only recorded to the chain when the block containing it is produced, discuss briefly the implications of the variance you recorded in part (b).

(d) [8 points]

Try to implement a better update rule for the security parameter \(D_j\). Explain your update rule and include the code.

Plot a histogram as in part (b) and compute the mean and variance of the elapsed times in creating a blockchain of length \(100\).

Discuss briefly why your update rule is better or worse than the update rule in part (a), in the context of your answer to (c).

(e) [4 points]

To simulate the effects of dynamically-changing mining power, suppose you add a slowdown parameter that changes for every block. If the parameter is \(s\), then your code should execute time.sleep(s) in every iteration of the loop that searches for a puzzle solution \(\eta\).

For every one of the \(100\) blocks, you should choose the sleep parameter via s = random.uniform(0.000,0.001).

Plot two histograms of the elapsed times and compute the mean and variance of the elapsed times using first the update rule of part (a), and then the update rule for part (d).