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