PUBKEY_PAIR_ADDRESS / PUBKEY_PAIR_ADDRESS_TEST
authorCryptoManiac <balthazar@yandex.ru>
Sat, 5 Mar 2016 23:02:57 +0000 (02:02 +0300)
committerCryptoManiac <balthazar@yandex.ru>
Sat, 5 Mar 2016 23:02:57 +0000 (02:02 +0300)
src/base58.cpp
src/base58.h
src/bitcoinrpc.cpp
src/bitcoinrpc.h
src/key.cpp
src/key.h
src/qt/coincontroldialog.cpp
src/rpcdump.cpp
src/rpcrawtransaction.cpp
src/rpcwallet.cpp
src/wallet.cpp

index 1842853..a524be6 100644 (file)
@@ -183,6 +183,11 @@ bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRe
         if (!vchData.empty())
             memcpy(&vchData[0], pdata, nSize);
     }
+    
+    const std::vector<unsigned char> &CBase58Data::GetData() const
+    {
+        return vchData;
+    }
 
     void CBase58Data::SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend)
     {
@@ -243,12 +248,22 @@ bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRe
         return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
     }
 
+    bool CBitcoinAddress::Set(const CMalleablePubKey &mpk) {
+        std::vector<unsigned char> vchPubkeyPair = mpk.Raw();
+        SetData(fTestNet ? PUBKEY_PAIR_ADDRESS_TEST : PUBKEY_PAIR_ADDRESS, &vchPubkeyPair[0], 68);
+        return true;
+    }
+
     bool CBitcoinAddress::IsValid() const
     {
         unsigned int nExpectedSize = 20;
         bool fExpectTestNet = false;
         switch(nVersion)
         {
+            case PUBKEY_PAIR_ADDRESS:
+                nExpectedSize = 68; // Serialized pair of public keys
+                fExpectTestNet = false;
+                break;
             case PUBKEY_ADDRESS:
                 nExpectedSize = 20; // Hash of public key
                 fExpectTestNet = false;
@@ -258,6 +273,10 @@ bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRe
                 fExpectTestNet = false;
                 break;
 
+            case PUBKEY_PAIR_ADDRESS_TEST:
+                nExpectedSize = 68;
+                fExpectTestNet = true;
+                break;
             case PUBKEY_ADDRESS_TEST:
                 nExpectedSize = 20;
                 fExpectTestNet = true;
@@ -304,6 +323,13 @@ bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRe
             keyID = CKeyID(id);
             return true;
         }
+        case PUBKEY_PAIR_ADDRESS:
+        case PUBKEY_PAIR_ADDRESS_TEST:
+        {
+            CMalleablePubKey mPubKey;
+            mPubKey.setvch(vchData);
+            keyID = mPubKey.GetID();
+        }
         default: return false;
         }
     }
@@ -319,6 +345,18 @@ bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRe
         default: return false;
         }
     }
+    
+    bool CBitcoinAddress::IsPair() const {
+        if (!IsValid())
+            return false;
+        switch (nVersion) {
+        case PUBKEY_PAIR_ADDRESS:
+        case PUBKEY_PAIR_ADDRESS_TEST: {
+            return true;
+        }
+        default: return false;
+        }
+    }
 
     void CBitcoinSecret::SetSecret(const CSecret& vchSecret, bool fCompressed)
     {
index b8a0e45..b312443 100644 (file)
@@ -67,6 +67,7 @@ public:
     bool SetString(const char* psz);
     bool SetString(const std::string& str);
     std::string ToString() const;
+    const std::vector<unsigned char> &GetData() const;
 
     int CompareTo(const CBase58Data& b58) const;
     bool operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; }
@@ -91,6 +92,7 @@ public:
     CBitcoinAddressVisitor(CBitcoinAddress *addrIn) : addr(addrIn) { }
     bool operator()(const CKeyID &id) const;
     bool operator()(const CScriptID &id) const;
+    bool operator()(const CMalleablePubKey &mpk) const;
     bool operator()(const CNoDestination &no) const;
 };
 
@@ -99,8 +101,10 @@ class CBitcoinAddress : public CBase58Data
 public:
     enum
     {
+        PUBKEY_PAIR_ADDRESS = 1,
         PUBKEY_ADDRESS = 8,
         SCRIPT_ADDRESS = 20,
+        PUBKEY_PAIR_ADDRESS_TEST = 6,
         PUBKEY_ADDRESS_TEST = 111,
         SCRIPT_ADDRESS_TEST = 196
     };
@@ -108,6 +112,7 @@ public:
     bool Set(const CKeyID &id);
     bool Set(const CScriptID &id);
     bool Set(const CTxDestination &dest);
+    bool Set(const CMalleablePubKey &mpk);
     bool IsValid() const;
 
     CBitcoinAddress()
