use of org.aion.base.type.Address in project aion by aionnetwork.
the class AionBlockchainImpl method addReward.
/**
* Add reward to block- and every uncle coinbase assuming the entire block
* is valid.
*
* @param block
* object containing the header and uncles
*/
private Map<Address, BigInteger> addReward(IAionBlock block, List<AionTxExecSummary> summaries) {
Map<Address, BigInteger> rewards = new HashMap<>();
BigInteger minerReward = this.chainConfiguration.getRewardsCalculator().calculateReward(block.getHeader());
rewards.put(block.getCoinbase(), minerReward);
/*
* Remaining fees (the ones paid to miners for running transactions) are
* already paid for at a earlier point in execution.
*/
track.addBalance(block.getCoinbase(), minerReward);
track.flush();
return rewards;
}
use of org.aion.base.type.Address in project aion by aionnetwork.
the class AionBlockchainImpl method generatePreBlock.
/**
* For generating the necessary transactions for a block
*
* @param block
* @return
*/
private RetValidPreBlock generatePreBlock(IAionBlock block) {
long saveTime = System.nanoTime();
List<AionTxReceipt> receipts = new ArrayList<>();
List<AionTxExecSummary> summaries = new ArrayList<>();
List<AionTransaction> transactions = new ArrayList<>();
long energyRemaining = block.getNrgLimit();
for (AionTransaction tx : block.getTransactionsList()) {
TransactionExecutor executor = new TransactionExecutor(tx, block, track, false, energyRemaining);
AionTxExecSummary summary = executor.execute();
if (!summary.isRejected()) {
track.flush();
AionTxReceipt receipt = summary.getReceipt();
receipt.setPostTxState(repository.getRoot());
receipt.setTransaction(tx);
// otherwise, assuming we don't have timeouts, add the
// transaction
transactions.add(tx);
receipts.add(receipt);
summaries.add(summary);
energyRemaining -= receipt.getEnergyUsed();
}
}
Map<Address, BigInteger> rewards = addReward(block, summaries);
track.flush();
long totalTime = System.nanoTime() - saveTime;
chainStats.addBlockExecTime(totalTime);
return new RetValidPreBlock(transactions, rewards, receipts, summaries);
}
use of org.aion.base.type.Address in project aion by aionnetwork.
the class AionBlockchainImpl method applyBlock.
private AionBlockSummary applyBlock(IAionBlock block) {
long saveTime = System.nanoTime();
List<AionTxReceipt> receipts = new ArrayList<>();
List<AionTxExecSummary> summaries = new ArrayList<>();
for (AionTransaction tx : block.getTransactionsList()) {
TransactionExecutor executor = new TransactionExecutor(tx, block, track);
AionTxExecSummary summary = executor.execute();
track.flush();
AionTxReceipt receipt = summary.getReceipt();
receipt.setPostTxState(repository.getRoot());
receipts.add(receipt);
summaries.add(summary);
}
Map<Address, BigInteger> rewards = addReward(block, summaries);
long totalTime = System.nanoTime() - saveTime;
chainStats.addBlockExecTime(totalTime);
return new AionBlockSummary(block, rewards, receipts, summaries);
}
use of org.aion.base.type.Address in project aion by aionnetwork.
the class AionHub method loadBlockchain.
private void loadBlockchain() {
this.repository.getBlockStore().load();
AionBlock bestBlock = this.repository.getBlockStore().getBestBlock();
boolean recovered = true;
boolean bestBlockShifted = true;
int countRecoveryAttempts = 0;
// fix the trie if necessary
while (// the best block was updated after recovery attempt
bestBlockShifted && // allow 5 recovery attempts
(countRecoveryAttempts < 5) && // recover only for non-null blocks
bestBlock != null && !this.repository.isValidRoot(bestBlock.getStateRoot())) {
long bestBlockNumber = bestBlock.getNumber();
byte[] bestBlockRoot = bestBlock.getStateRoot();
recovered = this.blockchain.recoverWorldState(this.repository, bestBlockNumber);
if (recovered) {
bestBlock = this.repository.getBlockStore().getBestBlock();
// checking is the best block has changed since attempting recovery
if (bestBlock == null) {
bestBlockShifted = true;
} else {
bestBlockShifted = // block number changed
!(bestBlockNumber == bestBlock.getNumber()) || // root hash changed
!(Arrays.equals(bestBlockRoot, bestBlock.getStateRoot()));
}
if (bestBlockShifted) {
LOG.info("Rebuilding world state SUCCEEDED by REVERTING to a previous block.");
} else {
LOG.info("Rebuilding world state SUCCEEDED.");
}
} else {
LOG.error("Rebuilding world state FAILED. " + "Stop the kernel (Ctrl+C) and use the command line revert option to move back to a valid block. " + "Check the Aion wiki for recommendations on choosing the block number.");
}
countRecoveryAttempts++;
}
// rebuild from genesis if (1) no best block (2) recovery failed
if (bestBlock == null || !recovered) {
if (bestBlock == null) {
LOG.info("DB is empty - adding Genesis");
} else {
LOG.info("DB could not be recovered - adding Genesis");
}
AionGenesis genesis = cfg.getGenesis();
// 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();
repository.commitBlock(genesis.getHeader());
this.repository.getBlockStore().saveBlock(genesis, genesis.getCumulativeDifficulty(), true);
blockchain.setBestBlock(genesis);
blockchain.setTotalDifficulty(genesis.getCumulativeDifficulty());
if (this.eventMgr != null) {
List<IEvent> evts = new ArrayList<>();
evts.add(new EventBlock(EventBlock.CALLBACK.ONBLOCK0));
evts.add(new EventBlock(EventBlock.CALLBACK.ONTRACE0));
this.eventMgr.registerEvent(evts);
} else {
LOG.error("Event manager is null !!!");
System.exit(-1);
}
LOG.info("loaded genesis block <num={}, root={}>", 0, ByteUtil.toHexString(genesis.getStateRoot()));
} else {
blockchain.setBestBlock(bestBlock);
BigInteger totalDifficulty = this.repository.getBlockStore().getTotalDifficulty();
blockchain.setTotalDifficulty(totalDifficulty);
LOG.info("loaded block <num={}, root={}>", blockchain.getBestBlock().getNumber(), LogUtil.toHexF8(blockchain.getBestBlock().getStateRoot()));
}
if (!Arrays.equals(blockchain.getBestBlock().getStateRoot(), EMPTY_TRIE_HASH)) {
this.repository.syncToRoot(blockchain.getBestBlock().getStateRoot());
}
this.repository.getBlockStore().load();
}
use of org.aion.base.type.Address in project aion by aionnetwork.
the class AionRepositoryImpl method updateBatch.
@Override
public synchronized void updateBatch(Map<Address, AccountState> stateCache, Map<Address, IContractDetails<DataWord>> detailsCache) {
for (Map.Entry<Address, AccountState> entry : stateCache.entrySet()) {
Address address = entry.getKey();
AccountState accountState = entry.getValue();
IContractDetails<DataWord> contractDetails = detailsCache.get(address);
if (accountState.isDeleted()) {
// TODO-A: batch operations here
rwLock.readLock().lock();
try {
worldState.delete(address.toBytes());
} catch (Exception e) {
LOG.error("key deleted exception [{}]", e.toString());
} finally {
rwLock.readLock().unlock();
}
LOG.debug("key deleted <key={}>", Hex.toHexString(address.toBytes()));
} else {
if (!contractDetails.isDirty()) {
// ContractState class
if (accountState.isDirty()) {
updateAccountState(address, accountState);
if (LOG.isTraceEnabled()) {
LOG.trace("update: [{}],nonce: [{}] balance: [{}] [{}]", Hex.toHexString(address.toBytes()), accountState.getNonce(), accountState.getBalance(), contractDetails.getStorage());
}
}
continue;
}
ContractDetailsCacheImpl contractDetailsCache = (ContractDetailsCacheImpl) contractDetails;
if (contractDetailsCache.origContract == null) {
contractDetailsCache.origContract = this.cfg.contractDetailsImpl();
try {
contractDetailsCache.origContract.setAddress(address);
} catch (Exception e) {
e.printStackTrace();
LOG.error("contractDetailsCache setAddress exception [{}]", e.toString());
}
contractDetailsCache.commit();
}
contractDetails = contractDetailsCache.origContract;
updateContractDetails(address, contractDetails);
if (!Arrays.equals(accountState.getCodeHash(), EMPTY_TRIE_HASH)) {
accountState.setStateRoot(contractDetails.getStorageHash());
}
updateAccountState(address, accountState);
if (LOG.isTraceEnabled()) {
LOG.trace("update: [{}],nonce: [{}] balance: [{}] [{}]", Hex.toHexString(address.toBytes()), accountState.getNonce(), accountState.getBalance(), contractDetails.getStorage());
}
}
}
LOG.trace("updated: detailsCache.size: {}", detailsCache.size());
stateCache.clear();
detailsCache.clear();
}
Aggregations