Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix!: encoding capacity overflow #1249

Merged
merged 49 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
1c3f876
fix overflow in encoding
iqdecay Dec 8, 2023
76d4232
Merge branch 'master' into iqdecay/fix-decoding-add-overflow
iqdecay Dec 12, 2023
7f15dc5
test: fix test message
iqdecay Dec 12, 2023
e0aac07
improve using code review suggestions
iqdecay Dec 12, 2023
bffdcfc
Merge branch 'master' into iqdecay/fix-decoding-add-overflow
MujkicA Dec 13, 2023
ccc0d24
refactor: apply code review suggestions
iqdecay Dec 15, 2023
56c6e68
Merge branch 'master' into iqdecay/fix-decoding-add-overflow
iqdecay Dec 15, 2023
3e6e4c9
Merge branch 'master' into iqdecay/fix-decoding-add-overflow
MujkicA Dec 18, 2023
dece654
Merge branch 'master' into iqdecay/fix-decoding-add-overflow
digorithm Dec 19, 2023
0678b34
Merge branch 'master' into iqdecay/fix-decoding-add-overflow
iqdecay Jan 8, 2024
722a5f0
showing that the fuzzing is right
iqdecay Dec 10, 2023
af463bf
refactor: move `CounterWithLimit` to utils file
iqdecay Jan 6, 2024
a70e0b8
rename file
iqdecay Jan 6, 2024
041a64d
add and use `EncoderConfig`
iqdecay Jan 14, 2024
0fc79c5
Merge branch 'master' into iqdecay/fix-encoding-capacity-overflow
iqdecay Jan 14, 2024
8788556
style: appease clippy and all formatting gods
iqdecay Jan 14, 2024
b3113d4
style: appease clippy and all formatting gods
iqdecay Jan 14, 2024
7e69f27
Merge branch 'master' into iqdecay/fix-encoding-capacity-overflow
iqdecay Jan 15, 2024
7629272
update max memory to fit in usize on wasm
iqdecay Jan 15, 2024
498c111
Merge branch 'master' into iqdecay/fix-encoding-capacity-overflow
hal3e Jan 17, 2024
e744df5
refactor: use Enum instead of bool for codec direction
iqdecay Jan 19, 2024
8361706
style: appease clippy and all formatting gods
iqdecay Jan 19, 2024
026bc2e
fix enum serialization
iqdecay Jan 19, 2024
f3e66a7
Merge branch 'master' into iqdecay/fix-encoding-capacity-overflow
iqdecay Jan 22, 2024
aaac47f
Merge branch 'master' into iqdecay/fix-encoding-capacity-overflow
digorithm Jan 24, 2024
3163e06
Merge branch 'master' into iqdecay/fix-encoding-capacity-overflow
hal3e Jan 25, 2024
13132c9
Update packages/fuels-core/src/codec/abi_encoder.rs
iqdecay Jan 30, 2024
b8efe9a
apply PR review comments
iqdecay Jan 30, 2024
56ac0f1
Merge branch 'master' into iqdecay/fix-encoding-capacity-overflow
iqdecay Jan 30, 2024
60529de
style: appease clippy and all formatting gods
iqdecay Jan 30, 2024
c392105
Update docs/src/codec/encoding.md
iqdecay Feb 1, 2024
52c2760
Update examples/codec/src/lib.rs
iqdecay Feb 1, 2024
d4d1986
Apply suggestions from code review
iqdecay Feb 1, 2024
8c65eba
apply code review suggestions
iqdecay Feb 1, 2024
3a8a5d0
fix things
iqdecay Feb 1, 2024
62d99bc
Merge branch 'master' into iqdecay/fix-encoding-capacity-overflow
iqdecay Feb 5, 2024
1a6ef27
add back make_fn_associated
iqdecay Feb 2, 2024
d581e56
fix error handling
iqdecay Feb 6, 2024
caca0af
update error message
iqdecay Feb 6, 2024
6900595
style: appease clippy and all formatting gods
iqdecay Feb 6, 2024
db0d528
apply suggestion
iqdecay Feb 7, 2024
94df9ed
Merge branch 'master' into iqdecay/fix-encoding-capacity-overflow
hal3e Feb 7, 2024
369ccbf
use interpolation
iqdecay Feb 7, 2024
5b89cd4
apply suggestions
iqdecay Feb 9, 2024
1bc2e63
do not return result
iqdecay Feb 12, 2024
28c4a5c
ebrst
iqdecay Feb 12, 2024
4f8b539
Update docs/src/codec/encoding.md
iqdecay Feb 12, 2024
bbf59f1
Merge branch 'master' into iqdecay/fix-encoding-capacity-overflow
iqdecay Feb 12, 2024
f6709bc
Update packages/fuels-code-gen/src/program_bindings/abigen/configurab…
iqdecay Feb 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/src/calling-contracts/low-level-calls.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,5 @@ you would construct the function selector and the calldata as such, and provide
```rust,ignore
{{#include ../../../examples/contracts/src/lib.rs:low_level_call}}
```

