coinbase / mesh-specifications

Specification files for the Mesh Blockchain Standard
Apache License 2.0
327 stars 93 forks source link

Need a way to derive the public key from an address - e.g. `/construction/address` #43

Closed teye closed 4 years ago

teye commented 4 years ago

Hi team, we have previously posted our problem on the forums and as suggested by @patrick-ogrady to open an issue for it,

https://community.rosetta-api.org/t/any-way-to-get-public-key-from-signer-package-before-combine/189

Is your feature request related to a problem? Please describe.

Our Zilliqa blockchain's signature is dependent on a Zilliqa transaction object which requires the sender public key.

Our signing process on the blockchain is as such:

  1. Create unsigned transaction object
  2. Convert it to a zilliqa transaction object with public key
  3. Convert (2) to bytes; during the process it appends additional params such as ID, network params, etc.
  4. Sign (2) to obtain a signature

This differs from the current rosetta-sdk which is:

  1. Create unsigned transaction object
  2. Sign (1) to obtain a signature

As a result, during /construction/submit in the construction tests, our blockchain verifies that the provided signature is always returning false and rejects them.

We wish to have access to the signer's public key at any of the Construction API steps before /construction/combine so as to use the unsigned transaction, add the public key and convert it to our transaction object before spitting out the proper “unsigned transaction” for /construction/payloads response.

Describe the solution you'd like

To have a new /construction/address to derive the public key from a given address. Think of it as a complement to construction/derive.

ConstructionAddressRequest

{
    "network_identifier": {
        "blockchain": "bitcoin",
        "network": "mainnet",
    },
    "account_identifier": {
        "address": "0x1234567890123456789012345678901234567890",
    },
    "metadata": {}
}

ConstructionAddressResponse

{
    "public_key": {
       "hex_bytes": "string",
       "curve_type": "secp256k1",
    },
    "metadata": {}
}

The new Contruction flow would be (/parse is omitted for clarity):

  1. /construciton/derive
  2. /construction/address
  3. /construction/preprocess (public key is passed as part of metadata)
  4. /construction/metadata
  5. /construction/payloads (unsigned json now contains the public key)
  6. (Sign with rosetta-sdk signer)
  7. /construction/combine (the rest follows as usual)

Note: We have not consider how to incorporate this into rosetta-cli tests given that not all blockchain providers require the proposed /construction/address.

Describe alternatives you've considered We have added our own object conversion in the keys package in a custom rosetta-sdk-go and it passes the Construction API tests.

https://github.com/teye/rosetta-sdk-go/blob/master/keys/signer_secp256k1.go#L75

https://github.com/teye/rosetta-sdk-go/blob/master/keys/signer_secp256k1.go#L143

However, this is not recommended as pointed out by @patrick-ogrady as it complicates the existing keys package.

Additional Information https://community.rosetta-api.org/t/any-way-to-get-public-key-from-signer-package-before-combine/189

patrick-ogrady commented 4 years ago

Thanks for posting this @teye! After some thinking, I believe the best way to do this is to add a field to ConstructionPreprocessResponse that lists all the address pubkeys that should be fetched and to add a field to ConstructionPayloadsRequest where these pubkeys can be provided (along with fetched metadata). The caller would be required to populate these during the construction flow using their "signing backend".

The best parts about this strategy is that it doesn't require adding any endpoints or breaking any existing flows! I'll make this PR early next week.

teye commented 4 years ago

Thanks @patrick-ogrady for brainstorming this out. This definitely is viable and the plus point is that you would be able to set these additional structs as false like the max_fee and suggested_fee_multiplier. Looking forward to the PR :+1: