Add support for createrawtransaction RPC command.
This commit is contained in:
parent
405eca4a44
commit
b6b2fd15b3
1 changed files with 103 additions and 15 deletions
118
rpcserver.go
118
rpcserver.go
|
@ -53,7 +53,7 @@ var rpcHandlers = map[string]commandHandler{
|
|||
"addnode": handleAddNode,
|
||||
"backupwallet": handleAskWallet,
|
||||
"createmultisig": handleAskWallet,
|
||||
"createrawtransaction": handleUnimplemented,
|
||||
"createrawtransaction": handleCreateRawTransaction,
|
||||
"debuglevel": handleDebugLevel,
|
||||
"decoderawtransaction": handleDecodeRawTransaction,
|
||||
"decodescript": handleUnimplemented,
|
||||
|
@ -460,6 +460,108 @@ func handleAddNode(s *rpcServer, cmd btcjson.Cmd) (interface{}, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
// messageToHex serializes a message to the wire protocol encoding using the
|
||||
// latest protocol version and returns a hex-encoded string of the result.
|
||||
func messageToHex(msg btcwire.Message) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
err := msg.BtcEncode(&buf, btcwire.ProtocolVersion)
|
||||
if err != nil {
|
||||
return "", btcjson.Error{
|
||||
Code: btcjson.ErrInternal.Code,
|
||||
Message: err.Error(),
|
||||
}
|
||||
}
|
||||
return hex.EncodeToString(buf.Bytes()), nil
|
||||
}
|
||||
|
||||
// handleCreateRawTransaction handles createrawtransaction commands.
|
||||
func handleCreateRawTransaction(s *rpcServer, cmd btcjson.Cmd) (interface{}, error) {
|
||||
c := cmd.(*btcjson.CreateRawTransactionCmd)
|
||||
|
||||
// Add all transaction inputs to a new transaction after performing
|
||||
// some validty checks.
|
||||
mtx := btcwire.NewMsgTx()
|
||||
for _, input := range c.Inputs {
|
||||
txHash, err := btcwire.NewShaHashFromStr(input.Txid)
|
||||
if err != nil {
|
||||
return nil, btcjson.ErrDecodeHexString
|
||||
}
|
||||
|
||||
if input.Vout < 0 {
|
||||
return nil, btcjson.Error{
|
||||
Code: btcjson.ErrInvalidParameter.Code,
|
||||
Message: "Invalid parameter, vout must be positive",
|
||||
}
|
||||
}
|
||||
|
||||
prevOut := btcwire.NewOutPoint(txHash, uint32(input.Vout))
|
||||
txIn := btcwire.NewTxIn(prevOut, []byte{})
|
||||
mtx.AddTxIn(txIn)
|
||||
}
|
||||
|
||||
// Add all transaction outputs to the transaction after performing
|
||||
// some validty checks.
|
||||
for encodedAddr, amount := range c.Amounts {
|
||||
// Ensure amount is in the valid range for monetary amounts.
|
||||
if amount <= 0 || amount > btcutil.MaxSatoshi {
|
||||
return nil, btcjson.Error{
|
||||
Code: btcjson.ErrType.Code,
|
||||
Message: "Invalid amount",
|
||||
}
|
||||
}
|
||||
|
||||
// Decode the provided address.
|
||||
addr, err := btcutil.DecodeAddr(encodedAddr)
|
||||
if err != nil {
|
||||
return nil, btcjson.Error{
|
||||
Code: btcjson.ErrInvalidAddressOrKey.Code,
|
||||
Message: btcjson.ErrInvalidAddressOrKey.Message +
|
||||
": " + err.Error(),
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the address is one of the supported types and that
|
||||
// the network encoded with the address matches the network the
|
||||
// server is currently on.
|
||||
net := s.server.btcnet
|
||||
switch addr := addr.(type) {
|
||||
case *btcutil.AddressPubKeyHash:
|
||||
net = addr.Net()
|
||||
case *btcutil.AddressScriptHash:
|
||||
net = addr.Net()
|
||||
default:
|
||||
return nil, btcjson.ErrInvalidAddressOrKey
|
||||
}
|
||||
if net != s.server.btcnet {
|
||||
return nil, btcjson.Error{
|
||||
Code: btcjson.ErrInvalidAddressOrKey.Code,
|
||||
Message: fmt.Sprintf("%s: %q",
|
||||
btcjson.ErrInvalidAddressOrKey.Message,
|
||||
encodedAddr),
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new script which pays to the provided address.
|
||||
pkScript, err := btcscript.PayToAddrScript(addr)
|
||||
if err != nil {
|
||||
return nil, btcjson.Error{
|
||||
Code: btcjson.ErrInternal.Code,
|
||||
Message: err.Error(),
|
||||
}
|
||||
}
|
||||
|
||||
txOut := btcwire.NewTxOut(amount, pkScript)
|
||||
mtx.AddTxOut(txOut)
|
||||
}
|
||||
|
||||
// Return the serialized and hex-encoded transaction.
|
||||
mtxHex, err := messageToHex(mtx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mtxHex, nil
|
||||
}
|
||||
|
||||
// handleDebugLevel handles debuglevel commands.
|
||||
func handleDebugLevel(s *rpcServer, cmd btcjson.Cmd) (interface{}, error) {
|
||||
c := cmd.(*btcjson.DebugLevelCmd)
|
||||
|
@ -614,20 +716,6 @@ func handleGetBestBlockHash(s *rpcServer, cmd btcjson.Cmd) (interface{}, error)
|
|||
return sha.String(), nil
|
||||
}
|
||||
|
||||
// messageToHex serializes a message to the wire protocol encoding using the
|
||||
// latest protocol version and returns a hex-encoded string of the result.
|
||||
func messageToHex(msg btcwire.Message) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
err := msg.BtcEncode(&buf, btcwire.ProtocolVersion)
|
||||
if err != nil {
|
||||
return "", btcjson.Error{
|
||||
Code: btcjson.ErrInternal.Code,
|
||||
Message: err.Error(),
|
||||
}
|
||||
}
|
||||
return hex.EncodeToString(buf.Bytes()), nil
|
||||
}
|
||||
|
||||
// handleGetBlock implements the getblock command.
|
||||
func handleGetBlock(s *rpcServer, cmd btcjson.Cmd) (interface{}, error) {
|
||||
c := cmd.(*btcjson.GetBlockCmd)
|
||||
|
|
Loading…
Reference in a new issue