|
|
|
@ -100,8 +100,14 @@ public class BonsaiPersistedWorldState implements MutableWorldState, BonsaiWorld |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected Hash calculateRootHash(final BonsaiWorldStateKeyValueStorage.Updater stateUpdater) { |
|
|
|
|
return calculateRootHash(stateUpdater, updater.copy()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected Hash calculateRootHash( |
|
|
|
|
final BonsaiWorldStateKeyValueStorage.Updater stateUpdater, |
|
|
|
|
final BonsaiWorldStateUpdater worldStateUpdater) { |
|
|
|
|
// first clear storage
|
|
|
|
|
for (final Address address : updater.getStorageToClear()) { |
|
|
|
|
for (final Address address : worldStateUpdater.getStorageToClear()) { |
|
|
|
|
// because we are clearing persisted values we need the account root as persisted
|
|
|
|
|
final BonsaiAccount oldAccount = |
|
|
|
|
worldStateStorage |
|
|
|
@ -138,12 +144,12 @@ public class BonsaiPersistedWorldState implements MutableWorldState, BonsaiWorld |
|
|
|
|
// second update account storage state. This must be done before updating the accounts so
|
|
|
|
|
// that we can get the storage state hash
|
|
|
|
|
for (final Map.Entry<Address, Map<Hash, BonsaiValue<UInt256>>> storageAccountUpdate : |
|
|
|
|
updater.getStorageToUpdate().entrySet()) { |
|
|
|
|
worldStateUpdater.getStorageToUpdate().entrySet()) { |
|
|
|
|
final Address updatedAddress = storageAccountUpdate.getKey(); |
|
|
|
|
final Hash updatedAddressHash = Hash.hash(updatedAddress); |
|
|
|
|
if (updater.getAccountsToUpdate().containsKey(updatedAddress)) { |
|
|
|
|
if (worldStateUpdater.getAccountsToUpdate().containsKey(updatedAddress)) { |
|
|
|
|
final BonsaiValue<BonsaiAccount> accountValue = |
|
|
|
|
updater.getAccountsToUpdate().get(updatedAddress); |
|
|
|
|
worldStateUpdater.getAccountsToUpdate().get(updatedAddress); |
|
|
|
|
final BonsaiAccount accountOriginal = accountValue.getPrior(); |
|
|
|
|
final Hash storageRoot = |
|
|
|
|
(accountOriginal == null) ? Hash.EMPTY_TRIE_HASH : accountOriginal.getStorageRoot(); |
|
|
|
@ -185,7 +191,7 @@ public class BonsaiPersistedWorldState implements MutableWorldState, BonsaiWorld |
|
|
|
|
|
|
|
|
|
// Third update the code. This has the side effect of ensuring a code hash is calculated.
|
|
|
|
|
for (final Map.Entry<Address, BonsaiValue<Bytes>> codeUpdate : |
|
|
|
|
updater.getCodeToUpdate().entrySet()) { |
|
|
|
|
worldStateUpdater.getCodeToUpdate().entrySet()) { |
|
|
|
|
final Bytes updatedCode = codeUpdate.getValue().getUpdated(); |
|
|
|
|
final Hash accountHash = Hash.hash(codeUpdate.getKey()); |
|
|
|
|
if (updatedCode == null || updatedCode.size() == 0) { |
|
|
|
@ -207,7 +213,7 @@ public class BonsaiPersistedWorldState implements MutableWorldState, BonsaiWorld |
|
|
|
|
|
|
|
|
|
// now add the accounts
|
|
|
|
|
for (final Map.Entry<Address, BonsaiValue<BonsaiAccount>> accountUpdate : |
|
|
|
|
updater.getAccountsToUpdate().entrySet()) { |
|
|
|
|
worldStateUpdater.getAccountsToUpdate().entrySet()) { |
|
|
|
|
final Bytes accountKey = accountUpdate.getKey(); |
|
|
|
|
final BonsaiValue<BonsaiAccount> bonsaiValue = accountUpdate.getValue(); |
|
|
|
|
final BonsaiAccount updatedAccount = bonsaiValue.getUpdated(); |
|
|
|
@ -235,12 +241,15 @@ public class BonsaiPersistedWorldState implements MutableWorldState, BonsaiWorld |
|
|
|
|
@Override |
|
|
|
|
public void persist(final BlockHeader blockHeader) { |
|
|
|
|
boolean success = false; |
|
|
|
|
|
|
|
|
|
final BonsaiWorldStateUpdater localUpdater = updater.copy(); |
|
|
|
|
|
|
|
|
|
final Hash originalBlockHash = worldStateBlockHash; |
|
|
|
|
final Hash originalRootHash = worldStateRootHash; |
|
|
|
|
final BonsaiWorldStateKeyValueStorage.Updater stateUpdater = worldStateStorage.updater(); |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
worldStateRootHash = calculateRootHash(stateUpdater); |
|
|
|
|
worldStateRootHash = calculateRootHash(stateUpdater, localUpdater); |
|
|
|
|
stateUpdater |
|
|
|
|
.getTrieBranchStorageTransaction() |
|
|
|
|
.put(WORLD_ROOT_HASH_KEY, worldStateRootHash.toArrayUnsafe()); |
|
|
|
@ -262,7 +271,7 @@ public class BonsaiPersistedWorldState implements MutableWorldState, BonsaiWorld |
|
|
|
|
.put(WORLD_BLOCK_HASH_KEY, worldStateBlockHash.toArrayUnsafe()); |
|
|
|
|
if (originalBlockHash.equals(blockHeader.getParentHash())) { |
|
|
|
|
LOG.debug("Writing Trie Log for {}", worldStateBlockHash); |
|
|
|
|
final TrieLogLayer trieLog = updater.generateTrieLog(worldStateBlockHash); |
|
|
|
|
final TrieLogLayer trieLog = localUpdater.generateTrieLog(worldStateBlockHash); |
|
|
|
|
trieLog.freeze(); |
|
|
|
|
archive.addLayeredWorldState(this, blockHeader, worldStateRootHash, trieLog); |
|
|
|
|
final BytesValueRLPOutput rlpLog = new BytesValueRLPOutput(); |
|
|
|
@ -331,7 +340,8 @@ public class BonsaiPersistedWorldState implements MutableWorldState, BonsaiWorld |
|
|
|
|
@Override |
|
|
|
|
public Hash frontierRootHash() { |
|
|
|
|
return calculateRootHash( |
|
|
|
|
new BonsaiWorldStateKeyValueStorage.Updater(noOpTx, noOpTx, noOpTx, noOpTx, noOpTx)); |
|
|
|
|
new BonsaiWorldStateKeyValueStorage.Updater(noOpTx, noOpTx, noOpTx, noOpTx, noOpTx), |
|
|
|
|
updater.copy()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public Hash blockHash() { |
|
|
|
|