Skip to content

Commit

Permalink
Initial draft of PR
Browse files Browse the repository at this point in the history
Signed-off-by: Ononiwu Maureen <[email protected]>
  • Loading branch information
Chinwendu20 committed Jul 5, 2023
1 parent d209c5e commit 7a8dac7
Show file tree
Hide file tree
Showing 11 changed files with 2,272 additions and 1,115 deletions.
607 changes: 501 additions & 106 deletions blockmanager.go

Large diffs are not rendered by default.

1,810 changes: 905 additions & 905 deletions blockmanager_test.go

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions headerfs/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ type BlockHeaderStore interface {
// The information about the new header tip after truncation is
// returned.
RollbackLastBlock() (*BlockStamp, error)

// BlockLocatorFromHeight returns the block locator object based on the height
// supplied as argument to the function.
BlockLocatorFromHeight(uint32) (blockchain.BlockLocator, error)
}

// headerBufPool is a pool of bytes.Buffer that will be re-used by the various
Expand Down Expand Up @@ -482,6 +486,25 @@ func (h *blockHeaderStore) LatestBlockLocator() (blockchain.BlockLocator, error)
return h.blockLocatorFromHash(chainTipHash)
}

// BlockLocatorFromHeight returns the block locator object based on the height
// supplied as argument to the function.
//
// NOTE: Part of the BlockHeaderStore interface.
func (h *blockHeaderStore) BlockLocatorFromHeight(height uint32) (blockchain.BlockLocator, error) {
// Lock store for read.
h.mtx.RLock()
defer h.mtx.RUnlock()

blockheader, err := h.FetchHeaderByHeight(height)
if err != nil {
return nil, err
}

blockHash := blockheader.BlockHash()

return h.blockLocatorFromHash(&blockHash)
}

// BlockLocatorFromHash computes a block locator given a particular hash. The
// standard Bitcoin algorithm to compute block locators are employed.
func (h *blockHeaderStore) BlockLocatorFromHash(hash *chainhash.Hash) (
Expand Down
7 changes: 6 additions & 1 deletion headerlist/header_list.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package headerlist

import "github.com/btcsuite/btcd/wire"
import (
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
)

// Chain is an interface that stores a list of Nodes. Each node represents a
// header in the main chain and also includes a height along with it. This is
Expand Down Expand Up @@ -36,6 +39,8 @@ type Node struct {
Header wire.BlockHeader

prev *Node

HeaderHash chainhash.Hash
}

// Prev attempts to access the prior node within the header chain relative to
Expand Down
165 changes: 83 additions & 82 deletions mock_store.go
Original file line number Diff line number Diff line change
@@ -1,84 +1,85 @@
package neutrino

import (
"fmt"

"github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/lightninglabs/neutrino/headerfs"
)

// mockBlockHeaderStore is an implementation of the BlockHeaderStore backed by
// a simple map.
type mockBlockHeaderStore struct {
headers map[chainhash.Hash]wire.BlockHeader
heights map[uint32]wire.BlockHeader
}

// A compile-time check to ensure the mockBlockHeaderStore adheres to the
// BlockHeaderStore interface.
var _ headerfs.BlockHeaderStore = (*mockBlockHeaderStore)(nil)

// NewMockBlockHeaderStore returns a version of the BlockHeaderStore that's
// backed by an in-memory map. This instance is meant to be used by callers
// outside the package to unit test components that require a BlockHeaderStore
// interface.
func newMockBlockHeaderStore() *mockBlockHeaderStore {
return &mockBlockHeaderStore{
headers: make(map[chainhash.Hash]wire.BlockHeader),
heights: make(map[uint32]wire.BlockHeader),
}
}

func (m *mockBlockHeaderStore) ChainTip() (*wire.BlockHeader,
uint32, error) {

return nil, 0, nil
}
func (m *mockBlockHeaderStore) LatestBlockLocator() (
blockchain.BlockLocator, error) {

return nil, nil
}

func (m *mockBlockHeaderStore) FetchHeaderByHeight(height uint32) (
*wire.BlockHeader, error) {

if header, ok := m.heights[height]; ok {
return &header, nil
}

return nil, headerfs.ErrHeightNotFound
}

func (m *mockBlockHeaderStore) FetchHeaderAncestors(uint32,
*chainhash.Hash) ([]wire.BlockHeader, uint32, error) {

return nil, 0, nil
}
func (m *mockBlockHeaderStore) HeightFromHash(*chainhash.Hash) (uint32, error) {
return 0, nil
}
func (m *mockBlockHeaderStore) RollbackLastBlock() (*headerfs.BlockStamp,
error) {

return nil, nil
}

func (m *mockBlockHeaderStore) FetchHeader(h *chainhash.Hash) (
*wire.BlockHeader, uint32, error) {

if header, ok := m.headers[*h]; ok {
return &header, 0, nil
}
return nil, 0, fmt.Errorf("not found")
}

func (m *mockBlockHeaderStore) WriteHeaders(headers ...headerfs.BlockHeader) error {
for _, h := range headers {
m.headers[h.BlockHash()] = *h.BlockHeader
}

return nil
}
//
//import (
// "fmt"
//
// "github.com/btcsuite/btcd/blockchain"
// "github.com/btcsuite/btcd/chaincfg/chainhash"
// "github.com/btcsuite/btcd/wire"
// "github.com/lightninglabs/neutrino/headerfs"
//)
//
//// mockBlockHeaderStore is an implementation of the BlockHeaderStore backed by
//// a simple map.
//type mockBlockHeaderStore struct {
// headers map[chainhash.Hash]wire.BlockHeader
// heights map[uint32]wire.BlockHeader
//}
//
//// A compile-time check to ensure the mockBlockHeaderStore adheres to the
//// BlockHeaderStore interface.
//var _ headerfs.BlockHeaderStore = (*mockBlockHeaderStore)(nil)
//
//// NewMockBlockHeaderStore returns a version of the BlockHeaderStore that's
//// backed by an in-memory map. This instance is meant to be used by callers
//// outside the package to unit test components that require a BlockHeaderStore
//// interface.
//func newMockBlockHeaderStore() *mockBlockHeaderStore {
// return &mockBlockHeaderStore{
// headers: make(map[chainhash.Hash]wire.BlockHeader),
// heights: make(map[uint32]wire.BlockHeader),
// }
//}
//
//func (m *mockBlockHeaderStore) ChainTip() (*wire.BlockHeader,
// uint32, error) {
//
// return nil, 0, nil
//}
//func (m *mockBlockHeaderStore) LatestBlockLocator() (
// blockchain.BlockLocator, error) {
//
// return nil, nil
//}
//
//func (m *mockBlockHeaderStore) FetchHeaderByHeight(height uint32) (
// *wire.BlockHeader, error) {
//
// if header, ok := m.heights[height]; ok {
// return &header, nil
// }
//
// return nil, headerfs.ErrHeightNotFound
//}
//
//func (m *mockBlockHeaderStore) FetchHeaderAncestors(uint32,
// *chainhash.Hash) ([]wire.BlockHeader, uint32, error) {
//
// return nil, 0, nil
//}
//func (m *mockBlockHeaderStore) HeightFromHash(*chainhash.Hash) (uint32, error) {
// return 0, nil
//}
//func (m *mockBlockHeaderStore) RollbackLastBlock() (*headerfs.BlockStamp,
// error) {
//
// return nil, nil
//}
//
//func (m *mockBlockHeaderStore) FetchHeader(h *chainhash.Hash) (
// *wire.BlockHeader, uint32, error) {
//
// if header, ok := m.headers[*h]; ok {
// return &header, 0, nil
// }
// return nil, 0, fmt.Errorf("not found")
//}
//
//func (m *mockBlockHeaderStore) WriteHeaders(headers ...headerfs.BlockHeader) error {
// for _, h := range headers {
// m.headers[h.BlockHash()] = *h.BlockHeader
// }
//
// return nil
//}
36 changes: 36 additions & 0 deletions neutrino.go
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,41 @@ func (sp *ServerPeer) SubscribeRecvMsg() (<-chan wire.Message, func()) {
}
}

