update
This commit is contained in:
parent
b0a364523a
commit
3b680a6cf9
|
@ -1,6 +1,7 @@
|
||||||
//! `anchor_client` provides an RPC client to send transactions and fetch
|
//! `anchor_client` provides an RPC client to send transactions and fetch
|
||||||
//! deserialized accounts from Solana programs written in `anchor_lang`.
|
//! deserialized accounts from Solana programs written in `anchor_lang`.
|
||||||
|
|
||||||
|
use anchor_lang::accounts::header;
|
||||||
use anchor_lang::solana_program::instruction::{AccountMeta, Instruction};
|
use anchor_lang::solana_program::instruction::{AccountMeta, Instruction};
|
||||||
use anchor_lang::solana_program::program_error::ProgramError;
|
use anchor_lang::solana_program::program_error::ProgramError;
|
||||||
use anchor_lang::solana_program::pubkey::Pubkey;
|
use anchor_lang::solana_program::pubkey::Pubkey;
|
||||||
|
@ -292,23 +293,11 @@ fn handle_program_log<T: anchor_lang::Event + anchor_lang::AnchorDeserialize>(
|
||||||
|
|
||||||
let mut slice: &[u8] = &borsh_bytes[..];
|
let mut slice: &[u8] = &borsh_bytes[..];
|
||||||
|
|
||||||
#[cfg(feature = "deprecated-layout")]
|
let disc = header::read_discriminator(slice);
|
||||||
let disc: [u8; 8] = {
|
|
||||||
let mut disc = [0; 8];
|
|
||||||
disc.copy_from_slice(&borsh_bytes[..8]);
|
|
||||||
slice = &slice[8..];
|
slice = &slice[8..];
|
||||||
disc
|
|
||||||
};
|
|
||||||
#[cfg(not(feature = "deprecated-layout"))]
|
|
||||||
let disc: [u8; 4] = {
|
|
||||||
let mut disc = [0; 4];
|
|
||||||
disc.copy_from_slice(&borsh_bytes[2..6]);
|
|
||||||
slice = &slice[8..];
|
|
||||||
disc
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut event = None;
|
let mut event = None;
|
||||||
if disc == T::discriminator() {
|
if disc == &T::discriminator() {
|
||||||
let e: T = anchor_lang::AnchorDeserialize::deserialize(&mut slice)
|
let e: T = anchor_lang::AnchorDeserialize::deserialize(&mut slice)
|
||||||
.map_err(|e| ClientError::LogParseError(e.to_string()))?;
|
.map_err(|e| ClientError::LogParseError(e.to_string()))?;
|
||||||
event = Some(e);
|
event = Some(e);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//! Account container that checks ownership on deserialization.
|
//! Account container that checks ownership on deserialization.
|
||||||
|
|
||||||
|
use crate::accounts::header;
|
||||||
use crate::error::ErrorCode;
|
use crate::error::ErrorCode;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use solana_program::account_info::AccountInfo;
|
use solana_program::account_info::AccountInfo;
|
||||||
|
@ -334,10 +335,7 @@ impl<'info, T: AccountSerialize + AccountDeserialize + Owner + Clone> AccountsEx
|
||||||
if &T::owner() == program_id {
|
if &T::owner() == program_id {
|
||||||
let info = self.to_account_info();
|
let info = self.to_account_info();
|
||||||
let mut data = info.try_borrow_mut_data()?;
|
let mut data = info.try_borrow_mut_data()?;
|
||||||
|
let dst = header::read_data_mut(&mut data);
|
||||||
// Chop off the header.
|
|
||||||
let dst: &mut [u8] = &mut data[8..];
|
|
||||||
|
|
||||||
let mut cursor = std::io::Cursor::new(dst);
|
let mut cursor = std::io::Cursor::new(dst);
|
||||||
self.account.try_serialize(&mut cursor)?;
|
self.account.try_serialize(&mut cursor)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
//! Type facilitating on demand zero copy deserialization.
|
//! Type facilitating on demand zero copy deserialization.
|
||||||
|
|
||||||
|
use crate::accounts::header;
|
||||||
use crate::error::ErrorCode;
|
use crate::error::ErrorCode;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use arrayref::array_ref;
|
|
||||||
use solana_program::account_info::AccountInfo;
|
use solana_program::account_info::AccountInfo;
|
||||||
use solana_program::entrypoint::ProgramResult;
|
use solana_program::entrypoint::ProgramResult;
|
||||||
use solana_program::instruction::AccountMeta;
|
use solana_program::instruction::AccountMeta;
|
||||||
|
@ -120,12 +120,7 @@ impl<'info, T: ZeroCopy + Owner> AccountLoader<'info, T> {
|
||||||
return Err(ErrorCode::AccountOwnedByWrongProgram.into());
|
return Err(ErrorCode::AccountOwnedByWrongProgram.into());
|
||||||
}
|
}
|
||||||
let data: &[u8] = &acc_info.try_borrow_data()?;
|
let data: &[u8] = &acc_info.try_borrow_data()?;
|
||||||
// Discriminator must match.
|
let disc_bytes = header::read_discriminator(data);
|
||||||
#[cfg(feature = "deprecated-layout")]
|
|
||||||
let disc_bytes = array_ref![data, 0, 8];
|
|
||||||
#[cfg(not(feature = "deprecated-layout"))]
|
|
||||||
let disc_bytes = array_ref![data, 2, 4];
|
|
||||||
|
|
||||||
if disc_bytes != &T::discriminator() {
|
if disc_bytes != &T::discriminator() {
|
||||||
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
|
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
|
||||||
}
|
}
|
||||||
|
@ -147,12 +142,7 @@ impl<'info, T: ZeroCopy + Owner> AccountLoader<'info, T> {
|
||||||
/// Returns a Ref to the account data structure for reading.
|
/// Returns a Ref to the account data structure for reading.
|
||||||
pub fn load(&self) -> Result<Ref<T>, ProgramError> {
|
pub fn load(&self) -> Result<Ref<T>, ProgramError> {
|
||||||
let data = self.acc_info.try_borrow_data()?;
|
let data = self.acc_info.try_borrow_data()?;
|
||||||
|
let disc_bytes = header::read_discriminator(&data);
|
||||||
#[cfg(feature = "deprecated-layout")]
|
|
||||||
let disc_bytes = array_ref![data, 0, 8];
|
|
||||||
#[cfg(not(feature = "deprecated-layout"))]
|
|
||||||
let disc_bytes = array_ref![data, 2, 4];
|
|
||||||
|
|
||||||
if disc_bytes != &T::discriminator() {
|
if disc_bytes != &T::discriminator() {
|
||||||
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
|
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
|
||||||
}
|
}
|
||||||
|
@ -170,12 +160,7 @@ impl<'info, T: ZeroCopy + Owner> AccountLoader<'info, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = self.acc_info.try_borrow_mut_data()?;
|
let data = self.acc_info.try_borrow_mut_data()?;
|
||||||
|
let disc_bytes = header::read_discriminator(&data);
|
||||||
#[cfg(feature = "deprecated-layout")]
|
|
||||||
let disc_bytes = array_ref![data, 0, 8];
|
|
||||||
#[cfg(not(feature = "deprecated-layout"))]
|
|
||||||
let disc_bytes = array_ref![data, 2, 4];
|
|
||||||
|
|
||||||
if disc_bytes != &T::discriminator() {
|
if disc_bytes != &T::discriminator() {
|
||||||
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
|
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
use arrayref::array_ref;
|
||||||
|
|
||||||
|
#[cfg(feature = "deprecated-layout")]
|
||||||
|
pub fn read_discriminator(data: &[u8]) -> &[u8; 8] {
|
||||||
|
array_ref![data, 0, 8]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "deprecated-layout"))]
|
||||||
|
pub fn read_discriminator<'a>(data: &[u8]) -> &[u8; 4] {
|
||||||
|
array_ref![data, 2, 4]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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(
|
||||||
|
&crate::solana_program::hash::hash(discriminator_preimage.as_bytes()).to_bytes()[..8],
|
||||||
|
);
|
||||||
|
discriminator
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "deprecated-layout"))]
|
||||||
|
pub fn create_discriminator(account_name: &str, namespace: Option<&str>) -> [u8; 4] {
|
||||||
|
let discriminator_preimage = format!("{}:{}", namespace.unwrap_or("account"), account_name);
|
||||||
|
let mut discriminator = [0u8; 4];
|
||||||
|
discriminator.copy_from_slice(
|
||||||
|
&crate::solana_program::hash::hash(discriminator_preimage.as_bytes()).to_bytes()[..4],
|
||||||
|
);
|
||||||
|
discriminator
|
||||||
|
}
|
||||||
|
|
||||||
|
// Header is 8 bytes regardless of layout.
|
||||||
|
pub fn read_data(account_data: &[u8]) -> &[u8] {
|
||||||
|
&account_data[8..]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_data_mut(account_data: &mut [u8]) -> &mut [u8] {
|
||||||
|
&mut account_data[8..]
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::accounts::header;
|
||||||
use crate::error::ErrorCode;
|
use crate::error::ErrorCode;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use arrayref::array_ref;
|
use arrayref::array_ref;
|
||||||
|
@ -59,13 +60,7 @@ impl<'info, T: ZeroCopy> Loader<'info, T> {
|
||||||
return Err(ErrorCode::AccountOwnedByWrongProgram.into());
|
return Err(ErrorCode::AccountOwnedByWrongProgram.into());
|
||||||
}
|
}
|
||||||
let data: &[u8] = &acc_info.try_borrow_data()?;
|
let data: &[u8] = &acc_info.try_borrow_data()?;
|
||||||
|
let disc_bytes = header::read_discriminator(data);
|
||||||
// Discriminator must match.
|
|
||||||
#[cfg(feature = "deprecated-layout")]
|
|
||||||
let disc_bytes = array_ref![data, 0, 8];
|
|
||||||
#[cfg(not(feature = "deprecated-layout"))]
|
|
||||||
let disc_bytes = array_ref![data, 2, 4];
|
|
||||||
|
|
||||||
if disc_bytes != &T::discriminator() {
|
if disc_bytes != &T::discriminator() {
|
||||||
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
|
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
|
||||||
}
|
}
|
||||||
|
@ -90,12 +85,7 @@ impl<'info, T: ZeroCopy> Loader<'info, T> {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
pub fn load(&self) -> Result<Ref<T>, ProgramError> {
|
pub fn load(&self) -> Result<Ref<T>, ProgramError> {
|
||||||
let data = self.acc_info.try_borrow_data()?;
|
let data = self.acc_info.try_borrow_data()?;
|
||||||
|
let disc_bytes = header::read_discriminator(&data);
|
||||||
#[cfg(feature = "deprecated-layout")]
|
|
||||||
let disc_bytes = array_ref![data, 0, 8];
|
|
||||||
#[cfg(not(feature = "deprecated-layout"))]
|
|
||||||
let disc_bytes = array_ref![data, 2, 4];
|
|
||||||
|
|
||||||
if disc_bytes != &T::discriminator() {
|
if disc_bytes != &T::discriminator() {
|
||||||
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
|
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
|
||||||
}
|
}
|
||||||
|
@ -113,12 +103,7 @@ impl<'info, T: ZeroCopy> Loader<'info, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = self.acc_info.try_borrow_mut_data()?;
|
let data = self.acc_info.try_borrow_mut_data()?;
|
||||||
|
let disc_bytes = header::read_discriminator(&data);
|
||||||
#[cfg(feature = "deprecated-layout")]
|
|
||||||
let disc_bytes = array_ref![data, 0, 8];
|
|
||||||
#[cfg(not(feature = "deprecated-layout"))]
|
|
||||||
let disc_bytes = array_ref![data, 2, 4];
|
|
||||||
|
|
||||||
if disc_bytes != &T::discriminator() {
|
if disc_bytes != &T::discriminator() {
|
||||||
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
|
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ pub mod cpi_account;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
pub mod cpi_state;
|
pub mod cpi_state;
|
||||||
|
pub mod header;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
pub mod loader;
|
pub mod loader;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
use crate::accounts::cpi_account::CpiAccount;
|
use crate::accounts::cpi_account::CpiAccount;
|
||||||
|
use crate::accounts::header;
|
||||||
use crate::error::ErrorCode;
|
use crate::error::ErrorCode;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use solana_program::account_info::AccountInfo;
|
use solana_program::account_info::AccountInfo;
|
||||||
|
@ -99,10 +100,7 @@ impl<'info, T: AccountSerialize + AccountDeserialize + Clone> AccountsExit<'info
|
||||||
fn exit(&self, _program_id: &Pubkey) -> ProgramResult {
|
fn exit(&self, _program_id: &Pubkey) -> ProgramResult {
|
||||||
let info = self.to_account_info();
|
let info = self.to_account_info();
|
||||||
let mut data = info.try_borrow_mut_data()?;
|
let mut data = info.try_borrow_mut_data()?;
|
||||||
|
let dst = header::read_data_mut(&mut data);
|
||||||
// Chop off the header.
|
|
||||||
let dst: &mut [u8] = &mut data[8..];
|
|
||||||
|
|
||||||
let mut cursor = std::io::Cursor::new(dst);
|
let mut cursor = std::io::Cursor::new(dst);
|
||||||
self.inner.account.try_serialize(&mut cursor)?;
|
self.inner.account.try_serialize(&mut cursor)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -19,7 +19,7 @@ const ACCOUNT_HEADER_SIZE = 8;
|
||||||
* Number of bytes of the account discriminator.
|
* Number of bytes of the account discriminator.
|
||||||
*/
|
*/
|
||||||
const ACCOUNT_DISCRIMINATOR_SIZE = 4;
|
const ACCOUNT_DISCRIMINATOR_SIZE = 4;
|
||||||
const DEPRECATED_ACCOUNT_DISCRIMINATOR_SIZE = 4;
|
const DEPRECATED_ACCOUNT_DISCRIMINATOR_SIZE = 8;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes and decodes account objects.
|
* Encodes and decodes account objects.
|
||||||
|
|
|
@ -24,7 +24,7 @@ import InstructionNamespaceFactory from "./instruction.js";
|
||||||
import RpcNamespaceFactory from "./rpc.js";
|
import RpcNamespaceFactory from "./rpc.js";
|
||||||
import TransactionNamespaceFactory from "./transaction.js";
|
import TransactionNamespaceFactory from "./transaction.js";
|
||||||
import { IdlTypes, TypeDef } from "./types.js";
|
import { IdlTypes, TypeDef } from "./types.js";
|
||||||
import * as features from "../../utils/features.js";
|
import { BorshAccountHeader } from "../../coder/borsh/accounts.js";
|
||||||
|
|
||||||
export default class StateFactory {
|
export default class StateFactory {
|
||||||
public static build<IDL extends Idl>(
|
public static build<IDL extends Idl>(
|
||||||
|
@ -175,16 +175,12 @@ export class StateClient<IDL extends Idl> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const expectedDiscriminator = await stateDiscriminator(state.struct.name);
|
const expectedDiscriminator = await stateDiscriminator(state.struct.name);
|
||||||
|
const discriminator = BorshAccountHeader.parseDiscriminator(
|
||||||
if (features.isSet("deprecated-layout")) {
|
accountInfo.data
|
||||||
if (expectedDiscriminator.compare(accountInfo.data.slice(0, 8))) {
|
);
|
||||||
|
if (discriminator.compare(expectedDiscriminator)) {
|
||||||
throw new Error("Invalid state discriminator");
|
throw new Error("Invalid state discriminator");
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (expectedDiscriminator.compare(accountInfo.data.slice(2, 6))) {
|
|
||||||
throw new Error("Invalid state discriminator");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.coder.state.decode(accountInfo.data);
|
return this.coder.state.decode(accountInfo.data);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue