Skip to content

Commit

Permalink
docs(HIP-632): Decouple from virtual addresses; referring only to ali…
Browse files Browse the repository at this point in the history
…ases (hashgraph#1011)
  • Loading branch information
david-bakin-sl authored Sep 16, 2024
1 parent 090259e commit 0d17b81
Showing 1 changed file with 96 additions and 26 deletions.
122 changes: 96 additions & 26 deletions HIP/hip-632.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,65 +10,121 @@ status: Accepted
last-call-date-time: 2023-01-10T07:00:00Z
created: 2022-11-28
discussions-to: https://github.com/hashgraph/hedera-improvement-proposal/discussions/638
updated: 2024-05-22
requires: 631
updated: 2024-09-13
requested-by: David Bakin <@david-bakin-sl>
requires: 583
---

## Abstract

Virtual Addresses introduced a list of ECDSA public addresses that are stored in the account entity and serve as the account identifier on the EVM for transactions. This is in addition to the `Hedera Account ID` that is used by default when no virtual addresses exist.
Hedera accounts have the capability to have a linked _EVM address alias_, an EVM address. In this way smart contracts can deal
interact with Hedera accounts.

One result of this change is that accounts now have an organized presentation of different address formats that support historical formats and EVM equivalent formats. These addresses may be stored within smart contract state but their usefulness is limited without the ability to differentiate addresses.
Accounts now have an organized presentation of different address formats that support historical formats and EVM equivalent
formats. These addresses may be stored within smart contract state but their usefulness is limited without the ability to differentiate addresses.

These methods will be placed in the system contract for the _Hedera Account Service_ (`HAS`).

## Motivation

Prior to HIP 631, deployed smart contracts may have stored an account with a Hedera Account ID or the extracted public address from an ECDSA public key. Subsequent to HIP 631, when a virtual address is added to an account it will now present itself as the virtual address and no longer use the Hedera Account ID. To avoid issues of lossed balance and permissions it is important that developers can distinguish between Hedera Account IDs and virtual addresses and translate easily between the them.
Since the same account may be referred to with two different 20-byte identifiers (EVM address alias or Hedera account num alias),
to avoid issues of loss of balance and permissions it is important that developers can distinguish between Hedera Account IDs
and EVM addresses and translate easily between them.

Many smart contracts utilize `ECRECOVER` as part of their authorization process in smart contracts.
However, this is limited to `ECDSA` based signatures, which leaves accounts that have `ED25519` and complex key types, supported by Hedera,
unable to do similar authorization.

Additionally, many smart contracts utilize `ECRECOVER` as part of their authorization process in smart contracts.
However, this is limited to `ECDSA` based signatures, which leaves `E25519` and complex key types not supported in Hedera.
To provide good user experience and to allow Hedera users to enjoy additional feature benefits over EVM equivalanece,
it is important to provide authorization options within smart contract for non-ECDSA keys.


## Definitions

An _account-num alias_ is the encoded form of a Hedera account ID's `num` field - an 8-byte number padded to an EVM 20-byte address by adding
12 bytes of `0` to the front of it.

An _EVM address alias_ is an EVM address associated with a Hedera account ID.
* The Hedera account may be a "hollow" account.

Both aliases thus present as 20-byte Ethereum addresses.

See [HIP-583](https://hips.hedera.com/hip/hip-583#rationale) for a full description of account-num aliases and EVM address aliases.
* This HIP does not address HIP-583 key aliases.

## Rationale

In smart contract executions the EVM will provide `msg.sender` values as either Hedera Account ID or virtual addresses.
In smart contract executions the EVM will provide `msg.sender` values as either an account-num alias or EVM address alias.
To support authorization flows that check addresses explicitly in smart contract code, the network should support smart contract distinguishing operations that allow smart contract to distinguish between the two forms.
Additionally, to support standard implicit checks the network should support system contract checks in a manner similar `ECRECOVER` for easy developer support.

## User stories

1. As a developer I want to be able to distinguish between Hedera Account ID and virtual addresses within a smart contract so I can resolve address mappings in balance, permission or similar scenarios.
1. As a developer I want to be able to distinguish between Hedera Account ID and aliases within a smart contract so I can resolve address mappings in balance, permission or similar scenarios.
2. As a developer I want to be able to confirm account authorization within a contract using simple `ECDSA`/`ED2519` key raw signatures as I would on Ethereum using `ECRECOVER`.
3. As a developer I want to be able to confirm account authorization for `ECDSA` accounts within a contract without being limited to `ECRECOVER`.
4. As a developer I want to be able to confirm account authorization for accounts within a contract using protobuf signature maps in a similar fashion as I would on Ethereum using `ECRECOVER`.

## Specification

A new system contract with functions to support address (Hedera Account ID and virtual) mapping reconciliation and authorization is proposed.
A new system contract with functions to support address (Hedera Account ID and EVM address alias) mapping and authorization is proposed.

This will aid developers to support smart contract migration logic for cases where aliases are encountered.
Additionally, EVM developers, who were limited to `ECRECOVER` authorization flows, will be able to expand
authorization checks to other key types.

This will aid developers to support smart contract migration logic for cases where Hedera Account ID or virtual address values are encountered. Additionally, EVM developers who were limited to `ECRECOVER` authorization flows will be able to expand authorization checks to other key types.
HAS methods here can use EVM-styled 20-byte addresses which are either Hedera account num aliases or EVM address
aliases.

* In this document the word _alias_, by itself, means either kind of alias.

(n.b.: See HIP-583 for definitions of Hedera account num alias and EVM address alias. Hedera key aliases, defined there,
are not supported by these methods.)

| hash | signature | return | description |
| --- | --- | --- | --- |
| | getVirtualAddresses(address) | address[] | returns an array of virtual addresses for a given Hedera Account ID |
| | getHederaAddress(address) | address | returns the top level Hedera Account ID if applicable |
| | isVirtualAddress(address) | bool | true if valid virtual address, false if long-zero or non existing account |
| | isAuthorized(address, messageHash, signatureBlob) | bool | true if account is authorized to carry out transaction execution on account. Accepts protobuf key signature blobs. May be used for ECDSA, ED25519 and complex key flows |
| | isAuthorizedRaw(address, messageHash, signatureBlob) | bool | true if account is authorized to carry out transaction execution on account. Accepts single key raw signature blobs (ECDSA and ED25519). This provides similar logic to ECRECOVER. |
| `0xdea3d081` | getEvmAddressAlias(address) | (ResponseCode, address) | given a Hedera Account ID (account num alias) returns the EVM address alias, if present |
| `0xbbf12d2e` | getHederaAccountNumAlias(address) | (ResponseCode, address) | given an alias returns the top level Hedera Account ID (as account num alias), if applicable |
| `0x308ef301` | isValidAlias(address) | bool | true if an account num alias or evm address alias), false if non existing account |
| `0xb2526367` | isAuthorized(address, bytes /\*message\*/, bytes /\*signatureBlob\*/) | (ResponseCode, bool) | true if account (named by an alias) is authorized to carry out transaction execution on account. Accepts protobuf key signature blobs. May be used for ECDSA, ED25519 and complex key flows |
| `0xb2a31da4` | isAuthorizedRaw(address, bytes /\*messageHash\*/, bytes /\*signatureBlob\*/) | bool | true if account (named by an alias) is authorized to carry out transaction execution on account. Accepts single key raw signature blobs (ECDSA and ED25519). This provides similar logic to ECRECOVER. |

### `isAuthorizedRaw(address, messageHash, signatureBlob)` Function Usage
This function is similar to using the ECRECOVER precompile function. Ethereum uses the secp256k1 curve to produce signatures which are 65 bytes in length (length of v = 1 byte and length of r and s = 32 bytes each). ED25519 signatures are 64 bytes in length. The address given can be either a Hedera Account ID or an Ethereum virtual address. The `isAuthorizedRaw` function call will perform the following steps to determine its result:
1. Call `isVirtualAddress` if the address is not a Hedera Account ID. Return false if not a virtual address.
2. Determine if the length of the signatureBlob is 65 bytes in length
* If true, extract v, r and s and run ECRECOVER(messageHash, v, r, s) and determine if the result matches any of the virtual address on the account. Return true if any matching address is found if given a Hedera Account ID. If given an Ethereum address, the recovered address must match the given address.
3. If length of signatureBlob is 64 bytes in length
* Retrieve the Hedera address. Determine if there is a single key associated with the Hedera Accound ID. If not return false.
This function is similar to using the ECRECOVER precompile function. Ethereum uses the secp256k1
curve to produce signatures which are 65 bytes in length (length of v = 1 byte and length of r and
s = 32 bytes each). ED25519 signatures are 64 bytes in length. The address given is an alias. The
appropriate message hash for the key type is given.


The `isAuthorizedRaw` function call will perform the following steps to determine its result:

1. If _not_ a Hedera account-num alias then return the result of `isValidAlias`. Otherwise (an EVM address alias):
2. If the length of the signatureBlob is 65 bytes in length (EC signature):
* Extract v, r and s and run `ECRECOVER(messageHash, v, r, s)`.
If the alias is an EVM address alias: Return `true` iff the recovered address is the alias.
If the alias is a Hedera account-num id: Return `true` if the result matches the alias on the account _or_
if the account has a single primitive EC key then `true` if the result matches the address derived from that public key.
3. Otherwise, if length of signatureBlob is 64 bytes in length (ED signature):
* Retrieve the Hedera address from the EVM address alias; if there is none return `false`.
Determine if there is a single primitive ED key associated with the Hedera Account ID. If not return false.
* If there is a single key, verify that the signature (the signatureBlob) signs the message hash and is attested by the account.

Calls to this method incur additional gas charges corresponding to the resource cost of validating a signature.

### `isAuthorized(address, message, signatureBlob)` Function Usage
This function is used for Hedera account (non Ethereum) signature validation. It handles the more complex signature types
which are available with Hedera accounts. One or more signatures will be encoded in protobuf format into the signatureBlob.
The message that the signatures are for is given.

### `isAuthorized(address, messageHash, signatureBlob)` Function Usage
This function is used for Hedera account (non Ethereum) signature validation. It handles the more complex signature types which are available with Hedera accounts. One or more signatures will be encoded in protobuf format into the signatureBlob. The precompile function will look up the keys for the account and determine if the signatures passed in via the signatureBlob satisfy the signing requirements for the account. For example, if the account has a threshhold key of needing 3 out of 4 signatures,the precompile function will sign the messageHash with each key on the account and determine if at least 3 signatures in the signatureBlob matches.
The precompile function will look up the keys for the account and determine if the signatures passed in via the signatureBlob
satisfy the signing requirements for the account. For example, if the account has a threshold key of needing 3 out of 4
signatures, the precompile function will validate signature against the message with each key on the account and determine
if at least 3 signatures in the signatureBlob matches.

The signatureBlob could be limited to encoding the following protobuf schema definitions
Calls to this method incur additional gas charges corresponding to the resource cost of validating a signature, plus
the (variable) cost of doing a cryptographic hash on the message.

The signatureBlob could be limited to encoding the following protobuf schema definitions:

~~~~
message SignatureMap {
Expand Down Expand Up @@ -114,6 +170,13 @@ message SignaturePair {
}
~~~~

(This method does not support ECDSA p-384 signatures or RSA signatures).

## Notes

* `isAuthorized` takes a _message_, not a _message hash_: This is because a complex key might include
both EC and ED keys, and EC and ED signatures use different cryptographic hashes.

## Backwards Compatibility

This functionality is newly proposed and thus does not overwrite or alter existing functionality.
Expand All @@ -132,16 +195,23 @@ Give example of using each function in context to show how they can be used to d
## Reference Implementation


## (New) Response Codes That Can Be Returned

## Rejected Ideas
* `INVALID_ARGUMENT_TO_SYSTEM_CONTRACT_METHOD` - an argument to a system contract method is invalid (e.g., byte array of wrong length)
* `ACCOUNT_MUST_HAVE_KEY` - account specified must have a key
* `ACCOUNT_MUST_HAVE_PRIMITIVE_KEY` - account specified must have a primitive key, i.e., not a threshold key or keylist

## Rejected Ideas

* There's no way to have an `EDRECOVER` similar to `ECRECOVER` in returning an address rather than a `bool`
because you can't actually get back the address from an ED25519 signature, the way `ECRECOVER` can.

## Open Issues


## References

- [HIP-583](https://hips.hedera.com/hip/hip-583) "Expand alias support in CryptoCreate & CryptoTransfer Transactions"
- [ECRECOVER Precompiled Contract](https://ethereum.github.io/execution-specs/autoapi/ethereum/frontier/vm/precompiled_contracts/ecrecover/index.html)
- [Ethereum Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf)
- [Protobuf restrictions for Hedera Precompile methods](../assets/hip-623/Protobuf%20restrictions%20for%20Hedera%20precompile%20methods%20(proposed).pdf)
Expand Down

0 comments on commit 0d17b81

Please sign in to comment.