add a height channel to keep track of incoming merkleblocks
This commit is contained in:
parent
ece5dc9d2d
commit
58c8d32ac5
@ -38,8 +38,11 @@ type SPVCon struct {
|
|||||||
WBytes uint64 // total bytes written
|
WBytes uint64 // total bytes written
|
||||||
RBytes uint64 // total bytes read
|
RBytes uint64 // total bytes read
|
||||||
|
|
||||||
TS *TxStore
|
TS *TxStore // transaction store to write to
|
||||||
param *chaincfg.Params
|
param *chaincfg.Params // network parameters (testnet3, testnetL)
|
||||||
|
|
||||||
|
// mBlockQueue is for keeping track of what height we've requested.
|
||||||
|
mBlockQueue chan RootAndHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
func OpenSPV(remoteNode string, hfn string,
|
func OpenSPV(remoteNode string, hfn string,
|
||||||
@ -114,7 +117,7 @@ func OpenSPV(remoteNode string, hfn string,
|
|||||||
go s.incomingMessageHandler()
|
go s.incomingMessageHandler()
|
||||||
s.outMsgQueue = make(chan wire.Message)
|
s.outMsgQueue = make(chan wire.Message)
|
||||||
go s.outgoingMessageHandler()
|
go s.outgoingMessageHandler()
|
||||||
|
s.mBlockQueue = make(chan RootAndHeight, 10) // queue of 10 requests? more?
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,27 +322,52 @@ func (s *SPVCon) IngestHeaders(m *wire.MsgHeaders) (bool, error) {
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RootAndHeight is needed instead of just height in case a fullnode
|
||||||
|
// responds abnormally (?) by sending out of order merkleblocks.
|
||||||
|
// we cache a merkleroot:height pair in the queue so we don't have to
|
||||||
|
// look them up from the disk.
|
||||||
|
type RootAndHeight struct {
|
||||||
|
root wire.ShaHash
|
||||||
|
height uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRootAndHeight saves like 2 lines.
|
||||||
|
func NewRootAndHeight(r wire.ShaHash, h uint32) (rah RootAndHeight) {
|
||||||
|
rah.root = r
|
||||||
|
rah.height = h
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// AskForMerkBlocks requests blocks from current to last
|
||||||
|
// right now this asks for 1 block per getData message.
|
||||||
|
// Maybe it's faster to ask for many in a each message?
|
||||||
func (s *SPVCon) AskForMerkBlocks(current, last uint32) error {
|
func (s *SPVCon) AskForMerkBlocks(current, last uint32) error {
|
||||||
var hdr wire.BlockHeader
|
var hdr wire.BlockHeader
|
||||||
_, err := s.headerFile.Seek(int64(current*80), os.SEEK_SET)
|
_, err := s.headerFile.Seek(int64(current*80), os.SEEK_SET)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// loop through all heights where we want merkleblocks.
|
||||||
for current < last {
|
for current < last {
|
||||||
|
// load header from file
|
||||||
err = hdr.Deserialize(s.headerFile)
|
err = hdr.Deserialize(s.headerFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
current++
|
|
||||||
|
|
||||||
bHash := hdr.BlockSha()
|
bHash := hdr.BlockSha()
|
||||||
|
// create inventory we're asking for
|
||||||
iv1 := wire.NewInvVect(wire.InvTypeFilteredBlock, &bHash)
|
iv1 := wire.NewInvVect(wire.InvTypeFilteredBlock, &bHash)
|
||||||
gdataMsg := wire.NewMsgGetData()
|
gdataMsg := wire.NewMsgGetData()
|
||||||
|
// add inventory
|
||||||
err = gdataMsg.AddInvVect(iv1)
|
err = gdataMsg.AddInvVect(iv1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
rah := NewRootAndHeight(hdr.MerkleRoot, current)
|
||||||
s.outMsgQueue <- gdataMsg
|
s.outMsgQueue <- gdataMsg
|
||||||
|
s.mBlockQueue <- rah // push height and mroot of requested block on queue
|
||||||
|
current++
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -43,22 +43,26 @@ func (s *SPVCon) incomingMessageHandler() {
|
|||||||
fmt.Printf(" got %d txs ", len(txids))
|
fmt.Printf(" got %d txs ", len(txids))
|
||||||
// fmt.Printf(" = got %d txs from block %s\n",
|
// fmt.Printf(" = got %d txs from block %s\n",
|
||||||
// len(txids), m.Header.BlockSha().String())
|
// len(txids), m.Header.BlockSha().String())
|
||||||
var height uint32
|
// var height uint32
|
||||||
if len(txids) > 0 {
|
// if len(txids) > 0 {
|
||||||
// make sure block is in our store before adding txs
|
// make sure block is in our store before adding txs
|
||||||
height, err = s.HeightFromHeader(m.Header)
|
// height, err = s.HeightFromHeader(m.Header)
|
||||||
if err != nil {
|
// height = 20000
|
||||||
log.Printf("Merkle block height error: %s\n", err.Error())
|
// if err != nil {
|
||||||
continue
|
//log.Printf("Merkle block height error: %s\n", err.Error())
|
||||||
}
|
// continue
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
rah := <-s.mBlockQueue // pop height off mblock queue
|
||||||
|
if !rah.root.IsEqual(&m.Header.MerkleRoot) {
|
||||||
|
log.Printf("out of order error")
|
||||||
}
|
}
|
||||||
for _, txid := range txids {
|
for _, txid := range txids {
|
||||||
err := s.TS.AddTxid(txid, height)
|
err := s.TS.AddTxid(txid, rah.height)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Txid store error: %s\n", err.Error())
|
log.Printf("Txid store error: %s\n", err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// nextReq <- true
|
|
||||||
|
|
||||||
case *wire.MsgHeaders:
|
case *wire.MsgHeaders:
|
||||||
moar, err := s.IngestHeaders(m)
|
moar, err := s.IngestHeaders(m)
|
||||||
|
@ -51,6 +51,7 @@ func (t *TxStore) AddTxid(txid *wire.ShaHash, height uint32) error {
|
|||||||
if txid == nil {
|
if txid == nil {
|
||||||
return fmt.Errorf("tried to add nil txid")
|
return fmt.Errorf("tried to add nil txid")
|
||||||
}
|
}
|
||||||
|
log.Printf("added %s at height %d\n", txid.String(), height)
|
||||||
t.OKTxids[*txid] = height
|
t.OKTxids[*txid] = height
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user