diff --git a/lib/base_wizard.py b/lib/base_wizard.py index 987e2cf5..58153f61 100644 --- a/lib/base_wizard.py +++ b/lib/base_wizard.py @@ -240,7 +240,7 @@ class BaseWizard(object): def on_hw_derivation(self, name, device_info, derivation): from .keystore import hardware_keystore - xtype = 'p2wpkh-p2sh' if derivation.startswith("m/49'/") else 'standard' + xtype = 'standard' try: xpub = self.plugin.get_xpub(device_info.device.id_, derivation, xtype, self) except BaseException as e: @@ -271,7 +271,7 @@ class BaseWizard(object): def restore_from_seed(self): self.opt_bip39 = True self.opt_ext = True - is_cosigning_seed = lambda x: bitcoin.seed_type(x) in ['standard', 'segwit'] + is_cosigning_seed = lambda x: bitcoin.seed_type(x) in ['standard'] test = bitcoin.is_seed if self.wallet_type == 'standard' else is_cosigning_seed self.restore_seed_dialog(run_next=self.on_restore_seed, test=test) @@ -280,7 +280,7 @@ class BaseWizard(object): if self.seed_type == 'bip39': f = lambda passphrase: self.on_restore_bip39(seed, passphrase) self.passphrase_dialog(run_next=f) if is_ext else f('') - elif self.seed_type in ['standard', 'segwit']: + elif self.seed_type in ['standard']: f = lambda passphrase: self.run('create_keystore', seed, passphrase) self.passphrase_dialog(run_next=f) if is_ext else f('') elif self.seed_type == 'old': @@ -313,7 +313,7 @@ class BaseWizard(object): from .bitcoin import xpub_type t1 = xpub_type(k.xpub) if self.wallet_type == 'standard': - if has_xpub and t1 not in ['standard', 'p2wpkh', 'p2wpkh-p2sh']: + if has_xpub and t1 not in ['standard']: self.show_error(_('Wrong key type') + ' %s'%t1) self.run('choose_keystore') return @@ -321,7 +321,7 @@ class BaseWizard(object): self.run('create_wallet') elif self.wallet_type == 'multisig': assert has_xpub - if t1 not in ['standard', 'p2wsh', 'p2wsh-p2sh']: + if t1 not in ['standard']: self.show_error(_('Wrong key type') + ' %s'%t1) self.run('choose_keystore') return @@ -380,17 +380,12 @@ class BaseWizard(object): title = _('Choose Seed type') message = ' '.join([ "The type of addresses used by your wallet will depend on your seed.", - "Segwit wallets use bech32 addresses, defined in BIP173.", - "Please note that websites and other wallets may not support these addresses yet.", - "Thus, you might want to keep using a non-segwit wallet in order to be able to receive bitcoins during the transition period." ]) choices = [ ('create_standard_seed', _('Standard')), - ('create_segwit_seed', _('Segwit')), ] self.choice_dialog(title=title, message=message, choices=choices, run_next=self.run) - def create_segwit_seed(self): self.create_seed('segwit') def create_standard_seed(self): self.create_seed('standard') def create_seed(self, seed_type): diff --git a/lib/bitcoin.py b/lib/bitcoin.py index 9c1e8b6f..918502ef 100644 --- a/lib/bitcoin.py +++ b/lib/bitcoin.py @@ -35,7 +35,6 @@ import pyaes from .util import bfh, bh2u, to_string from . import version from .util import print_error, InvalidPassword, assert_bytes, to_bytes, inv_dict -from . import segwit_addr def read_json_dict(filename): path = os.path.join(os.path.dirname(__file__), filename) @@ -51,21 +50,11 @@ def read_json_dict(filename): # Version numbers for BIP32 extended keys # standard: xprv, xpub -# segwit in p2sh: yprv, ypub -# native segwit: zprv, zpub XPRV_HEADERS = { 'standard': 0x0488ade4, - 'p2wpkh-p2sh': 0x049d7878, - 'p2wsh-p2sh': 0x295b005, - 'p2wpkh': 0x4b2430c, - 'p2wsh': 0x2aa7a99 } XPUB_HEADERS = { 'standard': 0x0488b21e, - 'p2wpkh-p2sh': 0x049d7cb2, - 'p2wsh-p2sh': 0x295b43f, - 'p2wpkh': 0x4b24746, - 'p2wsh': 0x2aa7ed3 } @@ -282,8 +271,6 @@ def seed_type(x): return 'old' elif is_new_seed(x): return 'standard' - elif is_new_seed(x, version.SEED_PREFIX_SW): - return 'segwit' elif is_new_seed(x, version.SEED_PREFIX_2FA): return '2fa' return '' @@ -323,7 +310,7 @@ def hash_160(public_key): return md.digest() -def hash160_to_b58_address(h160, addrtype, witness_program_version=1): +def hash160_to_b58_address(h160, addrtype): s = bytes([addrtype]) s += h160 return base_encode(s+Hash(s)[0:4], base=58) @@ -344,42 +331,15 @@ def hash160_to_p2sh(h160): def public_key_to_p2pkh(public_key): return hash160_to_p2pkh(hash_160(public_key)) -def hash_to_segwit_addr(h): - return segwit_addr.encode(NetworkConstants.SEGWIT_HRP, 0, h) - -def public_key_to_p2wpkh(public_key): - return hash_to_segwit_addr(hash_160(public_key)) - -def script_to_p2wsh(script): - return hash_to_segwit_addr(sha256(bfh(script))) - -def p2wpkh_nested_script(pubkey): - pkh = bh2u(hash_160(bfh(pubkey))) - return '00' + push_script(pkh) - -def p2wsh_nested_script(witness_script): - wsh = bh2u(sha256(bfh(witness_script))) - return '00' + push_script(wsh) - def pubkey_to_address(txin_type, pubkey): if txin_type == 'p2pkh': return public_key_to_p2pkh(bfh(pubkey)) - elif txin_type == 'p2wpkh': - return hash_to_segwit_addr(hash_160(bfh(pubkey))) - elif txin_type == 'p2wpkh-p2sh': - scriptSig = p2wpkh_nested_script(pubkey) - return hash160_to_p2sh(hash_160(bfh(scriptSig))) else: raise NotImplementedError(txin_type) def redeem_script_to_address(txin_type, redeem_script): if txin_type == 'p2sh': return hash160_to_p2sh(hash_160(bfh(redeem_script))) - elif txin_type == 'p2wsh': - return script_to_p2wsh(redeem_script) - elif txin_type == 'p2wsh-p2sh': - scriptSig = p2wsh_nested_script(redeem_script) - return hash160_to_p2sh(hash_160(bfh(scriptSig))) else: raise NotImplementedError(txin_type) @@ -391,13 +351,6 @@ def script_to_address(script): return addr def address_to_script(addr): - witver, witprog = segwit_addr.decode(NetworkConstants.SEGWIT_HRP, addr) - if witprog is not None: - assert (0 <= witver <= 16) - OP_n = witver + 0x50 if witver > 0 else 0 - script = bh2u(bytes([OP_n])) - script += push_script(bh2u(bytes(witprog))) - return script addrtype, hash_160 = b58_address_to_hash160(addr) if addrtype == NetworkConstants.ADDRTYPE_P2PKH: script = '76a9' # op_dup, op_hash_160 @@ -508,15 +461,9 @@ def DecodeBase58Check(psz): -# extended key export format for segwit - SCRIPT_TYPES = { 'p2pkh':0, - 'p2wpkh':1, - 'p2wpkh-p2sh':2, 'p2sh':5, - 'p2wsh':6, - 'p2wsh-p2sh':7 } @@ -567,13 +514,6 @@ def address_from_private_key(sec): public_key = public_key_from_private_key(privkey, compressed) return pubkey_to_address(txin_type, public_key) -def is_segwit_address(addr): - try: - witver, witprog = segwit_addr.decode(NetworkConstants.SEGWIT_HRP, addr) - except Exception as e: - return False - return witprog is not None - def is_b58_address(addr): try: addrtype, h = b58_address_to_hash160(addr) @@ -584,7 +524,7 @@ def is_b58_address(addr): return addr == hash160_to_b58_address(h, addrtype) def is_address(addr): - return is_segwit_address(addr) or is_b58_address(addr) + return is_b58_address(addr) def is_private_key(key): @@ -628,7 +568,7 @@ def verify_message(address, sig, message): public_key, compressed = pubkey_from_signature(sig, h) # check public key using the address pubkey = point_to_ser(public_key.pubkey.point, compressed) - for txin_type in ['p2pkh','p2wpkh','p2wpkh-p2sh']: + for txin_type in ['p2pkh']: addr = pubkey_to_address(txin_type, bh2u(pubkey)) if address == addr: break diff --git a/lib/blockchain.py b/lib/blockchain.py index 94402ac8..00f82b84 100644 --- a/lib/blockchain.py +++ b/lib/blockchain.py @@ -255,14 +255,6 @@ class Blockchain(util.PrintError): def get_hash(self, height): return hash_header(self.read_header(height)) - def BIP9(self, height, flag): - v = self.read_header(height)['version'] - return ((v & 0xE0000000) == 0x20000000) and ((v & flag) == flag) - - def segwit_support(self, N=144): - h = self.local_height - return sum([self.BIP9(h-i, 2) for i in range(N)])*10000/N/100. - def get_target(self, index): if bitcoin.NetworkConstants.TESTNET: return 0, 0 diff --git a/lib/commands.py b/lib/commands.py index cbb38d0b..2f823c28 100644 --- a/lib/commands.py +++ b/lib/commands.py @@ -123,7 +123,7 @@ class Commands: return ' '.join(sorted(known_commands.keys())) @command('') - def create(self, segwit=False): + def create(self): """Create a new wallet""" raise BaseException('Not a JSON-RPC command') @@ -159,10 +159,10 @@ class Commands: return True @command('') - def make_seed(self, nbits=132, entropy=1, language=None, segwit=False): + def make_seed(self, nbits=132, entropy=1, language=None): """Create a seed""" from .mnemonic import Mnemonic - t = 'segwit' if segwit else 'standard' + t = 'standard' s = Mnemonic(language).make_seed(t, nbits, custom_entropy=entropy) return s @@ -713,7 +713,6 @@ command_options = { 'change_addr': ("-c", "Change address. Default is a spare address, or the source address if it's not in the wallet"), 'nbits': (None, "Number of bits of entropy"), 'entropy': (None, "Custom entropy"), - 'segwit': (None, "Create segwit seed"), 'language': ("-L", "Default language for wordlist"), 'privkey': (None, "Private key. Set to '?' to get a prompt."), 'unsigned': ("-u", "Do not sign transaction"), diff --git a/lib/keystore.py b/lib/keystore.py index 67363273..9285ad14 100644 --- a/lib/keystore.py +++ b/lib/keystore.py @@ -571,7 +571,7 @@ def bip39_is_checksum_valid(mnemonic): def from_bip39_seed(seed, passphrase, derivation): k = BIP32_KeyStore({}) bip32_seed = bip39_to_seed(seed, passphrase) - t = 'p2wpkh-p2sh' if derivation.startswith("m/49'") else 'standard' # bip43 + t = 'standard' # bip43 k.add_xprv_from_seed(bip32_seed, t, derivation) return k @@ -681,17 +681,13 @@ def from_seed(seed, passphrase, is_p2sh): if t == 'old': keystore = Old_KeyStore({}) keystore.add_seed(seed) - elif t in ['standard', 'segwit']: + elif t in ['standard']: keystore = BIP32_KeyStore({}) keystore.add_seed(seed) keystore.passphrase = passphrase bip32_seed = Mnemonic.mnemonic_to_seed(seed, passphrase) - if t == 'standard': - der = "m/" - xtype = 'standard' - else: - der = "m/1'/" if is_p2sh else "m/0'/" - xtype = 'p2wsh' if is_p2sh else 'p2wpkh' + der = "m/" + xtype = 'standard' keystore.add_xprv_from_seed(bip32_seed, xtype, der) else: raise BaseException(t) diff --git a/lib/segwit_addr.py b/lib/segwit_addr.py deleted file mode 100644 index 3f3992a5..00000000 --- a/lib/segwit_addr.py +++ /dev/null @@ -1,122 +0,0 @@ -# Copyright (c) 2017 Pieter Wuille -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -"""Reference implementation for Bech32 and segwit addresses.""" - - -CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" - - -def bech32_polymod(values): - """Internal function that computes the Bech32 checksum.""" - generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3] - chk = 1 - for value in values: - top = chk >> 25 - chk = (chk & 0x1ffffff) << 5 ^ value - for i in range(5): - chk ^= generator[i] if ((top >> i) & 1) else 0 - return chk - - -def bech32_hrp_expand(hrp): - """Expand the HRP into values for checksum computation.""" - return [ord(x) >> 5 for x in hrp] + [0] + [ord(x) & 31 for x in hrp] - - -def bech32_verify_checksum(hrp, data): - """Verify a checksum given HRP and converted data characters.""" - return bech32_polymod(bech32_hrp_expand(hrp) + data) == 1 - - -def bech32_create_checksum(hrp, data): - """Compute the checksum values given HRP and data.""" - values = bech32_hrp_expand(hrp) + data - polymod = bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ 1 - return [(polymod >> 5 * (5 - i)) & 31 for i in range(6)] - - -def bech32_encode(hrp, data): - """Compute a Bech32 string given HRP and data values.""" - combined = data + bech32_create_checksum(hrp, data) - return hrp + '1' + ''.join([CHARSET[d] for d in combined]) - - -def bech32_decode(bech): - """Validate a Bech32 string, and determine HRP and data.""" - if ((any(ord(x) < 33 or ord(x) > 126 for x in bech)) or - (bech.lower() != bech and bech.upper() != bech)): - return (None, None) - bech = bech.lower() - pos = bech.rfind('1') - if pos < 1 or pos + 7 > len(bech) or len(bech) > 90: - return (None, None) - if not all(x in CHARSET for x in bech[pos+1:]): - return (None, None) - hrp = bech[:pos] - data = [CHARSET.find(x) for x in bech[pos+1:]] - if not bech32_verify_checksum(hrp, data): - return (None, None) - return (hrp, data[:-6]) - - -def convertbits(data, frombits, tobits, pad=True): - """General power-of-2 base conversion.""" - acc = 0 - bits = 0 - ret = [] - maxv = (1 << tobits) - 1 - max_acc = (1 << (frombits + tobits - 1)) - 1 - for value in data: - if value < 0 or (value >> frombits): - return None - acc = ((acc << frombits) | value) & max_acc - bits += frombits - while bits >= tobits: - bits -= tobits - ret.append((acc >> bits) & maxv) - if pad: - if bits: - ret.append((acc << (tobits - bits)) & maxv) - elif bits >= frombits or ((acc << (tobits - bits)) & maxv): - return None - return ret - - -def decode(hrp, addr): - """Decode a segwit address.""" - hrpgot, data = bech32_decode(addr) - if hrpgot != hrp: - return (None, None) - decoded = convertbits(data[1:], 5, 8, False) - if decoded is None or len(decoded) < 2 or len(decoded) > 40: - return (None, None) - if data[0] > 16: - return (None, None) - if data[0] == 0 and len(decoded) != 20 and len(decoded) != 32: - return (None, None) - return (data[0], decoded) - - -def encode(hrp, witver, witprog): - """Encode a segwit address.""" - ret = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5)) - assert decode(hrp, ret) is not (None, None) - return ret diff --git a/lib/storage.py b/lib/storage.py index fa991114..d4adadde 100644 --- a/lib/storage.py +++ b/lib/storage.py @@ -399,7 +399,6 @@ class WalletStorage(PrintError): def convert_version_15(self): if not self._is_upgrade_method_needed(14, 14): return - assert self.get('seed_type') != 'segwit' # unsupported derivation self.put('seed_version', 15) def convert_version_16(self): @@ -498,8 +497,6 @@ class WalletStorage(PrintError): seed_version = OLD_SEED_VERSION if len(self.get('master_public_key','')) == 128 else NEW_SEED_VERSION if seed_version > FINAL_SEED_VERSION: raise BaseException('This version of Electrum is too old to open this wallet') - if seed_version==14 and self.get('seed_type') == 'segwit': - self.raise_unsupported_version(seed_version) if seed_version >=12: return seed_version if seed_version not in [OLD_SEED_VERSION, NEW_SEED_VERSION]: diff --git a/lib/transaction.py b/lib/transaction.py index 756ea934..3e8270a2 100644 --- a/lib/transaction.py +++ b/lib/transaction.py @@ -301,10 +301,7 @@ def parse_scriptSig(d, _bytes): match = [ opcodes.OP_PUSHDATA4 ] if match_decoded(decoded, match): item = decoded[0][1] - if item[0] == 0: - d['address'] = bitcoin.hash160_to_p2sh(bitcoin.hash_160(item)) - d['type'] = 'p2wpkh-p2sh' if len(item) == 22 else 'p2wsh-p2sh' - else: + if item[0] != 0: # payto_pubkey d['type'] = 'p2pk' d['address'] = "(pubkey)" @@ -387,11 +384,6 @@ def get_address_from_output_script(_bytes): if match_decoded(decoded, match): return TYPE_ADDRESS, hash160_to_p2sh(decoded[1][1]) - # segwit address - match = [ opcodes.OP_0, opcodes.OP_PUSHDATA4 ] - if match_decoded(decoded, match): - return TYPE_ADDRESS, hash_to_segwit_addr(decoded[1][1]) - return TYPE_SCRIPT, bh2u(_bytes) @@ -423,29 +415,6 @@ def parse_input(vds): return d -def parse_witness(vds, txin): - n = vds.read_compact_size() - if n == 0: - return - if n == 0xffffffff: - txin['value'] = vds.read_uint64() - n = vds.read_compact_size() - w = list(bh2u(vds.read_bytes(vds.read_compact_size())) for i in range(n)) - if txin['type'] == 'coinbase': - pass - elif n > 2: - txin['signatures'] = parse_sig(w[1:-1]) - m, n, x_pubkeys, pubkeys, witnessScript = parse_redeemScript(bfh(w[-1])) - txin['num_sig'] = m - txin['x_pubkeys'] = x_pubkeys - txin['pubkeys'] = pubkeys - txin['witnessScript'] = witnessScript - else: - txin['num_sig'] = 1 - txin['x_pubkeys'] = [w[1]] - txin['pubkeys'] = [safe_parse_pubkey(w[1])] - txin['signatures'] = parse_sig([w[0]]) - def parse_output(vds, i): d = {} d['value'] = vds.read_int64() @@ -463,26 +432,9 @@ def deserialize(raw): start = vds.read_cursor d['version'] = vds.read_int32() n_vin = vds.read_compact_size() - is_segwit = (n_vin == 0) - if is_segwit: - marker = vds.read_bytes(1) - assert marker == b'\x01' - n_vin = vds.read_compact_size() d['inputs'] = [parse_input(vds) for i in range(n_vin)] n_vout = vds.read_compact_size() d['outputs'] = [parse_output(vds, i) for i in range(n_vout)] - if is_segwit: - for i in range(n_vin): - txin = d['inputs'][i] - parse_witness(vds, txin) - # segwit-native script - if not txin.get('scriptSig'): - if txin['num_sig'] == 1: - txin['type'] = 'p2wpkh' - txin['address'] = bitcoin.public_key_to_p2wpkh(bfh(txin['pubkeys'][0])) - else: - txin['type'] = 'p2wsh' - txin['address'] = bitcoin.script_to_p2wsh(txin['witnessScript']) d['lockTime'] = vds.read_uint32() return d @@ -661,30 +613,6 @@ class Transaction: sig_list = [sig if sig else NO_SIGNATURE for sig in x_signatures] return pk_list, sig_list - @classmethod - def serialize_witness(self, txin, estimate_size=False): - add_w = lambda x: var_int(len(x)//2) + x - if not self.is_segwit_input(txin): - return '00' - pubkeys, sig_list = self.get_siglist(txin, estimate_size) - if txin['type'] in ['p2wpkh', 'p2wpkh-p2sh']: - witness = var_int(2) + add_w(sig_list[0]) + add_w(pubkeys[0]) - elif txin['type'] in ['p2wsh', 'p2wsh-p2sh']: - n = len(sig_list) + 2 - witness_script = multisig_script(pubkeys, txin['num_sig']) - witness = var_int(n) + '00' + ''.join(add_w(x) for x in sig_list) + add_w(witness_script) - else: - raise BaseException('wrong txin type') - if self.is_txin_complete(txin) or estimate_size: - value_field = '' - else: - value_field = var_int(0xffffffff) + int_to_hex(txin['value'], 8) - return value_field + witness - - @classmethod - def is_segwit_input(self, txin): - return txin['type'] in ['p2wpkh', 'p2wpkh-p2sh', 'p2wsh', 'p2wsh-p2sh'] - @classmethod def input_script(self, txin, estimate_size=False): _type = txin['type'] @@ -701,16 +629,6 @@ class Transaction: script += push_script(redeem_script) elif _type == 'p2pkh': script += push_script(pubkeys[0]) - elif _type in ['p2wpkh', 'p2wsh']: - return '' - elif _type == 'p2wpkh-p2sh': - pubkey = safe_parse_pubkey(pubkeys[0]) - scriptSig = bitcoin.p2wpkh_nested_script(pubkey) - return push_script(scriptSig) - elif _type == 'p2wsh-p2sh': - witness_script = self.get_preimage_script(txin) - scriptSig = bitcoin.p2wsh_nested_script(witness_script) - return push_script(scriptSig) elif _type == 'address': script += push_script(pubkeys[0]) elif _type == 'unknown': @@ -726,16 +644,11 @@ class Transaction: @classmethod def get_preimage_script(self, txin): - # only for non-segwit if txin['type'] == 'p2pkh': return bitcoin.address_to_script(txin['address']) - elif txin['type'] in ['p2sh', 'p2wsh', 'p2wsh-p2sh']: + elif txin['type'] in ['p2sh']: pubkeys, x_pubkeys = self.get_sorted_pubkeys(txin) return multisig_script(pubkeys, txin['num_sig']) - elif txin['type'] in ['p2wpkh', 'p2wpkh-p2sh']: - pubkey = txin['pubkeys'][0] - pkh = bh2u(bitcoin.hash_160(bfh(pubkey))) - return '76a9' + push_script(pkh) + '88ac' elif txin['type'] == 'p2pk': pubkey = txin['pubkeys'][0] return bitcoin.public_key_to_p2pk_script(pubkey) @@ -782,53 +695,28 @@ class Transaction: outputs = self.outputs() txin = inputs[i] # TODO: py3 hex - if self.is_segwit_input(txin): - hashPrevouts = bh2u(Hash(bfh(''.join(self.serialize_outpoint(txin) for txin in inputs)))) - hashSequence = bh2u(Hash(bfh(''.join(int_to_hex(txin.get('sequence', 0xffffffff - 1), 4) for txin in inputs)))) - hashOutputs = bh2u(Hash(bfh(''.join(self.serialize_output(o) for o in outputs)))) - outpoint = self.serialize_outpoint(txin) - preimage_script = self.get_preimage_script(txin) - scriptCode = var_int(len(preimage_script) // 2) + preimage_script - amount = int_to_hex(txin['value'], 8) - nSequence = int_to_hex(txin.get('sequence', 0xffffffff - 1), 4) - preimage = nVersion + hashPrevouts + hashSequence + outpoint + scriptCode + amount + nSequence + hashOutputs + nLocktime + nHashType - else: - txins = var_int(len(inputs)) + ''.join(self.serialize_input(txin, self.get_preimage_script(txin) if i==k else '') for k, txin in enumerate(inputs)) - txouts = var_int(len(outputs)) + ''.join(self.serialize_output(o) for o in outputs) - preimage = nVersion + txins + txouts + nLocktime + nHashType + txins = var_int(len(inputs)) + ''.join(self.serialize_input(txin, self.get_preimage_script(txin) if i==k else '') for k, txin in enumerate(inputs)) + txouts = var_int(len(outputs)) + ''.join(self.serialize_output(o) for o in outputs) + preimage = nVersion + txins + txouts + nLocktime + nHashType return preimage - def is_segwit(self): - return any(self.is_segwit_input(x) for x in self.inputs()) - - def serialize(self, estimate_size=False, witness=True): + def serialize(self, estimate_size=False): nVersion = int_to_hex(self.version, 4) nLocktime = int_to_hex(self.locktime, 4) inputs = self.inputs() outputs = self.outputs() txins = var_int(len(inputs)) + ''.join(self.serialize_input(txin, self.input_script(txin, estimate_size)) for txin in inputs) txouts = var_int(len(outputs)) + ''.join(self.serialize_output(o) for o in outputs) - if witness and self.is_segwit(): - marker = '00' - flag = '01' - witness = ''.join(self.serialize_witness(x, estimate_size) for x in inputs) - return nVersion + marker + flag + txins + txouts + witness + nLocktime - else: - return nVersion + txins + txouts + nLocktime + return nVersion + txins + txouts + nLocktime def hash(self): print("warning: deprecated tx.hash()") return self.txid() def txid(self): - all_segwit = all(self.is_segwit_input(x) for x in self.inputs()) - if not all_segwit and not self.is_complete(): + if not self.is_complete(): return None - ser = self.serialize(witness=False) - return bh2u(Hash(bfh(ser))[::-1]) - - def wtxid(self): - ser = self.serialize(witness=True) + ser = self.serialize() return bh2u(Hash(bfh(ser))[::-1]) def add_inputs(self, inputs): @@ -867,15 +755,7 @@ class Transaction: '''Return an estimate of serialized input weight in weight units.''' script = cls.input_script(txin, True) input_size = len(cls.serialize_input(txin, script)) // 2 - - # note: we should actually branch based on tx.is_segwit() - # only if none of the inputs have a witness, is the size actually 0 - if cls.is_segwit_input(txin): - witness_size = len(cls.serialize_witness(txin, True)) // 2 - else: - witness_size = 0 - - return 4 * input_size + witness_size + return 4 * input_size @classmethod def virtual_size_from_weight(cls, weight): @@ -885,19 +765,9 @@ class Transaction: """Return an estimated total transaction size in bytes.""" return len(self.serialize(True)) // 2 if not self.is_complete() or self.raw is None else len(self.raw) // 2 # ASCII hex string - def estimated_witness_size(self): - """Return an estimate of witness size in bytes.""" - if not self.is_segwit(): - return 0 - inputs = self.inputs() - estimate = not self.is_complete() - witness = ''.join(self.serialize_witness(x, estimate) for x in inputs) - witness_size = len(witness) // 2 + 2 # include marker and flag - return witness_size - def estimated_base_size(self): """Return an estimated base transaction size in bytes.""" - return self.estimated_total_size() - self.estimated_witness_size() + return self.estimated_total_size() def estimated_weight(self): """Return an estimate of transaction weight.""" diff --git a/lib/version.py b/lib/version.py index 2f71ac17..1ab7e9f9 100644 --- a/lib/version.py +++ b/lib/version.py @@ -4,13 +4,10 @@ PROTOCOL_VERSION = '1.1' # protocol version requested # The hash of the mnemonic seed must begin with this SEED_PREFIX = '01' # Standard wallet SEED_PREFIX_2FA = '101' # Two-factor authentication -SEED_PREFIX_SW = '100' # Segwit wallet def seed_prefix(seed_type): if seed_type == 'standard': return SEED_PREFIX - elif seed_type == 'segwit': - return SEED_PREFIX_SW elif seed_type == '2fa': return SEED_PREFIX_2FA diff --git a/lib/wallet.py b/lib/wallet.py index 65cdd3da..c211e87b 100644 --- a/lib/wallet.py +++ b/lib/wallet.py @@ -346,7 +346,7 @@ class Abstract_Wallet(PrintError): return [] index = self.get_address_index(address) pk, compressed = self.keystore.get_private_key(index, password) - if self.txin_type in ['p2sh', 'p2wsh', 'p2wsh-p2sh']: + if self.txin_type in ['p2sh']: pubkeys = self.get_public_keys(address) redeem_script = self.pubkeys_to_redeem_script(pubkeys) else: @@ -1096,12 +1096,6 @@ class Abstract_Wallet(PrintError): address = txin['address'] if self.is_mine(address): txin['type'] = self.get_txin_type(address) - # segwit needs value to sign - if txin.get('value') is None and Transaction.is_segwit_input(txin): - received, spent = self.get_addr_io(address) - item = received.get(txin['prevout_hash']+':%d'%txin['prevout_n']) - tx_height, value, is_cb = item - txin['value'] = value self.add_input_sig_info(txin, address) def can_sign(self, tx): @@ -1519,11 +1513,11 @@ class Imported_Wallet(Simple_Wallet): txin_type, pubkey = self.keystore.import_privkey(sec, pw) except Exception: raise BaseException('Invalid private key', sec) - if txin_type in ['p2pkh', 'p2wpkh', 'p2wpkh-p2sh']: + if txin_type in ['p2pkh']: if redeem_script is not None: raise BaseException('Cannot use redeem script with', txin_type, sec) addr = bitcoin.pubkey_to_address(txin_type, pubkey) - elif txin_type in ['p2sh', 'p2wsh', 'p2wsh-p2sh']: + elif txin_type in ['p2sh']: if redeem_script is None: raise BaseException('Redeem script required for', txin_type, sec) addr = bitcoin.redeem_script_to_address(txin_type, redeem_script) @@ -1552,7 +1546,7 @@ class Imported_Wallet(Simple_Wallet): txin['x_pubkeys'] = [x_pubkey] txin['signatures'] = [None] return - if txin['type'] in ['p2pkh', 'p2wpkh', 'p2wpkh-p2sh']: + if txin['type'] in ['p2pkh']: pubkey = self.addresses[address]['pubkey'] txin['num_sig'] = 1 txin['x_pubkeys'] = [pubkey]