Skip to content

Commit

Permalink
Merge pull request #14 from pvyhnal-generalbytes/BPUB-805-convert-bech32
Browse files Browse the repository at this point in the history
Bpub 805 convert bech32
  • Loading branch information
rpanak-generalbytes authored Dec 19, 2018
2 parents 0826dd6 + 8cd0474 commit 9dca55e
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 1 deletion.
2 changes: 2 additions & 0 deletions bitrafael-client/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ dependencies {
compile(group: 'com.github.mmazi', name: 'rescu', version: '1.9.1')
runtime(group: 'org.slf4j', name: 'slf4j-api', version: '1.7.21')
runtime(group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.21')

testCompile(group: 'junit', name: 'junit', version: '4.10')
}

dependencySubstitutions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class Bech32 {

public static final String SEPARATOR = ":";
public static final String MAIN_NET_PREFIX = "bitcoincash";
public static final String CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";

private static final BigInteger[] POLYMOD_GENERATORS = new BigInteger[] {
Expand Down Expand Up @@ -123,6 +125,59 @@ public static String encodeHashToBech32Address(String humanPart, int version, by
return encodeToCharset(payloadData);
}


public static byte[] decodeCashAddress(String bitcoinCashAddress) {
if (!isValidCashAddress(bitcoinCashAddress)) {
throw new RuntimeException("Address wasn't valid: " + bitcoinCashAddress);
}

String[] addressParts = bitcoinCashAddress.split(SEPARATOR);
int datapos = 0;
if (addressParts.length == 2) {
String prefix = addressParts[0];
datapos++;
}

byte[] addressData = Bech32.decodeFromCharset(addressParts[datapos]);
addressData = Arrays.copyOfRange(addressData, 0, addressData.length - 8);
addressData = convertBits(addressData, 5, 8, true);
byte versionByte = addressData[0];
return Arrays.copyOfRange(addressData, 1, addressData.length);
}

public static boolean isValidCashAddress(String bitcoinCashAddress) {
try {
if (bitcoinCashAddress == null || bitcoinCashAddress.length() == 0) {
return false;
}
String prefix;
if (bitcoinCashAddress.contains(SEPARATOR)) {
String[] split = bitcoinCashAddress.split(SEPARATOR);
if (split.length != 2) {
return false;
}
prefix = split[0];
bitcoinCashAddress = split[1];
} else {
prefix = MAIN_NET_PREFIX;
}
if (!isSingleCase(bitcoinCashAddress))
return false;
bitcoinCashAddress = bitcoinCashAddress.toLowerCase();
byte[] checksumData = concatenateByteArrays(
concatenateByteArrays(encodePrefixToUInt5(prefix), new byte[]{0x00}),
Bech32.decodeFromCharset(bitcoinCashAddress));
byte[] calculateChecksumBytesPolymod = calculateChecksumBytesPolymod(checksumData);
return new BigInteger(calculateChecksumBytesPolymod).compareTo(BigInteger.ZERO) == 0;
} catch (RuntimeException re) {
return false;
}
}

private static boolean isSingleCase(String s) {
return s.equals(s.toLowerCase()) || s.equals(s.toUpperCase());
}

private static byte[] convertBits(byte[] bytes8Bits, int from, int to, boolean strictMode) {
int length = (int) (strictMode ? Math.floor((double) bytes8Bits.length * from / to)
: Math.ceil((double) bytes8Bits.length * from / to));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.generalbytes.bitrafael.api.wallet.bch;

import org.bitcoinj.core.Address;
import org.bitcoinj.params.MainNetParams;
import org.junit.Test;

import static org.junit.Assert.*;

public class Bech32Test {
@Test
public void test() {
assertEquals("11DstTXVTvo8DfczCQws6CHV718u74VV2",
new Address(MainNetParams.get(), Bech32.decodeCashAddress("qqqq4077ywes2cmda80crheea4m7zznszvk5lqedw9")).toBase58());
assertEquals("1P3GQYtcWgZHrrJhUa4ctoQ3QoCU2F65nz",
new Address(MainNetParams.get(), Bech32.decodeCashAddress("bitcoincash:qrcuqadqrzp2uztjl9wn5sthepkg22majyxw4gmv6p")).toBase58());
assertEquals("17WXKozdmX7zfjPRLZtJz5Avth4E3kq3xn",
new Address(MainNetParams.get(), Bech32.decodeCashAddress("qprkvgvvlvn856mkhuuh0kxtu7ngnu2sr5xhsvwye4")).toBase58());
}
}

0 comments on commit 9dca55e

Please sign in to comment.