Simplification of scriptPubKey handling code.
authorCryptoManiac <balthazar@yandex.ru>
Sun, 6 Mar 2016 20:54:53 +0000 (23:54 +0300)
committerCryptoManiac <balthazar@yandex.ru>
Sun, 6 Mar 2016 20:54:53 +0000 (23:54 +0300)
novacoin-qt.pro
src/base58.cpp
src/base58.h
src/qt/coincontroldialog.cpp
src/qt/signverifymessagedialog.cpp
src/qt/walletmodel.cpp
src/rpcrawtransaction.cpp
src/rpcwallet.cpp
src/script.cpp
src/script.h

index abafeb7..9b9cb14 100644 (file)
@@ -52,8 +52,8 @@ contains(RELEASE, 1) {
 }
 
 contains(DEBUG, 1) {
-    QMAKE_CXXFLAGS_RELEASE -= -O2
-    QMAKE_CFLAGS_RELEASE -= -O2
+    QMAKE_CXXFLAGS -= -O2
+    QMAKE_CFLAGS -= -O2
 
     QMAKE_CFLAGS += -g -O0
     QMAKE_CXXCFLAGS += -g -O0
index a524be6..2691ea4 100644 (file)
@@ -258,11 +258,13 @@ bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRe
     {
         unsigned int nExpectedSize = 20;
         bool fExpectTestNet = false;
+        bool fSimple = true;
         switch(nVersion)
         {
             case PUBKEY_PAIR_ADDRESS:
                 nExpectedSize = 68; // Serialized pair of public keys
                 fExpectTestNet = false;
+                fSimple = false;
                 break;
             case PUBKEY_ADDRESS:
                 nExpectedSize = 20; // Hash of public key
@@ -276,6 +278,7 @@ bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRe
             case PUBKEY_PAIR_ADDRESS_TEST:
                 nExpectedSize = 68;
                 fExpectTestNet = true;
+                fSimple = false;
                 break;
             case PUBKEY_ADDRESS_TEST:
                 nExpectedSize = 20;
@@ -289,7 +292,20 @@ bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRe
             default:
                 return false;
         }
-        return fExpectTestNet == fTestNet && vchData.size() == nExpectedSize;
+
+        // Basic format sanity check
+        bool fSeemsSane = (fExpectTestNet == fTestNet && vchData.size() == nExpectedSize);
+
+        if (fSeemsSane && !fSimple)
+        {
+            // Perform dditional checking
+            //    for pubkey pair addresses
+            CMalleablePubKey mpk;
+            mpk.setvch(vchData);
+            return mpk.IsValid();
+        }
+        else
+            return fSeemsSane;
     }
 
     CTxDestination CBitcoinAddress::Get() const {
@@ -345,6 +361,18 @@ bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRe
         default: return false;
         }
     }
+
+    bool CBitcoinAddress::IsPubKey() const {
+        if (!IsValid())
+            return false;
+        switch (nVersion) {
+        case PUBKEY_ADDRESS:
+        case PUBKEY_ADDRESS_TEST: {
+            return true;
+        }
+        default: return false;
+        }
+    }
     
     bool CBitcoinAddress::IsPair() const {
         if (!IsValid())
index b312443..d5df354 100644 (file)
@@ -142,6 +142,7 @@ public:
     CTxDestination Get() const;
     bool GetKeyID(CKeyID &keyID) const;
     bool IsScript() const;
+    bool IsPubKey() const;
     bool IsPair() const;
 };
 
index 3f67ee6..9ea82a4 100644 (file)
@@ -4,6 +4,7 @@
 #include "init.h"
 #include "base58.h"
 #include "bitcoinunits.h"
+#include "wallet.h"
 #include "walletmodel.h"
 #include "addresstablemodel.h"
 #include "optionsmodel.h"
@@ -469,17 +470,22 @@ void CoinControlDialog::updateLabels(WalletModel *model, QWidget* dialog)
         dPriorityInputs += (double)out.tx->vout[out.i].nValue * (out.nDepth+1);
 
         // Bytes
