mirror of
https://github.com/btcsuite/btcd.git
synced 2025-01-19 05:33:36 +01:00
parent
e4fa45ff08
commit
8aaad1e97b
53
mempool.go
53
mempool.go
@ -78,13 +78,22 @@ const (
|
||||
blockPrioritySize = 27000
|
||||
)
|
||||
|
||||
// TxDesc is a descriptor containing a transaction in the mempool and the
|
||||
// metadata we store about it.
|
||||
type TxDesc struct {
|
||||
Tx *btcutil.Tx // Transaction.
|
||||
Added time.Time // Time when added to pool.
|
||||
Height int64 // Blockheight when added to pool.
|
||||
Fee int64 // Transaction fees.
|
||||
}
|
||||
|
||||
// txMemPool is used as a source of transactions that need to be mined into
|
||||
// blocks and relayed to other peers. It is safe for concurrent access from
|
||||
// multiple peers.
|
||||
type txMemPool struct {
|
||||
sync.RWMutex
|
||||
server *server
|
||||
pool map[btcwire.ShaHash]*btcutil.Tx
|
||||
pool map[btcwire.ShaHash]*TxDesc
|
||||
orphans map[btcwire.ShaHash]*btcutil.Tx
|
||||
orphansByPrev map[btcwire.ShaHash]*list.List
|
||||
outpoints map[btcwire.OutPoint]*btcutil.Tx
|
||||
@ -581,8 +590,8 @@ func (mp *txMemPool) removeTransaction(tx *btcutil.Tx) {
|
||||
|
||||
// Remove the transaction and mark the referenced outpoints as unspent
|
||||
// by the pool.
|
||||
if tx, exists := mp.pool[*txHash]; exists {
|
||||
for _, txIn := range tx.MsgTx().TxIn {
|
||||
if txDesc, exists := mp.pool[*txHash]; exists {
|
||||
for _, txIn := range txDesc.Tx.MsgTx().TxIn {
|
||||
delete(mp.outpoints, txIn.PreviousOutpoint)
|
||||
}
|
||||
delete(mp.pool, *txHash)
|
||||
@ -627,10 +636,15 @@ func (mp *txMemPool) RemoveDoubleSpends(tx *btcutil.Tx) {
|
||||
// helper for maybeAcceptTransaction.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for writes).
|
||||
func (mp *txMemPool) addTransaction(tx *btcutil.Tx) {
|
||||
func (mp *txMemPool) addTransaction(tx *btcutil.Tx, height, fee int64) {
|
||||
// Add the transaction to the pool and mark the referenced outpoints
|
||||
// as spent by the pool.
|
||||
mp.pool[*tx.Sha()] = tx
|
||||
mp.pool[*tx.Sha()] = &TxDesc{
|
||||
Tx: tx,
|
||||
Added: time.Now(),
|
||||
Height: height,
|
||||
Fee: fee,
|
||||
}
|
||||
for _, txIn := range tx.MsgTx().TxIn {
|
||||
mp.outpoints[txIn.PreviousOutpoint] = tx
|
||||
}
|
||||
@ -668,7 +682,8 @@ func (mp *txMemPool) fetchInputTransactions(tx *btcutil.Tx) (btcchain.TxStore, e
|
||||
// Attempt to populate any missing inputs from the transaction pool.
|
||||
for _, txD := range txStore {
|
||||
if txD.Err == btcdb.TxShaMissing || txD.Tx == nil {
|
||||
if poolTx, exists := mp.pool[*txD.Hash]; exists {
|
||||
if poolTxDesc, exists := mp.pool[*txD.Hash]; exists {
|
||||
poolTx := poolTxDesc.Tx
|
||||
txD.Tx = poolTx
|
||||
txD.BlockHeight = mempoolHeight
|
||||
txD.Spent = make([]bool, len(poolTx.MsgTx().TxOut))
|
||||
@ -690,8 +705,8 @@ func (mp *txMemPool) FetchTransaction(txHash *btcwire.ShaHash) (*btcutil.Tx, err
|
||||
mp.RLock()
|
||||
defer mp.RUnlock()
|
||||
|
||||
if tx, exists := mp.pool[*txHash]; exists {
|
||||
return tx, nil
|
||||
if txDesc, exists := mp.pool[*txHash]; exists {
|
||||
return txDesc.Tx, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("transaction is not in the pool")
|
||||
@ -856,7 +871,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcutil.Tx, isOrphan *bool) erro
|
||||
}
|
||||
|
||||
// Add to transaction pool.
|
||||
mp.addTransaction(tx)
|
||||
mp.addTransaction(tx, nextBlockHeight-1, txFee)
|
||||
|
||||
txmpLog.Debugf("Accepted transaction %v (pool size: %v)", txHash,
|
||||
len(mp.pool))
|
||||
@ -1005,12 +1020,30 @@ func (mp *txMemPool) TxShas() []*btcwire.ShaHash {
|
||||
return hashes
|
||||
}
|
||||
|
||||
// TxDescs returns a slice of descriptors for all the transactions in the pool.
|
||||
// The descriptors are to be treated as read only.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) TxDescs() []*TxDesc {
|
||||
mp.RLock()
|
||||
defer mp.RUnlock()
|
||||
|
||||
descs := make([]*TxDesc, len(mp.pool))
|
||||
i := 0
|
||||
for _, desc := range mp.pool {
|
||||
descs[i] = desc
|
||||
i++
|
||||
}
|
||||
|
||||
return descs
|
||||
}
|
||||
|
||||
// newTxMemPool returns a new memory pool for validating and storing standalone
|
||||
// transactions until they are mined into a block.
|
||||
func newTxMemPool(server *server) *txMemPool {
|
||||
return &txMemPool{
|
||||
server: server,
|
||||
pool: make(map[btcwire.ShaHash]*btcutil.Tx),
|
||||
pool: make(map[btcwire.ShaHash]*TxDesc),
|
||||
orphans: make(map[btcwire.ShaHash]*btcutil.Tx),
|
||||
orphansByPrev: make(map[btcwire.ShaHash]*list.List),
|
||||
outpoints: make(map[btcwire.OutPoint]*btcutil.Tx),
|
||||
|
47
rpcserver.go
47
rpcserver.go
@ -870,13 +870,52 @@ func handleGetPeerInfo(s *rpcServer, cmd btcjson.Cmd, walletNotification chan []
|
||||
return s.server.PeerInfo(), nil
|
||||
}
|
||||
|
||||
type mempoolDescriptor struct {
|
||||
Size int `json:"size"`
|
||||
Fee int64 `json:"fee"`
|
||||
Time int64 `json:"time"`
|
||||
Height int64 `json:"height"`
|
||||
StartingPriority int `json:"startingpriority"`
|
||||
CurrentPriority int `json:"currentpriority"`
|
||||
Depends []string `json:"depends"`
|
||||
|
||||
}
|
||||
|
||||
// handleGetRawMempool implements the getrawmempool command.
|
||||
func handleGetRawMempool(s *rpcServer, cmd btcjson.Cmd, walletNotification chan []byte) (interface{}, error) {
|
||||
hashes := s.server.txMemPool.TxShas()
|
||||
hashStrings := make([]string, len(hashes))
|
||||
for i := 0; i < len(hashes); i++ {
|
||||
hashStrings[i] = hashes[i].String()
|
||||
c := cmd.(*btcjson.GetRawMempoolCmd)
|
||||
descs := s.server.txMemPool.TxDescs()
|
||||
|
||||
if c.Verbose {
|
||||
result := make(map[string]*mempoolDescriptor, len(descs))
|
||||
for _, desc := range descs {
|
||||
mpd := &mempoolDescriptor{
|
||||
Size: desc.Tx.MsgTx().SerializeSize(),
|
||||
Fee: desc.Fee,
|
||||
Time: desc.Added.Unix(),
|
||||
Height: desc.Height,
|
||||
StartingPriority: 0, // We don't mine.
|
||||
CurrentPriority: 0, // We don't mine.
|
||||
}
|
||||
for _, txIn := range desc.Tx.MsgTx().TxIn {
|
||||
hash := &txIn.PreviousOutpoint.Hash
|
||||
if s.server.txMemPool.HaveTransaction(hash) {
|
||||
mpd.Depends = append(mpd.Depends,
|
||||
hash.String())
|
||||
}
|
||||
}
|
||||
|
||||
result[desc.Tx.Sha().String()] = mpd
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
hashStrings := make([]string, len(descs))
|
||||
for i := range(hashStrings) {
|
||||
hashStrings[i] = descs[i].Tx.Sha().String()
|
||||
}
|
||||
|
||||
|
||||
return hashStrings, nil
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ var commandHandlers = map[string]*handlerData{
|
||||
"getdifficulty": &handlerData{0, 0, displayFloat64, nil, makeGetDifficulty, ""},
|
||||
"getgenerate": &handlerData{0, 0, displayGeneric, nil, makeGetGenerate, ""},
|
||||
"getpeerinfo": &handlerData{0, 0, displaySpewDump, nil, makeGetPeerInfo, ""},
|
||||
"getrawmempool": &handlerData{0, 0, displaySpewDump, nil, makeGetRawMempool, ""},
|
||||
"getrawmempool": &handlerData{0, 1, displaySpewDump, []conversionHandler{toBool}, makeGetRawMempool, "[verbose=false]"},
|
||||
"getrawtransaction": &handlerData{1, 1, displaySpewDump, []conversionHandler{nil, toInt}, makeGetRawTransaction, "<txhash> [verbose=0]"},
|
||||
"importprivkey": &handlerData{1, 2, displayGeneric, []conversionHandler{nil, nil, toBool}, makeImportPrivKey, "<wifprivkey> [label] [rescan=true]"},
|
||||
"listtransactions": &handlerData{0, 3, displaySpewDump, []conversionHandler{nil, toInt, toInt}, makeListTransactions, "[account] [count=10] [from=0]"},
|
||||
@ -209,7 +209,11 @@ func makeGetPeerInfo(args []interface{}) (btcjson.Cmd, error) {
|
||||
// makeRawMempool generates the cmd structure for
|
||||
// getrawmempool comands.
|
||||
func makeGetRawMempool(args []interface{}) (btcjson.Cmd, error) {
|
||||
return btcjson.NewGetRawMempoolCmd("btcctl")
|
||||
opt := make([]bool, 0, 1)
|
||||
if len(args) > 0 {
|
||||
opt = append(opt, args[0].(bool))
|
||||
}
|
||||
return btcjson.NewGetRawMempoolCmd("btcctl", opt...)
|
||||
}
|
||||
|
||||
// makeRawTransaction generates the cmd structure for
|
||||
|
Loading…
Reference in New Issue
Block a user