Bitcoin/public point to address: Difference between revisions

Content deleted Content added
Grondilu (talk | contribs)
→‎{{header|Raku}}: use openssl for digests and simplify code slightly
PSNOW123 (talk | contribs)
m Realigning text comments.
 
(8 intermediate revisions by 4 users not shown)
Line 22:
 
''Extra credit:'' add a verification procedure about the public point, making sure it belongs to the secp256k1 elliptic curve
 
=={{header|C}}==
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <string.h>
#include <ctype.h>
Line 98 ⟶ 97:
0));
return 0;
}</langsyntaxhighlight>
 
=={{header|C++}}==
This example uses the C++ code from the SHA-256 and RIPEMD160 tasks. This slightly complicates the code because
the previous tasks were designed to hash a string of ASCII characters rather than a byte array. However, it
enables the task to be completed without the use of any external libraries.
<syntaxhighlight lang="c++">
#include <cstdint>
#include <iostream>
#include <map>
#include <string>
#include <vector>
 
#include "SHA256.cpp"
#include "RIPEMD160.cpp"
SHA256 sha256{ };
RIPEMD160 ripemd160{ };
 
const std::string BITCOIN_SPECIAL_VALUE = "04";
const std::string BITCOIN_VERSION_NUMBER = "00";
 
std::map<char, uint32_t> base_map =
{ { '0', 0 }, { '1', 1 }, { '2', 2 }, { '3', 3 }, { '4', 4 }, { '5', 5 }, { '6', 6 }, { '7', 7 },
{ '8', 8 }, { '9', 9 }, { 'a', 10 }, { 'b', 11 }, { 'c', 12 }, { 'd', 13 }, { 'e', 14 }, { 'f', 15 },
{ 'A', 10 }, { 'B', 11 }, { 'C', 12 }, { 'D', 13 }, { 'E', 14 }, { 'F', 15 } };
 
std::vector<uint32_t> hex_to_bytes(const std::string& text) {
std::vector<uint32_t> bytes(text.size() / 2, 0);
for ( uint64_t i = 0; i < text.size(); i += 2 ) {
const uint32_t first_digit = base_map[text[i]];
const uint32_t second_digit = base_map[text[i + 1]];
bytes[i / 2] = ( first_digit << 4 ) + second_digit;
}
return bytes;
}
 
std::string vector_to_ascii_string(const std::vector<uint32_t>& bytes) {
std::string result = "";
for ( uint64_t i = 0; i < bytes.size(); ++i ) {
result += static_cast<char>(bytes[i]);
}
return result;
}
 
std::vector<uint32_t> compute_message_bytes(const std::string& text) {
// Convert the hexadecimal string 'text' into a suitable ASCII string for the SHA256 hash
std::vector<uint32_t> bytes_1 = hex_to_bytes(text);
std::string ascii_1 = vector_to_ascii_string(bytes_1);
std::string hexSHA256 = sha256.message_digest(ascii_1);
// Convert the hexadecimal string 'hexSHA256' into a suitable ASCII string for the RIPEMD160 hash
std::vector<uint32_t> bytes_2 = hex_to_bytes(hexSHA256);
std::string ascii_2 = vector_to_ascii_string(bytes_2);
std::string hexRIPEMD160 = BITCOIN_VERSION_NUMBER + ripemd160.message_digest(ascii_2);
return hex_to_bytes(hexRIPEMD160);
}
 
std::vector<uint32_t> compute_checksum(const std::vector<uint32_t>& bytes) {
// Convert the given byte array into a suitable ASCII string for the first SHA256 hash
std::string ascii_1 = vector_to_ascii_string(bytes);
std::string hex_1 = sha256.message_digest(ascii_1);
// Convert the hexadecimal string 'hex1' into a suitable ASCII string for the second SHA256 hash
std::vector<uint32_t> bytes_1 = hex_to_bytes(hex_1);
std::string ascii_2 = vector_to_ascii_string(bytes_1);
std::string hex_2 = sha256.message_digest(ascii_2);
std::vector<uint32_t> bytes_2 = hex_to_bytes(hex_2);
std::vector<uint32_t> result(bytes_2.begin(), bytes_2.begin() + 4);
return result;
}
 
// Return the given byte array encoded into a base58 starting with most one '1'
std::string encode_base_58(std::vector<uint32_t> bytes) {
const std::string ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
const uint32_t ALPHABET_SIZE = ALPHABET.size();
 
std::string result(34, ' ');
for ( int64_t n = result.size() - 1; n >= 0; --n ) {
uint32_t c = 0;
for ( uint64_t i = 0; i < bytes.size(); ++i ) {
c = c * 256 + bytes[i];
bytes[i] = c / ALPHABET_SIZE;
c %= ALPHABET_SIZE;
}
result[n] = ALPHABET[c];
}
 
while ( result.starts_with("11") ) {
result = result.substr(1);
}
return result;
}
 
// Return the encoded address of the given coordinates.
std::string encode_address(const std::string& x, const std::string& y) {
std::string public_point = BITCOIN_SPECIAL_VALUE + x + y;
if ( public_point.size() != 130 ) {
throw std::invalid_argument("Invalid public point string");
}
 
std::vector<uint32_t> message_bytes = compute_message_bytes(public_point);
std::vector<uint32_t> checksum = compute_checksum(message_bytes);
message_bytes.insert(message_bytes.end(), checksum.begin(), checksum.end());
return encode_base_58(message_bytes);
}
 
int main() {
std::string x = "50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352";
std::string y = "2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6";
 
std::cout << encode_address(x, y) << std::endl;
}
</syntaxhighlight>
{{ out }}
<pre>
16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
</pre>
 
=={{header|Common Lisp}}==
{{libheader|Quicklisp}}
{{libheader|Ironclad}}
<langsyntaxhighlight lang="lisp">
;;;; This is a revised version, inspired by a throwaway script originally
;;;; published at http://deedbot.org/bundle-381528.txt by the same Adlai.
Line 206 ⟶ 319:
(base58enc (checksum (sovcat '(0) (digest '(ripemd-160 sha256) point)))))))
 
</syntaxhighlight>
</lang>
 
Here's an example of how to feed a point into the functions defined above:
 
<syntaxhighlight lang="text">
 
;; ? (pubkey-to-p2pkh
Line 218 ⟶ 331:
;; "16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM"
 
</syntaxhighlight>
</lang>
 
=={{header|D}}==
Requires the second D module from the SHA-256 task.
{{trans|C}}
{{trans|Go}}
<langsyntaxhighlight lang="d">import std.stdio, std.algorithm, std.digest.ripemd, sha_256_2;
 
// A Bitcoin public point.
Line 281 ⟶ 393:
 
p.bitcoinEncode.writeln;
}</langsyntaxhighlight>
{{out}}
<pre>16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM</pre>
Line 290 ⟶ 402:
{{libheader| DCPripemd160}}
{{Trans|Go}}
<syntaxhighlight lang="delphi">
<lang Delphi>
program Public_point_to_address;
 
Line 453 ⟶ 565:
writeln(a.ToBase58);
readln;
end.</langsyntaxhighlight>
 
=={{header|Factor}}==
<langsyntaxhighlight lang="factor">USING: checksums checksums.ripemd checksums.sha io.binary kernel
math sequences ;
IN: rosetta-code.bitcoin.point-address
Line 478 ⟶ 589:
dup 0 prefix btc-checksum
append 0 prefix >base58 ;
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 485 ⟶ 596:
point>address . ! "16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM"
</pre>
 
=={{header|Go}}==
{{libheader|Go sub-repositories}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 588 ⟶ 698:
// show base58 representation
fmt.Println(string(a.A58()))
}</langsyntaxhighlight>
{{out}}
<pre>
16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
</pre>
 
=={{header|Haskell}}==
<langsyntaxhighlight lang="haskell">import Numeric (showIntAtBase)
import Data.List (unfoldr)
import Data.Binary (Word8)
Line 615 ⟶ 724:
0x50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352
0x2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6
</syntaxhighlight>
</lang>
{{out}}
<pre>"6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM"
</pre>
 
