4

I'm trying to implement the asset fingerprint in java.

So i'm importing these dependencies

<dependency>
    <groupId>org.bitcoinj</groupId>
    <artifactId>bitcoinj-core</artifactId>
    <version>0.15.10</version>
</dependency>
<dependency>
    <groupId>com.github.alphazero</groupId>
    <artifactId>Blake2b</artifactId>
    <version>bbf094983c</version>
</dependency>

And coded this as specified here: https://github.com/cardano-foundation/CIPs/pull/64

public static void main(String[] args) throws DecoderException {
    final String policyId = "2697bec9e609932eaaaafb34c8e1ea706549d268166ef60285026b85";
    final String assetName = "redomgrun";

    byte[] policyIdBytes = Hex.decodeHex(policyId);
    byte[] assetNameBytes = assetName.getBytes();

    Digest blakeDigest = Blake2b.Digest.newInstance(20);
    byte[] blakeHash = blakeDigest.digest(ArrayUtils.addAll(policyIdBytes, assetNameBytes));
    String bechString = Bech32.encode("asset", blakeHash);
    System.out.println(bechString);
}

But blake produces bytes like this

[127, -84, -10, 11, 1, -8, 78 ...

Which lead to String index out of range: 127 at bech encoding.

What am i doing wrong?

4

You have to first convert blakeHash bytes from 8 bits to 5 bits unsigned integer and then call Bech32.encode().

Sample code:

public static void main(String[] args) throws DecoderException {
    ...
    byte[] blakeHash = blakeDigest.digest(ArrayUtils.addAll(policyIdBytes, assetNameBytes));

    List<Integer> words = convertBits(blakeHash, 8, 5, false);
    byte[] bytes = new byte[words.size()];
    for(int i=0; i < words.size(); i++) {
        bytes[i] = words.get(i).byteValue();
    }

    String bechString = Bech32.encode("asset", bytes);
    System.out.println(bechString);
}

private static List<Integer> convertBits(byte[] data, int fromWidth, int toWidth, boolean pad) {
    int acc = 0;
    int bits = 0;
    int maxv = (1 << toWidth) - 1;
    List<Integer> ret = new ArrayList<>();

    for (int i = 0; i < data.length; i++) {
        int value = data[i] & 0xff;
        if (value < 0 || value >> fromWidth != 0) {
            return null;
        }
        acc = (acc << fromWidth) | value;
        bits += fromWidth;
        while (bits >= toWidth) {
            bits -= toWidth;
            ret.add((acc >> bits) & maxv);
        }
    }

    if (pad) {
        if (bits > 0) {
            ret.add((acc << (toWidth - bits)) & maxv);
        } else if (bits >= fromWidth || ((acc << (toWidth - bits)) & maxv) != 0) {
            return null;
        }
    }
    return ret;
}
1
  • thanks, that works, do you know of any apache etc. lib to do the conversion?
    – wutzebaer
    May 31 at 8:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.