Skip to content

Electrs integration for Bitcoin chain#3395

Closed
nkuba wants to merge 20 commits intomainfrom
bitcoin-electrs-integration
Closed

Electrs integration for Bitcoin chain#3395
nkuba wants to merge 20 commits intomainfrom
bitcoin-electrs-integration

Conversation

@nkuba
Copy link
Copy Markdown
Member

@nkuba nkuba commented Nov 2, 2022

This PR implements Bitcoin package integration with Electrs API.

TODO:

  • command flags for config properties
  • tests
  • PR description

Refs #3384
Refs #3369

nkuba added 7 commits November 2, 2022 21:56
We will start with integrating with electrs.
The handle is used for integration with Electrs.
The function uses config to build the connection.
The wrappers to request get and post calls with retries.
GetTransaction returns a bitcoin transaction of the given transaction
hash as TX ID.

The function calls Electrs API to get the transaction and converts the
returned transaction details to the format expected by the common
Bitcoin handle.
@nkuba nkuba self-assigned this Nov 2, 2022
@nkuba nkuba modified the milestone: v2.0.0-m2 Nov 2, 2022
nkuba added 9 commits November 3, 2022 15:47
We can simplify the code when we return bytes from response body instead
of passing a reader.
The function returns number of confirmations the transaction has.

It gets the transaction details and extracts the status data.

If the transaction is not found it retrurns an error.
If the transaction is not confirmed it returns `0`.

If the transaction is confirmed it compares the block number in which
transaction was included with the current block tip.

If the current block tip is the same number as transaction block number
then it retruns `1`.
If the current block tip is greater transaction block number it returns
the difference incremented by 1.

Examples:

latest block height = 2000
transaction block height = 2000
result = 1

latest block height = 2020
transaction block height = 2000
result = 21
The function gets the hash of the block at specfic height and then gets
the header of this block.
The block returned in electrs/esplora format is converted to the
expected bitcoin block type.
The function serializes the transaction and broadcast it.
If the status code is not 200 we use response body in the error message
as a nice-to-have. There is no need to handle the error or log it, as
this is a failure anyway.
The intention of the function is to return the most recent block that
was mined (added to the chain) - also called a "tip".
Replacing `Current` with `Latest` seems accurate and should reduce the
confusion, as `current` may suggest the block that is currently being
mined.
For Bitcoin it seems more common to use the name `block height` over
the `block number`.
Comment thread pkg/bitcoin/chain.go
GetCurrentBlockNumber() (uint, error)
// GetLatestBlockHeight gets the height of the latest block (tip). If the
// latest block was not determined, this function returns an error.
GetLatestBlockHeight() (uint, error)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@lukasz-zimnoch I hope you're fine with this rename.

The function expects the "chain tip", so the most recent mined block. I propose we use "latest", as "current" may be confusing and suggest that the block is being currently mined.

Also, I replaced "block number" with "block height", as it seems to be widely used in the Bitcoin ecosystem.

nkuba added 2 commits November 4, 2022 14:45
The basic set of unit tests for Electrs integration with mocked HTTP
client.
For unit tests we need a value to be returned by the `Serialize`
function. Until the function is implemented we will use a hardcoded
value.
"github.com/keep-network/keep-core/pkg/bitcoin"
)

type blockHeader struct {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's not forget about descriptions of all the functions and types.

Nonce: b.Nonce,
}

previousBlockHeaderHash, err := bitcoin.NewHashFromString(b.PreviousBlockHash, bitcoin.ReversedByteOrder)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we split this lengthy line?

nkuba added 2 commits November 4, 2022 16:06
The integration test connects to the real Electrs API exposed by the
Blockstream.
To run the test execute:
go test -v -tags=integration ./...
}

// Connect initializes handle with provided Config.
func Connect(config Config) (bitcoin.Chain, error) {
Copy link
Copy Markdown
Contributor

@tomaszslabon tomaszslabon Nov 7, 2022

Choose a reason for hiding this comment

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

Connect won't return an error even if the URL provided in the config is wrong.
We will only learn about the wrong URL when we try to use the Bitcoin chain for the first time.
I would consider adding a connection test before we leave Connect, so that we know we didn't make any mistake. We did such test when connecting to btc client in the old relay maintainer.

@pdyraga pdyraga added this to the v2.0.0-m3 milestone Nov 10, 2022
@nkuba
Copy link
Copy Markdown
Member Author

nkuba commented Nov 17, 2022

Closing in favor of #3406

@nkuba nkuba closed this Nov 17, 2022
tomaszslabon added a commit that referenced this pull request Dec 9, 2022
This PR implements Bitcoin package integration with [Electrum
API](https://electrumx-spesmilo.readthedocs.io/en/latest/protocol.html).

There are a couple of servers implementations supporting the Electrum
API:
- [ElectrumX](https://github.com/spesmilo/electrumx)
- [Esplora - Electrs by
Blockstream](https://github.com/Blockstream/electrs)
- [Fulcrum](https://github.com/cculianu/Fulcrum)

A list of publicly exposed Electrum protocol servers for Bitcoin can be
found here:
- mainnet: https://1209k.com/bitcoin-eye/ele.php?chain=btc
- testnet: https://1209k.com/bitcoin-eye/ele.php?chain=tbtc

We added integration tests to verify the implementation works correctly
with the most popular server implementations. To run the integration
tests execute:
```
go test -v -tags=integration ./...
```

There are a couple of TODOs in the code regarding the improvements that
will be handled in follow-up PRs.

Refs #3384
Refs #3369
Refs #3395
@pdyraga pdyraga modified the milestones: v2.0.0-m3, v2.0.0-m2 Jan 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants