Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13115656
wallet.h
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
50 KB
Subscribers
None
wallet.h
View Options
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Copyright (c) 2018 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_WALLET_WALLET_H
#define BITCOIN_WALLET_WALLET_H
#include
<amount.h>
#include
<outputtype.h>
#include
<script/ismine.h>
#include
<script/sign.h>
#include
<streams.h>
#include
<tinyformat.h>
#include
<ui_interface.h>
#include
<util/strencodings.h>
#include
<util/system.h>
#include
<validationinterface.h>
#include
<wallet/coinselection.h>
#include
<wallet/crypter.h>
#include
<wallet/rpcwallet.h>
#include
<wallet/walletdb.h>
#include
<algorithm>
#include
<atomic>
#include
<cstdint>
#include
<map>
#include
<set>
#include
<stdexcept>
#include
<string>
#include
<utility>
#include
<vector>
bool
AddWallet
(
const
std
::
shared_ptr
<
CWallet
>
&
wallet
);
bool
RemoveWallet
(
const
std
::
shared_ptr
<
CWallet
>
&
wallet
);
bool
HasWallets
();
std
::
vector
<
std
::
shared_ptr
<
CWallet
>>
GetWallets
();
std
::
shared_ptr
<
CWallet
>
GetWallet
(
const
std
::
string
&
name
);
//! Default for -keypool
static
const
unsigned
int
DEFAULT_KEYPOOL_SIZE
=
1000
;
//! -paytxfee default
constexpr
Amount
DEFAULT_PAY_TX_FEE
=
Amount
::
zero
();
//! -fallbackfee default
static
const
Amount
DEFAULT_FALLBACK_FEE
(
20000
*
SATOSHI
);
//! -mintxfee default
static
const
Amount
DEFAULT_TRANSACTION_MINFEE_PER_KB
=
1000
*
SATOSHI
;
//! minimum recommended increment for BIP 125 replacement txs
static
const
Amount
WALLET_INCREMENTAL_RELAY_FEE
(
5000
*
SATOSHI
);
//! Default for -spendzeroconfchange
static
const
bool
DEFAULT_SPEND_ZEROCONF_CHANGE
=
true
;
//! Default for -walletrejectlongchains
static
const
bool
DEFAULT_WALLET_REJECT_LONG_CHAINS
=
false
;
//! Default for -avoidpartialspends
static
const
bool
DEFAULT_AVOIDPARTIALSPENDS
=
false
;
static
const
bool
DEFAULT_WALLETBROADCAST
=
true
;
static
const
bool
DEFAULT_DISABLE_WALLET
=
false
;
class
CBlockIndex
;
class
CChainParams
;
class
CCoinControl
;
class
COutput
;
class
CReserveKey
;
class
CScript
;
class
CTxMemPool
;
class
CWalletTx
;
/** (client) version numbers for particular wallet features */
enum
WalletFeature
{
// the earliest version new wallets supports (only useful for
// getwalletinfo's clientversion output)
FEATURE_BASE
=
10500
,
// wallet encryption
FEATURE_WALLETCRYPT
=
40000
,
// compressed public keys
FEATURE_COMPRPUBKEY
=
60000
,
// Hierarchical key derivation after BIP32 (HD Wallet)
FEATURE_HD
=
130000
,
// Wallet with HD chain split (change outputs will use m/0'/1'/k)
FEATURE_HD_SPLIT
=
160300
,
// Wallet without a default key written
FEATURE_NO_DEFAULT_KEY
=
190700
,
// Upgraded to HD SPLIT and can have a pre-split keypool
FEATURE_PRE_SPLIT_KEYPOOL
=
200300
,
FEATURE_LATEST
=
FEATURE_PRE_SPLIT_KEYPOOL
,
};
//! Default for -addresstype
constexpr
OutputType
DEFAULT_ADDRESS_TYPE
{
OutputType
::
LEGACY
};
//! Default for -changetype
constexpr
OutputType
DEFAULT_CHANGE_TYPE
{
OutputType
::
CHANGE_AUTO
};
/** A key pool entry */
class
CKeyPool
{
public
:
int64_t
nTime
;
CPubKey
vchPubKey
;
// for change outputs
bool
fInternal
;
// For keys generated before keypool split upgrade
bool
m_pre_split
;
CKeyPool
();
CKeyPool
(
const
CPubKey
&
vchPubKeyIn
,
bool
internalIn
);
ADD_SERIALIZE_METHODS
;
template
<
typename
Stream
,
typename
Operation
>
inline
void
SerializationOp
(
Stream
&
s
,
Operation
ser_action
)
{
int
nVersion
=
s
.
GetVersion
();
if
(
!
(
s
.
GetType
()
&
SER_GETHASH
))
{
READWRITE
(
nVersion
);
}
READWRITE
(
nTime
);
READWRITE
(
vchPubKey
);
if
(
ser_action
.
ForRead
())
{
try
{
READWRITE
(
fInternal
);
}
catch
(
std
::
ios_base
::
failure
&
)
{
/**
* flag as external address if we can't read the internal
* boolean (this will be the case for any wallet before the HD
* chain split version)
*/
fInternal
=
false
;
}
try
{
READWRITE
(
m_pre_split
);
}
catch
(
std
::
ios_base
::
failure
&
)
{
/**
* flag as postsplit address if we can't read the m_pre_split
* boolean (this will be the case for any wallet that upgrades
* to HD chain split)
*/
m_pre_split
=
false
;
}
}
else
{
READWRITE
(
fInternal
);
READWRITE
(
m_pre_split
);
}
}
};
/** Address book data */
class
CAddressBookData
{
public
:
std
::
string
name
;
std
::
string
purpose
;
CAddressBookData
()
:
purpose
(
"unknown"
)
{}
typedef
std
::
map
<
std
::
string
,
std
::
string
>
StringMap
;
StringMap
destdata
;
};
struct
CRecipient
{
CScript
scriptPubKey
;
Amount
nAmount
;
bool
fSubtractFeeFromAmount
;
};
typedef
std
::
map
<
std
::
string
,
std
::
string
>
mapValue_t
;
static
inline
void
ReadOrderPos
(
int64_t
&
nOrderPos
,
mapValue_t
&
mapValue
)
{
if
(
!
mapValue
.
count
(
"n"
))
{
// TODO: calculate elsewhere
nOrderPos
=
-1
;
return
;
}
nOrderPos
=
atoi64
(
mapValue
[
"n"
].
c_str
());
}
static
inline
void
WriteOrderPos
(
const
int64_t
&
nOrderPos
,
mapValue_t
&
mapValue
)
{
if
(
nOrderPos
==
-1
)
{
return
;
}
mapValue
[
"n"
]
=
i64tostr
(
nOrderPos
);
}
struct
COutputEntry
{
CTxDestination
destination
;
Amount
amount
;
int
vout
;
};
/** A transaction with a merkle branch linking it to the block chain. */
class
CMerkleTx
{
private
:
/** Constant used in hashBlock to indicate tx has been abandoned */
static
const
uint256
ABANDON_HASH
;
public
:
CTransactionRef
tx
;
uint256
hashBlock
;
/**
* An nIndex == -1 means that hashBlock (in nonzero) refers to the earliest
* block in the chain we know this or any in-wallet dependency conflicts
* with. Older clients interpret nIndex == -1 as unconfirmed for backward
* compatibility.
*/
int
nIndex
;
CMerkleTx
()
{
SetTx
(
MakeTransactionRef
());
Init
();
}
explicit
CMerkleTx
(
CTransactionRef
arg
)
{
SetTx
(
std
::
move
(
arg
));
Init
();
}
void
Init
()
{
hashBlock
=
uint256
();
nIndex
=
-1
;
}
void
SetTx
(
CTransactionRef
arg
)
{
tx
=
std
::
move
(
arg
);
}
ADD_SERIALIZE_METHODS
;
template
<
typename
Stream
,
typename
Operation
>
inline
void
SerializationOp
(
Stream
&
s
,
Operation
ser_action
)
{
// For compatibility with older versions.
std
::
vector
<
uint256
>
vMerkleBranch
;
READWRITE
(
tx
);
READWRITE
(
hashBlock
);
READWRITE
(
vMerkleBranch
);
READWRITE
(
nIndex
);
}
void
SetMerkleBranch
(
const
CBlockIndex
*
pIndex
,
int
posInBlock
);
/**
* Return depth of transaction in blockchain:
* <0 : conflicts with a transaction this deep in the blockchain
* 0 : in memory pool, waiting to be included in a block
* >=1 : this many blocks deep in the main chain
*/
int
GetDepthInMainChain
()
const
EXCLUSIVE_LOCKS_REQUIRED
(
cs_main
);
bool
IsInMainChain
()
const
EXCLUSIVE_LOCKS_REQUIRED
(
cs_main
)
{
return
GetDepthInMainChain
()
>
0
;
}
/**
* @return number of blocks to maturity for this transaction:
* 0 : is not a coinbase transaction, or is a mature coinbase transaction
* >0 : is a coinbase transaction which matures in this many blocks
*/
int
GetBlocksToMaturity
()
const
EXCLUSIVE_LOCKS_REQUIRED
(
cs_main
);
bool
hashUnset
()
const
{
return
(
hashBlock
.
IsNull
()
||
hashBlock
==
ABANDON_HASH
);
}
bool
isAbandoned
()
const
{
return
(
hashBlock
==
ABANDON_HASH
);
}
void
setAbandoned
()
{
hashBlock
=
ABANDON_HASH
;
}
TxId
GetId
()
const
{
return
tx
->
GetId
();
}
bool
IsCoinBase
()
const
{
return
tx
->
IsCoinBase
();
}
bool
IsImmatureCoinBase
()
const
EXCLUSIVE_LOCKS_REQUIRED
(
cs_main
);
};
// Get the marginal bytes of spending the specified output
int
CalculateMaximumSignedInputSize
(
const
CTxOut
&
txout
,
const
CWallet
*
pwallet
);
/**
* A transaction with a bunch of additional info that only the owner cares
* about. It includes any unrecorded transactions needed to link it back to the
* block chain.
*/
class
CWalletTx
:
public
CMerkleTx
{
private
:
const
CWallet
*
pwallet
;
public
:
/**
* Key/value map with information about the transaction.
*
* The following keys can be read and written through the map and are
* serialized in the wallet database:
*
* "comment", "to" - comment strings provided to sendtoaddress,
* sendfrom, sendmany wallet RPCs
* "replaces_txid" - txid (as HexStr) of transaction replaced by
* bumpfee on transaction created by bumpfee
* "replaced_by_txid" - txid (as HexStr) of transaction created by
* bumpfee on transaction replaced by bumpfee
* "from", "message" - obsolete fields that could be set in UI prior to
* 2011 (removed in commit 4d9b223)
*
* The following keys are serialized in the wallet database, but shouldn't
* be read or written through the map (they will be temporarily added and
* removed from the map during serialization):
*
* "fromaccount" - serialized strFromAccount value
* "n" - serialized nOrderPos value
* "timesmart" - serialized nTimeSmart value
* "spent" - serialized vfSpent value that existed prior to
* 2014 (removed in commit 93a18a3)
*/
mapValue_t
mapValue
;
std
::
vector
<
std
::
pair
<
std
::
string
,
std
::
string
>>
vOrderForm
;
unsigned
int
fTimeReceivedIsTxTime
;
//!< time received by this node
unsigned
int
nTimeReceived
;
/**
* Stable timestamp that never changes, and reflects the order a transaction
* was added to the wallet. Timestamp is based on the block time for a
* transaction added as part of a block, or else the time when the
* transaction was received if it wasn't part of a block, with the timestamp
* adjusted in both cases so timestamp order matches the order transactions
* were added to the wallet. More details can be found in
* CWallet::ComputeTimeSmart().
*/
unsigned
int
nTimeSmart
;
/**
* From me flag is set to 1 for transactions that were created by the wallet
* on this bitcoin node, and set to 0 for transactions that were created
* externally and came in through the network or sendrawtransaction RPC.
*/
char
fFromMe
;
std
::
string
strFromAccount
;
//!< position in ordered transaction list
int64_t
nOrderPos
;
// memory only
mutable
bool
fDebitCached
;
mutable
bool
fCreditCached
;
mutable
bool
fImmatureCreditCached
;
mutable
bool
fAvailableCreditCached
;
mutable
bool
fWatchDebitCached
;
mutable
bool
fWatchCreditCached
;
mutable
bool
fImmatureWatchCreditCached
;
mutable
bool
fAvailableWatchCreditCached
;
mutable
bool
fChangeCached
;
mutable
bool
fInMempool
;
mutable
Amount
nDebitCached
;
mutable
Amount
nCreditCached
;
mutable
Amount
nImmatureCreditCached
;
mutable
Amount
nAvailableCreditCached
;
mutable
Amount
nWatchDebitCached
;
mutable
Amount
nWatchCreditCached
;
mutable
Amount
nImmatureWatchCreditCached
;
mutable
Amount
nAvailableWatchCreditCached
;
mutable
Amount
nChangeCached
;
CWalletTx
(
const
CWallet
*
pwalletIn
,
CTransactionRef
arg
)
:
CMerkleTx
(
std
::
move
(
arg
))
{
Init
(
pwalletIn
);
}
void
Init
(
const
CWallet
*
pwalletIn
)
{
pwallet
=
pwalletIn
;
mapValue
.
clear
();
vOrderForm
.
clear
();
fTimeReceivedIsTxTime
=
false
;
nTimeReceived
=
0
;
nTimeSmart
=
0
;
fFromMe
=
false
;
strFromAccount
.
clear
();
fDebitCached
=
false
;
fCreditCached
=
false
;
fImmatureCreditCached
=
false
;
fAvailableCreditCached
=
false
;
fWatchDebitCached
=
false
;
fWatchCreditCached
=
false
;
fImmatureWatchCreditCached
=
false
;
fAvailableWatchCreditCached
=
false
;
fChangeCached
=
false
;
fInMempool
=
false
;
nDebitCached
=
Amount
::
zero
();
nCreditCached
=
Amount
::
zero
();
nImmatureCreditCached
=
Amount
::
zero
();
nAvailableCreditCached
=
Amount
::
zero
();
nWatchDebitCached
=
Amount
::
zero
();
nWatchCreditCached
=
Amount
::
zero
();
nAvailableWatchCreditCached
=
Amount
::
zero
();
nImmatureWatchCreditCached
=
Amount
::
zero
();
nChangeCached
=
Amount
::
zero
();
nOrderPos
=
-1
;
}
template
<
typename
Stream
>
void
Serialize
(
Stream
&
s
)
const
{
char
fSpent
=
false
;
mapValue_t
mapValueCopy
=
mapValue
;
mapValueCopy
[
"fromaccount"
]
=
strFromAccount
;
WriteOrderPos
(
nOrderPos
,
mapValueCopy
);
if
(
nTimeSmart
)
{
mapValueCopy
[
"timesmart"
]
=
strprintf
(
"%u"
,
nTimeSmart
);
}
s
<<
static_cast
<
const
CMerkleTx
&>
(
*
this
);
//!< Used to be vtxPrev
std
::
vector
<
CMerkleTx
>
vUnused
;
s
<<
vUnused
<<
mapValueCopy
<<
vOrderForm
<<
fTimeReceivedIsTxTime
<<
nTimeReceived
<<
fFromMe
<<
fSpent
;
}
template
<
typename
Stream
>
void
Unserialize
(
Stream
&
s
)
{
Init
(
nullptr
);
char
fSpent
;
s
>>
static_cast
<
CMerkleTx
&>
(
*
this
);
//!< Used to be vtxPrev
std
::
vector
<
CMerkleTx
>
vUnused
;
s
>>
vUnused
>>
mapValue
>>
vOrderForm
>>
fTimeReceivedIsTxTime
>>
nTimeReceived
>>
fFromMe
>>
fSpent
;
strFromAccount
=
std
::
move
(
mapValue
[
"fromaccount"
]);
ReadOrderPos
(
nOrderPos
,
mapValue
);
nTimeSmart
=
mapValue
.
count
(
"timesmart"
)
?
(
unsigned
int
)
atoi64
(
mapValue
[
"timesmart"
])
:
0
;
mapValue
.
erase
(
"fromaccount"
);
mapValue
.
erase
(
"spent"
);
mapValue
.
erase
(
"n"
);
mapValue
.
erase
(
"timesmart"
);
}
//! make sure balances are recalculated
void
MarkDirty
()
{
fCreditCached
=
false
;
fAvailableCreditCached
=
false
;
fImmatureCreditCached
=
false
;
fWatchDebitCached
=
false
;
fWatchCreditCached
=
false
;
fAvailableWatchCreditCached
=
false
;
fImmatureWatchCreditCached
=
false
;
fDebitCached
=
false
;
fChangeCached
=
false
;
}
void
BindWallet
(
CWallet
*
pwalletIn
)
{
pwallet
=
pwalletIn
;
MarkDirty
();
}
//! filter decides which addresses will count towards the debit
Amount
GetDebit
(
const
isminefilter
&
filter
)
const
;
Amount
GetCredit
(
const
isminefilter
&
filter
)
const
EXCLUSIVE_LOCKS_REQUIRED
(
cs_main
);
Amount
GetImmatureCredit
(
bool
fUseCache
=
true
)
const
EXCLUSIVE_LOCKS_REQUIRED
(
cs_main
);
Amount
GetAvailableCredit
(
bool
fUseCache
=
true
)
const
EXCLUSIVE_LOCKS_REQUIRED
(
cs_main
);
Amount
GetImmatureWatchOnlyCredit
(
const
bool
fUseCache
=
true
)
const
EXCLUSIVE_LOCKS_REQUIRED
(
cs_main
);
Amount
GetAvailableWatchOnlyCredit
(
const
bool
fUseCache
=
true
)
const
EXCLUSIVE_LOCKS_REQUIRED
(
cs_main
);
Amount
GetChange
()
const
;
// Get the marginal bytes if spending the specified output from this
// transaction
int
GetSpendSize
(
unsigned
int
out
)
const
{
return
CalculateMaximumSignedInputSize
(
tx
->
vout
[
out
],
pwallet
);
}
void
GetAmounts
(
std
::
list
<
COutputEntry
>
&
listReceived
,
std
::
list
<
COutputEntry
>
&
listSent
,
Amount
&
nFee
,
std
::
string
&
strSentAccount
,
const
isminefilter
&
filter
)
const
;
bool
IsFromMe
(
const
isminefilter
&
filter
)
const
{
return
GetDebit
(
filter
)
>
Amount
::
zero
();
}
// True if only scriptSigs are different
bool
IsEquivalentTo
(
const
CWalletTx
&
tx
)
const
;
bool
InMempool
()
const
;
bool
IsTrusted
()
const
EXCLUSIVE_LOCKS_REQUIRED
(
cs_main
);
int64_t
GetTxTime
()
const
;
// RelayWalletTransaction may only be called if fBroadcastTransactions!
bool
RelayWalletTransaction
(
CConnman
*
connman
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_main
);
/**
* Pass this transaction to the mempool. Fails if absolute fee exceeds
* absurd fee.
*/
bool
AcceptToMemoryPool
(
const
Amount
nAbsurdFee
,
CValidationState
&
state
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_main
);
std
::
set
<
TxId
>
GetConflicts
()
const
;
};
class
COutput
{
public
:
const
CWalletTx
*
tx
;
int
i
;
int
nDepth
;
/**
* Pre-computed estimated size of this output as a fully-signed input in a
* transaction. Can be -1 if it could not be calculated.
*/
int
nInputBytes
;
/** Whether we have the private keys to spend this output */
bool
fSpendable
;
/** Whether we know how to spend this output, ignoring the lack of keys */
bool
fSolvable
;
/**
* Whether this output is considered safe to spend. Unconfirmed transactions
* from outside keys are considered unsafe and will not be used to fund new
* spending transactions.
*/
bool
fSafe
;
COutput
(
const
CWalletTx
*
txIn
,
int
iIn
,
int
nDepthIn
,
bool
fSpendableIn
,
bool
fSolvableIn
,
bool
fSafeIn
)
{
tx
=
txIn
;
i
=
iIn
;
nDepth
=
nDepthIn
;
fSpendable
=
fSpendableIn
;
fSolvable
=
fSolvableIn
;
fSafe
=
fSafeIn
;
nInputBytes
=
-1
;
// If known and signable by the given wallet, compute nInputBytes
// Failure will keep this value -1
if
(
fSpendable
&&
tx
)
{
nInputBytes
=
tx
->
GetSpendSize
(
i
);
}
}
std
::
string
ToString
()
const
;
inline
CInputCoin
GetInputCoin
()
const
{
return
CInputCoin
(
tx
->
tx
,
i
,
nInputBytes
);
}
};
/** Private key that includes an expiration date in case it never gets used. */
class
CWalletKey
{
public
:
CPrivKey
vchPrivKey
;
int64_t
nTimeCreated
;
int64_t
nTimeExpires
;
std
::
string
strComment
;
//! todo: add something to note what created it (user, getnewaddress,
//! change) maybe should have a map<string, string> property map
explicit
CWalletKey
(
int64_t
nExpires
=
0
);
ADD_SERIALIZE_METHODS
;
template
<
typename
Stream
,
typename
Operation
>
inline
void
SerializationOp
(
Stream
&
s
,
Operation
ser_action
)
{
int
nVersion
=
s
.
GetVersion
();
if
(
!
(
s
.
GetType
()
&
SER_GETHASH
))
READWRITE
(
nVersion
);
READWRITE
(
vchPrivKey
);
READWRITE
(
nTimeCreated
);
READWRITE
(
nTimeExpires
);
READWRITE
(
LIMITED_STRING
(
strComment
,
65536
));
}
};
/**
* DEPRECATED Internal transfers.
* Database key is acentry<account><counter>.
*/
class
CAccountingEntry
{
public
:
std
::
string
strAccount
;
Amount
nCreditDebit
;
int64_t
nTime
;
std
::
string
strOtherAccount
;
std
::
string
strComment
;
mapValue_t
mapValue
;
//!< position in ordered transaction list
int64_t
nOrderPos
;
uint64_t
nEntryNo
;
CAccountingEntry
()
{
SetNull
();
}
void
SetNull
()
{
nCreditDebit
=
Amount
::
zero
();
nTime
=
0
;
strAccount
.
clear
();
strOtherAccount
.
clear
();
strComment
.
clear
();
nOrderPos
=
-1
;
nEntryNo
=
0
;
}
template
<
typename
Stream
>
void
Serialize
(
Stream
&
s
)
const
{
int
nVersion
=
s
.
GetVersion
();
if
(
!
(
s
.
GetType
()
&
SER_GETHASH
))
{
s
<<
nVersion
;
}
//! Note: strAccount is serialized as part of the key, not here.
s
<<
nCreditDebit
<<
nTime
<<
strOtherAccount
;
mapValue_t
mapValueCopy
=
mapValue
;
WriteOrderPos
(
nOrderPos
,
mapValueCopy
);
std
::
string
strCommentCopy
=
strComment
;
if
(
!
mapValueCopy
.
empty
()
||
!
_ssExtra
.
empty
())
{
CDataStream
ss
(
s
.
GetType
(),
s
.
GetVersion
());
ss
.
insert
(
ss
.
begin
(),
'\0'
);
ss
<<
mapValueCopy
;
ss
.
insert
(
ss
.
end
(),
_ssExtra
.
begin
(),
_ssExtra
.
end
());
strCommentCopy
.
append
(
ss
.
str
());
}
s
<<
strCommentCopy
;
}
template
<
typename
Stream
>
void
Unserialize
(
Stream
&
s
)
{
int
nVersion
=
s
.
GetVersion
();
if
(
!
(
s
.
GetType
()
&
SER_GETHASH
))
{
s
>>
nVersion
;
}
//! Note: strAccount is serialized as part of the key, not here.
s
>>
nCreditDebit
>>
nTime
>>
LIMITED_STRING
(
strOtherAccount
,
65536
)
>>
LIMITED_STRING
(
strComment
,
65536
);
size_t
nSepPos
=
strComment
.
find
(
'\0'
);
mapValue
.
clear
();
if
(
std
::
string
::
npos
!=
nSepPos
)
{
CDataStream
ss
(
std
::
vector
<
char
>
(
strComment
.
begin
()
+
nSepPos
+
1
,
strComment
.
end
()),
s
.
GetType
(),
s
.
GetVersion
());
ss
>>
mapValue
;
_ssExtra
=
std
::
vector
<
char
>
(
ss
.
begin
(),
ss
.
end
());
}
ReadOrderPos
(
nOrderPos
,
mapValue
);
if
(
std
::
string
::
npos
!=
nSepPos
)
{
strComment
.
erase
(
nSepPos
);
}
mapValue
.
erase
(
"n"
);
}
private
:
std
::
vector
<
char
>
_ssExtra
;
};
struct
CoinSelectionParams
{
bool
use_bnb
=
true
;
size_t
change_output_size
=
0
;
size_t
change_spend_size
=
0
;
CFeeRate
effective_fee
=
CFeeRate
(
Amount
::
zero
());
size_t
tx_noinputs_size
=
0
;
CoinSelectionParams
(
bool
use_bnb_
,
size_t
change_output_size_
,
size_t
change_spend_size_
,
CFeeRate
effective_fee_
,
size_t
tx_noinputs_size_
)
:
use_bnb
(
use_bnb_
),
change_output_size
(
change_output_size_
),
change_spend_size
(
change_spend_size_
),
effective_fee
(
effective_fee_
),
tx_noinputs_size
(
tx_noinputs_size_
)
{}
CoinSelectionParams
()
{}
};
// forward declarations for ScanForWalletTransactions/RescanFromTime
class
WalletRescanReserver
;
/**
* A CWallet is an extension of a keystore, which also maintains a set of
* transactions and balances, and provides the ability to create new
* transactions.
*/
class
CWallet
final
:
public
CCryptoKeyStore
,
public
CValidationInterface
{
private
:
static
std
::
atomic
<
bool
>
fFlushScheduled
;
std
::
atomic
<
bool
>
fAbortRescan
{
false
};
// controlled by WalletRescanReserver
std
::
atomic
<
bool
>
fScanningWallet
{
false
};
std
::
mutex
mutexScanning
;
friend
class
WalletRescanReserver
;
WalletBatch
*
encrypted_batch
=
nullptr
;
//! the current wallet version: clients below this version are not able to
//! load the wallet
int
nWalletVersion
=
FEATURE_BASE
;
//! the maximum wallet format version: memory-only variable that specifies
//! to what version this wallet may be upgraded
int
nWalletMaxVersion
=
FEATURE_BASE
;
int64_t
nNextResend
=
0
;
int64_t
nLastResend
=
0
;
bool
fBroadcastTransactions
=
false
;
/**
* Used to keep track of spent outpoints, and detect and report conflicts
* (double-spends or mutated transactions where the mutant gets mined).
*/
typedef
std
::
multimap
<
COutPoint
,
TxId
>
TxSpends
;
TxSpends
mapTxSpends
;
void
AddToSpends
(
const
COutPoint
&
outpoint
,
const
TxId
&
wtxid
);
void
AddToSpends
(
const
TxId
&
wtxid
);
/**
* Mark a transaction (and its in-wallet descendants) as conflicting with a
* particular block.
*/
void
MarkConflicted
(
const
uint256
&
hashBlock
,
const
TxId
&
txid
);
void
SyncMetaData
(
std
::
pair
<
TxSpends
::
iterator
,
TxSpends
::
iterator
>
);
/**
* Used by TransactionAddedToMemorypool/BlockConnected/Disconnected.
* Should be called with pindexBlock and posInBlock if this is for a
* transaction that is included in a block.
*/
void
SyncTransaction
(
const
CTransactionRef
&
tx
,
const
CBlockIndex
*
pindex
=
nullptr
,
int
posInBlock
=
0
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
/* the HD chain data model (external chain counters) */
CHDChain
hdChain
;
/* HD derive new child key (on internal or external chain) */
void
DeriveNewChildKey
(
WalletBatch
&
batch
,
CKeyMetadata
&
metadata
,
CKey
&
secret
,
bool
internal
=
false
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
std
::
set
<
int64_t
>
setInternalKeyPool
;
std
::
set
<
int64_t
>
setExternalKeyPool
;
std
::
set
<
int64_t
>
set_pre_split_keypool
;
int64_t
m_max_keypool_index
=
0
;
std
::
map
<
CKeyID
,
int64_t
>
m_pool_key_to_index
;
int64_t
nTimeFirstKey
=
0
;
/**
* Private version of AddWatchOnly method which does not accept a timestamp,
* and which will reset the wallet's nTimeFirstKey value to 1 if the watch
* key did not previously have a timestamp associated with it. Because this
* is an inherited virtual method, it is accessible despite being marked
* private, but it is marked private anyway to encourage use of the other
* AddWatchOnly which accepts a timestamp and sets nTimeFirstKey more
* intelligently for more efficient rescans.
*/
bool
AddWatchOnly
(
const
CScript
&
dest
)
override
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
/**
* Wallet filename from wallet=<path> command line or config option.
* Used in debug logs and to send RPCs to the right wallet instance when
* more than one wallet is loaded.
*/
std
::
string
m_name
;
/** Internal database handle. */
std
::
unique_ptr
<
WalletDatabase
>
database
;
/**
* The following is used to keep track of how far behind the wallet is
* from the chain sync, and to allow clients to block on us being caught up.
*
* Note that this is *not* how far we've processed, we may need some rescan
* to have seen all transactions in the chain, but is only used to track
* live BlockConnected callbacks.
*
* Protected by cs_main (see BlockUntilSyncedToCurrentChain)
*/
const
CBlockIndex
*
m_last_block_processed
=
nullptr
;
public
:
const
CChainParams
&
chainParams
;
/*
* Main wallet lock.
* This lock protects all the fields added by CWallet.
*/
mutable
CCriticalSection
cs_wallet
;
/**
* Get database handle used by this wallet. Ideally this function would not
* be necessary.
*/
WalletDatabase
&
GetDBHandle
()
{
return
*
database
;
}
/**
* Select a set of coins such that nValueRet >= nTargetValue and at least
* all coins from coinControl are selected; Never select unconfirmed coins
* if they are not ours.
*/
bool
SelectCoins
(
const
std
::
vector
<
COutput
>
&
vAvailableCoins
,
const
Amount
nTargetValue
,
std
::
set
<
CInputCoin
>
&
setCoinsRet
,
Amount
&
nValueRet
,
const
CCoinControl
&
coin_control
,
CoinSelectionParams
&
coin_selection_params
,
bool
&
bnb_used
)
const
;
/**
* Get a name for this wallet for logging/debugging purposes.
*/
std
::
string
GetName
()
const
{
return
m_name
;
}
void
LoadKeyPool
(
int64_t
nIndex
,
const
CKeyPool
&
keypool
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
void
MarkPreSplitKeys
();
// Map from Key ID to key metadata.
std
::
map
<
CKeyID
,
CKeyMetadata
>
mapKeyMetadata
;
// Map from Script ID to key metadata (for watch-only keys).
std
::
map
<
CScriptID
,
CKeyMetadata
>
m_script_metadata
;
typedef
std
::
map
<
unsigned
int
,
CMasterKey
>
MasterKeyMap
;
MasterKeyMap
mapMasterKeys
;
unsigned
int
nMasterKeyMaxID
=
0
;
/** Construct wallet with specified name and database implementation. */
CWallet
(
const
CChainParams
&
chainParamsIn
,
std
::
string
name
,
std
::
unique_ptr
<
WalletDatabase
>
databaseIn
)
:
m_name
(
std
::
move
(
name
)),
database
(
std
::
move
(
databaseIn
)),
chainParams
(
chainParamsIn
)
{}
~
CWallet
()
{
delete
encrypted_batch
;
encrypted_batch
=
nullptr
;
}
std
::
map
<
TxId
,
CWalletTx
>
mapWallet
;
std
::
list
<
CAccountingEntry
>
laccentries
;
typedef
std
::
pair
<
CWalletTx
*
,
CAccountingEntry
*>
TxPair
;
typedef
std
::
multimap
<
int64_t
,
TxPair
>
TxItems
;
TxItems
wtxOrdered
;
int64_t
nOrderPosNext
=
0
;
uint64_t
nAccountingEntryNumber
=
0
;
std
::
map
<
CTxDestination
,
CAddressBookData
>
mapAddressBook
;
std
::
set
<
COutPoint
>
setLockedCoins
;
const
CWalletTx
*
GetWalletTx
(
const
TxId
&
txid
)
const
;
//! check whether we are allowed to upgrade (or already support) to the
//! named feature
bool
CanSupportFeature
(
enum
WalletFeature
wf
)
const
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
)
{
AssertLockHeld
(
cs_wallet
);
return
nWalletMaxVersion
>=
wf
;
}
/**
* populate vCoins with vector of available COutputs.
*/
void
AvailableCoins
(
std
::
vector
<
COutput
>
&
vCoins
,
bool
fOnlySafe
=
true
,
const
CCoinControl
*
coinControl
=
nullptr
,
const
Amount
nMinimumAmount
=
SATOSHI
,
const
Amount
nMaximumAmount
=
MAX_MONEY
,
const
Amount
nMinimumSumAmount
=
MAX_MONEY
,
const
uint64_t
nMaximumCount
=
0
,
const
int
nMinDepth
=
0
,
const
int
nMaxDepth
=
9999999
)
const
EXCLUSIVE_LOCKS_REQUIRED
(
cs_main
,
cs_wallet
);
/**
* Return list of available coins and locked coins grouped by non-change
* output address.
*/
std
::
map
<
CTxDestination
,
std
::
vector
<
COutput
>>
ListCoins
()
const
EXCLUSIVE_LOCKS_REQUIRED
(
cs_main
,
cs_wallet
);
/**
* Find non-change parent output.
*/
const
CTxOut
&
FindNonChangeParentOutput
(
const
CTransaction
&
tx
,
int
output
)
const
;
/**
* Shuffle and select coins until nTargetValue is reached while avoiding
* small change; This method is stochastic for some inputs and upon
* completion the coin set and corresponding actual target value is
* assembled.
*/
bool
SelectCoinsMinConf
(
const
Amount
nTargetValue
,
const
CoinEligibilityFilter
&
eligibility_filter
,
std
::
vector
<
OutputGroup
>
groups
,
std
::
set
<
CInputCoin
>
&
setCoinsRet
,
Amount
&
nValueRet
,
const
CoinSelectionParams
&
coin_selection_params
,
bool
&
bnb_used
)
const
;
bool
IsSpent
(
const
COutPoint
&
outpoint
)
const
EXCLUSIVE_LOCKS_REQUIRED
(
cs_main
);
std
::
vector
<
OutputGroup
>
GroupOutputs
(
const
std
::
vector
<
COutput
>
&
outputs
,
bool
single_coin
)
const
;
bool
IsLockedCoin
(
const
COutPoint
&
outpoint
)
const
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
void
LockCoin
(
const
COutPoint
&
output
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
void
UnlockCoin
(
const
COutPoint
&
output
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
void
UnlockAllCoins
()
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
void
ListLockedCoins
(
std
::
vector
<
COutPoint
>
&
vOutpts
)
const
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
/*
* Rescan abort properties
*/
void
AbortRescan
()
{
fAbortRescan
=
true
;
}
bool
IsAbortingRescan
()
{
return
fAbortRescan
;
}
bool
IsScanning
()
{
return
fScanningWallet
;
}
/**
* keystore implementation
* Generate a new key
*/
CPubKey
GenerateNewKey
(
WalletBatch
&
batch
,
bool
internal
=
false
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
//! Adds a key to the store, and saves it to disk.
bool
AddKeyPubKey
(
const
CKey
&
key
,
const
CPubKey
&
pubkey
)
override
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
bool
AddKeyPubKeyWithDB
(
WalletBatch
&
batch
,
const
CKey
&
key
,
const
CPubKey
&
pubkey
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
//! Adds a key to the store, without saving it to disk (used by LoadWallet)
bool
LoadKey
(
const
CKey
&
key
,
const
CPubKey
&
pubkey
)
{
return
CCryptoKeyStore
::
AddKeyPubKey
(
key
,
pubkey
);
}
//! Load metadata (used by LoadWallet)
void
LoadKeyMetadata
(
const
CKeyID
&
keyID
,
const
CKeyMetadata
&
metadata
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
void
LoadScriptMetadata
(
const
CScriptID
&
script_id
,
const
CKeyMetadata
&
metadata
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
bool
LoadMinVersion
(
int
nVersion
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
)
{
AssertLockHeld
(
cs_wallet
);
nWalletVersion
=
nVersion
;
nWalletMaxVersion
=
std
::
max
(
nWalletMaxVersion
,
nVersion
);
return
true
;
}
void
UpdateTimeFirstKey
(
int64_t
nCreateTime
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
//! Adds an encrypted key to the store, and saves it to disk.
bool
AddCryptedKey
(
const
CPubKey
&
vchPubKey
,
const
std
::
vector
<
uint8_t
>
&
vchCryptedSecret
)
override
;
//! Adds an encrypted key to the store, without saving it to disk (used by
//! LoadWallet)
bool
LoadCryptedKey
(
const
CPubKey
&
vchPubKey
,
const
std
::
vector
<
uint8_t
>
&
vchCryptedSecret
);
bool
AddCScript
(
const
CScript
&
redeemScript
)
override
;
bool
LoadCScript
(
const
CScript
&
redeemScript
);
//! Adds a destination data tuple to the store, and saves it to disk
bool
AddDestData
(
const
CTxDestination
&
dest
,
const
std
::
string
&
key
,
const
std
::
string
&
value
);
//! Erases a destination data tuple in the store and on disk
bool
EraseDestData
(
const
CTxDestination
&
dest
,
const
std
::
string
&
key
);
//! Adds a destination data tuple to the store, without saving it to disk
void
LoadDestData
(
const
CTxDestination
&
dest
,
const
std
::
string
&
key
,
const
std
::
string
&
value
);
//! Look up a destination data tuple in the store, return true if found
//! false otherwise
bool
GetDestData
(
const
CTxDestination
&
dest
,
const
std
::
string
&
key
,
std
::
string
*
value
)
const
;
//! Get all destination values matching a prefix.
std
::
vector
<
std
::
string
>
GetDestValues
(
const
std
::
string
&
prefix
)
const
;
//! Adds a watch-only address to the store, and saves it to disk.
bool
AddWatchOnly
(
const
CScript
&
dest
,
int64_t
nCreateTime
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
bool
RemoveWatchOnly
(
const
CScript
&
dest
)
override
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
//! Adds a watch-only address to the store, without saving it to disk (used
//! by LoadWallet)
bool
LoadWatchOnly
(
const
CScript
&
dest
);
//! Holds a timestamp at which point the wallet is scheduled (externally) to
//! be relocked. Caller must arrange for actual relocking to occur via
//! Lock().
int64_t
nRelockTime
=
0
;
bool
Unlock
(
const
SecureString
&
strWalletPassphrase
);
bool
ChangeWalletPassphrase
(
const
SecureString
&
strOldWalletPassphrase
,
const
SecureString
&
strNewWalletPassphrase
);
bool
EncryptWallet
(
const
SecureString
&
strWalletPassphrase
);
void
GetKeyBirthTimes
(
std
::
map
<
CTxDestination
,
int64_t
>
&
mapKeyBirth
)
const
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
unsigned
int
ComputeTimeSmart
(
const
CWalletTx
&
wtx
)
const
;
/**
* Increment the next transaction order id
* @return next transaction order id
*/
int64_t
IncOrderPosNext
(
WalletBatch
*
batch
=
nullptr
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
DBErrors
ReorderTransactions
();
bool
AccountMove
(
std
::
string
strFrom
,
std
::
string
strTo
,
const
Amount
nAmount
,
std
::
string
strComment
=
""
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
bool
GetLabelDestination
(
CTxDestination
&
dest
,
const
std
::
string
&
label
,
bool
bForceNew
=
false
);
void
MarkDirty
();
bool
AddToWallet
(
const
CWalletTx
&
wtxIn
,
bool
fFlushOnClose
=
true
);
void
LoadToWallet
(
const
CWalletTx
&
wtxIn
);
void
TransactionAddedToMempool
(
const
CTransactionRef
&
tx
)
override
;
void
BlockConnected
(
const
std
::
shared_ptr
<
const
CBlock
>
&
pblock
,
const
CBlockIndex
*
pindex
,
const
std
::
vector
<
CTransactionRef
>
&
vtxConflicted
)
override
;
void
BlockDisconnected
(
const
std
::
shared_ptr
<
const
CBlock
>
&
pblock
)
override
;
bool
AddToWalletIfInvolvingMe
(
const
CTransactionRef
&
tx
,
const
CBlockIndex
*
pIndex
,
int
posInBlock
,
bool
fUpdate
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
int64_t
RescanFromTime
(
int64_t
startTime
,
const
WalletRescanReserver
&
reserver
,
bool
update
);
CBlockIndex
*
ScanForWalletTransactions
(
CBlockIndex
*
pindexStart
,
CBlockIndex
*
pindexStop
,
const
WalletRescanReserver
&
reserver
,
bool
fUpdate
=
false
);
void
TransactionRemovedFromMempool
(
const
CTransactionRef
&
ptx
)
override
;
void
ReacceptWalletTransactions
();
void
ResendWalletTransactions
(
int64_t
nBestBlockTime
,
CConnman
*
connman
)
override
EXCLUSIVE_LOCKS_REQUIRED
(
cs_main
);
// ResendWalletTransactionsBefore may only be called if
// fBroadcastTransactions!
std
::
vector
<
uint256
>
ResendWalletTransactionsBefore
(
int64_t
nTime
,
CConnman
*
connman
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_main
);
Amount
GetBalance
()
const
;
Amount
GetUnconfirmedBalance
()
const
;
Amount
GetImmatureBalance
()
const
;
Amount
GetWatchOnlyBalance
()
const
;
Amount
GetUnconfirmedWatchOnlyBalance
()
const
;
Amount
GetImmatureWatchOnlyBalance
()
const
;
Amount
GetLegacyBalance
(
const
isminefilter
&
filter
,
int
minDepth
,
const
std
::
string
*
account
)
const
;
Amount
GetAvailableBalance
(
const
CCoinControl
*
coinControl
=
nullptr
)
const
;
OutputType
TransactionChangeType
(
OutputType
change_type
,
const
std
::
vector
<
CRecipient
>
&
vecSend
);
/**
* Insert additional inputs into the transaction by calling
* CreateTransaction();
*/
bool
FundTransaction
(
CMutableTransaction
&
tx
,
Amount
&
nFeeRet
,
int
&
nChangePosInOut
,
std
::
string
&
strFailReason
,
bool
lockUnspents
,
const
std
::
set
<
int
>
&
setSubtractFeeFromOutputs
,
CCoinControl
coinControl
);
bool
SignTransaction
(
CMutableTransaction
&
tx
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
/**
* Create a new transaction paying the recipients with a set of coins
* selected by SelectCoins(); Also create the change output, when needed
* @note passing nChangePosInOut as -1 will result in setting a random
* position
*/
bool
CreateTransaction
(
const
std
::
vector
<
CRecipient
>
&
vecSend
,
CTransactionRef
&
tx
,
CReserveKey
&
reservekey
,
Amount
&
nFeeRet
,
int
&
nChangePosInOut
,
std
::
string
&
strFailReason
,
const
CCoinControl
&
coin_control
,
bool
sign
=
true
);
bool
CommitTransaction
(
CTransactionRef
tx
,
mapValue_t
mapValue
,
std
::
vector
<
std
::
pair
<
std
::
string
,
std
::
string
>>
orderForm
,
std
::
string
fromAccount
,
CReserveKey
&
reservekey
,
CConnman
*
connman
,
CValidationState
&
state
);
void
ListAccountCreditDebit
(
const
std
::
string
&
strAccount
,
std
::
list
<
CAccountingEntry
>
&
entries
);
bool
AddAccountingEntry
(
const
CAccountingEntry
&
);
bool
AddAccountingEntry
(
const
CAccountingEntry
&
,
WalletBatch
*
batch
);
bool
DummySignTx
(
CMutableTransaction
&
txNew
,
const
std
::
set
<
CTxOut
>
&
txouts
)
const
{
std
::
vector
<
CTxOut
>
v_txouts
(
txouts
.
size
());
std
::
copy
(
txouts
.
begin
(),
txouts
.
end
(),
v_txouts
.
begin
());
return
DummySignTx
(
txNew
,
v_txouts
);
}
bool
DummySignTx
(
CMutableTransaction
&
txNew
,
const
std
::
vector
<
CTxOut
>
&
txouts
)
const
;
bool
DummySignInput
(
CTxIn
&
tx_in
,
const
CTxOut
&
txout
)
const
;
CFeeRate
m_pay_tx_fee
{
DEFAULT_PAY_TX_FEE
};
bool
m_spend_zero_conf_change
{
DEFAULT_SPEND_ZEROCONF_CHANGE
};
// will be defined via chainparams
bool
m_allow_fallback_fee
{
true
};
// Override with -mintxfee
CFeeRate
m_min_fee
{
DEFAULT_TRANSACTION_MINFEE_PER_KB
};
/**
* If fee estimation does not have enough data to provide estimates, use
* this fee instead. Has no effect if not using fee estimation Override with
* -fallbackfee
*/
CFeeRate
m_fallback_fee
{
DEFAULT_FALLBACK_FEE
};
OutputType
m_default_address_type
{
DEFAULT_ADDRESS_TYPE
};
OutputType
m_default_change_type
{
DEFAULT_CHANGE_TYPE
};
bool
NewKeyPool
();
size_t
KeypoolCountExternalKeys
()
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
bool
TopUpKeyPool
(
unsigned
int
kpSize
=
0
);
/**
* Reserves a key from the keypool and sets nIndex to its index
*
* @param[out] nIndex the index of the key in keypool
* @param[out] keypool the keypool the key was drawn from, which could be
* the the pre-split pool if present, or the internal or external pool
* @param fRequestedInternal true if the caller would like the key drawn
* from the internal keypool, false if external is preferred
*
* @return true if succeeded, false if failed due to empty keypool
* @throws std::runtime_error if keypool read failed, key was invalid,
* was not found in the wallet, or was misclassified in the internal
* or external keypool
*/
bool
ReserveKeyFromKeyPool
(
int64_t
&
nIndex
,
CKeyPool
&
keypool
,
bool
fRequestedInternal
);
void
KeepKey
(
int64_t
nIndex
);
void
ReturnKey
(
int64_t
nIndex
,
bool
fInternal
,
const
CPubKey
&
pubkey
);
bool
GetKeyFromPool
(
CPubKey
&
key
,
bool
internal
=
false
);
int64_t
GetOldestKeyPoolTime
();
/**
* Marks all keys in the keypool up to and including reserve_key as used.
*/
void
MarkReserveKeysAsUsed
(
int64_t
keypool_id
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
const
std
::
map
<
CKeyID
,
int64_t
>
&
GetAllReserveKeys
()
const
{
return
m_pool_key_to_index
;
}
std
::
set
<
std
::
set
<
CTxDestination
>>
GetAddressGroupings
()
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
std
::
map
<
CTxDestination
,
Amount
>
GetAddressBalances
()
EXCLUSIVE_LOCKS_REQUIRED
(
cs_main
);
std
::
set
<
CTxDestination
>
GetLabelAddresses
(
const
std
::
string
&
label
)
const
;
void
DeleteLabel
(
const
std
::
string
&
label
);
isminetype
IsMine
(
const
CTxIn
&
txin
)
const
;
/**
* Returns amount of debit if the input matches the filter, otherwise
* returns 0
*/
Amount
GetDebit
(
const
CTxIn
&
txin
,
const
isminefilter
&
filter
)
const
;
isminetype
IsMine
(
const
CTxOut
&
txout
)
const
;
Amount
GetCredit
(
const
CTxOut
&
txout
,
const
isminefilter
&
filter
)
const
;
bool
IsChange
(
const
CTxOut
&
txout
)
const
;
Amount
GetChange
(
const
CTxOut
&
txout
)
const
;
bool
IsMine
(
const
CTransaction
&
tx
)
const
;
/** should probably be renamed to IsRelevantToMe */
bool
IsFromMe
(
const
CTransaction
&
tx
)
const
;
Amount
GetDebit
(
const
CTransaction
&
tx
,
const
isminefilter
&
filter
)
const
;
/** Returns whether all of the inputs match the filter */
bool
IsAllFromMe
(
const
CTransaction
&
tx
,
const
isminefilter
&
filter
)
const
;
Amount
GetCredit
(
const
CTransaction
&
tx
,
const
isminefilter
&
filter
)
const
;
Amount
GetChange
(
const
CTransaction
&
tx
)
const
;
void
ChainStateFlushed
(
const
CBlockLocator
&
loc
)
override
;
DBErrors
LoadWallet
(
bool
&
fFirstRunRet
);
DBErrors
ZapWalletTx
(
std
::
vector
<
CWalletTx
>
&
vWtx
);
DBErrors
ZapSelectTx
(
std
::
vector
<
TxId
>
&
txIdsIn
,
std
::
vector
<
TxId
>
&
txIdsOut
)
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
bool
SetAddressBook
(
const
CTxDestination
&
address
,
const
std
::
string
&
strName
,
const
std
::
string
&
purpose
);
bool
DelAddressBook
(
const
CTxDestination
&
address
);
const
std
::
string
&
GetLabelName
(
const
CScript
&
scriptPubKey
)
const
;
void
GetScriptForMining
(
std
::
shared_ptr
<
CReserveScript
>
&
script
);
unsigned
int
GetKeyPoolSize
()
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
)
{
// set{Ex,In}ternalKeyPool
AssertLockHeld
(
cs_wallet
);
return
setInternalKeyPool
.
size
()
+
setExternalKeyPool
.
size
();
}
//! signify that a particular wallet feature is now used. this may change
//! nWalletVersion and nWalletMaxVersion if those are lower
void
SetMinVersion
(
enum
WalletFeature
,
WalletBatch
*
batch_in
=
nullptr
,
bool
fExplicit
=
false
);
//! change which version we're allowed to upgrade to (note that this does
//! not immediately imply upgrading to that format)
bool
SetMaxVersion
(
int
nVersion
);
//! get the current wallet format (the oldest client version guaranteed to
//! understand this wallet)
int
GetVersion
()
{
LOCK
(
cs_wallet
);
return
nWalletVersion
;
}
//! Get wallet transactions that conflict with given transaction (spend same
//! outputs)
std
::
set
<
TxId
>
GetConflicts
(
const
TxId
&
txid
)
const
;
//! Check if a given transaction has any of its outputs spent by another
//! transaction in the wallet
bool
HasWalletSpend
(
const
TxId
&
txid
)
const
EXCLUSIVE_LOCKS_REQUIRED
(
cs_wallet
);
//! Flush wallet (bitdb flush)
void
Flush
(
bool
shutdown
=
false
);
/** Wallet is about to be unloaded */
boost
::
signals2
::
signal
<
void
()
>
NotifyUnload
;
/**
* Address book entry changed.
* @note called with lock cs_wallet held.
*/
boost
::
signals2
::
signal
<
void
(
CWallet
*
wallet
,
const
CTxDestination
&
address
,
const
std
::
string
&
label
,
bool
isMine
,
const
std
::
string
&
purpose
,
ChangeType
status
)
>
NotifyAddressBookChanged
;
/**
* Wallet transaction added, removed or updated.
* @note called with lock cs_wallet held.
*/
boost
::
signals2
::
signal
<
void
(
CWallet
*
wallet
,
const
TxId
&
txid
,
ChangeType
status
)
>
NotifyTransactionChanged
;
/** Show progress e.g. for rescan */
boost
::
signals2
::
signal
<
void
(
const
std
::
string
&
title
,
int
nProgress
)
>
ShowProgress
;
/** Watch-only address added */
boost
::
signals2
::
signal
<
void
(
bool
fHaveWatchOnly
)
>
NotifyWatchonlyChanged
;
/** Inquire whether this wallet broadcasts transactions. */
bool
GetBroadcastTransactions
()
const
{
return
fBroadcastTransactions
;
}
/** Set whether this wallet broadcasts transactions. */
void
SetBroadcastTransactions
(
bool
broadcast
)
{
fBroadcastTransactions
=
broadcast
;
}
/** Return whether transaction can be abandoned */
bool
TransactionCanBeAbandoned
(
const
TxId
&
txid
)
const
;
/**
* Mark a transaction (and it in-wallet descendants) as abandoned so its
* inputs may be respent.
*/
bool
AbandonTransaction
(
const
TxId
&
txid
);
//! Verify wallet naming and perform salvage on the wallet if required
static
bool
Verify
(
const
CChainParams
&
chainParams
,
std
::
string
wallet_file
,
bool
salvage_wallet
,
std
::
string
&
error_string
,
std
::
string
&
warning_string
);
/**
* Initializes the wallet, returns a new CWallet instance or a null pointer
* in case of an error.
*/
static
std
::
shared_ptr
<
CWallet
>
CreateWalletFromFile
(
const
CChainParams
&
chainParams
,
const
std
::
string
&
name
,
const
fs
::
path
&
path
);
/**
* Wallet post-init setup
* Gives the wallet a chance to register repetitive tasks and complete
* post-init tasks
*/
void
postInitProcess
();
bool
BackupWallet
(
const
std
::
string
&
strDest
);
/* Set the HD chain model (chain child index counters) */
void
SetHDChain
(
const
CHDChain
&
chain
,
bool
memonly
);
const
CHDChain
&
GetHDChain
()
const
{
return
hdChain
;
}
/* Returns true if HD is enabled */
bool
IsHDEnabled
()
const
;
/* Generates a new HD seed (will not be activated) */
CPubKey
GenerateNewSeed
();
/**
* Derives a new HD seed (will not be activated)
*/
CPubKey
DeriveNewSeed
(
const
CKey
&
key
);
/**
* Set the current HD seed (will reset the chain child index counters)
* Sets the seed's version based on the current wallet version (so the
* caller must ensure the current wallet version is correct before calling
* this function).
*/
void
SetHDSeed
(
const
CPubKey
&
key
);
/**
* Blocks until the wallet state is up-to-date to /at least/ the current
* chain at the time this function is entered.
* Obviously holding cs_main/cs_wallet when going into this call may cause
* deadlock
*/
void
BlockUntilSyncedToCurrentChain
()
LOCKS_EXCLUDED
(
cs_main
,
cs_wallet
);
/**
* Explicitly make the wallet learn the related scripts for outputs to the
* given key. This is purely to make the wallet file compatible with older
* software, as CBasicKeyStore automatically does this implicitly for all
* keys now.
*/
void
LearnRelatedScripts
(
const
CPubKey
&
key
,
OutputType
);
/**
* Same as LearnRelatedScripts, but when the OutputType is not known (and
* could be anything).
*/
void
LearnAllRelatedScripts
(
const
CPubKey
&
key
);
};
/** A key allocated from the key pool. */
class
CReserveKey
final
:
public
CReserveScript
{
protected
:
CWallet
*
pwallet
;
int64_t
nIndex
{
-1
};
CPubKey
vchPubKey
;
bool
fInternal
{
false
};
public
:
explicit
CReserveKey
(
CWallet
*
pwalletIn
)
{
pwallet
=
pwalletIn
;
}
CReserveKey
(
const
CReserveKey
&
)
=
delete
;
CReserveKey
&
operator
=
(
const
CReserveKey
&
)
=
delete
;
~
CReserveKey
()
{
ReturnKey
();
}
void
ReturnKey
();
bool
GetReservedKey
(
CPubKey
&
pubkey
,
bool
internal
=
false
);
void
KeepKey
();
void
KeepScript
()
override
{
KeepKey
();
}
};
/**
* DEPRECATED Account information.
* Stored in wallet with key "acc"+string account name.
*/
class
CAccount
{
public
:
CPubKey
vchPubKey
;
CAccount
()
{
SetNull
();
}
void
SetNull
()
{
vchPubKey
=
CPubKey
();
}
ADD_SERIALIZE_METHODS
;
template
<
typename
Stream
,
typename
Operation
>
inline
void
SerializationOp
(
Stream
&
s
,
Operation
ser_action
)
{
int
nVersion
=
s
.
GetVersion
();
if
(
!
(
s
.
GetType
()
&
SER_GETHASH
))
{
READWRITE
(
nVersion
);
}
READWRITE
(
vchPubKey
);
}
};
/** RAII object to check and reserve a wallet rescan */
class
WalletRescanReserver
{
private
:
CWallet
*
m_wallet
;
bool
m_could_reserve
;
public
:
explicit
WalletRescanReserver
(
CWallet
*
w
)
:
m_wallet
(
w
),
m_could_reserve
(
false
)
{}
bool
reserve
()
{
assert
(
!
m_could_reserve
);
std
::
lock_guard
<
std
::
mutex
>
lock
(
m_wallet
->
mutexScanning
);
if
(
m_wallet
->
fScanningWallet
)
{
return
false
;
}
m_wallet
->
fScanningWallet
=
true
;
m_could_reserve
=
true
;
return
true
;
}
bool
isReserved
()
const
{
return
(
m_could_reserve
&&
m_wallet
->
fScanningWallet
);
}
~
WalletRescanReserver
()
{
std
::
lock_guard
<
std
::
mutex
>
lock
(
m_wallet
->
mutexScanning
);
if
(
m_could_reserve
)
{
m_wallet
->
fScanningWallet
=
false
;
}
}
};
// Calculate the size of the transaction assuming all signatures are max size
// Use DummySignatureCreator, which inserts 72 byte signatures everywhere.
// NOTE: this requires that all inputs must be in mapWallet (eg the tx should
// be IsAllFromMe).
int64_t
CalculateMaximumSignedTxSize
(
const
CTransaction
&
tx
,
const
CWallet
*
wallet
);
int64_t
CalculateMaximumSignedTxSize
(
const
CTransaction
&
tx
,
const
CWallet
*
wallet
,
const
std
::
vector
<
CTxOut
>
&
txouts
);
#endif
// BITCOIN_WALLET_WALLET_H
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sun, Mar 2, 11:40 (1 d, 6 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5187658
Default Alt Text
wallet.h (50 KB)
Attached To
rABC Bitcoin ABC
Event Timeline
Log In to Comment