diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go
index 4023b51de..90441e6e0 100644
--- a/btcjson/chainsvrcmds.go
+++ b/btcjson/chainsvrcmds.go
@@ -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,
}
}
diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go
index 84e719c03..527bc0ba8 100644
--- a/btcjson/chainsvrcmds_test.go
+++ b/btcjson/chainsvrcmds_test.go
@@ -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) {
diff --git a/docs/json_rpc_api.md b/docs/json_rpc_api.md
index 7779cf064..28928f046 100644
--- a/docs/json_rpc_api.md
+++ b/docs/json_rpc_api.md
@@ -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
`[`
`{`
`"txid": "hash", (string, required) the hash of the input transaction`
`"vout": n (numeric, required) the specific output of the input transaction to redeem`
`}, ...`
`]`
2. addresses and amounts (JSON object, required) - json object with addresses as keys and amounts as values
`{`
`"address": n.nnn (numeric, required) the address to send to as the key and the amount in BTC as the value`
`, ...`
`}`|
+|Parameters|1. transaction inputs (JSON array, required) - json array of json objects
`[`
`{`
`"txid": "hash", (string, required) the hash of the input transaction`
`"vout": n (numeric, required) the specific output of the input transaction to redeem`
`}, ...`
`]`
2. addresses and amounts (JSON object, required) - json object with addresses as keys and amounts as values
`{`
`"address": n.nnn (numeric, required) the address to send to as the key and the amount in BTC as the value`
`, ...`
`}`
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.
The transaction inputs are not signed in the created transaction.
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}]`
2. addresses and amounts `{"13cgrTP7wgbZYWrY9BZ22BV6p82QXQT3nY": 0.49213337}`|
+|Example Parameters|1. transaction inputs `[{"txid":"e6da89de7a6b8508ce8f371a3d0535b04b5e108cb1a6e9284602d3bfd357c018","vout":1}]`
2. addresses and amounts `{"13cgrTP7wgbZYWrY9BZ22BV6p82QXQT3nY": 0.49213337}`
3. locktime `0`|
|Example Return|`010000000118c057d3bfd3024628e9a6b18c105e4bb035053d1a378fce08856b7ade89dae6010000`
`0000ffffffff0199efee02000000001976a9141cb013db35ecccc156fdfd81d03a11c51998f99388`
`ac00000000`
**Newlines added for display purposes. The actual return does not contain newlines.**|
[Return to Overview](#MethodOverview)
diff --git a/rpcserver.go b/rpcserver.go
index 3af8a5b4b..e4365ad02 100644
--- a/rpcserver.go
+++ b/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
diff --git a/rpcserverhelp.go b/rpcserverhelp.go
index 915777a4a..d9b0b3053 100644
--- a/rpcserverhelp.go
+++ b/rpcserverhelp.go
@@ -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.