Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/auctions #39

Merged
merged 4 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions nada-project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -243,3 +243,13 @@ prime_size = 128
path = "src/shuffle_simple.py"
name = "shuffle_simple"
prime_size = 128

[[programs]]
path = "src/auction.py"
name = "auction"
prime_size = 128

[[programs]]
path = "src/auction_can_tie.py"
name = "auction_can_tie"
prime_size = 128
1 change: 1 addition & 0 deletions nillion_client_script.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ async def store_inputs_and_run_blind_computation(
blind_computation_results = compute_event.result.value
return {
'user_id': user_id,
'user_key': userkey,
'program_id': program_id,
'store_ids': store_ids,
'output': blind_computation_results,
Expand Down
26 changes: 26 additions & 0 deletions src/auction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from nada_dsl import *

def nada_main():
# Define parties
auctioneer = Party(name="auctioneer")
num_bidders = 5
bidders = [Party(name=f"bidder_{i}") for i in range(num_bidders)]

# Collect bids from each party
bids = [SecretInteger(Input(name=f"bid_{i}", party=bidders[i])) for i in range(num_bidders)]

# Initialize variables to track the highest bid and the winning party index
highest_bid = bids[0]
winning_index = Integer(0)

# Compare bids to find the highest
for i in range(1, num_bidders):
is_higher = bids[i] > highest_bid
highest_bid = is_higher.if_else(bids[i], highest_bid)
winning_index = is_higher.if_else(Integer(i), winning_index)

# Output the highest bid and the winning party index
return [
Output(highest_bid, "highest_bid", auctioneer),
Output(winning_index, "winning_index", auctioneer)
]
30 changes: 30 additions & 0 deletions src/auction_can_tie.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from nada_dsl import *

def nada_main():
# Define the auctioneer as the party responsible for overseeing the auction results
auctioneer = Party(name="auctioneer")

# Create a list of 5 bidders participating in the auction, 'bidder_0' to 'bidder_4'
num_bidders = 5
bidders = [Party(name=f"bidder_{i}") for i in range(num_bidders)]

# Collect bids from each bidder, where each bid is a SecretInteger input unique to the respective bidder
bids = [SecretInteger(Input(name=f"bid_{i}", party=bidders[i])) for i in range(num_bidders)]

# Determine the highest bid among all the bidders
# Start by initializing the highest bid to the first bidder's bid
highest_bid = bids[0]
# Iterate through the remaining bids to update the highest bid if a higher one is found
for i in range(1, num_bidders):
is_higher = bids[i] > highest_bid
highest_bid = is_higher.if_else(bids[i], highest_bid)

# Create a list of outputs for each bidder, indicating if their bid matches the highest bid
# Each output is a flag (1 if the bid matches the highest bid, 0 otherwise), visible to the auctioneer
flag_highest_bid = [
Output((bids[i] == highest_bid).if_else(Integer(1), Integer(0)), f"bidder_{i}_flag_highest_bid", auctioneer)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice

for i in range(num_bidders)
]

# Return the highest bid and a list of flags indicating which bidders flag the highest bid
return [Output(highest_bid, "highest_bid", auctioneer)] + flag_highest_bid
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the + here concatenation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, this is so that the outputs of the highest_bid and all the individual bid result flags are returned

15 changes: 10 additions & 5 deletions streamlit_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def create_party_inputs(input_info, input_values):
# Distribute parties between the columns
for i, party_name in enumerate(party_names):
with columns[i % len(columns)]:
st.subheader(f"{party_name}'s Inputs")
st.subheader(f"{party_name}'s inputs")
for input_name, value in input_values.items():
if input_info[input_name]['party'] == party_name:
input_type = input_info[input_name]['type']
Expand Down Expand Up @@ -222,9 +222,10 @@ def main(nada_test_file_name=None, path_nada_bin=None, path_nada_json=None):

st.subheader("Nada Program Result")

st.text('Output(s)')
# st.text('Output(s)')
st.success('Output(s)', icon="🖥️")
st.caption(f"The Nada program returned one or more outputs to designated output parties - {output_parties}")
st.success(result_message['output'], icon="🖥️")
st.json(result_message['output'])

st.text('Nilchain Nillion Address')
st.caption(f"Blind computation ran on the Nillion PetNet and operations were paid for on the Nilchain Testnet. Check out the Nilchain transactions that paid for each PetNet operation (store program, store secrets, compute) on the [Nillion Testnet Explorer](https://testnet.nillion.explorers.guru/account/{result_message['nillion_address']})")
Expand All @@ -234,8 +235,12 @@ def main(nada_test_file_name=None, path_nada_bin=None, path_nada_json=None):
st.caption('The Store IDs are the unique identifiers used to reference input values you stored in the Nillion Network on the PetNet.')
st.code(result_message['store_ids'], language='json')

st.text('PetNet User ID')
st.caption(f"The User ID is derived from your PetNet user public/private key pair and serves as your public user identifier on the Nillion Network. The user key is randomized every time you run this demo, so the User ID is also randomized.")
st.text('User Key')
st.caption(f"The user key is a private key derived from a PetNet user public/private key pair. It is randomized every time you run this page for the sake of the demo, ensuring that the key is different for each session.")
st.code(result_message['user_key'], language='json')

st.text('User ID')
st.caption(f"The user id is derived from your PetNet user key and serves as your public user identifier on the Nillion Network. Since the user key is randomized with each run of the demo, the user id is also randomized accordingly.")
st.code(result_message['user_id'], language='json')

st.text('Program ID')
Expand Down
26 changes: 26 additions & 0 deletions streamlit_demo_apps/app_auction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# This file was automatically generated by the generate-streamlit-app script.
# To run this file: from the root directory run `streamlit run streamlit_demo_apps/app_auction.py`

import sys
import os

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import streamlit_app

program_name = "auction"
program_test_name = "auction_test_1"

def main():
current_dir = os.path.dirname(os.path.abspath(__file__))
path_nada_bin = os.path.join(current_dir, "compiled_nada_programs", f"{program_name}.nada.bin")
path_nada_json = os.path.join(current_dir, "compiled_nada_programs", f"{program_name}.nada.json")

if not os.path.exists(path_nada_bin):
raise FileNotFoundError(f"Add `{program_name}.nada.bin` to the compiled_nada_programs folder.")
if not os.path.exists(path_nada_json):
raise FileNotFoundError(f"Run nada build --mir-json and add `{program_name}.nada.json` to the compiled_nada_programs folder.")

streamlit_app.main(program_test_name, path_nada_bin, path_nada_json)

if __name__ == "__main__":
main()
26 changes: 26 additions & 0 deletions streamlit_demo_apps/app_auction_can_tie.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# This file was automatically generated by the generate-streamlit-app script.
# To run this file: from the root directory run `streamlit run streamlit_demo_apps/app_auction_can_tie.py`

import sys
import os

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import streamlit_app

program_name = "auction_can_tie"
program_test_name = "auction_can_tie_test_1"

def main():
current_dir = os.path.dirname(os.path.abspath(__file__))
path_nada_bin = os.path.join(current_dir, "compiled_nada_programs", f"{program_name}.nada.bin")
path_nada_json = os.path.join(current_dir, "compiled_nada_programs", f"{program_name}.nada.json")

if not os.path.exists(path_nada_bin):
raise FileNotFoundError(f"Add `{program_name}.nada.bin` to the compiled_nada_programs folder.")
if not os.path.exists(path_nada_json):
raise FileNotFoundError(f"Run nada build --mir-json and add `{program_name}.nada.json` to the compiled_nada_programs folder.")

streamlit_app.main(program_test_name, path_nada_bin, path_nada_json)

if __name__ == "__main__":
main()
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"functions":[],"parties":[{"name":"auctioneer","source_ref_index":7},{"name":"bidder_0","source_ref_index":8},{"name":"bidder_1","source_ref_index":8},{"name":"bidder_2","source_ref_index":8},{"name":"bidder_3","source_ref_index":8},{"name":"bidder_4","source_ref_index":8}],"inputs":[{"type":"SecretInteger","party":"bidder_0","name":"bid_0","doc":"","source_ref_index":1},{"type":"SecretInteger","party":"bidder_1","name":"bid_1","doc":"","source_ref_index":1},{"type":"SecretInteger","party":"bidder_2","name":"bid_2","doc":"","source_ref_index":1},{"type":"SecretInteger","party":"bidder_3","name":"bid_3","doc":"","source_ref_index":1},{"type":"SecretInteger","party":"bidder_4","name":"bid_4","doc":"","source_ref_index":1}],"literals":[{"name":"0420609fa1d35394f41049df03ef341f","value":"0","type":"Integer"},{"name":"10d33944d37d5b1b833be6fd73d3033c","value":"1","type":"Integer"},{"name":"be9dc3499e38754968f0ed1e2d88d815","value":"2","type":"Integer"},{"name":"eb53046d942e0370244802bab2e0909f","value":"3","type":"Integer"},{"name":"78b3990d823c17d0e5317c335669f5a1","value":"4","type":"Integer"}],"outputs":[{"name":"highest_bid","operation_id":4315895696,"party":"auctioneer","type":"SecretInteger","source_ref_index":3},{"name":"winning_index","operation_id":4315896128,"party":"auctioneer","type":"SecretInteger","source_ref_index":6}],"operations":{"4315893248":{"LessThan":{"id":4315893248,"left":4315890608,"right":4315891616,"type":"SecretBoolean","source_ref_index":2}},"4315893680":{"IfElse":{"id":4315893680,"this":4315893248,"arg_0":4315893488,"arg_1":4315893008,"type":"SecretInteger","source_ref_index":4}},"4315895408":{"LessThan":{"id":4315895408,"left":4315894880,"right":4315892720,"type":"SecretBoolean","source_ref_index":2}},"4315894448":{"IfElse":{"id":4315894448,"this":4315893920,"arg_0":4315894256,"arg_1":4315893680,"type":"SecretInteger","source_ref_index":4}},"4315893488":{"LiteralReference":{"id":4315893488,"refers_to":"10d33944d37d5b1b833be6fd73d3033c","type":"Integer","source_ref_index":4}},"4315895024":{"LiteralReference":{"id":4315895024,"refers_to":"eb53046d942e0370244802bab2e0909f","type":"Integer","source_ref_index":4}},"4315893920":{"LessThan":{"id":4315893920,"left":4315893296,"right":4315892240,"type":"SecretBoolean","source_ref_index":2}},"4315895984":{"LiteralReference":{"id":4315895984,"refers_to":"78b3990d823c17d0e5317c335669f5a1","type":"Integer","source_ref_index":4}},"4315893008":{"LiteralReference":{"id":4315893008,"refers_to":"0420609fa1d35394f41049df03ef341f","type":"Integer","source_ref_index":5}},"4315890608":{"InputReference":{"id":4315890608,"refers_to":"bid_0","type":"SecretInteger","source_ref_index":1}},"4315894256":{"LiteralReference":{"id":4315894256,"refers_to":"be9dc3499e38754968f0ed1e2d88d815","type":"Integer","source_ref_index":4}},"4315891616":{"InputReference":{"id":4315891616,"refers_to":"bid_1","type":"SecretInteger","source_ref_index":1}},"4315893296":{"IfElse":{"id":4315893296,"this":4315893248,"arg_0":4315891616,"arg_1":4315890608,"type":"SecretInteger","source_ref_index":0}},"4315894688":{"LessThan":{"id":4315894688,"left":4315894112,"right":4315892480,"type":"SecretBoolean","source_ref_index":2}},"4315895696":{"IfElse":{"id":4315895696,"this":4315895408,"arg_0":4315892720,"arg_1":4315894880,"type":"SecretInteger","source_ref_index":0}},"4315894880":{"IfElse":{"id":4315894880,"this":4315894688,"arg_0":4315892480,"arg_1":4315894112,"type":"SecretInteger","source_ref_index":0}},"4315892240":{"InputReference":{"id":4315892240,"refers_to":"bid_2","type":"SecretInteger","source_ref_index":1}},"4315892480":{"InputReference":{"id":4315892480,"refers_to":"bid_3","type":"SecretInteger","source_ref_index":1}},"4315892720":{"InputReference":{"id":4315892720,"refers_to":"bid_4","type":"SecretInteger","source_ref_index":1}},"4315896128":{"IfElse":{"id":4315896128,"this":4315895408,"arg_0":4315895984,"arg_1":4315895216,"type":"SecretInteger","source_ref_index":4}},"4315895216":{"IfElse":{"id":4315895216,"this":4315894688,"arg_0":4315895024,"arg_1":4315894448,"type":"SecretInteger","source_ref_index":4}},"4315894112":{"IfElse":{"id":4315894112,"this":4315893920,"arg_0":4315892240,"arg_1":4315893296,"type":"SecretInteger","source_ref_index":0}}},"source_files":{"auction.py":"from nada_dsl import *\n\ndef nada_main():\n # Define parties\n auctioneer = Party(name=\"auctioneer\")\n num_bidders = 5\n bidders = [Party(name=f\"bidder_{i}\") for i in range(num_bidders)]\n \n # Collect bids from each party\n bids = [SecretInteger(Input(name=f\"bid_{i}\", party=bidders[i])) for i in range(num_bidders)]\n \n # Initialize variables to track the highest bid and the winning party index\n highest_bid = bids[0]\n winning_index = Integer(0)\n \n # Compare bids to find the highest\n for i in range(1, num_bidders):\n is_higher = bids[i] > highest_bid\n highest_bid = is_higher.if_else(bids[i], highest_bid)\n winning_index = is_higher.if_else(Integer(i), winning_index)\n \n # Output the highest bid and the winning party index\n return [\n Output(highest_bid, \"highest_bid\", auctioneer),\n Output(winning_index, \"winning_index\", auctioneer)\n ]\n"},"source_refs":[{"file":"auction.py","lineno":19,"offset":595,"length":61},{"file":"auction.py","lineno":10,"offset":234,"length":96},{"file":"auction.py","lineno":18,"offset":553,"length":41},{"file":"auction.py","lineno":24,"offset":801,"length":55},{"file":"auction.py","lineno":20,"offset":657,"length":68},{"file":"auction.py","lineno":14,"offset":442,"length":30},{"file":"auction.py","lineno":25,"offset":857,"length":58},{"file":"auction.py","lineno":5,"offset":62,"length":41},{"file":"auction.py","lineno":7,"offset":124,"length":69}]}
Binary file not shown.
Loading
Loading