serverwallet

Server-side payment links with metadata.
Info | Log | Files | Refs

btc.py (1777B)


      1 import os
      2 import logging
      3 import hashlib
      4 import time
      5 
      6 from bip32 import BIP32
      7 import base58
      8 
      9 from srvaddrgen import DbKey
     10 
     11 logg = logging.getLogger('btc')
     12 
     13 
     14 envkey = 'SRVADDRGEN_BTC_XPUB'
     15 
     16 def btc_reserve(responder, msg, dbenv): 
     17     logg.debug('processing btc')
     18     xpub = os.environ.get(envkey, None)
     19     idx = -1
     20     addr = None
     21     k = DbKey.BTC_XPUB.value
     22     xpub_bin = xpub.encode('utf-8')
     23     if xpub != None:
     24         tx = dbenv.begin(write=True)
     25         v = tx.get(k)
     26         if v == None:
     27             logg.info('BTC XPUB not set')
     28             v = b'\x00' * 8
     29             v += xpub_bin 
     30             tx.put(k, v, dupdata=False)
     31         tx.commit()
     32 
     33     tx = dbenv.begin(write=True)
     34     v = tx.get(k)
     35     idx = int.from_bytes(v[:8]) 
     36     if v[8:] != xpub_bin:
     37         responder.croak(500, 'Master key has changed on server. Contact server administrator.', reason='Illegal key change')
     38         raise responder
     39    
     40     xpub = v[8:].decode('utf-8')
     41     o = BIP32.from_xpub(xpub)
     42     pubk_bytes = o.get_pubkey_from_path('m/0/' + str(idx))
     43     hsh = b'\x00' + hashlib.new('ripemd160', hashlib.new('sha256', pubk_bytes).digest()).digest()
     44     pfx = hashlib.new('sha256', hashlib.new('sha256', hsh).digest()).digest()[:4]
     45     addr = base58.b58encode(hsh + pfx)
     46 
     47     k = DbKey.ADDR.value + addr
     48     v = int.to_bytes(idx, 8)
     49     v += int(time.time()).to_bytes(8)
     50     v += msg.serialize()
     51     r = tx.put(k, v, dupdata=False)
     52     if not r:
     53         tx.abort()
     54         return responder.croak(500, 'Database write error')
     55 
     56     idx = idx + 1
     57     k = DbKey.BTC_XPUB.value
     58     v = idx.to_bytes(8)
     59     v += xpub_bin
     60     r = tx.put(k, v)
     61     if not r:
     62         tx.abort()
     63         return responder.croak(500, 'Database write error')
     64 
     65     tx.commit()
     66     
     67     responder.complete(content=addr)