public bool Check(IHeaderValidationContext context, ref BlockValidationState validationState)
        {
            Protocol.Types.BlockHeader header = context.Header;

            if (header.PreviousBlockHash == null)
            {
                validationState.Invalid(BlockValidationStateResults.InvalidHeader, "prev-hash-null", "previous hash null, allowed only on genesis block");
                return(false);
            }

            // ensures tip previous header is present.
            if (!context.ChainState.TryGetKnownHeaderNode(context.Header.PreviousBlockHash !, out HeaderNode? previousNode))
            {
                //previous tip header not found, abort.
                validationState.Invalid(BlockValidationStateResults.MissingPreviousHeader, "prev-blk-not-found", "previous header not found, can't connect headers");
                return(false);
            }

            if (previousNode.IsInvalid())
            {
                validationState.Invalid(BlockValidationStateResults.CachedInvalid, "bad-prevblk", "previous block invalid");
                return(false);
            }

            context.SetData(PREV_BLOCK, previousNode);

            return(true);
        }
예제 #2
0
        public bool Check(IBlockValidationContext context, ref BlockValidationState validationState)
        {
            if (IsBlockMalleated(context.Block.Transactions !))
            {
                return(validationState.Invalid(BlockValidationStateResults.Mutated, "bad-txns-duplicate", "duplicate transaction"));
            }

            UInt256 computedMerkleRoot = _merkleRootCalculator.GetBlockMerkleRoot(context.Block);

            if (context.Block.Header !.MerkleRoot != computedMerkleRoot)
            {
                return(validationState.Invalid(BlockValidationStateResults.Mutated, "bad-txnmrklroot", "hashMerkleRoot mismatch"));
            }

            return(true);
        }
예제 #3
0
        public bool Check(IBlockValidationContext context, ref BlockValidationState validationState)
        {
            Protocol.Types.Transaction[] transactions = context.Block.Transactions !;

            // First transaction must be coinbase, the rest must not be
            if ((transactions.Length == 0) || !transactions[0].IsCoinBase())
            {
                validationState.Invalid(BlockValidationStateResults.Consensus, "bad-cb-missing", "first tx is not coinbase");
                return(false);
            }

            for (int i = 1; i < transactions.Length; i++)
            {
                if (transactions[i].IsCoinBase())
                {
                    validationState.Invalid(BlockValidationStateResults.Consensus, "bad-cb-multiple", "more than one coinbase");
                    return(false);
                }
            }

            return(true);
        }
예제 #4
0
        public bool Check(IHeaderValidationContext context, ref BlockValidationState validationState)
        {
            if (!context.TryGetData(CheckPreviousBlock.PREV_BLOCK, out HeaderNode? previousHeaderNode))
            {
                ThrowHelper.ThrowArgumentException("Fatal exception, this rule must be executed before CheckPreviousBlock, need previous header node");
                return(false);
            }

            if (context.Header.TimeStamp <= _headerMedianTimeCalculator.Calculate(previousHeaderNode !.Hash, previousHeaderNode.Height))
            {
                validationState.Invalid(BlockValidationStateResults.InvalidHeader, "time-too-old", "block's timestamp is too early");
                return(false);
            }

            // Check timestamp.
            if (context.Header.TimeStamp > (_dateTimeProvider.GetAdjustedTimeAsUnixTimestamp() + MAX_FUTURE_BLOCK_TIME))
            {
                validationState.Invalid(BlockValidationStateResults.TimeFuture, "time-too-new", "block timestamp too far in the future");
                return(false);
            }

            return(true);
        }
예제 #5
0
        public bool Check(IHeaderValidationContext context, ref BlockValidationState validationState)
        {
            BlockHeader header = context.Header;

            // Check proof of work matches claimed amount
            //if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, consensusParams))
            if (!_proofOfWorkCalculator.CheckProofOfWork(header))
            {
                validationState.Invalid(BlockValidationStateResults.InvalidHeader, "high-hash", "proof of work failed");
                return(false);
            }

            return(true);
        }
예제 #6
0
        public bool Check(IBlockValidationContext context, ref BlockValidationState validationState)
        {
            int transactionsCount = context.Block.Transactions !.Length;

            if (
                transactionsCount == 0 ||
                transactionsCount * _consensusParameters.WitnessScaleFactor > _consensusParameters.MaxBlockWeight ||
                GetBlockSize(context.Block) * _consensusParameters.WitnessScaleFactor > _consensusParameters.MaxBlockWeight
                )
            {
                return(validationState.Invalid(BlockValidationStateResults.Consensus, "bad-blk-length", "size limits failed"));
            }

            return(true);
        }
        public bool Check(IBlockValidationContext context, ref BlockValidationState validationState)
        {
            Transaction[] transactions = context.Block.Transactions !;

            for (int i = 0; i < transactions.Length; i++)
            {
                if (!PerformCheck(transactions[i], out TransactionValidationState? transactionValidationState))
                {
                    // checks performed here are context-free validation checks. The only possible failures are consensus failures.
                    return(validationState.Invalid(BlockValidationStateResults.Consensus, transactionValidationState.RejectReason !, transactionValidationState.DebugMessage !));
                }
            }

            return(true);
        }
예제 #8
0
        public bool Check(IHeaderValidationContext context, ref BlockValidationState validationState)
        {
            HeaderNode?existingHeader = context.KnownHeader;

            // check if the tip we want to set is already into our chain
            if (existingHeader != null)
            {
                if (existingHeader.IsInvalid())
                {
                    validationState.Invalid(BlockValidationStateResults.CachedInvalid, "duplicate", "block marked as invalid");
                    return(false);
                }

                // if the header has been already validated before, we can skip the validation process.
                context.ForceAsValid("The header we want to accept is already in our headers chain.");
            }

            return(true);
        }