This commit is contained in:
Armani Ferrante 2022-02-19 12:33:38 -05:00
parent 0068b5ca30
commit 72c1dc208b
No known key found for this signature in database
GPG Key ID: D597A80BCF8E12B7
5 changed files with 50 additions and 36 deletions

View File

@ -3,30 +3,58 @@ use solana_program::hash;
use std::io::{Cursor, Write};
pub const HEADER_LEN: usize = 8;
pub const LAYOUT_VERSION: u8 = 1;
const HEADER_LAYOUT_VERSION_INDEX: usize = 0;
const HEADER_TYPE_VERSION_INDEX: usize = 1;
#[cfg(feature = "deprecated-layout")]
const HEADER_DISCRIMINATOR_INDEX: usize = 0;
#[cfg(not(feature = "deprecated-layout"))]
const HEADER_DISCRIMINATOR_INDEX: usize = 2;
#[cfg(feature = "deprecated-layout")]
pub fn read_discriminator(data: &[u8]) -> &[u8; 8] {
array_ref![data, 0, 8]
}
pub const DISCRIMINATOR_LEN: usize = 8;
#[cfg(not(feature = "deprecated-layout"))]
pub fn read_discriminator(data: &[u8]) -> &[u8; 4] {
array_ref![data, 2, 4]
pub const DISCRIMINATOR_LEN: usize = 4;
pub const DEFAULT_ACCOUNT_VERSION: u8 = 1;
// Initializes the header. Should only be run once.
pub fn init(account_data: &mut [u8], discriminator: &[u8]) {
if !cfg!(feature = "deprecated-layout") {
write_layout_version(account_data, LAYOUT_VERSION);
write_account_version(account_data, DEFAULT_ACCOUNT_VERSION);
}
write_discriminator(account_data, discriminator);
}
#[cfg(feature = "deprecated-layout")]
pub fn create_discriminator(account_name: &str, namespace: Option<&str>) -> [u8; 8] {
let discriminator_preimage = format!("{}:{}", namespace.unwrap_or("account"), account_name);
let mut discriminator = [0u8; 8];
discriminator.copy_from_slice(&hash::hash(discriminator_preimage.as_bytes()).to_bytes()[..8]);
discriminator
fn write_layout_version(account_data: &mut [u8], version: u8) {
account_data[HEADER_LAYOUT_VERSION_INDEX] = version;
}
#[cfg(not(feature = "deprecated-layout"))]
pub fn create_discriminator(account_name: &str, namespace: Option<&str>) -> [u8; 4] {
fn write_account_version(account_data: &mut [u8], version: u8) {
account_data[HEADER_TYPE_VERSION_INDEX] = version;
}
fn write_discriminator(account_data: &mut [u8], discriminator: &[u8]) {
let dst: &mut [u8] = &mut account_data[HEADER_DISCRIMINATOR_INDEX..];
let mut cursor = Cursor::new(dst);
cursor.write_all(discriminator).unwrap();
}
pub fn read_discriminator(data: &[u8]) -> &[u8; DISCRIMINATOR_LEN] {
array_ref![data, HEADER_DISCRIMINATOR_INDEX, DISCRIMINATOR_LEN]
}
pub fn create_discriminator(
account_name: &str,
namespace: Option<&str>,
) -> [u8; DISCRIMINATOR_LEN] {
let discriminator_preimage = format!("{}:{}", namespace.unwrap_or("account"), account_name);
let mut discriminator = [0u8; 4];
discriminator.copy_from_slice(&hash::hash(discriminator_preimage.as_bytes()).to_bytes()[..4]);
let mut discriminator = [0u8; DISCRIMINATOR_LEN];
discriminator.copy_from_slice(
&hash::hash(discriminator_preimage.as_bytes()).to_bytes()[..DISCRIMINATOR_LEN],
);
discriminator
}
@ -38,20 +66,6 @@ pub fn read_data_mut(account_data: &mut [u8]) -> &mut [u8] {
&mut account_data[HEADER_LEN..]
}
pub fn write_discriminator(account_data: &mut [u8], discriminator: &[u8]) {
#[cfg(feature = "deprecated-layout")]
{
let mut cursor = Cursor::new(account_data);
cursor.write_all(discriminator).unwrap();
}
#[cfg(not(feature = "deprecated-layout"))]
{
let dst: &mut [u8] = &mut account_data[2..];
let mut cursor = Cursor::new(dst);
cursor.write_all(discriminator).unwrap();
}
}
// Bit of a hack. We return the length as a string and then parse it into
// a token stream in the macro code generation, so that we can isolate all
// the feature flagging to this one module, here.

View File

@ -150,7 +150,7 @@ pub fn generate_constraint_zeroed(f: &Field, _c: &ConstraintZeroed) -> proc_macr
let header_write = quote! {
{
use anchor_lang::Discriminator;
anchor_lang::accounts::header::write_discriminator(&mut __data, &#account_ty::discriminator());
anchor_lang::accounts::header::init(&mut __data, &#account_ty::discriminator());
}
};
// Check the *entire* account header is zero.
@ -532,7 +532,7 @@ fn generate_constraint_init(f: &Field, c: &ConstraintInitGroup) -> proc_macro2::
{
use anchor_lang::Discriminator;
let mut __data = actual_field.try_borrow_mut_data()?;
anchor_lang::accounts::header::write_discriminator(
anchor_lang::accounts::header::init(
&mut __data,
&#account_ty::discriminator(),
);

View File

@ -259,7 +259,7 @@ pub fn parse(
if is_deprecated_layout {
None
} else {
Some("0.1.0".to_string()) // TODO: make this a u8?
Some(1)
}
};

View File

@ -9,7 +9,7 @@ pub mod pda;
pub struct Idl {
// Version of the idl protocol.
#[serde(skip_serializing_if = "Option::is_none", default)]
pub layout_version: Option<String>,
pub layout_version: Option<u8>,
// Version of the program.
pub version: String,
pub name: String,

View File

@ -67,8 +67,8 @@ describe("deprecated-layout", () => {
assert.ok(expectedDiscriminator.length === 4);
assert.ok(givenDiscriminator.compare(expectedDiscriminator) === 0);
assert.ok(accountData.compare(Buffer.from([2, 0, 0, 0, 0, 0, 0, 0])) === 0);
assert.ok(header[0] === 0);
assert.ok(header[1] === 0);
assert.ok(header[0] === 1);
assert.ok(header[1] === 1);
assert.ok(header[6] === 0);
assert.ok(header[7] === 0);