Skip to content

Commit 91c3ae6

Browse files
fix: configurables encoding to have top level u8 and bool single-byte optimizations (#1294)
ConfigurablesEncoder now present enabling top-level byte or bool single-byte optimizations needed for encoding configurables. Co-authored-by: hal3e <[email protected]>
1 parent 71c0ad0 commit 91c3ae6

File tree

5 files changed

+63
-11
lines changed

5 files changed

+63
-11
lines changed

packages/fuels-code-gen/src/program_bindings/abigen/configurables.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ fn generate_struct_decl(configurable_struct_name: &Ident) -> TokenStream {
5151
#[derive(Clone, Debug, Default)]
5252
pub struct #configurable_struct_name {
5353
offsets_with_data: ::std::vec::Vec<(u64, ::std::vec::Vec<u8>)>,
54-
encoder: ::fuels::core::codec::ABIEncoder,
54+
encoder: ::fuels::core::codec::ConfigurablesEncoder,
5555
}
5656
}
5757
}
@@ -66,7 +66,7 @@ fn generate_struct_impl(
6666
impl #configurable_struct_name {
6767
pub fn new(encoder_config: ::fuels::core::codec::EncoderConfig) -> Self {
6868
Self {
69-
encoder: ::fuels::core::codec::ABIEncoder::new(encoder_config),
69+
encoder: ::fuels::core::codec::ConfigurablesEncoder::new(encoder_config),
7070
..::std::default::Default::default()
7171
}
7272
}

packages/fuels-core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ uint = { workspace = true, default-features = false }
3232

3333
[dev-dependencies]
3434
fuels-macros = { workspace = true }
35-
tokio = { workspace = true, features = ["test-util"] }
35+
tokio = { workspace = true, features = ["test-util", "macros"] }
3636

3737
[features]
3838
default = ["std"]

packages/fuels-core/src/codec/abi_encoder.rs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,24 @@ impl ABIEncoder {
4444
/// Encodes `Token`s in `args` following the ABI specs defined
4545
/// [here](https://github.com/FuelLabs/fuel-specs/blob/master/specs/protocol/abi.md)
4646
pub fn encode(&self, args: &[Token]) -> Result<UnresolvedBytes> {
47-
BoundedEncoder::new(self.config).encode(args)
47+
BoundedEncoder::new(self.config, false).encode(args)
48+
}
49+
}
50+
51+
#[derive(Default, Clone, Debug)]
52+
pub struct ConfigurablesEncoder {
53+
pub config: EncoderConfig,
54+
}
55+
56+
impl ConfigurablesEncoder {
57+
pub fn new(config: EncoderConfig) -> Self {
58+
Self { config }
59+
}
60+
61+
/// Encodes `Token`s in `args` following the ABI specs defined
62+
/// [here](https://github.com/FuelLabs/fuel-specs/blob/master/specs/protocol/abi.md)
63+
pub fn encode(&self, args: &[Token]) -> Result<UnresolvedBytes> {
64+
BoundedEncoder::new(self.config, true).encode(args)
4865
}
4966
}
5067

@@ -1122,7 +1139,31 @@ mod tests {
11221139
.map(|fun| fun(MAX_DEPTH + 1))
11231140
.for_each(|token| {
11241141
assert_encoding_failed(config, token, &msg);
1125-
})
1142+
});
1143+
}
1144+
1145+
#[test]
1146+
fn encoder_for_configurables_optimizes_top_level_u8() {
1147+
// given
1148+
let encoder = ConfigurablesEncoder::default();
1149+
1150+
// when
1151+
let encoded = encoder.encode(&[Token::U8(255)]).unwrap().resolve(0);
1152+
1153+
// then
1154+
assert_eq!(encoded, vec![255]);
1155+
}
1156+
1157+
#[test]
1158+
fn encoder_for_configurables_optimizes_top_level_bool() {
1159+
// given
1160+
let encoder = ConfigurablesEncoder::default();
1161+
1162+
// when
1163+
let encoded = encoder.encode(&[Token::Bool(true)]).unwrap().resolve(0);
1164+
1165+
// then
1166+
assert_eq!(encoded, vec![1]);
11261167
}
11271168

