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}}==