use of org.aion.base.db.Repository in project aion by aionnetwork.
the class DevCLI method printAccountDetails.
public static Cli.ReturnType printAccountDetails(String strAddress) {
// TODO AKI-681: more parameters would be useful, e.g. get account X at block Y
// read database configuration
CfgAion.inst().dbFromXML();
AionLoggerFactory.initAll(Map.of(LogEnum.GEN, LogLevel.INFO));
final Logger log = AionLoggerFactory.getLogger(LogEnum.GEN.name());
AionAddress address;
try {
address = new AionAddress(ByteUtil.hexStringToBytes(strAddress));
} catch (NumberFormatException e) {
log.error("The given argument «" + strAddress + "» cannot be converted to a valid account address.");
return Cli.ReturnType.ERROR;
}
// get the current repository
AionRepositoryImpl repository = AionRepositoryImpl.inst();
try {
Block bestBlock = repository.getBestBlock();
Repository snapshot = repository.getSnapshotTo(bestBlock.getStateRoot()).startTracking();
AccountState account = snapshot.getAccountState(address);
log.info(account.toString());
log.info(snapshot.getContractDetails(address).toString());
return Cli.ReturnType.EXIT;
} catch (Exception e) {
log.error("Error encountered while attempting to retrieve the account data.", e);
return Cli.ReturnType.ERROR;
} finally {
repository.close();
}
}
use of org.aion.base.db.Repository in project aion by aionnetwork.
the class AionRepositoryImplTest method testGetSnapshotToRoot.
@Test
public void testGetSnapshotToRoot() {
AionRepositoryImpl repository = AionRepositoryImpl.createForTesting(repoConfig);
// make some changes to the repository
final AionAddress account1 = AddressUtils.wrapAddress(value1);
final AionAddress account2 = AddressUtils.wrapAddress(value2);
final AionAddress account3 = AddressUtils.wrapAddress(value3);
RepositoryCache track = repository.startTracking();
track.addBalance(account1, BigInteger.ONE);
track.addBalance(account2, BigInteger.TWO);
track.addBalance(account3, BigInteger.TEN);
track.flushTo(repository, true);
repository.flush();
// get snapshot to root
Repository snapshot = repository.getSnapshotTo(repository.getRoot());
// check that the same values are retrieved
assertThat(repository.getBalance(account1)).isEqualTo(snapshot.getBalance(account1));
assertThat(repository.getBalance(account2)).isEqualTo(snapshot.getBalance(account2));
assertThat(repository.getBalance(account3)).isEqualTo(snapshot.getBalance(account3));
// make more changes to the initial repo
track = repository.startTracking();
track.addBalance(account1, BigInteger.TWO);
track.addBalance(account2, BigInteger.TWO);
track.addBalance(account3, BigInteger.TWO);
track.flushTo(repository, true);
// check that the values from the repo are larger
assertThat(repository.getBalance(account1)).isGreaterThan(snapshot.getBalance(account1));
assertThat(repository.getBalance(account2)).isGreaterThan(snapshot.getBalance(account2));
assertThat(repository.getBalance(account3)).isGreaterThan(snapshot.getBalance(account3));
// make the same changes to the snapshot
track = snapshot.startTracking();
track.addBalance(account1, BigInteger.TWO);
track.addBalance(account2, BigInteger.TWO);
track.addBalance(account3, BigInteger.TWO);
track.flushTo(snapshot, true);
// check that the values are again equal
assertThat(repository.getBalance(account1)).isEqualTo(snapshot.getBalance(account1));
assertThat(repository.getBalance(account2)).isEqualTo(snapshot.getBalance(account2));
assertThat(repository.getBalance(account3)).isEqualTo(snapshot.getBalance(account3));
// make more changes on the snapshot
track = snapshot.startTracking();
track.addBalance(account1, BigInteger.TEN);
track.addBalance(account2, BigInteger.TEN);
track.addBalance(account3, BigInteger.TEN);
track.flushTo(snapshot, true);
// check that the values from the snapshot are larger
assertThat(repository.getBalance(account1)).isLessThan(snapshot.getBalance(account1));
assertThat(repository.getBalance(account2)).isLessThan(snapshot.getBalance(account2));
assertThat(repository.getBalance(account3)).isLessThan(snapshot.getBalance(account3));
}
use of org.aion.base.db.Repository in project aion by aionnetwork.
the class AionBlockchainImpl method isValid.
/**
* This mechanism enforces a homeostasis in terms of the time between blocks; a smaller period
* between the last two blocks results in an increase in the difficulty level and thus
* additional computation required, lengthening the likely next period. Conversely, if the
* period is too large, the difficulty, and expected time to the next block, is reduced.
*/
private boolean isValid(Block block) {
if (block == null) {
return false;
}
if (!block.isGenesis()) {
if (!isValid(block.getHeader())) {
LOG.warn("Block {} has an invalid block header", block.getNumber());
return false;
}
List<AionTransaction> txs = block.getTransactionsList();
if (!isValidTxTrieRoot(block.getTxTrieRoot(), txs, block.getNumber(), LOG)) {
return false;
}
if (!txs.isEmpty()) {
Repository parentRepo = repository;
if (!Arrays.equals(bestBlock.getHash(), block.getParentHash())) {
parentRepo = repository.getSnapshotTo(getBlockByHash(block.getParentHash()).getStateRoot());
}
Map<AionAddress, BigInteger> nonceCache = new HashMap<>();
boolean unityForkEnabled = forkUtility.isUnityForkActive(block.getNumber());
boolean signatureSwapForkEnabled = forkUtility.isSignatureSwapForkActive(block.getNumber());
if (txs.parallelStream().anyMatch(tx -> TXValidator.validateTx(tx, unityForkEnabled, signatureSwapForkEnabled).isFail() || !TransactionTypeValidator.isValid(tx) || !beaconHashValidator.validateTxForBlock(tx, block))) {
LOG.error("Some transactions in the block are invalid");
for (AionTransaction tx : txs) {
TX_LOG.debug("Tx valid [" + TXValidator.validateTx(tx, unityForkEnabled, signatureSwapForkEnabled).isSuccess() + "]. Type valid [" + TransactionTypeValidator.isValid(tx) + "]\n" + tx.toString());
}
return false;
}
for (AionTransaction tx : txs) {
AionAddress txSender = tx.getSenderAddress();
BigInteger expectedNonce = nonceCache.get(txSender);
if (expectedNonce == null) {
expectedNonce = parentRepo.getNonce(txSender);
}
BigInteger txNonce = tx.getNonceBI();
if (!expectedNonce.equals(txNonce)) {
LOG.warn("Invalid transaction: Tx nonce {} != expected nonce {} (parent nonce: {}): {}", txNonce.toString(), expectedNonce.toString(), parentRepo.getNonce(txSender), tx);
return false;
}
// update cache
nonceCache.put(txSender, expectedNonce.add(BigInteger.ONE));
}
}
}
return true;
}
use of org.aion.base.db.Repository in project aion by aionnetwork.
the class BlockchainIntegrationTest method testSimpleOneTokenBalanceTransfer.
@Test
public void testSimpleOneTokenBalanceTransfer() {
// generate a recipient
final AionAddress receiverAddress = AddressUtils.wrapAddress("CAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFE");
StandaloneBlockchain.Bundle bundle = (new StandaloneBlockchain.Builder()).withValidatorConfiguration("simple").withDefaultAccounts().build();
StandaloneBlockchain bc = bundle.bc;
final ECKey sender = bundle.privateKeys.get(0);
final BigInteger senderInitialBalance = bc.getRepository().getBalance(new AionAddress(sender.getAddress()));
AionTransaction tx = AionTransaction.create(sender, BigInteger.valueOf(0).toByteArray(), receiverAddress, BigInteger.valueOf(100).toByteArray(), ByteUtil.EMPTY_BYTE_ARRAY, 21000L, energyPrice, TransactionTypes.DEFAULT, null);
MiningBlock block = bc.createNewMiningBlock(bc.getBestBlock(), Collections.singletonList(tx), true);
assertThat(block.getTransactionsList().size()).isEqualTo(1);
assertThat(block.getTransactionsList().get(0)).isEqualTo(tx);
ImportResult connection = bc.tryToConnect(block);
assertThat(connection).isEqualTo(ImportResult.IMPORTED_BEST);
// to be sure, perform some DB tests
Repository repo = bc.getRepository();
assertThat(repo.getBalance(receiverAddress)).isEqualTo(BigInteger.valueOf(100));
assertThat(repo.getBalance(new AionAddress(sender.getAddress()))).isEqualTo(senderInitialBalance.subtract(BigInteger.valueOf(21000).multiply(BigInteger.valueOf(energyPrice))).subtract(BigInteger.valueOf(100)));
}
Aggregations