1 // Aleth: Ethereum C++ client, tools and libraries.
2 // Copyright 2015-2019 Aleth Authors.
3 // Licensed under the GNU General Public License, Version 3.
4 #include "StateImporter.h"
5
6 #include <libdevcore/OverlayDB.h>
7 #include <libdevcore/RLP.h>
8 #include <libdevcore/TrieDB.h>
9
10 namespace dev
11 {
12 namespace eth
13 {
14
15 namespace
16 {
17
18 class StateImporter: public StateImporterFace
19 {
20 public:
StateImporter(OverlayDB & _stateDb)21 explicit StateImporter(OverlayDB& _stateDb): m_trie(&_stateDb) { m_trie.init(); }
22
importAccount(h256 const & _addressHash,u256 const & _nonce,u256 const & _balance,std::map<h256,bytes> const & _storage,h256 const & _codeHash)23 void importAccount(h256 const& _addressHash, u256 const& _nonce, u256 const& _balance, std::map<h256, bytes> const& _storage, h256 const& _codeHash) override
24 {
25 RLPStream s(4);
26 s << _nonce << _balance;
27
28 h256 const storageRoot = isAccountImported(_addressHash) ? accountStorageRoot(_addressHash) : EmptyTrie;
29 if (_storage.empty())
30 s.append(storageRoot);
31 else
32 {
33 SpecificTrieDB<GenericTrieDB<OverlayDB>, h256> storageDB(m_trie.db(), storageRoot);
34 for (auto const& hashAndValue: _storage)
35 storageDB.insert(hashAndValue.first, hashAndValue.second);
36
37 s.append(storageDB.root());
38 }
39
40 s << _codeHash;
41
42 m_trie.insert(_addressHash, &s.out());
43 }
44
importCode(bytesConstRef _code)45 h256 importCode(bytesConstRef _code) override
46 {
47 h256 const hash = sha3(_code);
48 m_trie.db()->insert(hash, _code);
49 return hash;
50 }
51
commitStateDatabase()52 void commitStateDatabase() override { m_trie.db()->commit(); }
53
isAccountImported(h256 const & _addressHash) const54 bool isAccountImported(h256 const& _addressHash) const override { return m_trie.contains(_addressHash); }
55
stateRoot() const56 h256 stateRoot() const override { return m_trie.root(); }
57
lookupCode(h256 const & _hash) const58 std::string lookupCode(h256 const& _hash) const override { return m_trie.db()->lookup(_hash); }
59
60 private:
61 // can be used only with already imported accounts
accountStorageRoot(h256 const & _addressHash) const62 h256 accountStorageRoot(h256 const& _addressHash) const
63 {
64 std::string const account = m_trie.at(_addressHash);
65 assert(!account.empty());
66
67 RLP accountRlp(account);
68 if (accountRlp.itemCount() < 3)
69 BOOST_THROW_EXCEPTION(InvalidAccountInTheDatabase());
70
71 return accountRlp[2].toHash<h256>(RLP::VeryStrict);
72 }
73
74 SpecificTrieDB<GenericTrieDB<OverlayDB>, h256> m_trie;
75 };
76
77 }
78
createStateImporter(OverlayDB & _stateDb)79 std::unique_ptr<StateImporterFace> createStateImporter(OverlayDB& _stateDb)
80 {
81 return std::unique_ptr<StateImporterFace>(new StateImporter(_stateDb));
82 }
83
84 }
85 }
86