LCOV - code coverage report
Current view: top level - src - compressor.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 28 31 90.3 %
Date: 2015-10-12 22:39:14 Functions: 12 19 63.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2014 The Bitcoin Core developers
       3             : // Distributed under the MIT software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #ifndef BITCOIN_COMPRESSOR_H
       7             : #define BITCOIN_COMPRESSOR_H
       8             : 
       9             : #include "primitives/transaction.h"
      10             : #include "script/script.h"
      11             : #include "serialize.h"
      12             : 
      13             : class CKeyID;
      14             : class CPubKey;
      15             : class CScriptID;
      16             : 
      17             : /** Compact serializer for scripts.
      18             :  *
      19             :  *  It detects common cases and encodes them much more efficiently.
      20             :  *  3 special cases are defined:
      21             :  *  * Pay to pubkey hash (encoded as 21 bytes)
      22             :  *  * Pay to script hash (encoded as 21 bytes)
      23             :  *  * Pay to pubkey starting with 0x02, 0x03 or 0x04 (encoded as 33 bytes)
      24             :  *
      25             :  *  Other scripts up to 121 bytes require 1 byte + script length. Above
      26             :  *  that, scripts up to 16505 bytes require 2 bytes + script length.
      27             :  */
      28             : class CScriptCompressor
      29             : {
      30             : private:
      31             :     /**
      32             :      * make this static for now (there are only 6 special scripts defined)
      33             :      * this can potentially be extended together with a new nVersion for
      34             :      * transactions, in which case this value becomes dependent on nVersion
      35             :      * and nHeight of the enclosing transaction.
      36             :      */
      37             :     static const unsigned int nSpecialScripts = 6;
      38             : 
      39             :     CScript &script;
      40             : protected:
      41             :     /**
      42             :      * These check for scripts for which a special case with a shorter encoding is defined.
      43             :      * They are implemented separately from the CScript test, as these test for exact byte
      44             :      * sequence correspondences, and are more strict. For example, IsToPubKey also verifies
      45             :      * whether the public key is valid (as invalid ones cannot be represented in compressed
      46             :      * form).
      47             :      */
      48             :     bool IsToKeyID(CKeyID &hash) const;
      49             :     bool IsToScriptID(CScriptID &hash) const;
      50             :     bool IsToPubKey(CPubKey &pubkey) const;
      51             : 
      52             :     bool Compress(std::vector<unsigned char> &out) const;
      53             :     unsigned int GetSpecialSize(unsigned int nSize) const;
      54             :     bool Decompress(unsigned int nSize, const std::vector<unsigned char> &out);
      55             : public:
      56       28839 :     CScriptCompressor(CScript &scriptIn) : script(scriptIn) { }
      57             : 
      58             :     unsigned int GetSerializeSize(int nType, int nVersion) const {
      59             :         std::vector<unsigned char> compr;
      60             :         if (Compress(compr))
      61             :             return compr.size();
      62             :         unsigned int nSize = script.size() + nSpecialScripts;
      63             :         return script.size() + VARINT(nSize).GetSerializeSize(nType, nVersion);
      64             :     }
      65             : 
      66             :     template<typename Stream>
      67       16498 :     void Serialize(Stream &s, int nType, int nVersion) const {
      68             :         std::vector<unsigned char> compr;
      69       16498 :         if (Compress(compr)) {
      70       16418 :             s << CFlatData(compr);
      71       16498 :             return;
      72             :         }
      73         160 :         unsigned int nSize = script.size() + nSpecialScripts;
      74          80 :         s << VARINT(nSize);
      75         160 :         s << CFlatData(script);
      76             :     }
      77             : 
      78             :     template<typename Stream>
      79       12341 :     void Unserialize(Stream &s, int nType, int nVersion) {
      80       12341 :         unsigned int nSize = 0;
      81       12341 :         s >> VARINT(nSize);
      82       12341 :         if (nSize < nSpecialScripts) {
      83       24682 :             std::vector<unsigned char> vch(GetSpecialSize(nSize), 0x00);
      84       12341 :             s >> REF(CFlatData(vch));
      85       12341 :             Decompress(nSize, vch);
      86       12341 :             return;
      87             :         }
      88           0 :         nSize -= nSpecialScripts;
      89           0 :         script.resize(nSize);
      90           0 :         s >> REF(CFlatData(script));
      91             :     }
      92             : };
      93             : 
      94             : /** wrapper for CTxOut that provides a more compact serialization */
      95             : class CTxOutCompressor
      96             : {
      97             : private:
      98             :     CTxOut &txout;
      99             : 
     100             : public:
     101             :     static uint64_t CompressAmount(uint64_t nAmount);
     102             :     static uint64_t DecompressAmount(uint64_t nAmount);
     103             : 
     104       28839 :     CTxOutCompressor(CTxOut &txoutIn) : txout(txoutIn) { }
     105             : 
     106       28839 :     ADD_SERIALIZE_METHODS;
     107             : 
     108             :     template <typename Stream, typename Operation>
     109       28839 :     inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
     110       28839 :         if (!ser_action.ForRead()) {
     111       16498 :             uint64_t nVal = CompressAmount(txout.nValue);
     112       16498 :             READWRITE(VARINT(nVal));
     113             :         } else {
     114       12341 :             uint64_t nVal = 0;
     115       12341 :             READWRITE(VARINT(nVal));
     116       12341 :             txout.nValue = DecompressAmount(nVal);
     117             :         }
     118       28839 :         CScriptCompressor cscript(REF(txout.scriptPubKey));
     119       28839 :         READWRITE(cscript);
     120       28839 :     }
     121             : };
     122             : 
     123             : #endif // BITCOIN_COMPRESSOR_H

Generated by: LCOV version 1.11