Skip to content

Commit

Permalink
Merge pull request #146 from NillionNetwork/chore/update-0.8.0
Browse files Browse the repository at this point in the history
Update 0.8.0
  • Loading branch information
psofiterol authored Dec 5, 2024
2 parents 97d3053 + e57c9fa commit d453712
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 39 deletions.
33 changes: 27 additions & 6 deletions docs/nillion.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@ Follow instructions to [install the Nillion SDK and Tools](/nillion-sdk-and-tool

# Usage

> **Note:**
> Starting with version `v0.8.0` output is serialized into YAML by default (can also be set to JSON).
> Any integrations relying on output parsing will have to be updated.
```bash
Usage: nillion [OPTIONS] <COMMAND>

Commands:
store-values Store values in the network
store-values Store or update values in the network
retrieve-values Retrieve values from the network
store-program Store a program in the network
compute Perform a computation in the network
Expand All @@ -26,18 +30,35 @@ Commands:
inspect-ids Display the node/user ids derived from the provided keys
shell-completions Generate shell completions
retrieve-permissions Retrieve permissions for stored secrets
overwrite-permissions Overwrite permissions on a stored secrets
overwrite-permissions Overwrite all permissions on a stored secrets
update-permissions Update certain permissions on a stored secrets
identity-gen Generate user identities
networks Manage network configurations
identities Manage identities
context Manage the context to use for all upcoming command invocations
help Print this message or the help of the given subcommand(s)

Options:
-i, --identity <IDENTITY> Identities configuration
-n, --network <NETWORK> Network configuration name
-h, --help Print help
-V, --version Print version
-i, --identity <IDENTITY>
Identities configuration

-n, --network <NETWORK>
Network configuration name

--output-format <OUTPUT_FORMAT>
Output format

[default: yaml]

Possible values:
- yaml: Serialise into YAML
- json: Serialise into JSON

-h, --help
Print help (see a summary with '-h')

-V, --version
Print version
```

For any of the commands listed above, you can run `nillion <COMMAND> --help` and get detailed information on usage.
91 changes: 62 additions & 29 deletions docs/python-client-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ getting the length of the array.
[Array](#nillion_client.Array)
* **Raises:**
**ValueError** – invalid secret type: Raises an error when a public encoded element is included inside a
secret array.
secret array.

### Example

Expand Down Expand Up @@ -743,21 +743,21 @@ Return the integer represented by the given array of bytes.

bytes
: Holds the array of bytes to convert. The argument must either
support the buffer protocol or be an iterable object producing bytes.
Bytes and bytearray are examples of built-in objects that support the
buffer protocol.
support the buffer protocol or be an iterable object producing bytes.
Bytes and bytearray are examples of built-in objects that support the
buffer protocol.

byteorder
: The byte order used to represent the integer. If byteorder is ‘big’,
the most significant byte is at the beginning of the byte array. If
byteorder is ‘little’, the most significant byte is at the end of the
byte array. To request the native byte order of the host system, use
<br/>
```
`
```
<br/>
sys.byteorder’ as the byte order value.
the most significant byte is at the beginning of the byte array. If
byteorder is ‘little’, the most significant byte is at the end of the
byte array. To request the native byte order of the host system, use
<br/>
```
`
```
<br/>
sys.byteorder’ as the byte order value.

signed
: Indicates whether two’s complement is used to represent the integer.
Expand Down Expand Up @@ -805,24 +805,24 @@ Return an array of bytes representing an integer.

length
: Length of bytes object to use. An OverflowError is raised if the
integer is not representable with the given number of bytes.
integer is not representable with the given number of bytes.

byteorder
: The byte order used to represent the integer. If byteorder is ‘big’,
the most significant byte is at the beginning of the byte array. If
byteorder is ‘little’, the most significant byte is at the end of the
byte array. To request the native byte order of the host system, use
<br/>
```
`
```
<br/>
sys.byteorder’ as the byte order value.
the most significant byte is at the beginning of the byte array. If
byteorder is ‘little’, the most significant byte is at the end of the
byte array. To request the native byte order of the host system, use
<br/>
```
`
```
<br/>
sys.byteorder’ as the byte order value.

signed
: Determines whether two’s complement is used to represent the integer.
If signed is False and a negative integer is given, an OverflowError
is raised.
If signed is False and a negative integer is given, an OverflowError
is raised.

<a id="nillion_client.PreprocessingElement.try_value"></a>

Expand Down Expand Up @@ -1210,7 +1210,7 @@ alias of `UUID`

<a id="nillion_client.VmClient"></a>

### *class* nillion_client.VmClient(key, network, payer, \_raise_if_called=True)
### *class* nillion_client.VmClient(key, network, payer, payment_mode, \_raise_if_called=True)

A class to interact with the Nillion network.

Expand Down Expand Up @@ -1241,6 +1241,33 @@ chain_client = NilChainPayer(
client = await VmClient.create(private_key, network, payer)
```

<a id="nillion_client.VmClient.add_funds"></a>

#### *async* add_funds(amount_unil, target_user=None)

Add funds to a user’s account on the nillion network.

By default this will fund the account tied to the user this client is currently using.

Funds will be automatically used when performing payments unless the payment mode in the client is
changed.

#### NOTE
Funds will expire after 30 days regardless of use so don’t add more funds than you intend to use
in the short term

<a id="nillion_client.VmClient.balance"></a>

#### *async* balance()

Gets the balance associated with the user’s account in the network.

This balance will be preferred when running operations and can be topped up by calling
[`VmClient.add_funds()`](#nillion_client.VmClient.add_funds).

* **Return type:**
`AccountBalanceResponse`

<a id="nillion_client.VmClient.close"></a>

#### close()
Expand Down Expand Up @@ -1308,7 +1335,7 @@ results = await client.retrieve_compute_results(compute_id).invoke()

<a id="nillion_client.VmClient.create"></a>

#### *async classmethod* create(key, network, payer)
#### *async classmethod* create(key, network, payer, payment_mode=PaymentMode.FROM_BALANCE)

Create a new Nillion client.

Expand Down Expand Up @@ -1354,7 +1381,7 @@ Request to get a payment receipt for a paid operation.

* **Parameters:**
* **signed_quote** (`SignedQuote`) – The quote to get a payment receipt for.
* **tx_hash** – The transaction hash where the payment was made.
* **tx_hash** (`str` | `None`) – The transaction hash where the payment was made.
* **Return type:**
`SignedReceipt`
* **Returns:**
Expand Down Expand Up @@ -1647,6 +1674,12 @@ permissions = Permissions.default_for_user(user_id)
await client.overwrite_permissions(values_id, permissions).invoke()
```

<a id="nillion_client.VmClient.payment_mode"></a>

#### payment_mode *: `PaymentMode`*

The payment mode to be used.

<a id="nillion_client.VmClient.pool_status"></a>

#### pool_status()
Expand Down Expand Up @@ -1828,4 +1861,4 @@ await client.update_permissions(values_id, delta).invoke()

#### user_id *: [`UserId`](#nillion_client.UserId)*

The user identifier associated with this client.
The user identifier associated with this client.
14 changes: 11 additions & 3 deletions docs/python-quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ We will write the following code within the `quickstart/client_code` directory i

Here the `nillion-client` imports will help us interact with the local chain and abstract away some of the technical details when using the python client, and finally we load the `.env` file containing the configs of the local devnet.

2. Obtain the local devnet config and create a user, payment config & node key, then initialize the client.
2. Obtain the local devnet config and create a user, payment config & node key, then initialize the client and topup the balance.

```python
# 2. Initial setup, Initialize NillionClient against nillion-devnet
Expand All @@ -277,9 +277,14 @@ We will write the following code within the `quickstart/client_code` directory i
party_name = "Party1"
program_name = "secret_addition_complete"
program_mir_path = f"../nada_quickstart_programs/target/{program_name}.nada.bin"

# Adding funds to the client balance so the upcoming operations can be paid for
funds_amount = 1000
print(f"💰 Adding some funds to the client balance: {funds_amount} uNIL")
await client.add_funds(funds_amount)
```

Here we load the network config created by `nillion-devnet`, then setup payment config and initialize the NillionClient.
Here we load the network config created by `nillion-devnet`, then setup payment config and initialize the NillionClient. Finally we are adding some funds to pay for the operations coming next.

3. Store a program

Expand Down Expand Up @@ -355,10 +360,13 @@ We will write the following code within the `quickstart/client_code` directory i
result = await client.retrieve_compute_results(compute_id).invoke()
print(f"✅ Compute complete for compute_id {compute_id}")
print(f"🖥️ The result is {result}")
balance = await client.balance()
print(f"💰 Final client balance: {balance.balance} uNIL")
client.close()
return result
```

Finally we return the result of the computation. Here we await for the next event to be available in the network, and then print the result.
Finally we return the result of the computation. Here we await for the next event to be available in the network, and then print the result and remaining balance.

7. Run the completed python script

Expand Down
104 changes: 104 additions & 0 deletions docs/threshold-signatures.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Nillion Signatures (tECDSA)

Nillion's threshold ECDSA (tECDSA) feature enables secure message and transaction signing while keeping your private keys protected within Nillion's distributed network. Your keys stay split across nodes during signing operations, and you can even grant permissions to let others participate in the signing process without exposing the actual keys.

:::info
Note: Threshold ECDSA signing is currently only available in the Nillion Python client. Support for other client libraries is coming soon.
:::

## Key Features

- **Secure Key Storage**: Import your private keys into Nillion and have them securely split across the network. Your keys are never reconstructed, even during signing operations.
- **Flexible Permissions**: Granularly control who can do what with your signing keys. You can have one party manage the keys, another prepare messages, and a third receive the final signatures.
- **Message Privacy**: Only message hashes are sent over the network during signing, keeping the actual content of your messages private.
- **High Performance**: Nillion's tECDSA signing can complete in under 10 seconds, even for large messages.

## Required Identifiers

Nillion's threshold ECDSA (tECDSA) feature uses a "builtin" Nada program that streamlines the signing process. This program has a pre-configured set of identifiers that you'll need to use:

```python
# program id
tecdsa_program_id = "builtin/tecdsa_sign"`

# input names
tecdsa_key_name = "tecdsa_private_key"
tecdsa_digest_name = "tecdsa_digest_message"
tecdsa_signature_name = "tecdsa_signature"

# party names
tecdsa_key_party = "tecdsa_key_party"
tecdsa_digest_party = "tecdsa_digest_message_party"
tecdsa_output_party = "tecdsa_output_party"
```

These predefined identifiers allow you to quickly integrate with Nillion's built-in tECDSA signing functionality, without needing to configure or manage the underlying program details. By using these values, you can get up and running with threshold ECDSA signing faster.

## Implementation Guide

Check out a complete [tECDSA code example here](https://github.com/NillionNetwork/python-examples/blob/feat/tecdsa-example/examples_and_tutorials/core_concept_single_party_compute/threshold_ecdsa_signature.py).

### Storing Your Key

Store your private key as a secret EcdsaPrivateKey value in Nillion:

```python
# Store an ECDSA private key in Nillion
my_ecdsa_key = {
"tecdsa_private_key": EcdsaPrivateKey(private_key_bytes)
}
key_id = await client.store_values(
my_ecdsa_key, ttl_days=5, permissions=permissions
).invoke()
```

### Signing Messages

Use the built-in "builtin/tecdsa_sign" nada program to sign a message with your stored private key:

```python
# Sign a message using your stored key
message = b"Your message here"

# Create the message hash
digest = hashes.Hash(hashes.SHA256())
digest.update(message)
hashed_message = digest.finalize()

# Get your signature
result = await client.compute(
"builtin/tecdsa_sign", input_bindings, output_bindings,
value_ids=[key_id, digest_id]
).invoke()
signature = result["tecdsa_signature"]
```

### Verifying Signatures

```python
# Get your signature components
(r, s) = signature.value
r_int = int.from_bytes(r, byteorder="big")
s_int = int.from_bytes(s, byteorder="big")

# Standard verification with any ECDSA library
public_key.verify(
signature, message, ec.ECDSA(hashes.SHA256())
)
```

## Security and Privacy

- **Distributed Key Storage**: Your keys are split across nodes - no single point of failure
- **Message Privacy**: Only hashes touch the network, not your actual messages
- **Granular Access**: Control exactly who can use your keys and how
- **Key Expiration**: Set TTLs to automatically remove old keys
- **Industry Standard**: Uses the same curve (secp256k1) as Ethereum

## Resources and Demos

To help you get started with Nillion's tECDSA functionality, we provide the following resources:

- **[Nillion Signature Tools](https://nillion-signature-tools.streamlit.app/)**: An interactive web app and developer tool that allows you to experiment with key generation, storage, and signing on the Nillion platform.
- **[Complete Code Example](https://github.com/NillionNetwork/python-examples/blob/feat/tecdsa-example/examples_and_tutorials/core_concept_single_party_compute/threshold_ecdsa_signature.py)**: A full, end-to-end implementation example demonstrating how to store a private key and use it for threshold ECDSA signing. This example is part of the Nillion Python examples repository.
- **[Python Client Reference](/python-client-reference)**: Detailed API documentation for the Nillion Python client, including the ECDSA-related features and functionality.
3 changes: 2 additions & 1 deletion sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ const sidebars = {
items: [
'python-quickstart',
'python-client-reference',
'threshold-signatures',
{
type: 'link',
label: 'Client Examples',
Expand Down Expand Up @@ -106,7 +107,7 @@ const sidebars = {
'js-client-hooks-permissions',
'js-client-hooks-other',
],
}
},
// {
// type: 'link',
// label: 'create-nillion-app',
Expand Down

0 comments on commit d453712

Please sign in to comment.