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