Bitcoin Forum
May 12, 2024, 04:05:29 AM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: « 1 2 [3]  All
  Print  
Author Topic: Python code for validating bitcoin address  (Read 47516 times)
super3
Legendary
*
Offline Offline

Activity: 1094
Merit: 1006


View Profile WWW
July 18, 2013, 11:17:25 PM
 #41

Is there any standalone Python code floating around out there? This is what I am using right now:

Code:
	def validate_address(self, address):
"""
Does simple validation of a bitcoin-like address.
Source: http://bit.ly/17OhFP5

param : address : an ASCII or unicode string, of a bitcoin address.
returns : boolean, indicating that the address has a correct format.

"""

address = self.clean(address)
# The first character indicates the "version" of the address.
CHARS_OK_FIRST = "123"
# alphanumeric characters without : l I O 0
CHARS_OK = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"

# We do not check the high length limit of the address.
# Usually, it is 35, but nobody knows what could happen in the future.
if len(address) < 27:
return False
elif address[0] not in CHARS_OK_FIRST:
return False

# We use the function "all" by passing it an enumerator as parameter.
# It does a little optimization :
# if one of the character is not valid, the next ones are not tested.
return all( ( char in CHARS_OK for char in address[1:] ) )

Bitcoin Dev / Storj - Decentralized Cloud Storage. Winner of Texas Bitcoin Conference Hackathon 2014. / Peercoin Web Lead / Primecoin Web Lead / Armory Guide Author / "Am I the only one that trusts Dogecoin more than the Federal Reserve?"
1715486729
Hero Member
*
Offline Offline

Posts: 1715486729

View Profile Personal Message (Offline)

Ignore
1715486729
Reply with quote  #2

1715486729
Report to moderator
1715486729
Hero Member
*
Offline Offline

Posts: 1715486729

View Profile Personal Message (Offline)

Ignore
1715486729
Reply with quote  #2

1715486729
Report to moderator
If you want to be a moderator, report many posts with accuracy. You will be noticed.
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
1715486729
Hero Member
*
Offline Offline

Posts: 1715486729

View Profile Personal Message (Offline)

Ignore
1715486729
Reply with quote  #2

1715486729
Report to moderator
1715486729
Hero Member
*
Offline Offline

Posts: 1715486729

View Profile Personal Message (Offline)

Ignore
1715486729
Reply with quote  #2

1715486729
Report to moderator
1715486729
Hero Member
*
Offline Offline

Posts: 1715486729

View Profile Personal Message (Offline)

Ignore
1715486729
Reply with quote  #2

1715486729
Report to moderator
airborne305
Newbie
*
Offline Offline

Activity: 27
Merit: 0


View Profile
January 04, 2014, 10:43:39 PM
 #42

This is regardless of whatever language you are trying to use and will require a bitcoind wallet running on your machine. basically take whatever text field that has the string you're trying to validate and turn it into a variable.


in your app or web page... textbox = $varAddress

onclick or script... whatever, send this to the wallet.
bitcoind validateaddress $varAddress

monitor response from [isvalid]. if "true," execute code. if false, execute other code.



Valid Address: [isvalid] = true            [address] = submitted address
Code:
server:~$ bitcoind validateaddress mkZuF2onXAxyGuuvoALbPEesMg99uv6k7r
{
    "isvalid" : true,
    "address" : "mkZuF2onXAxyGuuvoALbPEesMg99uv6k7r",
    "ismine" : false
}


Invalid Address: [isvalid] = false
Code:
server:~$ bitcoind validateaddress mkZuF2onXAxyGuuvoALbPEeIMg99uv6k7r 
{
    "isvalid" : false
}


Invalid Address: [isvalid] = false
Code:
server:~$ bitcoind validateaddress 7kZuF2onXAxyGuuvoALbPEeIMg99uv6k7r
{
    "isvalid" : false
}

Podey
Newbie
*
Offline Offline

Activity: 3
Merit: 0


View Profile
January 19, 2014, 03:18:20 PM
 #43

I wrote an Ada version of the bitcoin address validation code and posted it at rosettacode.org.
The example address someone posted in this thread, "miwxGypTcHDXT3m4avmrMMC4co7XWqbG9r," gets reported as invalid, but it also gets reported as invalid by http://blockexplorer.com/q/checkaddress/miwxGypTcHDXT3m4avmrMMC4co7XWqbG9r
Does someone have a quick answer to this puzzle? Ada is a good language to write reliable code, so I think it would be a good idea to have reference code for Ada for key functions like this.

 
Podey
Newbie
*
Offline Offline

Activity: 3
Merit: 0


View Profile
January 20, 2014, 12:34:07 PM
 #44

OK, duh, the problem was with the version number. The address' version is 6F, which is bogus, but otherwise it is valid. Code which doesn't care about the version number will report the address as valid.
PyTis
Newbie
*
Offline Offline

