Skip to content
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

Replace trait AnchorFromBlockPosition with new struct #1594

Merged
merged 1 commit into from
Oct 1, 2024

Conversation

jirijakes
Copy link
Contributor

@jirijakes jirijakes commented Sep 8, 2024

Description

This change replaces a way of creating new generic anchor from block and its height. Previous way was using conversion trait, newly it is a struct and From.

Closes #1266.

Notes to the reviewers

  • Removed tx_pos: I did not see its relevance (Anchor does not give access to it). Was it a relic from the past or something I overlooked?
  • I put BlockPosition into tx_data_traits.rs because I believe it should be next to Anchor. But then it's not a module just for traits. What would be better place?

Checklists

All Submissions:

  • I've signed all my commits
  • I followed the contribution guidelines
  • I ran cargo fmt and cargo clippy before committing

@jirijakes
Copy link
Contributor Author

@evanlinjin @LLFourn, is this what you meant in #1266?

@jirijakes jirijakes marked this pull request as draft September 8, 2024 08:22
@jirijakes jirijakes marked this pull request as ready for review September 8, 2024 08:31
@jirijakes
Copy link
Contributor Author

I am not sure about the failing test. Is there some flakiness? It ran alright in my fork and also my machine.

     Running tests/test_electrum.rs (target/debug/deps/test_electrum-5e966bdb43ca0ef0)

running 4 tests
test test_update_tx_graph_stop_gap ... FAILED
test test_update_tx_graph_without_keychain ... ok
test tx_can_become_unconfirmed_after_reorg ... ok
test test_sync ... ok

failures:

---- test_update_tx_graph_stop_gap stdout ----
Error: expected value at line 1 column 1


failures:
    test_update_tx_graph_stop_gap

error: test failed, to rerun pass `-p bdk_electrum --test test_electrum`
test result: FAILED. 3 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 7.73s

Error: Process completed with exit code 101.

Copy link
Contributor

@LLFourn LLFourn left a comment

Choose a reason for hiding this comment

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

Concept ACK.

crates/chain/src/tx_data_traits.rs Outdated Show resolved Hide resolved
/// Minimal set of parameters that are needed to construct a generic [`Anchor`].
/// Typically used as an additional constraint on anchor:
/// `A: Anchor + From<BlockPosition<'b>>`.
pub struct BlockPosition<'b> {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this should be called BlockAndHeight and should be documented simply as that. I'm not sure it should be described as the "minimal" set of parameters. It's more like like the maximal amount of detail about the block that could be needed to make an anchor i.e. any anchor should be able to be made from a BlockPosition. We could even type constraint that Anchor: for<'a> From<BlockPosition<'a>>.

Copy link
Member

Choose a reason for hiding this comment

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

If we were to have a merkle-proof anchor (which I think we should have), don't we also need a tx position in block? I'm not too great with naming, but I'm thinking TxPosInBlock?

pub struct TxPosInBlock<'b> {
    block: &'b Block,
    height: u32,
    tx_pos: usize, 
}

Copy link
Member

Choose a reason for hiding this comment

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

Also, we are missing some derives. #[derive(Debug, Clone, Copy, PartialEq, Eq)] I think makes sense for this type.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, we are missing some derives. #[derive(Debug, Clone, Copy, PartialEq, Eq)] I think makes sense for this type.

Added, thanks.

Copy link
Member

@evanlinjin evanlinjin Sep 10, 2024

Choose a reason for hiding this comment

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

All fields should be public as well, otherwise external modules/crates can't impl From<BlockPosition>.

Ohh I see u have a constructor and methods on it. I guess you did it this way instead of...

pub struct BlockPosition<'a> {
    pub block: &'a Block,
    pub height: u32,
    pub tx_pos: usize,
}

So that the blockhash can be precalculated?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm, it is more of my habit to start with hidden fields (in order to hide internals) and use getters. The blockhash was a bonus.

However, as BDK typically exposes publicly all fields, I guess it would be appropriate to follow also in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We could even type constraint that Anchor: for<'a> From<BlockPosition<'a>>.

From<BlockPosition> is currently used only by two methods. Wouldn't that be too strict to require that of every future implementation of Anchor?

I'm not sure it should be described as the "minimal" set of parameters. It's more like like the maximal amount of detail about the block that could be needed to make an anchor

Mmm, yeah, I see how it can be unclear. My idea was “if you have at least these parameters at disposal, you can create any anchor.“ I will reword.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes @evanlinjin's design looks right to me.

From is currently used only by two methods. Wouldn't that be too strict to require that of every future implementation of Anchor?

I think if you can't get your anchor from the full block and position you may be using anchors in a way you probably shouldn't.

Copy link
Contributor

Choose a reason for hiding this comment

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

If we were to have a merkle-proof anchor (which I think we should have), don't we also need a tx position in block?

If we decide this new struct should include the position of the tx in block, then the original name BlockPosition would again makes sense to me but I won't belabor the point.

Copy link
Member

Choose a reason for hiding this comment

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

BlockPosition may be interpreted as position of block in the Blockchain though

crates/chain/src/indexed_tx_graph.rs Outdated Show resolved Hide resolved
crates/chain/src/indexed_tx_graph.rs Outdated Show resolved Hide resolved
@jirijakes
Copy link
Contributor Author

I reflected some of the comments but have not figured out the name yet. I will sleep on it and will see tomorrow if I come with a better one. Until then, I will keep it as draft.

