Browse Source

Merge #730: Get rid of remaining direct rpc() calls outside blockchaininterface.py

d5cf3878ae Get rid of remaining direct rpc() calls outside blockchaininterface.py (Kristaps Kaupe)

Pull request description:

  Follow-up to #501.

  Test suite passes and also did some manual testnet testing. Had error receiving payjoin from testnet.demo.btcpayserver.org, but that doesn't seem related. More testing is needed before merging.

Top commit has no ACKs.

Tree-SHA512: 036483b0f47349dc3bd6fd8bb5be153e338f7fe547c7e5194becd1ba5975fe1d9880f2d557519a7a9a708da263dd18e38cf4c28a03d5fd9348fef73032b1e6e9
master
Kristaps Kaupe 5 years ago
parent
commit
970b0a46c2
No known key found for this signature in database
GPG Key ID: D47B1B4232B55437
  1. 147
      jmclient/jmclient/blockchaininterface.py
  2. 4
      jmclient/jmclient/payjoin.py
  3. 11
      jmclient/jmclient/wallet_service.py
  4. 2
      jmclient/test/commontest.py
  5. 3
      jmclient/test/test_psbt_wallet.py
  6. 2
      jmclient/test/test_tx_creation.py
  7. 2
      jmclient/test/test_wallet.py

147
jmclient/jmclient/blockchaininterface.py

