AddressResolver.java
/*
* @copyright defined in LICENSE.txt
*/
package hera.spec.resolver;
import static hera.util.EncodingUtils.decodeBase58WithCheck;
import static hera.util.EncodingUtils.encodeBase58WithCheck;
import static org.slf4j.LoggerFactory.getLogger;
import hera.annotation.ApiAudience;
import hera.annotation.ApiStability;
import hera.api.model.AccountAddress;
import hera.api.model.BytesValue;
import hera.exception.HerajException;
import hera.spec.AergoSpec;
import hera.util.BytesValueUtils;
import hera.util.NumberUtils;
import hera.util.pki.ECDSAKeyGenerator;
import java.security.PublicKey;
import org.slf4j.Logger;
@ApiAudience.Private
@ApiStability.Unstable
public class AddressResolver {
protected static final Logger logger = getLogger(AddressResolver.class);
/**
* Convert encoded address into raw one.
*
* @param encodedAddress an encoded address to convert
* @return raw account address
*/
public static BytesValue convertToRaw(final String encodedAddress) {
try {
logger.trace("Convert encoded address {} to raw address", encodedAddress);
final BytesValue rawWithPrefix = decodeBase58WithCheck(encodedAddress);
BytesValueUtils.validatePrefix(rawWithPrefix, AergoSpec.ADDRESS_PREFIX);
final BytesValue rawAddress = BytesValueUtils.trimPrefix(rawWithPrefix);
validateRawAddress(rawAddress);
return rawAddress;
} catch (HerajException e) {
throw e;
} catch (Exception e) {
throw new HerajException(e);
}
}
/**
* Convert raw address into encoded one.
*
* @param rawAddress a raw address to convert
* @return encoded address
*/
public static String convertToEncoded(final BytesValue rawAddress) {
try {
logger.trace("Convert raw address {} to encoded form", rawAddress);
validateRawAddress(rawAddress);
final BytesValue withPrefix = BytesValueUtils.append(rawAddress, AergoSpec.ADDRESS_PREFIX);
return encodeBase58WithCheck(withPrefix);
} catch (HerajException e) {
throw e;
} catch (Exception e) {
throw new HerajException(e);
}
}
protected static void validateRawAddress(final BytesValue rawAddress) {
if (!isValidRawAddress(rawAddress)) {
throw new HerajException("RawAddress length must be " + AergoSpec.ADDRESS_BYTE_LENGTH);
}
}
public static boolean isValidRawAddress(final BytesValue rawAddress) {
return rawAddress.length() == AergoSpec.ADDRESS_BYTE_LENGTH;
}
/**
* Recover public key from {@code accountAddress}.
*
* @param accountAddress an account address
* @return an extracted public key
*/
public static PublicKey recoverPublicKey(final AccountAddress accountAddress) {
try {
logger.trace("Recover public key from {}", accountAddress);
final byte[] rawAddress = accountAddress.getBytesValue().getValue();
return new ECDSAKeyGenerator().createPublicKey(rawAddress);
} catch (HerajException e) {
throw e;
} catch (Exception e) {
throw new HerajException(e);
}
}
/**
* Derive an {@link AccountAddress} from a public key.
*
* @param publicKey a public key
* @return an {@link AccountAddress}
*/
public static AccountAddress deriveAddress(final PublicKey publicKey) {
try {
logger.trace("derive account address from {}", publicKey);
final byte[] rawAddress = new byte[AergoSpec.ADDRESS_BYTE_LENGTH];
final org.bouncycastle.jce.interfaces.ECPublicKey ecPublicKey =
(org.bouncycastle.jce.interfaces.ECPublicKey) publicKey;
rawAddress[0] =
(byte) (ecPublicKey.getQ().getYCoord().toBigInteger().testBit(0) ? 0x03 : 0x02);
final byte[] xbyteArray =
NumberUtils.positiveToByteArray(ecPublicKey.getQ().getXCoord().toBigInteger());
System.arraycopy(xbyteArray, 0, rawAddress, rawAddress.length - xbyteArray.length,
xbyteArray.length);
return new AccountAddress(BytesValue.of(rawAddress));
} catch (Exception e) {
throw new HerajException(e);
}
}
}