Bitcoin/address validation: Difference between revisions
Content added Content deleted
(Added a test on address length.) |
(Added Wren) |
||
Line 2,333: | Line 2,333: | ||
fi |
fi |
||
}</lang> |
}</lang> |
||
=={{header|Wren}}== |
|||
{{trans|Kotlin}} |
|||
{{libheader|Wren-crypto}} |
|||
{{libheader|wren-str}} |
|||
{{libheader|Wren-fmt}} |
|||
<lang ecmascript>import "/crypto" for Sha256 |
|||
import "/str" for Str |
|||
import "/fmt" for Conv, Fmt |
|||
class Bitcoin { |
|||
static alphabet_ { "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" } |
|||
static contentEquals_(ba1, ba2) { |
|||
if (ba1.count != ba2.count) return false |
|||
return !(0...ba1.count).any { |i| ba1[i] != ba2[i] } |
|||
} |
|||
static decodeBase58_(input) { |
|||
var output = List.filled(25, 0) |
|||
for (c in input) { |
|||
var p = alphabet_.indexOf(c) |
|||
if (p == -1) return null |
|||
for (j in 24..1) { |
|||
p = p + 58 * output[j] |
|||
output[j] = p % 256 |
|||
p = p >> 8 |
|||
} |
|||
if (p != 0) return null |
|||
} |
|||
return output |
|||
} |
|||
static sha256_(data, start, len, recursion) { |
|||
if (recursion == 0) return data |
|||
var md = Sha256.digest(data[start...start+len]) |
|||
md = Str.chunks(md, 2).map { |x| Conv.atoi(x, 16) }.toList |
|||
return sha256_(md, 0, 32, recursion-1) |
|||
} |
|||
static validateAddress(address) { |
|||
var len = address.count |
|||
if (len < 26 || len > 35) return false |
|||
var decoded = decodeBase58_(address) |
|||
if (!decoded) return false |
|||
var hash = sha256_(decoded, 0, 21, 2) |
|||
return contentEquals_(hash[0..3], decoded[21..24]) |
|||
} |
|||
} |
|||
var addresses = [ |
|||
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", |
|||
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62j", |
|||
"1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9", |
|||
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62X", |
|||
"1ANNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", |
|||
"1A Na15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", |
|||
"BZbvjr", |
|||
"i55j", |
|||
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62!", |
|||
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62iz", |
|||
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62izz", |
|||
"1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9", |
|||
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I" |
|||
] |
|||
for (address in addresses) { |
|||
Fmt.print("$-36s -> $s", address, Bitcoin.validateAddress(address) ? "valid" : "invalid") |
|||
}</lang> |
|||
{{out}} |
|||
<pre> |
|||
1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i -> valid |
|||
1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62j -> invalid |
|||
1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9 -> valid |
|||
1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62X -> invalid |
|||
1ANNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i -> invalid |
|||
1A Na15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i -> invalid |
|||
BZbvjr -> invalid |
|||
i55j -> invalid |
|||
1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62! -> invalid |
|||
1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62iz -> invalid |
|||
1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62izz -> invalid |
|||
1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9 -> invalid |
|||
1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I -> invalid |
|||
</pre> |
|||
=={{header|zkl}}== |
=={{header|zkl}}== |