RosettaCodeData/Task/Bitcoin-address-validation/Pluto/bitcoin-address-validation.pluto
2026-04-30 12:34:36 -04:00

59 lines
1.8 KiB
Text

require "table2"
local crypto = require "crypto"
local fmt = require "fmt"
$define ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
local function decode_base58(input)
local output = table.rep(25, 0)
for i = 1, #input do
local c = input[i]
local p = ALPHABET:find(c, 1, true)
if !p then return nil end
p -= 1
for j = 25, 2, -1 do
p += 58 * output[j]
output[j] = p % 256
p >>= 8
end
if p != 0 then return nil end
end
return output
end
local function sha256(data, start, len, recursion)
if recursion == 0 then return data end
local ds = data:slice(start, start + len - 1)
local md = crypto.sha256(string.char(ds:unpack()))
md = md:split(""):chunk(2):map(|x| -> tonumber(x:concat(), 16))
return sha256(md, 1, 32, recursion - 1)
end
local function validate_address(address)
local len = #address
if len < 26 or len > 35 then return false end
local decoded = decode_base58(address)
if !decoded then return false end
local hash = sha256(decoded, 1, 21, 2)
return table.same(hash:slice(1, 4), decoded:slice(22, 25))
end
local addresses = {
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62j",
"1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9",
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62X",
"1ANNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",
"1A Na15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",
"BZbvjr",
"i55j",
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62!",
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62iz",
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62izz",
"1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9",
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I"
}
for addresses as address do
fmt.print("%-36s -> %s", address, validate_address(address) ? "valid" : "invalid")
end