Skip to content

Commit

Permalink
chore: Update to version 0.6.0 (#77)
Browse files Browse the repository at this point in the history
* feat: added more matrix inverse tests

* feat: updated python examples and tests for new client
  • Loading branch information
jcabrero authored Nov 21, 2024
1 parent f3c98b1 commit 1f49a94
Show file tree
Hide file tree
Showing 20 changed files with 2,245 additions and 1,401 deletions.
214 changes: 86 additions & 128 deletions examples/broadcasting/main.py
Original file line number Diff line number Diff line change
@@ -1,178 +1,136 @@
"""Broadcasting example script"""

import os
import sys

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

import asyncio
import os

import numpy as np
import py_nillion_client as nillion
from common.utils import compute, store_program, store_secret_array
import pytest
from config import DIM
from cosmpy.aerial.client import LedgerClient
from cosmpy.aerial.wallet import LocalWallet
from cosmpy.crypto.keypairs import PrivateKey
from dotenv import load_dotenv
from nillion_python_helpers import (create_nillion_client,
create_payments_config, get_quote,
get_quote_and_pay, pay_with_quote)
from py_nillion_client import NodeKey, UserKey
from nillion_client import (InputPartyBinding, Network, NilChainPayer,
NilChainPrivateKey, OutputPartyBinding,
Permissions, PrivateKey, SecretInteger, VmClient)

import nada_numpy.client as na_client

home = os.getenv("HOME")
load_dotenv(f"{home}/.config/nillion/nillion-devnet.env")


# Main asynchronous function to coordinate the process
async def main() -> None:
"""Main nada program"""
# 1 Party running simple addition on 1 stored secret and 1 compute time secret
async def main():
# Use the devnet configuration generated by `nillion-devnet`
network = Network.from_config("devnet")

cluster_id = os.getenv("NILLION_CLUSTER_ID")
grpc_endpoint = os.getenv("NILLION_NILCHAIN_GRPC")
chain_id = os.getenv("NILLION_NILCHAIN_CHAIN_ID")
seed = "my_seed"
userkey = UserKey.from_seed((seed))
nodekey = NodeKey.from_seed((seed))
client = create_nillion_client(userkey, nodekey)
party_id = client.party_id
user_id = client.user_id
# Create payments config and set up Nillion wallet with a private key to pay for operations
nilchain_key: str = os.getenv("NILLION_NILCHAIN_PRIVATE_KEY_0") # type: ignore
payer = NilChainPayer(
network,
wallet_private_key=NilChainPrivateKey(bytes.fromhex(nilchain_key)),
gas_limit=10000000,
)

# Use a random key to identify ourselves
signing_key = PrivateKey()
client = await VmClient.create(signing_key, network, payer)
party_names = na_client.parties(3)
program_name = "broadcasting"
program_mir_path = f"target/{program_name}.nada.bin"

# Create payments config and set up Nillion wallet with a private key to pay for operations
payments_config = create_payments_config(chain_id, grpc_endpoint)
payments_client = LedgerClient(payments_config)
payments_wallet = LocalWallet(
PrivateKey(bytes.fromhex(os.getenv("NILLION_NILCHAIN_PRIVATE_KEY_0"))),
prefix="nillion",
)
program_mir_path = f"./target/{program_name}.nada.bin"

##### STORE PROGRAM
print("-----STORE PROGRAM")

program_id = await store_program(
client,
payments_wallet,
payments_client,
user_id,
cluster_id,
program_name,
program_mir_path,
)
# Store program
program_mir = open(
os.path.join(os.path.dirname(os.path.abspath(__file__)), program_mir_path), "rb"
).read()
program_id = await client.store_program(program_name, program_mir).invoke()

##### STORE SECRETS
print("-----STORE SECRETS")
A = np.ones([DIM])
C = np.ones([DIM])
# Print details about stored program
print(f"Stored program_id: {program_id}")

# Create a permissions object to attach to the stored secret
permissions = nillion.Permissions.default_for_user(client.user_id)
permissions.add_compute_permissions({client.user_id: {program_id}})
##### STORE SECRETS
print("-----STORE SECRETS Party 0")

# Create a secret
store_id_A = await store_secret_array(
client,
payments_wallet,
payments_client,
cluster_id,
program_id,
A,
"A",
nillion.SecretInteger,
1,
permissions,
)
A = na_client.array(np.ones([DIM]), "A", SecretInteger)
C = na_client.array(np.ones([DIM]), "C", SecretInteger)

store_id_C = await store_secret_array(
client,
payments_wallet,
payments_client,
cluster_id,
program_id,
C,
"C",
nillion.SecretInteger,
1,
permissions,
# Create a permissions object to attach to the stored secret
permissions = Permissions.defaults_for_user(client.user_id).allow_compute(
client.user_id, program_id
)

# Create and store secrets for two parties
# Store a secret, passing in the receipt that shows proof of payment
values_A = await client.store_values(
A, ttl_days=5, permissions=permissions
).invoke()

B = np.ones([DIM])
D = np.ones([DIM])
print("Stored values_A: ", values_A)

store_id_B = await store_secret_array(
client,
payments_wallet,
payments_client,
cluster_id,
program_id,
B,
"B",
nillion.SecretInteger,
1,
permissions,
)
values_C = await client.store_values(
C, ttl_days=5, permissions=permissions
).invoke()

store_id_D = await store_secret_array(
client,
payments_wallet,
payments_client,
cluster_id,
program_id,
D,
"D",
nillion.SecretInteger,
1,
permissions,
print("Stored values_C: ", values_C)
print("-----STORE SECRETS Party 1")

# Create a secret
B = na_client.array(np.ones([DIM]), "B", SecretInteger)
D = na_client.array(np.ones([DIM]), "D", SecretInteger)

# Create a permissions object to attach to the stored secret
permissions = Permissions.defaults_for_user(client.user_id).allow_compute(
client.user_id, program_id
)

# Set up the compute bindings for the parties
compute_bindings = nillion.ProgramBindings(program_id)
# Store a secret, passing in the receipt that shows proof of payment
values_B = await client.store_values(
B, ttl_days=5, permissions=permissions
).invoke()

for party_name in party_names[:-1]:
compute_bindings.add_input_party(party_name, party_id)
compute_bindings.add_output_party(party_names[-1], party_id)
print("Stored values_B: ", values_B)

print(f"Computing using program {program_id}")
print(
f"Use secret store_id: {store_id_A}, {store_id_B}, {store_id_C}, {store_id_D}"
)
values_D = await client.store_values(
D, ttl_days=5, permissions=permissions
).invoke()

print("Stored values_D: ", values_D)

##### COMPUTE
print("-----COMPUTE")

# Bind the parties in the computation to the client to set input and output parties
compute_bindings = nillion.ProgramBindings(program_id)
compute_bindings.add_input_party(party_names[0], party_id)
compute_bindings.add_input_party(party_names[1], party_id)
compute_bindings.add_output_party(party_names[2], party_id)
input_bindings = [
InputPartyBinding(party_names[0], client.user_id),
InputPartyBinding(party_names[1], client.user_id),
]
output_bindings = [OutputPartyBinding(party_names[2], [client.user_id])]

# Create a computation time secret to use
computation_time_secrets = nillion.NadaValues({})

# Get cost quote, then pay for operation to compute
compute_time_values = {
# "my_int2": SecretInteger(10)
}

result = await compute(
client,
payments_wallet,
payments_client,
program_id,
cluster_id,
compute_bindings,
[store_id_A, store_id_B, store_id_C, store_id_D],
computation_time_secrets,
verbose=1,
# Compute, passing in the compute time values as well as the previously uploaded value.
print(
f"Invoking computation using program {program_id} and values id {values_A}, {values_B}, {values_C}, {values_D}"
)

compute_id = await client.compute(
program_id,
input_bindings,
output_bindings,
values=compute_time_values,
value_ids=[values_A, values_B, values_C, values_D],
).invoke()

# Print compute result
print(f"The computation was sent to the network. compute_id: {compute_id}")
result = await client.retrieve_compute_results(compute_id).invoke()
print(f"✅ Compute complete for compute_id {compute_id}")
print(f"🖥️ The result is {result}")
return result


# Run the main function if the script is executed directly
if __name__ == "__main__":
asyncio.run(main())
Loading

0 comments on commit 1f49a94

Please sign in to comment.