@ -1,5 +1,6 @@
import abc import abc
import ast
import random import random
import sys import sys
import time import time
@ -25,12 +26,11 @@ class BlockchainInterface(object):
def __init__(self): def __init__(self):
pass pass
@abc.abstractmethod
def is_address_imported(self, addr): def is_address_imported(self, addr):
try: """checks that address is already imported"""
return self.rpc('getaccount', [addr]) != ''
except JsonRpcError:
return len(self.rpc('getaddressinfo', [addr])['labels']) > 0
@abc.abstractmethod
def is_address_labeled(self, utxo, walletname): def is_address_labeled(self, utxo, walletname):
"""checks that UTXO belongs to the JM wallet""" """checks that UTXO belongs to the JM wallet"""
@ -68,6 +68,8 @@ class BlockchainInterface(object):
else: else:
return False return False
# ElectrumWalletInterface is currently broken
class ElectrumWalletInterface(BlockchainInterface): #pragma: no cover class ElectrumWalletInterface(BlockchainInterface): #pragma: no cover
"""A pseudo-blockchain interface using the existing """A pseudo-blockchain interface using the existing
Electrum server connection in an Electrum wallet. Electrum server connection in an Electrum wallet.
@ -159,17 +161,18 @@ class ElectrumWalletInterface(BlockchainInterface): #pragma: no cover
log.info("Got fee: " + btc.fee_per_kb_to_str(fee_per_kb_sat)) log.info("Got fee: " + btc.fee_per_kb_to_str(fee_per_kb_sat))
return fee_per_kb_sat return fee_per_kb_sat
class BitcoinCoreInterface(BlockchainInterface): class BitcoinCoreInterface(BlockchainInterface):
def __init__(self, jsonRpc, network): def __init__(self, jsonRpc, network):
super().__init__() super().__init__()
self.jsonRpc = jsonRpc self.jsonRpc = jsonRpc
blockchainInfo = self.rpc("getblockchaininfo", []) blockchainInfo = self._rpc("getblockchaininfo", [])
if not blockchainInfo: if not blockchainInfo:
# see note in BitcoinCoreInterface.rpc - here # see note in BitcoinCoreInterface.rpc - here
# we have to create this object before reactor start, # we have to create this object before reactor start,
# so reactor is not stopped, so we override the 'swallowing' # so reactor is not stopped, so we override the 'swallowing'
# of the Exception that happened in self.rpc(): # of the Exception that happened in self._rpc():
raise JsonRpcConnectionError("RPC connection to Bitcoin Core " raise JsonRpcConnectionError("RPC connection to Bitcoin Core "
"was not established successfully.") "was not established successfully.")
actualNet = blockchainInfo['chain'] actualNet = blockchainInfo['chain']
@ -180,21 +183,28 @@ class BitcoinCoreInterface(BlockchainInterface):
#special case of regtest and testnet having the same addr format #special case of regtest and testnet having the same addr format
raise Exception('wrong network configured') raise Exception('wrong network configured')
def is_address_imported(self, addr):
try:
return self._rpc('getaccount', [addr]) != ''
except JsonRpcError:
return len(self._rpc('getaddressinfo', [addr])['labels']) > 0
def get_block(self, blockheight): def get_block(self, blockheight):
"""Returns full serialized block at a given height. """Returns full serialized block at a given height.
""" """
block_hash = self.rpc('getblockhash', [blockheight]) block_hash = self._rpc('getblockhash', [blockheight])
block = self.rpc('getblock', [block_hash, False]) block = self._rpc('getblock', [block_hash, False])
if not block: if not block:
return False return False
return block return block
def rpc(self, method, args): def _rpc(self, method, args):
""" Returns the result of an rpc call to the Bitcoin Core RPC API. """ Returns the result of an rpc call to the Bitcoin Core RPC API.
If the connection is permanently or unrecognizably broken, None If the connection is permanently or unrecognizably broken, None
is returned *and the reactor is shutdown* (because we consider this is returned *and the reactor is shutdown* (because we consider this
condition unsafe - TODO possibly create a "freeze" mode that could condition unsafe - TODO possibly create a "freeze" mode that could
restart when the connection is healed, but that is tricky). restart when the connection is healed, but that is tricky).
Should not be called directly from outside code.
""" """
if method not in ['importaddress', 'walletpassphrase', 'getaccount', if method not in ['importaddress', 'walletpassphrase', 'getaccount',
'gettransaction', 'getrawtransaction', 'gettxout', 'gettransaction', 'getrawtransaction', 'gettxout',
@ -243,7 +253,7 @@ class BitcoinCoreInterface(BlockchainInterface):
"watchonly": True "watchonly": True
}) })
result = self.rpc('importmulti', [requests, {"rescan": False}]) result = self._rpc('importmulti', [requests, {"rescan": False}])
num_failed = 0 num_failed = 0
for row in result: for row in result:
@ -266,11 +276,11 @@ class BitcoinCoreInterface(BlockchainInterface):
def import_addresses_if_needed(self, addresses, wallet_name): def import_addresses_if_needed(self, addresses, wallet_name):
try: try:
imported_addresses = set(self.rpc('getaddressesbyaccount', imported_addresses = set(self._rpc('getaddressesbyaccount',
[wallet_name])) [wallet_name]))
except JsonRpcError: except JsonRpcError:
if wallet_name in self.rpc('listlabels', []): if wallet_name in self._rpc('listlabels', []):
imported_addresses = set(self.rpc('getaddressesbylabel', imported_addresses = set(self._rpc('getaddressesbylabel',
[wallet_name]).keys()) [wallet_name]).keys())
else: else:
imported_addresses = set() imported_addresses = set()
@ -283,7 +293,7 @@ class BitcoinCoreInterface(BlockchainInterface):
batch_size = 1000 batch_size = 1000
iteration = 0 iteration = 0
while True: while True:
new = self.rpc( new = self._rpc(
'listtransactions', 'listtransactions',
["*", batch_size, iteration * batch_size, True]) ["*", batch_size, iteration * batch_size, True])
for tx in new: for tx in new:
@ -307,7 +317,7 @@ class BitcoinCoreInterface(BlockchainInterface):
in the wallet (under any label/account), optionally in the wallet (under any label/account), optionally
skipping some. skipping some.
""" """
return self.rpc("listtransactions", ["*", num, skip, True]) return self._rpc("listtransactions", ["*", num, skip, True])
def get_transaction(self, txid): def get_transaction(self, txid):
""" Argument txid is passed in binary. """ Argument txid is passed in binary.
@ -319,10 +329,10 @@ class BitcoinCoreInterface(BlockchainInterface):
htxid = bintohex(txid) htxid = bintohex(txid)
#changed syntax in 0.14.0; allow both syntaxes #changed syntax in 0.14.0; allow both syntaxes
try: try:
res = self.rpc("gettransaction", [htxid, True]) res = self._rpc("gettransaction", [htxid, True])
except Exception as e: except Exception as e:
try: try:
res = self.rpc("gettransaction", [htxid, 1]) res = self._rpc("gettransaction", [htxid, 1])
except JsonRpcError as e: except JsonRpcError as e:
#This should never happen (gettransaction is a wallet rpc). #This should never happen (gettransaction is a wallet rpc).
log.warn("Failed gettransaction call; JsonRpcError: " + repr(e)) log.warn("Failed gettransaction call; JsonRpcError: " + repr(e))
@ -342,7 +352,7 @@ class BitcoinCoreInterface(BlockchainInterface):
""" """
txhex = bintohex(txbin) txhex = bintohex(txbin)
try: try:
txid = self.rpc('sendrawtransaction', [txhex]) txid = self._rpc('sendrawtransaction', [txhex])
except JsonRpcConnectionError as e: except JsonRpcConnectionError as e:
log.warning('error pushing = ' + repr(e)) log.warning('error pushing = ' + repr(e))
return False return False
@ -378,7 +388,7 @@ class BitcoinCoreInterface(BlockchainInterface):
log.warn("Invalid utxo format, ignoring: {}".format(txo)) log.warn("Invalid utxo format, ignoring: {}".format(txo))
result.append(None) result.append(None)
continue continue
ret = self.rpc('gettxout', [txo_hex, txo_idx, includeunconf]) ret = self._rpc('gettxout', [txo_hex, txo_idx, includeunconf])
if ret is None: if ret is None:
result.append(None) result.append(None)
else: else:
@ -399,7 +409,7 @@ class BitcoinCoreInterface(BlockchainInterface):
if super().fee_per_kb_has_been_manually_set(N): if super().fee_per_kb_has_been_manually_set(N):
# use the local bitcoin core relay fee as floor to avoid relay problems # use the local bitcoin core relay fee as floor to avoid relay problems
btc_relayfee = -1 btc_relayfee = -1
rpc_result = self.rpc('getnetworkinfo', None) rpc_result = self._rpc('getnetworkinfo', None)
btc_relayfee = rpc_result.get('relayfee', btc_relayfee) btc_relayfee = rpc_result.get('relayfee', btc_relayfee)
if btc_relayfee > 0: if btc_relayfee > 0:
relayfee_in_sat = int(Decimal(1e8) * Decimal(btc_relayfee)) relayfee_in_sat = int(Decimal(1e8) * Decimal(btc_relayfee))
@ -419,7 +429,7 @@ class BitcoinCoreInterface(BlockchainInterface):
estimate = -1 estimate = -1
retval = -1 retval = -1
for i in range(tries): for i in range(tries):
rpc_result = self.rpc('estimatesmartfee', [N + i]) rpc_result = self._rpc('estimatesmartfee', [N + i])
estimate = rpc_result.get('feerate', estimate) estimate = rpc_result.get('feerate', estimate)
if estimate > 0: if estimate > 0:
break break
@ -433,7 +443,7 @@ class BitcoinCoreInterface(BlockchainInterface):
def get_current_block_height(self): def get_current_block_height(self):
try: try:
res = self.rpc("getblockcount", []) res = self._rpc("getblockcount", [])
except JsonRpcError as e: except JsonRpcError as e:
log.error("Getblockcount RPC failed with: %i, %s" % ( log.error("Getblockcount RPC failed with: %i, %s" % (
e.code, e.message)) e.code, e.message))
@ -441,23 +451,32 @@ class BitcoinCoreInterface(BlockchainInterface):
return res return res
def get_best_block_hash(self): def get_best_block_hash(self):
return self.rpc('getbestblockhash', []) return self._rpc('getbestblockhash', [])
def get_block_time(self, blockhash): def get_best_block_median_time(self):
return self._rpc('getblockchaininfo', [])['mediantime']
def _get_block_header_data(self, blockhash, key):
try: try:
# works with pruning enabled, but only after v0.12 # works with pruning enabled, but only after v0.12
return self.rpc('getblockheader', [blockhash])['time'] return self._rpc('getblockheader', [blockhash])[key]
except JsonRpcError: except JsonRpcError:
return self.rpc('getblock', [blockhash])['time'] return self._rpc('getblock', [blockhash])[key]
def get_block_height(self, blockhash):
return self._get_block_header_data(blockhash, 'height')
def get_block_time(self, blockhash):
return self._get_block_header_data(blockhash, 'time')
def get_tx_merkle_branch(self, txid, blockhash=None): def get_tx_merkle_branch(self, txid, blockhash=None):
if not blockhash: if not blockhash:
tx = self.rpc("gettransaction", [txid]) tx = self._rpc("gettransaction", [txid])
if tx["confirmations"] < 1: if tx["confirmations"] < 1:
raise ValueError("Transaction not in block") raise ValueError("Transaction not in block")
blockhash = tx["blockhash"] blockhash = tx["blockhash"]
try: try:
core_proof = self.rpc("gettxoutproof", [[txid], blockhash]) core_proof = self._rpc("gettxoutproof", [[txid], blockhash])
except JsonRpcError: except JsonRpcError:
raise ValueError("Block containing transaction is pruned") raise ValueError("Block containing transaction is pruned")
return self.core_proof_to_merkle_branch(core_proof) return self.core_proof_to_merkle_branch(core_proof)
@ -469,12 +488,28 @@ class BitcoinCoreInterface(BlockchainInterface):
return core_proof[80:] return core_proof[80:]
def verify_tx_merkle_branch(self, txid, block_height, merkle_branch): def verify_tx_merkle_branch(self, txid, block_height, merkle_branch):
block_hash = self.rpc("getblockhash", [block_height]) block_hash = self._rpc("getblockhash", [block_height])
core_proof = self.rpc("getblockheader", [block_hash, False]) + \ core_proof = self._rpc("getblockheader", [block_hash, False]) + \
binascii.hexlify(merkle_branch).decode() binascii.hexlify(merkle_branch).decode()
ret = self.rpc("verifytxoutproof", [core_proof]) ret = self._rpc("verifytxoutproof", [core_proof])
return len(ret) == 1 and ret[0] == txid return len(ret) == 1 and ret[0] == txid
def listaddressgroupings(self):
return self._rpc('listaddressgroupings', [])
def listunspent(self, minconf=None):
listunspent_args = []
if 'listunspent_args' in jm_single().config.options('POLICY'):
listunspent_args = ast.literal_eval(jm_single().config.get(
'POLICY', 'listunspent_args'))
if minconf is not None:
listunspent_args[0] = minconf
return self._rpc('listunspent', listunspent_args)
def testmempoolaccept(self, rawtx):
return self._rpc('testmempoolaccept', [[rawtx]])
class RegtestBitcoinCoreMixin(): class RegtestBitcoinCoreMixin():
""" """
This Mixin provides helper functions that are used in Interface classes This Mixin provides helper functions that are used in Interface classes
@ -486,7 +521,7 @@ class RegtestBitcoinCoreMixin():
instruct to mine n blocks. instruct to mine n blocks.
""" """
try: try:
self.rpc('generatetoaddress', [n, self.destn_addr]) self._rpc('generatetoaddress', [n, self.destn_addr])
except JsonRpcConnectionError: except JsonRpcConnectionError:
#can happen if the blockchain is shut down #can happen if the blockchain is shut down
#automatically at the end of tests; this shouldn't #automatically at the end of tests; this shouldn't
@ -510,17 +545,18 @@ class RegtestBitcoinCoreMixin():
#mine enough to get to the reqd amt #mine enough to get to the reqd amt
reqd = int(amt - self.current_balance) reqd = int(amt - self.current_balance)
reqd_blocks = int(reqd/50) +1 reqd_blocks = int(reqd/50) +1
if self.rpc('setgenerate', [True, reqd_blocks]): if self._rpc('setgenerate', [True, reqd_blocks]):
raise Exception("Something went wrong") raise Exception("Something went wrong")
""" """
# now we do a custom create transaction and push to the receiver # now we do a custom create transaction and push to the receiver
txid = self.rpc('sendtoaddress', [receiving_addr, amt]) txid = self._rpc('sendtoaddress', [receiving_addr, amt])
if not txid: if not txid:
raise Exception("Failed to broadcast transaction") raise Exception("Failed to broadcast transaction")
# confirm # confirm
self.tick_forward_chain(1) self.tick_forward_chain(1)
return txid return txid
class BitcoinCoreNoHistoryInterface(BitcoinCoreInterface, RegtestBitcoinCoreMixin): class BitcoinCoreNoHistoryInterface(BitcoinCoreInterface, RegtestBitcoinCoreMixin):
def __init__(self, jsonRpc, network): def __init__(self, jsonRpc, network):
@ -537,8 +573,8 @@ class BitcoinCoreNoHistoryInterface(BitcoinCoreInterface, RegtestBitcoinCoreMixi
log.debug("Starting scan of UTXO set") log.debug("Starting scan of UTXO set")
st = time.time() st = time.time()
try: try:
self.rpc("scantxoutset", ["abort", []]) self._rpc("scantxoutset", ["abort", []])
self.scan_result = self.rpc("scantxoutset", ["start", self.scan_result = self._rpc("scantxoutset", ["start",
addr_list]) addr_list])
except JsonRpcError as e: except JsonRpcError as e:
raise RuntimeError("Bitcoin Core 0.17.0 or higher required " raise RuntimeError("Bitcoin Core 0.17.0 or higher required "
@ -567,23 +603,19 @@ class BitcoinCoreNoHistoryInterface(BitcoinCoreInterface, RegtestBitcoinCoreMixi
def list_transactions(self, num): def list_transactions(self, num):
return [] return []
def rpc(self, method, args): def listaddressgroupings(self):
if method == "listaddressgroupings": raise RuntimeError("default sync not supported by bitcoin-rpc-nohistory, use --recoversync")
raise RuntimeError("default sync not supported by bitcoin-rpc-nohistory, use --recoversync")
elif method == "listunspent": def listunspent(self):
minconf = 0 if len(args) < 1 else args[0] return [{
maxconf = 9999999 if len(args) < 2 else args[1] "address": self._get_addr_from_desc(u["desc"]),
return [{ "label": self.wallet_name,
"address": self._get_addr_from_desc(u["desc"]), "height": u["height"],
"label": self.wallet_name, "txid": u["txid"],
"height": u["height"], "vout": u["vout"],
"txid": u["txid"], "scriptPubKey": u["scriptPubKey"],
"vout": u["vout"], "amount": u["amount"]
"scriptPubKey": u["scriptPubKey"], } for u in self.scan_result["unspents"]]
"amount": u["amount"]
} for u in self.scan_result["unspents"]]
else:
return super().rpc(method, args)
def set_wallet_no_history(self, wallet): def set_wallet_no_history(self, wallet):
#make wallet-tool not display any new addresses #make wallet-tool not display any new addresses
@ -595,9 +627,10 @@ class BitcoinCoreNoHistoryInterface(BitcoinCoreInterface, RegtestBitcoinCoreMixi
wallet.disable_new_scripts = True wallet.disable_new_scripts = True
def tick_forward_chain(self, n): def tick_forward_chain(self, n):
self.destn_addr = self.rpc("getnewaddress", []) self.destn_addr = self._rpc("getnewaddress", [])
super().tick_forward_chain(n) super().tick_forward_chain(n)
# class for regtest chain access # class for regtest chain access
# running on local daemon. Only # running on local daemon. Only
# to be instantiated after network is up # to be instantiated after network is up
@ -611,7 +644,7 @@ class RegtestBitcoinCoreInterface(BitcoinCoreInterface, RegtestBitcoinCoreMixin)
self.absurd_fees = False self.absurd_fees = False
self.simulating = False self.simulating = False
self.shutdown_signal = False self.shutdown_signal = False
self.destn_addr = self.rpc("getnewaddress", []) self.destn_addr = self._rpc("getnewaddress", [])
def estimate_fee_per_kb(self, N): def estimate_fee_per_kb(self, N):
if not self.absurd_fees: if not self.absurd_fees:
@ -655,8 +688,8 @@ class RegtestBitcoinCoreInterface(BitcoinCoreInterface, RegtestBitcoinCoreMixin)
# in the wallet # in the wallet
res = [] res = []
for address in addresses: for address in addresses:
#self.rpc('importaddress', [address, 'watchonly']) #self._rpc('importaddress', [address, 'watchonly'])
res.append({'address': address, res.append({'address': address,
'balance': int(Decimal(1e8) * self.rpc( 'balance': int(Decimal(1e8) * self._rpc(
'getreceivedbyaddress', [address, 0]))}) 'getreceivedbyaddress', [address, 0]))})
return {'data': res} return {'data': res}

4
jmclient/jmclient/payjoin.py

@ -872,8 +872,8 @@ class PayjoinServer(Resource):
# it is still safer to at least verify the validity of the signatures # it is still safer to at least verify the validity of the signatures
# at this stage, to ensure no misbehaviour with using inputs # at this stage, to ensure no misbehaviour with using inputs
# that are not signed correctly: # that are not signed correctly:
res = jm_single().bc_interface.rpc('testmempoolaccept', [[bintohex( res = jm_single().bc_interface.testmempoolaccept(bintohex(
self.manager.payment_tx.serialize())]]) self.manager.payment_tx.serialize()))
if not res[0]["allowed"]: if not res[0]["allowed"]:
return self.bip78_error(request, "Proposed transaction was " return self.bip78_error(request, "Proposed transaction was "
"rejected from mempool.", "rejected from mempool.",

11
jmclient/jmclient/wallet_service.py

@ -484,7 +484,7 @@ class WalletService(Service):
have been used in our Core wallet with the specific label have been used in our Core wallet with the specific label
for our JM wallet. This operation is generally immediate. for our JM wallet. This operation is generally immediate.
""" """
agd = self.bci.rpc('listaddressgroupings', []) agd = self.bci.listaddressgroupings()
# flatten all groups into a single list; then, remove duplicates # flatten all groups into a single list; then, remove duplicates
fagd = (tuple(item) for sublist in agd for item in sublist) fagd = (tuple(item) for sublist in agd for item in sublist)
# "deduplicated flattened address grouping data" = dfagd # "deduplicated flattened address grouping data" = dfagd
@ -647,7 +647,7 @@ class WalletService(Service):
jlog.warning("Merkle branch likely not available, use " jlog.warning("Merkle branch likely not available, use "
+ "wallet-tool `addtxoutproof`") + "wallet-tool `addtxoutproof`")
merkle_branch = None merkle_branch = None
block_height = self.bci.rpc("getblockheader", [gettx["blockhash"]])["height"] block_height = self.bci.get_block_height(gettx["blockhash"])
if merkle_branch: if merkle_branch:
assert self.bci.verify_tx_merkle_branch(txid, block_height, merkle_branch) assert self.bci.verify_tx_merkle_branch(txid, block_height, merkle_branch)
self.wallet.add_burner_output(path_repr, gettx["hex"], block_height, self.wallet.add_burner_output(path_repr, gettx["hex"], block_height,
@ -729,12 +729,7 @@ class WalletService(Service):
wallet_name = self.get_wallet_name() wallet_name = self.get_wallet_name()
self.reset_utxos() self.reset_utxos()
listunspent_args = [] unspent_list = self.bci.listunspent()
if 'listunspent_args' in jm_single().config.options('POLICY'):
listunspent_args = ast.literal_eval(jm_single().config.get(
'POLICY', 'listunspent_args'))
unspent_list = self.bci.rpc('listunspent', listunspent_args)
# filter on label, but note (a) in certain circumstances (in- # filter on label, but note (a) in certain circumstances (in-
# wallet transfer) it is possible for the utxo to be labeled # wallet transfer) it is possible for the utxo to be labeled
# with the external label, and (b) the wallet will know if it # with the external label, and (b) the wallet will know if it

2
jmclient/test/commontest.py

@ -229,7 +229,7 @@ def ensure_bip65_activated():
#on regtest bip65 activates on height 1351 #on regtest bip65 activates on height 1351
#https://github.com/bitcoin/bitcoin/blob/1d1f8bbf57118e01904448108a104e20f50d2544/src/chainparams.cpp#L262 #https://github.com/bitcoin/bitcoin/blob/1d1f8bbf57118e01904448108a104e20f50d2544/src/chainparams.cpp#L262
BIP65Height = 1351 BIP65Height = 1351
current_height = jm_single().bc_interface.rpc("getblockchaininfo", [])["blocks"] current_height = jm_single().bc_interface.get_current_block_height()
until_bip65_activation = BIP65Height - current_height + 1 until_bip65_activation = BIP65Height - current_height + 1
if until_bip65_activation > 0: if until_bip65_activation > 0:
jm_single().bc_interface.tick_forward_chain(until_bip65_activation) jm_single().bc_interface.tick_forward_chain(until_bip65_activation)

3
jmclient/test/test_psbt_wallet.py

@ -231,8 +231,7 @@ def test_payjoin_workflow(setup_psbt_wallet, payment_amt, wallet_cls_sender,
# don't want to push the tx right now, because of test structure # don't want to push the tx right now, because of test structure
# (in production code this isn't really needed, we will not # (in production code this isn't really needed, we will not
# produce invalid payment transactions). # produce invalid payment transactions).
res = jm_single().bc_interface.rpc('testmempoolaccept', res = jm_single().bc_interface.testmempoolaccept(bintohex(extracted_tx))
[[bintohex(extracted_tx)]])
assert res[0]["allowed"], "Payment transaction was rejected from mempool." assert res[0]["allowed"], "Payment transaction was rejected from mempool."
# *** STEP 2 *** # *** STEP 2 ***

2
jmclient/test/test_tx_creation.py

@ -143,7 +143,7 @@ def test_spend_freeze_script(setup_tx_creation):
wallet_service = make_wallets(1, [[3, 0, 0, 0, 0]], 3)[0]['wallet'] wallet_service = make_wallets(1, [[3, 0, 0, 0, 0]], 3)[0]['wallet']
wallet_service.sync_wallet(fast=True) wallet_service.sync_wallet(fast=True)
mediantime = jm_single().bc_interface.rpc("getblockchaininfo", [])["mediantime"] mediantime = jm_single().bc_interface.get_best_block_median_time()
timeoffset_success_tests = [(2, False), (-60*60*24*30, True), (60*60*24*30, False)] timeoffset_success_tests = [(2, False), (-60*60*24*30, True), (60*60*24*30, False)]

2
jmclient/test/test_wallet.py

@ -755,7 +755,7 @@ def test_wallet_mixdepth_decrease(setup_wallet):
assert max_mixdepth >= 1, "bad default value for mixdepth for this test" assert max_mixdepth >= 1, "bad default value for mixdepth for this test"
utxo = fund_wallet_addr(wallet, wallet.get_internal_addr(max_mixdepth), 1) utxo = fund_wallet_addr(wallet, wallet.get_internal_addr(max_mixdepth), 1)
bci = jm_single().bc_interface bci = jm_single().bc_interface
unspent_list = bci.rpc('listunspent', [0]) unspent_list = bci.listunspent(0)
# filter on label, but note (a) in certain circumstances (in- # filter on label, but note (a) in certain circumstances (in-
# wallet transfer) it is possible for the utxo to be labeled # wallet transfer) it is possible for the utxo to be labeled
# with the external label, and (b) the wallet will know if it # with the external label, and (b) the wallet will know if it

Loading…
Cancel
Save