public override ProvenBlockHeader CreateProvenBlockHeader(PosBlock block)
        {
            var provenBlockHeader = new MainNetProvenBlockHeader(block);

            // Serialize the size.
            provenBlockHeader.ToBytes(this);

            return(provenBlockHeader);
        }
Beispiel #2
0
        public override ProvenBlockHeader CreateProvenBlockHeader(PosBlock block)
        {
            var provenBlockHeader = new XdsProvenBlockHeader(block, (XdsBlockHeader)this.CreateBlockHeader());

            // Serialize the size.
            provenBlockHeader.ToBytes(this);

            return(provenBlockHeader);
        }
Beispiel #3
0
        public static bool IsCanonicalBlockSignature(PosBlock block, bool checkLowS)
        {
            if (BlockStake.IsProofOfWork(block))
            {
                return(block.BlockSignature.IsEmpty());
            }

            return(checkLowS ?
                   ScriptEvaluationContext.IsLowDerSignature(block.BlockSignature.Signature) :
                   ScriptEvaluationContext.IsValidSignatureEncoding(block.BlockSignature.Signature));
        }
Beispiel #4
0
        /// <summary>
        /// Creates the and store a <see cref="ProvenBlockHeader" />.
        /// </summary>
        /// <param name="blockHeight">Height of the block used to generate its Proven Header.</param>
        /// <param name="block">Block used to generate its Proven Header.</param>
        /// <returns>Created <see cref="ProvenBlockHeader"/>.</returns>
        private ProvenBlockHeader CreateAndStoreProvenHeader(int blockHeight, PosBlock block)
        {
            ProvenBlockHeader newProvenHeader = ((PosConsensusFactory)this.network.Consensus.ConsensusFactory).CreateProvenBlockHeader(block);

            uint256 provenHeaderHash = newProvenHeader.GetHash();

            this.provenBlockHeaderStore.AddToPendingBatch(newProvenHeader, new HashHeightPair(provenHeaderHash, blockHeight));

            logger.LogTrace("Created Proven Header at height {0} with hash {1} and adding to the store (pending).", blockHeight, provenHeaderHash);

            return(newProvenHeader);
        }
Beispiel #5
0
        /// <summary>
        /// Creates a list of Proof of Stake blocks.
        /// </summary>
        /// <param name="amount">The amount of blocks to create.</param>
        public List <Block> CreatePosBlocks(int amount)
        {
            var blocks = new List <Block>();

            for (int i = 0; i < amount; i++)
            {
                PosBlock block = this.CreatePosBlock();
                block.Header.HashPrevBlock = blocks.LastOrDefault()?.GetHash() ?? this.Network.GenesisHash;
                blocks.Add(block);
            }

            return(blocks);
        }
        /// <summary>
        /// Checks if block signature is valid.
        /// </summary>
        /// <param name="block">The block.</param>
        /// <returns><c>true</c> if the signature is valid, <c>false</c> otherwise.</returns>
        private bool CheckBlockSignature(PosBlock block)
        {
            if (BlockStake.IsProofOfWork(block))
            {
                bool res = block.BlockSignature.IsEmpty();
                this.Logger.LogTrace("(-)[POW]:{0}", res);
                return(res);
            }

            var consensusRules = (PosConsensusRuleEngine)this.Parent;

            return(consensusRules.StakeValidator.CheckStakeSignature(block.BlockSignature, block.GetHash(), block.Transactions[1]));
        }
        /// <summary>
        /// Creates and store a <see cref="ProvenBlockHeader" /> generated by the signaled <see cref="ChainedHeaderBlock"/>.
        /// </summary>
        /// <param name="blockHeight">Height of the block used to generate its Proven Header.</param>
        /// <param name="chainedHeaderBlock">Block used to generate its Proven Header.</param>
        private void CreateAndStoreProvenHeader(int blockHeight, ChainedHeaderBlock chainedHeaderBlock)
        {
            PosBlock block = (PosBlock)chainedHeaderBlock.Block;

            ProvenBlockHeader newProvenHeader = ((PosConsensusFactory)this.network.Consensus.ConsensusFactory).CreateProvenBlockHeader(block);

            uint256 provenHeaderHash = newProvenHeader.GetHash();

            this.provenBlockHeaderStore.AddToPendingBatch(newProvenHeader, new HashHeightPair(provenHeaderHash, blockHeight));

            logger.LogTrace("Created Proven Header at height {0} with hash {1} and adding to the pending batch to be stored.", blockHeight, provenHeaderHash);

            chainedHeaderBlock.SetHeader(newProvenHeader);
        }
        /// <summary>
        /// Creates a list of Proof of Stake blocks.
        /// </summary>
        /// <param name="amount">The amount of blocks to create.</param>
        public List <Block> CreatePosBlocks(int amount)
        {
            var blocks = new List <Block>();

            for (int i = 0; i < amount; i++)
            {
                PosBlock block = this.CreatePosBlock();
                block.Header.HashPrevBlock  = blocks.LastOrDefault()?.GetHash() ?? this.Network.GenesisHash;
                block.Header.Bits           = Target.Difficulty1;
                block.Header.HashMerkleRoot = new uint256(RandomUtils.GetBytes(32));
                blocks.Add(block);
            }

            return(blocks);
        }