-        CTxDestination address;
-        if(ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
+        CBitcoinAddress address;
+        if(pwalletMain->ExtractAddress(out.tx->vout[out.i].scriptPubKey, address))
         {
-            CPubKey pubkey;
-            CKeyID *keyid = boost::get< CKeyID >(&address);
-            if (keyid && model->getPubKey(*keyid, pubkey))
-                nBytesInputs += (pubkey.IsCompressed() ? 148 : 180);
-            else
-                nBytesInputs += 148; // in all error cases, simply assume 148 here
+            if (address.IsPair())
+                nBytesInputs += 213;
+            else if (address.IsPubKey())
+            {
+                CPubKey pubkey;
+                CTxDestination dest = address.Get();
+                CKeyID *keyid = boost::get< CKeyID >(&dest);
+                if (keyid && model->getPubKey(*keyid, pubkey))
+                    nBytesInputs += (pubkey.IsCompressed() ? 148 : 180);
+                else
+                    nBytesInputs += 148; // in all error cases, simply assume 148 here
+            }
         }
-        else nBytesInputs += 148;
     }
 
     // calculation
@@ -631,10 +637,10 @@ void CoinControlDialog::updateView()
             itemOutput->setCheckState(COLUMN_CHECKBOX,Qt::Unchecked);
 
             // address
-/*
-            CTxDestination outputAddress;
+            CBitcoinAddress outputAddress;
             QString sAddress = "";
-            if(ExtractDestination(out.tx->vout[out.i].scriptPubKey, outputAddress))
+
+            if(pwalletMain->ExtractAddress(out.tx->vout[out.i].scriptPubKey, outputAddress))
             {
                 sAddress = CBitcoinAddress(outputAddress).ToString().c_str();
 
@@ -642,56 +648,14 @@ void CoinControlDialog::updateView()
                 if (!treeMode || (!(sAddress == sWalletAddress)))
                     itemOutput->setText(COLUMN_ADDRESS, sAddress);
 
-                CPubKey pubkey;
-                CKeyID *keyid = boost::get< CKeyID >(&outputAddress);
-                if (keyid && model->getPubKey(*keyid, pubkey) && !pubkey.IsCompressed())
-                    nInputSize = 180;
-            }
-*/
-            QString sAddress = "";
-            txnouttype whichType;
-            std::vector<valtype> vSolutions;
-            if (Solver(out.tx->vout[out.i].scriptPubKey, whichType, vSolutions))
-            {
-                CTxDestination address;
-                if (whichType == TX_PUBKEY)
+                if (outputAddress.IsPubKey())
                 {
-                    // Pay-to-Pubkey
-                    CPubKey pubKey = CPubKey(vSolutions[0]);
-                    address = pubKey.GetID();
-                    sAddress = CBitcoinAddress(address).ToString().c_str();
-
-                    if (!pubKey.IsCompressed())
-                        nInputSize = 180;
-                }
-                else if (whichType == TX_PUBKEYHASH)
-                {
-                    // Pay-to-PubkeyHash
-                    address = CKeyID(uint160(vSolutions[0]));
-                    sAddress = CBitcoinAddress(address).ToString().c_str();
-
                     CPubKey pubkey;
-                    CKeyID *keyid = boost::get< CKeyID >(&address);
+                    CTxDestination dest = outputAddress.Get();
+                    CKeyID *keyid = boost::get< CKeyID >(&dest);
                     if (keyid && model->getPubKey(*keyid, pubkey) && !pubkey.IsCompressed())
                         nInputSize = 180;
                 }
-                else if (whichType == TX_SCRIPTHASH)
-                {
-                    // Pay-to-ScriptHash
-                    address = CScriptID(uint160(vSolutions[0]));
-                    sAddress = CBitcoinAddress(address).ToString().c_str();
-                }
-                else if (whichType == TX_PUBKEY_DROP)
-                {
-                    // Pay-to-Pubkey-R
-                    CMalleableKeyView view;
-                    pwalletMain->CheckOwnership(CPubKey(vSolutions[0]), CPubKey(vSolutions[1]), view);
-                    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
-                if (!treeMode || (!(sAddress == sWalletAddress)))
-                    itemOutput->setText(COLUMN_ADDRESS, sAddress);
             }
 
             // label
index 187fe13..8d011ab 100644 (file)
@@ -288,4 +288,4 @@ void SignVerifyMessageDialog::keyPressEvent(QKeyEvent *event)
         close();
     }
 #endif
