Instantly share code, notes, and snippets.

# marekyggdrasil/figures_thumbnail.sh

Last active December 20, 2022 15:33
Star You must be signed in to star a gist
Example code for the tutorial on Pedersen Commitments and Confidential Transactions available under https://mareknarozniak.com/2021/06/22/ct/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
 #!/bin/sh convert -background none inputs_before.png inputs_after.png +append inputs.png   This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
 numpy matplotlib minicurve
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
 import math import matplotlib.pyplot as plt import numpy as np import hashlib from minicurve import MiniCurve as mc from minicurve import Visualizer from minicurve.helpers import inverse def add_digits(num, p): return (num - 1) % p if num > 0 else 0 def hashtard(m, p): hash = hashlib.sha256(str.encode(m)) num = int.from_bytes(hash.digest(), 'big') num = add_digits(num, p) return num def sign(m, k, d, G, p): # calculate public key R = k*G R = k*G # calculate e = H(M || r) where || is concatenation e = hashtard(m, p) # calculate the signature s = np.mod(k + d*e, p) # signature is s, R return s, R def verify(m, s, G, P, R, p): # e_v = H(M || r_v) e = hashtard(m, p) # calculate the verification lhs = s*G rhs = R+e*P # test if lhs = rhs if lhs == rhs: return True, lhs, rhs return False, lhs, rhs # n is a group order def isTransactionValid(G, inputs_data, outputs_data, p): inp, inputs_signature = inputs_data out, outputs_signature = outputs_data # calculate inputs - outputs P = inp - out # check if signature matches proving the difference is 0 inp_s, inp_R = inputs_signature out_s, out_R = outputs_signature s_comb = np.mod(inp_s - out_s, p) valid, _, _ = verify('m', s_comb, G, P, inp_R - out_R, p) return valid # article URL url = 'https://mareknarozniak.com/2021/06/22/ct/' # eliptic curve and finite field parameters p = 13 a = 1 b = 7 # we need two generator points, G for blinding factors and H for the amounts G = mc(a, b, p, x=10, y=4, label='G', color='tab:green', tracing=True) H = mc(a, b, p, x=9, y=11, label='H', color='tab:cyan', tracing=True) # construct the inputs # blinding factors bs = [1, 5] # amounts am = [2, 4] # compute blinded inputs inputs = [] for bsv, amv in zip(bs, am): R = bsv*G + amv*H R.setColor('tab:orange') inputs.append(R) # visualize pre-transaction space inputs.setLabel('?') inputs.setLabel('Alice') vis = Visualizer(a, b, p) vis.makeField() vis.points = [G, H] + inputs vis.generatePlot(title='Inputs before the transaction') plt.figtext(0.0, 0.01, url, rotation=0) vis.plot('inputs_before.png') # perform the transaction # the payor owns an input of value of 4 coins # is going to transfer 1 coin to payee and 3 coins # back to him/herself as a change inp = inputs # payor signs input with blinding factor as the private key k = 9 # random nonce inp_s, inp_R = sign('m', k, bs, G, p) # calculate the change, sending 3 coins back and choosing # the blinding factor 6 chn = 6*G + 3*H chn.setColor('tab:orange') chn.setLabel('Alice') # payor signs change with blinding factor as the private key, payor chooses 6 k = 1 # random nonce chn_s, chn_R = sign('m', k, 6, G, p) # now the payee creates own output, is receiving 1 coin # and choses the blinding factor of 7 nout = 7*G + 1*H nout.setColor('tab:orange') nout.setLabel('Bob') # payee signs own output with newly chosen blinding factor k = 3 # random nonce out_s, out_R = sign('m', k, 7, G, p) # gather all the outputs together to form a single output out = nout + chn # add output signatures as well comb_R = out_R + chn_R comb_s = np.mod(out_s + chn_s, p) # prepare data for the verifier inputs_signature = inp_s, inp_R inputs_data = inp, inputs_signature outputs_signature = comb_s, comb_R outputs_data = out, outputs_signature valid = isTransactionValid(G, inputs_data, outputs_data, p) print('Is transaction valid?', valid) # visualize the finite field after the transaction is made # start by removing the input that was just spent from the # finite field del inputs # include the newly created inputs into the field inputs.append(chn) inputs.append(nout) # plot again vis = Visualizer(a, b, p) vis.makeField() vis.points = [G, H] + inputs vis.generatePlot(title='Inputs after the transaction') vis.plot('inputs_after.png')