8000 Use iterator in `blockdata::script::Instructions` by Kixunil · Pull Request #673 · rust-bitcoin/rust-bitcoin · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Use iterator in blockdata::script::Instructions #673

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

Merged
merged 5 commits into from
Apr 30, 2022

Conversation

Kixunil
Copy link
Collaborator
@Kixunil Kixunil commented Oct 2, 2021

This refactors blockdata::script::Instructions to use
::core::slice::Iter<'a, u8> instead of &'a [u8] to better express
the intention and to avoid some slicing mistakes. Similarly to a
previous change this uses a macro to deduplicate the common logic and
the new read_uint_iter internal function to automatically advance the
iterator.

Addresses:
#662 (review)

@Kixunil Kixunil force-pushed the script_instructions_iter branch from 44b3dd4 to b5d5e63 Compare October 2, 2021 19:02
Copy link
Collaborator
@dr-orlovsky dr-orlovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found few nits. Concept ACK. Need more time for careful review and to ensure that all paths are test-covered.

self.data.nth(data_len); // Kill iterator so that it does not return an infinite stream of errors
return Some(Err(Error::NonMinimalPush));
}
let ret = Some(Ok(Instruction::PushBytes(&self.data.as_slice()[..n])));
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooops, n is not bound checked here because it relies on read_uint_iter which only checks it's len. Not caught by any test but thankfully fixed with improved design.

TODO write a test for this.

@Kixunil
Copy link
Collaborator Author
Kixunil commented Oct 7, 2021

I pushed a greatly improved version, please take a look.

@Kixunil Kixunil added code quality Makes code easier to understand and less likely to lead to problems waiting for author This can only progress if the author responds to a request. labels Dec 2, 2021
@Kixunil
Copy link
Collaborator Author
Kixunil commented Feb 9, 2022

@apoelstra addressed all your comments

apoelstra
apoelstra previously approved these changes Feb 9, 2022
Copy link
Member
@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 2349362b9fa38f660a3af016093157d768cd3b7a

@Kixunil Kixunil removed the waiting for author This can only progress if the author responds to a request. label Feb 9, 2022
Copy link
Member
@tcharding tcharding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have much value to add by my review, just tried to understand what was going on.

EDIT: Oh, my minor suggestion got lost somehow during review. Here it is again, an alternate way to write one of the functions just in case you like it.

    fn take_slice_or_kill(&mut self, len: usize) -> Result<&'a [u8], Error> {
        if len == 0 {
            return Ok(&[]);
        }

        if self.data.len() < len {
            self.kill();
            return Err(Error::EarlyEndOfScript);
        }

        let slice = &self.data.as_slice()[..len];
        self.data.nth(len - 1); // Consume the sliced elements.
        Ok(slice)
    }

@Kixunil
Copy link
Collaborator Author
Kixunil commented Feb 10, 2022

@tcharding if you do understand what's going on and you didn't find any problem that is very significant value: translates to ACK :)

Your suggestion makes handling of zero more explicit but also pull is far away from the subtraction, so I'm not sure it's strictly better and frankly I'm not motivated to dismiss a review for it. But I noticed I could've written saturating_sub(1) instead so will change it if there's another stronger reason to change the code.

Copy link
Collaborator
@dr-orlovsky dr-orlovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Catched one doc inconsistency with the code

apoelstra
apoelstra previously approved these changes Mar 17, 2022
Copy link
Member
@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK af289df56dd114ab6a29f41357583b366c07d764

dr-orlovsky
dr-orlovsky previously approved these changes Mar 18, 2022
Copy link
Collaborator
@dr-orlovsky dr-orlovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK af289df56dd114ab6a29f41357583b366c07d764, but needs rebase

Kixunil and others added 4 commits April 20, 2022 19:45
This refactors `blockdata::script::Instructions` to use
`::core::slice::Iter<'a, u8>` instead of `&'a [u8]` to better express
the intention and to avoid some slicing mistakes. Similarly to a
previous change this uses a macro to deduplicate the common logic and
the new `read_uint_iter` internal function to automatically advance the
iterator.

