def test_multisig(self, unsigned_pair, signed1_pair, fully_signed_pair,
                      signed2_pair):
        unsigned_hex, unsigned_json = unsigned_pair
        signed1_hex, signed1_json = signed1_pair
        fully_signed_hex, fully_signed_json = fully_signed_pair
        signed2_hex, signed2_json = signed2_pair

        tx = Transaction.from_extended_bytes(bytes.fromhex(unsigned_hex))

        keystore1, keystore2 = self.multisig_keystores()

        assert json.dumps(tx.to_dict()) == unsigned_json

        # Sign with keystore 1, then 2
        keystore1.sign_transaction(tx, "OLD")
        assert json.dumps(tx.to_dict()) == signed1_json

        keystore2.sign_transaction(tx, "BIP32")
        assert tx.serialize() == fully_signed_hex

        # Sign with keystore 2, then 1
        tx = Transaction.from_extended_bytes(bytes.fromhex(unsigned_hex))

        keystore2.sign_transaction(tx, "BIP32")
        assert json.dumps(tx.to_dict()) == signed2_json

        keystore1.sign_transaction(tx, "OLD")
        assert tx.serialize() == fully_signed_hex
        assert json.dumps(tx.to_dict()) == fully_signed_json
示例#2
0
    def test_multisig(self, unsigned_hex, signed1_hex, fully_signed_hex,
                      signed2_hex):
        tx = Transaction.from_hex(unsigned_hex)

        keystore1, keystore2 = self.multisig_keystores()

        # Check serializes the same
        assert tx.serialize() == unsigned_hex

        # Sign with keystore 1, then 2
        keystore1.sign_transaction(tx, None)
        result_hex = tx.serialize()
        assert tx.serialize() == signed1_hex

        keystore2.sign_transaction(tx, None)
        assert tx.serialize() == fully_signed_hex

        # Sign with keystore 2, then 1
        tx = Transaction.from_hex(unsigned_hex)

        keystore2.sign_transaction(tx, None)
        assert tx.serialize() == signed2_hex

        keystore1.sign_transaction(tx, None)
        assert tx.serialize() == fully_signed_hex
示例#3
0
    def sign_transaction(self, keystore: TrezorKeyStore, tx: Transaction,
                         xpub_path: Dict[str, str],
                         tx_context: TransactionContext) -> None:
        prev_txtypes: Dict[bytes, TransactionType] = {}
        for prev_tx_hash, prev_tx in tx_context.prev_txs.items():
            txtype = TransactionType()
            txtype.version = prev_tx.version
            txtype.lock_time = prev_tx.locktime
            txtype.inputs = self.tx_inputs(prev_tx, is_prev_tx=True)
            txtype.bin_outputs = [
                TxOutputBinType(amount=tx_output.value,
                                script_pubkey=bytes(tx_output.script_pubkey))
                for tx_output in prev_tx.outputs
            ]
            # Trezor tx hashes are same byte order as the reversed hex tx id.
            prev_trezor_tx_hash = bytes(reversed(prev_tx_hash))
            prev_txtypes[prev_trezor_tx_hash] = txtype

        client = self.get_client(keystore)
        inputs = self.tx_inputs(tx, xpub_path)
        outputs = self.tx_outputs(keystore, keystore.get_derivation(), tx)
        details = SignTx(lock_time=tx.locktime)
        signatures, _ = client.sign_tx(self.get_coin_name(),
                                       inputs,
                                       outputs,
                                       details=details,
                                       prev_txes=prev_txtypes)
        tx.update_signatures(signatures)
