Files
hush3/src/compressor.h
Duke Leto be16f80abc Hush Full Node is now GPLv3
Any projects which want to use Hush code from now on will need to be licensed as
GPLv3 or we will send the lawyers: https://www.softwarefreedom.org/

Notably, Komodo (KMD) is licensed as GPLv2 and is no longer compatible to receive
code changes, without causing legal issues. MIT projects, such as Zcash, also cannot pull
in changes from the Hush Full Node without permission from The Hush Developers,
which may in some circumstances grant an MIT license on a case-by-case basis.
2020-10-21 07:28:10 -04:00

137 lines
4.9 KiB
C++

// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the GPLv3 software license, see the accompanying
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
/******************************************************************************
* Copyright © 2014-2019 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#ifndef BITCOIN_COMPRESSOR_H
#define BITCOIN_COMPRESSOR_H
#include "primitives/transaction.h"
#include "script/script.h"
#include "serialize.h"
class CKeyID;
class CPubKey;
class CScriptID;
/** Compact serializer for scripts.
*
* It detects common cases and encodes them much more efficiently.
* 3 special cases are defined:
* * Pay to pubkey hash (encoded as 21 bytes)
* * Pay to script hash (encoded as 21 bytes)
* * Pay to pubkey starting with 0x02, 0x03 or 0x04 (encoded as 33 bytes)
*
* Other scripts up to 121 bytes require 1 byte + script length. Above
* that, scripts up to 16505 bytes require 2 bytes + script length.
*/
class CScriptCompressor
{
private:
/**
* make this static for now (there are only 6 special scripts defined)
* this can potentially be extended together with a new nVersion for
* transactions, in which case this value becomes dependent on nVersion
* and nHeight of the enclosing transaction.
*/
static const unsigned int nSpecialScripts = 6;
CScript &script;
protected:
/**
* These check for scripts for which a special case with a shorter encoding is defined.
* They are implemented separately from the CScript test, as these test for exact byte
* sequence correspondences, and are more strict. For example, IsToPubKey also verifies
* whether the public key is valid (as invalid ones cannot be represented in compressed
* form).
*/
bool IsToKeyID(CKeyID &hash) const;
bool IsToScriptID(CScriptID &hash) const;
bool IsToPubKey(CPubKey &pubkey) const;
bool Compress(std::vector<unsigned char> &out) const;
unsigned int GetSpecialSize(unsigned int nSize) const;
bool Decompress(unsigned int nSize, const std::vector<unsigned char> &out);
public:
CScriptCompressor(CScript &scriptIn) : script(scriptIn) { }
template<typename Stream>
void Serialize(Stream &s) const {
std::vector<unsigned char> compr;
if (Compress(compr)) {
s << CFlatData(compr);
return;
}
unsigned int nSize = script.size() + nSpecialScripts;
s << VARINT(nSize);
s << CFlatData(script);
}
template<typename Stream>
void Unserialize(Stream &s) {
unsigned int nSize = 0;
s >> VARINT(nSize);
if (nSize < nSpecialScripts) {
std::vector<unsigned char> vch(GetSpecialSize(nSize), 0x00);
s >> REF(CFlatData(vch));
Decompress(nSize, vch);
return;
}
nSize -= nSpecialScripts;
if (nSize > MAX_SCRIPT_SIZE) {
// Overly long script, replace with a short invalid one
script << OP_RETURN;
s.ignore(nSize);
} else {
script.resize(nSize);
s >> REF(CFlatData(script));
}
}
};
/** wrapper for CTxOut that provides a more compact serialization */
class CTxOutCompressor
{
private:
CTxOut &txout;
public:
static uint64_t CompressAmount(uint64_t nAmount);
static uint64_t DecompressAmount(uint64_t nAmount);
CTxOutCompressor(CTxOut &txoutIn) : txout(txoutIn) { }
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
if (!ser_action.ForRead()) {
uint64_t nVal = CompressAmount(txout.nValue);
READWRITE(VARINT(nVal));
} else {
uint64_t nVal = 0;
READWRITE(VARINT(nVal));
txout.nValue = DecompressAmount(nVal);
}
CScriptCompressor cscript(REF(txout.scriptPubKey));
READWRITE(cscript);
}
};
#endif // BITCOIN_COMPRESSOR_H