elrond.Address Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of erdjava Show documentation
Show all versions of erdjava Show documentation
The Java 1.8 SDK for interacting with the Elrond blockchain
package elrond;
import java.io.ByteArrayOutputStream;
import org.bitcoinj.core.Bech32;
import org.bouncycastle.util.encoders.DecoderException;
import org.bouncycastle.util.encoders.Hex;
import elrond.Exceptions.AddressException;
public class Address {
static final String HRP = "erd";
static final int PUBKEY_LENGTH = 32;
static final int PUBKEY_STRING_LENGTH = PUBKEY_LENGTH * 2; // hex-encoded
static final int BECH32_LENGTH = 62;
static final String ZERO_PUBKEY_STRING = "0000000000000000000000000000000000000000000000000000000000000000";
private final String valueHex;
private Address(String valueHex) {
this.valueHex = valueHex;
}
public static Address createZeroAddress() {
return new Address(ZERO_PUBKEY_STRING);
}
public static Address fromBech32(String value) throws Exceptions.AddressException {
Bech32.Bech32Data bech32Data;
try {
bech32Data = Bech32.decode(value);
}
catch(Exception e) {
throw new Exceptions.CannotCreateBech32AddressException(value);
}
if (!bech32Data.hrp.equals(HRP)) {
throw new Exceptions.BadAddressHrpException();
}
byte[] decodedBytes = convertBits(bech32Data.data, 5, 8, false);
String hex = new String(Hex.encode(decodedBytes));
return new Address(hex);
}
public static Address fromHex(String value) throws Exceptions.AddressException {
if (value.length() != PUBKEY_STRING_LENGTH || !isValidHex(value)) {
throw new Exceptions.CannotCreateAddressException(value);
}
return new Address(value);
}
private static boolean isValidHex(String value) {
try {
Hex.decode(value);
return true;
} catch (DecoderException error) {
return false;
}
}
public String hex() {
return this.valueHex;
}
public byte[] pubkey() {
return Hex.decode(this.valueHex);
}
public String bech32() throws AddressException {
byte[] pubkey = this.pubkey();
return Bech32.encode(HRP, convertBits(pubkey, 8, 5, true));
}
public static boolean isValidBech32(String value) {
try {
Address.fromBech32(value);
return true;
} catch (AddressException error) {
return false;
}
}
/**
* @param data represents the bytes to be converted
* @param fromBits represents the starting position
* @param toBits represents the ending position
* @param pad if set to true, will pad the result
* @return returns the converted bytes
* @throws AddressException if there is an issue with the data
* General power-of-2 base conversion.
*/
public static byte[] convertBits(byte[] data, int fromBits, int toBits, boolean pad) throws Exceptions.AddressException {
/*-
Reference Python implementation by Pieter Wuille:
def convertbits(data, frombits, tobits, pad=True):
acc = 0
bits = 0
ret = []
maxv = (1 << tobits) - 1
max_acc = (1 << (frombits + tobits - 1)) - 1
for value in data:
if value < 0 or (value >> frombits):
return None
acc = ((acc << frombits) | value) & max_acc
bits += frombits
while bits >= tobits:
bits -= tobits
ret.append((acc >> bits) & maxv)
if pad:
if bits:
ret.append((acc << (tobits - bits)) & maxv)
elif bits >= frombits or ((acc << (tobits - bits)) & maxv):
return None
return ret
*/
int acc = 0;
int bits = 0;
ByteArrayOutputStream ret = new ByteArrayOutputStream();
int maxv = (1 << toBits) - 1;
int maxAcc = (1 << (fromBits + toBits - 1)) - 1;
for (byte value : data) {
int valueAsInt = value & 0xff;
if ((valueAsInt < 0) || (valueAsInt >>> fromBits != 0)) {
throw new Exceptions.CannotConvertBitsException();
}
acc = ((acc << fromBits) | valueAsInt) & maxAcc;
bits += fromBits;
while (bits >= toBits) {
bits -= toBits;
ret.write((acc >>> bits) & maxv);
}
}
if (pad) {
if (bits > 0) {
ret.write((acc << (toBits - bits)) & maxv);
}
} else if (bits >= fromBits || ((acc << (toBits - bits)) & maxv) != 0) {
throw new Exceptions.CannotConvertBitsException();
}
return ret.toByteArray();
}
}