示例#4
0
 def input_script(self, txin, estimate_size=False):
     if txin['type'] == 'p2pkh':
         return Transaction.get_preimage_script(txin)
     if txin['type'] == 'p2sh':
         # Multisig verification has partial support, but is
         # disabled. This is the expected serialization though, so we
         # leave it here until we activate it.
         return '00' + push_script(Transaction.get_preimage_script(txin))
     raise Exception("unsupported type %s" % txin['type'])
    def test_add_transaction(self):
        cache = TxCache(self.store)

        tx = Transaction(tx_hex_1)
        cache.add_transaction(tx)
        self.assertTrue(cache.is_cached(tx.txid()))
        entry = cache.get_entry(tx.txid())
        self.assertEqual(TxFlags.HasByteData,
                         entry.flags & TxFlags.HasByteData)
        self.assertIsNotNone(entry.bytedata)
示例#6
0
 def sign_transaction(self, keystore: KeepKey_KeyStore, tx: Transaction,
                      xpub_path: Dict[str, str]) -> None:
     client = self.get_client(keystore)
     inputs = self.tx_inputs(tx, xpub_path)
     outputs = self.tx_outputs(keystore, keystore.get_derivation(), tx)
     signatures = client.sign_tx(self.get_coin_name(client),
                                 inputs,
                                 outputs,
                                 lock_time=tx.locktime)[0]
     tx.update_signatures(signatures)
示例#7
0
 def input_script(self, txin, estimate_size=False):
     type_ = txin.type()
     if type_ == ScriptType.P2PKH:
         return Transaction.get_preimage_script(txin)
     if type_ == ScriptType.MULTISIG_P2SH:
         # Multisig verification has partial support, but is
         # disabled. This is the expected serialization though, so we
         # leave it here until we activate it.
         return '00' + push_script(Transaction.get_preimage_script(txin))
     raise RuntimeError(f'unsupported type {type_}')
    async def test_broadcast_good_response(self, monkeypatch, cli):
        monkeypatch.setattr(self.rest_server, '_get_account',
                            _fake_get_account_succeeded)
        monkeypatch.setattr(self.rest_server.app_state.app,
                            '_create_transaction',
                            _fake_create_transaction_succeeded)
        monkeypatch.setattr(self.rest_server, '_broadcast_transaction',
                            _fake_broadcast_tx)
        monkeypatch.setattr(
            self.rest_server.app_state.app, 'get_and_set_frozen_utxos_for_tx',
            self.rest_server._fake_get_and_set_frozen_utxos_for_tx)
        monkeypatch.setattr(self.rest_server, 'send_request',
                            self.rest_server._fake_send_request)

        # mock request
        network = "test"
        wallet_name = "wallet_file1.sqlite"
        index = "1"
        resp = await cli.request(
            path=f"/v1/{network}/dapp/wallets/{wallet_name}/"
            f"{index}/txs/broadcast",
            method='post',
            json={"rawtx": rawtx})
        # check
        tx = Transaction.from_hex(rawtx)
        expected_json = {"value": {"txid": tx.txid()}}
        assert resp.status == 200, await resp.read()
        response = await resp.read()
        assert json.loads(response) == expected_json
def _fake_create_transaction_succeeded(file_id, message_bytes, child_wallet,
                                       password,
                                       require_confirmed) -> Tuple[Any, set]:
    # Todo - test _create_transaction separately
    tx = Transaction.from_hex(rawtx)
    frozen_utxos = set([])
    return tx, frozen_utxos
