Initial segwit support (testnet only)
This commit is contained in:
134
lib/wallet.py
134
lib/wallet.py
@@ -52,6 +52,7 @@ from version import *
|
||||
from keystore import load_keystore, Hardware_KeyStore
|
||||
from storage import multisig_type
|
||||
|
||||
import transaction
|
||||
from transaction import Transaction
|
||||
from plugins import run_hook
|
||||
import bitcoin
|
||||
@@ -436,7 +437,7 @@ class Abstract_Wallet(PrintError):
|
||||
label = ''
|
||||
height = conf = timestamp = None
|
||||
if tx.is_complete():
|
||||
tx_hash = tx.hash()
|
||||
tx_hash = tx.txid()
|
||||
if tx_hash in self.transactions.keys():
|
||||
label = self.get_label(tx_hash)
|
||||
height, conf, timestamp = self.get_tx_height(tx_hash)
|
||||
@@ -879,7 +880,7 @@ class Abstract_Wallet(PrintError):
|
||||
pubkey = public_key_from_private_key(privkey)
|
||||
address = address_from_private_key(privkey)
|
||||
u = network.synchronous_get(('blockchain.address.listunspent', [address]))
|
||||
pay_script = Transaction.pay_script(TYPE_ADDRESS, address)
|
||||
pay_script = transaction.get_scriptPubKey(address)
|
||||
for item in u:
|
||||
if len(inputs) >= imax:
|
||||
break
|
||||
@@ -1381,45 +1382,9 @@ class Imported_Wallet(Abstract_Wallet):
|
||||
txin['x_pubkeys'] = [ xpubkey ]
|
||||
txin['pubkeys'] = [ xpubkey ]
|
||||
txin['signatures'] = [None]
|
||||
txin['type'] = 'unknown'
|
||||
|
||||
|
||||
class P2PKH_Wallet(Abstract_Wallet):
|
||||
|
||||
def pubkeys_to_address(self, pubkey):
|
||||
return public_key_to_bc_address(pubkey.decode('hex'))
|
||||
|
||||
def load_keystore(self):
|
||||
self.keystore = load_keystore(self.storage, 'keystore')
|
||||
|
||||
def get_pubkey(self, c, i):
|
||||
pubkey_list = self.change_pubkeys if c else self.receiving_pubkeys
|
||||
return pubkey_list[i]
|
||||
|
||||
def get_public_keys(self, address):
|
||||
return [self.get_public_key(address)]
|
||||
|
||||
def add_input_sig_info(self, txin, address):
|
||||
if not self.keystore.can_import():
|
||||
txin['derivation'] = derivation = self.get_address_index(address)
|
||||
x_pubkey = self.keystore.get_xpubkey(*derivation)
|
||||
pubkey = self.get_pubkey(*derivation)
|
||||
else:
|
||||
pubkey = self.get_public_key(address)
|
||||
assert pubkey is not None
|
||||
x_pubkey = pubkey
|
||||
txin['x_pubkeys'] = [x_pubkey]
|
||||
txin['pubkeys'] = [pubkey]
|
||||
txin['signatures'] = [None]
|
||||
txin['redeemPubkey'] = pubkey
|
||||
txin['num_sig'] = 1
|
||||
|
||||
def sign_message(self, address, message, password):
|
||||
index = self.get_address_index(address)
|
||||
return self.keystore.sign_message(index, message, password)
|
||||
|
||||
def decrypt_message(self, pubkey, message, password):
|
||||
index = self.get_pubkey_index(pubkey)
|
||||
return self.keystore.decrypt_message(index, message, password)
|
||||
|
||||
|
||||
class Deterministic_Wallet(Abstract_Wallet):
|
||||
@@ -1545,8 +1510,53 @@ class Deterministic_Wallet(Abstract_Wallet):
|
||||
|
||||
|
||||
|
||||
class Standard_Wallet(Deterministic_Wallet, P2PKH_Wallet):
|
||||
wallet_type = 'standard'
|
||||
class Simple_Wallet(Abstract_Wallet):
|
||||
|
||||
""" Wallet with a single pubkey per address """
|
||||
|
||||
def load_keystore(self):
|
||||
self.keystore = load_keystore(self.storage, 'keystore')
|
||||
|
||||
def get_pubkey(self, c, i):
|
||||
pubkey_list = self.change_pubkeys if c else self.receiving_pubkeys
|
||||
return pubkey_list[i]
|
||||
|
||||
def get_public_keys(self, address):
|
||||
return [self.get_public_key(address)]
|
||||
|
||||
def add_input_sig_info(self, txin, address):
|
||||
if not self.keystore.can_import():
|
||||
txin['derivation'] = derivation = self.get_address_index(address)
|
||||
x_pubkey = self.keystore.get_xpubkey(*derivation)
|
||||
pubkey = self.get_pubkey(*derivation)
|
||||
else:
|
||||
pubkey = self.get_public_key(address)
|
||||
assert pubkey is not None
|
||||
x_pubkey = pubkey
|
||||
txin['x_pubkeys'] = [x_pubkey]
|
||||
txin['pubkeys'] = [pubkey]
|
||||
txin['signatures'] = [None]
|
||||
|
||||
addrtype, hash160 = bc_address_to_hash_160(address)
|
||||
if addrtype == bitcoin.ADDRTYPE_P2SH:
|
||||
txin['redeemScript'] = self.pubkeys_to_redeem_script(pubkey)
|
||||
txin['type'] = 'p2wpkh-p2sh'
|
||||
else:
|
||||
txin['redeemPubkey'] = pubkey
|
||||
txin['type'] = 'p2pkh'
|
||||
|
||||
txin['num_sig'] = 1
|
||||
|
||||
def sign_message(self, address, message, password):
|
||||
index = self.get_address_index(address)
|
||||
return self.keystore.sign_message(index, message, password)
|
||||
|
||||
def decrypt_message(self, pubkey, message, password):
|
||||
index = self.get_pubkey_index(pubkey)
|
||||
return self.keystore.decrypt_message(index, message, password)
|
||||
|
||||
|
||||
class Simple_Deterministic_Wallet(Deterministic_Wallet, Simple_Wallet):
|
||||
|
||||
def __init__(self, storage):
|
||||
Deterministic_Wallet.__init__(self, storage)
|
||||
@@ -1607,7 +1617,35 @@ class Standard_Wallet(Deterministic_Wallet, P2PKH_Wallet):
|
||||
return addr
|
||||
|
||||
|
||||
class Multisig_Wallet(Deterministic_Wallet):
|
||||
class P2SH:
|
||||
|
||||
def pubkeys_to_redeem_script(self, pubkeys):
|
||||
raise NotImplementedError()
|
||||
|
||||
def pubkeys_to_address(self, pubkeys):
|
||||
redeem_script = self.pubkeys_to_redeem_script(pubkeys)
|
||||
return bitcoin.hash160_to_p2sh(hash_160(redeem_script.decode('hex')))
|
||||
|
||||
|
||||
class P2PKH:
|
||||
|
||||
def pubkeys_to_address(self, pubkey):
|
||||
return bitcoin.public_key_to_p2pkh(pubkey.decode('hex'))
|
||||
|
||||
|
||||
class Standard_Wallet(Simple_Deterministic_Wallet, P2PKH):
|
||||
wallet_type = 'standard'
|
||||
|
||||
|
||||
class Segwit_Wallet(Simple_Deterministic_Wallet, P2SH):
|
||||
wallet_type = 'segwit'
|
||||
|
||||
def pubkeys_to_redeem_script(self, pubkey):
|
||||
return transaction.segwit_script(pubkey)
|
||||
|
||||
|
||||
|
||||
class Multisig_Wallet(Deterministic_Wallet, P2SH):
|
||||
# generic m of n
|
||||
gap_limit = 20
|
||||
|
||||
@@ -1622,12 +1660,10 @@ class Multisig_Wallet(Deterministic_Wallet):
|
||||
|
||||
def redeem_script(self, c, i):
|
||||
pubkeys = self.get_pubkeys(c, i)
|
||||
return Transaction.multisig_script(sorted(pubkeys), self.m)
|
||||
return transaction.multisig_script(sorted(pubkeys), self.m)
|
||||
|
||||
def pubkeys_to_address(self, pubkeys):
|
||||
redeem_script = Transaction.multisig_script(sorted(pubkeys), self.m)
|
||||
address = hash_160_to_bc_address(hash_160(redeem_script.decode('hex')), bitcoin.ADDRTYPE_P2SH)
|
||||
return address
|
||||
def pubkeys_to_redeem_script(self, pubkeys):
|
||||
return transaction.multisig_script(sorted(pubkeys), self.m)
|
||||
|
||||
def new_pubkeys(self, c, i):
|
||||
return [k.derive_pubkey(c, i) for k in self.get_keystores()]
|
||||
@@ -1683,6 +1719,7 @@ class Multisig_Wallet(Deterministic_Wallet):
|
||||
x_pubkeys = [k.get_xpubkey(*derivation) for k in self.get_keystores()]
|
||||
# sort pubkeys and x_pubkeys, using the order of pubkeys
|
||||
pubkeys, x_pubkeys = zip(*sorted(zip(pubkeys, x_pubkeys)))
|
||||
txin['type'] = 'p2sh'
|
||||
txin['pubkeys'] = list(pubkeys)
|
||||
txin['x_pubkeys'] = list(x_pubkeys)
|
||||
txin['signatures'] = [None] * len(pubkeys)
|
||||
@@ -1699,7 +1736,8 @@ wallet_constructors = {
|
||||
'standard': Standard_Wallet,
|
||||
'old': Standard_Wallet,
|
||||
'xpub': Standard_Wallet,
|
||||
'imported': Imported_Wallet
|
||||
'imported': Imported_Wallet,
|
||||
'segwit': Segwit_Wallet
|
||||
}
|
||||
|
||||
def register_constructor(wallet_type, constructor):
|
||||
|
||||
Reference in New Issue
Block a user