dash/src/compressor.cpp

193 lines
5.4 KiB
C++
Raw Normal View History

2014-08-20 18:33:30 +02:00
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
2014-08-20 18:33:30 +02:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
Backport 11651 (#3358) * scripted-diff: Replace #include "" with #include <> (ryanofsky) -BEGIN VERIFY SCRIPT- for f in \ src/*.cpp \ src/*.h \ src/bench/*.cpp \ src/bench/*.h \ src/compat/*.cpp \ src/compat/*.h \ src/consensus/*.cpp \ src/consensus/*.h \ src/crypto/*.cpp \ src/crypto/*.h \ src/crypto/ctaes/*.h \ src/policy/*.cpp \ src/policy/*.h \ src/primitives/*.cpp \ src/primitives/*.h \ src/qt/*.cpp \ src/qt/*.h \ src/qt/test/*.cpp \ src/qt/test/*.h \ src/rpc/*.cpp \ src/rpc/*.h \ src/script/*.cpp \ src/script/*.h \ src/support/*.cpp \ src/support/*.h \ src/support/allocators/*.h \ src/test/*.cpp \ src/test/*.h \ src/wallet/*.cpp \ src/wallet/*.h \ src/wallet/test/*.cpp \ src/wallet/test/*.h \ src/zmq/*.cpp \ src/zmq/*.h do base=${f%/*}/ relbase=${base#src/} sed -i "s:#include \"\(.*\)\"\(.*\):if test -e \$base'\\1'; then echo \"#include <\"\$relbase\"\\1>\\2\"; else echo \"#include <\\1>\\2\"; fi:e" $f done -END VERIFY SCRIPT- Signed-off-by: Pasta <pasta@dashboost.org> * scripted-diff: Replace #include "" with #include <> (Dash Specific) -BEGIN VERIFY SCRIPT- for f in \ src/bls/*.cpp \ src/bls/*.h \ src/evo/*.cpp \ src/evo/*.h \ src/governance/*.cpp \ src/governance/*.h \ src/llmq/*.cpp \ src/llmq/*.h \ src/masternode/*.cpp \ src/masternode/*.h \ src/privatesend/*.cpp \ src/privatesend/*.h do base=${f%/*}/ relbase=${base#src/} sed -i "s:#include \"\(.*\)\"\(.*\):if test -e \$base'\\1'; then echo \"#include <\"\$relbase\"\\1>\\2\"; else echo \"#include <\\1>\\2\"; fi:e" $f done -END VERIFY SCRIPT- Signed-off-by: Pasta <pasta@dashboost.org> * build: Remove -I for everything but project root Remove -I from build system for everything but the project root, and built-in dependencies. Signed-off-by: Pasta <pasta@dashboost.org> # Conflicts: # src/Makefile.test.include * qt: refactor: Use absolute include paths in .ui files * qt: refactor: Changes to make include paths absolute This makes all include paths in the GUI absolute. Many changes are involved as every single source file in src/qt/ assumes to be able to use relative includes. Signed-off-by: Pasta <pasta@dashboost.org> # Conflicts: # src/qt/dash.cpp # src/qt/optionsmodel.cpp # src/qt/test/rpcnestedtests.cpp * test: refactor: Use absolute include paths for test data files * Recommend #include<> syntax in developer notes * refactor: Include obj/build.h instead of build.h * END BACKPORT #11651 Remove trailing whitespace causing travis failure * fix backport 11651 Signed-off-by: Pasta <pasta@dashboost.org> * More of 11651 * fix blockchain.cpp Signed-off-by: pasta <pasta@dashboost.org> * Add missing "qt/" in includes * Add missing "test/" in includes * Fix trailing whitespaces Co-authored-by: Wladimir J. van der Laan <laanwj@gmail.com> Co-authored-by: Russell Yanofsky <russ@yanofsky.org> Co-authored-by: MeshCollider <dobsonsa68@gmail.com> Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
2020-03-19 23:46:56 +01:00
#include <compressor.h>
Backport 11651 (#3358) * scripted-diff: Replace #include "" with #include <> (ryanofsky) -BEGIN VERIFY SCRIPT- for f in \ src/*.cpp \ src/*.h \ src/bench/*.cpp \ src/bench/*.h \ src/compat/*.cpp \ src/compat/*.h \ src/consensus/*.cpp \ src/consensus/*.h \ src/crypto/*.cpp \ src/crypto/*.h \ src/crypto/ctaes/*.h \ src/policy/*.cpp \ src/policy/*.h \ src/primitives/*.cpp \ src/primitives/*.h \ src/qt/*.cpp \ src/qt/*.h \ src/qt/test/*.cpp \ src/qt/test/*.h \ src/rpc/*.cpp \ src/rpc/*.h \ src/script/*.cpp \ src/script/*.h \ src/support/*.cpp \ src/support/*.h \ src/support/allocators/*.h \ src/test/*.cpp \ src/test/*.h \ src/wallet/*.cpp \ src/wallet/*.h \ src/wallet/test/*.cpp \ src/wallet/test/*.h \ src/zmq/*.cpp \ src/zmq/*.h do base=${f%/*}/ relbase=${base#src/} sed -i "s:#include \"\(.*\)\"\(.*\):if test -e \$base'\\1'; then echo \"#include <\"\$relbase\"\\1>\\2\"; else echo \"#include <\\1>\\2\"; fi:e" $f done -END VERIFY SCRIPT- Signed-off-by: Pasta <pasta@dashboost.org> * scripted-diff: Replace #include "" with #include <> (Dash Specific) -BEGIN VERIFY SCRIPT- for f in \ src/bls/*.cpp \ src/bls/*.h \ src/evo/*.cpp \ src/evo/*.h \ src/governance/*.cpp \ src/governance/*.h \ src/llmq/*.cpp \ src/llmq/*.h \ src/masternode/*.cpp \ src/masternode/*.h \ src/privatesend/*.cpp \ src/privatesend/*.h do base=${f%/*}/ relbase=${base#src/} sed -i "s:#include \"\(.*\)\"\(.*\):if test -e \$base'\\1'; then echo \"#include <\"\$relbase\"\\1>\\2\"; else echo \"#include <\\1>\\2\"; fi:e" $f done -END VERIFY SCRIPT- Signed-off-by: Pasta <pasta@dashboost.org> * build: Remove -I for everything but project root Remove -I from build system for everything but the project root, and built-in dependencies. Signed-off-by: Pasta <pasta@dashboost.org> # Conflicts: # src/Makefile.test.include * qt: refactor: Use absolute include paths in .ui files * qt: refactor: Changes to make include paths absolute This makes all include paths in the GUI absolute. Many changes are involved as every single source file in src/qt/ assumes to be able to use relative includes. Signed-off-by: Pasta <pasta@dashboost.org> # Conflicts: # src/qt/dash.cpp # src/qt/optionsmodel.cpp # src/qt/test/rpcnestedtests.cpp * test: refactor: Use absolute include paths for test data files * Recommend #include<> syntax in developer notes * refactor: Include obj/build.h instead of build.h * END BACKPORT #11651 Remove trailing whitespace causing travis failure * fix backport 11651 Signed-off-by: Pasta <pasta@dashboost.org> * More of 11651 * fix blockchain.cpp Signed-off-by: pasta <pasta@dashboost.org> * Add missing "qt/" in includes * Add missing "test/" in includes * Fix trailing whitespaces Co-authored-by: Wladimir J. van der Laan <laanwj@gmail.com> Co-authored-by: Russell Yanofsky <russ@yanofsky.org> Co-authored-by: MeshCollider <dobsonsa68@gmail.com> Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
2020-03-19 23:46:56 +01:00
#include <pubkey.h>
#include <script/standard.h>
2014-08-20 18:33:30 +02:00
/*
* 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)
2014-08-20 18:33:30 +02:00
{
if (script.size() == 25 && script[0] == OP_DUP && script[1] == OP_HASH160
&& script[2] == 20 && script[23] == OP_EQUALVERIFY
&& script[24] == OP_CHECKSIG) {
memcpy(&hash, &script[3], 20);
return true;
}
return false;
}
static bool IsToScriptID(const CScript& script, CScriptID &hash)
2014-08-20 18:33:30 +02:00
{
if (script.size() == 23 && script[0] == OP_HASH160 && script[1] == 20
&& script[22] == OP_EQUAL) {
memcpy(&hash, &script[2], 20);
return true;
}
return false;
}
static bool IsToPubKey(const CScript& script, CPubKey &pubkey)
2014-08-20 18:33:30 +02:00
{
if (script.size() == 35 && script[0] == 33 && script[34] == OP_CHECKSIG
&& (script[1] == 0x02 || script[1] == 0x03)) {
pubkey.Set(&script[1], &script[34]);
return true;
}
if (script.size() == 67 && script[0] == 65 && script[66] == OP_CHECKSIG
&& script[1] == 0x04) {
pubkey.Set(&script[1], &script[66]);
return pubkey.IsFullyValid(); // if not fully valid, a case that would not be compressible
}
return false;
}
bool CompressScript(const CScript& script, std::vector<unsigned char> &out)
2014-08-20 18:33:30 +02:00
{
CKeyID keyID;
if (IsToKeyID(script, keyID)) {
2014-08-20 18:33:30 +02:00
out.resize(21);
out[0] = 0x00;
memcpy(&out[1], &keyID, 20);
return true;
}
CScriptID scriptID;
if (IsToScriptID(script, scriptID)) {
2014-08-20 18:33:30 +02:00
out.resize(21);
out[0] = 0x01;
memcpy(&out[1], &scriptID, 20);
return true;
}
CPubKey pubkey;
if (IsToPubKey(script, pubkey)) {
2014-08-20 18:33:30 +02:00
out.resize(33);
memcpy(&out[1], &pubkey[1], 32);
if (pubkey[0] == 0x02 || pubkey[0] == 0x03) {
out[0] = pubkey[0];
return true;
} else if (pubkey[0] == 0x04) {
out[0] = 0x04 | (pubkey[64] & 0x01);
return true;
}
}
return false;
}
unsigned int GetSpecialScriptSize(unsigned int nSize)
2014-08-20 18:33:30 +02:00
{
if (nSize == 0 || nSize == 1)
return 20;
if (nSize == 2 || nSize == 3 || nSize == 4 || nSize == 5)
return 32;
return 0;
}
bool DecompressScript(CScript& script, unsigned int nSize, const std::vector<unsigned char> &in)
2014-08-20 18:33:30 +02:00
{
switch(nSize) {
case 0x00:
script.resize(25);
script[0] = OP_DUP;
script[1] = OP_HASH160;
script[2] = 20;
memcpy(&script[3], in.data(), 20);
2014-08-20 18:33:30 +02:00
script[23] = OP_EQUALVERIFY;
script[24] = OP_CHECKSIG;
return true;
case 0x01:
script.resize(23);
script[0] = OP_HASH160;
script[1] = 20;
memcpy(&script[2], in.data(), 20);
2014-08-20 18:33:30 +02:00
script[22] = OP_EQUAL;
return true;
case 0x02:
case 0x03:
script.resize(35);
script[0] = 33;
script[1] = nSize;
memcpy(&script[2], in.data(), 32);
2014-08-20 18:33:30 +02:00
script[34] = OP_CHECKSIG;
return true;
case 0x04:
case 0x05:
unsigned char vch[33] = {};
vch[0] = nSize - 2;
memcpy(&vch[1], in.data(), 32);
2014-08-20 18:33:30 +02:00
CPubKey pubkey(&vch[0], &vch[33]);
if (!pubkey.Decompress())
return false;
assert(pubkey.size() == 65);
script.resize(67);
script[0] = 65;
memcpy(&script[1], pubkey.begin(), 65);
script[66] = OP_CHECKSIG;
return true;
}
return false;
}
// Amount compression:
// * If the amount is 0, output 0
// * first, divide the amount (in base units) by the largest power of 10 possible; call the exponent e (e is max 9)
// * if e<9, the last digit of the resulting number cannot be 0; store it as d, and drop it (divide by 10)
// * call the result n
// * output 1 + 10*(9*n + d - 1) + e
// * 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 CompressAmount(uint64_t n)
{
if (n == 0)
return 0;
int e = 0;
while (((n % 10) == 0) && e < 9) {
n /= 10;
e++;
}
if (e < 9) {
int d = (n % 10);
assert(d >= 1 && d <= 9);
n /= 10;
return 1 + (n*9 + d - 1)*10 + e;
} else {
return 1 + (n - 1)*10 + 9;
}
}
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)
return 0;
x--;
// x = 10*(9*n + d - 1) + e
int e = x % 10;
x /= 10;
uint64_t n = 0;
if (e < 9) {
// x = 9*n + d - 1
int d = (x % 9) + 1;
x /= 9;
// x = n
n = x*10 + d;
} else {
n = x+1;
}
while (e) {
n *= 10;
e--;
}
return n;
}