Browse Source

trustedcoin: p2wpkh billing addresses

3.3.3.1
SomberNight 6 years ago
committed by ThomasV
parent
commit
7b90d69443
  1. 12
      electrum/plugins/trustedcoin/qt.py
  2. 60
      electrum/plugins/trustedcoin/trustedcoin.py
  3. 12
      electrum/storage.py

12
electrum/plugins/trustedcoin/qt.py

@ -195,18 +195,6 @@ class Plugin(TrustedCoinPlugin):
vbox.addLayout(Buttons(CloseButton(d))) vbox.addLayout(Buttons(CloseButton(d)))
d.exec_() d.exec_()
def on_buy(self, window, k, v, d):
d.close()
if window.pluginsdialog:
window.pluginsdialog.close()
wallet = window.wallet
uri = "bitcoin:" + wallet.billing_info['billing_address'] + "?message=TrustedCoin %d Prepaid Transactions&amount="%k + str(Decimal(v)/100000000)
wallet.is_billing = True
window.pay_to_URI(uri)
window.payto_e.setFrozen(True)
window.message_e.setFrozen(True)
window.amount_e.setFrozen(True)
def go_online_dialog(self, wizard): def go_online_dialog(self, wizard):
msg = [ msg = [
_("Your wallet file is: {}.").format(os.path.abspath(wizard.storage.path)), _("Your wallet file is: {}.").format(os.path.abspath(wizard.storage.path)),

60
electrum/plugins/trustedcoin/trustedcoin.py

@ -28,13 +28,15 @@ import json
import base64 import base64
import time import time
import hashlib import hashlib
from collections import defaultdict
from typing import Dict
from urllib.parse import urljoin from urllib.parse import urljoin
from urllib.parse import quote from urllib.parse import quote
from aiohttp import ClientResponse from aiohttp import ClientResponse
from electrum import ecc, constants, keystore, version, bip32 from electrum import ecc, constants, keystore, version, bip32, bitcoin
from electrum.bitcoin import TYPE_ADDRESS, is_new_seed, public_key_to_p2pkh, seed_type, is_any_2fa_seed_type from electrum.bitcoin import TYPE_ADDRESS, is_new_seed, seed_type, is_any_2fa_seed_type
from electrum.bip32 import (deserialize_xpub, deserialize_xprv, bip32_private_key, CKD_pub, from electrum.bip32 import (deserialize_xpub, deserialize_xprv, bip32_private_key, CKD_pub,
serialize_xpub, bip32_root, bip32_private_derivation, xpub_type) serialize_xpub, bip32_root, bip32_private_derivation, xpub_type)
from electrum.crypto import sha256 from electrum.crypto import sha256
@ -244,14 +246,18 @@ class Wallet_2fa(Multisig_Wallet):
self.is_billing = False self.is_billing = False
self.billing_info = None self.billing_info = None
self._load_billing_addresses() self._load_billing_addresses()
self.plugin = None # type: TrustedCoinPlugin
def _load_billing_addresses(self): def _load_billing_addresses(self):
billing_addresses = self.storage.get('trustedcoin_billing_addresses', {}) billing_addresses = self.storage.get('trustedcoin_billing_addresses', {})
self._billing_addresses = {} # index -> addr self._billing_addresses = defaultdict(dict) # type: Dict[str, Dict[int, str]] # addr_type -> index -> addr
self._billing_addresses_set = set() # set of addrs
for addr_type, d in list(billing_addresses.items()):
self._billing_addresses[addr_type] = {}
# convert keys from str to int # convert keys from str to int
for index, addr in list(billing_addresses.items()): for index, addr in d.items():
self._billing_addresses[int(index)] = addr self._billing_addresses[addr_type][int(index)] = addr
self._billing_addresses_set = set(self._billing_addresses.values()) # set of addrs self._billing_addresses_set.add(addr)
def can_sign_without_server(self): def can_sign_without_server(self):
return not self.keystores['x2/'].is_watching_only() return not self.keystores['x2/'].is_watching_only()
@ -291,7 +297,7 @@ class Wallet_2fa(Multisig_Wallet):
self, coins, o, config, fixed_fee, change_addr) self, coins, o, config, fixed_fee, change_addr)
fee = self.extra_fee(config) if not is_sweep else 0 fee = self.extra_fee(config) if not is_sweep else 0
if fee: if fee:
address = self.billing_info['billing_address'] address = self.billing_info['billing_address_segwit']
fee_output = TxOutput(TYPE_ADDRESS, address, fee) fee_output = TxOutput(TYPE_ADDRESS, address, fee)
try: try:
tx = mk_tx(outputs + [fee_output]) tx = mk_tx(outputs + [fee_output])
@ -322,8 +328,9 @@ class Wallet_2fa(Multisig_Wallet):
self.billing_info = None self.billing_info = None
self.plugin.start_request_thread(self) self.plugin.start_request_thread(self)
def add_new_billing_address(self, billing_index: int, address: str): def add_new_billing_address(self, billing_index: int, address: str, addr_type: str):
saved_addr = self._billing_addresses.get(billing_index) billing_addresses_of_this_type = self._billing_addresses[addr_type]
saved_addr = billing_addresses_of_this_type.get(billing_index)
if saved_addr is not None: if saved_addr is not None:
if saved_addr == address: if saved_addr == address:
return # already saved this address return # already saved this address
@ -332,15 +339,16 @@ class Wallet_2fa(Multisig_Wallet):
'for index {}, already saved {}, now got {}' 'for index {}, already saved {}, now got {}'
.format(billing_index, saved_addr, address)) .format(billing_index, saved_addr, address))
# do we have all prior indices? (are we synced?) # do we have all prior indices? (are we synced?)
largest_index_we_have = max(self._billing_addresses) if self._billing_addresses else -1 largest_index_we_have = max(billing_addresses_of_this_type) if billing_addresses_of_this_type else -1
if largest_index_we_have + 1 < billing_index: # need to sync if largest_index_we_have + 1 < billing_index: # need to sync
for i in range(largest_index_we_have + 1, billing_index): for i in range(largest_index_we_have + 1, billing_index):
addr = make_billing_address(self, i) addr = make_billing_address(self, i, addr_type=addr_type)
self._billing_addresses[i] = addr billing_addresses_of_this_type[i] = addr
self._billing_addresses_set.add(addr) self._billing_addresses_set.add(addr)
# save this address; and persist to disk # save this address; and persist to disk
self._billing_addresses[billing_index] = address billing_addresses_of_this_type[billing_index] = address
self._billing_addresses_set.add(address) self._billing_addresses_set.add(address)
self._billing_addresses[addr_type] = billing_addresses_of_this_type
self.storage.put('trustedcoin_billing_addresses', self._billing_addresses) self.storage.put('trustedcoin_billing_addresses', self._billing_addresses)
# FIXME this often runs in a daemon thread, where storage.write will fail # FIXME this often runs in a daemon thread, where storage.write will fail
self.storage.write() self.storage.write()
@ -365,12 +373,17 @@ def make_xpub(xpub, s):
cK2, c2 = bip32._CKD_pub(cK, c, s) cK2, c2 = bip32._CKD_pub(cK, c, s)
return serialize_xpub(version, c2, cK2) return serialize_xpub(version, c2, cK2)
def make_billing_address(wallet, num): def make_billing_address(wallet, num, addr_type):
long_id, short_id = wallet.get_user_id() long_id, short_id = wallet.get_user_id()
xpub = make_xpub(get_billing_xpub(), long_id) xpub = make_xpub(get_billing_xpub(), long_id)
version, _, _, _, c, cK = deserialize_xpub(xpub) version, _, _, _, c, cK = deserialize_xpub(xpub)
cK, c = CKD_pub(cK, c, num) cK, c = CKD_pub(cK, c, num)
return public_key_to_p2pkh(cK) if addr_type == 'legacy':
return bitcoin.public_key_to_p2pkh(cK)
elif addr_type == 'segwit':
return bitcoin.public_key_to_p2wpkh(cK)
else:
raise ValueError(f'unexpected billing type: {addr_type}')
class TrustedCoinPlugin(BasePlugin): class TrustedCoinPlugin(BasePlugin):
@ -428,7 +441,7 @@ class TrustedCoinPlugin(BasePlugin):
return f return f
@finish_requesting @finish_requesting
def request_billing_info(self, wallet): def request_billing_info(self, wallet: 'Wallet_2fa'):
if wallet.can_sign_without_server(): if wallet.can_sign_without_server():
return return
self.print_error("request billing info") self.print_error("request billing info")
@ -438,11 +451,16 @@ class TrustedCoinPlugin(BasePlugin):
self.print_error('cannot connect to TrustedCoin server: {}'.format(repr(e))) self.print_error('cannot connect to TrustedCoin server: {}'.format(repr(e)))
return return
billing_index = billing_info['billing_index'] billing_index = billing_info['billing_index']
billing_address = make_billing_address(wallet, billing_index) # add segwit billing address; this will be used for actual billing
if billing_address != billing_info['billing_address']: billing_address = make_billing_address(wallet, billing_index, addr_type='segwit')
raise Exception('unexpected trustedcoin billing address: expected {}, received {}' if billing_address != billing_info['billing_address_segwit']:
.format(billing_address, billing_info['billing_address'])) raise Exception(f'unexpected trustedcoin billing address: '
wallet.add_new_billing_address(billing_index, billing_address) f'calculated {billing_address}, received {billing_info["billing_address_segwit"]}')
wallet.add_new_billing_address(billing_index, billing_address, addr_type='segwit')
# also add legacy billing address; only used for detecting past payments in GUI
billing_address = make_billing_address(wallet, billing_index, addr_type='legacy')
wallet.add_new_billing_address(billing_index, billing_address, addr_type='legacy')
wallet.billing_info = billing_info wallet.billing_info = billing_info
wallet.price_per_tx = dict(billing_info['price_per_tx']) wallet.price_per_tx = dict(billing_info['price_per_tx'])
wallet.price_per_tx.pop(1, None) wallet.price_per_tx.pop(1, None)

