def check_outputs(tx_name, method, inputs, outputs, error, records, server_db): """Check actual and expected outputs of a particular function.""" try: tested_module = sys.modules['counterpartylib.lib.{}'.format(tx_name)] except KeyError: # TODO: hack tested_module = sys.modules['counterpartylib.lib.messages.{}'.format(tx_name)] tested_method = getattr(tested_module, method) test_outputs = None if error is not None: with pytest.raises(error[0]) as exception: test_outputs = exec_tested_method(tx_name, method, tested_method, inputs, server_db) else: test_outputs = exec_tested_method(tx_name, method, tested_method, inputs, server_db) if pytest.config.option.gentxhex and method == 'compose': print('') tx_params = { 'encoding': 'multisig' } if tx_name == 'order' and inputs[1]=='BTC': print('give btc') tx_params['fee_provided'] = DP['fee_provided'] unsigned_tx_hex = transaction.construct(server_db, test_outputs, **tx_params) print(tx_name) print(unsigned_tx_hex) if outputs is not None: assert outputs == test_outputs if error is not None: assert str(exception.value) == error[1] if records is not None: for record in records: check_record(record, server_db)
def compose_transaction(db, name, params, encoding='auto', fee_per_kb=config.DEFAULT_FEE_PER_KB, regular_dust_size=config.DEFAULT_REGULAR_DUST_SIZE, multisig_dust_size=config.DEFAULT_MULTISIG_DUST_SIZE, op_return_value=config.DEFAULT_OP_RETURN_VALUE, pubkey=None, allow_unconfirmed_inputs=False, fee=None, fee_provided=0): """Create and return a transaction.""" # Get provided pubkeys. if type(pubkey) == str: provided_pubkeys = [pubkey] elif type(pubkey) == list: provided_pubkeys = pubkey elif pubkey == None: provided_pubkeys = [] else: assert False # Get additional pubkeys from `source` and `destination` params. # Convert `source` and `destination` to pubkeyhash form. for address_name in ['source', 'destination']: if address_name in params: address = params[address_name] provided_pubkeys += script.extract_pubkeys(address) params[address_name] = script.make_pubkeyhash(address) # Check validity of collected pubkeys. for pubkey in provided_pubkeys: if not script.is_fully_valid(binascii.unhexlify(pubkey)): raise script.AddressError('invalid public key: {}'.format(pubkey)) compose_method = sys.modules['counterpartylib.lib.messages.{}'.format( name)].compose compose_params = inspect.getargspec(compose_method)[0] missing_params = [ p for p in compose_params if p not in params and p != 'db' ] for param in missing_params: params[param] = None # try: # NOTE: For debugging, e.g. with `Invalid Params` error. tx_info = compose_method(db, **params) return transaction.construct( db, tx_info, encoding=encoding, fee_per_kb=fee_per_kb, regular_dust_size=regular_dust_size, multisig_dust_size=multisig_dust_size, op_return_value=op_return_value, provided_pubkeys=provided_pubkeys, allow_unconfirmed_inputs=allow_unconfirmed_inputs, exact_fee=fee, fee_provided=fee_provided)
def test_transaction_arc4_mocked(server_db): """ by default init_arc4 should be mocked in the test suite to always use `'00' * 32` as seed. """ v = int(100 * 1e8) tx_info = send.compose(server_db, ADDR[0], ADDR[1], 'XCP', v) send1hex = transaction.construct(server_db, tx_info) assert send1hex == '0100000001c1d8c075936c3495f6d653c50f73d987f75448d97a750249b1eb83bee71b24ae000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788acffffffff0336150000000000001976a9148d6ae8a3b381663118b4e1eff4cfc7d0954dd6ec88ac00000000000000001e6a1c8a5dda15fb6f05628a061e67576e926dc71a7fa2f0cceb951120a9322f30ea0b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000'
def compose_transaction(db, name, params, encoding='auto', fee_per_kb=config.DEFAULT_FEE_PER_KB, estimate_fee_per_kb=None, estimate_fee_per_kb_nblocks=config.ESTIMATE_FEE_NBLOCKS, regular_dust_size=config.DEFAULT_REGULAR_DUST_SIZE, multisig_dust_size=config.DEFAULT_MULTISIG_DUST_SIZE, op_return_value=config.DEFAULT_OP_RETURN_VALUE, pubkey=None, allow_unconfirmed_inputs=False, fee=None, fee_provided=0, unspent_tx_hash=None, custom_inputs=None, dust_return_pubkey=None, disable_utxo_locks=False): """Create and return a transaction.""" # Get provided pubkeys. if type(pubkey) == str: provided_pubkeys = [pubkey] elif type(pubkey) == list: provided_pubkeys = pubkey elif pubkey == None: provided_pubkeys = [] else: assert False # Get additional pubkeys from `source` and `destination` params. # Convert `source` and `destination` to pubkeyhash form. for address_name in ['source', 'destination']: if address_name in params: address = params[address_name] provided_pubkeys += script.extract_pubkeys(address) params[address_name] = script.make_pubkeyhash(address) # Check validity of collected pubkeys. for pubkey in provided_pubkeys: if not script.is_fully_valid(binascii.unhexlify(pubkey)): raise script.AddressError('invalid public key: {}'.format(pubkey)) compose_method = sys.modules['counterpartylib.lib.messages.{}'.format(name)].compose compose_params = inspect.getargspec(compose_method)[0] missing_params = [p for p in compose_params if p not in params and p != 'db'] for param in missing_params: params[param] = None tx_info = compose_method(db, **params) return transaction.construct(db, tx_info, encoding=encoding, fee_per_kb=fee_per_kb, estimate_fee_per_kb=estimate_fee_per_kb, estimate_fee_per_kb_nblocks=estimate_fee_per_kb_nblocks, regular_dust_size=regular_dust_size, multisig_dust_size=multisig_dust_size, op_return_value=op_return_value, provided_pubkeys=provided_pubkeys, allow_unconfirmed_inputs=allow_unconfirmed_inputs, exact_fee=fee, fee_provided=fee_provided, unspent_tx_hash=unspent_tx_hash, custom_inputs=custom_inputs, dust_return_pubkey=dust_return_pubkey, disable_utxo_locks=disable_utxo_locks)
def construct_tx(db, source, destination, disable_utxo_locks=False, custom_inputs=None): tx_info = send.compose(db, source, destination, config.XCP, 1) return transaction.construct(db, tx_info, disable_utxo_locks=disable_utxo_locks, custom_inputs=custom_inputs)
def test_transaction_arc4_unmocked(server_db): """ by default init_arc4 should be mocked in the test suite to always use `'00' * 32` as seed but with DISABLE_ARC4_MOCKING=True it should be disabled and actually produce different results """ with util_test.ConfigContext(DISABLE_ARC4_MOCKING=True): v = int(100 * 1e8) tx_info = send.compose(server_db, ADDR[0], ADDR[1], 'XCP', v) send1hex = transaction.construct(server_db, tx_info) assert send1hex == '0100000001c1d8c075936c3495f6d653c50f73d987f75448d97a750249b1eb83bee71b24ae000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788acffffffff0336150000000000001976a9148d6ae8a3b381663118b4e1eff4cfc7d0954dd6ec88ac00000000000000001e6a1c2a504df746f83442653dd7ada4dc727a030865749e9fba58ba71d71a2f30ea0b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000'
def check_outputs(tx_name, method, inputs, outputs, error, records, comment, mock_protocol_changes, server_db): """Check actual and expected outputs of a particular function.""" try: tested_module = sys.modules['counterpartylib.lib.{}'.format(tx_name)] except KeyError: # TODO: hack tested_module = sys.modules['counterpartylib.lib.messages.{}'.format( tx_name)] tested_method = getattr(tested_module, method) with MockProtocolChangesContext(**(mock_protocol_changes or {})): test_outputs = None if error is not None: with pytest.raises(error[0]) as exception: test_outputs = exec_tested_method(tx_name, method, tested_method, inputs, server_db) else: test_outputs = exec_tested_method(tx_name, method, tested_method, inputs, server_db) if pytest.config.option.gentxhex and method == 'compose': print('') tx_params = {'encoding': 'multisig'} if tx_name == 'order' and inputs[1] == 'BTC': print('give btc') tx_params['fee_provided'] = DP['fee_provided'] unsigned_tx_hex = transaction.construct( server_db, test_outputs, **tx_params) print(tx_name) print(unsigned_tx_hex) if outputs is not None: try: assert outputs == test_outputs except AssertionError: if pytest.config.getoption('verbose') >= 2: msg = "expected outputs don't match test_outputs:\noutputs=\n" + pprint.pformat( outputs) + "\ntest_outputs=\n" + pprint.pformat( test_outputs) else: msg = "expected outputs don't match test_outputs: outputs=%s test_outputs=%s" % ( outputs, test_outputs) raise Exception(msg) if error is not None: assert str(exception.value) == error[1] if records is not None: for record in records: check_record(record, server_db)
def run_scenario(scenario, rawtransactions_db): """Execute a scenario for integration test, returns a dump of the db, a json with raw transactions and the full log.""" server.initialise(database_file=':memory:', testnet=True, **COUNTERPARTYD_OPTIONS) config.PREFIX = b'TESTXXXX' util.FIRST_MULTISIG_BLOCK_TESTNET = 1 checkpoints = dict(check.CHECKPOINTS_TESTNET) check.CHECKPOINTS_TESTNET = {} logger = logging.getLogger() logger.setLevel(logging.DEBUG) logger_buff = io.StringIO() handler = logging.StreamHandler(logger_buff) handler.setLevel(logging.DEBUG) formatter = logging.Formatter('%(message)s') handler.setFormatter(formatter) logger.addHandler(handler) requests_log = logging.getLogger("requests") requests_log.setLevel(logging.WARNING) asyncio_log = logging.getLogger('asyncio') asyncio_log.setLevel(logging.ERROR) db = database.get_connection(read_only=False) initialise_db(db) raw_transactions = [] for tx in scenario: if tx[0] != 'create_next_block': mock_protocol_changes = tx[3] if len(tx) == 4 else {} with MockProtocolChangesContext(**(mock_protocol_changes or {})): module = sys.modules['counterpartylib.lib.messages.{}'.format( tx[0])] compose = getattr(module, 'compose') unsigned_tx_hex = transaction.construct( db, compose(db, *tx[1]), **tx[2]) raw_transactions.append({tx[0]: unsigned_tx_hex}) insert_raw_transaction(unsigned_tx_hex, db, rawtransactions_db) else: create_next_block(db, block_index=config.BURN_START + tx[1], parse_block=tx[2] if len(tx) == 3 else True) dump = dump_database(db) log = logger_buff.getvalue() db.close() check.CHECKPOINTS_TESTNET = checkpoints return dump, log, json.dumps(raw_transactions, indent=4)
def run_scenario(scenario): """Execute a scenario for integration test, returns a dump of the db, a json with raw transactions and the full log.""" server.initialise(database_file=':memory:', testnet=True, **COUNTERPARTYD_OPTIONS) config.PREFIX = b'TESTXXXX' util.FIRST_MULTISIG_BLOCK_TESTNET = 1 checkpoints = dict(check.CHECKPOINTS_TESTNET) check.CHECKPOINTS_TESTNET = {} logger = logging.getLogger() logger.setLevel(logging.DEBUG) logger_buff = io.StringIO() handler = logging.StreamHandler(logger_buff) handler.setLevel(logging.DEBUG) formatter = logging.Formatter('%(message)s') handler.setFormatter(formatter) logger.addHandler(handler) requests_log = logging.getLogger("requests") requests_log.setLevel(logging.WARNING) asyncio_log = logging.getLogger('asyncio') asyncio_log.setLevel(logging.ERROR) db = database.get_connection(read_only=False) initialise_db(db) raw_transactions = [] for tx in scenario: if tx[0] != 'create_next_block': mock_protocol_changes = tx[3] if len(tx) == 4 else {} with MockProtocolChangesContext(**(mock_protocol_changes or {})): module = sys.modules['counterpartylib.lib.messages.{}'.format(tx[0])] compose = getattr(module, 'compose') unsigned_tx_hex = transaction.construct(db, compose(db, *tx[1]), **tx[2]) raw_transactions.append({tx[0]: unsigned_tx_hex}) insert_raw_transaction(unsigned_tx_hex, db) else: create_next_block(db, block_index=config.BURN_START + tx[1], parse_block=tx[2] if len(tx) == 3 else True) dump = dump_database(db) log = logger_buff.getvalue() db.close() check.CHECKPOINTS_TESTNET = checkpoints return dump, log, json.dumps(raw_transactions, indent=4)
def check_outputs(tx_name, method, inputs, outputs, error, records, comment, mock_protocol_changes, server_db): """Check actual and expected outputs of a particular function.""" try: tested_module = sys.modules['counterpartylib.lib.{}'.format(tx_name)] except KeyError: # TODO: hack tested_module = sys.modules['counterpartylib.lib.messages.{}'.format(tx_name)] tested_method = getattr(tested_module, method) with MockProtocolChangesContext(**(mock_protocol_changes or {})): test_outputs = None if error is not None: with pytest.raises(error[0]) as exception: test_outputs = exec_tested_method(tx_name, method, tested_method, inputs, server_db) else: test_outputs = exec_tested_method(tx_name, method, tested_method, inputs, server_db) if pytest.config.option.gentxhex and method == 'compose': print('') tx_params = { 'encoding': 'multisig' } if tx_name == 'order' and inputs[1]=='BTC': print('give btc') tx_params['fee_provided'] = DP['fee_provided'] unsigned_tx_hex = transaction.construct(server_db, test_outputs, **tx_params) print(tx_name) print(unsigned_tx_hex) if outputs is not None: try: assert outputs == test_outputs except AssertionError: if pytest.config.getoption('verbose') >= 2: msg = "expected outputs don't match test_outputs:\noutputs=\n" + pprint.pformat(outputs) + "\ntest_outputs=\n" + pprint.pformat(test_outputs) else: msg = "expected outputs don't match test_outputs: outputs=%s test_outputs=%s" % (outputs, test_outputs) raise Exception(msg) if error is not None: assert str(exception.value) == error[1] if records is not None: for record in records: check_record(record, server_db)
def check_outputs(tx_name, method, inputs, outputs, error, records, counterpartyd_db): """Check actual and expected outputs of a particular function.""" try: tested_module = sys.modules['counterpartylib.lib.{}'.format(tx_name)] except KeyError: # TODO: hack tested_module = sys.modules['counterpartylib.lib.messages.{}'.format( tx_name)] tested_method = getattr(tested_module, method) test_outputs = None if error is not None: with pytest.raises(error[0]) as exception: test_outputs = exec_tested_method(tx_name, method, tested_method, inputs, counterpartyd_db) else: test_outputs = exec_tested_method(tx_name, method, tested_method, inputs, counterpartyd_db) if pytest.config.option.gentxhex and method == 'compose': print('') tx_params = {'encoding': 'multisig'} if tx_name == 'order' and inputs[1] == 'BTC': print('give btc') tx_params['fee_provided'] = DP['fee_provided'] unsigned_tx_hex = transaction.construct(counterpartyd_db, test_outputs, **tx_params) print(tx_name) print(unsigned_tx_hex) if outputs is not None: assert outputs == test_outputs if error is not None: assert str(exception.value) == error[1] if records is not None: for record in records: check_record(record, counterpartyd_db)
def compose_transaction( db, name, params, encoding='auto', fee_per_kb=None, estimate_fee_per_kb=None, estimate_fee_per_kb_conf_target=config.ESTIMATE_FEE_CONF_TARGET, estimate_fee_per_kb_mode=config.ESTIMATE_FEE_MODE, regular_dust_size=config.DEFAULT_REGULAR_DUST_SIZE, multisig_dust_size=config.DEFAULT_MULTISIG_DUST_SIZE, op_return_value=config.DEFAULT_OP_RETURN_VALUE, pubkey=None, allow_unconfirmed_inputs=False, fee=None, fee_provided=0, unspent_tx_hash=None, custom_inputs=None, dust_return_pubkey=None, disable_utxo_locks=False, extended_tx_info=False, p2sh_source_multisig_pubkeys=None, p2sh_source_multisig_pubkeys_required=None, p2sh_pretx_txid=None, old_style_api=True, segwit=False): """Create and return a transaction.""" # Get provided pubkeys. if type(pubkey) == str: provided_pubkeys = [pubkey] elif type(pubkey) == list: provided_pubkeys = pubkey elif pubkey == None: provided_pubkeys = [] else: assert False # Get additional pubkeys from `source` and `destination` params. # Convert `source` and `destination` to pubkeyhash form. for address_name in ['source', 'destination']: if address_name in params: address = params[address_name] if isinstance(address, list): """pubkey_list = [] for iaddr in address: provided_pubkeys += script.extract_pubkeys(iaddr) pubkey_list.append(script.make_pubkeyhash(iaddr)) params[address_name] = pubkey_list""" else: provided_pubkeys += script.extract_pubkeys(address) params[address_name] = script.make_pubkeyhash(address) # Check validity of collected pubkeys. for pubkey in provided_pubkeys: if not script.is_fully_valid(binascii.unhexlify(pubkey)): raise script.AddressError('invalid public key: {}'.format(pubkey)) compose_method = sys.modules['counterpartylib.lib.messages.{}'.format( name)].compose compose_params = inspect.getargspec(compose_method)[0] missing_params = [ p for p in compose_params if p not in params and p != 'db' ] for param in missing_params: params[param] = None # dont override fee_per_kb if specified if fee_per_kb is not None: estimate_fee_per_kb = False else: fee_per_kb = config.DEFAULT_FEE_PER_KB if 'extended_tx_info' in params: extended_tx_info = params['extended_tx_info'] del params['extended_tx_info'] if 'old_style_api' in params: old_style_api = params['old_style_api'] del params['old_style_api'] if 'segwit' in params: segwit = params['segwit'] del params['segwit'] tx_info = compose_method(db, **params) return transaction.construct( db, tx_info, encoding=encoding, fee_per_kb=fee_per_kb, estimate_fee_per_kb=estimate_fee_per_kb, estimate_fee_per_kb_conf_target=estimate_fee_per_kb_conf_target, regular_dust_size=regular_dust_size, multisig_dust_size=multisig_dust_size, op_return_value=op_return_value, provided_pubkeys=provided_pubkeys, allow_unconfirmed_inputs=allow_unconfirmed_inputs, exact_fee=fee, fee_provided=fee_provided, unspent_tx_hash=unspent_tx_hash, custom_inputs=custom_inputs, dust_return_pubkey=dust_return_pubkey, disable_utxo_locks=disable_utxo_locks, extended_tx_info=extended_tx_info, p2sh_source_multisig_pubkeys=p2sh_source_multisig_pubkeys, p2sh_source_multisig_pubkeys_required= p2sh_source_multisig_pubkeys_required, p2sh_pretx_txid=p2sh_pretx_txid, old_style_api=old_style_api, segwit=segwit)
def construct_tx(db, source, destination, disable_utxo_locks=False): tx_info = send.compose(db, source, destination, 'XCP', 1) return transaction.construct(db, tx_info, disable_utxo_locks=disable_utxo_locks)