mirror of
https://github.com/bitcoin/bitcoin.git
synced 2024-11-20 10:38:42 +01:00
Move compressor utility functions out of class
This commit is contained in:
parent
2405ce1df0
commit
76a9aacd3f
@ -9,7 +9,15 @@
|
||||
#include <pubkey.h>
|
||||
#include <script/standard.h>
|
||||
|
||||
bool CScriptCompressor::IsToKeyID(CKeyID &hash) const
|
||||
/*
|
||||
* 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).
|
||||
*/
|
||||
|
||||
static bool IsToKeyID(const CScript& script, CKeyID &hash)
|
||||
{
|
||||
if (script.size() == 25 && script[0] == OP_DUP && script[1] == OP_HASH160
|
||||
&& script[2] == 20 && script[23] == OP_EQUALVERIFY
|
||||
@ -20,7 +28,7 @@ bool CScriptCompressor::IsToKeyID(CKeyID &hash) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CScriptCompressor::IsToScriptID(CScriptID &hash) const
|
||||
static bool IsToScriptID(const CScript& script, CScriptID &hash)
|
||||
{
|
||||
if (script.size() == 23 && script[0] == OP_HASH160 && script[1] == 20
|
||||
&& script[22] == OP_EQUAL) {
|
||||
@ -30,7 +38,7 @@ bool CScriptCompressor::IsToScriptID(CScriptID &hash) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CScriptCompressor::IsToPubKey(CPubKey &pubkey) const
|
||||
static bool IsToPubKey(const CScript& script, CPubKey &pubkey)
|
||||
{
|
||||
if (script.size() == 35 && script[0] == 33 && script[34] == OP_CHECKSIG
|
||||
&& (script[1] == 0x02 || script[1] == 0x03)) {
|
||||
@ -45,24 +53,24 @@ bool CScriptCompressor::IsToPubKey(CPubKey &pubkey) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CScriptCompressor::Compress(std::vector<unsigned char> &out) const
|
||||
bool CompressScript(const CScript& script, std::vector<unsigned char> &out)
|
||||
{
|
||||
CKeyID keyID;
|
||||
if (IsToKeyID(keyID)) {
|
||||
if (IsToKeyID(script, keyID)) {
|
||||
out.resize(21);
|
||||
out[0] = 0x00;
|
||||
memcpy(&out[1], &keyID, 20);
|
||||
return true;
|
||||
}
|
||||
CScriptID scriptID;
|
||||
if (IsToScriptID(scriptID)) {
|
||||
if (IsToScriptID(script, scriptID)) {
|
||||
out.resize(21);
|
||||
out[0] = 0x01;
|
||||
memcpy(&out[1], &scriptID, 20);
|
||||
return true;
|
||||
}
|
||||
CPubKey pubkey;
|
||||
if (IsToPubKey(pubkey)) {
|
||||
if (IsToPubKey(script, pubkey)) {
|
||||
out.resize(33);
|
||||
memcpy(&out[1], &pubkey[1], 32);
|
||||
if (pubkey[0] == 0x02 || pubkey[0] == 0x03) {
|
||||
@ -76,7 +84,7 @@ bool CScriptCompressor::Compress(std::vector<unsigned char> &out) const
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int CScriptCompressor::GetSpecialSize(unsigned int nSize) const
|
||||
unsigned int GetSpecialScriptSize(unsigned int nSize)
|
||||
{
|
||||
if (nSize == 0 || nSize == 1)
|
||||
return 20;
|
||||
@ -85,7 +93,7 @@ unsigned int CScriptCompressor::GetSpecialSize(unsigned int nSize) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CScriptCompressor::Decompress(unsigned int nSize, const std::vector<unsigned char> &in)
|
||||
bool DecompressScript(CScript& script, unsigned int nSize, const std::vector<unsigned char> &in)
|
||||
{
|
||||
switch(nSize) {
|
||||
case 0x00:
|
||||
@ -139,7 +147,7 @@ bool CScriptCompressor::Decompress(unsigned int nSize, const std::vector<unsigne
|
||||
// * if e==9, we only know the resulting number is not zero, so output 1 + 10*(n - 1) + 9
|
||||
// (this is decodable, as d is in [1-9] and e is in [0-9])
|
||||
|
||||
uint64_t CTxOutCompressor::CompressAmount(uint64_t n)
|
||||
uint64_t CompressAmount(uint64_t n)
|
||||
{
|
||||
if (n == 0)
|
||||
return 0;
|
||||
@ -158,7 +166,7 @@ uint64_t CTxOutCompressor::CompressAmount(uint64_t n)
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t CTxOutCompressor::DecompressAmount(uint64_t x)
|
||||
uint64_t DecompressAmount(uint64_t x)
|
||||
{
|
||||
// x = 0 OR x = 1+10*(9*n + d - 1) + e OR x = 1+10*(n - 1) + 9
|
||||
if (x == 0)
|
||||
|
@ -14,6 +14,13 @@ class CKeyID;
|
||||
class CPubKey;
|
||||
class CScriptID;
|
||||
|
||||
bool CompressScript(const CScript& script, std::vector<unsigned char> &out);
|
||||
unsigned int GetSpecialScriptSize(unsigned int nSize);
|
||||
bool DecompressScript(CScript& script, unsigned int nSize, const std::vector<unsigned char> &out);
|
||||
|
||||
uint64_t CompressAmount(uint64_t nAmount);
|
||||
uint64_t DecompressAmount(uint64_t nAmount);
|
||||
|
||||
/** Compact serializer for scripts.
|
||||
*
|
||||
* It detects common cases and encodes them much more efficiently.
|
||||
@ -37,28 +44,13 @@ private:
|
||||
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:
|
||||
explicit CScriptCompressor(CScript &scriptIn) : script(scriptIn) { }
|
||||
|
||||
template<typename Stream>
|
||||
void Serialize(Stream &s) const {
|
||||
std::vector<unsigned char> compr;
|
||||
if (Compress(compr)) {
|
||||
if (CompressScript(script, compr)) {
|
||||
s << CFlatData(compr);
|
||||
return;
|
||||
}
|
||||
@ -72,9 +64,9 @@ public:
|
||||
unsigned int nSize = 0;
|
||||
s >> VARINT(nSize);
|
||||
if (nSize < nSpecialScripts) {
|
||||
std::vector<unsigned char> vch(GetSpecialSize(nSize), 0x00);
|
||||
std::vector<unsigned char> vch(GetSpecialScriptSize(nSize), 0x00);
|
||||
s >> CFlatData(vch);
|
||||
Decompress(nSize, vch);
|
||||
DecompressScript(script, nSize, vch);
|
||||
return;
|
||||
}
|
||||
nSize -= nSpecialScripts;
|
||||
@ -96,9 +88,6 @@ private:
|
||||
CTxOut &txout;
|
||||
|
||||
public:
|
||||
static uint64_t CompressAmount(uint64_t nAmount);
|
||||
static uint64_t DecompressAmount(uint64_t nAmount);
|
||||
|
||||
explicit CTxOutCompressor(CTxOut &txoutIn) : txout(txoutIn) { }
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
@ -25,16 +25,16 @@
|
||||
BOOST_FIXTURE_TEST_SUITE(compress_tests, BasicTestingSetup)
|
||||
|
||||
bool static TestEncode(uint64_t in) {
|
||||
return in == CTxOutCompressor::DecompressAmount(CTxOutCompressor::CompressAmount(in));
|
||||
return in == DecompressAmount(CompressAmount(in));
|
||||
}
|
||||
|
||||
bool static TestDecode(uint64_t in) {
|
||||
return in == CTxOutCompressor::CompressAmount(CTxOutCompressor::DecompressAmount(in));
|
||||
return in == CompressAmount(DecompressAmount(in));
|
||||
}
|
||||
|
||||
bool static TestPair(uint64_t dec, uint64_t enc) {
|
||||
return CTxOutCompressor::CompressAmount(dec) == enc &&
|
||||
CTxOutCompressor::DecompressAmount(enc) == dec;
|
||||
return CompressAmount(dec) == enc &&
|
||||
DecompressAmount(enc) == dec;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(compress_amounts)
|
||||
|
Loading…
Reference in New Issue
Block a user