Skip to content

Commit b21ea8d

Browse files
committed
Implement GetBlockHeader function
The function queries electrum server for a block header for a block at the given height and then returns it in the format expected by the bitcoin.Chain interface.
1 parent c51f12f commit b21ea8d

2 files changed

Lines changed: 63 additions & 2 deletions

File tree

pkg/bitcoin/electrum/block.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package electrum
2+
3+
import (
4+
"bytes"
5+
"encoding/hex"
6+
7+
"github.com/btcsuite/btcd/wire"
8+
"github.com/checksum0/go-electrum/electrum"
9+
10+
"github.com/keep-network/keep-core/pkg/bitcoin"
11+
)
12+
13+
// convertBlockHeader transforms a BlockHeader returned from Electrum protocol to
14+
// the format expected by the bitcoin.Chain interface.
15+
func convertBlockHeader(electrumResult *electrum.GetBlockHeaderResult) (*bitcoin.BlockHeader, error) {
16+
headerBytes, err := hex.DecodeString(electrumResult.Header)
17+
if err != nil {
18+
return nil, err
19+
}
20+
21+
buf := bytes.NewBuffer(headerBytes)
22+
23+
var b wire.BlockHeader
24+
if err := b.Deserialize(buf); err != nil {
25+
return nil, err
26+
}
27+
28+
result := &bitcoin.BlockHeader{
29+
Version: b.Version,
30+
PreviousBlockHeaderHash: bitcoin.Hash(b.PrevBlock),
31+
MerkleRootHash: bitcoin.Hash(b.MerkleRoot),
32+
Time: uint32(b.Timestamp.Unix()),
33+
Bits: b.Bits,
34+
Nonce: b.Nonce,
35+
}
36+
37+
return result, nil
38+
}

pkg/bitcoin/electrum/electrum.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,32 @@ func (c *Connection) GetLatestBlockHeight() (uint, error) {
141141
panic("not implemented")
142142
}
143143

144+
// GetBlockHeader gets the block header for the given block height. If the
145+
// block with the given height was not found on the chain, this function
146+
// returns an error.
144147
func (c *Connection) GetBlockHeader(
145148
blockHeight uint,
146149
) (*bitcoin.BlockHeader, error) {
147-
// TODO: Implementation.
148-
panic("not implemented")
150+
var getBlockHeaderResult *electrum.GetBlockHeaderResult
151+
err := wrappers.DoWithDefaultRetry(c.requestRetryTimeout, func(ctx context.Context) error {
152+
result, err := c.client.GetBlockHeader(c.ctx, uint32(blockHeight), 0)
153+
if err != nil {
154+
return fmt.Errorf(
155+
"GetBlockHeader failed: [%w]",
156+
err,
157+
)
158+
}
159+
getBlockHeaderResult = result
160+
return nil
161+
})
162+
if err != nil {
163+
return nil, fmt.Errorf("failed to get block header: [%w]", err)
164+
}
165+
166+
blockHeader, err := convertBlockHeader(getBlockHeaderResult)
167+
if err != nil {
168+
return nil, fmt.Errorf("failed to convert block header: %w", err)
169+
}
170+
171+
return blockHeader, nil
149172
}

0 commit comments

Comments
 (0)