Armani Ferrante %!s(int64=3) %!d(string=hai) anos
pai
achega
72c1dc208b

+ 43 - 29
lang/common/src/header.rs

@@ -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")]
-pub fn read_discriminator(data: &[u8]) -> &[u8; 8] {
-    array_ref![data, 0, 8]
-}
+const HEADER_DISCRIMINATOR_INDEX: usize = 0;
+#[cfg(not(feature = "deprecated-layout"))]
+const HEADER_DISCRIMINATOR_INDEX: usize = 2;
 
+#[cfg(feature = "deprecated-layout")]
+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.

+ 2 - 2
lang/syn/src/codegen/accounts/constraints.rs

@@ -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(),
                                 );

+ 1 - 1
lang/syn/src/idl/file.rs

@@ -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)
         }
     };
 

+ 1 - 1
lang/syn/src/idl/mod.rs

@@ -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,

+ 2 - 2
tests/deprecated-layout/tests/deprecated-layout.ts

@@ -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);