コード例 #1
0
ファイル: segwit_test.py プロジェクト: tatdig/pycoin
 def check_bip143_tx(self, tx_u_hex, tx_s_hex, txs_out_value_scripthex_pair,
                     tx_in_count, tx_out_count, version, lock_time):
     tx_u = Tx.from_hex(tx_u_hex)
     tx_s = Tx.from_hex(tx_s_hex)
     txs_out = [
         TxOut(int(coin_value * 1e8), h2b(script_hex))
         for coin_value, script_hex in txs_out_value_scripthex_pair
     ]
     for tx in (tx_u, tx_s):
         self.assertEqual(len(tx.txs_in), tx_in_count)
         self.assertEqual(len(tx.txs_out), tx_out_count)
         self.assertEqual(tx.version, version)
         self.assertEqual(tx.lock_time, lock_time)
         tx.set_unspents(txs_out)
     self.check_unsigned(tx_u)
     self.check_signed(tx_s)
     tx_hex = tx_u.as_hex()
     self.assertEqual(tx_hex, tx_u_hex)
     tx_hex = tx_s.as_hex()
     self.assertEqual(tx_hex, tx_s_hex)
     tx_u_prime = self.unsigned_copy(tx_s)
     tx_hex = tx_u_prime.as_hex()
     self.assertEqual(tx_hex, tx_u_hex)
     self.assertEqual(b2h_rev(double_sha256(h2b(tx_s_hex))), tx_s.w_id())
     self.assertEqual(b2h_rev(double_sha256(h2b(tx_u_hex))), tx_u.w_id())
     self.assertEqual(b2h_rev(double_sha256(h2b(tx_u_hex))), tx_u.id())
     return tx_u, tx_s
コード例 #2
0
ファイル: segwit_test.py プロジェクト: Stevengu999/pycoin
 def check_bip143_tx(self, tx_u_hex, tx_s_hex, txs_out_value_scripthex_pair, tx_in_count, tx_out_count, version, lock_time):
     tx_u = Tx.from_hex(tx_u_hex)
     tx_s = Tx.from_hex(tx_s_hex)
     txs_out = [
         TxOut(int(coin_value * 1e8), h2b(script_hex)) for coin_value, script_hex in txs_out_value_scripthex_pair
     ]
     for tx in (tx_u, tx_s):
         self.assertEqual(len(tx.txs_in), tx_in_count)
         self.assertEqual(len(tx.txs_out), tx_out_count)
         self.assertEqual(tx.version, version)
         self.assertEqual(tx.lock_time, lock_time)
         tx.set_unspents(txs_out)
     self.check_unsigned(tx_u)
     self.check_signed(tx_s)
     tx_hex = tx_u.as_hex()
     self.assertEqual(tx_hex, tx_u_hex)
     tx_hex = tx_s.as_hex()
     self.assertEqual(tx_hex, tx_s_hex)
     tx_u_prime = self.unsigned_copy(tx_s)
     tx_hex = tx_u_prime.as_hex()
     self.assertEqual(tx_hex, tx_u_hex)
     self.assertEqual(b2h_rev(double_sha256(h2b(tx_s_hex))), tx_s.w_id())
     self.assertEqual(b2h_rev(double_sha256(h2b(tx_u_hex))), tx_u.w_id())
     self.assertEqual(b2h_rev(double_sha256(h2b(tx_u_hex))), tx_u.id())
     return tx_u, tx_s
コード例 #3
0
ファイル: Fetcher.py プロジェクト: Erkan-Yilmaz/pycoinnet
 def _fetch_loop(self, next_message, getdata_loop_future):
     try:
         while True:
             name, data = yield from next_message()
             ITEM_LOOKUP = dict(tx="tx",
                                block="block",
                                merkleblock="header")
             if name in ITEM_LOOKUP:
                 item = data[ITEM_LOOKUP[name]]
                 the_hash = item.hash()
                 TYPE_DB = {
                     "tx": ITEM_TYPE_TX,
                     "block": ITEM_TYPE_BLOCK,
                     "merkleblock": ITEM_TYPE_MERKLEBLOCK
                 }
                 the_type = TYPE_DB[name]
                 inv_item = InvItem(the_type, the_hash)
                 if name == "merkleblock":
                     txs = []
                     for h in data["tx_hashes"]:
                         name, data = yield from next_message()
                         if name != "tx":
                             logging.error(
                                 "insufficient tx messages after merkleblock message: missing %s",
                                 b2h_rev(h))
                             del self.futures[inv_item]
                             future.set_result(None)
                             break
                         tx = data["tx"]
                         if tx.hash() != h:
                             logging.error(
                                 "missing tx message after merkleblock message: missing %s",
                                 b2h_rev(h))
                             del self.futures[inv_item]
                             future.set_result(None)
                             break
                         txs.append(tx)
                     item.txs = txs
                 future = self.futures.get(inv_item)
                 if future:
                     del self.futures[inv_item]
                     if not future.done():
                         future.set_result(item)
                     else:
                         logging.info("got %s unsolicited", item.id())
             if name == "notfound":
                 for inv_item in data["items"]:
                     the_hash = inv_item.data
                     future = self.futures.get(inv_item)
                     if future:
                         del self.futures[inv_item]
                         future.set_result(None)
     except EOFError:
         getdata_loop_future.cancel()
コード例 #4
0
    def validate_unspents(self, tx_db):
        """
        Spendable objects returned from blockchain.info or
        similar services contain coin_value information that must be trusted
        on faith. Mistaken coin_value data can result in coins being wasted
        to fees.

        This function solves this problem by iterating over the incoming
        transactions, fetching them from the tx_db in full, and verifying
        that the coin_values are as expected.

        Returns the fee for this transaction. If any of the spendables set by
        tx.set_unspents do not match the authenticated transactions, a
        ValidationFailureError is raised.
        """
        tx_hashes = set((tx_in.previous_hash for tx_in in self.txs_in))

        # build a local copy of the DB
        tx_lookup = {}
        for h in tx_hashes:
            if h == ZERO32:
                continue
            the_tx = tx_db.get(h)
            if the_tx is None:
                raise KeyError("hash id %s not in tx_db" % b2h_rev(h))
            if the_tx.hash() != h:
                raise KeyError(
                    "attempt to load Tx %s yielded a Tx with id %s" %
                    (h2b_rev(h), the_tx.id()))
            tx_lookup[h] = the_tx

        for idx, tx_in in enumerate(self.txs_in):
            if tx_in.previous_hash == ZERO32:
                continue
            txs_out = tx_lookup[tx_in.previous_hash].txs_out
            if tx_in.previous_index > len(txs_out):
                raise BadSpendableError(
                    "tx_out index %d is too big for Tx %s" %
                    (tx_in.previous_index, b2h_rev(tx_in.previous_hash)))
            tx_out1 = txs_out[tx_in.previous_index]
            tx_out2 = self.unspents[idx]
            if tx_out1.coin_value != tx_out2.coin_value:
                raise BadSpendableError(
                    "unspents[%d] coin value mismatch (%d vs %d)" %
                    (idx, tx_out1.coin_value, tx_out2.coin_value))
            if tx_out1.script != tx_out2.script:
                raise BadSpendableError("unspents[%d] script mismatch!" % idx)

        return self.fee()
