def output_derive_script(address: str, coin: CoinInfo) -> bytes: if coin.bech32_prefix and address.startswith(coin.bech32_prefix): # p2wpkh or p2wsh witprog = common.decode_bech32_address(coin.bech32_prefix, address) return output_script_native_p2wpkh_or_p2wsh(witprog) if (not utils.BITCOIN_ONLY and coin.cashaddr_prefix is not None and address.startswith(coin.cashaddr_prefix + ":")): prefix, addr = address.split(":") version, data = cashaddr.decode(prefix, addr) if version == cashaddr.ADDRESS_TYPE_P2KH: version = coin.address_type elif version == cashaddr.ADDRESS_TYPE_P2SH: version = coin.address_type_p2sh else: raise wire.DataError("Unknown cashaddr address type") raw_address = bytes([version]) + data else: try: raw_address = base58.decode_check(address, coin.b58_hash) except ValueError: raise wire.DataError("Invalid address") if address_type.check(coin.address_type, raw_address): # p2pkh pubkeyhash = address_type.strip(coin.address_type, raw_address) script = output_script_p2pkh(pubkeyhash) return script elif address_type.check(coin.address_type_p2sh, raw_address): # p2sh scripthash = address_type.strip(coin.address_type_p2sh, raw_address) script = output_script_p2sh(scripthash) return script raise wire.DataError("Invalid address type")
def output_derive_script(o: TxOutputType, coin: CoinInfo, root: bip32.HDNode) -> bytes: if o.script_type == OutputScriptType.PAYTOOPRETURN: # op_return output if o.amount != 0: raise SigningError( FailureType.DataError, "OP_RETURN output with non-zero amount" ) return output_script_paytoopreturn(o.op_return_data) if o.address_n: # change output if o.address: raise SigningError(FailureType.DataError, "Address in change output") o.address = get_address_for_change(o, coin, root) else: if not o.address: raise SigningError(FailureType.DataError, "Missing address") if coin.bech32_prefix and o.address.startswith(coin.bech32_prefix): # p2wpkh or p2wsh witprog = decode_bech32_address(coin.bech32_prefix, o.address) return output_script_native_p2wpkh_or_p2wsh(witprog) if coin.cashaddr_prefix is not None and o.address.startswith( coin.cashaddr_prefix + ":" ): prefix, addr = o.address.split(":") version, data = cashaddr.decode(prefix, addr) if version == cashaddr.ADDRESS_TYPE_P2KH: version = coin.address_type elif version == cashaddr.ADDRESS_TYPE_P2SH: version = coin.address_type_p2sh else: raise ValueError("Unknown cashaddr address type") raw_address = bytes([version]) + data else: raw_address = base58.decode_check(o.address, coin.b58_hash) if address_type.check(coin.address_type, raw_address): # p2pkh pubkeyhash = address_type.strip(coin.address_type, raw_address) script = output_script_p2pkh(pubkeyhash) if coin.bip115: script += script_replay_protection_bip115( o.block_hash_bip115, o.block_height_bip115 ) return script elif address_type.check(coin.address_type_p2sh, raw_address): # p2sh scripthash = address_type.strip(coin.address_type_p2sh, raw_address) script = output_script_p2sh(scripthash) if coin.bip115: script += script_replay_protection_bip115( o.block_hash_bip115, o.block_height_bip115 ) return script raise SigningError(FailureType.DataError, "Invalid address type")
def output_derive_script( o: TxOutputType, coin: coininfo.CoinInfo, keychain: seed.Keychain ) -> bytes: if o.script_type == OutputScriptType.PAYTOOPRETURN: return scripts.output_script_paytoopreturn(o.op_return_data) if o.address_n: # change output o.address = get_address_for_change(o, coin, keychain) if coin.bech32_prefix and o.address.startswith(coin.bech32_prefix): # p2wpkh or p2wsh witprog = addresses.decode_bech32_address(coin.bech32_prefix, o.address) return scripts.output_script_native_p2wpkh_or_p2wsh(witprog) if ( not utils.BITCOIN_ONLY and coin.cashaddr_prefix is not None and o.address.startswith(coin.cashaddr_prefix + ":") ): prefix, addr = o.address.split(":") version, data = cashaddr.decode(prefix, addr) if version == cashaddr.ADDRESS_TYPE_P2KH: version = coin.address_type elif version == cashaddr.ADDRESS_TYPE_P2SH: version = coin.address_type_p2sh else: raise SigningError("Unknown cashaddr address type") raw_address = bytes([version]) + data else: try: raw_address = base58.decode_check(o.address, coin.b58_hash) except ValueError: raise SigningError(FailureType.DataError, "Invalid address") if address_type.check(coin.address_type, raw_address): # p2pkh pubkeyhash = address_type.strip(coin.address_type, raw_address) script = scripts.output_script_p2pkh(pubkeyhash) return script elif address_type.check(coin.address_type_p2sh, raw_address): # p2sh scripthash = address_type.strip(coin.address_type_p2sh, raw_address) script = scripts.output_script_p2sh(scripthash) return script raise SigningError(FailureType.DataError, "Invalid address type")
def test_valid_address(self): # b58 -> cashaddr for b58, ca in VALID_ADDRESS: data = base58.decode_check(b58) version = data[0] if version == 5: version = 8 enc = cashaddr.encode('bitcoincash', version, data[1:]) self.assertEqual(ca, enc) # cashaddr -> base58 for b58, ca in VALID_ADDRESS: prefix, addr = ca.split(':') version, data = cashaddr.decode(prefix, addr) if version == 8: version = 5 enc = base58.encode_check(bytes([version]) + data) self.assertEqual(b58, enc)
def test_invalid_checksum(self): for test in VALID_CHECKSUM: test += 'xxx' prefix, addr = test.split(':') with self.assertRaises(ValueError): cashaddr.decode(prefix, addr)
def test_valid_checksum(self): for test in VALID_CHECKSUM: prefix, addr = test.split(':') cashaddr.decode(prefix, addr)