コード例 #1
0
ファイル: test.py プロジェクト: youngqqcn/cashaddress
 def test_to_cash_p2sh(self):
     self.assertEqual(
         convert.to_cash_address('3CWFddi6m4ndiGyKqzYvsFYagqDLPVMTzC'),
         'bitcoincash:ppm2qsznhks23z7629mms6s4cwef74vcwvn0h829pq')
     self.assertEqual(
         convert.to_cash_address(
             'bitcoincash:ppm2qsznhks23z7629mms6s4cwef74vcwvn0h829pq'),
         'bitcoincash:ppm2qsznhks23z7629mms6s4cwef74vcwvn0h829pq')
コード例 #2
0
ファイル: test.py プロジェクト: youngqqcn/cashaddress
 def test_to_cash_p2sh_testnet(self):
     self.assertEqual(
         convert.to_cash_address('2MwikwR6hoVijCmr1u8UgzFMHFP6rpQyRvP'),
         'bchtest:pqc3tyspqwn95retv5k3c5w4fdq0cxvv95u36gfk00')
     self.assertEqual(
         convert.to_cash_address(
             'bchtest:pqc3tyspqwn95retv5k3c5w4fdq0cxvv95u36gfk00'),
         'bchtest:pqc3tyspqwn95retv5k3c5w4fdq0cxvv95u36gfk00')
コード例 #3
0
ファイル: test.py プロジェクト: youngqqcn/cashaddress
 def test_to_cash_p2pkh(self):
     self.assertEqual(
         convert.to_cash_address('155fzsEBHy9Ri2bMQ8uuuR3tv1YzcDywd4'),
         'bitcoincash:qqkv9wr69ry2p9l53lxp635va4h86wv435995w8p2h')
     self.assertEqual(
         convert.to_cash_address(
             'bitcoincash:qqkv9wr69ry2p9l53lxp635va4h86wv435995w8p2h'),
         'bitcoincash:qqkv9wr69ry2p9l53lxp635va4h86wv435995w8p2h')
コード例 #4
0
ファイル: test.py プロジェクト: youngqqcn/cashaddress
 def test_to_cash_p2pkh_testnet(self):
     self.assertEqual(
         convert.to_cash_address('mqp7vM7eU7Vu9NPH1V7s7pPg5FFBMo6SWK'),
         'bchtest:qpc0qh2xc3tfzsljq79w37zx02kwvzm4gydm222qg8')
     self.assertEqual(
         convert.to_cash_address(
             'bchtest:qpc0qh2xc3tfzsljq79w37zx02kwvzm4gydm222qg8'),
         'bchtest:qpc0qh2xc3tfzsljq79w37zx02kwvzm4gydm222qg8')
コード例 #5
0
    def form_transaction_dict(cls, transaction):
        if not cls.is_memo(transaction):
            raise ValueError('Not valid transaction dict!')

        memo = Memo()
        memo.transaction_dict = transaction
        memo.transaction_hash = transaction['txid']
        memo.blockheight = transaction['blockheight']
        # memo.transaction_time=transaction['time']

        memo.__get_transfer()
        for vout in transaction['vout']:
            if vout['scriptPubKey']['hex'][0:2] == '6a' \
                    and vout['scriptPubKey']['hex'][4:8] in SUPPORTED_PREFIX:
                memo.prefix = vout['scriptPubKey']['hex'][4:8]
                memo.values = vout['scriptPubKey']['hex'][10:]
                break
        else:
            raise NotMemoTransaction(
                'No OP_RETURN data in the transaction or none memo supported data.'
            )

        addr_vin = []
        for vin in transaction['vin']:  # type:dict
            if 'addr' in vin:
                addr_vin.append(to_cash_address(vin['addr']))
        if len(addr_vin) >= 1:
            memo.sender = addr_vin[0]

        memo.transaction_time = transaction['time']

        return memo
コード例 #6
0
def address_to_public_key_hash(address):
    # LEGACYADDRESSDEPRECATION
    # FIXME: This legacy address support will be removed.
    address = cashaddress.to_cash_address(address)
    get_version(address)
    Address = cashaddress.Address._cash_string(address)
    return bytes(Address.payload)
