3c0d5aed73 Add get_tapscript to Witness (junderw)
4226d60205 Add Index<usize> and nth(index) to Witness (junderw)
Pull request description:
Ref: https://github.com/rust-bitcoin/rust-bitcoin/pull/672#issuecomment-980636502
[Add Index<usize> and nth(index) to Witness](4226d60205)
[4226d60](4226d60205)
Arbitrary indexing into Witness fixes the API of last and second_to_last to be more flexible.
This patch started off as an addition of third_to_last, but ended up evolving
into arbitrary indexing to allow for future use cases.
A list of the indices of the start byte for each witness element is stored as an ordered
contiguous group of u32s represented as 4 bytes each in the Vec<u8> contents.
The bytes are stored using to_ne_bytes for performance reasons. A helper function is added
to the tests to allow for easier contruction of the contents Vec in test vectors. u32 was
chosen because 22 bits are needed to store 4,000,000 which is the maximum weight limit for
a block. This might need to be reworked in the event of consensus limits increasing, but
u32 can hold 1000x the current limit, so it should be fine for the forseeable future.
The push and consensus_deserialize functions utilize rotate_left and rotate_right to move
the indices to the end of the new allocation. Depending on the size of the data, this
might be more of a performance hit than just allocating a new temporary Vec to store the
indices and append them after parsing is completed. However, for a majority of cases
rotating the indices should be faster. Suggestions to use VecDeque instead of Vec for
contents necessitate other considerations, since it is not a public facing change,
those optimizations can be dealt with in future patches.
The Index<usize> trait is implemented using the new nth method with expect.
The Iter struct is reworked to make use of the new data representation. This new data
structure makes it trivial to implement DoubleEndedIterator and other such traits, but
I have decided to leave this as out of scope for this patch.
---
[Add get_tapscript to Witness](a7501d9599)
[a7501d9](a7501d9599)
This new method will check the last witness element to see if it starts with 0x50, and
depending on the result it will return the second to last or third to last witness
element according to BIP341.
In its current state, Witness can not know what type of script it is fulfilling,
so it is up to the caller to verify if the previous output is a taproot output or not.
---
Edit: This is the previous PR body:
> In a taproot script payment with annex, quick access to the 3rd to last element (which is the actual script in this case) is convenient.
>
> This feels like kicking the can down the road again, but I think it's a nice to have method.
>
> RCasatta dr-orlovsky were discussing this issue. I would like to ask if they have any thoughts on the addition of this.
ACKs for top commit:
tcharding:
ACK 3c0d5aed73
apoelstra:
ACK 3c0d5aed73
Kixunil:
ACK 3c0d5aed73
Tree-SHA512: 0038eed6ad56786b8dd6d98db0d1846753b8b25de0bc1089cdc75d5850d0ccc66dde9a10be7fe09589ad7db118fd50ee9f7993695968df5c389457ccfcdaa761
This new method will check the last witness element to see if it starts with 0x50, and
depending on the result it will return the second to last or third to last witness
element according to BIP341.
In its current state, Witness can not know what type of script it is fulfilling,
so it is up to the caller to verify if the previous output is a taproot output or not.
Arbitrary indexing into Witness fixes the API of last and second_to_last to be more flexible.
This patch started off as an addition of third_to_last, but ended up evolving
into arbitrary indexing to allow for future use cases.
A list of the indices of the start byte for each witness element is stored as an ordered
contiguous group of u32s represented as 4 bytes each in the Vec<u8> contents.
The bytes are stored using to_ne_bytes for performance reasons. A helper function is added
to the tests to allow for easier contruction of the contents Vec in test vectors. u32 was
chosen because 22 bits are needed to store 4,000,000 which is the maximum weight limit for
a block. This might need to be reworked in the event of consensus limits increasing, but
u32 can hold 1000x the current limit, so it should be fine for the forseeable future.
The push and consensus_deserialize functions utilize rotate_left and rotate_right to move
the indices to the end of the new allocation. Depending on the size of the data, this
might be more of a performance hit than just allocating a new temporary Vec to store the
indices and append them after parsing is completed. However, for a majority of cases
rotating the indices should be faster. Suggestions to use VecDeque instead of Vec for
contents necessitate other considerations, since it is not a public facing change,
those optimizations can be dealt with in future patches.
The Index<usize> trait is implemented using the new nth method with expect.
The Iter struct is reworked to make use of the new data representation. This new data
structure makes it trivial to implement DoubleEndedIterator and other such traits, but
I have decided to leave this as out of scope for this patch.
It is considered idiomatic for types that have `iter()` method to also
implement `IntoIterator` for their references. `Witness` was missing
this so it is added here.
Done as part of the effort to flatten the `util` module.
The `sighash` module can stand alone in the crate root, it provides a
discreet set of functionality - the `SighashCache` and associated types.
Create a directory `bitcoin` and move into it the following as is with
no code changes:
- src
- Cargo.toml
- contrib
- test_data
- examples
Then do:
- Add a workspace to the repository root directory.
- Add the newly created `bitcoin` crate to the workspace.
- Exclude `fuzz` and `embedded` crates from the workspace.
- Add a contrib/test.sh script that runs contrib/test.sh in each
sub-crate
- Fix the bitcoin/contrib/test.sh script