@@ -119,6 +124,11 @@ public:
         Set(dest);
     }
 
+    CBitcoinAddress(const CMalleablePubKey &mpk)
+    {
+        Set(mpk);
+    }
+
     CBitcoinAddress(const std::string& strAddress)
     {
         SetString(strAddress);
@@ -132,11 +142,13 @@ public:
     CTxDestination Get() const;
     bool GetKeyID(CKeyID &keyID) const;
     bool IsScript() const;
+    bool IsPair() const;
 };
 
-bool inline CBitcoinAddressVisitor::operator()(const CKeyID &id) const         { return addr->Set(id); }
-bool inline CBitcoinAddressVisitor::operator()(const CScriptID &id) const      { return addr->Set(id); }
-bool inline CBitcoinAddressVisitor::operator()(const CNoDestination &id) const { return false; }
+bool inline CBitcoinAddressVisitor::operator()(const CKeyID &id) const            { return addr->Set(id); }
+bool inline CBitcoinAddressVisitor::operator()(const CScriptID &id) const         { return addr->Set(id); }
+bool inline CBitcoinAddressVisitor::operator()(const CMalleablePubKey &mpk) const { return addr->Set(mpk); }
+bool inline CBitcoinAddressVisitor::operator()(const CNoDestination &id) const    { return false; }
 
 /** A base58-encoded secret key */
 class CBitcoinSecret : public CBase58Data
index 80674d6..f52ae80 100644 (file)
@@ -321,7 +321,6 @@ static const CRPCCommand vRPCCommands[] =
     { "adjustmalleablepubkey",  &adjustmalleablepubkey,  false,  false},
     { "listmalleableviews",     &listmalleableviews,     false,  false},
     { "dumpmalleablekey",       &dumpmalleablekey,       false,  false},
-    { "validatemalleablepubkey",&validatemalleablepubkey,true,   false },
     { "importmalleablekey",     &importmalleablekey,     true,   false },
     { "encryptdata",            &encryptdata,            false,  false },
     { "decryptdata",            &decryptdata,            false,  false },
index 84dd6a4..5befb76 100644 (file)
@@ -211,7 +211,6 @@ extern json_spirit::Value adjustmalleablekey(const json_spirit::Array& params, b
 extern json_spirit::Value adjustmalleablepubkey(const json_spirit::Array& params, bool fHelp);
 extern json_spirit::Value listmalleableviews(const json_spirit::Array& params, bool fHelp);
 extern json_spirit::Value dumpmalleablekey(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value validatemalleablepubkey(const json_spirit::Array& params, bool fHelp);
 extern json_spirit::Value importmalleablekey(const json_spirit::Array& params, bool fHelp);
 
 extern json_spirit::Value encryptdata(const json_spirit::Array& params, bool fHelp); // in rpccrypt.cpp
index b1db7cb..1012915 100644 (file)
@@ -725,6 +725,14 @@ std::string CMalleablePubKey::ToString() const
     return EncodeBase58Check(vch);
 }
 
+bool CMalleablePubKey::setvch(const std::vector<unsigned char> &vchPubKeyPair)
+{
+    CDataStream ssKey(vchPubKeyPair, SER_NETWORK, PROTOCOL_VERSION);
+    ssKey >> *this;
+
+    return IsValid();
+}
+
 std::vector<unsigned char> CMalleablePubKey::Raw() const
 {
     CDataStream ssKey(SER_NETWORK, PROTOCOL_VERSION);
index bf1557a..bc7e2ab 100644 (file)
--- a/src/key.h
+++ b/src/key.h
@@ -251,6 +251,7 @@ public:
         return pubKeyL.GetID();
     }
 
+    bool setvch(const std::vector<unsigned char> &vchPubKeyPair);
     std::vector<unsigned char> Raw() const;
 
     CPubKey& GetL() { return pubKeyL; }
index 998a992..3f67ee6 100644 (file)
@@ -686,7 +686,7 @@ void CoinControlDialog::updateView()
                     // Pay-to-Pubkey-R
                     CMalleableKeyView view;
                     pwalletMain->CheckOwnership(CPubKey(vSolutions[0]), CPubKey(vSolutions[1]), view);
-                    sAddress = view.GetMalleablePubKey().ToString().c_str();
+                    sAddress = CBitcoinAddress(view.GetMalleablePubKey()).ToString().c_str();
                 }
 
                 // if listMode or change => show bitcoin address. In tree mode, address is not shown again for direct wallet address outputs
index 6a83604..6e72688 100644 (file)
@@ -260,7 +260,7 @@ Value dumpmalleablekey(const Array& params, bool fHelp)
 
     Object result;
     result.push_back(Pair("PrivatePair", mKey.ToString()));
