[Username blockchain model] Deriving public keys to sign with for given account

Hi I noticed that the /construction/payloads endpoint returns a list of SigningPayload.

This type has an “address” (v1.4.2) and “account_identifier” (v1.4.4) fields that are used to sign a payload. For blockchains that use a username model, how does the rosetta-cli know what public key(s) to sign with? The documentation for AccountIdentifier state that the ownership of an account should be supplied in the metadata field, but are there any assumptions made about how this JSON object should be structured?

Or more broadly, given an AccountIdentifier in a username model blockchain, how does the Construction API testing framework know which public key(s) to sign with?

CONTEXT: Kadena uses a username model and a single account could have multiple public keys associated with it.

:wave: @linda

This is a GREAT question! Before I dive into how the rosetta-cli does this, I’d like to provide some brief background on the new AccountIdentifier-based fields added in v1.4.4. We made this non-breaking change (we only deprecated the address-based fields instead of removing them) after realizing that our approach (in <v1.4.4) made it very difficult to coordinate the signing of transactions on blockchains that support using multiple keys with a given account. The implementer could only request signing from a single “string-based” address when there may have been multiple SubAccounts associated with a given address (each with a unique key). Now, implementers can request that a particular AccountIdentifier (with a populated SubAccount) provide a signature for a SigningPayload. (For other readers) If you only populate the deprecated, string-based address fields, nothing will break!

The new automated Construction API tester allows the caller to store a KeyPair for any *types.AccountIdentifier using the save_account action. When parsing SigningPayloads, the tester looks up each AccountIdentifier in key storage and signs with whatever key is stored there. If no key is stored for a particular AccountIdentifier, an error will be thrown. Note, you may have to store the same KeyPair for different AccountIdentifiers (if they should sign with the same key).

Here is a simple example of saving a new account:

Throughout Rosetta, we assume that all data included in an AccountIdentifier is used to uniquely identify an account. You can think of an account’s full identifier as the hash of an AccountIdentifier. If you change one metadata field, this would represent a different but related account (as it would share the same AccountIdentifier.Address with another account). Each AccountIdentifier has a unique balance and can be associated with AT MOST one KeyPair (storing multiple KeyPairs at a single “address” would require using multiple SubAccounts).

The only restriction on how the metadata should be structured is that the root level should be a JSON.Object (i.e. a map with string-based keys).

As long as you store at most a single KeyPair for each AccountIdentifier you are using, you shouldn’t have any problems!

1 Like