Activity: 1
Merit: 0


View Profile
February 25, 2014, 11:47:14 PM
Last edit: February 26, 2014, 06:34:20 PM by PyTis
 #45

Special thanks to Gavin Anderson

So I re-worked Gavin's code just a little bit, so I could basically type cast a Bitcoin address.

Below is my code.  Please let me know if you find any issues.

Code:
#!/usr/bin/env python
"""
# Special thanks to Gavin Andresen from bitcointalk.org
# in reference to: https://bitcointalk.org/index.php?topic=1026.0
# Edited By/Author Josh Lee PyTis.com, I also release my changes into the
# public domain.
"""

class BTCaddress(str):
""" Custom Bitcoin Address Verify-turend into a type for type-casting.
"""
import re

address_pattern = "[a-zA-Z1-9]{27,35}$"
address_expr = re.compile(r"%s"%address_pattern)
__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
__b58base = len(__b58chars)
_valid = False
_version = None

def __new__(cls,val):
if val is None:
# allow None to be passed in, so that we may clear out bitcoin addresses
# if you want, youc an raise an error instead, so that None doesn't pass silently
inst = str.__new__(cls, None)
inst._valid = False
inst._version = None
return inst

# I don't know if there could be a valid address with only numbers, but just in-case
if isinstance(val, int): val = str(val)

# remove preceading and trailing whitespace
if isinstance(val, basestring):
val = val.strip()
if not val:
# again, allow '' to be passed in, so that we may clear out bitcoin addresses
# if you want, you can raise an error instead, so that None doesn't pass silently
inst = str.__new__(cls, None)
inst._valid = False
inst._version = None
return inst
else:
if not cls.address_expr.match(val):
raise ValueError('Invalid Bitcoin address. Bad RE match r"%s".' % cls.address_pattern)
version = cls.getVersion(val)
if version is None:
raise ValueError('Invalid Bitcoin address. Version Missmatch: %r' % version)
else:
inst = str.__new__(cls, val)
inst._valid = True
inst._version = version
return inst
else:
raise TypeError('Invalid Bitcoin address. Not a string.')

valid = property(lambda s: s._valid)
version = property(lambda s: s._version)

@classmethod
def getVersion(cls, strAddress):
""" Returns None if strAddress is invalid. Otherwise returns integer version of address. """
from Crypto.Hash import SHA256
addr = cls.b58decode(strAddress,25)
if addr is None: return None
version = addr[0]
checksum = addr[-4:]
vh160 = addr[:-4] # Version plus hash160 is what is checksummed
h3=SHA256.new(SHA256.new(vh160).digest()).digest()
if h3[0:4] == checksum:
return ord(version)
return None

@classmethod
def b58encode(cls, v):
""" encode v, which is a string of bytes, to base58.
"""
long_value = 0L
for (i, c) in enumerate(v[::-1]):
long_value += (256**i) * ord(c)
result = ''
while long_value >= cls.__b58base:
div, mod = divmod(long_value, cls.__b58base)
result = cls.__b58chars[mod] + result
long_value = div
result = cls.__b58chars[long_value] + result

# Bitcoin does a little leading-zero-compression:
# leading 0-bytes in the input become leading-1s
nPad = 0
for c in v:
if c == '\0': nPad += 1
else: break

return (cls.__b58chars[0]*nPad) + result

@classmethod
def b58decode(cls, v, length):
""" decode v into a string of len bytes
"""
long_value = 0L
for (i, c) in enumerate(v[::-1]):
long_value += cls.__b58chars.find(c) * (cls.__b58base**i)

result = ''
while long_value >= 256:
div, mod = divmod(long_value, 256)
result = chr(mod) + result
long_value = div
result = chr(long_value) + result

nPad = 0
for c in v:
if c == cls.__b58chars[0]: nPad += 1
else: break

result = chr(0)*nPad + result
if length is not None and len(result) != length:
return None

return result

# - - - - - - - - - - - - - -
# END OF Custom Type class.
#



#
# tests below
# I found a page on a bitcoin wiki to explain to me different bitcoin address
# versions, I decided to test these, and other things that could go wrong.
# I then altered my code above, to get desired results.
#
# For more information on bitcoin address versions, please follow link:
# https://en.bitcoin.it/wiki/List_of_address_prefixes

tests = [
'17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem', # version 0 || TEST 1
u'3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX', # version 5 || TEST 2
'LhK2kQwiaAvhjWY799cZvMyYwnQAcxkarr', # vesrion 48 || TEST 3
'NATX6zEUNfxfvgVwz8qVnnw3hLhhYXhgQn', # version 52 || TEST 4
'mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn', # version 111 || TEST 5
'5Hwgr3u458GLafKBgxtssHSPqJnYoGrSzgQsPwLFhLNYskDPyyA', # version 128 || TEST 6
'92Pg46rUhgTT7romnV7iGW6W1gbGdeezqdbJCzShkCsYNzyyNcc', # version 239 || TEST 7
None, # testing None, No version || TEST 8
' 1111111111111111111114oLvT2', # test from https://bitcointalk.org/index.php?topic=1026.0 || TEST 9
float(123456789.01), #|| TEST 10
bool(True), # || TEST 11
'', # || TEST 12
'1NnZEPLmBEK2HryY4heeJQhQPB8LLbNiPe' # my bitcoin address :-) || TEST 13
]

for i, test in enumerate(tests):
print '-'*80
print 'typeof test: ', type(test)
print 'original value: ', test
try:
t = BTCaddress(test)
except TypeError, e:
print "TypeError: %s" % str(e)
except  ValueError, e:
print "ValueError: %s" % str(e)
else:
print 'test %s' % i, t
print 'test %s.type' % i, type(t)
print 'test %s.valid' % i, t.valid
print 'test %s.version' % i, t.version
print 't.getVersion()', t.getVersion(str(t))

print


-- fixed

Test output below:
Quote
--------------------------------------------------------------------------------
typeof test:  <type 'str'>
original value:  17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem
test 0 17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem
test 0.type <class '__main__.BTCaddress'>
test 0.valid True
test 0.version 0
--------------------------------------------------------------------------------
typeof test:  <type 'unicode'>
original value:  3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX
test 1 3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX
test 1.type <class '__main__.BTCaddress'>
test 1.valid True
test 1.version 5
--------------------------------------------------------------------------------
typeof test:  <type 'str'>
original value:  LhK2kQwiaAvhjWY799cZvMyYwnQAcxkarr
test 2 LhK2kQwiaAvhjWY799cZvMyYwnQAcxkarr
test 2.type <class '__main__.BTCaddress'>
test 2.valid True
test 2.version 48
--------------------------------------------------------------------------------
typeof test:  <type 'str'>
original value:  NATX6zEUNfxfvgVwz8qVnnw3hLhhYXhgQn
test 3 NATX6zEUNfxfvgVwz8qVnnw3hLhhYXhgQn
test 3.type <class '__main__.BTCaddress'>
test 3.valid True
test 3.version 52
--------------------------------------------------------------------------------
typeof test:  <type 'str'>
original value:  mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn
test 4 mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn
test 4.type <class '__main__.BTCaddress'>
test 4.valid True
test 4.version 111
--------------------------------------------------------------------------------
typeof test:  <type 'str'>
original value:  5Hwgr3u458GLafKBgxtssHSPqJnYoGrSzgQsPwLFhLNYskDPyyA
ValueError: Invalid Bitcoin address. Bad RE match r"[a-zA-Z1-9]{27,35}$".
--------------------------------------------------------------------------------
typeof test:  <type 'str'>
original value:  92Pg46rUhgTT7romnV7iGW6W1gbGdeezqdbJCzShkCsYNzyyNcc
ValueError: Invalid Bitcoin address. Bad RE match r"[a-zA-Z1-9]{27,35}$".
--------------------------------------------------------------------------------
typeof test:  <type 'NoneType'>
original value:  None
test 7 None
test 7.type <class '__main__.BTCaddress'>
test 7.valid False
test 7.version None
--------------------------------------------------------------------------------
typeof test:  <type 'str'>
original value:   1111111111111111111114oLvT2
test 8 1111111111111111111114oLvT2
test 8.type <class '__main__.BTCaddress'>
test 8.valid True
test 8.version 0
--------------------------------------------------------------------------------
typeof test:  <type 'float'>
original value:  123456789.01
TypeError: Invalid Bitcoin address. Not a string.
--------------------------------------------------------------------------------
typeof test:  <type 'bool'>
original value:  True
ValueError: Invalid Bitcoin address. Bad RE match r"[a-zA-Z1-9]{27,35}$".
--------------------------------------------------------------------------------
typeof test:  <type 'str'>
original value:  
test 11 None
test 11.type <class '__main__.BTCaddress'>
test 11.valid False
test 11.version None
--------------------------------------------------------------------------------
typeof test:  <type 'str'>
original value:  1NnZEPLmBEK2HryY4heeJQhQPB8LLbNiPe
test 12 1NnZEPLmBEK2HryY4heeJQhQPB8LLbNiPe
test 12.type <class '__main__.BTCaddress'>
test 12.valid True
test 12.version 0

-- last fix was just a typo in a code's comment
kadoban
Newbie
*
Offline Offline

Activity: 16
Merit: 0


View Profile WWW
March 18, 2014, 11:42:15 AM
 #46

A few people mentioned a 27 character bitcoin address, but there's been no mention that 26 character addresses exist. 11111111111111111111ufYVpS is an example.  The odds of it actually coming up in practice seem astronomical, but it is still valid (and a couple of the code examples here give a false negative for it).
Pages: « 1 2 [3]  All
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!