From c8988460a2865b99ee96da6799d37ac6ccb79d4d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 26 Jul 2013 01:06:01 +0200 Subject: Add support for watch-only addresses Changes: * Add Add/Have WatchOnly methods to CKeyStore, and implementations in CBasicKeyStore. * Add similar methods to CWallet, and support entries for it in CWalletDB. * Make IsMine in script/wallet return a new enum 'isminetype', rather than a boolean. This allows distinguishing between spendable and unspendable coins. * Add a field fSpendable to COutput (GetAvailableCoins' return type). * Mark watchonly coins in listunspent as 'watchonly': true. * Add 'watchonly' to validateaddress, suppressing script/pubkey/... in this case. Based on a patch by Eric Lombrozo. Conflicts: src/qt/walletmodel.cpp src/rpcserver.cpp src/wallet.cpp --- src/walletdb.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'src/walletdb.cpp') diff --git a/src/walletdb.cpp b/src/walletdb.cpp index 3ce2ef019..9338d5709 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -112,6 +112,12 @@ bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript) return Write(std::make_pair(std::string("cscript"), hash), redeemScript, false); } +bool CWalletDB::WriteWatchOnly(const CTxDestination &dest) +{ + nWalletDBUpdated++; + return Write(std::make_pair(std::string("watch"), CBitcoinAddress(dest).ToString()), '1'); +} + bool CWalletDB::WriteBestBlock(const CBlockLocator& locator) { nWalletDBUpdated++; @@ -404,6 +410,19 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, wss.fAnyUnordered = true; } } + else if (strType == "watch") + { + std::string strAddress; + ssKey >> strAddress; + char fYes; + ssValue >> fYes; + if (fYes == '1') + pwallet->LoadWatchOnly(CBitcoinAddress(strAddress).Get()); + + // Watch-only addresses have no birthday information for now, + // so set the wallet birthday to the beginning of time. + pwallet->nTimeFirstKey = 1; + } else if (strType == "key" || strType == "wkey") { CPubKey vchPubKey; -- cgit v1.2.3 From d5087d1ba08142bdf135333a0da08ef0f5fc7ef0 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 9 Jun 2014 21:11:59 +0200 Subject: Use script matching rather than destination matching for watch-only. This changes the keystore data format, wallet format and IsMine logic to detect watch-only outputs based on direct script matching rather than first trying to convert outputs to destinations (addresses). The reason is that we don't know how the software that has the spending keys works. It may support the same types of scripts as us, but that is not guaranteed. Furthermore, it removes the ambiguity between addresses used as identifiers for output scripts or identifiers for public keys. One practical implication is that adding a normal pay-to-pubkey-hash address via importaddress will not cause payments to the corresponding full public key to be detected as IsMine. If that is wanted, add those scripts directly (importaddress now also accepts any hex-encoded script). Conflicts: src/wallet.cpp --- src/walletdb.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/walletdb.cpp') diff --git a/src/walletdb.cpp b/src/walletdb.cpp index 9338d5709..a95baf83d 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -112,10 +112,10 @@ bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript) return Write(std::make_pair(std::string("cscript"), hash), redeemScript, false); } -bool CWalletDB::WriteWatchOnly(const CTxDestination &dest) +bool CWalletDB::WriteWatchOnly(const CScript &dest) { nWalletDBUpdated++; - return Write(std::make_pair(std::string("watch"), CBitcoinAddress(dest).ToString()), '1'); + return Write(std::make_pair(std::string("watchs"), dest), '1'); } bool CWalletDB::WriteBestBlock(const CBlockLocator& locator) @@ -410,14 +410,14 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, wss.fAnyUnordered = true; } } - else if (strType == "watch") + else if (strType == "watchs") { - std::string strAddress; - ssKey >> strAddress; + CScript script; + ssKey >> script; char fYes; ssValue >> fYes; if (fYes == '1') - pwallet->LoadWatchOnly(CBitcoinAddress(strAddress).Get()); + pwallet->LoadWatchOnly(script); // Watch-only addresses have no birthday information for now, // so set the wallet birthday to the beginning of time. -- cgit v1.2.3