コード例 #5
0
ファイル: serialize.py プロジェクト: hfeeki/btctxstore
 def reformat(spendable):
     return {
         "txid": b2h_rev(spendable.tx_hash),
         "index": spendable.tx_out_index,
         "value": spendable.coin_value,
         "script": b2h(spendable.script),
     }
コード例 #6
0
ファイル: serialize_test.py プロジェクト: solar559/pycoin-1
 def test_h2b(self):
     h = "000102"
     b = b"\x00\x01\x02"
     self.assertEqual(h2b(h), b)
     self.assertEqual(b2h(b), h)
     self.assertEqual(h2b_rev(h), b[::-1])
     self.assertEqual(b2h_rev(b), "020100")
コード例 #7
0
 def electrumx_script_hash(self, bech32: bool = False) -> str:
     addr = self.bech32_p2wpkh_address() if bech32 \
         else self.p2sh_p2wpkh_address()  # type: str
     script = standard_tx_out_script(addr)  # type: bytes
     h = SHA256.new()
     h.update(script)
     return b2h_rev(h.digest())
コード例 #8
0
def dump_inputs(tx, network, verbose_signature, traceback_f,
                disassembly_level):
    for idx, tx_in in enumerate(tx.txs_in):
        if tx.is_coinbase():
            print("%4d: COINBASE  %12.5f mBTC" %
                  (idx, satoshi_to_mbtc(tx.total_in())))
            continue
        suffix = ""
        if tx.missing_unspent(idx):
            tx_out = None
            address = tx_in.address(ui_context=network.ui)
        else:
            tx_out = tx.unspents[idx]
            sig_result = " sig ok" if tx.is_signature_ok(
                idx, traceback_f=traceback_f) else " BAD SIG"
            suffix = " %12.5f mBTC %s" % (satoshi_to_mbtc(
                tx_out.coin_value), sig_result)
            address = network.ui.address_for_script(tx_out.puzzle_script())
        t = "%4d: %34s from %s:%-4d%s" % (idx, address,
                                          b2h_rev(tx_in.previous_hash),
                                          tx_in.previous_index, suffix)
        print(t.rstrip())
        if disassembly_level > 0:
            dump_disassembly(tx, idx, network.extras.annotate)

        if verbose_signature:
            dump_signatures(tx, tx_in, tx_out, idx, network, traceback_f)
コード例 #9
0
def dump_inputs(tx, netcode, verbose_signature, address_prefix, traceback_f,
                disassembly_level):
    def signature_for_hash_type_f(hash_type, script):
        return tx.signature_hash(script, idx, hash_type)

    for idx, tx_in in enumerate(tx.txs_in):
        if tx.is_coinbase():
            print("%4d: COINBASE  %12.5f mBTC" %
                  (idx, satoshi_to_mbtc(tx.total_in())))
            continue
        suffix = ""
        if tx.missing_unspent(idx):
            tx_out = None
            address = tx_in.bitcoin_address(address_prefix=address_prefix)
        else:
            tx_out = tx.unspents[idx]
            sig_result = " sig ok" if tx.is_signature_ok(
                idx, traceback_f=traceback_f) else " BAD SIG"
            suffix = " %12.5f mBTC %s" % (satoshi_to_mbtc(
                tx_out.coin_value), sig_result)
            address = tx_out.bitcoin_address(netcode=netcode)
        t = "%4d: %34s from %s:%-4d%s" % (idx, address,
                                          b2h_rev(tx_in.previous_hash),
                                          tx_in.previous_index, suffix)
        print(t.rstrip())
        if disassembly_level > 0:
            dump_disassembly(tx_in, tx_out, tx.lock_time,
                             signature_for_hash_type_f)

        if verbose_signature:
            dump_signatures(tx, tx_in, tx_out, idx, netcode, address_prefix,
                            traceback_f, disassembly_level)
コード例 #10
0
ファイル: proxy.py プロジェクト: nelisky/pycoin
 def query_links (self, proxy):
     if self.previous_hash != 0:
         tx = ProxyTx.from_txhash(proxy, b2h_rev(self.previous_hash), do_query_links=False)
         txout = tx.txs_out[self.previous_index]
         self._address = txout.address(addrversion=proxy.addrversion)
         self.coin_value = txout.coin_value
         self.is_shallow = False
コード例 #11
0
ファイル: tx.py プロジェクト: onestarshang/pycoin
def dump_inputs(tx, netcode, verbose_signature, address_prefix, traceback_f, disassembly_level):

    def signature_for_hash_type_f(hash_type, script):
        return tx.signature_hash(script, idx, hash_type)

    for idx, tx_in in enumerate(tx.txs_in):
        if tx.is_coinbase():
            print("%4d: COINBASE  %12.5f mBTC" % (idx, satoshi_to_mbtc(tx.total_in())))
            continue
        suffix = ""
        if tx.missing_unspent(idx):
            tx_out = None
            address = tx_in.bitcoin_address(address_prefix=address_prefix)
        else:
            tx_out = tx.unspents[idx]
            sig_result = " sig ok" if tx.is_signature_ok(idx, traceback_f=traceback_f) else " BAD SIG"
            suffix = " %12.5f mBTC %s" % (satoshi_to_mbtc(tx_out.coin_value), sig_result)
            address = tx_out.bitcoin_address(netcode=netcode)
        t = "%4d: %34s from %s:%-4d%s" % (idx, address, b2h_rev(tx_in.previous_hash),
                                          tx_in.previous_index, suffix)
        print(t.rstrip())
        if disassembly_level > 0:
            dump_disassembly(tx_in, tx_out, tx.lock_time, signature_for_hash_type_f)

        if verbose_signature:
            dump_signatures(tx, tx_in, tx_out, idx, netcode, address_prefix, traceback_f, disassembly_level)
