Browse Source

add support for non-segwit maker

master
undeath 8 years ago
parent
commit
715985d8c5
  1. 2
      jmclient/jmclient/__init__.py
  2. 6
      jmclient/jmclient/maker.py
  3. 34
      jmclient/jmclient/wallet.py
  4. 16
      jmclient/jmclient/wallet_utils.py
  5. 20
      jmclient/jmclient/yieldgenerator.py

2
jmclient/jmclient/__init__.py

@ -18,7 +18,7 @@ from .slowaes import decryptData, encryptData
from .taker import Taker from .taker import Taker
from .wallet import (AbstractWallet, BitcoinCoreInterface, Wallet, from .wallet import (AbstractWallet, BitcoinCoreInterface, Wallet,
BitcoinCoreWallet, estimate_tx_fee, WalletError, BitcoinCoreWallet, estimate_tx_fee, WalletError,
create_wallet_file, SegwitWallet, Bip39Wallet) create_wallet_file, SegwitWallet, Bip39Wallet, get_wallet_cls)
from .configure import (load_program_config, get_p2pk_vbyte, from .configure import (load_program_config, get_p2pk_vbyte,
jm_single, get_network, validate_address, get_irc_mchannels, jm_single, get_network, validate_address, get_irc_mchannels,
get_blockchain_interface_instance, get_p2sh_vbyte, set_config) get_blockchain_interface_instance, get_p2sh_vbyte, set_config)

6
jmclient/jmclient/maker.py

@ -69,8 +69,7 @@ class Maker(object):
if res[0]['value'] < reqd_amt: if res[0]['value'] < reqd_amt:
reason = "commitment utxo too small: " + str(res[0]['value']) reason = "commitment utxo too small: " + str(res[0]['value'])
return reject(reason) return reject(reason)
if res[0]['address'] != btc.pubkey_to_p2sh_p2wpkh_address(cr_dict['P'], if res[0]['address'] != self.wallet.pubkey_to_address(cr_dict['P']):
self.wallet.get_vbyte()):
reason = "Invalid podle pubkey: " + str(cr_dict['P']) reason = "Invalid podle pubkey: " + str(cr_dict['P'])
return reject(reason) return reject(reason)
@ -147,7 +146,8 @@ class Maker(object):
times_seen_cj_addr = 0 times_seen_cj_addr = 0
times_seen_change_addr = 0 times_seen_change_addr = 0
for outs in txd['outs']: for outs in txd['outs']:
addr = btc.script_to_address(outs['script'], get_p2sh_vbyte()) #FIXME: the type of address should be detected from the script (p2pkh/p2sh)
addr = self.wallet.script_to_address(outs['script'])
if addr == cjaddr: if addr == cjaddr:
times_seen_cj_addr += 1 times_seen_cj_addr += 1
if outs['value'] != amount: if outs['value'] != amount:

34
jmclient/jmclient/wallet.py