示例#10
0
    async def test_create_and_broadcast_good_response(self, monkeypatch, cli):

        monkeypatch.setattr(self.rest_server, '_get_account',
                            _fake_get_account_succeeded)
        monkeypatch.setattr(self.rest_server.app_state.app, '_create_transaction',
                            _fake_create_transaction_succeeded)
        monkeypatch.setattr(self.rest_server, '_broadcast_transaction',
                            _fake_broadcast_tx)
        monkeypatch.setattr(self.rest_server.app_state.async_, 'spawn',
                            _fake_spawn)
        monkeypatch.setattr(self.rest_server.app_state.async_, 'spawn',
                            _fake_spawn)
        monkeypatch.setattr(self.rest_server.app_state.app, 'get_and_set_frozen_utxos_for_tx',
                            self.rest_server._fake_get_and_set_frozen_utxos_for_tx)
        monkeypatch.setattr(self.rest_server, 'send_request',
                            self.rest_server._fake_send_request)


        # mock request
        network = "test"
        wallet_name = "wallet_file1.sqlite"
        index = "1"
        password = "******"
        resp = await cli.request(path=f"/v1/{network}/dapp/wallets/{wallet_name}/"
                                      f"{index}/txs/create_and_broadcast",
                                 method='post',
                                 json={"outputs": [P2PKH_OUTPUT],
                                       "password": password})
        # check
        expected_json = {'txid': Transaction.from_hex(rawtx).txid()}
        assert resp.status == 200, await resp.read()
        response = await resp.read()
        assert json.loads(response) == expected_json
示例#11
0
    def test_tx_unsigned(self):
        tx = Transaction.from_hex(unsigned_blob)
        assert tx.version == 1
        assert len(tx.inputs) == 1
        txin = tx.inputs[0]
        assert txin.prev_hash.hex(
        ) == '49f35e43fefd22d8bb9e4b3ff294c6286154c25712baf6ab77b646e5074d6aed'
        assert txin.prev_idx == 1
        assert txin.script_sig.to_hex(
        ) == '01ff4c53ff0488b21e0000000000000000004f130d773e678a58366711837ec2e33ea601858262f8eaef246a7ebd19909c9a03c3b30e38ca7d797fee1223df1c9827b2a9f3379768f520910260220e0560014600002300'
        assert txin.sequence == 4294967294
        assert txin.value == 20112600
        assert txin.signatures == [NO_SIGNATURE]
        assert txin.x_pubkeys == [
            XPublicKey(
                'ff0488b21e0000000000000000004f130d773e678a58366711837ec2e33ea601858262f8eaef246a7ebd19909c9a03c3b30e38ca7d797fee1223df1c9827b2a9f3379768f520910260220e0560014600002300'
            )
        ]
        assert txin.address == address_from_string(
            '13Vp8Y3hD5Cb6sERfpxePz5vGJizXbWciN')
        assert txin.threshold == 1
        assert tx.outputs == [
            TxOutput(
                20112408,
                address_from_string(
                    '1MYXdf4moacvaEKZ57ozerpJ3t9xSeN6LK').to_script())
        ]
        assert tx.locktime == 507231

        assert tx.as_dict() == {'hex': unsigned_blob, 'complete': False}
示例#12
0
    async def broadcast(self, request):
        """Broadcast a rawtx (hex string) to the network. """
        try:
            required_vars = [VNAME.WALLET_NAME, VNAME.ACCOUNT_ID, VNAME.RAWTX]
            vars = await self.argparser(request, required_vars=required_vars)
            wallet_name = vars[VNAME.WALLET_NAME]
            index = vars[VNAME.ACCOUNT_ID]
            rawtx = vars[VNAME.RAWTX]

            account = self._get_account(wallet_name, index)
            tx = Transaction.from_hex(rawtx)
            self.raise_for_duplicate_tx(tx)
            frozen_utxos = self.app_state.app.get_and_set_frozen_utxos_for_tx(
                tx, account)
            result = await self._broadcast_transaction(rawtx, tx.hash(),
                                                       account)
            self.prev_transaction = result
            response = {"value": {"txid": result}}
            return good_response(response)
        except Fault as e:
            return fault_to_http_response(e)
        except aiorpcx.jsonrpc.RPCError as e:
            account.set_frozen_coin_state(frozen_utxos, False)
            self.remove_signed_transaction(tx, account)
            return fault_to_http_response(
                Fault(Errors.AIORPCX_ERROR_CODE, e.message))