=={{header|Java}}==
This example uses the Java code from the SHA-256 and RIPEMD-160 tasks. This slightly complicates the code because
the two previous tasks were designed to hash a string of ASCII characters rather than a byte array. However, it
enables the task to be completed without the use of any external libraries.
<syntaxhighlight lang="java">
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.stream.Collectors;
 
public final class BitcoinPublicPointToAddess {
 
public static void main(String[] args) {
String x = "50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352";
String y = "2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6";
if ( areValidCoordinates(x, y) ) {
System.out.println(encodeAddress(x, y));
} else {
System.out.println("Invalid Bitcoin public point coordinates");
}
}
// Return the encoded address of the given coordinates.
private static String encodeAddress(String x, String y) {
String publicPoint = BITCOIN_SPECIAL_VALUE + x + y;
if ( publicPoint.length() != 130 ) {
throw new AssertionError("Invalid public point string: " + publicPoint);
}
 
byte[] messageBytes = computeMessageBytes(publicPoint);
byte[] checksum = computeChecksum(messageBytes);
messageBytes = Arrays.copyOf(messageBytes, messageBytes.length + 4);
System.arraycopy(checksum, 0, messageBytes, 21, checksum.length);
return encodeBase58(messageBytes);
}
// Return the given byte array encoded into a base58 starting with most one '1'
private static String encodeBase58(byte[] bytes) {
final String ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
final int ALPHABET_SIZE = ALPHABET.length();
String[] temp = new String[34];
for ( int n = temp.length - 1; n >= 0; n-- ) {
int c = 0;
for ( int i = 0; i < bytes.length; i++ ) {
c = c * 256 + (int) ( bytes[i] & 0xFF );
bytes[i] = (byte) ( c / ALPHABET_SIZE );
c %= ALPHABET_SIZE;
}
temp[n] = ALPHABET.substring(c, c + 1);
}
String result = Arrays.stream(temp).collect(Collectors.joining(""));
while ( result.startsWith("11") ) {
result = result.substring(1);
}
return result;
}
// Return whether the given coordinates are those of a point on the secp256k1 elliptic curve
private static boolean areValidCoordinates(String x, String y) {
BigInteger modulus = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16);
BigInteger X = new BigInteger(x, 16);
BigInteger Y = new BigInteger(y, 16);
return Y.multiply(Y).mod(modulus).equals(X.multiply(X).multiply(X).add(BigInteger.valueOf(7)).mod(modulus));
}
private static byte[] computeMessageBytes(String text) {
// Convert the hexadecimal string 'text' into a suitable ASCII string for the SHA256 hash
byte[] bytesOne = hexToBytes(text);
String asciiOne = new String(bytesOne, StandardCharsets.ISO_8859_1);
String hexSHA256 = SHA256.messageDigest(asciiOne);
// Convert the hexadecimal string 'hexSHA256' into a suitable ASCII string for the RIPEMD160 hash
byte[] bytesTwo = hexToBytes(hexSHA256);
String asciiTwo = new String(bytesTwo, StandardCharsets.ISO_8859_1);
String hexRIPEMD160 = BITCOIN_VERSION_NUMBER + RIPEMD160.messageDigest(asciiTwo);
return hexToBytes(hexRIPEMD160);
}
private static byte[] computeChecksum(byte[] bytes) {
// Convert the given byte array into a suitable ASCII string for the first SHA256 hash
String asciiOne = new String(bytes, StandardCharsets.ISO_8859_1);
String hexOne = SHA256.messageDigest(asciiOne);
// Convert the hexadecimal string 'hex1' into a suitable ASCII string for the second SHA256 hash
byte[] bytesOne = hexToBytes(hexOne);
String asciiTwo = new String(bytesOne, StandardCharsets.ISO_8859_1);
String hexTwo = SHA256.messageDigest(asciiTwo);
return Arrays.copyOfRange(hexToBytes(hexTwo), 0, 4);
}
private static byte[] hexToBytes(String text) {
byte[] bytes = new byte[text.length() / 2];
for ( int i = 0; i < text.length(); i += 2 ) {
final int firstDigit = Character.digit(text.charAt(i), 16);
final int secondDigit = Character.digit(text.charAt(i + 1), 16);
bytes[i / 2] = (byte) ( ( firstDigit << 4 ) + secondDigit );;
}
return bytes;
}
private static final String BITCOIN_SPECIAL_VALUE = "04";
private static final String BITCOIN_VERSION_NUMBER = "00";
}
</syntaxhighlight>
{{ out }}
<pre>
16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
</pre>
 