Beispiel #9
0
        public void WhenCreatingNewProvenHeaderMerkleProofIsCorrectlyCreated()
        {
            PosBlock block = this.CreatePosBlock();

            // Add 20 more transactions.
            for (int i = 0; i < 20; i++)
            {
                Transaction tx = this.Network.CreateTransaction();

                tx.AddInput(new TxIn(Script.Empty));
                tx.AddOutput(Money.COIN + i, new Script(Enumerable.Range(1, 5).SelectMany(index => Guid.NewGuid().ToByteArray())));

                block.AddTransaction(tx);
            }

            block.UpdateMerkleRoot();
            ProvenBlockHeader provenBlockHeader = CreateNewProvenBlockHeaderMock(block);

            provenBlockHeader.MerkleProof.Hashes.Should().HaveCount(6);
            provenBlockHeader.MerkleProof.Check(provenBlockHeader.HashMerkleRoot).Should().BeTrue();
        }
Beispiel #10
0
        public async Task PutAsync_Inserts_MultipleProvenBlockHeadersAsync()
        {
            string folder = CreateTestDir(this);

            PosBlock          posBlock = CreatePosBlock();
            ProvenBlockHeader header1  = CreateNewProvenBlockHeaderMock(posBlock);
            ProvenBlockHeader header2  = CreateNewProvenBlockHeaderMock(posBlock);

            var items = new SortedDictionary <int, ProvenBlockHeader>()
            {
                { 0, header1 }, { 1, header2 }
            };

            // Put the items in the repository.
            using (IProvenBlockHeaderRepository repo = this.SetupRepository(this.Network, folder))
            {
                await repo.PutAsync(items, new HashHeightPair(header2.GetHash(), items.Count - 1));
            }

            // Check the ProvenBlockHeader exists in the database.
            using (var engine = new DB(new Options()
            {
                CreateIfMissing = true
            }, folder))
            {
                var headersOut = new Dictionary <byte[], byte[]>();
                var enumeator  = engine.GetEnumerator();
                while (enumeator.MoveNext())
                {
                    if (enumeator.Current.Key[0] == ProvenBlockHeaderTable)
                    {
                        headersOut.Add(enumeator.Current.Key, enumeator.Current.Value);
                    }
                }

                headersOut.Keys.Count.Should().Be(2);
                this.dataStoreSerializer.Deserialize <ProvenBlockHeader>(headersOut.First().Value).GetHash().Should().Be(items[0].GetHash());
                this.dataStoreSerializer.Deserialize <ProvenBlockHeader>(headersOut.Last().Value).GetHash().Should().Be(items[1].GetHash());
            }
        }
