mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 04:22:55 +01:00
Merge #12752: Move compressor utility functions out of class
76a9aacd3f
This commit is contained in:
parent
0802bdfa37
commit
2f542a93a1
@ -9,7 +9,15 @@
|
|||||||
#include <pubkey.h>
|
#include <pubkey.h>
|
||||||
#include <script/standard.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
|
if (script.size() == 25 && script[0] == OP_DUP && script[1] == OP_HASH160
|
||||||
&& script[2] == 20 && script[23] == OP_EQUALVERIFY
|
&& script[2] == 20 && script[23] == OP_EQUALVERIFY
|
||||||
@ -20,7 +28,7 @@ bool CScriptCompressor::IsToKeyID(CKeyID &hash) const
|
|||||||
return false;
|
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
|
if (script.size() == 23 && script[0] == OP_HASH160 && script[1] == 20
|
||||||
&& script[22] == OP_EQUAL) {
|
&& script[22] == OP_EQUAL) {
|
||||||
@ -30,7 +38,7 @@ bool CScriptCompressor::IsToScriptID(CScriptID &hash) const
|
|||||||
return false;
|
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
|
if (script.size() == 35 && script[0] == 33 && script[34] == OP_CHECKSIG
|
||||||
&& (script[1] == 0x02 || script[1] == 0x03)) {
|
&& (script[1] == 0x02 || script[1] == 0x03)) {
|
||||||
@ -45,24 +53,24 @@ bool CScriptCompressor::IsToPubKey(CPubKey &pubkey) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CScriptCompressor::Compress(std::vector<unsigned char> &out) const
|
bool CompressScript(const CScript& script, std::vector<unsigned char> &out)
|
||||||
{
|
{
|
||||||
CKeyID keyID;
|
CKeyID keyID;
|
||||||
if (IsToKeyID(keyID)) {
|
if (IsToKeyID(script, keyID)) {
|
||||||
out.resize(21);
|
out.resize(21);
|
||||||
out[0] = 0x00;
|
out[0] = 0x00;
|
||||||
memcpy(&out[1], &keyID, 20);
|
memcpy(&out[1], &keyID, 20);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
CScriptID scriptID;
|
CScriptID scriptID;
|
||||||
if (IsToScriptID(scriptID)) {
|
if (IsToScriptID(script, scriptID)) {
|
||||||
out.resize(21);
|
out.resize(21);
|
||||||
out[0] = 0x01;
|
out[0] = 0x01;
|
||||||
memcpy(&out[1], &scriptID, 20);
|
memcpy(&out[1], &scriptID, 20);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
CPubKey pubkey;
|
CPubKey pubkey;
|
||||||
if (IsToPubKey(pubkey)) {
|
if (IsToPubKey(script, pubkey)) {
|
||||||
out.resize(33);
|
out.resize(33);
|
||||||
memcpy(&out[1], &pubkey[1], 32);
|
memcpy(&out[1], &pubkey[1], 32);
|
||||||
if (pubkey[0] == 0x02 || pubkey[0] == 0x03) {
|
if (pubkey[0] == 0x02 || pubkey[0] == 0x03) {
|
||||||
@ -76,7 +84,7 @@ bool CScriptCompressor::Compress(std::vector<unsigned char> &out) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int CScriptCompressor::GetSpecialSize(unsigned int nSize) const
|
unsigned int GetSpecialScriptSize(unsigned int nSize)
|
||||||
{
|
{
|
||||||
if (nSize == 0 || nSize == 1)
|
if (nSize == 0 || nSize == 1)
|
||||||
return 20;
|
return 20;
|
||||||
@ -85,7 +93,7 @@ unsigned int CScriptCompressor::GetSpecialSize(unsigned int nSize) const
|
|||||||
return 0;
|
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) {
|
switch(nSize) {
|
||||||
case 0x00:
|
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
|
// * 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])
|
// (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)
|
if (n == 0)
|
||||||
return 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
|
// x = 0 OR x = 1+10*(9*n + d - 1) + e OR x = 1+10*(n - 1) + 9
|
||||||
if (x == 0)
|
if (x == 0)
|
||||||
|
@ -15,6 +15,13 @@ class CKeyID;
|
|||||||
class CPubKey;
|
class CPubKey;
|
||||||
class CScriptID;
|
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.
|
/** Compact serializer for scripts.
|
||||||
*
|
*
|
||||||
* It detects common cases and encodes them much more efficiently.
|
* It detects common cases and encodes them much more efficiently.
|
||||||
@ -38,28 +45,13 @@ private:
|
|||||||
static const unsigned int nSpecialScripts = 6;
|
static const unsigned int nSpecialScripts = 6;
|
||||||
|
|
||||||
CScript &script;
|
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:
|
public:
|
||||||
explicit CScriptCompressor(CScript &scriptIn) : script(scriptIn) { }
|
explicit CScriptCompressor(CScript &scriptIn) : script(scriptIn) { }
|
||||||
|
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
void Serialize(Stream &s) const {
|
void Serialize(Stream &s) const {
|
||||||
std::vector<unsigned char> compr;
|
std::vector<unsigned char> compr;
|
||||||
if (Compress(compr)) {
|
if (CompressScript(script, compr)) {
|
||||||
s << MakeSpan(compr);
|
s << MakeSpan(compr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -73,9 +65,9 @@ public:
|
|||||||
unsigned int nSize = 0;
|
unsigned int nSize = 0;
|
||||||
s >> VARINT(nSize);
|
s >> VARINT(nSize);
|
||||||
if (nSize < nSpecialScripts) {
|
if (nSize < nSpecialScripts) {
|
||||||
std::vector<unsigned char> vch(GetSpecialSize(nSize), 0x00);
|
std::vector<unsigned char> vch(GetSpecialScriptSize(nSize), 0x00);
|
||||||
s >> MakeSpan(vch);
|
s >> MakeSpan(vch);
|
||||||
Decompress(nSize, vch);
|
DecompressScript(script, nSize, vch);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nSize -= nSpecialScripts;
|
nSize -= nSpecialScripts;
|
||||||
@ -97,9 +89,6 @@ private:
|
|||||||
CTxOut &txout;
|
CTxOut &txout;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static uint64_t CompressAmount(uint64_t nAmount);
|
|
||||||
static uint64_t DecompressAmount(uint64_t nAmount);
|
|
||||||
|
|
||||||
explicit CTxOutCompressor(CTxOut &txoutIn) : txout(txoutIn) { }
|
explicit CTxOutCompressor(CTxOut &txoutIn) : txout(txoutIn) { }
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
ADD_SERIALIZE_METHODS;
|
||||||
|
@ -25,16 +25,16 @@
|
|||||||
BOOST_FIXTURE_TEST_SUITE(compress_tests, BasicTestingSetup)
|
BOOST_FIXTURE_TEST_SUITE(compress_tests, BasicTestingSetup)
|
||||||
|
|
||||||
bool static TestEncode(uint64_t in) {
|
bool static TestEncode(uint64_t in) {
|
||||||
return in == CTxOutCompressor::DecompressAmount(CTxOutCompressor::CompressAmount(in));
|
return in == DecompressAmount(CompressAmount(in));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool static TestDecode(uint64_t 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) {
|
bool static TestPair(uint64_t dec, uint64_t enc) {
|
||||||
return CTxOutCompressor::CompressAmount(dec) == enc &&
|
return CompressAmount(dec) == enc &&
|
||||||
CTxOutCompressor::DecompressAmount(enc) == dec;
|
DecompressAmount(enc) == dec;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(compress_amounts)
|
BOOST_AUTO_TEST_CASE(compress_amounts)
|
||||||
|
Loading…
Reference in New Issue
Block a user