anchor/tutorials/tutorial-2.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,&lt;svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22&gt;&lt;text y=%22.9em%22 font-size=%2290%22&gt;⚓ &lt;/text&gt;&lt;/svg&gt;">
<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.84e5cb69.js" as="script"><link rel="preload" href="/anchor/assets/js/2.90291299.js" as="script"><link rel="preload" href="/anchor/assets/js/19.4d4ff292.js" as="script"><link rel="prefetch" href="/anchor/assets/js/10.9a96e389.js"><link rel="prefetch" href="/anchor/assets/js/11.8ed09511.js"><link rel="prefetch" href="/anchor/assets/js/12.2382ff5e.js"><link rel="prefetch" href="/anchor/assets/js/13.7bb3490d.js"><link rel="prefetch" href="/anchor/assets/js/14.7f03477f.js"><link rel="prefetch" href="/anchor/assets/js/15.ec67cdb6.js"><link rel="prefetch" href="/anchor/assets/js/16.49529303.js"><link rel="prefetch" href="/anchor/assets/js/17.31820e82.js"><link rel="prefetch" href="/anchor/assets/js/18.a3c88079.js"><link rel="prefetch" href="/anchor/assets/js/20.42e65138.js"><link rel="prefetch" href="/anchor/assets/js/21.2312ea83.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>&amp;[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">&quot;Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS&quot;</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">&lt;</span><span class="token class-name">Create</span><span class="token operator">&gt;</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">-&gt;</span> <span class="token class-name">Result</span><span class="token operator">&lt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> counter <span class="token operator">=</span> <span class="token operator">&amp;</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">&lt;</span><span class="token class-name">Increment</span><span class="token operator">&gt;</span><span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token class-name">Result</span><span class="token operator">&lt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> counter <span class="token operator">=</span> <span class="token operator">&amp;</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">&lt;</span><span class="token lifetime-annotation symbol">'info</span><span class="token operator">&gt;</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">&lt;</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">&gt;</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">&lt;</span><span class="token lifetime-annotation symbol">'info</span><span class="token operator">&gt;</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">&lt;</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">&gt;</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">&lt;</span><span class="token lifetime-annotation symbol">'info</span><span class="token operator">&gt;</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">&lt;</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">&gt;</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">&lt;</span><span class="token lifetime-annotation symbol">'info</span><span class="token operator">&gt;</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">&lt;</span><span class="token lifetime-annotation symbol">'info</span><span class="token operator">&gt;</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">&lt;</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">&gt;</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">&lt;</span><span class="token lifetime-annotation symbol">'info</span><span class="token operator">&gt;</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.84e5cb69.js" defer></script><script src="/anchor/assets/js/2.90291299.js" defer></script><script src="/anchor/assets/js/19.4d4ff292.js" defer></script>
</body>
</html>