Add SHA3-256 FIPS 202 to Math API

Background

As part of enabling interoperability between NEAR Protocol and ICON Blockchain, we would need to implement SHA3-256 FIPS 202 hash precompile Runtime Logics. This proposal is poised to enable smart contracts to access standardized SHA3-256 hashing API from the Runtime.

Motivation

The motivation behind this proposal is interoperability across the blockchain environment. To validate the Merkle tree data from ICON, the SHA3-256 FIPS 202 hashing function is required because all of ICON blockchain’s hashes are created using the SHA3-256 FIPS 202 hashing function.

Affected major projects

This proposal affects runtime to add SHA3-256 FIPS 202.

Design

This proposal offers to implement an extension in the Math API of the Runtime Logics to achieve interoperability between the NEAR protocol and the ICON blockchain.

The existing keccak256 host function hashes the given value using the KECCAK-256 = Keccak[r = 1088, c = 512].

We propose to introduce the sha3-256 that uses FIPS-202 based standard. This standard was finalized according to the NIST, SHA3-256(M) = KECCAK [512] (M || 01, 256).

This proposal posits an add-on to the MathAPI.

The method to implement this is illustrated below:

pub fn sha3_256(&mut self, value_len: u64, value_ptr: u64, register_id: u64) -> Result<()> {
        use tiny_keccak::Hasher;

        self.gas_counter.pay_base(sha3_256_base)?;
        let value = self.get_vec_from_memory_or_register(value_ptr, value_len)?;
        self.gas_counter.pay_per_byte(sha3_256_byte, value.len() as u64)?;
        let mut value_hash = vec![0; 32];
        let mut sha3 = tiny_keccak::Sha3::v256();

        sha3.update(&value);
        sha3.finalize(&mut value_hash);

        self.internal_write_register(register_id, value_hash)
    }

The deterministic fee estimation has been done using the runtime-params-estimator to result in the following cost:

sha3_256_base: SAFETY_MULTIPLIER * 1513656750,
sha3_256_byte: SAFETY_MULTIPLIER * 8039117,

Standard scenarios

Smart contracts can access this API through the blockchain interface.

Guide level explanation:

A user wants to hash a particular data. The user calls the function sha3_256 from the smart contract. The result is the byte vector of the hash value.

Technical explanation:

The function sha3_256 accepts the length of the byte vector and its pointer as its input. When the user calls the function, it hashes the data with SHA3-256 FIPS 202 standard.

For the given parameters, test cases yielded the following results:

fn test_sha3_256() {
    use hex_literal::hex;

    let mut logic_builder = VMLogicBuilder::default();
    let mut logic = logic_builder.build(get_context(vec![], false));
    let data = hex!("0448250ebe88d77e0a12bcf530fe6a2cf1ac176945638d309b840d631940c93b78c2bd6d16f227a8877e3f1604cd75b9c5a8ab0cac95174a8a0a0f8ea9e4c10bca");
    let hash = hex!("c7647f7e251bf1bd70863c8693e93a4e77dd0c9a689073e987d51254317dc704");

    logic.sha3_256(data.len() as _, data.as_ptr() as _, 0).unwrap();
    let res = &vec![0u8; 32];
    logic.read_register(0, res.as_ptr() as _).expect("OK");

    assert_eq!(res, &hash);

    let len = data.len() as u64;
    assert_costs(map! {
        ExtCosts::base: 1,
        ExtCosts::read_memory_base: 1,
        ExtCosts::read_memory_byte: len,
        ExtCosts::write_memory_base: 1,
        ExtCosts::write_memory_byte: 32,
        ExtCosts::read_register_base: 1,
        ExtCosts::read_register_byte: 32,
        ExtCosts::write_register_base: 1,
        ExtCosts::write_register_byte: 32,
        ExtCosts::sha3_256_base: 1,
        ExtCosts::sha3_256_byte: len,
    });
}

Side-effects

  • Since this is a Runtime change, it would require a protocol upgrade.
  • The interface for the API should be included in the Smart contract SDKs.

Alternatives

Implementing the SHA3-265 FIPS 202 API directly into the smart contract will

  • Negatively affect the performance of the API
  • Increase the gas cost
  • Limit to one smart contract

Native addition will ensure better performance and reduce gas cost.

Pre-mortem

Since this is an add-on to the Math API, it is not expected to affect the existing behaviour of the runtime.

Libraries

  • tiny_keccak to implement SHA3 256 FIPS 202.
  • Alternative library:
    Octavo is a library that is in a very early stage of development and could be used in the future.
1 Like

Hey @MuhammedIrfan ! Thank you for the proposal!

How is it different from the existing sha3_256 host function?

Hi @nearmax Thank you for reviewing the proposal.

The existing keccak256 host function hashes the given value using the KECCAK-256 = Keccak[r = 1088, c = 512]. We propose to introduce the sha3-256 that uses FIPS-202 based standard. This standard was finalized according to the NIST, SHA3-256(M) = KECCAK [512] (M || 01, 256). This proposal posits an add-on to the MathAPI.

@eatmore What do you think?

Hi @nearmax . Hope you are doing good. Can you please guide us with the next steps? Can we start working on the proposal and raise a PR on nearcore and near-sdks to implement this feature?