def test_wrong_nVersion(self) -> None: """Creating a CBitcoinAddress from a unknown nVersion fails""" # tests run in mainnet, so both of the following should fail with self.assertRaises(CBitcoinAddressError): CBitcoinAddress('mpXwg4jMtRhuSpVq4xS3HFHmCmWp9NyGKt') with self.assertRaises(CBitcoinAddressError): CBitcoinAddress('2MyJKxYR2zNZZsZ39SgkCXWCfQtXKhnWSWq')
def test_from_nonstd_scriptPubKey(self) -> None: """CBitcoinAddress.from_scriptPubKey() with non-standard scriptPubKeys""" # Bad P2SH scriptPubKeys # non-canonical pushdata scriptPubKey = CScript(x('a94c14000000000000000000000000000000000000000087')) with self.assertRaises(CBitcoinAddressError): CBitcoinAddress.from_scriptPubKey(scriptPubKey) # Bad P2PKH scriptPubKeys # Missing a byte scriptPubKey = CScript(x('76a914000000000000000000000000000000000000000088')) with self.assertRaises(CBitcoinAddressError): CBitcoinAddress.from_scriptPubKey(scriptPubKey) # One extra byte scriptPubKey = CScript(x('76a914000000000000000000000000000000000000000088acac')) with self.assertRaises(CBitcoinAddressError): CBitcoinAddress.from_scriptPubKey(scriptPubKey) # One byte changed scriptPubKey = CScript(x('76a914000000000000000000000000000000000000000088ad')) with self.assertRaises(CBitcoinAddressError): CBitcoinAddress.from_scriptPubKey(scriptPubKey)
def test_from_invalid_scriptPubKey(self) -> None: """CBitcoinAddress.from_scriptPubKey() with invalid scriptPubKeys""" # We should raise a CBitcoinAddressError, not any other type of error # Truncated P2SH scriptPubKey = CScript(x('a91400000000000000000000000000000000000000')) with self.assertRaises(CBitcoinAddressError): CBitcoinAddress.from_scriptPubKey(scriptPubKey) # Truncated P2PKH scriptPubKey = CScript(x('76a91400000000000000000000000000000000000000')) with self.assertRaises(CBitcoinAddressError): CBitcoinAddress.from_scriptPubKey(scriptPubKey)
def listunspent(self, minconf=0, maxconf=9999999, addrs=None): """Return unspent transaction outputs in wallet Outputs will have between minconf and maxconf (inclusive) confirmations, optionally filtered to only include txouts paid to addresses in addrs. """ r = None if addrs is None: r = self._call('listunspent', minconf, maxconf) else: addrs = [str(addr) for addr in addrs] r = self._call('listunspent', minconf, maxconf, addrs) r2 = [] for unspent in r: unspent['outpoint'] = COutPoint(lx(unspent['txid']), unspent['vout']) del unspent['txid'] del unspent['vout'] # address isn't always available as Bitcoin Core allows scripts w/o # an address type to be imported into the wallet, e.g. non-p2sh # segwit try: unspent['address'] = CBitcoinAddress(unspent['address']) except KeyError: pass unspent['scriptPubKey'] = CScript( unhexlify(unspent['scriptPubKey'])) unspent['amount'] = int(unspent['amount'] * COIN) r2.append(unspent) return r2
def getrawchangeaddress(self): """Returns a new Bitcoin address, for receiving change. This is for use with raw transactions, NOT normal use. """ r = self._call('getrawchangeaddress') return CBitcoinAddress(r)
def validateaddress(self, address): """Return information about an address""" r = self._call('validateaddress', str(address)) if r['isvalid']: r['address'] = CBitcoinAddress(r['address']) if 'pubkey' in r: r['pubkey'] = unhexlify(r['pubkey']) return r
def T(str_addr, expected_bytes, expected_version, expected_class): addr = CCoinAddress(str_addr) addr2 = CBitcoinAddress(str_addr) self.assertEqual(addr, addr2) self.assertEqual(type(addr), type(addr2)) self.assertEqual(addr.to_bytes(), expected_bytes) self.assertEqual(addr.__class__, expected_class) if isinstance(addr, CBase58BitcoinAddress): self.assertEqual(addr.base58_prefix[0], expected_version) elif isinstance(addr, CBech32BitcoinAddress): self.assertEqual(addr.witver, expected_version)
def T(str_addr: str, expected_bytes: bytes, expected_version: int, expected_class: type) -> None: addr = CCoinAddress(str_addr) addr2 = CBitcoinAddress(str_addr) self.assertEqual(addr, addr2) self.assertEqual(type(addr), type(addr2)) self.assertEqual(bytes(addr), expected_bytes) self.assertEqual(addr.__class__, expected_class) if isinstance(addr, CBase58BitcoinAddress): self.assertEqual(addr.base58_prefix[0], expected_version) elif isinstance(addr, CBech32BitcoinAddress): self.assertEqual(addr.bech32_witness_version, expected_version)
def getnewaddress(self, account=None): """Return a new Bitcoin address for receiving payments. If account is not None, it is added to the address book so payments received with the address will be credited to account. """ r = None if account is not None: r = self._call('getnewaddress', account) else: r = self._call('getnewaddress') return CBitcoinAddress(r)
def _address_from_vout(self, txid, vout): script = vout.scriptPubKey if len(script) >= 38 and script[:6] == bitcoin.core.WITNESS_COINBASE_SCRIPTPUBKEY_MAGIC: return try: script = CScript(vout.scriptPubKey) if script.is_unspendable(): self.log.warn("Unspendable %s" % vout.scriptPubKey) if vout.scriptPubKey[2:4] == b'\xfe\xab': m = vout.scriptPubKey[4:].decode('utf-8') Message.create(message=m) return return str(TX_CBitcoinAddress.from_scriptPubKey(script)) except: self.log.warn('scriptPubKey invalid txid=%s scriptPubKey=%s value=%s' % (txid, b2lx(vout.scriptPubKey), vout.nValue))
def payment_ack(serialized_Payment_message): """Generates a PaymentACK object, captures client refund address and returns a message""" pao = o.PaymentACK() pao.payment.ParseFromString(serialized_Payment_message) pao.memo = 'String shown to user after payment confirmation' refund_address = CBitcoinAddress.from_scriptPubKey( CScript(pao.payment.refund_to[0].script)) sds_pa = pao.SerializeToString() open('sds_pa_blob', 'wb').write(sds_pa) headers = { 'Content-Type': 'application/bitcoin-payment', 'Accept': 'application/bitcoin-paymentack' } http_response_object = urllib2.Request('file:sds_pa_blob', None, headers) return http_response_object
def parse_vout(self, tx, txid, tx_data, vout, idx, batch=None, blockHeight=None): script = vout.scriptPubKey if len(script) >= 38 and script[:6] == bitcoin.core.WITNESS_COINBASE_SCRIPTPUBKEY_MAGIC: return try: script = CScript(vout.scriptPubKey) if script.is_unspendable(): self.log.warn("Unspendable %s" % vout.scriptPubKey) if vout.scriptPubKey[2:4] == b'\xfe\xab': m = vout.scriptPubKey[4:].decode('utf-8') Message.create(message=m) return address = str(TX_CBitcoinAddress.from_scriptPubKey(script)) except: self.log.warn('scriptPubKey invalid txid=%s scriptPubKey=%s value=%s' % (txid, b2lx(vout.scriptPubKey), vout.nValue)) return value = vout.nValue self.pututxo(txid, idx, address, value, wb=batch, scriptPubKey=vout.scriptPubKey.hex(), blockHeight=blockHeight) tx_data["vout"].append({"address": address, "value": value, "vout": idx}) if address in tx_data["addresses_out"]: tx_data["addresses_out"][address] += value else: tx_data["addresses_out"][address] = value tx_data["output_value"] += value # Update address tracking only when non-mempool (batch is not none) if batch: self.log.debug("Updating address %s with value %s" % (address, value)) if address in self.address_changes: self.address_changes[address]['balance'] += value self.address_changes[address]['received'] += value else: self.address_changes[address] = { 'balance': value, 'received': value, 'sent': 0, }
def T(str_addr: str) -> None: addr = CBitcoinAddress(str_addr) with self.assertRaises(NotImplementedError): addr.to_redeemScript()
RPC_PORT = 9332 BASE58_PREFIXES = { 'PUBKEY_ADDR': 48, 'SCRIPT_ADDR': 50, 'SECRET_KEY': 176, 'EXTENDED_PUBKEY': b'\x04\x88\xB2\x1E', 'EXTENDED_PRIVKEY': b'\x04\x88\xAD\xE4' } BECH32_HRP = 'ltc' BASE58_PREFIX_ALIAS = {5: 50} if __name__ == '__main__': SelectAlternativeParams(CoreLitecoinParams, MainLitecoinParams) canonical_adr = 'MMDkQMv8pGGmAXdVyxaW8YtQMCHw7eouma' legacy_adr = '3F1c6UWAs9RLN2Mbt5bAJue12VhVCorXzs' adr = CBitcoinAddress(legacy_adr) assert str(adr) == canonical_adr print("") print("Litecoin address", legacy_adr) print("is an alias to ", adr) print("but with P2SH script prefix 5 - the same as used by bitcoin.") print("Litecoin still supports this 'legacy' encoding after") print("introducing their native script prefix") print("")
def T(str_addr, expected_scriptPubKey_hexbytes): addr = CBitcoinAddress(str_addr) actual_scriptPubKey = addr.to_redeemScript() self.assertEqual(b2x(actual_scriptPubKey), expected_scriptPubKey_hexbytes)
def T(hex_scriptpubkey: str, expected_str_address: str, expected_class: type) -> None: scriptPubKey = CScript(x(hex_scriptpubkey)) addr = CBitcoinAddress.from_scriptPubKey(scriptPubKey) self.assertEqual(str(addr), expected_str_address) self.assertEqual(addr.__class__, expected_class)
seckey = CBitcoinKey.from_secret_bytes(h) # Create a redeemScript. Similar to a scriptPubKey the redeemScript must be # satisfied for the funds to be spent. txin_redeemScript = CScript([seckey.pub, OP_CHECKSIG]) print(b2x(txin_redeemScript)) # Create the magic P2SH scriptPubKey format from that redeemScript. You should # look at the CScript.to_p2sh_scriptPubKey() function in bitcointx.core.script # to understand what's happening, as well as read BIP16: # https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey() # Convert the P2SH scriptPubKey to a base58 Bitcoin address and print it. # You'll need to send some funds to it to create a txout to spend. txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey) print('Pay to:', str(txin_p2sh_address)) # Same as the txid:vout the createrawtransaction RPC call requires # # lx() takes *little-endian* hex and converts it to bytes; in Bitcoin # transaction hashes are shown little-endian rather than the usual big-endian. # There's also a corresponding x() convenience function that takes big-endian # hex and converts it to bytes. txid = lx('bff785da9f8169f49be92fa95e31f0890c385bfb1bd24d6b94d7900057c617ae') vout = 0 # Create the txin structure, which includes the outpoint. The scriptSig # defaults to being empty. txin = CMutableTxIn(COutPoint(txid, vout))
def T(str_addr: str, expected_scriptPubKey_hexbytes: str) -> None: addr = CBitcoinAddress(str_addr) actual_scriptPubKey = addr.to_scriptPubKey() self.assertEqual(b2x(actual_scriptPubKey), expected_scriptPubKey_hexbytes)
# defaults to being empty. txin = CMutableTxIn(COutPoint(txid, vout)) # We also need the scriptPubKey of the output we're spending because # SignatureHash() replaces the transaction scriptSig's with it. # # Here we'll create that scriptPubKey from scratch using the pubkey that # corresponds to the secret key we generated above. txin_scriptPubKey = \ P2PKHBitcoinAddress.from_pubkey(seckey.pub).to_scriptPubKey() # Create the txout. This time we create the scriptPubKey from a Bitcoin # address. txout = CMutableTxOut( 0.001 * COIN, CBitcoinAddress('1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8').to_scriptPubKey()) # Create the unsigned transaction. tx = CMutableTransaction([txin], [txout]) # Calculate the signature hash for that transaction. sighash = SignatureHash(txin_scriptPubKey, tx, 0, SIGHASH_ALL) # Now sign it. We have to append the type of signature we want to the end, in # this case the usual SIGHASH_ALL. sig = seckey.sign(sighash) + bytes([SIGHASH_ALL]) # Set the scriptSig of our transaction input appropriately. txin.scriptSig = CScript([sig, seckey.pub]) # Verify the signature worked. This calls EvalScript() and actually executes
def getaccountaddress(self, account=None): """Return the current Bitcoin address for receiving payments to this account.""" r = self._call('getaccountaddress', account) return CBitcoinAddress(r)