Author

Topic: PSBT/BIP174: how to create inputs/outputs using bitcoin-cli (Read 255 times)

staff
Activity: 3458
Merit: 6793
Just writing some code
then I get

Code:
error code: -4
error message:
Signing transaction failed
TBF this error is not actually descriptive of what is actually happening. There are two places where this same error is thrown. In one case, signing is actually failing. In the other case (which is what you are hitting here), the wallet is unable to calculate the estimated size of the final transaction which it does by using the dummy signer. So technically it's correct because dummy signing failed (it fails under the same circumstances that normal signing does too), but it isn't terribly helpful and is kind of confusing.

Also, correction to what I said above, walletcreatefundedpsbt doesn't actually fill in the metadata. It is just a version of createpsbt which selects inputs and change outputs for you. The metadata is added by walletprocesspsbt.
legendary
Activity: 3430
Merit: 3080
So something a little strange may be happening.

If I do:

Code:
walletcreatefundedpsbt [{"txid":"hextxid","vout":}] [{"
":}]

then I get

Code:
error code: -4
error message:
Signing transaction failed

whereas if walletcreatefundedpsbt chooses the inputs like this:

Code:
walletcreatefundedpsbt [] [{"
":}]

it returns a base64 string, and the outputs that supposedly cannot be signed from the previous command are chosen as inputs.


but then using utxoupdatepsbt on that string doesn't create any outputs, and both ScriptSig and ScriptPubkey in the metadata section are blank, although txids from the wallet are present. I am confused.


Edit: I was wrong, vout is 1 not 0. *sigh*

Sorry to anyone trying to follow along, this is really just one big case of me being too impatient mixed with not knowing what I'm doing
legendary
Activity: 3430
Merit: 3080
It clearly says that the second parameter named sign is a boolean whose default value is true. Because it is a boolean, the value you can use for it are true or false.

shit, it does.


If you have any suggestions on how this can be clearer, then please let us know. The way that this help text is written follows the way that we have been writing help texts for a long time.

Maybe an example at the bottom of the help text would help, but that's no excuse for me not reading the help properly

I've never seen this way of handling command parameters before, in bitcoin or elsewhere! But maybe this is something typical in RPC interfaces?


And perhaps I'm getting the conceptual details wrong again, but that doesn't change the result of decodepsbt, I get an array of inputs but no outputs.
(yes, the wallet for the inputs is loaded in the machine I'm using)
It is not an array of outputs, it is an array of output metadata. If your wallet does not own those outputs, then no output metadata will be given. The outputs are specified in the actual transaction at the top.

Using the same inputs as I used for createpsbt, I'm getting:

Code:
error code: -4
error message:
Signing transaction failed

(again, the wallet containing the inputs is loaded on the machine I'm using)
Are the inputs standard inputs (i.e. ones that Bitcoin Core can sign for)? Do you have all of the information for the inputs in the wallet (e.g. redeemScripts, witnessScripts, etc.)?

So at the moment I'm only familiarising myself with the commands for PSBTs. I'm doing this particular example very simply, so I'm letting bitcoin-cli create a standard redeem script, and I'm using P2PKH addresses for both inputs & outputs as further means of keeping things as simple as possible (I'll do all this with segwit transactions once I have the redeemScript I want to use working with P2PKH).

On the machine I'm using:
Code:
bitcoin-cli listunspent

The outputs with the txids and amounts I'm providing as inputs to the PSBT are returned by listunspent. They've got >6 confirmations, and they were not mined, but they were sent from mined outputs on another machine on my regtest-net.

then

Code:
bitcoin-cli walletcreatefundedpsbt $(cat psbtdata)

So there surely must be something going badly wrong with my setup... I find it hard to believe you guys don't have a test for such simple circumstances.
staff
Activity: 3458
Merit: 6793
Just writing some code
How could I have figured that out without asking? The available docs/help don't make any mention of that
Yes it does. The help text for walletprocesspsbt states:
Code:
walletprocesspsbt "psbt" ( sign "sighashtype" bip32derivs )

Update a PSBT with input information from our wallet and then sign inputs
that we can sign for.

Arguments:
1. psbt           (string, required) The transaction base64 string
2. sign           (boolean, optional, default=true) Also sign the transaction when updating
3. sighashtype    (string, optional, default=ALL) The signature hash type to sign with if not specified by the PSBT. Must be one of
                  "ALL"
                  "NONE"
                  "SINGLE"
                  "ALL|ANYONECANPAY"
                  "NONE|ANYONECANPAY"
                  "SINGLE|ANYONECANPAY"
4. bip32derivs    (boolean, optional, default=false) If true, includes the BIP 32 derivation paths for public keys if we know them
...
It clearly says that the second parameter named sign is a boolean whose default value is true. Because it is a boolean, the value you can use for it are true or false.

If you have any suggestions on how this can be clearer, then please let us know. The way that this help text is written follows the way that we have been writing help texts for a long time.

And perhaps I'm getting the conceptual details wrong again, but that doesn't change the result of decodepsbt, I get an array of inputs but no outputs.
(yes, the wallet for the inputs is loaded in the machine I'm using)
It is not an array of outputs, it is an array of output metadata. If your wallet does not own those outputs, then no output metadata will be given. The outputs are specified in the actual transaction at the top.

Using the same inputs as I used for createpsbt, I'm getting:

Code:
error code: -4
error message:
Signing transaction failed

(again, the wallet containing the inputs is loaded on the machine I'm using)
Are the inputs standard inputs (i.e. ones that Bitcoin Core can sign for)? Do you have all of the information for the inputs in the wallet (e.g. redeemScripts, witnessScripts, etc.)?

maybe I should specify exactly what I want to do


Either:

A. Receiver creates a .psbt file, with no inputs specified, but 1 or more outputs that pay to a custom ScriptPubKey (details of doing that are ot for this thread). Payer takes the .psbt, adds their input, signs it, broadcast

or if that's not possible...

B. Receiver creates the ScriptPubKey they wish to be paid to, Payer takes that and creates the .psbt themself, using that/those outputs, adds their own inputs, signs, broadcasts


Which (if either) of these is possible?
B is possible under specific circumstances.

First of all, what you want to do in A is not what PSBT is supposed to be used for. PSBT is not for the step where you choose the inputs and outputs of a transaction. It is for the step where you have already chosen the inputs and outputs and now need to sign the transaction and otherwise make it complete for broadcast. When the BIP says anything along the lines of "add input and output information" it means adding the input and output metadata. The inputs and outputs are already chosen, but their metadata is not necessarily available to the person who created the PSBT, so each participant in the transaction needs to add the metadata for their inputs.

B is possible if the scriptPubKey is an address. Bitcoin Core does not allow you to use custom scriptPubKeys, although you can achieve that by using P2SH/P2WSH addresses.

What you do is use walletcreatefundedpsbt, then walletprocesspsbt, then finalizepsbt. Your command should look something like this:

Code:
walletcreatefundedpsbt '[]' '[{"
":walletprocesspsbt ""
finalizepbt ""

If you really want to use sighash single, then you use the command I gave you earlier.
legendary
Activity: 3430
Merit: 3080
maybe I should specify exactly what I want to do


Either:

A. Receiver creates a .psbt file, with no inputs specified, but 1 or more outputs that pay to a custom ScriptPubKey (details of doing that are ot for this thread). Payer takes the .psbt, adds their input, signs it, broadcast

or if that's not possible...

B. Receiver creates the ScriptPubKey they wish to be paid to, Payer takes that and creates the .psbt themself, using that/those outputs, adds their own inputs, signs, broadcasts


Which (if either) of these is possible?
legendary
Activity: 3430
Merit: 3080
Code:
walletprocesspsbt  true "SINGLE"
should do what you want.

How could I have figured that out without asking? The available docs/help don't make any mention of that

And perhaps I'm getting the conceptual details wrong again, but that doesn't change the result of decodepsbt, I get an array of inputs but no outputs.
(yes, the wallet for the inputs is loaded in the machine I'm using)


The RPC you are looking for is walletcreatefundedpsbt.

Using the same inputs as I used for createpsbt, I'm getting:

Code:
error code: -4
error message:
Signing transaction failed

(again, the wallet containing the inputs is loaded on the machine I'm using)
staff
Activity: 3458
Merit: 6793
Just writing some code
It's not at all clear how this should be done


According to bitcoin-cli help createpsbt:

Code:
createpsbt [{"txid":"hex","vout":n,"sequence":n},...] [{"address":amount},{"data":"hex"},...]

When using the form from the help as above, the inputs array is never populated if checking it using decodepsbt
createpsbt has no access to your wallet or to the UTXO set. It is functionally the same as createrawtransaction and just drops the raw transaction into an otherwise blank PSBT.

The RPC you are looking for is walletcreatefundedpsbt. This is like a combination of createrawtransaction and fundrawtransaction. You specify the inputs and outputs as you were doing with createsbt and all of the metadata will be filled in from information in your wallet. If you don't choose enough inputs or you don't have a change output, more inputs will be selected and a change output added.

(slightly ot: why are inputs/outputs added to the transaction: array at all? What's the difference between inputs/outputs in transaction: and those in inputs: and outputs?)
That isn't a transaction array. It is a raw transaction. That raw transaction is what you would get from createrawtransaction. The input and output arrays contain metadata for each of the inputs and outputs in that transaction.

walletprocesspsbt is what's needed to specify inputs
That adds all of the metadata and signs the transaction.

utxoupdatepsbt the resulting base64 string doesn't make any changes to the PSBT
utxoupdatepsbt only works for segwit inputs.

so I'm trying various things

...and all are rejected. I have inputs (which I apparently cannot choose?), but no outputs
Code:
walletprocesspsbt  true "SINGLE"
should do what you want.
legendary
Activity: 3430
Merit: 3080
so I'm trying various things

Code:
bitcoin-cli walletprocesspsbt base64fromcreatepsbt sign

Code:
bitcoin-cli walletprocesspsbt base64fromcreatepsbt sign SINGLE

Code:
bitcoin-cli walletprocesspsbt base64fromcreatepsbt sign "SINGLE"

Code:
bitcoin-cli walletprocesspsbt base64fromcreatepsbt -sign "SINGLE"

Code:
bitcoin-cli walletprocesspsbt base64fromcreatepsbt -sign="SINGLE"

Code:
bitcoin-cli walletprocesspsbt base64fromcreatepsbt sign="SINGLE"


...and all are rejected. I have inputs (which I apparently cannot choose?), but no outputs
legendary
Activity: 3430
Merit: 3080
doh, just figured it out Grin

walletprocesspsbt is what's needed to specify inputs

still don't understand the purpose of the transaction: array, will these turn into the outputs after I figure out the magic words to do that? (I am attempting now to find the answer myself...)
legendary
Activity: 3430
Merit: 3080
It's not at all clear how this should be done


According to bitcoin-cli help createpsbt:

Code:
createpsbt [{"txid":"hex","vout":n,"sequence":n},...] [{"address":amount},{"data":"hex"},...]

When using the form from the help as above, the inputs array is never populated if checking it using decodepsbt

(slightly ot: why are inputs/outputs added to the transaction: array at all? What's the difference between inputs/outputs in transaction: and those in inputs: and outputs?)


utxoupdatepsbt the resulting base64 string doesn't make any changes to the PSBT


Either there is some syntactic structure missing from the help message, or there is some other 'addinput/output' a RPC call that isn't obvious to me
Jump to: