1
0

Initial segwit support (testnet only)

This commit is contained in:
ThomasV
2017-01-16 09:48:38 +01:00
parent 11377de398
commit 3a64ec0f2e
11 changed files with 341 additions and 198 deletions

View File

@@ -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):