コード例 #12
0
 def reformat(spendable):
     return {
         "txid": b2h_rev(spendable.tx_hash),
         "index": spendable.tx_out_index,
         "value": spendable.coin_value,
         "script": b2h(spendable.script)
     }
コード例 #13
0
ファイル: test_serialize.py プロジェクト: E-LLP/pycoin
 def test_h2b(self):
     h = "000102"
     b = b"\x00\x01\x02"
     self.assertEqual(h2b(h), b)
     self.assertEqual(b2h(b), h)
     self.assertEqual(h2b_rev(h), b[::-1])
     self.assertEqual(b2h_rev(b), "020100")
コード例 #14
0
ファイル: insight.py プロジェクト: Stevengu999/pycoin
 def tx_for_tx_hash(self, tx_hash):
     URL = "%s/api/tx/%s" % (self.base_url, b2h_rev(tx_hash))
     r = json.loads(urlopen(URL).read().decode("utf8"))
     tx = tx_from_json_dict(r)
     if tx.hash() == tx_hash:
         return tx
     return None
コード例 #15
0
ファイル: insight.py プロジェクト: NinjaDevelper/btctxstore
 def get_tx(self, tx_hash):
     URL = "%s/api/rawtx/%s" % (self.base_url, b2h_rev(tx_hash))
     r = json.loads(urlopen(URL).read().decode("utf8"))
     tx = Tx.tx_from_hex(r['rawtx'])
     if tx.hash() == tx_hash:
         return tx
     return None
コード例 #16
0
 def save_spendable(self, spendable):
     tx_hash = b2h_rev(spendable.tx_hash)
     script = b2h(spendable.script)
     c = self._exec_sql("insert or replace into Spendable values (?, ?, ?, ?, ?, ?, ?)", tx_hash,
                         spendable.tx_out_index, spendable.coin_value, script,
                         spendable.block_index_available, spendable.does_seem_spent,
                         spendable.block_index_spent)
コード例 #17
0
ファイル: blockexplorer.py プロジェクト: hfeeki/btctxstore
 def get_tx(self, tx_hash):
     url = "%s/rawtx/%s" % (self.base_url, b2h_rev(tx_hash))
     result = json.loads(urlopen(url).read().decode("utf8"))
     tx = Tx.from_hex(result["rawtx"])
     if tx.hash() == tx_hash:
         return tx
     return None
コード例 #18
0
ファイル: blockexplorer.py プロジェクト: StorjOld/btctxstore
 def get_tx(self, tx_hash):
     url = "%s/rawtx/%s" % (self.base_url, b2h_rev(tx_hash))
     result = json.loads(urlopen(url).read().decode("utf8"))
     tx = Tx.from_hex(result["rawtx"])
     if tx.hash() == tx_hash:
         return tx
     return None
コード例 #19
0
ファイル: insight.py プロジェクト: microfins/pycoin
 def tx_for_tx_hash(self, tx_hash):
     URL = "%s/api/tx/%s" % (self.base_url, b2h_rev(tx_hash))
     r = json.loads(urlopen(URL).read().decode("utf8"))
     tx = tx_from_json_dict(r)
     if tx.hash() == tx_hash:
         return tx
     return None
コード例 #20
0
ファイル: insight.py プロジェクト: hfeeki/btctxstore
 def get_tx(self, tx_hash):
     URL = "%s/api/rawtx/%s" % (self.base_url, b2h_rev(tx_hash))
     r = json.loads(urlopen(URL).read().decode("utf8"))
     tx = Tx.from_hex(r['rawtx'])
     if tx.hash() == tx_hash:
         return tx
     return None
コード例 #21
0
ファイル: blockr_io.py プロジェクト: Bluejudy/pycoin
def get_tx(tx_hash):
    """
    Get a Tx by its hash.
    """
    URL = "http://btc.blockr.io/api/v1/tx/raw/%s" % b2h_rev(tx_hash)
    r = json.loads(urlopen(URL).read().decode("utf8"))
    tx = Tx.parse(io.BytesIO(h2b(r.get("data").get("tx").get("hex"))))
    return tx
コード例 #22
0
ファイル: blockr_io.py プロジェクト: newexo/pycoin
def get_tx(tx_hash):
    """
    Get a Tx by its hash.
    """
    URL = "%s/tx/raw/%s" % (blockrendpoint.url, b2h_rev(tx_hash))
    r = json.loads(urlopen(URL).read().decode("utf8"))
    tx = Tx.parse(io.BytesIO(h2b(r.get("data").get("tx").get("hex"))))
    return tx
コード例 #23
0
def get_tx(tx_hash):
    """
    Get a Tx by its hash.
    """
    URL = "http://btc.blockr.io/api/v1/tx/raw/%s" % b2h_rev(tx_hash)
    r = json.loads(urlopen(URL).read().decode("utf8"))
    tx = Tx.parse(io.BytesIO(h2b(r.get("data").get("tx").get("hex"))))
    return tx
コード例 #24
0
 def tx_for_tx_hash(self, tx_hash):
     URL = "%s/getrawtransaction?txid=%s&decrypt=0" % (self.base_url,
                                                       b2h_rev(tx_hash))
     r = urlopen(URL).read().decode("utf8")
     tx = Tx.from_hex(r)
     if tx.hash() == tx_hash:
         return tx
     return None
コード例 #25
0
 def __str__(self):
     BLOCK = "Block"
     TX = "Tx"
     INV_TYPES = {0: "?", 1: TX, 2: BLOCK, 3: "Merkle", 1073741825: TX, 1073741826: BLOCK}
     idx = self.item_type
     if idx not in INV_TYPES.keys():
         idx = 0
     return "InvItem %s [%s]" % (INV_TYPES[idx], b2h_rev(self.data))
コード例 #26
0
ファイル: biteasy.py プロジェクト: acerix/doge-millionaire
def tx_for_tx_hash(tx_hash):
    URL = "https://api.biteasy.com/blockchain/v1/transactions/%s" % b2h_rev(tx_hash)
    r = Request(URL,
                headers={"content-type": "application/json", "accept": "*/*", "User-Agent": "curl/7.29.0" })
    d = urlopen(r).read()
    tx = json_to_tx(d.decode("utf8"))
    if tx.hash() == tx_hash:
        return tx
    return None
コード例 #27
0
ファイル: tx_db.py プロジェクト: Bluejudy/pycoin
 def put(self, tx):
     name = b2h_rev(tx.hash())
     if self.writable_cache_path:
         try:
             path = os.path.join(self.writable_cache_path, "%s_tx.bin" % name)
             with open(path, "wb") as f:
                 tx.stream(f)
         except IOError:
             pass
