Browse Source

Update README

armaniferrante 4 năm trước cách đây
mục cha
commit
c89bb72c78
2 tập tin đã thay đổi với 34 bổ sung28 xóa
  1. 33 27
      README.md
  2. 1 1
      cli/src/main.rs

+ 33 - 27
README.md

@@ -1,16 +1,21 @@
 # Anchor ⚓
 
-Anchor is a DSL for Solana's [Sealevel](https://medium.com/solana-labs/sealevel-parallel-processing-thousands-of-smart-contracts-d814b378192) runtime.
+Anchor is a DSL for Solana's [Sealevel](https://medium.com/solana-labs/sealevel-parallel-processing-thousands-of-smart-contracts-d814b378192) runtime, providing a safer and more convenient programming model to the Solana developer along with the ability to extract an [IDL](https://en.wikipedia.org/wiki/Interface_description_language) from source.
+
+## Note
+
+* **Anchor is in active development, so all APIs are subject to change.**
+* **The code is unaudited. Use at your own risk.**
 
 ## Goal
 
-It's primary goal is to add safety to Solana programs by providing the ability to more easily reason about program inputs. Because Solana program's are stateless, a transaction must specify accounts to be executed. And because an untrusted client specifies those accounts, a program must responsibily validate all input to the program to ensure it is what it claims to be (in addition to any instruction specific access control the program needs to do). This is particularly burdensome when there are lots of dependencies between accounts, leading to repetitive [boilerplate](https://github.com/project-serum/serum-dex/blob/master/registry/src/access_control.rs) code for account validation along with the ability to easily shoot oneself in the foot by forgetting to validate any particular account.
+It's primary goal is to add safety to one's programs by providing the ability to more easily reason about program inputs. Because Solana programs are stateless, a transaction must specify accounts to be executed. And because an untrusted client specifies those accounts, a program must responsibily validate all input to the program to ensure it is what it claims to be (in addition to any instruction specific access control the program needs to do). This is particularly burdensome when there are lots of dependencies between accounts, leading to repetitive [boilerplate](https://github.com/project-serum/serum-dex/blob/master/registry/src/access_control.rs) code for account validation along with the ability to easily shoot oneself in the foot by forgetting to validate any particular account.
 
-For example, one could imagine easily writing a faulty SPL token program that forgets to check the owner of a token account actually matches the owner on the account. So one must write an `if` statement to check for all such preconditions. Instead, one can write an account "anchor" to do these checks.
+For example, one could imagine easily writing a faulty SPL token program that forgets to check the owner of a token account actually matches the owner on the account. So one must write an `if` statement to check for all such conditions. Instead, one can use the Anchor DSL to do these checks.
 
 ## Example
 
-An example program looks like this.
+See a full example [here](./examples/basic/src/lib.rs) along with a generated [IDL](./examples/basic/idl.json).
 
 ```rust
 use anchor::prelude::*;
@@ -19,18 +24,19 @@ use anchor::prelude::*;
 
 #[program]
 mod example {
-    pub fn create_root(accs: &mut Initialize, initial_data: u64) {
-	  accs.root.account.initialized = true;
-	  accs.root.account.data = initial_data;
+    pub fn create_root(ctx: Context<Initialize>, initial_data: u64) {
+      let root = &mut ctx.accounts.root;
+	  root.account.initialized = true;
+	  root.account.data = initial_data;
     }
 }
 
 // Accounts anchor definition.
 
-#[derive(Anchor)]
+#[derive(Accounts)]
 pub struct Initialize<'info> {
     #[anchor(mut, "!root.initialized")]
-    pub root: AnchorAccount<'info, Root>,
+    pub root: ProgramAccount<'info, Root>,
 }
 
 // Program owned account.
@@ -46,11 +52,10 @@ The program above does the following
 
 * Transforms the accounts array into the `Initialize` struct.
 * Performs all constraint checks. Here, ensuring that the `Root` account is not initialized
-  by checking the *literal* constraint demarcated by double quotes "".
+  by checking the *literal* constraint demarcated by double quotes "" and ensuring the `root`
+  account is owned by the executing program.
 * Saves the newly updated account state, marked as `mut`.
 
-See a full example [here](https://github.com/armaniferrante/serum-dex/blob/armani/anchor/anchor/examples/basic/src/lib.rs).
-
 ### Marking a program.
 
 The `#[program]` attribute marks a program.
@@ -71,50 +76,51 @@ fn entry(program_id: &Pubkey, accounts: &[AccountInfo], instruction_data: &[u8])
 }
 ```
 
-Additionally, it will generate code to both 1) deserialize the `accounts` slice into the correct accounts `Anchor`, ensuring all specified constraints are satisified, and 2) deserialize the `instruction_data` and dispatch to the correct handler (e.g., `initialize` in the example above).
+Additionally, it will generate code to both 1) deserialize the `accounts` slice into a validated accounts, typed accounts struct, ensuring all specified constraints are satisified, and 2) deserialize the `instruction_data` and dispatch to the correct handler (e.g., `initialize` in the example above).
 
 ### Creating an instruction handler.
 
 Each method inside the program corresponds to an instruction handler.
 
 ```rust
-pub fn initialize(accs: &mut Initialize, initial_data: u64) {
+pub fn initialize(ctx: Context<Initialize>, initial_data: u64) {
   ...
 }
 ```
 
-Note that the `program` handler inputs are broken up into two sections: 1) an accounts struct for the instruction, deriving the `Anchor` and a variable length set of program arguments deserialized from the instruction data.
+Note that the `program` handler inputs are broken up into two sections: 1) an accounts struct for the instruction, deriving the `Accounts` macro and a variable length set of program arguments deserialized from the instruction data.
 
-## Marking an Anchor.
+## Marking an Accounts struct.
 
-Account anchors are deserialized structs from the Solana `accounts` slice. To create one, mark your struct with the `#[derive(Anchor)]` macro.
+Account anchors are deserialized structs from the Solana `accounts` slice. To create one, mark your struct with the `#[derive(Accounts)]` macro.
 
 ```rust
-#[derive(Anchor)]
+#[derive(Accounts)]
 pub struct Initialize<'info> {
     #[anchor(mut, "!root.initialized")]
-    pub root: AnchorAccount<'info, Root>,
+    pub root: ProgramAccount<'info, Root>,
 }
 ```
 
 This anchor will perform constraint checks before your `initialize` instruction handler is called. This example, in particular, will execute the code *literal* provided `"!root.initialized"`. If any of the constraints fail to be satisfied, the instruction will exit with an error and your instruction handler will never be called. `mut` marks the account mutable and will be written to account storage on program exit.
 
-## Anchor attribute syntax.
+## Accounts attribute syntax.
 
-There are several inert attributes (attributes that are consumed only for the purposes of the Anchor macro) that can be specified on the struct deriving `Anchor`.
+There are several inert attributes (attributes that are consumed only for the purposes of the Anchor macro) that can be specified on the struct deriving `Accounts`.
 
 | Attribute | Where Applicable | Description |
 |:--|:--|:--|
-| `#[anchor(signer)]` | On raw `AccountInfo` structs. | Checks the given account signed the transaction. |
-| `#[anchor(mut)]` | On `AnchorAccount` structs. | Marks the account as mutable and persists the state transition. |
-| `#[anchor(belongs_to = <target>)]` | On `AnchorAccount` structs | Checks the `target` field on the account matches the `target` field in the accounts array. `target` name must match. |
-| `#[anchor(owner = <program \| skip>)]` | On `AnchorAccount` and `AccountInfo` structs | Checks the owner of the account is the current program or skips the check. Defaults to `program`, if not given. |
-| `#[anchor("<code-literal>")]` | On `AnchorAccount` structs | Executes the given code literal as a constraint. The literal should evaluate to a boolean. |
+| `#[account(signer)]` | On raw `AccountInfo` structs. | Checks the given account signed the transaction. |
+| `#[account(mut)]` | On `AnchorAccount` structs. | Marks the account as mutable and persists the state transition. |
+| `#[account(belongs_to = <target>)]` | On `AnchorAccount` structs | Checks the `target` field on the account matches the `target` field in the accounts array. `target` name must match. |
+| `#[account(owner = <program \| skip>)]` | On `AnchorAccount` and `AccountInfo` structs | Checks the owner of the account is the current program or skips the check. Defaults to `program`, if not given. |
+| `#[account("<code-literal>")]` | On `AnchorAccount` structs | Executes the given code literal as a constraint. The literal should evaluate to a boolean. |
+| `#[access_control(<method>)]` | On program instruction handlers | Runs `method` before executing the instruction. |
 
 ## Future work.
 
 * Standalone constraint expressions. Define expressions in the same way you'd define any other type and then reference them from Anchor structs. This would allow sharing constraints between Anchor structs. Also could do something similar to solidity's function annotation.
-* Constraints on containers. Accounts can be passed in as logical groups, e.g., `Vec<Root>` using the example above, or even as custom structs, e.g., `MyCustomContainer` (where each field itself is an instance of `AnchorAccount`), which might provide a more convient way to reference a group of accounts.
+* Constraints on containers. Accounts can be passed in as logical groups, e.g., `Vec<Root>` using the example above, or even as custom structs, e.g., `MyCustomContainer` (where each field itself is an instance of `ProgramAccount`), which might provide a more convient way to reference a group of accounts.
 * Sysvars. Sysvars should be detected and auto deserialized with owner checks.
 * SPL programs. Similarly, SPL programs should be detected and deserialized with owner checks.
 * Client generation. It's straight forward to use the parsers here to emit an IDL that can be used to generate clients.

+ 1 - 1
cli/src/main.rs

@@ -44,7 +44,7 @@ fn idl(file: String, out: Option<String>) -> Result<()> {
     let idl = anchor_syn::parser::file::parse(&file)?;
     let idl_json = serde_json::to_string_pretty(&idl)?;
     if let Some(out) = out {
-        std::fs::write(out, idl_json);
+        std::fs::write(out, idl_json)?;
         return Ok(());
     }
     println!("{}", idl_json);