Bitcoin/address validation: Difference between revisions
Content added Content deleted
m (rev4 now in sha256.e) |
(Added nim implementation.) |
||
Line 1,202: | Line 1,202: | ||
1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I -> invalid |
1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I -> invalid |
||
</pre> |
</pre> |
||
=={{header|Nim}}== |
|||
Requires libssl library to perform SHA256. Build with -d:ssl flag. |
|||
<lang nim>import algorithm |
|||
const SHA256Len = 32 |
|||
const AddrLen = 25 |
|||
const AddrMsgLen = 21 |
|||
const AddrChecksumOffset = 21 |
|||
const AddrChecksumLen = 4 |
|||
proc SHA256(d: pointer, n: culong, md: pointer = nil): cstring {.cdecl, dynlib: "libssl.so", importc.} |
|||
proc decodeBase58(inStr: string, outArray: var openarray[uint8]) = |
|||
let base = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" |
|||
outArray.fill(0) |
|||
for aChar in inStr: |
|||
var accum = base.find(aChar) |
|||
if accum < 0: |
|||
raise newException(ValueError, "Invalid character: " & $aChar) |
|||
for outIndex in countDown((AddrLen - 1), 0): |
|||
accum += 58 * outArray[outIndex].int |
|||
outArray[outIndex] = (accum mod 256).uint8 |
|||
accum = accum div 256 |
|||
if accum != 0: |
|||
raise newException(ValueError, "Address string too long") |
|||
proc verifyChecksum(addrData: openarray[uint8]) : bool = |
|||
let doubleHash = SHA256(SHA256(cast[ptr uint8](addrData), AddrMsgLen), SHA256Len) |
|||
for ii in 0 ..< AddrChecksumLen: |
|||
if doubleHash[ii].uint8 != addrData[AddrChecksumOffset + ii]: |
|||
return false |
|||
return true |
|||
proc main() = |
|||
let |
|||
testVectors : seq[string] = @[ |
|||
"3yQ", |
|||
"1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9", |
|||
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", |
|||
"1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9", |
|||
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I", |
|||
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62ix", |
|||
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62ixx", |
|||
"17NdbrSGoUotzeGCcMMCqnFkEvLymoou9j", |
|||
"1badbadbadbadbadbadbadbadbadbadbad", |
|||
"16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM", |
|||
"1111111111111111111114oLvT2", |
|||
"BZbvjr", |
|||
] |
|||
var |
|||
buf: array[AddrLen, uint8] |
|||
astr: string |
|||
for vector in testVectors: |
|||
stdout.write(vector & " : ") |
|||
try: |
|||
decodeBase58(vector, buf) |
|||
if buf[0] != 0: |
|||
stdout.write("NG - invalid version number\n") |
|||
elif verifyChecksum(buf): |
|||
stdout.write("OK\n") |
|||
else: |
|||
stdout.write("NG - checksum invalid\n") |
|||
except: |
|||
stdout.write("NG - " & getCurrentExceptionMsg() & "\n") |
|||
main() |
|||
</lang> |
|||
{{out}} |
|||
<pre> |
|||
3yQ : NG - checksum invalid |
|||
1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9 : OK |
|||
1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i : OK |
|||
1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9 : NG - checksum invalid |
|||
1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I : NG - Invalid character: I |
|||
1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62ix : NG - invalid version number |
|||
1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62ixx : NG - Address string too long |
|||
17NdbrSGoUotzeGCcMMCqnFkEvLymoou9j : OK |
|||
1badbadbadbadbadbadbadbadbadbadbad : NG - invalid version number |
|||
16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM : OK |
|||
1111111111111111111114oLvT2 : OK |
|||
BZbvjr : OK |
|||
</pre> |
|||
Note: The last two test addresses have valid checksums and conform to the specified address constraints. |
|||
=={{header|Oberon-2}}== |
=={{header|Oberon-2}}== |