-
Notifications
You must be signed in to change notification settings - Fork 113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enabling JournalPruneDataSource #478
Changes from all commits
024681a
a19a604
349c930
4041344
f8152db
9377138
493f112
7e8dfbd
ab40ed4
46fccd6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,18 +3,18 @@ | |
* | ||
* This file is part of the aion network project. | ||
* | ||
* The aion network project is free software: you can redistribute it | ||
* and/or modify it under the terms of the GNU General Public License | ||
* as published by the Free Software Foundation, either version 3 of | ||
* The aion network project is free software: you can redistribute it | ||
* and/or modify it under the terms of the GNU General Public License | ||
* as published by the Free Software Foundation, either version 3 of | ||
* the License, or any later version. | ||
* | ||
* The aion network project is distributed in the hope that it will | ||
* be useful, but WITHOUT ANY WARRANTY; without even the implied | ||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
* The aion network project is distributed in the hope that it will | ||
* be useful, but WITHOUT ANY WARRANTY; without even the implied | ||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
* See the GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with the aion network project source files. | ||
* along with the aion network project source files. | ||
* If not, see <https://www.gnu.org/licenses/>. | ||
* | ||
* Contributors: | ||
|
@@ -271,9 +271,23 @@ private void loadBlockchain() { | |
bestBlock != null && // recover only for non-null blocks | ||
!this.repository.isValidRoot(bestBlock.getStateRoot())) { | ||
|
||
LOG.info("Recovery initiated due to corrupt world state at block " + bestBlock.getNumber() + "."); | ||
|
||
long bestBlockNumber = bestBlock.getNumber(); | ||
byte[] bestBlockRoot = bestBlock.getStateRoot(); | ||
|
||
// ensure that the genesis state exists before attempting recovery | ||
AionGenesis genesis = cfg.getGenesis(); | ||
if (!this.repository.isValidRoot(genesis.getStateRoot())) { | ||
LOG.info( | ||
"Corrupt world state for genesis block hash: " + genesis.getShortHash() + ", number: " + genesis | ||
.getNumber() + "."); | ||
|
||
buildGenesis(genesis); | ||
|
||
LOG.info("Rebuilding genesis block SUCCEEDED."); | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if buildGenesis fails? Do we need any log message here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if there is anything wrong with the genesis file an error message will be printed before recovery is attempted |
||
recovered = this.blockchain.recoverWorldState(this.repository, bestBlock); | ||
|
||
if (!this.repository.isValidRoot(bestBlock.getStateRoot())) { | ||
|
@@ -324,24 +338,8 @@ private void loadBlockchain() { | |
|
||
AionGenesis genesis = cfg.getGenesis(); | ||
|
||
// initialization section for network balance contract | ||
IRepositoryCache track = repository.startTracking(); | ||
|
||
Address networkBalanceAddress = PrecompiledContracts.totalCurrencyAddress; | ||
track.createAccount(networkBalanceAddress); | ||
buildGenesis(genesis); | ||
|
||
for (Map.Entry<Integer, BigInteger> addr : genesis.getNetworkBalances().entrySet()) { | ||
track.addStorageRow(networkBalanceAddress, new DataWord(addr.getKey()), new DataWord(addr.getValue())); | ||
} | ||
|
||
for (Address addr : genesis.getPremine().keySet()) { | ||
track.createAccount(addr); | ||
track.addBalance(addr, genesis.getPremine().get(addr).getBalance()); | ||
} | ||
track.flush(); | ||
|
||
repository.commitBlock(genesis.getHeader()); | ||
this.repository.getBlockStore().saveBlock(genesis, genesis.getDifficultyBI(), true); | ||
blockchain.setBestBlock(genesis); | ||
blockchain.setTotalDifficulty(genesis.getDifficultyBI()); | ||
|
||
|
@@ -396,6 +394,30 @@ private void loadBlockchain() { | |
// this.repository.getBlockStore().load(); | ||
} | ||
|
||
private void buildGenesis(AionGenesis genesis) { | ||
// initialization section for network balance contract | ||
IRepositoryCache track = repository.startTracking(); | ||
|
||
Address networkBalanceAddress = PrecompiledContracts.totalCurrencyAddress; | ||
track.createAccount(networkBalanceAddress); | ||
|
||
for (Map.Entry<Integer, BigInteger> addr : genesis.getNetworkBalances().entrySet()) { | ||
track.addStorageRow( | ||
networkBalanceAddress, | ||
new DataWord(addr.getKey()), | ||
new DataWord(addr.getValue())); | ||
} | ||
|
||
for (Address addr : genesis.getPremine().keySet()) { | ||
track.createAccount(addr); | ||
track.addBalance(addr, genesis.getPremine().get(addr).getBalance()); | ||
} | ||
track.flush(); | ||
|
||
this.repository.commitBlock(genesis.getHeader()); | ||
this.repository.getBlockStore().saveBlock(genesis, genesis.getCumulativeDifficulty(), true); | ||
} | ||
|
||
public void close() { | ||
LOG.info("<KERNEL SHUTDOWN SEQUENCE>"); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -76,7 +76,12 @@ private static class AionRepositoryImplHolder { | |
// repository singleton instance | ||
private final static AionRepositoryImpl inst = new AionRepositoryImpl( | ||
new RepositoryConfig(new File(config.getBasePath(), config.getDb().getPath()).getAbsolutePath(), | ||
-1, | ||
config.getDb().getPrune() > 0 ? | ||
// if the value is smaller than backward step | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pruning value should dictate parameters for our sync. So if we set a value of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the interaction between pruning and sync is tuned in #498 |
||
// there is the risk of importing state-less blocks after reboot | ||
(128 > config.getDb().getPrune() ? 128 : config.getDb().getPrune()) : | ||
// negative value => pruning disabled | ||
config.getDb().getPrune(), | ||
ContractDetailsAion.getInstance(), | ||
config.getDb())); | ||
} | ||
|
@@ -115,7 +120,7 @@ public TransactionStore<AionTransaction, AionTxReceipt, AionTxInfo> getTransacti | |
} | ||
|
||
private Trie createStateTrie() { | ||
return new SecureTrie(stateDatabase).withPruningEnabled(pruneBlockCount >= 0); | ||
return new SecureTrie(stateDSPrune).withPruningEnabled(pruneBlockCount > 0); | ||
} | ||
|
||
@Override | ||
|
@@ -501,34 +506,31 @@ public void commitBlock(A0BlockHeader blockHeader) { | |
worldState.sync(); | ||
detailsDS.syncLargeStorage(); | ||
|
||
// temporarily removed since never used | ||
/* if (pruneBlockCount >= 0) { | ||
stateDSPrune.storeBlockChanges(blockHeader); | ||
detailsDS.getStorageDSPrune().storeBlockChanges(blockHeader); | ||
pruneBlocks(blockHeader); | ||
} */ | ||
if (pruneBlockCount > 0) { | ||
stateDSPrune.storeBlockChanges(blockHeader); | ||
detailsDS.getStorageDSPrune().storeBlockChanges(blockHeader); | ||
pruneBlocks(blockHeader); | ||
} | ||
} finally { | ||
rwLock.writeLock().unlock(); | ||
} | ||
} | ||
|
||
// TODO-AR: reenable state pruning | ||
// temporarily removed since never used | ||
/* private void pruneBlocks(A0BlockHeader curBlock) { | ||
if (curBlock.getNumber() > bestBlockNumber) { // pruning only on | ||
// increasing blocks | ||
private void pruneBlocks(A0BlockHeader curBlock) { | ||
if (curBlock.getNumber() > bestBlockNumber) { | ||
// pruning only on increasing blocks | ||
long pruneBlockNumber = curBlock.getNumber() - pruneBlockCount; | ||
if (pruneBlockNumber >= 0) { | ||
byte[] pruneBlockHash = blockStore.getBlockHashByNumber(pruneBlockNumber); | ||
if (pruneBlockHash != null) { | ||
A0BlockHeader header = blockStore.getBlockByHash(pruneBlockHash).getHeader(); | ||
// stateDSPrune.prune(header); | ||
// detailsDS.getStorageDSPrune().prune(header); | ||
stateDSPrune.prune(header); | ||
detailsDS.getStorageDSPrune().prune(header); | ||
} | ||
} | ||
} | ||
bestBlockNumber = curBlock.getNumber(); | ||
} */ | ||
} | ||
|
||
public Trie getWorldState() { | ||
return worldState; | ||
|
@@ -543,7 +545,7 @@ public IRepository getSnapshotTo(byte[] root) { | |
repo.blockStore = blockStore; | ||
repo.cfg = cfg; | ||
repo.stateDatabase = this.stateDatabase; | ||
// repo.stateDSPrune = this.stateDSPrune; | ||
repo.stateDSPrune = this.stateDSPrune; | ||
repo.pruneBlockCount = this.pruneBlockCount; | ||
repo.detailsDS = this.detailsDS; | ||
repo.isSnapshot = true; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
buildGenesis()
seems to be building the genesis state based on the currentrepository
. It's correct for the latter usage, when the database is empty, but is it still valid here?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's valid, i.e. it always results in the same state root, because when calling
createAccount(Address)
thestateRoot = EMPTY_TRIE_HASH;
, so it does not build on the state root of the tracked repository