Verify Mercury bank account balance
Introduction
This vFunction proves whether or not the balance of a Mercury bank account is greater than a given value. This process ensures that only the vFunction can obtain the secrets required to access the Mercury bank account, and it can share the result in a verifiable way.
The vFunction runs in a secure environment, it then asks for secrets to a provider, this provider verifies the identity of the vFunction and checks its authenticity. After that it shares the secrets with the vFunction, then the vFunction can access the Mercury Bank API and process the information. Lastly, the vFunction signs the results and publishes them.
Write the vFunction
The first step is for the vFunction to get the Mercury API secrets for the account whose balance is to be proved. The vFunction uses the SDK to prove its identity and get the secrets from the account owner's secrets provider (there are several types of secrets providers, eg: via mobile app, web socket server, or HTTP server, we use a web socket server here).
The secrets provider validates vFunction identity to ensure that it is the code to prove a Mercury account balance. If the checks pass, the secrets provider encrypts the account's API credentials with the vFunction's public key. This means that no one but the vFunction can decrypt the credentials.
function_params = vFunction.FunctionParams()
# Get the secrets from the provider
secrets_bundle = connection.WsockSecretsProvider(function_params).get_secrets()
account_id = secrets_bundle["mercuryBank"]["accountId"]
mercury_token = secrets_bundle["mercuryBank"]["mercuryToken"]
recipient_email = secrets_bundle["email"]
balance_threshold = secrets_bundle["threshold_balance"]
# Get the information from the mercury account
result_value = mercury_balance_check(account_id, mercury_token, balance_threshold)With the secrets obtained from the provider, the vFunction can call the Mercury Bank APIs. In this case, we want to know if the balance of a Mercury bank account is greater than a given value. The vFunction uses the secrets to access and process the bank account information.
def mercury_balance_check(account_id, mercury_token, balance_threshold):
# Set the url for the mercury API to get the account information
# Use the account id
mercury_bank_url = "https://api.mercury.com/api/v1/account/{}".format(account_id)
# Use the mercury token for the API
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": "Bearer {}".format(mercury_token)
}
response = requests.request("GET", mercury_bank_url, headers=headers)
mercury_data = json.loads(response.text)
if "errors" in mercury_data:
return False
if mercury_data["currentBalance"] > balance_threshold:
return True
return FalseThe final step is to include the results of the computation and sign them with AWS's private key. The document is delivered by email (or any other delivery method that you can code including blockchains) and can be used as proof. Anyone can use AWS's public key to validate the results of this computation.
result_dict = {
"result": result_value,
"balance": balance_threshold
}
# Send the email with the results
function_params.email_results(recipient_email, result_dict)Full code example
Check the full code for this vFunction in the vfunction-sdk repository.
Build the verifiable vFunction
Once you have written your vFunction you need to build it so it can be verified. For this, you will use the verifiably build API.
Upload your vFunction
You will upload your vFunction as a zip file which includes a file named main.py which contains the process of the function, a requirements file requirements.txt with the required dependencies, a Dockerfile named customer.Dockerfile which has the steps to build your function, and a bash script named run.sh which tells the vFunction to start the main python script. You compress those files and the generated zip is the vFunction file you will upload.
Check Mercury bank example files, for an example of each type of file and the generated zip.
Use the API to generate a URL to upload the file, send the "objectKey" which is the name that the file with being saved with. In this case, we are going to save the file as mercuryBankExample.zip.
curl --request POST -H "x-api-key: <api-key>" -H "x-api-key-id: <api-key-id>" --data
'{"objectKey":"mercuryBankExample.zip"}' "https://vbuild.us-east-2.verifiably.com/source"You will get a presigned url, use that url to upload the file and send the file from your computer.
curl -X PUT -H "Content-type: multipart/form-data" -T mercuryBankExample.zip
-L "<presigned-url>"Build your vFunction
Once you have uploaded your vFunction file you can use the API to start the build process. You will need to send the name and the sha256 of the zip file you uploaded as well as the sha256 of the docker image you are using. For more information about hashes visit Hash documentation. In this case we are going to use the hash for the python base image that you can inspect following the base image inspection.
curl --request POST -H "x-api-key: <api-key>" -H "x-api-key-id: <api-key-id>" --data
'{"objectKey":"mercuryBankExample.zip",
"zipSHA":"2cba0efa3c42c7411f982d0315aa52c1b5f667ea49c0a1ca473eca483df8bf86",
"imageSHA":"sha256:eac311267cb4ea66a7d71caa42c24aa5e78f72ad599dad9454362e6c5aea603d"}'
"https://vbuild.us-east-2.verifiably.com/build"Check the build status
To check the status of your build, use the API and send the build id you got when you started the build.
curl --request GET -H "x-api-key: <apai-key>" -H "x-api-key-id: <api-key-id>"
"https://vbuild.us-east-2.verifiably.com/build/<build-id>"Run the secrets server
To setup the server you will need to install the python library wsock-secrets-provider, and then write the code of your secrets provider where you include the secrets and the pcr you are going to accept. To obtain the values of your PCR check Obtain PCR values for your build.
from verifiably_wsock_secrets_provider import credentials_provider
credentials = {
"mercuryBank":{
"accountId": "accountId",
"mercuryToken": "mercuryToken"
},
"email": "youremail@email.com",
"threshold_balance": 5000
}
expected_pcrs = {
"0": "7fe1bebdf111b0ec18bb7b015f750d38e9f60a1c5734386d75e5c3e44739bf756f60d6f0169931d52491bcfa76bf9f04",
"1": "bcdf05fefccaa8e55bf2c8d6dee9e79bbff31e34bf28a99aa19e6b29c37ee80b214a414b7607236edf26fcb78654e63f",
"2": "5b28485e4162b83b2ebe3d6eb6e6e0035eca7c8da771d4d6ee913ad2b336a2d348980056f3cc510a6181c2b237f3bfc0"
}
secretProvider = credentials_provider.SecretsProvider(credentials, expected_pcrs)
secretProvider.start()Run this python script and it will start a provider, you will be prompted with a connection id, this connection id will be used to execute the vFunction.
Execute the vFunction
Use the verifiably API to execute the vFunction, send the build id of the build you want to execute and the connection id of the provider that will share the secrets with the vFunction.
curl --request POST -H "x-api-key: <api-key>" -H "x-api-key-id: <api-key-id>" --data
'{"build_id":"<build-id>",
"params": {"wSockConnectionId":"<wsock-connection-id>"}}'
"https://vfunctions.us-east-2.verifiably.com/execution"Check execution status
You can get the execution status using the execution id you got when calling the API.
curl --request GET -H "x-api-key: <api-key>" -H "x-api-key-id: <api-key-id>"
"https://vfunctions.us-east-2.verifiably.com/execution/<execution-id>"Verify the results
Once you receive your vFunction results you can easily verify and get the signed values. Just use the verifiably checker python library. Use the following code as a guide. When you run it, it will check the authenticity of the results and print them.
from verifiably_checker import attestation
expected_pcrs = {
"0": "7fe1bebdf111b0ec18bb7b015f750d38e9f60a1c5734386d75e5c3e44739bf756f60d6f0169931d52491bcfa76bf9f04",
"1": "bcdf05fefccaa8e55bf2c8d6dee9e79bbff31e34bf28a99aa19e6b29c37ee80b214a414b7607236edf26fcb78654e63f",
"2": "5b28485e4162b83b2ebe3d6eb6e6e0035eca7c8da771d4d6ee913ad2b336a2d348980056f3cc510a6181c2b237f3bfc0"
}
# Use the name of the results you got from the vFunction
results_file = 'result_att_doc.txt'
with open(results_file, 'r') as f:
vfunctions_results = f.read()
# Use the results to get the user data
if attestation.verify_attestation_doc(vfunctions_results, expected_pcrs):
user_data = attestation.get_user_data(vfunctions_results)
print(user_data)