> Note: the `calldata!` macro uses the default `EncoderConfig` configuration under the hood.
24 changes: 24 additions & 0 deletions docs/src/codec/encoding.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,27 @@ There is also a shortcut-macro that can encode multiple types which implement [`

> Note:
> The above example will call `.resolve(0)`. Don't use it if you're encoding heap types.

## Configuring the encoder

The encoder can be configured to limit its resource expenditure:

```rust,ignore
{{#include ../../../examples/codec/src/lib.rs:configuring_the_encoder}}
```

The default values for the `EncoderConfig` are:

```rust,ignore
{{#include ../../../packages/fuels-core/src/codec/abi_encoder.rs:default_encoder_config}}
```

## Configuring the encoder for contract/script calls

You can also configure the encoder used to encode the arguments of the contract method:

```rust,ignore
{{#include ../../../examples/contracts/src/lib.rs:contract_encoder_config}}
```

The same method is available for script calls.
22 changes: 20 additions & 2 deletions examples/codec/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#[cfg(test)]
mod tests {
use fuels::{core::codec::DecoderConfig, types::errors::Result};
use fuels::{
core::codec::{DecoderConfig, EncoderConfig},
types::errors::Result,
};

#[test]
fn encoding_a_type() -> Result<()> {
Expand All @@ -17,7 +20,7 @@ mod tests {
}

let instance = MyStruct { field: 101 };
let encoded: UnresolvedBytes = ABIEncoder::encode(&[instance.into_token()])?;
let encoded: UnresolvedBytes = ABIEncoder::default().encode(&[instance.into_token()])?;
let load_memory_address: u64 = 0x100;
let _: Vec<u8> = encoded.resolve(load_memory_address);
//ANCHOR_END: encoding_example
Expand Down Expand Up @@ -98,4 +101,19 @@ mod tests {

Ok(())
}

#[test]
fn configuring_the_encoder() -> Result<()> {
// ANCHOR: configuring_the_encoder
use fuels::core::codec::ABIEncoder;

ABIEncoder::new(EncoderConfig {
max_depth: 5,
max_tokens: 100,
max_total_enum_width: 10_000,
});
// ANCHOR_END: configuring_the_encoder

Ok(())
}
}
38 changes: 36 additions & 2 deletions examples/contracts/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#[cfg(test)]
mod tests {
use fuels::core::codec::EncoderConfig;
use fuels::{
core::codec::DecoderConfig,
prelude::{Config, LoadConfiguration, StorageConfiguration},
Expand Down Expand Up @@ -677,7 +678,7 @@ mod tests {

// Perform contract call with wallet_2
let response = contract_instance
.with_account(wallet_2)? // Connect wallet_2
.with_account(wallet_2) // Connect wallet_2
.methods() // Get contract methods
.get_msg_amount() // Our contract method
.call() // Perform the contract call.
Expand Down Expand Up @@ -830,7 +831,7 @@ mod tests {
.initialize_counter(42)
.with_decoder_config(DecoderConfig {
max_depth: 10,
max_tokens: 20_00,
max_tokens: 2_000,
})
.call()
.await?;
Expand Down Expand Up @@ -910,4 +911,37 @@ mod tests {

Ok(())
}

#[tokio::test]
async fn configure_encoder_config() -> Result<()> {
use fuels::prelude::*;

setup_program_test!(
Wallets("wallet"),
Abigen(Contract(
name = "MyContract",
project = "packages/fuels/tests/contracts/contract_test"
)),
Deploy(
name = "contract_instance",
contract = "MyContract",
wallet = "wallet"
)
);

// ANCHOR: contract_encoder_config
let _ = contract_instance
.with_encoder_config(EncoderConfig {
max_depth: 10,
max_tokens: 2_000,
max_total_enum_width: 10_000,
})
.methods()
.initialize_counter(42)
.call()
.await?;
// ANCHOR_END: contract_encoder_config

Ok(())
}
}
4 changes: 2 additions & 2 deletions examples/predicates/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ mod tests {
abi = "packages/fuels/tests/predicates/signatures/out/debug/signatures-abi.json"
));

let predicate_data = MyPredicateEncoder::encode_data(signatures);
let predicate_data = MyPredicateEncoder::default().encode_data(signatures)?;
let code_path = "../../packages/fuels/tests/predicates/signatures/out/debug/signatures.bin";

let predicate: Predicate = Predicate::load_from(code_path)?
Expand Down Expand Up @@ -134,7 +134,7 @@ mod tests {
// ANCHOR_END: predicate_data_setup

// ANCHOR: with_predicate_data
let predicate_data = MyPredicateEncoder::encode_data(4096, 4096);
let predicate_data = MyPredicateEncoder::default().encode_data(4096, 4096)?;
let code_path =
"../../packages/fuels/tests/predicates/basic_predicate/out/debug/basic_predicate.bin";

Expand Down
11 changes: 5 additions & 6 deletions examples/rust_bindings/src/rust_bindings_formatted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ pub mod abigen_bindings {
pub fn account(&self) -> T {
self.account.clone()
}
pub fn with_account<U: Account>(&self, account: U) -> Result<MyContract<U>> {
::core::result::Result::Ok(MyContract {
pub fn with_account<U: Account>(&self, account: U) -> MyContract<U> {
MyContract {
contract_id: self.contract_id.clone(),
account,
log_decoder: self.log_decoder.clone(),
})
}
}
pub async fn get_balances(&self) -> Result<::std::collections::HashMap<AssetId, u64>> {
ViewOnlyAccount::try_provider(&self.account)?
Expand Down Expand Up @@ -77,8 +77,8 @@ pub mod abigen_bindings {
&[Tokenizable::into_token(value)],
self.log_decoder.clone(),
false,
ABIEncoder::new(EncoderConfig::default()),
)
.expect("method not found (this should never happen)")
}
#[doc = "Calls the contract's `increment_counter` function"]
pub fn increment_counter(&self, value: u64) -> ContractCallHandler<T, u64> {
Expand All @@ -89,8 +89,8 @@ pub mod abigen_bindings {
&[value.into_token()],
self.log_decoder.clone(),
false,
ABIEncoder::new(EncoderConfig::default()),
)
.expect("method not found (this should never happen)")
}
}
impl<T: Account> contract::SettableContract for MyContract<T> {
Expand Down Expand Up @@ -120,4 +120,3 @@ pub mod abigen_bindings {
pub use abigen_bindings::my_contract_mod::MyContract;
pub use abigen_bindings::my_contract_mod::MyContractConfigurables;
pub use abigen_bindings::my_contract_mod::MyContractMethods;

Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,12 @@ pub(crate) fn contract_bindings(
generate_code_for_configurable_constants(&configuration_struct_name, &abi.configurables)?;

let code = quote! {
#[derive(Debug, Clone)]
pub struct #name<T: ::fuels::accounts::Account> {
contract_id: ::fuels::types::bech32::Bech32ContractId,
account: T,
log_decoder: ::fuels::core::codec::LogDecoder
log_decoder: ::fuels::core::codec::LogDecoder,
encoder_config: ::fuels::core::codec::EncoderConfig,
}

impl<T: ::fuels::accounts::Account> #name<T>
Expand All @@ -51,7 +53,8 @@ pub(crate) fn contract_bindings(
) -> Self {
let contract_id: ::fuels::types::bech32::Bech32ContractId = contract_id.into();
let log_decoder = ::fuels::core::codec::LogDecoder::new(#log_formatters);
Self { contract_id, account, log_decoder }
let encoder_config = ::fuels::core::codec::EncoderConfig::default();
Self { contract_id, account, log_decoder, encoder_config }
}

pub fn contract_id(&self) -> &::fuels::types::bech32::Bech32ContractId {
Expand All @@ -62,8 +65,21 @@ pub(crate) fn contract_bindings(
self.account.clone()
}

pub fn with_account<U: ::fuels::accounts::Account>(&self, account: U) -> ::fuels::types::errors::Result<#name<U>> {
::core::result::Result::Ok(#name { contract_id: self.contract_id.clone(), account, log_decoder: self.log_decoder.clone()})
pub fn with_account<U: ::fuels::accounts::Account>(self, account: U)
-> #name<U> {
#name {
contract_id: self.contract_id,
account,
log_decoder: self.log_decoder,
encoder_config: self.encoder_config
}
}

pub fn with_encoder_config(mut self, encoder_config: ::fuels::core::codec::EncoderConfig)
-> #name::<T> {
self.encoder_config = encoder_config;

self
}

pub async fn get_balances(&self) -> ::fuels::types::errors::Result<::std::collections::HashMap<::fuels::types::AssetId, u64>> {
Expand All @@ -77,7 +93,8 @@ pub(crate) fn contract_bindings(
#methods_name {
contract_id: self.contract_id.clone(),
account: self.account.clone(),
log_decoder: self.log_decoder.clone()
log_decoder: self.log_decoder.clone(),
encoder_config: self.encoder_config.clone(),
}
}
}
Expand All @@ -86,7 +103,8 @@ pub(crate) fn contract_bindings(
pub struct #methods_name<T: ::fuels::accounts::Account> {
contract_id: ::fuels::types::bech32::Bech32ContractId,
account: T,
log_decoder: ::fuels::core::codec::LogDecoder
log_decoder: ::fuels::core::codec::LogDecoder,
encoder_config: ::fuels::core::codec::EncoderConfig,
}

impl<T: ::fuels::accounts::Account> #methods_name<T> {
Expand Down Expand Up @@ -157,8 +175,8 @@ pub(crate) fn expand_fn(abi_fun: &FullABIFunction) -> Result<TokenStream> {
&#arg_tokens,
self.log_decoder.clone(),
#is_payable,
self.encoder_config.clone(),
)
.expect("method not found (this should never happen)")
};
generator.set_body(body);

Expand Down Expand Up @@ -355,8 +373,8 @@ mod tests {
],
self.log_decoder.clone(),
false,
self.encoder_config.clone(),
)
.expect("method not found (this should never happen)")
}
};

Expand Down Expand Up @@ -411,8 +429,8 @@ mod tests {
&[::fuels::core::traits::Tokenizable::into_token(bimbam)],
self.log_decoder.clone(),
false,
self.encoder_config.clone(),
)
.expect("method not found (this should never happen)")
}
};

Expand Down Expand Up @@ -523,8 +541,8 @@ mod tests {
)],
self.log_decoder.clone(),
false,
self.encoder_config.clone(),
)
.expect("method not found (this should never happen)")
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ pub(crate) struct FunctionGenerator {
output_type: TokenStream,
body: TokenStream,
doc: Option<String>,
is_method: bool,
}

impl FunctionGenerator {
Expand All @@ -38,7 +37,6 @@ impl FunctionGenerator {
output_type: output_type.to_token_stream(),
body: Default::default(),
doc: None,
is_method: true,
})
}

Expand All @@ -47,11 +45,6 @@ impl FunctionGenerator {
self
}

pub fn make_fn_associated(&mut self) -> &mut Self {
self.is_method = false;
self
}

pub fn set_body(&mut self, body: TokenStream) -> &mut Self {
self.body = body;
self
Expand Down Expand Up @@ -110,9 +103,7 @@ impl FunctionGenerator {
let output_type = self.output_type();
let body = &self.body;

let self_param = self.is_method.then_some(quote! {&self,});

let params = quote! { #self_param #(#arg_declarations),* };
let params = quote! { &self, #(#arg_declarations),* };

quote! {
#doc
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,19 @@ pub(crate) fn predicate_bindings(
generate_code_for_configurable_constants(&configuration_struct_name, &abi.configurables)?;

let code = quote! {
pub struct #encoder_struct_name;
#[derive(Default)]
pub struct #encoder_struct_name{
encoder: ::fuels::core::codec::ABIEncoder,
}

impl #encoder_struct_name {
#encode_function

pub fn new(encoder_config: ::fuels::core::codec::EncoderConfig) -> Self {
Self {
encoder: ::fuels::core::codec::ABIEncoder::new(encoder_config)
}
}
}

#constant_configuration_code
Expand All @@ -51,14 +60,16 @@ fn expand_fn(abi: &FullProgramABI) -> Result<TokenStream> {
let arg_tokens = generator.tokenized_args();

let body = quote! {
::fuels::core::codec::ABIEncoder::encode(&#arg_tokens).expect("Cannot encode predicate data")
self.encoder.encode(&#arg_tokens)
};
let output_type = quote! {
::fuels::types::errors::Result<::fuels::types::unresolved_bytes::UnresolvedBytes>
};

generator
.set_doc("Run the predicate's encode function with the provided arguments".to_string())
.set_name("encode_data".to_string())
.set_output_type(quote! { ::fuels::types::unresolved_bytes::UnresolvedBytes})
.make_fn_associated()
.set_output_type(output_type)
.set_body(body);

Ok(generator.generate())
Expand Down
Loading
Loading