示例#13
0
 def test_update_signatures(self):
     signed_tx = Tx.from_hex(signed_tx_3)
     sigs = [next(input.script_sig.ops())[:-1] for input in signed_tx.inputs]
     tx = Transaction.from_extended_bytes(bytes.fromhex(unsigned_tx))
     tx.update_signatures(sigs)
     assert tx.is_complete()
     assert tx.txid() == "b83acf939a92c420d0cb8d45d5d4dfad4e90369ebce0f49a45808dc1b41259b0"
    def test_tx_unsigned(self):
        tx = Transaction.from_extended_bytes(bytes.fromhex(unsigned_blob))
        assert tx.version == 1
        assert len(tx.inputs) == 1
        txin = tx.inputs[0]
        assert txin.prev_hash.hex(
        ) == '49f35e43fefd22d8bb9e4b3ff294c6286154c25712baf6ab77b646e5074d6aed'
        assert txin.prev_idx == 1
        assert txin.script_sig.to_hex(
        ) == '01ff4c53ff0488b21e0000000000000000004f130d773e678a58366711837ec2e33ea601858262f8eaef246a7ebd19909c9a03c3b30e38ca7d797fee1223df1c9827b2a9f3379768f520910260220e0560014600002300'
        assert txin.sequence == 4294967294
        assert txin.value == 20112600
        assert txin.signatures == [NO_SIGNATURE]
        assert txin.x_pubkeys == [
            XPublicKey.from_hex(
                'ff0488b21e0000000000000000004f130d773e678a58366711837ec2e33ea601858262f8eaef246a7ebd19909c9a03c3b30e38ca7d797fee1223df1c9827b2a9f3379768f520910260220e0560014600002300'
            )
        ]
        assert txin.threshold == 1
        assert (tx.outputs[0].value == 20112408 and tx.outputs[0].script_pubkey == \
            address_from_string('1MYXdf4moacvaEKZ57ozerpJ3t9xSeN6LK').to_script())
        assert tx.locktime == 507231

        assert json.dumps(
            tx.to_dict()
        ) == '{"version": 1, "hex": "010000000149f35e43fefd22d8bb9e4b3ff294c6286154c25712baf6ab77b646e5074d6aed010000002401ff2103b5bbebceeb33c1b61f649596b9c3611c6b2853a1f6b48bce05dd54f667fa2166feffffff0118e43201000000001976a914e158fb15c888037fdc40fb9133b4c1c3c688706488ac5fbd0700", "complete": false, "inputs": [{"script_type": 2, "threshold": 1, "value": 20112600, "signatures": ["ff"], "x_pubkeys": [{"bip32_xpub": "xpub661MyMwAqRbcFL6WFqND2XM2w1EfpBwFfhsSUcw9xDR3nH8eYLv4z4HAhxv5zkqjHojWsPYK1ZSK7yCr8fZ9iWU6D361G2ryv5UgsKjbeDq", "derivation_path": [0, 35]}]}]}'
示例#15
0
def get_small_tx() -> Transaction:
    path = Path(dirname(
        os.path.realpath(__file__))).joinpath("data/transactions/hello.txt")
    with open(path, "r") as f:
        rawtx = f.read()
    tx = Transaction.from_hex(rawtx)
    return tx
示例#16
0
 def sign_tx(self, unsigned_tx_hex, priv_keys):
     keypairs = {XPublicKey.from_hex(priv_key.public_key.to_hex()):
                 (priv_key.to_bytes(), priv_key.is_compressed())
                 for priv_key in priv_keys}
     tx = Transaction.from_extended_bytes(bytes.fromhex(unsigned_tx_hex))
     tx.sign(keypairs)
     return tx
