Skip to content

Commit

Permalink
make bfg compatible with blockstream's electrs (#278)
Browse files Browse the repository at this point in the history
we want to try out blockstream's electrs as opposed to the community one, this allows us to do so
  • Loading branch information
ClaytonNorthey92 authored Oct 11, 2024
1 parent 99d0038 commit b00bc1f
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 23 deletions.
26 changes: 18 additions & 8 deletions e2e/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ services:
- "18443:18443"
- "18444:18444"
volumes:
- { type: "tmpfs", target: "/bitcoin/.bitcoin" }
- bitcoindata:/bitcoin/.bitcoin

bitcoind-initialblocks:
image: "kylemanna/bitcoind@sha256:5d97bbe3c74856818f0b3a1e718eb3968981ab03ce08aaf1c7d528f99aaf30b7"
Expand Down Expand Up @@ -56,24 +56,33 @@ services:
- "$BTC_ADDRESS"

electrs:
build:
context: https://github.com/romanz/electrs.git#1d02f10ec38edbc3b7df6b16bb8989d9bc0aaa0f
image: blockstream/esplora@sha256:1fb16180f430f75da28eca37a265630c7192b3c103aafd9b9ba4bf5b6d9c8ea8
depends_on:
- "bitcoind"
command:
- electrs
- electrs_bitcoin/bin/electrs
- --electrum-rpc-addr
- '0.0.0.0:50001'
- --daemon-rpc-addr
- "bitcoind:18443"
- --daemon-p2p-addr
- "bitcoind:18444"
- --network
- regtest
- --cookie-file
- "/tmp/.cookie"
- --cookie
- "user:password"
- "-vvv"
- "--timestamp"
- --utxos-limit
- "50000"
- --electrum-txs-limit
- "50000"
- --blocks-dir
- "/bitcoindata/regtest/blocks"
environment:
RUST_LOG: debug
RUST_BACKTRACE: "full"
volumes:
- ./cookie:/tmp/.cookie
- bitcoindata:/bitcoindata:ro
deploy:
restart_policy:
condition: "on-failure"
Expand Down Expand Up @@ -295,3 +304,4 @@ services:

volumes:
l2configs:
bitcoindata:
20 changes: 10 additions & 10 deletions e2e/e2e_ext_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,13 +436,13 @@ func handleMockElectrsConnection(ctx context.Context, t *testing.T, conn net.Con
res := electrs.JSONRPCResponse{}
if req.Method == "blockchain.transaction.broadcast" {
res.ID = req.ID
res.Error = nil
res.Error = ""
res.Result = json.RawMessage([]byte(fmt.Sprintf("\"%s\"", mb.TxID())))
}

if req.Method == "blockchain.headers.subscribe" {
res.ID = req.ID
res.Error = nil
res.Error = ""
headerNotification := electrs.HeaderNotification{
Height: mockTxheight,
BinaryHeader: "aaaa",
Expand All @@ -458,13 +458,13 @@ func handleMockElectrsConnection(ctx context.Context, t *testing.T, conn net.Con

if req.Method == "blockchain.block.header" {
res.ID = req.ID
res.Error = nil
res.Error = ""
res.Result = json.RawMessage([]byte(mockEncodedBlockHeader))
}

if req.Method == "blockchain.transaction.id_from_pos" {
res.ID = req.ID
res.Error = nil
res.Error = ""

params := []any{}

Expand All @@ -474,7 +474,7 @@ func handleMockElectrsConnection(ctx context.Context, t *testing.T, conn net.Con
}

result := struct {
TXHash string `json:"tx_id"`
TXHash string `json:"tx_hash"`
Merkle []string `json:"merkle"`
}{}

Expand All @@ -488,7 +488,7 @@ func handleMockElectrsConnection(ctx context.Context, t *testing.T, conn net.Con
// pretend that there are no transactions past mockTxHeight
// and mockTxPos
if params[0].(float64) >= mockTxheight && params[1].(float64) > mockTxPos {
res.Error = electrs.NewJSONRPCError(1, "no tx at position")
res.Error = "no tx at position"
}

b, err := json.Marshal(&result)
Expand All @@ -501,7 +501,7 @@ func handleMockElectrsConnection(ctx context.Context, t *testing.T, conn net.Con

if req.Method == "blockchain.transaction.get" {
res.ID = req.ID
res.Error = nil
res.Error = ""

params := []any{}

Expand All @@ -521,7 +521,7 @@ func handleMockElectrsConnection(ctx context.Context, t *testing.T, conn net.Con

if req.Method == "blockchain.scripthash.get_balance" {
res.ID = req.ID
res.Error = nil
res.Error = ""
j, err := json.Marshal(electrs.Balance{
Confirmed: 1,
Unconfirmed: 2,
Expand All @@ -535,7 +535,7 @@ func handleMockElectrsConnection(ctx context.Context, t *testing.T, conn net.Con

if req.Method == "blockchain.headers.subscribe" {
res.ID = req.ID
res.Error = nil
res.Error = ""
j, err := json.Marshal(electrs.HeaderNotification{
Height: 10,
})
Expand All @@ -547,7 +547,7 @@ func handleMockElectrsConnection(ctx context.Context, t *testing.T, conn net.Con

if req.Method == "blockchain.scripthash.listunspent" {
res.ID = req.ID
res.Error = nil
res.Error = ""
hash := []byte{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2,
Expand Down
4 changes: 2 additions & 2 deletions hemi/electrs/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ func readResponse(ctx context.Context, r io.Reader, reqID uint64) (*JSONRPCRespo
if err = json.Unmarshal(b, &res); err != nil {
return nil, fmt.Errorf("unmarshal response: %w", err)
}
if res.Error != nil {
return nil, RPCError(res.Error.Message)
if res.Error != "" {
return nil, RPCError(res.Error)
}

if res.ID != reqID {
Expand Down
6 changes: 3 additions & 3 deletions hemi/electrs/electrs.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func NewJSONRPCRequest(id uint64, method string, params any) (*JSONRPCRequest, e

type JSONRPCResponse struct {
JSONRPC string `json:"jsonrpc"`
Error *JSONRPCError `json:"error,omitempty"`
Error string `json:"error,omitempty"`
Result json.RawMessage `json:"result"`
ID uint64 `json:"id"`
}
Expand Down Expand Up @@ -400,13 +400,13 @@ func (c *Client) Transaction(ctx context.Context, txHash []byte) ([]byte, error)

func (c *Client) TransactionAtPosition(ctx context.Context, height, index uint64) ([]byte, []string, error) {
result := struct {
TXHash string `json:"tx_id"`
TXHash string `json:"tx_hash"`
Merkle []string `json:"merkle"`
}{}

params := []any{height, index, true}
if err := c.call(ctx, "blockchain.transaction.id_from_pos", &params, &result); err != nil {
if strings.HasPrefix(err.Error(), "invalid tx_pos ") {
if strings.HasPrefix(err.Error(), "No tx in position ") {
return nil, nil, NewNoTxAtPositionError(err)
} else if strings.HasPrefix(err.Error(), "db error: DBError('block ") && strings.Contains(err.Error(), " not on disk ") {
return nil, nil, NewBlockNotOnDiskError(err)
Expand Down

0 comments on commit b00bc1f

Please sign in to comment.