102 lines
30 KiB
HTML
102 lines
30 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en-US">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<title>Account Constraints and Access Control | ⚓ Anchor</title>
|
|
<meta name="generator" content="VuePress 1.8.2">
|
|
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>⚓ </text></svg>">
|
|
<meta name="description" content="">
|
|
<meta name="theme-color" content="#3eaf7c">
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
|
<link rel="preload" href="/anchor/assets/css/0.styles.21b321ec.css" as="style"><link rel="preload" href="/anchor/assets/js/app.130b905b.js" as="script"><link rel="preload" href="/anchor/assets/js/2.90291299.js" as="script"><link rel="preload" href="/anchor/assets/js/19.54c54ce4.js" as="script"><link rel="prefetch" href="/anchor/assets/js/10.a81a7d6e.js"><link rel="prefetch" href="/anchor/assets/js/11.e20cdb5e.js"><link rel="prefetch" href="/anchor/assets/js/12.d30544e0.js"><link rel="prefetch" href="/anchor/assets/js/13.41fde578.js"><link rel="prefetch" href="/anchor/assets/js/14.8bf73db0.js"><link rel="prefetch" href="/anchor/assets/js/15.25c2e2bd.js"><link rel="prefetch" href="/anchor/assets/js/16.b6cb9e25.js"><link rel="prefetch" href="/anchor/assets/js/17.29eac49f.js"><link rel="prefetch" href="/anchor/assets/js/18.db5dc2ee.js"><link rel="prefetch" href="/anchor/assets/js/20.873107aa.js"><link rel="prefetch" href="/anchor/assets/js/21.46f202de.js"><link rel="prefetch" href="/anchor/assets/js/3.397fd877.js"><link rel="prefetch" href="/anchor/assets/js/4.f90252b7.js"><link rel="prefetch" href="/anchor/assets/js/5.47891694.js"><link rel="prefetch" href="/anchor/assets/js/6.493f79e9.js"><link rel="prefetch" href="/anchor/assets/js/7.32936426.js"><link rel="prefetch" href="/anchor/assets/js/8.9fc829e7.js"><link rel="prefetch" href="/anchor/assets/js/9.525a5964.js">
|
|
<link rel="stylesheet" href="/anchor/assets/css/0.styles.21b321ec.css">
|
|
</head>
|
|
<body>
|
|
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/anchor/" class="home-link router-link-active"><!----> <span class="site-name">⚓ Anchor</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="https://book.anchor-lang.com" target="_blank" rel="noopener noreferrer" class="nav-link external">
|
|
The Anchor Book
|
|
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://docs.rs/anchor-lang/latest/anchor_lang/" target="_blank" rel="noopener noreferrer" class="nav-link external">
|
|
Rust
|
|
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://project-serum.github.io/anchor/ts/index.html" target="_blank" rel="noopener noreferrer" class="nav-link external">
|
|
TypeScript
|
|
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://github.com/project-serum/anchor" target="_blank" rel="noopener noreferrer" class="nav-link external">
|
|
GitHub
|
|
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="https://book.anchor-lang.com" target="_blank" rel="noopener noreferrer" class="nav-link external">
|
|
The Anchor Book
|
|
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://docs.rs/anchor-lang/latest/anchor_lang/" target="_blank" rel="noopener noreferrer" class="nav-link external">
|
|
Rust
|
|
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://project-serum.github.io/anchor/ts/index.html" target="_blank" rel="noopener noreferrer" class="nav-link external">
|
|
TypeScript
|
|
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://github.com/project-serum/anchor" target="_blank" rel="noopener noreferrer" class="nav-link external">
|
|
GitHub
|
|
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <!----></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Getting Started</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/anchor/getting-started/introduction.html" class="sidebar-link">Introduction</a></li><li><a href="/anchor/getting-started/installation.html" class="sidebar-link">Installing Dependencies</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Teams</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/anchor/getting-started/projects.html" class="sidebar-link">Projects</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>Tutorials</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/anchor/tutorials/tutorial-0.html" class="sidebar-link">A Minimal Example</a></li><li><a href="/anchor/tutorials/tutorial-1.html" class="sidebar-link">Arguments and Accounts</a></li><li><a href="/anchor/tutorials/tutorial-2.html" aria-current="page" class="active sidebar-link">Account Constraints and Access Control</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/anchor/tutorials/tutorial-2.html#clone-the-repo" class="sidebar-link">Clone the Repo</a></li><li class="sidebar-sub-header"><a href="/anchor/tutorials/tutorial-2.html#defining-a-program" class="sidebar-link">Defining a Program</a></li><li class="sidebar-sub-header"><a href="/anchor/tutorials/tutorial-2.html#next-steps" class="sidebar-link">Next Steps</a></li></ul></li><li><a href="/anchor/tutorials/tutorial-3.html" class="sidebar-link">Cross Program Invocations (CPI)</a></li><li><a href="/anchor/tutorials/tutorial-4.html" class="sidebar-link">Errors</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>CLI</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/anchor/cli/commands.html" class="sidebar-link">Commands</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Source Verification</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/anchor/getting-started/verification.html" class="sidebar-link">Verifiable Builds</a></li><li><a href="/anchor/getting-started/publishing.html" class="sidebar-link">Publishing Source</a></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="account-constraints-and-access-control"><a href="#account-constraints-and-access-control" class="header-anchor">#</a> Account Constraints and Access Control</h1> <p>This tutorial covers how to specify constraints and access control on accounts, a problem
|
|
somewhat unique to the parallel nature of Solana.</p> <p>On Solana, a transaction must specify all accounts required for execution. And because an untrusted client specifies those accounts, a program must responsibly validate all such accounts are what the client claims they are--in addition to any instruction specific access control the program needs to do.</p> <p>For example, you could imagine easily writing a faulty token program that forgets to check if the <strong>signer</strong> of a transaction claiming to be the <strong>owner</strong> of a Token <code>Account</code> actually matches the <strong>owner</strong> on that account. Furthermore, imagine what might happen if the program expects a <code>Mint</code> account but a malicious user gives a token <code>Account</code>.</p> <p>To address these problems, Anchor provides several types, traits, and macros. It's easiest to understand by seeing how they're used in an example, but a couple include</p> <ul><li><a href="https://docs.rs/anchor-lang/latest/anchor_lang/derive.Accounts.html" target="_blank" rel="noopener noreferrer">Accounts<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>: derive macro implementing the <code>Accounts</code> <a href="https://docs.rs/anchor-lang/latest/anchor_lang/trait.Accounts.html" target="_blank" rel="noopener noreferrer">trait<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>, allowing a struct to transform
|
|
from the untrusted <code>&[AccountInfo]</code> slice given to a Solana program into a validated struct
|
|
of deserialized account types.</li> <li><a href="https://docs.rs/anchor-lang/latest/anchor_lang/attr.account.html" target="_blank" rel="noopener noreferrer">#[account]<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>: attribute macro implementing <a href="https://docs.rs/anchor-lang/latest/anchor_lang/trait.AccountSerialize.html" target="_blank" rel="noopener noreferrer">AccountSerialize<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> and <a href="https://docs.rs/anchor-lang/latest/anchor_lang/trait.AnchorDeserialize.html" target="_blank" rel="noopener noreferrer">AccountDeserialize<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>, automatically prepending a unique 8 byte discriminator to the account array. The discriminator is defined by the first 8 bytes of the <code>Sha256</code> hash of the account's Rust identifier--i.e., the struct type name--and ensures no account can be substituted for another.</li> <li><a href="https://docs.rs/anchor-lang/latest/anchor_lang/accounts/account/struct.Account.html" target="_blank" rel="noopener noreferrer">Account<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>: a wrapper type for a deserialized account implementing <code>AccountDeserialize</code>. Using this type within an <code>Accounts</code> struct will ensure the account is <strong>owned</strong> by the address defined by <code>declare_id!</code> where the inner account was defined.</li></ul> <p>With the above, we can define preconditions for any instruction handler expecting a certain set of
|
|
accounts, allowing us to more easily reason about the security of our programs.</p> <h2 id="clone-the-repo"><a href="#clone-the-repo" class="header-anchor">#</a> Clone the Repo</h2> <p>To get started, clone the repo.</p> <div class="language-bash extra-class"><pre class="language-bash"><code><span class="token function">git</span> clone https://github.com/project-serum/anchor
|
|
</code></pre></div><p>Change directories to the <a href="https://github.com/project-serum/anchor/tree/master/examples/tutorial/basic-2" target="_blank" rel="noopener noreferrer">example<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>.</p> <div class="language-bash extra-class"><pre class="language-bash"><code><span class="token builtin class-name">cd</span> anchor/examples/tutorial/basic-2
|
|
</code></pre></div><p>And install any additional JavaScript dependencies:</p> <div class="language-bash extra-class"><pre class="language-bash"><code><span class="token function">yarn</span> <span class="token function">install</span>
|
|
</code></pre></div><h2 id="defining-a-program"><a href="#defining-a-program" class="header-anchor">#</a> Defining a Program</h2> <p>Here we have a simple <strong>Counter</strong> program, where anyone can create a counter, but only the assigned
|
|
<strong>authority</strong> can increment it.</p> <div class="language-rs extra-class"><pre class="language-rs"><code><span class="token keyword">use</span> <span class="token namespace">anchor_lang<span class="token punctuation">::</span>prelude<span class="token punctuation">::</span></span><span class="token operator">*</span><span class="token punctuation">;</span>
|
|
<span class="token macro property">declare_id!</span><span class="token punctuation">(</span><span class="token string">"Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
|
<span class="token attribute attr-name">#[program]</span>
|
|
<span class="token keyword">mod</span> <span class="token module-declaration namespace">basic_2</span> <span class="token punctuation">{</span>
|
|
<span class="token keyword">use</span> <span class="token keyword">super</span><span class="token punctuation">::</span><span class="token operator">*</span><span class="token punctuation">;</span>
|
|
<span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">create</span><span class="token punctuation">(</span>ctx<span class="token punctuation">:</span> <span class="token class-name">Context</span><span class="token operator"><</span><span class="token class-name">Create</span><span class="token operator">></span><span class="token punctuation">,</span> authority<span class="token punctuation">:</span> <span class="token class-name">Pubkey</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">Result</span><span class="token operator"><</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">></span> <span class="token punctuation">{</span>
|
|
<span class="token keyword">let</span> counter <span class="token operator">=</span> <span class="token operator">&</span><span class="token keyword">mut</span> ctx<span class="token punctuation">.</span>accounts<span class="token punctuation">.</span>counter<span class="token punctuation">;</span>
|
|
counter<span class="token punctuation">.</span>authority <span class="token operator">=</span> authority<span class="token punctuation">;</span>
|
|
counter<span class="token punctuation">.</span>count <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
|
|
<span class="token class-name">Ok</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
|
|
<span class="token punctuation">}</span>
|
|
<span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">increment</span><span class="token punctuation">(</span>ctx<span class="token punctuation">:</span> <span class="token class-name">Context</span><span class="token operator"><</span><span class="token class-name">Increment</span><span class="token operator">></span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">Result</span><span class="token operator"><</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">></span> <span class="token punctuation">{</span>
|
|
<span class="token keyword">let</span> counter <span class="token operator">=</span> <span class="token operator">&</span><span class="token keyword">mut</span> ctx<span class="token punctuation">.</span>accounts<span class="token punctuation">.</span>counter<span class="token punctuation">;</span>
|
|
counter<span class="token punctuation">.</span>count <span class="token operator">+=</span> <span class="token number">1</span><span class="token punctuation">;</span>
|
|
<span class="token class-name">Ok</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
|
|
<span class="token punctuation">}</span>
|
|
<span class="token punctuation">}</span>
|
|
<span class="token attribute attr-name">#[derive(Accounts)]</span>
|
|
<span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">Create</span><span class="token operator"><</span><span class="token lifetime-annotation symbol">'info</span><span class="token operator">></span> <span class="token punctuation">{</span>
|
|
<span class="token attribute attr-name">#[account(init, payer = user, space = 8 + 40)]</span>
|
|
<span class="token keyword">pub</span> counter<span class="token punctuation">:</span> <span class="token class-name">Account</span><span class="token operator"><</span><span class="token lifetime-annotation symbol">'info</span><span class="token punctuation">,</span> <span class="token class-name">Counter</span><span class="token operator">></span><span class="token punctuation">,</span>
|
|
<span class="token attribute attr-name">#[account(mut)]</span>
|
|
<span class="token keyword">pub</span> user<span class="token punctuation">:</span> <span class="token class-name">Signer</span><span class="token operator"><</span><span class="token lifetime-annotation symbol">'info</span><span class="token operator">></span><span class="token punctuation">,</span>
|
|
<span class="token keyword">pub</span> system_program<span class="token punctuation">:</span> <span class="token class-name">Program</span><span class="token operator"><</span><span class="token lifetime-annotation symbol">'info</span><span class="token punctuation">,</span> <span class="token class-name">System</span><span class="token operator">></span><span class="token punctuation">,</span>
|
|
<span class="token punctuation">}</span>
|
|
<span class="token attribute attr-name">#[derive(Accounts)]</span>
|
|
<span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">Increment</span><span class="token operator"><</span><span class="token lifetime-annotation symbol">'info</span><span class="token operator">></span> <span class="token punctuation">{</span>
|
|
<span class="token attribute attr-name">#[account(mut, has_one = authority)]</span>
|
|
<span class="token keyword">pub</span> counter<span class="token punctuation">:</span> <span class="token class-name">Account</span><span class="token operator"><</span><span class="token lifetime-annotation symbol">'info</span><span class="token punctuation">,</span> <span class="token class-name">Counter</span><span class="token operator">></span><span class="token punctuation">,</span>
|
|
<span class="token keyword">pub</span> authority<span class="token punctuation">:</span> <span class="token class-name">Signer</span><span class="token operator"><</span><span class="token lifetime-annotation symbol">'info</span><span class="token operator">></span><span class="token punctuation">,</span>
|
|
<span class="token punctuation">}</span>
|
|
<span class="token attribute attr-name">#[account]</span>
|
|
<span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">Counter</span> <span class="token punctuation">{</span>
|
|
<span class="token keyword">pub</span> authority<span class="token punctuation">:</span> <span class="token class-name">Pubkey</span><span class="token punctuation">,</span>
|
|
<span class="token keyword">pub</span> count<span class="token punctuation">:</span> <span class="token keyword">u64</span><span class="token punctuation">,</span>
|
|
<span class="token punctuation">}</span>
|
|
</code></pre></div><p>If you've gone through the previous tutorials the <code>create</code> instruction should be straightforward.
|
|
Let's focus on the <code>increment</code> instruction, specifically the <code>Increment</code> struct deriving
|
|
<code>Accounts</code>.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token attribute attr-name">#[derive(Accounts)]</span>
|
|
<span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">Increment</span><span class="token operator"><</span><span class="token lifetime-annotation symbol">'info</span><span class="token operator">></span> <span class="token punctuation">{</span>
|
|
<span class="token attribute attr-name">#[account(mut, has_one = authority)]</span>
|
|
<span class="token keyword">pub</span> counter<span class="token punctuation">:</span> <span class="token class-name">Account</span><span class="token operator"><</span><span class="token lifetime-annotation symbol">'info</span><span class="token punctuation">,</span> <span class="token class-name">Counter</span><span class="token operator">></span><span class="token punctuation">,</span>
|
|
<span class="token keyword">pub</span> authority<span class="token punctuation">:</span> <span class="token class-name">Signer</span><span class="token operator"><</span><span class="token lifetime-annotation symbol">'info</span><span class="token operator">></span><span class="token punctuation">,</span>
|
|
<span class="token punctuation">}</span>
|
|
</code></pre></div><p>Here, a couple <code>#[account(..)]</code> attributes are used.</p> <ul><li><code>mut</code>: tells the program to persist all changes to the account.</li> <li><code>has_one</code>: enforces the constraint that <code>Increment.counter.authority == Increment.authority.key</code>.</li></ul> <p>Another new concept here is the <code>Signer</code> type. This enforces the constraint that the <code>authority</code>
|
|
account <strong>signed</strong> the transaction. However, anchor doesn't fetch the data on that account.</p> <p>If any of these constraints do not hold, then the <code>increment</code> instruction will never be executed.
|
|
This allows us to completely separate account validation from our program's business logic, allowing us
|
|
to reason about each concern more easily. For more, see the full <a href="https://docs.rs/anchor-lang/latest/anchor_lang/derive.Accounts.html" target="_blank" rel="noopener noreferrer">list<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> of account constraints.</p> <h2 id="next-steps"><a href="#next-steps" class="header-anchor">#</a> Next Steps</h2> <p>We've covered the basics for writing a single program using Anchor on Solana. But the power of
|
|
blockchains come not from a single program, but from combining multiple <em>composable</em> programs
|
|
(buzzword...check). Next, we'll see how to call one program from another.</p></div> <footer class="page-edit"><!----> <!----></footer> <div class="page-nav"><p class="inner"><span class="prev">
|
|
←
|
|
<a href="/anchor/tutorials/tutorial-1.html" class="prev">
|
|
Arguments and Accounts
|
|
</a></span> <span class="next"><a href="/anchor/tutorials/tutorial-3.html">
|
|
Cross Program Invocations (CPI)
|
|
</a>
|
|
→
|
|
</span></p></div> </main></div><div class="global-ui"></div></div>
|
|
<script src="/anchor/assets/js/app.130b905b.js" defer></script><script src="/anchor/assets/js/2.90291299.js" defer></script><script src="/anchor/assets/js/19.54c54ce4.js" defer></script>
|
|
</body>
|
|
</html>
|