ic4j / ic4j-candid

Java Candid for The Internet Computer (IC4J) is a set of native Java libraries to manage the Internet Computer Candid types
Apache License 2.0
3 stars 2 forks source link

Unexpected error: Invalid textual format: expected ... for some valid principal ids #2

Closed chinaryov closed 2 years ago

chinaryov commented 2 years ago

Hello!

A principal for example: aabzk-v6a3g-5u6a6-vcoqh-effzk-jb676-f47sd-bkqgg-afgmm-7wlka-hqe

Calling method 'Principal.fromString' with provided principal throws exception: org.ic4j.types.PrincipalError: Invalid textual format: expected "aokvp-qgzxn-hqhvi-tubzb-joksi-px7rp-h4qyk-ubrqb-jtdh5-s2qb4-ba"

checksum = BigInteger.valueOf(Long.valueOf(hasher.getValue()).intValue()).toByteArray(); For some principals this code returns checksum 3 bytes. Must be 4 bytes.

Best regards, Alexander

chinaryov commented 2 years ago

I have patched it locally. Part of code

    public String toString() {
        if (value.isPresent()) {
            final byte[] valueBytes = value.get();
            final byte[] checksum = toChecksumBytes(valueBytes);
            final byte[] bytes = concatByteArrays(checksum, valueBytes);

            String output = codec.encodeAsString(bytes);
            output = makeAsciiLowerCase(output);

            // remove padding
            output = StringUtils.stripEnd(output, "=");
            output = output.replaceAll("(.{5})", "$1-");
            return output;
        } else {
            return "";
        }
    }

    private byte[] toChecksumBytes(byte[] valueBytes) {
        final CRC32 hasher = new CRC32();
        hasher.update(valueBytes);

        final long hasherValue = hasher.getValue();
        if (hasherValue > 0) {
            return to4Bytes((int) hasherValue);
        }
        return new byte[]{0, 0, 0, 0};
    }

    private byte[] to4Bytes(int value) {
        final byte[] bytes = new byte[4];
        bytes[0] = (byte) ((value >>> 24) & 0xFF);
        bytes[1] = (byte) ((value >>> 16) & 0xFF);
        bytes[2] = (byte) ((value >>> 8) & 0xFF);
        bytes[3] = (byte) ((value) & 0xFF);
        return bytes;
    }
rdobrik commented 2 years ago

Thank you Alexander, let me incorporate this into main branch and test it. Then make another release candidate. I will add your use case into our Unit test. Really appreciate your help!

Roman

rdobrik commented 2 years ago

Added your code toy the main branch. Pushed out Release Candidate 12 to Maven Central. It should be available there soon.

Maven

org.ic4j ic4j-candid 0.6.12

Gradle implementation 'org.ic4j:ic4j-candid:0.6.12'

chinaryov commented 2 years ago

I just did migration to the newest version org.ic4j ic4j-candid 0.6.12. It works well. Thank you.

rdobrik commented 2 years ago

Thank you Alexander, this was a great catch! Your code works very well.