예제 #1
0
 // Check whether the coinstake timestamp meets protocol
 public static bool CheckCoinStakeTimestamp(int nHeight, long nTimeBlock, long nTimeTx)
 {
     if (StakeValidator.IsProtocolV2(nHeight))
     {
         return((nTimeBlock == nTimeTx) && ((nTimeTx & STAKE_TIMESTAMP_MASK) == 0));
     }
     else
     {
         return(nTimeBlock == nTimeTx);
     }
 }
        public PosConsensusValidator(StakeValidator stakeValidator, Network network,
                                     StakeChain stakeChain, ConcurrentChain chain, CoinView coinView)
            : base(network)
        {
            Guard.NotNull(network.Consensus.Option <PosConsensusOptions>(), nameof(network.Consensus.Options));

            this.stakeValidator   = stakeValidator;
            this.stakeChain       = stakeChain;
            this.chain            = chain;
            this.coinView         = coinView;
            this.consensusOptions = network.Consensus.Option <PosConsensusOptions>();
        }
예제 #3
0
        public override void CheckBlockHeader(ContextInformation context)
        {
            context.SetStake();

            if (context.Stake.BlockStake.IsProofOfWork())
            {
                if (!context.BlockResult.Block.Header.CheckProofOfWork())
                {
                    ConsensusErrors.HighHash.Throw();
                }
            }

            context.NextWorkRequired = StakeValidator.GetNextTargetRequired(stakeChain, context.BlockResult.ChainedBlock.Previous, context.Consensus,
                                                                            context.Stake.BlockStake.IsProofOfStake());
        }
예제 #4
0
        public static bool CheckBlockSignature(Block block)
        {
            if (BlockStake.IsProofOfWork(block))
            {
                return(block.BlockSignatur.IsEmpty());
            }

            if (block.BlockSignatur.IsEmpty())
            {
                return(false);
            }

            var txout = block.Transactions[1].Outputs[1];

            if (PayToPubkeyTemplate.Instance.CheckScriptPubKey(txout.ScriptPubKey))
            {
                var pubKey = PayToPubkeyTemplate.Instance.ExtractScriptPubKeyParameters(txout.ScriptPubKey);
                return(pubKey.Verify(block.GetHash(), new ECDSASignature(block.BlockSignatur.Signature)));
            }

            if (StakeValidator.IsProtocolV3((int)block.Header.Time))
            {
                // Block signing key also can be encoded in the nonspendable output
                // This allows to not pollute UTXO set with useless outputs e.g. in case of multisig staking

                var ops = txout.ScriptPubKey.ToOps().ToList();
                if (!ops.Any())                 // script.GetOp(pc, opcode, vchPushValue))
                {
                    return(false);
                }
                if (ops.ElementAt(0).Code != OpcodeType.OP_RETURN)                 // OP_RETURN)
                {
                    return(false);
                }
                if (ops.Count < 2)                 // script.GetOp(pc, opcode, vchPushValue)
                {
                    return(false);
                }
                var data = ops.ElementAt(1).PushData;
                if (!ScriptEvaluationContext.IsCompressedOrUncompressedPubKey(data))
                {
                    return(false);
                }
                return(new PubKey(data).Verify(block.GetHash(), new ECDSASignature(block.BlockSignatur.Signature)));
            }

            return(false);
        }
예제 #5
0
        public override void ContextualCheckBlockHeader(ContextInformation context)
        {
            base.ContextualCheckBlockHeader(context);

            var chainedBlock = context.BlockResult.ChainedBlock;

            if (!StakeValidator.IsProtocolV3((int)chainedBlock.Header.Time))
            {
                if (chainedBlock.Header.Version > BlockHeader.CURRENT_VERSION)
                {
                    ConsensusErrors.BadVersion.Throw();
                }
            }

            if (StakeValidator.IsProtocolV2(chainedBlock.Height) && chainedBlock.Header.Version < 7)
            {
                ConsensusErrors.BadVersion.Throw();
            }
            else if (!StakeValidator.IsProtocolV2(chainedBlock.Height) && chainedBlock.Header.Version > 6)
            {
                ConsensusErrors.BadVersion.Throw();
            }

            if (context.Stake.BlockStake.IsProofOfWork() && chainedBlock.Height > this.ConsensusParams.LastPOWBlock)
            {
                ConsensusErrors.ProofOfWorkTooHeigh.Throw();
            }

            // Check coinbase timestamp
            if (chainedBlock.Header.Time > FutureDrift(context.BlockResult.Block.Transactions[0].Time, chainedBlock.Height))
            {
                ConsensusErrors.TimeTooNew.Throw();
            }

            // Check coinstake timestamp
            if (context.Stake.BlockStake.IsProofOfStake() &&
                !PosConsensusValidator.CheckCoinStakeTimestamp(chainedBlock.Height, chainedBlock.Header.Time, context.BlockResult.Block.Transactions[1].Time))
            {
                ConsensusErrors.StakeTimeViolation.Throw();
            }

            // Check timestamp against prev
            if (chainedBlock.Header.Time <= StakeValidator.GetPastTimeLimit(chainedBlock.Previous) ||
                FutureDrift(chainedBlock.Header.Time, chainedBlock.Height) < chainedBlock.Previous.Header.Time)
            {
                ConsensusErrors.BlockTimestampTooEarly.Throw();
            }
        }
예제 #6
0
 private static long FutureDrift(long nTime, int nHeight)
 {
     return(StakeValidator.IsProtocolV2(nHeight) ? FutureDriftV2(nTime) : FutureDriftV1(nTime));
 }