-
Notifications
You must be signed in to change notification settings - Fork 139
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
Upgrade bitcoin dependency to v0.29.0 #450
Upgrade bitcoin dependency to v0.29.0 #450
Conversation
a373def
to
084bb97
Compare
084bb97
to
c525f53
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found a few mistakes. Disclaimer: didn't do super-deep review.
src/descriptor/tr.rs
Outdated
@@ -257,6 +257,7 @@ impl<Pk: MiniscriptKey> Tr<Pk> { | |||
TaprootBuilderError::EmptyTree => { | |||
unreachable!("Taptree is a well formed tree with atleast 1 element") | |||
} | |||
_ => unreachable!("non_exhaustive catchall"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually wrong, a new variant could be added for any reason. To correctly handle the error it needs to be returned.
If this is too much hassle maybe we should improve the API or perhaps commit to never changing TaprootBuilderError
and remove #[non_exhaustive]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This whole error match is strange, every error variant has an unreachable!
. To be honest I was mainly just interested in checking that rust-bitcoin
worked so I just hacked this up to make it build.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They have explanation why it should be OK, so I think it's fine. But it makes me question the whole API. Maybe we should've used typestate instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will make a cleanup PR to upstream to cleanup this API
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fixed now, please check my use of a single unreachable
statement @sanket1729
}, | ||
///Absolute Timelock for CLTV. | ||
AbsoluteTimelock { | ||
/// The value of Absolute timelock | ||
time: u32, | ||
n: LockTime, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
time
was definitely a better name than n
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its a block height or a block time. n
is from n OP_CLTV
and nLockTime
- that's why I used n
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
n
in nLockTime
literally means number. It's meaningless. I do see that time
is confusing, so lock_time
would be better because most people already know it can be height.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Used lock_time
for this field and similarly sequence
for SatisfiedConstraint::RelativeTimelock
field.
fn index(&self, index: I) -> &Self::Output { | ||
&self.0[index] | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't Hash
impl Deref
? if it does this shouldn't be needed at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added this because of the trait bounds on Hash
trait (from bitcoin_consensus
). Deref
doesn't help with that, right? Or am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see any Hash
trait in bitcoin_consensus
, I guess you mean bitcoin_hashes
. You're right that Deref
doesn't help but it's a question if that bound should be there since it's quite burdensome. I'd have to look into it deeper. The first check is will anything break if we remove it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll investigate this, cheers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see: rust-bitcoin/bitcoin_hashes#168
@@ -820,16 +821,16 @@ impl Property for Type { | |||
// Note that for CLTV this is a limitation not of Bitcoin but Miniscript. The | |||
// number on the stack would be a 5 bytes signed integer but Miniscript's B type | |||
// only consumes 4 bytes from the stack. | |||
if t == 0 || (t & SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0 { | |||
if t == PackedLockTime::ZERO { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did the code originally attempt to check if lock times are actually enabled or something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Originally both sequnece and locktime (After
and Older
) where handled together. When I split them apart I kept the disable check even though it seemed wrong, finally I got the confidence to remove it :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not just after vs older -- the original code would look at a u32
which might contain a value that didn't encode any locktime at all.
It's not clear to me that this check can be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No worries, since this PR is not a merge candidate this bridge doesn't need crossing now. I imagine between @apoelstra and @sanket1729 this will have to be worked out when miniscript upgrades to use rust-bitcoin 0.29.0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Flagging this thread, this will need resolving before we can consider upgrading to the newly release version of rust-bitcoin
. Sorry to be a drag but I think this is kind of subtle and will need input by @sanket1729 and/or @apoelstra to work it out. I can code up the solution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel confident that removing this check is correct. This was just checking something else entirely which was wrong.
This was checking a check on sequence values in script which has no constraints. The only constraint we have is on transaction's sequence, which is different from checking the number encoded in script.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@apoelstra are you convinced that this is resolved?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me re-read this PR.
c525f53
to
06ae8b7
Compare
Thanks for the review @Kixunil! |
06ae8b7
to
d73f5e3
Compare
870ad59 Rename is_finalized to is_finalizable (sanket1729) aaadd25 Add breaking test that allowed incomplete builders to be created (sanket1729) 0b88051 Update TaprootBuilder::finalize (sanket1729) 5813ec7 Return EmptyTree instead of OverCompleteTree when there are no scripts to add (sanket1729) Pull request description: Found while reviewing rust-bitcoin/rust-miniscript#450 . There is also a BUG fix in the second commit that would have let users spendinfo from incomplete trees. The bug was introduced in #936 which I am responsible for ACKing ACKs for top commit: apoelstra: ACK 870ad59 Kixunil: ACK 870ad59 tcharding: ACK 870ad59 Tree-SHA512: 61442bd95df6912865cbecdc207f330b241e7fbb88b5e915243b2b48a756bea9eb29cb28d8c8249647a0a2ac514df4737bddab695f63075bd55284be5be228ff
870ad59 Rename is_finalized to is_finalizable (sanket1729) aaadd25 Add breaking test that allowed incomplete builders to be created (sanket1729) 0b88051 Update TaprootBuilder::finalize (sanket1729) 5813ec7 Return EmptyTree instead of OverCompleteTree when there are no scripts to add (sanket1729) Pull request description: Found while reviewing rust-bitcoin/rust-miniscript#450 . There is also a BUG fix in the second commit that would have let users spendinfo from incomplete trees. The bug was introduced in #936 which I am responsible for ACKing ACKs for top commit: apoelstra: ACK 870ad59 Kixunil: ACK 870ad59 tcharding: ACK 870ad59 Tree-SHA512: 61442bd95df6912865cbecdc207f330b241e7fbb88b5e915243b2b48a756bea9eb29cb28d8c8249647a0a2ac514df4737bddab695f63075bd55284be5be228ff
110b5d8 Bump version to v0.29.0 (Tobin C. Harding) Pull request description: Add changelog notes and bump the version number to v0.29.0. ## Notes I attempted to go through all the PRs since last release, please sing out if you had a PR merged that is not mentioned and you would like it mentioned. The changelog notes can be changed or improved, please do not take me writing them to imply I know exactly what goes on round here - I just made an effort to save others having to do it. ## TODO - [x] merge all 'required' PRs - #1131 - #1137 - #1129 - #1151 - #1165 (add release notes still) - [x] Ensure all green from the CI run on: rust-bitcoin/rust-miniscript#450 - [ ] Carry out (and improve) the #1106 ACKs for top commit: tcharding: ACK 110b5d8 Kixunil: ACK 110b5d8 apoelstra: ACK 110b5d8 sanket1729: reACK 110b5d8 Tree-SHA512: d00c70534476794c01cd694ea9a23affef947c4f913b14344405272bc99cc00763f1ac755cc677e7afbd3dbef573d786251c9093d5dbafd76ee0cf86ca3b0ebd
d73f5e3
to
05c5637
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly ACK. did a round of careful review. Just waiting on reply for comparison FIXME comment
src/miniscript/astelem.rs
Outdated
@@ -620,9 +621,11 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> { | |||
.push_slice(&Pk::hash_to_hash160(hash)[..]) | |||
.push_opcode(opcodes::all::OP_EQUALVERIFY), | |||
Terminal::After(t) => builder | |||
.push_int(t as i64) | |||
.push_int(t.0.into()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit(here and elsewhere): slightly prefer to use t.to_u32()
over t.0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I changed them all.
@@ -437,16 +438,16 @@ pub trait Property: Sized { | |||
// Note that for CLTV this is a limitation not of Bitcoin but Miniscript. The | |||
// number on the stack would be a 5 bytes signed integer but Miniscript's B type | |||
// only consumes 4 bytes from the stack. | |||
if t == 0 || (t & SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0 { | |||
if t == PackedLockTime::ZERO { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just making sure that this was a bug that was fixed here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe so but that belief is based on the meaningless-ness of comparing a LockTime
to the disable bit of sequence.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still at a loss as to exactly what the comment means. It should be removed now though, right?
@@ -820,16 +821,16 @@ impl Property for Type { | |||
// Note that for CLTV this is a limitation not of Bitcoin but Miniscript. The | |||
// number on the stack would be a 5 bytes signed integer but Miniscript's B type | |||
// only consumes 4 bytes from the stack. | |||
if t == 0 || (t & SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0 { | |||
if t == PackedLockTime::ZERO { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel confident that removing this check is correct. This was just checking something else entirely which was wrong.
This was checking a check on sequence values in script which has no constraints. The only constraint we have is on transaction's sequence, which is different from checking the number encoded in script.
src/policy/semantic.rs
Outdated
self = match self { | ||
Policy::After(t) => { | ||
if !timelock::absolute_timelocks_are_same_unit(t, n) { | ||
// FIXME: If the point of the LockTime type is to make it hard to make mistakes then | ||
// this code shows it fails at that since we _must_ check is_same_unit before comparing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, sorry I was absent during the review of the initial code. I get it that there was some hesitance in implementing PartialOrd
, but why not have a method that returns Optioncmp::Ordering?
We should really not need to check that they are same units here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PartialOrd
gives us a method that returns Option<cmp::Ordering>
. It's Ord
that we couldn't implement, because there is no natural total ordering on timelocks, but which we wanted to implement so that you could use Vec::sort
and derive Ord
on structures that contain timelocks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think @sanket1729 means that PartialOrd
still allows <
and >
operators which are foot guns. Maybe this should be a clippy
lint.
Thanks for the review @sanket1729, I'll get back to this soonish, no rush because AFAIU there are a few other crates to upgrade first. Feel free to take this work and use it if you don't want to wait for me. |
src/miniscript/satisfy.rs
Outdated
if self.is_height_locked() && n.is_height_locked() | ||
|| self.is_time_locked() && n.is_time_locked() | ||
{ | ||
n.to_consensus_u32() <= self.to_consensus_u32() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The previous implementation masked the sequence before doing the comparison. How can we justify not doing this here? What if one has the RBF disabled and the other doesn't for example (disabling RBF will always be the highest value unless you mask out that bit).
PS methods on Sequence
like is_satisfied_by_height
and is_satisfied_by_time
would be super useful here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How can we justify not doing this here?
Thanks man, you are 100% correct, this code is not the same as the code it replaces - that's my bug.
PS methods on Sequence like is_satisfied_by_height and is_satisfied_by_time would be super useful here.
A relative lock time type is meant to be in the works (not sure if anyone is actively working on it yet) and that type would have these methods you suggest. When Sequence
was added relative lock time methods were explicitly out of scope.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've reverted these changes, so we now have
// We need a relative lock time type in rust-bitcoin to clean this up.
/* If nSequence encodes a relative lock-time, this mask is
* applied to extract that lock-time from the sequence field. */
const SEQUENCE_LOCKTIME_MASK: u32 = 0x0000ffff;
const SEQUENCE_LOCKTIME_TYPE_FLAG: u32 = 0x00400000;
let mask = SEQUENCE_LOCKTIME_MASK | SEQUENCE_LOCKTIME_TYPE_FLAG;
let masked_n = n.to_consensus_u32() & mask;
let masked_seq = self.to_consensus_u32() & mask;
if masked_n < SEQUENCE_LOCKTIME_TYPE_FLAG && masked_seq >= SEQUENCE_LOCKTIME_TYPE_FLAG {
false
} else {
masked_n <= masked_seq
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see #455 which implements this using a new relative::LockTime
API.
05c5637
to
4a0a87b
Compare
@@ -109,36 +106,35 @@ pub trait Satisfier<Pk: MiniscriptKey + ToPublicKey> { | |||
} | |||
|
|||
/// Assert whether an relative locktime is satisfied | |||
fn check_older(&self, _: u32) -> bool { | |||
fn check_older(&self, _: Sequence) -> bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you introduce a relative locktime type then it should probably be passed in here instead of Sequence
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks man, I've done that now in the demo PR.
be5a7bc
to
478ff7f
Compare
I don't think we should wait for relative lock time PR in bitcoin 0.30.0. We would need a version of rust-miniscript that supports bitcoin 0.29.0 |
fd48ef3
to
c51595b
Compare
src/policy/semantic.rs
Outdated
Policy::Unsatisfiable | ||
} else if t > n { | ||
} else if t.to_consensus_u32() > n.to_consensus_u32() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is okay, but I would have expected an API like
let cmp_res = t.is_greater_than(n) ; // Any other name.
match(cmp_res) {
Some(true),
Some(false),
None,
}
Rust miniscript/or any other downstream project should need to know that they should check !t.is_same_unit() before comparing.
Perhaps, something worth looking at 0.30.0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could add a method is_satisfied_by_lock
in the same manner as relative::LockTime
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which would give us the much nicer:
Policy::After(t) => {
let t = LockTime::from(t);
} else if !t.is_satisfied_by_lock(n) {
Policy::Unsatisfiable
} else {
Policy::After(t.into())
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Face palm, we actually provide a patter for this in the rustdocs (double face palm, I even wrote the rustdocs and still forgot to use the correct pattern)
I've updated the PR to be
Policy::After(t) => {
let t = LockTime::from(t);
let is_satisfied_by = match (t, n) {
(Blocks(t), Blocks(n)) => t <= n,
(Seconds(t), Seconds(n)) => t <= n,
_ => false
};
if !is_satisfied_by {
Policy::Unsatisfiable
} else {
Policy::After(t.into())
}
}
c51595b
to
882d791
Compare
Hey @sanket1729, seems @josediegorobles is pretty keen to use the upcoming release, is there anything else that needs doing before we can consider this PR and get a release out? |
882d791
to
363b438
Compare
Cargo already uses an env var to configure the toolchain `RUSTUP_TOOLCHAIN`, there is no need for our custom `TOOLCHAIN` environment variable.
A recent release of `form_urlencoded` breaks our dev build when using 1.41.1 toolchain. Pin the `url` and `form_urlencoded` dependencies when on 1.41.1 toolchain.
Depend on the newly released bitcoin 0.29.0
363b438
to
24a2498
Compare
Hi @tcharding, there is nothing that needs to be done in particular here. I have a few cleanups in mind, but those can wait for |
Hi, @sanket1729 by suggestion of @tcharding i started a PR for the release: tcharding#1 What version must be, 7.1.0 or 8.0.0? And what other things must be on the changelog? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 24a2498. Reviewed by range-diff from c51595b .
I am waiting on @apoelstra to respond to the comment issue he raised. #450 (comment)
}), | ||
("older", 1) => expression::terminal(&top.args[0], |x| { | ||
expression::parse_num(x).map(Policy::Older) | ||
expression::parse_num(x).map(|x| Policy::older(x)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: there was no need for the |x|
here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 24a2498
@sanket1729 in future before merging can you edit PR descriptions to remove the |
@apoelstra, will take care from next time |
Should I just not put mentions in the PR description? I thought it was only in the commit log (on the actual patch) that mattered? |
@tcharding no, it matters both on the commits and in the PR description. (Though the PR description is really easy to edit, for anyone with merge permissions, while the commits are a pain.) |
My bad, duly schooled :) |
@apoelstra are you sure? I was never spuriously notified from PRs. Creation doesn't count as spurious - I consider mentioning explicitly wanting to notify someone. |
@Kixunil yes, though I believe the reason is that our merge script copies the entire PR description into the merge commit message. |
Ah, good point! Could the merge script be modified to replace |
I don't know -- could you open an issue on https://github.com/bitcoin-core/bitcoin-maintainer-tools/ ? Note that it does currently display an angry warning if there are @s in the PR description, which I always respond to by just editing the PR description and trying again ... maybe they don't want to modify PRs by default but it'd be nice if there was at least a gitconfig flag or something to do it. |
3f451db Release 8.0.0 (sanket1729) Pull request description: Draft release PR. Still blocked on reviews of 1) #418 2) #450 3) #461 ACKs for top commit: apoelstra: ACK 3f451db Tree-SHA512: aa455fd57a894b1edb49b6273126a05c9d0897ca50ee572fa8a59b4d2a96e2013f2ed9ec4b96cd5e449ba5b5ee6bd32aa57da110df69bd35b8a970ccb1440002
…022_10 cddc22d Merge rust-bitcoin/rust-miniscript#450: Upgrade bitcoin dependency to v0.29.0 (Change satisfier locktime)
This is going to need a pretty careful review by @sanket1729 and/or @apoelstra to double check all the sequence/lock_time stuff. Even with the new APIs this stuff is non-trivial. This patch changes the current behaviour around logic for these two types. I am unable to work out if current behaviour has bugs in it or if I just don't fully understand it.
Note
Please ignore the branch name, it stale now since this PR upgrades to the newly released bitcoin v0.29.1