示例#17
0
    def maybe_send_invoice_payment(self, tx: Transaction) -> bool:
        pr = self._payment_request
        if pr:
            tx_hash = tx.hash()
            invoice_id = pr.get_id()

            # TODO: Remove the dependence of broadcasting a transaction to pay an invoice on that
            # invoice being active in the send tab. Until then we assume that broadcasting a
            # transaction that is not related to the active invoice and it's repercussions, has
            # been confirmed by the appropriate calling logic. Like `confirm_broadcast_transaction`
            # in the main window logic.
            invoice_row = self._account.invoices.get_invoice_for_id(invoice_id)
            if tx_hash != invoice_row.tx_hash:
                # Calling logic should have detected this and warned/confirmed with the user.
                return True

            if pr.has_expired():
                pr.error = _("The invoice has expired")
                self.payment_request_error_signal.emit(invoice_id, tx_hash)
                return False

            if not pr.send_payment(self._account, str(tx)):
                self.payment_request_error_signal.emit(invoice_id, tx_hash)
                return False

            self._account.invoices.set_invoice_paid(invoice_id)

            self._payment_request = None
            # On success we broadcast as well, but it is assumed that the merchant also
            # broadcasts.
        return True
    def test_add_transaction_update(self):
        cache = TransactionCache(self.store)

        tx = Transaction.from_hex(tx_hex_1)
        data = [
            tx.hash(),
            TxData(height=1295924,
                   position=4,
                   fee=None,
                   date_added=1,
                   date_updated=1), None, TxFlags.Unset, None
        ]
        with SynchronousWriter() as writer:
            cache.add([data], completion_callback=writer.get_callback())
            assert writer.succeeded()

        entry = cache.get_entry(tx.hash())
        assert entry is not None
        assert TxFlags.Unset == entry.flags & TxFlags.STATE_MASK

        with SynchronousWriter() as writer:
            cache.add_transaction(tx,
                                  TxFlags.StateCleared,
                                  completion_callback=writer.get_callback())
            assert writer.succeeded()

        tx_hash = tx.hash()
        entry = cache.get_entry(tx_hash)
        assert entry is not None
        assert cache.have_transaction_data_cached(tx_hash)
        assert TxFlags.StateCleared == entry.flags & TxFlags.StateCleared
示例#19
0
    def do_send(self, window: 'ElectrumWindow', account: AbstractAccount,
                tx: Transaction) -> None:
        def on_done(window, future):
            try:
                future.result()
            except Exception as exc:
                window.on_exception(exc)
            else:
                window.show_message('\n'.join((
                    _("Your transaction was sent to the cosigning pool."),
                    _("Open your cosigner wallet to retrieve it."),
                )))

        def send_message():
            server.put(item.keyhash_hex, message)

        account_id = account.get_id()
        for item in self._items:
            if self._is_theirs(window, account_id, item, tx):
                raw_tx_bytes = json.dumps(tx.to_dict()).encode()
                public_key = PublicKey.from_bytes(item.pubkey_bytes)
                message = public_key.encrypt_message_to_base64(raw_tx_bytes)
                WaitingDialog(item.window,
                              _('Sending transaction to cosigning pool...'),
                              send_message,
                              on_done=partial(on_done, item.window))
示例#20
0
 def show_send_to_cosigner_button(self, account: AbstractAccount,
                                  tx: Transaction) -> bool:
     if tx.is_complete() or account.can_sign(tx):
         return False
     account_id = account.get_id()
     return any(
         self._is_theirs(account_id, item, tx) for item in self._items)
 def test_txid_p2sh_to_p2sh(self):
     # Note the public keys in this transaction are not sorted.  This also tests we do
     # not sort them.
     tx = Transaction.from_hex(
         '01000000018695eef2250b3a3b6ef45fe065e601610e69dd7a56de742092d40e6276e6c9ec00000000fdfd000047304402203199bf8e49f7203e8bcbfd754aa356c6ba61643a3490f8aef3888e0aaa7c048c02201e7180bfd670f4404e513359b4020fbc85d6625e3e265e0c357e8611f11b83e401483045022100e60f897db114679f9a310a032a22e9a7c2b8080affe2036c480ff87bf6f45ada02202dbd27af38dd97d418e24d89c3bb7a97e359dd927c1094d8c9e5cac57df704fb014c69522103adc563b9f5e506f485978f4e913c10da208eac6d96d49df4beae469e81a4dd982102c52bc9643a021464a31a3bfa99cfa46afaa4b3acda31e025da204b4ee44cc07a2103a1c8edcc3310b3d7937e9e4179e7bd9cdf31c276f985f4eb356f21b874225eb153aeffffffff02b8ce05000000000017a9145c9c158430b7b79c3ad7ef9bdf981601eda2412d87b82400000000000017a9146bf3ff89019ecc5971a39cdd4f1cabd3b647ad5d8700000000'
     )
     assert '2caab5a11fa1ec0f5bb014b8858d00fecf2c001e15d22ad04379ad7b36fef305' == tx.txid(
     )
