Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

Commit

Permalink
More Auth Next docs updates (#311)
Browse files Browse the repository at this point in the history
* Remove rust-auth.mdx

* Update authorization docs and `Address` type info.

* Added auth info to transactions doc.

* Added a document about migrating to auth next.
  • Loading branch information
dmkozh authored Feb 14, 2023
1 parent 05dafa2 commit 3ebd2e1
Show file tree
Hide file tree
Showing 6 changed files with 481 additions and 133 deletions.
76 changes: 76 additions & 0 deletions docs/how-to-guides/auth-migration.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
sidebar_position: 20
title: Migrating Auth to SDK 0.6.0
---

This is a guide about migrating authorization code in contracts written before
SDK 0.6.0 to the new version of auth (Soroban authorization framework).

For general information on authorization in Soroban see the
[authorization overview](../learn/authorization.mdx) and the [example](auth.mdx).

## Migrating `env.invoker()`

The simplest authorization approach prevously was to use `env.invoker()`. This
concept is no longer present in Soroban SDK or host (it is available at the
transaction building time though, [details]).

[details]: invoking-contracts-with-transactions.mdx#authorization-data

In order to migrate a contract that uses `env.invoker()` do the following:

1. Add an `Address` argument to the function signature, for example,
`addr: Address`. This is the authorized entity that we will use instead of
invoker.
1. Call `addr.require_auth()` at the top of the function code to ensure that
the address has authorized the function call.
1. Replace all the instances of `env.invoker()` with `addr`.

A small example of migration:

Before:

```rust
struct MyContract;
impl MyContract {
fn set_val(env: Env, val: i128) {
env.storage().set(&env.invoker(), &val);
}
}
```

After:

```rust
struct MyContract;
impl MyContract {
fn set_val(env: Env, addr: Address, val: i128) {
addr.require_auth();
env.storage().set(&addr, &val);
}
}
```

A more detailed example can be found in the Soroban timelock example migration
[PR][timelock-pr].

[timelock-pr]: https://github.com/stellar/soroban-examples/pull/204/files#diff-6884bc67aadaf666f4042b239666265a3bd57074d1ed58c7fc807120b9458025

## Migrating `soroban-auth`

For more advanced auth use cases the `soroban-auth` library could be used.
In order to migrate from this library to Soroban authorization framework do the
following steps:

1. Change the type of all the `Identifier` variables to `Address`.
1. Change the type of all the `Signature` types to `Address`.
1. Replace signature verification code with a call of
`require_auth`/`require_auth_for_args` for the respective `Address` that has
been represented by a `Signature` before.
1. Remove nonces and nonce-related code as the replay protection is already
ensured by the Soroban host.

An example of `soroban-auth` migration can be found in the Soroban token
example migration [PR][token-pr].

[token-pr]: https://github.com/stellar/soroban-examples/pull/205/files
2 changes: 1 addition & 1 deletion docs/how-to-guides/build-your-own-sdk.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 20
sidebar_position: 21
title: Build Your Own SDK
---

Expand Down
89 changes: 88 additions & 1 deletion docs/how-to-guides/invoking-contracts-with-transactions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ The `InvokeHostFunctionOp` can be used to perform the following Soroban operatio

## InvokeHostFunctionOp

The XDR of `HostFunction` and `InvokeHostFunctionOp` below can be found [here](https://github.com/stellar/stellar-xdr/blob/026c9cd074bdb28ddde8ee52f2a4502d9e518a09/Stellar-transaction.x#L523-L539)
The XDR of `HostFunction` and `InvokeHostFunctionOp` below can be found
[here][XDR].

[XDR]: https://github.com/stellar/stellar-xdr/blob/df18148747e807618acf4639db41c4fd6f0be9fc/Stellar-transaction.x#L554-L563

```c++
union HostFunction switch (HostFunctionType type)
Expand All @@ -34,6 +37,9 @@ struct InvokeHostFunctionOp
HostFunction function;
// The footprint for this invocation
LedgerFootprint footprint;
// Per-address authorizations for this host fn
// Currently only supported for INVOKE_CONTRACT function
ContractAuth auth<>;
};
```

Expand Down Expand Up @@ -97,3 +103,84 @@ The `function` in `InvokeHostFunctionOp` will be executed by the Soroban host en
### Footprint
The footprint must contain the `LedgerKeys` that will be read and/or written. More information about the footprint can be found in the advanced section of [interacting with contracts](../learn/interacting-with-contracts#storage-footprint-and-preflight).
### Authorization Data
This is currently only supported for `HOST_FUNCTION_TYPE_INVOKE_CONTRACT`.
Soroban [authorization framework](../learn/authorization.mdx) provides a
standardized way for passing authorization data to the contract invocations via
`ContractAuth` structures.
```c++
struct AddressWithNonce
{
SCAddress address;
uint64 nonce;
};

struct ContractAuth
{
AddressWithNonce* addressWithNonce; // not present for invoker
AuthorizedInvocation rootInvocation;
SCVec signatureArgs;
};
```
`ContractAuth` contains a tree of invocations authorized by an `Address` and
the correponding signature (in `Address`-dependent format).
In order to build a `ContractAuth` the following is required:
- `Address` that authorizes the invocations and the corresponding `nonce`.
- When `addressWithNonce` is missing, then it means that the transaction
source account (or operation source when present) authorizes these
invocations. `signatureArgs` have to be skipped as well in this case.
- `nonce` has to correspond to the `contractID` of the `rootInvocation`. It
is stored in the ledger entry with `CONTRACT_DATA` key with `contractID` from
`rootInvocation` and `SCVal` `key` with the following value:
`ScVal::Object(Some(ScObject::NonceKey(address)))`.
- `rootInvocation` structure corresponding to the authorized invocation tree
- `signatureArgs` - signature (or multiple signatures) that sign the 32-byte
payload that is a SHA-256 hash of `ENVELOPE_TYPE_CONTRACT_AUTH` preimage
([XDR][envelope-xdr]). The signature structure is defined by the `Address` (see
below for the Stellar account signatures). This should be empty if
`addressWithNonce` is not present (as transaction/operation signature is used
instead).
`AuthorizedInvocation` defines a node in the authorized invocation tree:
```c++
struct AuthorizedInvocation
{
Hash contractID;
SCSymbol functionName;
SCVec args;
AuthorizedInvocation subInvocations<>;
};
```
`AuthorizedInvocation` needs to include a contract, contract function, arguments
of `require_auth`/`require_auth_for_args` call and all the authorized
sub-contract invocations originating from the current node.
[envelope-xdr]: https://github.com/stellar/stellar-xdr/blob/df18148747e807618acf4639db41c4fd6f0be9fc/Stellar-transaction.x#L681
#### Stellar Account Signatures
`signatureArgs` format is user-defined for the [custom accounts], but it is
protocol-defined for the Stellar accounts.
The signatures for the Stellar account are a vector of the following Soroban
[structures] in the Soroban SDK format:
```rust
#[contracttype]
pub struct AccountEd25519Signature {
pub public_key: BytesN<32>,
pub signature: BytesN<64>,
}
```
[structures]: https://github.com/stellar/rs-soroban-env/blob/main/soroban-env-host/src/native_contract/account_contract.rs#L33
[custom accounts]: ../learn/authorization.mdx#account-abstraction
Loading

0 comments on commit 3ebd2e1

Please sign in to comment.