How to get the Account Identifier from Principal in Motoko?

The Account Identifier is used in Ledger Canister, so it’s important to get the account identifier in motoko for those canisters integrating with Ledger Canister.

I find the source code of get account identifier in golang:

the blob (Principal’s bytes format) is principal.NewSelfAuthenticatingId(der).Bytes(), and to convert to account identifier, it involves complex functions such as sha224.

How to get the Account Identifier from Principal in Motoko.

In Motoko, here’s all you should need - this is the whoami logic we use for testing:

actor {
    public shared (msg) func whoami() : async Principal {
        msg.caller
    };
};

All you need is to check the argument’s caller

1 Like

@flyq You can find a sha256 implementation here: Motoko Packages
This isn’t enough for your use case however, as to generate an AccountIdentifier from a principal, sha224 is used. Unless that is added it may not be possible to generate AccountIdentifiers in mo

3 Likes

Wikipedia suggests there’s few changes needed to the sha256 implementation to calculate sha244 instead (assuming that implementation is based on the wikipedia algorithm)

2 Likes

@prithvi @claudio Thanks for your useful information.
according to this:
https://golang.org/src/crypto/sha256/sha256.go
The difference between sha224 and sha256 is few, so I will try it.

2 Likes
4 Likes

Good stuff, thanks for contributing!

For the ones who want a version in Python; here is a gist

3 Likes

Damn I must have started my lib an hour before you posted this, and only just checked in now to post it. It’s the same as yours (change IV and skipped the last block in the sum stage).

I’ll move onto working on the AccountIdentifiers now. The python gist makes it easy to follow

1 Like

I am not sure what are subaccount; for now it’s hardcoded to bytearray of zeroes.

The original rust code is here: ic/account_identifier.rs at 024de2fc73d7f6f5df5a92edf9675851f9ebbf59 · dfinity/ic · GitHub

1 Like

The sub account can be any Nat256, allowing for sub accounts from the same principal. E.g. in NNS if you add a new account I believe it’s just the next account number (so the second one would be 1 as a 32byte blob)

1 Like

The problem is not solved perfectly, Account Identifier is CRC-32(X) + X, in which X is currently available in motoko, but CRC-32 is not. So the next work is to implement CRC32 in motoko.

1 Like

Yep, I’m currently working on a CRC32 implementation, but I think they one they use is a little bit harder.

2 Likes

Could you post the output for that principal ID in your gist? I dont have python handy to run it. Trying to see if I can get my motoko script to generate the same thing.

Currently have a working crc32, which should be the same as the one from the binascii python library so hoping it should match

1 Like

Yes sure

m7b5y-itxyr-mr2gt-kvadr-2dity-bh3n5-ff7bb-vvm2v-3ftew-5wjtg-2qe -> 15a32831331d752b5c4cff5b9351bea8015d90f2c3831c6f3fca9c5287a4dbff

kb4lg-bqaaa-aaaab-qabfq-cai -> 22c138e9ab7156bf99a09fb4edabb12a35cae06ed162577ab6479d3dfd2f26c6

gmk2m-oiaaa-aaaab-qaaja-cai -> 17506366cdd9f3478b35944a6eed621f6fe14176abd1dfa26720e31785ab8462

Awesome, so my accountid script is working, using the sha224 lib and a custom crc32 motoko lib:

d40689c8-39e8-40d8-8bbf-70b4c03269fb

Currently this is hard coded for the sub account (SUBACCOUNT_ZERO), I’ll add the ability for custom sub accounts and then complete some more testing locally and get something uploaded today.

It’s a bit unusual though, both CRC32 and SHA224 are pretty non-standard, and unlikely to be re-used much. Does it make sense to condense all of this into a single library?

2 Likes

I think it makes sense to contribute them to these libraries:

2 Likes

I added my crc32 lib to the CRC package here: GitHub - stephenandrews/motoko-crc: The CRC Package

I’ve uploaded a library for the AccountIdentifiers: GitHub - stephenandrews/motoko-accountid - this seems to hold true for the examples posted above, and I will continue with a few more.

This will allow us to communicate with the ledger canister directly for transfers etc. I am currently working on a wrapping canister as well.

4 Likes