@jirijakes
Copy link
Contributor Author

  • Renamed to TxPosInBlock. Although this name still does not feel perfect, it is better than BlockPosition and I cannot think of other.
  • Reworded docomment.
  • I still kept TxPosInBlock's fields private, accessible via getters. It feels a bit better suitable for this purpose: with public fields instead of a constructor, one of the fields would be height and therefore block hash would have to be calculated on every access. Please let me know if public fields would be better regardless.

Thanks everybody for the comments!

@jirijakes jirijakes marked this pull request as ready for review September 11, 2024 12:21
Copy link
Contributor

@oleonardolima oleonardolima left a comment

Choose a reason for hiding this comment

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

Concept ACK

I agree, the naming is hard. I wasn't able to come up with any other idea than TxBlockId (which I don't think really suits 😅)

Comment on lines 299 to 302
graph.merge(self.graph.insert_anchor(
tx.compute_txid(),
TxPosInBlock::new(block, height, tx_pos).into(),
));
Copy link
Member

Choose a reason for hiding this comment

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

This means we are constructing TxPosInBlock on every tx, thus re-computing the block hash for every tx... I have a couple of ideas to fix this.

  1. Make all fields of TxPositionInBlock public and get rid of construction and getter methods.
  2. Add a method to change the tx_pos. I.e. fn with_tx_pos(self, tx_pos: usize) -> Self.

I'm in favor of 1. because it is simpler and I don't see much value in having an API that enforces the consistency of the type. I don't see the caller constructing this type. The main usecase of this type (as I understand) is for implementing From<TxPositionInBlock> for anchors types that support it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Make all fields of TxPositionInBlock public and get rid of construction and getter methods.

Made fields public as suggested.

Although that puts us back to the beginning (suggestion to pass only height, not BlockId), the repeated calculation of block hash should be avoided. Most likely why the creation of BlockId was in the original code in a first place.

@jirijakes
Copy link
Contributor Author

Another round:

  • fields in TxPosInBlock public, one of them is block_id instead of height to avoid repetead recalculations of block hash
  • if we want to have all anchors implement From<TxPosInBlock>, as hinted by @LLFourn, I believe it could be done in a followup rather than here.

@evanlinjin
Copy link
Member

I think it makes sense to include this change in v1.0 since this is a minor breaking change and the work is done.

The worst case scenario is that users that created custom anchors that used methods which required AnchorFromBlockPosition will need to change to impl From<TxPosInBlock>.

If we deem this breaking change as unacceptable, there is a way to make this non-breaking. We can keep AnchorFromBlockPosition and anything that impls it will impl From<TxPosInBlock>. We also mark AnchorFromBlockPosition as deprecated.

I'm in favor of just making this change breaking since it's so minor.

@ValuedMammal
Copy link
Contributor

How about calling it TxBlockPosition @jirijakes @evanlinjin

@evanlinjin
Copy link
Member

How about calling it TxBlockPosition @jirijakes @evanlinjin

How about PositionInBlock? 😅

@LagginTimes
Copy link
Contributor

LagginTimes commented Sep 19, 2024

How about calling it TxBlockPosition @jirijakes @evanlinjin

How about PositionInBlock? 😅

Maybe BlockTxPosition might be preferable? Or just TxPosition? 😅

Copy link
Member

@evanlinjin evanlinjin left a comment

Choose a reason for hiding this comment

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

Looks good to me, just some doc changes and I'll happy to ACK.

There is a bit of bike-shedding going on with the naming.

I'm happy with how it is currently, or BlockTxPosition, or PositionInBlock, or TxBlockPosition. Whatever you choose, I will ACK.

crates/chain/src/tx_data_traits.rs Outdated Show resolved Hide resolved
crates/chain/src/tx_data_traits.rs Show resolved Hide resolved
@oleonardolima
Copy link
Contributor

Alongside Evan's comments, please do mind the commit message to follow https://www.conventionalcommits.org/en/v1.0.0/ too.

I'm fine with the name suggestions above, although I tend more toward either: TxPosInBlock (current) or TxBlockPosition (these seem clearer to me).

…ruct

This change replaces a way of creating new generic anchor from block,
its height and transaction position. Previous way was using conversion
trait, newly it is a struct and `From`.
@jirijakes
Copy link
Contributor Author

Addressed @evanlinjin's comments and changed commit message (hope it's right).

Apologies for the delay.

@ValuedMammal ValuedMammal added this to the 1.0.0-beta milestone Sep 29, 2024
@LagginTimes
Copy link
Contributor

Nit: I would probably reword the commit description to be something like:

This change revises how a generic anchor is created from a block, its
`BlockId`, and the transaction's position. The previous approach used a
conversion trait, while the new approach uses a struct and the `From`
trait.

Copy link
Contributor

@LLFourn LLFourn left a comment

Choose a reason for hiding this comment

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

ACK ab8068b

a trait is deleted I ack. Would like @evanlinjin and @LagginTimes to ACK too.

@LagginTimes
Copy link
Contributor

ACK ab8068b

@notmandatory notmandatory merged commit 139d971 into bitcoindevkit:master Oct 1, 2024
21 checks passed
@ValuedMammal ValuedMammal mentioned this pull request Oct 2, 2024
32 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

An alternative approach to AnchorFromBlockPosition.
7 participants