Skip to content

Commit

Permalink
Merge pull request #208 from kcalvinalvin/2024-11-01-update-mempool-f…
Browse files Browse the repository at this point in the history
…rom-btcd

mempool, btcd, btcjson, rpcclient: pull in mempool PRs from btcd
  • Loading branch information
kcalvinalvin authored Nov 5, 2024
2 parents cff9aa7 + 6a52210 commit 6ed428f
Show file tree
Hide file tree
Showing 21 changed files with 1,669 additions and 403 deletions.
22 changes: 22 additions & 0 deletions btcjson/chainsvrcmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -1267,6 +1267,27 @@ func NewVerifyUtxoChainTipInclusionProofCmd(proof string) *VerifyUtxoChainTipInc
return &VerifyUtxoChainTipInclusionProofCmd{Proof: proof}
}

// TestMempoolAcceptCmd defines the testmempoolaccept JSON-RPC command.
type TestMempoolAcceptCmd struct {
// An array of hex strings of raw transactions.
RawTxns []string

// Reject transactions whose fee rate is higher than the specified
// value, expressed in BTC/kvB, optional, default="0.10".
MaxFeeRate float64 `json:"omitempty"`
}

// NewTestMempoolAcceptCmd returns a new instance which can be used to issue a
// testmempoolaccept JSON-RPC command.
func NewTestMempoolAcceptCmd(rawTxns []string,
maxFeeRate float64) *TestMempoolAcceptCmd {

return &TestMempoolAcceptCmd{
RawTxns: rawTxns,
MaxFeeRate: maxFeeRate,
}
}

func init() {
// No special flags for commands in this file.
flags := UsageFlag(0)
Expand Down Expand Up @@ -1346,4 +1367,5 @@ func init() {
MustRegisterCmd("verifymessage", (*VerifyMessageCmd)(nil), flags)
MustRegisterCmd("verifytxoutproof", (*VerifyTxOutProofCmd)(nil), flags)
MustRegisterCmd("verifyutxochaintipinclusionproof", (*VerifyUtxoChainTipInclusionProofCmd)(nil), flags)
MustRegisterCmd("testmempoolaccept", (*TestMempoolAcceptCmd)(nil), flags)
}
28 changes: 28 additions & 0 deletions btcjson/chainsvrcmds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1490,6 +1490,34 @@ func TestChainSvrCmds(t *testing.T) {
marshalled: `{"jsonrpc":"1.0","method":"getdescriptorinfo","params":["123"],"id":1}`,
unmarshalled: &btcjson.GetDescriptorInfoCmd{Descriptor: "123"},
},
{
name: "testmempoolaccept",
newCmd: func() (interface{}, error) {
return btcjson.NewCmd("testmempoolaccept", []string{"rawhex"}, 0.1)
},
staticCmd: func() interface{} {
return btcjson.NewTestMempoolAcceptCmd([]string{"rawhex"}, 0.1)
},
marshalled: `{"jsonrpc":"1.0","method":"testmempoolaccept","params":[["rawhex"],0.1],"id":1}`,
unmarshalled: &btcjson.TestMempoolAcceptCmd{
RawTxns: []string{"rawhex"},
MaxFeeRate: 0.1,
},
},
{
name: "testmempoolaccept with maxfeerate",
newCmd: func() (interface{}, error) {
return btcjson.NewCmd("testmempoolaccept", []string{"rawhex"}, 0.01)
},
staticCmd: func() interface{} {
return btcjson.NewTestMempoolAcceptCmd([]string{"rawhex"}, 0.01)
},
marshalled: `{"jsonrpc":"1.0","method":"testmempoolaccept","params":[["rawhex"],0.01],"id":1}`,
unmarshalled: &btcjson.TestMempoolAcceptCmd{
RawTxns: []string{"rawhex"},
MaxFeeRate: 0.01,
},
},
}

t.Logf("Running %d tests", len(tests))
Expand Down
60 changes: 58 additions & 2 deletions btcjson/chainsvrresults.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,8 +347,8 @@ type GetBlockTemplateResult struct {
NonceRange string `json:"noncerange,omitempty"`

// Block proposal from BIP 0023.
Capabilities []string `json:"capabilities,omitempty"`
RejectReasion string `json:"reject-reason,omitempty"`
Capabilities []string `json:"capabilities,omitempty"`
RejectReason string `json:"reject-reason,omitempty"`
}