Beispiel #11
0
        public static bool IsCanonicalBlockSignature(PosBlock block, bool checkLowS)
        {
            if (BlockStake.IsProofOfWork(block))
            {
                return(block.BlockSignature.IsEmpty());
            }

            // A signature should have only one representation, or malleability vectors are introduced.
            // Therefore, an ECDSA signature, per BIP66, must be in strict DER encoding.
            // Additionally, the 'S' value of the signature must be the lower of the two possible values.

            // Recall that, for an ECDSA signature, the R and S values are both modulo N (aka the curve order).
            // Further, a signature (R, S) is equivalent to (R, -S mod N).

            // In other words there are always 2 valid S values, call them S and S'.

            // A small example of why S + S' = N:
            // N = 7
            // S = 4
            // ((N - S) % N) = 3 = S', therefore S + S' = 7 = N

            // Given S + S' = N, there will always be one S value greater than half the curve order
            // (N / 2), and one less than this.
            // The canonical signature is required to use the so-called 'low S' value, the one less than N / 2.

            // Therefore to get the other S' value (the complement) we calculate S' = N - S.

            // We can switch between the canonical and non-canonical form by calculating the complement of
            // whichever representation we currently have in a signature.

            // Using N + S will give a valid signature too, but will not give the complement, as (N + S) mod N = S.

            // For POS blocks that have a signature we do not append a SIGHASH type at the end of the signature.
            // Therefore IsValidSignatureEncoding should be called with haveSigHash = false when validating
            // POS blocks.

            return(checkLowS
                ? ScriptEvaluationContext.IsLowDerSignature(block.BlockSignature.Signature, false)
                : ScriptEvaluationContext.IsValidSignatureEncoding(block.BlockSignature.Signature, false));
        }
Beispiel #12
0
        /// <returns>Tip of a created chain of headers.</returns>
        public ChainedHeader BuildChainWithProvenHeaders(int blockCount)
        {
            ChainedHeader currentHeader = ChainedHeadersHelper.CreateGenesisChainedHeader(this.Network);

            for (int i = 1; i < blockCount; i++)
            {
                PosBlock          block  = this.CreatePosBlockMock();
                ProvenBlockHeader header = ((PosConsensusFactory)this.Network.Consensus.ConsensusFactory).CreateProvenBlockHeader(block);

                header.Nonce         = RandomUtils.GetUInt32();
                header.HashPrevBlock = currentHeader.HashBlock;
                header.Bits          = Target.Difficulty1;

                ChainedHeader prevHeader = currentHeader;
                currentHeader = new ChainedHeader(header, header.GetHash(), i);

                currentHeader.SetPrivatePropertyValue("Previous", prevHeader);
                prevHeader.Next.Add(currentHeader);
            }

            return(currentHeader);
        }
        /// <summary>
        /// Builds a chain of proven headers.
        /// </summary>
        /// <param name="blockCount">The amount of blocks to chain.</param>
        /// <param name="startingHeader">Build the chain from this header, if not start from genesis.</param>
        /// <returns>Tip of a created chain of headers.</returns>
        public ChainedHeader BuildProvenHeaderChain(int blockCount, ChainedHeader startingHeader = null)
        {
            startingHeader = startingHeader ?? ChainedHeadersHelper.CreateGenesisChainedHeader(this.Network);

            for (int i = 1; i < blockCount; i++)
            {
                PosBlock          block  = this.CreatePosBlock();
                ProvenBlockHeader header = ((PosConsensusFactory)this.Network.Consensus.ConsensusFactory).CreateProvenBlockHeader(block);

                header.Nonce         = RandomUtils.GetUInt32();
                header.HashPrevBlock = startingHeader.HashBlock;
                header.Bits          = Target.Difficulty1;

                ChainedHeader prevHeader = startingHeader;
                startingHeader = new ChainedHeader(header, header.GetHash(), prevHeader.Height + 1);

                startingHeader.SetPrivatePropertyValue("Previous", prevHeader);
                prevHeader.Next.Add(startingHeader);
            }

            return(startingHeader);
        }
        public PosBlockBuilder(Network network, Key privateKey = null)
        {
            if (privateKey == null)
            {
                var mnemonic = new Mnemonic(Wordlist.English, WordCount.Twelve);
                privateKey = mnemonic.DeriveExtKey().PrivateKey;
            }

            // Create coinstake Tx.
            Transaction previousTx = network.CreateTransaction();

            previousTx.AddOutput(new TxOut());
            Transaction coinstakeTx = network.CreateTransaction();

            coinstakeTx.AddOutput(new TxOut(0, Script.Empty));
            coinstakeTx.AddOutput(new TxOut(50, new Script()));
            coinstakeTx.AddInput(previousTx, 0);

            // Create coinbase Tx.
            Transaction coinBaseTx = network.CreateTransaction();

            coinBaseTx.AddOutput(100, new Script());
            coinBaseTx.AddInput(new TxIn());

            var block = (PosBlock)network.CreateBlock();

            block.AddTransaction(coinBaseTx);
            block.AddTransaction(coinstakeTx);

            ECDSASignature signature = privateKey.Sign(block.Header.GetHash());

            block.BlockSignature = new BlockSignature {
                Signature = signature.ToDER()
            };

            this.posBlock = block;
        }
