From 518b4c89563a34b1248fc9a98f814266a02e5fd1 Mon Sep 17 00:00:00 2001 From: wydengyre Date: Fri, 15 Sep 2023 16:26:16 +0100 Subject: [PATCH] rpcclient: CreateRawTransaction replaceable parameter Support the RPC `createrawtransaction` `replaceable` parameter, which allows disabling opt-in RBF. --- btcjson/chainsvrcmds.go | 16 +++++++++------- btcjson/chainsvrcmds_test.go | 18 ++++++++++-------- rpcclient/rawtransactions.go | 8 ++++---- rpcserverhelp.go | 1 + 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index aa1d4415..6f8550ea 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -57,9 +57,10 @@ type TransactionInput struct { // CreateRawTransactionCmd defines the createrawtransaction JSON-RPC command. type CreateRawTransactionCmd struct { - Inputs []TransactionInput - Amounts map[string]float64 `jsonrpcusage:"{\"address\":amount,...}"` // In BTC - LockTime *int64 + Inputs []TransactionInput + Amounts map[string]float64 `jsonrpcusage:"{\"address\":amount,...}"` // In BTC + LockTime *int64 + Replaceable *bool } // NewCreateRawTransactionCmd returns a new instance which can be used to issue @@ -68,16 +69,17 @@ type CreateRawTransactionCmd struct { // Amounts are in BTC. Passing in nil and the empty slice as inputs is equivalent, // both gets interpreted as the empty slice. func NewCreateRawTransactionCmd(inputs []TransactionInput, amounts map[string]float64, - lockTime *int64) *CreateRawTransactionCmd { + lockTime *int64, replaceable *bool) *CreateRawTransactionCmd { // to make sure we're serializing this to the empty list and not null, we // explicitly initialize the list if inputs == nil { inputs = []TransactionInput{} } return &CreateRawTransactionCmd{ - Inputs: inputs, - Amounts: amounts, - LockTime: lockTime, + Inputs: inputs, + Amounts: amounts, + LockTime: lockTime, + Replaceable: replaceable, } } diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index 99983288..410490eb 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -24,6 +24,7 @@ func TestChainSvrCmds(t *testing.T) { t.Parallel() testID := int(1) + trueB := true tests := []struct { name string newCmd func() (interface{}, error) @@ -53,7 +54,7 @@ func TestChainSvrCmds(t *testing.T) { {Txid: "123", Vout: 1}, } amounts := map[string]float64{"456": .0123} - return btcjson.NewCreateRawTransactionCmd(txInputs, amounts, nil) + return btcjson.NewCreateRawTransactionCmd(txInputs, amounts, nil, nil) }, marshalled: `{"jsonrpc":"1.0","method":"createrawtransaction","params":[[{"txid":"123","vout":1}],{"456":0.0123}],"id":1}`, unmarshalled: &btcjson.CreateRawTransactionCmd{ @@ -68,7 +69,7 @@ func TestChainSvrCmds(t *testing.T) { }, staticCmd: func() interface{} { amounts := map[string]float64{"456": .0123} - return btcjson.NewCreateRawTransactionCmd(nil, amounts, nil) + return btcjson.NewCreateRawTransactionCmd(nil, amounts, nil, nil) }, marshalled: `{"jsonrpc":"1.0","method":"createrawtransaction","params":[[],{"456":0.0123}],"id":1}`, unmarshalled: &btcjson.CreateRawTransactionCmd{ @@ -80,20 +81,21 @@ func TestChainSvrCmds(t *testing.T) { name: "createrawtransaction optional", newCmd: func() (interface{}, error) { return btcjson.NewCmd("createrawtransaction", `[{"txid":"123","vout":1}]`, - `{"456":0.0123}`, int64(12312333333)) + `{"456":0.0123}`, int64(12312333333), &trueB) }, staticCmd: func() interface{} { txInputs := []btcjson.TransactionInput{ {Txid: "123", Vout: 1}, } amounts := map[string]float64{"456": .0123} - return btcjson.NewCreateRawTransactionCmd(txInputs, amounts, btcjson.Int64(12312333333)) + return btcjson.NewCreateRawTransactionCmd(txInputs, amounts, btcjson.Int64(12312333333), &trueB) }, - marshalled: `{"jsonrpc":"1.0","method":"createrawtransaction","params":[[{"txid":"123","vout":1}],{"456":0.0123},12312333333],"id":1}`, + marshalled: `{"jsonrpc":"1.0","method":"createrawtransaction","params":[[{"txid":"123","vout":1}],{"456":0.0123},12312333333,true],"id":1}`, unmarshalled: &btcjson.CreateRawTransactionCmd{ - Inputs: []btcjson.TransactionInput{{Txid: "123", Vout: 1}}, - Amounts: map[string]float64{"456": .0123}, - LockTime: btcjson.Int64(12312333333), + Inputs: []btcjson.TransactionInput{{Txid: "123", Vout: 1}}, + Amounts: map[string]float64{"456": .0123}, + LockTime: btcjson.Int64(12312333333), + Replaceable: &trueB, }, }, { diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index 1df61952..06ea7f2b 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -291,13 +291,13 @@ func (r FutureCreateRawTransactionResult) Receive() (*wire.MsgTx, error) { // // See CreateRawTransaction for the blocking version and more details. func (c *Client) CreateRawTransactionAsync(inputs []btcjson.TransactionInput, - amounts map[btcutil.Address]btcutil.Amount, lockTime *int64) FutureCreateRawTransactionResult { + amounts map[btcutil.Address]btcutil.Amount, lockTime *int64, replaceable *bool) FutureCreateRawTransactionResult { convertedAmts := make(map[string]float64, len(amounts)) for addr, amount := range amounts { convertedAmts[addr.String()] = amount.ToBTC() } - cmd := btcjson.NewCreateRawTransactionCmd(inputs, convertedAmts, lockTime) + cmd := btcjson.NewCreateRawTransactionCmd(inputs, convertedAmts, lockTime, replaceable) return c.SendCmd(cmd) } @@ -305,9 +305,9 @@ func (c *Client) CreateRawTransactionAsync(inputs []btcjson.TransactionInput, // and sending to the provided addresses. If the inputs are either nil or an // empty slice, it is interpreted as an empty slice. func (c *Client) CreateRawTransaction(inputs []btcjson.TransactionInput, - amounts map[btcutil.Address]btcutil.Amount, lockTime *int64) (*wire.MsgTx, error) { + amounts map[btcutil.Address]btcutil.Amount, lockTime *int64, replaceable *bool) (*wire.MsgTx, error) { - return c.CreateRawTransactionAsync(inputs, amounts, lockTime).Receive() + return c.CreateRawTransactionAsync(inputs, amounts, lockTime, replaceable).Receive() } // FutureSendRawTransactionResult is a future promise to deliver the result diff --git a/rpcserverhelp.go b/rpcserverhelp.go index a42804e9..62bcb3bf 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -54,6 +54,7 @@ var helpDescsEnUS = map[string]string{ "createrawtransaction-amounts--value": "n.nnn", "createrawtransaction-amounts--desc": "The destination address as the key and the amount in BTC as the value", "createrawtransaction-locktime": "Locktime value; a non-zero value will also locktime-activate the inputs", + "createrawtransaction-replaceable": "If false, do not mark this transaction as BIP125-replaceable.", "createrawtransaction--result0": "Hex-encoded bytes of the serialized transaction", // ScriptSig help.