コード例 #7
0
def get_xpub_address(xpub, index):
    # 0 => public addresses
    # 1 => change addresses, only for internal use
    account_type = 0
    xpub_subkey = xpub.subkey(account_type)
    addr = xpub_subkey.subkey(index).bitcoin_address()
    caddr = convert.to_cash_address(addr)
    #print(caddr)

    #return caddr.upper()
    return caddr
コード例 #8
0
 def __get_transfer(self):
     """
     generate transfer form transaction dict
     """
     transfer = []
     for vout in self.transaction_dict['vout']:
         if 'addresses' in vout['scriptPubKey']:
             transfer.append(
                 (to_cash_address(vout['scriptPubKey']['addresses'][0]),
                  vout['value']))
     self.transfer = transfer
コード例 #9
0
def pubkey_to_legacy_address(pubkey, main_net=True):
    pubkey = pubkey.decode("hex")

    addr_prefix = ADDR_PREFIX
    if not main_net:
        addr_prefix = ADDR_PREFIX_TEST

    h20 = utils.hash160(pubkey)
    d21 = addr_prefix + h20
    c4 = utils.checksum(d21)

    d25 = d21 + c4
    return to_cash_address(base58.b58encode(d25))
コード例 #10
0
def redeemscript_to_p2sh_address(redeem_script, main_net=True):
    redeem_script = redeem_script.decode("hex")

    script_prefix = SCRIPT_PREFIX
    if not main_net:
        script_prefix = SCRIPT_PREFIX_TEST

    h20 = utils.hash160(redeem_script)
    d21 = script_prefix + h20
    c4 = utils.checksum(d21)

    d25 = d21 + c4
    return to_cash_address(base58.b58encode(d25))
コード例 #11
0
def pub2add(pubkey):
    """Convert a Bitcoin public key to a cash address
    """
    # Public key from a known safely stored private key
    # pub_hex = '0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352'
    pub_hex = pubkey
    pub = bytes.fromhex(pub_hex)
    # print('pubkey', pub)

    # Perform SHA-256 hashing on the public key
    m = hashlib.sha256()
    m.update(pub)
    pub_sha256 = m.digest()
    # print('pub_sha256', pub_sha256)

    # Perform RIPEMD-160 hashing on the result of SHA-256
    h = hashlib.new('ripemd160')
    h.update(pub_sha256)
    pub_double = h.digest()
    # print('\npub_double', pub_double)

    # Add version byte in front of RIPEMD-160 hash (0x00 for Main Network)
    version_byte = bytes.fromhex('00')
    pub_double_full = version_byte + pub_double
    # print('version bytes added', pub_double_full)

    # Perform SHA-256 hash on the extended RIPEMD-160 result
    shan1 = hashlib.sha256()
    shan1.update(pub_double_full)
    shan1 = shan1.digest()
    # print('\nFirst SHA256:', shan1)

    # Perform SHA-256 hash on the result of the previous SHA-256 hash
    shan2 = hashlib.sha256()
    shan2.update(shan1)
    shan2 = shan2.digest()
    # print('\nSecond SHA256:', shan2)

    # Append the first 4 bytes of the second SHA-256 hash (checksum)
    # This is the 25-byte binary Bitcoin Address.
    checksum = shan2[:4]
    twenty5byte = pub_double_full + checksum
    # print('twenty5byte', twenty5byte)

    # Convert the result from a byte string into a base58 string using Base58Check
    # encoding.
    leg_address = encodeb58(twenty5byte)

    # Convert to cashaddress
    address = convert.to_cash_address(leg_address)
    print(address)
コード例 #12
0
 def get_uncompressed_coin(private_key):
     print("Warning Uncompressed key")
     config_alias = BitcoinConf
     coin_type = Bip44Coins.BITCOIN
     decodedWif = WifDecoder.Decode(
         wif_str=private_key, net_addr_ver=config_alias.WIF_NET_VER.Main())
     bip44_mst = Bip44.FromAddressPrivKey(decodedWif, coin_type)
     to_hex = bip44_mst.PublicKey().RawUncompressed().ToBytes()
     pub_key_bytes = b'\x04' + to_hex
     legacy_address = Base58Encoder.CheckEncode(
         config_alias.P2PKH_NET_VER.Main() +
         CryptoUtils.Hash160(pub_key_bytes))
     address = convert.to_cash_address(legacy_address).replace(
         'bitcoincash:', '')
     return CryptoCoin(address, private_key)
コード例 #13
0
def sign_message(message, coin, key=None, encoding='utf8'):

    # message = message.encode('utf8')

    coin_dispatcher = {
        'btc': cr.Bitcoin(),
        'bch': cr.BitcoinCash(),
        'ltc': cr.Litecoin()
    }

    client = coin_dispatcher[coin]

    # if no key provided, create one randomly
    if key is None:
        priv = random.randint(1, KEY_UPPER_LIMIT)
        pub = client.privtopub(priv)
        addr = client.privtoaddr(priv)
    else:
        try:
            priv = int(key)
            pub = client.privtopub(priv)
            addr = client.privtoaddr(priv)
        except:
            priv = cr.sha256(key)
            pub = client.privtopub(priv)
            addr = client.privtoaddr(priv)

    # sign message
    # if coin == 'ltc':
    #     signature = cr.litecoin_ecdsa_sign(message, priv)
    # else:
    #     signature = cr.ecdsa_sign(message, priv)
    signature = cr.bytes_ecdsa_sign(message, priv, coin, encoding)

    if coin == 'bch':
        addr = convert.to_cash_address(addr)

    # output
    output = {
        "address": addr,
        "signature": signature,
        "message": message,
        "private_key": priv,
        "public_key": pub,
        "coin": coin
    }

    return output
コード例 #14
0
    def __init__(self,address):
        if not isinstance(address,str):
            raise TypeError('address should be str!')
        if not is_valid(address):
            raise ValueError('{} is not a valid address'.format(address))

        self._address = to_cash_address(address)
        self.memos_send=[]  # list of memos sent by user
        self.memos_post=[]  # list of post memo sent by user
        self.memos_like=[]  # list of like / tip memo sent by user

        self.memos_receive=[]   # list of memos that are not sent by user but transfer BCH to user

        self._private_key=None

        self.name=None
        self.following=set()
コード例 #15
0
def address_to_public_key_hash(address):
    address = convert.to_cash_address(address)
    Address = convert.Address._cash_string(address)
    return bytes(Address.payload)
コード例 #16
0
ファイル: transaction.py プロジェクト: SKlayer/bitcashcn
def sanitize_tx_data(unspents, outputs, fee, leftover, combine=True, message=None, compressed=True, custom_pushdata=False):
    """
    sanitize_tx_data()

    fee is in satoshis per byte.
    """

    outputs = deque(outputs)

    for i, output in enumerate(outputs):
        dest, amount, currency = output
        # LEGACYADDRESSDEPRECATION
        # FIXME: Will be removed in an upcoming release, breaking compatibility with legacy addresses.
        dest = cashaddress.to_cash_address(dest)
        outputs[i] = (dest, currency_to_satoshi_cached(amount, currency))

    if not unspents:
        raise ValueError('Transactions must have at least one unspent.')

    # Temporary storage so all outputs precede messages.
    messages = deque()
    total_op_return_size = 0

    if message and (custom_pushdata is False):
        try:
            message = message.encode('utf-8')
        except AttributeError:
            pass # assume message is already a bytes-like object

        message_chunks = chunk_data(message, MESSAGE_LIMIT)

        for message in message_chunks:
            messages.appendleft((message, 0))
            total_op_return_size += get_op_return_size(message, custom_pushdata=False)

    elif message and (custom_pushdata is True):
        if (len(message) >= MESSAGE_LIMIT):
            # FIXME add capability for >220 bytes for custom pushdata elements
            raise ValueError("Currently cannot exceed 220 bytes with custom_pushdata.")
        else:
            messages.append((message, 0))
            total_op_return_size += get_op_return_size(message, custom_pushdata=True)


    # Include return address in fee estimate.
    total_in = 0
    num_outputs = len(outputs) + 1
    sum_outputs = sum(out[1] for out in outputs)

    if combine:
        # calculated_fee is in total satoshis.
        calculated_fee = estimate_tx_fee(len(unspents), num_outputs, fee, compressed, total_op_return_size)
        total_out = sum_outputs + calculated_fee
        unspents = unspents.copy()
        total_in += sum(unspent.amount for unspent in unspents)

    else:
        unspents = sorted(unspents, key=lambda x: x.amount)

        index = 0

        for index, unspent in enumerate(unspents):
            total_in += unspent.amount
            calculated_fee = estimate_tx_fee(len(unspents[:index + 1]), num_outputs, fee, compressed, total_op_return_size)
            total_out = sum_outputs + calculated_fee

            if total_in >= total_out:
                break

        unspents[:] = unspents[:index + 1]

    remaining = total_in - total_out


    if remaining > DUST_LIMIT:
        outputs.append((leftover, remaining))
    elif remaining < 0:
        raise InsufficientFunds('Balance {} is less than {} (including '
                                'fee).'.format(total_in, total_out))

    outputs.extendleft(messages)

    return unspents, list(outputs)
コード例 #17
0
def sanitize_tx_data(unspents, outputs, fee, leftover, combine=True, message=None, compressed=True):
    """
    sanitize_tx_data()

    fee is in satoshis per byte.
    """

    outputs = outputs.copy()

    for i, output in enumerate(outputs):
        dest, amount, currency = output
        # LEGACYADDRESSDEPRECATION
        # FIXME: Will be removed in an upcoming release, breaking compatibility with legacy addresses.
        dest = cashaddress.to_cash_address(dest)
        outputs[i] = (dest, currency_to_satoshi_cached(amount, currency))

    if not unspents:
        raise ValueError('Transactions must have at least one unspent.')

    # Temporary storage so all outputs precede messages.
    messages = []

    if message:
        message_chunks = chunk_data(message.encode('utf-8'), MESSAGE_LIMIT)

        for message in message_chunks:
            messages.append((message, 0))

    # Include return address in fee estimate.

    total_in = 0
    num_outputs = len(outputs) + len(messages) + 1
    sum_outputs = sum(out[1] for out in outputs)

    if combine:
        # calculated_fee is in total satoshis.
        calculated_fee = estimate_tx_fee(len(unspents), num_outputs, fee, compressed)
        total_out = sum_outputs + calculated_fee
        unspents = unspents.copy()
        total_in += sum(unspent.amount for unspent in unspents)

    else:
        unspents = sorted(unspents, key=lambda x: x.amount)

        index = 0

        for index, unspent in enumerate(unspents):
            total_in += unspent.amount
            calculated_fee = estimate_tx_fee(len(unspents[:index + 1]), num_outputs, fee, compressed)
            total_out = sum_outputs + calculated_fee

            if total_in >= total_out:
                break

        unspents[:] = unspents[:index + 1]

    remaining = total_in - total_out

    if remaining > 0:
        outputs.append((leftover, remaining))
    elif remaining < 0:
        raise InsufficientFunds('Balance {} is less than {} (including '
                                'fee).'.format(total_in, total_out))

    outputs.extend(messages)

    return unspents, outputs
コード例 #18
0
print()
print(
    get_transaction_btc(
        'a7e3babfd7658cfa5ebf5d9b1477da0b40cab68d75c7bc8638eaafcba066b062'))
print()
print(get_transactions('qqa0dwrk79um6wgmzk9rrv303l2qwppuk5vmr8taqq'))

k = Key('L3KavUvcjBj7pzKBMS4doKyJpBY4nJJbm31VnVwhcC26mTvCP3Lh')
# k = PrivateKeyTestnet('cPW1zL9JJzgTKwQyHYeQ8KE5Cdo33fGE15QcZiWDCWKHhU43KsU2')
# print(k.public_key)
print(k.address)
# print(k._public_key)
# print(k.public_point)
address = convert.to_legacy_address(k.address)
print(address)
bchaddr = convert.to_cash_address('13A8QNwEeuYyvcPSJwR4F5xDr6RUryLVfw')
# print(bchaddr)
# print(k.to_wif())
print(k.get_balance(currency='satoshi'))
# print(k.unspents)
# print(k.transactions)
print(k.get_transactions())
print(k.get_unspents())
txid = k.send([('13A8QNwEeuYyvcPSJwR4F5xDr6RUryLVfw', 0.01001, 'bch')],
              fee=452)
