diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml index 8f5a6322..587bb8e1 100644 --- a/e2e/docker-compose.yml +++ b/e2e/docker-compose.yml @@ -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" @@ -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" @@ -295,3 +304,4 @@ services: volumes: l2configs: + bitcoindata: diff --git a/e2e/e2e_ext_test.go b/e2e/e2e_ext_test.go index 73de82bd..26ca63ee 100644 --- a/e2e/e2e_ext_test.go +++ b/e2e/e2e_ext_test.go @@ -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", @@ -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{} @@ -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"` }{} @@ -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) @@ -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{} @@ -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, @@ -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, }) @@ -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, diff --git a/hemi/electrs/conn.go b/hemi/electrs/conn.go index 3d6394ce..1abc3a76 100644 --- a/hemi/electrs/conn.go +++ b/hemi/electrs/conn.go @@ -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 { diff --git a/hemi/electrs/electrs.go b/hemi/electrs/electrs.go index 92e7d25b..a4a0893f 100644 --- a/hemi/electrs/electrs.go +++ b/hemi/electrs/electrs.go @@ -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"` } @@ -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", ¶ms, &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)