25 #include <libethashseal/Ethash.h>
37 RLP manifest(manifestBytes);
42 BOOST_THROW_EXCEPTION(UnsupportedSnapshotManifestVersion());
44 BOOST_THROW_EXCEPTION(InvalidSnapshotManifest());
48 LOG(m_logger) <<
"Importing snapshot for block " << blockNumber <<
" block hash " << blockHash;
52 importStateChunks(_snapshotStorage, stateChunkHashes, stateRoot);
55 importBlockChunks(_snapshotStorage, blockChunkHashes);
58 void SnapshotImporter::importStateChunks(
SnapshotStorageFace const& _snapshotStorage,
h256s const& _stateChunkHashes,
h256 const& _stateRoot)
60 size_t const stateChunkCount = _stateChunkHashes.size();
62 size_t chunksImported = 0;
63 size_t accountsImported = 0;
65 for (
auto const& stateChunkHash: _stateChunkHashes)
67 std::string
const chunkUncompressed = _snapshotStorage.
readChunk(stateChunkHash);
69 RLP const accounts(chunkUncompressed);
70 size_t const accountCount = accounts.itemCount();
71 for (
size_t accountIndex = 0; accountIndex < accountCount; ++accountIndex)
73 RLP const addressAndAccount = accounts[accountIndex];
75 BOOST_THROW_EXCEPTION(InvalidStateChunkData());
79 BOOST_THROW_EXCEPTION(InvalidStateChunkData());
83 BOOST_THROW_EXCEPTION(AccountAlreadyImported());
85 RLP const account = addressAndAccount[1];
87 BOOST_THROW_EXCEPTION(InvalidStateChunkData());
92 RLP const storage = account[4];
93 std::map<h256, bytes> storageMap;
94 for (
auto hashAndValue: storage)
96 if (hashAndValue.itemCount() != 2)
97 BOOST_THROW_EXCEPTION(InvalidStateChunkData());
100 if (!keyHash || storageMap.find(keyHash) != storageMap.end())
101 BOOST_THROW_EXCEPTION(InvalidStateChunkData());
105 BOOST_THROW_EXCEPTION(InvalidStateChunkData());
107 storageMap.emplace(keyHash, std::move(value));
122 if (!codeHash || m_stateImporter.
lookupCode(codeHash).empty())
123 BOOST_THROW_EXCEPTION(InvalidStateChunkData());
126 BOOST_THROW_EXCEPTION(InvalidStateChunkData());
129 m_stateImporter.
importAccount(addressHash, nonce, balance, storageMap, codeHash);
131 accountsImported += accountCount;
136 LOG(m_logger) <<
"Imported chunk " << chunksImported <<
" (" << accounts.itemCount()
137 <<
" account records) Total account records imported: " << accountsImported;
138 LOG(m_logger) << stateChunkCount - chunksImported <<
" chunks left to import";
142 LOG(m_logger) <<
"Chunks imported: " << chunksImported;
143 LOG(m_logger) <<
"Account records imported: " << accountsImported;
144 LOG(m_logger) <<
"Reconstructed state root: " << m_stateImporter.
stateRoot();
145 LOG(m_logger) <<
"Manifest state root: " << _stateRoot;
146 if (m_stateImporter.
stateRoot() != _stateRoot)
147 BOOST_THROW_EXCEPTION(StateTrieReconstructionFailed());
150 void SnapshotImporter::importBlockChunks(SnapshotStorageFace
const& _snapshotStorage,
h256s const& _blockChunkHashes)
152 size_t const blockChunkCount = _blockChunkHashes.size();
153 size_t blockChunksImported = 0;
155 for (
auto chunk = _blockChunkHashes.rbegin(); chunk != _blockChunkHashes.rend(); ++chunk)
157 std::string
const chunkUncompressed = _snapshotStorage.readChunk(*chunk);
159 RLP blockChunk(chunkUncompressed);
160 if (blockChunk.itemCount() < 3)
161 BOOST_THROW_EXCEPTION(InvalidBlockChunkData());
163 int64_t
const firstBlockNumber = blockChunk[0].toPositiveInt64(
RLP::VeryStrict);
166 if (!firstBlockNumber || !firstBlockHash || !firstBlockDifficulty)
167 BOOST_THROW_EXCEPTION(InvalidBlockChunkData());
169 LOG(m_logger) <<
"chunk first block " << firstBlockNumber <<
" first block hash "
170 << firstBlockHash <<
" difficulty " << firstBlockDifficulty;
172 size_t const itemCount = blockChunk.itemCount();
173 h256 parentHash = firstBlockHash;
174 int64_t number = firstBlockNumber + 1;
175 u256 totalDifficulty = firstBlockDifficulty;
176 for (
size_t i = 3; i < itemCount; ++i, ++number)
178 RLP blockAndReceipts = blockChunk[i];
179 if (blockAndReceipts.itemCount() != 2)
180 BOOST_THROW_EXCEPTION(InvalidBlockChunkData());
182 RLP abridgedBlock = blockAndReceipts[0];
185 header.setParentHash(parentHash);
189 RLP transactions = abridgedBlock[8];
190 h256 const txRoot =
trieRootOver(transactions.itemCount(), [&](
unsigned i) { return rlp(i); }, [&](
unsigned i) { return transactions[i].data().toBytes(); });
191 RLP uncles = abridgedBlock[9];
192 RLP receipts = blockAndReceipts[1];
193 std::vector<bytesConstRef> receiptsVector;
194 for (
auto receipt: receipts)
195 receiptsVector.push_back(receipt.data());
197 h256 const unclesHash =
sha3(uncles.data());
198 header.setRoots(txRoot, receiptsRoot, unclesHash, blockStateRoot);
200 header.setLogBloom(abridgedBlock[2].toHash<LogBloom>(
RLP::VeryStrict));
202 header.setDifficulty(difficulty);
203 header.setNumber(number);
206 header.setTimestamp(abridgedBlock[6].toPositiveInt64(
RLP::VeryStrict));
209 Ethash::setMixHash(header, abridgedBlock[10].toHash<h256>(
RLP::VeryStrict));
210 Ethash::setNonce(header, abridgedBlock[11].toHash<Nonce>(
RLP::VeryStrict));
212 totalDifficulty += difficulty;
213 m_blockChainImporter.
importBlock(header, transactions, uncles, receipts, totalDifficulty);
215 parentHash = header.hash();
218 LOG(m_logger) <<
"Imported chunk " << *chunk <<
" (" << itemCount - 3 <<
" blocks)";
219 LOG(m_logger) << blockChunkCount - (++blockChunksImported) <<
" chunks left to import";
221 if (chunk == _blockChunkHashes.rbegin())
223 LOG(m_logger) <<
"Setting chain start block: " << firstBlockNumber + 1;