Programs

Programs

The purpose of an Entropy program is to determine whether a group of nodes should generate a signature or not. Developers can create and deploy programs, but validator nodes are the only agents that will directly interact with the programs once deployed. Programs do not return any data other than a success or failed response.

Quick summary

  1. What are Entropy Programs: WebAssembly (WASM) components used by signing nodes to determine whether they should generate a signature and how to generate that signature.
  2. Who uses them: validator nodes are the only agents directly interacting with deployed programs. However, Entropy Program developers will create, test, and deploy them. End-users do not directly interact with Entropy programs.
  3. What can they do: define which accounts can generate specific signatures and the process by which those nodes generate the signatures. Programs can contain custom hashing functions to create arbitrary signatures.
  4. What they can’t do: return any data other than success/failure responses, call external chains, access external data, or access any non-deterministic data.

Simple example

As a simple example, a program could be designed to check the length of a message. If the message is more than 10 characters, then the program returns OK, and the signing nodes create and return a valid signature to the account that submits the message. If the message is more than 10 characters, then the program fails, and no signature is created.

flowchart LR
  A[Entropy account]
  B{Length > 10}
  C[Signing nodes]
  D[Fail]
  E[Success]
 
  A --> | send message | B
  B -- true --> E
  E --> | generate signature | C
  C --> | valid signature | A
 
  B -- false --> D
You can view a Rust implementation of this example in the Entropy Programs GitHub repo.

Requirements

Entropy programs are WebAssembly components that implement an Entropy-specific interface. The only function that a user must manually implement is evaluate, which takes the user’s signature request as input and returns a success or an error. If no error is returned, then the message in the signature request will be signed using the program’s corresponding key pair with the specified hashing algorithm.

Program Configs

Programs can include a configuration which allows users to modify the evaluation behaviour without having to recompile and upload a new program to the chain. The format of this is undefined, allowing a configuration to be defined as a serialized C-compatible struct, UTF-8 JSON string, or anything in between.

Auxiliary Data

Programs can require users to include auxiliary data, separate from the message, in their signature request.

Oracle Data

Oracle data is information that can be grabbed by the chain and passed through to Entropy programs. The programs can then do whatever they want with this data. The data contained by the oracles comes from the Oracle pallet and OracleData storage slot OracleData takes in a key and outputs the value associated with that key. Since all programs must be deterministic, oracle data needs to come from the chain.

Available oracles

The following table lists the currently available oracles:

KeyValueType
block_number_entropyStores the current block number of entropy.u32

Encoding and decoding

All oracle data is SCALE encoded. To decode oracle data use:

impl Program for OracleExample {
    fn evaluate(
        _signature_request: SignatureRequest,
        _config: Option<Vec<u8>>,
        oracle_data: Option<Vec<Vec<u8>>>,
    ) -> Result<(), Error> {
        let data = oracle_data.ok_or(Error::Evaluation("No oracle data provided.".to_string()))?;
        let block_number = u32::decode(&mut data[0].as_ref())
            .map_err(|_| Error::Evaluation("Unable to decode oracle data".to_string()))?;
        if block_number > 100 {
            return Err(Error::Evaluation("Block Number too large".to_string()));
        }
        Ok(())
    }

    fn custom_hash(_data: Vec<u8>) -> Option<Vec<u8>> {
        None
    }
}

A complete copy of the above example can be found in the Entropy Core GitHub repository.

Custom Hashing

As ECDSA schemes sign 256-bit numbers, programs can include a custom_hash function so users can utilize less common hashing functions. In its simplest form, the function converts a signature request (which also contains the message) into a 256-bit number.

Limitations

Size

Compiled programs must be less than 1 MB.

External data

Programs must be deterministic and cannot currently call other chains or directly access external data. However, developers can pass in auxiliary data, which can be obtained when the program is deployed.

Calling other programs

Programs cannot currently call other programs, however this is a planned feature.

As a workaround, you can set a list of programs that are evaluated one after the other. For example:

  1. Check a signature in the auxiliary data with the device key proxy program
  2. Check that the message is an EVM transaction with the ’to’ field matching an allow list with the ACL program.

Randomness

Programs cannot access the operating system’s random number generator.

If the program is not deterministic, it will cause issues because the nodes will only receive a signature if all TSS nodes involved in the signature request successfully evaluate the program. However, users can input random data into the program through the auxiliary data. Programs do not have access to the operating system’s random number generator. If the program is non-deterministic, there will be problems, as the nodes will only get a signature if all TSS nodes involved in the signature request successfully evaluate the program. However, users can pass random data into the program through the auxiliary data.

Upload Programs

Programs are written and compiled to WASM using the entropyxyz/programs repository.

The workflow is as follows:

  1. A program owner calls set_program in the program pallet with:
    • the program bytecode
    • the configuration interface, which is a serialized JSON object that allows a user to know the configuration of the program and then set their own individualized configuration in programsData
    • The signing key signs the transaction and becomes the deployer key
    • A reference counter gets set to 0 when uploading and is used to track how many users are using a program
  2. A program then gets stored in the Programs storage slot with the key being H(bytecode + configuration_interface). The hash is used by a user to point to the programs they want applied to their key. Every time a program is referenced, the reference counter increments
  3. Since the key is a hash, it is not possible to edit or modify programs (since that would change the hash).
  4. Programs can be removed if the ref count is zero by the deploy key

Device-proxy

The device-proxy program is an Entropy program available at 0000000000000000000000000000000000000000000000000000000000000000. Its main functionality is to:

  1. Verify signatures based on the provided configuration and auxiliary data.
  2. Check if a given public key is in the allowed set of keys (from the provided config).
  3. Verify the generated signature against the provided message.