Bitcoin/address validation: Difference between revisions
Content deleted Content added
→{{header|Python}}: Provided error capturing for addresses that cannot be decoded using the decode_base58 |
|||
Line 1,721: | Line 1,721: | ||
</pre> |
</pre> |
||
=={{header|Scala}}== |
|||
<lang Scala>import java.security.MessageDigest |
|||
import java.util.Arrays.copyOfRange |
|||
import scala.annotation.tailrec |
|||
import scala.math.BigInt |
|||
object BitcoinAddressValidator extends App { |
|||
private def bitcoinTestHarness(address: String, expected: Boolean): Unit = |
|||
assert(validateBitcoinAddress(address) == expected, s"Expected $expected for $address%s, but got ${!expected}.") |
|||
private def validateBitcoinAddress(addr: String): Boolean = { |
|||
def sha256(data: Array[Byte]) = { |
|||
val md: MessageDigest = MessageDigest.getInstance("SHA-256") |
|||
md.update(data) |
|||
md.digest |
|||
} |
|||
def decodeBase58To25Bytes(input: String): Option[Array[Byte]] = { |
|||
def ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" |
|||
@tailrec |
|||
def loop(s: String, accu: BigInt): BigInt = { |
|||
if (s.isEmpty) accu |
|||
else { |
|||
val p = ALPHABET.indexOf(s.head) |
|||
if (p >= 0) loop(s.tail, accu * 58 + p) |
|||
else -1 |
|||
} |
|||
} |
|||
val num = loop(input, 0) |
|||
if (num >= 0) { |
|||
val (result, numBytes) = (new Array[Byte](25), num.toByteArray) |
|||
System.arraycopy(numBytes, 0, result, result.length - numBytes.length, numBytes.length) |
|||
Some(result) |
|||
} |
|||
else None |
|||
} |
|||
if (27 to 34 contains addr.length) { |
|||
val decoded = decodeBase58To25Bytes(addr) |
|||
if (decoded.isEmpty) false |
|||
else { |
|||
val hash1 = sha256(copyOfRange(decoded.get, 0, 21)) |
|||
copyOfRange(sha256(hash1), 0, 4) |
|||
.sameElements(copyOfRange(decoded.get, 21, 25)) |
|||
} |
|||
} else false |
|||
} // validateBitcoinAddress |
|||
bitcoinTestHarness("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", true) |
|||
bitcoinTestHarness("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62j", false) |
|||
bitcoinTestHarness("1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9", true) |
|||
bitcoinTestHarness("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62X", false) |
|||
bitcoinTestHarness("1ANNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", false) |
|||
bitcoinTestHarness("1A Na15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", false) |
|||
bitcoinTestHarness("BZbvjr", false) |
|||
bitcoinTestHarness("i55j", false) |
|||
bitcoinTestHarness("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62!", false) |
|||
bitcoinTestHarness("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62iz", false) |
|||
bitcoinTestHarness("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62izz", false) |
|||
bitcoinTestHarness("1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9", false) |
|||
bitcoinTestHarness("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I", false) |
|||
println(s"Successfully completed without errors. [total ${scala.compat.Platform.currentTime - executionStart}ms]") |
|||
}</lang> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
{{tcllib|sha256}} |
{{tcllib|sha256}} |