def _generate_new_keypair(self): seed = str(random.randrange(2 ** 256)) # Deprecated (pre-BIP32) # self.secret = hashlib.sha256(secret).hexdigest() # self.pubkey = privkey_to_pubkey(self.secret) # self.log.debug('Keys %s %s', self.secret, self.pubkey) # Move to BIP32 keys m/0/0/0 wallet = bitcoin.bip32_ckd(bitcoin.bip32_master_key(seed), 0) wallet_chain = bitcoin.bip32_ckd(wallet, 0) bip32_identity_priv = bitcoin.bip32_ckd(wallet_chain, 0) identity_priv = bitcoin.bip32_extract_key(bip32_identity_priv) bip32_identity_pub = bitcoin.bip32_privtopub(bip32_identity_priv) identity_pub = bitcoin.encode_pubkey(bitcoin.bip32_extract_key(bip32_identity_pub), 'hex') self.pubkey = identity_pub self.secret = identity_priv new_settings = { "secret": self.secret, "pubkey": self.pubkey, "bip32_seed": seed } self.db_connection.update_entries("settings", new_settings, {"market_id": self.market_id}) self.settings.update(new_settings)
def _derive_and_print(master_key: str, *path: int, derive_pub_key: bool = True, magicbyte: int = 0): master_pub_key = bitcoin.bip32_privtopub(master_key) derived_key = _derived_key(master_key, *path) if derive_pub_key: derived_bip32_pub_key = _derived_key(master_pub_key, *path) derived_pub_key = bitcoin.bip32_extract_key(derived_bip32_pub_key) else: derived_bip32_pub_key = derived_pub_key = 'N.A.' derived_pub_key_from_key = bitcoin.bip32_privtopub(derived_key) print(''' Derivation path: ({}), Derived BIP32 key: {}, Derived BIP32 public key: {}, BIP32 public key from derived BIP32 private: {}, Derived key: {}, Derived public key: {}, Public key from derived key: {}, BTC address: {} '''.format( ', '.join( str(x) if x <= 2**31 else str(x - 2**31) + '\'' for x in path), derived_key, derived_bip32_pub_key, derived_pub_key_from_key, bitcoin.bip32_extract_key(derived_key), derived_pub_key, bitcoin.privtopub(bitcoin.bip32_extract_key(derived_key)), bitcoin.pubtoaddr(bitcoin.privtopub( bitcoin.bip32_extract_key(derived_key)), magicbyte=magicbyte)))
def _generate_new_keypair(self): seed = str(random.randrange(2**256)) # Deprecated (pre-BIP32) # self.secret = hashlib.sha256(secret).hexdigest() # self.pubkey = privkey_to_pubkey(self.secret) # self.log.debug('Keys %s %s', self.secret, self.pubkey) # Move to BIP32 keys m/0/0/0 wallet = bitcoin.bip32_ckd(bitcoin.bip32_master_key(seed), 0) wallet_chain = bitcoin.bip32_ckd(wallet, 0) bip32_identity_priv = bitcoin.bip32_ckd(wallet_chain, 0) identity_priv = bitcoin.bip32_extract_key(bip32_identity_priv) bip32_identity_pub = bitcoin.bip32_privtopub(bip32_identity_priv) identity_pub = bitcoin.encode_pubkey( bitcoin.bip32_extract_key(bip32_identity_pub), 'hex') self.pubkey = identity_pub self.secret = identity_priv new_settings = { "secret": self.secret, "pubkey": self.pubkey, "bip32_seed": seed } self.db_connection.update_entries("settings", new_settings, {"market_id": self.market_id}) self.settings.update(new_settings)
def showDetails(mnemonic, passphrase="", i=1): myMnemonic = mnemonic passphrase = passphrase mnemo = Mnemonic('english') seed = hexlify(mnemo.to_seed(myMnemonic, passphrase=passphrase)) print 'Seed:\t\t\t\t', seed priv = bitcoin.bip32_master_key(unhexlify(seed)) print 'Xpriv:\t\t\t\t', priv key = bitcoin.encode_privkey(bitcoin.bip32_extract_key(priv), 'wif_compressed') print 'Key:\t\t\t\t', key pub = bitcoin.bip32_privtopub(priv) print 'Derived public key:\t', pub pubHex = bitcoin.bip32_extract_key(pub) print 'public key (hex):\t', pubHex print 'Master Key address:\t', bitcoin.pubtoaddr(pubHex) print "" print "TREZOR Keys:" account = 0 derivedPrivateKey = bitcoin.bip32_ckd( bitcoin.bip32_ckd(bitcoin.bip32_ckd(priv, 44 + HARDENED), HARDENED), HARDENED + account) print 'Derived private key:', derivedPrivateKey privateKey = bitcoin.encode_privkey( bitcoin.bip32_extract_key(derivedPrivateKey), 'wif_compressed') print 'private key (wif):\t', privateKey derivedPublicKey = bitcoin.bip32_privtopub(derivedPrivateKey) print 'Derived public key:', derivedPublicKey publicKeyHex = bitcoin.privtopub(privateKey) print 'public key (hex):\t', publicKeyHex address = bitcoin.pubtoaddr(publicKeyHex) print 'address:\t\t\t', address print "" print "Account public keys (XPUB)" xpubs = [] for i in range(0, i): derivedPrivateKey = bitcoin.bip32_ckd( bitcoin.bip32_ckd(bitcoin.bip32_ckd(priv, 44 + HARDENED), HARDENED), HARDENED + i) xpub = bitcoin.bip32_privtopub(derivedPrivateKey) print 'Account', i, 'xpub:', xpub xpubs.append(xpub) return xpubs
def showDetails(mnemonic, passphrase="", i=1): myMnemonic = mnemonic passphrase = passphrase mnemo = Mnemonic('english') seed = hexlify(mnemo.to_seed(myMnemonic, passphrase=passphrase)) print 'Seed:\t\t\t\t', seed priv = bitcoin.bip32_master_key(unhexlify(seed)) print 'Xpriv:\t\t\t\t', priv key = bitcoin.encode_privkey(bitcoin.bip32_extract_key(priv), 'wif_compressed') print 'Key:\t\t\t\t', key pub = bitcoin.bip32_privtopub(priv) print 'Derived public key:\t', pub pubHex = bitcoin.bip32_extract_key(pub) print 'public key (hex):\t', pubHex print 'Master Key address:\t', bitcoin.pubtoaddr(pubHex) print "" print "TREZOR Keys:" account = 0 derivedPrivateKey = bitcoin.bip32_ckd(bitcoin.bip32_ckd(bitcoin.bip32_ckd(priv, 44+HARDENED), HARDENED), HARDENED+account) print 'Derived private key:', derivedPrivateKey privateKey = bitcoin.encode_privkey(bitcoin.bip32_extract_key(derivedPrivateKey), 'wif_compressed') print 'private key (wif):\t', privateKey derivedPublicKey = bitcoin.bip32_privtopub(derivedPrivateKey) print 'Derived public key:', derivedPublicKey publicKeyHex = bitcoin.privtopub(privateKey) print 'public key (hex):\t', publicKeyHex address = bitcoin.pubtoaddr(publicKeyHex) print 'address:\t\t\t', address print "" print "Account public keys (XPUB)" xpubs = [] for i in range(0, i): derivedPrivateKey = bitcoin.bip32_ckd(bitcoin.bip32_ckd(bitcoin.bip32_ckd(priv, 44+HARDENED), HARDENED), HARDENED+i) xpub = bitcoin.bip32_privtopub(derivedPrivateKey) print 'Account', i, 'xpub:', xpub xpubs.append(xpub) return xpubs
def cosign(master_xpriv, recovery_package): raw_txs = recovery_package['txs'] print "Signing %d transactions" % len(raw_txs) for tx_index, tx_raw in enumerate(raw_txs): print "\nTransaction #", tx_index hex_tx = tx_raw['bytes'] tx = bitcoin.transaction.deserialize(unhexlify(hex_tx)) keypaths = tx_raw['input_paths'] keypairs = {} for p in keypaths: xpriv = seedlib.bip32_child(master_xpriv, p) priv = bitcoin.bip32_extract_key(xpriv) pub = bitcoin.privtopub(priv) keypairs[pub] = priv for i, inp in enumerate(tx['ins']): (sigs, pubkeys, redeemScript, M, N) = multisig.decode_multisig_script(inp['script']) for p in pubkeys: if p in keypairs: sig_new = bitcoin.multisign(hex_tx, i, redeemScript, keypairs[p]) sigs.append(sig_new) tx_new = bitcoin.apply_multisignatures( unhexlify(hex_tx), i, redeemScript, sigs) print "Signed transaction %d input %d" % (tx_index, i) # replace tx with newly signed transaction hex_tx = hexlify(tx_new) recovery_package['txs'][tx_index]['bytes'] = hex_tx return recovery_package
def get_private_for_chain(account, key_number, settings=None): if settings is None: settings = Settings.Instance().get_settings_json() account_key = settings['accounts'][account]['accountKey'] return_key = bitcoin.bip32_ckd( account_key, key_number ) return_key = bitcoin.bip32_extract_key( return_key ) return return_key
def create_invoice_domain (domain, payer): cur = BMMySQL().conn().cursor(MySQLdb.cursors.DictCursor) filterwarnings('ignore', category = MySQLdb.Warning) cur.execute ("SELECT bm, masterpubkey_btc, offset_btc, feeamount, feecurrency FROM domain WHERE name = %s AND active = 1", (domain)) result = False for row in cur.fetchall(): result = row while result: if result['masterpubkey_btc'][0:4] == "xpub": # BIP44 dpk1 = bitcoin.bip32_ckd(result['masterpubkey_btc'], 0) dpk2 = bitcoin.bip32_ckd(dpk1, result['offset_btc']) pubkey = bitcoin.bip32_extract_key(dpk2) else: # Electrum 1.x pubkey = bitcoin.electrum_pubkey(result['masterpubkey_btc'], result['offset_btc']) address = bitcoin.pubkey_to_address(pubkey) bitcoind_importaddress(address) cur.execute ("UPDATE domain SET offset_btc = offset_btc + 1 WHERE name = %s AND active = 1 AND masterpubkey_btc = %s", (domain, result['masterpubkey_btc'])) if result['feecurrency'] in ("USD", "GBP", "EUR"): result['feeamount'] /= decimal.Decimal(get_bitcoin_price(result['feecurrency'])) cur.execute ("INSERT IGNORE INTO invoice (issuer, payer, address, coin, amount, type, paid) VALUES (%s, %s, %s, 'BTC', %s, 0, 0)", (result['bm'], payer, address, result['feeamount'])) # invoice already exists for that address, increment if cur.rowcount == 0: cur.execute ("SELECT bm, masterpubkey_btc, offset_btc, feeamount, feecurrency FROM domain WHERE name = %s AND active = 1", (domain)) result = False for row in cur.fetchall(): result = row continue cur.close() return address, result['feeamount']; cur.close() return False
def get_bip32_key(public_keys): settings = Settings.Instance().get_settings_json() if (settings['bip32master'] is None): return None account_number, account_key, key_number = KeyHelper.get_account_number_and_chain( settings) #see if we already have this cached, and I can just get the key fast cached = set(settings['accounts'][account_number].get(keys, [])) pub_set = set(public_keys) hits = cached & pub_set if len(hits) > 0: return KeyHelper.get_private_for_chain(account_number, hits[0][0], settings) #drat, didn't find it! at least we can only need to test the ones that #we didn't already check missed = set(range(key_number)) - set([cache[0] for cache in cached]) for i in missed: priv = bitcoin.bip32_ckd(account_key, i) priv = bitcoin.bip32_extract_key(priv) canidate = bitcoin.privtopub(priv) if (canidate in public_keys): return priv return None
def get_next_public_key(): settings = Settings.Instance().get_settings_json() if (settings['bip32master'] is None): raise RuntimeError("Master key has not been set up yet") account_number, account_key, key_number = KeyHelper.get_account_number_and_chain( settings) return_key = bitcoin.bip32_ckd(account_key, key_number) return_key = bitcoin.bip32_extract_key(return_key) return_key = bitcoin.privtopub(return_key) #save key for later if 'keys' not in settings['accounts'][account_number]: settings['accounts'][account_number]['keys'] = [] settings['accounts'][account_number]['keys'].append( (key_number, return_key, False)) #we increment the key counter after making the key #because the chain code is 0 indexed, making the 0th key #the first one we use key_number += 1 #remember to save our new key settings['accounts'][account_number]['numKeys'] = key_number Settings.Instance().save_config_file(settings) return return_key
def get_private_for_chain(account, key_number, settings=None): if settings is None: settings = Settings.Instance().get_settings_json() account_key = settings['accounts'][account]['accountKey'] return_key = bitcoin.bip32_ckd(account_key, key_number) return_key = bitcoin.bip32_extract_key(return_key) return return_key
def regenerate_keys(account_key, needed_keys, key_list): for key in needed_keys: return_key = bitcoin.bip32_ckd(account_key, key) return_key = bitcoin.bip32_extract_key(return_key) return_key = bitcoin.privtopub(return_key) key_list.append((key, return_key, False)) return
def get_bip32_key( public_keys ): settings = Settings.Instance().get_settings_json() if( settings['bip32master'] is None ): return None account_number, account_key, key_number = KeyHelper.get_account_number_and_chain( settings ) #see if we already have this cached, and I can just get the key fast cached = set( settings['accounts'][account_number].get(keys,[]) ) pub_set = set( public_keys ) hits = cached & pub_set if len(hits) > 0: return KeyHelper.get_private_for_chain( account_number, hits[0][0], settings ) #drat, didn't find it! at least we can only need to test the ones that #we didn't already check missed = set(range(key_number)) - set([cache[0] for cache in cached]) for i in missed: priv = bitcoin.bip32_ckd( account_key, i ) priv = bitcoin.bip32_extract_key( priv ) canidate = bitcoin.privtopub( priv ) if( canidate in public_keys ): return priv return None
def get_next_public_key( ): settings = Settings.Instance().get_settings_json() if( settings['bip32master'] is None ): raise RuntimeError( "Master key has not been set up yet" ) account_number, account_key, key_number = KeyHelper.get_account_number_and_chain( settings ) return_key = bitcoin.bip32_ckd( account_key, key_number ) return_key = bitcoin.bip32_extract_key( return_key ) return_key = bitcoin.privtopub( return_key ) #save key for later if 'keys' not in settings['accounts'][account_number]: settings['accounts'][account_number]['keys'] = [] settings['accounts'][account_number]['keys'].append( (key_number, return_key, False ) ) #we increment the key counter after making the key #because the chain code is 0 indexed, making the 0th key #the first one we use key_number += 1 #remember to save our new key settings['accounts'][account_number]['numKeys'] = key_number Settings.Instance().save_config_file( settings ) return return_key
def _derive_address(self, change_or_deposit, index, master_key): xpriv = bip32_ckd( bip32_ckd(self.get_bip44_master(master_key), change_or_deposit), index) priv = bip32_extract_key(xpriv) address = privtoaddr(priv, self.get_address_byte()) return address, priv
def create_invoice_user (email): cur = BMMySQL().conn().cursor(MySQLdb.cursors.DictCursor) cur.execute ("SELECT bm, masterpubkey_btc, offset_btc, feeamount, feecurrency FROM user WHERE email = %s AND active = 1", (email)) result = False for row in cur.fetchall(): result = row if result: if result['masterpubkey_btc'][0:4] == "xpub": # BIP44 dpk1 = bitcoin.bip32_ckd(result['masterpubkey_btc'], 0) dpk2 = bitcoin.bip32_ckd(dpk1, result['offset_btc']) pubkey = bitcoin.bip32_extract_key(dpk2) else: # Electrum 1.x pubkey = bitcoin.electrum_pubkey(result['masterpubkey_btc'], result['offset_btc']) address = bitcoin.pubkey_to_address(pubkey) bitcoind_importaddress(address) cur.execute ("UPDATE user SET offset_btc = offset_btc + 1 WHERE email = %s AND active = 1 AND masterpubkey_btc = %s", (email, result['masterpubkey_btc'])) if result['feecurrency'] in ("USD", "GBP", "EUR"): result['feeamount'] /= decimal.Decimal(get_bitcoin_price(result['feecurrency'])) cur.execute ("INSERT INTO invoice (issuer, address, coin, amount, type, paid) VALUES (%s, %s, 'BTC', %s, 1, 0)", (result['bm'], address, result['feeamount'])) cur.close() return address, result['feeamount']; cur.close() return False
def regenerate_keys( account_key, needed_keys, key_list ): for key in needed_keys: return_key = bitcoin.bip32_ckd(account_key, key) return_key = bitcoin.bip32_extract_key(return_key) return_key = bitcoin.privtopub(return_key) key_list.append( ( key, return_key, False ) ) return
def derive_childkey(key, chaincode, prefix=bitcoin.MAINNET_PUBLIC): """ Given a 33 byte public key and 32 byte chaincode (both in hex) derive the first child key. """ master_key = bitcoin.bip32_serialize((prefix, 0, b"\x00" * 4, 0, unhexlify(chaincode), unhexlify(key))) child_key = bitcoin.bip32_ckd(master_key, 0) return bitcoin.bip32_extract_key(child_key)
def derive_childkey(key, chaincode, prefix=bitcoin.MAINNET_PUBLIC): """ Given a 33 byte public key and 32 byte chaincode (both in hex) derive the first child key. """ master_key = bitcoin.bip32_serialize((prefix, 0, b'\x00'*4, 0, unhexlify(chaincode), unhexlify(key))) child_key = bitcoin.bip32_ckd(master_key, 0) return bitcoin.bip32_extract_key(child_key)
def getPrivKey(xpriv, i): privkeys = {} priv0 = bitcoin.bip32_ckd(xpriv, 0) privateKey = bitcoin.bip32_ckd(priv0, i) wifKey = bitcoin.encode_privkey(bitcoin.bip32_extract_key(privateKey), 'wif_compressed') address_fromPriv = bitcoin.privtoaddr(wifKey) privkeys[address_fromPriv] = wifKey return privkeys
def getAddressesFromXPUB(xpub, i=10): addressList = [] pub0 = bitcoin.bip32_ckd(xpub, 0) for i in range (0, i): publicKey = bitcoin.bip32_ckd(pub0, i) hexKey = bitcoin.encode_pubkey(bitcoin.bip32_extract_key(publicKey), 'hex_compressed') address_fromPub = bitcoin.pubtoaddr(hexKey) addressList.append(address_fromPub) return addressList
def key_address(masterkey, path): """Compute address and private key (hex) for path""" derived_key = descend(masterkey, path) priv_key = btc.bip32_deserialize(derived_key)[-1] pub_key = btc.bip32_extract_key(btc.bip32_privtopub(derived_key)) priv_key_hex = btc.encode_privkey( btc.decode_privkey(priv_key, 'bin_compressed'), 'hex') address = btc.pubkey_to_address(pub_key) return priv_key_hex, address
def get_next_address(send_job): if 'addresses' in send_job: this_index = send_job['index'] send_job['index'] = (send_job['index'] + 1) % len(send_job['addresses']) return send_job['addresses'][this_index] elif 'xpub' in send_job: send_job['index'] += 1 return btc.pubtoaddr(btc.bip32_extract_key(btc.bip32_ckd( send_job['xpub'], send_job['index']-1)), get_p2pk_vbyte()) else: assert False
def _generate_new_keypair(self): seed = str(random.randrange(2**256)) # Deprecated (pre-BIP32) # self.secret = hashlib.sha256(secret).hexdigest() # self.pubkey = privkey_to_pubkey(self.secret) # self.log.debug('Keys %s %s', self.secret, self.pubkey) # Move to BIP32 keys m/0/0/0 wallet = bitcoin.bip32_ckd(bitcoin.bip32_master_key(seed), 0) wallet_chain = bitcoin.bip32_ckd(wallet, 0) bip32_identity_priv = bitcoin.bip32_ckd(wallet_chain, 0) identity_priv = bitcoin.bip32_extract_key(bip32_identity_priv) bip32_identity_pub = bitcoin.bip32_privtopub(bip32_identity_priv) identity_pub = bitcoin.encode_pubkey( bitcoin.bip32_extract_key(bip32_identity_pub), 'hex') self.pubkey = identity_pub self.secret = identity_priv # Generate SIN sha_hash = hashlib.sha256() sha_hash.update(self.pubkey) ripe_hash = hashlib.new('ripemd160') ripe_hash.update(sha_hash.digest()) self.guid = ripe_hash.hexdigest() self.sin = obelisk.EncodeBase58Check('\x0F\x02%s' % ripe_hash.digest()) newsettings = { "secret": self.secret, "pubkey": self.pubkey, "guid": self.guid, "sin": self.sin, "bip32_seed": seed } self.db_connection.update_entries("settings", newsettings, {"market_id": self.market_id}) self.settings.update(newsettings)
def _generate_new_keypair(self): seed = str(random.randrange(2 ** 256)) # Deprecated (pre-BIP32) # self.secret = hashlib.sha256(secret).hexdigest() # self.pubkey = privkey_to_pubkey(self.secret) # self.log.debug('Keys %s %s', self.secret, self.pubkey) # Move to BIP32 keys m/0/0/0 wallet = bitcoin.bip32_ckd(bitcoin.bip32_master_key(seed), 0) wallet_chain = bitcoin.bip32_ckd(wallet, 0) bip32_identity_priv = bitcoin.bip32_ckd(wallet_chain, 0) identity_priv = bitcoin.bip32_extract_key(bip32_identity_priv) bip32_identity_pub = bitcoin.bip32_privtopub(bip32_identity_priv) identity_pub = bitcoin.encode_pubkey(bitcoin.bip32_extract_key(bip32_identity_pub), 'hex') self.pubkey = identity_pub self.secret = identity_priv # Generate SIN sha_hash = hashlib.sha256() sha_hash.update(self.pubkey) ripe_hash = hashlib.new('ripemd160') ripe_hash.update(sha_hash.digest()) self.guid = ripe_hash.hexdigest() self.sin = obelisk.EncodeBase58Check('\x0F\x02%s' % ripe_hash.digest()) newsettings = { "secret": self.secret, "pubkey": self.pubkey, "guid": self.guid, "sin": self.sin, "bip32_seed": seed } self.db_connection.update_entries("settings", newsettings, {"market_id": self.market_id}) self.settings.update(newsettings)
def get_signing_key(self, contract_id): # Get BIP32 child signing key for this order id rows = self.db_connection.select_entries("keystore", { 'contract_id': contract_id }) if len(rows): key_id = rows[0]['id'] settings = self.get_settings() wallet = bitcoin.bip32_ckd(bitcoin.bip32_master_key(settings.get('bip32_seed')), 1) wallet_chain = bitcoin.bip32_ckd(wallet, 0) bip32_identity_priv = bitcoin.bip32_ckd(wallet_chain, key_id) # bip32_identity_pub = bitcoin.bip32_privtopub(bip32_identity_priv) return bitcoin.encode_privkey(bitcoin.bip32_extract_key(bip32_identity_priv), 'wif') else: self.log.error('No keys found for that contract id: #%s', contract_id) return
def get_scriptpubkeys(self, change, from_index, count): result = [] for index in range(from_index, from_index + count): pubkeys = [ btc.bip32_extract_key(btc.bip32_ckd(branch[change], index)) for branch in self.pubkey_branches ] pubkeys = sorted(pubkeys) redeemScript = "" redeemScript += "%x" % (0x50 + self.m) #op_m for p in pubkeys: redeemScript += "21" #length redeemScript += p redeemScript += "%x" % (0x50 + len(pubkeys)) #op_n redeemScript += "ae" # op_checkmultisig scriptpubkey = self.redeem_script_to_scriptpubkey(redeemScript) self.scriptpubkey_index[scriptpubkey] = (change, index) result.append(scriptpubkey) self.next_index[change] = max(self.next_index[change], from_index + count) return result
def generate_new_pubkey(self, contract_id): self.log.debug('Generating new pubkey for contract') # Retrieve next key id from DB next_key_id = len(self.db_connection.select_entries("keystore", select_fields="id")) + 1 # Store updated key in DB self.db_connection.insert_entry( "keystore", { 'contract_id': contract_id } ) # Generate new child key (m/1/0/n) wallet = bitcoin.bip32_ckd(bitcoin.bip32_master_key(self.settings.get('bip32_seed')), 1) wallet_chain = bitcoin.bip32_ckd(wallet, 0) bip32_identity_priv = bitcoin.bip32_ckd(wallet_chain, next_key_id) bip32_identity_pub = bitcoin.bip32_privtopub(bip32_identity_priv) pubkey = bitcoin.encode_pubkey(bitcoin.bip32_extract_key(bip32_identity_pub), 'hex') return pubkey
def generate_new_pubkey(self, contract_id): self.log.debug('Generating new pubkey for contract') # Retrieve next key id from DB next_key_id = len( self.db_connection.select_entries("keystore", select_fields="id")) + 1 # Store updated key in DB self.db_connection.insert_entry("keystore", {'contract_id': contract_id}) # Generate new child key (m/1/0/n) wallet = bitcoin.bip32_ckd( bitcoin.bip32_master_key(self.settings.get('bip32_seed')), 1) wallet_chain = bitcoin.bip32_ckd(wallet, 0) bip32_identity_priv = bitcoin.bip32_ckd(wallet_chain, next_key_id) bip32_identity_pub = bitcoin.bip32_privtopub(bip32_identity_priv) pubkey = bitcoin.encode_pubkey( bitcoin.bip32_extract_key(bip32_identity_pub), 'hex') return pubkey
def get_pubkey(self, change, index): return btc.bip32_extract_key( btc.bip32_ckd(self.branches[change], index))
def get_key(self, mixing_depth, forchange, i): return btc.bip32_extract_key(btc.bip32_ckd( self.keys[mixing_depth][forchange], i))
import bitcoin from os import urandom user = '******' email = '*****@*****.**' SECRET_KEY = urandom(32) master_key = bitcoin.bip32_master_key((user + email).encode() + SECRET_KEY) print(master_key) for i in range(10): child = bitcoin.bip32_ckd(master_key, i) addr = bitcoin.bip32_extract_key(child) print(bitcoin.privtoaddr(addr, 0x58))
def add_receipt(self, received, libbitcoin_client, feedback=None, quality=None, description=None, delivery_time=None, customer_service=None, review="", dispute=False, claim=None, payout=True): """ Add the final piece of the contract that appends the review and payout transaction. """ self.blockchain = libbitcoin_client receipt_json = { "buyer_receipt": { "receipt": { "ref_hash": digest(json.dumps(self.contract, indent=4)).encode("hex"), "listing": { "received": received, "listing_hash": self.contract["buyer_order"]["order"]["ref_hash"] }, "dispute": { "dispute": dispute } } } } if None not in (feedback, quality, description, delivery_time, customer_service): receipt_json["buyer_receipt"]["receipt"]["rating"] = {} receipt_json["buyer_receipt"]["receipt"]["rating"]["feedback"] = feedback receipt_json["buyer_receipt"]["receipt"]["rating"]["quality"] = quality receipt_json["buyer_receipt"]["receipt"]["rating"]["description"] = description receipt_json["buyer_receipt"]["receipt"]["rating"]["delivery_time"] = delivery_time receipt_json["buyer_receipt"]["receipt"]["rating"]["customer_service"] = customer_service receipt_json["buyer_receipt"]["receipt"]["rating"]["review"] = review if payout: order_id = self.contract["vendor_order_confirmation"]["invoice"]["ref_hash"] outpoints = pickle.loads(self.db.Purchases().get_outpoint(order_id)) payout_address = self.contract["vendor_order_confirmation"]["invoice"]["payout"]["address"] redeem_script = str(self.contract["buyer_order"]["order"]["payment"]["redeem_script"]) for output in outpoints: del output["value"] value = self.contract["vendor_order_confirmation"]["invoice"]["payout"]["value"] outs = [{'value': value, 'address': payout_address}] tx = bitcoin.mktx(outpoints, outs) signatures = [] chaincode = self.contract["buyer_order"]["order"]["payment"]["chaincode"] masterkey_b = bitcoin.bip32_extract_key(self.keychain.bitcoin_master_privkey) buyer_priv = derive_childkey(masterkey_b, chaincode, bitcoin.MAINNET_PRIVATE) masterkey_v = self.contract["vendor_offer"]["listing"]["id"]["pubkeys"]["bitcoin"] vendor_key = derive_childkey(masterkey_v, chaincode) valid_inputs = 0 for index in range(0, len(outpoints)): sig = bitcoin.multisign(tx, index, redeem_script, buyer_priv) signatures.append({"input_index": index, "signature": sig}) for s in self.contract["vendor_order_confirmation"]["invoice"]["payout"]["signature(s)"]: if s["input_index"] == index: if bitcoin.verify_tx_input(tx, index, redeem_script, s["signature"], vendor_key): tx = bitcoin.apply_multisignatures(tx, index, str(redeem_script), sig, str(s["signature"])) valid_inputs += 1 receipt_json["buyer_receipt"]["receipt"]["payout"] = {} if valid_inputs == len(outpoints): self.log.info("Broadcasting payout tx %s to network" % bitcoin.txhash(tx)) self.blockchain.broadcast(tx) receipt_json["buyer_receipt"]["receipt"]["payout"]["txid"] = bitcoin.txhash(tx) receipt_json["buyer_receipt"]["receipt"]["payout"]["signature(s)"] = signatures receipt_json["buyer_receipt"]["receipt"]["payout"]["value"] = value if claim: receipt_json["buyer_receipt"]["receipt"]["dispute"]["claim"] = claim receipt = json.dumps(receipt_json["buyer_receipt"]["receipt"], indent=4) receipt_json["buyer_receipt"]["signature"] = \ self.keychain.signing_key.sign(receipt, encoder=nacl.encoding.HexEncoder)[:128] self.contract["buyer_receipt"] = receipt_json["buyer_receipt"]
def create(self, expiration_date, metadata_category, title, description, currency_code, price, process_time, nsfw, shipping_origin=None, shipping_regions=None, est_delivery_domestic=None, est_delivery_international=None, terms_conditions=None, returns=None, keywords=None, category=None, condition=None, sku=None, images=None, free_shipping=None, shipping_currency_code=None, shipping_domestic=None, shipping_international=None, options=None, moderators=None): """ All parameters are strings except: :param expiration_date: `string` (must be formatted UTC datetime) :param keywords: `list` :param nsfw: `boolean` :param images: a `list` of image files :param free_shipping: `boolean` :param shipping_origin: a 'string' formatted `CountryCode` :param shipping_regions: a 'list' of 'string' formatted `CountryCode`s :param options: a 'dict' containing options as keys and 'list' as option values. :param moderators: a 'list' of 'string' guids (hex encoded). """ profile = Profile(self.db).get() self.contract = OrderedDict({ "vendor_offer": { "listing": { "metadata": { "version": "0.1", "category": metadata_category.lower(), "category_sub": "fixed price" }, "id": { "guid": self.keychain.guid.encode("hex"), "pubkeys": { "guid": self.keychain.guid_signed_pubkey[64:].encode( "hex"), "bitcoin": bitcoin.bip32_extract_key( self.keychain.bitcoin_master_pubkey), "encryption": self.keychain.encryption_pubkey.encode("hex") } }, "item": { "title": title, "description": description, "process_time": process_time, "price_per_unit": {}, "nsfw": nsfw } } } }) if expiration_date == "": self.contract["vendor_offer"]["listing"]["metadata"][ "expiry"] = "never" else: self.contract["vendor_offer"]["listing"]["metadata"][ "expiry"] = expiration_date + " UTC" if metadata_category == "physical good" and condition is not None: self.contract["vendor_offer"]["listing"]["item"][ "condition"] = condition if currency_code.upper() == "BTC": item = self.contract["vendor_offer"]["listing"]["item"] item["price_per_unit"]["bitcoin"] = price else: item = self.contract["vendor_offer"]["listing"]["item"] item["price_per_unit"]["fiat"] = {} item["price_per_unit"]["fiat"]["price"] = price item["price_per_unit"]["fiat"]["currency_code"] = currency_code if keywords is not None: self.contract["vendor_offer"]["listing"]["item"]["keywords"] = [] self.contract["vendor_offer"]["listing"]["item"][ "keywords"].extend(keywords) if category is not None: self.contract["vendor_offer"]["listing"]["item"][ "category"] = category if sku is not None: self.contract["vendor_offer"]["listing"]["item"]["sku"] = sku if options is not None: self.contract["vendor_offer"]["listing"]["item"][ "options"] = options if metadata_category == "physical good": self.contract["vendor_offer"]["listing"]["shipping"] = {} shipping = self.contract["vendor_offer"]["listing"]["shipping"] shipping["shipping_origin"] = shipping_origin if free_shipping is False: self.contract["vendor_offer"]["listing"]["shipping"][ "free"] = False self.contract["vendor_offer"]["listing"]["shipping"][ "flat_fee"] = {} if shipping_currency_code == "BTC": self.contract["vendor_offer"]["listing"]["shipping"][ "flat_fee"]["bitcoin"] = {} self.contract["vendor_offer"]["listing"]["shipping"][ "flat_fee"]["bitcoin"]["domestic"] = shipping_domestic self.contract["vendor_offer"]["listing"]["shipping"][ "flat_fee"]["bitcoin"][ "international"] = shipping_international else: shipping = self.contract["vendor_offer"]["listing"][ "shipping"] shipping["flat_fee"]["fiat"] = {} shipping["flat_fee"]["fiat"]["price"] = {} shipping["flat_fee"]["fiat"]["price"][ "domestic"] = shipping_domestic shipping["flat_fee"]["fiat"]["price"][ "international"] = shipping_international shipping["flat_fee"]["fiat"][ "currency_code"] = shipping_currency_code else: self.contract["vendor_offer"]["listing"]["shipping"][ "free"] = True self.contract["vendor_offer"]["listing"]["shipping"][ "shipping_regions"] = [] for region in shipping_regions: shipping = self.contract["vendor_offer"]["listing"]["shipping"] shipping["shipping_regions"].append(region) listing = self.contract["vendor_offer"]["listing"] listing["shipping"]["est_delivery"] = {} listing["shipping"]["est_delivery"][ "domestic"] = est_delivery_domestic listing["shipping"]["est_delivery"][ "international"] = est_delivery_international if profile.HasField("handle"): self.contract["vendor_offer"]["listing"]["id"][ "blockchain_id"] = profile.handle if images is not None: self.contract["vendor_offer"]["listing"]["item"][ "image_hashes"] = [] for image_hash in images: if len(image_hash) != 40: raise Exception("Invalid image hash") self.contract["vendor_offer"]["listing"]["item"][ "image_hashes"].append(image_hash) if terms_conditions is not None or returns is not None: self.contract["vendor_offer"]["listing"]["policy"] = {} if terms_conditions is not None: self.contract["vendor_offer"]["listing"]["policy"][ "terms_conditions"] = terms_conditions if returns is not None: self.contract["vendor_offer"]["listing"]["policy"][ "returns"] = returns if moderators is not None: self.contract["vendor_offer"]["listing"]["moderators"] = [] for mod in moderators: mod_info = self.db.ModeratorStore().get_moderator( unhexlify(mod)) print mod_info if mod_info is not None: moderator = { "guid": mod, "blockchain_id": mod_info[6], "pubkeys": { "signing": { "key": mod_info[1][64:].encode("hex"), "signature": mod_info[1][:64].encode("hex") }, "encryption": { "key": mod_info[2].encode("hex"), "signature": mod_info[3].encode("hex") }, "bitcoin": { "key": mod_info[4].encode("hex"), "signature": mod_info[5].encode("hex") } } } self.contract["vendor_offer"]["listing"][ "moderators"].append(moderator) listing = json.dumps(self.contract["vendor_offer"]["listing"], indent=4) self.contract["vendor_offer"]["signature"] = \ self.keychain.signing_key.sign(listing, encoder=nacl.encoding.HexEncoder)[:128] self.save()
def verify(self, sender_key): """ Validate that an order sent over by a buyer is filled out correctly. """ try: contract_dict = json.loads(json.dumps(self.contract, indent=4), object_pairs_hook=OrderedDict) del contract_dict["buyer_order"] contract_hash = digest(json.dumps(contract_dict, indent=4)) ref_hash = unhexlify( self.contract["buyer_order"]["order"]["ref_hash"]) # verify that the reference hash matches the contract and that the contract actually exists if contract_hash != ref_hash or not self.db.HashMap().get_file( ref_hash): raise Exception("Order for contract that doesn't exist") # verify the signature on the order verify_key = nacl.signing.VerifyKey(sender_key) verify_key.verify( json.dumps(self.contract["buyer_order"]["order"], indent=4), unhexlify(self.contract["buyer_order"]["signature"])) # TODO: verify the bitcoin signature after we add it # verify buyer included the correct bitcoin amount for payment price_json = self.contract["vendor_offer"]["listing"]["item"][ "price_per_unit"] if "bitcoin" in price_json: asking_price = price_json["bitcoin"] else: currency_code = price_json["fiat"]["currency_code"] fiat_price = price_json["fiat"]["price"] request = Request('https://api.bitcoinaverage.com/ticker/' + currency_code.upper() + '/last') response = urlopen(request) conversion_rate = response.read() asking_price = float("{0:.8f}".format( float(fiat_price) / float(conversion_rate))) if asking_price > self.contract["buyer_order"]["order"]["payment"][ "amount"]: raise Exception("Insuffient Payment") # verify a valid moderator was selected # TODO: handle direct payments valid_mod = False for mod in self.contract["vendor_offer"]["listing"]["moderators"]: if mod["guid"] == self.contract["buyer_order"]["order"][ "moderator"]: valid_mod = True if not valid_mod: raise Exception("Invalid moderator") # verify all the shipping fields exist if self.contract["vendor_offer"]["listing"]["metadata"][ "category"] == "physical good": shipping = self.contract["buyer_order"]["order"]["shipping"] keys = [ "ship_to", "address", "postal_code", "city", "state", "country" ] for value in map(shipping.get, keys): if value is None: raise Exception("Missing shipping field") # verify buyer ID pubkeys = self.contract["buyer_order"]["order"]["id"]["pubkeys"] keys = ["guid", "bitcoin", "encryption"] for value in map(pubkeys.get, keys): if value is None: raise Exception("Missing pubkey field") # verify redeem script chaincode = self.contract["buyer_order"]["order"]["payment"][ "chaincode"] for mod in self.contract["vendor_offer"]["listing"]["moderators"]: if mod["guid"] == self.contract["buyer_order"]["order"][ "moderator"]: masterkey_m = mod["pubkeys"]["bitcoin"]["key"] masterkey_b = self.contract["buyer_order"]["order"]["id"][ "pubkeys"]["bitcoin"] masterkey_v = bitcoin.bip32_extract_key( self.keychain.bitcoin_master_pubkey) buyer_key = derive_childkey(masterkey_b, chaincode) vendor_key = derive_childkey(masterkey_v, chaincode) moderator_key = derive_childkey(masterkey_m, chaincode) redeem_script = bitcoin.mk_multisig_script( [buyer_key, vendor_key, moderator_key], 2) if redeem_script != self.contract["buyer_order"]["order"][ "payment"]["redeem_script"]: raise Exception("Invalid redeem script") # verify the payment address if self.testnet: payment_address = bitcoin.p2sh_scriptaddr(redeem_script, 196) else: payment_address = bitcoin.p2sh_scriptaddr(redeem_script) if payment_address != self.contract["buyer_order"]["order"][ "payment"]["address"]: raise Exception("Incorrect payment address") return True except Exception: return False
def _derive_address(self, change_or_deposit, index, master_key): xpriv = bip32_ckd(bip32_ckd(self.get_bip44_master( master_key), change_or_deposit), index) priv = bip32_extract_key(xpriv) address = privtoaddr(priv, self.get_address_byte()) return address, priv
def nextWord(currSeed, nextPos): global seedCount global f if nextPos < len(sys.argv) - 1: if len(seedStruct[nextPos]) > 1: for x in range(seedStruct[nextPos]['min'], seedStruct[nextPos]['max'] + 1): #print("WordLength: " + str(x) + "------------------------------") for theWord in words[x]: currSeed += theWord + " " nextWord(currSeed, nextPos + 1) currSeed = currSeed.strip().rsplit(' ', 1)[0] + " " else: currSeed += seedStruct[nextPos]['word'] + " " nextWord(currSeed, nextPos + 1) currSeed = currSeed.strip().rsplit(' ', 1)[0] + " " else: if len(seedStruct[nextPos]) > 1: for x in range(seedStruct[nextPos]['min'], seedStruct[nextPos]['max'] + 1): #print("WordLength: " + str(x) + "------------------------------") for theWord in words[x]: currSeed += theWord else: currSeed += seedStruct[nextPos]['word'] seedCount += 1 #print("Seed:" + currSeed) try: entropy = binascii.hexlify(m.to_entropy(currSeed)) hexSeed = binascii.hexlify(m.to_seed(currSeed)) print("Found valid seed!") #print(hexSeed) print("Seed: " + currSeed) output = open('keys_' + str(seedCount) + '.txt', 'w') output.write('Seed: ' + currSeed + '\n') xprv = bitcoin.bip32_master_key(binascii.unhexlify(hexSeed)) #xprvReceive = bitcoin.bip32_ckd(bitcoin.bip32_ckd(xprv, 2**31),0) #m/0'/0 #xprvChange = bitcoin.bip32_ckd(bitcoin.bip32_ckd(xprv, 2**31),1) #m/0'/1 #m/44'/0'/0'/0 - Receive xprvReceive = bitcoin.bip32_ckd( bitcoin.bip32_ckd( bitcoin.bip32_ckd(bitcoin.bip32_ckd(xprv, 44 + 2**31), 2**31), 2**31), 0) #m/44'/0'/0'/1 - Change xprvChange = bitcoin.bip32_ckd( bitcoin.bip32_ckd( bitcoin.bip32_ckd(bitcoin.bip32_ckd(xprv, 44 + 2**31), 2**31), 2**31), 1) rcvAddr = [] chgAddr = [] rcvPrivKey = [] chgPrivKey = [] sys.stdout.write("Generating Seed Keys/Addresses.") for x in range(0, 100): if x % 10 == 0: sys.stdout.write(".") childprivReceive = bitcoin.bip32_ckd(xprvReceive, x) childprivChange = bitcoin.bip32_ckd(xprvChange, x) pkeyReceive = bitcoin.bip32_extract_key(childprivReceive) pkeyChange = bitcoin.bip32_extract_key(childprivChange) rcvAddr.append(bitcoin.privtoaddr(pkeyReceive)) chgAddr.append(bitcoin.privtoaddr(pkeyChange)) rcvPrivKey.append( bitcoin.encode_privkey(pkeyReceive, 'wif_compressed')) chgPrivKey.append( bitcoin.encode_privkey(pkeyChange, 'wif_compressed')) for x in range(0, 100): output.write(rcvPrivKey[x] + '\n') output.write(chgPrivKey[x] + '\n') output.write( '------ END KEYS ------------------------------------\n') for x in range(0, 100): output.write(rcvAddr[x] + '\n') output.write(chgAddr[x] + '\n') output.write( '------ END ADDRESSES -------------------------------\n') output.close() print("Dumped!") except ValueError: sys.stdout.write('.') if seedCount % 1000000 == 0: print(str(seedCount) + ' Seeds ' + str(datetime.now())) f.write((str(seedCount) + ' Seeds ' + str(datetime.now())) + '\n') currSeed = currSeed.strip().rsplit(' ', 1)[0] + " "
def add_purchase_info(self, quantity, ship_to=None, shipping_address=None, city=None, state=None, postal_code=None, country=None, moderator=None, options=None): """ Update the contract with the buyer's purchase information. """ profile = Profile(self.db).get() order_json = { "buyer_order": { "order": { "ref_hash": digest(json.dumps(self.contract, indent=4)).encode("hex"), "quantity": quantity, "id": { "guid": self.keychain.guid.encode("hex"), "pubkeys": { "guid": self.keychain.guid_signed_pubkey[64:].encode( "hex"), "bitcoin": bitcoin.bip32_extract_key( self.keychain.bitcoin_master_pubkey), "encryption": self.keychain.encryption_pubkey.encode("hex") } }, "payment": {} } } } if profile.HasField("handle"): order_json["buyer_order"]["order"]["id"][ "blockchain_id"] = profile.handle if self.contract["vendor_offer"]["listing"]["metadata"][ "category"] == "physical good": order_json["buyer_order"]["order"]["shipping"] = {} order_json["buyer_order"]["order"]["shipping"]["ship_to"] = ship_to order_json["buyer_order"]["order"]["shipping"][ "address"] = shipping_address order_json["buyer_order"]["order"]["shipping"]["city"] = city order_json["buyer_order"]["order"]["shipping"]["state"] = state order_json["buyer_order"]["order"]["shipping"][ "postal_code"] = postal_code order_json["buyer_order"]["order"]["shipping"]["country"] = country if options is not None: order_json["buyer_order"]["order"]["options"] = options if moderator: # TODO: Handle direct payments chaincode = sha256(str( random.getrandbits(256))).digest().encode("hex") order_json["buyer_order"]["order"]["payment"][ "chaincode"] = chaincode valid_mod = False for mod in self.contract["vendor_offer"]["listing"]["moderators"]: if mod["guid"] == moderator: order_json["buyer_order"]["order"]["moderator"] = moderator masterkey_m = mod["pubkeys"]["bitcoin"]["key"] valid_mod = True if not valid_mod: return False masterkey_b = bitcoin.bip32_extract_key( self.keychain.bitcoin_master_pubkey) masterkey_v = self.contract["vendor_offer"]["listing"]["id"][ "pubkeys"]["bitcoin"] buyer_key = derive_childkey(masterkey_b, chaincode) vendor_key = derive_childkey(masterkey_v, chaincode) moderator_key = derive_childkey(masterkey_m, chaincode) redeem_script = bitcoin.mk_multisig_script( [buyer_key, vendor_key, moderator_key], 2) order_json["buyer_order"]["order"]["payment"][ "redeem_script"] = redeem_script if self.testnet: payment_address = bitcoin.p2sh_scriptaddr(redeem_script, 196) else: payment_address = bitcoin.p2sh_scriptaddr(redeem_script) order_json["buyer_order"]["order"]["payment"][ "address"] = payment_address price_json = self.contract["vendor_offer"]["listing"]["item"][ "price_per_unit"] if "bitcoin" in price_json: order_json["buyer_order"]["order"]["payment"][ "amount"] = price_json["bitcoin"] else: currency_code = price_json["fiat"]["currency_code"] fiat_price = price_json["fiat"]["price"] try: request = Request('https://api.bitcoinaverage.com/ticker/' + currency_code.upper() + '/last') response = urlopen(request) conversion_rate = response.read() except URLError: return False order_json["buyer_order"]["order"]["payment"]["amount"] = float( "{0:.8f}".format(float(fiat_price) / float(conversion_rate))) self.contract["buyer_order"] = order_json["buyer_order"] order = json.dumps(self.contract["buyer_order"]["order"], indent=4) # TODO: This should also be signed with the bitcoin key. It's the only way a moderator # will have to link this contract to a bitcoin transaction. self.contract["buyer_order"]["signature"] = \ self.keychain.signing_key.sign(order, encoder=nacl.encoding.HexEncoder)[:128] return (self.contract["buyer_order"]["order"]["payment"]["address"], order_json["buyer_order"]["order"]["payment"]["amount"])
def add_receipt(self, received, libbitcoin_client, feedback=None, quality=None, description=None, delivery_time=None, customer_service=None, review="", dispute=False, claim=None, payout=True): """ Add the final piece of the contract that appends the review and payout transaction. """ self.blockchain = libbitcoin_client receipt_json = { "buyer_receipt": { "receipt": { "ref_hash": digest(json.dumps(self.contract, indent=4)).encode("hex"), "listing": { "received": received, "listing_hash": self.contract["buyer_order"]["order"]["ref_hash"] }, "dispute": { "dispute": dispute } } } } if None not in (feedback, quality, description, delivery_time, customer_service): receipt_json["buyer_receipt"]["receipt"]["rating"] = {} receipt_json["buyer_receipt"]["receipt"]["rating"][ "feedback"] = feedback receipt_json["buyer_receipt"]["receipt"]["rating"][ "quality"] = quality receipt_json["buyer_receipt"]["receipt"]["rating"][ "description"] = description receipt_json["buyer_receipt"]["receipt"]["rating"][ "delivery_time"] = delivery_time receipt_json["buyer_receipt"]["receipt"]["rating"][ "customer_service"] = customer_service receipt_json["buyer_receipt"]["receipt"]["rating"][ "review"] = review if payout: order_id = self.contract["vendor_order_confirmation"]["invoice"][ "ref_hash"] outpoints = pickle.loads( self.db.Purchases().get_outpoint(order_id)) payout_address = self.contract["vendor_order_confirmation"][ "invoice"]["payout"]["address"] redeem_script = str(self.contract["buyer_order"]["order"] ["payment"]["redeem_script"]) for output in outpoints: del output["value"] value = self.contract["vendor_order_confirmation"]["invoice"][ "payout"]["value"] outs = [{'value': value, 'address': payout_address}] tx = bitcoin.mktx(outpoints, outs) signatures = [] chaincode = self.contract["buyer_order"]["order"]["payment"][ "chaincode"] masterkey_b = bitcoin.bip32_extract_key( self.keychain.bitcoin_master_privkey) buyer_priv = derive_childkey(masterkey_b, chaincode, bitcoin.MAINNET_PRIVATE) masterkey_v = self.contract["vendor_offer"]["listing"]["id"][ "pubkeys"]["bitcoin"] vendor_key = derive_childkey(masterkey_v, chaincode) valid_inputs = 0 for index in range(0, len(outpoints)): sig = bitcoin.multisign(tx, index, redeem_script, buyer_priv) signatures.append({"input_index": index, "signature": sig}) for s in self.contract["vendor_order_confirmation"]["invoice"][ "payout"]["signature(s)"]: if s["input_index"] == index: if bitcoin.verify_tx_input(tx, index, redeem_script, s["signature"], vendor_key): tx = bitcoin.apply_multisignatures( tx, index, str(redeem_script), sig, str(s["signature"])) valid_inputs += 1 receipt_json["buyer_receipt"]["receipt"]["payout"] = {} if valid_inputs == len(outpoints): self.log.info("Broadcasting payout tx %s to network" % bitcoin.txhash(tx)) self.blockchain.broadcast(tx) receipt_json["buyer_receipt"]["receipt"]["payout"][ "txid"] = bitcoin.txhash(tx) receipt_json["buyer_receipt"]["receipt"]["payout"][ "signature(s)"] = signatures receipt_json["buyer_receipt"]["receipt"]["payout"]["value"] = value if claim: receipt_json["buyer_receipt"]["receipt"]["dispute"][ "claim"] = claim receipt = json.dumps(receipt_json["buyer_receipt"]["receipt"], indent=4) receipt_json["buyer_receipt"]["signature"] = \ self.keychain.signing_key.sign(receipt, encoder=nacl.encoding.HexEncoder)[:128] self.contract["buyer_receipt"] = receipt_json["buyer_receipt"]
def add_order_confirmation(self, payout_address, comments=None, shipper=None, tracking_number=None, est_delivery=None, url=None, password=None): """ Add the vendor's order confirmation to the contract. """ if not self.testnet and not (payout_address[:1] == "1" or payout_address[:1] == "3"): raise Exception("Bitcoin address is not a mainnet address") elif self.testnet and not \ (payout_address[:1] == "n" or payout_address[:1] == "m" or payout_address[:1] == "2"): raise Exception("Bitcoin address is not a testnet address") try: bitcoin.b58check_to_hex(payout_address) except AssertionError: raise Exception("Invalid Bitcoin address") conf_json = { "vendor_order_confirmation": { "invoice": { "ref_hash": digest(json.dumps(self.contract, indent=4)).encode("hex") } } } if self.contract["vendor_offer"]["listing"]["metadata"]["category"] == "physical good": shipping = {"shipper": shipper, "tracking_number": tracking_number, "est_delivery": est_delivery} conf_json["vendor_order_confirmation"]["invoice"]["shipping"] = shipping elif self.contract["vendor_offer"]["listing"]["metadata"]["category"] == "digital good": content_source = {"url": url, "password": password} conf_json["vendor_order_confirmation"]["invoice"]["content_source"] = content_source if comments: conf_json["vendor_order_confirmation"]["invoice"]["comments"] = comments confirmation = json.dumps(conf_json["vendor_order_confirmation"]["invoice"], indent=4) conf_json["vendor_order_confirmation"]["signature"] = \ self.keychain.signing_key.sign(confirmation, encoder=nacl.encoding.HexEncoder)[:128] order_id = digest(json.dumps(self.contract, indent=4)).encode("hex") # apply signatures outpoints = pickle.loads(self.db.Sales().get_outpoint(order_id)) redeem_script = self.contract["buyer_order"]["order"]["payment"]["redeem_script"] value = 0 for output in outpoints: value += output["value"] del output["value"] value -= TRANSACTION_FEE outs = [{'value': value, 'address': payout_address}] tx = bitcoin.mktx(outpoints, outs) signatures = [] chaincode = self.contract["buyer_order"]["order"]["payment"]["chaincode"] masterkey_v = bitcoin.bip32_extract_key(self.keychain.bitcoin_master_privkey) vendor_priv = derive_childkey(masterkey_v, chaincode, bitcoin.MAINNET_PRIVATE) for index in range(0, len(outpoints)): sig = bitcoin.multisign(tx, index, redeem_script, vendor_priv) signatures.append({"input_index": index, "signature": sig}) conf_json["vendor_order_confirmation"]["invoice"]["payout"] = {} conf_json["vendor_order_confirmation"]["invoice"]["payout"]["address"] = payout_address conf_json["vendor_order_confirmation"]["invoice"]["payout"]["value"] = value conf_json["vendor_order_confirmation"]["invoice"]["payout"]["signature(s)"] = signatures self.contract["vendor_order_confirmation"] = conf_json["vendor_order_confirmation"] self.db.Sales().update_status(order_id, 2) file_path = DATA_FOLDER + "store/listings/in progress/" + order_id + ".json" with open(file_path, 'w') as outfile: outfile.write(json.dumps(self.contract, indent=4))
def add_order_confirmation(self, payout_address, comments=None, shipper=None, tracking_number=None, est_delivery=None, url=None, password=None): """ Add the vendor's order confirmation to the contract. """ if not self.testnet and not (payout_address[:1] == "1" or payout_address[:1] == "3"): raise Exception("Bitcoin address is not a mainnet address") elif self.testnet and not \ (payout_address[:1] == "n" or payout_address[:1] == "m" or payout_address[:1] == "2"): raise Exception("Bitcoin address is not a testnet address") try: bitcoin.b58check_to_hex(payout_address) except AssertionError: raise Exception("Invalid Bitcoin address") conf_json = { "vendor_order_confirmation": { "invoice": { "ref_hash": digest(json.dumps(self.contract, indent=4)).encode("hex") } } } if self.contract["vendor_offer"]["listing"]["metadata"][ "category"] == "physical good": shipping = { "shipper": shipper, "tracking_number": tracking_number, "est_delivery": est_delivery } conf_json["vendor_order_confirmation"]["invoice"][ "shipping"] = shipping elif self.contract["vendor_offer"]["listing"]["metadata"][ "category"] == "digital good": content_source = {"url": url, "password": password} conf_json["vendor_order_confirmation"]["invoice"][ "content_source"] = content_source if comments: conf_json["vendor_order_confirmation"]["invoice"][ "comments"] = comments confirmation = json.dumps( conf_json["vendor_order_confirmation"]["invoice"], indent=4) conf_json["vendor_order_confirmation"]["signature"] = \ self.keychain.signing_key.sign(confirmation, encoder=nacl.encoding.HexEncoder)[:128] order_id = digest(json.dumps(self.contract, indent=4)).encode("hex") # apply signatures outpoints = pickle.loads(self.db.Sales().get_outpoint(order_id)) redeem_script = self.contract["buyer_order"]["order"]["payment"][ "redeem_script"] value = 0 for output in outpoints: value += output["value"] del output["value"] value -= TRANSACTION_FEE outs = [{'value': value, 'address': payout_address}] tx = bitcoin.mktx(outpoints, outs) signatures = [] chaincode = self.contract["buyer_order"]["order"]["payment"][ "chaincode"] masterkey_v = bitcoin.bip32_extract_key( self.keychain.bitcoin_master_privkey) vendor_priv = derive_childkey(masterkey_v, chaincode, bitcoin.MAINNET_PRIVATE) for index in range(0, len(outpoints)): sig = bitcoin.multisign(tx, index, redeem_script, vendor_priv) signatures.append({"input_index": index, "signature": sig}) conf_json["vendor_order_confirmation"]["invoice"]["payout"] = {} conf_json["vendor_order_confirmation"]["invoice"]["payout"][ "address"] = payout_address conf_json["vendor_order_confirmation"]["invoice"]["payout"][ "value"] = value conf_json["vendor_order_confirmation"]["invoice"]["payout"][ "signature(s)"] = signatures self.contract["vendor_order_confirmation"] = conf_json[ "vendor_order_confirmation"] self.db.Sales().update_status(order_id, 2) file_path = DATA_FOLDER + "store/listings/in progress/" + order_id + ".json" with open(file_path, 'w') as outfile: outfile.write(json.dumps(self.contract, indent=4))
def add_purchase_info( self, quantity, ship_to=None, shipping_address=None, city=None, state=None, postal_code=None, country=None, moderator=None, options=None, ): """ Update the contract with the buyer's purchase information. """ profile = Profile(self.db).get() order_json = { "buyer_order": { "order": { "ref_hash": digest(json.dumps(self.contract, indent=4)).encode("hex"), "quantity": quantity, "id": { "guid": self.keychain.guid.encode("hex"), "pubkeys": { "guid": self.keychain.guid_signed_pubkey[64:].encode("hex"), "bitcoin": bitcoin.bip32_extract_key(self.keychain.bitcoin_master_pubkey), "encryption": self.keychain.encryption_pubkey.encode("hex"), }, }, "payment": {}, } } } if profile.HasField("handle"): order_json["buyer_order"]["order"]["id"]["blockchain_id"] = profile.handle if self.contract["vendor_offer"]["listing"]["metadata"]["category"] == "physical good": order_json["buyer_order"]["order"]["shipping"] = {} order_json["buyer_order"]["order"]["shipping"]["ship_to"] = ship_to order_json["buyer_order"]["order"]["shipping"]["address"] = shipping_address order_json["buyer_order"]["order"]["shipping"]["city"] = city order_json["buyer_order"]["order"]["shipping"]["state"] = state order_json["buyer_order"]["order"]["shipping"]["postal_code"] = postal_code order_json["buyer_order"]["order"]["shipping"]["country"] = country if options is not None: order_json["buyer_order"]["order"]["options"] = options if moderator: # TODO: Handle direct payments chaincode = sha256(str(random.getrandbits(256))).digest().encode("hex") order_json["buyer_order"]["order"]["payment"]["chaincode"] = chaincode valid_mod = False for mod in self.contract["vendor_offer"]["listing"]["moderators"]: if mod["guid"] == moderator: order_json["buyer_order"]["order"]["moderator"] = moderator masterkey_m = mod["pubkeys"]["bitcoin"]["key"] valid_mod = True if not valid_mod: return False masterkey_b = bitcoin.bip32_extract_key(self.keychain.bitcoin_master_pubkey) masterkey_v = self.contract["vendor_offer"]["listing"]["id"]["pubkeys"]["bitcoin"] buyer_key = derive_childkey(masterkey_b, chaincode) vendor_key = derive_childkey(masterkey_v, chaincode) moderator_key = derive_childkey(masterkey_m, chaincode) redeem_script = "75" + bitcoin.mk_multisig_script([buyer_key, vendor_key, moderator_key], 2) order_json["buyer_order"]["order"]["payment"]["redeem_script"] = redeem_script if self.testnet: payment_address = bitcoin.p2sh_scriptaddr(redeem_script, 196) else: payment_address = bitcoin.p2sh_scriptaddr(redeem_script) order_json["buyer_order"]["order"]["payment"]["address"] = payment_address price_json = self.contract["vendor_offer"]["listing"]["item"]["price_per_unit"] if "bitcoin" in price_json: order_json["buyer_order"]["order"]["payment"]["amount"] = price_json["bitcoin"] else: currency_code = price_json["fiat"]["currency_code"] fiat_price = price_json["fiat"]["price"] try: request = Request("https://api.bitcoinaverage.com/ticker/" + currency_code.upper() + "/last") response = urlopen(request) conversion_rate = response.read() except URLError: return False order_json["buyer_order"]["order"]["payment"]["amount"] = float( "{0:.8f}".format(float(fiat_price) / float(conversion_rate)) ) self.contract["buyer_order"] = order_json["buyer_order"] order = json.dumps(self.contract["buyer_order"]["order"], indent=4) self.contract["buyer_order"]["signature"] = self.keychain.signing_key.sign( order, encoder=nacl.encoding.HexEncoder )[:128] return self.contract["buyer_order"]["order"]["payment"]["address"]
def get_bip32_private_key(self, path_n, master_key): priv = self.bip32_descend(master_key, path_n) ret = bitcoin.bip32_extract_key(priv) return ret
def get_key(self, mixing_depth, forchange, i): return btc.bip32_extract_key(btc.bip32_ckd(self.keys[mixing_depth][forchange], i))
def verify(self, sender_key): """ Validate that an order sent over by a buyer is filled out correctly. """ try: contract_dict = json.loads(json.dumps(self.contract, indent=4), object_pairs_hook=OrderedDict) del contract_dict["buyer_order"] contract_hash = digest(json.dumps(contract_dict, indent=4)) ref_hash = unhexlify(self.contract["buyer_order"]["order"]["ref_hash"]) # verify that the reference hash matches the contract and that the contract actually exists if contract_hash != ref_hash or not self.db.HashMap().get_file(ref_hash): raise Exception("Order for contract that doesn't exist") # verify the signature on the order verify_key = nacl.signing.VerifyKey(sender_key) verify_key.verify( json.dumps(self.contract["buyer_order"]["order"], indent=4), unhexlify(self.contract["buyer_order"]["signature"]), ) # verify buyer included the correct bitcoin amount for payment price_json = self.contract["vendor_offer"]["listing"]["item"]["price_per_unit"] if "bitcoin" in price_json: asking_price = price_json["bitcoin"] else: currency_code = price_json["fiat"]["currency_code"] fiat_price = price_json["fiat"]["price"] request = Request("https://api.bitcoinaverage.com/ticker/" + currency_code.upper() + "/last") response = urlopen(request) conversion_rate = response.read() asking_price = float("{0:.8f}".format(float(fiat_price) / float(conversion_rate))) if asking_price > self.contract["buyer_order"]["order"]["payment"]["amount"]: raise Exception("Insuffient Payment") # verify a valid moderator was selected # TODO: handle direct payments valid_mod = False for mod in self.contract["vendor_offer"]["listing"]["moderators"]: if mod["guid"] == self.contract["buyer_order"]["order"]["moderator"]: valid_mod = True if not valid_mod: raise Exception("Invalid moderator") # verify all the shipping fields exist if self.contract["vendor_offer"]["listing"]["metadata"]["category"] == "physical good": shipping = self.contract["buyer_order"]["order"]["shipping"] keys = ["ship_to", "address", "postal_code", "city", "state", "country"] for value in map(shipping.get, keys): if value is None: raise Exception("Missing shipping field") # verify buyer ID pubkeys = self.contract["buyer_order"]["order"]["id"]["pubkeys"] keys = ["guid", "bitcoin", "encryption"] for value in map(pubkeys.get, keys): if value is None: raise Exception("Missing pubkey field") # verify redeem script chaincode = self.contract["buyer_order"]["order"]["payment"]["chaincode"] for mod in self.contract["vendor_offer"]["listing"]["moderators"]: if mod["guid"] == self.contract["buyer_order"]["order"]["moderator"]: masterkey_m = mod["pubkeys"]["bitcoin"]["key"] masterkey_v = bitcoin.bip32_extract_key(self.keychain.bitcoin_master_pubkey) masterkey_b = self.contract["buyer_order"]["order"]["id"]["pubkeys"]["bitcoin"] buyer_key = derive_childkey(masterkey_b, chaincode) vendor_key = derive_childkey(masterkey_v, chaincode) moderator_key = derive_childkey(masterkey_m, chaincode) redeem_script = "75" + bitcoin.mk_multisig_script([buyer_key, vendor_key, moderator_key], 2) if redeem_script != self.contract["buyer_order"]["order"]["payment"]["redeem_script"]: raise Exception("Invalid redeem script") # verify the payment address if self.testnet: payment_address = bitcoin.p2sh_scriptaddr(redeem_script, 196) else: payment_address = bitcoin.p2sh_scriptaddr(redeem_script) if payment_address != self.contract["buyer_order"]["order"]["payment"]["address"]: raise Exception("Incorrect payment address") return True except Exception: return False
def load_wallet(wallet_file, get_password_fn): """load and if necessary decrypt a bitcoinj wallet file :param wallet_file: an open bitcoinj wallet file :type wallet_file: file :param get_password_fn: a callback returning a password that's called iff one is required :type get_password_fn: function :return: the Wallet protobuf message or None if no password was entered when required :rtype: wallet_pb2.Wallet """ wallet_file.seek(0) magic_bytes = wallet_file.read(12) wallet_file.seek(0, os.SEEK_END) wallet_size = wallet_file.tell() wallet_file.seek(0) if magic_bytes[2:6] != b"org." and wallet_size % 16 == 0: import pylibscrypt takes_long = not pylibscrypt._done # if a binary library wasn't found, this'll take a while ciphertext = wallet_file.read() assert len(ciphertext) % 16 == 0 password = get_password_fn(takes_long) if not password: return None # Derive the encryption key salt = '\x35\x51\x03\x80\x75\xa3\xb0\xc5' key = pylibscrypt.scrypt(password.encode('utf_16_be'), salt, olen=32) # Decrypt the wallet ( v0.5.0+ ) try: plaintext = aes256_cbc_decrypt(ciphertext[16:], key, ciphertext[:16]) if plaintext[2:6] != b"org.": raise ValueError('incorrect password') except ValueError as e: if e.args[0] == 'incorrect password': # Decrypt the wallet ( < v0.5.0 ) iv = '\xa3\x44\x39\x1f\x53\x83\x11\xb3\x29\x54\x86\x16\xc4\x89\x72\x3e' plaintext = aes256_cbc_decrypt(ciphertext, key, iv) global multibit_hd_password multibit_hd_password = password # Else it's not whole-file encrypted else: password = None plaintext = wallet_file.read() # Parse the wallet protobuf pb_wallet = wallet_pb2.Wallet() try: pb_wallet.ParseFromString(plaintext) except Exception as e: msg = 'not a wallet file: ' + str(e) if password: msg = "incorrect password (or " + msg + ")" raise ValueError(msg) f = open('parsed_wallet.txt','w') f.write(pb_wallet.__str__()) f.close() foundAddr = [] for trans in pb_wallet.transaction: if trans.pool == 4: print("--------------------------------------------------------------------------------") print("TXID: " + binascii.hexlify(trans.hash)) for out in trans.transaction_output: print("") faddr = bitcoin.bin_to_b58check(bitcoin.deserialize_script(out.script_bytes)[2]) print("Addr: " + faddr) foundAddr.append(faddr) print("Amt: " + str(out.value * 0.00000001) + " BTC") print("") print("--------------------------------------------------------------------------------") seed = None sys.stdout.write('Finding Seed....') salt = pb_wallet.encryption_parameters.salt dkey = pylibscrypt.scrypt(password.encode('utf_16_be'), salt, olen=32) for wkey in pb_wallet.key: if wkey.type == 3: seed = aes256_cbc_decrypt(wkey.encrypted_deterministic_seed.encrypted_private_key, dkey, wkey.encrypted_deterministic_seed.initialisation_vector) break if not seed: print("No DETERMINISTIC_MNEMONIC seed found!") return None else: print("Done!") xprv = bitcoin.bip32_master_key(seed) xprvReceive = bitcoin.bip32_ckd(bitcoin.bip32_ckd(xprv, 2**31),0) #m/0'/0 xprvChange = bitcoin.bip32_ckd(bitcoin.bip32_ckd(xprv, 2**31),1) #m/0'/1 rcvAddr = [] chgAddr = [] rcvPrivKey = [] chgPrivKey = [] sys.stdout.write("Generating Addresses/Keys.") for x in range(0,1000): if x % 10 == 0: sys.stdout.write(".") childprivReceive = bitcoin.bip32_ckd(xprvReceive, x) childprivChange = bitcoin.bip32_ckd(xprvChange, x) pkeyReceive = bitcoin.bip32_extract_key(childprivReceive) pkeyChange = bitcoin.bip32_extract_key(childprivChange) #addressReceive = privtoaddr(pkeyReceive) #addressChange = privtoaddr(pkeyChange) rcvAddr.append(bitcoin.privtoaddr(pkeyReceive)) chgAddr.append(bitcoin.privtoaddr(pkeyChange)) rcvPrivKey.append(bitcoin.encode_privkey(pkeyReceive, 'wif_compressed')) chgPrivKey.append(bitcoin.encode_privkey(pkeyChange, 'wif_compressed')) print("Done!") print("--------------------------------------------------------------------------------") for addy in foundAddr: if addy in rcvAddr: print("") print("Found Address: " + addy) print("PrivateKey: " + rcvPrivKey[rcvAddr.index(addy)]) elif addy in chgAddr: print("") print("Found Change Address: " + addy) print("PrivateKey: " + chgPrivKey[chgAddr.index(addy)]) else: print("") print("Address not found: " + addy) print("") print("--------------------------------------------------------------------------------") return pb_wallet
def create( self, expiration_date, metadata_category, title, description, currency_code, price, process_time, nsfw, shipping_origin=None, shipping_regions=None, est_delivery_domestic=None, est_delivery_international=None, terms_conditions=None, returns=None, keywords=None, category=None, condition=None, sku=None, images=None, free_shipping=None, shipping_currency_code=None, shipping_domestic=None, shipping_international=None, options=None, moderators=None, ): """ All parameters are strings except: :param expiration_date: `string` (must be formatted UTC datetime) :param keywords: `list` :param nsfw: `boolean` :param images: a `list` of image files :param free_shipping: `boolean` :param shipping_origin: a 'string' formatted `CountryCode` :param shipping_regions: a 'list' of 'string' formatted `CountryCode`s :param options: a 'dict' containing options as keys and 'list' as option values. :param moderators: a 'list' of 'string' guids (hex encoded). """ profile = Profile(self.db).get() self.contract = OrderedDict( { "vendor_offer": { "listing": { "metadata": { "version": "0.1", "category": metadata_category.lower(), "category_sub": "fixed price", }, "id": { "guid": self.keychain.guid.encode("hex"), "pubkeys": { "guid": self.keychain.guid_signed_pubkey[64:].encode("hex"), "bitcoin": bitcoin.bip32_extract_key(self.keychain.bitcoin_master_pubkey), "encryption": self.keychain.encryption_pubkey.encode("hex"), }, }, "item": { "title": title, "description": description, "process_time": process_time, "price_per_unit": {}, "nsfw": nsfw, }, } } } ) if expiration_date.lower() == "never": self.contract["vendor_offer"]["listing"]["metadata"]["expiry"] = "never" else: self.contract["vendor_offer"]["listing"]["metadata"]["expiry"] = expiration_date + " UTC" if metadata_category == "physical good" and condition is not None: self.contract["vendor_offer"]["listing"]["item"]["condition"] = condition if currency_code.upper() == "BTC": item = self.contract["vendor_offer"]["listing"]["item"] item["price_per_unit"]["bitcoin"] = price else: item = self.contract["vendor_offer"]["listing"]["item"] item["price_per_unit"]["fiat"] = {} item["price_per_unit"]["fiat"]["price"] = price item["price_per_unit"]["fiat"]["currency_code"] = currency_code if keywords is not None: self.contract["vendor_offer"]["listing"]["item"]["keywords"] = [] self.contract["vendor_offer"]["listing"]["item"]["keywords"].extend(keywords) if category is not None: self.contract["vendor_offer"]["listing"]["item"]["category"] = category if sku is not None: self.contract["vendor_offer"]["listing"]["item"]["sku"] = sku if options is not None: self.contract["vendor_offer"]["listing"]["item"]["options"] = options if metadata_category == "physical good": self.contract["vendor_offer"]["listing"]["shipping"] = {} shipping = self.contract["vendor_offer"]["listing"]["shipping"] shipping["shipping_origin"] = shipping_origin if free_shipping is False: self.contract["vendor_offer"]["listing"]["shipping"]["free"] = False self.contract["vendor_offer"]["listing"]["shipping"]["flat_fee"] = {} if shipping_currency_code == "BTC": self.contract["vendor_offer"]["listing"]["shipping"]["flat_fee"]["bitcoin"] = {} self.contract["vendor_offer"]["listing"]["shipping"]["flat_fee"]["bitcoin"][ "domestic" ] = shipping_domestic self.contract["vendor_offer"]["listing"]["shipping"]["flat_fee"]["bitcoin"][ "international" ] = shipping_international else: shipping = self.contract["vendor_offer"]["listing"]["shipping"] shipping["flat_fee"]["fiat"] = {} shipping["flat_fee"]["fiat"]["price"] = {} shipping["flat_fee"]["fiat"]["price"]["domestic"] = shipping_domestic shipping["flat_fee"]["fiat"]["price"]["international"] = shipping_international shipping["flat_fee"]["fiat"]["currency_code"] = shipping_currency_code else: self.contract["vendor_offer"]["listing"]["shipping"]["free"] = True self.contract["vendor_offer"]["listing"]["shipping"]["shipping_regions"] = [] for region in shipping_regions: shipping = self.contract["vendor_offer"]["listing"]["shipping"] shipping["shipping_regions"].append(region) listing = self.contract["vendor_offer"]["listing"] listing["shipping"]["est_delivery"] = {} listing["shipping"]["est_delivery"]["domestic"] = est_delivery_domestic listing["shipping"]["est_delivery"]["international"] = est_delivery_international if profile.HasField("handle"): self.contract["vendor_offer"]["listing"]["id"]["blockchain_id"] = profile.handle if images is not None: self.contract["vendor_offer"]["listing"]["item"]["image_hashes"] = [] for image_hash in images: self.contract["vendor_offer"]["listing"]["item"]["image_hashes"].append(image_hash) if terms_conditions is not None or returns is not None: self.contract["vendor_offer"]["listing"]["policy"] = {} if terms_conditions is not None: self.contract["vendor_offer"]["listing"]["policy"]["terms_conditions"] = terms_conditions if returns is not None: self.contract["vendor_offer"]["listing"]["policy"]["returns"] = returns if moderators is not None: self.contract["vendor_offer"]["listing"]["moderators"] = [] for mod in moderators: mod_info = self.db.ModeratorStore().get_moderator(unhexlify(mod)) print mod_info if mod_info is not None: moderator = { "guid": mod, "blockchain_id": mod_info[6], "pubkeys": { "signing": { "key": mod_info[1][64:].encode("hex"), "signature": mod_info[1][:64].encode("hex"), }, "encryption": {"key": mod_info[2].encode("hex"), "signature": mod_info[3].encode("hex")}, "bitcoin": {"key": mod_info[4].encode("hex"), "signature": mod_info[5].encode("hex")}, }, } self.contract["vendor_offer"]["listing"]["moderators"].append(moderator) listing = json.dumps(self.contract["vendor_offer"]["listing"], indent=4) self.contract["vendor_offer"]["signature"] = self.keychain.signing_key.sign( listing, encoder=nacl.encoding.HexEncoder )[:128] self.save()