public static async Task<MnemonicReference> ParseAsync (ChainBase chain, IBlockRepository blockRepository, Wordlist wordList, string sentence) { var w = wordList.GetWords(sentence).Length; var finalAddress = wordList.ToBits(sentence); var rawAddress = DecryptFinalAddress(finalAddress); int blockHeight; int x = DecodeBlockHeight(rawAddress, out blockHeight); var header = chain.GetBlock(blockHeight); if(header == null) throw new InvalidBrainAddressException("This block does not exists"); var block = await blockRepository.GetBlockAsync(header.HashBlock).ConfigureAwait(false); if(block == null || block.GetHash() != header.HashBlock) throw new InvalidBrainAddressException("This block does not exists"); int y1 = BitCount((int)block.Transactions.Count); int y2 = 11 * w - 1 - x - c; int y = Math.Min(y1, y2); int txIndex = Decode(Substring(rawAddress, x, y)); if(txIndex >= block.Transactions.Count) throw new InvalidBrainAddressException("The Transaction Index is out of the bound of the block"); var transaction = block.Transactions[(int)txIndex]; return Parse(chain, wordList, sentence, transaction, block); }
public ChainedBlock FindFork(ChainBase chain) { if (chain == null) { throw new ArgumentNullException("chain"); } return(FindFork(chain.ToEnumerable(true).Select(o => o.HashBlock))); }
public ChainedBlock SetTip(ChainBase otherChain) { if (otherChain == null) { throw new ArgumentNullException("otherChain"); } return(SetTip(otherChain.Tip)); }
/// <summary> /// Returns the first common block between two chains /// </summary> /// <param name="chain">The other chain</param> /// <returns>First common block or null</returns> public ChainedBlock FindFork(ChainBase chain) { if (chain == null) { throw new ArgumentNullException(nameof(chain)); } return(FindFork(chain.Tip.EnumerateToGenesis().Select(o => o.HashBlock))); }
public bool SameTip(ChainBase chain) { if (chain == null) { throw new ArgumentNullException("chain"); } return(Tip.HashBlock == chain.Tip.HashBlock); }
/// <summary> /// Sets the tip of this chain to the tip of another chain. /// </summary> /// <param name="otherChain">The other chain whose tip to apply to this chain.</param> /// <returns>The new tip.</returns> public ChainedHeader SetTip(ChainBase otherChain) { if (otherChain == null) { throw new ArgumentNullException("otherChain"); } return(this.SetTip(otherChain.Tip)); }
public static MnemonicReference Parse (ChainBase chain, Wordlist wordList, string sentence, Transaction transaction, Block block) { return(Parse(chain, wordList, sentence, transaction, block.Filter(transaction.GetHash()))); }
/// <summary> /// /// </summary> /// <param name="chain"></param> /// <param name="blockRepository"></param> /// <param name="blockHeight"></param> /// <param name="txIndex"></param> /// <param name="txOutIndex"></param> /// <exception cref="NBitcoin.InvalidBrainAddressException"></exception> /// <returns></returns> public static async Task<MnemonicReference> CreateAsync (ChainBase chain, IBlockRepository blockRepository, int blockHeight, int txIndex, int txOutIndex) { var header = chain.GetBlock(blockHeight); if(header == null) throw new InvalidBrainAddressException("This block does not exists"); var block = await blockRepository.GetBlockAsync(header.HashBlock).ConfigureAwait(false); if(block == null || block.GetHash() != header.HashBlock) throw new InvalidBrainAddressException("This block does not exists"); return Create(chain, block, blockHeight, txIndex, txOutIndex); }
public const uint ModifierInterval = 10 * 60; // time to elapse before new modifier is computed public static bool CheckAndComputeStake(IBlockRepository blockStore, ITransactionRepository trasnactionStore, IBlockTransactionMapStore mapStore, StakeChain stakeChain, ChainBase chainIndex, ChainedBlock pindex, Block block, out BlockStake blockStake) { if (block.GetHash() != pindex.HashBlock) { throw new ArgumentException(); } blockStake = new BlockStake(block); uint256 hashProof = null; // Verify hash target and signature of coinstake tx if (BlockStake.IsProofOfStake(block)) { var pindexPrev = pindex.Previous; var prevBlockStake = stakeChain.Get(pindexPrev.HashBlock); if (prevBlockStake == null) { return(false); // the stake proof of the previous block is not set } uint256 targetProofOfStake; if (!CheckProofOfStake(blockStore, trasnactionStore, mapStore, pindexPrev, prevBlockStake, block.Transactions[1], pindex.Header.Bits.ToCompact(), out hashProof, out targetProofOfStake)) { return(false); // error("AcceptBlock() : check proof-of-stake failed for block %s", hash.ToString()); } } // PoW is checked in CheckBlock() if (BlockStake.IsProofOfWork(block)) { hashProof = pindex.Header.GetPoWHash(); } // todo: is this the same as chain work? // compute chain trust score //pindexNew.nChainTrust = (pindexNew->pprev ? pindexNew->pprev->nChainTrust : 0) + pindexNew->GetBlockTrust(); // compute stake entropy bit for stake modifier if (!blockStake.SetStakeEntropyBit(blockStake.GetStakeEntropyBit())) { return(false); //error("AddToBlockIndex() : SetStakeEntropyBit() failed"); } // Record proof hash value blockStake.HashProof = hashProof; // compute stake modifier return(ComputeStakeModifier(chainIndex, pindex, blockStake, stakeChain)); }
public static MnemonicReference Create ( ChainBase chain, Block block, int blockHeight, int txIndex, int txOutIndex) { var header = chain.GetBlock(blockHeight); if(header == null || block.GetHash() != header.HashBlock) throw new InvalidBrainAddressException("This block does not exists"); if(txIndex >= block.Transactions.Count) throw new InvalidBrainAddressException("The Transaction Index is out of the bound of the block"); var transaction = block.Transactions[txIndex]; return Create(chain, transaction, block, txOutIndex); }
public static bool ComputeStakeModifier(ChainBase chainIndex, ChainedBlock pindex) { var pindexPrev = pindex.Previous; // compute stake modifier ulong nStakeModifier; bool fGeneratedStakeModifier; if (!ComputeNextStakeModifier(chainIndex, pindexPrev, out nStakeModifier, out fGeneratedStakeModifier)) { return(false); //error("AddToBlockIndex() : ComputeNextStakeModifier() failed"); } pindex.Header.PosParameters.SetStakeModifier(nStakeModifier, fGeneratedStakeModifier); pindex.Header.PosParameters.StakeModifierV2 = ComputeStakeModifierV2( pindexPrev, pindex.Header.PosParameters.IsProofOfWork() ? pindex.HashBlock : pindex.Header.PosParameters.PrevoutStake.Hash); return(true); }
/// <summary> /// /// </summary> /// <param name="chain"></param> /// <param name="blockRepository"></param> /// <param name="blockHeight"></param> /// <param name="txIndex"></param> /// <param name="txOutIndex"></param> /// <exception cref="NBitcoin.InvalidBrainAddressException"></exception> /// <returns></returns> public static async Task <MnemonicReference> CreateAsync (ChainBase chain, IBlockRepository blockRepository, int blockHeight, int txIndex, int txOutIndex) { var header = chain.GetBlock(blockHeight); if (header == null) { throw new InvalidBrainAddressException("This block does not exists"); } var block = await blockRepository.GetBlockAsync(header.HashBlock).ConfigureAwait(false); if (block == null || block.GetHash() != header.HashBlock) { throw new InvalidBrainAddressException("This block does not exists"); } return(Create(chain, block, blockHeight, txIndex, txOutIndex)); }
public static bool ComputeStakeModifier(ChainBase chainIndex, ChainedBlock pindex, BlockStake blockStake, StakeChain stakeChain) { var pindexPrev = pindex.Previous; var blockStakePrev = pindexPrev == null ? null : stakeChain.Get(pindexPrev.HashBlock); // compute stake modifier ulong nStakeModifier; bool fGeneratedStakeModifier; if (!ComputeNextStakeModifier(stakeChain, chainIndex, pindexPrev, out nStakeModifier, out fGeneratedStakeModifier)) { return(false); //error("AddToBlockIndex() : ComputeNextStakeModifier() failed"); } blockStake.SetStakeModifier(nStakeModifier, fGeneratedStakeModifier); blockStake.StakeModifierV2 = ComputeStakeModifierV2( pindexPrev, blockStakePrev, blockStake.IsProofOfWork() ? pindex.HashBlock : blockStake.PrevoutStake.Hash); return(true); }
public static async Task <MnemonicReference> ParseAsync (ChainBase chain, IBlockRepository blockRepository, Wordlist wordList, string sentence) { var w = wordList.GetWords(sentence).Length; var finalAddress = wordList.ToBits(sentence); var rawAddress = DecryptFinalAddress(finalAddress); int blockHeight; int x = DecodeBlockHeight(rawAddress, out blockHeight); var header = chain.GetBlock(blockHeight); if (header == null) { throw new InvalidBrainAddressException("This block does not exists"); } var block = await blockRepository.GetBlockAsync(header.HashBlock).ConfigureAwait(false); if (block == null || block.GetHash() != header.HashBlock) { throw new InvalidBrainAddressException("This block does not exists"); } int y1 = BitCount((int)block.Transactions.Count); int y2 = 11 * w - 1 - x - c; int y = Math.Min(y1, y2); int txIndex = Decode(Substring(rawAddress, x, y)); if (txIndex >= block.Transactions.Count) { throw new InvalidBrainAddressException("The Transaction Index is out of the bound of the block"); } var transaction = block.Transactions[(int)txIndex]; return(Parse(chain, wordList, sentence, transaction, block)); }
public static MnemonicReference Create ( ChainBase chain, Block block, int blockHeight, int txIndex, int txOutIndex) { var header = chain.GetBlock(blockHeight); if (header == null || block.GetHash() != header.HashBlock) { throw new InvalidBrainAddressException("This block does not exists"); } if (txIndex >= block.Transactions.Count) { throw new InvalidBrainAddressException("The Transaction Index is out of the bound of the block"); } var transaction = block.Transactions[txIndex]; return(Create(chain, transaction, block, txOutIndex)); }
public static MnemonicReference Parse (ChainBase chain, Wordlist wordList, string sentence, Transaction transaction, MerkleBlock merkleBlock) { var indices = wordList.ToIndices(sentence); //Step1: Determine w = number of words in the mnemonic code int w = indices.Length; //Convert mnemonic code into finalAddress following BIP-0039 var finalAddress = Wordlist.ToBits(indices); var rawAddress = DecryptFinalAddress(finalAddress); int blockHeight = 0; var x = DecodeBlockHeight(rawAddress, out blockHeight); var header = chain.GetBlock((int)blockHeight); if (header == null) { throw new InvalidBrainAddressException("This block does not exists"); } if (header.HashBlock != merkleBlock.Header.GetHash()) { throw new InvalidBrainAddressException("The provided merkleblock do not match the block of the sentence"); } var blockId = header.HashBlock; MerkleNode root = merkleBlock.PartialMerkleTree.TryGetMerkleRoot(); if (root == null || root.Hash != header.Header.HashMerkleRoot) { throw new InvalidBrainAddressException("Invalid partial merkle tree"); } int y1 = BitCount((int)merkleBlock.PartialMerkleTree.TransactionCount); int y2 = 11 * w - 1 - x - c; int y = Math.Min(y1, y2); int txIndex = Decode(Substring(rawAddress, x, y)); var txLeaf = root.GetLeafs().Skip((int)txIndex).FirstOrDefault(); if (txLeaf == null || txLeaf.Hash != transaction.GetHash()) { throw new InvalidBrainAddressException("The transaction do not appear in the block"); } int z1 = BitCount(transaction.Outputs.Count); int z2 = 11 * w - 1 - x - y - c; int z = Math.Min(z1, z2); int outputIndex = Decode(Substring(rawAddress, x + y, z)); if (outputIndex >= transaction.Outputs.Count) { throw new InvalidBrainAddressException("The specified txout index is outside of the transaction bounds"); } var txOut = transaction.Outputs[outputIndex]; var cs = 11 * w - 1 - x - y - z; var actualChecksum = Substring(rawAddress, x + y + z, cs); var expectedChecksum = CalculateChecksum(blockId, txIndex, outputIndex, txOut.ScriptPubKey, cs); if (!actualChecksum.OfType <bool>().SequenceEqual(expectedChecksum.OfType <bool>())) { throw new InvalidBrainAddressException("Invalid checksum"); } return(new MnemonicReference() { BlockHeight = (int)blockHeight, TransactionIndex = (int)txIndex, WordIndices = indices, Checksum = actualChecksum, Output = transaction.Outputs[outputIndex], OutputIndex = (int)outputIndex, BlockId = blockId, Transaction = transaction }); }
public static MnemonicReference Parse (ChainBase chain, Wordlist wordList, string sentence, Transaction transaction, MerkleBlock merkleBlock) { var indices = wordList.ToIndices(sentence); //Step1: Determine w = number of words in the mnemonic code int w = indices.Length; //Convert mnemonic code into finalAddress following BIP-0039 var finalAddress = Wordlist.ToBits(indices); var rawAddress = DecryptFinalAddress(finalAddress); int blockHeight = 0; var x = DecodeBlockHeight(rawAddress, out blockHeight); var header = chain.GetBlock((int)blockHeight); if(header == null) throw new InvalidBrainAddressException("This block does not exists"); if(header.HashBlock != merkleBlock.Header.GetHash()) throw new InvalidBrainAddressException("The provided merkleblock do not match the block of the sentence"); var blockId = header.HashBlock; MerkleNode root = merkleBlock.PartialMerkleTree.TryGetMerkleRoot(); if(root == null || root.Hash != header.Header.HashMerkleRoot) throw new InvalidBrainAddressException("Invalid partial merkle tree"); int y1 = BitCount((int)merkleBlock.PartialMerkleTree.TransactionCount); int y2 = 11 * w - 1 - x - c; int y = Math.Min(y1, y2); int txIndex = Decode(Substring(rawAddress, x, y)); var txLeaf = root.GetLeafs().Skip((int)txIndex).FirstOrDefault(); if(txLeaf == null || txLeaf.Hash != transaction.GetHash()) throw new InvalidBrainAddressException("The transaction do not appear in the block"); int z1 = BitCount(transaction.Outputs.Count); int z2 = 11 * w - 1 - x - y - c; int z = Math.Min(z1, z2); int outputIndex = Decode(Substring(rawAddress, x + y, z)); if(outputIndex >= transaction.Outputs.Count) throw new InvalidBrainAddressException("The specified txout index is outside of the transaction bounds"); var txOut = transaction.Outputs[outputIndex]; var cs = 11 * w - 1 - x - y - z; var actualChecksum = Substring(rawAddress, x + y + z, cs); var expectedChecksum = CalculateChecksum(blockId, txIndex, outputIndex, txOut.ScriptPubKey, cs); if(!actualChecksum.OfType<bool>().SequenceEqual(expectedChecksum.OfType<bool>())) throw new InvalidBrainAddressException("Invalid checksum"); return new MnemonicReference() { BlockHeight = (int)blockHeight, TransactionIndex = (int)txIndex, WordIndices = indices, Checksum = actualChecksum, Output = transaction.Outputs[outputIndex], OutputIndex = (int)outputIndex, BlockId = blockId, Transaction = transaction }; }
public static MnemonicReference Parse (ChainBase chain, Wordlist wordList, string sentence, Transaction transaction, Block block) { return Parse(chain, wordList, sentence, transaction, block.Filter(transaction.GetHash())); }
public static MnemonicReference Create (ChainBase chain, Transaction transaction, MerkleBlock merkleBlock, int txOutIndex) { var blockId = merkleBlock.Header.GetHash(); var merkleRoot = merkleBlock.PartialMerkleTree.TryGetMerkleRoot(); if(merkleRoot == null || merkleRoot.Hash != merkleBlock.Header.HashMerkleRoot) throw new InvalidBrainAddressException("Invalid merkle block"); if(txOutIndex >= transaction.Outputs.Count) throw new InvalidBrainAddressException("The specified txout index is outside of the transaction bounds"); var matchedLeaf = merkleRoot.GetLeafs().Select((node, index) => new { node, index }).FirstOrDefault(_ => _.node.Hash == transaction.GetHash()); if(matchedLeaf == null) throw new InvalidBrainAddressException("Transaction not included in this merkle block"); var chainedHeader = chain.GetBlock(blockId); if(chainedHeader == null) throw new InvalidBrainAddressException("The block provided is not in the current chain"); var blockHeight = chainedHeader.Height; var txIndex = matchedLeaf.index; var txOut = transaction.Outputs[txOutIndex]; var block = chain.GetBlock(blockId); BitArray encodedBlockHeight = EncodeBlockHeight(blockHeight); int x = encodedBlockHeight.Length; //ymin = ceiling(log(txIndex + 1, 2)) int ymin = BitCount(txIndex + 1); //zmin = ceiling(log(outputIndex + 1, 2)) int zmin = BitCount(txOutIndex + 1); //w = ceiling((x + ymin + zmin + c + 1)/11) int w = RoundTo(x + ymin + zmin + c + 1, 11) / 11; int y = 0; int z = 0; for( ; ; w++) { int y1 = BitCount((int)merkleBlock.PartialMerkleTree.TransactionCount); int y2 = 11 * w - 1 - x - c; y = Math.Min(y1, y2); if(ymin > y) continue; int z1 = BitCount(transaction.Outputs.Count); int z2 = 11 * w - 1 - x - y - c; z = Math.Min(z1, z2); if(zmin > z) continue; break; } var cs = 11 * w - 1 - x - y - z; var checksum = CalculateChecksum(blockId, txIndex, txOutIndex, txOut.ScriptPubKey, cs); var rawAddress = Concat(encodedBlockHeight, Encode(txIndex, y), Encode(txOutIndex, z), checksum); var finalAddress = EncryptRawAddress(rawAddress); return new MnemonicReference() { BlockHeight = blockHeight, TransactionIndex = txIndex, OutputIndex = txOutIndex, Checksum = checksum, WordIndices = Wordlist.ToIntegers(finalAddress), Output = transaction.Outputs[txOutIndex], Transaction = transaction, BlockId = blockId }; }
public void SynchronizeChain(ChainBase chain) { if(chain.Tip != null && chain.Genesis.HashBlock != Configuration.Network.GetGenesis().GetHash()) throw new ArgumentException("Incompatible Network between the indexer and the chain", "chain"); if(chain.Tip == null) chain.SetTip(new ChainedBlock(Configuration.Network.GetGenesis().Header, 0)); GetChainChangesUntilFork(chain.Tip, false) .UpdateChain(chain); }
public ChainedBlock SetTip(ChainBase otherChain) { if(otherChain == null) throw new ArgumentNullException("otherChain"); return SetTip(otherChain.Tip); }
public ChainedBlock SetTip(ChainBase otherChain) { return(SetTip(otherChain.Tip)); }
public static MnemonicReference Create(ChainBase chain, Transaction transaction, Block block, int txOutIndex) { return(Create(chain, transaction, block.Filter(transaction.GetHash()), txOutIndex)); }
public bool SameTip(ChainBase chain) { if(chain == null) throw new ArgumentNullException("chain"); return Tip.HashBlock == chain.Tip.HashBlock; }
public static MnemonicReference Create (ChainBase chain, Transaction transaction, MerkleBlock merkleBlock, int txOutIndex) { var blockId = merkleBlock.Header.GetHash(); var merkleRoot = merkleBlock.PartialMerkleTree.TryGetMerkleRoot(); if (merkleRoot == null || merkleRoot.Hash != merkleBlock.Header.HashMerkleRoot) { throw new InvalidBrainAddressException("Invalid merkle block"); } if (txOutIndex >= transaction.Outputs.Count) { throw new InvalidBrainAddressException("The specified txout index is outside of the transaction bounds"); } var matchedLeaf = merkleRoot.GetLeafs().Select((node, index) => new { node, index }).FirstOrDefault(_ => _.node.Hash == transaction.GetHash()); if (matchedLeaf == null) { throw new InvalidBrainAddressException("Transaction not included in this merkle block"); } var chainedHeader = chain.GetBlock(blockId); if (chainedHeader == null) { throw new InvalidBrainAddressException("The block provided is not in the current chain"); } var blockHeight = chainedHeader.Height; var txIndex = matchedLeaf.index; var txOut = transaction.Outputs[txOutIndex]; var block = chain.GetBlock(blockId); BitArray encodedBlockHeight = EncodeBlockHeight(blockHeight); int x = encodedBlockHeight.Length; //ymin = ceiling(log(txIndex + 1, 2)) int ymin = BitCount(txIndex + 1); //zmin = ceiling(log(outputIndex + 1, 2)) int zmin = BitCount(txOutIndex + 1); //w = ceiling((x + ymin + zmin + c + 1)/11) int w = RoundTo(x + ymin + zmin + c + 1, 11) / 11; int y = 0; int z = 0; for ( ; ; w++) { int y1 = BitCount((int)merkleBlock.PartialMerkleTree.TransactionCount); int y2 = 11 * w - 1 - x - c; y = Math.Min(y1, y2); if (ymin > y) { continue; } int z1 = BitCount(transaction.Outputs.Count); int z2 = 11 * w - 1 - x - y - c; z = Math.Min(z1, z2); if (zmin > z) { continue; } break; } var cs = 11 * w - 1 - x - y - z; var checksum = CalculateChecksum(blockId, txIndex, txOutIndex, txOut.ScriptPubKey, cs); var rawAddress = Concat(encodedBlockHeight, Encode(txIndex, y), Encode(txOutIndex, z), checksum); var finalAddress = EncryptRawAddress(rawAddress); return(new MnemonicReference() { BlockHeight = blockHeight, TransactionIndex = txIndex, OutputIndex = txOutIndex, Checksum = checksum, WordIndices = Wordlist.ToIntegers(finalAddress), Output = transaction.Outputs[txOutIndex], Transaction = transaction, BlockId = blockId }); }
// Stake Modifier (hash modifier of proof-of-stake): // The purpose of stake modifier is to prevent a txout (coin) owner from // computing future proof-of-stake generated by this txout at the time // of transaction confirmation. To meet kernel protocol, the txout // must hash with a future stake modifier to generate the proof. // Stake modifier consists of bits each of which is contributed from a // selected block of a given block group in the past. // The selection of a block is based on a hash of the block's proof-hash and // the previous stake modifier. // Stake modifier is recomputed at a fixed time interval instead of every // block. This is to make it difficult for an attacker to gain control of // additional bits in the stake modifier, even after generating a chain of // blocks. private static bool ComputeNextStakeModifier(StakeChain stakeChain, ChainBase chainIndex, ChainedBlock pindexPrev, out ulong nStakeModifier, out bool fGeneratedStakeModifier) { nStakeModifier = 0; fGeneratedStakeModifier = false; if (pindexPrev == null) { fGeneratedStakeModifier = true; return(true); // genesis block's modifier is 0 } // First find current stake modifier and its generation block time // if it's not old enough, return the same stake modifier long nModifierTime = 0; if (!GetLastStakeModifier(stakeChain, pindexPrev, out nStakeModifier, out nModifierTime)) { return(false); //error("ComputeNextStakeModifier: unable to get last modifier"); } //LogPrint("stakemodifier", "ComputeNextStakeModifier: prev modifier=0x%016x time=%s\n", nStakeModifier, DateTimeStrFormat(nModifierTime)); if (nModifierTime / ModifierInterval >= pindexPrev.Header.Time / ModifierInterval) { return(true); } // Sort candidate blocks by timestamp var sortedByTimestamp = new SortedDictionary <uint, uint256>(); long nSelectionInterval = GetStakeModifierSelectionInterval(); long nSelectionIntervalStart = (pindexPrev.Header.Time / ModifierInterval) * ModifierInterval - nSelectionInterval; var pindex = pindexPrev; while (pindex != null && pindex.Header.Time >= nSelectionIntervalStart) { sortedByTimestamp.Add(pindex.Header.Time, pindex.HashBlock); pindex = pindex.Previous; } int nHeightFirstCandidate = pindex?.Height + 1 ?? 0; // Select 64 blocks from candidate blocks to generate stake modifier ulong nStakeModifierNew = 0; long nSelectionIntervalStop = nSelectionIntervalStart; var mapSelectedBlocks = new Dictionary <uint256, ChainedBlock>(); for (int nRound = 0; nRound < Math.Min(64, sortedByTimestamp.Count); nRound++) { // add an interval section to the current selection round nSelectionIntervalStop += GetStakeModifierSelectionIntervalSection(nRound); // select a block from the candidates of current round if (!SelectBlockFromCandidates(stakeChain, pindexPrev, sortedByTimestamp, mapSelectedBlocks, nSelectionIntervalStop, nStakeModifier, out pindex)) { return(false); // error("ComputeNextStakeModifier: unable to select block at round %d", nRound); } // write the entropy bit of the selected block var blockStake = stakeChain.Get(pindex.HashBlock); nStakeModifierNew |= ((ulong)blockStake.GetStakeEntropyBit() << nRound); // add the selected block from candidates to selected list mapSelectedBlocks.Add(pindex.HashBlock, pindex); //LogPrint("stakemodifier", "ComputeNextStakeModifier: selected round %d stop=%s height=%d bit=%d\n", nRound, DateTimeStrFormat(nSelectionIntervalStop), pindex->nHeight, pindex->GetStakeEntropyBit()); } // // Print selection map for visualization of the selected blocks // if (LogAcceptCategory("stakemodifier")) // { // string strSelectionMap = ""; // '-' indicates proof-of-work blocks not selected // strSelectionMap.insert(0, pindexPrev->nHeight - nHeightFirstCandidate + 1, '-'); // pindex = pindexPrev; // while (pindex && pindex->nHeight >= nHeightFirstCandidate) // { // // '=' indicates proof-of-stake blocks not selected // if (pindex->IsProofOfStake()) // strSelectionMap.replace(pindex->nHeight - nHeightFirstCandidate, 1, "="); // pindex = pindex->pprev; // } // BOOST_FOREACH(const PAIRTYPE(uint256, const CBlockIndex*)& item, mapSelectedBlocks) // { // // 'S' indicates selected proof-of-stake blocks // // 'W' indicates selected proof-of-work blocks // strSelectionMap.replace(item.second->nHeight - nHeightFirstCandidate, 1, item.second->IsProofOfStake()? "S" : "W"); // } // LogPrintf("ComputeNextStakeModifier: selection height [%d, %d] map %s\n", nHeightFirstCandidate, pindexPrev->nHeight, strSelectionMap); // } //LogPrint("stakemodifier", "ComputeNextStakeModifier: new modifier=0x%016x time=%s\n", nStakeModifierNew, DateTimeStrFormat(pindexPrev->GetBlockTime())); nStakeModifier = nStakeModifierNew; fGeneratedStakeModifier = true; return(true); }
public static MnemonicReference Create(ChainBase chain, Transaction transaction, Block block, int txOutIndex) { return Create(chain, transaction, block.Filter(transaction.GetHash()), txOutIndex); }
public ChainedBlock FindFork(ChainBase chain) { if(chain == null) throw new ArgumentNullException("chain"); return FindFork(chain.ToEnumerable(true).Select(o => o.HashBlock)); }