Line 625 ⟶ 844:
 
'''Main functions''':
<langsyntaxhighlight lang="julia">const digits = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
function encodebase58(b::Vector{<:Integer})
out = Vector{Char}(34)
Line 652 ⟶ 871:
end
pubpoint2address(x::AbstractString, y::AbstractString) =
pubpoint2address(hex2bytes(x), hex2bytes(y))</langsyntaxhighlight>
 
'''Main''':
<langsyntaxhighlight lang="julia">x = "50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352"
y = "2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6"
println(pubpoint2address(x, y)))</langsyntaxhighlight>
 
{{out}}
<pre>6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM</pre>
 
=={{header|Wolfram Language}}/{{header|Mathematica}}==
<lang Mathematica>BlockchainKeyEncode[
PublicKey[
<|
"Type"->"EllipticCurve",
"PublicCurvePoint"-> {
16^^50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352,
16^^2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6
}
|>
],
"Address",
BlockchainBase-> "Bitcoin"
]</lang>
{{output}}
<pre>16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM</pre>
 
=={{header|Nim}}==
 
Line 689 ⟶ 890:
The “bignum” library is used to check if the public point belongs to the “secp256k1” elliptic curve.
 
<langsyntaxhighlight lang="nim">import parseutils
import nimcrypto
import bignum
Line 756 ⟶ 957:
"2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6")
echo "Coordinates are valid."
echo "Address is: ", address</langsyntaxhighlight>
 
{{out}}
<pre>Coordinates are valid.
Address is: 16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM</pre>
 
=={{header|Perl}}==
Here we'll use the standard Digest::SHA module, and the CPAN-available Crypt::RIPEMD160 and Encode::Base58::GMP.
<langsyntaxhighlight lang="perl">
use Crypt::RIPEMD160;
use Digest::SHA qw(sha256);
Line 785 ⟶ 985:
'2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6'
;
</syntaxhighlight>
</lang>
{{out}}
<pre>16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM</pre>
 
=={{header|Phix}}==
<!--<langsyntaxhighlight Phixlang="phix">(notonline)-->
<span style="color: #008080;">without</span> <span style="color: #008080;">javascript_semantics</span> <span style="color: #000080;font-style:italic;">-- no ripemd160.js as yet</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #7060A8;">sha256</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
Line 834 ⟶ 1,033:
<span style="color: #0000FF;">?</span><span style="color: #000000;">coin_encode</span><span style="color: #0000FF;">(</span>x"<span style="color: #0000FF;">50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352</span>"<span style="color: #0000FF;">,</span>
x"<span style="color: #0000FF;">2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6</span>"<span style="color: #0000FF;">)</span>
<!--</langsyntaxhighlight>-->
There is actually an sha256.js included, not that I recommend it.<br>
You could probably get this to work in a browser if you provide a suitable ripemd160.js and tweak p2js to use it.
Line 842 ⟶ 1,041:
"16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM"
</pre>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(load "ripemd160.l")
(load "sha256.l")
 
Line 882 ⟶ 1,080:
(point2address
"50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352"
"2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6" ) )</langsyntaxhighlight>
{{out}}
<pre>"16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM"</pre>
 
=={{header|Python}}==
<langsyntaxhighlight lang="python">#!/usr/bin/env python3
 
import binascii
Line 909 ⟶ 1,106:
print(public_point_to_address(
b'50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352',
b'2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6'))</langsyntaxhighlight>
{{out}}
<pre>
b'6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM'
</pre>
 
=={{header|Racket}}==
 
