Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
|
|
@ -0,0 +1,80 @@
|
|||
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:
|
||||
if vector[0] notin {'1', '3'}:
|
||||
raise newException(ValueError, "invalid starting character")
|
||||
if vector.len < 26:
|
||||
raise newException(ValueError, "address too short")
|
||||
|
||||
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()
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
import nimcrypto
|
||||
import strformat
|
||||
|
||||
const
|
||||
|
||||
DecodedLength = 25 # Decoded address length.
|
||||
CheckSumLength = 4 # Checksum length in address.
|
||||
|
||||
# Representation of a decoded address.
|
||||
type Bytes25 = array[DecodedLength, byte]
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
|
||||
proc base58Decode(input: string): Bytes25 =
|
||||
## Decode a base58 encoded bitcoin address.
|
||||
|
||||
const Base = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
||||
|
||||
for ch in input:
|
||||
|
||||
var n = Base.find(ch)
|
||||
if n < 0:
|
||||
raise newException(ValueError, "invalid character: " & ch)
|
||||
|
||||
for i in countdown(result.high, 0):
|
||||
n += 58 * result[i].int
|
||||
result[i] = byte(n and 255)
|
||||
n = n div 256
|
||||
|
||||
if n != 0:
|
||||
raise newException(ValueError, "decoded address is too long")
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
|
||||
proc verifyChecksum(data: Bytes25) =
|
||||
## Verify that data has the expected checksum.
|
||||
|
||||
var digest = sha256.digest(data.toOpenArray(0, data.high - CheckSumLength))
|
||||
digest = sha256.digest(digest.data)
|
||||
if digest.data[0..<CheckSumLength] != data[^CheckSumLength..^1]:
|
||||
raise newException(ValueError, "wrong checksum")
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
|
||||
proc checkValidity(address: string) =
|
||||
## Check the validity of a bitcoin address.
|
||||
|
||||
try:
|
||||
if address[0] notin {'1', '3'}:
|
||||
raise newException(ValueError, "starting character is not 1 or 3")
|
||||
if address.len < 26:
|
||||
raise newException(ValueError, "address too short")
|
||||
|
||||
address.base58Decode().verifyChecksum()
|
||||
echo fmt"Address “{address}” is valid."
|
||||
|
||||
except ValueError:
|
||||
echo fmt"Address “{address}” is invalid ({getCurrentExceptionMsg()})."
|
||||
|
||||
|
||||
#———————————————————————————————————————————————————————————————————————————————————————————————————
|
||||
|
||||
const testVectors : seq[string] = @[
|
||||
"3yQ", # Invalid.
|
||||
"1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9", # Valid.
|
||||
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", # Valid.
|
||||
"1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9", # Invalid.
|
||||
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I", # Invalid.
|
||||
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62ix", # Invalid.
|
||||
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62ixx", # Invalid.
|
||||
"17NdbrSGoUotzeGCcMMCqnFkEvLymoou9j", # Valid.
|
||||
"1badbadbadbadbadbadbadbadbadbadbad", # Invalid.
|
||||
"16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM", # Valid.
|
||||
"1111111111111111111114oLvT2", # Valid.
|
||||
"BZbvjr"] # Invalid.
|
||||
|
||||
for vector in testVectors:
|
||||
vector.checkValidity()
|
||||
Loading…
Add table
Add a link
Reference in a new issue