-
Notifications
You must be signed in to change notification settings - Fork 0
/
piper.py
executable file
·330 lines (231 loc) · 8.79 KB
/
piper.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
#!/usr/bin/python
# This file is part of Piper.
#
# Piper is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Piper is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Piper. If not, see <http://www.gnu.org/licenses/>.
#
# Piper Copyright (C) 2013 Christopher Cassano
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
import qrcode
import sys
import sqlite3
from btc_case import lcd_display
from subprocess import Popen, PIPE
sys.path.append('/home/pi/build/Python-Thermal-Printer')
from Adafruit_Thermal import *
def print_seed(seed):
printer = Adafruit_Thermal("/dev/ttyAMA0", 19200, timeout=5)
printer.println(seed)
printer.feed(3)
printer.sleep() # Tell printer to sleep
printer.wake() # Call wake() before printing again, even if reset
printer.setDefault() # Restore printer to defaults
def print_keypair(pubkey, privkey, leftBorderText, curbtc, inputamt, tx_hash):
#open the printer itself
printer = Adafruit_Thermal("/dev/ttyAMA0", 19200, timeout=5)
#load a blank image of the paper wallet with no QR codes or keys on it which we will draw on
if(len(privkey) <= 51):
finalImg = Image.open("/home/pi/build/Piper/btc-wallet-blank.bmp")
else:
finalImg = Image.open("/home/pi/build/Piper/btc-wallet-enc.bmp")
#---begin the public key qr code generation and drawing section---
#we begin the QR code creation process
#feel free to change the error correct level as you see fit
qr = qrcode.QRCode(
version=None,
error_correction=qrcode.constants.ERROR_CORRECT_M,
box_size=10,
border=0,
)
qr.add_data(pubkey)
qr.make(fit=True)
pubkeyImg = qr.make_image()
#resize the qr code to match our design
pubkeyImg = pubkeyImg.resize((175,175), Image.NEAREST)
font = ImageFont.truetype("/usr/share/fonts/ttf/ubuntu-font-family-0.80/UbuntuMono-R.ttf", 20)
draw = ImageDraw.Draw(finalImg)
startPos=(110,38)
charDist=15
lineHeight=23
lastCharPos=0
keyLength = len(pubkey)
print keyLength
while(keyLength % 17 != 0):
pubkey += " "
keyLength = len(pubkey)
#draw 2 lines of 17 characters each. keyLength always == 34 so keylength/17 == 2
for x in range(0,keyLength/17):
lastCharPos=0
#print a line
for y in range(0, 17):
theChar = pubkey[(x*17)+y]
charSize = draw.textsize(theChar, font=font)
#if y is 0 then this is the first run of this loop, and we should use startPos[0] for the x coordinate instead of the lastCharPos
if y == 0:
draw.text((startPos[0],startPos[1]+(lineHeight*x)),theChar, font=font, fill=0)
lastCharPos = startPos[0]+charSize[0]+(charDist-charSize[0])
else:
draw.text((lastCharPos,startPos[1]+(lineHeight*x)),theChar, font=font, fill=0)
lastCharPos = lastCharPos + charSize[0] + (charDist-charSize[0])
#draw the QR code on the final image
finalImg.paste(pubkeyImg, (150, 106))
#---end the public key qr code generation and drawing section---
#---begin the private key qr code generation and drawing section---
#we begin the QR code creation process
#feel free to change the error correct level as you see fit
qr = qrcode.QRCode(
version=None,
error_correction=qrcode.constants.ERROR_CORRECT_M,
box_size=10,
border=0,
)
qr.add_data(privkey)
qr.make(fit=True)
privkeyImg = qr.make_image()
#resize the qr code to match our design
privkeyImg = privkeyImg.resize((220,220), Image.NEAREST)
#draw the QR code on the final image
finalImg.paste(privkeyImg, (125, 560))
startPos=(110,807)
charDist=15
lineHeight=23
lastCharPos=0
keyLength = len(privkey)
while(keyLength % 17 != 0):
privkey += " "
keyLength = len(privkey)
#draw 2 lines of 17 characters each. keyLength always == 34 so keylength/17 == 2
for x in range(0,keyLength/17):
lastCharPos=0
#print a line
for y in range(0, 17):
theChar = privkey[(x*17)+y]
charSize = draw.textsize(theChar, font=font)
#print charSize
if y == 0:
draw.text((startPos[0],startPos[1]+(lineHeight*x)),theChar, font=font, fill=0)
lastCharPos = startPos[0]+charSize[0]+(charDist-charSize[0])
else:
draw.text((lastCharPos,startPos[1]+(lineHeight*x)),theChar, font=font, fill=0)
lastCharPos = lastCharPos + charSize[0] + (charDist-charSize[0])
#---end the private key qr code generation and drawing section---
#create the divider
rightMarkText = "ArchReactor.org"
font = ImageFont.truetype("/usr/share/fonts/ttf/swansea.ttf", 20)
rightMarkSize = draw.textsize(rightMarkText, font=font)
leftMarkOrigin = (10, 15)
rightMarkOrigin = (384-rightMarkSize[0]-10, 15)
dividerLineImg = Image.open("/home/pi/build/Piper/dividerline.bmp")
draw = ImageDraw.Draw(dividerLineImg)
draw.text(leftMarkOrigin, leftBorderText, font=font, fill=0)
draw.text(rightMarkOrigin,rightMarkText, font=font, fill=0)
#finalImg.save('file.png')
#dividerLineImg.save('file2.png')
#do the actual printing
usd = 1.0/float(curbtc)
returnamt = usd*float(inputamt)
printer.println("1BTC=$"+str(curbtc))
printer.println("1USD=B"+str(usd))
printer.println("Input=$"+str(inputamt))
printer.println("Return=B"+str(returnamt))
printer.println("Transaction Hash: "+str(tx_hash))
printer.printImage(finalImg)
#if(len(privkey) <= 51):
# printer.println(privkey[:17]+"\n")
# printer.justify('R')
# printer.println(privkey[17:34]+"\n")
# printer.justify('L')
# printer.println(privkey[34:]+"\n")
#else:
# printer.println(privkey)
#print the divider line
printer.printImage(dividerLineImg)
#print some blank space so we can get a clean tear of the paper
printer.feed(3)
printer.sleep() # Tell printer to sleep
printer.wake() # Call wake() before printing again, even if reset
printer.setDefault() # Restore printer to defaults
def genAndPrintKeys(curbtc, inputamt, numCopies, password, lcd):
remPubKey = False
remPrivKey = False
#open serial number file which tracks the serial number
snumfile = open('serialnumber.txt', 'r+')
snum = snumfile.read()
#open the printer itself
printer = Adafruit_Thermal("/dev/ttyAMA0", 19200, timeout=5)
#load a blank image of the paper wallet with no QR codes or keys on it which we will draw on
finalImg = Image.open("btc-wallet-blank.bmp")
lcd_display(lcd, "Generating", "address")
#this actually generates the keys. see the file genkeys.py or genkeys_forget.py
import genkeys as btckeys
btckeys.genKeys()
if btckeys.keysAreValid == False:
printer.write("Error: The generated keys (public/private) are not the correct length. Please try again.")
#import wallet_enc as WalletEnc
#encrypt the keys if needed
#if(password != ""):
# privkey = WalletEnc.pw_encode(btckeys.privkey, password)
#else:
privkey = btckeys.privkey
rememberKeys = False
sqlitePubKey = ""
sqlitePrivKey = ""
strToWrite = ""
if remPubKey:
strToWrite = "\nPublic Key: "+btckeys.pubkey
sqlitePubKey = btckeys.pubkey
rememberKeys = True
if remPrivKey:
strToWrite = strToWrite + "\nPrivate Key: "+privkey
sqlitePrivKey = privkey
rememberKeys = True
if rememberKeys == True:
#store it to the sqlite db
con = None
try:
con = sqlite3.connect('/home/pi/build/Piper/keys.db3')
con.execute("INSERT INTO keys (serialnum, public, private) VALUES (?,?,?)", (snum, sqlitePubKey, sqlitePrivKey))
except sqlite3.Error, e:
print "Error %s:" % e.args[0]
sys.exit(1)
finally:
if con:
con.commit()
con.close()
#store it in a flat file on the sd card
f = open("/boot/keys.txt", 'a+')
strToWrite = "Serial Number: " + snum + strToWrite
f.write(strToWrite);
f.write("\n---------------------------------\n")
f.close()
leftMarkText = "Serial Number: "+snum
lcd_display(lcd, "Transferring", "Bitcoins!")
usd = 1.0/float(curbtc)
returnamt = usd*float(inputamt)
#electrum -w /home/pi/.electrum/wallets/default_wallet -f 0.0001 payto 1PPyJbKyMtKjiMPJcm4dYbRdy9BcW3i3j2 0.0030
transfer_cmd = ['electrum', '-w', '/home/pi/.electrum/wallets/default_wallet', '-f', '0.0001', 'payto', str(btckeys.pubkey), str(returnamt)]
tx_hash = Popen(transfer_cmd, stdout=PIPE).communicate()[0]
lcd_display(lcd, "Printing", "receipt")
#do the actual printing
for x in range(0, numCopies):
#piper.print_keypair(pubkey, privkey, leftBorderText)
print_keypair(btckeys.pubkey, privkey, leftMarkText, curbtc, inputamt, tx_hash)
if numCopies > 1 and x < numCopies-1:
time.sleep(30)
#update serial number
snumfile.seek(0,0)
snumfile.write(str(int(snum)+1))
snumfile.close()
return btckeys.pubkey