示例#22
0
 def test_fd_read_write(self):
     tx_hex = (
         '0100000001de8ead15a3044065ed8274b79af5fe7f860f5a026c241e9dd93dd3ce26208aeb010000001'
         'd01ff1afd76a9148c16fd67cdf85cdd2b7686081152424159c3eb3388acfeffffffb06eb70000000000'
         '01f06db700000000001976a9148c16fd67cdf85cdd2b7686081152424159c3eb3388ac7ce40800'
     )
     tx = Transaction.from_hex(tx_hex)
     assert tx.serialize() == tx_hex
示例#23
0
    def broadcast_transaction(self, tx_hex: Optional[str]=None, wallet_name: Optional[str]=None,
                              wallet_memo: Optional[str]=None) -> str:
        wallet = None
        if wallet_name and wallet_memo:
            wallet = self._get_wallet(wallet_name)

        tx = Transaction(tx_hex)
        try:
            tx_id = app_state.daemon.network.broadcast_transaction_and_wait(tx)
        except aiorpcx.jsonrpc.RPCError as e:
            if e.code == 1 and e.message.find("too-long-mempool-chain") != -1:
                return jsonrpclib.Fault(100, "too-long-mempool-chain")
            print("raising rpc error", e.code, e.message)
            raise e
        if tx.is_complete() and wallet_name and wallet_memo:
            wallet.set_label(tx_id, wallet_memo)
        return tx_id
示例#24
0
 def show_send_to_cosigner_button(self, window: 'ElectrumWindow', account: AbstractAccount,
         tx: Transaction) -> bool:
     if window.network is None:
         return False
     if tx.is_complete() or account.can_sign(tx):
         return False
     account_id = account.get_id()
     return any(self._is_theirs(window, account_id, item, tx) for item in self._items)
示例#25
0
    def _sign_tx_and_broadcast_if_complete(self, amount: int, tx: Transaction,
                                           tx_desc: str) -> None:
        # confirmation dialog
        fee = tx.get_fee()

        msg = []
        if fee < round(tx.estimated_size() * 0.5):
            msg.append(
                _('Warning') + ': ' +
                _('The fee is less than 500 sats/kb. It may take a very long time to confirm.'
                  ))
        msg.append("")
        msg.append(_("Enter your password to proceed"))

        password = self._main_window.password_dialog(
            '\n'.join(msg),
            fields=[
                (_("Amount to send"),
                 QLabel(app_state.format_amount_and_units(amount))),
                (_("Mining fee"),
                 QLabel(app_state.format_amount_and_units(fee))),
            ])
        if not password:
            return

        def sign_done(success: bool) -> None:
            if success:
                if not tx.is_complete():
                    self._main_window.show_transaction(
                        self._account, tx, pr=self._payment_request)
                    self.clear()
                    return

                self._main_window.broadcast_transaction(
                    self._account, tx, tx_desc)

        tx_context: Optional[TransactionContext] = None
        if self._payment_request is not None:
            tx_context = TransactionContext(
                invoice_id=self._payment_request.get_id())

        self._main_window.sign_tx_with_password(tx,
                                                sign_done,
                                                password,
                                                tx_context=tx_context)
