Key Decryption Oracle
What you’ll do
- Start a local test chain (anvil).
- Deploy the on-chain Key Decryption Oracle Contract.
- Start the off-chain Key Decryption Oracle.
- Deploy the on-chain demo contract that talks to the key decryption oracle contract.
- Check the results stored in the demo contract.
Required Installations
You need foundry (for the chain tooling) and jbang (to start a web service with the renderer).
For installation instructions see the setup page.
Apart from this we assume that cat, tr and sed are present.
The following commands should be run in a shell (macOS Terminal, Windows GitBash). You may use the copy button and just paste them into the shell.
Step-by-Step
1. Launch a local chain for testing
Run:
anvil
2. Deploy the Key Decryption Oracle Contract and the Demo Contract
2.1. Download KeyDecryptionOracle.sol and DemoContract.sol
Run:
REPO=https://gitlab.com/finmath/finmath-decryption-oracle/-/raw/main/oracle-keys
curl --create-dirs -L $REPO/src/main/solidity/IKeyDecryptionOracleCallback.sol -o IKeyDecryptionOracleCallback.sol
curl --create-dirs -L $REPO/src/main/solidity/IKeyDecryptionOracle.sol -o IKeyDecryptionOracle.sol
curl --create-dirs -L $REPO/src/main/solidity/KeyDecryptionOracle.sol -o KeyDecryptionOracle.sol
curl --create-dirs -L $REPO/src/main/solidity/DemoContract.sol -o DemoContract.sol
2.2. Build and deploy the contract KeyDecryptionOracle
Run:
export RPC_URL="http://127.0.0.1:8545"
export PRIVATE_KEY="0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"
OWNER=$(cast wallet address --private-key "$PRIVATE_KEY")
CONTRACT_PATH=.
CONTRACT_NAME=KeyDecryptionOracle
FULFILLMENTMODE=0
PERMISSIONLESS=true
CONTRACT_ADDRESS=$(
forge create --use 0.8.20 --broadcast --root . --json "$CONTRACT_PATH/$CONTRACT_NAME.sol:$CONTRACT_NAME" --rpc-url "$RPC_URL" --private-key "$PRIVATE_KEY" \
--constructor-args "$OWNER" "$FULFILLMENTMODE" "$PERMISSIONLESS" \
| tr -d '\r\n' \
| sed -nE 's/.*"deployedTo"[[:space:]]*:[[:space:]]*"(0x[0-9a-fA-F]{40})".*/\1/p'
)
echo "Contract deployed at $CONTRACT_ADDRESS"
2.3. Build and deploy the contract DemoContract
Run:
export RPC_URL="http://127.0.0.1:8545"
export PRIVATE_KEY="0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"
OWNER=$(cast wallet address --private-key "$PRIVATE_KEY")
CONTRACT_PATH=.
CONTRACT_NAME=DemoContract
DEMO_CONTRACT_ADDRESS=$(
forge create --use 0.8.20 --broadcast --root . --json "$CONTRACT_PATH/$CONTRACT_NAME.sol:$CONTRACT_NAME" --rpc-url "$RPC_URL" --private-key "$PRIVATE_KEY" \
--constructor-args "$CONTRACT_ADDRESS" \
| tr -d '\r\n' \
| sed -nE 's/.*"deployedTo"[[:space:]]*:[[:space:]]*"(0x[0-9a-fA-F]{40})".*/\1/p'
)
echo "Contract deployed at $DEMO_CONTRACT_ADDRESS"
3. Launch the KeyDecryptionOracle service (locally)
3.1. Download the script that will generate a new private key for the decryption oracle.
REPO=https://gitlab.com/finmath/finmath-decryption-oracle/-/raw/main
curl --create-dirs -L $REPO/scripts/generate-keys.sh -o generate-keys.sh
chmod 755 generate-keys.sh
3.2. Generate the private key for the key decryption oracle
export SECRETS_DIR=$(pwd)/secrets
./generate-keys.sh
3.3. Launch the KeyDecryptionOracle service (locally)
Run (in the same shell that deployed the contract and the same folder as $SECRETS_DIR):
jbang --java 21 -Dethereum.rpcUrl=http://127.0.0.1:8545 -Dethereum.chainId=1337 -Dethereum.keydecryptionoracle.contract=$CONTRACT_ADDRESS -Dethereum.keydecryptionoracle.stateFile=oracle-state.txt net.finmath:finmath-decryption-oracle-encrypted-hashed-keys:2.5.5 > jbang.log 2>&1 </dev/null &
3.4. Show the log of the KeyDecryptionOracle
(Optional): In a new Window / shell, in the same directory, run:
tail -f jbang.log
This allows you to observe the log of the decryption oracle service.
Then return to the previous shell that deployed the contract (this is important, because we will use the environment variables $CONTRACT_ADDRESS and $DEMO_CONTRACT_ADDRESS).
4. Key Generation
4.1 Trigger a key generation (through the demo contract)
Run:
ID=1
TRANSACTION=0x0002
cast send "$DEMO_CONTRACT_ADDRESS" \
"requestGenerate(uint256,bytes)" $ID $TRANSACTION \
--rpc-url "$RPC_URL" --private-key "$PRIVATE_KEY" --legacy --gas-price 1gwei --gas-limit 300000
The demo contract will trigger a key generation and will await the result. The result will be stored under result id $ID.
4.2 Define a Helper Function to Fetch the Result form the Contract
We define a function that fetches the result from the demo contract.
After this function has been defined we may fetch a result from the contract via oracle_get_result <id>.
Run:
oracle_get_result () {
local id="$1"
local sig='getResult(uint256)(uint8,uint8,address,bytes,bytes,bytes,address,bytes,uint256,uint256)'
# temp file to avoid subshell issues
local tmpfile
tmpfile="$(mktemp)"
cast call "$DEMO_CONTRACT_ADDRESS" "$sig" "$id" --rpc-url "$RPC_URL" > "$tmpfile" || {
rm -f "$tmpfile"
echo "cast call failed" >&2
return 1
}
vars=(status kind requester key encryptedKey hashedKey receiverContract transaction createdAt updatedAt)
{
for v in "${vars[@]}"; do
IFS= read -r "$v" || break
done
} < "$tmpfile"
rm -f "$tmpfile"
# Optional pretty print
cat <<RESULT
kind..............: $kind (1=generate, 2=verify, 3=decrypt)
status............: $status (0=None, 1=Pending, 2=Generated, 3=Verified, 4=Released, 5=Denied)
requester.........: $requester
key...............: $key
encryptedKey......: $encryptedKey
hashedKey.........: $hashedKey
receiverContract..: $receiverContract
transaction.......: $transaction
createdAt.........: $createdAt
updatedAt.........: $updatedAt
RESULT
}
4.3 Fetch the Result
Run:
oracle_get_result $ID
This will fetch the rsult. The encrypted key will be stored under $encryptedKey.
5. Key Verification
5.1. Request a Key Verification
We take the previously generated $encryptedKey and request a verification, that is, the oracle will confirm
us the hash of the key, the decrypted $encryptedKey, without exposing that key.
Run:
ID=2
ENC_KEY=$encryptedKey
cast send "$DEMO_CONTRACT_ADDRESS" \
"requestVerify(uint256,bytes)" $ID $ENC_KEY \
--rpc-url "$RPC_URL" --private-key "$PRIVATE_KEY" --legacy --gas-price 1gwei --gas-limit 300000
5.2 Fetch the Result
Run:
oracle_get_result $ID
This will fetch and display the result.
6. Decryption
6.1. Request a Key Decryption
We take the previously generated $encryptedKey and request a decryption. The decryption can only be requested to be submitted to
an eligible contract (information that is contained in the key) - in our case the demo contract is eligible.
Run:
ID=3
ENC_KEY=$encryptedKey
cast send "$DEMO_CONTRACT_ADDRESS" \
"requestDecrypt(uint256,bytes,bytes)" $ID $ENC_KEY $TRANSACTION \
--rpc-url "$RPC_URL" --private-key "$PRIVATE_KEY" --legacy --gas-price 1gwei --gas-limit 300000
6.2 Fetch the Result
Run:
oracle_get_result $ID
This will fetch and display the result.
Last updated: 2025‑12‑24
