3

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?

1 Answer 1

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
    Commented May 31, 2021 at 8:44

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