コード例 #28
0
ファイル: insight.py プロジェクト: xgess/btctxstore
 def confirms(self, txid):
     try:
         url = "%s/tx/%s" % (self.base_url, b2h_rev(txid))
         result = json.loads(urlopen(url).read().decode("utf8"))
         return result.get("confirmations", 0)
     except HTTPError as ex:
         if ex.code == 404:  # unpublished tx
             return None
         else:
             raise ex
コード例 #29
0
 def put(self, tx):
     name = b2h_rev(tx.hash())
     if self.writable_cache_path:
         try:
             path = os.path.join(self.writable_cache_path,
                                 "%s_tx.bin" % name)
             with open(path, "wb") as f:
                 tx.stream(f)
         except IOError:
             pass
コード例 #30
0
 def tx_for_tx_hash(self, tx_hash):
     """
     Get a Tx by its hash.
     """
     url = "%s/rawtx/%s" % (self.url, b2h_rev(tx_hash))
     d = urlopen(url).read()
     j = json.loads(d.decode("utf8"))
     tx = Tx.from_hex(j.get("rawtx", ""))
     if tx.hash() == tx_hash:
         return tx
コード例 #31
0
    def verify_tx_in(self, tx_in_idx, tx_out_script, expected_hash_type=None):
        tx_in = self.txs_in[tx_in_idx]

        def signature_for_hash_type_f(hash_type, script):
            return self.signature_hash(script, tx_in_idx, hash_type)

        if not tx_in.verify(
                tx_out_script, signature_for_hash_type_f, expected_hash_type, tx_version=self.version):
            raise ValidationFailureError(
                "just signed script Tx %s TransactionIn index %d did not verify" % (
                    b2h_rev(tx_in.previous_hash), tx_in_idx))
コード例 #32
0
def post_unpack_merkleblock(d, f):
    """
    A post-processing "post_unpack" to merkleblock messages.

    It validates the merkle proofs (throwing an exception if there's
    an error), and returns the list of transaction hashes in "tx_hashes".

    The transactions are supposed to be sent immediately after the merkleblock message.
    """
    level_widths = []
    count = d["total_transactions"]
    while count > 1:
        level_widths.append(count)
        count += 1
        count //= 2
    level_widths.append(1)
    level_widths.reverse()

    tx_acc = []
    flags = d["flags"]
    hashes = list(reversed(d["hashes"]))
    left_hash, flag_index = _recurse(level_widths, 0, 0, hashes, flags, 0,
                                     tx_acc)

    if len(hashes) > 0:
        raise ValueError("extra hashes: %s" % hashes)

    idx, r = divmod(flag_index - 1, 8)
    if idx != len(flags) - 1:
        raise ValueError("not enough flags consumed")

    if flags[idx] > (1 << (r + 1)) - 1:
        raise ValueError("unconsumed 1 flag bits set")

    if left_hash != d["header"].merkle_root:
        raise ValueError(
            "merkle root %s does not match calculated hash %s" %
            (b2h_rev(d["header"].merkle_root), b2h_rev(left_hash)))

    d["tx_hashes"] = tx_acc
    return d
コード例 #33
0
ファイル: blockcypher.py プロジェクト: tatdig/pycoin
 def tx_for_tx_hash(self, tx_hash):
     """
     returns the pycoin.tx object for tx_hash
     """
     try:
         url_append = "?token=%s&includeHex=true" % self.api_key
         url = self.base_url("txs/%s%s" % (b2h_rev(tx_hash), url_append))
         result = json.loads(urlopen(url).read().decode("utf8"))
         tx = Tx.parse(io.BytesIO(h2b(result.get("hex"))))
         return tx
     except:
         raise Exception
コード例 #34
0
ファイル: blockcypher.py プロジェクト: Stevengu999/pycoin
 def tx_for_tx_hash(self, tx_hash):
     """
     returns the pycoin.tx object for tx_hash
     """
     try:
         url_append = "?token=%s&includeHex=true" % self.api_key
         url = self.base_url("txs/%s%s" % (b2h_rev(tx_hash), url_append))
         result = json.loads(urlopen(url).read().decode("utf8"))
         tx = Tx.parse(io.BytesIO(h2b(result.get("hex"))))
         return tx
     except:
         raise Exception
コード例 #35
0
 def spendable_for_hash_index(self, tx_hash, tx_out_index):
     tx_hash_hex = b2h_rev(tx_hash)
     SQL = ("select coin_value, script, block_index_available, "
            "does_seem_spent, block_index_spent from Spendable where "
            "tx_hash = ? and tx_out_index = ?")
     c = self._exec_sql(SQL, tx_hash_hex, tx_out_index)
     r = c.fetchone()
     if r is None:
         return r
     return Spendable(coin_value=r[0], script=h2b(r[1]), tx_hash=tx_hash,
                      tx_out_index=tx_out_index, block_index_available=r[2],
                      does_seem_spent=r[3], block_index_spent=r[4])
コード例 #36
0
ファイル: block.py プロジェクト: lucayepa/pycoin
def dump_block(block, network):
    blob = stream_to_bytes(block.stream)
    print("%d bytes   block hash %s" % (len(blob), block.id()))
    print("version %d" % block.version)
    print("prior block hash %s" % b2h_rev(block.previous_block_hash))
    print("merkle root %s" % binascii.hexlify(block.merkle_root).decode("utf8"))
    print("timestamp %s" % datetime.datetime.utcfromtimestamp(block.timestamp).isoformat())
    print("difficulty %d" % block.difficulty)
    print("nonce %s" % block.nonce)
    print("%d transaction%s" % (len(block.txs), "s" if len(block.txs) != 1 else ""))
    for idx, tx in enumerate(block.txs):
        print("Tx #%d:" % idx)
        dump_tx(tx, netcode=network)
コード例 #37
0
def dump_block(block, network):
    blob = stream_to_bytes(block.stream)
    print("%d bytes   block hash %s" % (len(blob), block.id()))
    print("version %d" % block.version)
    print("prior block hash %s" % b2h_rev(block.previous_block_hash))
    print("merkle root %s" % b2h(block.merkle_root))
    print("timestamp %s" % datetime.datetime.utcfromtimestamp(block.timestamp).isoformat())
    print("difficulty %d" % block.difficulty)
    print("nonce %s" % block.nonce)
    print("%d transaction%s" % (len(block.txs), "s" if len(block.txs) != 1 else ""))
    for idx, tx in enumerate(block.txs):
        print("Tx #%d:" % idx)
        dump_tx(tx, network=network, verbose_signature=False, disassembly_level=0, do_trace=False, use_pdb=False)
