Compare commits
4 Commits
1f70434f1e
...
97b074f88c
Author | SHA1 | Date |
---|---|---|
Jean Marchand (Exotic Markets) | 97b074f88c | |
czkz | c96846fce2 | |
acheron | 10c997552e | |
Jean Marchand | 003a298cd7 |
|
@ -16,7 +16,8 @@ The minor version will be incremented upon a breaking change and the patch versi
|
|||
|
||||
### Fixes
|
||||
|
||||
- syn: Eliminate variable allocations that build up stack space for token extension code generation ([#2913](https://github.com/coral-xyz/anchor/pull/2913)).
|
||||
- lang: Eliminate variable allocations that build up stack space for token extension code generation ([#2913](https://github.com/coral-xyz/anchor/pull/2913)).
|
||||
- ts: Fix incorrect `maxSupportedTransactionVersion` in `AnchorProvider.send*()` methods ([#2922](https://github.com/coral-xyz/anchor/pull/2922)).
|
||||
|
||||
### Breaking
|
||||
|
||||
|
|
2
Makefile
2
Makefile
|
@ -15,6 +15,8 @@ publish:
|
|||
sleep 25
|
||||
cd lang/derive/accounts/ && cargo publish && cd ../../../
|
||||
sleep 25
|
||||
cd lang/derive/serde/ && cargo publish && cd ../../../
|
||||
sleep 25
|
||||
cd lang/derive/space/ && cargo publish && cd ../../../
|
||||
sleep 25
|
||||
cd lang/attribute/access-control/ && cargo publish && cd ../../../
|
||||
|
|
|
@ -4,8 +4,8 @@ use proc_macro::TokenStream;
|
|||
use proc_macro2::{Ident, TokenStream as TokenStream2, TokenTree};
|
||||
use quote::{quote, quote_spanned, ToTokens};
|
||||
use syn::{
|
||||
parse::ParseStream, parse2, parse_macro_input, Attribute, DeriveInput, Fields, GenericArgument,
|
||||
LitInt, PathArguments, Type, TypeArray,
|
||||
parse::ParseStream, parse2, parse_macro_input, spanned::Spanned, DeriveInput, Field, Fields,
|
||||
GenericArgument, LitInt, PathArguments, Type, TypeArray,
|
||||
};
|
||||
|
||||
/// Implements a [`Space`](./trait.Space.html) trait on the given
|
||||
|
@ -13,6 +13,7 @@ use syn::{
|
|||
///
|
||||
/// For types that have a variable size like String and Vec, it is necessary to indicate the size by the `max_len` attribute.
|
||||
/// For nested types, it is necessary to specify a size for each variable type (see example).
|
||||
/// A raw space can be specified with the `space` attribute.
|
||||
///
|
||||
/// # Example
|
||||
/// ```ignore
|
||||
|
@ -24,6 +25,8 @@ use syn::{
|
|||
/// pub string_one: String,
|
||||
/// #[max_len(10, 5)]
|
||||
/// pub nested: Vec<Vec<u8>>,
|
||||
/// #[space(200)]
|
||||
/// pub string_two: String,
|
||||
/// }
|
||||
///
|
||||
/// #[derive(Accounts)]
|
||||
|
@ -35,7 +38,7 @@ use syn::{
|
|||
/// pub data: Account<'info, ExampleAccount>,
|
||||
/// }
|
||||
/// ```
|
||||
#[proc_macro_derive(InitSpace, attributes(max_len))]
|
||||
#[proc_macro_derive(InitSpace, attributes(max_len, space))]
|
||||
pub fn derive_init_space(item: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(item as DeriveInput);
|
||||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
||||
|
@ -44,10 +47,7 @@ pub fn derive_init_space(item: TokenStream) -> TokenStream {
|
|||
let expanded: TokenStream2 = match input.data {
|
||||
syn::Data::Struct(strct) => match strct.fields {
|
||||
Fields::Named(named) => {
|
||||
let recurse = named.named.into_iter().map(|f| {
|
||||
let mut max_len_args = get_max_len_args(&f.attrs);
|
||||
len_from_type(f.ty, &mut max_len_args)
|
||||
});
|
||||
let recurse = named.named.into_iter().map(get_len);
|
||||
|
||||
quote! {
|
||||
#[automatically_derived]
|
||||
|
@ -60,10 +60,7 @@ pub fn derive_init_space(item: TokenStream) -> TokenStream {
|
|||
},
|
||||
syn::Data::Enum(enm) => {
|
||||
let variants = enm.variants.into_iter().map(|v| {
|
||||
let len = v.fields.into_iter().map(|f| {
|
||||
let mut max_len_args = get_max_len_args(&f.attrs);
|
||||
len_from_type(f.ty, &mut max_len_args)
|
||||
});
|
||||
let len = v.fields.into_iter().map(get_len);
|
||||
|
||||
quote! {
|
||||
0 #(+ #len)*
|
||||
|
@ -174,21 +171,45 @@ fn parse_len_arg(item: ParseStream) -> Result<VecDeque<TokenStream2>, syn::Error
|
|||
Ok(result)
|
||||
}
|
||||
|
||||
fn get_max_len_args(attributes: &[Attribute]) -> Option<VecDeque<TokenStream2>> {
|
||||
attributes
|
||||
.iter()
|
||||
.find(|a| a.path.is_ident("max_len"))
|
||||
.and_then(|a| a.parse_args_with(parse_len_arg).ok())
|
||||
fn get_next_arg(ident: &Ident, args: &mut Option<VecDeque<TokenStream2>>) -> TokenStream2 {
|
||||
let Some(arg_list) = args else {
|
||||
return quote_spanned!(ident.span() => compile_error!("The number of lengths are invalid (Please use `#[max_len(your_len)]`)."));
|
||||
};
|
||||
|
||||
let Some(arg) = arg_list.pop_back() else {
|
||||
return quote_spanned!(ident.span() => compile_error!("Expected max_len attribute."));
|
||||
};
|
||||
|
||||
quote!(#arg)
|
||||
}
|
||||
|
||||
fn get_next_arg(ident: &Ident, args: &mut Option<VecDeque<TokenStream2>>) -> TokenStream2 {
|
||||
if let Some(arg_list) = args {
|
||||
if let Some(arg) = arg_list.pop_back() {
|
||||
quote!(#arg)
|
||||
} else {
|
||||
quote_spanned!(ident.span() => compile_error!("The number of lengths are invalid."))
|
||||
}
|
||||
fn get_len(field: Field) -> TokenStream2 {
|
||||
let mut len_attrs = field
|
||||
.attrs
|
||||
.iter()
|
||||
.filter(|a| a.path.is_ident("max_len") || a.path.is_ident("space"));
|
||||
|
||||
let Some(len_attr) = len_attrs.next() else {
|
||||
return len_from_type(field.ty, &mut None);
|
||||
};
|
||||
|
||||
if len_attrs.next().is_some() {
|
||||
return quote_spanned!(field.span() => compile_error!("Cannot have space and max_len or duplicate at the same time."));
|
||||
}
|
||||
|
||||
let mut args = len_attr.parse_args_with(parse_len_arg).ok();
|
||||
|
||||
if len_attr.path.is_ident("max_len") {
|
||||
len_from_type(field.ty, &mut args)
|
||||
} else {
|
||||
quote_spanned!(ident.span() => compile_error!("Expected max_len attribute."))
|
||||
let Some(mut space_arg) = args else {
|
||||
return quote_spanned!(field.span() => compile_error!("Can't parse the arg len token."));
|
||||
};
|
||||
|
||||
if space_arg.len() != 1 {
|
||||
return quote_spanned!(field.span() => compile_error!("Need to have only one space specified."));
|
||||
}
|
||||
|
||||
space_arg.pop_front().unwrap()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,6 +97,12 @@ pub struct TestConst {
|
|||
pub test_array: [u8; MAX_LEN as usize],
|
||||
}
|
||||
|
||||
#[derive(InitSpace)]
|
||||
pub struct RawSpace {
|
||||
#[space(100)]
|
||||
pub test_string: Vec<u8>,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_struct() {
|
||||
assert_eq!(TestEmptyAccount::INIT_SPACE, 0);
|
||||
|
@ -147,3 +153,8 @@ fn test_full_path() {
|
|||
fn test_const() {
|
||||
assert_eq!(TestConst::INIT_SPACE, (4 + 10) + 10)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_raw_space() {
|
||||
assert_eq!(RawSpace::INIT_SPACE, 100)
|
||||
}
|
||||
|
|
|
@ -174,8 +174,10 @@ export class AnchorProvider implements Provider {
|
|||
? tx.signatures?.[0] || new Uint8Array()
|
||||
: tx.signature ?? new Uint8Array()
|
||||
);
|
||||
const maxVer = isVersionedTransaction(tx) ? 0 : undefined;
|
||||
const failedTx = await this.connection.getTransaction(txSig, {
|
||||
commitment: "confirmed",
|
||||
maxSupportedTransactionVersion: maxVer,
|
||||
});
|
||||
if (!failedTx) {
|
||||
throw err;
|
||||
|
@ -256,8 +258,10 @@ export class AnchorProvider implements Provider {
|
|||
? tx.signatures?.[0] || new Uint8Array()
|
||||
: tx.signature ?? new Uint8Array()
|
||||
);
|
||||
const maxVer = isVersionedTransaction(tx) ? 0 : undefined;
|
||||
const failedTx = await this.connection.getTransaction(txSig, {
|
||||
commitment: "confirmed",
|
||||
maxSupportedTransactionVersion: maxVer,
|
||||
});
|
||||
if (!failedTx) {
|
||||
throw err;
|
||||
|
|
Loading…
Reference in New Issue