| # |
| # DJango field type for a Bitcoin Address |
| # |
| importre |
| fromdjangoimportforms |
| fromdjango.forms.utilimportValidationError |
| fromCrypto.HashimportSHA256 |
|
| classBCAddressField(forms.CharField): |
| default_error_messages= { |
| 'invalid': 'Invalid Bitcoin address.', |
| } |
|
| def__init__(self, *args, **kwargs): |
| super(BCAddressField, self).__init__(*args, **kwargs) |
|
| defclean(self, value): |
| value=value.strip() |
| ifre.match(r"[a-zA-Z1-9]{27,35}$", value) isNone: |
| raiseValidationError(self.error_messages['invalid']) |
| version=get_bcaddress_version(value) |
| ifversionisNone: |
| raiseValidationError(self.error_messages['invalid']) |
| returnvalue |
|
| importmath |
|
| __b58chars='123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' |
| __b58base=len(__b58chars) |
|
| defb58encode(v): |
| """ encode v, which is a string of bytes, to base58. |
| """ |
|
| long_value=0L |
| for (i, c) inenumerate(v[::-1]): |
| long_value+= (256**i) *ord(c) |
|
| result='' |
| whilelong_value>=__b58base: |
| div, mod=divmod(long_value, __b58base) |
| result=__b58chars[mod] +result |
| long_value=div |
| result=__b58chars[long_value] +result |
|
| # Bitcoin does a little leading-zero-compression: |
| # leading 0-bytes in the input become leading-1s |
| nPad=0 |
| forcinv: |
| ifc=='\0': nPad+=1 |
| else: break |
|
| return (__b58chars[0]*nPad) +result |
|
| defb58decode(v, length): |
| """ decode v into a string of len bytes |
| """ |
| long_value=0L |
| for (i, c) inenumerate(v[::-1]): |
| long_value+=__b58chars.find(c) * (__b58base**i) |
|
| result='' |
| whilelong_value>=256: |
| div, mod=divmod(long_value, 256) |
| result=chr(mod) +result |
| long_value=div |
| result=chr(long_value) +result |
|
| nPad=0 |
| forcinv: |
| ifc==__b58chars[0]: nPad+=1 |
| else: break |
|
| result=chr(0)*nPad+result |
| iflengthisnotNoneandlen(result) !=length: |
| returnNone |
|
| returnresult |
|
| defget_bcaddress_version(strAddress): |
| """ Returns None if strAddress is invalid. Otherwise returns integer version of address. """ |
| addr=b58decode(strAddress,25) |
| ifaddrisNone: returnNone |
| version=addr[0] |
| checksum=addr[-4:] |
| vh160=addr[:-4] # Version plus hash160 is what is checksummed |
| h3=SHA256.new(SHA256.new(vh160).digest()).digest() |
| ifh3[0:4] ==checksum: |
| returnord(version) |
| returnNone |
-
-
-