コード例 #38
0
ファイル: util.py プロジェクト: superac22/micropayment-core
def load_tx(get_txs_func, rawtx):
    Tx.ALLOW_SEGWIT = False  # FIXME remove on next pycoin version
    tx = Tx.from_hex(rawtx)

    unspent_info = {}  # txid -> index
    for txin in tx.txs_in:
        unspent_info[b2h_rev(txin.previous_hash)] = txin.previous_index
    utxo_rawtxs = get_txs_func(list(unspent_info.keys()))

    for utxo_txid, utxo_rawtx in utxo_rawtxs.items():
        utxo_tx = Tx.from_hex(utxo_rawtx)
        prev_index = unspent_info[utxo_txid]
        tx.unspents.append(utxo_tx.txs_out[prev_index])
    return tx
コード例 #39
0
ファイル: Fetcher.py プロジェクト: E-LLP/pycoinnet
 def _fetch_loop(self, next_message, getdata_loop_future):
     try:
         while True:
             name, data = yield from next_message()
             ITEM_LOOKUP = dict(tx="tx", block="block", merkleblock="header")
             if name in ITEM_LOOKUP:
                 item = data[ITEM_LOOKUP[name]]
                 the_hash = item.hash()
                 TYPE_DB = {"tx": ITEM_TYPE_TX,
                            "block": ITEM_TYPE_BLOCK,
                            "merkleblock": ITEM_TYPE_MERKLEBLOCK}
                 the_type = TYPE_DB[name]
                 inv_item = InvItem(the_type, the_hash)
                 future = self.futures.get(inv_item)
                 if name == "merkleblock":
                     txs = []
                     for h in data["tx_hashes"]:
                         name, data = yield from next_message()
                         if name != "tx":
                             logging.error(
                                 "insufficient tx messages after merkleblock message: missing %s",
                                 b2h_rev(h))
                             del self.futures[inv_item]
                             future.set_result(None)
                             break
                         tx = data["tx"]
                         if tx.hash() != h:
                             logging.error(
                                 "missing tx message after merkleblock message: missing %s", b2h_rev(h))
                             del self.futures[inv_item]
                             future.set_result(None)
                             break
                         txs.append(tx)
                     item.txs = txs
                 if future is not None:
                     del self.futures[inv_item]
                     if not future.done():
                         future.set_result(item)
                     else:
                         logging.info("got %s unsolicited", item.id())
             if name == "notfound":
                 for inv_item in data["items"]:
                     the_hash = inv_item.data
                     future = self.futures.get(inv_item)
                     if future:
                         del self.futures[inv_item]
                         future.set_result(None)
     except EOFError:
         getdata_loop_future.cancel()
コード例 #40
0
def unspents_from_db(txs_in, ignore_missing=False):
    unspents = []
    for tx_in in txs_in:
        if tx_in.is_coinbase():
            unspents.append(None)
            continue
        tx = searchByHash(tx_in.previous_hash)
        if tx and tx.hash() == tx_in.previous_hash:
            unspents.append(tx.txs_out[tx_in.previous_index])
        elif ignore_missing:
            unspents.append(None)
        else:
            raise KeyError(
                "can't find tx_out for %s:%d" % (b2h_rev(tx_in.previous_hash), tx_in.previous_index))
    return unspents  
コード例 #41
0
ファイル: block.py プロジェクト: sky8273/pycoin
def dump_block(block, netcode=None):
    if netcode is None:
        netcode = get_current_netcode()
    blob = stream_to_bytes(block.stream)
    print("%d bytes   block hash %s" % (len(blob), block.id()))
    print("version %d" % block.version)
    print("prior block hash %s" % b2h_rev(block.previous_block_hash))
    print("merkle root %s" % b2h(block.merkle_root))
    print("timestamp %s" % datetime.datetime.utcfromtimestamp(block.timestamp).isoformat())
    print("difficulty %d" % block.difficulty)
    print("nonce %s" % block.nonce)
    print("%d transaction%s" % (len(block.txs), "s" if len(block.txs) != 1 else ""))
    for idx, tx in enumerate(block.txs):
        print("Tx #%d:" % idx)
        dump_tx(tx, netcode=netcode)
コード例 #42
0
ファイル: block.py プロジェクト: onestarshang/pycoin
def dump_block(block, netcode=None):
    if netcode is None:
        netcode = get_current_netcode()
    blob = stream_to_bytes(block.stream)
    print("%d bytes   block hash %s" % (len(blob), block.id()))
    print("version %d" % block.version)
    print("prior block hash %s" % b2h_rev(block.previous_block_hash))
    print("merkle root %s" % b2h(block.merkle_root))
    print("timestamp %s" % datetime.datetime.utcfromtimestamp(block.timestamp).isoformat())
    print("difficulty %d" % block.difficulty)
    print("nonce %s" % block.nonce)
    print("%d transaction%s" % (len(block.txs), "s" if len(block.txs) != 1 else ""))
    for idx, tx in enumerate(block.txs):
        print("Tx #%d:" % idx)
        dump_tx(tx, netcode=netcode, verbose_signature=False, disassembly_level=0, do_trace=False, use_pdb=False)
コード例 #43
0
def dump_tx(tx, netcode='BTC'):
    address_prefix = address_prefix_for_netcode(netcode)
    tx_bin = stream_to_bytes(tx.stream)
    print("Version: %2d  tx hash %s  %d bytes   " %
          (tx.version, tx.id(), len(tx_bin)))
    print("TxIn count: %d; TxOut count: %d" %
          (len(tx.txs_in), len(tx.txs_out)))
    if tx.lock_time == 0:
        meaning = "valid anytime"
    elif tx.lock_time < LOCKTIME_THRESHOLD:
        meaning = "valid after block index %d" % tx.lock_time
    else:
        when = datetime.datetime.utcfromtimestamp(tx.lock_time)
        meaning = "valid on or after %s utc" % when.isoformat()
    print("Lock time: %d (%s)" % (tx.lock_time, meaning))
    print("Input%s:" % ('s' if len(tx.txs_in) != 1 else ''))
    missing_unspents = tx.missing_unspents()
    for idx, tx_in in enumerate(tx.txs_in):
        if tx.is_coinbase():
            print("%4d: COINBASE  %12.5f mBTC" %
                  (idx, satoshi_to_mbtc(tx.total_in())))
        else:
            suffix = ""
            if tx.missing_unspent(idx):
                address = tx_in.bitcoin_address(address_prefix=address_prefix)
            else:
                tx_out = tx.unspents[idx]
                sig_result = " sig ok" if tx.is_signature_ok(
                    idx) else " BAD SIG"
                suffix = " %12.5f mBTC %s" % (satoshi_to_mbtc(
                    tx_out.coin_value), sig_result)
                address = tx_out.bitcoin_address(netcode=netcode)
            t = "%4d: %34s from %s:%-4d%s" % (idx, address,
                                              b2h_rev(tx_in.previous_hash),
                                              tx_in.previous_index, suffix)
            print(t.rstrip())
    print("Output%s:" % ('s' if len(tx.txs_out) != 1 else ''))
    for idx, tx_out in enumerate(tx.txs_out):
        amount_mbtc = satoshi_to_mbtc(tx_out.coin_value)
        address = tx_out.bitcoin_address(netcode=netcode) or "(unknown)"
        print("%4d: %34s receives %12.5f mBTC" % (idx, address, amount_mbtc))
    if not missing_unspents:
        print("Total input  %12.5f mBTC" % satoshi_to_mbtc(tx.total_in()))
    print("Total output %12.5f mBTC" % satoshi_to_mbtc(tx.total_out()))
    if not missing_unspents:
        print("Total fees   %12.5f mBTC" % satoshi_to_mbtc(tx.fee()))
