use of duckutil.TimeRecordAuto in project snowblossom by snowblossomcoin.
the class BlockchainUtil method addBlockToHistory.
private static void addBlockToHistory(BlockSummary.Builder bs, int shard, BlockImportList bil) {
try (TimeRecordAuto tra = TimeRecord.openAuto("BlockchainUtil.addBlockToHistoryMap")) {
if (!bs.getShardHistoryMap().containsKey(shard)) {
bs.putShardHistoryMap(shard, bil);
} else {
BlockImportList.Builder b = BlockImportList.newBuilder();
b.mergeFrom(bs.getShardHistoryMap().get(shard));
b.mergeFrom(bil);
bs.putShardHistoryMap(shard, b.build());
}
}
}
use of duckutil.TimeRecordAuto in project snowblossom by snowblossomcoin.
the class BlockIngestor method ingestBlock.
public boolean ingestBlock(Block blk) throws ValidationException {
ChainHash blockhash;
try (TimeRecordAuto tra_blk = TimeRecord.openAuto("BlockIngestor.ingestBlock");
MetricLog mlog = new MetricLog()) {
mlog.setOperation("ingest_block");
mlog.setModule("block_ingestor");
Validation.checkBlockBasics(node.getParams(), blk, true, false);
if (blk.getHeader().getShardId() != shard_id) {
throw new ValidationException("Block for incorrect shard");
}
blockhash = new ChainHash(blk.getHeader().getSnowHash());
mlog.set("hash", blockhash.toString());
mlog.set("height", blk.getHeader().getBlockHeight());
mlog.set("shard", blk.getHeader().getShardId());
mlog.set("size", blk.toByteString().size());
mlog.set("tx_count", blk.getTransactionsCount());
if (db.getBlockSummaryMap().containsKey(blockhash.getBytes())) {
return false;
}
ChainHash prevblock = new ChainHash(blk.getHeader().getPrevBlockHash());
BlockSummary prev_summary;
if (prevblock.equals(ChainHash.ZERO_HASH)) {
prev_summary = getStartSummary();
} else {
try (TimeRecordAuto tra_prv = TimeRecord.openAuto("BlockIngestor.getPrevSummary")) {
prev_summary = db.getBlockSummaryMap().get(prevblock.getBytes());
}
}
if (prev_summary == null) {
return false;
}
long tx_body_size = 0;
for (Transaction tx : blk.getTransactionsList()) {
tx_body_size += tx.getInnerData().size();
tx_body_size += tx.getTxHash().size();
}
BlockSummary summary = BlockchainUtil.getNewSummary(blk.getHeader(), prev_summary, node.getParams(), blk.getTransactionsCount(), tx_body_size, blk.getImportedBlocksList());
Validation.deepBlockValidation(node.getParams(), node.getUtxoHashedTrie(), blk, prev_summary);
summary = saveOtherChainIndexBits(summary, prev_summary, blk);
if (tx_index) {
try (TimeRecordAuto tra_tx = TimeRecord.openAuto("BlockIngestor.saveTx")) {
ByteString block_hash_str = blockhash.getBytes();
HashMap<ByteString, Transaction> tx_map = new HashMap<>();
for (Transaction tx : blk.getTransactionsList()) {
tx_map.put(tx.getTxHash(), tx);
}
db.getTransactionMap().putAll(tx_map);
}
}
try (TimeRecordAuto tra_tx = TimeRecord.openAuto("BlockIngestor.blockSave")) {
db.getBlockMap().put(blockhash.getBytes(), blk);
saveBlockChildMapping(blk.getHeader().getPrevBlockHash(), blockhash.getBytes());
for (ImportedBlock ib : blk.getImportedBlocksList()) {
// not positive we actually need this, but what the hell
saveBlockChildMapping(ib.getHeader().getPrevBlockHash(), ib.getHeader().getSnowHash());
node.getDB().getBlockHeaderMap().put(ib.getHeader().getSnowHash(), ib.getHeader());
}
db.setBestBlockAt(blk.getHeader().getShardId(), blk.getHeader().getBlockHeight(), BlockchainUtil.readInteger(summary.getWorkSum()));
// THIS IS SUPER IMPORTANT!!!!
// the summary being saved in the summary map acts as a signal that
// - this block is fully stored
// - we have the utxo saved
// - we have the block itself saved
// - if we are using tx_index, we have the transactions saved
// - the previous block summary is also saved, which by induction means
// that we have every block from this one all the way back to block 0
// In short, after the summary is written, things can depend on this being
// a valid and correct block that goes all the way back to block 0.
// It might not be in the main chain, but it can be counted on to be valid chain
db.getBlockSummaryMap().put(blockhash.getBytes(), summary);
mlog.set("saved", 1);
}
if (ShardUtil.shardSplit(summary, params)) {
for (int child : ShardUtil.getShardChildIds(summary.getHeader().getShardId())) {
mlog.set("shard_split", 1);
try {
node.openShard(child);
} catch (Exception e) {
logger.warning(" Unable to open shard: " + e);
}
}
}
ChainHash prev_hash = new ChainHash(blk.getHeader().getPrevBlockHash());
logger.info(String.format("New block: Shard %d Height %d %s (tx:%d sz:%d) - from %s", shard_id, blk.getHeader().getBlockHeight(), blockhash, blk.getTransactionsCount(), blk.toByteString().size(), prev_hash));
node.getBlockForge().tickle(summary);
SnowUserService u = node.getUserService();
if (u != null) {
u.tickleBlocks();
}
if (BlockchainUtil.isBetter(chainhead, summary)) {
mlog.set("head_update", 1);
chainhead = summary;
db.getBlockSummaryMap().put(HEAD, summary);
// System.out.println("UTXO at new root: " + HexUtil.getHexString(summary.getHeader().getUtxoRootHash()));
// node.getUtxoHashedTrie().printTree(summary.getHeader().getUtxoRootHash());
updateHeights(summary);
logger.info(String.format("New chain tip: Shard %d Height %d %s (tx:%d sz:%d)", shard_id, blk.getHeader().getBlockHeight(), blockhash, blk.getTransactionsCount(), blk.toByteString().size()));
String age = MiscUtils.getAgeSummary(System.currentTimeMillis() - blk.getHeader().getTimestamp());
logger.info(String.format(" The activated field is %d (%s). This block was %s ago.", chainhead.getActivatedField(), params.getSnowFieldInfo(chainhead.getActivatedField()).getName(), age));
if (u != null) {
u.tickleBlocks();
}
node.getMemPool(shard_id).tickleBlocks(new ChainHash(summary.getHeader().getUtxoRootHash()));
node.getPeerage().sendAllTips(summary.getHeader().getShardId());
}
}
return true;
}
use of duckutil.TimeRecordAuto in project snowblossom by snowblossomcoin.
the class ShardBlockForge method getBlockTemplate.
public BlockTemplate getBlockTemplate(SubscribeBlockTemplateRequest mine_to) {
try (TimeRecordAuto tra_gbt = TimeRecord.openAuto("ShardBlockForge.getBlockTemplate")) {
last_template_request = System.currentTimeMillis();
if (node.getBlockIngestor(0).getHead() == null) {
// Let the old thing do the genesis gag
return node.getBlockForge(0).getBlockTemplate(mine_to);
}
ArrayList<BlockConcept> possible_set = current_top_concepts;
if (possible_set == null)
return null;
if (possible_set.size() == 0)
return null;
Random rnd = new Random();
// Random
// BlockConcept selected = possible_set.get( rnd.nextInt(possible_set.size()) );
// First 4
// BlockConcept selected = possible_set.get( rnd.nextInt(Math.min(4,possible_set.size())) );
// First
BlockConcept selected = possible_set.get(0);
try {
Block block = fleshOut(selected, mine_to);
if (block != null) {
return BlockTemplate.newBuilder().setBlock(block).setAdvancesShard(selected.getAdvancesShard()).build();
} else {
return null;
}
} catch (ValidationException e) {
logger.warning("Validation failed in block fleshOut: " + e);
return null;
}
} catch (Throwable t) {
logger.warning("Exception in getBlockTemplate: " + t);
t.printStackTrace();
return null;
}
}
use of duckutil.TimeRecordAuto in project snowblossom by snowblossomcoin.
the class ShardUtxoImport method getImportBlock.
/**
* Gets the ImportedBlock as if *all* the exported shards were to be imported.
* That way this can be filtered for what is needed but cached as a whole thing.
*/
public ImportedBlock getImportBlock(ChainHash hash) {
synchronized (cache) {
ImportedBlock ib = cache.get(hash);
if (ib != null)
return ib;
}
try (TimeRecordAuto tra = TimeRecord.openAuto("ShardUtxoImport.getImportBlock")) {
ImportedBlock ib = null;
if (node.getDB().getBlockTrust(hash)) {
ib = node.getDB().getImportedBlockMap().get(hash.getBytes());
}
if (ib == null) {
ImportedBlock.Builder ibb = ImportedBlock.newBuilder();
Block blk = node.getDB().getBlockMap().get(hash.getBytes());
if (blk == null)
return null;
ibb.setHeader(blk.getHeader());
Set<Integer> cover_set = ShardUtil.getCoverSet(blk.getHeader().getShardId(), node.getParams());
Map<Integer, ImportedOutputList.Builder> output_list_map = new TreeMap<>();
for (Transaction tx : blk.getTransactionsList()) {
TransactionInner tx_inner = TransactionUtil.getInner(tx);
ArrayList<ByteString> tx_out_wire_lst;
try {
tx_out_wire_lst = TransactionUtil.extractWireFormatTxOut(tx);
} catch (ValidationException e) {
throw new RuntimeException(e);
}
int out_idx = 0;
for (TransactionOutput tx_out : tx_inner.getOutputsList()) {
if (!cover_set.contains(tx_out.getTargetShard())) {
int ts = tx_out.getTargetShard();
if (!output_list_map.containsKey(ts)) {
output_list_map.put(ts, ImportedOutputList.newBuilder());
}
ImportedOutput io = ImportedOutput.newBuilder().setRawOutput(tx_out_wire_lst.get(out_idx)).setTxId(tx.getTxHash()).setOutIdx(out_idx).build();
output_list_map.get(ts).addTxOuts(io);
}
out_idx++;
}
}
for (Map.Entry<Integer, ImportedOutputList.Builder> me : output_list_map.entrySet()) {
ibb.putImportOutputs(me.getKey(), me.getValue().build());
}
ib = ibb.build();
}
try (TimeRecordAuto tra_cache = TimeRecord.openAuto("ShardUtxoImport.getImportBlock_cachesave")) {
synchronized (cache) {
cache.put(hash, ib);
}
}
return ib;
}
}
use of duckutil.TimeRecordAuto in project snowblossom by snowblossomcoin.
the class SnowUserService method submitBlock.
@Override
public void submitBlock(Block block, StreamObserver<SubmitReply> responseObserver) {
try (TimeRecordAuto tra = TimeRecord.openAuto("SnowUserService.submitBlock")) {
try {
logger.info("Submit block: " + node.getForgeInfo().getHeaderString(block.getHeader()));
int shard_id = block.getHeader().getShardId();
// TODO check to see if we are tracking that shard
node.getBlockIngestor(shard_id).ingestBlock(block);
logger.info("Accepted block: " + node.getForgeInfo().getBlockTextSummary(block.getHeader()));
} catch (ValidationException e) {
logger.info("Rejecting block: " + e);
logger.info("Rejected block: " + node.getForgeInfo().getBlockTextSummary(block.getHeader()));
responseObserver.onNext(SubmitReply.newBuilder().setSuccess(false).setErrorMessage("Rejecting block: " + e).build());
responseObserver.onCompleted();
return;
}
responseObserver.onNext(SubmitReply.newBuilder().setSuccess(true).build());
responseObserver.onCompleted();
}
}
Aggregations