remove segwit from lib
This commit is contained in:
parent
a154b9c2b6
commit
fc0d01ec2c
|
@ -240,7 +240,7 @@ class BaseWizard(object):
|
||||||
|
|
||||||
def on_hw_derivation(self, name, device_info, derivation):
|
def on_hw_derivation(self, name, device_info, derivation):
|
||||||
from .keystore import hardware_keystore
|
from .keystore import hardware_keystore
|
||||||
xtype = 'p2wpkh-p2sh' if derivation.startswith("m/49'/") else 'standard'
|
xtype = 'standard'
|
||||||
try:
|
try:
|
||||||
xpub = self.plugin.get_xpub(device_info.device.id_, derivation, xtype, self)
|
xpub = self.plugin.get_xpub(device_info.device.id_, derivation, xtype, self)
|
||||||
except BaseException as e:
|
except BaseException as e:
|
||||||
|
@ -271,7 +271,7 @@ class BaseWizard(object):
|
||||||
def restore_from_seed(self):
|
def restore_from_seed(self):
|
||||||
self.opt_bip39 = True
|
self.opt_bip39 = True
|
||||||
self.opt_ext = 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
|
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)
|
self.restore_seed_dialog(run_next=self.on_restore_seed, test=test)
|
||||||
|
|
||||||
|
@ -280,7 +280,7 @@ class BaseWizard(object):
|
||||||
if self.seed_type == 'bip39':
|
if self.seed_type == 'bip39':
|
||||||
f = lambda passphrase: self.on_restore_bip39(seed, passphrase)
|
f = lambda passphrase: self.on_restore_bip39(seed, passphrase)
|
||||||
self.passphrase_dialog(run_next=f) if is_ext else f('')
|
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)
|
f = lambda passphrase: self.run('create_keystore', seed, passphrase)
|
||||||
self.passphrase_dialog(run_next=f) if is_ext else f('')
|
self.passphrase_dialog(run_next=f) if is_ext else f('')
|
||||||
elif self.seed_type == 'old':
|
elif self.seed_type == 'old':
|
||||||
|
@ -313,7 +313,7 @@ class BaseWizard(object):
|
||||||
from .bitcoin import xpub_type
|
from .bitcoin import xpub_type
|
||||||
t1 = xpub_type(k.xpub)
|
t1 = xpub_type(k.xpub)
|
||||||
if self.wallet_type == 'standard':
|
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.show_error(_('Wrong key type') + ' %s'%t1)
|
||||||
self.run('choose_keystore')
|
self.run('choose_keystore')
|
||||||
return
|
return
|
||||||
|
@ -321,7 +321,7 @@ class BaseWizard(object):
|
||||||
self.run('create_wallet')
|
self.run('create_wallet')
|
||||||
elif self.wallet_type == 'multisig':
|
elif self.wallet_type == 'multisig':
|
||||||
assert has_xpub
|
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.show_error(_('Wrong key type') + ' %s'%t1)
|
||||||
self.run('choose_keystore')
|
self.run('choose_keystore')
|
||||||
return
|
return
|
||||||
|
@ -380,17 +380,12 @@ class BaseWizard(object):
|
||||||
title = _('Choose Seed type')
|
title = _('Choose Seed type')
|
||||||
message = ' '.join([
|
message = ' '.join([
|
||||||
"The type of addresses used by your wallet will depend on your seed.",
|
"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 = [
|
choices = [
|
||||||
('create_standard_seed', _('Standard')),
|
('create_standard_seed', _('Standard')),
|
||||||
('create_segwit_seed', _('Segwit')),
|
|
||||||
]
|
]
|
||||||
self.choice_dialog(title=title, message=message, choices=choices, run_next=self.run)
|
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_standard_seed(self): self.create_seed('standard')
|
||||||
|
|
||||||
def create_seed(self, seed_type):
|
def create_seed(self, seed_type):
|
||||||
|
|
|
@ -35,7 +35,6 @@ import pyaes
|
||||||
from .util import bfh, bh2u, to_string
|
from .util import bfh, bh2u, to_string
|
||||||
from . import version
|
from . import version
|
||||||
from .util import print_error, InvalidPassword, assert_bytes, to_bytes, inv_dict
|
from .util import print_error, InvalidPassword, assert_bytes, to_bytes, inv_dict
|
||||||
from . import segwit_addr
|
|
||||||
|
|
||||||
def read_json_dict(filename):
|
def read_json_dict(filename):
|
||||||
path = os.path.join(os.path.dirname(__file__), 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
|
# Version numbers for BIP32 extended keys
|
||||||
# standard: xprv, xpub
|
# standard: xprv, xpub
|
||||||
# segwit in p2sh: yprv, ypub
|
|
||||||
# native segwit: zprv, zpub
|
|
||||||
XPRV_HEADERS = {
|
XPRV_HEADERS = {
|
||||||
'standard': 0x0488ade4,
|
'standard': 0x0488ade4,
|
||||||
'p2wpkh-p2sh': 0x049d7878,
|
|
||||||
'p2wsh-p2sh': 0x295b005,
|
|
||||||
'p2wpkh': 0x4b2430c,
|
|
||||||
'p2wsh': 0x2aa7a99
|
|
||||||
}
|
}
|
||||||
XPUB_HEADERS = {
|
XPUB_HEADERS = {
|
||||||
'standard': 0x0488b21e,
|
'standard': 0x0488b21e,
|
||||||
'p2wpkh-p2sh': 0x049d7cb2,
|
|
||||||
'p2wsh-p2sh': 0x295b43f,
|
|
||||||
'p2wpkh': 0x4b24746,
|
|
||||||
'p2wsh': 0x2aa7ed3
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -282,8 +271,6 @@ def seed_type(x):
|
||||||
return 'old'
|
return 'old'
|
||||||
elif is_new_seed(x):
|
elif is_new_seed(x):
|
||||||
return 'standard'
|
return 'standard'
|
||||||
elif is_new_seed(x, version.SEED_PREFIX_SW):
|
|
||||||
return 'segwit'
|
|
||||||
elif is_new_seed(x, version.SEED_PREFIX_2FA):
|
elif is_new_seed(x, version.SEED_PREFIX_2FA):
|
||||||
return '2fa'
|
return '2fa'
|
||||||
return ''
|
return ''
|
||||||
|
@ -323,7 +310,7 @@ def hash_160(public_key):
|
||||||
return md.digest()
|
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 = bytes([addrtype])
|
||||||
s += h160
|
s += h160
|
||||||
return base_encode(s+Hash(s)[0:4], base=58)
|
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):
|
def public_key_to_p2pkh(public_key):
|
||||||
return hash160_to_p2pkh(hash_160(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):
|
def pubkey_to_address(txin_type, pubkey):
|
||||||
if txin_type == 'p2pkh':
|
if txin_type == 'p2pkh':
|
||||||
return public_key_to_p2pkh(bfh(pubkey))
|
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:
|
else:
|
||||||
raise NotImplementedError(txin_type)
|
raise NotImplementedError(txin_type)
|
||||||
|
|
||||||
def redeem_script_to_address(txin_type, redeem_script):
|
def redeem_script_to_address(txin_type, redeem_script):
|
||||||
if txin_type == 'p2sh':
|
if txin_type == 'p2sh':
|
||||||
return hash160_to_p2sh(hash_160(bfh(redeem_script)))
|
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:
|
else:
|
||||||
raise NotImplementedError(txin_type)
|
raise NotImplementedError(txin_type)
|
||||||
|
|
||||||
|
@ -391,13 +351,6 @@ def script_to_address(script):
|
||||||
return addr
|
return addr
|
||||||
|
|
||||||
def address_to_script(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)
|
addrtype, hash_160 = b58_address_to_hash160(addr)
|
||||||
if addrtype == NetworkConstants.ADDRTYPE_P2PKH:
|
if addrtype == NetworkConstants.ADDRTYPE_P2PKH:
|
||||||
script = '76a9' # op_dup, op_hash_160
|
script = '76a9' # op_dup, op_hash_160
|
||||||
|
@ -508,15 +461,9 @@ def DecodeBase58Check(psz):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# extended key export format for segwit
|
|
||||||
|
|
||||||
SCRIPT_TYPES = {
|
SCRIPT_TYPES = {
|
||||||
'p2pkh':0,
|
'p2pkh':0,
|
||||||
'p2wpkh':1,
|
|
||||||
'p2wpkh-p2sh':2,
|
|
||||||
'p2sh':5,
|
'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)
|
public_key = public_key_from_private_key(privkey, compressed)
|
||||||
return pubkey_to_address(txin_type, public_key)
|
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):
|
def is_b58_address(addr):
|
||||||
try:
|
try:
|
||||||
addrtype, h = b58_address_to_hash160(addr)
|
addrtype, h = b58_address_to_hash160(addr)
|
||||||
|
@ -584,7 +524,7 @@ def is_b58_address(addr):
|
||||||
return addr == hash160_to_b58_address(h, addrtype)
|
return addr == hash160_to_b58_address(h, addrtype)
|
||||||
|
|
||||||
def is_address(addr):
|
def is_address(addr):
|
||||||
return is_segwit_address(addr) or is_b58_address(addr)
|
return is_b58_address(addr)
|
||||||
|
|
||||||
|
|
||||||
def is_private_key(key):
|
def is_private_key(key):
|
||||||
|
@ -628,7 +568,7 @@ def verify_message(address, sig, message):
|
||||||
public_key, compressed = pubkey_from_signature(sig, h)
|
public_key, compressed = pubkey_from_signature(sig, h)
|
||||||
# check public key using the address
|
# check public key using the address
|
||||||
pubkey = point_to_ser(public_key.pubkey.point, compressed)
|
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))
|
addr = pubkey_to_address(txin_type, bh2u(pubkey))
|
||||||
if address == addr:
|
if address == addr:
|
||||||
break
|
break
|
||||||
|
|
|
@ -255,14 +255,6 @@ class Blockchain(util.PrintError):
|
||||||
def get_hash(self, height):
|
def get_hash(self, height):
|
||||||
return hash_header(self.read_header(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):
|
def get_target(self, index):
|
||||||
if bitcoin.NetworkConstants.TESTNET:
|
if bitcoin.NetworkConstants.TESTNET:
|
||||||
return 0, 0
|
return 0, 0
|
||||||
|
|
|
@ -123,7 +123,7 @@ class Commands:
|
||||||
return ' '.join(sorted(known_commands.keys()))
|
return ' '.join(sorted(known_commands.keys()))
|
||||||
|
|
||||||
@command('')
|
@command('')
|
||||||
def create(self, segwit=False):
|
def create(self):
|
||||||
"""Create a new wallet"""
|
"""Create a new wallet"""
|
||||||
raise BaseException('Not a JSON-RPC command')
|
raise BaseException('Not a JSON-RPC command')
|
||||||
|
|
||||||
|
@ -159,10 +159,10 @@ class Commands:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@command('')
|
@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"""
|
"""Create a seed"""
|
||||||
from .mnemonic import Mnemonic
|
from .mnemonic import Mnemonic
|
||||||
t = 'segwit' if segwit else 'standard'
|
t = 'standard'
|
||||||
s = Mnemonic(language).make_seed(t, nbits, custom_entropy=entropy)
|
s = Mnemonic(language).make_seed(t, nbits, custom_entropy=entropy)
|
||||||
return s
|
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"),
|
'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"),
|
'nbits': (None, "Number of bits of entropy"),
|
||||||
'entropy': (None, "Custom entropy"),
|
'entropy': (None, "Custom entropy"),
|
||||||
'segwit': (None, "Create segwit seed"),
|
|
||||||
'language': ("-L", "Default language for wordlist"),
|
'language': ("-L", "Default language for wordlist"),
|
||||||
'privkey': (None, "Private key. Set to '?' to get a prompt."),
|
'privkey': (None, "Private key. Set to '?' to get a prompt."),
|
||||||
'unsigned': ("-u", "Do not sign transaction"),
|
'unsigned': ("-u", "Do not sign transaction"),
|
||||||
|
|
|
@ -571,7 +571,7 @@ def bip39_is_checksum_valid(mnemonic):
|
||||||
def from_bip39_seed(seed, passphrase, derivation):
|
def from_bip39_seed(seed, passphrase, derivation):
|
||||||
k = BIP32_KeyStore({})
|
k = BIP32_KeyStore({})
|
||||||
bip32_seed = bip39_to_seed(seed, passphrase)
|
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)
|
k.add_xprv_from_seed(bip32_seed, t, derivation)
|
||||||
return k
|
return k
|
||||||
|
|
||||||
|
@ -681,17 +681,13 @@ def from_seed(seed, passphrase, is_p2sh):
|
||||||
if t == 'old':
|
if t == 'old':
|
||||||
keystore = Old_KeyStore({})
|
keystore = Old_KeyStore({})
|
||||||
keystore.add_seed(seed)
|
keystore.add_seed(seed)
|
||||||
elif t in ['standard', 'segwit']:
|
elif t in ['standard']:
|
||||||
keystore = BIP32_KeyStore({})
|
keystore = BIP32_KeyStore({})
|
||||||
keystore.add_seed(seed)
|
keystore.add_seed(seed)
|
||||||
keystore.passphrase = passphrase
|
keystore.passphrase = passphrase
|
||||||
bip32_seed = Mnemonic.mnemonic_to_seed(seed, passphrase)
|
bip32_seed = Mnemonic.mnemonic_to_seed(seed, passphrase)
|
||||||
if t == 'standard':
|
der = "m/"
|
||||||
der = "m/"
|
xtype = 'standard'
|
||||||
xtype = 'standard'
|
|
||||||
else:
|
|
||||||
der = "m/1'/" if is_p2sh else "m/0'/"
|
|
||||||
xtype = 'p2wsh' if is_p2sh else 'p2wpkh'
|
|
||||||
keystore.add_xprv_from_seed(bip32_seed, xtype, der)
|
keystore.add_xprv_from_seed(bip32_seed, xtype, der)
|
||||||
else:
|
else:
|
||||||
raise BaseException(t)
|
raise BaseException(t)
|
||||||
|
|
|
@ -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
|
|
|
@ -399,7 +399,6 @@ class WalletStorage(PrintError):
|
||||||
def convert_version_15(self):
|
def convert_version_15(self):
|
||||||
if not self._is_upgrade_method_needed(14, 14):
|
if not self._is_upgrade_method_needed(14, 14):
|
||||||
return
|
return
|
||||||
assert self.get('seed_type') != 'segwit' # unsupported derivation
|
|
||||||
self.put('seed_version', 15)
|
self.put('seed_version', 15)
|
||||||
|
|
||||||
def convert_version_16(self):
|
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
|
seed_version = OLD_SEED_VERSION if len(self.get('master_public_key','')) == 128 else NEW_SEED_VERSION
|
||||||
if seed_version > FINAL_SEED_VERSION:
|
if seed_version > FINAL_SEED_VERSION:
|
||||||
raise BaseException('This version of Electrum is too old to open this wallet')
|
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:
|
if seed_version >=12:
|
||||||
return seed_version
|
return seed_version
|
||||||
if seed_version not in [OLD_SEED_VERSION, NEW_SEED_VERSION]:
|
if seed_version not in [OLD_SEED_VERSION, NEW_SEED_VERSION]:
|
||||||
|
|
|
@ -301,10 +301,7 @@ def parse_scriptSig(d, _bytes):
|
||||||
match = [ opcodes.OP_PUSHDATA4 ]
|
match = [ opcodes.OP_PUSHDATA4 ]
|
||||||
if match_decoded(decoded, match):
|
if match_decoded(decoded, match):
|
||||||
item = decoded[0][1]
|
item = decoded[0][1]
|
||||||
if item[0] == 0:
|
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:
|
|
||||||
# payto_pubkey
|
# payto_pubkey
|
||||||
d['type'] = 'p2pk'
|
d['type'] = 'p2pk'
|
||||||
d['address'] = "(pubkey)"
|
d['address'] = "(pubkey)"
|
||||||
|
@ -387,11 +384,6 @@ def get_address_from_output_script(_bytes):
|
||||||
if match_decoded(decoded, match):
|
if match_decoded(decoded, match):
|
||||||
return TYPE_ADDRESS, hash160_to_p2sh(decoded[1][1])
|
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)
|
return TYPE_SCRIPT, bh2u(_bytes)
|
||||||
|
|
||||||
|
|
||||||
|
@ -423,29 +415,6 @@ def parse_input(vds):
|
||||||
return d
|
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):
|
def parse_output(vds, i):
|
||||||
d = {}
|
d = {}
|
||||||
d['value'] = vds.read_int64()
|
d['value'] = vds.read_int64()
|
||||||
|
@ -463,26 +432,9 @@ def deserialize(raw):
|
||||||
start = vds.read_cursor
|
start = vds.read_cursor
|
||||||
d['version'] = vds.read_int32()
|
d['version'] = vds.read_int32()
|
||||||
n_vin = vds.read_compact_size()
|
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)]
|
d['inputs'] = [parse_input(vds) for i in range(n_vin)]
|
||||||
n_vout = vds.read_compact_size()
|
n_vout = vds.read_compact_size()
|
||||||
d['outputs'] = [parse_output(vds, i) for i in range(n_vout)]
|
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()
|
d['lockTime'] = vds.read_uint32()
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@ -661,30 +613,6 @@ class Transaction:
|
||||||
sig_list = [sig if sig else NO_SIGNATURE for sig in x_signatures]
|
sig_list = [sig if sig else NO_SIGNATURE for sig in x_signatures]
|
||||||
return pk_list, sig_list
|
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
|
@classmethod
|
||||||
def input_script(self, txin, estimate_size=False):
|
def input_script(self, txin, estimate_size=False):
|
||||||
_type = txin['type']
|
_type = txin['type']
|
||||||
|
@ -701,16 +629,6 @@ class Transaction:
|
||||||
script += push_script(redeem_script)
|
script += push_script(redeem_script)
|
||||||
elif _type == 'p2pkh':
|
elif _type == 'p2pkh':
|
||||||
script += push_script(pubkeys[0])
|
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':
|
elif _type == 'address':
|
||||||
script += push_script(pubkeys[0])
|
script += push_script(pubkeys[0])
|
||||||
elif _type == 'unknown':
|
elif _type == 'unknown':
|
||||||
|
@ -726,16 +644,11 @@ class Transaction:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_preimage_script(self, txin):
|
def get_preimage_script(self, txin):
|
||||||
# only for non-segwit
|
|
||||||
if txin['type'] == 'p2pkh':
|
if txin['type'] == 'p2pkh':
|
||||||
return bitcoin.address_to_script(txin['address'])
|
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)
|
pubkeys, x_pubkeys = self.get_sorted_pubkeys(txin)
|
||||||
return multisig_script(pubkeys, txin['num_sig'])
|
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':
|
elif txin['type'] == 'p2pk':
|
||||||
pubkey = txin['pubkeys'][0]
|
pubkey = txin['pubkeys'][0]
|
||||||
return bitcoin.public_key_to_p2pk_script(pubkey)
|
return bitcoin.public_key_to_p2pk_script(pubkey)
|
||||||
|
@ -782,53 +695,28 @@ class Transaction:
|
||||||
outputs = self.outputs()
|
outputs = self.outputs()
|
||||||
txin = inputs[i]
|
txin = inputs[i]
|
||||||
# TODO: py3 hex
|
# TODO: py3 hex
|
||||||
if self.is_segwit_input(txin):
|
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))
|
||||||
hashPrevouts = bh2u(Hash(bfh(''.join(self.serialize_outpoint(txin) for txin in inputs))))
|
txouts = var_int(len(outputs)) + ''.join(self.serialize_output(o) for o in outputs)
|
||||||
hashSequence = bh2u(Hash(bfh(''.join(int_to_hex(txin.get('sequence', 0xffffffff - 1), 4) for txin in inputs))))
|
preimage = nVersion + txins + txouts + nLocktime + nHashType
|
||||||
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
|
|
||||||
return preimage
|
return preimage
|
||||||
|
|
||||||
def is_segwit(self):
|
def serialize(self, estimate_size=False):
|
||||||
return any(self.is_segwit_input(x) for x in self.inputs())
|
|
||||||
|
|
||||||
def serialize(self, estimate_size=False, witness=True):
|
|
||||||
nVersion = int_to_hex(self.version, 4)
|
nVersion = int_to_hex(self.version, 4)
|
||||||
nLocktime = int_to_hex(self.locktime, 4)
|
nLocktime = int_to_hex(self.locktime, 4)
|
||||||
inputs = self.inputs()
|
inputs = self.inputs()
|
||||||
outputs = self.outputs()
|
outputs = self.outputs()
|
||||||
txins = var_int(len(inputs)) + ''.join(self.serialize_input(txin, self.input_script(txin, estimate_size)) for txin in inputs)
|
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)
|
txouts = var_int(len(outputs)) + ''.join(self.serialize_output(o) for o in outputs)
|
||||||
if witness and self.is_segwit():
|
return nVersion + txins + txouts + nLocktime
|
||||||
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
|
|
||||||
|
|
||||||
def hash(self):
|
def hash(self):
|
||||||
print("warning: deprecated tx.hash()")
|
print("warning: deprecated tx.hash()")
|
||||||
return self.txid()
|
return self.txid()
|
||||||
|
|
||||||
def txid(self):
|
def txid(self):
|
||||||
all_segwit = all(self.is_segwit_input(x) for x in self.inputs())
|
if not self.is_complete():
|
||||||
if not all_segwit and not self.is_complete():
|
|
||||||
return None
|
return None
|
||||||
ser = self.serialize(witness=False)
|
ser = self.serialize()
|
||||||
return bh2u(Hash(bfh(ser))[::-1])
|
|
||||||
|
|
||||||
def wtxid(self):
|
|
||||||
ser = self.serialize(witness=True)
|
|
||||||
return bh2u(Hash(bfh(ser))[::-1])
|
return bh2u(Hash(bfh(ser))[::-1])
|
||||||
|
|
||||||
def add_inputs(self, inputs):
|
def add_inputs(self, inputs):
|
||||||
|
@ -867,15 +755,7 @@ class Transaction:
|
||||||
'''Return an estimate of serialized input weight in weight units.'''
|
'''Return an estimate of serialized input weight in weight units.'''
|
||||||
script = cls.input_script(txin, True)
|
script = cls.input_script(txin, True)
|
||||||
input_size = len(cls.serialize_input(txin, script)) // 2
|
input_size = len(cls.serialize_input(txin, script)) // 2
|
||||||
|
return 4 * input_size
|
||||||
# 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
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def virtual_size_from_weight(cls, weight):
|
def virtual_size_from_weight(cls, weight):
|
||||||
|
@ -885,19 +765,9 @@ class Transaction:
|
||||||
"""Return an estimated total transaction size in bytes."""
|
"""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
|
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):
|
def estimated_base_size(self):
|
||||||
"""Return an estimated base transaction size in bytes."""
|
"""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):
|
def estimated_weight(self):
|
||||||
"""Return an estimate of transaction weight."""
|
"""Return an estimate of transaction weight."""
|
||||||
|
|
|
@ -4,13 +4,10 @@ PROTOCOL_VERSION = '1.1' # protocol version requested
|
||||||
# The hash of the mnemonic seed must begin with this
|
# The hash of the mnemonic seed must begin with this
|
||||||
SEED_PREFIX = '01' # Standard wallet
|
SEED_PREFIX = '01' # Standard wallet
|
||||||
SEED_PREFIX_2FA = '101' # Two-factor authentication
|
SEED_PREFIX_2FA = '101' # Two-factor authentication
|
||||||
SEED_PREFIX_SW = '100' # Segwit wallet
|
|
||||||
|
|
||||||
|
|
||||||
def seed_prefix(seed_type):
|
def seed_prefix(seed_type):
|
||||||
if seed_type == 'standard':
|
if seed_type == 'standard':
|
||||||
return SEED_PREFIX
|
return SEED_PREFIX
|
||||||
elif seed_type == 'segwit':
|
|
||||||
return SEED_PREFIX_SW
|
|
||||||
elif seed_type == '2fa':
|
elif seed_type == '2fa':
|
||||||
return SEED_PREFIX_2FA
|
return SEED_PREFIX_2FA
|
||||||
|
|
|
@ -346,7 +346,7 @@ class Abstract_Wallet(PrintError):
|
||||||
return []
|
return []
|
||||||
index = self.get_address_index(address)
|
index = self.get_address_index(address)
|
||||||
pk, compressed = self.keystore.get_private_key(index, password)
|
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)
|
pubkeys = self.get_public_keys(address)
|
||||||
redeem_script = self.pubkeys_to_redeem_script(pubkeys)
|
redeem_script = self.pubkeys_to_redeem_script(pubkeys)
|
||||||
else:
|
else:
|
||||||
|
@ -1096,12 +1096,6 @@ class Abstract_Wallet(PrintError):
|
||||||
address = txin['address']
|
address = txin['address']
|
||||||
if self.is_mine(address):
|
if self.is_mine(address):
|
||||||
txin['type'] = self.get_txin_type(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)
|
self.add_input_sig_info(txin, address)
|
||||||
|
|
||||||
def can_sign(self, tx):
|
def can_sign(self, tx):
|
||||||
|
@ -1519,11 +1513,11 @@ class Imported_Wallet(Simple_Wallet):
|
||||||
txin_type, pubkey = self.keystore.import_privkey(sec, pw)
|
txin_type, pubkey = self.keystore.import_privkey(sec, pw)
|
||||||
except Exception:
|
except Exception:
|
||||||
raise BaseException('Invalid private key', sec)
|
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:
|
if redeem_script is not None:
|
||||||
raise BaseException('Cannot use redeem script with', txin_type, sec)
|
raise BaseException('Cannot use redeem script with', txin_type, sec)
|
||||||
addr = bitcoin.pubkey_to_address(txin_type, pubkey)
|
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:
|
if redeem_script is None:
|
||||||
raise BaseException('Redeem script required for', txin_type, sec)
|
raise BaseException('Redeem script required for', txin_type, sec)
|
||||||
addr = bitcoin.redeem_script_to_address(txin_type, redeem_script)
|
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['x_pubkeys'] = [x_pubkey]
|
||||||
txin['signatures'] = [None]
|
txin['signatures'] = [None]
|
||||||
return
|
return
|
||||||
if txin['type'] in ['p2pkh', 'p2wpkh', 'p2wpkh-p2sh']:
|
if txin['type'] in ['p2pkh']:
|
||||||
pubkey = self.addresses[address]['pubkey']
|
pubkey = self.addresses[address]['pubkey']
|
||||||
txin['num_sig'] = 1
|
txin['num_sig'] = 1
|
||||||
txin['x_pubkeys'] = [pubkey]
|
txin['x_pubkeys'] = [pubkey]
|
||||||
|
|
Loading…
Reference in New Issue