diff --git a/docs/how-to-guides/auth-migration.mdx b/docs/how-to-guides/auth-migration.mdx new file mode 100644 index 00000000..f4f5f25b --- /dev/null +++ b/docs/how-to-guides/auth-migration.mdx @@ -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 \ No newline at end of file diff --git a/docs/how-to-guides/build-your-own-sdk.mdx b/docs/how-to-guides/build-your-own-sdk.mdx index b5d077af..a078a668 100644 --- a/docs/how-to-guides/build-your-own-sdk.mdx +++ b/docs/how-to-guides/build-your-own-sdk.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 20 +sidebar_position: 21 title: Build Your Own SDK --- diff --git a/docs/how-to-guides/invoking-contracts-with-transactions.mdx b/docs/how-to-guides/invoking-contracts-with-transactions.mdx index 7d56cee8..9c520615 100644 --- a/docs/how-to-guides/invoking-contracts-with-transactions.mdx +++ b/docs/how-to-guides/invoking-contracts-with-transactions.mdx @@ -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) @@ -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<>; }; ``` @@ -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 \ No newline at end of file diff --git a/docs/learn/authorization.mdx b/docs/learn/authorization.mdx index eb95bb0f..af21023b 100644 --- a/docs/learn/authorization.mdx +++ b/docs/learn/authorization.mdx @@ -3,69 +3,336 @@ sidebar_position: 3 title: Authorization --- +:::info + +This is an overview of the Soroban authorization framework. +If you need to just migrate the contract to the new SDK, see the +[migration doc](../how-to-guides/auth-migration.mdx). + +::: + + # Authorization -Authorization is the process of judging which operations "should" or "should not" be allowed to occur; it is about judging _permission_. +Authorization is the process of judging which operations "should" or "should +not" be allowed to occur; it is about judging _permission_. + +Authorization differs from _authentication_, which is the narrower problem of +judging whether a person "is who they say they are", or whether a message +claiming to come from a person "really" came from them. + +Authorization often uses cryptographic authentication (via signatures) to +support its judgments, but is a broader, more general process. + +## Soroban Authorization Framework + +Soroban aims at providing a light-weight, but flexible and extensible framework +that allows contracts to implement arbitrarily complex authorization rules, +while providing built-in implementation for some common tasks (such as replay +prevention). The framework consists of the following components: + +* Contract-specific authorization - custom authorization rules implemented by + contracts using the private contract storage and abstract accounts. +* Account abstraction - allows users to customize their authentication rules and + define universal authorization policies via custom account contracts + (this includes the built-in support for the Stellar accounts). +* Host-based authorization library - ensures integrity between the custom + accounts and regular contracts. Also defines the structured signature payload + format, ensures replay prevention and takes care of providing the correct + signature contexts. + +Soroban host also provides some cryptographic functions (signature verfication, +hashing) which may be useful for the custom account implementation. + +Contracts that use Soroban authorization framework are interoperable with each +other. Also it is easier for the client applications to write generic code for +interaction with Soroban authorization framework. For example, wallets can +implement a generalized way to present and sign Soroban payloads. + +We realize that it's not possible to cover each and every case, but we hope that +the vast majority of the contracts can operate within the framework and thus +contribute into building a more cohesive ecosystem. Custom authorization +frameworks are still possible to implement, but are not encouraged(unless there +are no alternatives). + +### Contract-specific Authorization + +#### Contract storage + +Contracts have an exclusive read and write access to their [storage] in the +ledger. This allows contracts to safely control and manage user access to their +data. For example, a token contract may ensure that only administrator can mint +more of the token by storing the administrator identity in its storage. +Similarly, it can make sure that only an owner of the balance may transfer that +balance. + +[storage]: ../getting-started/storing-data.mdx + + +#### `Address` + +The storage-based approach described in the previous section requires a way to +represent the user identities and authenticate them. `Address` type is a +host-managed type that performs these functions. + +From the contract perspective `Address` is an opaque identifier type. The +contract logic doesn't need to depend on the internal representation of the +`Address` (see [Account Abstraction](#account-abstraction) section below for +more details). + +`Address` type has two similar methods in Soroban SDK: `require_auth` and +`require_auth_for_args` (these methods call the respective Soroban host +function). The only difference between the functions is the ability to +customize the invocation arguments. See [auth example] +(../how-to-guides/auth.mdx) that demonstrates how to use these functions. + +Both functions ensure that the `Address` has authorized the call of the current +function within the current context (where context is defined by `require_auth` +calls in the current call stack; see more formal definition in the +[section below](#requireauth-implementation-details)). The authentication rules +for this authorization are defined by the `Address` and are enforced by the +Soroban host. Replay protection is also implemented in the host, i.e. there is +normally no need for a contract to manage its own nonces. + +#### Authorizing Sub-contract Calls + +One of the key features of Soroban Authorization Framework is the ability to +easily make authorized sub-contract calls. For example, it is possible for a +contract to call `require_auth` for an `Address` and then call `token.xfer` +authorized for the same `Address` (see [timelock example] that demonstrates +this pattern). + +Contracts don't need to do anything special to benefit from this feature. Just +calling a sub-contract that calls `require_auth` will ensure that the +sub-contract call has been properly authorized. + +[timelock example]: ../how-to-guides/timelock.mdx + +#### When to `require_auth` + +The main authorization-related decision a contract writer needs to make for any +given `Address` is whether they need call `require_auth` for it. While the +decision needs to be made on case-by-case basis, here are some rules of thumb: + +- If the access to the `Address` data in this contract is read-only, then + `require_auth` is probably not needed. +- If the `Address` data in this contract is being modified in a way that's not + strictly beneficial to the user, then `require_auth` is probably needed + (e.g. reducing the user's token balance needs to be authorized, while + increasing it doesn't need to be authorized) +- If a contract calls another contract that will call `require_auth` for the + `Address` (e.g. `token.xfer`), then adding `require_auth` in the caller would + ensure that the authorization for the inner call can't be reused outside of + your contract. For example, if you want to do something positive for the + user, but only when they have transferred some token to your contract, then + the contract call itself should `require_auth`. + +#### Authorizing Multiple `Address`es + +There is no explicit restriction on how many `Address` entities the contract +uses and how many `Address`es have `require_auth` called. That means that it is +possible to authorize a contract call on behalf on multiple users, which may +even have different authorization contexts (customized via arguments in +`require_auth_for_args`). [Atomic swap] is an example that deals with +authorization of two `Address`es. + +[Atomic swap]: ../how-to-guides/atomic-swap.mdx + +Note though, that contracts that deal with multiple authorized `Address`es need +a bit more complex support on the client side (to collect and attach the proper +signatures). + +### Account Abstraction + +Account abstraction is a way to decouple the authentication logic from the +contract-specific authorization rules. The `Address` defined above is in fact +an identifier of an 'abstract' account. That is, the contracts know the +`Address` and can require authorization from it, but they don't know how +exactly it is implemented. + +For example, imagine a token contract. Its responsibilities are to manage the +balances of multiple users (transfer, mint, burn etc.). There is really nothing +about these responsibilities that has anything to do with _how exactly_ the +user authorized the balance-modifying transaction. The users may want to use +some hardware key that supports new generation of crypto algorithms(which don't +even have to exist today) or they may want to have bespoke multisig scheme and +none of this really has anything to do with the token logic. + +Account abstraction provides a convenient extension point for every contract +that uses `Address` for authorization. It doesn't solve all the issues +automatically - client-side tooling may still need to be adapted to support +different authentication schemes or different wallets. But the on-chain state +doesn't need to be modified and modifying the on-chain state is a much harder +problem. + +#### Types of Account Implementations + +Conceptually, every abstract account is a special contract that defines +authentication rules and potentially some additional account-specific +authorization policies. However, for the sake of optimization and integration +with the existing Stellar accounts, Soroban supports 4 different kinds of the +account implementations. + +Below are the general descriptions of these implementations. See the transaction +[guide](../how-to-guides/invoking-contracts-with-transactions.mdx) for the +concrete information of how different accounts are represented. + +##### Stellar Account + +Corresponds to `Address::Account`. + +This is a special, built-in 'account contract' that handles all the Stellar +accounts. It is not a real contract and doesn't need to be deployed. + +This supports the Stellar multisig with medium threshold. See Stellar +[documentation] for more details on multisig and thresholds. + +[documentation]: +https://developers.stellar.org/docs/encyclopedia/signatures-multisig + +##### Transaction Invoker + +Corresponds to `Address::Account`. + +This is also a Stellar account, but its signature is inferred from the source +account of the Stellar transaction (or operation, if it has one). + +This is purely an optimization of the [Stellar Account](#stellar-account) that +allows to skip one signature in case if the transaction source account also +authorizes the contract invocation. + +##### Contract Invoker + +Corresponds to `Address::Contract`. + +This is a special case of an 'account' that may appear only when a contract +calls another contract. We consider that since the contract makes a call, then +it must be authorizing it (otherwise, it shouldn't have made that call). Hence +all the `require_auth` calls made on behalf of the **direct** invoker contract +`Address` are considered to be authorized (but not any calls on behalf of the +contract deeper down the stack). + +##### Custom Account + +Corresponds to `Address::Contract`. + +This is the the extension point of account abstraction. Custom account is a +special contract that implements `check_auth` method. If any contract calls +`require_auth` for the `Address` of this contract, Soroban host will call +`check_auth` with the corresponding arguments. -Authorization differs from _authentication_, which is the narrower problem of judging whether a person "is who they say they are", or whether a message claiming to come from a person "really" came from them. +`check_auth` gets a signature payload, a list of signatures (in any user-defined +format) and a list of the contract invocations that are being authorized by +these signatures. Its responsibility is to perform the authentication via +verifying the signatures and also (optionally) to apply a custom authorization +policy. For example, a signature weight system similar to Stellar can be +implemented, but it also can have customizable rules for the weights, e.g. to +allow spending more than X units of token Y only given signature weight Z. -Authorization often uses cryptographic authentication (via signatures) to support its judgments, but is a broader, more general process. +Custom account can also be treated as a custodial smart wallet. It holds the +user's funds (token balances, NFTs etc.) and provides the user(s) with ways to +authorize operations on these funds. That said, nothing prevents custom +accounts to authorize operations that have nothing to do with any balances, for +example, it can be used to perform administrative functions for tokens +(don't forget, custom account simply defines what to do when `require_auth` is +called). -## Basic authorization: writing to `CONTRACT_DATA` +For the exact interface and more details, see the [custom account example]. -The basic authorization rule is simple: each contract has an identifier, each `CONTRACT_DATA` ledger entry carries the identifier of a contract, and only the contract with the same identifier as a `CONTRACT_DATA` ledger entry can write to it. +[custom account example]: ../how-to-guides/custom-account.mdx -## Complex authorization: multiple users and the impracticality of general rules +### Advanced Concepts -Authorization is complicated by the fact that contracts do not exist or execute in isolation: they record data related to multiple users and run transactions that change multiple users' data simultaneously. Each user might reasonably want (and be permitted) to modify some parts of a contract's data, but not other parts. +Most of the contracts shouldn't need the concepts described in this section. +Refer to this when developing complex contracts that deal with deep contract +call trees and/or multiple `Address`es. -We might expect the system to have a rich set of built-in authorization rules, to allow modeling individual users, their data, and the sets of data each user of a contract can or cannot modify under a variety of transactions and signatures. This is however impractical in general: each contract has complex and unforeseeable conditions governing access to its data. +#### `require_auth` implementation details -As an example, consider a contract holding accounts for users, and exposing a "transfer" operation. If a contract has ledger entries representing account balances for users A and B, then a transfer from A to B probably requires modifying the ledger entries associated with both A and B. But which transfers should be permitted? One possible rule would be to allow transfers from A to B only when A has sufficient funds and A signed the transaction; then B could not initiate the transfer nor could A overspend their balance. But that is not the only possible rule: reasonable contracts might allow "overdraft" on A's account, or could permit A to delegate to B the right to withdraw some of A's funds when necessary. +When a Soroban transaction is executed on-chain, the host collects a list of +`ContractAuth` entries from the transaction ([XDR][contract-auth]). These +entries contain authorized invocation trees, a nonce and the corresponding +signatures. The host uses these entries to verify authorization during the +contract execution. -In general, the conditions in which data associated with each user should or should-not be modified can be quite complex, and vary on a contract-by-contract basis. Indeed, one way of thinking of contracts is as _primarily_ a set of rules for authorizing changes to data. It is therefore not possible (or at least not practical) to capture all plausible authorization patterns with structured, declarative authorization rules "outside the contracts". The contracts _are_ the rules. +Every time `require_auth`/`require_auth_for_args` host function is called for +non-contract-invoker account, the following steps happen: -Instead, we focus on facilities provided _to_ contracts to _support them_ in making authorization decisions for themselves, in their own code. +- Find an authorized invocation tree that matches the `require_auth` call. The + matching process is pretty involved and is described in the section below. +- If authentication hasn't happened for this tree yet, then perform it: + - Verify and consume nonce. Nonce is implemented as autoincrement counter per + contract ID and `Address`. + - Build the expected [signature payload preimage] and compute its SHA-256 hash + to get the final signature payload + - Call `check_auth` of the account contract corresponding to the `Address` + using the signature payload and the invocations from the authorization + tree +- Mark the invocation as 'exhausted' in its authorized invocation tree. +'Exhausted' invocations will be skipped when matching the future `require_auth` + calls. -## Tools for authorization: identities, messages and authorizations +If any of the steps above fails, then the authorization is considered +unsuccessful. -Several mechanisms are provided to each contract to make authorization decisions. The mechanisms fall into two categories: +Notice, that authentication happens just once per tree, as the whole tree needs +to be signed. -- Common data structures and functions in the SDK. -- Host functions that assist in validating aspects of these data structures. +[contract-auth]: https://github.com/stellar/stellar-xdr/blob/df18148747e807618acf4639db41c4fd6f0be9fc/Stellar-transaction.x#L547 +[signature payload]: https://github.com/stellar/stellar-xdr/blob/df18148747e807618acf4639db41c4fd6f0be9fc/Stellar-transaction.x#L681 -### Common data structures and functions +#### Matching Authorized Invocation Trees -The common data structures involved in authorization model key concepts used in authorization judgments. They are provided by the SDK, and form a base set of functionality that should be sufficient for expressing many authorization patterns in other contracts. +In order for authorizations to succeed, all the +`require_auth`/`require_auth_for_args` calls have to be covered by the +corresponding `AuthorizedInvocation` trees in transaction (defined in +transaction [XDR][invocation-xdr]). -These concepts are: +Formally, this correspondence is defined as following. -- **Identities**: these are the parties that can initiate actions subject to authorization judgments. Identities may be one of three types: - - **Single-key users**, represented by a single Ed25519 public key - - **Account users**, represented by a reference to an existing account on the Stellar network (which stores, in an account ledger entry, a list of weighted authorized signing keys) - - **Contracts**, represented by a contract ID (not a public key) -- **Payloads**: these encode a request from an identity to perform - some action, such that the payload can have an authorization claim made - about it, and an authorization judgment applied to it. Payloads - include the name of the contract function being invoked, the contract ID, - the network passphrase, and a set of general parameters to that action. The - set of general parameters should include the Identifier on the Signature, as - well as the nonce. -- **Authorizations**: these are statements made _about payloads_. Each authorization encodes the claim that the action described by the payload is authorized to occur, on the authority of some identity. Authorizations may have three forms, corresponding to the three forms of identity: single-key, account, and contract. +Given a top-level contract invocation `I` we can build a 'contract invocation +tree' `T` by tracing all the sub-contract calls (a directed edge `A->B` in the +tree means 'contract function A calls contract function B). Note, that we only +consider the functions that are implemented in different contracts, i.e. any +function calls that don't involve a contract invocation via host `call` are +considered to belong to the same node. -Contracts decide when a payload is authorized with two separate steps: +Let's say authorization is required from addresses `A_1..A_N`. Then for every +address `A_i` there are two kinds of nodes in the invocation tree `T`: +`R`-nodes that had a `require_auth` call for `A_i` and `N`-nodes that didn't +have such call. Then we remove all the `N`-nodes and all the edges from `T` +from the tree and add the directed edges connecting the remaining `R`-nodes +such that the edge goes from `R_j` to `R_k` if there was a path between `R_j` +and `R_k` in `T` that doesn't contain any other `R`-nodes. As a result we get a +forest `AuthorizedInvocation` trees for `A_i`. Notice, that these trees don't +have to have their root be `I` node (i.e. the top-level contract call), so it's +possible to e.g. batch the authorized call together without requiring signing +the batching function. -- Validate the provided authorization, by some mixture of checking signatures or examining the invocation context. -- Evaluate the operation requested by the payload to see if it fits the contract's unique rules for that operation. +In simpler terms, `AuthorizedInvocation` trees for an `Address` are subsets of +the full invocation tree that are 'condensed' to only contain invocations that +have `require_auth` call for that `Address`. -The first step often requires host-function support. The second step is always contract-specific, and cannot be provided by the platform in general. +During the matching process that happens for every `require_auth` host tries +to match the current path in `T` to an `AuthorizedInvocation` tree for the +corresponding `Address`. The path is considered to be matched only when there is +a corresponding path of *exhausted* `R` nodes leading to the current call. This +means that if the `Address` signs a sequence of calls `A.foo->B.bar->C.baz`, +then it authorization check will fail in case if `A.foo` directly calls `C.baz` +because `C.baz` strictly has to be called from `B.bar`. -### Authorization-validation host functions +##### Duplicate Addresses -Three families of host function are provided to validate authorizations: +In case if the same contract function calls `require_auth` for the same +`Address` multiple times (e.g. when multiple operations from the same user are +being batched), every `require_auth` call still has to have a corresponding node +in the `AuthorizedInvocation` tree. Due to that, there might be multiple valid +trees that make all the authorization checks pass. There is nothing wrong about +that - the address still must have authorized all the invocations. The only +requirement for such cases to be handled correctly is to ensure that the +`require_auth` calls for an `Address` happen before the corresponding +sub-contract calls. -- **Cryptographic validation** functions. These help validate the "single-key user" form of authorization. Specifically these functions compute SHA256 hashes and verify Ed25519 signatures. -- **Account authorization** functions. These help validate the "account user" form of authorization. Specifically these functions allow looking up the signing thresholds and weights for signing keys, as stored in existing account ledger entries in the Stellar blockchain. -- **Invoking contract** function. This helps validate the "contract" form of authorization. Specifically this function returns the contract ID of the contract that invoked the currently-executing contract. If no contract invoked the currently-executing contract, this function traps. +[invocation-xdr]: +https://github.com/stellar/stellar-xdr/blob/df18148747e807618acf4639db41c4fd6f0be9fc/Stellar-transaction.x#L533 -This last function deserves further explanation. A contract can be invoked either from a transaction (originating outside of the host) or from a cross-contract call made by some _other_ contract. When some contract X decides to invoke some other contract Y, it is generally sufficient to consider the _fact that X called Y_ as evidence that X authorizes whatever request it is making to Y with that call. After all, if X did not wish to authorize such an invocation, it would not make it! So the only information necessary to evaluate a "contract" authorization is the identity of the (directly) invoking contract. diff --git a/docs/learn/built-in-types.mdx b/docs/learn/built-in-types.mdx index 79872dbb..7c23746c 100644 --- a/docs/learn/built-in-types.mdx +++ b/docs/learn/built-in-types.mdx @@ -85,21 +85,14 @@ already has a value for that key replaces the value. ## Address (`Address`) -Address is union of all the types that can be the invoker of a contract. +Address is a universal opaque identifier to use in contracts. It may represent +a 'classic' Stellar account, a custom account implemented in Soroban or just +an arbitrary contract. -Address may be an account ID (`AccountId`) or a contract ID (`BytesN<32>`). +Address can be used as a contract function input argument (for example, to +identify the payment recipient), as a data key (for example, to store the +balance), as the authentication & authorization source (for example, to +authorize a token transfer) etc. -The Address type is implemented like an [enum custom type] and is stored as a -two element Vec. - -[enum custom type]: custom-types#enum-unit-and-tuple-variants - -## Account ID (`AccountId`) - -Account ID is an identifier for an account. - -Most of the time contracts should use the `Address` type, which is a - -In contracts the ID is opaque and does not expose the identifier to the -contract, but the value can be used as a key in maps, or compared with other -account identifiers. +See [authorization documentation](authorization.mdx) for more details on how to +use the `Address` type. \ No newline at end of file diff --git a/docs/reference/sdks/rust-auth.mdx b/docs/reference/sdks/rust-auth.mdx deleted file mode 100644 index 6624ce37..00000000 --- a/docs/reference/sdks/rust-auth.mdx +++ /dev/null @@ -1,75 +0,0 @@ ---- -sidebar_position: 2 -title: Soroban Rust Auth SDK ---- - -The `soroban-auth` Rust crate contains the Soroban Rust Auth SDK. It provides -types and utilities for authenticating participants in a variety of ways -including: - -- Authenticating by being the invoker, as an transaction source account or a - contract. -- Presigned invocations with account signers or ed25519 keys, similar to - [EIP-2612] and [EIP-712] in the Ethereum ecosystem. - -:::info - -If you're just starting to explore Soroban, checkout the [auth example] that -uses a simpler form of invoker auth. - -::: - -The Auth SDK identifies participants with the `Identifier` type, and -participants choose how they will be authenticated by providing a `Signature`. - -An `Identifier` can represent a: - -- Account ID -- Contract ID -- Ed25519 key - -A `Signature` can be an: - -- Invoker — An invoking transaction source account, or an invoking contract. -- Account – An invocation presigned with account signers. -- Ed25519 – An invocation presigned with an ed25519 key. - -Intended for use alongside the [`soroban-sdk`]. - -[`soroban-sdk`]: rust -[EIP-2612]: https://eips.ethereum.org/EIPS/eip-2612 -[EIP-712]: https://eips.ethereum.org/EIPS/eip-712 - -:::info - -Report issues and share feedback about the `soroban-auth` -[here](https://github.com/stellar/rs-soroban-sdk/issues/new/choose). - -::: - -## SDK Documentation - -Auth documentation is available at: -https://docs.rs/soroban-auth - -## Subscribe to Releases - -Subscribe to releases on the GitHub repository: -https://github.com/stellar/rs-soroban-sdk - -## Add `soroban-auth` as a Dependency - -Add the following sections to the `Cargo.toml` to import `soroban-auth`. - -```toml -[features] -testutils = ["soroban-auth/testutils"] - -[dependencies] -soroban-sdk = "0.4.2" -soroban-auth = "0.4.2" - -[dev_dependencies] -soroban-sdk = { version = "0.4.2", features = ["testutils"] } -soroban-auth = { version = "0.4.2", features = ["testutils"] } -```