Ethereum  PoC-8
The C++ Implementation of Ethereum
SealEngine.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 */
17 
18 #include "SealEngine.h"
19 #include "TransactionBase.h"
20 
21 using namespace std;
22 namespace dev
23 {
24 namespace eth
25 {
26 SealEngineRegistrar* SealEngineRegistrar::s_this = nullptr;
27 
28 void NoProof::init()
29 {
31 }
32 
33 void NoProof::populateFromParent(BlockHeader& _bi, BlockHeader const& _parent) const
34 {
35  SealEngineFace::populateFromParent(_bi, _parent);
36  _bi.setDifficulty(calculateEthashDifficulty(chainParams(), _bi, _parent));
37  _bi.setGasLimit(calculateGasLimit(chainParams(), _bi));
38 }
39 
40 void NoProof::generateSeal(BlockHeader const& _bi)
41 {
42  BlockHeader header(_bi);
43  header.setSeal(NonceField, h64{0});
44  header.setSeal(MixHashField, h256{0});
45  RLPStream ret;
46  header.streamRLP(ret);
47  if (m_onSealGenerated)
48  m_onSealGenerated(ret.out());
49 }
50 
51 void NoProof::verify(Strictness _s, BlockHeader const& _bi, BlockHeader const& _parent, bytesConstRef _block) const
52 {
53  SealEngineFace::verify(_s, _bi, _parent, _block);
54 
55  if (_parent)
56  {
57  // Check difficulty is correct given the two timestamps.
58  auto expected = calculateEthashDifficulty(chainParams(), _bi, _parent);
59  auto difficulty = _bi.difficulty();
60  if (difficulty != expected)
61  BOOST_THROW_EXCEPTION(InvalidDifficulty() << RequirementError((bigint)expected, (bigint)difficulty));
62  }
63 }
64 
65 void SealEngineFace::verify(Strictness _s, BlockHeader const& _bi, BlockHeader const& _parent, bytesConstRef _block) const
66 {
67  _bi.verify(_s, _parent, _block);
68 
69  if (_s != CheckNothingNew)
70  {
71  if (_bi.difficulty() < chainParams().minimumDifficulty)
72  BOOST_THROW_EXCEPTION(
73  InvalidDifficulty() << RequirementError(
74  bigint(chainParams().minimumDifficulty), bigint(_bi.difficulty())));
75 
76  if (_bi.gasLimit() < chainParams().minGasLimit)
77  BOOST_THROW_EXCEPTION(InvalidGasLimit() << RequirementError(
78  bigint(chainParams().minGasLimit), bigint(_bi.gasLimit())));
79 
80  if (_bi.gasLimit() > chainParams().maxGasLimit)
81  BOOST_THROW_EXCEPTION(InvalidGasLimit() << RequirementError(
82  bigint(chainParams().maxGasLimit), bigint(_bi.gasLimit())));
83 
84  if (_bi.number() && _bi.extraData().size() > chainParams().maximumExtraDataSize)
85  {
86  BOOST_THROW_EXCEPTION(
87  ExtraDataTooBig()
88  << RequirementError(bigint(chainParams().maximumExtraDataSize),
89  bigint(_bi.extraData().size()))
90  << errinfo_extraData(_bi.extraData()));
91  }
92 
93  u256 const& daoHardfork = chainParams().daoHardforkBlock;
94  if (daoHardfork != 0 && daoHardfork + 9 >= daoHardfork && _bi.number() >= daoHardfork &&
95  _bi.number() <= daoHardfork + 9)
96  if (_bi.extraData() != fromHex("0x64616f2d686172642d666f726b"))
97  BOOST_THROW_EXCEPTION(
98  ExtraDataIncorrect()
99  << errinfo_comment("Received block from the wrong fork (invalid extradata)."));
100  }
101 
102  if (_parent)
103  {
104  auto gasLimit = _bi.gasLimit();
105  auto parentGasLimit = _parent.gasLimit();
106  if (gasLimit < chainParams().minGasLimit || gasLimit > chainParams().maxGasLimit ||
107  gasLimit <= parentGasLimit - parentGasLimit / chainParams().gasLimitBoundDivisor ||
108  gasLimit >= parentGasLimit + parentGasLimit / chainParams().gasLimitBoundDivisor)
109  BOOST_THROW_EXCEPTION(
110  InvalidGasLimit()
111  << errinfo_min(
112  (bigint)((bigint)parentGasLimit -
113  (bigint)(parentGasLimit / chainParams().gasLimitBoundDivisor)))
114  << errinfo_got((bigint)gasLimit)
115  << errinfo_max((bigint)((bigint)parentGasLimit +
116  parentGasLimit / chainParams().gasLimitBoundDivisor)));
117  }
118 }
119 
120 void SealEngineFace::populateFromParent(BlockHeader& _bi, BlockHeader const& _parent) const
121 {
122  _bi.populateFromParent(_parent);
123 }
124 
125 void SealEngineFace::verifyTransaction(ImportRequirements::value _ir, TransactionBase const& _t,
126  BlockHeader const& _header, u256 const& _gasUsed) const
127 {
128  if ((_ir & ImportRequirements::TransactionSignatures) && _header.number() < chainParams().EIP158ForkBlock && _t.isReplayProtected())
129  BOOST_THROW_EXCEPTION(InvalidSignature());
130 
131  if ((_ir & ImportRequirements::TransactionSignatures) &&
132  _header.number() < chainParams().experimentalForkBlock && _t.hasZeroSignature())
133  BOOST_THROW_EXCEPTION(InvalidSignature());
134 
135  if ((_ir & ImportRequirements::TransactionBasic) &&
136  _header.number() >= chainParams().experimentalForkBlock && _t.hasZeroSignature() &&
137  (_t.value() != 0 || _t.gasPrice() != 0 || _t.nonce() != 0))
138  BOOST_THROW_EXCEPTION(InvalidZeroSignatureTransaction() << errinfo_got((bigint)_t.gasPrice()) << errinfo_got((bigint)_t.value()) << errinfo_got((bigint)_t.nonce()));
139 
140  if (_header.number() >= chainParams().homesteadForkBlock && (_ir & ImportRequirements::TransactionSignatures) && _t.hasSignature())
141  _t.checkLowS();
142 
143  eth::EVMSchedule const& schedule = evmSchedule(_header.number());
144 
145  // Pre calculate the gas needed for execution
146  if ((_ir & ImportRequirements::TransactionBasic) && _t.baseGasRequired(schedule) > _t.gas())
147  BOOST_THROW_EXCEPTION(OutOfGasIntrinsic() << RequirementError(
148  (bigint)(_t.baseGasRequired(schedule)), (bigint)_t.gas()));
149 
150  // Avoid transactions that would take us beyond the block gas limit.
151  if (_gasUsed + (bigint)_t.gas() > _header.gasLimit())
152  BOOST_THROW_EXCEPTION(BlockGasLimitReached() << RequirementErrorComment(
153  (bigint)(_header.gasLimit() - _gasUsed), (bigint)_t.gas(),
154  string("_gasUsed + (bigint)_t.gas() > _header.gasLimit()")));
155 }
156 
157 SealEngineFace* SealEngineRegistrar::create(ChainOperationParams const& _params)
158 {
159  SealEngineFace* ret = create(_params.sealEngineName);
160  assert(ret && "Seal engine not found.");
161  if (ret)
162  ret->setChainParams(_params);
163  return ret;
164 }
165 
166 EVMSchedule const& SealEngineBase::evmSchedule(u256 const& _blockNumber) const
167 {
168  return chainParams().scheduleForBlockNumber(_blockNumber);
169 }
170 
171 u256 SealEngineBase::blockReward(u256 const& _blockNumber) const
172 {
173  EVMSchedule const& schedule{evmSchedule(_blockNumber)};
174  return chainParams().blockReward(schedule);
175 }
176 
178  ChainOperationParams const& _chainParams, BlockHeader const& _bi, BlockHeader const& _parent)
179 {
180  const unsigned c_expDiffPeriod = 100000;
181 
182  if (!_bi.number())
183  throw GenesisBlockCannotBeCalculated();
184  auto const& minimumDifficulty = _chainParams.minimumDifficulty;
185  auto const& difficultyBoundDivisor = _chainParams.difficultyBoundDivisor;
186  auto const& durationLimit = _chainParams.durationLimit;
187 
188  bigint target; // stick to a bigint for the target. Don't want to risk going negative.
189  if (_bi.number() < _chainParams.homesteadForkBlock)
190  // Frontier-era difficulty adjustment
191  target = _bi.timestamp() >= _parent.timestamp() + durationLimit ?
192  _parent.difficulty() - (_parent.difficulty() / difficultyBoundDivisor) :
193  (_parent.difficulty() + (_parent.difficulty() / difficultyBoundDivisor));
194  else
195  {
196  bigint const timestampDiff = bigint(_bi.timestamp()) - _parent.timestamp();
197  bigint const adjFactor =
198  _bi.number() < _chainParams.byzantiumForkBlock ?
199  max<bigint>(1 - timestampDiff / 10, -99) : // Homestead-era difficulty adjustment
200  max<bigint>((_parent.hasUncles() ? 2 : 1) - timestampDiff / 9,
201  -99); // Byzantium-era difficulty adjustment
202 
203  target = _parent.difficulty() + _parent.difficulty() / 2048 * adjFactor;
204  }
205 
206  bigint o = target;
207  unsigned exponentialIceAgeBlockNumber = unsigned(_parent.number() + 1);
208 
209  // EIP-1234 Constantinople Ice Age delay
210  if (_bi.number() >= _chainParams.constantinopleForkBlock)
211  {
212  if (exponentialIceAgeBlockNumber >= 5000000)
213  exponentialIceAgeBlockNumber -= 5000000;
214  else
215  exponentialIceAgeBlockNumber = 0;
216  }
217  // EIP-649 Byzantium Ice Age delay
218  else if (_bi.number() >= _chainParams.byzantiumForkBlock)
219  {
220  if (exponentialIceAgeBlockNumber >= 3000000)
221  exponentialIceAgeBlockNumber -= 3000000;
222  else
223  exponentialIceAgeBlockNumber = 0;
224  }
225 
226  unsigned periodCount = exponentialIceAgeBlockNumber / c_expDiffPeriod;
227  if (periodCount > 1)
228  o += (bigint(1) << (periodCount - 2)); // latter will eventually become huge, so ensure
229  // it's a bigint.
230 
231  o = max<bigint>(minimumDifficulty, o);
232  return u256(min<bigint>(o, std::numeric_limits<u256>::max()));
233 }
234 
236  ChainOperationParams const& _chainParams, BlockHeader const& _bi, u256 const& _gasFloorTarget)
237 {
238  u256 gasFloorTarget = _gasFloorTarget == Invalid256 ? 3141562 : _gasFloorTarget;
239  u256 gasLimit = _bi.gasLimit();
240  u256 boundDivisor = _chainParams.gasLimitBoundDivisor;
241  if (gasLimit < gasFloorTarget)
242  return min<u256>(gasFloorTarget, gasLimit + gasLimit / boundDivisor - 1);
243  else
244  return max<u256>(gasFloorTarget,
245  gasLimit - gasLimit / boundDivisor + 1 + (_bi.gasUsed() * 6 / 5) / boundDivisor);
246 }
247 }
248 } // namespace dev eth
Too little gas to pay for the base transaction cost.
Definition: Address.cpp:20
u256 calculateEthashDifficulty(ChainOperationParams const &_chainParams, BlockHeader const &_bi, BlockHeader const &_parent)
Definition: SealEngine.cpp:177
bool hasUncles() const
Definition: BlockHeader.h:159
u256 const & difficulty() const
Definition: BlockHeader.h:170
void populateFromParent(BlockHeader const &parent)
Encapsulation of a block header. Class to contain all of a block header&#39;s data. It is able to parse a...
Definition: BlockHeader.h:96
bool verify(Public const &_k, Signature const &_s, h256 const &_hash)
Verify signature.
Definition: Common.cpp:254
Definition: FixedHash.h:390
boost::error_info< struct tag_min, bigint > errinfo_min
Definition: Exceptions.h:84
boost::error_info< struct tag_max, bigint > errinfo_max
Definition: Exceptions.h:85
int64_t number() const
Definition: BlockHeader.h:166
boost::multiprecision::number< boost::multiprecision::cpp_int_backend<> > bigint
Definition: Common.h:118
bytes fromHex(std::string const &_s, WhenError _throw=WhenError::DontThrow)
Definition: CommonData.cpp:81
int64_t timestamp() const
Definition: BlockHeader.h:160
u256 constexpr Invalid256
Definition: Common.h:147
boost::error_info< struct tag_got, bigint > errinfo_got
Definition: Exceptions.h:83
boost::error_info< struct tag_extraData, bytes > errinfo_extraData
Definition: Exceptions.h:92
void setGasLimit(u256 const &_v)
Definition: BlockHeader.h:150
u256 calculateGasLimit(ChainOperationParams const &_chainParams, BlockHeader const &_bi, u256 const &_gasFloorTarget)
Definition: SealEngine.cpp:235
void streamRLP(RLPStream &_s, IncludeSeal _i=WithSeal) const
bytes const & out() const
Read the byte stream.
Definition: RLP.h:419
boost::tuple< errinfo_required, errinfo_got, errinfo_comment > RequirementErrorComment
Definition: Exceptions.h:87
void setSeal(unsigned _offset, T const &_value)
Definition: BlockHeader.h:154
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void > > u256
Definition: Common.h:121
std::string sealEngineName
The chain sealer name: e.g. Ethash, NoProof, BasicAuthority.
boost::error_info< struct tag_comment, std::string > errinfo_comment
Definition: Assertions.h:69
void setChainParams(ChainOperationParams const &_params)
Definition: SealEngine.h:75
u256 const & gasLimit() const
Definition: BlockHeader.h:167
void verify(Strictness _s=CheckEverything, BlockHeader const &_parent=BlockHeader(), bytesConstRef _block=bytesConstRef()) const
bytes const & extraData() const
Definition: BlockHeader.h:168
boost::tuple< errinfo_required, errinfo_got > RequirementError
Definition: Exceptions.h:86
Class for writing to an RLP bytestream.
Definition: RLP.h:369
int64_t baseGasRequired(EVMSchedule const &_es) const
void setDifficulty(u256 const &_v)
Definition: BlockHeader.h:153
Encodes a transaction, ready to be exported to or freshly imported from RLP.
u256 const & gasUsed() const
Definition: BlockHeader.h:165
#define ETH_REGISTER_SEAL_ENGINE(Name)
Definition: SealEngine.h:133