// 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>(); }
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()); }
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); }
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(); } }
private static long FutureDrift(long nTime, int nHeight) { return(StakeValidator.IsProtocolV2(nHeight) ? FutureDriftV2(nTime) : FutureDriftV1(nTime)); }