@ -101,6 +101,10 @@ class AbstractWallet(object):
""" """
return None return None
@classmethod
def pubkey_to_address(cls, pubkey):
return None
def update_cache_index(self): def update_cache_index(self):
pass pass
@ -214,12 +218,17 @@ class Wallet(AbstractWallet):
""" """
return btc.sign(tx, i, priv) return btc.sign(tx, i, priv)
def script_to_address(self, script): @classmethod
def script_to_address(cls, script):
"""Return the address for a given output script, """Return the address for a given output script,
which will be p2pkh for the default Wallet object, which will be p2pkh for the default Wallet object,
and reading the correct network byte from the config. and reading the correct network byte from the config.
""" """
return btc.script_to_address(script, get_p2pk_vbyte()) return btc.script_to_address(script, cls.get_vbyte())
@classmethod
def pubkey_to_address(cls, pubkey):
return btc.pubkey_to_address(pubkey, cls.get_vbyte())
def read_wallet_file_data(self, filename, pwd=None, wallet_dir=None): def read_wallet_file_data(self, filename, pwd=None, wallet_dir=None):
self.path = None self.path = None
@ -385,8 +394,8 @@ class Wallet(AbstractWallet):
self.spent_utxos += removed_utxos.keys() self.spent_utxos += removed_utxos.keys()
return removed_utxos return removed_utxos
@staticmethod
def get_vbyte(self): def get_vbyte():
return get_p2pk_vbyte() return get_p2pk_vbyte()
def add_new_utxos(self, tx, txid): def add_new_utxos(self, tx, txid):
@ -467,7 +476,8 @@ class SegwitWallet(Bip39Wallet):
root = btc.bip32_ckd(pre_root, testnet_flag + 2**31) root = btc.bip32_ckd(pre_root, testnet_flag + 2**31)
return [btc.bip32_ckd(root, c + 2**31) for c in range(self.max_mix_depth)] return [btc.bip32_ckd(root, c + 2**31) for c in range(self.max_mix_depth)]
def get_vbyte(self): @staticmethod
def get_vbyte():
return get_p2sh_vbyte() return get_p2sh_vbyte()
def get_txtype(self): def get_txtype(self):
@ -484,13 +494,18 @@ class SegwitWallet(Bip39Wallet):
pub = btc.privtopub(self.get_key(mixing_depth, forchange, i)) pub = btc.privtopub(self.get_key(mixing_depth, forchange, i))
return btc.pubkey_to_p2sh_p2wpkh_address(pub, magicbyte=self.get_vbyte()) return btc.pubkey_to_p2sh_p2wpkh_address(pub, magicbyte=self.get_vbyte())
def script_to_address(self, script): @classmethod
def script_to_address(cls, script):
"""Return the address for a given output script, """Return the address for a given output script,
which will be p2sh-p2wpkh for the segwit (currently). which will be p2sh-p2wpkh for the segwit (currently).
The underlying witness is however invisible at this layer; The underlying witness is however invisible at this layer;
so it's just a p2sh address. so it's just a p2sh address.
""" """
return btc.script_to_address(script, get_p2sh_vbyte()) return btc.script_to_address(script, cls.get_vbyte())
@classmethod
def pubkey_to_address(cls, pubkey):
return btc.pubkey_to_p2sh_p2wpkh_address(pubkey, cls.get_vbyte())
def sign(self, tx, i, priv, amount): def sign(self, tx, i, priv, amount):
"""Sign a transaction; the amount field """Sign a transaction; the amount field
@ -551,3 +566,8 @@ class BitcoinCoreWallet(AbstractWallet): #pragma: no cover
if exc.code != -14: if exc.code != -14:
raise exc raise exc
# Wrong passphrase, try again. # Wrong passphrase, try again.
def get_wallet_cls():
if jm_single().config.get("POLICY", "segwit") == "true":
return SegwitWallet
return Wallet

16
jmclient/jmclient/wallet_utils.py

@ -9,10 +9,10 @@ from datetime import datetime
from mnemonic import Mnemonic from mnemonic import Mnemonic
from optparse import OptionParser from optparse import OptionParser
import getpass import getpass
from jmclient import (get_network, Wallet, Bip39Wallet, podle, from jmclient import (get_network, get_wallet_cls, Bip39Wallet, podle,
encryptData, get_p2sh_vbyte, get_p2pk_vbyte, jm_single, encryptData, get_p2sh_vbyte, get_p2pk_vbyte, jm_single,
mn_decode, mn_encode, BitcoinCoreInterface, mn_decode, mn_encode, BitcoinCoreInterface,
JsonRpcError, sync_wallet, WalletError, SegwitWallet) JsonRpcError, sync_wallet, WalletError)
from jmbase.support import get_password from jmbase.support import get_password
import jmclient.btc as btc import jmclient.btc as btc
@ -815,8 +815,6 @@ def wallet_tool_main(wallet_root_path):
""" """
parser = get_wallettool_parser() parser = get_wallettool_parser()
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
walletclass = SegwitWallet if jm_single().config.get(
"POLICY", "segwit") == "true" else Wallet
# if the index_cache stored in wallet.json is longer than the default # if the index_cache stored in wallet.json is longer than the default
# then set maxmixdepth to the length of index_cache # then set maxmixdepth to the length of index_cache
maxmixdepth_configured = True maxmixdepth_configured = True
@ -840,15 +838,15 @@ def wallet_tool_main(wallet_root_path):
seed = args[0] seed = args[0]
method = ('display' if len(args) == 1 else args[1].lower()) method = ('display' if len(args) == 1 else args[1].lower())
if not os.path.exists(os.path.join(wallet_root_path, seed)): if not os.path.exists(os.path.join(wallet_root_path, seed)):
wallet = walletclass(seed, None, options.maxmixdepth, wallet = get_wallet_cls()(seed, None, options.maxmixdepth,
options.gaplimit, extend_mixdepth= not maxmixdepth_configured, options.gaplimit, extend_mixdepth= not maxmixdepth_configured,
storepassword=(method == 'importprivkey'), storepassword=(method == 'importprivkey'),
wallet_dir=wallet_root_path) wallet_dir=wallet_root_path)
else: else:
while True: while True:
try: try:
pwd = get_password("Enter wallet decryption passphrase: ") pwd = get_password("Enter wallet decryption passphrase: ")
wallet = walletclass(seed, pwd, wallet = get_wallet_cls()(seed, pwd,
options.maxmixdepth, options.maxmixdepth,
options.gaplimit, options.gaplimit,
extend_mixdepth=not maxmixdepth_configured, extend_mixdepth=not maxmixdepth_configured,

20
jmclient/jmclient/yieldgenerator.py

@ -9,7 +9,7 @@ from twisted.python.log import startLogging
from optparse import OptionParser from optparse import OptionParser
from jmbase import get_password from jmbase import get_password
from jmclient import (Maker, jm_single, get_network, load_program_config, get_log, from jmclient import (Maker, jm_single, get_network, load_program_config, get_log,
SegwitWallet, sync_wallet, JMClientProtocolFactory, get_wallet_cls, sync_wallet, JMClientProtocolFactory,
start_reactor, calc_cj_fee, WalletError) start_reactor, calc_cj_fee, WalletError)
jlog = get_log() jlog = get_log()
@ -87,13 +87,13 @@ class YieldGeneratorBasic(YieldGenerator):
# print mix_balance # print mix_balance
max_mix = max(mix_balance, key=mix_balance.get) max_mix = max(mix_balance, key=mix_balance.get)
f = '0' f = '0'
if self.ordertype == 'swreloffer': if self.ordertype in ('reloffer', 'swreloffer'):
f = self.cjfee_r f = self.cjfee_r
#minimum size bumped if necessary such that you always profit #minimum size bumped if necessary such that you always profit
#least 50% of the miner fee #least 50% of the miner fee
self.minsize = max(int(1.5 * self.txfee / float(self.cjfee_r)), self.minsize = max(int(1.5 * self.txfee / float(self.cjfee_r)),
self.minsize) self.minsize)
elif self.ordertype == 'swabsoffer': elif self.ordertype in ('absoffer', 'swabsoffer'):
f = str(self.txfee + self.cjfee_a) f = str(self.txfee + self.cjfee_a)
order = {'oid': 0, order = {'oid': 0,
'ordertype': self.ordertype, 'ordertype': self.ordertype,
@ -215,13 +215,13 @@ def ygmain(ygclass, txfee=1000, cjfee_a=200, cjfee_r=0.002, ordertype='swreloffe
wallet_name = args[0] wallet_name = args[0]
ordertype = options.ordertype ordertype = options.ordertype
txfee = options.txfee txfee = options.txfee
if ordertype == 'swreloffer': if ordertype in ('reloffer', 'swreloffer'):
if options.cjfee != '': if options.cjfee != '':
cjfee_r = options.cjfee cjfee_r = options.cjfee
# minimum size is such that you always net profit at least 20% # minimum size is such that you always net profit at least 20%
#of the miner fee #of the miner fee
minsize = max(int(1.2 * txfee / float(cjfee_r)), options.minsize) minsize = max(int(1.2 * txfee / float(cjfee_r)), options.minsize)
elif ordertype == 'swabsoffer': elif ordertype in ('absoffer', 'swabsoffer'):
if options.cjfee != '': if options.cjfee != '':
cjfee_a = int(options.cjfee) cjfee_a = int(options.cjfee)
minsize = options.minsize minsize = options.minsize
@ -233,15 +233,15 @@ def ygmain(ygclass, txfee=1000, cjfee_a=200, cjfee_r=0.002, ordertype='swreloffe
load_program_config() load_program_config()
if not os.path.exists(os.path.join('wallets', wallet_name)): if not os.path.exists(os.path.join('wallets', wallet_name)):
wallet = SegwitWallet(wallet_name, None, max_mix_depth=MAX_MIX_DEPTH, wallet = get_wallet_cls()(wallet_name, None, max_mix_depth=MAX_MIX_DEPTH,
gaplimit=options.gaplimit) gaplimit=options.gaplimit)
else: else:
while True: while True:
try: try:
pwd = get_password("Enter wallet decryption passphrase: ") pwd = get_password("Enter wallet decryption passphrase: ")
wallet = SegwitWallet(wallet_name, pwd, wallet = get_wallet_cls()(wallet_name, pwd,
max_mix_depth=MAX_MIX_DEPTH, max_mix_depth=MAX_MIX_DEPTH,
gaplimit=options.gaplimit) gaplimit=options.gaplimit)
except WalletError: except WalletError:
print("Wrong password, try again.") print("Wrong password, try again.")
continue continue

Loading…
Cancel
Save