Convert to use new btcutil.Tx and btcchain APIs.
This commit updates btcd to work with the new btcchain APIs which now accept btcutil.Tx instead of raw btcwire.MsgTx. It also modifies the transaction memory pool to store btcutil.Tx. This is part of the ongoing transaction hash optimization effort noted in conformal/btcd#25.
This commit is contained in:
parent
7d8bb5ab4c
commit
08fc3050a3
4 changed files with 84 additions and 95 deletions
|
@ -55,7 +55,7 @@ type donePeerMsg struct {
|
|||
// txMsg packages a bitcoin tx message and the peer it came from together
|
||||
// so the block handler has access to that information.
|
||||
type txMsg struct {
|
||||
tx *btcwire.MsgTx
|
||||
tx *btcutil.Tx
|
||||
peer *peer
|
||||
}
|
||||
|
||||
|
@ -269,12 +269,12 @@ func (b *blockManager) logBlockHeight(numTx, height int64, latestHash *btcwire.S
|
|||
// handleTxMsg handles transaction messages from all peers.
|
||||
func (b *blockManager) handleTxMsg(tmsg *txMsg) {
|
||||
// Keep track of which peer the tx was sent from.
|
||||
txHash, _ := tmsg.tx.TxSha()
|
||||
txHash := tmsg.tx.Sha()
|
||||
|
||||
// If we didn't ask for this block then the peer is misbehaving.
|
||||
if _, ok := tmsg.peer.requestedTxns[txHash]; !ok {
|
||||
if _, ok := tmsg.peer.requestedTxns[*txHash]; !ok {
|
||||
log.Warnf("BMGR: Got unrequested transaction %v from %s -- "+
|
||||
"disconnecting", &txHash, tmsg.peer.addr)
|
||||
"disconnecting", txHash, tmsg.peer.addr)
|
||||
tmsg.peer.Disconnect()
|
||||
return
|
||||
}
|
||||
|
@ -287,8 +287,8 @@ func (b *blockManager) handleTxMsg(tmsg *txMsg) {
|
|||
// already knows about it and as such we shouldn't have any more
|
||||
// instances of trying to fetch it, or we failed to insert and thus
|
||||
// we'll retry next time we get an inv.
|
||||
delete(tmsg.peer.requestedTxns, txHash)
|
||||
delete(b.requestedTxns, txHash)
|
||||
delete(tmsg.peer.requestedTxns, *txHash)
|
||||
delete(b.requestedTxns, *txHash)
|
||||
|
||||
if err != nil {
|
||||
// When the error is a rule error, it means the transaction was
|
||||
|
@ -646,7 +646,7 @@ func (b *blockManager) handleNotifyMsg(notification *btcchain.Notification) {
|
|||
|
||||
// Remove all of the transactions (except the coinbase) in the
|
||||
// connected block from the transaction pool.
|
||||
for _, tx := range block.MsgBlock().Transactions[1:] {
|
||||
for _, tx := range block.Transactions()[1:] {
|
||||
b.server.txMemPool.removeTransaction(tx)
|
||||
}
|
||||
|
||||
|
@ -666,7 +666,7 @@ func (b *blockManager) handleNotifyMsg(notification *btcchain.Notification) {
|
|||
|
||||
// Reinsert all of the transactions (except the coinbase) into
|
||||
// the transaction pool.
|
||||
for _, tx := range block.MsgBlock().Transactions[1:] {
|
||||
for _, tx := range block.Transactions()[1:] {
|
||||
err := b.server.txMemPool.ProcessTransaction(tx)
|
||||
if err != nil {
|
||||
// Remove the transaction and all transactions
|
||||
|
@ -695,7 +695,7 @@ func (b *blockManager) NewPeer(p *peer) {
|
|||
|
||||
// QueueTx adds the passed transaction message and peer to the block handling
|
||||
// queue.
|
||||
func (b *blockManager) QueueTx(tx *btcwire.MsgTx, p *peer) {
|
||||
func (b *blockManager) QueueTx(tx *btcutil.Tx, p *peer) {
|
||||
// Don't accept more transactions if we're shutting down.
|
||||
if atomic.LoadInt32(&b.shutdown) != 0 {
|
||||
p.txProcessed <- false
|
||||
|
|
131
mempool.go
131
mempool.go
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/conformal/btcchain"
|
||||
"github.com/conformal/btcdb"
|
||||
"github.com/conformal/btcscript"
|
||||
"github.com/conformal/btcutil"
|
||||
"github.com/conformal/btcwire"
|
||||
"math"
|
||||
"math/big"
|
||||
|
@ -77,10 +78,10 @@ const (
|
|||
type txMemPool struct {
|
||||
sync.RWMutex
|
||||
server *server
|
||||
pool map[btcwire.ShaHash]*btcwire.MsgTx
|
||||
orphans map[btcwire.ShaHash]*btcwire.MsgTx
|
||||
pool map[btcwire.ShaHash]*btcutil.Tx
|
||||
orphans map[btcwire.ShaHash]*btcutil.Tx
|
||||
orphansByPrev map[btcwire.ShaHash]*list.List
|
||||
outpoints map[btcwire.OutPoint]*btcwire.MsgTx
|
||||
outpoints map[btcwire.OutPoint]*btcutil.Tx
|
||||
}
|
||||
|
||||
// isDust returns whether or not the passed transaction output amount is
|
||||
|
@ -191,11 +192,13 @@ func checkPkScriptStandard(pkScript []byte) error {
|
|||
// finalized, conforming to more stringent size constraints, having scripts
|
||||
// of recognized forms, and not containing "dust" outputs (those that are
|
||||
// so small it costs more to process them than they are worth).
|
||||
func checkTransactionStandard(tx *btcwire.MsgTx, height int64) error {
|
||||
func checkTransactionStandard(tx *btcutil.Tx, height int64) error {
|
||||
msgTx := tx.MsgTx()
|
||||
|
||||
// The transaction must be a currently supported version.
|
||||
if tx.Version > btcwire.TxVersion || tx.Version < 1 {
|
||||
if msgTx.Version > btcwire.TxVersion || msgTx.Version < 1 {
|
||||
str := fmt.Sprintf("transaction version %d is not in the "+
|
||||
"valid range of %d-%d", tx.Version, 1,
|
||||
"valid range of %d-%d", msgTx.Version, 1,
|
||||
btcwire.TxVersion)
|
||||
return TxRuleError(str)
|
||||
}
|
||||
|
@ -212,7 +215,7 @@ func checkTransactionStandard(tx *btcwire.MsgTx, height int64) error {
|
|||
// size of a transaction. This also helps mitigate CPU exhaustion
|
||||
// attacks.
|
||||
var serializedTxBuf bytes.Buffer
|
||||
err := tx.Serialize(&serializedTxBuf)
|
||||
err := msgTx.Serialize(&serializedTxBuf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -223,7 +226,7 @@ func checkTransactionStandard(tx *btcwire.MsgTx, height int64) error {
|
|||
return TxRuleError(str)
|
||||
}
|
||||
|
||||
for i, txIn := range tx.TxIn {
|
||||
for i, txIn := range msgTx.TxIn {
|
||||
// Each transaction input signature script must not exceed the
|
||||
// maximum size allowed for a standard transaction. See
|
||||
// the comment on maxStandardSigScriptSize for more details.
|
||||
|
@ -247,7 +250,7 @@ func checkTransactionStandard(tx *btcwire.MsgTx, height int64) error {
|
|||
|
||||
// None of the output public key scripts can be a non-standard script or
|
||||
// be "dust".
|
||||
for i, txOut := range tx.TxOut {
|
||||
for i, txOut := range msgTx.TxOut {
|
||||
err := checkPkScriptStandard(txOut.PkScript)
|
||||
if err != nil {
|
||||
str := fmt.Sprintf("transaction output %d: %v", i, err)
|
||||
|
@ -270,7 +273,7 @@ func checkTransactionStandard(tx *btcwire.MsgTx, height int64) error {
|
|||
// pushes. This help prevent resource exhaustion attacks by "creative" use of
|
||||
// scripts that are super expensive to process like OP_DUP OP_CHECKSIG OP_DROP
|
||||
// repeated a large number of times followed by a final OP_TRUE.
|
||||
func checkInputsStandard(tx *btcwire.MsgTx) error {
|
||||
func checkInputsStandard(tx *btcutil.Tx) error {
|
||||
// TODO(davec): Implement
|
||||
return nil
|
||||
}
|
||||
|
@ -287,11 +290,11 @@ func (mp *txMemPool) removeOrphan(txHash *btcwire.ShaHash) {
|
|||
}
|
||||
|
||||
// Remove the reference from the previous orphan index.
|
||||
for _, txIn := range tx.TxIn {
|
||||
for _, txIn := range tx.MsgTx().TxIn {
|
||||
originTxHash := txIn.PreviousOutpoint.Hash
|
||||
if orphans, exists := mp.orphansByPrev[originTxHash]; exists {
|
||||
for e := orphans.Front(); e != nil; e = e.Next() {
|
||||
if e.Value.(*btcwire.MsgTx) == tx {
|
||||
if e.Value.(*btcutil.Tx) == tx {
|
||||
orphans.Remove(e)
|
||||
break
|
||||
}
|
||||
|
@ -349,13 +352,13 @@ func (mp *txMemPool) limitNumOrphans() error {
|
|||
// addOrphan adds an orphan transaction to the orphan pool.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for writes).
|
||||
func (mp *txMemPool) addOrphan(tx *btcwire.MsgTx, txHash *btcwire.ShaHash) {
|
||||
func (mp *txMemPool) addOrphan(tx *btcutil.Tx) {
|
||||
// Limit the number orphan transactions to prevent memory exhaustion. A
|
||||
// random orphan is evicted to make room if needed.
|
||||
mp.limitNumOrphans()
|
||||
|
||||
mp.orphans[*txHash] = tx
|
||||
for _, txIn := range tx.TxIn {
|
||||
mp.orphans[*tx.Sha()] = tx
|
||||
for _, txIn := range tx.MsgTx().TxIn {
|
||||
originTxHash := txIn.PreviousOutpoint.Hash
|
||||
if mp.orphansByPrev[originTxHash] == nil {
|
||||
mp.orphansByPrev[originTxHash] = list.New()
|
||||
|
@ -363,14 +366,14 @@ func (mp *txMemPool) addOrphan(tx *btcwire.MsgTx, txHash *btcwire.ShaHash) {
|
|||
mp.orphansByPrev[originTxHash].PushBack(tx)
|
||||
}
|
||||
|
||||
log.Debugf("TXMP: Stored orphan transaction %v (total: %d)", txHash,
|
||||
log.Debugf("TXMP: Stored orphan transaction %v (total: %d)", tx.Sha(),
|
||||
len(mp.orphans))
|
||||
}
|
||||
|
||||
// maybeAddOrphan potentially adds an orphan to the orphan pool.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for writes).
|
||||
func (mp *txMemPool) maybeAddOrphan(tx *btcwire.MsgTx, txHash *btcwire.ShaHash) error {
|
||||
func (mp *txMemPool) maybeAddOrphan(tx *btcutil.Tx) error {
|
||||
// Ignore orphan transactions that are too large. This helps avoid
|
||||
// a memory exhaustion attack based on sending a lot of really large
|
||||
// orphans. In the case there is a valid transaction larger than this,
|
||||
|
@ -382,7 +385,7 @@ func (mp *txMemPool) maybeAddOrphan(tx *btcwire.MsgTx, txHash *btcwire.ShaHash)
|
|||
// maxOrphanTxSize * maxOrphanTransactions (which is 500MB as of the
|
||||
// time this comment was written).
|
||||
var serializedTxBuf bytes.Buffer
|
||||
err := tx.Serialize(&serializedTxBuf)
|
||||
err := tx.MsgTx().Serialize(&serializedTxBuf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -395,7 +398,7 @@ func (mp *txMemPool) maybeAddOrphan(tx *btcwire.MsgTx, txHash *btcwire.ShaHash)
|
|||
}
|
||||
|
||||
// Add the orphan if the none of the above disqualified it.
|
||||
mp.addOrphan(tx, txHash)
|
||||
mp.addOrphan(tx)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -471,11 +474,11 @@ func (mp *txMemPool) HaveTransaction(hash *btcwire.ShaHash) bool {
|
|||
// removeTransaction removes the passed transaction from the memory pool.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for writes).
|
||||
func (mp *txMemPool) removeTransaction(tx *btcwire.MsgTx) {
|
||||
func (mp *txMemPool) removeTransaction(tx *btcutil.Tx) {
|
||||
// Remove any transactions which rely on this one.
|
||||
txHash, _ := tx.TxSha()
|
||||
for i := uint32(0); i < uint32(len(tx.TxOut)); i++ {
|
||||
outpoint := btcwire.NewOutPoint(&txHash, i)
|
||||
txHash := tx.Sha()
|
||||
for i := uint32(0); i < uint32(len(tx.MsgTx().TxOut)); i++ {
|
||||
outpoint := btcwire.NewOutPoint(txHash, i)
|
||||
if txRedeemer, exists := mp.outpoints[*outpoint]; exists {
|
||||
mp.removeTransaction(txRedeemer)
|
||||
}
|
||||
|
@ -483,11 +486,11 @@ func (mp *txMemPool) removeTransaction(tx *btcwire.MsgTx) {
|
|||
|
||||
// Remove the transaction and mark the referenced outpoints as unspent
|
||||
// by the pool.
|
||||
if tx, exists := mp.pool[txHash]; exists {
|
||||
for _, txIn := range tx.TxIn {
|
||||
if tx, exists := mp.pool[*txHash]; exists {
|
||||
for _, txIn := range tx.MsgTx().TxIn {
|
||||
delete(mp.outpoints, txIn.PreviousOutpoint)
|
||||
}
|
||||
delete(mp.pool, txHash)
|
||||
delete(mp.pool, *txHash)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -496,11 +499,11 @@ func (mp *txMemPool) removeTransaction(tx *btcwire.MsgTx) {
|
|||
// helper for maybeAcceptTransaction.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for writes).
|
||||
func (mp *txMemPool) addTransaction(tx *btcwire.MsgTx, txHash *btcwire.ShaHash) {
|
||||
func (mp *txMemPool) addTransaction(tx *btcutil.Tx) {
|
||||
// Add the transaction to the pool and mark the referenced outpoints
|
||||
// as spent by the pool.
|
||||
mp.pool[*txHash] = tx
|
||||
for _, txIn := range tx.TxIn {
|
||||
mp.pool[*tx.Sha()] = tx
|
||||
for _, txIn := range tx.MsgTx().TxIn {
|
||||
mp.outpoints[txIn.PreviousOutpoint] = tx
|
||||
}
|
||||
}
|
||||
|
@ -511,12 +514,11 @@ func (mp *txMemPool) addTransaction(tx *btcwire.MsgTx, txHash *btcwire.ShaHash)
|
|||
// main chain.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for reads).
|
||||
func (mp *txMemPool) checkPoolDoubleSpend(tx *btcwire.MsgTx) error {
|
||||
for _, txIn := range tx.TxIn {
|
||||
func (mp *txMemPool) checkPoolDoubleSpend(tx *btcutil.Tx) error {
|
||||
for _, txIn := range tx.MsgTx().TxIn {
|
||||
if txR, exists := mp.outpoints[txIn.PreviousOutpoint]; exists {
|
||||
hash, _ := txR.TxSha()
|
||||
str := fmt.Sprintf("transaction %v in the pool "+
|
||||
"already spends the same coins", hash)
|
||||
"already spends the same coins", txR.Sha())
|
||||
return TxRuleError(str)
|
||||
}
|
||||
}
|
||||
|
@ -529,7 +531,7 @@ func (mp *txMemPool) checkPoolDoubleSpend(tx *btcwire.MsgTx) error {
|
|||
// fetch any missing inputs from the transaction pool.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for reads).
|
||||
func (mp *txMemPool) fetchInputTransactions(tx *btcwire.MsgTx) (btcchain.TxStore, error) {
|
||||
func (mp *txMemPool) fetchInputTransactions(tx *btcutil.Tx) (btcchain.TxStore, error) {
|
||||
txStore, err := mp.server.blockManager.blockChain.FetchTransactionStore(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -541,7 +543,7 @@ func (mp *txMemPool) fetchInputTransactions(tx *btcwire.MsgTx) (btcchain.TxStore
|
|||
if poolTx, exists := mp.pool[*txD.Hash]; exists {
|
||||
txD.Tx = poolTx
|
||||
txD.BlockHeight = mempoolHeight
|
||||
txD.Spent = make([]bool, len(poolTx.TxOut))
|
||||
txD.Spent = make([]bool, len(poolTx.MsgTx().TxOut))
|
||||
txD.Err = nil
|
||||
}
|
||||
}
|
||||
|
@ -555,7 +557,7 @@ func (mp *txMemPool) fetchInputTransactions(tx *btcwire.MsgTx) (btcchain.TxStore
|
|||
// orphans.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) FetchTransaction(txHash *btcwire.ShaHash) (*btcwire.MsgTx, error) {
|
||||
func (mp *txMemPool) FetchTransaction(txHash *btcwire.ShaHash) (*btcutil.Tx, error) {
|
||||
// Protect concurrent access.
|
||||
mp.RLock()
|
||||
defer mp.RUnlock()
|
||||
|
@ -573,17 +575,14 @@ func (mp *txMemPool) FetchTransaction(txHash *btcwire.ShaHash) (*btcwire.MsgTx,
|
|||
// rules, orphan transaction handling, and insertion into the memory pool.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for writes).
|
||||
func (mp *txMemPool) maybeAcceptTransaction(tx *btcwire.MsgTx, isOrphan *bool) error {
|
||||
func (mp *txMemPool) maybeAcceptTransaction(tx *btcutil.Tx, isOrphan *bool) error {
|
||||
*isOrphan = false
|
||||
txHash, err := tx.TxSha()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
txHash := tx.Sha()
|
||||
|
||||
// Don't accept the transaction if it already exists in the pool. This
|
||||
// applies to orphan transactions as well. This check is intended to
|
||||
// be a quick check to weed out duplicates.
|
||||
if mp.haveTransaction(&txHash) {
|
||||
if mp.haveTransaction(txHash) {
|
||||
str := fmt.Sprintf("already have transaction %v", txHash)
|
||||
return TxRuleError(str)
|
||||
}
|
||||
|
@ -591,7 +590,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcwire.MsgTx, isOrphan *bool) e
|
|||
// Perform preliminary sanity checks on the transaction. This makes
|
||||
// use of btcchain which contains the invariant rules for what
|
||||
// transactions are allowed into blocks.
|
||||
err = btcchain.CheckTransactionSanity(tx)
|
||||
err := btcchain.CheckTransactionSanity(tx)
|
||||
if err != nil {
|
||||
if _, ok := err.(btcchain.RuleError); ok {
|
||||
return TxRuleError(err.Error())
|
||||
|
@ -610,7 +609,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcwire.MsgTx, isOrphan *bool) e
|
|||
// value for now. This is an artifact of older bitcoind clients which
|
||||
// treated this field as an int32 and would treat anything larger
|
||||
// incorrectly (as negative).
|
||||
if tx.LockTime > math.MaxInt32 {
|
||||
if tx.MsgTx().LockTime > math.MaxInt32 {
|
||||
str := fmt.Sprintf("transaction %v is has a lock time after "+
|
||||
"2038 which is not accepted yet", txHash)
|
||||
return TxRuleError(str)
|
||||
|
@ -658,7 +657,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcwire.MsgTx, isOrphan *bool) e
|
|||
|
||||
// Don't allow the transaction if it exists in the main chain and is not
|
||||
// not already fully spent.
|
||||
if txD, exists := txStore[txHash]; exists && txD.Err == nil {
|
||||
if txD, exists := txStore[*txHash]; exists && txD.Err == nil {
|
||||
for _, isOutputSpent := range txD.Spent {
|
||||
if !isOutputSpent {
|
||||
str := fmt.Sprintf("transaction already exists")
|
||||
|
@ -666,7 +665,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcwire.MsgTx, isOrphan *bool) e
|
|||
}
|
||||
}
|
||||
}
|
||||
delete(txStore, txHash)
|
||||
delete(txStore, *txHash)
|
||||
|
||||
// Transaction is an orphan if any of the inputs don't exist.
|
||||
for _, txD := range txStore {
|
||||
|
@ -707,7 +706,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcwire.MsgTx, isOrphan *bool) e
|
|||
// Verify crypto signatures for each input and reject the transaction if
|
||||
// any don't verify.
|
||||
flags := btcscript.ScriptBip16 | btcscript.ScriptCanonicalSignatures
|
||||
err = btcchain.ValidateTransactionScripts(tx, &txHash, txStore, flags)
|
||||
err = btcchain.ValidateTransactionScripts(tx, txStore, flags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -715,7 +714,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcwire.MsgTx, isOrphan *bool) e
|
|||
// TODO(davec): Rate-limit free transactions
|
||||
|
||||
// Add to transaction pool.
|
||||
mp.addTransaction(tx, &txHash)
|
||||
mp.addTransaction(tx)
|
||||
|
||||
log.Debugf("TXMP: Accepted transaction %v (pool size: %v)", txHash,
|
||||
len(mp.pool))
|
||||
|
@ -723,7 +722,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcwire.MsgTx, isOrphan *bool) e
|
|||
// TODO(davec): Notifications
|
||||
|
||||
// Generate the inventory vector and relay it.
|
||||
iv := btcwire.NewInvVect(btcwire.InvTypeTx, &txHash)
|
||||
iv := btcwire.NewInvVect(btcwire.InvTypeTx, txHash)
|
||||
mp.server.RelayInventory(iv)
|
||||
|
||||
return nil
|
||||
|
@ -757,31 +756,28 @@ func (mp *txMemPool) processOrphans(hash *btcwire.ShaHash) error {
|
|||
var enext *list.Element
|
||||
for e := orphans.Front(); e != nil; e = enext {
|
||||
enext = e.Next()
|
||||
tx := e.Value.(*btcwire.MsgTx)
|
||||
tx := e.Value.(*btcutil.Tx)
|
||||
|
||||
// Remove the orphan from the orphan pool.
|
||||
orphanHash, err := tx.TxSha()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mp.removeOrphan(&orphanHash)
|
||||
orphanHash := tx.Sha()
|
||||
mp.removeOrphan(orphanHash)
|
||||
|
||||
// Potentially accept the transaction into the
|
||||
// transaction pool.
|
||||
var isOrphan bool
|
||||
err = mp.maybeAcceptTransaction(tx, &isOrphan)
|
||||
err := mp.maybeAcceptTransaction(tx, &isOrphan)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if isOrphan {
|
||||
mp.removeOrphan(&orphanHash)
|
||||
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)
|
||||
processHashes.PushBack(orphanHash)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -794,20 +790,17 @@ func (mp *txMemPool) processOrphans(hash *btcwire.ShaHash) error {
|
|||
// rules, orphan transaction handling, and insertion into the memory pool.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) ProcessTransaction(tx *btcwire.MsgTx) error {
|
||||
func (mp *txMemPool) ProcessTransaction(tx *btcutil.Tx) error {
|
||||
// Protect concurrent access.
|
||||
mp.Lock()
|
||||
defer mp.Unlock()
|
||||
|
||||
txHash, err := tx.TxSha()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
txHash := tx.Sha()
|
||||
log.Tracef("TXMP: Processing transaction %v", txHash)
|
||||
|
||||
// Potentially accept the transaction to the memory pool.
|
||||
var isOrphan bool
|
||||
err = mp.maybeAcceptTransaction(tx, &isOrphan)
|
||||
err := mp.maybeAcceptTransaction(tx, &isOrphan)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -816,14 +809,14 @@ func (mp *txMemPool) ProcessTransaction(tx *btcwire.MsgTx) error {
|
|||
// 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(&txHash)
|
||||
err := mp.processOrphans(txHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// When the transaction is an orphan (has inputs missing),
|
||||
// potentially add it to the orphan pool.
|
||||
err := mp.maybeAddOrphan(tx, &txHash)
|
||||
err := mp.maybeAddOrphan(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -856,9 +849,9 @@ func (mp *txMemPool) TxShas() []*btcwire.ShaHash {
|
|||
func newTxMemPool(server *server) *txMemPool {
|
||||
return &txMemPool{
|
||||
server: server,
|
||||
pool: make(map[btcwire.ShaHash]*btcwire.MsgTx),
|
||||
orphans: make(map[btcwire.ShaHash]*btcwire.MsgTx),
|
||||
pool: make(map[btcwire.ShaHash]*btcutil.Tx),
|
||||
orphans: make(map[btcwire.ShaHash]*btcutil.Tx),
|
||||
orphansByPrev: make(map[btcwire.ShaHash]*list.List),
|
||||
outpoints: make(map[btcwire.OutPoint]*btcwire.MsgTx),
|
||||
outpoints: make(map[btcwire.OutPoint]*btcutil.Tx),
|
||||
}
|
||||
}
|
||||
|
|
19
peer.go
19
peer.go
|
@ -325,7 +325,7 @@ func (p *peer) pushTxMsg(sha *btcwire.ShaHash, doneChan chan bool) error {
|
|||
"pool: %v", sha, err)
|
||||
return err
|
||||
}
|
||||
p.QueueMessage(tx, doneChan)
|
||||
p.QueueMessage(tx.MsgTx(), doneChan)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -453,12 +453,10 @@ func (p *peer) handleMemPoolMsg(msg *btcwire.MsgMemPool) {
|
|||
// 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.InvTypeTx, &hash)
|
||||
// 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
|
||||
|
@ -466,16 +464,15 @@ func (p *peer) handleTxMsg(msg *btcwire.MsgTx) {
|
|||
// 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(msg, p)
|
||||
p.server.blockManager.QueueTx(tx, p)
|
||||
<-p.txProcessed
|
||||
}
|
||||
|
||||
// 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 convience methods and things such as
|
||||
// hash caching.
|
||||
// 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.
|
||||
|
|
11
rpcserver.go
11
rpcserver.go
|
@ -725,7 +725,8 @@ func jsonRead(body []byte, s *rpcServer, walletNotification chan []byte) (reply
|
|||
}
|
||||
return
|
||||
}
|
||||
err = s.server.txMemPool.ProcessTransaction(msgtx)
|
||||
tx := btcutil.NewTx(msgtx)
|
||||
err = s.server.txMemPool.ProcessTransaction(tx)
|
||||
if err != nil {
|
||||
log.Errorf("RPCS: Failed to process transaction: %v", err)
|
||||
err = btcjson.Error{
|
||||
|
@ -736,15 +737,13 @@ func jsonRead(body []byte, s *rpcServer, walletNotification chan []byte) (reply
|
|||
}
|
||||
|
||||
var result interface{}
|
||||
txsha, err := msgtx.TxSha()
|
||||
if err == nil {
|
||||
result = txsha.String()
|
||||
}
|
||||
txsha := tx.Sha()
|
||||
result = txsha.String()
|
||||
|
||||
// If called from websocket code, add a mined tx hashes
|
||||
// request.
|
||||
if walletNotification != nil {
|
||||
s.ws.requests.AddMinedTxRequest(walletNotification, &txsha)
|
||||
s.ws.requests.AddMinedTxRequest(walletNotification, txsha)
|
||||
}
|
||||
|
||||
reply = btcjson.Reply{
|
||||
|
|
Loading…
Reference in a new issue