// GetMempoolEntryResult models the data returned from the getmempoolentry's
Expand Down Expand Up @@ -966,3 +966,59 @@ type CreateTransactionFromBDKWalletResult struct {
TxHash string `json:"txhash"`
RawBytes string `json:"rawbytes"`
}

// TestMempoolAcceptResult models the data from the testmempoolaccept command.
// The result of the mempool acceptance test for each raw transaction in the
// input array. Returns results for each transaction in the same order they
// were passed in. Transactions that cannot be fully validated due to failures
// in other transactions will not contain an 'allowed' result.
type TestMempoolAcceptResult struct {
// Txid is the transaction hash in hex.
Txid string `json:"txid"`

// Wtxid is the transaction witness hash in hex.
Wtxid string `json:"wtxid"`

// PackageError is the package validation error, if any (only possible
// if rawtxs had more than 1 transaction).
PackageError string `json:"package-error"`

// Allowed specifies whether this tx would be accepted to the mempool
// and pass client-specified maxfeerate. If not present, the tx was not
// fully validated due to a failure in another tx in the list.
Allowed bool `json:"allowed,omitempty"`

// Vsize is the virtual transaction size as defined in BIP 141. This is
// different from actual serialized size for witness transactions as
// witness data is discounted (only present when 'allowed' is true)
Vsize int32 `json:"vsize,omitempty"`

// Fees specifies the transaction fees (only present if 'allowed' is
// true).
Fees *TestMempoolAcceptFees `json:"fees,omitempty"`

// RejectReason is the rejection string (only present when 'allowed' is
// false).
RejectReason string `json:"reject-reason,omitempty"`
}

