Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/coincontrol.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class CCoinControl
int nSplitBlock;
//! If false, allows unselected inputs, but requires all selected inputs be used
bool fAllowOtherInputs;
//! Includes watch only addresses which match the ISMINE_WATCH_SOLVABLE criteria
//! Includes watch only addresses which are solvable
bool fAllowWatchOnly;
//! Minimum absolute fee (not per kilobyte)
CAmount nMinimumTotalFee;
Expand Down
4 changes: 2 additions & 2 deletions src/policy/policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ static const unsigned int MAX_P2SH_SIGOPS = 15;
* with. However scripts violating these flags may still be present in valid
* blocks and we must accept those blocks.
*/
static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY_FLAGS |
static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY_FLAGS |
SCRIPT_VERIFY_DERSIG |
SCRIPT_VERIFY_STRICTENC |
SCRIPT_VERIFY_MINIMALDATA |
Expand All @@ -36,7 +36,7 @@ static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY
SCRIPT_VERIFY_LOW_S;

/** For convenience, standard but not mandatory verify flags. */
static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS;
static constexpr unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS;

// Sanity check the magic numbers when we change them
BOOST_STATIC_ASSERT(DEFAULT_BLOCK_MAX_SIZE <= MAX_BLOCK_SIZE_CURRENT);
Expand Down
22 changes: 12 additions & 10 deletions src/script/ismine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey)
std::vector<valtype> vSolutions;
txnouttype whichType;
if(!Solver(scriptPubKey, whichType, vSolutions)) {
if(keystore.HaveWatchOnly(scriptPubKey))
return ISMINE_WATCH_UNSOLVABLE;
if(keystore.HaveWatchOnly(scriptPubKey)) {
return ISMINE_WATCH_ONLY;
}

return ISMINE_NO;
}
Expand Down Expand Up @@ -77,12 +78,15 @@ isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey)
CKeyID ownerKeyID = CKeyID(uint160(vSolutions[1]));
bool spendKeyIsMine = keystore.HaveKey(ownerKeyID);

if (spendKeyIsMine && stakeKeyIsMine)
return ISMINE_SPENDABLE_STAKEABLE;
else if (stakeKeyIsMine)
return ISMINE_COLD;
else if (spendKeyIsMine)
if (spendKeyIsMine) {
// If the wallet has both keys, ISMINE_SPENDABLE_DELEGATED
// takes precedence over ISMINE_COLD
return ISMINE_SPENDABLE_DELEGATED;
} else if (stakeKeyIsMine) {
return ISMINE_COLD;
} else {
// todo: Include watch only..
}
break;
}
case TX_MULTISIG: {
Expand All @@ -99,9 +103,7 @@ isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey)
}

if (keystore.HaveWatchOnly(scriptPubKey)) {
// TODO: This could be optimized some by doing some work after the above solver
SignatureData sigdata;
return ProduceSignature(DummySignatureCreator(&keystore), scriptPubKey, sigdata, false) ? ISMINE_WATCH_SOLVABLE : ISMINE_WATCH_UNSOLVABLE;
return ISMINE_WATCH_ONLY;
}

return ISMINE_NO;
Expand Down
36 changes: 26 additions & 10 deletions src/script/ismine.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,47 @@

#include "key.h"
#include "script/standard.h"
#include <bitset>

class CKeyStore;
class CScript;

/** IsMine() return codes */
enum isminetype {
ISMINE_NO = 0,
//! Indicates that we dont know how to create a scriptSig that would solve this if we were given the appropriate private keys
ISMINE_WATCH_UNSOLVABLE = 1,
//! Indicates that we know how to create a scriptSig that would solve this if we were given the appropriate private keys
ISMINE_WATCH_SOLVABLE = 2,
ISMINE_WATCH_ONLY = ISMINE_WATCH_SOLVABLE | ISMINE_WATCH_UNSOLVABLE,
ISMINE_SPENDABLE = 4,
ISMINE_WATCH_ONLY = 1 << 0,
ISMINE_SPENDABLE = 1 << 1,
//! Indicates that we have the staking key of a P2CS
ISMINE_COLD = 8,
ISMINE_COLD = 1 << 2,
//! Indicates that we have the spending key of a P2CS
ISMINE_SPENDABLE_DELEGATED = 16,
ISMINE_SPENDABLE_DELEGATED = 1 << 3,
ISMINE_SPENDABLE_ALL = ISMINE_SPENDABLE_DELEGATED | ISMINE_SPENDABLE,
ISMINE_SPENDABLE_STAKEABLE = ISMINE_SPENDABLE_DELEGATED | ISMINE_COLD,
ISMINE_ALL = ISMINE_WATCH_ONLY | ISMINE_SPENDABLE | ISMINE_COLD | ISMINE_SPENDABLE_DELEGATED
ISMINE_ALL = ISMINE_WATCH_ONLY | ISMINE_SPENDABLE | ISMINE_COLD | ISMINE_SPENDABLE_DELEGATED,
ISMINE_ENUM_ELEMENTS
};
/** used for bitflags of isminetype */
typedef uint8_t isminefilter;

isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest);

/**
* Cachable amount subdivided into watchonly and spendable parts.
*/
struct CachableAmount
{
// NO and ALL are never (supposed to be) cached
std::bitset<ISMINE_ENUM_ELEMENTS> m_cached;
CAmount m_value[ISMINE_ENUM_ELEMENTS];
inline void Reset()
{
m_cached.reset();
}
void Set(isminefilter filter, CAmount value)
{
m_cached.set(filter);
m_value[filter] = value;
}
};

#endif // BITCOIN_SCRIPT_ISMINE_H
15 changes: 15 additions & 0 deletions src/script/sign.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,3 +380,18 @@ bool DummySignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const
vchSig[6 + 33 + 32] = SIGHASH_ALL;
return true;
}

bool IsSolvable(const CKeyStore& store, const CScript& script)
{
// This check is to make sure that the script we created can actually be solved for and signed by us
// if we were to have the private keys. This is just to make sure that the script is valid and that,
// if found in a transaction, we would still accept and relay that transaction. In particular,
DummySignatureCreator creator(&store);
SignatureData sigs;
if (ProduceSignature(creator, script, sigs, false)) {
// VerifyScript check is just defensive, and should never fail.
assert(VerifyScript(sigs.scriptSig, script, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker()));
return true;
}
return false;
}
6 changes: 6 additions & 0 deletions src/script/sign.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,10 @@ SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignature
SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn);
void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const SignatureData& data);

/* Check whether we know how to sign for an output like this, assuming we
* have all private keys. While this function does not need private keys, the passed
* keystore is used to look up public keys and redeemscripts by hash.
* Solvability is unrelated to whether we consider this output to be ours. */
bool IsSolvable(const CKeyStore& store, const CScript& script);

#endif // BITCOIN_SCRIPT_SIGN_H
6 changes: 2 additions & 4 deletions src/wallet/test/wallet_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,8 @@ static void add_coin(const CAmount& nValue, int nAge = 6*24, bool fIsFromMe = fa
tx.vin.resize(1);
}
CWalletTx* wtx = new CWalletTx(pwalletMain, tx);
if (fIsFromMe)
{
wtx->fDebitCached = true;
wtx->nDebitCached = 1;
if (fIsFromMe) {
wtx->m_amounts[CWalletTx::DEBIT].Set(ISMINE_SPENDABLE, 1);
}
COutput output(wtx, nInput, nAge, true, true);
vCoins.push_back(output);
Expand Down
Loading