From 9d7fb99b8bd041e7d51ac1095bf696ac52083b7c Mon Sep 17 00:00:00 2001 From: David Hill Date: Thu, 7 May 2015 12:28:25 -0400 Subject: [PATCH] Add script verification errors to signrawtransaction result. This mimics Bitcoin Core commit 8ac2a4e1788426329b842eea7121b8eac7875c76 --- internal/rpchelp/helpdescs_en_US.go | 8 ++++++++ rpcserver.go | 28 +++++++++++++++++++++++----- rpcserverhelp.go | 2 +- 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/internal/rpchelp/helpdescs_en_US.go b/internal/rpchelp/helpdescs_en_US.go index 6d3953d..2311001 100644 --- a/internal/rpchelp/helpdescs_en_US.go +++ b/internal/rpchelp/helpdescs_en_US.go @@ -316,6 +316,14 @@ var helpDescsEnUS = map[string]string{ // SignRawTransactionResult help. "signrawtransactionresult-hex": "The resulting transaction encoded as a hexadecimal string", "signrawtransactionresult-complete": "Whether all input signatures have been created", + "signrawtransactionresult-errors": "Script verification errors (if exists)", + + // SignRawTransactionError help. + "signrawtransactionerror-error": "Verification or signing error related to the input", + "signrawtransactionerror-sequence": "Script sequence number", + "signrawtransactionerror-scriptSig": "The hex-encoded signature script", + "signrawtransactionerror-txid": "The transaction hash of the referenced previous output", + "signrawtransactionerror-vout": "The output index of the referenced previous output", // ValidateAddressCmd help. "validateaddress--synopsis": "Verify that an address is valid.\n" + diff --git a/rpcserver.go b/rpcserver.go index bbc2538..c91d083 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2981,7 +2981,7 @@ func SignRawTransaction(w *wallet.Wallet, chainSvr *chain.Client, icmd interface // `complete' denotes that we successfully signed all outputs and that // all scripts will run to completion. This is returned as part of the // reply. - complete := true + var signErrors []btcjson.SignRawTransactionError for i, txIn := range msgTx.TxIn { input, ok := inputs[txIn.PreviousOutPoint] if !ok { @@ -3060,7 +3060,14 @@ func SignRawTransaction(w *wallet.Wallet, chainSvr *chain.Client, icmd interface // Failure to sign isn't an error, it just means that // the tx isn't complete. if err != nil { - complete = false + signErrors = append(signErrors, + btcjson.SignRawTransactionError{ + TxID: txIn.PreviousOutPoint.Hash.String(), + Vout: txIn.PreviousOutPoint.Index, + ScriptSig: hex.EncodeToString(txIn.SignatureScript), + Sequence: txIn.Sequence, + Error: err.Error(), + }) continue } txIn.SignatureScript = script @@ -3070,8 +3077,18 @@ func SignRawTransaction(w *wallet.Wallet, chainSvr *chain.Client, icmd interface // Find out if it is completely satisfied or still needs more. vm, err := txscript.NewEngine(input, msgTx, i, txscript.StandardVerifyFlags) - if err != nil || vm.Execute() != nil { - complete = false + if err == nil { + err = vm.Execute() + } + if err != nil { + signErrors = append(signErrors, + btcjson.SignRawTransactionError{ + TxID: txIn.PreviousOutPoint.Hash.String(), + Vout: txIn.PreviousOutPoint.Index, + ScriptSig: hex.EncodeToString(txIn.SignatureScript), + Sequence: txIn.Sequence, + Error: err.Error(), + }) } } @@ -3086,7 +3103,8 @@ func SignRawTransaction(w *wallet.Wallet, chainSvr *chain.Client, icmd interface return btcjson.SignRawTransactionResult{ Hex: hex.EncodeToString(buf.Bytes()), - Complete: complete, + Complete: len(signErrors) == 0, + Errors: signErrors, }, nil } diff --git a/rpcserverhelp.go b/rpcserverhelp.go index fc83455..f4435df 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -35,7 +35,7 @@ func helpDescsEnUS() map[string]string { "sendtoaddress": "sendtoaddress \"address\" amount (\"comment\" \"commentto\")\n\nAuthors, signs, and sends a transaction that outputs some amount to a payment address.\nUnlike sendfrom, outputs are always chosen from the default account.\nA change output is automatically included to send extra output value back to the original account.\n\nArguments:\n1. address (string, required) Address to pay\n2. amount (numeric, required) Amount to send to the payment address valued in bitcoin\n3. comment (string, optional) Unused\n4. commentto (string, optional) Unused\n\nResult:\n\"value\" (string) The transaction hash of the sent transaction\n", "settxfee": "settxfee amount\n\nModify the increment used each time more fee is required for an authored transaction.\n\nArguments:\n1. amount (numeric, required) The new fee increment valued in bitcoin\n\nResult:\ntrue|false (boolean) The boolean 'true'\n", "signmessage": "signmessage \"address\" \"message\"\n\nSigns a message using the private key of a payment address.\n\nArguments:\n1. address (string, required) Payment address of private key used to sign the message with\n2. message (string, required) Message to sign\n\nResult:\n\"value\" (string) The signed message encoded as a base64 string\n", - "signrawtransaction": "signrawtransaction \"rawtx\" ([{\"txid\":\"value\",\"vout\":n,\"scriptpubkey\":\"value\",\"redeemscript\":\"value\"},...] [\"privkey\",...] flags=\"ALL\")\n\nSigns transaction inputs using private keys from this wallet and request.\nThe valid flags options are ALL, NONE, SINGLE, ALL|ANYONECANPAY, NONE|ANYONECANPAY, and SINGLE|ANYONECANPAY.\n\nArguments:\n1. rawtx (string, required) Unsigned or partially unsigned transaction to sign encoded as a hexadecimal string\n2. inputs (array of object, optional) Additional data regarding inputs that this wallet may not be tracking\n3. privkeys (array of string, optional) Additional WIF-encoded private keys to use when creating signatures\n4. flags (string, optional, default=\"ALL\") Sighash flags\n\nResult:\n{\n \"hex\": \"value\", (string) The resulting transaction encoded as a hexadecimal string\n \"complete\": true|false, (boolean) Whether all input signatures have been created\n} \n", + "signrawtransaction": "signrawtransaction \"rawtx\" ([{\"txid\":\"value\",\"vout\":n,\"scriptpubkey\":\"value\",\"redeemscript\":\"value\"},...] [\"privkey\",...] flags=\"ALL\")\n\nSigns transaction inputs using private keys from this wallet and request.\nThe valid flags options are ALL, NONE, SINGLE, ALL|ANYONECANPAY, NONE|ANYONECANPAY, and SINGLE|ANYONECANPAY.\n\nArguments:\n1. rawtx (string, required) Unsigned or partially unsigned transaction to sign encoded as a hexadecimal string\n2. inputs (array of object, optional) Additional data regarding inputs that this wallet may not be tracking\n3. privkeys (array of string, optional) Additional WIF-encoded private keys to use when creating signatures\n4. flags (string, optional, default=\"ALL\") Sighash flags\n\nResult:\n{\n \"hex\": \"value\", (string) The resulting transaction encoded as a hexadecimal string\n \"complete\": true|false, (boolean) Whether all input signatures have been created\n \"errors\": [{ (array of object) Script verification errors (if exists)\n \"txid\": \"value\", (string) The transaction hash of the referenced previous output\n \"vout\": n, (numeric) The output index of the referenced previous output\n \"scriptSig\": \"value\", (string) The hex-encoded signature script\n \"sequence\": n, (numeric) Script sequence number\n \"error\": \"value\", (string) Verification or signing error related to the input\n },...], \n} \n", "validateaddress": "validateaddress \"address\"\n\nVerify that an address is valid.\nExtra details are returned if the address is controlled by this wallet.\nThe following fields are valid only when the address is controlled by this wallet (ismine=true): isscript, pubkey, iscompressed, account, addresses, hex, script, and sigsrequired.\nThe following fields are only valid when address has an associated public key: pubkey, iscompressed.\nThe following fields are only valid when address is a pay-to-script-hash address: addresses, hex, and script.\nIf the address is a multisig address controlled by this wallet, the multisig fields will be left unset if the wallet is locked since the redeem script cannot be decrypted.\n\nArguments:\n1. address (string, required) Address to validate\n\nResult:\n{\n \"isvalid\": true|false, (boolean) Whether or not the address is valid\n \"address\": \"value\", (string) The payment address (only when isvalid is true)\n \"ismine\": true|false, (boolean) Whether this address is controlled by the wallet (only when isvalid is true)\n \"iswatchonly\": true|false, (boolean) Unset\n \"isscript\": true|false, (boolean) Whether the payment address is a pay-to-script-hash address (only when isvalid is true)\n \"pubkey\": \"value\", (string) The associated public key of the payment address, if any (only when isvalid is true)\n \"iscompressed\": true|false, (boolean) Whether the address was created by hashing a compressed public key, if any (only when isvalid is true)\n \"account\": \"value\", (string) The account this payment address belongs to (only when isvalid is true)\n \"addresses\": [\"value\",...], (array of string) All associated payment addresses of the script if address is a multisig address (only when isvalid is true)\n \"hex\": \"value\", (string) The redeem script \n \"script\": \"value\", (string) The class of redeem script for a multisig address\n \"sigsrequired\": n, (numeric) The number of required signatures to redeem outputs to the multisig address\n} \n", "verifymessage": "verifymessage \"address\" \"signature\" \"message\"\n\nVerify a message was signed with the associated private key of some address.\n\nArguments:\n1. address (string, required) Address used to sign message\n2. signature (string, required) The signature to verify\n3. message (string, required) The message to verify\n\nResult:\ntrue|false (boolean) Whether the message was signed with the private key of 'address'\n", "walletlock": "walletlock\n\nLock the wallet.\n\nArguments:\nNone\n\nResult:\nNothing\n",