Skip to content

Commit

Permalink
Merge pull request #2053 from yyforyongyu/testmempoolaccept
Browse files Browse the repository at this point in the history
support `testmempoolaccept` for both `bitcoind` and `btcd`
  • Loading branch information
Roasbeef authored Jan 16, 2024
2 parents 91cdf0d + fbe65bf commit 17fdc52
Show file tree
Hide file tree
Showing 26 changed files with 2,063 additions and 339 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ btcutil/psbt/coverage.txt

# vim
*.swp
*.swo
/.vim

# Binaries produced by "make build"
/addblock
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ lint: $(LINT_BIN)
clean:
@$(call print, "Cleaning source.$(NC)")
$(RM) coverage.txt btcec/coverage.txt btcutil/coverage.txt btcutil/psbt/coverage.txt

tidy-module:
echo "Running 'go mod tidy' for all modules"
scripts/tidy_modules.sh

.PHONY: all \
default \
Expand Down
10 changes: 5 additions & 5 deletions blockchain/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,9 +243,9 @@ func CheckTransactionSanity(tx *btcutil.Tx) error {
return ruleError(ErrBadTxOutValue, str)
}
if satoshi > btcutil.MaxSatoshi {
str := fmt.Sprintf("transaction output value of %v is "+
"higher than max allowed value of %v", satoshi,
btcutil.MaxSatoshi)
str := fmt.Sprintf("transaction output value is "+
"higher than max allowed value: %v > %v ",
satoshi, btcutil.MaxSatoshi)
return ruleError(ErrBadTxOutValue, str)
}

Expand Down Expand Up @@ -968,8 +968,8 @@ func CheckTransactionInputs(tx *btcutil.Tx, txHeight int32, utxoView *UtxoViewpo
return 0, ruleError(ErrBadTxOutValue, str)
}
if originTxSatoshi > btcutil.MaxSatoshi {
str := fmt.Sprintf("transaction output value of %v is "+
"higher than max allowed value of %v",
str := fmt.Sprintf("transaction output value is "+
"higher than max allowed value: %v > %v ",
btcutil.Amount(originTxSatoshi),
btcutil.MaxSatoshi)
return 0, ruleError(ErrBadTxOutValue, str)
Expand Down
22 changes: 22 additions & 0 deletions btcjson/chainsvrcmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -1042,6 +1042,27 @@ func NewVerifyTxOutProofCmd(proof string) *VerifyTxOutProofCmd {
}
}

// 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 @@ -1102,4 +1123,5 @@ func init() {
MustRegisterCmd("verifychain", (*VerifyChainCmd)(nil), flags)
MustRegisterCmd("verifymessage", (*VerifyMessageCmd)(nil), flags)
MustRegisterCmd("verifytxoutproof", (*VerifyTxOutProofCmd)(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 @@ -1472,6 +1472,34 @@ func TestChainSvrCmds(t *testing.T) {
marshalled: `{"jsonrpc":"1.0","method":"getzmqnotifications","params":[],"id":1}`,
unmarshalled: &btcjson.GetZmqNotificationsCmd{},
},
{
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 @@ -304,8 +304,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 @@ -855,3 +855,59 @@ type LoadWalletResult struct {
type DumpWalletResult struct {
Filename string `json:"filename"`
}

// 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"`
}
8 changes: 0 additions & 8 deletions btcutil/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M=
github.com/btcsuite/btcd v0.23.4 h1:IzV6qqkfwbItOS/sg/aDfPDsjPP8twrCOE2R93hxMlQ=
github.com/btcsuite/btcd v0.23.4/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=
github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd h1:js1gPwhcFflTZ7Nzl7WHaOTlTr5hIrR4n1NM4v9n4Kw=
github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A=
github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA=
Expand All @@ -18,15 +16,12 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtyd
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I=
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand All @@ -36,7 +31,6 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8=
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
Expand All @@ -55,9 +49,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ require (
github.com/gorilla/websocket v1.5.0
github.com/jessevdk/go-flags v1.4.0
github.com/jrick/logrotate v1.0.0
github.com/stretchr/testify v1.7.0
github.com/stretchr/testify v1.8.4
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed
Expand All @@ -26,7 +26,8 @@ require (
github.com/golang/snappy v0.0.4 // indirect
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
github.com/stretchr/objx v0.5.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

// The retract statements below fixes an accidental push of the tags of a btcd
Expand Down
11 changes: 9 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,14 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
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/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
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=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
Expand Down Expand Up @@ -125,5 +131,6 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
26 changes: 26 additions & 0 deletions integration/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//go:build rpctest
// +build rpctest

package integration

import (
"os"

"github.com/btcsuite/btcd/rpcclient"
"github.com/btcsuite/btclog"
)

type logWriter struct{}

func (logWriter) Write(p []byte) (n int, err error) {
os.Stdout.Write(p)
return len(p), nil
}

func init() {
backendLog := btclog.NewBackend(logWriter{})
testLog := backendLog.Logger("ITEST")
testLog.SetLevel(btclog.LevelDebug)

rpcclient.UseLogger(testLog)
}
Loading

0 comments on commit 17fdc52

Please sign in to comment.