11281169
fn assert_encoding_failed(config: EncoderConfig, token: Token, msg: &str) {

packages/fuels-core/src/codec/abi_encoder/bounded_encoder.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ use crate::{
1616
};
1717

1818
pub(crate) struct BoundedEncoder {
19+
used_for_configurables: bool,
1920
depth_tracker: CounterWithLimit,
2021
token_tracker: CounterWithLimit,
2122
max_total_enum_width: usize,
2223
}
2324

2425
impl BoundedEncoder {
25-
pub(crate) fn new(config: EncoderConfig) -> Self {
26+
pub(crate) fn new(config: EncoderConfig, used_for_configurables: bool) -> Self {
2627
let depth_tracker =
2728
CounterWithLimit::new(config.max_depth, "depth", CodecDirection::Encoding);
2829
let token_tracker =
@@ -31,6 +32,7 @@ impl BoundedEncoder {
3132
depth_tracker,
3233
token_tracker,
3334
max_total_enum_width: config.max_total_enum_width,
35+
used_for_configurables,
3436
}
3537
}
3638

@@ -41,8 +43,16 @@ impl BoundedEncoder {
4143
// going through the whole array of tokens, which can be pretty inefficient.
4244
let data = if args.len() == 1 {
4345
match args[0] {
44-
Token::Bool(arg_bool) => vec![Self::encode_bool_as_u64(arg_bool)],
46+
Token::U8(arg_u8) if self.used_for_configurables => {
47+
vec![Self::encode_u8_as_byte(arg_u8)]
48+
}
4549
Token::U8(arg_u8) => vec![Self::encode_u8_as_u64(arg_u8)],
50+
Token::Bool(arg_bool) if self.used_for_configurables => {
51+
vec![Self::encode_bool_as_byte(arg_bool)]
52+
}
53+
Token::Bool(arg_bool) => {
54+
vec![Self::encode_bool_as_u64(arg_bool)]
55+
}
4656
_ => self.encode_tokens(args, true)?,
4757
}
4858
} else {
@@ -56,10 +66,10 @@ impl BoundedEncoder {
5666
let mut offset_in_bytes = 0;
5767
let mut data = vec![];
5868

59-
for token in tokens.iter() {
69+
for token in tokens {
6070
self.token_tracker.increase()?;
6171
let mut new_data = self.encode_token(token)?;
62-
offset_in_bytes += new_data.iter().map(|x| x.size_in_bytes()).sum::<usize>();
72+
offset_in_bytes += new_data.iter().map(Data::size_in_bytes).sum::<usize>();
6373

6474
data.append(&mut new_data);
6575

@@ -102,7 +112,7 @@ impl BoundedEncoder {
102112
Token::U256(arg_u256) => vec![Self::encode_u256(*arg_u256)],
103113
Token::Bool(arg_bool) => vec![Self::encode_bool_as_byte(*arg_bool)],
104114
Token::B256(arg_bits256) => vec![Self::encode_b256(arg_bits256)],
105-
Token::RawSlice(data) => Self::encode_raw_slice(data.to_vec())?,
115+
Token::RawSlice(data) => Self::encode_raw_slice(data.clone())?,
106116
Token::StringSlice(arg_string) => Self::encode_string_slice(arg_string)?,
107117
Token::StringArray(arg_string) => vec![Self::encode_string_array(arg_string)?],
108118
Token::Array(arg_array) => {

packages/fuels/tests/configurables.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ async fn contract_configurables() -> Result<()> {
9494
let new_enum = EnumWithGeneric::VariantTwo;
9595

9696
let configurables = MyContractConfigurables::default()
97+
.with_U8(7)?
9798
.with_STR_4(new_str.clone())?
9899
.with_STRUCT(new_struct.clone())?
99100
.with_ENUM(new_enum.clone())?;
@@ -115,7 +116,7 @@ async fn contract_configurables() -> Result<()> {
115116
.await?;
116117

117118
let expected_value = (
118-
8u8,
119+
7u8,
119120
true,
120121
[253u32, 254u32, 255u32],
121122
new_str,

0 commit comments

Comments
 (0)