Uses code from [[SHA-256#Racket]] (which is isolated in a submodule).
 
<langsyntaxhighlight lang="racket">#lang racket/base
(module sha256 racket/base
;; define a quick SH256 FFI interface, similar to the Racket's default
Line 1,038 ⟶ 1,234:
(bytes->HEX-STRING s7) => "D61967F6"
(bytes->HEX-STRING s8) => "00010966776006953D5567439E5E39F86A0D273BEED61967F6"
s9 => #"16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM"))</langsyntaxhighlight>
 
{{out}}
Line 1,044 ⟶ 1,240:
1 test passed
8 tests passed</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
 
<syntaxhighlight lang="raku" perl6line>sub dgst(blob8 $b, Str :$dgst) returns blob8 {
given run «openssl dgst "-$dgst" -binary», :in, :out, :bin {
.in.write: $b;
Line 1,073 ⟶ 1,268:
0x50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352,
0x2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6;
</syntaxhighlight>
</lang>
{{out}}
<pre>6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM</pre>
 
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby">
# Translate public point to Bitcoin address
#
Line 1,100 ⟶ 1,294:
end
puts res.reverse
</syntaxhighlight>
</lang>
{{out}}
<pre>
6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
</pre>
 
=={{header|Rust}}==
<langsyntaxhighlight lang="rust">
use ring::digest::{digest, SHA256};
use ripemd160ripemd::{Digest, Ripemd160};
 
use hex::FromHex;
Line 1,174 ⟶ 1,367:
}
 
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,188 ⟶ 1,381:
which encodes a string with the Base58 encoding used by Bitcoin. No external library is needed.
 
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
include "bytedata.s7i";
include "msgdigest.s7i";
Line 1,207 ⟶ 1,400:
writeln(publicPointToAddress("50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352",
"2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6"));
end func;</langsyntaxhighlight>
 
{{out}}
Line 1,213 ⟶ 1,406:
16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
</pre>
 
=={{header|Tcl}}==
{{tcllib|ripemd160}}
{{tcllib|sha256}}
<langsyntaxhighlight lang="tcl">package require ripemd160
package require sha256
 
Line 1,245 ⟶ 1,437:
append addr [binary format "a4" [string range $hash 0 3]]
return [base58encode $addr]
}</langsyntaxhighlight>
Demonstrating
<langsyntaxhighlight lang="tcl">puts [bitcoin_mkaddr \
0x50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352 \
0x2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6]</langsyntaxhighlight>
{{out}}
<pre>
16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM
</pre>
=={{header|Wolfram Language}}/{{header|Mathematica}}==
 
<syntaxhighlight lang="mathematica">BlockchainKeyEncode[
PublicKey[
<|
"Type"->"EllipticCurve",
"PublicCurvePoint"-> {
16^^50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352,
16^^2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6
}
|>
],
"Address",
BlockchainBase-> "Bitcoin"
]</syntaxhighlight>
{{output}}
<pre>16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM</pre>
=={{header|Wren}}==
{{trans|Go}}
Line 1,260 ⟶ 1,467:
{{libheader|Wren-str}}
{{libheader|Wren-fmt}}
<langsyntaxhighlight ecmascriptlang="wren">import "./crypto" for Sha256, Ripemd160
import "./str" for Str
import "./fmt" for Conv
 
// converts an hexadecimal string to a byte list.
Line 1,354 ⟶ 1,561:
a.setPoint(p)
// show base58 representation
System.print(a.a58.map { |b| String.fromByte(b) }.join())</langsyntaxhighlight>
 
{{out}}
Line 1,363 ⟶ 1,570:
=={{header|zkl}}==
Uses shared library zklMsgHash.
<langsyntaxhighlight lang="zkl">var [const] MsgHash=Import.lib("zklMsgHash"); // SHA-256, etc
 
const symbols = "123456789" // 58 characters: no cap i,o; ell, zero
Line 1,389 ⟶ 1,596:
d,chkSum := Data(), MsgHash.SHA256(bytes,1,d) : MsgHash.SHA256(_,1,d);
base58Encode(bytes.append(chkSum.del(4,*))); // first 4 bytes of hashed hash
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">e:=coinEncode(
"50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352",
"2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6");
(e=="16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM").println();</langsyntaxhighlight>
{{out}}
<pre>True</pre>
 
 
{{omit from|Brlcad}}
{{omit from|GUISS}}