-}
\ No newline at end of file
+}
index a185ed3..d761fa0 100644 (file)
@@ -207,7 +207,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipie
         foreach(const SendCoinsRecipient &rcp, recipients)
         {
             CScript scriptPubKey;
-            scriptPubKey.SetDestination(CBitcoinAddress(rcp.address.toStdString()).Get());
+            scriptPubKey.SetAddress(CBitcoinAddress(rcp.address.toStdString()));
             vecSend.push_back(make_pair(scriptPubKey, rcp.amount));
         }
 
@@ -531,4 +531,4 @@ void WalletModel::clearOrphans()
 CWallet* WalletModel::getWallet()
 {
     return wallet;
-}
\ No newline at end of file
+}
index 1272156..c2a10f3 100644 (file)
@@ -296,23 +296,15 @@ Value createrawtransaction(const Array& params, bool fHelp)
 
         if (address.IsValid())
         {
+            scriptPubKey.SetAddress(address);
+
+            // Don't perform duplication checking for pubkey-pair addresses
             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 R, pubKeyVariant;
-                mpk.GetVariant(R, pubKeyVariant);
-                scriptPubKey.SetDestination(R, pubKeyVariant);
-            }
         }
         else
             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid output destination: ")+s.name_);
index a0e6afc..7ad807e 100644 (file)
@@ -329,20 +329,7 @@ Value sendtoaddress(const Array& params, bool fHelp)
 
     CBitcoinAddress address(strAddress);
     if (address.IsValid())
-    {
-        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);
-        }
-    }
+        scriptPubKey.SetAddress(address);
     else
         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid NovaCoin address");
 
@@ -721,20 +708,7 @@ Value sendfrom(const Array& params, bool fHelp)
 
     CBitcoinAddress address(strAddress);
     if (address.IsValid())
-    {
-        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);
-        }
-    }
+        scriptPubKey.SetAddress(address);
     else
         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid NovaCoin address");
 
@@ -800,12 +774,15 @@ Value sendmany(const Array& params, bool fHelp)
         if (!address.IsValid())
             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid NovaCoin address: ")+s.name_);
 
-        if (setAddress.count(address))
-            throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
-        setAddress.insert(address);
+        if (!address.IsPair())
+        {
+            if (setAddress.count(address))
+                throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
+            setAddress.insert(address);
+        }
 
         CScript scriptPubKey;
-        scriptPubKey.SetDestination(address.Get());
+        scriptPubKey.SetAddress(address);
         int64_t nAmount = AmountFromValue(s.value_);
 
         if (nAmount < nMinimumInputValue)
index 040c906..ceacdc3 100644 (file)
@@ -2136,13 +2136,25 @@ void CScript::SetDestination(const CTxDestination& dest)
     boost::apply_visitor(CScriptVisitor(this), dest);
 }
 
-void CScript::SetDestination(const CPubKey& R, CPubKey& pubKeyVariant)
+void CScript::SetAddress(const CBitcoinAddress& dest)
 {
     this->clear();
-    *this << pubKeyVariant << R << OP_DROP << OP_CHECKSIG;
+    if (dest.IsScript())
+        *this << OP_HASH160 << dest.GetData() << OP_EQUAL;
+    else if (dest.IsPubKey())
+        *this << OP_DUP << OP_HASH160 << dest.GetData() << OP_EQUALVERIFY << OP_CHECKSIG;
+    else if (dest.IsPair()) {
+        // Pubkey pair address, going to generate
+        //   new one-time public key.
+        CMalleablePubKey mpk;
+        if (!mpk.setvch(dest.GetData()))
+            return;
+        CPubKey R, pubKeyVariant;
+        mpk.GetVariant(R, pubKeyVariant);
+        *this << pubKeyVariant << R << OP_DROP << OP_CHECKSIG;
+    }
 }
 
-
 void CScript::SetMultisig(int nRequired, const std::vector<CKey>& keys)
 {
     this->clear();
index 00b0525..af523e6 100644 (file)
 
 #include "keystore.h"
 #include "bignum.h"
+#include "base58.h"
 
 typedef std::vector<uint8_t> valtype;
 
 class CTransaction;
+class CBitcoinAddress;
 
 static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes
 
@@ -583,7 +585,7 @@ public:
     bool HasCanonicalPushes() const;
 
     void SetDestination(const CTxDestination& address);
-    void SetDestination(const CPubKey& R, CPubKey& pubKeyVariant);
+    void SetAddress(const CBitcoinAddress& dest);
     void SetMultisig(int nRequired, const std::vector<CKey>& keys);