Ejemplo n.º 1
0
 /// <inheritdoc cref="BaseStore.PutTxIdBlockHashIndex(TxId, BlockHash)"/>
 public override void PutTxIdBlockHashIndex(TxId txId, BlockHash blockHash)
 {
     _txIdBlockHashIndexDb.Put(
         TxIdBlockHashIndexKey(txId, blockHash),
         blockHash.ToByteArray()
         );
 }
Ejemplo n.º 2
0
 internal ITrie GetTrie(BlockHash blockHash)
 =>
 new MerkleTrie(
     _stateKeyValueStore,
     new HashNode(
         new HashDigest <SHA256>(
             _stateHashKeyValueStore.Get(blockHash.ToByteArray()))));
Ejemplo n.º 3
0
        /// <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);
        }
Ejemplo n.º 4
0
        public void DefaultConstructor()
        {
            BlockHash def = default;

            TestUtils.AssertBytesEqual(new byte[32].ToImmutableArray(), def.ByteArray);
            TestUtils.AssertBytesEqual(new byte[32], def.ToByteArray());
        }
Ejemplo n.º 5
0
        /// <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());
        }
Ejemplo n.º 6
0
        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);
        }
Ejemplo n.º 7
0
        /// <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++;
                }
            }
        }
Ejemplo n.º 8
0
 public bool ContainsBlockStates(BlockHash blockHash)
 {
     return(_stateHashKeyValueStore.Exists(blockHash.ToByteArray()));
 }
Ejemplo n.º 9
0
 public HashDigest <SHA256> GetRootHash(BlockHash blockHash)
 => new HashDigest <SHA256>(_stateHashKeyValueStore.Get(blockHash.ToByteArray()));
Ejemplo n.º 10
0
 public static void AssertBytesEqual(BlockHash?expected, BlockHash?actual) =>
 AssertBytesEqual(expected?.ToByteArray(), actual?.ToByteArray());