// TODO: Unexport HeaderQuery
func (sp *ServerPeer) QueryGetHeadersMsg(req interface{}) error {

queryGetHeaders, ok := req.(*HeaderQuery)

if !ok {
return errors.New("request is not type HeaderQuery")
}

err := sp.PushGetHeadersMsg(queryGetHeaders.Locator, queryGetHeaders.StopHash)

if err != nil {
return err
}

return nil
}

func (sp *ServerPeer) IsPeerBehindStartHeight(req interface{}) bool {
queryGetHeaders, ok := req.(*HeaderQuery)
if !ok {
log.Tracef("request is not type HeaderQuery")

return true
}
if sp.LastBlock() < queryGetHeaders.StartHeight {

return false

}

return true

}

// OnDisconnect returns a channel that will be closed when this peer is
// disconnected.
//
Expand Down Expand Up @@ -745,6 +780,7 @@ func NewChainService(cfg Config) (*ChainService, error) {
ConnectedPeers: s.ConnectedPeers,
NewWorker: query.NewWorker,
Ranking: query.NewPeerRanking(),
TestNewWorker: query.TestNewWorker,
})

// We set the queryPeers method to point to queryChainServicePeers,
Expand Down
43 changes: 43 additions & 0 deletions query/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,24 @@ type Request struct {
HandleResp func(req, resp wire.Message, peer string) Progress
}

type TestRequest struct {
// Req is the message request to send.
Req interface{}

// HandleResp is a response handler that will be called for every
// message received from the peer that the request was made to. It
// should validate the response against the request made, and return a
// Progress indicating whether the request was answered by this
// particular response.
//
// NOTE: Since the worker's job queue will be stalled while this method
// is running, it should not be doing any expensive operations. It
// should validate the response and immediately return the progress.
// The response should be handed off to another goroutine for
// processing.
HandleResp func(resp wire.Message, peer TestPeer, testReq *TestQueryJob) Progress
}

// Dispatcher is an interface defining the API for dispatching queries to
// bitcoin peers.
type Dispatcher interface {
Expand All @@ -120,6 +138,7 @@ type Dispatcher interface {
// batch of queries will be sent. Responses for the individual queries
// should be handled by the response handler of each Request.
Query(reqs []*Request, options ...QueryOption) chan error
TestQuery(reqs []*TestRequest, options ...QueryOption) chan error
}

// Peer is the interface that defines the methods needed by the query package
Expand All @@ -143,3 +162,27 @@ type Peer interface {
// disconnected.
OnDisconnect() <-chan struct{}
}

type TestPeer interface {
// QueueMessageWithEncoding adds the passed bitcoin message to the peer
// send queue.
QueueMessageWithEncoding(msg wire.Message, doneChan chan<- struct{},
encoding wire.MessageEncoding)

// SubscribeRecvMsg adds a OnRead subscription to the peer. All bitcoin
// messages received from this peer will be sent on the returned
// channel. A closure is also returned, that should be called to cancel
// the subscription.
SubscribeRecvMsg() (<-chan wire.Message, func())

// Addr returns the address of this peer.
Addr() string

// OnDisconnect returns a channel that will be closed when this peer is
// disconnected.
OnDisconnect() <-chan struct{}

QueryGetHeadersMsg(req interface{}) error

IsPeerBehindStartHeight(req interface{}) bool
}
Loading

0 comments on commit 7a8dac7

Please sign in to comment.