-    result.push_back(Pair("PublicPair", mKey.GetMalleablePubKey().ToString()));
+    result.push_back(Pair("Address", CBitcoinAddress(mKey.GetMalleablePubKey()).ToString()));
 
     return result;
 }
@@ -284,7 +284,7 @@ Value importmalleablekey(const Array& params, bool fHelp)
     {
         fSuccess = pwalletMain->AddMalleableKey(mKey);
         result.push_back(Pair("Successful", fSuccess));
-        result.push_back(Pair("PublicPair", mKey.GetMalleablePubKey().ToString()));
+        result.push_back(Pair("Address", CBitcoinAddress(mKey.GetMalleablePubKey()).ToString()));
         result.push_back(Pair("KeyView", CMalleableKeyView(mKey).ToString()));
     }
     else
index 7767898..1272156 100644 (file)
@@ -49,7 +49,7 @@ void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeH
 
             CMalleableKeyView view;
             if (pwalletMain->CheckOwnership(CPubKey(vSolutions[0]), CPubKey(vSolutions[1]), view))
-                out.push_back(Pair("pubkeyPair", view.GetMalleablePubKey().ToString()));
+                out.push_back(Pair("pubkeyPair", CBitcoinAddress(view.GetMalleablePubKey()).ToString()));
         }
         else
         {
@@ -293,23 +293,29 @@ Value createrawtransaction(const Array& params, bool fHelp)
         // Create output destination script
         CScript scriptPubKey;
         CBitcoinAddress address(s.name_);
-        if (!address.IsValid())
+
+        if (address.IsValid())
         {
-            CMalleablePubKey mpk(s.name_);
-            if (!mpk.IsValid())
-                throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid output destination: ")+s.name_);
+            if (!address.IsPair())
+            {
+                scriptPubKey.SetDestination(address.Get());
+                if (setAddress.count(address))
+                    throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
+                setAddress.insert(address);
+            }
+            else
+            {
+                CMalleablePubKey mpk;
+                if (!mpk.setvch(address.GetData()))
+                    throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid output destination: ")+s.name_);
 
-            CPubKey keyVariant, R;
-            mpk.GetVariant(R, keyVariant);
-            scriptPubKey.SetDestination(R, keyVariant);
+                CPubKey R, pubKeyVariant;
+                mpk.GetVariant(R, pubKeyVariant);
+                scriptPubKey.SetDestination(R, pubKeyVariant);
+            }
         }
         else
-        {
-            scriptPubKey.SetDestination(address.Get());
-            if (setAddress.count(address))
-                throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
-            setAddress.insert(address);
-        }
+            throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid output destination: ")+s.name_);
 
         int64_t nAmount = AmountFromValue(s.value_);
 
index 12b6603..a0e6afc 100644 (file)
@@ -329,17 +329,22 @@ Value sendtoaddress(const Array& params, bool fHelp)
 
     CBitcoinAddress address(strAddress);
     if (address.IsValid())
-        scriptPubKey.SetDestination(address.Get());
-    else
     {
-        CMalleablePubKey mpk(strAddress);
-        if (!mpk.IsValid())
-            throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid NovaCoin address");
+        if (!address.IsPair())
+            scriptPubKey.SetDestination(address.Get());
+        else
+        {
+            CMalleablePubKey mpk;
+            if (!mpk.setvch(address.GetData()))
+                throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid NovaCoin address");
 
-        CPubKey R, pubKeyVariant;
-        mpk.GetVariant(R, pubKeyVariant);
-        scriptPubKey.SetDestination(R, pubKeyVariant);
+            CPubKey R, pubKeyVariant;
+            mpk.GetVariant(R, pubKeyVariant);
+            scriptPubKey.SetDestination(R, pubKeyVariant);
+        }
     }
+    else
+        throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid NovaCoin address");
 
     // Amount
     int64_t nAmount = AmountFromValue(params[1]);
@@ -716,17 +721,23 @@ Value sendfrom(const Array& params, bool fHelp)
 
     CBitcoinAddress address(strAddress);
     if (address.IsValid())
-        scriptPubKey.SetDestination(address.Get());
-    else
     {
-        CMalleablePubKey mpk(strAddress);
-        if (!mpk.IsValid())
-            throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid NovaCoin address");
+        if (!address.IsPair())
+            scriptPubKey.SetDestination(address.Get());
+        else
+        {
+            CMalleablePubKey mpk;
+            if (!mpk.setvch(address.GetData()))
+                throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid NovaCoin address");
 
-        CPubKey R, pubKeyVariant;
-        mpk.GetVariant(R, pubKeyVariant);
-        scriptPubKey.SetDestination(R, pubKeyVariant);
+            CPubKey R, pubKeyVariant;
+            mpk.GetVariant(R, pubKeyVariant);
+            scriptPubKey.SetDestination(R, pubKeyVariant);
+        }
     }
+    else
+        throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid NovaCoin address");
+
 
     int64_t nAmount = AmountFromValue(params[2]);
 
@@ -1747,18 +1758,34 @@ Value validateaddress(const Array& params, bool fHelp)
     ret.push_back(Pair("isvalid", isValid));
     if (isValid)
     {
-        CTxDestination dest = address.Get();
-        string currentAddress = address.ToString();
-        ret.push_back(Pair("address", currentAddress));
-        isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : MINE_NO;
-        ret.push_back(Pair("ismine", mine != MINE_NO));
-        if (mine != MINE_NO) {
-            ret.push_back(Pair("watchonly", mine == MINE_WATCH_ONLY));
-            Object detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest);
-            ret.insert(ret.end(), detail.begin(), detail.end());
+        if (address.IsPair())
+        {
+            CMalleablePubKey mpk;
+            mpk.setvch(address.GetData());
+            ret.push_back(Pair("ispair", true));
+
+            CMalleableKeyView view;
+            bool isMine = pwalletMain->GetMalleableView(mpk, view);
+            ret.push_back(Pair("ismine", isMine));
+
+            if (isMine)
+                ret.push_back(Pair("KeyView", view.ToString()));
+        }
+        else
+        {
+            CTxDestination dest = address.Get();
+            string currentAddress = address.ToString();
+            ret.push_back(Pair("address", currentAddress));
+            isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : MINE_NO;
+            ret.push_back(Pair("ismine", mine != MINE_NO));
+            if (mine != MINE_NO) {
+                ret.push_back(Pair("watchonly", mine == MINE_WATCH_ONLY));
+                Object detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest);
+                ret.insert(ret.end(), detail.begin(), detail.end());
+            }
+            if (pwalletMain->mapAddressBook.count(dest))
+                ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest]));
         }
