Skip to content

Commit 7ec01fd

Browse files
authored
Merge pull request #4278 from PastaPastaPasta/backports-0.18-pr9
Backports 0.18 pr9
2 parents 8c91a8b + 682c31d commit 7ec01fd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+374
-208
lines changed

doc/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ The Dash Core repo's [root README](/README.md) contains relevant information on
7676
- [Tor Support](tor.md)
7777
- [Init Scripts (systemd/upstart/openrc)](init.md)
7878
- [ZMQ](zmq.md)
79+
- [PSBT support](psbt.md)
7980

8081
License
8182
---------------------

doc/psbt.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# PSBT Howto for Bitcoin Core
2+
3+
Since Bitcoin Core 0.17, an RPC interface exists for Partially Signed Bitcoin
4+
Transactions (PSBTs, as specified in
5+
[BIP 174](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki)).
6+
7+
This document describes the overall workflow for producing signed transactions
8+
through the use of PSBT, and the specific RPC commands used in typical
9+
scenarios.
10+
11+
## PSBT in general
12+
13+
PSBT is an interchange format for Bitcoin transactions that are not fully signed
14+
yet, together with relevant metadata to help entities work towards signing it.
15+
It is intended to simplify workflows where multiple parties need to cooperate to
16+
produce a transaction. Examples include hardware wallets, multisig setups, and
17+
[CoinJoin](https://bitcointalk.org/?topic=279249) transactions.
18+
19+
### Overall workflow
20+
21+
Overall, the construction of a fully signed Bitcoin transaction goes through the
22+
following steps:
23+
24+
- A **Creator** proposes a particular transaction to be created. They construct
25+
a PSBT that contains certain inputs and outputs, but no additional metadata.
26+
- For each input, an **Updater** adds information about the UTXOs being spent by
27+
the transaction to the PSBT. They also add information about the scripts and
28+
public keys involved in each of the inputs (and possibly outputs) of the PSBT.
29+
- **Signers** inspect the transaction and its metadata to decide whether they
30+
agree with the transaction. They can use amount information from the UTXOs
31+
to assess the values and fees involved. If they agree, they produce a
32+
partial signature for the inputs for which they have relevant key(s).
33+
- A **Finalizer** is run for each input to convert the partial signatures and
34+
possibly script information into a final `scriptSig` and/or `scriptWitness`.
35+
- An **Extractor** produces a valid Bitcoin transaction (in network format)
36+
from a PSBT for which all inputs are finalized.
37+
38+
Generally, each of the above (excluding Creator and Extractor) will simply
39+
add more and more data to a particular PSBT, until all inputs are fully signed.
40+
In a naive workflow, they all have to operate sequentially, passing the PSBT
41+
from one to the next, until the Extractor can convert it to a real transaction.
42+
In order to permit parallel operation, **Combiners** can be employed which merge
43+
metadata from different PSBTs for the same unsigned transaction.
44+
45+
The names above in bold are the names of the roles defined in BIP174. They're
46+
useful in understanding the underlying steps, but in practice, software and
47+
hardware implementations will typically implement multiple roles simultaneously.
48+
49+
## PSBT in Bitcoin Core
50+
51+
### RPCs
52+
53+
- **`converttopsbt` (Creator)** is a utility RPC that converts an
54+
unsigned raw transaction to PSBT format. It ignores existing signatures.
55+
- **`createpsbt` (Creator)** is a utility RPC that takes a list of inputs and
56+
outputs and converts them to a PSBT with no additional information. It is
57+
equivalent to calling `createrawtransaction` followed by `converttopsbt`.
58+
- **`walletcreatefundedpsbt` (Creator, Updater)** is a wallet RPC that creates a
59+
PSBT with the specified inputs and outputs, adds additional inputs and change
60+
to it to balance it out, and adds relevant metadata. In particular, for inputs
61+
that the wallet knows about (counting towards its normal or watch-only
62+
balance), UTXO information will be added. For outputs and inputs with UTXO
63+
information present, key and script information will be added which the wallet
64+
knows about. It is equivalent to running `createrawtransaction`, followed by
65+
`fundrawtransaction`, and `converttopsbt`.
66+
- **`walletprocesspsbt` (Updater, Signer, Finalizer)** is a wallet RPC that takes as
67+
input a PSBT, adds UTXO, key, and script data to inputs and outputs that miss
68+
it, and optionally signs inputs. Where possible it also finalizes the partial
69+
signatures.
70+
- **`finalizepsbt` (Finalizer, Extractor)** is a utility RPC that finalizes any
71+
partial signatures, and if all inputs are finalized, converts the result to a
72+
fully signed transaction which can be broadcast with `sendrawtransaction`.
73+
- **`combinepsbt` (Combiner)** is a utility RPC that implements a Combiner. It
74+
can be used at any point in the workflow to merge information added to
75+
different versions of the same PSBT. In particular it is useful to combine the
76+
output of multiple Updaters or Signers.
77+
- **`decodepsbt`** is a diagnostic utility RPC which will show all information in
78+
a PSBT in human-readable form, as well as compute its eventual fee if known.
79+
80+
### Workflows
81+
82+
#### Multisig with multiple Bitcoin Core instances
83+
84+
Alice, Bob, and Carol want to create a 2-of-3 multisig address. They're all using
85+
Bitcoin Core. We assume their wallets only contain the multisig funds. In case
86+
they also have a personal wallet, this can be accomplished through the
87+
multiwallet feature - possibly resulting in a need to add `-rpcwallet=name` to
88+
the command line in case `bitcoin-cli` is used.
89+
90+
Setup:
91+
- All three call `getnewaddress` to create a new address; call these addresses
92+
*Aalice*, *Abob*, and *Acarol*.
93+
- All three call `getaddressinfo X`, with *X* their respective address, and
94+
remember the corresponding public keys. Call these public keys *Kalice*,
95+
*Kbob*, and *Kcarol*.
96+
- All three now run `addmultisigaddress 2 ["Kalice","Kbob","Kcarol"]` to teach
97+
their wallet about the multisig script. Call the address produced by this
98+
command *Amulti*. They may be required to explicitly specify the same
99+
addresstype option each, to avoid constructing different versions due to
100+
differences in configuration.
101+
- They also run `importaddress "Amulti" "" false` to make their wallets treat
102+
payments to *Amulti* as contributing to the watch-only balance.
103+
- Others can verify the produced address by running
104+
`createmultisig 2 ["Kalice","Kbob","Kcarol"]`, and expecting *Amulti* as
105+
output. Again, it may be necessary to explicitly specify the addresstype
106+
in order to get a result that matches. This command won't enable them to
107+
initiate transactions later, however.
108+
- They can now give out *D* as address others can pay to.
109+
110+
Later, when *V* BTC has been received on *Amulti*, and Bob and Carol want to
111+
move the coins in their entirety to address *Asend*, with no change. Alice
112+
does not need to be involved.
113+
- One of them - let's assume Carol here - initiates the creation. She runs
114+
`walletcreatefundedpsbt [] {"Asend":V} 0 false {"subtractFeeFromOutputs":[0], "includeWatching":true}`.
115+
We call the resulting PSBT *P*. P does not contain any signatures.
116+
- Carol needs to sign the transaction herself. In order to do so, she runs
117+
`walletprocesspsbt P`, and gives the resulting PSBT *P2* to Bob.
118+
- Bob inspects the PSBT using `decodepsbt "P2"` to determine if the transaction
119+
has indeed just the expected input, and an output to *Asend*, and the fee is
120+
reasonable. If he agrees, he calls `walletprocesspsbt "P2"` to sign. The
121+
resulting PSBT *P3* contains both Carol's and Bob's signature.
122+
- Now anyone can call `finalizepsbt "P2"` to extract a fully signed transaction
123+
*T*.
124+
- Finally anyone can broadcast the transaction using `sendrawtransaction "T"`.
125+
126+
In case there are more signers, it may be advantageous to let them all sign in
127+
parallel, rather passing the PSBT from one signer to the next one. In the
128+
above example this would translate to Carol handing a copy of *P* to each signer
129+
separately. They can then all invoke `walletprocesspsbt P`, and end up with
130+
their individually-signed PSBT structures. They then all send those back to
131+
Carol (or anyone) who can combine them using `combinepsbt`. The last two steps
132+
(`finalizepsbt` and `sendrawtransaction`) remain unchanged.

src/bech32.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ uint32_t PolyMod(const data& v)
5858
// v, it corresponds to x^2 + v0*x + v1 mod g(x). As 1 mod g(x) = 1, that is the starting value
5959
// for `c`.
6060
uint32_t c = 1;
61-
for (auto v_i : v) {
61+
for (const auto v_i : v) {
6262
// We want to update `c` to correspond to a polynomial with one extra term. If the initial
6363
// value of `c` consists of the coefficients of c(x) = f(x) mod g(x), we modify it to
6464
// correspond to c'(x) = (f(x) * x + v_i) mod g(x), where v_i is the next input to
@@ -149,7 +149,7 @@ std::string Encode(const std::string& hrp, const data& values) {
149149
data combined = Cat(values, checksum);
150150
std::string ret = hrp + '1';
151151
ret.reserve(ret.size() + combined.size());
152-
for (auto c : combined) {
152+
for (const auto c : combined) {
153153
ret += CHARSET[c];
154154
}
155155
return ret;

src/bench/mempool_eviction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ static void AddTx(const CMutableTransaction& tx, const CAmount& nFee, CTxMemPool
1616
bool spendsCoinbase = false;
1717
unsigned int sigOpCost = 4;
1818
LockPoints lp;
19-
pool.addUnchecked(tx.GetHash(), CTxMemPoolEntry(
19+
pool.addUnchecked(CTxMemPoolEntry(
2020
MakeTransactionRef(tx), nFee, nTime, nHeight,
2121
spendsCoinbase, sigOpCost, lp));
2222
}

src/cuckoocache.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -396,15 +396,15 @@ class cache
396396
std::array<uint32_t, 8> locs = compute_hashes(e);
397397
// Make sure we have not already inserted this element
398398
// If we have, make sure that it does not get deleted
399-
for (uint32_t loc : locs)
399+
for (const uint32_t loc : locs)
400400
if (table[loc] == e) {
401401
please_keep(loc);
402402
epoch_flags[loc] = last_epoch;
403403
return;
404404
}
405405
for (uint8_t depth = 0; depth < depth_limit; ++depth) {
406406
// First try to insert to an empty slot, if one exists
407-
for (uint32_t loc : locs) {
407+
for (const uint32_t loc : locs) {
408408
if (!collection_flags.bit_is_set(loc))
409409
continue;
410410
table[loc] = std::move(e);
@@ -468,7 +468,7 @@ class cache
468468
inline bool contains(const Element& e, const bool erase) const
469469
{
470470
std::array<uint32_t, 8> locs = compute_hashes(e);
471-
for (uint32_t loc : locs)
471+
for (const uint32_t loc : locs)
472472
if (table[loc] == e) {
473473
if (erase)
474474
allow_erase(loc);

src/dash-cli.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ static void SetupCliArgs()
4646
gArgs.AddArg("-named", strprintf("Pass named instead of positional arguments (default: %s)", DEFAULT_NAMED), false, OptionsCategory::OPTIONS);
4747
gArgs.AddArg("-rpcclienttimeout=<n>", strprintf("Timeout in seconds during HTTP requests, or 0 for no timeout. (default: %d)", DEFAULT_HTTP_CLIENT_TIMEOUT), false, OptionsCategory::OPTIONS);
4848
gArgs.AddArg("-rpcconnect=<ip>", strprintf("Send commands to node running on <ip> (default: %s)", DEFAULT_RPCCONNECT), false, OptionsCategory::OPTIONS);
49-
gArgs.AddArg("-rpccookiefile=<loc>", _("Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)"), false, OptionsCategory::OPTIONS);
49+
gArgs.AddArg("-rpccookiefile=<loc>", "Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)", false, OptionsCategory::OPTIONS);
5050
gArgs.AddArg("-rpcpassword=<pw>", "Password for JSON-RPC connections", false, OptionsCategory::OPTIONS);
5151
gArgs.AddArg("-rpcport=<port>", strprintf("Connect to JSON-RPC on <port> (default: %u or testnet: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort()), false, OptionsCategory::OPTIONS);
5252
gArgs.AddArg("-rpcuser=<user>", "Username for JSON-RPC connections", false, OptionsCategory::OPTIONS);

src/httprpc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ void StopHTTPRPC();
2323
/** Start HTTP REST subsystem.
2424
* Precondition; HTTP and RPC has been started.
2525
*/
26-
bool StartREST();
26+
void StartREST();
2727
/** Interrupt RPC REST subsystem.
2828
*/
2929
void InterruptREST();

src/init.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,7 @@ void SetupServerArgs()
530530

531531
gArgs.AddArg("-addressindex", strprintf("Maintain a full address index, used to query for the balance, txids and unspent outputs for addresses (default: %u)", DEFAULT_ADDRESSINDEX), false, OptionsCategory::INDEXING);
532532
gArgs.AddArg("-reindex", "Rebuild chain state and block index from the blk*.dat files on disk", false, OptionsCategory::INDEXING);
533-
gArgs.AddArg("-reindex-chainstate", "Rebuild chain state from the currently indexed blocks", false, OptionsCategory::INDEXING);
533+
gArgs.AddArg("-reindex-chainstate", "Rebuild chain state from the currently indexed blocks. When in pruning mode or if blocks on disk might be corrupted, use full -reindex instead.", false, OptionsCategory::INDEXING);
534534
gArgs.AddArg("-spentindex", strprintf("Maintain a full spent index, used to query the spending txid and input index for an outpoint (default: %u)", DEFAULT_SPENTINDEX), false, OptionsCategory::INDEXING);
535535
gArgs.AddArg("-timestampindex", strprintf("Maintain a timestamp index for block hashes, used to query blocks hashes by a range of timestamps (default: %u)", DEFAULT_TIMESTAMPINDEX), false, OptionsCategory::INDEXING);
536536
gArgs.AddArg("-txindex", strprintf("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)", DEFAULT_TXINDEX), false, OptionsCategory::INDEXING);
@@ -1038,8 +1038,7 @@ static bool AppInitServers()
10381038
StartRPC();
10391039
if (!StartHTTPRPC())
10401040
return false;
1041-
if (gArgs.GetBoolArg("-rest", DEFAULT_REST_ENABLE) && !StartREST())
1042-
return false;
1041+
if (gArgs.GetBoolArg("-rest", DEFAULT_REST_ENABLE)) StartREST();
10431042
StartHTTPServer();
10441043
return true;
10451044
}

src/net.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ CNode* CConnman::FindNode(const CService& addr, bool fExcludeDisconnecting)
381381
bool CConnman::CheckIncomingNonce(uint64_t nonce)
382382
{
383383
LOCK(cs_vNodes);
384-
for (CNode* pnode : vNodes) {
384+
for (const CNode* pnode : vNodes) {
385385
if (!pnode->fSuccessfullyConnected && !pnode->fInbound && pnode->GetLocalNonce() == nonce)
386386
return false;
387387
}
@@ -2019,7 +2019,7 @@ void CConnman::ThreadDNSAddressSeed()
20192019

20202020
LOCK(cs_vNodes);
20212021
int nRelevant = 0;
2022-
for (auto pnode : vNodes) {
2022+
for (const CNode* pnode : vNodes) {
20232023
nRelevant += pnode->fSuccessfullyConnected && !pnode->fFeeler && !pnode->fOneShot && !pnode->m_manual_connection && !pnode->fInbound && !pnode->m_masternode_probe_connection;
20242024
}
20252025
if (nRelevant >= 2) {
@@ -2126,7 +2126,7 @@ int CConnman::GetExtraOutboundCount()
21262126
int nOutbound = 0;
21272127
{
21282128
LOCK(cs_vNodes);
2129-
for (CNode* pnode : vNodes) {
2129+
for (const CNode* pnode : vNodes) {
21302130
// don't count outbound masternodes
21312131
if (pnode->m_masternode_connection) {
21322132
continue;
@@ -2201,7 +2201,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
22012201
std::set<std::vector<unsigned char> > setConnected;
22022202
if (!Params().AllowMultipleAddressesFromGroup()) {
22032203
LOCK(cs_vNodes);
2204-
for (CNode* pnode : vNodes) {
2204+
for (const CNode* pnode : vNodes) {
22052205
if (!pnode->fInbound && !pnode->m_masternode_connection && !pnode->m_manual_connection) {
22062206
// Netgroups for inbound and addnode peers are not excluded because our goal here
22072207
// is to not use multiple of our limited outbound slots on a single netgroup

src/net_processing.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1163,7 +1163,7 @@ void PeerLogicValidation::BlockConnected(const std::shared_ptr<const CBlock>& pb
11631163
// Erase orphan transactions included or precluded by this block
11641164
if (vOrphanErase.size()) {
11651165
int nErased = 0;
1166-
for (uint256 &orphanHash : vOrphanErase) {
1166+
for (const uint256& orphanHash : vOrphanErase) {
11671167
nErased += EraseOrphanTx(orphanHash);
11681168
}
11691169
LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx included or conflicted by block\n", nErased);

0 commit comments

Comments
 (0)