Addresses:
rust-bitcoin#662 (review)
This creates a few primitive functions for handling iterators and uses
them to avoid repeated code. As a result not only is the code simpler
but also fixes a forgotten bound check. Thanks to a helper function
which always does bounds check correctly this can no longer be
forgotten.
* Changes `Option` to `Result` to avoid repeated `.ok_or(...)`
* Renames `max` to `min_push_len`
* Removes useless variable
Co-authored-by: Dr. Maxim Orlovsky <orlovsky@pandoracore.com>
@Kixunil Kixunil dismissed stale reviews from dr-orlovsky and apoelstra via e6ff754 April 20, 2022 17:47
@Kixunil Kixunil force-pushed the script_instructions_iter branch from af289df to e6ff754 Compare April 20, 2022 17:47
@Kixunil Kixunil added the before edition bump We want to merge this before edition is bumped label Apr 20, 2022
The code would've taken one element when an empty slice was requested.

Co-authored-by: Tobin C. Harding <me@tobin.cc>
Copy link
Member
@tcharding tcharding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 2c28d3b

Thanks for the co-authored-by!

Copy link
Member
@sanket1729 sanket1729 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 2c28d3b. I don't want to hold ACKs on minor things as they can be in a fixup later.

return Some(Err(Error::EarlyEndOfScript));
}
if self.enforce_minimal {
if n == 1 && (self.data[1] == 0x81 || (self.data[1] > 0 && self.data[1] <= 16)) {
self.data = &[];
// index acceess is safe because we checked the lenght above
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:
s/lenght/length

Some(Ok(Instruction::PushBytes(&[])))
},
_ => {
Some(self.take_slice_or_kill(n).map(Instruction::PushBytes).ok_or(Error::EarlyEndOfScript))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self and other reviewers: There is no need to check enforce_minimal on 0 bytes as there is only one possible value (vec![])

let data_len = self.data.len();
self.data.nth(data_len); // Kill iterator so that it does not return an infinite stream of errors
return Some(Err(Error::NonMinimalPush));
let op_byte = self.data.as_slice().first();
Copy link
Member
@sanket1729 sanket1729 Apr 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:
This is not the op_byte. This is more like first_byte and we are checking first_byte is not equal to op_byte?

    fn next(&mut self) -> Option<Result<Instruction<'a>, Error>> {
        let &byte = self.data.next()?; // this should be op_byte

@Kixunil
Copy link
Collaborator Author
Kixunil commented Apr 22, 2022

OK, will try to make fixup PR. @tcharding "co-authored by" is inserted by GitHub, I don't mind. :)

@Kixunil Kixunil added this to the 0.29.0 milestone Apr 25, 2022
@sanket1729
Copy link
Member

Merging this based on

  • My and @tcharding's ACKs on tip.
  • @apoelstra's and @dr-orlovsky's previous ACKs and reviewing the minor range diff which was some whitspaces and the last commit.

@sanket1729 sanket1729 merged commit d5a28fc into rust-bitcoin:master Apr 30, 2022
@Kixunil Kixunil deleted the script_instructions_iter branch May 2, 2022 12:05
ChallengeDev210 pushed a commit to ChallengeDev210/rust-bitcoin that referenced this pull request Aug 1, 2022
…pt::Instructions`

2c28d3b Fix handling of empty slice in Instructions (Martin Habovštiak)
e6ff754 Fix doc of take_slice_or_kill (Martin Habovštiak)
0ec6d96 Cleanup after `Instructions` refactoring (Martin Habovstiak)
bc76325 Move repeated code to functions in script (Martin Habovstiak)
1f55edf Use iterator in `blockdata::script::Instructions` (Martin Habovstiak)

Pull request description:

  This refactors `blockdata::script::Instructions` to use
  `::core::slice::Iter<'a, u8>` instead of `&'a [u8]` to better express
  the intention and to avoid some slicing mistakes. Similarly to a
  previous change this uses a macro to deduplicate the common logic and
  the new `read_uint_iter` internal function to automatically advance the
  iterator.

  Addresses:
  rust-bitcoin/rust-bitcoin#662 (review)

ACKs for top commit:
  tcharding:
    ACK 2c28d3b
  sanket1729:
    ACK 2c28d3b. I don't want to hold ACKs on minor things as they can be in a fixup later.

Tree-SHA512: 9dc770b9f7958efbd0df2cc2d3546e23deca5df2f94ea2c42b089df628f4b99f08032ca4aa8822caf6643a8892903e1bda41228b78c8519b90bcaa1255d9acc6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
before edition bump We want to merge this before edition is bumped code quality Makes code easier to understand and less likely to lead to problems
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants
0