Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR extends the Steel IDL detection heuristic in
Confidence Score: 4/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Deserialize JSON to serde_json::Value] --> B{instructions array present\nand non-empty?}
B -- No --> Z[discriminant_size = 8\nDefault / Anchor]
B -- Yes --> C[For each instruction .all]
C --> D{has 'discriminant' key?}
D -- Yes --> E{has non-empty 'discriminator'?}
E -- No --> F[is_steel_discriminant = true\nVariant 1 - explicit discriminant field]
E -- Yes --> G[is_steel_discriminant = false]
D -- No --> H{disc_len == 1?}
H -- Yes --> I[is_steel_short_discriminator = true\nVariant 2 - 1-byte array NEW]
H -- No --> J[is_steel_short_discriminator = false]
F --> K{is_steel_discriminant OR\nis_steel_short_discriminator?}
G --> K
I --> K
J --> K
K -- all true --> L[discriminant_size = 1\nSteel-style]
K -- any false --> Z
Prompt To Fix All With AIThis is a comment left during a code review.
Path: hyperstack-idl/src/snapshot.rs
Line: 56-62
Comment:
**No tests added for new detection variant**
The new `is_steel_short_discriminator` branch is the only untested code path in this file. The existing test in `test_snapshot_serde` uses an 8-byte discriminator and a `null` discriminant, which exercises neither variant 1 nor variant 2 of the Steel detection through the custom `Deserialize` impl (since the round-trip test bypasses raw JSON parsing of this heuristic).
A dedicated test like the following should be added to verify that the detection works end-to-end:
```rust
#[test]
fn test_steel_short_discriminator_detection() {
let json = r#"{
"name": "test_program",
"version": "0.1.0",
"accounts": [],
"instructions": [
{
"name": "my_ix",
"discriminator": [42],
"accounts": [],
"args": []
}
],
"types": [],
"events": [],
"errors": []
}"#;
let snapshot: IdlSnapshot = serde_json::from_str(json).expect("deserialize");
assert_eq!(snapshot.discriminant_size, 1);
}
```
Without this, a regression that breaks variant 2 detection would go unnoticed.
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: hyperstack-idl/src/snapshot.rs
Line: 60
Comment:
**Heuristic may conflict with `get_discriminator()` for 1-byte arrays**
When `is_steel_short_discriminator` is true, `discriminant_size` is set to `1`. Inside `get_discriminator()` (line 187), if `self.discriminator` is non-empty (e.g., `[42]`), it is returned as-is — so the returned `Vec<u8>` has length 1.
However, if any downstream consumer validates `get_discriminator().len() == discriminant_size` or slices transaction bytes using `discriminant_size`, the 1-byte vec returned for variant 2 is consistent with `discriminant_size == 1`. This is fine as long as all consumers are aligned.
The subtle risk is: if a program has a mix of instructions — some satisfying variant 1 (`is_steel_discriminant`) and others variant 2 (`is_steel_short_discriminator`) — the `.all()` still resolves to `true` and `discriminant_size` becomes `1`. In that case, variant-1 instructions (which have no `discriminator` array at all, so `self.discriminator` is empty) fall through to `get_discriminator()`'s `discriminant` branch and return a 1-byte vec, which remains consistent. Mixed programs appear safe, but the interaction is non-obvious and worth a comment.
How can I resolve this? If you propose a fix, please make it concise.Last reviewed commit: "fix: Improve Steel I..." |
| // Steel-style variant 2: discriminator is stored as a 1-byte array (no | ||
| // discriminant field). This happens when the AST was generated from a | ||
| // Steel IDL that serialised its u8 discriminant directly into the | ||
| // discriminator field. | ||
| let is_steel_short_discriminator = !has_discriminant && disc_len == 1; | ||
|
|
||
| is_steel_discriminant || is_steel_short_discriminator |
There was a problem hiding this comment.
No tests added for new detection variant
The new is_steel_short_discriminator branch is the only untested code path in this file. The existing test in test_snapshot_serde uses an 8-byte discriminator and a null discriminant, which exercises neither variant 1 nor variant 2 of the Steel detection through the custom Deserialize impl (since the round-trip test bypasses raw JSON parsing of this heuristic).
A dedicated test like the following should be added to verify that the detection works end-to-end:
#[test]
fn test_steel_short_discriminator_detection() {
let json = r#"{
"name": "test_program",
"version": "0.1.0",
"accounts": [],
"instructions": [
{
"name": "my_ix",
"discriminator": [42],
"accounts": [],
"args": []
}
],
"types": [],
"events": [],
"errors": []
}"#;
let snapshot: IdlSnapshot = serde_json::from_str(json).expect("deserialize");
assert_eq!(snapshot.discriminant_size, 1);
}Without this, a regression that breaks variant 2 detection would go unnoticed.
Prompt To Fix With AI
This is a comment left during a code review.
Path: hyperstack-idl/src/snapshot.rs
Line: 56-62
Comment:
**No tests added for new detection variant**
The new `is_steel_short_discriminator` branch is the only untested code path in this file. The existing test in `test_snapshot_serde` uses an 8-byte discriminator and a `null` discriminant, which exercises neither variant 1 nor variant 2 of the Steel detection through the custom `Deserialize` impl (since the round-trip test bypasses raw JSON parsing of this heuristic).
A dedicated test like the following should be added to verify that the detection works end-to-end:
```rust
#[test]
fn test_steel_short_discriminator_detection() {
let json = r#"{
"name": "test_program",
"version": "0.1.0",
"accounts": [],
"instructions": [
{
"name": "my_ix",
"discriminator": [42],
"accounts": [],
"args": []
}
],
"types": [],
"events": [],
"errors": []
}"#;
let snapshot: IdlSnapshot = serde_json::from_str(json).expect("deserialize");
assert_eq!(snapshot.discriminant_size, 1);
}
```
Without this, a regression that breaks variant 2 detection would go unnoticed.
How can I resolve this? If you propose a fix, please make it concise.| // discriminant field). This happens when the AST was generated from a | ||
| // Steel IDL that serialised its u8 discriminant directly into the | ||
| // discriminator field. | ||
| let is_steel_short_discriminator = !has_discriminant && disc_len == 1; |
There was a problem hiding this comment.
Heuristic may conflict with
get_discriminator() for 1-byte arrays
When is_steel_short_discriminator is true, discriminant_size is set to 1. Inside get_discriminator() (line 187), if self.discriminator is non-empty (e.g., [42]), it is returned as-is — so the returned Vec<u8> has length 1.
However, if any downstream consumer validates get_discriminator().len() == discriminant_size or slices transaction bytes using discriminant_size, the 1-byte vec returned for variant 2 is consistent with discriminant_size == 1. This is fine as long as all consumers are aligned.
The subtle risk is: if a program has a mix of instructions — some satisfying variant 1 (is_steel_discriminant) and others variant 2 (is_steel_short_discriminator) — the .all() still resolves to true and discriminant_size becomes 1. In that case, variant-1 instructions (which have no discriminator array at all, so self.discriminator is empty) fall through to get_discriminator()'s discriminant branch and return a 1-byte vec, which remains consistent. Mixed programs appear safe, but the interaction is non-obvious and worth a comment.
Prompt To Fix With AI
This is a comment left during a code review.
Path: hyperstack-idl/src/snapshot.rs
Line: 60
Comment:
**Heuristic may conflict with `get_discriminator()` for 1-byte arrays**
When `is_steel_short_discriminator` is true, `discriminant_size` is set to `1`. Inside `get_discriminator()` (line 187), if `self.discriminator` is non-empty (e.g., `[42]`), it is returned as-is — so the returned `Vec<u8>` has length 1.
However, if any downstream consumer validates `get_discriminator().len() == discriminant_size` or slices transaction bytes using `discriminant_size`, the 1-byte vec returned for variant 2 is consistent with `discriminant_size == 1`. This is fine as long as all consumers are aligned.
The subtle risk is: if a program has a mix of instructions — some satisfying variant 1 (`is_steel_discriminant`) and others variant 2 (`is_steel_short_discriminator`) — the `.all()` still resolves to `true` and `discriminant_size` becomes `1`. In that case, variant-1 instructions (which have no `discriminator` array at all, so `self.discriminator` is empty) fall through to `get_discriminator()`'s `discriminant` branch and return a 1-byte vec, which remains consistent. Mixed programs appear safe, but the interaction is non-obvious and worth a comment.
How can I resolve this? If you propose a fix, please make it concise.
No description provided.