示例#26
0
    def remove_signed_transaction(self, tx: Transaction, wallet: AbstractAccount):
        # must remove signed transactions after a failed broadcast attempt (to unlock utxos)
        # if it's a re-broadcast attempt (same txid) and we already have a StateDispatched or
        # StateCleared transaction then *no deletion* should occur
        tx_hash = tx.hash()
        signed_tx = wallet.get_transaction(tx_hash, flags=TxFlags.StateSigned)

        if signed_tx:
            wallet.delete_transaction(tx_hash)
示例#27
0
 def test_fd_read_write(self):
     tx_hex = ('010000000111111111111111111111111111111111111111111111111111111111111111111b'
         '000000ec0001ff483045022100ae42f172f722ac2392ef3e5958d78bbca1ebedbce47eff27ba66345b'
         'e781c46f02207c9ab6ff496791bf2e56300ff4621beaec6ccdd3639e460612569c6e0407e09a414c9e'
         '5245fe84717a26df3332b129e59faaab25c11752277bc55c07d8724e1660e63b862d00b41d3db01e29'
         'ed54ca83300eb73d82b5381536298f40fdad8c1e307b66cf39a9000000004c53ff0488b21e00000000'
         '0000000000f79d7a4d3ea07099f09fbf35c3103908cbb4b1f30e8602a06ffbdbb213d0025602e9aa22'
         'cc7106abab85e4c41f18f030c370213769c18d6754f3d0584e69a7fa120000000052aeffffffffb414'
         '0000000000000188130000000000001976a914000000000000000000000000000000000000000088ac'
         '00000000')
     tx = Transaction.from_extended_bytes(bytes.fromhex(tx_hex))
     # We do not serialize the old extended byte format anymore.
     assert tx.serialize() != tx_hex
示例#28
0
    def test_get_unverified_entries_too_high(self):
        cache = TransactionCache(self.store)

        tx_1 = Transaction.from_hex(tx_hex_1)
        tx_hash_1 = tx_1.hash()
        data = TxData(height=11, position=22, date_added=1, date_updated=1)
        with SynchronousWriter() as writer:
            cache.add([ (tx_hash_1, data, tx_1, TxFlags.StateSettled, None) ],
                completion_callback=writer.get_callback())
            assert writer.succeeded()

        results = cache.get_unverified_entries(100)
        assert 0 == len(results)
示例#29
0
    def test_add_transaction(self):
        cache = TransactionCache(self.store)

        tx = Transaction.from_hex(tx_hex_1)
        tx_hash = tx.hash()
        with SynchronousWriter() as writer:
            cache.add_transaction(tx_hash, tx, completion_callback=writer.get_callback())
            assert writer.succeeded()

        assert cache.is_cached(tx_hash)
        entry = cache.get_entry(tx_hash)
        assert TxFlags.HasByteData == entry.flags & TxFlags.HasByteData
        assert cache.have_transaction_data_cached(tx_hash)
示例#30
0
    def test_add_transaction_update(self):
        cache = TxCache(self.store)

        tx = Transaction(tx_hex_1)
        data = [
            tx.txid(),
            TxData(height=1295924, timestamp=1555296290, position=4, fee=None),
            None, TxFlags.StateCleared
        ]
        cache.add([data])
        entry = cache.get_entry(tx.txid())
        self.assertIsNotNone(entry)
        self.assertEqual(TxFlags.StateCleared,
                         entry.flags & TxFlags.StateCleared)

        cache.add_transaction(tx, TxFlags.StateSettled)

        entry = cache.get_entry(tx.txid())
        self.assertIsNotNone(entry)
        self.assertIsNotNone(entry.bytedata)
        self.assertEqual(TxFlags.StateSettled,
                         entry.flags & TxFlags.StateSettled)