Skip to content

Commit

Permalink
test: add test for btc block header deserialize (#26)
Browse files Browse the repository at this point in the history
* fmt

Signed-off-by: Vu Vo <[email protected]>

* refactor error assert in test

Signed-off-by: Vu Vo <[email protected]>

* fix some comments

Signed-off-by: Vu Vo <[email protected]>

* verify size of block header is 80 bytes

Signed-off-by: Vu Vo <[email protected]>

* fix testing data

Signed-off-by: Vu Vo <[email protected]>

* fmt

Signed-off-by: Vu Vo <[email protected]>

* Apply suggestions from code review

Co-authored-by: sczembor <[email protected]>
Signed-off-by: Vu Vo <[email protected]>

* define error in btc light client

Signed-off-by: Vu Vo <[email protected]>

* spv errors when decode

Signed-off-by: Vu Vo <[email protected]>

* format remaing error

Signed-off-by: Vu Vo <[email protected]>

* tiny fix

Signed-off-by: Vu Vo <[email protected]>

* more tests

Signed-off-by: Vu Vo <[email protected]>

* Apply suggestions from code review

Co-authored-by: sczembor <[email protected]>
Signed-off-by: Vu Vo <[email protected]>

* Update btc_header_bytes_test.go

Co-authored-by: sczembor <[email protected]>
Signed-off-by: Vu Vo <[email protected]>

---------

Signed-off-by: Vu Vo <[email protected]>
Co-authored-by: sczembor <[email protected]>
  • Loading branch information
vuvoth and sczembor authored Jan 15, 2025
1 parent 30187fb commit e669927
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 118 deletions.
19 changes: 14 additions & 5 deletions btclightclient/btc_header_bytes.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,23 @@ import (
"github.com/btcsuite/btcd/wire"
)

// We don't want to make it compilicated yet :D
// type BTCHeaderBytes []byte
// const BTCHeaderSize = 80
const BTCHeaderSize = 80 // 80 bytes

// Utils for converting hex string to header
// The input must be 80 bytes hex string type
func BlockHeaderFromHex(hexStr string) (wire.BlockHeader, error) {
data, _ := hex.DecodeString(hexStr)
var header wire.BlockHeader

if len(hexStr) != BTCHeaderSize*2 {
return header, ErrInvalidHeaderSize
}

data, err := hex.DecodeString(hexStr)
if err != nil {
return header, err
}

reader := bytes.NewReader(data)
err := header.Deserialize(reader)
err = header.Deserialize(reader)
return header, err
}
55 changes: 55 additions & 0 deletions btclightclient/btc_header_bytes_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package btclightclient

import (
"encoding/hex"
"testing"

"gotest.tools/assert"
)

func TestBTCHeaderFromHex(t *testing.T) {
type testCase struct {
name string
headerHex string
expectedBlockHash string
expectedError error
}

run := func(t *testing.T, tc testCase) {
header, err := BlockHeaderFromHex(tc.headerHex)
blockHash := header.BlockHash()
if tc.expectedError != nil {
assert.Error(t, err, tc.expectedError.Error())
} else {
assert.NilError(t, err)
assert.Equal(t, tc.expectedBlockHash, blockHash.String())
}
}

testCases := []testCase{
{
name: "happy test case",
headerHex: "020000004cdba1415b2c6e7808c1b3c18df1374238454f7104203475bf01000000000000c17ea9d06015dc83902911cd24837a8ba4bdc0c1d72b873f906d921e06e48d2f984a8250ef75051a72a8061a",
expectedError: nil,
expectedBlockHash: "0000000000000363d7f5f3341fb0b5b69949103e2d681591c9f737e4ea67e2a7",
},
{
name: "invalid header length",
headerHex: "020000004cdba1415b2c6e7808c1b3c18df1374238454f7104203475bf01000000000000c17ea9d06015dc83902911cd24837a8ba4bdc0c1d72b873f906d921e06e48d2f984a8250ef75051a72a8061ab",
expectedError: ErrInvalidHeaderSize,
expectedBlockHash: "0000000000000363d7f5f3341fb0b5b69949103e2d681591c9f737e4ea67e2a7",
},
{
name: "non-hex character",
headerHex: "020000004cdba1415b2c6e7808c1b3c18df1374238454f7104203475bf01000000000000c17ea9d06015dc83902911cd24837a8ba4bdc0c1d72b873f906d921e06e48d2f984a8250ef75051a72a8061Q",
expectedError: hex.InvalidByteError('Q'),
expectedBlockHash: "",
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
run(t, tc)
})
}
}
15 changes: 7 additions & 8 deletions btclightclient/btc_light_client.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package btclightclient

import (
"errors"
"fmt"
"math/big"
"time"
Expand Down Expand Up @@ -53,13 +52,13 @@ func (lc *BTCLightClient) FindPreviousCheckpoint() (blockchain.HeaderCtx, error)
func (lc *BTCLightClient) InsertHeader(header wire.BlockHeader) error {

if lb := lc.btcStore.LightBlockByHash(header.BlockHash()); lb != nil {
return errors.New("parent block not found")
return ErrBlockNotInChain
}

parentHash := header.PrevBlock
parent := lc.btcStore.LightBlockByHash(parentHash)
if parent == nil {
return errors.New("block doesn't belong to any fork")
return ErrParentBlockNotInChain
}

// we need to handle 2 cases:
Expand Down Expand Up @@ -89,7 +88,7 @@ func (lc *BTCLightClient) forkOfBlockhash(bh chainhash.Hash) ([]*LightBlock, err
for count := 0; count <= MaxForkAge; count++ {
curr := lc.btcStore.LightBlockByHash(bh)
if checkpoint.Height > curr.Height {
return nil, errors.New("fork too old")
return nil, ErrForkTooOld
}
fork = append(fork, curr)
if bh.IsEqual(&checkpointHash) {
Expand All @@ -98,7 +97,7 @@ func (lc *BTCLightClient) forkOfBlockhash(bh chainhash.Hash) ([]*LightBlock, err
bh = curr.Header.PrevBlock
}

return nil, errors.New("block not found or too old")
return nil, ErrForkTooOld
}

// We follow:
Expand Down Expand Up @@ -163,15 +162,15 @@ func (lc *BTCLightClient) CreateNewFork(parent *LightBlock, header wire.BlockHea

func (lc *BTCLightClient) ForkAge(bh chainhash.Hash) (int32, error) {
lb := lc.btcStore.LightBlockByHash(bh)
checkpoint := lc.btcStore.LatestCheckPoint()
if lb == nil {
return 0, errors.New("hash doesn't belong to db")
return 0, ErrBlockNotInChain
}

if !lc.btcStore.IsForkHead(bh) {
return 0, errors.New("hash not a latest block in forks")
return 0, ErrBlockIsNotForkHead
}

checkpoint := lc.btcStore.LatestCheckPoint()
age := lb.Height - checkpoint.Height
return age, nil
}
Expand Down
1 change: 0 additions & 1 deletion btclightclient/btc_light_client_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ func (s *MemStore) SetIsNotHead(bh chainhash.Hash) {
delete(s.latestBlockHashOfFork, bh)
}

// TODO: convert to iterator rather than returning a map
func (s *MemStore) LatestBlockHashOfFork() []chainhash.Hash {
hashes := []chainhash.Hash{}
for h := range s.latestBlockHashOfFork {
Expand Down
Loading

0 comments on commit e669927

Please sign in to comment.