Bitcoin/address validation: Difference between revisions

Added nim implementation.
m (rev4 now in sha256.e)
(Added nim implementation.)
Line 1,202:
1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I -> invalid
</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}}==
Anonymous user