print(txid)

print(get_balance('qz7xc0vl85nck65ffrsx5wvewjznp9lflgktxc5878',
                  currency='bch'))
print(
    get_balance_btc('bc1q5j8j9y55mc05ws84smk36ndau4ptj9yj72eldz',
コード例 #19
0
 def test_to_cash_p2pkh_regtest(self):
     self.assertEqual(convert.to_cash_address('moehusBtUt3aKW5c2p3ZTRkSTRrr3dpnwe', regtest=True),
                      'bchreg:qpvns5lcufh5haf5jt79fk8trcw4j8c3nsvhdappvt')
     self.assertEqual(convert.to_cash_address('bchreg:qpvns5lcufh5haf5jt79fk8trcw4j8c3nsvhdappvt', regtest=True),
                      'bchreg:qpvns5lcufh5haf5jt79fk8trcw4j8c3nsvhdappvt')
コード例 #20
0
    def update(self, dt):
        # only one factor at a time
        if len(self.listener.received) != 0:
            return

        # poll server for each id_2FA
        print("Satochip update...")
        for keyhash in self.myfactors.datastore.keys():
            # if keyhash in self.listener.received:
            # continue
            try:
                message = server.get(keyhash)
            except Exception as e:
                self.display = "Error: cannot contact server:" + str(e)
                Logger.warning("Satochip: cannot contact server: " + str(e))
                break
            if message:
                self.listener.received.add(keyhash)
                label = self.myfactors.datastore.get(keyhash)['label_2FA']
                Logger.debug("Satochip: Received challenge for: " + keyhash)
                Logger.debug("Satochip: Corresponding label: " + label)
                Logger.debug("Satochip: Challenge received: " + message)

                # decrypt message & remove padding
                key_2FA = bytes.fromhex(
                    self.myfactors.datastore.get(keyhash)['key_2FA'])
                message = base64.b64decode(message)
                iv = message[0:16]
                ciphertext = message[16:]

                decrypter = pyaes.Decrypter(
                    pyaes.AESModeOfOperationCBC(key_2FA, iv))
                decrypted = decrypter.feed(ciphertext)
                decrypted += decrypter.feed()
                Logger.debug("Satochip: Challenge decrypted: " +
                             decrypted.decode('ascii'))
                message = json.loads(decrypted)
                if 'action' in message:
                    action = message['action']
                else:
                    action = "sign_tx"

                if action == "reset_seed":
                    authentikeyx = message['authentikeyx']
                    txt = "Request to reset the seed!\nAuthentikey:" + authentikeyx
                    challenge = authentikeyx + 32 * 'FF'
                elif action == "reset_2FA":
                    txt = "Request to reset 2FA!\nID_2FA:" + keyhash
                    try:
                        id_2FA_20b = self.myfactors.datastore.get(
                            keyhash)['id_2FA_20b']
                    except Exception as ex:  # not supported for 2FA created in app version <=0.8/0.9
                        id_2FA_20b = keyhash
                    challenge = id_2FA_20b + 44 * 'AA'
                elif action == "sign_msg":
                    msg = message['msg']
                    if 'alt' in message:
                        altcoin = message['alt']
                        headersize = bytes([len(altcoin) + 17])
                        paddedmsgbytes = headersize + altcoin.encode(
                            'utf8') + b" Signed Message:\n" + num_to_var_int(
                                len(msg)) + bytes(msg, 'utf-8')
                    else:
                        altcoin = "Bitcoin"
                        paddedmsgbytes = b"\x18Bitcoin Signed Message:\n" + num_to_var_int(
                            len(msg)) + bytes(msg, 'utf-8')

                    txt = "Request to sign " + altcoin + " message:\n" + msg + "\n"
                    paddedmsghash = sha256(paddedmsgbytes).hexdigest()
                    challenge = paddedmsghash + 32 * "BB"
                elif action == "sign_tx":
                    is_segwit = message['sw']
                    txt = "2FA: " + label + "\n"

                    # coin type:
                    coin_type = message['ct']
                    if coin_type == 0:
                        coin = Bitcoin(False)
                    elif coin_type == 1:  #btc testnet
                        coin = Bitcoin(True)
                    elif coin_type == 2:  #litecoin
                        istest = message['tn']
                        coin = Litecoin(testnet=istest)
                    elif coin_type == 145:  #bcash
                        istest = message['tn']
                        coin = BitcoinCash(testnet=istest)
                        is_segwit = True  # bcash uses BIP143 for signature hash creation
                    else:
                        Logger.warning("Satochip: Coin not (yet) supported: " +
                                       str(coin_type))
                        coin = BaseCoin()
                    txt += "Coin: " + coin.display_name + "\n"

                    # parse tx into a clear message for approval
                    pre_tx_hex = message['tx']
                    pre_tx = bytes.fromhex(pre_tx_hex)
                    pre_hash_hex = sha256(sha256(pre_tx).digest()).hexdigest()
                    challenge = pre_hash_hex + 32 * '00'
                    if is_segwit:

                        #parse segwit tx
                        txin_type = message['ty']
                        txparser = TxParser(pre_tx)
                        while not txparser.is_parsed():
                            chunk = txparser.parse_segwit_transaction()

                        Logger.debug("Satochip: hashPrevouts: " +
                                     txparser.hashPrevouts.hex())
                        Logger.debug("Satochip: hashSequence: " +
                                     txparser.hashSequence.hex())
                        Logger.debug("Satochip: txOutHash: " +
                                     txparser.txOutHash[::-1].hex())
                        Logger.debug("Satochip: txOutIndex: " +
                                     str(txparser.txOutIndexLong))
                        Logger.debug("Satochip: inputScript: " +
                                     txparser.inputScript.hex())
                        Logger.debug("Satochip: inputAmount: " +
                                     str(txparser.inputAmountLong))
                        Logger.debug("Satochip: nSequence: " +
                                     txparser.nSequence.hex())
                        Logger.debug("Satochip: hashOutputs: " +
                                     txparser.hashOutputs.hex())
                        Logger.debug("Satochip: nLocktime: " +
                                     txparser.nLocktime.hex())
                        Logger.debug("Satochip: nHashType: " +
                                     txparser.nHashType.hex())

                        script = txparser.inputScript.hex()
                        if txin_type == 'p2wpkh':
                            hash = transaction.output_script_to_h160(script)
                            hash = bytes.fromhex(hash)
                            addr = coin.hash_to_segwit_addr(hash)
                            Logger.debug("Satochip: p2wpkh address: " + addr)
                        elif txin_type == 'p2wsh':  #multisig-segwit
                            addr = coin.script_to_p2wsh(script)
                            Logger.debug("Satochip: p2wsh address: " + addr)
                        elif txin_type == 'p2wsh-p2sh':
                            h = transaction.output_script_to_h160(script)
                            addr = coin.p2sh_scriptaddr("0020" + h)
                            Logger.debug("Satochip: p2wsh-p2sh address: " +
                                         addr)
                        elif txin_type == 'p2wpkh-p2sh':
                            # for p2wpkh-p2sh addres is derived from script hash, see https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#P2WPKH_nested_in_BIP16_P2SH
                            h = transaction.output_script_to_h160(script)
                            addr = coin.p2sh_scriptaddr("0014" + h)
                            Logger.debug("Satochip: p2wpkh-p2sh address: " +
                                         addr)
                        elif (coin_type
                              == 145) and (txin_type == 'p2pkh' or txin_type
                                           == 'p2sh'):  # for bcash
                            addr = coin.scripttoaddr(script)
                            addr = convert.to_cash_address(
                                addr)  #cashAddr conversion
                            addr = addr.split(":", 1)[-1]  #remove prefix
                            Logger.debug("Satochip: txin type: " + txin_type +
                                         " address: " + addr)
                        else:
                            addr = "unsupported script:" + script + "\n"

                        txt += "input:\n"
                        txt += "    " + "address: " + addr + " spent: " + str(
                            txparser.inputAmountLong /
                            100000) + "\n"  #satoshi to mBtc

                        #parse outputs
                        outputs_hex = message['txo']
                        outputs = bytes.fromhex(outputs_hex)
                        hashOutputs = sha256(sha256(
                            outputs[1:]).digest()).hexdigest()
                        outparser = TxParser(outputs)
                        while not outparser.is_parsed():
                            chunk = outparser.parse_outputs()

                        nb_outs = outparser.txCurrentOutput
                        Logger.debug("Satochip: nbrOutputs: " + str(nb_outs))
                        txt += "nb_outputs: " + str(nb_outs) + "\n"
                        txt += "outputs:\n"
                        amnt_out = 0
                        for i in range(nb_outs):
                            amnt = outparser.outAmounts[i]
                            amnt_out += amnt
                            script = outparser.outScripts[i].hex()
                            is_data_script = False
                            Logger.debug("Satochip: outScripts: " + script)
                            Logger.debug("Satochip: amount: " + str(amnt))
                            if script.startswith('76a914'):  #p2pkh
                                addr = coin.scripttoaddr(script)
                            elif script.startswith('a914'):  #p2sh
                                addr = coin.scripttoaddr(script)
                            elif script.startswith('0014'):  #p2wpkh
                                hash = bytes.fromhex(script[4:])
                                addr = coin.hash_to_segwit_addr(hash)
                            elif script.startswith('0020'):  #p2wsh
                                hash = bytes.fromhex(script[4:])
                                addr = coin.hash_to_segwit_addr(hash)
                            elif script.startswith(
                                    '6a'):  # op_return data script
                                addr = "DATA: " + bytes.fromhex(
                                    script[6:]).decode('utf-8')
                                is_data_script = True
                            else:
                                addr = "unsupported script:" + script + "\n"

                            if coin_type == 145 and not is_data_script:
                                addr = convert.to_cash_address(
                                    addr)  #cashAddr conversion
                                addr = addr.split(":", 1)[-1]  #remove prefix

                            Logger.debug("Satochip: address: " + addr)
                            txt += "    " + "address: " + addr + " spent: " + str(
                                amnt / 100000) + "\n"  #satoshi to mBtc
                        txt += "    " + "total: " + str(
                            amnt_out / 100000
                        ) + " m" + coin.coin_symbol + "\n"  #satoshi to mBtc

                        if hashOutputs != txparser.hashOutputs.hex():
                            txt += "Warning! inconsistent output hashes!\n"

                    # non-segwit tx
                    else:
                        pre_tx_dic = {}
                        try:
                            pre_tx_dic = transaction.deserialize(pre_tx)
                        except Exception as e:
                            Logger.warning(
                                "Exception during (non-segwit) tx parsing: " +
                                str(e))
                            txt = "Error parsing tx!"
                            self.listener.clear(keyhash)
                            break
                        Logger.debug("Satochip: pre_tx_dic: " +
                                     str(pre_tx_dic))

                        # inputs
                        amount_in = 0
                        ins = pre_tx_dic['ins']
                        nb_ins = len(ins)
                        txt += "nb_inputs: " + str(nb_ins) + "\n"
                        txt += "inputs:\n"
                        for i in ins:
                            script = i['script'].hex()
                            Logger.debug("Satochip: input script: " + script)

                            # recover script and corresponding addresse
                            if script == "":  # all input scripts are removed for signing except 1
                                outpoint = i['outpoint']
                                hash = outpoint['hash'].hex()
                                index = outpoint['index']
                                #Logger.debug('Satochip: hash: hash:index: ' +hash+":"+str(index))
                                tx = coin.fetchtx(hash)
                                #Logger.debug('Satochip: tx: '+str(tx))
                                outs = tx['out']
                                out = outs[index]
                                val = out['value']
                                script = out['script']
                                addr = coin.scripttoaddr(script)
                                addr = "(empty for signing: " + addr[
                                    0:16] + "...)"
                            if script.endswith("ae"):  #m-of-n pay-to-multisig
                                m = int(script[0:2], 16) - 80
                                n = int(script[-4:-2], 16) - 80
                                txt += "    " + "multisig " + str(
                                    m) + "-of-" + str(n) + "\n"
                                addr = coin.p2sh_scriptaddr(script)
                                Logger.debug("Satochip: address multisig: " +
                                             addr)
                            else:  #p2pkh, p2sh
                                addr = coin.scripttoaddr(script)
                                Logger.debug("Satochip: address: " + addr)

                            # get value from blockchain explorer
                            val = 0
                            try:
                                unspent = coin.unspent_web(addr)
                                for d in unspent:
                                    val += d['value']
                            except Exception as e:
                                Logger.warning(
                                    "Exception during coin.unspent_web request: "
                                    + str(e))
                                #try to get value from electrum server (seem slow...)
                                # try:
                                # hs= sha256(bytes.fromhex(script)).digest()
                                # hs= hs[::-1]
                                # balances=  coin.balance(True, hs.hex())
                                # val= sum(balances)
                                # except Exception as e:
                                # Logger.warning("Exception during coin.balance request: "+str(e))

                            txt += "    " + "address: " + addr + " balance: " + str(
                                val / 100000) + "\n"
                            amount_in += val
                        txt += "    " + "total: " + str(
                            amount_in / 100000
                        ) + " m" + coin.coin_symbol + "\n"  #satoshi to mBtc

                        # outputs
                        fee = 0
                        amount_out = 0
                        outs = pre_tx_dic['outs']
                        nb_outs = len(outs)
                        txt += "nb_outputs: " + str(nb_outs) + "\n"
                        txt += "outputs:\n"
                        for o in outs:
                            val = (o['value'])
                            script = o['script'].hex()
                            Logger.debug("Satochip: output script: " + script)
                            if script.startswith('76a914'):  # p2pkh
                                addr = coin.scripttoaddr(script)
                            elif script.startswith('a914'):  # p2sh
                                addr = coin.scripttoaddr(script)
                            elif script.startswith('0014'):  #p2wpkh
                                hash = bytes.fromhex(script[4:])
                                addr = coin.hash_to_segwit_addr(hash)
                            elif script.startswith('0020'):  #p2wsh
                                hash = bytes.fromhex(script[4:])
                                addr = coin.hash_to_segwit_addr(hash)
                            else:
                                addr = "unsupported script:" + script + "\n"
                            txt += "    " + "address: " + addr + " spent: " + str(
                                val / 100000) + "\n"  #satoshi to mBtc
                            amount_out += val
                        txt += "    " + "total: " + str(
                            amount_out / 100000
                        ) + " m" + coin.coin_symbol + "\n"  #satoshi to mBtc
                        fee = amount_in - amount_out
                        if fee >= 0:
                            txt += "    " + "fees:  " + str(
                                fee / 100000
                            ) + " m" + coin.coin_symbol + "\n"  #satoshi to mBtc
                else:
                    txt = "Unsupported operation: " + decrypted.decode('ascii')

                # 2FA challenges:
                # - Tx approval: [ 32b Tx hash | 32-bit 0x00-padding ]
                # - ECkey import:[ 32b coordx  | 32-bit (0x10^key_nb)-padding ]
                # - ECkey reset: [ 32b coordx  | 32-bit (0x20^key_nb)-padding ]
                # - 2FA reset:   [ 20b 2FA_ID  | 32-bit 0xAA-padding ]
                # - Seed reset:  [ 32b authntikey-coordx  | 32-bit 0xFF-padding ]
                # - Msg signing: [ 32b SHA26(btcHeader+msg) | 32-bit 0xBB-padding ]
                self.listener.postbox.append([keyhash, challenge])
                self.display = txt
                self.label_logs += txt + "\n"
                Logger.info("Satochip: \nNew challenge: " + challenge +
                            "\nReceived on " + str(datetime.now()) + ":\n" +
                            txt)

                self.btn_disabled = False
                break
コード例 #21
0
 def test_to_cash_p2sh_regtest(self):
     self.assertEqual(convert.to_cash_address('2MwSNRexxm3uhAKF696xq3ztdiqgMj36rJo', regtest=True),
                      'bchreg:pqklc8ehp365xvtru6a394e4wxz52nt5nurac3g7rq')
     self.assertEqual(convert.to_cash_address('bchreg:pqklc8ehp365xvtru6a394e4wxz52nt5nurac3g7rq', regtest=True),
                      'bchreg:pqklc8ehp365xvtru6a394e4wxz52nt5nurac3g7rq')
コード例 #22
0
ファイル: tna.py プロジェクト: digger3d/bitd-importer
def to_cash_addr(addr):
    return convert.to_cash_address(addr)[12:]  # remove "bitcoincash:" prefix