Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save cdetrio/c5da3ecd887d77512ae52fdc3475462c to your computer and use it in GitHub Desktop.
Save cdetrio/c5da3ecd887d77512ae52fdc3475462c to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"from scipy.stats import entropy\n",
"import numpy as np\n",
"import math\n",
"\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Channel capacities and 51% attacks\n",
"\n",
"If we view a blockchain as a communication channel, an attacker's hash rate corresponds to adversarial noise. The level of adversarial noise places an upper bound on the [channel capacity](https://en.wikipedia.org/wiki/Channel_capacity).\n",
"\n",
"Our starting point is [LaViola and Miller's model](https://socrates1024.s3.amazonaws.com/consensus.pdf) of bitcoin's PoW blockchain as a statistical test between two exponential distributions, i.e. the KL-divergence between two rate parameters (the arrival rate of blocks from correct processes vs. the arrival rate of blocks from byzantine processes):\n",
"\n",
"> We can thus relate the Byzantine consensus problem to a statistical test. At each instant, every process prefers the value that is most likely, given the available information, to be preferred by the largest number of processes. For the particular puzzle we defined, the only discriminating information is the number of distinct puzzle solutions found. Consider the number of bits of certainty obtained per message, (i.e., k/x). From Equation 1, this is equal to the KL-divergence between two exponential distributions, where δ is the ratio between the respective scale parameters. ([LaViola and Miller, 2012](https://socrates1024.s3.amazonaws.com/consensus.pdf))\n",
"\n",
"\n",
"We'll look at the relation between this KL-divergence, the capacity of a binary symmetric channel, and the capacity of a Poisson channel."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"# KL-divergence between two exponential rate parameters (from Miller 2012 paper)\n",
"# > Let B be a subset of n − f correct processes. ...\n",
"# > the subset B finds puzzle solutions according to a Poisson arrival process\n",
"# > with expected interarrival time µ_B = (δ/2)µ, where δ = 2(n−f)/n > 1 (in particular, faster than half the overall rate).\n",
"\n",
"\n",
"# KL-divergence formula: https://en.wikipedia.org/wiki/Exponential_distribution#Kullback.E2.80.93Leibler_divergence\n",
"# p and q are rate (or scale) parameters\n",
"# rate parameter for overall rate = 2\n",
"# rate parameter for half of overall rate = 1\n",
"\n",
"def ExponentialKLd(p, q):\n",
" nats = (p/q - np.log(p/q) - 1) # KL-divergence in nats\n",
" return nats*np.log2(math.e) # convert from nats to bits"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's calculate the bits of information per block when 70% of the processes are correct."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.091651189185343443"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# scale parameter for 70% = 0.7*2 = 1.4\n",
"# compare 70% of hashrate (1.4) to half of overall hashrate (1)\n",
"\n",
"ExponentialKLd(1.4, 1)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"So when 70% of processes are correct, each block carries 0.09165.. bits of information.\n",
"\n",
"Since 70% of processes are correct, the noise rate is 30%. As a sanity check, let's compare to the capacity of a [binary symmetric channel](https://en.wikipedia.org/wiki/Binary_symmetric_channel)."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def H(x): # entropy of a biased coin flip\n",
" return -(1 - x)*np.log2(1 - x) - x*np.log2(x)\n",
"\n",
"def BSCcapacity(x): # capacity of a binary symmetric channel\n",
" # x = bit error rate\n",
" return 1 - H(x)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.1187091007693073"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"BSCcapacity(0.30) # capacity when noise rate is 30%"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"The bits per block (0.09165..) is below the binary symmetric channel capacity (0.1187..), so it passes our sanity check.\n",
"\n",
"Let's check when 55% of processes are correct."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.0067659803389613724"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 0.55*2 = 1.1\n",
"ExponentialKLd(1.1, 1)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.0072255460121917192"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 55% correct, or 45% noise\n",
"BSCcapacity(0.45)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"Good, with 55% of processes correct, the bits per block is still below the channel capacity. Let's try with 51% correct."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.00028474862100832558"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 0.51*2 = 1.02\n",
"ExponentialKLd(1.02, 1)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.00028855824719009604"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"BSCcapacity(0.49)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"0.000284.. < 0.000288.. so the sanity check is still good.\n",
"\n",
"Observe that as the proportion of correct processes decreases to 0.5, the bits of information per block approaches 0. That's what we should expect, since the theoretical capacity of a binary symmetric channel with a 50% noise rate is 0."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.0"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"BSCcapacity(0.5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's go in the direction of less noise, and try with 90% correct processes."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.30615912615622071"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 0.9*2 = 1.8\n",
"ExponentialKLd(1.8, 1)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.53100440641071878"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"BSCcapacity(0.1)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"The bits per block (0.306..) is way below the BSC capacity (0.531..), and the gap only grows as the correct proportion increases to 100% (noise rate decreases to 0%).\n",
"\n",
"Let's check the gap when 99.9% of processes are correct."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.44125306767685413"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 0.999 * 2 = 1.998\n",
"ExponentialKLd(1.998, 1)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.98859224226253883"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"BSCcapacity(0.001)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"So with higher noise rates (e.g. 30% to 50%), the information per block approaches the capacity of a binary symmetric channel. But with lower noise rates (e.g. 0% to 20%), the information per block is well below the BSC capacity.\n",
"\n",
"Let's look for a channel model that works better than BSC for lower noise rates.\n",
"\n",
"Recall that the information per block is the KL-divergence between two exponential distributions. Since blocks arrive according to a Poisson process (i.e. the times between arrivals form an exponential distribution), this suggests trying a Poisson channel as the channel model."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"# Poisson channel capacity formula taken from (1.5) in http://wiki.epfl.ch/edicpublic/documents/Candidacy%20exam/wyner.pdf\n",
"# > for codes which achieve capacity, the average number of received photons per second is q_star*A*T. \n",
"\n",
"# A = peak power constraint of input\n",
"# ortho*A = average power constraint. when average-power == peak-power, ortho=1\n",
"# lam0 = \"dark current\" noise. nonnegative constant\n",
"# total rate of poisson channel = A + lam0\n",
"# s = lam0/A\n",
"# q_star = min(ortho, q0(s))\n",
"# q0(s) = [ ((1+s)^(1+s)) / ((s^s)*e) ] - s\n",
"\n",
"\n",
"def poissonCapacity(A):\n",
" lam0 = 1 - A # A is rate of \"correct\" input, lam0 is the noise rate\n",
" s = lam0/A\n",
" q0 = ( ((1+s)**(1+s)) / ((s**s)*math.e) ) - s\n",
" q_star = min(1, q0)\n",
" C = A * ( (q_star*(1+s)*math.log(1+s)) + ((1-q_star)*s*math.log(s)) - ((q_star+s)*math.log(q_star+s)) )\n",
" return C*np.log2(math.e) # convert from nats to bits\n",
"\n",
"\n",
"# formula for high noise.. s -> infinity\n",
"# (1.7a) in http://wiki.epfl.ch/edicpublic/documents/Candidacy%20exam/wyner.pdf\n",
"# couldn't get sensible results from this formula, but might try again in the future\n",
"#def noisyPoissonC(A, lam0):\n",
"# s = lam0/A\n",
"# q_star = min(1, 1/2)\n",
"# big_o = (1 / s**2)\n",
"# C = ( A*q_star*(1-q_star) ) / ( 2*s ) + big_o\n",
"# return C*np.log2(math.e)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's check the gap between the information per block and the poisson channel capacity when 90% of processes are correct."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.31637116481270106"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# A is the correct rate\n",
"# lam0 is the noise rate\n",
"\n",
"# check the capacity when 90% of processes are correct\n",
"poissonCapacity(0.90)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.30615912615622071"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 0.9*2 = 1.8\n",
"ExponentialKLd(1.8, 1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Using a Poisson channel rather than a binary symmetric channel, the gap is much closer!\n",
"\n",
"Let's go ahead and plot all three: the information per block, the capacity of a binary symmetric channel, and the capacity of a Poisson channel."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def bitsPerBlock(correct_rates):\n",
" data_points = [[x, ExponentialKLd(2*x, 1)] for x in correct_rates]\n",
" return np.array(data_points)\n",
"\n",
"\n",
"def BSCdataPoints(correct_rates):\n",
" data_points = [[x, BSCcapacity(1-x)] for x in correct_rates]\n",
" return np.array(data_points)\n",
"\n",
"\n",
"def poissonDataPoints(correct_rates):\n",
" data_points = [[x, poissonCapacity(x)] for x in correct_rates]\n",
" return np.array(data_points)\n",
"\n",
"\n",
"\n",
"noise_rates = np.linspace(0.01, 0.49, num=49) # from 0.01 to 0.49 because 0.50 causes warning\n",
"correct_rates = (1 - noise_rates)[::-1]\n",
"\n",
"poisson_data = poissonDataPoints(correct_rates)\n",
"bsc_data = BSCdataPoints(correct_rates)\n",
"pow_data = bitsPerBlock(correct_rates)\n"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "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\nwQKee+65cJcVFJqwKJEm0FnxBSLYY2JiAnpumTWJlO7YLbQFiRRSNWrUYMCAASdHaWPGjKFly5ZU\nqHimU9wAACAASURBVFCB3r17k5CQcPK59erVY9q0aQDMmzePTp06Ua5cOapXr84f//hHAI4dO8bN\nN99M5cqVqVChAp07d2bXrl0AbN++nSuvvJJKlSrRuHFj3nvvvZPvHRsby+DBg7n11lspW7YsrVq1\nYuHChWete8WKFfTv359KlSpRvXp1nn/+ecD/0XL8+PGzvs8LL7xAo0aNKFu2LC1btmT06NEnf/bh\nhx/So0cPHn/8cSpWrEiDBg2YMGHCyZ/HxMTw1FNP0aNHD8qWLcsll1zCnj17Tv58zpw5dO/enQoV\nKtCuXTtmzJgR0L9Bamoq//jHP07W1alTJ7Zt2wbAww8/TJ06dShXrhydOnVi9uzZp/xvdt1113Hj\njTdStmxZOnbsSHx8fEC/K8C7775LixYtTv58yZIlgP93njp1KhMmTOD555/nyy+/5Pzzz6d9+/Z8\n9dVXdOrU6ZT3efXVV7n66qsD+l0Lo5iYmICCHTPLt4cvPzDJKcm2ppKzA4vmBPwakUiQnf/O81q9\nevVsypQpZma2efNma9mypT311FO2evVqK126tE2ZMsWSk5PtxRdftEaNGtmJEydOvm7q1KlmZta1\na1f75JNPzMzs8OHDNnfuXDMze/vtt23gwIF29OhRS01NtUWLFtmBAwfMzKxnz572wAMPWFJSki1Z\nssSqVKli06ZNMzOzp59+2kqUKGHjx4+31NRUe+KJJ6xr165nrP/AgQNWvXp1e/XVVy0pKckOHjx4\n8vOzep8RI0bYTz/9ZGZmX375pZUuXdp27NhhZmZDhw61YsWK2XvvvWepqan21ltvWY0aNU6+Njo6\n2ho1amRr1661o0ePWkxMjP35z382M7OtW7dapUqVbPz48WZmNnnyZKtUqZL9/PPPZmYWExNj77//\n/hl/nxdffNFat25ta9asMTOz+Ph427Nnj5mZffLJJ7Z3715LSUmxV155xapXr25JSUknf9dixYrZ\nyJEjLTk52V5++WWrX7++JScnZ/m7Dh8+3GrWrGkLFiwwM7N169bZpk2bfvXvHBsba7fccsvJWpOS\nkqxixYq2atWqk+fatWtno0aNOuPvVhgB9umnn9prr732q/N2rmw81w8j/cjO/+Gt3bTEjhZzZseP\n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\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x1047f7e10>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, ax = plt.subplots(figsize=(8,6))\n",
"\n",
"plt.plot(poisson_data[:,0], poisson_data[:,1], label='Poisson channel capacity')\n",
"plt.plot(bsc_data[:,0], bsc_data[:,1], label='binary symmetric channel capacity')\n",
"plt.plot(pow_data[:,0], pow_data[:,1], label='bits per PoW block')\n",
"\n",
"xticks = [poisson_data[:,0][i] for i in range(len(poisson_data[:,0])) if (i%4==0)]\n",
"xticks.append(0.99)\n",
"xticklabels = (1 - np.array(xticks))\n",
"\n",
"ax.set_xticks(xticks)\n",
"ax.set_xticklabels(xticklabels)\n",
"plt.xlabel('error rate')\n",
"plt.ylabel('channel capacity (bits per message)')\n",
"ax.set_yscale('log')\n",
"legend = ax.legend(loc='best', shadow=True)\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.11"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment