Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lang: Zero copy deserialization #202

Merged
merged 23 commits into from
Apr 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ _examples: &examples
- npm install -g mocha
- npm install -g ts-mocha
- npm install -g typescript
- npm install -g @project-serum/anchor
- cd ts && yarn && yarn build && npm link && cd ../
- npm install -g @project-serum/serum
- npm install -g @project-serum/common
- npm install -g @solana/spl-token
Expand All @@ -28,7 +28,7 @@ _examples: &examples
- export PATH="/home/travis/.local/share/solana/install/active_release/bin:$PATH"
- export NODE_PATH="/home/travis/.nvm/versions/node/v$NODE_VERSION/lib/node_modules/:$NODE_PATH"
- yes | solana-keygen new
- cargo install --git https://github.com/project-serum/anchor anchor-cli --locked
- cargo install --path $TRAVIS_BUILD_DIR/cli anchor-cli --locked

jobs:
include:
Expand Down Expand Up @@ -59,6 +59,7 @@ jobs:
- pushd examples/events && anchor test && popd
- pushd examples/cashiers-check && anchor test && popd
- pushd examples/typescript && yarn && anchor test && popd
- pushd examples/zero-copy && yarn && anchor test && popd
- <<: *examples
name: Runs the examples 2
script:
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ incremented for features.
## Features

* lang: Allows one to specify multiple `with` targets when creating associated acconts ([#197](https://github.com/project-serum/anchor/pull/197)).
* lang, ts: Add array support ([#202](https://github.com/project-serum/anchor/pull/202)).
* lang: Zero copy deserialization for accounts ([#202](https://github.com/project-serum/anchor/pull/202)).

## [0.4.3] - 2021-04-13

Expand Down
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions examples/zero-copy/Anchor.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cluster = "localnet"
wallet = "~/.config/solana/id.json"
4 changes: 4 additions & 0 deletions examples/zero-copy/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[workspace]
members = [
"programs/*"
]
12 changes: 12 additions & 0 deletions examples/zero-copy/migrations/deploy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Migrations are an early feature. Currently, they're nothing more than this
// single deploy script that's invoked from the CLI, injecting a provider
// configured from the workspace's Anchor.toml.

const anchor = require("@project-serum/anchor");

module.exports = async function (provider) {
// Configure client to use the provider.
anchor.setProvider(provider);

// Add your deploy script here.
}
18 changes: 18 additions & 0 deletions examples/zero-copy/programs/zero-copy/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "zero-copy"
version = "0.1.0"
description = "Created with Anchor"
edition = "2018"

[lib]
crate-type = ["cdylib", "lib"]
name = "zero_copy"

[features]
no-entrypoint = []
no-idl = []
cpi = ["no-entrypoint"]
default = []

[dependencies]
anchor-lang = { path = "../../../../lang" }
2 changes: 2 additions & 0 deletions examples/zero-copy/programs/zero-copy/Xargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[target.bpfel-unknown-unknown.dependencies.std]
features = []
144 changes: 144 additions & 0 deletions examples/zero-copy/programs/zero-copy/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
//! This example demonstrates the use of zero copy deserialization for accounts.
//! The main noticeable benefit one achieves using zero copy is the ability
//! to create accounts larger than the size of the stack or heap, as is
//! demonstrated by the event queue in this example.

use anchor_lang::prelude::*;

#[program]
pub mod zero_copy {
use super::*;

pub fn create_foo(ctx: Context<CreateFoo>) -> ProgramResult {
let foo = &mut ctx.accounts.foo.load_init()?;
foo.authority = *ctx.accounts.authority.key;
foo.set_second_authority(ctx.accounts.authority.key);
Ok(())
}

pub fn update_foo(ctx: Context<UpdateFoo>, data: u64) -> ProgramResult {
let mut foo = ctx.accounts.foo.load_mut()?;
foo.data = data;
Ok(())
}

pub fn update_foo_second(ctx: Context<UpdateFooSecond>, second_data: u64) -> ProgramResult {
let mut foo = ctx.accounts.foo.load_mut()?;
foo.second_data = second_data;
Ok(())
}

pub fn create_bar(ctx: Context<CreateBar>) -> ProgramResult {
let bar = &mut ctx.accounts.bar.load_init()?;
bar.authority = *ctx.accounts.authority.key;
Ok(())
}

pub fn update_bar(ctx: Context<UpdateBar>, data: u64) -> ProgramResult {
let bar = &mut ctx.accounts.bar.load_mut()?;
bar.data = data;
Ok(())
}

pub fn create_large_account(_ctx: Context<CreateLargeAccount>) -> ProgramResult {
Ok(())
}

pub fn update_large_account(
ctx: Context<UpdateLargeAccount>,
idx: u32,
data: u64,
) -> ProgramResult {
let event_q = &mut ctx.accounts.event_q.load_mut()?;
event_q.events[idx as usize] = Event {
data,
from: *ctx.accounts.from.key,
};
Ok(())
}
}

#[derive(Accounts)]
pub struct CreateFoo<'info> {
#[account(init)]
foo: Loader<'info, Foo>,
#[account(signer)]
authority: AccountInfo<'info>,
rent: Sysvar<'info, Rent>,
}

#[derive(Accounts)]
pub struct UpdateFoo<'info> {
#[account(mut, has_one = authority)]
foo: Loader<'info, Foo>,
#[account(signer)]
authority: AccountInfo<'info>,
}

#[derive(Accounts)]
pub struct UpdateFooSecond<'info> {
#[account(mut, "&foo.load()?.get_second_authority() == second_authority.key")]
foo: Loader<'info, Foo>,
#[account(signer)]
second_authority: AccountInfo<'info>,
}

#[derive(Accounts)]
pub struct CreateBar<'info> {
#[account(associated = authority, with = foo)]
bar: Loader<'info, Bar>,
#[account(signer)]
authority: AccountInfo<'info>,
foo: Loader<'info, Foo>,
rent: Sysvar<'info, Rent>,
system_program: AccountInfo<'info>,
}

#[derive(Accounts)]
pub struct UpdateBar<'info> {
#[account(mut, has_one = authority)]
bar: Loader<'info, Bar>,
#[account(signer)]
authority: AccountInfo<'info>,
}

#[derive(Accounts)]
pub struct CreateLargeAccount<'info> {
#[account(init)]
event_q: Loader<'info, EventQ>,
rent: Sysvar<'info, Rent>,
}

#[derive(Accounts)]
pub struct UpdateLargeAccount<'info> {
#[account(mut)]
event_q: Loader<'info, EventQ>,
#[account(signer)]
from: AccountInfo<'info>,
}

#[account(zero_copy)]
pub struct Foo {
pub authority: Pubkey,
pub data: u64,
pub second_data: u64,
#[accessor(Pubkey)] // The `accessor` api will likely be removed.
pub second_authority: [u8; 32],
}

#[associated(zero_copy)]
pub struct Bar {
pub authority: Pubkey,
pub data: u64,
}

#[account(zero_copy)]
pub struct EventQ {
pub events: [Event; 25000],
}

#[zero_copy]
pub struct Event {
pub from: Pubkey,
pub data: u64,
}
Loading