/// <inheritdoc cref="BaseStore.PutTxIdBlockHashIndex(TxId, BlockHash)"/> public override void PutTxIdBlockHashIndex(TxId txId, BlockHash blockHash) { _txIdBlockHashIndexDb.Put( TxIdBlockHashIndexKey(txId, blockHash), blockHash.ToByteArray() ); }
internal ITrie GetTrie(BlockHash blockHash) => new MerkleTrie( _stateKeyValueStore, new HashNode( new HashDigest <SHA256>( _stateHashKeyValueStore.Get(blockHash.ToByteArray()))));
/// <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); }
public void DefaultConstructor() { BlockHash def = default; TestUtils.AssertBytesEqual(new byte[32].ToImmutableArray(), def.ByteArray); TestUtils.AssertBytesEqual(new byte[32], def.ToByteArray()); }
/// <inheritdoc cref="BaseStore.PutTxIdBlockHashIndex(TxId, BlockHash)"/> public override void PutTxIdBlockHashIndex(TxId txId, BlockHash blockHash) { var path = TxIdBlockHashIndexPath(txId, blockHash); var dirPath = path.GetDirectory(); CreateDirectoryRecursively(_txIdBlockHashIndex, dirPath); _txIdBlockHashIndex.WriteAllBytes(path, blockHash.ToByteArray()); }
public IValue?GetState(string stateKey, BlockHash?blockHash = null, Guid?chainId = null) { if (blockHash is null) { throw new ArgumentNullException(nameof(blockHash)); } var stateHash = _stateHashKeyValueStore.Get(blockHash?.ToByteArray() !); var stateTrie = new MerkleTrie( _stateKeyValueStore, new HashNode(new HashDigest <SHA256>(stateHash)), _secure); var key = Encoding.UTF8.GetBytes(stateKey); return(stateTrie.TryGet(key, out IValue? value) ? value : null); }
/// <summary> /// Executes the <paramref name="actions"/> step by step, and emits /// <see cref="ActionEvaluation"/> for each step. /// </summary> /// <param name="blockHash">The <see cref="Block{T}.Hash"/> of <see cref="Block{T}"/> that /// <paramref name="actions"/> belongs to.</param> /// <param name="blockIndex">The <see cref="Block{T}.Index"/> of <see cref="Block{T}"/> that /// <paramref name="actions"/> belongs to.</param> /// <param name="txid">The <see cref="Transaction{T}.Id"/> of <see cref="Transaction{T}"/> /// that <paramref name="actions"/> belongs to. This can be <c>null</c> on rehearsal mode /// or if an action is a <see cref="IBlockPolicy{T}.BlockAction"/>.</param> /// <param name="previousStates">The states immediately before <paramref name="actions"/> /// being executed. Note that its <see cref="IAccountStateDelta.UpdatedAddresses"/> are /// remained to the returned next states.</param> /// <param name="minerAddress">An address of block miner.</param> /// <param name="signer">Signer of the <paramref name="actions"/>.</param> /// <param name="signature"><see cref="Transaction{T}"/> signature used to generate random /// seeds.</param> /// <param name="actions">Actions to evaluate.</param> /// <param name="rehearsal">Pass <c>true</c> if it is intended /// to be dry-run (i.e., the returned result will be never used). /// The default value is <c>false</c>.</param> /// <param name="previousBlockStatesTrie">The trie to contain states at previous block. /// </param> /// <param name="blockAction">Pass <c>true</c> if it is /// <see cref="IBlockPolicy{T}.BlockAction"/>.</param> /// <returns>Enumerates <see cref="ActionEvaluation"/>s for each one in /// <paramref name="actions"/>. The order is the same to the <paramref name="actions"/>. /// Note that each <see cref="IActionContext.Random"/> object /// has a unconsumed state. /// </returns> internal static IEnumerable <ActionEvaluation> EvaluateActionsGradually( BlockHash blockHash, long blockIndex, TxId?txid, IAccountStateDelta previousStates, Address minerAddress, Address signer, byte[] signature, IImmutableList <IAction> actions, bool rehearsal = false, ITrie previousBlockStatesTrie = null, bool blockAction = false) { ActionContext CreateActionContext( IAccountStateDelta prevStates, int randomSeed ) => new ActionContext( signer: signer, miner: minerAddress, blockIndex: blockIndex, previousStates: prevStates, randomSeed: randomSeed, rehearsal: rehearsal, previousBlockStatesTrie: previousBlockStatesTrie, blockAction: blockAction ); byte[] hashedSignature; using (var hasher = SHA1.Create()) { hashedSignature = hasher.ComputeHash(signature); } byte[] blockHashBytes = blockHash.ToByteArray(); int seed = (blockHashBytes.Length > 0 ? BitConverter.ToInt32(blockHashBytes, 0) : 0) ^ (signature.Any() ? BitConverter.ToInt32(hashedSignature, 0) : 0); IAccountStateDelta states = previousStates; Exception exc = null; ILogger logger = Log.ForContext <ActionEvaluation>(); foreach (IAction action in actions) { ActionContext context = CreateActionContext(states, seed); IAccountStateDelta nextStates = context.PreviousStates; try { DateTimeOffset actionExecutionStarted = DateTimeOffset.Now; nextStates = action.Execute(context); TimeSpan spent = DateTimeOffset.Now - actionExecutionStarted; logger.Verbose($"{action} execution spent {spent.TotalMilliseconds} ms."); } catch (Exception e) { if (rehearsal) { var msg = $"The action {action} threw an exception during its " + "rehearsal. It is probably because the logic of the " + $"action {action} is not enough generic so that it " + "can cover every case including rehearsal mode.\n" + "The IActionContext.Rehearsal property also might be " + "useful to make the action can deal with the case of " + "rehearsal mode.\n" + "See also this exception's InnerException property."; exc = new UnexpectedlyTerminatedActionException( null, null, null, null, action, msg, e ); } else { var stateRootHash = context.PreviousStateRootHash; var msg = $"The action {action} (block #{blockIndex} {blockHash}, tx {txid}, " + $"state root hash {stateRootHash}) threw an exception " + "during execution. See also this exception's InnerException property."; logger.Error("{Message}\nInnerException: {ExcMessage}", msg, e.Message); exc = new UnexpectedlyTerminatedActionException( blockHash, blockIndex, txid, stateRootHash, action, msg, e ); } } // As IActionContext.Random is stateful, we cannot reuse // the context which is once consumed by Execute(). ActionContext equivalentContext = CreateActionContext(states, seed); yield return(new ActionEvaluation( action, equivalentContext, nextStates, exc )); states = nextStates; unchecked { seed++; } } }
public bool ContainsBlockStates(BlockHash blockHash) { return(_stateHashKeyValueStore.Exists(blockHash.ToByteArray())); }
public HashDigest <SHA256> GetRootHash(BlockHash blockHash) => new HashDigest <SHA256>(_stateHashKeyValueStore.Get(blockHash.ToByteArray()));
public static void AssertBytesEqual(BlockHash?expected, BlockHash?actual) => AssertBytesEqual(expected?.ToByteArray(), actual?.ToByteArray());