Ethereum  PoC-8
The C++ Implementation of Ethereum
Precompiled.cpp
Go to the documentation of this file.
1 /*
2  This file is part of cpp-ethereum.
3 
4  cpp-ethereum is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  cpp-ethereum is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16 */
22 #include "Precompiled.h"
23 #include <libdevcore/Log.h>
24 #include <libdevcore/SHA3.h>
25 #include <libdevcrypto/Hash.h>
26 #include <libdevcrypto/Common.h>
27 #include <libdevcrypto/LibSnark.h>
28 #include <libethcore/Common.h>
29 using namespace std;
30 using namespace dev;
31 using namespace dev::eth;
32 
33 PrecompiledRegistrar* PrecompiledRegistrar::s_this = nullptr;
34 
35 PrecompiledExecutor const& PrecompiledRegistrar::executor(std::string const& _name)
36 {
37  if (!get()->m_execs.count(_name))
38  BOOST_THROW_EXCEPTION(ExecutorNotFound());
39  return get()->m_execs[_name];
40 }
41 
42 PrecompiledPricer const& PrecompiledRegistrar::pricer(std::string const& _name)
43 {
44  if (!get()->m_pricers.count(_name))
45  BOOST_THROW_EXCEPTION(PricerNotFound());
46  return get()->m_pricers[_name];
47 }
48 
49 namespace
50 {
51 
53 {
54  struct
55  {
56  h256 hash;
57  h256 v;
58  h256 r;
59  h256 s;
60  } in;
61 
62  memcpy(&in, _in.data(), min(_in.size(), sizeof(in)));
63 
64  h256 ret;
65  u256 v = (u256)in.v;
66  if (v >= 27 && v <= 28)
67  {
68  SignatureStruct sig(in.r, in.s, (byte)((int)v - 27));
69  if (sig.isValid())
70  {
71  try
72  {
73  if (Public rec = recover(sig, in.hash))
74  {
75  ret = dev::sha3(rec);
76  memset(ret.data(), 0, 12);
77  return {true, ret.asBytes()};
78  }
79  }
80  catch (...) {}
81  }
82  }
83  return {true, {}};
84 }
85 
87 {
88  return {true, dev::sha256(_in).asBytes()};
89 }
90 
92 {
93  return {true, h256(dev::ripemd160(_in), h256::AlignRight).asBytes()};
94 }
95 
97 {
98  return {true, _in.toBytes()};
99 }
100 
101 // Parse _count bytes of _in starting with _begin offset as big endian int.
102 // If there's not enough bytes in _in, consider it infinitely right-padded with zeroes.
103 bigint parseBigEndianRightPadded(bytesConstRef _in, bigint const& _begin, bigint const& _count)
104 {
105  if (_begin > _in.count())
106  return 0;
107  assert(_count <= numeric_limits<size_t>::max() / 8); // Otherwise, the return value would not fit in the memory.
108 
109  size_t const begin{_begin};
110  size_t const count{_count};
111 
112  // crop _in, not going beyond its size
113  bytesConstRef cropped = _in.cropped(begin, min(count, _in.count() - begin));
114 
115  bigint ret = fromBigEndian<bigint>(cropped);
116  // shift as if we had right-padding zeroes
117  assert(count - cropped.count() <= numeric_limits<size_t>::max() / 8);
118  ret <<= 8 * (count - cropped.count());
119 
120  return ret;
121 }
122 
124 {
125  bigint const baseLength(parseBigEndianRightPadded(_in, 0, 32));
126  bigint const expLength(parseBigEndianRightPadded(_in, 32, 32));
127  bigint const modLength(parseBigEndianRightPadded(_in, 64, 32));
128  assert(modLength <= numeric_limits<size_t>::max() / 8); // Otherwise gas should be too expensive.
129  assert(baseLength <= numeric_limits<size_t>::max() / 8); // Otherwise, gas should be too expensive.
130  if (modLength == 0 && baseLength == 0)
131  return {true, bytes{}}; // This is a special case where expLength can be very big.
132  assert(expLength <= numeric_limits<size_t>::max() / 8);
133 
134  bigint const base(parseBigEndianRightPadded(_in, 96, baseLength));
135  bigint const exp(parseBigEndianRightPadded(_in, 96 + baseLength, expLength));
136  bigint const mod(parseBigEndianRightPadded(_in, 96 + baseLength + expLength, modLength));
137 
138  bigint const result = mod != 0 ? boost::multiprecision::powm(base, exp, mod) : bigint{0};
139 
140  size_t const retLength(modLength);
141  bytes ret(retLength);
142  toBigEndian(result, ret);
143 
144  return {true, ret};
145 }
146 
147 namespace
148 {
149  bigint expLengthAdjust(bigint const& _expOffset, bigint const& _expLength, bytesConstRef _in)
150  {
151  if (_expLength <= 32)
152  {
153  bigint const exp(parseBigEndianRightPadded(_in, _expOffset, _expLength));
154  return exp ? msb(exp) : 0;
155  }
156  else
157  {
158  bigint const expFirstWord(parseBigEndianRightPadded(_in, _expOffset, 32));
159  size_t const highestBit(expFirstWord ? msb(expFirstWord) : 0);
160  return 8 * (_expLength - 32) + highestBit;
161  }
162  }
163 
164  bigint multComplexity(bigint const& _x)
165  {
166  if (_x <= 64)
167  return _x * _x;
168  if (_x <= 1024)
169  return (_x * _x) / 4 + 96 * _x - 3072;
170  else
171  return (_x * _x) / 16 + 480 * _x - 199680;
172  }
173 }
174 
176 {
177  bigint const baseLength(parseBigEndianRightPadded(_in, 0, 32));
178  bigint const expLength(parseBigEndianRightPadded(_in, 32, 32));
179  bigint const modLength(parseBigEndianRightPadded(_in, 64, 32));
180 
181  bigint const maxLength(max(modLength, baseLength));
182  bigint const adjustedExpLength(expLengthAdjust(baseLength + 96, expLength, _in));
183 
184  return multComplexity(maxLength) * max<bigint>(adjustedExpLength, 1) / 20;
185 }
186 
188 {
189  return dev::crypto::alt_bn128_G1_add(_in);
190 }
191 
193 {
194  return dev::crypto::alt_bn128_G1_mul(_in);
195 }
196 
198 {
200 }
201 
203 {
204  return 100000 + (_in.size() / 192) * 80000;
205 }
206 
207 }
dev::ripemd160
h160 ripemd160(bytesConstRef _input)
Definition: Hash.cpp:400
dev::toBigEndian
void toBigEndian(T _val, Out &o_out)
Definition: CommonData.h:124
dev::vector_ref< byte const >
dev::eth::PrecompiledExecutor
std::function< std::pair< bool, bytes >(bytesConstRef _in)> PrecompiledExecutor
Definition: Precompiled.h:34
dev::FixedHash::data
byte * data()
Definition: FixedHash.h:138
dev::sha3
bool sha3(bytesConstRef _input, bytesRef o_output) noexcept
Definition: SHA3.cpp:28
dev::crypto::alt_bn128_G1_add
std::pair< bool, bytes > alt_bn128_G1_add(bytesConstRef _in)
Definition: LibSnark.cpp:171
dev::h256
FixedHash< 32 > h256
Definition: FixedHash.h:356
dev::crypto::alt_bn128_pairing_product
std::pair< bool, bytes > alt_bn128_pairing_product(bytesConstRef _in)
Definition: LibSnark.cpp:131
Common.h
dev::eth
Definition: BasicAuthority.h:32
LibSnark.h
ETH_REGISTER_PRECOMPILED_PRICER
#define ETH_REGISTER_PRECOMPILED_PRICER(Name)
Definition: Precompiled.h:69
dev::FixedHash< 32 >
Common.h
dev::eth::PrecompiledPricer
std::function< bigint(bytesConstRef _in)> PrecompiledPricer
Definition: Precompiled.h:35
dev::SignatureStruct
Definition: Common.h:51
dev::vector_ref::cropped
vector_ref< _T > cropped(size_t _begin, size_t _count) const
Definition: vector_ref.h:60
dev::recover
Public recover(Signature const &_sig, h256 const &_hash)
Recovers Public key from signed message hash.
Definition: Common.cpp:221
dev::bytes
std::vector< byte > bytes
Definition: Common.h:72
SHA3.h
dev::vector_ref::size
size_t size() const
Definition: vector_ref.h:53
dev::eth::PrecompiledRegistrar
Definition: Precompiled.h:41
Precompiled.h
dev::bigint
boost::multiprecision::number< boost::multiprecision::cpp_int_backend<> > bigint
Definition: Common.h:118
std
Definition: FixedHash.h:393
dev::u256
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void > > u256
Definition: Common.h:121
dev
Definition: Address.cpp:21
ETH_REGISTER_PRECOMPILED
#define ETH_REGISTER_PRECOMPILED(Name)
Definition: Precompiled.h:68
dev::vector_ref::count
size_t count() const
Definition: vector_ref.h:51
dev::FixedHash::asBytes
bytes asBytes() const
Definition: FixedHash.h:150
Log.h
Hash.h
dev::sha256
h256 sha256(bytesConstRef _input) noexcept
Definition: Hash.cpp:30
dev::crypto::alt_bn128_G1_mul
std::pair< bool, bytes > alt_bn128_G1_mul(bytesConstRef _in)
Definition: LibSnark.cpp:187