// TestMempoolAcceptFees models the `fees` section from the testmempoolaccept
// command.
type TestMempoolAcceptFees struct {
// Base is the transaction fee in BTC.
Base float64 `json:"base"`

// EffectiveFeeRate specifies the effective feerate in BTC per KvB. May
// differ from the base feerate if, for example, there are modified
// fees from prioritisetransaction or a package feerate was used.
//
// NOTE: this field only exists in bitcoind v25.0 and above.
EffectiveFeeRate float64 `json:"effective-feerate"`

// EffectiveIncludes specifies transactions whose fees and vsizes are
// included in effective-feerate. Each item is a transaction wtxid in
// hex.
//
// NOTE: this field only exists in bitcoind v25.0 and above.
EffectiveIncludes []string `json:"effective-includes"`
}
2 changes: 1 addition & 1 deletion electrum/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ func handleTransactionBroadcast(s *ElectrumServer, cmd *btcjson.Request, conn ne
// Also, since an error is being returned to the caller, ensure the
// transaction is removed from the memory pool.
if len(acceptedTxs) == 0 || !acceptedTxs[0].Tx.Hash().IsEqual(tx.Hash()) {
s.cfg.Mempool.RemoveTransaction(tx, true, true)
s.cfg.Mempool.RemoveTransaction(tx, true)

errStr := fmt.Errorf("transaction %v is not in accepted list",
tx.Hash())
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/davecgh/go-spew v1.1.1
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1
github.com/decred/dcrd/lru v1.0.0
github.com/gorilla/websocket v1.5.0
github.com/jessevdk/go-flags v1.4.0
github.com/jrick/logrotate v1.0.0
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23
Expand All @@ -27,6 +28,7 @@ require (
github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/objx v0.1.0 // indirect
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
)
Expand Down
17 changes: 3 additions & 14 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -78,25 +78,12 @@ github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
github.com/utreexo/utreexo v0.0.0-20240130053814-4aa282fe3804 h1:9uJDD7lEbhQ/JQhdIPVJ2yk8tLh8nvwNz87shyUe+RQ=
github.com/utreexo/utreexo v0.0.0-20240130053814-4aa282fe3804/go.mod h1:RT9JpZADhLr2YJVBgp48tmUxVeAHaAbOSr6p6nAEJpI=
github.com/utreexo/utreexo v0.0.0-20240207085148-754fd0816976 h1:1r3hZAaf7zhLd/hT4wYB8PkYOLylgCDlJaxS8MRitZA=
github.com/utreexo/utreexo v0.0.0-20240207085148-754fd0816976/go.mod h1:RT9JpZADhLr2YJVBgp48tmUxVeAHaAbOSr6p6nAEJpI=
github.com/utreexo/utreexo v0.1.0 h1:ddbIk/yU7sqZ/7Q2XoZhaeWqMBRwhHXaoFRvKYx7uLo=
github.com/utreexo/utreexo v0.1.0/go.mod h1:RT9JpZADhLr2YJVBgp48tmUxVeAHaAbOSr6p6nAEJpI=
github.com/utreexo/utreexo v0.1.2 h1:KLC8rlwPep3w9sYapEgDROYUBNmLzsO5aTPTorBJhJc=
github.com/utreexo/utreexo v0.1.2/go.mod h1:RT9JpZADhLr2YJVBgp48tmUxVeAHaAbOSr6p6nAEJpI=
github.com/utreexo/utreexo v0.1.3 h1:Z7tj8DTZNHd927ZWT7NSKx14+Dk6BoMeDPhDOmFlibo=
github.com/utreexo/utreexo v0.1.3/go.mod h1:RT9JpZADhLr2YJVBgp48tmUxVeAHaAbOSr6p6nAEJpI=
github.com/utreexo/utreexo v0.1.4 h1:jygjZscJEzab7woP7aB6YWUKjhsV5Mrbjj873inhwR8=
github.com/utreexo/utreexo v0.1.4/go.mod h1:RT9JpZADhLr2YJVBgp48tmUxVeAHaAbOSr6p6nAEJpI=
github.com/utreexo/utreexo v0.1.5 h1:nnG2VvwDYPkXCSRicV15eAbh2vvTp/g4Pot3vlseGdQ=
github.com/utreexo/utreexo v0.1.5/go.mod h1:RT9JpZADhLr2YJVBgp48tmUxVeAHaAbOSr6p6nAEJpI=
github.com/utreexo/utreexo v0.2.1 h1:xycdaHK+HhDZO5MY6Clq7YeXEDguzar1GrAYqIJ1gvs=
github.com/utreexo/utreexo v0.2.1/go.mod h1:xIu3cTtT0jNdntc1qJhVyQV/RX03Sk9gFD3UAzALvuU=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
Expand All @@ -112,6 +99,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand All @@ -128,6 +116,7 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
Expand Down
71 changes: 71 additions & 0 deletions mempool/interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package mempool

import (
"time"

"github.com/utreexo/utreexod/btcjson"
"github.com/utreexo/utreexod/btcutil"
"github.com/utreexo/utreexod/chaincfg/chainhash"
"github.com/utreexo/utreexod/wire"
)

// TxMempool defines an interface that's used by other subsystems to interact
// with the mempool.
type TxMempool interface {
// LastUpdated returns the last time a transaction was added to or
// removed from the source pool.
LastUpdated() time.Time

// TxDescs returns a slice of descriptors for all the transactions in
// the pool.
TxDescs() []*TxDesc

// RawMempoolVerbose returns all the entries in the mempool as a fully
// populated btcjson result.
RawMempoolVerbose() map[string]*btcjson.GetRawMempoolVerboseResult

// Count returns the number of transactions in the main pool. It does
// not include the orphan pool.
Count() int

// FetchTransaction returns the requested transaction from the
// transaction pool. This only fetches from the main transaction pool
// and does not include orphans.
FetchTransaction(txHash *chainhash.Hash) (*btcutil.Tx, error)

// HaveTransaction returns whether or not the passed transaction
// already exists in the main pool or in the orphan pool.
HaveTransaction(hash *chainhash.Hash) bool

// 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.
//
// It returns a slice of transactions added to the mempool. When the
// error is nil, the list will include the passed transaction itself
// along with any additional orphan transactions that were added as a
// result of the passed one being accepted.
ProcessTransaction(tx *btcutil.Tx, allowOrphan,
rateLimit bool, tag Tag) ([]*TxDesc, error)

// RemoveTransaction removes the passed transaction from the mempool.
// When the removeRedeemers flag is set, any transactions that redeem
// outputs from the removed transaction will also be removed
// recursively from the mempool, as they would otherwise become
// orphans.
RemoveTransaction(tx *btcutil.Tx, removeRedeemers bool)

// CheckMempoolAcceptance behaves similarly to bitcoind's
// `testmempoolaccept` RPC method. It will perform a series of checks
// to decide whether this transaction can be accepted to the mempool.
// If not, the specific error is returned and the caller needs to take
// actions based on it.
CheckMempoolAcceptance(tx *btcutil.Tx) (*MempoolAcceptResult, error)

// CheckSpend checks whether the passed outpoint is already spent by
// a transaction in the mempool. If that's the case the spending
// transaction will be returned, if not nil will be returned.
CheckSpend(op wire.OutPoint) *btcutil.Tx
}
Loading

0 comments on commit 6ed428f

Please sign in to comment.