コード例 #44
0
ファイル: insight.py プロジェクト: Stevengu999/pycoin
 def get_blockheader_with_transaction_hashes(self, block_hash):
     URL = "%s/api/block/%s" % (self.base_url, b2h_rev(block_hash))
     r = json.loads(urlopen(URL).read().decode("utf8"))
     version = r.get("version")
     previous_block_hash = h2b_rev(r.get("previousblockhash"))
     merkle_root = h2b_rev(r.get("merkleroot"))
     timestamp = r.get("time")
     difficulty = int(r.get("bits"), 16)
     nonce = int(r.get("nonce"))
     tx_hashes = [h2b_rev(tx_hash) for tx_hash in r.get("tx")]
     blockheader = BlockHeader(version, previous_block_hash, merkle_root, timestamp, difficulty, nonce)
     if blockheader.hash() != block_hash:
         return None, None
     calculated_hash = merkle(tx_hashes, double_sha256)
     if calculated_hash != merkle_root:
         return None, None
     blockheader.height = r.get("height")
     return blockheader, tx_hashes
コード例 #45
0
ファイル: insight.py プロジェクト: stafur/pycoin
 def get_blockheader_with_transaction_hashes(self, block_hash):
     URL = "%s/api/block/%s" % (self.base_url, b2h_rev(block_hash))
     r = json.loads(urlopen(URL).read().decode("utf8"))
     version = r.get("version")
     previous_block_hash = h2b_rev(r.get("previousblockhash"))
     merkle_root = h2b_rev(r.get("merkleroot"))
     timestamp = r.get("time")
     difficulty = int(r.get("bits"), 16)
     nonce = int(r.get("nonce"))
     tx_hashes = [h2b_rev(tx_hash) for tx_hash in r.get("tx")]
     blockheader = BlockHeader(version, previous_block_hash, merkle_root, timestamp, difficulty, nonce)
     if blockheader.hash() != block_hash:
         return None, None
     calculated_hash = merkle(tx_hashes, double_sha256)
     if calculated_hash != merkle_root:
         return None, None
     blockheader.height = r.get("height")
     return blockheader, tx_hashes
コード例 #46
0
ファイル: proxy.py プロジェクト: nelisky/pycoin
    def from_hex (klass, proxy, hexv):
        STANDARD_SCRIPT_OUT = "OP_DUP OP_HASH160 %s OP_EQUALVERIFY OP_CHECKSIG"
        tx = ProxyTx.parse(StringIO(binascii.unhexlify(hexv)))
        uto = []
        for txi in tx.txs_in:
            if proxy is None:
                pscript = ''
            else:
                thistx = proxy.getTx(b2h_rev(txi.previous_hash), shallow_txins=True)
                pscript = thistx.txs_out[txi.previous_index].script
            uto.append(UnsignedTxOut(txi.previous_hash, txi.previous_index, None, pscript))

        uti = []
        for txo in tx.txs_out:
            script_text = STANDARD_SCRIPT_OUT % b2h(txo.address_h160())
            script_bin = compile(script_text)
            uti.append(ProxyTxOut(txo.coin_value, script_bin))

        return klass(tx.version, uto, uti, tx.lock_time)
コード例 #47
0
    def test_block(self):
        expected_checksum = '0000000000089F7910F6755C10EA2795EC368A29B435D80770AD78493A6FECF1'.lower()

        block_data = h2b(
            "010000007480150B299A16BBCE5CCDB1D1BBC65CFC5893B01E6619107C552000000000"
            "007900A2B203D24C69710AB6A94BEB937E1B1ADD64C2327E268D8C3E5F8B41DBED8796"
            "974CED66471B204C324703010000000100000000000000000000000000000000000000"
            "00000000000000000000000000FFFFFFFF0804ED66471B024001FFFFFFFF0100F2052A"
            "010000004341045FEE68BAB9915C4EDCA4C680420ED28BBC369ED84D48AC178E1F5F7E"
            "EAC455BBE270DABA06802145854B5E29F0A7F816E2DF906E0FE4F6D5B4C9B92940E4F0"
            "EDAC000000000100000001F7B30415D1A7BF6DB91CB2A272767C6799D721A4178AA328"
            "E0D77C199CB3B57F010000008A4730440220556F61B84F16E637836D2E74B8CB784DE4"
            "0C28FE3EF93CCB7406504EE9C7CAA5022043BD4749D4F3F7F831AC696748AD8D8E79AE"
            "B4A1C539E742AA3256910FC88E170141049A414D94345712893A828DE57B4C2054E2F5"
            "96CDCA9D0B4451BA1CA5F8847830B9BE6E196450E6ABB21C540EA31BE310271AA00A49"
            "ED0BA930743D1ED465BAD0FFFFFFFF0200E1F505000000001976A914529A63393D63E9"
            "80ACE6FA885C5A89E4F27AA08988ACC0ADA41A000000001976A9145D17976537F30886"
            "5ED533CCCFDD76558CA3C8F088AC00000000010000000165148D894D3922EF5FFDA962"
            "BE26016635C933D470C8B0AB7618E869E3F70E3C000000008B48304502207F5779EBF4"
            "834FEAEFF4D250898324EB5C0833B16D7AF4C1CB0F66F50FCF6E85022100B78A65377F"
            "D018281E77285EFC31E5B9BA7CB7E20E015CF6B7FA3E4A466DD195014104072AD79E0A"
            "A38C05FA33DD185F84C17F611E58A8658CE996D8B04395B99C7BE36529CAB7606900A0"
            "CD5A7AEBC6B233EA8E0FE60943054C63620E05E5B85F0426FFFFFFFF02404B4C000000"
            "00001976A914D4CAA8447532CA8EE4C80A1AE1D230A01E22BFDB88AC8013A0DE010000"
            "001976A9149661A79AE1F6D487AF3420C13E649D6DF3747FC288AC00000000")

        # try to parse a block

        block = Block.parse(io.BytesIO(block_data))

        print(block)
        assert b2h_rev(block.hash()) == expected_checksum

        for tx in block.txs:
            print(tx)
            for t in tx.txs_in:
                print("  %s" % t)
            for t in tx.txs_out:
                print("  %s" % t)

        block.check_merkle_hash()
