cip | title | author | discussions-to | status | type | category | created | license |
---|---|---|---|---|---|---|---|---|
20 |
Generic hash function support via extensible precompile |
James Prestwich <[email protected]> |
Superseded |
Standards |
Ring 0 |
2020-10-25 |
Apache 2.0 |
Important
This feature has been removed in CIP-63.
The key words "MUST", "MUST NOT", "SHOULD", and "MAY" in this document are to be interpreted as described in RFC 2119.
This CIP specifies an extensible precompile that provides access to multiple hash functions to the EVM. It also specifies a process for including new hash functions in the precompile.
As a descendant of the EVM, Celo supports only a handful of common hash functions. This restricts the design-space of Celo protocols, and prevents certain protocols from being evaluated by the EVM. We propose a single precompile that provides access to common cryptographic hashes, and can be easily extended with minimal impact on chain security and performance.
We also propose a reduced subset of the CIP process that applies specifically to hash function enrollment. This CIP20 process is intended to reduce the burden of review on CIP editors and Celo Blockchain developers, as well as speed inclusion of useful functionality for dapp developers.
- Provide support for common cryptographic hash functions
- Expand options for on-chain verification of protocols not specifically designed for EVM compatibility - e.g. Verification of off-chain signatures using Blake2Xs, including Celo's own epoch commitments within a smart contract. - e.g. Verification of remote Proof of Work from a wide variety of chains
- Provide a clear route for acceptance and adoption of additional hash functions
As of FORK_BLOCK_NUMBER
we introduce a new precompiled contract at address
0xE2
that provides access to a set of pre-determined hash functions. The input
to this pre-compile consists of a one-byte selector, a function-specific
parameter block, and the preimage. The output of this pre-compile is dependent
on the selector, and may be fixed- or variable-length. If the selector is
unknown (not on the current compatibility list), or the function-specific, the
precompile MUST return an error.
To be eligible for inclusion, a proposed hash function meet the following criteria:
- There MUST be a standardized specification for the function.
- There MUST be an existing high-quality implementation in Go.
- The proposer SHOULD provide an implementation of the precompile extension.
- The proposer SHOULD also provide test vectors, and fuzzing setups for this implementation.
- The proposer SHOULD provide benchmarks according to the standardized CIP20 benchmarking process below.
- The function MUST be pure.
- This is intended to disqualify
ethash
and other stateful functions.
- This is intended to disqualify
- The function MUST NOT be memory intensive
- This is intended to disqualify "memory-hard" hash functions and other potential DoS vectors
- E.g.
scrypt
,argon
- The function SHOULD NOT be a combination of other hash functions
- Prefer adding each component separately, and building the composition as a Solidity function.
- This is intended to disqualify common PoW-specific combinations.
- E.g.
sha256d
,X11
,
Once these criteria are met the function must be proposed via a pull request.
The pull request SHOULD include a link to an existing implementation and
concrete use case for the new hash function. The pull request MUST be named
according to the following template: [CIP-0020 Extension] DigestFunctionName
.
The pull request MUST update this CIP with the following information:
- A new row in the table below
- The status MUST be set to
Proposed
. - The selector MUST be marked
TODO
. Selectors will be assigned by the CIP editors, not the proposer.
- The status MUST be set to
- If any function-specific parameters are required:
- A link to full documentation in a new file in the
CIP-0020/
folder.
- A link to full documentation in a new file in the
- If the ouput is not a fixed-length digest:
- A link to full documentation in a new file in the
CIP-0020/
folder.
- A link to full documentation in a new file in the
The pull request MUST NOT:
- Modify any existing table row or text outside of the table.
- Conflict with the selector or name of any existing function.
- Modify any other files in this repository.
New hash functions will be reviewed by participants of the Celo ACD calls. Review will be scheduled via the ACD call process. Submitters are responsible for requesting that their submission be included in the agenda.
Reviewers MAY ask the proposer for additional justification or to clarify decisions made with respect to the input and output formats. Rough consensus of ACD call participants is required, but Reviewers SHOULD accept any proposal that meets all criteria and contains a well-tested implementation.
Function Name | Extended Docs | Input Format | Output Format | Link to specification | Status | |
---|---|---|---|---|---|---|
0x00 | SHA3-256 | n/a | preimage only | 32 bytes | link | Proposed |
0x01 | SHA3-512 | n/a | preimage only | 64 bytes | link | Proposed |
0x02 | Keccak-512 | n/a | preimage only | 64 bytes | link | Proposed |
0x03 | SHA2-512 | n/a | preimage only | 64 bytes | link | |
0x10 | Blake2s | CIP-0020/blake2s.md | configuration, key, and preimage | Variable | link | Proposed |
Calling the precompile with an undefined selector or otherwise invalid input
will cost INVALID_CIP20_INPUT_GAS
(initially set to 200
) gas and cause an
error.
New hash functions MUST include a gas cost function and MUST include benchmarks that justify that function. This function SHOULD account for setup costs and per-block processing of input. To conform to existing hash function precompile and opcode behavior, we recommend they be priced as a base gas cost for the invocation plus an amount of gas per EVM word processed.
The initial SHA-3 variants (SHA3-256, SHA3-512, and Keccak-512) will be priced
identically to the existing Keccak-256 at 30 + (6 * words)
.
The initial SHA-2 variant (SHA2-512) will be priced identically to the existing
SHA2-256 precompile. It will cost 60 + (12 * words)
.
Please refer to the blake2s document for details of the blake2s gas pricing function.
EVM_WORD_SIZE: int = 32
def price_word_metered_hash(
base: int,
per_word: int,
input: bytes
) -> int:
length_ceiling = len(input) + EVM_WORD_SIZE - 1
words = length_ceiling // EVM_WORD_SIZE
return base + words * per_word
def price_sha3_variant(input: bytes) -> int:
return price_word_metered_hash(30, 6, input)
def price_sha2_512(input: bytes) -> int:
return price_word_metered_hash(60, 12, input)
I considered adding one precompile per hash function, with each function having its own CIP. This would use a potentially large, fragmented, portion of the precompile address space. Subjecting a new hash function to the full CIP review process seems unnecessary, as the use cases are clear and the risk is low.
## TODO ##
- To follow.
-
This is a permanent departure from compatibility with the Ethereum EVM, and its functionality ought to be wrapped in a Celo-specific contract to prevent accidental use in an Ethereum-targeted contract.
-
Given that this is a pure function exposed at the contract layer, it is unlikely to have a significant risk on the consensus or governance processes.
-
Each hash function will need to be priced separately. The pricing function for this precompile will grow in complexity over time.
-
If more than 200 hash functions are merged, the selector space will become crowded and we will need to plan to add a second selector byte.
This work is licensed under the Apache License, Version 2.0.