本文整理汇总了Golang中github.com/conformal/btcwire.NewInvVect函数的典型用法代码示例。如果您正苦于以下问题:Golang NewInvVect函数的具体用法?Golang NewInvVect怎么用?Golang NewInvVect使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了NewInvVect函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Golang代码示例。
示例1: handleBlockMsg
// handleBlockMsg is invoked when a peer receives a block bitcoin message. It
// blocks until the bitcoin block has been fully processed.
func (p *peer) handleBlockMsg(msg *btcwire.MsgBlock, buf []byte) {
// Convert the raw MsgBlock to a btcutil.Block which provides some
// convenience methods and things such as hash caching.
block := btcutil.NewBlockFromBlockAndBytes(msg, buf)
// Add the block to the known inventory for the peer.
hash, err := block.Sha()
if err != nil {
log.Errorf("Unable to get block hash: %v", err)
return
}
iv := btcwire.NewInvVect(btcwire.InvTypeBlock, hash)
p.addKnownInventory(iv)
// Queue the block up to be handled by the block
// manager and intentionally block further receives
// until the bitcoin block is fully processed and known
// good or bad. This helps prevent a malicious peer
// from queueing up a bunch of bad blocks before
// disconnecting (or being disconnected) and wasting
// memory. Additionally, this behavior is depended on
// by at least the block acceptance test tool as the
// reference implementation processes blocks in the same
// thread and therefore blocks further messages until
// the bitcoin block has been fully processed.
p.server.blockManager.QueueBlock(block, p)
<-p.blockProcessed
}
示例2: handleTxMsg
// handleTxMsg is invoked when a peer receives a tx bitcoin message. It blocks
// until the bitcoin transaction has been fully processed. Unlock the block
// handler this does not serialize all transactions through a single thread
// transactions don't rely on the previous one in a linear fashion like blocks.
func (p *peer) handleTxMsg(msg *btcwire.MsgTx) {
// Add the transaction to the known inventory for the peer.
hash, err := msg.TxSha()
if err != nil {
log.Errorf("Unable to get transaction hash: %v", err)
return
}
iv := btcwire.NewInvVect(btcwire.InvVect_Tx, &hash)
p.addKnownInventory(iv)
// Process the transaction.
err = p.server.txMemPool.ProcessTransaction(msg)
if err != nil {
// When the error is a rule error, it means the transaction was
// simply rejected as opposed to something actually going wrong,
// so log it as such. Otherwise, something really did go wrong,
// so log it as an actual error.
if _, ok := err.(TxRuleError); ok {
log.Infof("Rejected transaction %v: %v", hash, err)
} else {
log.Errorf("Failed to process transaction %v: %v", hash, err)
}
return
}
}
示例3: fetchHeaderBlocks
// fetchHeaderBlocks creates and sends a request to the syncPeer for the next
// list of blocks to be downloaded based on the current list of headers.
func (b *blockManager) fetchHeaderBlocks() {
// Nothing to do if there is no start header.
if b.startHeader == nil {
bmgrLog.Warnf("fetchHeaderBlocks called with no start header")
return
}
// Build up a getdata request for the list of blocks the headers
// describe. The size hint will be limited to btcwire.MaxInvPerMsg by
// the function, so no need to double check it here.
gdmsg := btcwire.NewMsgGetDataSizeHint(uint(b.headerList.Len()))
numRequested := 0
for e := b.startHeader; e != nil; e = e.Next() {
node, ok := e.Value.(*headerNode)
if !ok {
bmgrLog.Warn("Header list node type is not a headerNode")
continue
}
iv := btcwire.NewInvVect(btcwire.InvTypeBlock, node.sha)
if !b.haveInventory(iv) {
b.requestedBlocks[*node.sha] = true
b.syncPeer.requestedBlocks[*node.sha] = true
gdmsg.AddInvVect(iv)
numRequested++
}
b.startHeader = e.Next()
if numRequested >= btcwire.MaxInvPerMsg {
break
}
}
if len(gdmsg.InvList) > 0 {
b.syncPeer.QueueMessage(gdmsg, nil)
}
}
示例4: handleMemPoolMsg
// handleMemPoolMsg is invoked when a peer receives a mempool bitcoin message.
// It creates and sends an inventory message with the contents of the memory
// pool up to the maximum inventory allowed per message.
func (p *peer) handleMemPoolMsg(msg *btcwire.MsgMemPool) {
// Generate inventory message with the available transactions in the
// transaction memory pool. Limit it to the max allowed inventory
// per message. The the NewMsgInvSizeHint function automatically limits
// the passed hint to the maximum allowed, so it's safe to pass it
// without double checking it here.
hashes := p.server.txMemPool.TxShas()
invMsg := btcwire.NewMsgInvSizeHint(uint(len(hashes)))
for i, hash := range hashes {
// Another thread might have removed the transaction from the
// pool since the initial query.
if !p.server.txMemPool.IsTransactionInPool(hash) {
continue
}
iv := btcwire.NewInvVect(btcwire.InvTypeTx, hash)
invMsg.AddInvVect(iv)
if i+1 >= btcwire.MaxInvPerMsg {
break
}
}
// Send the inventory message if there is anything to send.
if len(invMsg.InvList) > 0 {
p.QueueMessage(invMsg, nil)
}
}
示例5: TestInv
// TestInv tests the MsgInv API.
func TestInv(t *testing.T) {
pver := btcwire.ProtocolVersion
// Ensure the command is expected value.
wantCmd := "inv"
msg := btcwire.NewMsgInv()
if cmd := msg.Command(); cmd != wantCmd {
t.Errorf("NewMsgInv: wrong command - got %v want %v",
cmd, wantCmd)
}
// Ensure max payload is expected value for latest protocol version.
// Num inventory vectors (varInt) + max allowed inventory vectors.
wantPayload := uint32(1800009)
maxPayload := msg.MaxPayloadLength(pver)
if maxPayload != wantPayload {
t.Errorf("MaxPayloadLength: wrong max payload length for "+
"protocol version %d - got %v, want %v", pver,
maxPayload, wantPayload)
}
// Ensure inventory vectors are added properly.
hash := btcwire.ShaHash{}
iv := btcwire.NewInvVect(btcwire.InvTypeBlock, &hash)
err := msg.AddInvVect(iv)
if err != nil {
t.Errorf("AddInvVect: %v", err)
}
if msg.InvList[0] != iv {
t.Errorf("AddInvVect: wrong invvect added - got %v, want %v",
spew.Sprint(msg.InvList[0]), spew.Sprint(iv))
}
// Ensure adding more than the max allowed inventory vectors per
// message returns an error.
for i := 0; i < btcwire.MaxInvPerMsg; i++ {
err = msg.AddInvVect(iv)
}
if err == nil {
t.Errorf("AddInvVect: expected error on too many inventory " +
"vectors not received")
}
// Ensure creating the message with a size hint larger than the max
// works as expected.
msg = btcwire.NewMsgInvSizeHint(btcwire.MaxInvPerMsg + 1)
wantCap := btcwire.MaxInvPerMsg
if cap(msg.InvList) != wantCap {
t.Errorf("NewMsgInvSizeHint: wrong cap for size hint - "+
"got %v, want %v", cap(msg.InvList), wantCap)
}
return
}
示例6: pushBlockMsg
// pushBlockMsg sends a block message for the provided block hash to the
// connected peer. An error is returned if the block hash is not known.
func (p *peer) pushBlockMsg(sha *btcwire.ShaHash, doneChan chan bool) error {
// What should this function do about the rate limiting the
// number of blocks queued for this peer?
// Current thought is have a counting mutex in the peer
// such that if > N Tx/Block requests are currently in
// the tx queue, wait until the mutex clears allowing more to be
// sent. This prevents 500 1+MB blocks from being loaded into
// memory and sit around until the output queue drains.
// Actually the outputQueue has a limit of 50 in its queue
// but still 50MB to 1.6GB(50 32MB blocks) just setting
// in memory waiting to be sent is pointless.
// I would recommend a getdata request limit of about 5
// outstanding objects.
// Should the tx complete api be a mutex or channel?
blk, err := p.server.db.FetchBlockBySha(sha)
if err != nil {
log.Tracef("PEER: Unable to fetch requested block sha %v: %v",
sha, err)
return err
}
// We only send the channel for this message if we aren't sending
// an inv straight after.
var dc chan bool
sendInv := p.continueHash != nil && p.continueHash.IsEqual(sha)
if !sendInv {
dc = doneChan
}
p.QueueMessage(blk.MsgBlock(), dc)
// When the peer requests the final block that was advertised in
// response to a getblocks message which requested more blocks than
// would fit into a single message, send it a new inventory message
// to trigger it to issue another getblocks message for the next
// batch of inventory.
if p.continueHash != nil && p.continueHash.IsEqual(sha) {
hash, _, err := p.server.db.NewestSha()
if err == nil {
invMsg := btcwire.NewMsgInv()
iv := btcwire.NewInvVect(btcwire.InvTypeBlock, hash)
invMsg.AddInvVect(iv)
p.QueueMessage(invMsg, doneChan)
p.continueHash = nil
} else if doneChan != nil {
// Avoid deadlock when caller waits on channel.
go func() {
doneChan <- false
}()
}
}
return nil
}
示例7: processOrphans
// processOrphans determines if there are any orphans which depend on the passed
// transaction hash (they are no longer orphans if true) and potentially accepts
// them. It repeats the process for the newly accepted transactions (to detect
// further orphans which may no longer be orphans) until there are no more.
//
// This function MUST be called with the mempool lock held (for writes).
func (mp *txMemPool) processOrphans(hash *btcwire.ShaHash) error {
// Start with processing at least the passed hash.
processHashes := list.New()
processHashes.PushBack(hash)
for processHashes.Len() > 0 {
// Pop the first hash to process.
firstElement := processHashes.Remove(processHashes.Front())
processHash := firstElement.(*btcwire.ShaHash)
// Look up all orphans that are referenced by the transaction we
// just accepted. This will typically only be one, but it could
// be multiple if the referenced transaction contains multiple
// outputs. Skip to the next item on the list of hashes to
// process if there are none.
orphans, exists := mp.orphansByPrev[*processHash]
if !exists || orphans == nil {
continue
}
var enext *list.Element
for e := orphans.Front(); e != nil; e = enext {
enext = e.Next()
tx := e.Value.(*btcutil.Tx)
// Remove the orphan from the orphan pool.
orphanHash := tx.Sha()
mp.removeOrphan(orphanHash)
// Potentially accept the transaction into the
// transaction pool.
var isOrphan bool
err := mp.maybeAcceptTransaction(tx, &isOrphan, true, true)
if err != nil {
return err
}
if !isOrphan {
// Generate the inventory vector and relay it.
iv := btcwire.NewInvVect(btcwire.InvTypeTx, tx.Sha())
mp.server.RelayInventory(iv)
} else {
mp.removeOrphan(orphanHash)
}
// Add this transaction to the list of transactions to
// process so any orphans that depend on this one are
// handled too.
processHashes.PushBack(orphanHash)
}
}
return nil
}
示例8: ProcessTransaction
// ProcessTransaction is the main workhorse for handling insertion of new
// free-standing transactions into the memory pool. It includes functionality
// such as rejecting duplicate transactions, ensuring transactions follow all
// rules, orphan transaction handling, and insertion into the memory pool.
//
// This function is safe for concurrent access.
func (mp *txMemPool) ProcessTransaction(tx *btcutil.Tx, allowOrphan, rateLimit bool) error {
// Protect concurrent access.
mp.Lock()
defer mp.Unlock()
txmpLog.Tracef("Processing transaction %v", tx.Sha())
// Potentially accept the transaction to the memory pool.
var isOrphan bool
err := mp.maybeAcceptTransaction(tx, &isOrphan, true, rateLimit)
if err != nil {
return err
}
if !isOrphan {
// Generate the inventory vector and relay it.
iv := btcwire.NewInvVect(btcwire.InvTypeTx, tx.Sha())
mp.server.RelayInventory(iv)
// Accept any orphan transactions that depend on this
// transaction (they are no longer orphans) and repeat for those
// accepted transactions until there are no more.
err := mp.processOrphans(tx.Sha())
if err != nil {
return err
}
} else {
// The transaction is an orphan (has inputs missing). Reject
// it if the flag to allow orphans is not set.
if !allowOrphan {
// NOTE: RejectDuplicate is really not an accurate
// reject code here, but it matches the reference
// implementation and there isn't a better choice due
// to the limited number of reject codes. Missing
// inputs is assumed to mean they are already spent
// which is not really always the case.
return txRuleError(btcwire.RejectDuplicate,
"transaction spends unknown inputs")
}
// Potentially add the orphan transaction to the orphan pool.
err := mp.maybeAddOrphan(tx)
if err != nil {
return err
}
}
return nil
}
示例9: TestInvVect
// TestInvVect tests the InvVect API.
func TestInvVect(t *testing.T) {
ivType := btcwire.InvTypeBlock
hash := btcwire.ShaHash{}
// Ensure we get the same payload and signature back out.
iv := btcwire.NewInvVect(ivType, &hash)
if iv.Type != ivType {
t.Errorf("NewInvVect: wrong type - got %v, want %v",
iv.Type, ivType)
}
if !iv.Hash.IsEqual(&hash) {
t.Errorf("NewInvVect: wrong hash - got %v, want %v",
spew.Sdump(iv.Hash), spew.Sdump(hash))
}
}
示例10: handleTxMsg
// handleTxMsg is invoked when a peer receives a tx bitcoin message. It blocks
// until the bitcoin transaction has been fully processed. Unlock the block
// handler this does not serialize all transactions through a single thread
// transactions don't rely on the previous one in a linear fashion like blocks.
func (p *peer) handleTxMsg(msg *btcwire.MsgTx) {
// Add the transaction to the known inventory for the peer.
// Convert the raw MsgTx to a btcutil.Tx which provides some convenience
// methods and things such as hash caching.
tx := btcutil.NewTx(msg)
iv := btcwire.NewInvVect(btcwire.InvTypeTx, tx.Sha())
p.addKnownInventory(iv)
// Queue the transaction up to be handled by the block manager and
// intentionally block further receives until the transaction is fully
// processed and known good or bad. This helps prevent a malicious peer
// from queueing up a bunch of bad transactions before disconnecting (or
// being disconnected) and wasting memory.
p.server.blockManager.QueueTx(tx, p)
<-p.txProcessed
}
示例11: handleSendRawTransaction
// handleSendRawTransaction implements the sendrawtransaction command.
func handleSendRawTransaction(s *rpcServer, cmd btcjson.Cmd) (interface{}, error) {
c := cmd.(*btcjson.SendRawTransactionCmd)
// Deserialize and send off to tx relay
serializedTx, err := hex.DecodeString(c.HexTx)
if err != nil {
return nil, btcjson.ErrDecodeHexString
}
msgtx := btcwire.NewMsgTx()
err = msgtx.Deserialize(bytes.NewBuffer(serializedTx))
if err != nil {
err := btcjson.Error{
Code: btcjson.ErrDeserialization.Code,
Message: "TX decode failed",
}
return nil, err
}
tx := btcutil.NewTx(msgtx)
err = s.server.txMemPool.ProcessTransaction(tx, false)
if err != nil {
// When the error is a rule error, it means the transaction was
// simply rejected as opposed to something actually going wrong,
// so log it as such. Otherwise, something really did go wrong,
// so log it as an actual error. In both cases, a JSON-RPC
// error is returned to the client with the deserialization
// error code (to match bitcoind behavior).
if _, ok := err.(TxRuleError); ok {
rpcsLog.Debugf("Rejected transaction %v: %v", tx.Sha(),
err)
} else {
rpcsLog.Errorf("Failed to process transaction %v: %v",
tx.Sha(), err)
}
err = btcjson.Error{
Code: btcjson.ErrDeserialization.Code,
Message: fmt.Sprintf("TX rejected: %v", err),
}
return nil, err
}
// We keep track of all the sendrawtransaction request txs so that we
// can rebroadcast them if they don't make their way into a block.
iv := btcwire.NewInvVect(btcwire.InvTypeTx, tx.Sha())
s.server.AddRebroadcastInventory(iv)
return tx.Sha().String(), nil
}
示例12: pushBlockMsg
// pushBlockMsg sends a block message for the provided block hash to the
// connected peer. An error is returned if the block hash is not known.
func (p *peer) pushBlockMsg(sha *btcwire.ShaHash, doneChan, waitChan chan bool) error {
blk, err := p.server.db.FetchBlockBySha(sha)
if err != nil {
peerLog.Tracef("Unable to fetch requested block sha %v: %v",
sha, err)
return err
}
// Once we have fetched data wait for any previous operation to finish.
if waitChan != nil {
<-waitChan
}
// We only send the channel for this message if we aren't sending
// an inv straight after.
var dc chan bool
sendInv := p.continueHash != nil && p.continueHash.IsEqual(sha)
if !sendInv {
dc = doneChan
}
p.QueueMessage(blk.MsgBlock(), dc)
// When the peer requests the final block that was advertised in
// response to a getblocks message which requested more blocks than
// would fit into a single message, send it a new inventory message
// to trigger it to issue another getblocks message for the next
// batch of inventory.
if p.continueHash != nil && p.continueHash.IsEqual(sha) {
hash, _, err := p.server.db.NewestSha()
if err == nil {
invMsg := btcwire.NewMsgInv()
iv := btcwire.NewInvVect(btcwire.InvTypeBlock, hash)
invMsg.AddInvVect(iv)
p.QueueMessage(invMsg, doneChan)
p.continueHash = nil
} else if doneChan != nil {
// Avoid deadlock when caller waits on channel.
go func() {
doneChan <- false
}()
}
}
return nil
}
示例13: handleMemPoolMsg
// handleMemPoolMsg is invoked when a peer receives a mempool bitcoin message.
// It creates and sends an inventory message with the contents of the memory
// pool up to the maximum inventory allowed per message.
func (p *peer) handleMemPoolMsg(msg *btcwire.MsgMemPool) {
// Generate inventory message with the available transactions in the
// transaction memory pool. Limit it to the max allowed inventory
// per message.
invMsg := btcwire.NewMsgInv()
hashes := p.server.txMemPool.TxShas()
for i, hash := range hashes {
iv := btcwire.NewInvVect(btcwire.InvTypeTx, hash)
invMsg.AddInvVect(iv)
if i+1 >= btcwire.MaxInvPerMsg {
break
}
}
// Send the inventory message if there is anything to send.
if len(invMsg.InvList) > 0 {
p.QueueMessage(invMsg, nil)
}
}
示例14: ProcessTransaction
// ProcessTransaction is the main workhorse for handling insertion of new
// free-standing transactions into the memory pool. It includes functionality
// such as rejecting duplicate transactions, ensuring transactions follow all
// rules, orphan transaction handling, and insertion into the memory pool.
//
// This function is safe for concurrent access.
func (mp *txMemPool) ProcessTransaction(tx *btcutil.Tx, allowOrphan, rateLimit bool) error {
// Protect concurrent access.
mp.Lock()
defer mp.Unlock()
txmpLog.Tracef("Processing transaction %v", tx.Sha())
// Potentially accept the transaction to the memory pool.
var isOrphan bool
err := mp.maybeAcceptTransaction(tx, &isOrphan, true, rateLimit)
if err != nil {
return err
}
if !isOrphan {
// Generate the inventory vector and relay it.
iv := btcwire.NewInvVect(btcwire.InvTypeTx, tx.Sha())
mp.server.RelayInventory(iv)
// Accept any orphan transactions that depend on this
// transaction (they are no longer orphans) and repeat for those
// accepted transactions until there are no more.
err := mp.processOrphans(tx.Sha())
if err != nil {
return err
}
} else {
// The transaction is an orphan (has inputs missing). Reject
// it if the flag to allow orphans is not set.
if !allowOrphan {
return TxRuleError("transaction spends unknown inputs")
}
// Potentially add the orphan transaction to the orphan pool.
err := mp.maybeAddOrphan(tx)
if err != nil {
return err
}
}
return nil
}
示例15: fetchHeaderBlocks
// fetchHeaderBlocks is creates and sends a request to the syncPeer for
// the next list of blocks to be downloaded.
func (b *blockManager) fetchHeaderBlocks() {
gdmsg := btcwire.NewMsgGetDataSizeHint(btcwire.MaxInvPerMsg)
numRequested := 0
startBlock := b.startBlock
for {
if b.startBlock == nil {
break
}
blockHash := b.startBlock
firstblock, ok := b.headerPool[*blockHash]
if !ok {
bmgrLog.Warnf("current fetch block %v missing from headerPool", blockHash)
break
}
iv := btcwire.NewInvVect(btcwire.InvTypeBlock, blockHash)
if !b.haveInventory(iv) {
b.requestedBlocks[*blockHash] = true
b.syncPeer.requestedBlocks[*blockHash] = true
gdmsg.AddInvVect(iv)
numRequested++
}
if b.fetchBlock == nil {
b.fetchBlock = b.startBlock
}
if firstblock.next == nil {
b.startBlock = nil
break
} else {
b.startBlock = &firstblock.next.sha
}
if numRequested >= btcwire.MaxInvPerMsg {
break
}
}
if len(gdmsg.InvList) > 0 {
bmgrLog.Debugf("requesting block %v len %v\n", startBlock, len(gdmsg.InvList))
b.syncPeer.QueueMessage(gdmsg, nil)
}
}