/// <inheritdoc/> public override IEnumerable <Tuple <HashDigest <SHA256>, long> > IterateStateReferences( Guid chainId, string key, long?highestIndex, long?lowestIndex, int?limit) { highestIndex ??= long.MaxValue; lowestIndex ??= 0; limit ??= int.MaxValue; if (highestIndex < lowestIndex) { var message = $"highestIndex({highestIndex}) must be greater than or equal to " + $"lowestIndex({lowestIndex})"; throw new ArgumentException( message, nameof(highestIndex)); } byte[] keyBytes = RocksDBStoreBitConverter.GetBytes(key); byte[] prefix = StateRefKeyPrefix.Concat(keyBytes).ToArray(); return(IterateStateReferences( chainId, prefix, highestIndex.Value, lowestIndex.Value, limit.Value)); }
/// <inheritdoc cref="BaseStore.AppendIndex(Guid, BlockHash)"/> public override long AppendIndex(Guid chainId, BlockHash hash) { long index = CountIndex(chainId); try { byte[] indexBytes = RocksDBStoreBitConverter.GetBytes(index); byte[] key = IndexKeyPrefix.Concat(indexBytes).ToArray(); ColumnFamilyHandle cf = GetColumnFamily(_chainDb, chainId); using var writeBatch = new WriteBatch(); writeBatch.Put(key, hash.ToByteArray(), cf); writeBatch.Put(IndexCountKey, RocksDBStoreBitConverter.GetBytes(index + 1), cf); _chainDb.Write(writeBatch); } catch (Exception e) { LogUnexpectedException(nameof(AppendIndex), e); } return(index); }
/// <inheritdoc/> public override void PutTransaction <T>(Transaction <T> tx) { if (_txCache.ContainsKey(tx.Id)) { return; } byte[] key = TxKey(tx.Id); if (!(_txIndexDb.Get(key) is null)) { return; } long timestamp = tx.Timestamp.ToUnixTimeSeconds(); string txDbName = $"epoch{(int)timestamp / _txEpochUnitSeconds}"; _rwTxLock.EnterWriteLock(); try { if (!_txDbCache.TryGetValue(txDbName, out RocksDb txDb)) { txDb = RocksDBUtils.OpenRocksDb(_options, TxDbPath(txDbName)); _txDbCache.AddOrUpdate(txDbName, txDb); } txDb.Put(key, tx.Serialize(true)); _txIndexDb.Put(key, RocksDBStoreBitConverter.GetBytes(txDbName)); _txCache.AddOrUpdate(tx.Id, tx); } finally { _rwTxLock.ExitWriteLock(); } }
private byte[] StateRefKey(string stateKey, long blockIndex) { byte[] stateKeyBytes = RocksDBStoreBitConverter.GetBytes(stateKey); byte[] blockIndexBytes = RocksDBStoreBitConverter.GetBytes(blockIndex); return(StateRefKeyPrefix .Concat(stateKeyBytes) .Concat(blockIndexBytes) .ToArray()); }
/// <inheritdoc/> public override void IncreaseTxNonce(Guid chainId, Address signer, long delta = 1) { ColumnFamilyHandle cf = GetColumnFamily(_chainDb, chainId); long nextNonce = GetTxNonce(chainId, signer) + delta; byte[] key = TxNonceKey(signer); byte[] bytes = RocksDBStoreBitConverter.GetBytes(nextNonce); _chainDb.Put(key, bytes, cf); }
/// <inheritdoc/> public override void ForkBlockIndexes( Guid sourceChainId, Guid destinationChainId, HashDigest <SHA256> branchPoint) { HashDigest <SHA256>?genesisHash = IterateIndexes(sourceChainId, 0, 1) .Cast <HashDigest <SHA256>?>() .FirstOrDefault(); if (genesisHash is null || branchPoint.Equals(genesisHash)) { return; } ColumnFamilyHandle cf = GetColumnFamily(_chainDb, destinationChainId); var writeBatch = new WriteBatch(); long index = 0; try { foreach (Iterator it in IterateDb(_chainDb, IndexKeyPrefix, sourceChainId)) { byte[] hashBytes = it.Value(); writeBatch.Put(it.Key(), hashBytes, cf); index += 1; if (writeBatch.Count() >= ForkWriteBatchSize) { _chainDb.Write(writeBatch); writeBatch.Dispose(); writeBatch = new WriteBatch(); } if (branchPoint.ToByteArray().SequenceEqual(hashBytes)) { break; } } } finally { _chainDb.Write(writeBatch); writeBatch.Dispose(); } _chainDb.Put( IndexCountKey, RocksDBStoreBitConverter.GetBytes(index), cf ); }
/// <inheritdoc/> public override void PutBlock <T>(Block <T> block) { if (_blockCache.ContainsKey(block.Hash)) { return; } byte[] key = BlockKey(block.Hash); if (!(_blockIndexDb.Get(key) is null)) { return; } long timestamp = block.Timestamp.ToUnixTimeSeconds(); foreach (Transaction <T> tx in block.Transactions) { PutTransaction(tx); } _rwBlockLock.EnterWriteLock(); try { string blockDbName = $"epoch{timestamp / _blockEpochUnitSeconds}"; RocksDb blockDb; lock (_blockDbCache) { if (!_blockDbCache.TryGetValue(blockDbName, out blockDb)) { blockDb = RocksDBUtils.OpenRocksDb(_options, BlockDbPath(blockDbName)); _blockDbCache.AddOrUpdate(blockDbName, blockDb); } } BlockDigest digest = BlockDigest.FromBlock(block); byte[] value = digest.Serialize(); blockDb.Put(key, value); _blockIndexDb.Put(key, RocksDBStoreBitConverter.GetBytes(blockDbName)); _blockCache.AddOrUpdate(block.Hash, digest); } catch (Exception e) { LogUnexpectedException(nameof(PutBlock), e); } finally { _rwBlockLock.ExitWriteLock(); } }
/// <inheritdoc/> public override void IncreaseTxNonce(Guid chainId, Address signer, long delta = 1) { try { ColumnFamilyHandle cf = GetColumnFamily(_chainDb, chainId); long nextNonce = GetTxNonce(chainId, signer) + delta; byte[] key = TxNonceKey(signer); byte[] bytes = RocksDBStoreBitConverter.GetBytes(nextNonce); _chainDb.Put(key, bytes, cf); } catch (Exception e) { LogUnexpectedException(nameof(IncreaseTxNonce), e); } }
/// <inheritdoc/> public override long AppendIndex(Guid chainId, HashDigest <SHA256> hash) { long index = CountIndex(chainId); byte[] indexBytes = RocksDBStoreBitConverter.GetBytes(index); byte[] key = IndexKeyPrefix.Concat(indexBytes).ToArray(); ColumnFamilyHandle cf = GetColumnFamily(_chainDb, chainId); using var writeBatch = new WriteBatch(); writeBatch.Put(key, hash.ToByteArray(), cf); writeBatch.Put(IndexCountKey, RocksDBStoreBitConverter.GetBytes(index + 1), cf); _chainDb.Write(writeBatch); return(index); }
/// <inheritdoc cref="BaseStore.ForkBlockIndexes(Guid, Guid, BlockHash)"/> public override void ForkBlockIndexes( Guid sourceChainId, Guid destinationChainId, BlockHash branchpoint ) { BlockHash?genesisHash = IterateIndexes(sourceChainId, 0, 1).FirstOrDefault(); if (genesisHash is null || branchpoint.Equals(genesisHash)) { return; } ColumnFamilyHandle srcCf = GetColumnFamily(_chainDb, sourceChainId); ColumnFamilyHandle destCf = GetColumnFamily(_chainDb, destinationChainId); foreach (Iterator k in IterateDb(_chainDb, IndexKeyPrefix, destinationChainId)) { _chainDb.Remove(k.Key(), destCf); } long bpIndex = GetBlockIndex(branchpoint).Value; if (GetPreviousChainInfo(srcCf) is { } chainInfo&& chainInfo.Item2 == bpIndex) { ForkBlockIndexes(chainInfo.Item1, destinationChainId, branchpoint); return; } _chainDb.Put(PreviousChainIdKey, sourceChainId.ToByteArray(), destCf); _chainDb.Put( PreviousChainIndexKey, RocksDBStoreBitConverter.GetBytes(bpIndex), destCf ); _chainDb.Put( IndexCountKey, RocksDBStoreBitConverter.GetBytes(bpIndex + 1), destCf ); AddFork(srcCf, destinationChainId); }
/// <inheritdoc cref="BaseStore.IndexBlockHash(Guid, long)"/> public override BlockHash?IndexBlockHash(Guid chainId, long index) { if (index < 0) { index += CountIndex(chainId); if (index < 0) { return(null); } } ColumnFamilyHandle cf = GetColumnFamily(_chainDb, chainId); byte[] indexBytes = RocksDBStoreBitConverter.GetBytes(index); byte[] key = IndexKeyPrefix.Concat(indexBytes).ToArray(); byte[] bytes = _chainDb.Get(key, cf); return(bytes is null ? (BlockHash?)null : new BlockHash(bytes)); }
private BlockHash?IndexBlockHash(Guid chainId, long index, bool includeDeleted) { try { if (index < 0) { index += CountIndex(chainId); if (index < 0) { return(null); } } ColumnFamilyHandle cf = GetColumnFamily(_chainDb, chainId); if (!includeDeleted && IsDeletionMarked(cf)) { return(null); } if (GetPreviousChainInfo(cf) is { } chainInfo&& chainInfo.Item2 >= index) { return(IndexBlockHash(chainInfo.Item1, index, true)); } byte[] indexBytes = RocksDBStoreBitConverter.GetBytes(index); byte[] key = IndexKeyPrefix.Concat(indexBytes).ToArray(); byte[] bytes = _chainDb.Get(key, cf); return(bytes is null ? (BlockHash?)null : new BlockHash(bytes)); } catch (Exception e) { LogUnexpectedException(nameof(IndexBlockHash), e); } return(null); }