Beispiel #15
0
        public (ChainedHeader chainedHeader, List <ProvenBlockHeader> provenBlockHeaders) BuildChainWithProvenHeaders(int blockCount, Network network, bool addNext = false)
        {
            Guard.Assert(blockCount > 0);

            var provenBlockHeaders = new List <ProvenBlockHeader>();

            ChainedHeader chainedHeader       = null;
            ChainedHeader previousChainHeader = null;

            for (int i = 0; i < blockCount; i++)
            {
                PosBlock          block  = CreatePosBlockMock();
                ProvenBlockHeader header = ((PosConsensusFactory)this.Network.Consensus.ConsensusFactory).CreateProvenBlockHeader(block);

                header.Nonce         = RandomUtils.GetUInt32();
                header.HashPrevBlock = i > 0 ? chainedHeader.HashBlock : null;
                header.Bits          = Target.Difficulty1;

                chainedHeader = new ChainedHeader(header, header.GetHash(), i);

                if (previousChainHeader != null)
                {
                    chainedHeader.SetPrivatePropertyValue("Previous", previousChainHeader);

                    if (addNext)
                    {
                        chainedHeader.Previous.Next.Add(chainedHeader);
                    }
                }

                previousChainHeader = chainedHeader;

                provenBlockHeaders.Add(header);
            }

            return(chainedHeader, provenBlockHeaders);
        }
Beispiel #16
0
        public async Task PutAsync_Add_Ten_ProvenBlockHeaders_Dispose_On_Initialise_Repo_TipHeight_Should_Be_At_Last_Saved_TipAsync()
        {
            string folder = CreateTestDir(this);

            PosBlock posBlock = CreatePosBlockMock();
            var      headers  = new List <ProvenBlockHeader>();

            for (int i = 0; i < 10; i++)
            {
                headers.Add(CreateNewProvenBlockHeaderMock(posBlock));
            }

            // Put the items in the repository.
            using (IProvenBlockHeaderRepository repo = this.SetupRepository(this.Network, folder))
            {
                await repo.PutAsync(headers, new HashHeightPair(headers.Last().GetHash(), headers.Count - 1));
            }

            using (IProvenBlockHeaderRepository newRepo = this.SetupRepository(this.Network, folder))
            {
                newRepo.TipHashHeight.Hash.Should().Be(headers.Last().GetHash());
                newRepo.TipHashHeight.Height.Should().Be(headers.Count - 1);
            }
        }
Beispiel #17
0
        public async Task PutAsyncsDisposeOnInitialiseShouldBeAtLastSavedTipAsync()
        {
            string folder = CreateTestDir(this);

            PosBlock posBlock = CreatePosBlock();
            var      headers  = new SortedDictionary <int, ProvenBlockHeader>();

            for (int i = 0; i < 10; i++)
            {
                headers.Add(i, CreateNewProvenBlockHeaderMock(posBlock));
            }

            // Put the items in the repository.
            using (IProvenBlockHeaderRepository repo = this.SetupRepository(this.Network, folder))
            {
                await repo.PutAsync(headers, new HashHeightPair(headers.Last().Value.GetHash(), headers.Count - 1));
            }

            using (IProvenBlockHeaderRepository newRepo = this.SetupRepository(this.Network, folder))
            {
                newRepo.TipHashHeight.Hash.Should().Be(headers.Last().Value.GetHash());
                newRepo.TipHashHeight.Height.Should().Be(headers.Count - 1);
            }
        }