コード例 #48
0
ファイル: BlockChainView.py プロジェクト: dzyk/pycoinnet
    def do_headers_improve_path(self, headers):
        """
        Raises ValueError if headers path don't extend from anywhere in this view.

        Returns False if the headers don't improve the path.

        If the headers DO improve the path, return the value of the block index of
        the first header.

        So you need to rewind to "new_start_idx" before applying the new blocks.
        """
        tuples = []
        if len(self.node_tuples) == 0:
            if headers[0].previous_block_hash != HASH_INITIAL_BLOCK:
                return False
            the_tuple = GENESIS_TUPLE
        else:
            the_tuple = self.tuple_for_hash(headers[0].previous_block_hash)
            if the_tuple is None:
                return False
        new_start_idx = the_tuple[0] + 1
        total_work = the_tuple[-1]
        expected_prior_hash = the_tuple[1]
        for idx, h in enumerate(headers):
            if h.previous_block_hash != expected_prior_hash:
                raise ValueError(
                    "headers are not properly linked: no known block with hash %s" % b2h_rev(
                        h.previous_block_hash))
            total_work += 1  # TODO: make this difficulty/work instead of path size
            expected_prior_hash = h.hash()
            tuples.append((idx + new_start_idx, expected_prior_hash, total_work))
        if total_work <= self.last_block_tuple()[-1]:
            return False

        # the headers DO improve things

        old_tuples = self.node_tuples
        self._set_tuples(t for t in old_tuples if t[0] < new_start_idx)
        self._add_tuples(tuples)
        return new_start_idx
コード例 #49
0
ファイル: tx.py プロジェクト: Bluejudy/pycoin
def dump_tx(tx, netcode='BTC'):
    address_prefix = address_prefix_for_netcode(netcode)
    tx_bin = stream_to_bytes(tx.stream)
    print("Version: %2d  tx hash %s  %d bytes   " % (tx.version, tx.id(), len(tx_bin)))
    print("TxIn count: %d; TxOut count: %d" % (len(tx.txs_in), len(tx.txs_out)))
    if tx.lock_time == 0:
        meaning = "valid anytime"
    elif tx.lock_time < LOCKTIME_THRESHOLD:
        meaning = "valid after block index %d" % tx.lock_time
    else:
        when = datetime.datetime.utcfromtimestamp(tx.lock_time)
        meaning = "valid on or after %s utc" % when.isoformat()
    print("Lock time: %d (%s)" % (tx.lock_time, meaning))
    print("Input%s:" % ('s' if len(tx.txs_in) != 1 else ''))
    missing_unspents = tx.missing_unspents()
    for idx, tx_in in enumerate(tx.txs_in):
        if tx.is_coinbase():
            print("%3d: COINBASE  %12.5f mBTC" % (idx, satoshi_to_mbtc(tx.total_in())))
        else:
            suffix = ""
            if tx.missing_unspent(idx):
                address = tx_in.bitcoin_address(address_prefix=address_prefix)
            else:
                tx_out = tx.unspents[idx]
                sig_result = " sig ok" if tx.is_signature_ok(idx) else " BAD SIG"
                suffix = " %12.5f mBTC %s" % (satoshi_to_mbtc(tx_out.coin_value), sig_result)
                address = tx_out.bitcoin_address(netcode=netcode)
            print("%3d: %34s from %s:%d%s" % (idx, address, b2h_rev(tx_in.previous_hash),
                  tx_in.previous_index, suffix))
    print("Output%s:" % ('s' if len(tx.txs_out) != 1 else ''))
    for idx, tx_out in enumerate(tx.txs_out):
        amount_mbtc = satoshi_to_mbtc(tx_out.coin_value)
        address = tx_out.bitcoin_address(netcode=netcode) or "(unknown)"
        print("%3d: %34s receives %12.5f mBTC" % (idx, address, amount_mbtc))
    if not missing_unspents:
        print("Total input  %12.5f mBTC" % satoshi_to_mbtc(tx.total_in()))
    print(    "Total output %12.5f mBTC" % satoshi_to_mbtc(tx.total_out()))
    if not missing_unspents:
        print("Total fees   %12.5f mBTC" % satoshi_to_mbtc(tx.fee()))
コード例 #50
0
 def delete_spendable(self, tx_hash, tx_out_index):
     c = self._exec_sql("delete from Spendable where tx_hash = ? and tx_out_index = ?",
                         b2h_rev(tx_hash), tx_out_index)
コード例 #51
0
def post_unpack_merkleblock(d, f):
    """
    A post-processing "post_unpack" to merkleblock messages.

    It validates the merkle proofs (throwing an exception if there's
    an error), and returns the list of transaction hashes in "tx_hashes".

    The transactions are supposed to be sent immediately after the merkleblock message.
    """
    def recurse(level_widths, level_index, node_index, hashes, flags, flag_index, tx_acc):
        idx, r = divmod(flag_index, 8)
        mask = (1 << r)
        flag_index += 1
        if flags[idx] & mask == 0:
            h = hashes.pop()
            return h, flag_index

        if level_index == len(level_widths) - 1:
            h = hashes.pop()
            tx_acc.append(h)
            return h, flag_index

        # traverse the left
        left_hash, flag_index = recurse(
            level_widths, level_index+1, node_index*2, hashes, flags, flag_index, tx_acc)

        # is there a right?
        if node_index*2+1 < level_widths[level_index+1]:
            right_hash, flag_index = recurse(
                level_widths, level_index+1, node_index*2+1, hashes, flags, flag_index, tx_acc)

            if left_hash == right_hash:
                raise ValueError("merkle hash has same left and right value at node %d" % node_index)
        else:
            right_hash = left_hash

        return double_sha256(left_hash + right_hash), flag_index

    level_widths = []
    count = d["total_transactions"]
    while count > 1:
        level_widths.append(count)
        count += 1
        count //= 2
    level_widths.append(1)
    level_widths.reverse()

    tx_acc = []
    flags = d["flags"]
    hashes = list(reversed(d["hashes"]))
    left_hash, flag_index = recurse(level_widths, 0, 0, hashes, flags, 0, tx_acc)

    if len(hashes) > 0:
        raise ValueError("extra hashes: %s" % hashes)

    idx, r = divmod(flag_index-1, 8)
    if idx != len(flags) - 1:
        raise ValueError("not enough flags consumed")

    if flags[idx] > (1 << (r+1))-1:
        raise ValueError("unconsumed 1 flag bits set")

    if left_hash != d["header"].merkle_root:
        raise ValueError(
            "merkle root %s does not match calculated hash %s" % (
                b2h_rev(d["header"].merkle_root), b2h_rev(left_hash)))

    d["tx_hashes"] = tx_acc
    return d