12
electrum/storage.py

@ -44,7 +44,7 @@ from .keystore import bip44_derivation
OLD_SEED_VERSION = 4 # electrum versions < 2.0 OLD_SEED_VERSION = 4 # electrum versions < 2.0
NEW_SEED_VERSION = 11 # electrum versions >= 2.0 NEW_SEED_VERSION = 11 # electrum versions >= 2.0
FINAL_SEED_VERSION = 18 # electrum >= 2.7 will set this to prevent FINAL_SEED_VERSION = 19 # electrum >= 2.7 will set this to prevent
# old versions from overwriting new format # old versions from overwriting new format
@ -354,6 +354,7 @@ class WalletStorage(JsonDB):
self.convert_version_16() self.convert_version_16()
self.convert_version_17() self.convert_version_17()
self.convert_version_18() self.convert_version_18()
self.convert_version_19()
self.put('seed_version', FINAL_SEED_VERSION) # just to be sure self.put('seed_version', FINAL_SEED_VERSION) # just to be sure
self.write() self.write()
@ -572,11 +573,16 @@ class WalletStorage(JsonDB):
# delete verified_tx3 as its structure changed # delete verified_tx3 as its structure changed
if not self._is_upgrade_method_needed(17, 17): if not self._is_upgrade_method_needed(17, 17):
return return
self.put('verified_tx3', None) self.put('verified_tx3', None)
self.put('seed_version', 18) self.put('seed_version', 18)
def convert_version_19(self):
# delete trustedcoin_billing_addresses
if not self._is_upgrade_method_needed(18, 18):
return
self.put('trustedcoin_billing_addresses', None)
self.put('seed_version', 19)
def convert_imported(self): def convert_imported(self):
if not self._is_upgrade_method_needed(0, 13): if not self._is_upgrade_method_needed(0, 13):
return return

Loading…
Cancel
Save