RosettaCodeData/Task/Bitcoin-address-validation/Phix/bitcoin-address-validation.phix
2019-09-12 10:33:56 -07:00

76 lines
3 KiB
Text

-- demo\rosetta\bitcoin_address_validation.exw
include builtins\sha256.e
constant b58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
string charmap = ""
function valid(string s, bool expected)
bool res := (expected==false)
if charmap="" then
charmap = repeat('\0',256)
for i=1 to length(b58) do
charmap[b58[i]] = i
end for
end if
-- not at all sure about this:
-- if length(s)!=34 then
-- return {res,"bad length"}
-- end if
if not find(s[1],"13") then
return {res,"first character is not 1 or 3"}
end if
string out = repeat('\0',25)
for i=1 to length(s) do
integer c = charmap[s[i]]
if c=0 then
return {res,"bad char"}
end if
c -= 1
for j=25 to 1 by -1 do
c += 58 * out[j];
out[j] = and_bits(c,#FF)
c = floor(c/#100)
end for
if c!=0 then
return {res,"address too long"}
end if
end for
if out[1]!='\0' then
return {res,"not version 0"}
end if
if out[22..$]!=sha256(sha256(out[1..21]))[1..4] then
return {res,"bad digest"}
end if
res := (expected==true)
return {res,"OK"}
end function
constant tests = {{"1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9",true}, -- OK
{"1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9",false}, -- bad digest
{"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",true}, -- OK
{"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62j",false}, -- bad disgest
{"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62X",false}, -- bad digest (checksum changed, original data.)
{"1ANNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",false}, -- bad digest (data changed, original checksum.)
{"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62iz",false}, -- not version 0
{"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62izz",false}, -- address too long
{"1BGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",false}, -- bad digest
{"1A Na15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",false}, -- bad char
{"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I",false}, -- bad char
{"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62!",false}, -- bad char
{"1AGNa15ZQXAZUgFiqJ3i7Z2DPU2J6hW62i",false}, -- bad digest
{"1111111111111111111114oLvT2", true}, -- OK
{"17NdbrSGoUotzeGCcMMCqnFkEvLymoou9j",true}, -- OK
{"1badbadbadbadbadbadbadbadbadbadbad",false}, -- not version 0
{"BZbvjr",false}, -- first character is not 1 or 3 (checksum is fine, address too short)
{"i55j",false}, -- first character is not 1 or 3 (checksum is fine, address too short)
{"16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM", true}, -- OK (from public_point_to_address)
$}
for i=1 to length(tests) do
{string ti, bool expected} = tests[i]
{bool res, string coin_err} = valid(ti,expected)
if not res then
printf(1,"%s: %s\n", {ti, coin_err})
{} = wait_key()
end if
end for