コード例 #52
0
 def tx_for_tx_hash(self, tx_hash):
     "Get a Tx by its hash."
     URL = "%s/tx/raw/%s" % (self.url, b2h_rev(tx_hash))
     r = json.loads(url_open(URL).read().decode("utf8"))
     tx = Tx.parse(io.BytesIO(h2b(r.get("data").get("tx").get("hex"))))
     return tx
コード例 #53
0
 def broadcast_tx(self, transaction):
     as_hex = transaction.as_hex()
     transaction = CTransaction.deserialize(h2b(as_hex))
     tx_id = bitcoin.rpc.Proxy().sendrawtransaction(transaction)
     # reverse endianness for bitcoind
     return b2h_rev(tx_id)
コード例 #54
0
ファイル: tx.py プロジェクト: kustomzone/pycoin
def dump_tx(tx, netcode, verbose_signature, disassembly_level, do_trace):
    address_prefix = address_prefix_for_netcode(netcode)
    tx_bin = stream_to_bytes(tx.stream)
    print("Version: %2d  tx hash %s  %d bytes   " % (tx.version, tx.id(), len(tx_bin)))
    print("TxIn count: %d; TxOut count: %d" % (len(tx.txs_in), len(tx.txs_out)))
    if tx.lock_time == 0:
        meaning = "valid anytime"
    elif tx.lock_time < LOCKTIME_THRESHOLD:
        meaning = "valid after block index %d" % tx.lock_time
    else:
        when = datetime.datetime.utcfromtimestamp(tx.lock_time)
        meaning = "valid on or after %s utc" % when.isoformat()
    print("Lock time: %d (%s)" % (tx.lock_time, meaning))
    print("Input%s:" % ('s' if len(tx.txs_in) != 1 else ''))
    missing_unspents = tx.missing_unspents()
    traceback_f = trace_script if do_trace else None
    for idx, tx_in in enumerate(tx.txs_in):
        if disassembly_level > 0:
            signature_for_hash_type_f = lambda hash_type, script: tx.signature_hash(
                                        script, idx, hash_type)
        if tx.is_coinbase():
            print("%4d: COINBASE  %12.5f mBTC" % (idx, satoshi_to_mbtc(tx.total_in())))
        else:
            suffix = ""
            if tx.missing_unspent(idx):
                tx_out = None
                address = tx_in.bitcoin_address(address_prefix=address_prefix)
            else:
                tx_out = tx.unspents[idx]
                sig_result = " sig ok" if tx.is_signature_ok(idx, traceback_f=traceback_f) else " BAD SIG"
                suffix = " %12.5f mBTC %s" % (satoshi_to_mbtc(tx_out.coin_value), sig_result)
                address = tx_out.bitcoin_address(netcode=netcode)
            t = "%4d: %34s from %s:%-4d%s" % (idx, address, b2h_rev(tx_in.previous_hash),
                                              tx_in.previous_index, suffix)
            print(t.rstrip())
            if disassembly_level > 0:
                out_script = b''
                if tx_out:
                    out_script = tx_out.script
                for (pre_annotations, pc, opcode, instruction, post_annotations) in \
                        disassemble_scripts(tx_in.script, out_script, signature_for_hash_type_f):
                    for l in pre_annotations:
                        print("           %s" % l)
                    print(    "    %4x: %02x  %s" % (pc, opcode, instruction))
                    for l in post_annotations:
                        print("           %s" % l)

            if verbose_signature:
                signatures = []
                for opcode in opcode_list(tx_in.script):
                    if not opcode.startswith("OP_"):
                        try:
                            signatures.append(parse_signature_blob(h2b(opcode)))
                        except UnexpectedDER:
                            pass
                if signatures:
                    sig_types_identical = (zip(*signatures)[1]).count(signatures[0][1]) == len(signatures)
                    i = 1 if len(signatures) > 1 else ''
                    for sig_pair, sig_type in signatures:
                        print("      r{0}: {1:#x}\n      s{0}: {2:#x}".format(i, *sig_pair))
                        if not sig_types_identical and tx_out:
                            print("      z{}: {:#x} {}".format(i, tx.signature_hash(tx_out.script, idx, sig_type),
                                                               sighash_type_to_string(sig_type)))
                        if i: i += 1
                    if sig_types_identical and tx_out:
                        print("      z:{} {:#x} {}".format(' ' if i else '', tx.signature_hash(tx_out.script, idx, sig_type),
                                                           sighash_type_to_string(sig_type)))

    print("Output%s:" % ('s' if len(tx.txs_out) != 1 else ''))
    for idx, tx_out in enumerate(tx.txs_out):
        amount_mbtc = satoshi_to_mbtc(tx_out.coin_value)
        address = tx_out.bitcoin_address(netcode=netcode) or "(unknown)"
        print("%4d: %34s receives %12.5f mBTC" % (idx, address, amount_mbtc))
        if disassembly_level > 0:
            for (pre_annotations, pc, opcode, instruction, post_annotations) in \
                    disassemble_scripts(b'', tx_out.script, signature_for_hash_type_f):
                for l in pre_annotations:
                    print("           %s" % l)
                print(    "    %4x: %02x  %s" % (pc, opcode, instruction))
                for l in post_annotations:
                    print("           %s" % l)

    if not missing_unspents:
        print("Total input  %12.5f mBTC" % satoshi_to_mbtc(tx.total_in()))
    print(    "Total output %12.5f mBTC" % satoshi_to_mbtc(tx.total_out()))
    if not missing_unspents:
        print("Total fees   %12.5f mBTC" % satoshi_to_mbtc(tx.fee()))