Skip to content

Commit

Permalink
make bfg compatible with blockstream's electrs
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 committed Oct 8, 2024
1 parent ee45b5c commit 308922c
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 @@ -435,13 +435,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 @@ -457,13 +457,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 @@ -473,7 +473,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 @@ -487,7 +487,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 @@ -500,7 +500,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 @@ -520,7 +520,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 @@ -534,7 +534,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 @@ -546,7 +546,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 308922c

Please sign in to comment.