Becoming an oracle provider for StarkEx
StarkEx uses external price feeds, which oracle providers pass to the operator. The operator sends the price tick to the StarkEx gateway using the addTransaction
method with the OraclePricesTick
transaction. StarkEx supports combining prices from a quorum of oracle providers into a single price update.
For more information, see Oracle price tick.
You can become an oracle provider for a StarkEx-powered application by contacting the application operator and completing the following tasks:
-
Install and run the StarkEx CLI.
-
Derive your Stark key pair from an Ethereum key pair.
-
Add the public Stark key to the general configuration.
-
Start signing prices.
These tasks are described below.
Installing and running the StarkEx CLI
-
Docker
-
Git
-
1GB of free disk space in the Docker working directory (
/var/lib/docker
)
-
Using Git, clone the stark-perpetual repository at https://github.com/starkware-libs/stark-perpetual.
-
Navigate to the
stark-perpetual
directory and build the StarkWare Perpetual Docker image.$ docker build . -t stark-perpetual
This command builds a container named
stark_perpetual
that includes all dependencies and runs various tests. -
Run the
stark-perpetual
cli from the image:$ docker run --rm --entrypoint /bin/bash -it stark-perpetual
A shell opens with a prompt similar to the following:
`root@17617744386d:/app#`.
-
Activate the virtual environment:
root@17617744386d:/app# source build/Release/src/services/perpetual/public/perpetual_public_venv/bin/activate
The following prefix appears in the command prompt:
(perpetual_public_venv)
The StarkEx CLI console is now running. You can view command line help by entering the following command:
(perpetual_public_venv) <prompt>:/app# python src/services/perpetual/public/stark_cli.py
--help
Deriving your Stark key pair from an Ethereum key pair.
STARK proofs use signatures based on the STARK curve, which differ from Ethereum signatures. So in order to sign on prices for the system you need to create a private and public Stark key pair.
The procedure described here is simple and secure.
-
An Ethereum private key
-
Create an Ethereum signature using your private Ethereum key and the constant string
StarkKeyDerivation
, or its hex representation,0x537461726b4b657944657269766174696f6e
. -
Use the Keccak hash function to hash r and s signature components to one 256-bit word.
-
Remove the last five bits of the resulting number to get the 251-bit private Stark key.
-
Derive the public Stark key from the private Stark key with the
get_public
method:(perpetual_public_venv) <prompt>:/app# python src/services/perpetual/public/stark_cli.py \ --method get_public \ --key <private_stark_key>
This example uses the following Ethereum private key and signature to derive the public and private Stark key.
Ethereum private key |
0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d |
Ethereum signature |
fd85e77f5bb436eb90a4c3324a02fea6ef766e6ac85bffccb6e1cdc03479e9ac 058e6fb13916131dd4df1911098e2df71d582ab86281bf2553e55571aa99064b 1c |
Ethereum signature hash |
|
Using the above Ethereum signature hash, you can derive the private and public Stark keys as follows:
-
Remove the last five bits of the Ethereum signature hash to get the 251-bit private Stark key.
The resulting private Stark key is
178047D3869489C055D7EA54C014FFB834A069C9595186ABE04EA4D1223A03F
-
Derive the public Stark key using the
get_public
method:(perpetual_public_venv)
:/app# python src/services/perpetual/public/stark_cli.py \ --method get_public \ --key 178047D3869489C055D7EA54C014FFB834A069C9595186ABE04EA4D1223A03F The resulting public Stark key is
0x1895a6a77ae14e7987b9cb51329a5adfb17bd8e7c638f92d6892d76e51cebcf
.
Adding the public Stark key to the general configuration
In order for the STARK proof to be able to use the oracle’s signature, the oracle’s signature must be part of the application’s general configuration, defined in the StarkEx contract for the application.
The application’s general configuration includes a list of public keys that are permitted to sign on each type of synthetic asset. For more information, see Configuration Per Synthetic assetId.
For security reasons, when you add a new public key to the general configuration of a deployed system, StarkEx requires a period of time before the new key goes into effect. This period enables users that do not approve of the change to exit. |
As an oracle provider, you cannot directly change the configuration, only the application’s operator can edit the configuration.
This procedure requires the participation of the following parties:
-
the oracle provider
-
the operator
-
StarkWare
-
A public Stark key.
-
The operator’s consent to add the oracle provider.
-
Oracle provider: Send your public Stark key to the operator that owns the application for which you want to provide oracle price ticks.
-
operator: For each type of synthetic asset that the oracle provider supports, add the key to the list of trusted public keys in the general configuration. The hash of the general configuration is part of the onchain contract.
StarkWare sees the changes and updates the contract.
-
StarkWare: After a waiting period, StarkWare publishes the updated contract.
Signing prices
Calculating the hash to sign
The hash
method generates a number, which is less than FIELD_PRIME
, that the sign
method uses to generate a signature.
The method first uses the asset_name
and oracle_name
parameters to generate a number that occupies 252 bits according to the following mapping:
84 bits | 128 bits | 40 bits |
---|---|---|
0 |
|
|
Then, it uses the price
and the timestamp
parameters to generate a second number that occupies 252 bits according to the following mapping:
100 bits | 120 bits | 32 bits |
---|---|---|
0 |
|
|
Finally, it executes a Pedersen hash function using the two generated numbers to generate hash data.
-
Call the
hash
method:(perpetual_public_venv) <prompt>:/app# python src/services/perpetual/public/stark_cli.py \ --method hash \ --oracle <oracle> \ --asset <asset> \ --price <price> \ --time <timestamp>
Where the parameters are as follows:
oracle
The hex encoding for your oracle’s name.
A 40-bit number.asset
The hex encoding of a name you choose for the asset pair. For example:
BTCUSD
.
A 128-bit number.price
The hex encoding of the price.
A 120-bit number, with 18 digits after the decimal point.timestamp
Seconds since the Unix epoch.
A 32-bit number.
All providers should use the same hex values to refer to the same assets and oracles.
For example, consider that asset
refers to BTCUSD
, and oracle
refers to Maker. All data providers should use the same hex values for BTCUSD
, and the same hex values for Maker
, in their signatures.
The hash
method combines and hashes the parameters.
This example uses the following information:
-
oracle
= The hex value ofMaker
, which is0x4d616b6572
. -
asset
= The 128-bit hex value ofBTCUSD
, which is0x42544355534400000000000000000000
. -
price
: The prices is $11512.34. The hex value of11512.34
* 1018 is0x27015cfcb0230820000
. -
timestamp
: The timestamp of the transaction is January 1st, 2020, which is 1577836800 seconds after the Unix epoch. The hex value of1577836800
is0x5e0be100
The hash function generates the following numbers:
-
first_number
=425443555344000000000000000000004d616b6572
, constructed as follows:84 bits 128 bits 40 bits 0
, not shown in the result425443555344
, the hex encoding ofBTCUSD
, followed by trailing zeroes that occupy the remaining bits4d616b6572
, the hex encoding ofMaker
-
second_number
= 0 (100-bit) || price (120-bit) || timestamp (32-bit) = 27015cfcb02308200005e0be100100 bits 120 bits 32 bits 0
, not shown in the result27015cfcb0230820000
, the hex encoding of 11512.34 * 10185e0be100
, the hex encoding of 1577836800, which is the number of seconds since the Unix epoch.The leading zeroes, which occupy the first 84 bits, do not appear in this example.
-
data_hash = pedersen(first_number, second_number) = 3e4113feb6c403cb0c954e5c09d239bf88fedb075220270f44173ac3cd41858
(perpetual_public_venv) $:/app# python src/services/perpetual/public/stark_cli.py \
--method hash \
--oracle 4d616b6572 \
--asset 42544355534400000000000000000000 \
--price 27015cfcb0230820000 \
--time 5e0be100
Signing the hashed message
-
Call the
sign
method:(perpetual_public_venv) <prompt>:/app# python src/services/perpetual/public/stark_cli.py \ --method sign \ --key <key> \ --data <data>
Where the parameters are as follows:
key
The private Stark key.
data
The hash of the message data.
This example uses:
-
the private Stark key from Example: Deriving a Stark key pair for the
key
parameter -
the value for
data_hash
from Example: Calculating the hash to sign for thedata
parameter
(perpetual_public_venv) <prompt>:/app# python src/services/perpetual/public/stark_cli.py \
--method sign \
--key 178047D3869489C055D7EA54C014FFB834A069C9595186ABE04EA4D1223A03F \
--data 3e4113feb6c403cb0c954e5c09d239bf88fedb075220270f44173ac3cd41858
The resulting signature is:
r: 0x6a7a118a6fa508c4f0eb77ea0efbc8d48a64d4a570d93f5c61cd886877cb920
s: 0x6de9006a7bbf610d583d514951c98d15b1a0f6c78846986491d2c8ca049fd55