use of neo.model.core.Block in project neo-java by coranos.
the class TestDBMapDb method test006putAndGetTransactionWithHash.
/**
* test put, and getTransactionWithHash.
*/
@Test
public void test006putAndGetTransactionWithHash() {
try (TestLocalControllerNode controller = getTestLocalControllerNode()) {
final Block block = MockUtil.getMockBlock003();
controller.getBlockDb().put(true, GenesisBlockUtil.GENESIS_BLOCK);
controller.getBlockDb().put(true, block);
final Transaction expectedTransaction = block.getTransactionList().get(0);
final Transaction actualTransaction = controller.getBlockDb().getTransactionWithHash(expectedTransaction.getHash());
Assert.assertEquals("transactions should match.", expectedTransaction.toJSONObject().toString(2), actualTransaction.toJSONObject().toString(2));
}
}
use of neo.model.core.Block in project neo-java by coranos.
the class BlockImportExportUtil method importBlocks.
/**
* imports the blocks from the file.
*
* @param controller
* the controller.
*/
public static void importBlocks(final LocalControllerNode controller) {
final LocalNodeData localNodeData = controller.getLocalNodeData();
final BlockDb blockDb = localNodeData.getBlockDb();
try (OutputStream statsFileOut = new FileOutputStream(localNodeData.getChainExportStatsFileName());
PrintWriter statsWriter = new PrintWriter(statsFileOut, true)) {
statsWriter.println(OPEN_BRACKET);
long maxIndex = 0;
try (InputStream fileIn = new FileInputStream(localNodeData.getChainExportDataFileName());
BufferedInputStream buffIn = new BufferedInputStream(fileIn, 1024 * 1024 * 32);
DataInputStream in = new DataInputStream(buffIn)) {
final byte[] maxIndexBa = new byte[UInt32.SIZE];
in.read(maxIndexBa);
if (LOG.isTraceEnabled()) {
LOG.info("import maxIndexBa asread {}", Hex.encode(maxIndexBa));
}
ArrayUtils.reverse(maxIndexBa);
maxIndex = new UInt32(maxIndexBa).asLong();
LOG.info("started import {}", INTEGER_FORMAT.format(maxIndex));
long startMs = -1;
long interimBlocks = 0;
long interimBytes = 0;
final long[] interimTx = new long[TransactionType.values().length];
final long[] interimTxNetworkFees = new long[TransactionType.values().length];
long totalTx = 0;
final Map<String, Long> numBlocksByTxCountMap = new TreeMap<>();
@SuppressWarnings("unchecked") final Set<UInt160>[] activeAccountSet = new Set[TransactionType.values().length];
for (int txOrdinal = 0; txOrdinal < activeAccountSet.length; txOrdinal++) {
activeAccountSet[txOrdinal] = new TreeSet<>();
}
long procStartMs = System.currentTimeMillis();
for (long blockIx = 0; blockIx < maxIndex; blockIx++) {
final int length = Integer.reverseBytes(in.readInt());
LOG.debug("STARTED import {} of {} length {}", INTEGER_FORMAT.format(blockIx), INTEGER_FORMAT.format(maxIndex), INTEGER_FORMAT.format(length));
final byte[] ba = new byte[length];
in.read(ba);
final Block block = new Block(ByteBuffer.wrap(ba));
final boolean forceSynch = (blockIx % BlockDb.BLOCK_FORCE_SYNCH_INTERVAL) == 0;
blockDb.put(forceSynch, block);
interimBlocks++;
interimBytes += ba.length;
for (final Transaction tx : block.getTransactionList()) {
interimTx[tx.type.ordinal()]++;
final Fixed8 systemFee = localNodeData.getTransactionSystemFeeMap().get(tx.type);
interimTxNetworkFees[tx.type.ordinal()] += getNetworkFee(blockDb, tx, systemFee).value;
totalTx++;
for (final TransactionOutput txOut : tx.outputs) {
activeAccountSet[tx.type.ordinal()].add(txOut.scriptHash);
}
}
LOG.debug("SUCCESS import {} of {} hash {}", INTEGER_FORMAT.format(blockIx), INTEGER_FORMAT.format(maxIndex), block.hash);
MapUtil.increment(numBlocksByTxCountMap, String.valueOf(block.getTransactionList().size()));
final Timestamp blockTs = block.getTimestamp();
if (startMs < 0) {
startMs = blockTs.getTime();
}
final long ms = blockTs.getTime() - startMs;
if (ms > (86400 * 1000)) {
blockDb.put(true);
final Block maxBlockHeader = blockDb.getHeaderOfBlockWithMaxIndex();
final JSONObject stats = getStats(blockDb, interimBlocks, interimBytes, interimTx, activeAccountSet, procStartMs, blockTs, interimTxNetworkFees, numBlocksByTxCountMap);
if (blockIx > 0) {
statsWriter.println(COMMA);
}
statsWriter.println(stats);
final long maxBlockHeaderIndex = maxBlockHeader.getIndexAsLong();
LOG.info("INTERIM import {} of {}, bx {}, tx {} json {}", INTEGER_FORMAT.format(blockIx), INTEGER_FORMAT.format(maxIndex), INTEGER_FORMAT.format(maxBlockHeaderIndex), INTEGER_FORMAT.format(totalTx), stats);
startMs = blockTs.getTime();
for (int ix = 0; ix < interimTx.length; ix++) {
interimTx[ix] = 0;
interimTxNetworkFees[ix] = 0;
}
interimBlocks = 0;
interimBytes = 0;
for (int txOrdinal = 0; txOrdinal < activeAccountSet.length; txOrdinal++) {
activeAccountSet[txOrdinal].clear();
}
numBlocksByTxCountMap.clear();
procStartMs = System.currentTimeMillis();
}
}
blockDb.put(true);
LOG.info("SUCCESS import {}, synched", INTEGER_FORMAT.format(maxIndex));
} catch (final IOException e) {
if (e instanceof EOFException) {
blockDb.put(true);
final Block maxBlockHeader = blockDb.getHeaderOfBlockWithMaxIndex();
LOG.error("FAILURE import {} of {}, synched, EOFException", INTEGER_FORMAT.format(maxBlockHeader.getIndexAsLong()), maxIndex);
LOG.error("EOFException", e);
return;
} else {
throw new RuntimeException(e);
}
} finally {
statsWriter.println(CLOSE_BRACKET);
}
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
use of neo.model.core.Block in project neo-java by coranos.
the class LocalControllerNode method onBlock.
/**
* does something on a "block" message.
*
* @param peer
* the peer that sent the message.
* @param message
* the message.
*/
private void onBlock(final RemoteNodeControllerRunnable peer, final Message message) {
if (stopped) {
return;
}
final Block newBlock = message.getPayload(Block.class);
final String expected = new String(Hex.encodeHexString(message.getPayloadByteArray()));
final String actual = Hex.encodeHexString(newBlock.toByteArray());
if (!expected.equals(actual)) {
LOG.error("onBlock newBlock: {}", newBlock);
LOG.error("onBlock expected: {}", expected);
LOG.error("onBlock actual : {}", actual);
return;
}
LocalNodeDataSynchronizedUtil.addUnverifiedBlock(localNodeData, newBlock);
// LocalNodeDataSynchronizedUtil.verifyUnverifiedBlocks(localNodeData);
}
use of neo.model.core.Block in project neo-java by coranos.
the class LocalNodeDataSynchronizedUtil method addHeaderIfNewUnsynchronized.
/**
* add the header if it is new, this is the unsynchronized helper method.
*
* @param localNodeData
* the local node data to use.
* @param header
* the header to add.
* @return true if added, gfalse if not.
*/
private static boolean addHeaderIfNewUnsynchronized(final LocalNodeData localNodeData, final Header header) {
final long headerIndex = header.getIndexAsLong();
LOG.trace("STARTED addHeaderIfNewUnsynchronized adding header : index:{}; hash:{};", headerIndex, header.hash);
final Block highestBlock = localNodeData.getBlockDb().getHeaderOfBlockWithMaxIndex();
if (highestBlock != null) {
final long maxBlockIndex = highestBlock.getIndexAsLong();
// }
if (headerIndex <= maxBlockIndex) {
final String message = "FAILURE addHeaderIfNewUnsynchronized[1]" + " (headerIndex[{}] <= maxBlockIndex[{}]) adding header : index:{}; hash:{};";
LOG.trace(message, headerIndex, maxBlockIndex, headerIndex, header.hash);
return false;
}
}
if (!localNodeData.getUnverifiedBlockPoolSet().isEmpty()) {
final long maxBlockIndex = highestBlock.getIndexAsLong();
final long numUnverifiedBlockCount = localNodeData.getUnverifiedBlockPoolSet().size();
final long maxUnverifiedBlockIndex = localNodeData.getUnverifiedBlockPoolSet().last().getIndexAsLong();
final boolean gapsInBlocks = (maxBlockIndex + numUnverifiedBlockCount) <= maxUnverifiedBlockIndex;
if (LOG.isTraceEnabled()) {
final String message = "INTERIM addHeaderIfNewUnsynchronized[2] " + " (maxBlockIndex[{}]+numUnverifiedBlockCount[{}] <= maxUnverifiedBlockIndex[{}]), " + " gaps:{};";
LOG.trace(message, maxBlockIndex, numUnverifiedBlockCount, maxUnverifiedBlockIndex, gapsInBlocks);
}
if (gapsInBlocks) {
if (LOG.isTraceEnabled()) {
final String message = "INTERIM addHeaderIfNewUnsynchronized[2]" + " (maxBlockIndex[{}]+numUnverifiedBlockCount[{}] <= maxUnverifiedBlockIndex[{}])," + " there are gaps in unverified blocks.";
LOG.trace(message, maxBlockIndex, numUnverifiedBlockCount, maxUnverifiedBlockIndex);
}
if (localNodeData.getBlockDb().containsBlockWithHash(header.hash)) {
final String message = "FAILURE addHeaderIfNewUnsynchronized[3]" + " containsBlockWithHash : index:{}; hash:{}; ";
LOG.trace(message, headerIndex, maxUnverifiedBlockIndex, headerIndex, header.hash);
return false;
}
} else {
if (headerIndex <= maxUnverifiedBlockIndex) {
final String message = "FAILURE addHeaderIfNewUnsynchronized[4]" + " (headerIndex[{}] <= maxUnverifiedBlockIndex[{}]) adding header : index:{}; hash:{};";
LOG.trace(message, headerIndex, maxUnverifiedBlockIndex, headerIndex, header.hash);
return false;
}
}
}
if (localNodeData.getVerifiedHeaderPoolMap().containsKey(headerIndex)) {
final String message = "FAILURE addHeaderIfNewUnsynchronized[5]" + " getVerifiedHeaderPoolMap().containsKey():true; adding header : index:{}; hash:{};";
LOG.trace(message, headerIndex, header.hash);
return false;
}
if (localNodeData.getVerifiedHeaderPoolMap().containsKey(headerIndex)) {
final String message = "FAILURE addHeaderIfNewUnsynchronized[6]" + " getVerifiedHeaderPoolMap().containsKey(headerIndex):true; adding header : index:{}; hash:{};";
LOG.trace(message, headerIndex, header.hash);
return false;
}
if (localNodeData.getUnverifiedHeaderPoolSet().contains(header)) {
final String message = "FAILURE addHeaderIfNewUnsynchronized[7]" + " getUnverifiedHeaderPoolSet().contains(header):true; adding header : index:{}; hash:{};";
LOG.trace(message, headerIndex, header.hash);
return false;
}
localNodeData.getUnverifiedHeaderPoolSet().add(header);
localNodeData.updateHighestHeaderTime();
LOG.trace("SUCCESS addHeaderIfNewUnsynchronized adding header : index:{}; hash:{};", headerIndex, header.hash);
return true;
}
use of neo.model.core.Block in project neo-java by coranos.
the class LocalNodeDataSynchronizedUtil method requestHeaders.
/**
* request headers from the remote node.
*
* @param localNodeData
* the local node data to use.
* @param remoteNodeData
* the remote node data to use.
*/
public static void requestHeaders(final LocalNodeData localNodeData, final RemoteNodeData remoteNodeData) {
synchronized (localNodeData) {
final UInt256 hashRaw;
final long index;
if (localNodeData.getUnverifiedBlockPoolSet().isEmpty() && (!localNodeData.getVerifiedHeaderPoolMap().isEmpty())) {
final long highestHeaderIndex = localNodeData.getVerifiedHeaderPoolMap().lastKey();
final Header highestHeader = localNodeData.getVerifiedHeaderPoolMap().get(highestHeaderIndex);
LOG.debug("requestHeaders getVerifiedHeaderPoolMap height:{};hash:{};", highestHeaderIndex, highestHeader.hash);
hashRaw = highestHeader.hash;
index = highestHeader.getIndexAsLong();
} else {
final Block highestBlock = localNodeData.getBlockDb().getHeaderOfBlockWithMaxIndex();
if (highestBlock != null) {
LOG.debug("requestHeaders getHighestBlock height:{};hash:{};", highestBlock.getIndexAsLong(), highestBlock.hash);
hashRaw = highestBlock.hash;
index = highestBlock.getIndexAsLong();
} else {
LOG.debug("requestHeaders hash is genesis.");
hashRaw = GenesisBlockUtil.GENESIS_HASH;
index = GenesisBlockUtil.GENESIS_BLOCK.getIndexAsLong();
}
}
final byte[] ba = hashRaw.getBytesCopy();
final UInt256 hash = new UInt256(ba);
LOG.debug("requestHeaders index:{};hash:{};", index, hash);
// fixed bug at height 2000190
// final String goodHashStr =
// "8cb9fee28a48a45468e3c0a229fd4473288cdd9794c10cac7b8f4681ca404342";
// final UInt256 goodHash = new
// UInt256(ByteBuffer.wrap(Hex.decode(goodHashStr)));
// MessageUtil.sendGetHeaders(remoteNodeData, localNodeData, goodHash);
MessageUtil.sendGetHeaders(remoteNodeData, localNodeData, hash);
}
}
Aggregations