btcjson: Add optional locktime to createrawtransaction
rpcserver: If the locktime is given, the transaction inputs will be set to a non-max value, activating the locktime. The locktime for the new transaction will be set to the given value. This mimics Bitcoin Core commit 212bcca92089f406d9313dbe6d0e1d25143d61ff
This commit is contained in:
parent
489ba8d31d
commit
4b7206b54f
5 changed files with 51 additions and 8 deletions
|
@ -53,18 +53,22 @@ type TransactionInput struct {
|
|||
|
||||
// CreateRawTransactionCmd defines the createrawtransaction JSON-RPC command.
|
||||
type CreateRawTransactionCmd struct {
|
||||
Inputs []TransactionInput
|
||||
Amounts map[string]float64 `jsonrpcusage:"{\"address\":amount,...}"` // In BTC
|
||||
Inputs []TransactionInput
|
||||
Amounts map[string]float64 `jsonrpcusage:"{\"address\":amount,...}"` // In BTC
|
||||
LockTime *int64
|
||||
}
|
||||
|
||||
// NewCreateRawTransactionCmd returns a new instance which can be used to issue
|
||||
// a createrawtransaction JSON-RPC command.
|
||||
//
|
||||
// Amounts are in BTC.
|
||||
func NewCreateRawTransactionCmd(inputs []TransactionInput, amounts map[string]float64) *CreateRawTransactionCmd {
|
||||
func NewCreateRawTransactionCmd(inputs []TransactionInput, amounts map[string]float64,
|
||||
lockTime *int64) *CreateRawTransactionCmd {
|
||||
|
||||
return &CreateRawTransactionCmd{
|
||||
Inputs: inputs,
|
||||
Amounts: amounts,
|
||||
Inputs: inputs,
|
||||
Amounts: amounts,
|
||||
LockTime: lockTime,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ func TestChainSvrCmds(t *testing.T) {
|
|||
{Txid: "123", Vout: 1},
|
||||
}
|
||||
amounts := map[string]float64{"456": .0123}
|
||||
return btcjson.NewCreateRawTransactionCmd(txInputs, amounts)
|
||||
return btcjson.NewCreateRawTransactionCmd(txInputs, amounts, nil)
|
||||
},
|
||||
marshalled: `{"jsonrpc":"1.0","method":"createrawtransaction","params":[[{"txid":"123","vout":1}],{"456":0.0123}],"id":1}`,
|
||||
unmarshalled: &btcjson.CreateRawTransactionCmd{
|
||||
|
@ -59,6 +59,27 @@ func TestChainSvrCmds(t *testing.T) {
|
|||
Amounts: map[string]float64{"456": .0123},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "createrawtransaction optional",
|
||||
newCmd: func() (interface{}, error) {
|
||||
return btcjson.NewCmd("createrawtransaction", `[{"txid":"123","vout":1}]`,
|
||||
`{"456":0.0123}`, 12312333333)
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
txInputs := []btcjson.TransactionInput{
|
||||
{Txid: "123", Vout: 1},
|
||||
}
|
||||
amounts := map[string]float64{"456": .0123}
|
||||
return btcjson.NewCreateRawTransactionCmd(txInputs, amounts, btcjson.Int64(12312333333))
|
||||
},
|
||||
marshalled: `{"jsonrpc":"1.0","method":"createrawtransaction","params":[[{"txid":"123","vout":1}],{"456":0.0123},12312333333],"id":1}`,
|
||||
unmarshalled: &btcjson.CreateRawTransactionCmd{
|
||||
Inputs: []btcjson.TransactionInput{{Txid: "123", Vout: 1}},
|
||||
Amounts: map[string]float64{"456": .0123},
|
||||
LockTime: btcjson.Int64(12312333333),
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "decoderawtransaction",
|
||||
newCmd: func() (interface{}, error) {
|
||||
|
|
|
@ -199,10 +199,10 @@ the method name for further details such as parameter and return information.
|
|||
| | |
|
||||
|---|---|
|
||||
|Method|createrawtransaction|
|
||||
|Parameters|1. transaction inputs (JSON array, required) - json array of json objects<br />`[`<br /> `{`<br /> `"txid": "hash", (string, required) the hash of the input transaction`<br /> `"vout": n (numeric, required) the specific output of the input transaction to redeem`<br /> `}, ...`<br />`]`<br />2. addresses and amounts (JSON object, required) - json object with addresses as keys and amounts as values<br />`{`<br /> `"address": n.nnn (numeric, required) the address to send to as the key and the amount in BTC as the value`<br /> `, ...`<br />`}`|
|
||||
|Parameters|1. transaction inputs (JSON array, required) - json array of json objects<br />`[`<br /> `{`<br /> `"txid": "hash", (string, required) the hash of the input transaction`<br /> `"vout": n (numeric, required) the specific output of the input transaction to redeem`<br /> `}, ...`<br />`]`<br />2. addresses and amounts (JSON object, required) - json object with addresses as keys and amounts as values<br />`{`<br /> `"address": n.nnn (numeric, required) the address to send to as the key and the amount in BTC as the value`<br /> `, ...`<br />`}`<br />3. locktime (int64, optional, default=0) - specifies the transaction locktime. If non-zero, the inputs will also have their locktimes activated. |
|
||||
|Description|Returns a new transaction spending the provided inputs and sending to the provided addresses.<br />The transaction inputs are not signed in the created transaction.<br />The `signrawtransaction` RPC command provided by wallet must be used to sign the resulting transaction.|
|
||||
|Returns|`"transaction" (string) hex-encoded bytes of the serialized transaction`|
|
||||
|Example Parameters|1. transaction inputs `[{"txid":"e6da89de7a6b8508ce8f371a3d0535b04b5e108cb1a6e9284602d3bfd357c018","vout":1}]`<br />2. addresses and amounts `{"13cgrTP7wgbZYWrY9BZ22BV6p82QXQT3nY": 0.49213337}`|
|
||||
|Example Parameters|1. transaction inputs `[{"txid":"e6da89de7a6b8508ce8f371a3d0535b04b5e108cb1a6e9284602d3bfd357c018","vout":1}]`<br />2. addresses and amounts `{"13cgrTP7wgbZYWrY9BZ22BV6p82QXQT3nY": 0.49213337}`<br />3. locktime `0`|
|
||||
|Example Return|`010000000118c057d3bfd3024628e9a6b18c105e4bb035053d1a378fce08856b7ade89dae6010000`<br />`0000ffffffff0199efee02000000001976a9141cb013db35ecccc156fdfd81d03a11c51998f99388`<br />`ac00000000`<br /><font color="orange">**Newlines added for display purposes. The actual return does not contain newlines.**</font>|
|
||||
[Return to Overview](#MethodOverview)<br />
|
||||
|
||||
|
|
17
rpcserver.go
17
rpcserver.go
|
@ -511,6 +511,15 @@ func messageToHex(msg wire.Message) (string, error) {
|
|||
func handleCreateRawTransaction(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
|
||||
c := cmd.(*btcjson.CreateRawTransactionCmd)
|
||||
|
||||
// Validate the locktime, if given.
|
||||
if c.LockTime != nil &&
|
||||
(*c.LockTime < 0 || *c.LockTime > int64(wire.MaxTxInSequenceNum)) {
|
||||
return nil, &btcjson.RPCError{
|
||||
Code: btcjson.ErrRPCInvalidParameter,
|
||||
Message: "Locktime out of range",
|
||||
}
|
||||
}
|
||||
|
||||
// Add all transaction inputs to a new transaction after performing
|
||||
// some validity checks.
|
||||
mtx := wire.NewMsgTx()
|
||||
|
@ -522,6 +531,9 @@ func handleCreateRawTransaction(s *rpcServer, cmd interface{}, closeChan <-chan
|
|||
|
||||
prevOut := wire.NewOutPoint(txHash, uint32(input.Vout))
|
||||
txIn := wire.NewTxIn(prevOut, []byte{})
|
||||
if c.LockTime != nil && *c.LockTime != 0 {
|
||||
txIn.Sequence = wire.MaxTxInSequenceNum - 1
|
||||
}
|
||||
mtx.AddTxIn(txIn)
|
||||
}
|
||||
|
||||
|
@ -584,6 +596,11 @@ func handleCreateRawTransaction(s *rpcServer, cmd interface{}, closeChan <-chan
|
|||
mtx.AddTxOut(txOut)
|
||||
}
|
||||
|
||||
// Set the Locktime, if given.
|
||||
if c.LockTime != nil {
|
||||
mtx.LockTime = uint32(*c.LockTime)
|
||||
}
|
||||
|
||||
// Return the serialized and hex-encoded transaction. Note that this
|
||||
// is intentionally not directly returning because the first return
|
||||
// value is a string and it would result in returning an empty string to
|
||||
|
|
|
@ -52,6 +52,7 @@ var helpDescsEnUS = map[string]string{
|
|||
"createrawtransaction-amounts--key": "address",
|
||||
"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--result0": "Hex-encoded bytes of the serialized transaction",
|
||||
|
||||
// ScriptSig help.
|
||||
|
|
Loading…
Reference in a new issue