Beispiel #18
0
        public ChainedHeaderBlock AddNextBlock(List <Transaction> transactions)
        {
            ChainedHeader previous = this.ChainIndexer.Tip;

            BlockHeader nextHeader = this.Network.Consensus.ConsensusFactory.CreateBlockHeader();

            nextHeader.HashPrevBlock = previous.HashBlock;

            ChainedHeader chainedHeader = new ChainedHeader(nextHeader, nextHeader.GetHash(), previous);

            var block = new PosBlock(chainedHeader.Header);

            foreach (var tx in transactions)
            {
                block.AddTransaction(tx);
            }

            chainedHeader.Block = block;

            this.ChainIndexer.Add(chainedHeader);
            this.AddBlockToBlockStore(block);

            return(new ChainedHeaderBlock(block, chainedHeader));
        }
 public ProvenBlockHeaderBuilder(PosBlock posBlock, Network network)
 {
     this.provenBlockHeader = ((PosConsensusFactory)network.Consensus.ConsensusFactory).CreateProvenBlockHeader(posBlock);
 }
Beispiel #20
0
        /// <summary>
        /// Checks if block signature is valid.
        /// </summary>
        /// <param name="block">The block.</param>
        /// <returns><c>true</c> if the signature is valid, <c>false</c> otherwise.</returns>
        private bool CheckBlockSignature(PosBlock block)
        {
            if (BlockStake.IsProofOfWork(block))
            {
                bool res = block.BlockSignature.IsEmpty();
                this.Logger.LogTrace("(-)[POW]:{0}", res);
                return(res);
            }

            if (block.BlockSignature.IsEmpty())
            {
                this.Logger.LogTrace("(-)[EMPTY]:false");
                return(false);
            }

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

            if (PayToPubkeyTemplate.Instance.CheckScriptPubKey(txout.ScriptPubKey))
            {
                PubKey pubKey = PayToPubkeyTemplate.Instance.ExtractScriptPubKeyParameters(txout.ScriptPubKey);
                bool   res    = pubKey.Verify(block.GetHash(), new ECDSASignature(block.BlockSignature.Signature));
                this.Logger.LogTrace("(-)[P2PK]:{0}", res);
                return(res);
            }

            // 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.

            List <Op> ops = txout.ScriptPubKey.ToOps().ToList();

            if (!ops.Any()) // script.GetOp(pc, opcode, vchPushValue))
            {
                this.Logger.LogTrace("(-)[NO_OPS]:false");
                return(false);
            }

            if (ops.ElementAt(0).Code != OpcodeType.OP_RETURN) // OP_RETURN)
            {
                this.Logger.LogTrace("(-)[NO_OP_RETURN]:false");
                return(false);
            }

            if (ops.Count != 2)
            {
                this.Logger.LogTrace("(-)[INVALID_OP_COUNT]:false");
                return(false);
            }

            byte[] data = ops.ElementAt(1).PushData;

            if (data.Length > MaxPushDataSize)
            {
                this.Logger.LogTrace("(-)[PUSH_DATA_TOO_LARGE]:false");
                return(false);
            }

            if (!ScriptEvaluationContext.IsCompressedOrUncompressedPubKey(data))
            {
                this.Logger.LogTrace("(-)[NO_PUSH_DATA]:false");
                return(false);
            }

            bool verifyRes = new PubKey(data).Verify(block.GetHash(), new ECDSASignature(block.BlockSignature.Signature));

            return(verifyRes);
        }
Beispiel #21
0
 public XdsProvenBlockHeader(PosBlock block, XdsBlockHeader xdsBlockHeader) : base(block, xdsBlockHeader)
 {
 }
Beispiel #22
0
 public X1ProvenBlockHeader(PosBlock block, X1BlockHeader x1BlockHeader) : base(block, x1BlockHeader)
 {
 }
Beispiel #23
0
 public MainNetProvenBlockHeader(PosBlock block) : base(block)
 {
 }