PRCYCoin  2.0.0.7rc1
P2P Digital Currency
compressor.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin 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 #include "compressor.h"
7 
8 #include "hash.h"
9 #include "pubkey.h"
10 #include "script/standard.h"
11 
13 {
14  if (script.size() == 25 && script[0] == OP_DUP && script[1] == OP_HASH160 && script[2] == 20 && script[23] == OP_EQUALVERIFY && script[24] == OP_CHECKSIG) {
15  memcpy(&hash, &script[3], 20);
16  return true;
17  }
18  return false;
19 }
20 
22 {
23  if (script.size() == 23 && script[0] == OP_HASH160 && script[1] == 20 && script[22] == OP_EQUAL) {
24  memcpy(&hash, &script[2], 20);
25  return true;
26  }
27  return false;
28 }
29 
31 {
32  if (script.size() == 35 && script[0] == 33 && script[34] == OP_CHECKSIG && (script[1] == 0x02 || script[1] == 0x03)) {
33  pubkey.Set(&script[1], &script[34]);
34  return true;
35  }
36  if (script.size() == 67 && script[0] == 65 && script[66] == OP_CHECKSIG && script[1] == 0x04) {
37  pubkey.Set(&script[1], &script[66]);
38  return pubkey.IsFullyValid(); // if not fully valid, a case that would not be compressible
39  }
40  return false;
41 }
42 
43 bool CScriptCompressor::Compress(std::vector<unsigned char>& out) const
44 {
45  CKeyID keyID;
46  if (IsToKeyID(keyID)) {
47  out.resize(21);
48  out[0] = 0x00;
49  memcpy(&out[1], &keyID, 20);
50  return true;
51  }
52  CScriptID scriptID;
53  if (IsToScriptID(scriptID)) {
54  out.resize(21);
55  out[0] = 0x01;
56  memcpy(&out[1], &scriptID, 20);
57  return true;
58  }
59  CPubKey pubkey;
60  if (IsToPubKey(pubkey)) {
61  out.resize(33);
62  memcpy(&out[1], &pubkey[1], 32);
63  if (pubkey[0] == 0x02 || pubkey[0] == 0x03) {
64  out[0] = pubkey[0];
65  return true;
66  } else if (pubkey[0] == 0x04) {
67  out[0] = 0x04 | (pubkey[64] & 0x01);
68  return true;
69  }
70  }
71  return false;
72 }
73 
74 unsigned int CScriptCompressor::GetSpecialSize(unsigned int nSize) const
75 {
76  if (nSize == 0 || nSize == 1)
77  return 20;
78  if (nSize == 2 || nSize == 3 || nSize == 4 || nSize == 5)
79  return 32;
80  return 0;
81 }
82 
83 bool CScriptCompressor::Decompress(unsigned int nSize, const std::vector<unsigned char>& in)
84 {
85  switch (nSize) {
86  case 0x00:
87  script.resize(25);
88  script[0] = OP_DUP;
89  script[1] = OP_HASH160;
90  script[2] = 20;
91  memcpy(&script[3], &in[0], 20);
92  script[23] = OP_EQUALVERIFY;
93  script[24] = OP_CHECKSIG;
94  return true;
95  case 0x01:
96  script.resize(23);
97  script[0] = OP_HASH160;
98  script[1] = 20;
99  memcpy(&script[2], &in[0], 20);
100  script[22] = OP_EQUAL;
101  return true;
102  case 0x02:
103  case 0x03:
104  script.resize(35);
105  script[0] = 33;
106  script[1] = nSize;
107  memcpy(&script[2], &in[0], 32);
108  script[34] = OP_CHECKSIG;
109  return true;
110  case 0x04:
111  case 0x05:
112  unsigned char vch[33] = {};
113  vch[0] = nSize - 2;
114  memcpy(&vch[1], &in[0], 32);
115  CPubKey pubkey(&vch[0], &vch[33]);
116  if (!pubkey.Decompress())
117  return false;
118  assert(pubkey.size() == 65);
119  script.resize(67);
120  script[0] = 65;
121  memcpy(&script[1], pubkey.begin(), 65);
122  script[66] = OP_CHECKSIG;
123  return true;
124  }
125  return false;
126 }
127 
128 // Amount compression:
129 // * If the amount is 0, output 0
130 // * first, divide the amount (in base units) by the largest power of 10 possible; call the exponent e (e is max 9)
131 // * if e<9, the last digit of the resulting number cannot be 0; store it as d, and drop it (divide by 10)
132 // * call the result n
133 // * output 1 + 10*(9*n + d - 1) + e
134 // * if e==9, we only know the resulting number is not zero, so output 1 + 10*(n - 1) + 9
135 // (this is decodable, as d is in [1-9] and e is in [0-9])
136 
138 {
139  if (n == 0)
140  return 0;
141  int e = 0;
142  while (((n % 10) == 0) && e < 9) {
143  n /= 10;
144  e++;
145  }
146  if (e < 9) {
147  int d = (n % 10);
148  assert(d >= 1 && d <= 9);
149  n /= 10;
150  return 1 + (n * 9 + d - 1) * 10 + e;
151  } else {
152  return 1 + (n - 1) * 10 + 9;
153  }
154 }
155 
157 {
158  // x = 0 OR x = 1+10*(9*n + d - 1) + e OR x = 1+10*(n - 1) + 9
159  if (x == 0)
160  return 0;
161  x--;
162  // x = 10*(9*n + d - 1) + e
163  int e = x % 10;
164  x /= 10;
165  uint64_t n = 0;
166  if (e < 9) {
167  // x = 9*n + d - 1
168  int d = (x % 9) + 1;
169  x /= 9;
170  // x = n
171  n = x * 10 + d;
172  } else {
173  n = x + 1;
174  }
175  while (e) {
176  n *= 10;
177  e--;
178  }
179  return n;
180 }
CScriptCompressor::IsToKeyID
bool IsToKeyID(CKeyID &hash) const
These check for scripts for which a special case with a shorter encoding is defined.
Definition: compressor.cpp:12
CScriptCompressor::GetSpecialSize
unsigned int GetSpecialSize(unsigned int nSize) const
Definition: compressor.cpp:74
CScriptCompressor::IsToPubKey
bool IsToPubKey(CPubKey &pubkey) const
Definition: compressor.cpp:30
CPubKey::Set
void Set(const T pbegin, const T pend)
Initialize a public key using begin/end iterators to byte data.
Definition: pubkey.h:71
OP_HASH160
@ OP_HASH160
Definition: script.h:152
memcpy
void * memcpy(void *a, const void *b, size_t c)
Definition: glibc_compat.cpp:15
CPubKey::Decompress
bool Decompress()
Turn this public key into an uncompressed public key.
Definition: pubkey.cpp:69
CTxOutCompressor::CompressAmount
static uint64_t CompressAmount(uint64_t nAmount)
Definition: compressor.cpp:137
CKeyID
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:29
pubkey.h
compressor.h
CPubKey::begin
const unsigned char * begin() const
Definition: pubkey.h:95
CScriptCompressor::IsToScriptID
bool IsToScriptID(CScriptID &hash) const
Definition: compressor.cpp:21
OP_DUP
@ OP_DUP
Definition: script.h:90
standard.h
CPubKey::size
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Definition: pubkey.h:94
OP_CHECKSIG
@ OP_CHECKSIG
Definition: script.h:155
CScriptCompressor::Compress
bool Compress(std::vector< unsigned char > &out) const
Definition: compressor.cpp:43
prevector::resize
void resize(size_type new_size)
Definition: prevector.h:316
CPubKey
An encapsulated public key.
Definition: pubkey.h:37
CScriptCompressor::Decompress
bool Decompress(unsigned int nSize, const std::vector< unsigned char > &out)
Definition: compressor.cpp:83
prevector::size
size_type size() const
Definition: prevector.h:282
OP_EQUAL
@ OP_EQUAL
Definition: script.h:111
CPubKey::IsFullyValid
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid())
Definition: pubkey.cpp:54
hash.h
CScriptCompressor::script
CScript & script
Definition: compressor.h:39
CScriptID
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:20
OP_EQUALVERIFY
@ OP_EQUALVERIFY
Definition: script.h:112
CTxOutCompressor::DecompressAmount
static uint64_t DecompressAmount(uint64_t nAmount)
Definition: compressor.cpp:156