-        if (pwalletMain->mapAddressBook.count(dest))
-            ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest]));
     }
     return ret;
 }
@@ -1906,43 +1933,16 @@ Value newmalleablekey(const Array& params, bool fHelp)
         throw runtime_error("Unable to generate new malleable key");
 
     CMalleablePubKey mPubKey = mKey.GetMalleablePubKey();
-    CDataStream ssPublicBytes(SER_NETWORK, PROTOCOL_VERSION);
-    ssPublicBytes << mPubKey;
 
     Object result;
     result.push_back(Pair("PublicPair", mPubKey.ToString()));
-    result.push_back(Pair("PublicBytes", HexStr(ssPublicBytes.begin(), ssPublicBytes.end())));
+    result.push_back(Pair("PublicBytes", HexStr(mPubKey.Raw())));
+    result.push_back(Pair("Address", CBitcoinAddress(mPubKey).ToString()));
     result.push_back(Pair("KeyView", keyView.ToString()));
 
     return result;
 }
 
-Value validatemalleablepubkey(const Array& params, bool fHelp)
-{
-    if (fHelp || params.size() != 1)
-        throw runtime_error(
-            "validatemalleablekey <Malleable public key data>\n"
-            "Check the validity and ownership for priovided malleable public key.\n");
-
-    CMalleablePubKey mpk;
-    bool isValid = mpk.SetString(params[0].get_str());
-
-    Object result;
-    result.push_back(Pair("isvalid", isValid));
-
-    if (isValid)
-    {
-        CMalleableKeyView view;
-        bool isMine = pwalletMain->GetMalleableView(mpk, view);
-        result.push_back(Pair("ismine", isMine));
-
-        if (isMine)
-            result.push_back(Pair("KeyView", view.ToString()));
-    }
-
-    return result;
-}
-
 Value adjustmalleablekey(const Array& params, bool fHelp)
 {
     if (fHelp || params.size() != 3)
@@ -1982,8 +1982,7 @@ Value adjustmalleablepubkey(const Array& params, bool fHelp)
     CMalleablePubKey malleablePubKey;
 
     if (pubKeyPair.size() == 136) {
-        CDataStream ssPublicBytes(ParseHex(pubKeyPair), SER_NETWORK, PROTOCOL_VERSION);
-        ssPublicBytes >> malleablePubKey;
+        malleablePubKey.setvch(ParseHex(pubKeyPair));
     } else
         malleablePubKey.SetString(pubKeyPair);
 
index ee601ca..908afaa 100644 (file)
@@ -2829,7 +2829,7 @@ bool CWallet::ExtractAddress(const CScript& scriptPubKey, std::string& addressRe
         if (!CheckOwnership(CPubKey(vSolutions[0]), CPubKey(vSolutions[1]), view))
             return false;
 
-        addressRet = view.GetMalleablePubKey().ToString();
+        addressRet = CBitcoinAddress(view.GetMalleablePubKey()).ToString();
         return true;
     }
     else if (whichType == TX_PUBKEYHASH)