public bool TryRemoveChainedHeader(UInt256 blockHash) { var key = MakeHeaderKey(blockHash); Slice existingValue; if (!db.TryGet(ReadOptions.Default, key, out existingValue)) { return(false); } var chainedHeader = DataDecoder.DecodeChainedHeader(existingValue.ToArray()); var writeBatch = new WriteBatch(); try { writeBatch.Delete(key); writeBatch.Delete(MakeTotalWorkKey(blockHash, chainedHeader.TotalWork)); db.Write(WriteOptions.Default, writeBatch); } finally { writeBatch.Dispose(); } return(true); }
public ChainedHeader FindMaxTotalWork() { using (var handle = this.cursorCache.TakeItem()) { var cursor = handle.Item; Api.JetSetCurrentIndex(cursor.jetSession, cursor.blockHeadersTableId, "IX_TotalWork"); // IX_TotalWork is in reverse order, so higher total work comes first if (Api.TryMoveFirst(cursor.jetSession, cursor.blockHeadersTableId)) { var maxTotalWork = BigInteger.Zero; var candidateHeaders = new List <ChainedHeader>(); do { // check if this block is valid var valid = Api.RetrieveColumnAsBoolean(cursor.jetSession, cursor.blockHeadersTableId, cursor.blockHeaderValidColumnId); if (valid == null || valid.Value) { // decode chained header var chainedHeader = DataDecoder.DecodeChainedHeader(Api.RetrieveColumn(cursor.jetSession, cursor.blockHeadersTableId, cursor.blockHeaderBytesColumnId)); // initialize max total work, if it isn't yet if (maxTotalWork == BigInteger.Zero) { maxTotalWork = chainedHeader.TotalWork; } // add this header as a candidate if it ties the max total work if (chainedHeader.TotalWork >= maxTotalWork) { candidateHeaders.Add(chainedHeader); } else { break; } } }while (Api.TryMoveNext(cursor.jetSession, cursor.blockHeadersTableId)); // take the earliest header seen with the max total work candidateHeaders.Sort((left, right) => left.DateSeen.CompareTo(right.DateSeen)); return(candidateHeaders.FirstOrDefault()); } // no valid chained header found return(null); } }
public bool TryGetChainedHeader(UInt256 blockHash, out ChainedHeader chainedHeader) { var key = MakeHeaderKey(blockHash); Slice value; if (db.TryGet(new ReadOptions(), key, out value)) { chainedHeader = DataDecoder.DecodeChainedHeader(value.ToArray()); return(true); } else { chainedHeader = default(ChainedHeader); return(false); } }
public IEnumerable <ChainedHeader> ReadChainedHeaders() { using (var handle = this.cursorCache.TakeItem()) { var cursor = handle.Item; Api.JetSetCurrentIndex(cursor.jetSession, cursor.blockHeadersTableId, null); if (Api.TryMoveFirst(cursor.jetSession, cursor.blockHeadersTableId)) { do { // decode chained header and return var chainedHeader = DataDecoder.DecodeChainedHeader(Api.RetrieveColumn(cursor.jetSession, cursor.blockHeadersTableId, cursor.blockHeaderBytesColumnId)); yield return(chainedHeader); }while (Api.TryMoveNext(cursor.jetSession, cursor.blockHeadersTableId)); } } }
public bool TryGetChainedHeader(UInt256 blockHash, out ChainedHeader chainedHeader) { using (var handle = this.cursorCache.TakeItem()) { var cursor = handle.Item; Api.JetSetCurrentIndex(cursor.jetSession, cursor.blockHeadersTableId, "IX_BlockHash"); Api.MakeKey(cursor.jetSession, cursor.blockHeadersTableId, DbEncoder.EncodeUInt256(blockHash), MakeKeyGrbit.NewKey); if (Api.TrySeek(cursor.jetSession, cursor.blockHeadersTableId, SeekGrbit.SeekEQ)) { chainedHeader = DataDecoder.DecodeChainedHeader(Api.RetrieveColumn(cursor.jetSession, cursor.blockHeadersTableId, cursor.blockHeaderBytesColumnId)); return(true); } else { chainedHeader = default(ChainedHeader); return(false); } } }
public bool TryGetHeader(UInt256 blockHash, out ChainedHeader header) { CheckTransaction(); using (SetSessionContext()) { Api.JetSetCurrentIndex(this.jetSession, this.headersTableId, "IX_BlockHash"); Api.MakeKey(this.jetSession, this.headersTableId, DbEncoder.EncodeUInt256(blockHash), MakeKeyGrbit.NewKey); if (Api.TrySeek(this.jetSession, this.headersTableId, SeekGrbit.SeekEQ)) { var headerBytes = Api.RetrieveColumn(this.jetSession, this.headersTableId, this.headerBytesColumnId); header = DataDecoder.DecodeChainedHeader(headerBytes); return(true); } header = default(ChainedHeader); return(false); } }
public IEnumerable <ChainedHeader> ReadChainedHeaders() { using (var snapshot = db.GetSnapshot()) { var readOptions = new ReadOptions { Snapshot = snapshot }; using (var iterator = db.NewIterator(readOptions)) { iterator.SeekToFirst(); while (iterator.Valid() && iterator.Key().ToArray()[0] == HEADER_PREFIX) { var chainedHeader = DataDecoder.DecodeChainedHeader(iterator.Value().ToArray()); yield return(chainedHeader); iterator.Next(); } } } }
public ChainedHeader FindMaxTotalWork() { var maxTotalWork = BigInteger.Zero; var candidateHeaders = new List <ChainedHeader>(); using (var snapshot = db.GetSnapshot()) { var readOptions = new ReadOptions { Snapshot = snapshot }; using (var iterator = db.NewIterator(readOptions)) { // totalWork will be sorted lowest to highest iterator.SeekToLast(); while (iterator.Valid()) { var key = iterator.Key().ToArray(); if (key[0] != TOTAL_WORK_PREFIX) { break; } UInt256 blockHash; BigInteger totalWork; DecodeTotalWorkKey(key, out blockHash, out totalWork); // check if this block is valid bool isValid; var blockInvalidKey = MakeBlockInvalidKey(blockHash); Slice blockInvalidSlice; if (db.TryGet(readOptions, blockInvalidKey, out blockInvalidSlice)) { var blockInvalidBytes = blockInvalidSlice.ToArray(); isValid = !(blockInvalidBytes.Length == 1 && blockInvalidBytes[0] == 1); } else { isValid = true; } if (isValid) { var headerKey = MakeHeaderKey(blockHash); Slice headerSlice; if (db.TryGet(readOptions, headerKey, out headerSlice)) { // decode chained header var chainedHeader = DataDecoder.DecodeChainedHeader(headerSlice.ToArray()); // initialize max total work, if it isn't yet if (maxTotalWork == BigInteger.Zero) { maxTotalWork = chainedHeader.TotalWork; } if (chainedHeader.TotalWork > maxTotalWork) { maxTotalWork = chainedHeader.TotalWork; candidateHeaders = new List <ChainedHeader>(); } // add this header as a candidate if it ties the max total work if (chainedHeader.TotalWork >= maxTotalWork) { candidateHeaders.Add(chainedHeader); } else { break; } } } iterator.Prev(); } } } // take the earliest header seen with the max total work candidateHeaders.Sort((left, right) => left.DateSeen.CompareTo(right.DateSeen)); return(candidateHeaders.FirstOrDefault()); }
private void InitWorkQueueDictionaries() { unspentTxes = CreateWorkQueueDictionary <UInt256, UnspentTx>(MakeUnspentTxKey, x => DataDecoder.DecodeUnspentTx(x)); unspentTxesApplier = CreateApplier <UInt256, UnspentTx>(MakeUnspentTxKey, x => DataEncoder.EncodeUnspentTx(x)); unspentTxes.WorkQueue.LinkTo(unspentTxesApplier, new DataflowLinkOptions { PropagateCompletion = true }); unspentTxOutputs = CreateWorkQueueDictionary <TxOutputKey, TxOutput>(MakeUnspentTxOutputKey, x => DataDecoder.DecodeTxOutput(x)); unspentTxOutputsApplier = CreateApplier <TxOutputKey, TxOutput>(MakeUnspentTxOutputKey, x => DataEncoder.EncodeTxOutput(x)); unspentTxOutputs.WorkQueue.LinkTo(unspentTxOutputsApplier, new DataflowLinkOptions { PropagateCompletion = true }); globals = CreateWorkQueueDictionary <GlobalValue, Slice>(MakeGlobalKey, x => x); globalsApplier = CreateApplier <GlobalValue, Slice>(MakeGlobalKey, x => x.ToArray()); globals.WorkQueue.LinkTo(globalsApplier, new DataflowLinkOptions { PropagateCompletion = true }); headers = CreateWorkQueueDictionary <UInt256, ChainedHeader>(MakeHeaderKey, x => DataDecoder.DecodeChainedHeader(x)); headersApplier = CreateApplier <UInt256, ChainedHeader>(MakeHeaderKey, x => DataEncoder.EncodeChainedHeader(x)); headers.WorkQueue.LinkTo(headersApplier, new DataflowLinkOptions { PropagateCompletion = true }); spentTxes = CreateWorkQueueDictionary <int, BlockSpentTxes>(MakeSpentTxesKey, x => DataDecoder.DecodeBlockSpentTxes(x)); spentTxesApplier = CreateApplier <int, BlockSpentTxes>(MakeSpentTxesKey, x => DataEncoder.EncodeBlockSpentTxes(x)); spentTxes.WorkQueue.LinkTo(spentTxesApplier, new DataflowLinkOptions { PropagateCompletion = true }); unmintedTxes = CreateWorkQueueDictionary <UInt256, IImmutableList <UnmintedTx> >(MakeUnmintedTxesKey, x => DataDecoder.DecodeUnmintedTxList(x)); unmintedTxesApplier = CreateApplier <UInt256, IImmutableList <UnmintedTx> >(MakeUnmintedTxesKey, x => DataEncoder.EncodeUnmintedTxList(x)); unmintedTxes.WorkQueue.LinkTo(unmintedTxesApplier, new DataflowLinkOptions { PropagateCompletion = true }); }
public bool TryGetHeader(UInt256 blockHash, out ChainedHeader header) { CheckTransaction(); return(CursorTryGet(blockHash, out header, headers, MakeHeaderKey, x => DataDecoder.DecodeChainedHeader(x))); }