Advance Topics

Encrypted Queries (To Be Updated…)

(Coming Soon on Testnet and Mainnet compatible with Iris update)

Certain contexts, such as smart contracts on public blockchains, might require a level of privacy to protect data from public scrutiny. Developers can make encrypted Say network queries by encrypting all of a query with a secret key. The encrypted queries feature may be of interested to developers who want to deploy their blockchain applications of public networks. For example, if an application leverages data from an authenticated API, it would be dangerous to disclose the API key to anyway who is monitoring the public chain.

One the query is encrypted, only Saynetwork will then be able to decrypt the request using the same secret key

To encrypt the query, Saynetwork provides a public webpage interface, which can be found at https://ae.say.network the backend is serving from api subdomain. Alternatively, A CLI tool is under development to encrypt an arbitrary string of text.

Encrypting of datasource URL in our case:

http://api.openweathermap.org/data/2.5/weather?q=amritsar&appid=my_real_key

Returns:

cf349a4ca439fc621bd5a76f4a87faf3b125baee81fcc1023ca361627e7dd58670e79bfffeb94591b1bcd86196e96b9395b47d74d2c6215743b75c35f857d77f98e085d1a98efb3c758504a34be5b276fe5e6044fcf86836cfcd7f267ccbb3f6531783b08413544ab2ff2f8b0309c0a413590948fff79ef9099635649cccb3cef06dd2a238ecfbbb38d015ed20a54e941c0b3867ca47b93247

The encryption uses aes-256-gcm, you just need to pass the query as UTF-8 string, salt and iv are randomly generated.

Example

include "Say.aes"
contract MyContract =
    record state = {
      query_id : bytes(32),
      answer: option(string)
     }

    stateful entrypoint init() = 
     Say.setOracle("oracle_ukey")
     {query_id = #000000000000000000000000000000000000000000000000000000000000000,
      answer = None}
    public entrypoint plus() : address =
      Say.getOracleAddress()

    payable stateful entrypoint query() : bytes(32) =
      require(Say.getBaseFee() =< Call.value, "Insufficient fee")
      let _id : bytes(32) = Say.query("cf349a4ca439fc621bd5a76f4a87faf3b125baee81fcc1023ca361627e7dd58670e79bfffeb94591b1bcd86196e96b9395b47d74d2c6215743b75c35f857d77f98e085d1a98efb3c758504a34be5b276fe5e6044fcf86836cfcd7f267ccbb3f6531783b08413544ab2ff2f8b0309c0a413590948fff79ef9099635649cccb3cef06dd2a238ecfbbb38d015ed20a54e941c0b3867ca47b93247", Call.value)
      put(state{query_id=_id})
      _id
    
    stateful entrypoint getAnswer() : option(string) =
      Say.getAnswer(state.query_id)

    stateful entrypoint useAnswer() : option(string) =
      put(state{answer = Say.getAnswer(state.query_id)})
      state.answer