Skip to content

Commit 4c0703f

Browse files
authored
interface: Introduce lightweight crate for instruction + id (#200)
* interface: Introduce lightweight crate for instruction + id #### Problem In order to publish the v3 SDK crates and have them usable in Agave, we also need to have SPL crates using the v3 SDK crates. However, we have a circular dependency between Agave and SPL which currently makes this impossible. The overall plan is to have Agave only use "interface" crates from SPL, which have no dependencies on Agave crates. You can see more info about the project at https://github.com/orgs/anza-xyz/projects/27 Memo is very simple, since it just exposes an instruction creator and id to Agave. #### Summary of changes Create the new interface crate with the instruction and id. The Rust scripts needed to be adapted to having more than one crate, so I copied all the scripts from token-2022 and updated the commands in package.json accordingly. NOTE: There is a difference in the `build_memo` instruction creator. In the interface crate, it accepts any program id, whereas the program crate hardcodes the v3 id. Since we're planning on deploying p-memo soon under a new program id, this new function will be easier to use. * Actually add the interface crate files * Remove semver check for now * Wait a bit longer for the program to be deployed and ready * Explicitly build and test p-memo
1 parent f8f39a2 commit 4c0703f

File tree

18 files changed

+207
-132
lines changed

18 files changed

+207
-132
lines changed

.github/workflows/main.yml

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,27 @@ on:
77
branches: [main]
88

99
jobs:
10+
format_and_lint_interface:
11+
name: Format & Lint Interface
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Git Checkout
15+
uses: actions/checkout@v4
16+
17+
- name: Setup Environment
18+
uses: ./.github/actions/setup
19+
with:
20+
clippy: true
21+
rustfmt: true
22+
cargo-cache-key: cargo-interface-lint
23+
cargo-cache-fallback-key: cargo-interface
24+
25+
- name: Format
26+
run: pnpm interface:format
27+
28+
- name: Lint
29+
run: pnpm interface:lint
30+
1031
format_and_lint_programs:
1132
name: Format & Lint Programs
1233
runs-on: ubuntu-latest
@@ -81,26 +102,6 @@ jobs:
81102
- name: Run cargo-audit
82103
run: pnpm rust:audit
83104

84-
semver_rust:
85-
name: Check semver Rust
86-
runs-on: ubuntu-latest
87-
steps:
88-
- name: Git Checkout
89-
uses: actions/checkout@v4
90-
91-
- name: Setup Environment
92-
uses: ./.github/actions/setup
93-
with:
94-
cargo-cache-key: cargo-semver
95-
96-
- name: Install cargo-audit
97-
uses: taiki-e/install-action@v2
98-
with:
99-
tool: cargo-semver-checks
100-
101-
- name: Run semver checks
102-
run: pnpm rust:semver
103-
104105
spellcheck_rust:
105106
name: Spellcheck Rust
106107
runs-on: ubuntu-latest
@@ -138,6 +139,9 @@ jobs:
138139
- name: Build Programs
139140
run: pnpm programs:build
140141

142+
- name: Build p-memo
143+
run: pnpm p-memo:build
144+
141145
- name: Upload Program Builds
142146
uses: actions/upload-artifact@v4
143147
with:
@@ -151,6 +155,23 @@ jobs:
151155
path: ./**/*.so
152156
key: ${{ runner.os }}-builds-${{ github.sha }}
153157

158+
test_interface:
159+
name: Test Interface
160+
runs-on: ubuntu-latest
161+
needs: format_and_lint_interface
162+
steps:
163+
- name: Git Checkout
164+
uses: actions/checkout@v4
165+
166+
- name: Setup Environment
167+
uses: ./.github/actions/setup
168+
with:
169+
cargo-cache-key: cargo-interface-tests
170+
cargo-cache-fallback-key: cargo-interface
171+
172+
- name: Test
173+
run: pnpm interface:test
174+
154175
test_programs:
155176
name: Test Programs
156177
runs-on: ubuntu-latest
@@ -169,6 +190,9 @@ jobs:
169190
- name: Test Programs
170191
run: pnpm programs:test
171192

193+
- name: Test p-memo
194+
run: pnpm p-memo:test
195+
172196
generate_clients:
173197
name: Check Client Generation
174198
runs-on: ubuntu-latest

Cargo.lock

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[workspace]
22
resolver = "2"
3-
members = ["clients/rust", "p-memo", "program"]
3+
members = ["clients/rust", "interface", "p-memo", "program"]
44

55
[workspace.metadata.cli]
66
solana = "2.3.4"

interface/Cargo.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
name = "spl-memo-interface"
3+
version = "1.0.0"
4+
description = "Solana Program Library Memo Interface"
5+
authors = ["Solana Labs Maintainers <[email protected]>"]
6+
repository = "https://github.com/solana-labs/solana-program-library"
7+
license = "Apache-2.0"
8+
edition = "2021"
9+
10+
[dependencies]
11+
solana-instruction = "2.2.1"
12+
solana-pubkey = "2.2.1"
13+
14+
[lib]
15+
crate-type = ["lib"]
16+
17+
[package.metadata.docs.rs]
18+
targets = ["x86_64-unknown-linux-gnu"]

interface/src/instruction.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
use {
2+
solana_instruction::{AccountMeta, Instruction},
3+
solana_pubkey::Pubkey,
4+
};
5+
6+
/// Build a memo instruction, possibly signed
7+
///
8+
/// Accounts expected by this instruction:
9+
///
10+
/// 0. `..0+N` `[signer]` Expected signers; if zero provided, instruction will
11+
/// be processed as a normal, unsigned spl-memo
12+
pub fn build_memo(program_id: &Pubkey, memo: &[u8], signer_pubkeys: &[&Pubkey]) -> Instruction {
13+
Instruction {
14+
program_id: *program_id,
15+
accounts: signer_pubkeys
16+
.iter()
17+
.map(|&pubkey| AccountMeta::new_readonly(*pubkey, true))
18+
.collect(),
19+
data: memo.to_vec(),
20+
}
21+
}
22+
23+
#[cfg(test)]
24+
mod tests {
25+
use super::*;
26+
27+
#[test]
28+
fn test_build_memo() {
29+
let program_id = Pubkey::new_unique();
30+
let signer_pubkey = Pubkey::new_unique();
31+
let memo = "🐆".as_bytes();
32+
let instruction = build_memo(&program_id, memo, &[&signer_pubkey]);
33+
assert_eq!(memo, instruction.data);
34+
assert_eq!(instruction.accounts.len(), 1);
35+
assert_eq!(instruction.accounts[0].pubkey, signer_pubkey);
36+
}
37+
}

interface/src/lib.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#![deny(missing_docs)]
2+
3+
//! An interface for programs that accept a string of encoded characters and
4+
//! verifies that it parses, while verifying and logging signers.
5+
6+
/// Instruction type
7+
pub mod instruction;
8+
9+
/// Legacy symbols from Memo version 1
10+
pub mod v1 {
11+
solana_pubkey::declare_id!("Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo");
12+
}
13+
14+
/// Symbols from Memo version 3
15+
pub mod v3 {
16+
solana_pubkey::declare_id!("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr");
17+
}

package.json

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
{
22
"private": true,
33
"scripts": {
4-
"programs:build": "zx ./scripts/program/build.mjs",
5-
"programs:test": "zx ./scripts/program/test.mjs",
6-
"programs:format": "zx ./scripts/program/format.mjs",
7-
"programs:lint": "zx ./scripts/program/lint.mjs",
4+
"interface:test": "zx ./scripts/rust/test.mjs interface",
5+
"interface:format": "zx ./scripts/rust/format.mjs interface",
6+
"interface:lint": "zx ./scripts/rust/lint.mjs interface",
7+
"programs:build": "zx ./scripts/rust/build-sbf.mjs program",
8+
"programs:test": "zx ./scripts/rust/test-sbf.mjs program",
9+
"programs:format": "zx ./scripts/rust/format.mjs program",
10+
"programs:lint": "zx ./scripts/rust/lint.mjs program",
11+
"p-memo:build": "zx ./scripts/rust/build-sbf.mjs p-memo",
12+
"p-memo:test": "zx ./scripts/rust/test-sbf.mjs p-memo",
813
"solana:check": "zx ./scripts/check-solana-version.mjs",
914
"solana:link": "zx ./scripts/link-solana-version.mjs",
1015
"generate": "pnpm generate:clients",
@@ -22,7 +27,7 @@
2227
"clients:rust:test": "zx ./scripts/client/test-rust.mjs",
2328
"template:upgrade": "zx ./scripts/upgrade-template.mjs",
2429
"rust:spellcheck": "cargo spellcheck --code 1",
25-
"rust:audit": "zx ./scripts/audit-rust.mjs",
30+
"rust:audit": "zx ./scripts/rust/audit.mjs",
2631
"rust:semver": "cargo semver-checks"
2732
},
2833
"devDependencies": {

program/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ solana-msg = "2.2.1"
1818
solana-program-entrypoint = "2.3.0"
1919
solana-program-error = "2.2.2"
2020
solana-pubkey = "2.2.1"
21+
spl-memo-interface = { path = "../interface", version = "1.0.0" }
2122

2223
[dev-dependencies]
2324
solana-program-test = "2.3.6"

program/src/lib.rs

Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,12 @@ pub mod processor;
1212
pub use {
1313
solana_account_info, solana_instruction, solana_msg, solana_program_entrypoint,
1414
solana_program_error, solana_pubkey,
15+
spl_memo_interface::{
16+
v1,
17+
v3::{check_id, id, ID},
18+
},
1519
};
16-
use {
17-
solana_instruction::{AccountMeta, Instruction},
18-
solana_pubkey::Pubkey,
19-
};
20-
21-
/// Legacy symbols from Memo version 1
22-
pub mod v1 {
23-
solana_pubkey::declare_id!("Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo");
24-
}
25-
26-
solana_pubkey::declare_id!("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr");
20+
use {solana_instruction::Instruction, solana_pubkey::Pubkey};
2721

2822
/// Build a memo instruction, possibly signed
2923
///
@@ -32,27 +26,5 @@ solana_pubkey::declare_id!("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr");
3226
/// 0. `..0+N` `[signer]` Expected signers; if zero provided, instruction will
3327
/// be processed as a normal, unsigned spl-memo
3428
pub fn build_memo(memo: &[u8], signer_pubkeys: &[&Pubkey]) -> Instruction {
35-
Instruction {
36-
program_id: id(),
37-
accounts: signer_pubkeys
38-
.iter()
39-
.map(|&pubkey| AccountMeta::new_readonly(*pubkey, true))
40-
.collect(),
41-
data: memo.to_vec(),
42-
}
43-
}
44-
45-
#[cfg(test)]
46-
mod tests {
47-
use super::*;
48-
49-
#[test]
50-
fn test_build_memo() {
51-
let signer_pubkey = Pubkey::new_unique();
52-
let memo = "🐆".as_bytes();
53-
let instruction = build_memo(memo, &[&signer_pubkey]);
54-
assert_eq!(memo, instruction.data);
55-
assert_eq!(instruction.accounts.len(), 1);
56-
assert_eq!(instruction.accounts[0].pubkey, signer_pubkey);
57-
}
29+
spl_memo_interface::instruction::build_memo(&id(), memo, signer_pubkeys)
5830
}

scripts/program/build.mjs

Lines changed: 0 additions & 13 deletions
This file was deleted.

0 commit comments

Comments
 (0)