public override ProvenBlockHeader CreateProvenBlockHeader(PosBlock block) { var provenBlockHeader = new MainNetProvenBlockHeader(block); // Serialize the size. provenBlockHeader.ToBytes(this); return(provenBlockHeader); }
public override ProvenBlockHeader CreateProvenBlockHeader(PosBlock block) { var provenBlockHeader = new XdsProvenBlockHeader(block, (XdsBlockHeader)this.CreateBlockHeader()); // Serialize the size. provenBlockHeader.ToBytes(this); return(provenBlockHeader); }
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)); }
/// <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); }
/// <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); }
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(); }
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()); } }
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)); }
/// <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; }
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); }
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); } }
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); } }
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); }
/// <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); }
public XdsProvenBlockHeader(PosBlock block, XdsBlockHeader xdsBlockHeader) : base(block, xdsBlockHeader) { }
public X1ProvenBlockHeader(PosBlock block, X1BlockHeader x1BlockHeader) : base(block, x1BlockHeader) { }
public MainNetProvenBlockHeader(PosBlock block) : base(block) { }